## Coverage Report

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

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

    /libfido2/src/cbor.c

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