Coverage Report

Created: 2022-07-22 12:05

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