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