1 /*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifdef ESP_PLATFORM
8 #include "esp_system.h"
9 #include "mbedtls/bignum.h"
10 #endif
11
12 #include "utils/includes.h"
13 #include "utils/common.h"
14 #include "crypto.h"
15 #include "random.h"
16 #include "sha256.h"
17 #include "mbedtls/pk.h"
18
crypto_bignum_init(void)19 struct crypto_bignum *crypto_bignum_init(void)
20 {
21 mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
22 if (bn == NULL) {
23 return NULL;
24 }
25
26 mbedtls_mpi_init(bn);
27
28 return (struct crypto_bignum *)bn;
29 }
30
31
crypto_bignum_init_set(const u8 * buf,size_t len)32 struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
33 {
34 int ret = 0;
35 mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
36 if (bn == NULL) {
37 return NULL;
38 }
39
40 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(bn, buf, len));
41 return (struct crypto_bignum *) bn;
42
43 cleanup:
44 os_free(bn);
45 return NULL;
46 }
47
48
crypto_bignum_deinit(struct crypto_bignum * n,int clear)49 void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
50 {
51 mbedtls_mpi_free((mbedtls_mpi *)n);
52 os_free((mbedtls_mpi *)n);
53 }
54
55
crypto_bignum_to_bin(const struct crypto_bignum * a,u8 * buf,size_t buflen,size_t padlen)56 int crypto_bignum_to_bin(const struct crypto_bignum *a,
57 u8 *buf, size_t buflen, size_t padlen)
58 {
59 int num_bytes, offset;
60 int ret;
61
62 if (padlen > buflen) {
63 return -1;
64 }
65
66 num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a);
67
68 if ((size_t) num_bytes > buflen) {
69 return -1;
70 }
71 if (padlen > (size_t) num_bytes) {
72 offset = padlen - num_bytes;
73 } else {
74 offset = 0;
75 }
76
77 os_memset(buf, 0, offset);
78 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((mbedtls_mpi *) a, buf + offset, mbedtls_mpi_size((mbedtls_mpi *)a)));
79
80 return num_bytes + offset;
81 cleanup:
82 return ret;
83 }
84
85
crypto_bignum_add(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)86 int crypto_bignum_add(const struct crypto_bignum *a,
87 const struct crypto_bignum *b,
88 struct crypto_bignum *c)
89 {
90 return mbedtls_mpi_add_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
91 -1 : 0;
92 }
93
94
crypto_bignum_mod(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)95 int crypto_bignum_mod(const struct crypto_bignum *a,
96 const struct crypto_bignum *b,
97 struct crypto_bignum *c)
98 {
99 return mbedtls_mpi_mod_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ? -1 : 0;
100 }
101
102
crypto_bignum_exptmod(const struct crypto_bignum * a,const struct crypto_bignum * b,const struct crypto_bignum * c,struct crypto_bignum * d)103 int crypto_bignum_exptmod(const struct crypto_bignum *a,
104 const struct crypto_bignum *b,
105 const struct crypto_bignum *c,
106 struct crypto_bignum *d)
107 {
108 return mbedtls_mpi_exp_mod((mbedtls_mpi *) d, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b, (const mbedtls_mpi *) c, NULL) ? -1 : 0;
109
110 }
111
112
crypto_bignum_inverse(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)113 int crypto_bignum_inverse(const struct crypto_bignum *a,
114 const struct crypto_bignum *b,
115 struct crypto_bignum *c)
116 {
117 return mbedtls_mpi_inv_mod((mbedtls_mpi *) c, (const mbedtls_mpi *) a,
118 (const mbedtls_mpi *) b) ? -1 : 0;
119 }
120
121
crypto_bignum_sub(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)122 int crypto_bignum_sub(const struct crypto_bignum *a,
123 const struct crypto_bignum *b,
124 struct crypto_bignum *c)
125 {
126 return mbedtls_mpi_sub_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
127 -1 : 0;
128 }
129
130
crypto_bignum_div(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)131 int crypto_bignum_div(const struct crypto_bignum *a,
132 const struct crypto_bignum *b,
133 struct crypto_bignum *c)
134 {
135 return mbedtls_mpi_div_mpi((mbedtls_mpi *) c, NULL, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
136 -1 : 0;
137 }
138
139
crypto_bignum_mulmod(const struct crypto_bignum * a,const struct crypto_bignum * b,const struct crypto_bignum * c,struct crypto_bignum * d)140 int crypto_bignum_mulmod(const struct crypto_bignum *a,
141 const struct crypto_bignum *b,
142 const struct crypto_bignum *c,
143 struct crypto_bignum *d)
144 {
145 int res;
146 #if ALLOW_EVEN_MOD || !CONFIG_MBEDTLS_HARDWARE_MPI // Must enable ALLOW_EVEN_MOD if c is even
147 mbedtls_mpi temp;
148 mbedtls_mpi_init(&temp);
149
150 res = mbedtls_mpi_mul_mpi(&temp, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
151 if (res) {
152 return -1;
153 }
154
155 res = mbedtls_mpi_mod_mpi((mbedtls_mpi *) d, &temp, (mbedtls_mpi *) c);
156
157 mbedtls_mpi_free(&temp);
158 #else
159 // Works with odd modulus only, but it is faster with HW acceleration
160 res = esp_mpi_mul_mpi_mod((mbedtls_mpi *) d, (mbedtls_mpi *) a, (mbedtls_mpi *) b, (mbedtls_mpi *) c);
161 #endif
162 return res ? -1 : 0;
163 }
164
165
crypto_bignum_cmp(const struct crypto_bignum * a,const struct crypto_bignum * b)166 int crypto_bignum_cmp(const struct crypto_bignum *a,
167 const struct crypto_bignum *b)
168 {
169 return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
170 }
171
172
crypto_bignum_bits(const struct crypto_bignum * a)173 int crypto_bignum_bits(const struct crypto_bignum *a)
174 {
175 return mbedtls_mpi_bitlen((const mbedtls_mpi *) a);
176 }
177
178
crypto_bignum_is_zero(const struct crypto_bignum * a)179 int crypto_bignum_is_zero(const struct crypto_bignum *a)
180 {
181 return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 0) == 0);
182 }
183
184
crypto_bignum_is_one(const struct crypto_bignum * a)185 int crypto_bignum_is_one(const struct crypto_bignum *a)
186 {
187 return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 1) == 0);
188 }
189
190
crypto_bignum_legendre(const struct crypto_bignum * a,const struct crypto_bignum * p)191 int crypto_bignum_legendre(const struct crypto_bignum *a,
192 const struct crypto_bignum *p)
193 {
194 mbedtls_mpi exp, tmp;
195 int res = -2, ret;
196
197 mbedtls_mpi_init(&exp);
198 mbedtls_mpi_init(&tmp);
199
200 /* exp = (p-1) / 2 */
201 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *) p, 1));
202 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 1));
203 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *) a, &exp, (const mbedtls_mpi *) p, NULL));
204
205 if (mbedtls_mpi_cmp_int(&tmp, 1) == 0) {
206 res = 1;
207 } else if (mbedtls_mpi_cmp_int(&tmp, 0) == 0
208 /* The below check is workaround for the case where HW
209 * does not behave properly for X ^ A mod M when X is
210 * power of M. Instead of returning value 0, value M is
211 * returned.*/
212 || mbedtls_mpi_cmp_mpi(&tmp, (const mbedtls_mpi *)p) == 0) {
213 res = 0;
214 } else {
215 res = -1;
216 }
217
218 cleanup:
219 mbedtls_mpi_free(&tmp);
220 mbedtls_mpi_free(&exp);
221 return res;
222 }
223
crypto_bignum_to_string(const struct crypto_bignum * a,u8 * buf,size_t buflen,size_t padlen)224 int crypto_bignum_to_string(const struct crypto_bignum *a,
225 u8 *buf, size_t buflen, size_t padlen)
226 {
227 int num_bytes, offset;
228 size_t outlen;
229
230 if (padlen > buflen) {
231 return -1;
232 }
233
234 num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a);
235
236 if (padlen > (size_t) num_bytes) {
237 offset = padlen - num_bytes;
238 } else {
239 offset = 0;
240 }
241
242 os_memset(buf, 0, offset);
243 mbedtls_mpi_write_string((mbedtls_mpi *) a, 16, (char *)(buf + offset),
244 mbedtls_mpi_size((mbedtls_mpi *)a), &outlen);
245
246 return outlen;
247 }
248
crypto_bignum_addmod(const struct crypto_bignum * a,const struct crypto_bignum * b,const struct crypto_bignum * c,struct crypto_bignum * d)249 int crypto_bignum_addmod(const struct crypto_bignum *a,
250 const struct crypto_bignum *b,
251 const struct crypto_bignum *c,
252 struct crypto_bignum *d)
253 {
254 struct crypto_bignum *tmp = crypto_bignum_init();
255 int ret = -1;
256
257 if (mbedtls_mpi_add_mpi((mbedtls_mpi *) tmp, (const mbedtls_mpi *) b, (const mbedtls_mpi *) c) < 0)
258 goto fail;
259
260 if (mbedtls_mpi_mod_mpi( (mbedtls_mpi *) a, (const mbedtls_mpi *) tmp, (const mbedtls_mpi *) d) < 0)
261 goto fail;
262
263 ret = 0;
264 fail:
265 crypto_bignum_deinit(tmp, 0);
266 return ret;
267 }
268
crypto_free_buffer(unsigned char * buf)269 void crypto_free_buffer(unsigned char *buf)
270 {
271 os_free(buf);
272 }
273