• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
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 #include <stdlib.h>
16 #include "hvb_crypto.h"
17 #include "hvb_util.h"
18 #include "hvb_rsa.h"
19 
20 enum {
21     RESULT_OK = 0,
22     ERROR_MEMORY_EMPTY,
23     ERROR_MEMORY_NO_ENOUGH,
24     ERROR_WORDLEN_ZERO,
25 };
26 
27 #ifndef __WORDSIZE
28 #if defined(__LP64__)
29 #define __WORDSIZE 64
30 #elif defined(__LP32__)
31 #define __WORDSIZE 32
32 #else
33 #error "not support word size "
34 #endif
35 #endif
36 
37 #define WORD_BYTE_SIZE sizeof(unsigned long)
38 #define WORD_BIT_SIZE (WORD_BYTE_SIZE * 8)
39 #define WORD_BIT_MASK (((1UL << WORD_BIT_SIZE) - 1))
40 #define byte2bit(byte) ((byte) << 3)
41 #define SWORD_BIT_SIZE (WORD_BIT_SIZE / 2)
42 #define SWORD_BIT_MASK ((1UL << SWORD_BIT_SIZE) - 1)
43 
lin_clear(struct long_int_num * p_a)44 static void lin_clear(struct long_int_num *p_a)
45 {
46     (void)hvb_memset_s(p_a->data_mem, p_a->mem_size, 0, p_a->mem_size);
47 }
48 
lin_copy(struct long_int_num * p_src,struct long_int_num * p_dst)49 static int lin_copy(struct long_int_num *p_src, struct long_int_num *p_dst)
50 {
51     if (p_src->valid_word_len * WORD_BYTE_SIZE > p_dst->mem_size) {
52         return ERROR_MEMORY_NO_ENOUGH;
53     }
54 
55     if (hvb_memcpy_s(p_dst->p_uint, p_dst->mem_size, p_src->p_uint, p_src->valid_word_len * WORD_BYTE_SIZE) != 0) {
56         return ERROR_MEMORY_NO_ENOUGH;
57     }
58 
59     p_dst->valid_word_len = p_src->valid_word_len;
60 
61     return RESULT_OK;
62 }
63 
lin_compare(struct long_int_num * p_a,struct long_int_num * p_b)64 static int lin_compare(struct long_int_num *p_a, struct long_int_num *p_b)
65 {
66     int i;
67 
68     if (p_a->valid_word_len != p_b->valid_word_len) {
69         return p_a->valid_word_len - p_b->valid_word_len;
70     }
71 
72     if (p_a->valid_word_len == 0) {
73         return 0;
74     }
75 
76     for (i = p_a->valid_word_len - 1; i >= 0; --i) {
77         if (p_a->p_uint[i] != p_b->p_uint[i]) {
78             if (p_a->p_uint[i] > p_b->p_uint[i])
79                 return 1;
80             return -1;
81         }
82     }
83     return 0;
84 }
85 
lin_calloc(struct long_int_num * p_long_int,uint32_t word_len)86 static int lin_calloc(struct long_int_num *p_long_int, uint32_t word_len)
87 {
88     unsigned long *p_data = NULL;
89 
90     if (word_len == 0) {
91         return ERROR_WORDLEN_ZERO;
92     }
93     p_data = hvb_malloc(word_len * WORD_BYTE_SIZE);
94     if (p_data == NULL) {
95         return ERROR_MEMORY_EMPTY;
96     }
97 
98     if (hvb_memset_s(p_data, word_len * WORD_BYTE_SIZE, 0, word_len * WORD_BYTE_SIZE) != 0) {
99         hvb_free(p_data);
100         return ERROR_MEMORY_NO_ENOUGH;
101     }
102 
103     p_long_int->data_mem = p_data;
104     p_long_int->mem_size = word_len * WORD_BYTE_SIZE;
105     p_long_int->p_uint = p_data;
106     p_long_int->valid_word_len = 0;
107 
108     return RESULT_OK;
109 }
110 
lin_create(uint32_t word_len)111 struct long_int_num *lin_create(uint32_t word_len)
112 {
113     struct long_int_num *p_res = NULL;
114 
115     p_res = hvb_malloc(sizeof(struct long_int_num));
116     if (p_res == NULL) {
117         return NULL;
118     }
119 
120     if (lin_calloc(p_res, word_len) > 0) {
121         hvb_free(p_res);
122         return NULL;
123     }
124     p_res->valid_word_len = 0;
125     return p_res;
126 }
127 
lin_free(struct long_int_num * p_long_int)128 void lin_free(struct long_int_num *p_long_int)
129 {
130     if (!p_long_int) {
131         return;
132     }
133     if (p_long_int->p_uint != NULL) {
134         hvb_free(p_long_int->data_mem);
135         p_long_int->p_uint = NULL;
136     }
137     hvb_free(p_long_int);
138 
139     return;
140 }
141 
bn_get_valid_len(const uint8_t * pd,uint32_t size)142 uint32_t bn_get_valid_len(const uint8_t *pd, uint32_t size)
143 {
144 	uint32_t i = 0;
145 	uint32_t valid_len = size;
146 
147     if (!pd) {
148         return 0;
149     }
150 
151     while (valid_len > 0 && pd[i++] == 0) {
152         valid_len--;
153     }
154 
155 	return valid_len;
156 }
157 
lin_update_valid_len(struct long_int_num * p_a)158 void lin_update_valid_len(struct long_int_num *p_a)
159 {
160     unsigned long *p_data = NULL;
161     uint32_t i;
162 
163     if (!p_a) {
164         return;
165     }
166 
167     p_data = p_a->p_uint + p_a->valid_word_len - 1;
168     for (i = 0; i < p_a->valid_word_len; ++i) {
169         if (*p_data != 0) {
170             break;
171         }
172         --p_data;
173     }
174     p_a->valid_word_len -= i;
175 }
176 
lin_mul_word(unsigned long a,unsigned long b,unsigned long * res_hi,unsigned long * res_low)177 static void lin_mul_word(unsigned long a, unsigned long b, unsigned long *res_hi, unsigned long *res_low)
178 {
179 #if defined(__aarch64__)
180     unsigned long hi = 0;
181     *res_low = a * b;
182     __asm__ volatile ("umulh %0, %1, %2" : "+r"(hi) : "r"(a), "r"(b) :);
183     *res_hi = hi;
184 #else
185 
186 #if defined(__uint128_t)
187     #if __WORDSIZE == 32
188     unsigned long long aa, bb;
189 #elif __WORDSIZE == 64
190     __uint128_t aa, bb;
191 #else
192     #error "not support word size "
193 #endif
194     aa = a;
195     bb = b;
196     aa = aa * bb;
197     *res_hi = aa >> WORD_BIT_SIZE;
198     *res_low = aa & WORD_BIT_MASK;
199 #else
200     unsigned long a_h, a_l;
201     unsigned long b_h, b_l;
202     unsigned long res_h, res_l;
203     unsigned long c, t;
204     a_h = a >> SWORD_BIT_SIZE;
205     a_l = a & SWORD_BIT_MASK;
206     b_h = b >> SWORD_BIT_SIZE;
207     b_l = b & SWORD_BIT_MASK;
208 
209     res_h = a_h * b_h;
210     res_l = a_l * b_l;
211 
212     c = a_h * b_l;
213     res_h += c >> SWORD_BIT_SIZE;
214     t = res_l;
215     res_l += c << SWORD_BIT_SIZE;
216     res_h += t > res_l;
217 
218     c = a_l * b_h;
219     res_h += c >> SWORD_BIT_SIZE;
220     t = res_l;
221     res_l += c << SWORD_BIT_SIZE;
222     res_h += t > res_l;
223     *res_hi  = res_h;
224     *res_low = res_l;
225 #endif
226 #endif
227 }
228 
lin_sub(struct long_int_num * p_a,struct long_int_num * p_b)229 static void lin_sub(struct long_int_num *p_a, struct long_int_num *p_b)
230 {
231     uint32_t i;
232     unsigned long c;
233     unsigned long t;
234 
235     c = 0;
236     for (i = 0; i < p_b->valid_word_len; ++i) {
237         t = p_a->p_uint[i] < c;
238         p_a->p_uint[i] = p_a->p_uint[i] - c;
239 
240         c = (p_a->p_uint[i] < p_b->p_uint[i]) + t;
241         p_a->p_uint[i] = p_a->p_uint[i] - p_b->p_uint[i];
242     }
243     for (; i < p_a->valid_word_len && c; ++i) {
244         t = p_a->p_uint[i] < c;
245         p_a->p_uint[i] = p_a->p_uint[i] - c;
246         c = t;
247     }
248     lin_update_valid_len(p_a);
249 }
250 
251 #define dword_add_word(a, b, r)               \
252     do {                       \
253         r##_l = a##_l + (b);           \
254         r##_h = a##_h + (r##_l < (b)); \
255     } while (0)
256 
montgomery_mul_add(struct long_int_num * p_a,unsigned long b,struct long_int_num * p_n,unsigned long n_n0_i,struct long_int_num * p_res)257 static void montgomery_mul_add(struct long_int_num *p_a, unsigned long b, struct long_int_num *p_n,
258                                unsigned long n_n0_i, struct long_int_num *p_res)
259 {
260     unsigned long x_h, x_l;
261     unsigned long d0;
262     unsigned long y_h, y_l;
263     unsigned long t_h, t_l;
264     unsigned long *p_ad = p_a->p_uint;
265     unsigned long *p_nd = p_n->p_uint;
266     unsigned long *p_rd = p_res->p_uint;
267     uint32_t i;
268 
269     while (p_a->valid_word_len > p_n->valid_word_len) {
270         lin_sub(p_a, p_n);
271     }
272 
273     lin_mul_word(p_a->p_uint[0], b, &x_h, &x_l);
274 
275     dword_add_word(x, p_rd[0], x);
276 
277     d0 = x_l * n_n0_i;
278 
279     lin_mul_word(d0, p_nd[0], &y_h, &y_l);
280     dword_add_word(y, x_l, y);
281 
282     for (i = 1; i < p_a->valid_word_len; ++i) {
283         lin_mul_word(p_ad[i], b, &t_h, &t_l);
284         dword_add_word(t, p_rd[i], t);
285         dword_add_word(t, x_h, x);
286 
287         lin_mul_word(d0, p_nd[i], &t_h, &t_l);
288         dword_add_word(t, x_l, t);
289         dword_add_word(t, y_h, y);
290 
291         p_rd[i - 1] = y_l;
292     }
293 
294     p_rd[i - 1] = x_h + y_h;
295 
296     p_res->valid_word_len = p_n->valid_word_len;
297     if (p_rd[i - 1] < x_h) {
298         lin_sub(p_res, p_n);
299     }
300 }
301 
montgomery_mod_mul(struct long_int_num * p_a,struct long_int_num * p_b,struct long_int_num * p_n,unsigned long n_n0_i,struct long_int_num * p_res)302 static void montgomery_mod_mul(struct long_int_num *p_a, struct long_int_num *p_b, struct long_int_num *p_n,
303                                unsigned long n_n0_i, struct long_int_num *p_res)
304 {
305     uint32_t i;
306 
307     lin_clear(p_res);
308 
309     for (i = 0; i < p_b->valid_word_len; ++i) {
310         montgomery_mul_add(p_a, p_b->p_uint[i], p_n, n_n0_i, p_res);
311     }
312 }
313 
montgomery_mod_exp(struct long_int_num * p_m,struct long_int_num * p_n,unsigned long n_n0_i,struct long_int_num * p_rr,uint32_t exp)314 struct long_int_num *montgomery_mod_exp(struct long_int_num *p_m, struct long_int_num *p_n, unsigned long n_n0_i,
315                                         struct long_int_num *p_rr, uint32_t exp)
316 {
317     struct long_int_num *p_res = NULL;
318     struct long_int_num *p_mr = NULL;
319     struct long_int_num *p_square = NULL;
320     int i;
321     if ((exp & 1UL) == 0) {
322         goto fail_final;
323     }
324 
325     p_mr = lin_create(p_n->valid_word_len);
326     if (p_mr == NULL) {
327         goto fail_final;
328     }
329 
330     p_square = lin_create(p_n->valid_word_len);
331     if (p_square == NULL) {
332         goto fail_final;
333     }
334 
335     p_res = lin_create(p_n->valid_word_len);
336     if (p_res == NULL) {
337         goto fail_final;
338     }
339 
340     montgomery_mod_mul(p_m, p_rr, p_n, n_n0_i, p_mr);
341     i = byte2bit(sizeof(exp)) - 1;
342     for (; i >= 0; --i) {
343         if (exp & (1UL << i)) {
344             break;
345         }
346     }
347 
348     lin_copy(p_mr, p_res);
349 
350     for (--i; i > 0; --i) {
351         montgomery_mod_mul(p_res, p_res, p_n, n_n0_i, p_square);
352         if (exp & (1UL << i)) {
353             montgomery_mod_mul(p_mr, p_square, p_n, n_n0_i, p_res);
354         } else {
355             lin_copy(p_square, p_res);
356         }
357     }
358     montgomery_mod_mul(p_res, p_res, p_n, n_n0_i, p_square);
359     montgomery_mod_mul(p_m, p_square, p_n, n_n0_i, p_res);
360 
361     if (lin_compare(p_res, p_n) >= 0) {
362         lin_sub(p_res, p_n);
363     }
364 
365 fail_final:
366     lin_free(p_mr);
367     lin_free(p_square);
368 
369     return p_res;
370 }
371 
lin_get_bitlen(struct long_int_num * p_a)372 uint32_t lin_get_bitlen(struct long_int_num *p_a)
373 {
374     int i;
375     int bit_len;
376     unsigned long *p_data = NULL;
377     unsigned long value;
378 
379     if (!p_a || p_a->valid_word_len == 0) {
380         return 0;
381     }
382     p_data = p_a->p_uint;
383     for (i = p_a->valid_word_len - 1; i >= 0; --i) {
384         if (p_data[i] != 0)
385             break;
386     }
387 
388     bit_len = (i + 1) * WORD_BIT_SIZE;
389 
390     if (bit_len == 0) {
391         return 0;
392     }
393 
394     for (value = p_data[i]; ((signed long)value) > 0; value = value << 1) {
395         --bit_len;
396     }
397 
398     return bit_len;
399 }
400