Coverage Report

Created: 2025-10-04 18:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/libfido2/src/cred.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2018-2024 Yubico AB. All rights reserved.
3
 * Use of this source code is governed by a BSD-style
4
 * license that can be found in the LICENSE file.
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#include <openssl/sha.h>
9
#include <openssl/x509.h>
10
11
#include "fido.h"
12
#include "fido/es256.h"
13
14
#ifndef FIDO_MAXMSG_CRED
15
11.0k
#define FIDO_MAXMSG_CRED        4096
16
#endif
17
18
static int
19
parse_makecred_reply(const cbor_item_t *key, const cbor_item_t *val, void *arg)
20
13.9k
{
21
13.9k
        fido_cred_t *cred = arg;
22
23
13.9k
        if (cbor_isa_uint(key) == false ||
24
13.9k
            cbor_int_get_width(key) != CBOR_INT_8) {
25
114
                fido_log_debug("%s: cbor type", __func__);
26
114
                return (0); /* ignore */
27
114
        }
28
29
13.8k
        switch (cbor_get_uint8(key)) {
30
4.91k
        case 1: /* fmt */
31
4.91k
                return (cbor_decode_fmt(val, &cred->fmt));
32
4.88k
        case 2: /* authdata */
33
4.88k
                if (fido_blob_decode(val, &cred->authdata_raw) < 0) {
34
2
                        fido_log_debug("%s: fido_blob_decode", __func__);
35
2
                        return (-1);
36
2
                }
37
4.88k
                return (cbor_decode_cred_authdata(val, cred->type,
38
4.88k
                    &cred->authdata_cbor, &cred->authdata, &cred->attcred,
39
4.88k
                    &cred->authdata_ext));
40
3.87k
        case 3: /* attestation statement */
41
3.87k
                return (cbor_decode_attstmt(val, &cred->attstmt));
42
8
        case 4: /* enterprise attestation */
43
8
                return (cbor_decode_bool(val, &cred->ea.att));
44
4
        case 5: /* large blob key */
45
4
                return (fido_blob_decode(val, &cred->largeblob_key));
46
164
        default: /* ignore */
47
164
                fido_log_debug("%s: cbor type", __func__);
48
164
                return (0);
49
13.8k
        }
50
13.8k
}
51
52
static int
53
fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
54
    int *ms)
55
9.16k
{
56
9.16k
        fido_blob_t      f;
57
9.16k
        fido_blob_t     *ecdh = NULL;
58
9.16k
        fido_opt_t       uv = cred->uv;
59
9.16k
        es256_pk_t      *pk = NULL;
60
9.16k
        cbor_item_t     *argv[10];
61
9.16k
        const uint8_t    cmd = CTAP_CBOR_MAKECRED;
62
9.16k
        int              r;
63
64
9.16k
        memset(&f, 0, sizeof(f));
65
9.16k
        memset(argv, 0, sizeof(argv));
66
67
9.16k
        if (cred->cdh.ptr == NULL || cred->type == 0) {
68
16
                fido_log_debug("%s: cdh=%p, type=%d", __func__,
69
16
                    (void *)cred->cdh.ptr, cred->type);
70
16
                r = FIDO_ERR_INVALID_ARGUMENT;
71
16
                goto fail;
72
16
        }
73
74
9.15k
        if ((argv[0] = fido_blob_encode(&cred->cdh)) == NULL ||
75
9.15k
            (argv[1] = cbor_encode_rp_entity(&cred->rp)) == NULL ||
76
9.15k
            (argv[2] = cbor_encode_user_entity(&cred->user)) == NULL ||
77
9.15k
            (argv[3] = cbor_encode_pubkey_param(cred->type)) == NULL) {
78
180
                fido_log_debug("%s: cbor encode", __func__);
79
180
                r = FIDO_ERR_INTERNAL;
80
180
                goto fail;
81
180
        }
82
83
        /* excluded credentials */
84
8.97k
        if (cred->excl.len)
85
6.26k
                if ((argv[4] = cbor_encode_pubkey_list(&cred->excl)) == NULL) {
86
509
                        fido_log_debug("%s: cbor_encode_pubkey_list", __func__);
87
509
                        r = FIDO_ERR_INTERNAL;
88
509
                        goto fail;
89
509
                }
90
91
        /* extensions */
92
8.46k
        if (cred->ext.mask)
93
6.40k
                if ((argv[5] = cbor_encode_cred_ext(&cred->ext,
94
6.40k
                    &cred->blob)) == NULL) {
95
94
                        fido_log_debug("%s: cbor_encode_cred_ext", __func__);
96
94
                        r = FIDO_ERR_INTERNAL;
97
94
                        goto fail;
98
94
                }
99
100
        /* user verification */
101
8.36k
        if (pin != NULL || (uv == FIDO_OPT_TRUE &&
102
6.40k
            fido_dev_supports_permissions(dev))) {
103
6.40k
                if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
104
1.54k
                        fido_log_debug("%s: fido_do_ecdh", __func__);
105
1.54k
                        goto fail;
106
1.54k
                }
107
4.85k
                if ((r = cbor_add_uv_params(dev, cmd, &cred->cdh, pk, ecdh,
108
4.85k
                    pin, cred->rp.id, &argv[7], &argv[8], ms)) != FIDO_OK) {
109
476
                        fido_log_debug("%s: cbor_add_uv_params", __func__);
110
476
                        goto fail;
111
476
                }
112
4.38k
                uv = FIDO_OPT_OMIT;
113
4.38k
        }
114
115
        /* options */
116
6.34k
        if (cred->rk != FIDO_OPT_OMIT || uv != FIDO_OPT_OMIT)
117
2.34k
                if ((argv[6] = cbor_encode_cred_opt(cred->rk, uv)) == NULL) {
118
14
                        fido_log_debug("%s: cbor_encode_cred_opt", __func__);
119
14
                        r = FIDO_ERR_INTERNAL;
120
14
                        goto fail;
121
14
                }
122
123
        /* enterprise attestation */
124
6.32k
        if (cred->ea.mode != 0)
125
2.38k
                if ((argv[9] = cbor_build_uint8((uint8_t)cred->ea.mode)) ==
126
2.38k
                    NULL) {
127
2
                        fido_log_debug("%s: cbor_build_uint8", __func__);
128
2
                        r = FIDO_ERR_INTERNAL;
129
2
                        goto fail;
130
2
                }
131
132
        /* framing and transmission */
133
6.32k
        if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
134
6.32k
            fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
135
788
                fido_log_debug("%s: fido_tx", __func__);
136
788
                r = FIDO_ERR_TX;
137
788
                goto fail;
138
788
        }
139
140
5.53k
        r = FIDO_OK;
141
9.16k
fail:
142
9.16k
        es256_pk_free(&pk);
143
9.16k
        fido_blob_free(&ecdh);
144
9.16k
        cbor_vector_free(argv, nitems(argv));
145
9.16k
        free(f.ptr);
146
147
9.16k
        return (r);
148
5.53k
}
149
150
static int
151
fido_dev_make_cred_rx(fido_dev_t *dev, fido_cred_t *cred, int *ms)
152
5.53k
{
153
5.53k
        unsigned char   *reply;
154
5.53k
        int              reply_len;
155
5.53k
        int              r;
156
157
5.53k
        fido_cred_reset_rx(cred);
158
159
5.53k
        if ((reply = malloc(FIDO_MAXMSG_CRED)) == NULL) {
160
11
                r = FIDO_ERR_INTERNAL;
161
11
                goto fail;
162
11
        }
163
164
5.52k
        if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, reply, FIDO_MAXMSG_CRED,
165
5.52k
            ms)) < 0) {
166
285
                fido_log_debug("%s: fido_rx", __func__);
167
285
                r = FIDO_ERR_RX;
168
285
                goto fail;
169
285
        }
170
171
5.24k
        if ((r = cbor_parse_reply(reply, (size_t)reply_len, cred,
172
5.24k
            parse_makecred_reply)) != FIDO_OK) {
173
1.64k
                fido_log_debug("%s: parse_makecred_reply", __func__);
174
1.64k
                goto fail;
175
1.64k
        }
176
177
3.59k
        if (cred->fmt == NULL || fido_blob_is_empty(&cred->authdata_cbor) ||
178
3.59k
            fido_blob_is_empty(&cred->attcred.id)) {
179
99
                r = FIDO_ERR_INVALID_CBOR;
180
99
                goto fail;
181
99
        }
182
183
3.49k
        r = FIDO_OK;
184
5.53k
fail:
185
5.53k
        free(reply);
186
187
5.53k
        if (r != FIDO_OK)
188
2.04k
                fido_cred_reset_rx(cred);
189
190
5.53k
        return (r);
191
3.49k
}
192
193
static int
194
fido_dev_make_cred_wait(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
195
    int *ms)
196
9.16k
{
197
9.16k
        int  r;
198
199
9.16k
        if ((r = fido_dev_make_cred_tx(dev, cred, pin, ms)) != FIDO_OK ||
200
9.16k
            (r = fido_dev_make_cred_rx(dev, cred, ms)) != FIDO_OK)
201
5.67k
                return (r);
202
203
3.49k
        return (FIDO_OK);
204
9.16k
}
205
206
int
207
fido_dev_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
208
17.4k
{
209
17.4k
        int ms = dev->timeout_ms;
210
211
#ifdef USE_WINHELLO
212
        if (dev->flags & FIDO_DEV_WINHELLO)
213
                return (fido_winhello_make_cred(dev, cred, pin, ms));
214
#endif
215
17.4k
        if (fido_dev_is_fido2(dev) == false) {
216
8.30k
                if (pin != NULL || cred->rk == FIDO_OPT_TRUE ||
217
8.30k
                    cred->ext.mask != 0)
218
4.97k
                        return (FIDO_ERR_UNSUPPORTED_OPTION);
219
3.32k
                return (u2f_register(dev, cred, &ms));
220
8.30k
        }
221
222
9.16k
        return (fido_dev_make_cred_wait(dev, cred, pin, &ms));
223
17.4k
}
224
225
static int
226
check_extensions(const fido_cred_ext_t *authdata_ext,
227
    const fido_cred_ext_t *ext)
228
6.21k
{
229
6.21k
        fido_cred_ext_t  tmp;
230
231
        /* XXX: largeBlobKey is not part of the extensions map */
232
6.21k
        memcpy(&tmp, ext, sizeof(tmp));
233
6.21k
        tmp.mask &= ~FIDO_EXT_LARGEBLOB_KEY;
234
235
6.21k
        return (timingsafe_bcmp(authdata_ext, &tmp, sizeof(*authdata_ext)));
236
6.21k
}
237
238
int
239
fido_check_rp_id(const char *id, const unsigned char *obtained_hash)
240
11.9k
{
241
11.9k
        unsigned char expected_hash[SHA256_DIGEST_LENGTH];
242
243
11.9k
        explicit_bzero(expected_hash, sizeof(expected_hash));
244
245
11.9k
        if (SHA256((const unsigned char *)id, strlen(id),
246
11.9k
            expected_hash) != expected_hash) {
247
55
                fido_log_debug("%s: sha256", __func__);
248
55
                return (-1);
249
55
        }
250
251
11.9k
        return (timingsafe_bcmp(expected_hash, obtained_hash,
252
11.9k
            SHA256_DIGEST_LENGTH));
253
11.9k
}
254
255
static int
256
get_signed_hash_u2f(fido_blob_t *dgst, const unsigned char *rp_id,
257
    size_t rp_id_len, const fido_blob_t *clientdata, const fido_blob_t *id,
258
    const es256_pk_t *pk)
259
576
{
260
576
        const uint8_t    zero = 0;
261
576
        const uint8_t    four = 4; /* uncompressed point */
262
576
        const EVP_MD    *md = NULL;
263
576
        EVP_MD_CTX      *ctx = NULL;
264
576
        int              ok = -1;
265
266
576
        if (dgst->len < SHA256_DIGEST_LENGTH ||
267
576
            (md = EVP_sha256()) == NULL ||
268
576
            (ctx = EVP_MD_CTX_new()) == NULL ||
269
576
            EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
270
576
            EVP_DigestUpdate(ctx, &zero, sizeof(zero)) != 1 ||
271
576
            EVP_DigestUpdate(ctx, rp_id, rp_id_len) != 1 ||
272
576
            EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
273
576
            EVP_DigestUpdate(ctx, id->ptr, id->len) != 1 ||
274
576
            EVP_DigestUpdate(ctx, &four, sizeof(four)) != 1 ||
275
576
            EVP_DigestUpdate(ctx, pk->x, sizeof(pk->x)) != 1 ||
276
576
            EVP_DigestUpdate(ctx, pk->y, sizeof(pk->y)) != 1 ||
277
576
            EVP_DigestFinal_ex(ctx, dgst->ptr, NULL) != 1) {
278
49
                fido_log_debug("%s: sha256", __func__);
279
49
                goto fail;
280
49
        }
281
527
        dgst->len = SHA256_DIGEST_LENGTH;
282
283
527
        ok = 0;
284
576
fail:
285
576
        EVP_MD_CTX_free(ctx);
286
287
576
        return (ok);
288
527
}
289
290
static int
291
verify_attstmt(const fido_blob_t *dgst, const fido_attstmt_t *attstmt)
292
5.13k
{
293
5.13k
        BIO             *rawcert = NULL;
294
5.13k
        X509            *cert = NULL;
295
5.13k
        EVP_PKEY        *pkey = NULL;
296
5.13k
        int              ok = -1;
297
298
5.13k
        if (!attstmt->x5c.len) {
299
0
                fido_log_debug("%s: x5c.len=%zu", __func__, attstmt->x5c.len);
300
0
                return (-1);
301
0
        }
302
303
        /* openssl needs ints */
304
5.13k
        if (attstmt->x5c.ptr[0].len > INT_MAX) {
305
0
                fido_log_debug("%s: x5c[0].len=%zu", __func__,
306
0
                    attstmt->x5c.ptr[0].len);
307
0
                return (-1);
308
0
        }
309
310
        /* fetch key from x509 */
311
5.13k
        if ((rawcert = BIO_new_mem_buf(attstmt->x5c.ptr[0].ptr,
312
5.13k
            (int)attstmt->x5c.ptr[0].len)) == NULL ||
313
5.13k
            (cert = d2i_X509_bio(rawcert, NULL)) == NULL ||
314
5.13k
            (pkey = X509_get_pubkey(cert)) == NULL) {
315
3.06k
                fido_log_debug("%s: x509 key", __func__);
316
3.06k
                goto fail;
317
3.06k
        }
318
319
2.07k
        switch (attstmt->alg) {
320
35
        case COSE_UNSPEC:
321
1.15k
        case COSE_ES256:
322
1.15k
                ok = es256_verify_sig(dgst, pkey, &attstmt->sig);
323
1.15k
                break;
324
32
        case COSE_ES384:
325
32
                ok = es384_verify_sig(dgst, pkey, &attstmt->sig);
326
32
                break;
327
4
        case COSE_RS256:
328
4
                ok = rs256_verify_sig(dgst, pkey, &attstmt->sig);
329
4
                break;
330
517
        case COSE_RS1:
331
517
                ok = rs1_verify_sig(dgst, pkey, &attstmt->sig);
332
517
                break;
333
367
        case COSE_EDDSA:
334
367
                ok = eddsa_verify_sig(dgst, pkey, &attstmt->sig);
335
367
                break;
336
0
        default:
337
0
                fido_log_debug("%s: unknown alg %d", __func__, attstmt->alg);
338
0
                break;
339
2.07k
        }
340
341
5.13k
fail:
342
5.13k
        BIO_free(rawcert);
343
5.13k
        X509_free(cert);
344
5.13k
        EVP_PKEY_free(pkey);
345
346
5.13k
        return (ok);
347
2.07k
}
348
349
int
350
fido_cred_verify(const fido_cred_t *cred)
351
28.3k
{
352
28.3k
        unsigned char   buf[1024]; /* XXX */
353
28.3k
        fido_blob_t     dgst;
354
28.3k
        int             cose_alg;
355
28.3k
        int             r;
356
357
28.3k
        dgst.ptr = buf;
358
28.3k
        dgst.len = sizeof(buf);
359
360
        /* do we have everything we need? */
361
28.3k
        if (cred->cdh.ptr == NULL || cred->authdata_cbor.ptr == NULL ||
362
28.3k
            cred->attstmt.x5c.ptr == NULL || cred->attstmt.sig.ptr == NULL ||
363
28.3k
            cred->fmt == NULL || cred->attcred.id.ptr == NULL ||
364
28.3k
            cred->rp.id == NULL) {
365
22.3k
                fido_log_debug("%s: cdh=%p, authdata=%p, x5c=%p, sig=%p, "
366
22.3k
                    "fmt=%p id=%p, rp.id=%s", __func__, (void *)cred->cdh.ptr,
367
22.3k
                    (void *)cred->authdata_cbor.ptr,
368
22.3k
                    (void *)cred->attstmt.x5c.ptr,
369
22.3k
                    (void *)cred->attstmt.sig.ptr, (void *)cred->fmt,
370
22.3k
                    (void *)cred->attcred.id.ptr, cred->rp.id);
371
22.3k
                r = FIDO_ERR_INVALID_ARGUMENT;
372
22.3k
                goto out;
373
22.3k
        }
374
375
6.01k
        if (fido_check_rp_id(cred->rp.id, cred->authdata.rp_id_hash) != 0) {
376
496
                fido_log_debug("%s: fido_check_rp_id", __func__);
377
496
                r = FIDO_ERR_INVALID_PARAM;
378
496
                goto out;
379
496
        }
380
381
5.52k
        if (fido_check_flags(cred->authdata.flags, FIDO_OPT_TRUE,
382
5.52k
            cred->uv) < 0) {
383
7
                fido_log_debug("%s: fido_check_flags", __func__);
384
7
                r = FIDO_ERR_INVALID_PARAM;
385
7
                goto out;
386
7
        }
387
388
5.51k
        if (check_extensions(&cred->authdata_ext, &cred->ext) != 0) {
389
9
                fido_log_debug("%s: check_extensions", __func__);
390
9
                r = FIDO_ERR_INVALID_PARAM;
391
9
                goto out;
392
9
        }
393
394
5.50k
        if ((cose_alg = cred->attstmt.alg) == COSE_UNSPEC)
395
180
                cose_alg = COSE_ES256; /* backwards compat */
396
397
5.50k
        if (!strcmp(cred->fmt, "packed")) {
398
4.09k
                if (fido_get_signed_hash(cose_alg, &dgst, &cred->cdh,
399
4.09k
                    &cred->authdata_cbor) < 0) {
400
168
                        fido_log_debug("%s: fido_get_signed_hash", __func__);
401
168
                        r = FIDO_ERR_INTERNAL;
402
168
                        goto out;
403
168
                }
404
4.09k
        } else if (!strcmp(cred->fmt, "fido-u2f")) {
405
504
                if (get_signed_hash_u2f(&dgst, cred->authdata.rp_id_hash,
406
504
                    sizeof(cred->authdata.rp_id_hash), &cred->cdh,
407
504
                    &cred->attcred.id, &cred->attcred.pubkey.es256) < 0) {
408
44
                        fido_log_debug("%s: get_signed_hash_u2f", __func__);
409
44
                        r = FIDO_ERR_INTERNAL;
410
44
                        goto out;
411
44
                }
412
902
        } else if (!strcmp(cred->fmt, "tpm")) {
413
899
                if (fido_get_signed_hash_tpm(&dgst, &cred->cdh,
414
899
                    &cred->authdata_raw, &cred->attstmt, &cred->attcred) < 0) {
415
157
                        fido_log_debug("%s: fido_get_signed_hash_tpm", __func__);
416
157
                        r = FIDO_ERR_INTERNAL;
417
157
                        goto out;
418
157
                }
419
899
        } else {
420
3
                fido_log_debug("%s: unknown fmt %s", __func__, cred->fmt);
421
3
                r = FIDO_ERR_INVALID_ARGUMENT;
422
3
                goto out;
423
3
        }
424
425
5.13k
        if (verify_attstmt(&dgst, &cred->attstmt) < 0) {
426
5.12k
                fido_log_debug("%s: verify_attstmt", __func__);
427
5.12k
                r = FIDO_ERR_INVALID_SIG;
428
5.12k
                goto out;
429
5.12k
        }
430
431
11
        r = FIDO_OK;
432
28.3k
out:
433
28.3k
        explicit_bzero(buf, sizeof(buf));
434
435
28.3k
        return (r);
436
11
}
437
438
int
439
fido_cred_verify_self(const fido_cred_t *cred)
440
19.6k
{
441
19.6k
        unsigned char   buf[1024]; /* XXX */
442
19.6k
        fido_blob_t     dgst;
443
19.6k
        int             ok = -1;
444
19.6k
        int             r;
445
446
19.6k
        dgst.ptr = buf;
447
19.6k
        dgst.len = sizeof(buf);
448
449
        /* do we have everything we need? */
450
19.6k
        if (cred->cdh.ptr == NULL || cred->authdata_cbor.ptr == NULL ||
451
19.6k
            cred->attstmt.x5c.ptr != NULL || cred->attstmt.sig.ptr == NULL ||
452
19.6k
            cred->fmt == NULL || cred->attcred.id.ptr == NULL ||
453
19.6k
            cred->rp.id == NULL) {
454
18.4k
                fido_log_debug("%s: cdh=%p, authdata=%p, x5c=%p, sig=%p, "
455
18.4k
                    "fmt=%p id=%p, rp.id=%s", __func__, (void *)cred->cdh.ptr,
456
18.4k
                    (void *)cred->authdata_cbor.ptr,
457
18.4k
                    (void *)cred->attstmt.x5c.ptr,
458
18.4k
                    (void *)cred->attstmt.sig.ptr, (void *)cred->fmt,
459
18.4k
                    (void *)cred->attcred.id.ptr, cred->rp.id);
460
18.4k
                r = FIDO_ERR_INVALID_ARGUMENT;
461
18.4k
                goto out;
462
18.4k
        }
463
464
1.17k
        if (fido_check_rp_id(cred->rp.id, cred->authdata.rp_id_hash) != 0) {
465
466
                fido_log_debug("%s: fido_check_rp_id", __func__);
466
466
                r = FIDO_ERR_INVALID_PARAM;
467
466
                goto out;
468
466
        }
469
470
713
        if (fido_check_flags(cred->authdata.flags, FIDO_OPT_TRUE,
471
713
            cred->uv) < 0) {
472
10
                fido_log_debug("%s: fido_check_flags", __func__);
473
10
                r = FIDO_ERR_INVALID_PARAM;
474
10
                goto out;
475
10
        }
476
477
703
        if (check_extensions(&cred->authdata_ext, &cred->ext) != 0) {
478
4
                fido_log_debug("%s: check_extensions", __func__);
479
4
                r = FIDO_ERR_INVALID_PARAM;
480
4
                goto out;
481
4
        }
482
483
699
        if (!strcmp(cred->fmt, "packed")) {
484
622
                if (fido_get_signed_hash(cred->attcred.type, &dgst, &cred->cdh,
485
622
                    &cred->authdata_cbor) < 0) {
486
42
                        fido_log_debug("%s: fido_get_signed_hash", __func__);
487
42
                        r = FIDO_ERR_INTERNAL;
488
42
                        goto out;
489
42
                }
490
622
        } else if (!strcmp(cred->fmt, "fido-u2f")) {
491
72
                if (get_signed_hash_u2f(&dgst, cred->authdata.rp_id_hash,
492
72
                    sizeof(cred->authdata.rp_id_hash), &cred->cdh,
493
72
                    &cred->attcred.id, &cred->attcred.pubkey.es256) < 0) {
494
5
                        fido_log_debug("%s: get_signed_hash_u2f", __func__);
495
5
                        r = FIDO_ERR_INTERNAL;
496
5
                        goto out;
497
5
                }
498
72
        } else {
499
5
                fido_log_debug("%s: unknown fmt %s", __func__, cred->fmt);
500
5
                r = FIDO_ERR_INVALID_ARGUMENT;
501
5
                goto out;
502
5
        }
503
504
647
        switch (cred->attcred.type) {
505
89
        case COSE_ES256:
506
89
                ok = es256_pk_verify_sig(&dgst, &cred->attcred.pubkey.es256,
507
89
                    &cred->attstmt.sig);
508
89
                break;
509
235
        case COSE_ES384:
510
235
                ok = es384_pk_verify_sig(&dgst, &cred->attcred.pubkey.es384,
511
235
                    &cred->attstmt.sig);
512
235
                break;
513
82
        case COSE_RS256:
514
82
                ok = rs256_pk_verify_sig(&dgst, &cred->attcred.pubkey.rs256,
515
82
                    &cred->attstmt.sig);
516
82
                break;
517
241
        case COSE_EDDSA:
518
241
                ok = eddsa_pk_verify_sig(&dgst, &cred->attcred.pubkey.eddsa,
519
241
                    &cred->attstmt.sig);
520
241
                break;
521
0
        default:
522
0
                fido_log_debug("%s: unsupported cose_alg %d", __func__,
523
0
                    cred->attcred.type);
524
0
                r = FIDO_ERR_UNSUPPORTED_OPTION;
525
0
                goto out;
526
647
        }
527
528
647
        if (ok < 0)
529
647
                r = FIDO_ERR_INVALID_SIG;
530
0
        else
531
0
                r = FIDO_OK;
532
533
19.6k
out:
534
19.6k
        explicit_bzero(buf, sizeof(buf));
535
536
19.6k
        return (r);
537
647
}
538
539
fido_cred_t *
540
fido_cred_new(void)
541
74.5k
{
542
74.5k
        return (calloc(1, sizeof(fido_cred_t)));
543
74.5k
}
544
545
static void
546
fido_cred_clean_authdata(fido_cred_t *cred)
547
263k
{
548
263k
        fido_blob_reset(&cred->authdata_cbor);
549
263k
        fido_blob_reset(&cred->authdata_raw);
550
263k
        fido_blob_reset(&cred->attcred.id);
551
552
263k
        memset(&cred->authdata_ext, 0, sizeof(cred->authdata_ext));
553
263k
        memset(&cred->authdata, 0, sizeof(cred->authdata));
554
263k
        memset(&cred->attcred, 0, sizeof(cred->attcred));
555
263k
}
556
557
static void
558
fido_cred_clean_attstmt(fido_attstmt_t *attstmt)
559
200k
{
560
200k
        fido_blob_reset(&attstmt->certinfo);
561
200k
        fido_blob_reset(&attstmt->pubarea);
562
200k
        fido_blob_reset(&attstmt->cbor);
563
200k
        fido_free_blob_array(&attstmt->x5c);
564
200k
        fido_blob_reset(&attstmt->sig);
565
566
200k
        memset(attstmt, 0, sizeof(*attstmt));
567
200k
}
568
569
static void
570
fido_cred_clean_attobj(fido_cred_t *cred)
571
128k
{
572
128k
        free(cred->fmt);
573
128k
        cred->fmt = NULL;
574
128k
        fido_cred_clean_authdata(cred);
575
128k
        fido_cred_clean_attstmt(&cred->attstmt);
576
128k
}
577
578
void
579
fido_cred_reset_tx(fido_cred_t *cred)
580
112k
{
581
112k
        fido_blob_reset(&cred->cd);
582
112k
        fido_blob_reset(&cred->cdh);
583
112k
        fido_blob_reset(&cred->user.id);
584
112k
        fido_blob_reset(&cred->blob);
585
586
112k
        free(cred->rp.id);
587
112k
        free(cred->rp.name);
588
112k
        free(cred->user.icon);
589
112k
        free(cred->user.name);
590
112k
        free(cred->user.display_name);
591
112k
        fido_cred_empty_exclude_list(cred);
592
593
112k
        memset(&cred->rp, 0, sizeof(cred->rp));
594
112k
        memset(&cred->user, 0, sizeof(cred->user));
595
112k
        memset(&cred->ext, 0, sizeof(cred->ext));
596
597
112k
        cred->type = 0;
598
112k
        cred->rk = FIDO_OPT_OMIT;
599
112k
        cred->uv = FIDO_OPT_OMIT;
600
112k
        cred->ea.mode = 0;
601
112k
}
602
603
void
604
fido_cred_reset_rx(fido_cred_t *cred)
605
119k
{
606
119k
        fido_cred_clean_attobj(cred);
607
119k
        fido_blob_reset(&cred->largeblob_key);
608
119k
        cred->ea.att = false;
609
119k
}
610
611
void
612
fido_cred_free(fido_cred_t **cred_p)
613
74.1k
{
614
74.1k
        fido_cred_t *cred;
615
616
74.1k
        if (cred_p == NULL || (cred = *cred_p) == NULL)
617
12
                return;
618
74.1k
        fido_cred_reset_tx(cred);
619
74.1k
        fido_cred_reset_rx(cred);
620
74.1k
        free(cred);
621
74.1k
        *cred_p = NULL;
622
74.1k
}
623
624
int
625
fido_cred_set_authdata(fido_cred_t *cred, const unsigned char *ptr, size_t len)
626
39.9k
{
627
39.9k
        cbor_item_t             *item = NULL;
628
39.9k
        struct cbor_load_result  cbor;
629
39.9k
        int                      r = FIDO_ERR_INVALID_ARGUMENT;
630
631
39.9k
        fido_cred_clean_authdata(cred);
632
633
39.9k
        if (ptr == NULL || len == 0)
634
31.1k
                goto fail;
635
636
8.80k
        if ((item = cbor_load(ptr, len, &cbor)) == NULL) {
637
274
                fido_log_debug("%s: cbor_load", __func__);
638
274
                goto fail;
639
274
        }
640
641
8.53k
        if (fido_blob_decode(item, &cred->authdata_raw) < 0) {
642
31
                fido_log_debug("%s: fido_blob_decode", __func__);
643
31
                goto fail;
644
31
        }
645
646
8.49k
        if (cbor_decode_cred_authdata(item, cred->type, &cred->authdata_cbor,
647
8.49k
            &cred->authdata, &cred->attcred, &cred->authdata_ext) < 0) {
648
444
                fido_log_debug("%s: cbor_decode_cred_authdata", __func__);
649
444
                goto fail;
650
444
        }
651
652
8.05k
        r = FIDO_OK;
653
39.9k
fail:
654
39.9k
        if (item != NULL)
655
8.53k
                cbor_decref(&item);
656
657
39.9k
        if (r != FIDO_OK)
658
31.8k
                fido_cred_clean_authdata(cred);
659
660
39.9k
        return (r);
661
8.05k
}
662
663
int
664
fido_cred_set_authdata_raw(fido_cred_t *cred, const unsigned char *ptr,
665
    size_t len)
666
31.8k
{
667
31.8k
        cbor_item_t     *item = NULL;
668
31.8k
        int              r = FIDO_ERR_INVALID_ARGUMENT;
669
670
31.8k
        fido_cred_clean_authdata(cred);
671
672
31.8k
        if (ptr == NULL || len == 0)
673
31.1k
                goto fail;
674
675
736
        if (fido_blob_set(&cred->authdata_raw, ptr, len) < 0) {
676
1
                fido_log_debug("%s: fido_blob_set", __func__);
677
1
                r = FIDO_ERR_INTERNAL;
678
1
                goto fail;
679
1
        }
680
681
735
        if ((item = cbor_build_bytestring(ptr, len)) == NULL) {
682
8
                fido_log_debug("%s: cbor_build_bytestring", __func__);
683
8
                r = FIDO_ERR_INTERNAL;
684
8
                goto fail;
685
8
        }
686
687
727
        if (cbor_decode_cred_authdata(item, cred->type, &cred->authdata_cbor,
688
727
            &cred->authdata, &cred->attcred, &cred->authdata_ext) < 0) {
689
337
                fido_log_debug("%s: cbor_decode_cred_authdata", __func__);
690
337
                goto fail;
691
337
        }
692
693
390
        r = FIDO_OK;
694
31.8k
fail:
695
31.8k
        if (item != NULL)
696
727
                cbor_decref(&item);
697
698
31.8k
        if (r != FIDO_OK)
699
31.4k
                fido_cred_clean_authdata(cred);
700
701
31.8k
        return (r);
702
390
}
703
704
int
705
fido_cred_set_id(fido_cred_t *cred, const unsigned char *ptr, size_t len)
706
26.0k
{
707
26.0k
        if (fido_blob_set(&cred->attcred.id, ptr, len) < 0)
708
159
                return (FIDO_ERR_INVALID_ARGUMENT);
709
710
25.8k
        return (FIDO_OK);
711
26.0k
}
712
713
int
714
fido_cred_set_x509(fido_cred_t *cred, const unsigned char *ptr, size_t len)
715
51.4k
{
716
51.4k
        fido_blob_t x5c_blob;
717
51.4k
        fido_blob_t *list_ptr = NULL;
718
719
51.4k
        memset(&x5c_blob, 0, sizeof(x5c_blob));
720
51.4k
        fido_free_blob_array(&cred->attstmt.x5c);
721
722
51.4k
        if (fido_blob_set(&x5c_blob, ptr, len) < 0)
723
48.6k
                return (FIDO_ERR_INVALID_ARGUMENT);
724
725
2.81k
        if (cred->attstmt.x5c.len == SIZE_MAX) {
726
0
                fido_blob_reset(&x5c_blob);
727
0
                return (FIDO_ERR_INVALID_ARGUMENT);
728
0
        }
729
730
2.81k
        if ((list_ptr = recallocarray(cred->attstmt.x5c.ptr,
731
2.81k
            cred->attstmt.x5c.len, cred->attstmt.x5c.len + 1,
732
2.81k
            sizeof(x5c_blob))) == NULL) {
733
29
                fido_blob_reset(&x5c_blob);
734
29
                return (FIDO_ERR_INTERNAL);
735
29
        }
736
737
2.78k
        list_ptr[cred->attstmt.x5c.len++] = x5c_blob;
738
2.78k
        cred->attstmt.x5c.ptr = list_ptr;
739
740
2.78k
        return (FIDO_OK);
741
2.81k
}
742
743
int
744
fido_cred_set_sig(fido_cred_t *cred, const unsigned char *ptr, size_t len)
745
51.4k
{
746
51.4k
        if (fido_blob_set(&cred->attstmt.sig, ptr, len) < 0)
747
47.3k
                return (FIDO_ERR_INVALID_ARGUMENT);
748
749
4.11k
        return (FIDO_OK);
750
51.4k
}
751
752
int
753
fido_cred_set_attstmt(fido_cred_t *cred, const unsigned char *ptr, size_t len)
754
39.9k
{
755
39.9k
        cbor_item_t             *item = NULL;
756
39.9k
        struct cbor_load_result  cbor;
757
39.9k
        int                      r = FIDO_ERR_INVALID_ARGUMENT;
758
759
39.9k
        fido_cred_clean_attstmt(&cred->attstmt);
760
761
39.9k
        if (ptr == NULL || len == 0)
762
31.2k
                goto fail;
763
764
8.63k
        if ((item = cbor_load(ptr, len, &cbor)) == NULL) {
765
47
                fido_log_debug("%s: cbor_load", __func__);
766
47
                goto fail;
767
47
        }
768
769
8.59k
        if (cbor_decode_attstmt(item, &cred->attstmt) < 0) {
770
508
                fido_log_debug("%s: cbor_decode_attstmt", __func__);
771
508
                goto fail;
772
508
        }
773
774
8.08k
        r = FIDO_OK;
775
39.9k
fail:
776
39.9k
        if (item != NULL)
777
8.59k
                cbor_decref(&item);
778
779
39.9k
        if (r != FIDO_OK)
780
31.8k
                fido_cred_clean_attstmt(&cred->attstmt);
781
782
39.9k
        return (r);
783
8.08k
}
784
785
int
786
fido_cred_set_attobj(fido_cred_t *cred, const unsigned char *ptr, size_t len)
787
8.67k
{
788
8.67k
        cbor_item_t             *item = NULL;
789
8.67k
        struct cbor_load_result  cbor;
790
8.67k
        int                      r = FIDO_ERR_INVALID_ARGUMENT;
791
792
8.67k
        fido_cred_clean_attobj(cred);
793
794
8.67k
        if (ptr == NULL || len == 0)
795
9
                goto fail;
796
797
8.66k
        if ((item = cbor_load(ptr, len, &cbor)) == NULL) {
798
930
                fido_log_debug("%s: cbor_load", __func__);
799
930
                goto fail;
800
930
        }
801
7.73k
        if (cbor_decode_attobj(item, cred) != 0) {
802
6.48k
                fido_log_debug("%s: cbor_decode_attobj", __func__);
803
6.48k
                goto fail;
804
6.48k
        }
805
806
1.25k
        r = FIDO_OK;
807
8.67k
fail:
808
8.67k
        if (item != NULL)
809
7.73k
                cbor_decref(&item);
810
811
8.67k
        return (r);
812
1.25k
}
813
814
int
815
fido_cred_exclude(fido_cred_t *cred, const unsigned char *id_ptr, size_t id_len)
816
710k
{
817
710k
        fido_blob_t id_blob;
818
710k
        fido_blob_t *list_ptr;
819
820
710k
        memset(&id_blob, 0, sizeof(id_blob));
821
822
710k
        if (fido_blob_set(&id_blob, id_ptr, id_len) < 0)
823
2.80k
                return (FIDO_ERR_INVALID_ARGUMENT);
824
825
707k
        if (cred->excl.len == SIZE_MAX) {
826
0
                free(id_blob.ptr);
827
0
                return (FIDO_ERR_INVALID_ARGUMENT);
828
0
        }
829
830
707k
        if ((list_ptr = recallocarray(cred->excl.ptr, cred->excl.len,
831
707k
            cred->excl.len + 1, sizeof(fido_blob_t))) == NULL) {
832
2.11k
                free(id_blob.ptr);
833
2.11k
                return (FIDO_ERR_INTERNAL);
834
2.11k
        }
835
836
705k
        list_ptr[cred->excl.len++] = id_blob;
837
705k
        cred->excl.ptr = list_ptr;
838
839
705k
        return (FIDO_OK);
840
707k
}
841
842
int
843
fido_cred_empty_exclude_list(fido_cred_t *cred)
844
112k
{
845
112k
        fido_free_blob_array(&cred->excl);
846
112k
        memset(&cred->excl, 0, sizeof(cred->excl));
847
848
112k
        return (FIDO_OK);
849
112k
}
850
851
int
852
fido_cred_set_clientdata(fido_cred_t *cred, const unsigned char *data,
853
    size_t data_len)
854
0
{
855
0
        if (!fido_blob_is_empty(&cred->cdh) ||
856
0
            fido_blob_set(&cred->cd, data, data_len) < 0) {
857
0
                return (FIDO_ERR_INVALID_ARGUMENT);
858
0
        }
859
0
        if (fido_sha256(&cred->cdh, data, data_len) < 0) {
860
0
                fido_blob_reset(&cred->cd);
861
0
                return (FIDO_ERR_INTERNAL);
862
0
        }
863
864
0
        return (FIDO_OK);
865
0
}
866
867
int
868
fido_cred_set_clientdata_hash(fido_cred_t *cred, const unsigned char *hash,
869
    size_t hash_len)
870
63.2k
{
871
63.2k
        if (!fido_blob_is_empty(&cred->cd) ||
872
63.2k
            fido_blob_set(&cred->cdh, hash, hash_len) < 0)
873
4.86k
                return (FIDO_ERR_INVALID_ARGUMENT);
874
875
58.3k
        return (FIDO_OK);
876
63.2k
}
877
878
int
879
fido_cred_set_rp(fido_cred_t *cred, const char *id, const char *name)
880
63.2k
{
881
63.2k
        fido_rp_t *rp = &cred->rp;
882
883
63.2k
        if (rp->id != NULL) {
884
17.3k
                free(rp->id);
885
17.3k
                rp->id = NULL;
886
17.3k
        }
887
63.2k
        if (rp->name != NULL) {
888
17.3k
                free(rp->name);
889
17.3k
                rp->name = NULL;
890
17.3k
        }
891
892
63.2k
        if (id != NULL && (rp->id = strdup(id)) == NULL)
893
378
                goto fail;
894
62.8k
        if (name != NULL && (rp->name = strdup(name)) == NULL)
895
191
                goto fail;
896
897
62.6k
        return (FIDO_OK);
898
569
fail:
899
569
        free(rp->id);
900
569
        free(rp->name);
901
569
        rp->id = NULL;
902
569
        rp->name = NULL;
903
904
569
        return (FIDO_ERR_INTERNAL);
905
62.8k
}
906
907
int
908
fido_cred_set_user(fido_cred_t *cred, const unsigned char *user_id,
909
    size_t user_id_len, const char *name, const char *display_name,
910
    const char *icon)
911
41.1k
{
912
41.1k
        fido_user_t *up = &cred->user;
913
914
41.1k
        if (up->id.ptr != NULL) {
915
17.2k
                free(up->id.ptr);
916
17.2k
                up->id.ptr = NULL;
917
17.2k
                up->id.len = 0;
918
17.2k
        }
919
41.1k
        if (up->name != NULL) {
920
17.2k
                free(up->name);
921
17.2k
                up->name = NULL;
922
17.2k
        }
923
41.1k
        if (up->display_name != NULL) {
924
17.2k
                free(up->display_name);
925
17.2k
                up->display_name = NULL;
926
17.2k
        }
927
41.1k
        if (up->icon != NULL) {
928
17.2k
                free(up->icon);
929
17.2k
                up->icon = NULL;
930
17.2k
        }
931
932
41.1k
        if (user_id != NULL && fido_blob_set(&up->id, user_id, user_id_len) < 0)
933
231
                goto fail;
934
40.9k
        if (name != NULL && (up->name = strdup(name)) == NULL)
935
150
                goto fail;
936
40.8k
        if (display_name != NULL &&
937
40.8k
            (up->display_name = strdup(display_name)) == NULL)
938
116
                goto fail;
939
40.6k
        if (icon != NULL && (up->icon = strdup(icon)) == NULL)
940
158
                goto fail;
941
942
40.5k
        return (FIDO_OK);
943
655
fail:
944
655
        free(up->id.ptr);
945
655
        free(up->name);
946
655
        free(up->display_name);
947
655
        free(up->icon);
948
949
655
        up->id.ptr = NULL;
950
655
        up->id.len = 0;
951
655
        up->name = NULL;
952
655
        up->display_name = NULL;
953
655
        up->icon = NULL;
954
955
655
        return (FIDO_ERR_INTERNAL);
956
40.6k
}
957
958
int
959
fido_cred_set_extensions(fido_cred_t *cred, int ext)
960
29.7k
{
961
29.7k
        if (ext == 0)
962
1.21k
                cred->ext.mask = 0;
963
28.5k
        else {
964
28.5k
                if ((ext & FIDO_EXT_CRED_MASK) != ext)
965
18.1k
                        return (FIDO_ERR_INVALID_ARGUMENT);
966
10.3k
                cred->ext.mask |= ext;
967
10.3k
        }
968
969
11.5k
        return (FIDO_OK);
970
29.7k
}
971
972
int
973
fido_cred_set_options(fido_cred_t *cred, bool rk, bool uv)
974
0
{
975
0
        cred->rk = rk ? FIDO_OPT_TRUE : FIDO_OPT_FALSE;
976
0
        cred->uv = uv ? FIDO_OPT_TRUE : FIDO_OPT_FALSE;
977
978
0
        return (FIDO_OK);
979
0
}
980
981
int
982
fido_cred_set_rk(fido_cred_t *cred, fido_opt_t rk)
983
11.7k
{
984
11.7k
        cred->rk = rk;
985
986
11.7k
        return (FIDO_OK);
987
11.7k
}
988
989
int
990
fido_cred_set_uv(fido_cred_t *cred, fido_opt_t uv)
991
11.9k
{
992
11.9k
        cred->uv = uv;
993
994
11.9k
        return (FIDO_OK);
995
11.9k
}
996
997
int
998
fido_cred_set_entattest(fido_cred_t *cred, int ea)
999
16.6k
{
1000
16.6k
        if (ea != 0 && ea != FIDO_ENTATTEST_VENDOR &&
1001
16.6k
            ea != FIDO_ENTATTEST_PLATFORM)
1002
3.79k
                return (FIDO_ERR_INVALID_ARGUMENT);
1003
1004
12.9k
        cred->ea.mode = ea;
1005
1006
12.9k
        return (FIDO_OK);
1007
16.6k
}
1008
1009
int
1010
fido_cred_set_prot(fido_cred_t *cred, int prot)
1011
38.7k
{
1012
38.7k
        if (prot == 0) {
1013
22.5k
                cred->ext.mask &= ~FIDO_EXT_CRED_PROTECT;
1014
22.5k
                cred->ext.prot = 0;
1015
22.5k
        } else {
1016
16.1k
                if (prot != FIDO_CRED_PROT_UV_OPTIONAL &&
1017
16.1k
                    prot != FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID &&
1018
16.1k
                    prot != FIDO_CRED_PROT_UV_REQUIRED)
1019
167
                        return (FIDO_ERR_INVALID_ARGUMENT);
1020
1021
16.0k
                cred->ext.mask |= FIDO_EXT_CRED_PROTECT;
1022
16.0k
                cred->ext.prot = prot;
1023
16.0k
        }
1024
1025
38.5k
        return (FIDO_OK);
1026
38.7k
}
1027
1028
int
1029
fido_cred_set_pin_minlen(fido_cred_t *cred, size_t len)
1030
24.3k
{
1031
24.3k
        if (len == 0)
1032
18.3k
                cred->ext.mask &= ~FIDO_EXT_MINPINLEN;
1033
6.03k
        else
1034
6.03k
                cred->ext.mask |= FIDO_EXT_MINPINLEN;
1035
1036
24.3k
        cred->ext.minpinlen = len;
1037
1038
24.3k
        return (FIDO_OK);
1039
24.3k
}
1040
1041
int
1042
fido_cred_set_blob(fido_cred_t *cred, const unsigned char *ptr, size_t len)
1043
4.54k
{
1044
4.54k
        if (ptr == NULL || len == 0)
1045
5
                return (FIDO_ERR_INVALID_ARGUMENT);
1046
4.54k
        if (fido_blob_set(&cred->blob, ptr, len) < 0)
1047
9
                return (FIDO_ERR_INTERNAL);
1048
1049
4.53k
        cred->ext.mask |= FIDO_EXT_CRED_BLOB;
1050
1051
4.53k
        return (FIDO_OK);
1052
4.54k
}
1053
1054
int
1055
fido_cred_set_fmt(fido_cred_t *cred, const char *fmt)
1056
4.73k
{
1057
4.73k
        free(cred->fmt);
1058
4.73k
        cred->fmt = NULL;
1059
1060
4.73k
        if (fmt == NULL)
1061
0
                return (FIDO_ERR_INVALID_ARGUMENT);
1062
1063
4.73k
        if (strcmp(fmt, "packed") && strcmp(fmt, "fido-u2f") &&
1064
4.73k
            strcmp(fmt, "none") && strcmp(fmt, "tpm"))
1065
0
                return (FIDO_ERR_INVALID_ARGUMENT);
1066
1067
4.73k
        if ((cred->fmt = strdup(fmt)) == NULL)
1068
34
                return (FIDO_ERR_INTERNAL);
1069
1070
4.70k
        return (FIDO_OK);
1071
4.73k
}
1072
1073
int
1074
fido_cred_set_type(fido_cred_t *cred, int cose_alg)
1075
63.2k
{
1076
63.2k
        if (cred->type != 0)
1077
17.4k
                return (FIDO_ERR_INVALID_ARGUMENT);
1078
45.7k
        if (cose_alg != COSE_ES256 && cose_alg != COSE_ES384 &&
1079
45.7k
            cose_alg != COSE_RS256 && cose_alg != COSE_EDDSA)
1080
0
                return (FIDO_ERR_INVALID_ARGUMENT);
1081
1082
45.7k
        cred->type = cose_alg;
1083
1084
45.7k
        return (FIDO_OK);
1085
45.7k
}
1086
1087
int
1088
fido_cred_type(const fido_cred_t *cred)
1089
24.6k
{
1090
24.6k
        return (cred->type);
1091
24.6k
}
1092
1093
uint8_t
1094
fido_cred_flags(const fido_cred_t *cred)
1095
19.6k
{
1096
19.6k
        return (cred->authdata.flags);
1097
19.6k
}
1098
1099
uint32_t
1100
fido_cred_sigcount(const fido_cred_t *cred)
1101
19.6k
{
1102
19.6k
        return (cred->authdata.sigcount);
1103
19.6k
}
1104
1105
const unsigned char *
1106
fido_cred_clientdata_hash_ptr(const fido_cred_t *cred)
1107
19.7k
{
1108
19.7k
        return (cred->cdh.ptr);
1109
19.7k
}
1110
1111
size_t
1112
fido_cred_clientdata_hash_len(const fido_cred_t *cred)
1113
19.7k
{
1114
19.7k
        return (cred->cdh.len);
1115
19.7k
}
1116
1117
const unsigned char *
1118
fido_cred_x5c_ptr(const fido_cred_t *cred)
1119
19.7k
{
1120
19.7k
        return (fido_cred_x5c_list_ptr(cred, 0));
1121
19.7k
}
1122
1123
size_t
1124
fido_cred_x5c_len(const fido_cred_t *cred)
1125
19.7k
{
1126
19.7k
        return (fido_cred_x5c_list_len(cred, 0));
1127
19.7k
}
1128
1129
size_t
1130
fido_cred_x5c_list_count(const fido_cred_t *cred)
1131
42.6k
{
1132
42.6k
        return (cred->attstmt.x5c.len);
1133
42.6k
}
1134
1135
const unsigned char *
1136
fido_cred_x5c_list_ptr(const fido_cred_t *cred, size_t i)
1137
42.7k
{
1138
42.7k
        if (i >= cred->attstmt.x5c.len)
1139
36.8k
                return (NULL);
1140
1141
5.98k
        return (cred->attstmt.x5c.ptr[i].ptr);
1142
42.7k
}
1143
1144
size_t
1145
fido_cred_x5c_list_len(const fido_cred_t *cred, size_t i)
1146
42.7k
{
1147
42.7k
        if (i >= cred->attstmt.x5c.len)
1148
36.8k
                return (0);
1149
1150
5.98k
        return (cred->attstmt.x5c.ptr[i].len);
1151
42.7k
}
1152
1153
const unsigned char *
1154
fido_cred_sig_ptr(const fido_cred_t *cred)
1155
19.7k
{
1156
19.7k
        return (cred->attstmt.sig.ptr);
1157
19.7k
}
1158
1159
size_t
1160
fido_cred_sig_len(const fido_cred_t *cred)
1161
19.7k
{
1162
19.7k
        return (cred->attstmt.sig.len);
1163
19.7k
}
1164
1165
const unsigned char *
1166
fido_cred_authdata_ptr(const fido_cred_t *cred)
1167
28.4k
{
1168
28.4k
        return (cred->authdata_cbor.ptr);
1169
28.4k
}
1170
1171
size_t
1172
fido_cred_authdata_len(const fido_cred_t *cred)
1173
28.4k
{
1174
28.4k
        return (cred->authdata_cbor.len);
1175
28.4k
}
1176
1177
const unsigned char *
1178
fido_cred_authdata_raw_ptr(const fido_cred_t *cred)
1179
19.7k
{
1180
19.7k
        return (cred->authdata_raw.ptr);
1181
19.7k
}
1182
1183
size_t
1184
fido_cred_authdata_raw_len(const fido_cred_t *cred)
1185
19.7k
{
1186
19.7k
        return (cred->authdata_raw.len);
1187
19.7k
}
1188
1189
const unsigned char *
1190
fido_cred_attstmt_ptr(const fido_cred_t *cred)
1191
28.4k
{
1192
28.4k
        return (cred->attstmt.cbor.ptr);
1193
28.4k
}
1194
1195
size_t
1196
fido_cred_attstmt_len(const fido_cred_t *cred)
1197
28.4k
{
1198
28.4k
        return (cred->attstmt.cbor.len);
1199
28.4k
}
1200
1201
const unsigned char *
1202
fido_cred_pubkey_ptr(const fido_cred_t *cred)
1203
24.6k
{
1204
24.6k
        const void *ptr;
1205
1206
24.6k
        switch (cred->attcred.type) {
1207
4.70k
        case COSE_ES256:
1208
4.70k
                ptr = &cred->attcred.pubkey.es256;
1209
4.70k
                break;
1210
420
        case COSE_ES384:
1211
420
                ptr = &cred->attcred.pubkey.es384;
1212
420
                break;
1213
285
        case COSE_RS256:
1214
285
                ptr = &cred->attcred.pubkey.rs256;
1215
285
                break;
1216
790
        case COSE_EDDSA:
1217
790
                ptr = &cred->attcred.pubkey.eddsa;
1218
790
                break;
1219
18.4k
        default:
1220
18.4k
                ptr = NULL;
1221
18.4k
                break;
1222
24.6k
        }
1223
1224
24.6k
        return (ptr);
1225
24.6k
}
1226
1227
size_t
1228
fido_cred_pubkey_len(const fido_cred_t *cred)
1229
24.6k
{
1230
24.6k
        size_t len;
1231
1232
24.6k
        switch (cred->attcred.type) {
1233
4.70k
        case COSE_ES256:
1234
4.70k
                len = sizeof(cred->attcred.pubkey.es256);
1235
4.70k
                break;
1236
420
        case COSE_ES384:
1237
420
                len = sizeof(cred->attcred.pubkey.es384);
1238
420
                break;
1239
285
        case COSE_RS256:
1240
285
                len = sizeof(cred->attcred.pubkey.rs256);
1241
285
                break;
1242
790
        case COSE_EDDSA:
1243
790
                len = sizeof(cred->attcred.pubkey.eddsa);
1244
790
                break;
1245
18.4k
        default:
1246
18.4k
                len = 0;
1247
18.4k
                break;
1248
24.6k
        }
1249
1250
24.6k
        return (len);
1251
24.6k
}
1252
1253
const unsigned char *
1254
fido_cred_id_ptr(const fido_cred_t *cred)
1255
44.4k
{
1256
44.4k
        return (cred->attcred.id.ptr);
1257
44.4k
}
1258
1259
size_t
1260
fido_cred_id_len(const fido_cred_t *cred)
1261
44.4k
{
1262
44.4k
        return (cred->attcred.id.len);
1263
44.4k
}
1264
1265
const unsigned char *
1266
fido_cred_aaguid_ptr(const fido_cred_t *cred)
1267
19.6k
{
1268
19.6k
        return (cred->attcred.aaguid);
1269
19.6k
}
1270
1271
size_t
1272
fido_cred_aaguid_len(const fido_cred_t *cred)
1273
19.6k
{
1274
19.6k
        return (sizeof(cred->attcred.aaguid));
1275
19.6k
}
1276
1277
int
1278
fido_cred_prot(const fido_cred_t *cred)
1279
24.8k
{
1280
24.8k
        return (cred->ext.prot);
1281
24.8k
}
1282
1283
size_t
1284
fido_cred_pin_minlen(const fido_cred_t *cred)
1285
39.4k
{
1286
39.4k
        return (cred->ext.minpinlen);
1287
39.4k
}
1288
1289
const char *
1290
fido_cred_fmt(const fido_cred_t *cred)
1291
28.4k
{
1292
28.4k
        return (cred->fmt);
1293
28.4k
}
1294
1295
const char *
1296
fido_cred_rp_id(const fido_cred_t *cred)
1297
19.7k
{
1298
19.7k
        return (cred->rp.id);
1299
19.7k
}
1300
1301
const char *
1302
fido_cred_rp_name(const fido_cred_t *cred)
1303
19.7k
{
1304
19.7k
        return (cred->rp.name);
1305
19.7k
}
1306
1307
const char *
1308
fido_cred_user_name(const fido_cred_t *cred)
1309
24.6k
{
1310
24.6k
        return (cred->user.name);
1311
24.6k
}
1312
1313
const char *
1314
fido_cred_display_name(const fido_cred_t *cred)
1315
24.6k
{
1316
24.6k
        return (cred->user.display_name);
1317
24.6k
}
1318
1319
const unsigned char *
1320
fido_cred_user_id_ptr(const fido_cred_t *cred)
1321
24.6k
{
1322
24.6k
        return (cred->user.id.ptr);
1323
24.6k
}
1324
1325
size_t
1326
fido_cred_user_id_len(const fido_cred_t *cred)
1327
24.6k
{
1328
24.6k
        return (cred->user.id.len);
1329
24.6k
}
1330
1331
const unsigned char *
1332
fido_cred_largeblob_key_ptr(const fido_cred_t *cred)
1333
19.6k
{
1334
19.6k
        return (cred->largeblob_key.ptr);
1335
19.6k
}
1336
1337
size_t
1338
fido_cred_largeblob_key_len(const fido_cred_t *cred)
1339
19.6k
{
1340
19.6k
        return (cred->largeblob_key.len);
1341
19.6k
}
1342
1343
bool
1344
fido_cred_entattest(const fido_cred_t *cred)
1345
19.6k
{
1346
19.6k
        return (cred->ea.att);
1347
19.6k
}