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
}