Coverage Report

Created: 2021-10-21 13:35

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