1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2019-04-25 tyx the first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <hw_bignum.h>
14
15 static struct rt_hwcrypto_ctx *bignum_default;
16
hwcrypto_bignum_dev_is_init(void)17 rt_inline rt_err_t hwcrypto_bignum_dev_is_init(void)
18 {
19 struct rt_hwcrypto_device *dev;
20
21 if (bignum_default)
22 {
23 return RT_EOK;
24 }
25 dev = rt_hwcrypto_dev_default();
26 if (dev == RT_NULL)
27 {
28 return -RT_ERROR;
29 }
30 return rt_hwcrypto_bignum_default(dev);
31 }
32
33 /**
34 * @brief Setting bignum default devices
35 *
36 * @return RT_EOK on success.
37 */
rt_hwcrypto_bignum_default(struct rt_hwcrypto_device * device)38 rt_err_t rt_hwcrypto_bignum_default(struct rt_hwcrypto_device *device)
39 {
40 if (bignum_default)
41 {
42 rt_hwcrypto_ctx_destroy(bignum_default);
43 bignum_default = RT_NULL;
44 }
45 if (device == RT_NULL)
46 {
47 return RT_EOK;
48 }
49 bignum_default = rt_hwcrypto_ctx_create(device, HWCRYPTO_TYPE_BIGNUM, sizeof(struct hwcrypto_bignum));
50 if (bignum_default == RT_NULL)
51 {
52 return -RT_ERROR;
53 }
54 return RT_EOK;
55 }
56
57 /**
58 * @brief Init bignum obj
59 *
60 * @param n bignum obj
61 */
rt_hwcrypto_bignum_init(struct hw_bignum_mpi * n)62 void rt_hwcrypto_bignum_init(struct hw_bignum_mpi *n)
63 {
64 if(n == RT_NULL)
65 return;
66
67 n->sign = 1;
68 n->total = 0;
69 n->p = RT_NULL;
70 }
71
72 /**
73 * @brief free a bignum obj
74 *
75 * @param Pointer to bignum obj
76 */
rt_hwcrypto_bignum_free(struct hw_bignum_mpi * n)77 void rt_hwcrypto_bignum_free(struct hw_bignum_mpi *n)
78 {
79 if (n)
80 {
81 rt_memset(n->p, 0xFF, n->total);
82 rt_free(n->p);
83 n->sign = 0;
84 n->total = 0;
85 n->p = RT_NULL;
86 }
87 }
88
89 /**
90 * @brief Get length of bignum as an unsigned binary buffer
91 *
92 * @param n bignum obj
93 *
94 * @return binary buffer length
95 */
rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi * n)96 int rt_hwcrypto_bignum_get_len(const struct hw_bignum_mpi *n)
97 {
98 int tmp_len, total;
99
100 if (n == RT_NULL || n->p == RT_NULL)
101 {
102 return 0;
103 }
104 tmp_len = 0;
105 total = n->total;
106 while ((total > 0) && (n->p[total - 1] == 0))
107 {
108 tmp_len++;
109 total--;
110 }
111 return n->total - tmp_len;
112 }
113
114 /**
115 * @brief Export n into unsigned binary data, big endian
116 *
117 * @param n bignum obj
118 * @param buf Buffer for the binary number
119 * @param len Length of the buffer
120 *
121 * @return export bin length
122 */
rt_hwcrypto_bignum_export_bin(struct hw_bignum_mpi * n,rt_uint8_t * buf,int len)123 int rt_hwcrypto_bignum_export_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len)
124 {
125 int cp_len, i, j;
126
127 if (n == RT_NULL || buf == RT_NULL)
128 {
129 return 0;
130 }
131 rt_memset(buf, 0, len);
132 cp_len = (int)n->total > len ? len : (int)n->total;
133 for(i = cp_len, j = 0; i > 0; i--, j++)
134 {
135 buf[i - 1] = n->p[j];
136 }
137
138 return cp_len;
139 }
140
141 /**
142 * @brief Import n from unsigned binary data, big endian
143 *
144 * @param n bignum obj
145 * @param buf Buffer for the binary number
146 * @param len Length of the buffer
147 *
148 * @return import length.
149 */
rt_hwcrypto_bignum_import_bin(struct hw_bignum_mpi * n,rt_uint8_t * buf,int len)150 int rt_hwcrypto_bignum_import_bin(struct hw_bignum_mpi *n, rt_uint8_t *buf, int len)
151 {
152 int cp_len, i, j;
153 void *temp_p;
154
155 if (n == RT_NULL || buf == RT_NULL)
156 {
157 return 0;
158 }
159 if ((int)n->total < len)
160 {
161 temp_p = rt_malloc(len);
162 if (temp_p == RT_NULL)
163 {
164 return 0;
165 }
166 rt_free(n->p);
167 n->p = temp_p;
168 n->total = len;
169 }
170
171 n->sign = 1;
172 rt_memset(n->p, 0, n->total);
173 cp_len = (int)n->total > len ? len : n->total;
174
175 for(i = cp_len, j = 0; i > 0; i--, j++)
176 {
177 n->p[j] = buf[i - 1];
178 }
179
180 return cp_len;
181 }
182
183 /**
184 * @brief x = a + b
185 *
186 * @param a bignum obj
187 * @param b bignum obj
188 * @param c bignum obj
189 *
190 * @return RT_EOK on success.
191 */
rt_hwcrypto_bignum_add(struct hw_bignum_mpi * x,const struct hw_bignum_mpi * a,const struct hw_bignum_mpi * b)192 rt_err_t rt_hwcrypto_bignum_add(struct hw_bignum_mpi *x,
193 const struct hw_bignum_mpi *a,
194 const struct hw_bignum_mpi *b)
195 {
196 struct hwcrypto_bignum *bignum_ctx;
197
198 if (hwcrypto_bignum_dev_is_init() != RT_EOK)
199 {
200 return -RT_ERROR;
201 }
202 bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
203 if (bignum_ctx->ops->add)
204 {
205 return bignum_ctx->ops->add(bignum_ctx, x, a, b);
206 }
207 return -RT_ERROR;
208 }
209
210 /**
211 * @brief x = a - b
212 *
213 * @param a bignum obj
214 * @param b bignum obj
215 * @param c bignum obj
216 *
217 * @return RT_EOK on success.
218 */
rt_hwcrypto_bignum_sub(struct hw_bignum_mpi * x,const struct hw_bignum_mpi * a,const struct hw_bignum_mpi * b)219 rt_err_t rt_hwcrypto_bignum_sub(struct hw_bignum_mpi *x,
220 const struct hw_bignum_mpi *a,
221 const struct hw_bignum_mpi *b)
222 {
223 struct hwcrypto_bignum *bignum_ctx;
224
225 if (hwcrypto_bignum_dev_is_init() != RT_EOK)
226 {
227 return -RT_ERROR;
228 }
229 bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
230 if (bignum_ctx->ops->sub)
231 {
232 return bignum_ctx->ops->sub(bignum_ctx, x, a, b);
233 }
234 return -RT_ERROR;
235 }
236
237 /**
238 * @brief x = a * b
239 *
240 * @param a bignum obj
241 * @param b bignum obj
242 * @param c bignum obj
243 *
244 * @return RT_EOK on success.
245 */
rt_hwcrypto_bignum_mul(struct hw_bignum_mpi * x,const struct hw_bignum_mpi * a,const struct hw_bignum_mpi * b)246 rt_err_t rt_hwcrypto_bignum_mul(struct hw_bignum_mpi *x,
247 const struct hw_bignum_mpi *a,
248 const struct hw_bignum_mpi *b)
249 {
250 struct hwcrypto_bignum *bignum_ctx;
251
252 if (hwcrypto_bignum_dev_is_init() != RT_EOK)
253 {
254 return -RT_ERROR;
255 }
256 bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
257 if (bignum_ctx->ops->mul)
258 {
259 return bignum_ctx->ops->mul(bignum_ctx, x, a, b);
260 }
261 return -RT_ERROR;
262 }
263
264 /**
265 * @brief x = a * b (mod c)
266 *
267 * @param a bignum obj
268 * @param b bignum obj
269 * @param c bignum obj
270 *
271 * @return RT_EOK on success.
272 */
rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi * x,const struct hw_bignum_mpi * a,const struct hw_bignum_mpi * b,const struct hw_bignum_mpi * c)273 rt_err_t rt_hwcrypto_bignum_mulmod(struct hw_bignum_mpi *x,
274 const struct hw_bignum_mpi *a,
275 const struct hw_bignum_mpi *b,
276 const struct hw_bignum_mpi *c)
277 {
278 struct hwcrypto_bignum *bignum_ctx;
279
280 if (hwcrypto_bignum_dev_is_init() != RT_EOK)
281 {
282 return -RT_ERROR;
283 }
284 bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
285 if (bignum_ctx->ops->mulmod)
286 {
287 return bignum_ctx->ops->mulmod(bignum_ctx, x, a, b, c);
288 }
289 return -RT_ERROR;
290 }
291
292 /**
293 * @brief x = a ^ b (mod c)
294 *
295 * @param a bignum obj
296 * @param b bignum obj
297 * @param c bignum obj
298 *
299 * @return RT_EOK on success.
300 */
rt_hwcrypto_bignum_exptmod(struct hw_bignum_mpi * x,const struct hw_bignum_mpi * a,const struct hw_bignum_mpi * b,const struct hw_bignum_mpi * c)301 rt_err_t rt_hwcrypto_bignum_exptmod(struct hw_bignum_mpi *x,
302 const struct hw_bignum_mpi *a,
303 const struct hw_bignum_mpi *b,
304 const struct hw_bignum_mpi *c)
305 {
306 struct hwcrypto_bignum *bignum_ctx;
307
308 if (hwcrypto_bignum_dev_is_init() != RT_EOK)
309 {
310 return -RT_ERROR;
311 }
312 bignum_ctx = (struct hwcrypto_bignum *)bignum_default;
313 if (bignum_ctx->ops->exptmod)
314 {
315 return bignum_ctx->ops->exptmod(bignum_ctx, x, a, b, c);
316 }
317 return -RT_ERROR;
318 }
319