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