## Coverage Report

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

    /libfido2/src/eddsa.c

    Line
    Count
    Source (jump to first uncovered line)
    1
    /*
    2
     * Copyright (c) 2019-2021 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/obj_mac.h>
    10
    11
    #include "fido.h"
    12
    #include "fido/eddsa.h"
    13
    14
    #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3070000f
    15
    EVP_PKEY *
    16
    EVP_PKEY_new_raw_public_key(int type, ENGINE *e, const unsigned char *key,
    17
        size_t keylen)
    18
    {
    19
            (void)type;
    20
            (void)e;
    21
            (void)key;
    22
            (void)keylen;
    23
    24
            fido_log_debug("%s: unimplemented", __func__);
    25
    26
            return (NULL);
    27
    }
    28
    29
    int
    30
    EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
    31
        size_t *len)
    32
    {
    33
            (void)pkey;
    34
            (void)pub;
    35
            (void)len;
    36
    37
            fido_log_debug("%s: unimplemented", __func__);
    38
    39
            return (0);
    40
    }
    41
    #endif /* LIBRESSL_VERSION_NUMBER */
    42
    43
    #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3040000f
    44
    int
    45
    EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen,
    46
        const unsigned char *tbs, size_t tbslen)
    47
    {
    48
            (void)ctx;
    49
            (void)sigret;
    50
            (void)siglen;
    51
            (void)tbs;
    52
            (void)tbslen;
    53
    54
            fido_log_debug("%s: unimplemented", __func__);
    55
    56
            return (0);
    57
    }
    58
    #endif /* LIBRESSL_VERSION_NUMBER < 0x3040000f */
    59
    60
    static int
    61
    decode_coord(const cbor_item_t *item, void *xy, size_t xy_len)
    62
    302
    {
    63
    302
            if (cbor_isa_bytestring(item) == false ||
    64
    302
                cbor_bytestring_is_definite(item) == false ||
    65
    302
                cbor_bytestring_length(item) != xy_len) {
    66
    11
                    fido_log_debug("%s: cbor type", __func__);
    67
    11
                    return (-1);
    68
    11
            }
    69
    70
    291
            memcpy(xy, cbor_bytestring_handle(item), xy_len);
    71
    72
    291
            return (0);
    73
    302
    }
    74
    75
    static int
    76
    decode_pubkey_point(const cbor_item_t *key, const cbor_item_t *val, void *arg)
    77
    1.33k
    {
    78
    1.33k
            eddsa_pk_t *k = arg;
    79
    80
    1.33k
            if (cbor_isa_negint(key) == false ||
    81
    1.33k
                cbor_int_get_width(key) != CBOR_INT_8)
    82
    688
                    return (0); /* ignore */
    83
    84
    648
            switch (cbor_get_uint8(key)) {
    85
    302
            case 1: /* x coordinate */
    86
    302
                    return (decode_coord(val, &k->x, sizeof(k->x)));
    87
    648
            }
    88
    89
    346
            return (0); /* ignore */
    90
    648
    }
    91
    92
    int
    93
    eddsa_pk_decode(const cbor_item_t *item, eddsa_pk_t *k)
    94
    344
    {
    95
    344
            if (cbor_isa_map(item) == false ||
    96
    344
                cbor_map_is_definite(item) == false ||
    97
    344
                cbor_map_iter(item, k, decode_pubkey_point) < 0) {
    98
    19
                    fido_log_debug("%s: cbor type", __func__);
    99
    19
                    return (-1);
    100
    19
            }
    101
    102
    325
            return (0);
    103
    344
    }
    104
    105
    eddsa_pk_t *
    106
    eddsa_pk_new(void)
    107
    1.45k
    {
    108
    1.45k
            return (calloc(1, sizeof(eddsa_pk_t)));
    109
    1.45k
    }
    110
    111
    void
    112
    eddsa_pk_free(eddsa_pk_t **pkp)
    113
    2.86k
    {
    114
    2.86k
            eddsa_pk_t *pk;
    115
    116
    2.86k
            if (pkp == NULL || (pk = *pkp) == NULL)
    117
    1.41k
                    return;
    118
    119
    1.44k
            freezero(pk, sizeof(*pk));
    120
    1.44k
            *pkp = NULL;
    121
    1.44k
    }
    122
    123
    int
    124
    eddsa_pk_from_ptr(eddsa_pk_t *pk, const void *ptr, size_t len)
    125
    729
    {
    126
    729
            EVP_PKEY *pkey;
    127
    128
    729
            if (len < sizeof(*pk))
    129
    676
                    return (FIDO_ERR_INVALID_ARGUMENT);
    130
    131
    53
            memcpy(pk, ptr, sizeof(*pk));
    132
    133
    53
            if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) {
    134
    1
                    fido_log_debug("%s: eddsa_pk_to_EVP_PKEY", __func__);
    135
    1
                    return (FIDO_ERR_INVALID_ARGUMENT);
    136
    1
            }
    137
    138
    52
            EVP_PKEY_free(pkey);
    139
    140
    52
            return (FIDO_OK);
    141
    53
    }
    142
    143
    EVP_PKEY *
    144
    eddsa_pk_to_EVP_PKEY(const eddsa_pk_t *k)
    145
    890
    {
    146
    890
            EVP_PKEY *pkey = NULL;
    147
    148
    890
            if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, k->x,
    149
    890
                sizeof(k->x))) == NULL)
    150
    11
                    fido_log_debug("%s: EVP_PKEY_new_raw_public_key", __func__);
    151
    152
    890
            return (pkey);
    153
    890
    }
    154
    155
    int
    156
    eddsa_pk_from_EVP_PKEY(eddsa_pk_t *pk, const EVP_PKEY *pkey)
    157
    719
    {
    158
    719
            size_t len = 0;
    159
    160
    719
            if (EVP_PKEY_base_id(pkey) != EVP_PKEY_ED25519)
    161
    0
                    return (FIDO_ERR_INVALID_ARGUMENT);
    162
    719
            if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1 ||
    163
    719
                len != sizeof(pk->x))
    164
    3
                    return (FIDO_ERR_INTERNAL);
    165
    716
            if (EVP_PKEY_get_raw_public_key(pkey, pk->x, &len) != 1 ||
    166
    716
                len != sizeof(pk->x))
    167
    5
                    return (FIDO_ERR_INTERNAL);
    168
    169
    711
            return (FIDO_OK);
    170
    716
    }
    171
    172
    int
    173
    eddsa_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
    174
        const fido_blob_t *sig)
    175
    110
    {
    176
    110
            EVP_MD_CTX      *mdctx = NULL;
    177
    110
            int              ok = -1;
    178
    179
    110
            if (EVP_PKEY_base_id(pkey) != EVP_PKEY_ED25519) {
    180
    5
                    fido_log_debug("%s: EVP_PKEY_base_id", __func__);
    181
    5
                    goto fail;
    182
    5
            }
    183
    184
            /* EVP_DigestVerify needs ints */
    185
    105
            if (dgst->len > INT_MAX || sig->len > INT_MAX) {
    186
    0
                    fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__,
    187
    0
                        dgst->len, sig->len);
    188
    0
                    return (-1);
    189
    0
            }
    190
    191
    105
            if ((mdctx = EVP_MD_CTX_new()) == NULL) {
    192
    5
                    fido_log_debug("%s: EVP_MD_CTX_new", __func__);
    193
    5
                    goto fail;
    194
    5
            }
    195
    196
    100
            if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1) {
    197
    2
                    fido_log_debug("%s: EVP_DigestVerifyInit", __func__);
    198
    2
                    goto fail;
    199
    2
            }
    200
    201
    98
            if (EVP_DigestVerify(mdctx, sig->ptr, sig->len, dgst->ptr,
    202
    98
                dgst->len) != 1) {
    203
    98
                    fido_log_debug("%s: EVP_DigestVerify", __func__);
    204
    98
                    goto fail;
    205
    98
            }
    206
    207
    0
            ok = 0;
    208
    110
    fail:
    209
    110
            EVP_MD_CTX_free(mdctx);
    210
    211
    110
            return (ok);
    212
    0
    }
    213
    214
    int
    215
    eddsa_pk_verify_sig(const fido_blob_t *dgst, const eddsa_pk_t *pk,
    216
        const fido_blob_t *sig)
    217
    108
    {
    218
    108
            EVP_PKEY        *pkey;
    219
    108
            int              ok = -1;
    220
    221
    108
            if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL ||
    222
    108
                eddsa_verify_sig(dgst, pkey, sig) < 0) {
    223
    108
                    fido_log_debug("%s: eddsa_verify_sig", __func__);
    224
    108
                    goto fail;
    225
    108
            }
    226
    227
    0
            ok = 0;
    228
    108
    fail:
    229
    108
            EVP_PKEY_free(pkey);
    230
    231
    108
            return (ok);
    232
    0
    }