## Coverage Report

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

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

    /libfido2/src/config.c

    Line
    Count
    Source
    1
    /*
    2
     * Copyright (c) 2020-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 "fido.h"
    9
    #include "fido/config.h"
    10
    #include "fido/es256.h"
    11
    12
    14.3k
    #define CMD_ENABLE_ENTATTEST    0x01
    13
    14.2k
    #define CMD_TOGGLE_ALWAYS_UV    0x02
    14
    32.8k
    #define CMD_SET_PIN_MINLEN      0x03
    15
    16
    static int
    17
    config_prepare_hmac(uint8_t subcmd, const cbor_item_t *item, fido_blob_t *hmac)
    18
    42.5k
    {
    19
    42.5k
            uint8_t prefix[32 + 2 * sizeof(uint8_t)], cbor[128];
    20
    42.5k
            size_t cbor_len = 0;
    21
    22
    42.5k
            memset(prefix, 0xff, sizeof(prefix));
    23
    42.5k
            prefix[sizeof(prefix) - 2] = CTAP_CBOR_CONFIG;
    24
    42.5k
            prefix[sizeof(prefix) - 1] = subcmd;
    25
    26
    42.5k
            if (item != NULL) {
    27
    23.6k
                    if ((cbor_len = cbor_serialize(item, cbor, sizeof(cbor))) == 0) {
    28
    5.83k
                            fido_log_debug("%s: cbor_serialize", __func__);
    29
    5.83k
                            return -1;
    30
    5.83k
                    }
    31
    23.6k
            }
    32
    36.6k
            if ((hmac->ptr = malloc(cbor_len + sizeof(prefix))) == NULL) {
    33
    260
                    fido_log_debug("%s: malloc", __func__);
    34
    260
                    return -1;
    35
    260
            }
    36
    36.4k
            memcpy(hmac->ptr, prefix, sizeof(prefix));
    37
    36.4k
            memcpy(hmac->ptr + sizeof(prefix), cbor, cbor_len);
    38
    36.4k
            hmac->len = cbor_len + sizeof(prefix);
    39
    40
    36.4k
            return 0;
    41
    36.6k
    }
    42
    43
    static int
    44
    config_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **paramv, size_t paramc,
    45
        const char *pin, int *ms)
    46
    61.5k
    {
    47
    61.5k
            cbor_item_t *argv[4];
    48
    61.5k
            es256_pk_t *pk = NULL;
    49
    61.5k
            fido_blob_t *ecdh = NULL, f, hmac;
    50
    61.5k
            const uint8_t cmd = CTAP_CBOR_CONFIG;
    51
    61.5k
            int r = FIDO_ERR_INTERNAL;
    52
    53
    61.5k
            memset(&f, 0, sizeof(f));
    54
    61.5k
            memset(&hmac, 0, sizeof(hmac));
    55
    61.5k
            memset(&argv, 0, sizeof(argv));
    56
    57
            /* subCommand */
    58
    61.5k
            if ((argv[0] = cbor_build_uint8(subcmd)) == NULL) {
    59
    196
                    fido_log_debug("%s: cbor encode", __func__);
    60
    196
                    goto fail;
    61
    196
            }
    62
    63
            /* subCommandParams */
    64
    61.3k
            if (paramc != 0 &&
    65
    61.3k
                (argv[1] = cbor_flatten_vector(paramv, paramc)) == NULL) {
    66
    114
                    fido_log_debug("%s: cbor_flatten_vector", __func__);
    67
    114
                    goto fail;
    68
    114
            }
    69
    70
            /* pinProtocol, pinAuth */
    71
    61.1k
            if (pin != NULL ||
    72
    61.1k
                (fido_dev_supports_permissions(dev) && fido_dev_has_uv(dev))) {
    73
    42.5k
                    if (config_prepare_hmac(subcmd, argv[1], &hmac) < 0) {
    74
    6.09k
                            fido_log_debug("%s: config_prepare_hmac", __func__);
    75
    6.09k
                            goto fail;
    76
    6.09k
                    }
    77
    36.4k
                    if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
    78
    34.1k
                            fido_log_debug("%s: fido_do_ecdh", __func__);
    79
    34.1k
                            goto fail;
    80
    34.1k
                    }
    81
    2.22k
                    if ((r = cbor_add_uv_params(dev, cmd, &hmac, pk, ecdh, pin,
    82
    2.22k
                        NULL, &argv[3], &argv[2], ms)) != FIDO_OK) {
    83
    2.17k
                            fido_log_debug("%s: cbor_add_uv_params", __func__);
    84
    2.17k
                            goto fail;
    85
    2.17k
                    }
    86
    2.22k
            }
    87
    88
            /* framing and transmission */
    89
    18.7k
            if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
    90
    18.7k
                fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
    91
    722
                    fido_log_debug("%s: fido_tx", __func__);
    92
    722
                    r = FIDO_ERR_TX;
    93
    722
                    goto fail;
    94
    722
            }
    95
    96
    18.0k
            r = FIDO_OK;
    97
    61.5k
    fail:
    98
    61.5k
            cbor_vector_free(argv, nitems(argv));
    99
    61.5k
            es256_pk_free(&pk);
    100
    61.5k
            fido_blob_free(&ecdh);
    101
    61.5k
            free(f.ptr);
    102
    61.5k
            free(hmac.ptr);
    103
    104
    61.5k
            return r;
    105
    18.0k
    }
    106
    107
    static int
    108
    config_enable_entattest_wait(fido_dev_t *dev, const char *pin, int *ms)
    109
    14.3k
    {
    110
    14.3k
            int r;
    111
    112
    14.3k
            if ((r = config_tx(dev, CMD_ENABLE_ENTATTEST, NULL, 0, pin,
    113
    14.3k
                ms)) != FIDO_OK)
    114
    9.63k
                    return r;
    115
    116
    4.75k
            return fido_rx_cbor_status(dev, ms);
    117
    14.3k
    }
    118
    119
    int
    120
    fido_dev_enable_entattest(fido_dev_t *dev, const char *pin)
    121
    14.3k
    {
    122
    14.3k
            int ms = dev->timeout_ms;
    123
    124
    14.3k
            return (config_enable_entattest_wait(dev, pin, &ms));
    125
    14.3k
    }
    126
    127
    static int
    128
    config_toggle_always_uv_wait(fido_dev_t *dev, const char *pin, int *ms)
    129
    14.2k
    {
    130
    14.2k
            int r;
    131
    132
    14.2k
            if ((r = config_tx(dev, CMD_TOGGLE_ALWAYS_UV, NULL, 0, pin,
    133
    14.2k
                ms)) != FIDO_OK)
    134
    9.49k
                    return r;
    135
    136
    4.76k
            return (fido_rx_cbor_status(dev, ms));
    137
    14.2k
    }
    138
    139
    int
    140
    fido_dev_toggle_always_uv(fido_dev_t *dev, const char *pin)
    141
    14.2k
    {
    142
    14.2k
            int ms = dev->timeout_ms;
    143
    144
    14.2k
            return config_toggle_always_uv_wait(dev, pin, &ms);
    145
    14.2k
    }
    146
    147
    static int
    148
    config_pin_minlen_tx(fido_dev_t *dev, size_t len, bool force,
    149
        const fido_str_array_t *rpid, const char *pin, int *ms)
    150
    41.8k
    {
    151
    41.8k
            cbor_item_t *argv[3];
    152
    41.8k
            int r;
    153
    154
    41.8k
            memset(argv, 0, sizeof(argv));
    155
    156
    41.8k
            if ((rpid == NULL && len == 0 && !force) || len > UINT8_MAX) {
    157
    6.61k
                    r = FIDO_ERR_INVALID_ARGUMENT;
    158
    6.61k
                    goto fail;
    159
    6.61k
            }
    160
    35.2k
            if (len && (argv[0] = cbor_build_uint8((uint8_t)len)) == NULL) {
    161
    7
                    fido_log_debug("%s: cbor_encode_uint8", __func__);
    162
    7
                    r = FIDO_ERR_INTERNAL;
    163
    7
                    goto fail;
    164
    7
            }
    165
    35.2k
            if (rpid != NULL && (argv[1] = cbor_encode_str_array(rpid)) == NULL) {
    166
    2.34k
                    fido_log_debug("%s: cbor_encode_str_array", __func__);
    167
    2.34k
                    r = FIDO_ERR_INTERNAL;
    168
    2.34k
                    goto fail;
    169
    2.34k
            }
    170
    32.8k
            if (force && (argv[2] = cbor_build_bool(true)) == NULL) {
    171
    17
                    fido_log_debug("%s: cbor_build_bool", __func__);
    172
    17
                    r = FIDO_ERR_INTERNAL;
    173
    17
                    goto fail;
    174
    17
            }
    175
    32.8k
            if ((r = config_tx(dev, CMD_SET_PIN_MINLEN, argv, nitems(argv),
    176
    32.8k
                pin, ms)) != FIDO_OK) {
    177
    24.3k
                    fido_log_debug("%s: config_tx", __func__);
    178
    24.3k
                    goto fail;
    179
    24.3k
            }
    180
    181
    41.8k
    fail:
    182
    41.8k
            cbor_vector_free(argv, nitems(argv));
    183
    184
    41.8k
            return r;
    185
    32.8k
    }
    186
    187
    static int
    188
    config_pin_minlen(fido_dev_t *dev, size_t len, bool force,
    189
        const fido_str_array_t *rpid, const char *pin, int *ms)
    190
    41.8k
    {
    191
    41.8k
            int r;
    192
    193
    41.8k
            if ((r = config_pin_minlen_tx(dev, len, force, rpid, pin,
    194
    41.8k
                ms)) != FIDO_OK)
    195
    33.3k
                    return r;
    196
    197
    8.48k
            return fido_rx_cbor_status(dev, ms);
    198
    41.8k
    }
    199
    200
    int
    201
    fido_dev_set_pin_minlen(fido_dev_t *dev, size_t len, const char *pin)
    202
    14.0k
    {
    203
    14.0k
            int ms = dev->timeout_ms;
    204
    205
    14.0k
            return config_pin_minlen(dev, len, false, NULL, pin, &ms);
    206
    14.0k
    }
    207
    208
    int
    209
    fido_dev_force_pin_change(fido_dev_t *dev, const char *pin)
    210
    14.4k
    {
    211
    14.4k
            int ms = dev->timeout_ms;
    212
    213
    14.4k
            return config_pin_minlen(dev, 0, true, NULL, pin, &ms);
    214
    14.4k
    }
    215
    216
    int
    217
    fido_dev_set_pin_minlen_rpid(fido_dev_t *dev, const char * const *rpid,
    218
        size_t n, const char *pin)
    219
    14.4k
    {
    220
    14.4k
            fido_str_array_t sa;
    221
    14.4k
            int ms = dev->timeout_ms;
    222
    14.4k
            int r;
    223
    224
    14.4k
            memset(&sa, 0, sizeof(sa));
    225
    14.4k
            if (fido_str_array_pack(&sa, rpid, n) < 0) {
    226
    1.09k
                    fido_log_debug("%s: fido_str_array_pack", __func__);
    227
    1.09k
                    r = FIDO_ERR_INTERNAL;
    228
    1.09k
                    goto fail;
    229
    1.09k
            }
    230
    13.3k
            r = config_pin_minlen(dev, 0, false, &sa, pin, &ms);
    231
    14.4k
    fail:
    232
    14.4k
            fido_str_array_free(&sa);
    233
    234
    14.4k
            return r;
    235
    13.3k
    }