Coverage Report

Created: 2024-06-03 09:43

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