## Coverage Report

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

    /libfido2/src/cbor.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/hmac.h>
    9
    #include <openssl/sha.h>
    10
    #include "fido.h"
    11
    12
    static int
    13
    check_key_type(cbor_item_t *item)
    14
    305k
    {
    15
    305k
            if (item->type == CBOR_TYPE_UINT || item->type == CBOR_TYPE_NEGINT ||
    16
    305k
                item->type == CBOR_TYPE_STRING)
    17
    305k
                    return (0);
    18
    19
    412
            fido_log_debug("%s: invalid type: %d", __func__, item->type);
    20
    21
    412
            return (-1);
    22
    305k
    }
    23
    24
    /*
    25
     * Validate CTAP2 canonical CBOR encoding rules for maps.
    26
     */
    27
    static int
    28
    ctap_check_cbor(cbor_item_t *prev, cbor_item_t *curr)
    29
    152k
    {
    30
    152k
            size_t  curr_len;
    31
    152k
            size_t  prev_len;
    32
    33
    152k
            if (check_key_type(prev) < 0 || check_key_type(curr) < 0)
    34
    412
                    return (-1);
    35
    36
    152k
            if (prev->type != curr->type) {
    37
    9.27k
                    if (prev->type < curr->type)
    38
    8.80k
                            return (0);
    39
    475
                    fido_log_debug("%s: unsorted types", __func__);
    40
    475
                    return (-1);
    41
    9.27k
            }
    42
    43
    143k
            if (curr->type == CBOR_TYPE_UINT || curr->type == CBOR_TYPE_NEGINT) {
    44
    95.5k
                    if (cbor_int_get_width(curr) >= cbor_int_get_width(prev) &&
    45
    95.5k
                        cbor_get_int(curr) > cbor_get_int(prev))
    46
    94.8k
                            return (0);
    47
    95.5k
            } else {
    48
    47.5k
                    curr_len = cbor_string_length(curr);
    49
    47.5k
                    prev_len = cbor_string_length(prev);
    50
    51
    47.5k
                    if (curr_len > prev_len || (curr_len == prev_len &&
    52
    10.4k
                        memcmp(cbor_string_handle(prev), cbor_string_handle(curr),
    53
    10.3k
                        curr_len) < 0))
    54
    47.3k
                            return (0);
    55
    47.5k
            }
    56
    57
    894
            fido_log_debug("%s: invalid cbor", __func__);
    58
    59
    894
            return (-1);
    60
    143k
    }
    61
    62
    int
    63
    cbor_map_iter(const cbor_item_t *item, void *arg, int(*f)(const cbor_item_t *,
    64
        const cbor_item_t *, void *))
    65
    52.1k
    {
    66
    52.1k
            struct cbor_pair        *v;
    67
    52.1k
            size_t                   n;
    68
    69
    52.1k
            if ((v = cbor_map_handle(item)) == NULL) {
    70
    98
                    fido_log_debug("%s: cbor_map_handle", __func__);
    71
    98
                    return (-1);
    72
    98
            }
    73
    74
    52.0k
            n = cbor_map_size(item);
    75
    76
    250k
            for (size_t i = 0; i < n; i++) {
    77
    204k
                    if (v[i].key == NULL || v[i].value == NULL) {
    78
    0
                            fido_log_debug("%s: key=%p, value=%p for i=%zu",
    79
    0
                                __func__, (void *)v[i].key, (void *)v[i].value, i);
    80
    0
                            return (-1);
    81
    0
                    }
    82
    204k
                    if (i && ctap_check_cbor(v[i - 1].key, v[i].key) < 0) {
    83
    1.78k
                            fido_log_debug("%s: ctap_check_cbor", __func__);
    84
    1.78k
                            return (-1);
    85
    1.78k
                    }
    86
    202k
                    if (f(v[i].key, v[i].value, arg) < 0) {
    87
    3.98k
                            fido_log_debug("%s: iterator < 0 on i=%zu", __func__,
    88
    3.98k
                                i);
    89
    3.98k
                            return (-1);
    90
    3.98k
                    }
    91
    202k
            }
    92
    93
    46.3k
            return (0);
    94
    52.0k
    }
    95
    96
    int
    97
    cbor_array_iter(const cbor_item_t *item, void *arg, int(*f)(const cbor_item_t *,
    98
        void *))
    99
    28.9k
    {
    100
    28.9k
            cbor_item_t     **v;
    101
    28.9k
            size_t            n;
    102
    103
    28.9k
            if ((v = cbor_array_handle(item)) == NULL) {
    104
    29
                    fido_log_debug("%s: cbor_array_handle", __func__);
    105
    29
                    return (-1);
    106
    29
            }
    107
    108
    28.9k
            n = cbor_array_size(item);
    109
    110
    87.9k
            for (size_t i = 0; i < n; i++)
    111
    59.9k
                    if (v[i] == NULL || f(v[i], arg) < 0) {
    112
    884
                            fido_log_debug("%s: iterator < 0 on i=%zu,%p",
    113
    884
                                __func__, i, (void *)v[i]);
    114
    884
                            return (-1);
    115
    884
                    }
    116
    117
    28.0k
            return (0);
    118
    28.9k
    }
    119
    120
    int
    121
    cbor_parse_reply(const unsigned char *blob, size_t blob_len, void *arg,
    122
        int(*parser)(const cbor_item_t *, const cbor_item_t *, void *))
    123
    26.7k
    {
    124
    26.7k
            cbor_item_t             *item = NULL;
    125
    26.7k
            struct cbor_load_result  cbor;
    126
    26.7k
            int                      r;
    127
    128
    26.7k
            if (blob_len < 1) {
    129
    3.19k
                    fido_log_debug("%s: blob_len=%zu", __func__, blob_len);
    130
    3.19k
                    r = FIDO_ERR_RX;
    131
    3.19k
                    goto fail;
    132
    3.19k
            }
    133
    134
    23.5k
            if (blob[0] != FIDO_OK) {
    135
    1.20k
                    fido_log_debug("%s: blob[0]=0x%02x", __func__, blob[0]);
    136
    1.20k
                    r = blob[0];
    137
    1.20k
                    goto fail;
    138
    1.20k
            }
    139
    140
    22.3k
            if ((item = cbor_load(blob + 1, blob_len - 1, &cbor)) == NULL) {
    141
    364
                    fido_log_debug("%s: cbor_load", __func__);
    142
    364
                    r = FIDO_ERR_RX_NOT_CBOR;
    143
    364
                    goto fail;
    144
    364
            }
    145
    146
    22.0k
            if (cbor_isa_map(item) == false ||
    147
    22.0k
                cbor_map_is_definite(item) == false) {
    148
    394
                    fido_log_debug("%s: cbor type", __func__);
    149
    394
                    r = FIDO_ERR_RX_INVALID_CBOR;
    150
    394
                    goto fail;
    151
    394
            }
    152
    153
    21.6k
            if (cbor_map_iter(item, arg, parser) < 0) {
    154
    4.51k
                    fido_log_debug("%s: cbor_map_iter", __func__);
    155
    4.51k
                    r = FIDO_ERR_RX_INVALID_CBOR;
    156
    4.51k
                    goto fail;
    157
    4.51k
            }
    158
    159
    17.1k
            r = FIDO_OK;
    160
    26.7k
    fail:
    161
    26.7k
            if (item != NULL)
    162
    22.0k
                    cbor_decref(&item);
    163
    164
    26.7k
            return (r);
    165
    17.1k
    }
    166
    167
    void
    168
    cbor_vector_free(cbor_item_t **item, size_t len)
    169
    31.8k
    {
    170
    154k
            for (size_t i = 0; i < len; i++)
    171
    122k
                    if (item[i] != NULL)
    172
    62.6k
                            cbor_decref(&item[i]);
    173
    31.8k
    }
    174
    175
    int
    176
    cbor_bytestring_copy(const cbor_item_t *item, unsigned char **buf, size_t *len)
    177
    10.6k
    {
    178
    10.6k
            if (*buf != NULL || *len != 0) {
    179
    4
                    fido_log_debug("%s: dup", __func__);
    180
    4
                    return (-1);
    181
    4
            }
    182
    183
    10.6k
            if (cbor_isa_bytestring(item) == false ||
    184
    10.6k
                cbor_bytestring_is_definite(item) == false) {
    185
    44
                    fido_log_debug("%s: cbor type", __func__);
    186
    44
                    return (-1);
    187
    44
            }
    188
    189
    10.6k
            *len = cbor_bytestring_length(item);
    190
    10.6k
            if ((*buf = malloc(*len)) == NULL) {
    191
    84
                    *len = 0;
    192
    84
                    return (-1);
    193
    84
            }
    194
    195
    10.5k
            memcpy(*buf, cbor_bytestring_handle(item), *len);
    196
    197
    10.5k
            return (0);
    198
    10.6k
    }
    199
    200
    int
    201
    cbor_string_copy(const cbor_item_t *item, char **str)
    202
    112k
    {
    203
    112k
            size_t len;
    204
    205
    112k
            if (*str != NULL) {
    206
    1
                    fido_log_debug("%s: dup", __func__);
    207
    1
                    return (-1);
    208
    1
            }
    209
    210
    112k
            if (cbor_isa_string(item) == false ||
    211
    112k
                cbor_string_is_definite(item) == false) {
    212
    734
                    fido_log_debug("%s: cbor type", __func__);
    213
    734
                    return (-1);
    214
    734
            }
    215
    216
    111k
            if ((len = cbor_string_length(item)) == SIZE_MAX ||
    217
    111k
                (*str = malloc(len + 1)) == NULL)
    218
    298
                    return (-1);
    219
    220
    111k
            memcpy(*str, cbor_string_handle(item), len);
    221
    111k
            (*str)[len] = '\0';
    222
    223
    111k
            return (0);
    224
    111k
    }
    225
    226
    int
    227
    cbor_add_bytestring(cbor_item_t *item, const char *key,
    228
        const unsigned char *value, size_t value_len)
    229
    40.9k
    {
    230
    40.9k
            struct cbor_pair pair;
    231
    40.9k
            int ok = -1;
    232
    233
    40.9k
            memset(&pair, 0, sizeof(pair));
    234
    235
    40.9k
            if ((pair.key = cbor_build_string(key)) == NULL ||
    236
    40.9k
                (pair.value = cbor_build_bytestring(value, value_len)) == NULL) {
    237
    32
                    fido_log_debug("%s: cbor_build", __func__);
    238
    32
                    goto fail;
    239
    32
            }
    240
    241
    40.8k
            if (!cbor_map_add(item, pair)) {
    242
    17
                    fido_log_debug("%s: cbor_map_add", __func__);
    243
    17
                    goto fail;
    244
    17
            }
    245
    246
    40.8k
            ok = 0;
    247
    40.9k
    fail:
    248
    40.9k
            if (pair.key)
    249
    40.9k
                    cbor_decref(&pair.key);
    250
    40.9k
            if (pair.value)
    251
    40.8k
                    cbor_decref(&pair.value);
    252
    253
    40.9k
            return (ok);
    254
    40.8k
    }
    255
    256
    int
    257
    cbor_add_string(cbor_item_t *item, const char *key, const char *value)
    258
    45.9k
    {
    259
    45.9k
            struct cbor_pair pair;
    260
    45.9k
            int ok = -1;
    261
    262
    45.9k
            memset(&pair, 0, sizeof(pair));
    263
    264
    45.9k
            if ((pair.key = cbor_build_string(key)) == NULL ||
    265
    45.9k
                (pair.value = cbor_build_string(value)) == NULL) {
    266
    52
                    fido_log_debug("%s: cbor_build", __func__);
    267
    52
                    goto fail;
    268
    52
            }
    269
    270
    45.8k
            if (!cbor_map_add(item, pair)) {
    271
    18
                    fido_log_debug("%s: cbor_map_add", __func__);
    272
    18
                    goto fail;
    273
    18
            }
    274
    275
    45.8k
            ok = 0;
    276
    45.9k
    fail:
    277
    45.9k
            if (pair.key)
    278
    45.8k
                    cbor_decref(&pair.key);
    279
    45.9k
            if (pair.value)
    280
    45.8k
                    cbor_decref(&pair.value);
    281
    282
    45.9k
            return (ok);
    283
    45.8k
    }
    284
    285
    int
    286
    cbor_add_bool(cbor_item_t *item, const char *key, fido_opt_t value)
    287
    1.86k
    {
    288
    1.86k
            struct cbor_pair pair;
    289
    1.86k
            int ok = -1;
    290
    291
    1.86k
            memset(&pair, 0, sizeof(pair));
    292
    293
    1.86k
            if ((pair.key = cbor_build_string(key)) == NULL ||
    294
    1.86k
                (pair.value = cbor_build_bool(value == FIDO_OPT_TRUE)) == NULL) {
    295
    8
                    fido_log_debug("%s: cbor_build", __func__);
    296
    8
                    goto fail;
    297
    8
            }
    298
    299
    1.85k
            if (!cbor_map_add(item, pair)) {
    300
    3
                    fido_log_debug("%s: cbor_map_add", __func__);
    301
    3
                    goto fail;
    302
    3
            }
    303
    304
    1.85k
            ok = 0;
    305
    1.86k
    fail:
    306
    1.86k
            if (pair.key)
    307
    1.85k
                    cbor_decref(&pair.key);
    308
    1.86k
            if (pair.value)
    309
    1.85k
                    cbor_decref(&pair.value);
    310
    311
    1.86k
            return (ok);
    312
    1.85k
    }
    313
    314
    static int
    315
    cbor_add_uint8(cbor_item_t *item, const char *key, uint8_t value)
    316
    516
    {
    317
    516
            struct cbor_pair pair;
    318
    516
            int ok = -1;
    319
    320
    516
            memset(&pair, 0, sizeof(pair));
    321
    322
    516
            if ((pair.key = cbor_build_string(key)) == NULL ||
    323
    516
                (pair.value = cbor_build_uint8(value)) == NULL) {
    324
    3
                    fido_log_debug("%s: cbor_build", __func__);
    325
    3
                    goto fail;
    326
    3
            }
    327
    328
    513
            if (!cbor_map_add(item, pair)) {
    329
    1
                    fido_log_debug("%s: cbor_map_add", __func__);
    330
    1
                    goto fail;
    331
    1
            }
    332
    333
    512
            ok = 0;
    334
    516
    fail:
    335
    516
            if (pair.key)
    336
    514
                    cbor_decref(&pair.key);
    337
    516
            if (pair.value)
    338
    513
                    cbor_decref(&pair.value);
    339
    340
    516
            return (ok);
    341
    512
    }
    342
    343
    static int
    344
    cbor_add_arg(cbor_item_t *item, uint8_t n, cbor_item_t *arg)
    345
    82.4k
    {
    346
    82.4k
            struct cbor_pair pair;
    347
    82.4k
            int ok = -1;
    348
    349
    82.4k
            memset(&pair, 0, sizeof(pair));
    350
    351
    82.4k
            if (arg == NULL)
    352
    28.2k
                    return (0); /* empty argument */
    353
    354
    54.1k
            if ((pair.key = cbor_build_uint8(n)) == NULL) {
    355
    129
                    fido_log_debug("%s: cbor_build", __func__);
    356
    129
                    goto fail;
    357
    129
            }
    358
    359
    54.0k
            pair.value = arg;
    360
    361
    54.0k
            if (!cbor_map_add(item, pair)) {
    362
    127
                    fido_log_debug("%s: cbor_map_add", __func__);
    363
    127
                    goto fail;
    364
    127
            }
    365
    366
    53.9k
            ok = 0;
    367
    54.1k
    fail:
    368
    54.1k
            if (pair.key)
    369
    54.0k
                    cbor_decref(&pair.key);
    370
    371
    54.1k
            return (ok);
    372
    53.9k
    }
    373
    374
    cbor_item_t *
    375
    cbor_flatten_vector(cbor_item_t *argv[], size_t argc)
    376
    23.5k
    {
    377
    23.5k
            cbor_item_t     *map;
    378
    23.5k
            uint8_t          i;
    379
    380
    23.5k
            if (argc > UINT8_MAX - 1)
    381
    0
                    return (NULL);
    382
    383
    23.5k
            if ((map = cbor_new_definite_map(argc)) == NULL)
    384
    64
                    return (NULL);
    385
    386
    105k
            for (i = 0; i < argc; i++)
    387
    82.4k
                    if (cbor_add_arg(map, (uint8_t)(i + 1), argv[i]) < 0)
    388
    256
                            break;
    389
    390
    23.5k
            if (i != argc) {
    391
    256
                    cbor_decref(&map);
    392
    256
                    map = NULL;
    393
    256
            }
    394
    395
    23.5k
            return (map);
    396
    23.5k
    }
    397
    398
    int
    399
    cbor_build_frame(uint8_t cmd, cbor_item_t *argv[], size_t argc, fido_blob_t *f)
    400
    18.2k
    {
    401
    18.2k
            cbor_item_t     *flat = NULL;
    402
    18.2k
            unsigned char   *cbor = NULL;
    403
    18.2k
            size_t           cbor_len;
    404
    18.2k
            size_t           cbor_alloc_len;
    405
    18.2k
            int              ok = -1;
    406
    407
    18.2k
            if ((flat = cbor_flatten_vector(argv, argc)) == NULL)
    408
    252
                    goto fail;
    409
    410
    17.9k
            cbor_len = cbor_serialize_alloc(flat, &cbor, &cbor_alloc_len);
    411
    17.9k
            if (cbor_len == 0 || cbor_len == SIZE_MAX) {
    412
    47
                    fido_log_debug("%s: cbor_len=%zu", __func__, cbor_len);
    413
    47
                    goto fail;
    414
    47
            }
    415
    416
    17.9k
            if ((f->ptr = malloc(cbor_len + 1)) == NULL)
    417
    34
                    goto fail;
    418
    419
    17.9k
            f->len = cbor_len + 1;
    420
    17.9k
            f->ptr[0] = cmd;
    421
    17.9k
            memcpy(f->ptr + 1, cbor, f->len - 1);
    422
    423
    17.9k
            ok = 0;
    424
    18.2k
    fail:
    425
    18.2k
            if (flat != NULL)
    426
    17.9k
                    cbor_decref(&flat);
    427
    428
    18.2k
            free(cbor);
    429
    430
    18.2k
            return (ok);
    431
    17.9k
    }
    432
    433
    cbor_item_t *
    434
    cbor_encode_rp_entity(const fido_rp_t *rp)
    435
    1.21k
    {
    436
    1.21k
            cbor_item_t *item = NULL;
    437
    438
    1.21k
            if ((item = cbor_new_definite_map(2)) == NULL)
    439
    5
                    return (NULL);
    440
    441
    1.21k
            if ((rp->id && cbor_add_string(item, "id", rp->id) < 0) ||
    442
    1.21k
                (rp->name && cbor_add_string(item, "name", rp->name) < 0)) {
    443
    11
                    cbor_decref(&item);
    444
    11
                    return (NULL);
    445
    11
            }
    446
    447
    1.20k
            return (item);
    448
    1.21k
    }
    449
    450
    cbor_item_t *
    451
    cbor_encode_user_entity(const fido_user_t *user)
    452
    1.59k
    {
    453
    1.59k
            cbor_item_t             *item = NULL;
    454
    1.59k
            const fido_blob_t       *id = &user->id;
    455
    1.59k
            const char              *display = user->display_name;
    456
    457
    1.59k
            if ((item = cbor_new_definite_map(4)) == NULL)
    458
    8
                    return (NULL);
    459
    460
    1.58k
            if ((id->ptr && cbor_add_bytestring(item, "id", id->ptr, id->len) < 0) ||
    461
    1.58k
                (user->icon && cbor_add_string(item, "icon", user->icon) < 0) ||
    462
    1.58k
                (user->name && cbor_add_string(item, "name", user->name) < 0) ||
    463
    1.58k
                (display && cbor_add_string(item, "displayName", display) < 0)) {
    464
    47
                    cbor_decref(&item);
    465
    47
                    return (NULL);
    466
    47
            }
    467
    468
    1.53k
            return (item);
    469
    1.58k
    }
    470
    471
    cbor_item_t *
    472
    cbor_encode_pubkey_param(int cose_alg)
    473
    1.16k
    {
    474
    1.16k
            cbor_item_t             *item = NULL;
    475
    1.16k
            cbor_item_t             *body = NULL;
    476
    1.16k
            struct cbor_pair         alg;
    477
    1.16k
            int                      ok = -1;
    478
    479
    1.16k
            memset(&alg, 0, sizeof(alg));
    480
    481
    1.16k
            if ((item = cbor_new_definite_array(1)) == NULL ||
    482
    1.16k
                (body = cbor_new_definite_map(2)) == NULL ||
    483
    1.16k
                cose_alg > -1 || cose_alg < INT16_MIN)
    484
    8
                    goto fail;
    485
    486
    1.15k
            alg.key = cbor_build_string("alg");
    487
    488
    1.15k
            if (-cose_alg - 1 > UINT8_MAX)
    489
    269
                    alg.value = cbor_build_negint16((uint16_t)(-cose_alg - 1));
    490
    886
            else
    491
    886
                    alg.value = cbor_build_negint8((uint8_t)(-cose_alg - 1));
    492
    493
    1.15k
            if (alg.key == NULL || alg.value == NULL) {
    494
    10
                    fido_log_debug("%s: cbor_build", __func__);
    495
    10
                    goto fail;
    496
    10
            }
    497
    498
    1.14k
            if (cbor_map_add(body, alg) == false ||
    499
    1.14k
                cbor_add_string(body, "type", "public-key") < 0 ||
    500
    1.14k
                cbor_array_push(item, body) == false)
    501
    20
                    goto fail;
    502
    503
    1.12k
            ok  = 0;
    504
    1.16k
    fail:
    505
    1.16k
            if (ok < 0) {
    506
    38
                    if (item != NULL) {
    507
    35
                            cbor_decref(&item);
    508
    35
                            item = NULL;
    509
    35
                    }
    510
    38
            }
    511
    512
    1.16k
            if (body != NULL)
    513
    1.15k
                    cbor_decref(&body);
    514
    1.16k
            if (alg.key != NULL)
    515
    1.15k
                    cbor_decref(&alg.key);
    516
    1.16k
            if (alg.value != NULL)
    517
    1.15k
                    cbor_decref(&alg.value);
    518
    519
    1.16k
            return (item);
    520
    1.12k
    }
    521
    522
    cbor_item_t *
    523
    cbor_encode_pubkey(const fido_blob_t *pubkey)
    524
    39.0k
    {
    525
    39.0k
            cbor_item_t *cbor_key = NULL;
    526
    527
    39.0k
            if ((cbor_key = cbor_new_definite_map(2)) == NULL ||
    528
    39.0k
                cbor_add_bytestring(cbor_key, "id", pubkey->ptr, pubkey->len) < 0 ||
    529
    39.0k
                cbor_add_string(cbor_key, "type", "public-key") < 0) {
    530
    59
                    if (cbor_key)
    531
    51
                            cbor_decref(&cbor_key);
    532
    59
                    return (NULL);
    533
    59
            }
    534
    535
    39.0k
            return (cbor_key);
    536
    39.0k
    }
    537
    538
    cbor_item_t *
    539
    cbor_encode_pubkey_list(const fido_blob_array_t *list)
    540
    1.06k
    {
    541
    1.06k
            cbor_item_t     *array = NULL;
    542
    1.06k
            cbor_item_t     *key = NULL;
    543
    544
    1.06k
            if ((array = cbor_new_definite_array(list->len)) == NULL)
    545
    3
                    goto fail;
    546
    547
    39.3k
            for (size_t i = 0; i < list->len; i++) {
    548
    38.3k
                    if ((key = cbor_encode_pubkey(&list->ptr[i])) == NULL ||
    549
    38.3k
                        cbor_array_push(array, key) == false)
    550
    54
                            goto fail;
    551
    38.2k
                    cbor_decref(&key);
    552
    38.2k
            }
    553
    554
    1.00k
            return (array);
    555
    57
    fail:
    556
    57
            if (key != NULL)
    557
    18
                    cbor_decref(&key);
    558
    57
            if (array != NULL)
    559
    54
                    cbor_decref(&array);
    560
    561
    57
            return (NULL);
    562
    1.06k
    }
    563
    564
    cbor_item_t *
    565
    cbor_encode_str_array(const fido_str_array_t *a)
    566
    895
    {
    567
    895
            cbor_item_t     *array = NULL;
    568
    895
            cbor_item_t     *entry = NULL;
    569
    570
    895
            if ((array = cbor_new_definite_array(a->len)) == NULL)
    571
    1
                    goto fail;
    572
    573
    24.4k
            for (size_t i = 0; i < a->len; i++) {
    574
    23.6k
                    if ((entry = cbor_build_string(a->ptr[i])) == NULL ||
    575
    23.6k
                        cbor_array_push(array, entry) == false)
    576
    131
                            goto fail;
    577
    23.5k
                    cbor_decref(&entry);
    578
    23.5k
            }
    579
    580
    763
            return (array);
    581
    132
    fail:
    582
    132
            if (entry != NULL)
    583
    54
                    cbor_decref(&entry);
    584
    132
            if (array != NULL)
    585
    131
                    cbor_decref(&array);
    586
    587
    132
            return (NULL);
    588
    894
    }
    589
    590
    static int
    591
    cbor_encode_largeblob_key_ext(cbor_item_t *map)
    592
    500
    {
    593
    500
            if (map == NULL ||
    594
    500
                cbor_add_bool(map, "largeBlobKey", FIDO_OPT_TRUE) < 0)
    595
    2
                    return (-1);
    596
    597
    498
            return (0);
    598
    500
    }
    599
    600
    cbor_item_t *
    601
    cbor_encode_cred_ext(const fido_cred_ext_t *ext, const fido_blob_t *blob)
    602
    774
    {
    603
    774
            cbor_item_t *item = NULL;
    604
    774
            size_t size = 0;
    605
    606
    774
            if (ext->mask & FIDO_EXT_CRED_BLOB)
    607
    280
                    size++;
    608
    774
            if (ext->mask & FIDO_EXT_HMAC_SECRET)
    609
    358
                    size++;
    610
    774
            if (ext->mask & FIDO_EXT_CRED_PROTECT)
    611
    518
                    size++;
    612
    774
            if (ext->mask & FIDO_EXT_LARGEBLOB_KEY)
    613
    327
                    size++;
    614
    774
            if (ext->mask & FIDO_EXT_MINPINLEN)
    615
    182
                    size++;
    616
    617
    774
            if (size == 0 || (item = cbor_new_definite_map(size)) == NULL)
    618
    1
                    return (NULL);
    619
    620
    773
            if (ext->mask & FIDO_EXT_CRED_BLOB) {
    621
    280
                    if (cbor_add_bytestring(item, "credBlob", blob->ptr,
    622
    280
                        blob->len) < 0) {
    623
    1
                            cbor_decref(&item);
    624
    1
                            return (NULL);
    625
    1
                    }
    626
    280
            }
    627
    772
            if (ext->mask & FIDO_EXT_CRED_PROTECT) {
    628
    516
                    if (ext->prot < 0 || ext->prot > UINT8_MAX ||
    629
    516
                        cbor_add_uint8(item, "credProtect",
    630
    516
                        (uint8_t)ext->prot) < 0) {
    631
    4
                            cbor_decref(&item);
    632
    4
                            return (NULL);
    633
    4
                    }
    634
    516
            }
    635
    768
            if (ext->mask & FIDO_EXT_HMAC_SECRET) {
    636
    357
                    if (cbor_add_bool(item, "hmac-secret", FIDO_OPT_TRUE) < 0) {
    637
    1
                            cbor_decref(&item);
    638
    1
                            return (NULL);
    639
    1
                    }
    640
    357
            }
    641
    767
            if (ext->mask & FIDO_EXT_LARGEBLOB_KEY) {
    642
    325
                    if (cbor_encode_largeblob_key_ext(item) < 0) {
    643
    1
                            cbor_decref(&item);
    644
    1
                            return (NULL);
    645
    1
                    }
    646
    325
            }
    647
    766
            if (ext->mask & FIDO_EXT_MINPINLEN) {
    648
    179
                    if (cbor_add_bool(item, "minPinLength", FIDO_OPT_TRUE) < 0) {
    649
    1
                            cbor_decref(&item);
    650
    1
                            return (NULL);
    651
    1
                    }
    652
    179
            }
    653
    654
    765
            return (item);
    655
    766
    }
    656
    657
    cbor_item_t *
    658
    cbor_encode_cred_opt(fido_opt_t rk, fido_opt_t uv)
    659
    280
    {
    660
    280
            cbor_item_t *item = NULL;
    661
    662
    280
            if ((item = cbor_new_definite_map(2)) == NULL)
    663
    1
                    return (NULL);
    664
    279
            if ((rk != FIDO_OPT_OMIT && cbor_add_bool(item, "rk", rk) < 0) ||
    665
    279
                (uv != FIDO_OPT_OMIT && cbor_add_bool(item, "uv", uv) < 0)) {
    666
    3
                    cbor_decref(&item);
    667
    3
                    return (NULL);
    668
    3
            }
    669
    670
    276
            return (item);
    671
    279
    }
    672
    673
    cbor_item_t *
    674
    cbor_encode_assert_opt(fido_opt_t up, fido_opt_t uv)
    675
    232
    {
    676
    232
            cbor_item_t *item = NULL;
    677
    678
    232
            if ((item = cbor_new_definite_map(2)) == NULL)
    679
    1
                    return (NULL);
    680
    231
            if ((up != FIDO_OPT_OMIT && cbor_add_bool(item, "up", up) < 0) ||
    681
    231
                (uv != FIDO_OPT_OMIT && cbor_add_bool(item, "uv", uv) < 0)) {
    682
    3
                    cbor_decref(&item);
    683
    3
                    return (NULL);
    684
    3
            }
    685
    686
    228
            return (item);
    687
    231
    }
    688
    689
    cbor_item_t *
    690
    cbor_encode_pin_auth(const fido_dev_t *dev, const fido_blob_t *secret,
    691
        const fido_blob_t *data)
    692
    2.27k
    {
    693
    2.27k
            const EVP_MD    *md = NULL;
    694
    2.27k
            unsigned char    dgst[SHA256_DIGEST_LENGTH];
    695
    2.27k
            unsigned int     dgst_len;
    696
    2.27k
            size_t           outlen;
    697
    2.27k
            uint8_t          prot;
    698
    2.27k
            fido_blob_t      key;
    699
    700
    2.27k
            key.ptr = secret->ptr;
    701
    2.27k
            key.len = secret->len;
    702
    703
    2.27k
            if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
    704
    0
                    fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
    705
    0
                    return (NULL);
    706
    0
            }
    707
    708
            /* select hmac portion of the shared secret */
    709
    2.27k
            if (prot == CTAP_PIN_PROTOCOL2 && key.len > 32)
    710
    32
                    key.len = 32;
    711
    712
    2.27k
            if ((md = EVP_sha256()) == NULL || HMAC(md, key.ptr,
    713
    2.26k
                (int)key.len, data->ptr, data->len, dgst,
    714
    2.26k
                &dgst_len) == NULL || dgst_len != SHA256_DIGEST_LENGTH)
    715
    21
                    return (NULL);
    716
    717
    2.25k
            outlen = (prot == CTAP_PIN_PROTOCOL1) ? 16 : dgst_len;
    718
    719
    2.25k
            return (cbor_build_bytestring(dgst, outlen));
    720
    2.27k
    }
    721
    722
    cbor_item_t *
    723
    cbor_encode_pin_opt(const fido_dev_t *dev)
    724
    11.7k
    {
    725
    11.7k
            uint8_t     prot;
    726
    727
    11.7k
            if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
    728
    1.90k
                    fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
    729
    1.90k
                    return (NULL);
    730
    1.90k
            }
    731
    732
    9.82k
            return (cbor_build_uint8(prot));
    733
    11.7k
    }
    734
    735
    cbor_item_t *
    736
    cbor_encode_change_pin_auth(const fido_dev_t *dev, const fido_blob_t *secret,
    737
        const fido_blob_t *new_pin_enc, const fido_blob_t *pin_hash_enc)
    738
    33
    {
    739
    33
            unsigned char    dgst[SHA256_DIGEST_LENGTH];
    740
    33
            unsigned int     dgst_len;
    741
    33
            cbor_item_t     *item = NULL;
    742
    33
            const EVP_MD    *md = NULL;
    743
    33
            HMAC_CTX        *ctx = NULL;
    744
    33
            fido_blob_t      key;
    745
    33
            uint8_t          prot;
    746
    33
            size_t           outlen;
    747
    748
    33
            key.ptr = secret->ptr;
    749
    33
            key.len = secret->len;
    750
    751
    33
            if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
    752
    0
                    fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
    753
    0
                    goto fail;
    754
    0
            }
    755
    756
    33
            if (prot == CTAP_PIN_PROTOCOL2 && key.len > 32)
    757
    23
                    key.len = 32;
    758
    759
    33
            if ((ctx = HMAC_CTX_new()) == NULL ||
    760
    33
                (md = EVP_sha256())  == NULL ||
    761
    33
                HMAC_Init_ex(ctx, key.ptr, (int)key.len, md, NULL) == 0 ||
    762
    33
                HMAC_Update(ctx, new_pin_enc->ptr, new_pin_enc->len) == 0 ||
    763
    33
                HMAC_Update(ctx, pin_hash_enc->ptr, pin_hash_enc->len) == 0 ||
    764
    33
                HMAC_Final(ctx, dgst, &dgst_len) == 0 ||
    765
    33
                dgst_len != SHA256_DIGEST_LENGTH) {
    766
    7
                    fido_log_debug("%s: HMAC", __func__);
    767
    7
                    goto fail;
    768
    7
            }
    769
    770
    26
            outlen = (prot == CTAP_PIN_PROTOCOL1) ? 16 : dgst_len;
    771
    772
    26
            if ((item = cbor_build_bytestring(dgst, outlen)) == NULL) {
    773
    1
                    fido_log_debug("%s: cbor_build_bytestring", __func__);
    774
    1
                    goto fail;
    775
    1
            }
    776
    777
    33
    fail:
    778
    33
            HMAC_CTX_free(ctx);
    779
    780
    33
            return (item);
    781
    26
    }
    782
    783
    static int
    784
    cbor_encode_hmac_secret_param(const fido_dev_t *dev, cbor_item_t *item,
    785
        const fido_blob_t *ecdh, const es256_pk_t *pk, const fido_blob_t *salt)
    786
    62
    {
    787
    62
            cbor_item_t             *param = NULL;
    788
    62
            cbor_item_t             *argv[4];
    789
    62
            struct cbor_pair         pair;
    790
    62
            fido_blob_t             *enc = NULL;
    791
    62
            uint8_t                  prot;
    792
    62
            int                      r;
    793
    794
    62
            memset(argv, 0, sizeof(argv));
    795
    62
            memset(&pair, 0, sizeof(pair));
    796
    797
    62
            if (item == NULL || ecdh == NULL || pk == NULL || salt->ptr == NULL) {
    798
    9
                    fido_log_debug("%s: ecdh=%p, pk=%p, salt->ptr=%p", __func__,
    799
    9
                        (const void *)ecdh, (const void *)pk,
    800
    9
                        (const void *)salt->ptr);
    801
    9
                    r = FIDO_ERR_INTERNAL;
    802
    9
                    goto fail;
    803
    9
            }
    804
    805
    53
            if (salt->len != 32 && salt->len != 64) {
    806
    0
                    fido_log_debug("%s: salt->len=%zu", __func__, salt->len);
    807
    0
                    r = FIDO_ERR_INTERNAL;
    808
    0
                    goto fail;
    809
    0
            }
    810
    811
    53
            if ((enc = fido_blob_new()) == NULL ||
    812
    53
                aes256_cbc_enc(dev, ecdh, salt, enc) < 0) {
    813
    2
                    fido_log_debug("%s: aes256_cbc_enc", __func__);
    814
    2
                    r = FIDO_ERR_INTERNAL;
    815
    2
                    goto fail;
    816
    2
            }
    817
    818
    51
            if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
    819
    0
                    fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
    820
    0
                    r = FIDO_ERR_INTERNAL;
    821
    0
                    goto fail;
    822
    0
            }
    823
    824
            /* XXX not pin, but salt */
    825
    51
            if ((argv[0] = es256_pk_encode(pk, 1)) == NULL ||
    826
    51
                (argv[1] = fido_blob_encode(enc)) == NULL ||
    827
    51
                (argv[2] = cbor_encode_pin_auth(dev, ecdh, enc)) == NULL ||
    828
    51
                (prot != 1 && (argv[3] = cbor_build_uint8(prot)) == NULL)) {
    829
    6
                    fido_log_debug("%s: cbor encode", __func__);
    830
    6
                    r = FIDO_ERR_INTERNAL;
    831
    6
                    goto fail;
    832
    6
            }
    833
    834
    45
            if ((param = cbor_flatten_vector(argv, nitems(argv))) == NULL) {
    835
    1
                    fido_log_debug("%s: cbor_flatten_vector", __func__);
    836
    1
                    r = FIDO_ERR_INTERNAL;
    837
    1
                    goto fail;
    838
    1
            }
    839
    840
    44
            if ((pair.key = cbor_build_string("hmac-secret")) == NULL) {
    841
    1
                    fido_log_debug("%s: cbor_build", __func__);
    842
    1
                    r = FIDO_ERR_INTERNAL;
    843
    1
                    goto fail;
    844
    1
            }
    845
    846
    43
            pair.value = param;
    847
    848
    43
            if (!cbor_map_add(item, pair)) {
    849
    1
                    fido_log_debug("%s: cbor_map_add", __func__);
    850
    1
                    r = FIDO_ERR_INTERNAL;
    851
    1
                    goto fail;
    852
    1
            }
    853
    854
    42
            r = FIDO_OK;
    855
    856
    62
    fail:
    857
    62
            cbor_vector_free(argv, nitems(argv));
    858
    859
    62
            if (param != NULL)
    860
    44
                    cbor_decref(&param);
    861
    62
            if (pair.key != NULL)
    862
    43
                    cbor_decref(&pair.key);
    863
    864
    62
            fido_blob_free(&enc);
    865
    866
    62
            return (r);
    867
    42
    }
    868
    869
    cbor_item_t *
    870
    cbor_encode_assert_ext(fido_dev_t *dev, const fido_assert_ext_t *ext,
    871
        const fido_blob_t *ecdh, const es256_pk_t *pk)
    872
    316
    {
    873
    316
            cbor_item_t *item = NULL;
    874
    316
            size_t size = 0;
    875
    876
    316
            if (ext->mask & FIDO_EXT_CRED_BLOB)
    877
    215
                    size++;
    878
    316
            if (ext->mask & FIDO_EXT_HMAC_SECRET)
    879
    62
                    size++;
    880
    316
            if (ext->mask & FIDO_EXT_LARGEBLOB_KEY)
    881
    187
                    size++;
    882
    316
            if (size == 0 || (item = cbor_new_definite_map(size)) == NULL)
    883
    1
                    return (NULL);
    884
    885
    315
            if (ext->mask & FIDO_EXT_CRED_BLOB) {
    886
    214
                    if (cbor_add_bool(item, "credBlob", FIDO_OPT_TRUE) < 0) {
    887
    1
                            cbor_decref(&item);
    888
    1
                            return (NULL);
    889
    1
                    }
    890
    214
            }
    891
    314
            if (ext->mask & FIDO_EXT_HMAC_SECRET) {
    892
    62
                    if (cbor_encode_hmac_secret_param(dev, item, ecdh, pk,
    893
    62
                        &ext->hmac_salt) < 0) {
    894
    20
                            cbor_decref(&item);
    895
    20
                            return (NULL);
    896
    20
                    }
    897
    62
            }
    898
    294
            if (ext->mask & FIDO_EXT_LARGEBLOB_KEY) {
    899
    175
                    if (cbor_encode_largeblob_key_ext(item) < 0) {
    900
    1
                            cbor_decref(&item);
    901
    1
                            return (NULL);
    902
    1
                    }
    903
    175
            }
    904
    905
    293
            return (item);
    906
    294
    }
    907
    908
    int
    909
    cbor_decode_fmt(const cbor_item_t *item, char **fmt)
    910
    457
    {
    911
    457
            char    *type = NULL;
    912
    913
    457
            if (cbor_string_copy(item, &type) < 0) {
    914
    9
                    fido_log_debug("%s: cbor_string_copy", __func__);
    915
    9
                    return (-1);
    916
    9
            }
    917
    918
    448
            if (strcmp(type, "packed") && strcmp(type, "fido-u2f") &&
    919
    448
                strcmp(type, "none") && strcmp(type, "tpm")) {
    920
    3
                    fido_log_debug("%s: type=%s", __func__, type);
    921
    3
                    free(type);
    922
    3
                    return (-1);
    923
    3
            }
    924
    925
    445
            *fmt = type;
    926
    927
    445
            return (0);
    928
    448
    }
    929
    930
    struct cose_key {
    931
            int kty;
    932
            int alg;
    933
            int crv;
    934
    };
    935
    936
    static int
    937
    find_cose_alg(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    938
    8.88k
    {
    939
    8.88k
            struct cose_key *cose_key = arg;
    940
    941
    8.88k
            if (cbor_isa_uint(key) == true &&
    942
    8.88k
                cbor_int_get_width(key) == CBOR_INT_8) {
    943
    4.09k
                    switch (cbor_get_uint8(key)) {
    944
    2.02k
                    case 1:
    945
    2.02k
                            if (cbor_isa_uint(val) == false ||
    946
    2.02k
                                cbor_get_int(val) > INT_MAX || cose_key->kty != 0) {
    947
    48
                                    fido_log_debug("%s: kty", __func__);
    948
    48
                                    return (-1);
    949
    48
                            }
    950
    951
    1.97k
                            cose_key->kty = (int)cbor_get_int(val);
    952
    953
    1.97k
                            break;
    954
    1.98k
                    case 3:
    955
    1.98k
                            if (cbor_isa_negint(val) == false ||
    956
    1.98k
                                cbor_get_int(val) > INT_MAX || cose_key->alg != 0) {
    957
    56
                                    fido_log_debug("%s: alg", __func__);
    958
    56
                                    return (-1);
    959
    56
                            }
    960
    961
    1.92k
                            cose_key->alg = -(int)cbor_get_int(val) - 1;
    962
    963
    1.92k
                            break;
    964
    4.09k
                    }
    965
    4.79k
            } else if (cbor_isa_negint(key) == true &&
    966
    4.79k
                cbor_int_get_width(key) == CBOR_INT_8) {
    967
    4.56k
                    if (cbor_get_uint8(key) == 0) {
    968
                            /* get crv if not rsa, otherwise ignore */
    969
    1.75k
                            if (cbor_isa_uint(val) == true &&
    970
    1.75k
                                cbor_get_int(val) <= INT_MAX &&
    971
    1.75k
                                cose_key->crv == 0)
    972
    1.58k
                                    cose_key->crv = (int)cbor_get_int(val);
    973
    1.75k
                    }
    974
    4.56k
            }
    975
    976
    8.78k
            return (0);
    977
    8.88k
    }
    978
    979
    static int
    980
    get_cose_alg(const cbor_item_t *item, int *cose_alg)
    981
    2.09k
    {
    982
    2.09k
            struct cose_key cose_key;
    983
    984
    2.09k
            memset(&cose_key, 0, sizeof(cose_key));
    985
    986
    2.09k
            *cose_alg = 0;
    987
    988
    2.09k
            if (cbor_isa_map(item) == false ||
    989
    2.09k
                cbor_map_is_definite(item) == false ||
    990
    2.09k
                cbor_map_iter(item, &cose_key, find_cose_alg) < 0) {
    991
    215
                    fido_log_debug("%s: cbor type", __func__);
    992
    215
                    return (-1);
    993
    215
            }
    994
    995
    1.88k
            switch (cose_key.alg) {
    996
    1.09k
            case COSE_ES256:
    997
    1.09k
                    if (cose_key.kty != COSE_KTY_EC2 ||
    998
    1.09k
                        cose_key.crv != COSE_P256) {
    999
    69
                            fido_log_debug("%s: invalid kty/crv", __func__);
    1000
    69
                            return (-1);
    1001
    69
                    }
    1002
    1.02k
                    break;
    1003
    1.02k
            case COSE_ES384:
    1004
    90
                    if (cose_key.kty != COSE_KTY_EC2 ||
    1005
    90
                        cose_key.crv != COSE_P384) {
    1006
    11
                            fido_log_debug("%s: invalid kty/crv", __func__);
    1007
    11
                            return (-1);
    1008
    11
                    }
    1009
    79
                    break;
    1010
    450
            case COSE_EDDSA:
    1011
    450
                    if (cose_key.kty != COSE_KTY_OKP ||
    1012
    450
                        cose_key.crv != COSE_ED25519) {
    1013
    106
                            fido_log_debug("%s: invalid kty/crv", __func__);
    1014
    106
                            return (-1);
    1015
    106
                    }
    1016
    344
                    break;
    1017
    344
            case COSE_RS256:
    1018
    173
                    if (cose_key.kty != COSE_KTY_RSA) {
    1019
    3
                            fido_log_debug("%s: invalid kty/crv", __func__);
    1020
    3
                            return (-1);
    1021
    3
                    }
    1022
    170
                    break;
    1023
    170
            default:
    1024
    78
                    fido_log_debug("%s: unknown alg %d", __func__, cose_key.alg);
    1025
    1026
    78
                    return (-1);
    1027
    1.88k
            }
    1028
    1029
    1.61k
            *cose_alg = cose_key.alg;
    1030
    1031
    1.61k
            return (0);
    1032
    1.88k
    }
    1033
    1034
    int
    1035
    cbor_decode_pubkey(const cbor_item_t *item, int *type, void *key)
    1036
    2.09k
    {
    1037
    2.09k
            if (get_cose_alg(item, type) < 0) {
    1038
    482
                    fido_log_debug("%s: get_cose_alg", __func__);
    1039
    482
                    return (-1);
    1040
    482
            }
    1041
    1042
    1.61k
            switch (*type) {
    1043
    1.02k
            case COSE_ES256:
    1044
    1.02k
                    if (es256_pk_decode(item, key) < 0) {
    1045
    8
                            fido_log_debug("%s: es256_pk_decode", __func__);
    1046
    8
                            return (-1);
    1047
    8
                    }
    1048
    1.01k
                    break;
    1049
    1.01k
            case COSE_ES384:
    1050
    79
                    if (es384_pk_decode(item, key) < 0) {
    1051
    10
                            fido_log_debug("%s: es384_pk_decode", __func__);
    1052
    10
                            return (-1);
    1053
    10
                    }
    1054
    69
                    break;
    1055
    170
            case COSE_RS256:
    1056
    170
                    if (rs256_pk_decode(item, key) < 0) {
    1057
    15
                            fido_log_debug("%s: rs256_pk_decode", __func__);
    1058
    15
                            return (-1);
    1059
    15
                    }
    1060
    155
                    break;
    1061
    344
            case COSE_EDDSA:
    1062
    344
                    if (eddsa_pk_decode(item, key) < 0) {
    1063
    19
                            fido_log_debug("%s: eddsa_pk_decode", __func__);
    1064
    19
                            return (-1);
    1065
    19
                    }
    1066
    325
                    break;
    1067
    325
            default:
    1068
    0
                    fido_log_debug("%s: invalid cose_alg %d", __func__, *type);
    1069
    0
                    return (-1);
    1070
    1.61k
            }
    1071
    1072
    1.56k
            return (0);
    1073
    1.61k
    }
    1074
    1075
    static int
    1076
    decode_attcred(const unsigned char **buf, size_t *len, int cose_alg,
    1077
        fido_attcred_t *attcred)
    1078
    1.12k
    {
    1079
    1.12k
            cbor_item_t             *item = NULL;
    1080
    1.12k
            struct cbor_load_result  cbor;
    1081
    1.12k
            uint16_t                 id_len;
    1082
    1.12k
            int                      ok = -1;
    1083
    1084
    1.12k
            fido_log_xxd(*buf, *len, "%s", __func__);
    1085
    1086
    1.12k
            if (fido_buf_read(buf, len, &attcred->aaguid,
    1087
    1.12k
                sizeof(attcred->aaguid)) < 0) {
    1088
    1
                    fido_log_debug("%s: fido_buf_read aaguid", __func__);
    1089
    1
                    return (-1);
    1090
    1
            }
    1091
    1092
    1.12k
            if (fido_buf_read(buf, len, &id_len, sizeof(id_len)) < 0) {
    1093
    1
                    fido_log_debug("%s: fido_buf_read id_len", __func__);
    1094
    1
                    return (-1);
    1095
    1
            }
    1096
    1097
    1.12k
            attcred->id.len = (size_t)be16toh(id_len);
    1098
    1.12k
            if ((attcred->id.ptr = malloc(attcred->id.len)) == NULL)
    1099
    3
                    return (-1);
    1100
    1101
    1.12k
            fido_log_debug("%s: attcred->id.len=%zu", __func__, attcred->id.len);
    1102
    1103
    1.12k
            if (fido_buf_read(buf, len, attcred->id.ptr, attcred->id.len) < 0) {
    1104
    19
                    fido_log_debug("%s: fido_buf_read id", __func__);
    1105
    19
                    return (-1);
    1106
    19
            }
    1107
    1108
    1.10k
            if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
    1109
    10
                    fido_log_debug("%s: cbor_load", __func__);
    1110
    10
                    goto fail;
    1111
    10
            }
    1112
    1113
    1.09k
            if (cbor_decode_pubkey(item, &attcred->type, &attcred->pubkey) < 0) {
    1114
    136
                    fido_log_debug("%s: cbor_decode_pubkey", __func__);
    1115
    136
                    goto fail;
    1116
    136
            }
    1117
    1118
    956
            if (attcred->type != cose_alg) {
    1119
    8
                    fido_log_debug("%s: cose_alg mismatch (%d != %d)", __func__,
    1120
    8
                        attcred->type, cose_alg);
    1121
    8
                    goto fail;
    1122
    8
            }
    1123
    1124
    948
            *buf += cbor.read;
    1125
    948
            *len -= cbor.read;
    1126
    1127
    948
            ok = 0;
    1128
    1.10k
    fail:
    1129
    1.10k
            if (item != NULL)
    1130
    1.09k
                    cbor_decref(&item);
    1131
    1132
    1.10k
            return (ok);
    1133
    948
    }
    1134
    1135
    static int
    1136
    decode_cred_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    1137
    134
    {
    1138
    134
            fido_cred_ext_t *authdata_ext = arg;
    1139
    134
            char            *type = NULL;
    1140
    134
            int              ok = -1;
    1141
    1142
    134
            if (cbor_string_copy(key, &type) < 0) {
    1143
    20
                    fido_log_debug("%s: cbor type", __func__);
    1144
    20
                    ok = 0; /* ignore */
    1145
    20
                    goto out;
    1146
    20
            }
    1147
    1148
    114
            if (strcmp(type, "hmac-secret") == 0) {
    1149
    34
                    if (cbor_decode_bool(val, NULL) < 0) {
    1150
    3
                            fido_log_debug("%s: cbor_decode_bool", __func__);
    1151
    3
                            goto out;
    1152
    3
                    }
    1153
    31
                    if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
    1154
    25
                            authdata_ext->mask |= FIDO_EXT_HMAC_SECRET;
    1155
    80
            } else if (strcmp(type, "credProtect") == 0) {
    1156
    38
                    if (cbor_isa_uint(val) == false ||
    1157
    38
                        cbor_int_get_width(val) != CBOR_INT_8) {
    1158
    2
                            fido_log_debug("%s: cbor type", __func__);
    1159
    2
                            goto out;
    1160
    2
                    }
    1161
    36
                    authdata_ext->mask |= FIDO_EXT_CRED_PROTECT;
    1162
    36
                    authdata_ext->prot = cbor_get_uint8(val);
    1163
    42
            } else if (strcmp(type, "credBlob") == 0) {
    1164
    16
                    if (cbor_decode_bool(val, NULL) < 0) {
    1165
    1
                            fido_log_debug("%s: cbor_decode_bool", __func__);
    1166
    1
                            goto out;
    1167
    1
                    }
    1168
    15
                    if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
    1169
    9
                            authdata_ext->mask |= FIDO_EXT_CRED_BLOB;
    1170
    26
            } else if (strcmp(type, "minPinLength") == 0) {
    1171
    13
                    if (cbor_isa_uint(val) == false ||
    1172
    13
                        cbor_int_get_width(val) != CBOR_INT_8) {
    1173
    4
                            fido_log_debug("%s: cbor type", __func__);
    1174
    4
                            goto out;
    1175
    4
                    }
    1176
    9
                    authdata_ext->mask |= FIDO_EXT_MINPINLEN;
    1177
    9
                    authdata_ext->minpinlen = cbor_get_uint8(val);
    1178
    9
            }
    1179
    1180
    104
            ok = 0;
    1181
    134
    out:
    1182
    134
            free(type);
    1183
    1184
    134
            return (ok);
    1185
    104
    }
    1186
    1187
    static int
    1188
    decode_cred_extensions(const unsigned char **buf, size_t *len,
    1189
        fido_cred_ext_t *authdata_ext)
    1190
    101
    {
    1191
    101
            cbor_item_t             *item = NULL;
    1192
    101
            struct cbor_load_result  cbor;
    1193
    101
            int                      ok = -1;
    1194
    1195
    101
            memset(authdata_ext, 0, sizeof(*authdata_ext));
    1196
    1197
    101
            fido_log_xxd(*buf, *len, "%s", __func__);
    1198
    1199
    101
            if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
    1200
    6
                    fido_log_debug("%s: cbor_load", __func__);
    1201
    6
                    goto fail;
    1202
    6
            }
    1203
    1204
    95
            if (cbor_isa_map(item) == false ||
    1205
    95
                cbor_map_is_definite(item) == false ||
    1206
    95
                cbor_map_iter(item, authdata_ext, decode_cred_extension) < 0) {
    1207
    13
                    fido_log_debug("%s: cbor type", __func__);
    1208
    13
                    goto fail;
    1209
    13
            }
    1210
    1211
    82
            *buf += cbor.read;
    1212
    82
            *len -= cbor.read;
    1213
    1214
    82
            ok = 0;
    1215
    101
    fail:
    1216
    101
            if (item != NULL)
    1217
    95
                    cbor_decref(&item);
    1218
    1219
    101
            return (ok);
    1220
    82
    }
    1221
    1222
    static int
    1223
    decode_assert_extension(const cbor_item_t *key, const cbor_item_t *val,
    1224
        void *arg)
    1225
    287
    {
    1226
    287
            fido_assert_extattr_t   *authdata_ext = arg;
    1227
    287
            char                    *type = NULL;
    1228
    287
            int                      ok = -1;
    1229
    1230
    287
            if (cbor_string_copy(key, &type) < 0) {
    1231
    43
                    fido_log_debug("%s: cbor type", __func__);
    1232
    43
                    ok = 0; /* ignore */
    1233
    43
                    goto out;
    1234
    43
            }
    1235
    1236
    244
            if (strcmp(type, "hmac-secret") == 0) {
    1237
    186
                    if (fido_blob_decode(val, &authdata_ext->hmac_secret_enc) < 0) {
    1238
    7
                            fido_log_debug("%s: fido_blob_decode", __func__);
    1239
    7
                            goto out;
    1240
    7
                    }
    1241
    179
                    authdata_ext->mask |= FIDO_EXT_HMAC_SECRET;
    1242
    179
            } else if (strcmp(type, "credBlob") == 0) {
    1243
    23
                    if (fido_blob_decode(val, &authdata_ext->blob) < 0) {
    1244
    1
                            fido_log_debug("%s: fido_blob_decode", __func__);
    1245
    1
                            goto out;
    1246
    1
                    }
    1247
    22
                    authdata_ext->mask |= FIDO_EXT_CRED_BLOB;
    1248
    22
            }
    1249
    1250
    236
            ok = 0;
    1251
    287
    out:
    1252
    287
            free(type);
    1253
    1254
    287
            return (ok);
    1255
    236
    }
    1256
    1257
    static int
    1258
    decode_assert_extensions(const unsigned char **buf, size_t *len,
    1259
        fido_assert_extattr_t *authdata_ext)
    1260
    341
    {
    1261
    341
            cbor_item_t             *item = NULL;
    1262
    341
            struct cbor_load_result  cbor;
    1263
    341
            int                      ok = -1;
    1264
    1265
    341
            fido_log_xxd(*buf, *len, "%s", __func__);
    1266
    1267
    341
            if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
    1268
    15
                    fido_log_debug("%s: cbor_load", __func__);
    1269
    15
                    goto fail;
    1270
    15
            }
    1271
    1272
    326
            if (cbor_isa_map(item) == false ||
    1273
    326
                cbor_map_is_definite(item) == false ||
    1274
    326
                cbor_map_iter(item, authdata_ext, decode_assert_extension) < 0) {
    1275
    75
                    fido_log_debug("%s: cbor type", __func__);
    1276
    75
                    goto fail;
    1277
    75
            }
    1278
    1279
    251
            *buf += cbor.read;
    1280
    251
            *len -= cbor.read;
    1281
    1282
    251
            ok = 0;
    1283
    341
    fail:
    1284
    341
            if (item != NULL)
    1285
    326
                    cbor_decref(&item);
    1286
    1287
    341
            return (ok);
    1288
    251
    }
    1289
    1290
    int
    1291
    cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg,
    1292
        fido_blob_t *authdata_cbor, fido_authdata_t *authdata,
    1293
        fido_attcred_t *attcred, fido_cred_ext_t *authdata_ext)
    1294
    1.13k
    {
    1295
    1.13k
            const unsigned char     *buf = NULL;
    1296
    1.13k
            size_t                   len;
    1297
    1.13k
            size_t                   alloc_len;
    1298
    1299
    1.13k
            if (cbor_isa_bytestring(item) == false ||
    1300
    1.13k
                cbor_bytestring_is_definite(item) == false) {
    1301
    0
                    fido_log_debug("%s: cbor type", __func__);
    1302
    0
                    return (-1);
    1303
    0
            }
    1304
    1305
    1.13k
            if (authdata_cbor->ptr != NULL ||
    1306
    1.13k
                (authdata_cbor->len = cbor_serialize_alloc(item,
    1307
    1.13k
                &authdata_cbor->ptr, &alloc_len)) == 0) {
    1308
    9
                    fido_log_debug("%s: cbor_serialize_alloc", __func__);
    1309
    9
                    return (-1);
    1310
    9
            }
    1311
    1312
    1.12k
            buf = cbor_bytestring_handle(item);
    1313
    1.12k
            len = cbor_bytestring_length(item);
    1314
    1.12k
            fido_log_xxd(buf, len, "%s", __func__);
    1315
    1316
    1.12k
            if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
    1317
    2
                    fido_log_debug("%s: fido_buf_read", __func__);
    1318
    2
                    return (-1);
    1319
    2
            }
    1320
    1321
    1.12k
            authdata->sigcount = be32toh(authdata->sigcount);
    1322
    1323
    1.12k
            if (attcred != NULL) {
    1324
    1.12k
                    if ((authdata->flags & CTAP_AUTHDATA_ATT_CRED) == 0 ||
    1325
    1.12k
                        decode_attcred(&buf, &len, cose_alg, attcred) < 0)
    1326
    179
                            return (-1);
    1327
    1.12k
            }
    1328
    1329
    948
            if (authdata_ext != NULL) {
    1330
    948
                    if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0 &&
    1331
    948
                        decode_cred_extensions(&buf, &len, authdata_ext) < 0)
    1332
    19
                            return (-1);
    1333
    948
            }
    1334
    1335
            /* XXX we should probably ensure that len == 0 at this point */
    1336
    1337
    929
            return (FIDO_OK);
    1338
    948
    }
    1339
    1340
    int
    1341
    cbor_decode_assert_authdata(const cbor_item_t *item, fido_blob_t *authdata_cbor,
    1342
        fido_authdata_t *authdata, fido_assert_extattr_t *authdata_ext)
    1343
    1.52k
    {
    1344
    1.52k
            const unsigned char     *buf = NULL;
    1345
    1.52k
            size_t                   len;
    1346
    1.52k
            size_t                   alloc_len;
    1347
    1348
    1.52k
            if (cbor_isa_bytestring(item) == false ||
    1349
    1.52k
                cbor_bytestring_is_definite(item) == false) {
    1350
    0
                    fido_log_debug("%s: cbor type", __func__);
    1351
    0
                    return (-1);
    1352
    0
            }
    1353
    1354
    1.52k
            if (authdata_cbor->ptr != NULL ||
    1355
    1.52k
                (authdata_cbor->len = cbor_serialize_alloc(item,
    1356
    1.52k
                &authdata_cbor->ptr, &alloc_len)) == 0) {
    1357
    22
                    fido_log_debug("%s: cbor_serialize_alloc", __func__);
    1358
    22
                    return (-1);
    1359
    22
            }
    1360
    1361
    1.50k
            buf = cbor_bytestring_handle(item);
    1362
    1.50k
            len = cbor_bytestring_length(item);
    1363
    1364
    1.50k
            fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len);
    1365
    1366
    1.50k
            if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
    1367
    6
                    fido_log_debug("%s: fido_buf_read", __func__);
    1368
    6
                    return (-1);
    1369
    6
            }
    1370
    1371
    1.49k
            authdata->sigcount = be32toh(authdata->sigcount);
    1372
    1373
    1.49k
            if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0) {
    1374
    341
                    if (decode_assert_extensions(&buf, &len, authdata_ext) < 0) {
    1375
    90
                            fido_log_debug("%s: decode_assert_extensions",
    1376
    90
                                __func__);
    1377
    90
                            return (-1);
    1378
    90
                    }
    1379
    341
            }
    1380
    1381
            /* XXX we should probably ensure that len == 0 at this point */
    1382
    1383
    1.40k
            return (FIDO_OK);
    1384
    1.49k
    }
    1385
    1386
    static int
    1387
    decode_x5c(const cbor_item_t *item, void *arg)
    1388
    807
    {
    1389
    807
            fido_blob_t *x5c = arg;
    1390
    1391
    807
            if (x5c->len)
    1392
    341
                    return (0); /* ignore */
    1393
    1394
    466
            return (fido_blob_decode(item, x5c));
    1395
    807
    }
    1396
    1397
    static int
    1398
    decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    1399
    2.68k
    {
    1400
    2.68k
            fido_attstmt_t  *attstmt = arg;
    1401
    2.68k
            char            *name = NULL;
    1402
    2.68k
            int              ok = -1;
    1403
    1404
    2.68k
            if (cbor_string_copy(key, &name) < 0) {
    1405
    69
                    fido_log_debug("%s: cbor type", __func__);
    1406
    69
                    ok = 0; /* ignore */
    1407
    69
                    goto out;
    1408
    69
            }
    1409
    1410
    2.61k
            if (!strcmp(name, "alg")) {
    1411
    830
                    if (cbor_isa_negint(val) == false ||
    1412
    830
                        cbor_get_int(val) > UINT16_MAX) {
    1413
    8
                            fido_log_debug("%s: alg", __func__);
    1414
    8
                            goto out;
    1415
    8
                    }
    1416
    822
                    attstmt->alg = -(int)cbor_get_int(val) - 1;
    1417
    822
                    if (attstmt->alg != COSE_ES256 && attstmt->alg != COSE_ES384 &&
    1418
    822
                        attstmt->alg != COSE_RS256 && attstmt->alg != COSE_EDDSA &&
    1419
    822
                        attstmt->alg != COSE_RS1) {
    1420
    22
                            fido_log_debug("%s: unsupported attstmt->alg=%d",
    1421
    22
                                __func__, attstmt->alg);
    1422
    22
                            goto out;
    1423
    22
                    }
    1424
    1.78k
            } else if (!strcmp(name, "sig")) {
    1425
    807
                    if (fido_blob_decode(val, &attstmt->sig) < 0) {
    1426
    12
                            fido_log_debug("%s: sig", __func__);
    1427
    12
                            goto out;
    1428
    12
                    }
    1429
    982
            } else if (!strcmp(name, "x5c")) {
    1430
    472
                    if (cbor_isa_array(val) == false ||
    1431
    472
                        cbor_array_is_definite(val) == false ||
    1432
    472
                        cbor_array_iter(val, &attstmt->x5c, decode_x5c) < 0) {
    1433
    19
                            fido_log_debug("%s: x5c", __func__);
    1434
    19
                            goto out;
    1435
    19
                    }
    1436
    510
            } else if (!strcmp(name, "certInfo")) {
    1437
    95
                    if (fido_blob_decode(val, &attstmt->certinfo) < 0) {
    1438
    1
                            fido_log_debug("%s: certinfo", __func__);
    1439
    1
                            goto out;
    1440
    1
                    }
    1441
    415
            } else if (!strcmp(name, "pubArea")) {
    1442
    102
                    if (fido_blob_decode(val, &attstmt->pubarea) < 0) {
    1443
    3
                            fido_log_debug("%s: pubarea", __func__);
    1444
    3
                            goto out;
    1445
    3
                    }
    1446
    102
            }
    1447
    1448
    2.55k
            ok = 0;
    1449
    2.68k
    out:
    1450
    2.68k
            free(name);
    1451
    1452
    2.68k
            return (ok);
    1453
    2.55k
    }
    1454
    1455
    int
    1456
    cbor_decode_attstmt(const cbor_item_t *item, fido_attstmt_t *attstmt)
    1457
    895
    {
    1458
    895
            size_t alloc_len;
    1459
    1460
    895
            if (cbor_isa_map(item) == false ||
    1461
    895
                cbor_map_is_definite(item) == false ||
    1462
    895
                cbor_map_iter(item, attstmt, decode_attstmt_entry) < 0) {
    1463
    86
                    fido_log_debug("%s: cbor type", __func__);
    1464
    86
                    return (-1);
    1465
    86
            }
    1466
    1467
    809
            if (attstmt->cbor.ptr != NULL ||
    1468
    809
                (attstmt->cbor.len = cbor_serialize_alloc(item,
    1469
    809
                &attstmt->cbor.ptr, &alloc_len)) == 0) {
    1470
    10
                    fido_log_debug("%s: cbor_serialize_alloc", __func__);
    1471
    10
                    return (-1);
    1472
    10
            }
    1473
    1474
    799
            return (0);
    1475
    809
    }
    1476
    1477
    int
    1478
    cbor_decode_uint64(const cbor_item_t *item, uint64_t *n)
    1479
    26.5k
    {
    1480
    26.5k
            if (cbor_isa_uint(item) == false) {
    1481
    105
                    fido_log_debug("%s: cbor type", __func__);
    1482
    105
                    return (-1);
    1483
    105
            }
    1484
    1485
    26.4k
            *n = cbor_get_int(item);
    1486
    1487
    26.4k
            return (0);
    1488
    26.5k
    }
    1489
    1490
    static int
    1491
    decode_cred_id_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    1492
    2.84k
    {
    1493
    2.84k
            fido_blob_t     *id = arg;
    1494
    2.84k
            char            *name = NULL;
    1495
    2.84k
            int              ok = -1;
    1496
    1497
    2.84k
            if (cbor_string_copy(key, &name) < 0) {
    1498
    160
                    fido_log_debug("%s: cbor type", __func__);
    1499
    160
                    ok = 0; /* ignore */
    1500
    160
                    goto out;
    1501
    160
            }
    1502
    1503
    2.68k
            if (!strcmp(name, "id"))
    1504
    858
                    if (fido_blob_decode(val, id) < 0) {
    1505
    5
                            fido_log_debug("%s: cbor_bytestring_copy", __func__);
    1506
    5
                            goto out;
    1507
    5
                    }
    1508
    1509
    2.68k
            ok = 0;
    1510
    2.84k
    out:
    1511
    2.84k
            free(name);
    1512
    1513
    2.84k
            return (ok);
    1514
    2.68k
    }
    1515
    1516
    int
    1517
    cbor_decode_cred_id(const cbor_item_t *item, fido_blob_t *id)
    1518
    1.39k
    {
    1519
    1.39k
            if (cbor_isa_map(item) == false ||
    1520
    1.39k
                cbor_map_is_definite(item) == false ||
    1521
    1.39k
                cbor_map_iter(item, id, decode_cred_id_entry) < 0) {
    1522
    25
                    fido_log_debug("%s: cbor type", __func__);
    1523
    25
                    return (-1);
    1524
    25
            }
    1525
    1526
    1.36k
            return (0);
    1527
    1.39k
    }
    1528
    1529
    static int
    1530
    decode_user_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    1531
    3.39k
    {
    1532
    3.39k
            fido_user_t     *user = arg;
    1533
    3.39k
            char            *name = NULL;
    1534
    3.39k
            int              ok = -1;
    1535
    1536
    3.39k
            if (cbor_string_copy(key, &name) < 0) {
    1537
    34
                    fido_log_debug("%s: cbor type", __func__);
    1538
    34
                    ok = 0; /* ignore */
    1539
    34
                    goto out;
    1540
    34
            }
    1541
    1542
    3.35k
            if (!strcmp(name, "icon")) {
    1543
    46
                    if (cbor_string_copy(val, &user->icon) < 0) {
    1544
    1
                            fido_log_debug("%s: icon", __func__);
    1545
    1
                            goto out;
    1546
    1
                    }
    1547
    3.31k
            } else if (!strcmp(name, "name")) {
    1548
    232
                    if (cbor_string_copy(val, &user->name) < 0) {
    1549
    2
                            fido_log_debug("%s: name", __func__);
    1550
    2
                            goto out;
    1551
    2
                    }
    1552
    3.08k
            } else if (!strcmp(name, "displayName")) {
    1553
    111
                    if (cbor_string_copy(val, &user->display_name) < 0) {
    1554
    1
                            fido_log_debug("%s: display_name", __func__);
    1555
    1
                            goto out;
    1556
    1
                    }
    1557
    2.97k
            } else if (!strcmp(name, "id")) {
    1558
    811
                    if (fido_blob_decode(val, &user->id) < 0) {
    1559
    4
                            fido_log_debug("%s: id", __func__);
    1560
    4
                            goto out;
    1561
    4
                    }
    1562
    811
            }
    1563
    1564
    3.35k
            ok = 0;
    1565
    3.39k
    out:
    1566
    3.39k
            free(name);
    1567
    1568
    3.39k
            return (ok);
    1569
    3.35k
    }
    1570
    1571
    int
    1572
    cbor_decode_user(const cbor_item_t *item, fido_user_t *user)
    1573
    1.33k
    {
    1574
    1.33k
            if (cbor_isa_map(item) == false ||
    1575
    1.33k
                cbor_map_is_definite(item) == false ||
    1576
    1.33k
                cbor_map_iter(item, user, decode_user_entry) < 0) {
    1577
    19
                    fido_log_debug("%s: cbor type", __func__);
    1578
    19
                    return (-1);
    1579
    19
            }
    1580
    1581
    1.31k
            return (0);
    1582
    1.33k
    }
    1583
    1584
    static int
    1585
    decode_rp_entity_entry(const cbor_item_t *key, const cbor_item_t *val,
    1586
        void *arg)
    1587
    318
    {
    1588
    318
            fido_rp_t       *rp = arg;
    1589
    318
            char            *name = NULL;
    1590
    318
            int              ok = -1;
    1591
    1592
    318
            if (cbor_string_copy(key, &name) < 0) {
    1593
    18
                    fido_log_debug("%s: cbor type", __func__);
    1594
    18
                    ok = 0; /* ignore */
    1595
    18
                    goto out;
    1596
    18
            }
    1597
    1598
    300
            if (!strcmp(name, "id")) {
    1599
    45
                    if (cbor_string_copy(val, &rp->id) < 0) {
    1600
    1
                            fido_log_debug("%s: id", __func__);
    1601
    1
                            goto out;
    1602
    1
                    }
    1603
    255
            } else if (!strcmp(name, "name")) {
    1604
    2
                    if (cbor_string_copy(val, &rp->name) < 0) {
    1605
    1
                            fido_log_debug("%s: name", __func__);
    1606
    1
                            goto out;
    1607
    1
                    }
    1608
    2
            }
    1609
    1610
    298
            ok = 0;
    1611
    318
    out:
    1612
    318
            free(name);
    1613
    1614
    318
            return (ok);
    1615
    298
    }
    1616
    1617
    int
    1618
    cbor_decode_rp_entity(const cbor_item_t *item, fido_rp_t *rp)
    1619
    316
    {
    1620
    316
            if (cbor_isa_map(item) == false ||
    1621
    316
                cbor_map_is_definite(item) == false ||
    1622
    316
                cbor_map_iter(item, rp, decode_rp_entity_entry) < 0) {
    1623
    6
                    fido_log_debug("%s: cbor type", __func__);
    1624
    6
                    return (-1);
    1625
    6
            }
    1626
    1627
    310
            return (0);
    1628
    316
    }
    1629
    1630
    int
    1631
    cbor_decode_bool(const cbor_item_t *item, bool *v)
    1632
    38.4k
    {
    1633
    38.4k
            if (cbor_isa_float_ctrl(item) == false ||
    1634
    38.4k
                cbor_float_get_width(item) != CBOR_FLOAT_0 ||
    1635
    38.4k
                cbor_is_bool(item) == false) {
    1636
    2.66k
                    fido_log_debug("%s: cbor type", __func__);
    1637
    2.66k
                    return (-1);
    1638
    2.66k
            }
    1639
    1640
    35.8k
            if (v != NULL)
    1641
    355
                    *v = cbor_ctrl_value(item) == CBOR_CTRL_TRUE;
    1642
    1643
    35.8k
            return (0);
    1644
    38.4k
    }
    1645
    1646
    cbor_item_t *
    1647
    cbor_build_uint(const uint64_t value)
    1648
    3.32k
    {
    1649
    3.32k
            if (value <= UINT8_MAX)
    1650
    1.84k
                    return cbor_build_uint8((uint8_t)value);
    1651
    1.48k
            else if (value <= UINT16_MAX)
    1652
    969
                    return cbor_build_uint16((uint16_t)value);
    1653
    512
            else if (value <= UINT32_MAX)
    1654
    512
                    return cbor_build_uint32((uint32_t)value);
    1655
    1656
    0
            return cbor_build_uint64(value);
    1657
    3.32k
    }
    1658
    1659
    int
    1660
    cbor_array_append(cbor_item_t **array, cbor_item_t *item)
    1661
    204
    {
    1662
    204
            cbor_item_t **v, *ret;
    1663
    204
            size_t n;
    1664
    1665
    204
            if ((v = cbor_array_handle(*array)) == NULL ||
    1666
    204
                (n = cbor_array_size(*array)) == SIZE_MAX ||
    1667
    204
                (ret = cbor_new_definite_array(n + 1)) == NULL)
    1668
    2
                    return -1;
    1669
    348
            for (size_t i = 0; i < n; i++) {
    1670
    150
                    if (cbor_array_push(ret, v[i]) == 0) {
    1671
    4
                            cbor_decref(&ret);
    1672
    4
                            return -1;
    1673
    4
                    }
    1674
    150
            }
    1675
    198
            if (cbor_array_push(ret, item) == 0) {
    1676
    1
                    cbor_decref(&ret);
    1677
    1
                    return -1;
    1678
    1
            }
    1679
    197
            cbor_decref(array);
    1680
    197
            *array = ret;
    1681
    1682
    197
            return 0;
    1683
    198
    }
    1684
    1685
    int
    1686
    cbor_array_drop(cbor_item_t **array, size_t idx)
    1687
    192
    {
    1688
    192
            cbor_item_t **v, *ret;
    1689
    192
            size_t n;
    1690
    1691
    192
            if ((v = cbor_array_handle(*array)) == NULL ||
    1692
    192
                (n = cbor_array_size(*array)) == 0 || idx >= n ||
    1693
    192
                (ret = cbor_new_definite_array(n - 1)) == NULL)
    1694
    2
                    return -1;
    1695
    406
            for (size_t i = 0; i < n; i++) {
    1696
    220
                    if (i != idx && cbor_array_push(ret, v[i]) == 0) {
    1697
    4
                            cbor_decref(&ret);
    1698
    4
                            return -1;
    1699
    4
                    }
    1700
    220
            }
    1701
    186
            cbor_decref(array);
    1702
    186
            *array = ret;
    1703
    1704
    186
            return 0;
    1705
    190
    }