Coverage Report

Created: 2021-03-26 11:35

/libfido2/src/rs256.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2018 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 < 0x10100000L
15
static int
16
RSA_bits(const RSA *r)
17
{
18
        return (BN_num_bits(r->n));
19
}
20
21
static int
22
RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
23
{
24
        r->n = n;
25
        r->e = e;
26
        r->d = d;
27
28
        return (1);
29
}
30
31
static void
32
RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
33
{
34
        *n = r->n;
35
        *e = r->e;
36
        *d = r->d;
37
}
38
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
39
40
static int
41
decode_bignum(const cbor_item_t *item, void *ptr, size_t len)
42
154
{
43
154
        if (cbor_isa_bytestring(item) == false ||
44
154
            cbor_bytestring_is_definite(item) == false ||
45
154
            cbor_bytestring_length(item) != len) {
46
10
                fido_log_debug("%s: cbor type", __func__);
47
10
                return (-1);
48
10
        }
49
144
50
144
        memcpy(ptr, cbor_bytestring_handle(item), len);
51
144
52
144
        return (0);
53
144
}
54
55
static int
56
decode_rsa_pubkey(const cbor_item_t *key, const cbor_item_t *val, void *arg)
57
342
{
58
342
        rs256_pk_t *k = arg;
59
342
60
342
        if (cbor_isa_negint(key) == false ||
61
342
            cbor_int_get_width(key) != CBOR_INT_8)
62
182
                return (0); /* ignore */
63
160
64
160
        switch (cbor_get_uint8(key)) {
65
85
        case 0: /* modulus */
66
85
                return (decode_bignum(val, &k->n, sizeof(k->n)));
67
69
        case 1: /* public exponent */
68
69
                return (decode_bignum(val, &k->e, sizeof(k->e)));
69
6
        }
70
6
71
6
        return (0); /* ignore */
72
6
}
73
74
int
75
rs256_pk_decode(const cbor_item_t *item, rs256_pk_t *k)
76
91
{
77
91
        if (cbor_isa_map(item) == false ||
78
91
            cbor_map_is_definite(item) == false ||
79
91
            cbor_map_iter(item, k, decode_rsa_pubkey) < 0) {
80
15
                fido_log_debug("%s: cbor type", __func__);
81
15
                return (-1);
82
15
        }
83
76
84
76
        return (0);
85
76
}
86
87
rs256_pk_t *
88
rs256_pk_new(void)
89
979
{
90
979
        return (calloc(1, sizeof(rs256_pk_t)));
91
979
}
92
93
void
94
rs256_pk_free(rs256_pk_t **pkp)
95
2.10k
{
96
2.10k
        rs256_pk_t *pk;
97
2.10k
98
2.10k
        if (pkp == NULL || (pk = *pkp) == NULL)
99
2.10k
                return;
100
975
101
975
        freezero(pk, sizeof(*pk));
102
975
        *pkp = NULL;
103
975
}
104
105
int
106
rs256_pk_from_ptr(rs256_pk_t *pk, const void *ptr, size_t len)
107
507
{
108
507
        if (len < sizeof(*pk))
109
458
                return (FIDO_ERR_INVALID_ARGUMENT);
110
49
111
49
        memcpy(pk, ptr, sizeof(*pk));
112
49
113
49
        return (FIDO_OK);
114
49
}
115
116
EVP_PKEY *
117
rs256_pk_to_EVP_PKEY(const rs256_pk_t *k)
118
622
{
119
622
        RSA             *rsa = NULL;
120
622
        EVP_PKEY        *pkey = NULL;
121
622
        BIGNUM          *n = NULL;
122
622
        BIGNUM          *e = NULL;
123
622
        int              ok = -1;
124
622
125
622
        if ((n = BN_new()) == NULL || (e = BN_new()) == NULL)
126
622
                goto fail;
127
593
128
593
        if (BN_bin2bn(k->n, sizeof(k->n), n) == NULL ||
129
593
            BN_bin2bn(k->e, sizeof(k->e), e) == NULL) {
130
16
                fido_log_debug("%s: BN_bin2bn", __func__);
131
16
                goto fail;
132
16
        }
133
577
134
577
        if ((rsa = RSA_new()) == NULL || RSA_set0_key(rsa, n, e, NULL) == 0) {
135
6
                fido_log_debug("%s: RSA_set0_key", __func__);
136
6
                goto fail;
137
6
        }
138
571
139
571
        /* at this point, n and e belong to rsa */
140
571
        n = NULL;
141
571
        e = NULL;
142
571
143
571
        if ((pkey = EVP_PKEY_new()) == NULL ||
144
571
            EVP_PKEY_assign_RSA(pkey, rsa) == 0) {
145
21
                fido_log_debug("%s: EVP_PKEY_assign_RSA", __func__);
146
21
                goto fail;
147
21
        }
148
550
149
550
        rsa = NULL; /* at this point, rsa belongs to evp */
150
550
151
550
        ok = 0;
152
622
fail:
153
622
        if (n != NULL)
154
622
                BN_free(n);
155
622
        if (e != NULL)
156
622
                BN_free(e);
157
622
        if (rsa != NULL)
158
622
                RSA_free(rsa);
159
622
        if (ok < 0 && pkey != NULL) {
160
9
                EVP_PKEY_free(pkey);
161
9
                pkey = NULL;
162
9
        }
163
622
164
622
        return (pkey);
165
550
}
166
167
int
168
rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa)
169
468
{
170
468
        const BIGNUM    *n = NULL;
171
468
        const BIGNUM    *e = NULL;
172
468
        const BIGNUM    *d = NULL;
173
468
        int              k;
174
468
175
468
        if (RSA_bits(rsa) != 2048) {
176
436
                fido_log_debug("%s: invalid key length", __func__);
177
436
                return (FIDO_ERR_INVALID_ARGUMENT);
178
436
        }
179
32
180
32
        RSA_get0_key(rsa, &n, &e, &d);
181
32
182
32
        if (n == NULL || e == NULL) {
183
0
                fido_log_debug("%s: RSA_get0_key", __func__);
184
0
                return (FIDO_ERR_INTERNAL);
185
0
        }
186
32
187
32
        if ((k = BN_num_bytes(n)) < 0 || (size_t)k > sizeof(pk->n) ||
188
32
            (k = BN_num_bytes(e)) < 0 || (size_t)k > sizeof(pk->e)) {
189
0
                fido_log_debug("%s: invalid key", __func__);
190
0
                return (FIDO_ERR_INTERNAL);
191
0
        }
192
32
193
32
        if ((k = BN_bn2bin(n, pk->n)) < 0 || (size_t)k > sizeof(pk->n) ||
194
32
            (k = BN_bn2bin(e, pk->e)) < 0 || (size_t)k > sizeof(pk->e)) {
195
3
                fido_log_debug("%s: BN_bn2bin", __func__);
196
3
                return (FIDO_ERR_INTERNAL);
197
3
        }
198
29
199
29
        return (FIDO_OK);
200
29
}