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