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