## Coverage Report

#### Created: 2023-09-23 17:42

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