Coverage Report

Created: 2022-04-27 14:33

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