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