## Coverage Report

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

    /libfido2/src/rs256.c

    Line
    Count
    Source (jump to first uncovered line)
    1
    /*
    2
     * Copyright (c) 2018-2022 Yubico AB. All rights reserved.
    3
     * Use of this source code is governed by a BSD-style
    4
     * license that can be found in the LICENSE file.
    5
     * SPDX-License-Identifier: BSD-2-Clause
    6
     */
    7
    8
    #include <openssl/bn.h>
    9
    #include <openssl/rsa.h>
    10
    #include <openssl/obj_mac.h>
    11
    12
    #include "fido.h"
    13
    #include "fido/rs256.h"
    14
    15
    #if OPENSSL_VERSION_NUMBER >= 0x30000000
    16
    25
    #define get0_RSA(x)     EVP_PKEY_get0_RSA((x))
    17
    #else
    18
    #define get0_RSA(x)     EVP_PKEY_get0((x))
    19
    #endif
    20
    21
    #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050200fL
    22
    static EVP_MD *
    23
    rs256_get_EVP_MD(void)
    24
    {
    25
            const EVP_MD *from;
    26
            EVP_MD *to = NULL;
    27
    28
            if ((from = EVP_sha256()) != NULL && (to = malloc(sizeof(*to))) != NULL)
    29
                    memcpy(to, from, sizeof(*to));
    30
    31
            return (to);
    32
    }
    33
    34
    static void
    35
    rs256_free_EVP_MD(EVP_MD *md)
    36
    {
    37
            freezero(md, sizeof(*md));
    38
    }
    39
    #elif OPENSSL_VERSION_NUMBER >= 0x30000000
    40
    static EVP_MD *
    41
    rs256_get_EVP_MD(void)
    42
    26
    {
    43
    26
            return (EVP_MD_fetch(NULL, "SHA2-256", NULL));
    44
    26
    }
    45
    46
    static void
    47
    rs256_free_EVP_MD(EVP_MD *md)
    48
    27
    {
    49
    27
            EVP_MD_free(md);
    50
    27
    }
    51
    #else
    52
    static EVP_MD *
    53
    rs256_get_EVP_MD(void)
    54
    {
    55
            const EVP_MD *md;
    56
    57
            if ((md = EVP_sha256()) == NULL)
    58
                    return (NULL);
    59
    60
            return (EVP_MD_meth_dup(md));
    61
    }
    62
    63
    static void
    64
    rs256_free_EVP_MD(EVP_MD *md)
    65
    {
    66
            EVP_MD_meth_free(md);
    67
    }
    68
    #endif /* LIBRESSL_VERSION_NUMBER */
    69
    70
    static int
    71
    decode_bignum(const cbor_item_t *item, void *ptr, size_t len)
    72
    224
    {
    73
    224
            if (cbor_isa_bytestring(item) == false ||
    74
    224
                cbor_bytestring_is_definite(item) == false ||
    75
    224
                cbor_bytestring_length(item) != len) {
    76
    7
                    fido_log_debug("%s: cbor type", __func__);
    77
    7
                    return (-1);
    78
    7
            }
    79
    80
    217
            memcpy(ptr, cbor_bytestring_handle(item), len);
    81
    82
    217
            return (0);
    83
    224
    }
    84
    85
    static int
    86
    decode_rsa_pubkey(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    87
    636
    {
    88
    636
            rs256_pk_t *k = arg;
    89
    90
    636
            if (cbor_isa_negint(key) == false ||
    91
    636
                cbor_int_get_width(key) != CBOR_INT_8)
    92
    384
                    return (0); /* ignore */
    93
    94
    252
            switch (cbor_get_uint8(key)) {
    95
    116
            case 0: /* modulus */
    96
    116
                    return (decode_bignum(val, &k->n, sizeof(k->n)));
    97
    108
            case 1: /* public exponent */
    98
    108
                    return (decode_bignum(val, &k->e, sizeof(k->e)));
    99
    252
            }
    100
    101
    28
            return (0); /* ignore */
    102
    252
    }
    103
    104
    int
    105
    rs256_pk_decode(const cbor_item_t *item, rs256_pk_t *k)
    106
    170
    {
    107
    170
            if (cbor_isa_map(item) == false ||
    108
    170
                cbor_map_is_definite(item) == false ||
    109
    170
                cbor_map_iter(item, k, decode_rsa_pubkey) < 0) {
    110
    15
                    fido_log_debug("%s: cbor type", __func__);
    111
    15
                    return (-1);
    112
    15
            }
    113
    114
    155
            return (0);
    115
    170
    }
    116
    117
    rs256_pk_t *
    118
    rs256_pk_new(void)
    119
    641
    {
    120
    641
            return (calloc(1, sizeof(rs256_pk_t)));
    121
    641
    }
    122
    123
    void
    124
    rs256_pk_free(rs256_pk_t **pkp)
    125
    2.76k
    {
    126
    2.76k
            rs256_pk_t *pk;
    127
    128
    2.76k
            if (pkp == NULL || (pk = *pkp) == NULL)
    129
    2.12k
                    return;
    130
    131
    639
            freezero(pk, sizeof(*pk));
    132
    639
            *pkp = NULL;
    133
    639
    }
    134
    135
    int
    136
    rs256_pk_from_ptr(rs256_pk_t *pk, const void *ptr, size_t len)
    137
    614
    {
    138
    614
            EVP_PKEY *pkey;
    139
    140
    614
            if (len < sizeof(*pk))
    141
    556
                    return (FIDO_ERR_INVALID_ARGUMENT);
    142
    143
    58
            memcpy(pk, ptr, sizeof(*pk));
    144
    145
    58
            if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) {
    146
    28
                    fido_log_debug("%s: rs256_pk_to_EVP_PKEY", __func__);
    147
    28
                    return (FIDO_ERR_INVALID_ARGUMENT);
    148
    28
            }
    149
    150
    30
            EVP_PKEY_free(pkey);
    151
    152
    30
            return (FIDO_OK);
    153
    58
    }
    154
    155
    EVP_PKEY *
    156
    rs256_pk_to_EVP_PKEY(const rs256_pk_t *k)
    157
    744
    {
    158
    744
            RSA             *rsa = NULL;
    159
    744
            EVP_PKEY        *pkey = NULL;
    160
    744
            BIGNUM          *n = NULL;
    161
    744
            BIGNUM          *e = NULL;
    162
    744
            int              ok = -1;
    163
    164
    744
            if ((n = BN_new()) == NULL || (e = BN_new()) == NULL)
    165
    15
                    goto fail;
    166
    167
    729
            if (BN_bin2bn(k->n, sizeof(k->n), n) == NULL ||
    168
    729
                BN_bin2bn(k->e, sizeof(k->e), e) == NULL) {
    169
    31
                    fido_log_debug("%s: BN_bin2bn", __func__);
    170
    31
                    goto fail;
    171
    31
            }
    172
    173
    698
            if ((rsa = RSA_new()) == NULL || RSA_set0_key(rsa, n, e, NULL) == 0) {
    174
    17
                    fido_log_debug("%s: RSA_set0_key", __func__);
    175
    17
                    goto fail;
    176
    17
            }
    177
    178
            /* at this point, n and e belong to rsa */
    179
    681
            n = NULL;
    180
    681
            e = NULL;
    181
    182
    681
            if (RSA_bits(rsa) != 2048) {
    183
    590
                    fido_log_debug("%s: invalid key length", __func__);
    184
    590
                    goto fail;
    185
    590
            }
    186
    187
    91
            if ((pkey = EVP_PKEY_new()) == NULL ||
    188
    91
                EVP_PKEY_assign_RSA(pkey, rsa) == 0) {
    189
    9
                    fido_log_debug("%s: EVP_PKEY_assign_RSA", __func__);
    190
    9
                    goto fail;
    191
    9
            }
    192
    193
    82
            rsa = NULL; /* at this point, rsa belongs to evp */
    194
    195
    82
            ok = 0;
    196
    744
    fail:
    197
    744
            if (n != NULL)
    198
    55
                    BN_free(n);
    199
    744
            if (e != NULL)
    200
    48
                    BN_free(e);
    201
    744
            if (rsa != NULL)
    202
    611
                    RSA_free(rsa);
    203
    744
            if (ok < 0 && pkey != NULL) {
    204
    5
                    EVP_PKEY_free(pkey);
    205
    5
                    pkey = NULL;
    206
    5
            }
    207
    208
    744
            return (pkey);
    209
    82
    }
    210
    211
    int
    212
    rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa)
    213
    23
    {
    214
    23
            const BIGNUM    *n = NULL;
    215
    23
            const BIGNUM    *e = NULL;
    216
    23
            const BIGNUM    *d = NULL;
    217
    23
            int              k;
    218
    219
    23
            if (RSA_bits(rsa) != 2048) {
    220
    0
                    fido_log_debug("%s: invalid key length", __func__);
    221
    0
                    return (FIDO_ERR_INVALID_ARGUMENT);
    222
    0
            }
    223
    224
    23
            RSA_get0_key(rsa, &n, &e, &d);
    225
    226
    23
            if (n == NULL || e == NULL) {
    227
    0
                    fido_log_debug("%s: RSA_get0_key", __func__);
    228
    0
                    return (FIDO_ERR_INTERNAL);
    229
    0
            }
    230
    231
    23
            if ((k = BN_num_bytes(n)) < 0 || (size_t)k > sizeof(pk->n) ||
    232
    23
                (k = BN_num_bytes(e)) < 0 || (size_t)k > sizeof(pk->e)) {
    233
    0
                    fido_log_debug("%s: invalid key", __func__);
    234
    0
                    return (FIDO_ERR_INTERNAL);
    235
    0
            }
    236
    237
    23
            if ((k = BN_bn2bin(n, pk->n)) < 0 || (size_t)k > sizeof(pk->n) ||
    238
    23
                (k = BN_bn2bin(e, pk->e)) < 0 || (size_t)k > sizeof(pk->e)) {
    239
    3
                    fido_log_debug("%s: BN_bn2bin", __func__);
    240
    3
                    return (FIDO_ERR_INTERNAL);
    241
    3
            }
    242
    243
    20
            return (FIDO_OK);
    244
    23
    }
    245
    246
    int
    247
    rs256_pk_from_EVP_PKEY(rs256_pk_t *pk, const EVP_PKEY *pkey)
    248
    25
    {
    249
    25
            const RSA *rsa;
    250
    251
    25
            if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA ||
    252
    25
                (rsa = get0_RSA(pkey)) == NULL)
    253
    2
                    return (FIDO_ERR_INVALID_ARGUMENT);
    254
    255
    23
            return (rs256_pk_from_RSA(pk, rsa));
    256
    25
    }
    257
    258
    int
    259
    rs256_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
    260
        const fido_blob_t *sig)
    261
    27
    {
    262
    27
            EVP_PKEY_CTX    *pctx = NULL;
    263
    27
            EVP_MD          *md = NULL;
    264
    27
            int              ok = -1;
    265
    266
    27
            if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
    267
    1
                    fido_log_debug("%s: EVP_PKEY_base_id", __func__);
    268
    1
                    goto fail;
    269
    1
            }
    270
    271
    26
            if ((md = rs256_get_EVP_MD()) == NULL) {
    272
    0
                    fido_log_debug("%s: rs256_get_EVP_MD", __func__);
    273
    0
                    goto fail;
    274
    0
            }
    275
    276
    26
            if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL ||
    277
    26
                EVP_PKEY_verify_init(pctx) != 1 ||
    278
    26
                EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1 ||
    279
    26
                EVP_PKEY_CTX_set_signature_md(pctx, md) != 1) {
    280
    4
                    fido_log_debug("%s: EVP_PKEY_CTX", __func__);
    281
    4
                    goto fail;
    282
    4
            }
    283
    284
    22
            if (EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr,
    285
    22
                dgst->len) != 1) {
    286
    22
                    fido_log_debug("%s: EVP_PKEY_verify", __func__);
    287
    22
                    goto fail;
    288
    22
            }
    289
    290
    0
            ok = 0;
    291
    27
    fail:
    292
    27
            EVP_PKEY_CTX_free(pctx);
    293
    27
            rs256_free_EVP_MD(md);
    294
    295
    27
            return (ok);
    296
    0
    }
    297
    298
    int
    299
    rs256_pk_verify_sig(const fido_blob_t *dgst, const rs256_pk_t *pk,
    300
        const fido_blob_t *sig)
    301
    72
    {
    302
    72
            EVP_PKEY        *pkey;
    303
    72
            int              ok = -1;
    304
    305
    72
            if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL ||
    306
    72
                rs256_verify_sig(dgst, pkey, sig) < 0) {
    307
    72
                    fido_log_debug("%s: rs256_verify_sig", __func__);
    308
    72
                    goto fail;
    309
    72
            }
    310
    311
    0
            ok = 0;
    312
    72
    fail:
    313
    72
            EVP_PKEY_free(pkey);
    314
    315
    72
            return (ok);
    316
    0
    }