1 /*
2 * SPDX-FileCopyrightText: 2015-2023 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_rng_wrapper(void * ctx,unsigned char * buf,size_t len)19 static int crypto_rng_wrapper(void *ctx, unsigned char *buf, size_t len)
20 {
21 return random_get_bytes(buf, len);
22 }
23
crypto_bignum_init(void)24 struct crypto_bignum *crypto_bignum_init(void)
25 {
26 mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
27 if (bn == NULL) {
28 return NULL;
29 }
30
31 mbedtls_mpi_init(bn);
32
33 return (struct crypto_bignum *)bn;
34 }
35
36
crypto_bignum_init_set(const u8 * buf,size_t len)37 struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
38 {
39 int ret = 0;
40 mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
41 if (bn == NULL) {
42 return NULL;
43 }
44
45 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(bn, buf, len));
46 return (struct crypto_bignum *) bn;
47
48 cleanup:
49 os_free(bn);
50 return NULL;
51 }
52
53
crypto_bignum_init_uint(unsigned int val)54 struct crypto_bignum * crypto_bignum_init_uint(unsigned int val)
55 {
56
57 mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi));
58 if (bn == NULL) {
59 return NULL;
60 }
61
62 mbedtls_mpi_init(bn);
63 mbedtls_mpi_lset(bn, val);
64
65 return (struct crypto_bignum *)bn;
66 }
67
68
crypto_bignum_deinit(struct crypto_bignum * n,int clear)69 void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
70 {
71 mbedtls_mpi_free((mbedtls_mpi *)n);
72 os_free((mbedtls_mpi *)n);
73 }
74
75
crypto_bignum_to_bin(const struct crypto_bignum * a,u8 * buf,size_t buflen,size_t padlen)76 int crypto_bignum_to_bin(const struct crypto_bignum *a,
77 u8 *buf, size_t buflen, size_t padlen)
78 {
79 int num_bytes, offset;
80 int ret;
81
82 if (padlen > buflen) {
83 return -1;
84 }
85
86 num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a);
87
88 if ((size_t) num_bytes > buflen) {
89 return -1;
90 }
91 if (padlen > (size_t) num_bytes) {
92 offset = padlen - num_bytes;
93 } else {
94 offset = 0;
95 }
96
97 os_memset(buf, 0, offset);
98 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((mbedtls_mpi *) a, buf + offset, mbedtls_mpi_size((mbedtls_mpi *)a)));
99
100 return num_bytes + offset;
101 cleanup:
102 return ret;
103 }
104
105
crypto_bignum_add(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)106 int crypto_bignum_add(const struct crypto_bignum *a,
107 const struct crypto_bignum *b,
108 struct crypto_bignum *c)
109 {
110 return mbedtls_mpi_add_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
111 -1 : 0;
112 }
113
114
crypto_bignum_mod(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)115 int crypto_bignum_mod(const struct crypto_bignum *a,
116 const struct crypto_bignum *b,
117 struct crypto_bignum *c)
118 {
119 return mbedtls_mpi_mod_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ? -1 : 0;
120 }
121
122
crypto_bignum_exptmod(const struct crypto_bignum * a,const struct crypto_bignum * b,const struct crypto_bignum * c,struct crypto_bignum * d)123 int crypto_bignum_exptmod(const struct crypto_bignum *a,
124 const struct crypto_bignum *b,
125 const struct crypto_bignum *c,
126 struct crypto_bignum *d)
127 {
128 return mbedtls_mpi_exp_mod((mbedtls_mpi *) d, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b, (const mbedtls_mpi *) c, NULL) ? -1 : 0;
129
130 }
131
132
crypto_bignum_inverse(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)133 int crypto_bignum_inverse(const struct crypto_bignum *a,
134 const struct crypto_bignum *b,
135 struct crypto_bignum *c)
136 {
137 return mbedtls_mpi_inv_mod((mbedtls_mpi *) c, (const mbedtls_mpi *) a,
138 (const mbedtls_mpi *) b) ? -1 : 0;
139 }
140
141
crypto_bignum_sub(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)142 int crypto_bignum_sub(const struct crypto_bignum *a,
143 const struct crypto_bignum *b,
144 struct crypto_bignum *c)
145 {
146 return mbedtls_mpi_sub_mpi((mbedtls_mpi *) c, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
147 -1 : 0;
148 }
149
150
crypto_bignum_div(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)151 int crypto_bignum_div(const struct crypto_bignum *a,
152 const struct crypto_bignum *b,
153 struct crypto_bignum *c)
154 {
155 return mbedtls_mpi_div_mpi((mbedtls_mpi *) c, NULL, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) ?
156 -1 : 0;
157 }
158
159
crypto_bignum_mulmod(const struct crypto_bignum * a,const struct crypto_bignum * b,const struct crypto_bignum * c,struct crypto_bignum * d)160 int crypto_bignum_mulmod(const struct crypto_bignum *a,
161 const struct crypto_bignum *b,
162 const struct crypto_bignum *c,
163 struct crypto_bignum *d)
164 {
165 return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d, (const mbedtls_mpi *)a, (const mbedtls_mpi *)b) ||
166 mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, (mbedtls_mpi *)d, (const mbedtls_mpi *)c) ? -1 : 0;
167 }
168
crypto_bignum_sqrmod(const struct crypto_bignum * a,const struct crypto_bignum * b,struct crypto_bignum * c)169 int crypto_bignum_sqrmod(const struct crypto_bignum *a,
170 const struct crypto_bignum *b,
171 struct crypto_bignum *c)
172 {
173 int res;
174 struct crypto_bignum *tmp = crypto_bignum_init();
175 if (!tmp) {
176 return -1;
177 }
178
179 res = mbedtls_mpi_copy((mbedtls_mpi *) tmp,(const mbedtls_mpi *) a);
180 res = crypto_bignum_mulmod(a,tmp,b,c);
181
182 crypto_bignum_deinit(tmp, 0);
183 return res ? -1 : 0;
184 }
185
186
crypto_bignum_rshift(const struct crypto_bignum * a,int n,struct crypto_bignum * r)187 int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
188 struct crypto_bignum *r)
189 {
190 int res;
191 res = mbedtls_mpi_copy((mbedtls_mpi *) r,(const mbedtls_mpi *) a);
192 if (res) {
193 return -1;
194 }
195
196 res = mbedtls_mpi_shift_r((mbedtls_mpi *)r, n);
197 return res ? -1 : 0;
198
199 }
200
201
crypto_bignum_cmp(const struct crypto_bignum * a,const struct crypto_bignum * b)202 int crypto_bignum_cmp(const struct crypto_bignum *a,
203 const struct crypto_bignum *b)
204 {
205 return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) a, (const mbedtls_mpi *) b);
206 }
207
208
crypto_bignum_bits(const struct crypto_bignum * a)209 int crypto_bignum_bits(const struct crypto_bignum *a)
210 {
211 return mbedtls_mpi_bitlen((const mbedtls_mpi *) a);
212 }
213
214
crypto_bignum_is_zero(const struct crypto_bignum * a)215 int crypto_bignum_is_zero(const struct crypto_bignum *a)
216 {
217 return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 0) == 0);
218 }
219
220
crypto_bignum_is_one(const struct crypto_bignum * a)221 int crypto_bignum_is_one(const struct crypto_bignum *a)
222 {
223 return (mbedtls_mpi_cmp_int((const mbedtls_mpi *) a, 1) == 0);
224 }
225
crypto_bignum_is_odd(const struct crypto_bignum * a)226 int crypto_bignum_is_odd(const struct crypto_bignum *a)
227 {
228 return (mbedtls_mpi_get_bit((const mbedtls_mpi *) a, 0) == 1);
229 }
230
crypto_bignum_rand(struct crypto_bignum * r,const struct crypto_bignum * m)231 int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
232 {
233 return ((mbedtls_mpi_random((mbedtls_mpi *) r, 0, (const mbedtls_mpi *) m,
234 crypto_rng_wrapper, NULL) != 0) ? -1 : 0);
235 }
236
crypto_bignum_legendre(const struct crypto_bignum * a,const struct crypto_bignum * p)237 int crypto_bignum_legendre(const struct crypto_bignum *a,
238 const struct crypto_bignum *p)
239 {
240 mbedtls_mpi exp, tmp;
241 int res = -2, ret;
242
243 mbedtls_mpi_init(&exp);
244 mbedtls_mpi_init(&tmp);
245
246 /* exp = (p-1) / 2 */
247 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *) p, 1));
248 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 1));
249 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *) a, &exp, (const mbedtls_mpi *) p, NULL));
250
251 if (mbedtls_mpi_cmp_int(&tmp, 1) == 0) {
252 res = 1;
253 } else if (mbedtls_mpi_cmp_int(&tmp, 0) == 0
254 /* The below check is workaround for the case where HW
255 * does not behave properly for X ^ A mod M when X is
256 * power of M. Instead of returning value 0, value M is
257 * returned.*/
258 || mbedtls_mpi_cmp_mpi(&tmp, (const mbedtls_mpi *)p) == 0) {
259 res = 0;
260 } else {
261 res = -1;
262 }
263
264 cleanup:
265 mbedtls_mpi_free(&tmp);
266 mbedtls_mpi_free(&exp);
267 return res;
268 }
269
crypto_bignum_to_string(const struct crypto_bignum * a,u8 * buf,size_t buflen,size_t padlen)270 int crypto_bignum_to_string(const struct crypto_bignum *a,
271 u8 *buf, size_t buflen, size_t padlen)
272 {
273 int num_bytes, offset;
274 size_t outlen;
275
276 if (padlen > buflen) {
277 return -1;
278 }
279
280 num_bytes = mbedtls_mpi_size((mbedtls_mpi *) a);
281
282 if (padlen > (size_t) num_bytes) {
283 offset = padlen - num_bytes;
284 } else {
285 offset = 0;
286 }
287
288 os_memset(buf, 0, offset);
289 mbedtls_mpi_write_string((mbedtls_mpi *) a, 16, (char *)(buf + offset),
290 mbedtls_mpi_size((mbedtls_mpi *)a), &outlen);
291
292 return outlen;
293 }
294
crypto_bignum_addmod(const struct crypto_bignum * a,const struct crypto_bignum * b,const struct crypto_bignum * c,struct crypto_bignum * d)295 int crypto_bignum_addmod(const struct crypto_bignum *a,
296 const struct crypto_bignum *b,
297 const struct crypto_bignum *c,
298 struct crypto_bignum *d)
299 {
300 struct crypto_bignum *tmp = crypto_bignum_init();
301 int ret = -1;
302
303 if (mbedtls_mpi_add_mpi((mbedtls_mpi *) tmp, (const mbedtls_mpi *) a, (const mbedtls_mpi *) b) < 0)
304 goto fail;
305
306 if (mbedtls_mpi_mod_mpi( (mbedtls_mpi *) d, (const mbedtls_mpi *) tmp, (const mbedtls_mpi *) c) < 0)
307 goto fail;
308
309 ret = 0;
310 fail:
311 crypto_bignum_deinit(tmp, 0);
312 return ret;
313 }
314
crypto_free_buffer(unsigned char * buf)315 void crypto_free_buffer(unsigned char *buf)
316 {
317 os_free(buf);
318 }
319