Coverage Report

Created: 2025-03-01 02:43

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