Coverage Report

Created: 2024-02-05 19:20

/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
106
#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
67
{
43
67
        return (EVP_MD_fetch(NULL, "SHA2-256", NULL));
44
67
}
45
46
static void
47
rs256_free_EVP_MD(EVP_MD *md)
48
69
{
49
69
        EVP_MD_free(md);
50
69
}
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
284
{
73
284
        if (cbor_isa_bytestring(item) == false ||
74
284
            cbor_bytestring_is_definite(item) == false ||
75
284
            cbor_bytestring_length(item) != len) {
76
31
                fido_log_debug("%s: cbor type", __func__);
77
31
                return (-1);
78
31
        }
79
80
253
        memcpy(ptr, cbor_bytestring_handle(item), len);
81
82
253
        return (0);
83
284
}
84
85
static int
86
decode_rsa_pubkey(const cbor_item_t *key, const cbor_item_t *val, void *arg)
87
2.04k
{
88
2.04k
        rs256_pk_t *k = arg;
89
90
2.04k
        if (cbor_isa_negint(key) == false ||
91
2.04k
            cbor_int_get_width(key) != CBOR_INT_8)
92
1.46k
                return (0); /* ignore */
93
94
571
        switch (cbor_get_uint8(key)) {
95
139
        case 0: /* modulus */
96
139
                return (decode_bignum(val, &k->n, sizeof(k->n)));
97
145
        case 1: /* public exponent */
98
145
                return (decode_bignum(val, &k->e, sizeof(k->e)));
99
571
        }
100
101
287
        return (0); /* ignore */
102
571
}
103
104
int
105
rs256_pk_decode(const cbor_item_t *item, rs256_pk_t *k)
106
536
{
107
536
        if (cbor_isa_map(item) == false ||
108
536
            cbor_map_is_definite(item) == false ||
109
536
            cbor_map_iter(item, k, decode_rsa_pubkey) < 0) {
110
40
                fido_log_debug("%s: cbor type", __func__);
111
40
                return (-1);
112
40
        }
113
114
496
        return (0);
115
536
}
116
117
rs256_pk_t *
118
rs256_pk_new(void)
119
1.04k
{
120
1.04k
        return (calloc(1, sizeof(rs256_pk_t)));
121
1.04k
}
122
123
void
124
rs256_pk_free(rs256_pk_t **pkp)
125
4.69k
{
126
4.69k
        rs256_pk_t *pk;
127
128
4.69k
        if (pkp == NULL || (pk = *pkp) == NULL)
129
3.64k
                return;
130
131
1.04k
        freezero(pk, sizeof(*pk));
132
1.04k
        *pkp = NULL;
133
1.04k
}
134
135
int
136
rs256_pk_from_ptr(rs256_pk_t *pk, const void *ptr, size_t len)
137
941
{
138
941
        EVP_PKEY *pkey;
139
140
941
        if (len < sizeof(*pk))
141
728
                return (FIDO_ERR_INVALID_ARGUMENT);
142
143
213
        memcpy(pk, ptr, sizeof(*pk));
144
145
213
        if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) {
146
96
                fido_log_debug("%s: rs256_pk_to_EVP_PKEY", __func__);
147
96
                return (FIDO_ERR_INVALID_ARGUMENT);
148
96
        }
149
150
117
        EVP_PKEY_free(pkey);
151
152
117
        return (FIDO_OK);
153
213
}
154
155
EVP_PKEY *
156
rs256_pk_to_EVP_PKEY(const rs256_pk_t *k)
157
1.28k
{
158
1.28k
        RSA             *rsa = NULL;
159
1.28k
        EVP_PKEY        *pkey = NULL;
160
1.28k
        BIGNUM          *n = NULL;
161
1.28k
        BIGNUM          *e = NULL;
162
1.28k
        int              ok = -1;
163
164
1.28k
        if ((n = BN_new()) == NULL || (e = BN_new()) == NULL)
165
19
                goto fail;
166
167
1.26k
        if (BN_bin2bn(k->n, sizeof(k->n), n) == NULL ||
168
1.26k
            BN_bin2bn(k->e, sizeof(k->e), e) == NULL) {
169
49
                fido_log_debug("%s: BN_bin2bn", __func__);
170
49
                goto fail;
171
49
        }
172
173
1.21k
        if ((rsa = RSA_new()) == NULL || RSA_set0_key(rsa, n, e, NULL) == 0) {
174
22
                fido_log_debug("%s: RSA_set0_key", __func__);
175
22
                goto fail;
176
22
        }
177
178
        /* at this point, n and e belong to rsa */
179
1.19k
        n = NULL;
180
1.19k
        e = NULL;
181
182
1.19k
        if (RSA_bits(rsa) != 2048) {
183
889
                fido_log_debug("%s: invalid key length", __func__);
184
889
                goto fail;
185
889
        }
186
187
301
        if ((pkey = EVP_PKEY_new()) == NULL ||
188
301
            EVP_PKEY_assign_RSA(pkey, rsa) == 0) {
189
10
                fido_log_debug("%s: EVP_PKEY_assign_RSA", __func__);
190
10
                goto fail;
191
10
        }
192
193
291
        rsa = NULL; /* at this point, rsa belongs to evp */
194
195
291
        ok = 0;
196
1.28k
fail:
197
1.28k
        if (n != NULL)
198
80
                BN_free(n);
199
1.28k
        if (e != NULL)
200
71
                BN_free(e);
201
1.28k
        if (rsa != NULL)
202
914
                RSA_free(rsa);
203
1.28k
        if (ok < 0 && pkey != NULL) {
204
6
                EVP_PKEY_free(pkey);
205
6
                pkey = NULL;
206
6
        }
207
208
1.28k
        return (pkey);
209
291
}
210
211
int
212
rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa)
213
104
{
214
104
        const BIGNUM    *n = NULL;
215
104
        const BIGNUM    *e = NULL;
216
104
        const BIGNUM    *d = NULL;
217
104
        int              k;
218
219
104
        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
104
        RSA_get0_key(rsa, &n, &e, &d);
225
226
104
        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
104
        if ((k = BN_num_bytes(n)) < 0 || (size_t)k > sizeof(pk->n) ||
232
104
            (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
104
        if ((k = BN_bn2bin(n, pk->n)) < 0 || (size_t)k > sizeof(pk->n) ||
238
104
            (k = BN_bn2bin(e, pk->e)) < 0 || (size_t)k > sizeof(pk->e)) {
239
4
                fido_log_debug("%s: BN_bn2bin", __func__);
240
4
                return (FIDO_ERR_INTERNAL);
241
4
        }
242
243
100
        return (FIDO_OK);
244
104
}
245
246
int
247
rs256_pk_from_EVP_PKEY(rs256_pk_t *pk, const EVP_PKEY *pkey)
248
106
{
249
106
        const RSA *rsa;
250
251
106
        if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA ||
252
106
            (rsa = get0_RSA(pkey)) == NULL)
253
2
                return (FIDO_ERR_INVALID_ARGUMENT);
254
255
104
        return (rs256_pk_from_RSA(pk, rsa));
256
106
}
257
258
int
259
rs256_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
260
    const fido_blob_t *sig)
261
69
{
262
69
        EVP_PKEY_CTX    *pctx = NULL;
263
69
        EVP_MD          *md = NULL;
264
69
        int              ok = -1;
265
266
69
        if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
267
2
                fido_log_debug("%s: EVP_PKEY_base_id", __func__);
268
2
                goto fail;
269
2
        }
270
271
67
        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
67
        if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL ||
277
67
            EVP_PKEY_verify_init(pctx) != 1 ||
278
67
            EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1 ||
279
67
            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
63
        if (EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr,
285
63
            dgst->len) != 1) {
286
63
                fido_log_debug("%s: EVP_PKEY_verify", __func__);
287
63
                goto fail;
288
63
        }
289
290
0
        ok = 0;
291
69
fail:
292
69
        EVP_PKEY_CTX_free(pctx);
293
69
        rs256_free_EVP_MD(md);
294
295
69
        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
126
{
302
126
        EVP_PKEY        *pkey;
303
126
        int              ok = -1;
304
305
126
        if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL ||
306
126
            rs256_verify_sig(dgst, pkey, sig) < 0) {
307
126
                fido_log_debug("%s: rs256_verify_sig", __func__);
308
126
                goto fail;
309
126
        }
310
311
0
        ok = 0;
312
126
fail:
313
126
        EVP_PKEY_free(pkey);
314
315
126
        return (ok);
316
0
}