Coverage Report

Created: 2022-07-22 12:05

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