## Coverage Report

#### Created: 2025-03-01 02:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /libfido2/src/assert.c

    Line
    Count
    Source
    1
    /*
    2
     * Copyright (c) 2018-2023 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
    10
    #include "fido.h"
    11
    #include "fido/es256.h"
    12
    #include "fido/rs256.h"
    13
    #include "fido/eddsa.h"
    14
    15
    static int
    16
    adjust_assert_count(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    17
    6.22k
    {
    18
    6.22k
            fido_assert_t   *assert = arg;
    19
    6.22k
            uint64_t         n;
    20
    21
            /* numberOfCredentials; see section 6.2 */
    22
    6.22k
            if (cbor_isa_uint(key) == false ||
    23
    6.22k
                cbor_int_get_width(key) != CBOR_INT_8 ||
    24
    6.22k
                cbor_get_uint8(key) != 5) {
    25
    5.70k
                    fido_log_debug("%s: cbor_type", __func__);
    26
    5.70k
                    return (0); /* ignore */
    27
    5.70k
            }
    28
    29
    516
            if (cbor_decode_uint64(val, &n) < 0 || n > SIZE_MAX) {
    30
    4
                    fido_log_debug("%s: cbor_decode_uint64", __func__);
    31
    4
                    return (-1);
    32
    4
            }
    33
    34
    512
            if (assert->stmt_len != 0 || assert->stmt_cnt != 1 ||
    35
    512
                (size_t)n < assert->stmt_cnt) {
    36
    4
                    fido_log_debug("%s: stmt_len=%zu, stmt_cnt=%zu, n=%zu",
    37
    4
                        __func__, assert->stmt_len, assert->stmt_cnt, (size_t)n);
    38
    4
                    return (-1);
    39
    4
            }
    40
    41
    508
            if (fido_assert_set_count(assert, (size_t)n) != FIDO_OK) {
    42
    112
                    fido_log_debug("%s: fido_assert_set_count", __func__);
    43
    112
                    return (-1);
    44
    112
            }
    45
    46
    396
            assert->stmt_len = 0; /* XXX */
    47
    48
    396
            return (0);
    49
    508
    }
    50
    51
    static int
    52
    parse_assert_reply(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    53
    9.97k
    {
    54
    9.97k
            fido_assert_stmt *stmt = arg;
    55
    56
    9.97k
            if (cbor_isa_uint(key) == false ||
    57
    9.97k
                cbor_int_get_width(key) != CBOR_INT_8) {
    58
    300
                    fido_log_debug("%s: cbor type", __func__);
    59
    300
                    return (0); /* ignore */
    60
    300
            }
    61
    62
    9.67k
            switch (cbor_get_uint8(key)) {
    63
    2.75k
            case 1: /* credential id */
    64
    2.75k
                    return (cbor_decode_cred_id(val, &stmt->id));
    65
    2.38k
            case 2: /* authdata */
    66
    2.38k
                    if (fido_blob_decode(val, &stmt->authdata_raw) < 0) {
    67
    14
                            fido_log_debug("%s: fido_blob_decode", __func__);
    68
    14
                            return (-1);
    69
    14
                    }
    70
    2.37k
                    return (cbor_decode_assert_authdata(val, &stmt->authdata_cbor,
    71
    2.37k
                        &stmt->authdata, &stmt->authdata_ext));
    72
    2.21k
            case 3: /* signature */
    73
    2.21k
                    return (fido_blob_decode(val, &stmt->sig));
    74
    1.78k
            case 4: /* user attributes */
    75
    1.78k
                    return (cbor_decode_user(val, &stmt->user));
    76
    3
            case 7: /* large blob key */
    77
    3
                    return (fido_blob_decode(val, &stmt->largeblob_key));
    78
    534
            default: /* ignore */
    79
    534
                    fido_log_debug("%s: cbor type", __func__);
    80
    534
                    return (0);
    81
    9.67k
            }
    82
    9.67k
    }
    83
    84
    static int
    85
    fido_dev_get_assert_tx(fido_dev_t *dev, fido_assert_t *assert,
    86
        const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin, int *ms)
    87
    3.57k
    {
    88
    3.57k
            fido_blob_t      f;
    89
    3.57k
            fido_opt_t       uv = assert->uv;
    90
    3.57k
            cbor_item_t     *argv[7];
    91
    3.57k
            const uint8_t    cmd = CTAP_CBOR_ASSERT;
    92
    3.57k
            int              r;
    93
    94
    3.57k
            memset(argv, 0, sizeof(argv));
    95
    3.57k
            memset(&f, 0, sizeof(f));
    96
    97
            /* do we have everything we need? */
    98
    3.57k
            if (assert->rp_id == NULL || assert->cdh.ptr == NULL) {
    99
    0
                    fido_log_debug("%s: rp_id=%p, cdh.ptr=%p", __func__,
    100
    0
                        (void *)assert->rp_id, (void *)assert->cdh.ptr);
    101
    0
                    r = FIDO_ERR_INVALID_ARGUMENT;
    102
    0
                    goto fail;
    103
    0
            }
    104
    105
    3.57k
            if ((argv[0] = cbor_build_string(assert->rp_id)) == NULL ||
    106
    3.57k
                (argv[1] = fido_blob_encode(&assert->cdh)) == NULL) {
    107
    22
                    fido_log_debug("%s: cbor encode", __func__);
    108
    22
                    r = FIDO_ERR_INTERNAL;
    109
    22
                    goto fail;
    110
    22
            }
    111
    112
            /* allowed credentials */
    113
    3.55k
            if (assert->allow_list.len) {
    114
    1.89k
                    const fido_blob_array_t *cl = &assert->allow_list;
    115
    1.89k
                    if ((argv[2] = cbor_encode_pubkey_list(cl)) == NULL) {
    116
    321
                            fido_log_debug("%s: cbor_encode_pubkey_list", __func__);
    117
    321
                            r = FIDO_ERR_INTERNAL;
    118
    321
                            goto fail;
    119
    321
                    }
    120
    1.89k
            }
    121
    122
    3.23k
            if (assert->ext.mask)
    123
    1.67k
                    if ((argv[3] = cbor_encode_assert_ext(dev, &assert->ext, ecdh,
    124
    1.67k
                        pk)) == NULL) {
    125
    221
                            fido_log_debug("%s: cbor_encode_assert_ext", __func__);
    126
    221
                            r = FIDO_ERR_INTERNAL;
    127
    221
                            goto fail;
    128
    221
                    }
    129
    130
            /* user verification */
    131
    3.01k
            if (pin != NULL || (uv == FIDO_OPT_TRUE &&
    132
    1.81k
                fido_dev_supports_permissions(dev))) {
    133
    1.23k
                    if ((r = cbor_add_uv_params(dev, cmd, &assert->cdh, pk, ecdh,
    134
    1.23k
                        pin, assert->rp_id, &argv[5], &argv[6], ms)) != FIDO_OK) {
    135
    404
                            fido_log_debug("%s: cbor_add_uv_params", __func__);
    136
    404
                            goto fail;
    137
    404
                    }
    138
    828
                    uv = FIDO_OPT_OMIT;
    139
    828
            }
    140
    141
            /* options */
    142
    2.61k
            if (assert->up != FIDO_OPT_OMIT || uv != FIDO_OPT_OMIT)
    143
    1.06k
                    if ((argv[4] = cbor_encode_assert_opt(assert->up, uv)) == NULL) {
    144
    16
                            fido_log_debug("%s: cbor_encode_assert_opt", __func__);
    145
    16
                            r = FIDO_ERR_INTERNAL;
    146
    16
                            goto fail;
    147
    16
                    }
    148
    149
            /* frame and transmit */
    150
    2.59k
            if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
    151
    2.59k
                fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
    152
    370
                    fido_log_debug("%s: fido_tx", __func__);
    153
    370
                    r = FIDO_ERR_TX;
    154
    370
                    goto fail;
    155
    370
            }
    156
    157
    2.22k
            r = FIDO_OK;
    158
    3.57k
    fail:
    159
    3.57k
            cbor_vector_free(argv, nitems(argv));
    160
    3.57k
            free(f.ptr);
    161
    162
    3.57k
            return (r);
    163
    2.22k
    }
    164
    165
    static int
    166
    fido_dev_get_assert_rx(fido_dev_t *dev, fido_assert_t *assert, int *ms)
    167
    2.22k
    {
    168
    2.22k
            unsigned char   *msg;
    169
    2.22k
            int              msglen;
    170
    2.22k
            int              r;
    171
    172
    2.22k
            fido_assert_reset_rx(assert);
    173
    174
    2.22k
            if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
    175
    3
                    r = FIDO_ERR_INTERNAL;
    176
    3
                    goto out;
    177
    3
            }
    178
    179
    2.22k
            if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
    180
    169
                    fido_log_debug("%s: fido_rx", __func__);
    181
    169
                    r = FIDO_ERR_RX;
    182
    169
                    goto out;
    183
    169
            }
    184
    185
            /* start with room for a single assertion */
    186
    2.05k
            if ((assert->stmt = calloc(1, sizeof(fido_assert_stmt))) == NULL) {
    187
    4
                    r = FIDO_ERR_INTERNAL;
    188
    4
                    goto out;
    189
    4
            }
    190
    2.04k
            assert->stmt_len = 0;
    191
    2.04k
            assert->stmt_cnt = 1;
    192
    193
            /* adjust as needed */
    194
    2.04k
            if ((r = cbor_parse_reply(msg, (size_t)msglen, assert,
    195
    2.04k
                adjust_assert_count)) != FIDO_OK) {
    196
    245
                    fido_log_debug("%s: adjust_assert_count", __func__);
    197
    245
                    goto out;
    198
    245
            }
    199
    200
            /* parse the first assertion */
    201
    1.80k
            if ((r = cbor_parse_reply(msg, (size_t)msglen, &assert->stmt[0],
    202
    1.80k
                parse_assert_reply)) != FIDO_OK) {
    203
    152
                    fido_log_debug("%s: parse_assert_reply", __func__);
    204
    152
                    goto out;
    205
    152
            }
    206
    1.65k
            assert->stmt_len = 1;
    207
    208
    1.65k
            r = FIDO_OK;
    209
    2.22k
    out:
    210
    2.22k
            freezero(msg, FIDO_MAXMSG);
    211
    212
    2.22k
            return (r);
    213
    1.65k
    }
    214
    215
    static int
    216
    fido_get_next_assert_tx(fido_dev_t *dev, int *ms)
    217
    1.22k
    {
    218
    1.22k
            const unsigned char cbor[] = { CTAP_CBOR_NEXT_ASSERT };
    219
    220
    1.22k
            if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor), ms) < 0) {
    221
    10
                    fido_log_debug("%s: fido_tx", __func__);
    222
    10
                    return (FIDO_ERR_TX);
    223
    10
            }
    224
    225
    1.21k
            return (FIDO_OK);
    226
    1.22k
    }
    227
    228
    static int
    229
    fido_get_next_assert_rx(fido_dev_t *dev, fido_assert_t *assert, int *ms)
    230
    1.21k
    {
    231
    1.21k
            unsigned char   *msg;
    232
    1.21k
            int              msglen;
    233
    1.21k
            int              r;
    234
    235
    1.21k
            if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
    236
    4
                    r = FIDO_ERR_INTERNAL;
    237
    4
                    goto out;
    238
    4
            }
    239
    240
    1.21k
            if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
    241
    49
                    fido_log_debug("%s: fido_rx", __func__);
    242
    49
                    r = FIDO_ERR_RX;
    243
    49
                    goto out;
    244
    49
            }
    245
    246
            /* sanity check */
    247
    1.16k
            if (assert->stmt_len >= assert->stmt_cnt) {
    248
    0
                    fido_log_debug("%s: stmt_len=%zu, stmt_cnt=%zu", __func__,
    249
    0
                        assert->stmt_len, assert->stmt_cnt);
    250
    0
                    r = FIDO_ERR_INTERNAL;
    251
    0
                    goto out;
    252
    0
            }
    253
    254
    1.16k
            if ((r = cbor_parse_reply(msg, (size_t)msglen,
    255
    1.16k
                &assert->stmt[assert->stmt_len], parse_assert_reply)) != FIDO_OK) {
    256
    113
                    fido_log_debug("%s: parse_assert_reply", __func__);
    257
    113
                    goto out;
    258
    113
            }
    259
    260
    1.05k
            r = FIDO_OK;
    261
    1.21k
    out:
    262
    1.21k
            freezero(msg, FIDO_MAXMSG);
    263
    264
    1.21k
            return (r);
    265
    1.05k
    }
    266
    267
    static int
    268
    fido_dev_get_assert_wait(fido_dev_t *dev, fido_assert_t *assert,
    269
        const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin, int *ms)
    270
    3.57k
    {
    271
    3.57k
            int r;
    272
    273
    3.57k
            if ((r = fido_dev_get_assert_tx(dev, assert, pk, ecdh, pin,
    274
    3.57k
                ms)) != FIDO_OK ||
    275
    3.57k
                (r = fido_dev_get_assert_rx(dev, assert, ms)) != FIDO_OK)
    276
    1.92k
                    return (r);
    277
    278
    2.70k
            while (assert->stmt_len < assert->stmt_cnt) {
    279
    1.22k
                    if ((r = fido_get_next_assert_tx(dev, ms)) != FIDO_OK ||
    280
    1.22k
                        (r = fido_get_next_assert_rx(dev, assert, ms)) != FIDO_OK)
    281
    176
                            return (r);
    282
    1.05k
                    assert->stmt_len++;
    283
    1.05k
            }
    284
    285
    1.47k
            return (FIDO_OK);
    286
    1.65k
    }
    287
    288
    static int
    289
    decrypt_hmac_secrets(const fido_dev_t *dev, fido_assert_t *assert,
    290
        const fido_blob_t *key)
    291
    148
    {
    292
    454
            for (size_t i = 0; i < assert->stmt_cnt; i++) {
    293
    358
                    fido_assert_stmt *stmt = &assert->stmt[i];
    294
    358
                    if (stmt->authdata_ext.hmac_secret_enc.ptr != NULL) {
    295
    198
                            if (aes256_cbc_dec(dev, key,
    296
    198
                                &stmt->authdata_ext.hmac_secret_enc,
    297
    198
                                &stmt->hmac_secret) < 0) {
    298
    52
                                    fido_log_debug("%s: aes256_cbc_dec %zu",
    299
    52
                                        __func__, i);
    300
    52
                                    return (-1);
    301
    52
                            }
    302
    198
                    }
    303
    358
            }
    304
    305
    96
            return (0);
    306
    148
    }
    307
    308
    int
    309
    fido_dev_get_assert(fido_dev_t *dev, fido_assert_t *assert, const char *pin)
    310
    8.50k
    {
    311
    8.50k
            fido_blob_t     *ecdh = NULL;
    312
    8.50k
            es256_pk_t      *pk = NULL;
    313
    8.50k
            int              ms = dev->timeout_ms;
    314
    8.50k
            int              r;
    315
    316
    #ifdef USE_WINHELLO
    317
            if (dev->flags & FIDO_DEV_WINHELLO)
    318
                    return (fido_winhello_get_assert(dev, assert, pin, ms));
    319
    #endif
    320
    321
    8.50k
            if (assert->rp_id == NULL || assert->cdh.ptr == NULL) {
    322
    29
                    fido_log_debug("%s: rp_id=%p, cdh.ptr=%p", __func__,
    323
    29
                        (void *)assert->rp_id, (void *)assert->cdh.ptr);
    324
    29
                    return (FIDO_ERR_INVALID_ARGUMENT);
    325
    29
            }
    326
    327
    8.47k
            if (fido_dev_is_fido2(dev) == false) {
    328
    3.93k
                    if (pin != NULL || assert->ext.mask != 0)
    329
    1.08k
                            return (FIDO_ERR_UNSUPPORTED_OPTION);
    330
    2.85k
                    return (u2f_authenticate(dev, assert, &ms));
    331
    3.93k
            }
    332
    333
    4.53k
            if (pin != NULL || (assert->uv == FIDO_OPT_TRUE &&
    334
    2.60k
                fido_dev_supports_permissions(dev)) ||
    335
    4.53k
                (assert->ext.mask & FIDO_EXT_HMAC_SECRET)) {
    336
    2.79k
                    if ((r = fido_do_ecdh(dev, &pk, &ecdh, &ms)) != FIDO_OK) {
    337
    956
                            fido_log_debug("%s: fido_do_ecdh", __func__);
    338
    956
                            goto fail;
    339
    956
                    }
    340
    2.79k
            }
    341
    342
    3.57k
            r = fido_dev_get_assert_wait(dev, assert, pk, ecdh, pin, &ms);
    343
    3.57k
            if (r == FIDO_OK && (assert->ext.mask & FIDO_EXT_HMAC_SECRET))
    344
    148
                    if (decrypt_hmac_secrets(dev, assert, ecdh) < 0) {
    345
    52
                            fido_log_debug("%s: decrypt_hmac_secrets", __func__);
    346
    52
                            r = FIDO_ERR_INTERNAL;
    347
    52
                            goto fail;
    348
    52
                    }
    349
    350
    4.53k
    fail:
    351
    4.53k
            es256_pk_free(&pk);
    352
    4.53k
            fido_blob_free(&ecdh);
    353
    354
    4.53k
            return (r);
    355
    3.57k
    }
    356
    357
    int
    358
    fido_check_flags(uint8_t flags, fido_opt_t up, fido_opt_t uv)
    359
    8.97k
    {
    360
    8.97k
            fido_log_debug("%s: flags=%02x", __func__, flags);
    361
    8.97k
            fido_log_debug("%s: up=%d, uv=%d", __func__, up, uv);
    362
    363
    8.97k
            if (up == FIDO_OPT_TRUE &&
    364
    8.97k
                (flags & CTAP_AUTHDATA_USER_PRESENT) == 0) {
    365
    130
                    fido_log_debug("%s: CTAP_AUTHDATA_USER_PRESENT", __func__);
    366
    130
                    return (-1); /* user not present */
    367
    130
            }
    368
    369
    8.84k
            if (uv == FIDO_OPT_TRUE &&
    370
    8.84k
                (flags & CTAP_AUTHDATA_USER_VERIFIED) == 0) {
    371
    134
                    fido_log_debug("%s: CTAP_AUTHDATA_USER_VERIFIED", __func__);
    372
    134
                    return (-1); /* user not verified */
    373
    134
            }
    374
    375
    8.70k
            return (0);
    376
    8.84k
    }
    377
    378
    static int
    379
    check_extensions(int authdata_ext, int ext)
    380
    3.34k
    {
    381
            /* XXX: largeBlobKey is not part of extensions map */
    382
    3.34k
            ext &= ~FIDO_EXT_LARGEBLOB_KEY;
    383
    3.34k
            if (authdata_ext != ext) {
    384
    164
                    fido_log_debug("%s: authdata_ext=0x%x != ext=0x%x", __func__,
    385
    164
                        authdata_ext, ext);
    386
    164
                    return (-1);
    387
    164
            }
    388
    389
    3.17k
            return (0);
    390
    3.34k
    }
    391
    392
    static int
    393
    get_es256_hash(fido_blob_t *dgst, const fido_blob_t *clientdata,
    394
        const fido_blob_t *authdata)
    395
    4.12k
    {
    396
    4.12k
            const EVP_MD    *md;
    397
    4.12k
            EVP_MD_CTX      *ctx = NULL;
    398
    399
    4.12k
            if (dgst->len < SHA256_DIGEST_LENGTH ||
    400
    4.12k
                (md = EVP_sha256()) == NULL ||
    401
    4.12k
                (ctx = EVP_MD_CTX_new()) == NULL ||
    402
    4.12k
                EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
    403
    4.12k
                EVP_DigestUpdate(ctx, authdata->ptr, authdata->len) != 1 ||
    404
    4.12k
                EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
    405
    4.12k
                EVP_DigestFinal_ex(ctx, dgst->ptr, NULL) != 1) {
    406
    128
                    EVP_MD_CTX_free(ctx);
    407
    128
                    return (-1);
    408
    128
            }
    409
    3.99k
            dgst->len = SHA256_DIGEST_LENGTH;
    410
    411
    3.99k
            EVP_MD_CTX_free(ctx);
    412
    413
    3.99k
            return (0);
    414
    4.12k
    }
    415
    416
    static int
    417
    get_es384_hash(fido_blob_t *dgst, const fido_blob_t *clientdata,
    418
        const fido_blob_t *authdata)
    419
    1.89k
    {
    420
    1.89k
            const EVP_MD    *md;
    421
    1.89k
            EVP_MD_CTX      *ctx = NULL;
    422
    423
    1.89k
            if (dgst->len < SHA384_DIGEST_LENGTH ||
    424
    1.89k
                (md = EVP_sha384()) == NULL ||
    425
    1.89k
                (ctx = EVP_MD_CTX_new()) == NULL ||
    426
    1.89k
                EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
    427
    1.89k
                EVP_DigestUpdate(ctx, authdata->ptr, authdata->len) != 1 ||
    428
    1.89k
                EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
    429
    1.89k
                EVP_DigestFinal_ex(ctx, dgst->ptr, NULL) != 1) {
    430
    91
                    EVP_MD_CTX_free(ctx);
    431
    91
                    return (-1);
    432
    91
            }
    433
    1.80k
            dgst->len = SHA384_DIGEST_LENGTH;
    434
    435
    1.80k
            EVP_MD_CTX_free(ctx);
    436
    437
    1.80k
            return (0);
    438
    1.89k
    }
    439
    440
    static int
    441
    get_eddsa_hash(fido_blob_t *dgst, const fido_blob_t *clientdata,
    442
        const fido_blob_t *authdata)
    443
    706
    {
    444
    706
            if (SIZE_MAX - authdata->len < clientdata->len ||
    445
    706
                dgst->len < authdata->len + clientdata->len)
    446
    45
                    return (-1);
    447
    448
    661
            memcpy(dgst->ptr, authdata->ptr, authdata->len);
    449
    661
            memcpy(dgst->ptr + authdata->len, clientdata->ptr, clientdata->len);
    450
    661
            dgst->len = authdata->len + clientdata->len;
    451
    452
    661
            return (0);
    453
    706
    }
    454
    455
    int
    456
    fido_get_signed_hash(int cose_alg, fido_blob_t *dgst,
    457
        const fido_blob_t *clientdata, const fido_blob_t *authdata_cbor)
    458
    6.76k
    {
    459
    6.76k
            cbor_item_t             *item = NULL;
    460
    6.76k
            fido_blob_t              authdata;
    461
    6.76k
            struct cbor_load_result  cbor;
    462
    6.76k
            int                      ok = -1;
    463
    464
    6.76k
            fido_log_debug("%s: cose_alg=%d", __func__, cose_alg);
    465
    466
    6.76k
            if ((item = cbor_load(authdata_cbor->ptr, authdata_cbor->len,
    467
    6.76k
                &cbor)) == NULL || cbor_isa_bytestring(item) == false ||
    468
    6.76k
                cbor_bytestring_is_definite(item) == false) {
    469
    30
                    fido_log_debug("%s: authdata", __func__);
    470
    30
                    goto fail;
    471
    30
            }
    472
    6.73k
            authdata.ptr = cbor_bytestring_handle(item);
    473
    6.73k
            authdata.len = cbor_bytestring_length(item);
    474
    475
    6.73k
            switch (cose_alg) {
    476
    3.71k
            case COSE_ES256:
    477
    4.12k
            case COSE_RS256:
    478
    4.12k
                    ok = get_es256_hash(dgst, clientdata, &authdata);
    479
    4.12k
                    break;
    480
    1.89k
            case COSE_ES384:
    481
    1.89k
                    ok = get_es384_hash(dgst, clientdata, &authdata);
    482
    1.89k
                    break;
    483
    706
            case COSE_EDDSA:
    484
    706
                    ok = get_eddsa_hash(dgst, clientdata, &authdata);
    485
    706
                    break;
    486
    0
            default:
    487
    0
                    fido_log_debug("%s: unknown cose_alg", __func__);
    488
    0
                    break;
    489
    6.73k
            }
    490
    6.76k
    fail:
    491
    6.76k
            if (item != NULL)
    492
    6.73k
                    cbor_decref(&item);
    493
    494
    6.76k
            return (ok);
    495
    6.73k
    }
    496
    497
    int
    498
    fido_assert_verify(const fido_assert_t *assert, size_t idx, int cose_alg,
    499
        const void *pk)
    500
    155k
    {
    501
    155k
            unsigned char            buf[1024]; /* XXX */
    502
    155k
            fido_blob_t              dgst;
    503
    155k
            const fido_assert_stmt  *stmt = NULL;
    504
    155k
            int                      ok = -1;
    505
    155k
            int                      r;
    506
    507
    155k
            dgst.ptr = buf;
    508
    155k
            dgst.len = sizeof(buf);
    509
    510
    155k
            if (idx >= assert->stmt_len || pk == NULL) {
    511
    407
                    r = FIDO_ERR_INVALID_ARGUMENT;
    512
    407
                    goto out;
    513
    407
            }
    514
    515
    155k
            stmt = &assert->stmt[idx];
    516
    517
            /* do we have everything we need? */
    518
    155k
            if (assert->cdh.ptr == NULL || assert->rp_id == NULL ||
    519
    155k
                stmt->authdata_cbor.ptr == NULL || stmt->sig.ptr == NULL) {
    520
    151k
                    fido_log_debug("%s: cdh=%p, rp_id=%s, authdata=%p, sig=%p",
    521
    151k
                        __func__, (void *)assert->cdh.ptr, assert->rp_id,
    522
    151k
                        (void *)stmt->authdata_cbor.ptr, (void *)stmt->sig.ptr);
    523
    151k
                    r = FIDO_ERR_INVALID_ARGUMENT;
    524
    151k
                    goto out;
    525
    151k
            }
    526
    527
    3.59k
            if (fido_check_flags(stmt->authdata.flags, assert->up,
    528
    3.59k
                assert->uv) < 0) {
    529
    251
                    fido_log_debug("%s: fido_check_flags", __func__);
    530
    251
                    r = FIDO_ERR_INVALID_PARAM;
    531
    251
                    goto out;
    532
    251
            }
    533
    534
    3.34k
            if (check_extensions(stmt->authdata_ext.mask, assert->ext.mask) < 0) {
    535
    164
                    fido_log_debug("%s: check_extensions", __func__);
    536
    164
                    r = FIDO_ERR_INVALID_PARAM;
    537
    164
                    goto out;
    538
    164
            }
    539
    540
    3.17k
            if (fido_check_rp_id(assert->rp_id, stmt->authdata.rp_id_hash) != 0) {
    541
    394
                    fido_log_debug("%s: fido_check_rp_id", __func__);
    542
    394
                    r = FIDO_ERR_INVALID_PARAM;
    543
    394
                    goto out;
    544
    394
            }
    545
    546
    2.78k
            if (fido_get_signed_hash(cose_alg, &dgst, &assert->cdh,
    547
    2.78k
                &stmt->authdata_cbor) < 0) {
    548
    194
                    fido_log_debug("%s: fido_get_signed_hash", __func__);
    549
    194
                    r = FIDO_ERR_INTERNAL;
    550
    194
                    goto out;
    551
    194
            }
    552
    553
    2.58k
            switch (cose_alg) {
    554
    307
            case COSE_ES256:
    555
    307
                    ok = es256_pk_verify_sig(&dgst, pk, &stmt->sig);
    556
    307
                    break;
    557
    1.59k
            case COSE_ES384:
    558
    1.59k
                    ok = es384_pk_verify_sig(&dgst, pk, &stmt->sig);
    559
    1.59k
                    break;
    560
    270
            case COSE_RS256:
    561
    270
                    ok = rs256_pk_verify_sig(&dgst, pk, &stmt->sig);
    562
    270
                    break;
    563
    421
            case COSE_EDDSA:
    564
    421
                    ok = eddsa_pk_verify_sig(&dgst, pk, &stmt->sig);
    565
    421
                    break;
    566
    0
            default:
    567
    0
                    fido_log_debug("%s: unsupported cose_alg %d", __func__,
    568
    0
                        cose_alg);
    569
    0
                    r = FIDO_ERR_UNSUPPORTED_OPTION;
    570
    0
                    goto out;
    571
    2.58k
            }
    572
    573
    2.58k
            if (ok < 0)
    574
    2.58k
                    r = FIDO_ERR_INVALID_SIG;
    575
    0
            else
    576
    0
                    r = FIDO_OK;
    577
    155k
    out:
    578
    155k
            explicit_bzero(buf, sizeof(buf));
    579
    580
    155k
            return (r);
    581
    2.58k
    }
    582
    583
    int
    584
    fido_assert_set_clientdata(fido_assert_t *assert, const unsigned char *data,
    585
        size_t data_len)
    586
    0
    {
    587
    0
            if (!fido_blob_is_empty(&assert->cdh) ||
    588
    0
                fido_blob_set(&assert->cd, data, data_len) < 0) {
    589
    0
                    return (FIDO_ERR_INVALID_ARGUMENT);
    590
    0
            }
    591
    0
            if (fido_sha256(&assert->cdh, data, data_len) < 0) {
    592
    0
                    fido_blob_reset(&assert->cd);
    593
    0
                    return (FIDO_ERR_INTERNAL);
    594
    0
            }
    595
    596
    0
            return (FIDO_OK);
    597
    0
    }
    598
    599
    int
    600
    fido_assert_set_clientdata_hash(fido_assert_t *assert,
    601
        const unsigned char *hash, size_t hash_len)
    602
    172k
    {
    603
    172k
            if (!fido_blob_is_empty(&assert->cd) ||
    604
    172k
                fido_blob_set(&assert->cdh, hash, hash_len) < 0)
    605
    3.00k
                    return (FIDO_ERR_INVALID_ARGUMENT);
    606
    607
    169k
            return (FIDO_OK);
    608
    172k
    }
    609
    610
    int
    611
    fido_assert_set_hmac_salt(fido_assert_t *assert, const unsigned char *salt,
    612
        size_t salt_len)
    613
    17.0k
    {
    614
    17.0k
            if ((salt_len != 32 && salt_len != 64) ||
    615
    17.0k
                fido_blob_set(&assert->ext.hmac_salt, salt, salt_len) < 0)
    616
    16.1k
                    return (FIDO_ERR_INVALID_ARGUMENT);
    617
    618
    882
            return (FIDO_OK);
    619
    17.0k
    }
    620
    621
    int
    622
    fido_assert_set_hmac_secret(fido_assert_t *assert, size_t idx,
    623
        const unsigned char *secret, size_t secret_len)
    624
    0
    {
    625
    0
            if (idx >= assert->stmt_len || (secret_len != 32 && secret_len != 64) ||
    626
    0
                fido_blob_set(&assert->stmt[idx].hmac_secret, secret,
    627
    0
                secret_len) < 0)
    628
    0
                    return (FIDO_ERR_INVALID_ARGUMENT);
    629
    630
    0
            return (FIDO_OK);
    631
    0
    }
    632
    633
    int
    634
    fido_assert_set_rp(fido_assert_t *assert, const char *id)
    635
    172k
    {
    636
    172k
            if (assert->rp_id != NULL) {
    637
    8.48k
                    free(assert->rp_id);
    638
    8.48k
                    assert->rp_id = NULL;
    639
    8.48k
            }
    640
    641
    172k
            if (id == NULL)
    642
    2.52k
                    return (FIDO_ERR_INVALID_ARGUMENT);
    643
    644
    170k
            if ((assert->rp_id = strdup(id)) == NULL)
    645
    429
                    return (FIDO_ERR_INTERNAL);
    646
    647
    169k
            return (FIDO_OK);
    648
    170k
    }
    649
    650
    #ifdef USE_WINHELLO
    651
    int
    652
    fido_assert_set_winhello_appid(fido_assert_t *assert, const char *id)
    653
    {
    654
            if (assert->appid != NULL) {
    655
                    free(assert->appid);
    656
                    assert->appid = NULL;
    657
            }
    658
    659
            if (id == NULL)
    660
                    return (FIDO_ERR_INVALID_ARGUMENT);
    661
    662
            if ((assert->appid = strdup(id)) == NULL)
    663
                    return (FIDO_ERR_INTERNAL);
    664
    665
            return (FIDO_OK);
    666
    }
    667
    #else
    668
    int
    669
    fido_assert_set_winhello_appid(fido_assert_t *assert, const char *id)
    670
    0
    {
    671
    0
            (void)assert;
    672
    0
            (void)id;
    673
    674
    0
            return (FIDO_ERR_UNSUPPORTED_EXTENSION);
    675
    0
    }
    676
    #endif /* USE_WINHELLO */
    677
    678
    int
    679
    fido_assert_allow_cred(fido_assert_t *assert, const unsigned char *ptr,
    680
        size_t len)
    681
    320k
    {
    682
    320k
            fido_blob_t      id;
    683
    320k
            fido_blob_t     *list_ptr;
    684
    320k
            int              r;
    685
    686
    320k
            memset(&id, 0, sizeof(id));
    687
    688
    320k
            if (assert->allow_list.len == SIZE_MAX) {
    689
    0
                    r = FIDO_ERR_INVALID_ARGUMENT;
    690
    0
                    goto fail;
    691
    0
            }
    692
    693
    320k
            if (fido_blob_set(&id, ptr, len) < 0 || (list_ptr =
    694
    318k
                recallocarray(assert->allow_list.ptr, assert->allow_list.len,
    695
    318k
                assert->allow_list.len + 1, sizeof(fido_blob_t))) == NULL) {
    696
    2.72k
                    r = FIDO_ERR_INVALID_ARGUMENT;
    697
    2.72k
                    goto fail;
    698
    2.72k
            }
    699
    700
    317k
            list_ptr[assert->allow_list.len++] = id;
    701
    317k
            assert->allow_list.ptr = list_ptr;
    702
    703
    317k
            return (FIDO_OK);
    704
    2.72k
    fail:
    705
    2.72k
            free(id.ptr);
    706
    707
    2.72k
            return (r);
    708
    320k
    }
    709
    710
    int
    711
    fido_assert_empty_allow_list(fido_assert_t *assert)
    712
    166k
    {
    713
    166k
            fido_free_blob_array(&assert->allow_list);
    714
    166k
            memset(&assert->allow_list, 0, sizeof(assert->allow_list));
    715
    716
    166k
            return (FIDO_OK);
    717
    166k
    }
    718
    719
    int
    720
    fido_assert_set_extensions(fido_assert_t *assert, int ext)
    721
    161k
    {
    722
    161k
            if (ext == 0)
    723
    9.78k
                    assert->ext.mask = 0;
    724
    152k
            else {
    725
    152k
                    if ((ext & FIDO_EXT_ASSERT_MASK) != ext)
    726
    145k
                            return (FIDO_ERR_INVALID_ARGUMENT);
    727
    6.48k
                    assert->ext.mask |= ext;
    728
    6.48k
            }
    729
    730
    16.2k
            return (FIDO_OK);
    731
    161k
    }
    732
    733
    int
    734
    fido_assert_set_options(fido_assert_t *assert, bool up, bool uv)
    735
    0
    {
    736
    0
            assert->up = up ? FIDO_OPT_TRUE : FIDO_OPT_FALSE;
    737
    0
            assert->uv = uv ? FIDO_OPT_TRUE : FIDO_OPT_FALSE;
    738
    739
    0
            return (FIDO_OK);
    740
    0
    }
    741
    742
    int
    743
    fido_assert_set_up(fido_assert_t *assert, fido_opt_t up)
    744
    91.8k
    {
    745
    91.8k
            assert->up = up;
    746
    747
    91.8k
            return (FIDO_OK);
    748
    91.8k
    }
    749
    750
    int
    751
    fido_assert_set_uv(fido_assert_t *assert, fido_opt_t uv)
    752
    6.97k
    {
    753
    6.97k
            assert->uv = uv;
    754
    755
    6.97k
            return (FIDO_OK);
    756
    6.97k
    }
    757
    758
    const unsigned char *
    759
    fido_assert_clientdata_hash_ptr(const fido_assert_t *assert)
    760
    156k
    {
    761
    156k
            return (assert->cdh.ptr);
    762
    156k
    }
    763
    764
    size_t
    765
    fido_assert_clientdata_hash_len(const fido_assert_t *assert)
    766
    156k
    {
    767
    156k
            return (assert->cdh.len);
    768
    156k
    }
    769
    770
    fido_assert_t *
    771
    fido_assert_new(void)
    772
    167k
    {
    773
    167k
            return (calloc(1, sizeof(fido_assert_t)));
    774
    167k
    }
    775
    776
    void
    777
    fido_assert_reset_tx(fido_assert_t *assert)
    778
    166k
    {
    779
    166k
            free(assert->rp_id);
    780
    166k
            free(assert->appid);
    781
    166k
            fido_blob_reset(&assert->cd);
    782
    166k
            fido_blob_reset(&assert->cdh);
    783
    166k
            fido_blob_reset(&assert->ext.hmac_salt);
    784
    166k
            fido_assert_empty_allow_list(assert);
    785
    166k
            memset(&assert->ext, 0, sizeof(assert->ext));
    786
    166k
            assert->rp_id = NULL;
    787
    166k
            assert->appid = NULL;
    788
    166k
            assert->up = FIDO_OPT_OMIT;
    789
    166k
            assert->uv = FIDO_OPT_OMIT;
    790
    166k
    }
    791
    792
    static void
    793
    fido_assert_reset_extattr(fido_assert_extattr_t *ext)
    794
    316k
    {
    795
    316k
            fido_blob_reset(&ext->hmac_secret_enc);
    796
    316k
            fido_blob_reset(&ext->blob);
    797
    316k
            memset(ext, 0, sizeof(*ext));
    798
    316k
    }
    799
    800
    void
    801
    fido_assert_reset_rx(fido_assert_t *assert)
    802
    169k
    {
    803
    472k
            for (size_t i = 0; i < assert->stmt_cnt; i++) {
    804
    303k
                    free(assert->stmt[i].user.icon);
    805
    303k
                    free(assert->stmt[i].user.name);
    806
    303k
                    free(assert->stmt[i].user.display_name);
    807
    303k
                    fido_blob_reset(&assert->stmt[i].user.id);
    808
    303k
                    fido_blob_reset(&assert->stmt[i].id);
    809
    303k
                    fido_blob_reset(&assert->stmt[i].hmac_secret);
    810
    303k
                    fido_blob_reset(&assert->stmt[i].authdata_cbor);
    811
    303k
                    fido_blob_reset(&assert->stmt[i].authdata_raw);
    812
    303k
                    fido_blob_reset(&assert->stmt[i].largeblob_key);
    813
    303k
                    fido_blob_reset(&assert->stmt[i].sig);
    814
    303k
                    fido_assert_reset_extattr(&assert->stmt[i].authdata_ext);
    815
    303k
                    memset(&assert->stmt[i], 0, sizeof(assert->stmt[i]));
    816
    303k
            }
    817
    169k
            free(assert->stmt);
    818
    169k
            assert->stmt = NULL;
    819
    169k
            assert->stmt_len = 0;
    820
    169k
            assert->stmt_cnt = 0;
    821
    169k
    }
    822
    823
    void
    824
    fido_assert_free(fido_assert_t **assert_p)
    825
    167k
    {
    826
    167k
            fido_assert_t *assert;
    827
    828
    167k
            if (assert_p == NULL || (assert = *assert_p) == NULL)
    829
    103
                    return;
    830
    166k
            fido_assert_reset_tx(assert);
    831
    166k
            fido_assert_reset_rx(assert);
    832
    166k
            free(assert);
    833
    166k
            *assert_p = NULL;
    834
    166k
    }
    835
    836
    size_t
    837
    fido_assert_count(const fido_assert_t *assert)
    838
    167k
    {
    839
    167k
            return (assert->stmt_len);
    840
    167k
    }
    841
    842
    const char *
    843
    fido_assert_rp_id(const fido_assert_t *assert)
    844
    156k
    {
    845
    156k
            return (assert->rp_id);
    846
    156k
    }
    847
    848
    uint8_t
    849
    fido_assert_flags(const fido_assert_t *assert, size_t idx)
    850
    156k
    {
    851
    156k
            if (idx >= assert->stmt_len)
    852
    11.0k
                    return (0);
    853
    854
    145k
            return (assert->stmt[idx].authdata.flags);
    855
    156k
    }
    856
    857
    uint32_t
    858
    fido_assert_sigcount(const fido_assert_t *assert, size_t idx)
    859
    156k
    {
    860
    156k
            if (idx >= assert->stmt_len)
    861
    11.0k
                    return (0);
    862
    863
    145k
            return (assert->stmt[idx].authdata.sigcount);
    864
    156k
    }
    865
    866
    const unsigned char *
    867
    fido_assert_authdata_ptr(const fido_assert_t *assert, size_t idx)
    868
    156k
    {
    869
    156k
            if (idx >= assert->stmt_len)
    870
    11.0k
                    return (NULL);
    871
    872
    145k
            return (assert->stmt[idx].authdata_cbor.ptr);
    873
    156k
    }
    874
    875
    size_t
    876
    fido_assert_authdata_len(const fido_assert_t *assert, size_t idx)
    877
    156k
    {
    878
    156k
            if (idx >= assert->stmt_len)
    879
    11.0k
                    return (0);
    880
    881
    145k
            return (assert->stmt[idx].authdata_cbor.len);
    882
    156k
    }
    883
    884
    const unsigned char *
    885
    fido_assert_authdata_raw_ptr(const fido_assert_t *assert, size_t idx)
    886
    156k
    {
    887
    156k
            if (idx >= assert->stmt_len)
    888
    11.0k
                    return (NULL);
    889
    890
    145k
            return (assert->stmt[idx].authdata_raw.ptr);
    891
    156k
    }
    892
    893
    size_t
    894
    fido_assert_authdata_raw_len(const fido_assert_t *assert, size_t idx)
    895
    156k
    {
    896
    156k
            if (idx >= assert->stmt_len)
    897
    11.0k
                    return (0);
    898
    899
    145k
            return (assert->stmt[idx].authdata_raw.len);
    900
    156k
    }
    901
    902
    const unsigned char *
    903
    fido_assert_sig_ptr(const fido_assert_t *assert, size_t idx)
    904
    156k
    {
    905
    156k
            if (idx >= assert->stmt_len)
    906
    11.0k
                    return (NULL);
    907
    908
    145k
            return (assert->stmt[idx].sig.ptr);
    909
    156k
    }
    910
    911
    size_t
    912
    fido_assert_sig_len(const fido_assert_t *assert, size_t idx)
    913
    156k
    {
    914
    156k
            if (idx >= assert->stmt_len)
    915
    11.0k
                    return (0);
    916
    917
    145k
            return (assert->stmt[idx].sig.len);
    918
    156k
    }
    919
    920
    const unsigned char *
    921
    fido_assert_id_ptr(const fido_assert_t *assert, size_t idx)
    922
    156k
    {
    923
    156k
            if (idx >= assert->stmt_len)
    924
    11.0k
                    return (NULL);
    925
    926
    145k
            return (assert->stmt[idx].id.ptr);
    927
    156k
    }
    928
    929
    size_t
    930
    fido_assert_id_len(const fido_assert_t *assert, size_t idx)
    931
    156k
    {
    932
    156k
            if (idx >= assert->stmt_len)
    933
    11.0k
                    return (0);
    934
    935
    145k
            return (assert->stmt[idx].id.len);
    936
    156k
    }
    937
    938
    const unsigned char *
    939
    fido_assert_user_id_ptr(const fido_assert_t *assert, size_t idx)
    940
    156k
    {
    941
    156k
            if (idx >= assert->stmt_len)
    942
    11.0k
                    return (NULL);
    943
    944
    145k
            return (assert->stmt[idx].user.id.ptr);
    945
    156k
    }
    946
    947
    size_t
    948
    fido_assert_user_id_len(const fido_assert_t *assert, size_t idx)
    949
    156k
    {
    950
    156k
            if (idx >= assert->stmt_len)
    951
    11.0k
                    return (0);
    952
    953
    145k
            return (assert->stmt[idx].user.id.len);
    954
    156k
    }
    955
    956
    const char *
    957
    fido_assert_user_icon(const fido_assert_t *assert, size_t idx)
    958
    156k
    {
    959
    156k
            if (idx >= assert->stmt_len)
    960
    11.0k
                    return (NULL);
    961
    962
    145k
            return (assert->stmt[idx].user.icon);
    963
    156k
    }
    964
    965
    const char *
    966
    fido_assert_user_name(const fido_assert_t *assert, size_t idx)
    967
    156k
    {
    968
    156k
            if (idx >= assert->stmt_len)
    969
    11.0k
                    return (NULL);
    970
    971
    145k
            return (assert->stmt[idx].user.name);
    972
    156k
    }
    973
    974
    const char *
    975
    fido_assert_user_display_name(const fido_assert_t *assert, size_t idx)
    976
    156k
    {
    977
    156k
            if (idx >= assert->stmt_len)
    978
    11.0k
                    return (NULL);
    979
    980
    145k
            return (assert->stmt[idx].user.display_name);
    981
    156k
    }
    982
    983
    const unsigned char *
    984
    fido_assert_hmac_secret_ptr(const fido_assert_t *assert, size_t idx)
    985
    156k
    {
    986
    156k
            if (idx >= assert->stmt_len)
    987
    11.0k
                    return (NULL);
    988
    989
    145k
            return (assert->stmt[idx].hmac_secret.ptr);
    990
    156k
    }
    991
    992
    size_t
    993
    fido_assert_hmac_secret_len(const fido_assert_t *assert, size_t idx)
    994
    156k
    {
    995
    156k
            if (idx >= assert->stmt_len)
    996
    11.0k
                    return (0);
    997
    998
    145k
            return (assert->stmt[idx].hmac_secret.len);
    999
    156k
    }
    1000
    1001
    const unsigned char *
    1002
    fido_assert_largeblob_key_ptr(const fido_assert_t *assert, size_t idx)
    1003
    156k
    {
    1004
    156k
            if (idx >= assert->stmt_len)
    1005
    11.0k
                    return (NULL);
    1006
    1007
    145k
            return (assert->stmt[idx].largeblob_key.ptr);
    1008
    156k
    }
    1009
    1010
    size_t
    1011
    fido_assert_largeblob_key_len(const fido_assert_t *assert, size_t idx)
    1012
    156k
    {
    1013
    156k
            if (idx >= assert->stmt_len)
    1014
    11.0k
                    return (0);
    1015
    1016
    145k
            return (assert->stmt[idx].largeblob_key.len);
    1017
    156k
    }
    1018
    1019
    const unsigned char *
    1020
    fido_assert_blob_ptr(const fido_assert_t *assert, size_t idx)
    1021
    156k
    {
    1022
    156k
            if (idx >= assert->stmt_len)
    1023
    11.0k
                    return (NULL);
    1024
    1025
    145k
            return (assert->stmt[idx].authdata_ext.blob.ptr);
    1026
    156k
    }
    1027
    1028
    size_t
    1029
    fido_assert_blob_len(const fido_assert_t *assert, size_t idx)
    1030
    156k
    {
    1031
    156k
            if (idx >= assert->stmt_len)
    1032
    11.0k
                    return (0);
    1033
    1034
    145k
            return (assert->stmt[idx].authdata_ext.blob.len);
    1035
    156k
    }
    1036
    1037
    static void
    1038
    fido_assert_clean_authdata(fido_assert_stmt *stmt)
    1039
    13.4k
    {
    1040
    13.4k
            fido_blob_reset(&stmt->authdata_cbor);
    1041
    13.4k
            fido_blob_reset(&stmt->authdata_raw);
    1042
    13.4k
            fido_assert_reset_extattr(&stmt->authdata_ext);
    1043
    13.4k
            memset(&stmt->authdata, 0, sizeof(stmt->authdata));
    1044
    13.4k
    }
    1045
    1046
    int
    1047
    fido_assert_set_authdata(fido_assert_t *assert, size_t idx,
    1048
        const unsigned char *ptr, size_t len)
    1049
    313k
    {
    1050
    313k
            cbor_item_t             *item = NULL;
    1051
    313k
            fido_assert_stmt        *stmt = NULL;
    1052
    313k
            struct cbor_load_result  cbor;
    1053
    313k
            int                      r;
    1054
    1055
    313k
            if (idx >= assert->stmt_len || ptr == NULL || len == 0)
    1056
    303k
                    return (FIDO_ERR_INVALID_ARGUMENT);
    1057
    1058
    10.4k
            stmt = &assert->stmt[idx];
    1059
    10.4k
            fido_assert_clean_authdata(stmt);
    1060
    1061
    10.4k
            if ((item = cbor_load(ptr, len, &cbor)) == NULL) {
    1062
    121
                    fido_log_debug("%s: cbor_load", __func__);
    1063
    121
                    r = FIDO_ERR_INVALID_ARGUMENT;
    1064
    121
                    goto fail;
    1065
    121
            }
    1066
    1067
    10.2k
            if (fido_blob_decode(item, &stmt->authdata_raw) < 0) {
    1068
    108
                fido_log_debug("%s: fido_blob_decode", __func__);
    1069
    108
                r = FIDO_ERR_INTERNAL;
    1070
    108
                goto fail;
    1071
    108
            }
    1072
    1073
    10.1k
            if (cbor_decode_assert_authdata(item, &stmt->authdata_cbor,
    1074
    10.1k
                &stmt->authdata, &stmt->authdata_ext) < 0) {
    1075
    791
                    fido_log_debug("%s: cbor_decode_assert_authdata", __func__);
    1076
    791
                    r = FIDO_ERR_INVALID_ARGUMENT;
    1077
    791
                    goto fail;
    1078
    791
            }
    1079
    1080
    9.39k
            r = FIDO_OK;
    1081
    10.4k
    fail:
    1082
    10.4k
            if (item != NULL)
    1083
    10.2k
                    cbor_decref(&item);
    1084
    1085
    10.4k
            if (r != FIDO_OK)
    1086
    1.02k
                    fido_assert_clean_authdata(stmt);
    1087
    1088
    10.4k
            return (r);
    1089
    9.39k
    }
    1090
    1091
    int
    1092
    fido_assert_set_authdata_raw(fido_assert_t *assert, size_t idx,
    1093
        const unsigned char *ptr, size_t len)
    1094
    304k
    {
    1095
    304k
            cbor_item_t             *item = NULL;
    1096
    304k
            fido_assert_stmt        *stmt = NULL;
    1097
    304k
            int                      r;
    1098
    1099
    304k
            if (idx >= assert->stmt_len || ptr == NULL || len == 0)
    1100
    303k
                    return (FIDO_ERR_INVALID_ARGUMENT);
    1101
    1102
    1.00k
            stmt = &assert->stmt[idx];
    1103
    1.00k
            fido_assert_clean_authdata(stmt);
    1104
    1105
    1.00k
            if (fido_blob_set(&stmt->authdata_raw, ptr, len) < 0) {
    1106
    5
                    fido_log_debug("%s: fido_blob_set", __func__);
    1107
    5
                    r = FIDO_ERR_INTERNAL;
    1108
    5
                    goto fail;
    1109
    5
            }
    1110
    1111
    995
            if ((item = cbor_build_bytestring(ptr, len)) == NULL) {
    1112
    7
                    fido_log_debug("%s: cbor_build_bytestring", __func__);
    1113
    7
                    r = FIDO_ERR_INTERNAL;
    1114
    7
                    goto fail;
    1115
    7
            }
    1116
    1117
    988
            if (cbor_decode_assert_authdata(item, &stmt->authdata_cbor,
    1118
    988
                &stmt->authdata, &stmt->authdata_ext) < 0) {
    1119
    956
                    fido_log_debug("%s: cbor_decode_assert_authdata", __func__);
    1120
    956
                    r = FIDO_ERR_INVALID_ARGUMENT;
    1121
    956
                    goto fail;
    1122
    956
            }
    1123
    1124
    32
            r = FIDO_OK;
    1125
    1.00k
    fail:
    1126
    1.00k
            if (item != NULL)
    1127
    988
                    cbor_decref(&item);
    1128
    1129
    1.00k
            if (r != FIDO_OK)
    1130
    968
                    fido_assert_clean_authdata(stmt);
    1131
    1132
    1.00k
            return (r);
    1133
    32
    }
    1134
    1135
    int
    1136
    fido_assert_set_sig(fido_assert_t *a, size_t idx, const unsigned char *ptr,
    1137
        size_t len)
    1138
    313k
    {
    1139
    313k
            if (idx >= a->stmt_len || ptr == NULL || len == 0)
    1140
    303k
                    return (FIDO_ERR_INVALID_ARGUMENT);
    1141
    10.1k
            if (fido_blob_set(&a->stmt[idx].sig, ptr, len) < 0)
    1142
    60
                    return (FIDO_ERR_INTERNAL);
    1143
    1144
    10.0k
            return (FIDO_OK);
    1145
    10.1k
    }
    1146
    1147
    /* XXX shrinking leaks memory; fortunately that shouldn't happen */
    1148
    int
    1149
    fido_assert_set_count(fido_assert_t *assert, size_t n)
    1150
    158k
    {
    1151
    158k
            void *new_stmt;
    1152
    1153
    158k
    #ifdef FIDO_FUZZ
    1154
    158k
            if (n > UINT8_MAX) {
    1155
    112
                    fido_log_debug("%s: n > UINT8_MAX", __func__);
    1156
    112
                    return (FIDO_ERR_INTERNAL);
    1157
    112
            }
    1158
    158k
    #endif
    1159
    1160
    158k
            new_stmt = recallocarray(assert->stmt, assert->stmt_cnt, n,
    1161
    158k
                sizeof(fido_assert_stmt));
    1162
    158k
            if (new_stmt == NULL)
    1163
    411
                    return (FIDO_ERR_INTERNAL);
    1164
    1165
    158k
            assert->stmt = new_stmt;
    1166
    158k
            assert->stmt_cnt = n;
    1167
    158k
            assert->stmt_len = n;
    1168
    1169
    158k
            return (FIDO_OK);
    1170
    158k
    }