Coverage Report

Created: 2022-01-17 10:46

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