1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
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
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <assert.h>
20
21 #include "core_804.h"
22 #include "wm_irq.h"
23 #include "wm_regs.h"
24 #include "wm_debug.h"
25 #include "wm_internal_flash.h"
26 #include "wm_pmu.h"
27 #include "wm_crypto_hard.h"
28
29 #undef DIGIT_BIT
30 #define DIGIT_BIT 28 // 32
31
32 #define SOFT_RESET_RC4 25
33 #define SOFT_RESET_AES 26
34 #define SOFT_RESET_DES 27
35
36 #define RNG_SWITCH 28
37 #define RNG_LOAD_SEED 29
38 #define RNG_START 30
39
40 #define TRNG_EN 0
41 #define TRNG_SEL 1
42 #define TRNG_DIG_BYPASS 2
43 #define TRNG_CP 3
44 #define TRNG_INT_MASK 6
45 #define USE_TRNG 1
46
47 #define DES_KEY_LEN 8
48 #define DES3_KEY_LEN 24
49 #define DES3_IV_LEN 8
50
51 #define SHA1_HASH_SIZE 20
52 #define MD5_HASH_SIZE 16
53
54 #define STORE32H(x, y) do { \
55 (y)[0] = (unsigned char)(((x)>>24)&255); \
56 (y)[1] = (unsigned char)(((x)>>16)&255); \
57 (y)[2] = (unsigned char)(((x)>>8)&255); \
58 (y)[3] = (unsigned char)((x)&255); \
59 }while (0)
60 #define STORE32L(x, y) do { \
61 unsigned long __t = (x); \
62 memcpy_s(y, sizeof(y), &__t, 4); \
63 }while (0)
64
65 #define CRYPTO_LOG(...)
66 // extern volatile uint32_t sys_count;
67 #define sys_count tls_os_get_time()
68
69 struct wm_crypto_ctx g_crypto_ctx = {0, 0,
70 #ifndef CONFIG_KERNEL_NONE
71 NULL
72 #endif
73 };
74
75 #if 1
76 typedef s32 psPool_t;
77 #include "libtommath.h"
78 #define pstm_set(a, b) mp_set((mp_int *)(a), (b))
79 #define pstm_init(pool, a) wpa_mp_init((mp_int *)(a))
80 #define pstm_count_bits(a) mp_count_bits((mp_int *)(a))
81 #define pstm_init_for_read_unsigned_bin(pool, a, len) mp_init_for_read_unsigned_bin((mp_int *)(a), (len))
82 #define pstm_read_unsigned_bin(a, b, c) mp_read_unsigned_bin((mp_int *)(a), (b), (c))
83 #define pstm_copy(a, b) mp_copy((mp_int *)(a), (mp_int *)(b))
84 #define pstm_clear(a) mp_clear((mp_int *)(a))
85 #define pstm_clamp(a) mp_clamp((mp_int *)(a))
86 #define pstm_mulmod(pool, a, b, c, d) mp_mulmod((mp_int *)(a), (mp_int *)(b), (mp_int *)(c), (mp_int *)(d))
87 #define pstm_exptmod(pool, G, X, P, Y) mp_exptmod((mp_int *)(G), (mp_int *)(X), (mp_int *)(P), (mp_int *)(Y))
88 #define pstm_reverse mp_reverse
89 #define pstm_cmp mp_cmp
90 #define pstm_to_unsigned_bin_nr(pool, a, b) mp_to_unsigned_bin_nr((mp_int *)(a), (unsigned char *)(b))
91
92 #define pstm_2expt(a, b) mp_2expt((mp_int *)(a), (b))
93 #define pstm_mod(pool, a, b, c) mp_mod((mp_int *)(a), (mp_int *)(b), (mp_int *)(c))
94
95 #endif
96
RSA_F_IRQHandler(void)97 void RSA_F_IRQHandler(void)
98 {
99 uint32_t cpu_sr;
100 cpu_sr = tls_os_set_critical();
101 RSACON = 0x00;
102 g_crypto_ctx.rsa_complete = 1;
103 tls_os_release_critical(cpu_sr);
104 }
CRYPTION_IRQHandler(void)105 void CRYPTION_IRQHandler(void)
106 {
107 uint32_t cpu_sr;
108 cpu_sr = tls_os_set_critical();
109 tls_reg_write32(HR_CRYPTO_SEC_STS, 0x10000);
110 g_crypto_ctx.gpsec_complete = 1;
111 tls_os_release_critical(cpu_sr);
112 }
113
114 #if 1
pstm_get_bit(hstm_int * a,int16 idx)115 static int16 pstm_get_bit (hstm_int *a, int16 idx)
116 {
117 int16 r;
118 int16 n = idx / DIGIT_BIT;
119 int16 m = idx % DIGIT_BIT;
120
121 if (a->used <= 0) {
122 return 0;
123 }
124
125 r = (a->dp[n] >> m) & 0x01;
126 return r;
127 }
128 #endif
Reflect(u32 ref,u8 ch)129 u32 Reflect(u32 ref, u8 ch)
130 {
131 int i;
132 u32 value = 0;
133 for (i = 1; i < (ch + 1); i++) {
134 if (ref & 1)
135 value |= 1 << (ch - i);
136 ref >>= 1;
137 }
138 return value;
139 }
140 #ifndef CONFIG_KERNEL_NONE
tls_crypto_sem_lock(void)141 void tls_crypto_sem_lock(void)
142 {
143 if (g_crypto_ctx.gpsec_lock == NULL) {
144 return;
145 }
146 tls_os_sem_acquire(g_crypto_ctx.gpsec_lock, 0);
147 }
tls_crypto_sem_unlock(void)148 void tls_crypto_sem_unlock(void)
149 {
150 if (g_crypto_ctx.gpsec_lock == NULL) {
151 return;
152 }
153 tls_os_sem_release(g_crypto_ctx.gpsec_lock);
154 }
155 #else
156 #define tls_crypto_sem_lock
157 #define tls_crypto_sem_unlock
158 #endif
tls_crypto_set_key(void * key,int keylen)159 void tls_crypto_set_key(void *key, int keylen)
160 {
161 uint32_t *key32 = (uint32_t *)key;
162 int i = 0;
163 for (i = 0; i < keylen / 4 && i < 6; i++) {
164 M32(HR_CRYPTO_KEY0 + (4 * i)) = key32[i];
165 }
166 if (keylen == 32) {
167 M32(HR_CRYPTO_KEY6) = key32[6];
168 M32(HR_CRYPTO_KEY7) = key32[7];
169 }
170 }
tls_crypto_set_iv(void * iv,int ivlen)171 void tls_crypto_set_iv(void *iv, int ivlen)
172 {
173 uint32_t *IV32 = (uint32_t *)iv;
174
175 if (ivlen >= 8) {
176 M32(HR_CRYPTO_IV0) = IV32[0];
177 M32(HR_CRYPTO_IV0 + 4) = IV32[1];
178 }
179 if (ivlen == 16) {
180 M32(HR_CRYPTO_IV1) = IV32[2];
181 M32(HR_CRYPTO_IV1 + 4) = IV32[3];
182 }
183 }
184
185 /**
186 * @brief This function is used to stop random produce.
187 *
188 * @param[in] None
189 *
190 * @retval 0 success
191 * @retval other failed
192 *
193 * @note None
194 */
tls_crypto_random_stop(void)195 int tls_crypto_random_stop(void)
196 {
197 unsigned int sec_cfg;
198 unsigned int cpu_sr;
199 #if USE_TRNG
200 #else
201 unsigned int val;
202 #endif
203 #if USE_TRNG
204 sec_cfg = 0x40;
205 tls_reg_write32(HR_CRYPTO_TRNG_CR, sec_cfg);
206 cpu_sr = tls_os_set_critical();
207 g_crypto_ctx.gpsec_complete = 0;
208 tls_os_release_critical(cpu_sr);
209 #else
210 val = tls_reg_read32(HR_CRYPTO_SEC_CFG);
211 sec_cfg = val & ~(1 << RNG_START);
212 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
213 #endif
214 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
215 tls_crypto_sem_unlock();
216 return ERR_CRY_OK;
217 }
218
219 /**
220 * @brief This function initializes random digit seed and BIT number.
221 *
222 * @param[in] seed The random digit seed.
223 * @param[in] rng_switch The random digit bit number. (0: 16bit 1:32bit)
224 *
225 * @retval 0 success
226 * @retval other failed
227 *
228 * @note None
229 */
tls_crypto_random_init(u32 seed,CRYPTO_RNG_SWITCH rng_switch)230 int tls_crypto_random_init(u32 seed, CRYPTO_RNG_SWITCH rng_switch)
231 {
232 unsigned int sec_cfg;
233 unsigned int cpu_sr;
234 tls_crypto_sem_lock();
235 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
236 #if USE_TRNG
237 sec_cfg = (1 << TRNG_INT_MASK) | (4 << TRNG_CP) | (1 << TRNG_SEL) | (1 << TRNG_EN);
238 sec_cfg &= ~(1 << TRNG_INT_MASK);
239 cpu_sr = tls_os_set_critical();
240 g_crypto_ctx.gpsec_complete = 0;
241 tls_os_release_critical(cpu_sr);
242 tls_reg_write32(HR_CRYPTO_TRNG_CR, sec_cfg);
243 #else
244 tls_reg_write32(HR_CRYPTO_KEY0, seed);
245 sec_cfg = (rng_switch << RNG_SWITCH) | (1 << RNG_LOAD_SEED) | (1 << RNG_START);
246 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
247 #endif
248 return ERR_CRY_OK;
249 }
250
251 /**
252 * @brief This function is used to get random digit content.
253 *
254 * @param[in] out Pointer to the output of random digit.
255 * @param[in] len The random digit bit number will output.
256 *
257 * @retval 0 success
258 * @retval other failed
259 *
260 * @note None
261 */
tls_crypto_random_bytes(unsigned char * out,u32 len)262 int tls_crypto_random_bytes(unsigned char *out, u32 len)
263 {
264 unsigned int val;
265 unsigned int cpu_sr;
266 uint32 inLen = len;
267 int randomBytes;
268 #if USE_TRNG
269 randomBytes = 4;
270 #else
271 val = tls_reg_read32(HR_CRYPTO_SEC_CFG);
272 randomBytes = val & (1 << RNG_SWITCH) ? 4 : 2;
273 #endif
274 while (inLen > 0) {
275 #if USE_TRNG
276 while (TRUE) {
277 cpu_sr = tls_os_set_critical();
278 if (g_crypto_ctx.gpsec_complete)
279 break;
280 tls_os_release_critical(cpu_sr);
281 }
282 g_crypto_ctx.gpsec_complete = 0;
283 tls_os_release_critical(cpu_sr);
284 #endif
285 val = tls_reg_read32(HR_CRYPTO_RNG_RESULT);
286 if (inLen >= randomBytes) {
287 memcpy_s(out, sizeof(out), (char *)&val, randomBytes);
288 out += randomBytes;
289 inLen -= randomBytes;
290 } else {
291 memcpy_s(out, sizeof(out), (char *)&val, inLen);
292 inLen = 0;
293 }
294 }
295 return ERR_CRY_OK;
296 }
297
298 /**
299 * @brief This function is used to generate true random number.
300 *
301 * @param[in] out Pointer to the output of random number.
302 * @param[in] len The random number length.
303 *
304 * @retval 0 success
305 * @retval other failed
306 *
307 * @note None
308 */
tls_crypto_trng(unsigned char * out,u32 len)309 int tls_crypto_trng(unsigned char *out, u32 len)
310 {
311 unsigned int sec_cfg, val;
312 unsigned int cpu_sr;
313 uint32 inLen = len;
314 int randomBytes = 4;
315
316 tls_crypto_sem_lock();
317 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
318 sec_cfg = (1 << TRNG_INT_MASK) | (4 << TRNG_CP) | (1 << TRNG_SEL) | (1 << TRNG_EN);
319 sec_cfg &= ~(1 << TRNG_INT_MASK);
320 cpu_sr = tls_os_set_critical();
321 g_crypto_ctx.gpsec_complete = 0;
322 tls_os_release_critical(cpu_sr);
323 tls_reg_write32(HR_CRYPTO_TRNG_CR, sec_cfg);
324 delay_cnt(1000);
325 while (inLen > 0) {
326 while (TRUE) {
327 cpu_sr = tls_os_set_critical();
328 if (g_crypto_ctx.gpsec_complete)
329 break;
330 tls_os_release_critical(cpu_sr);
331 }
332 g_crypto_ctx.gpsec_complete = 0;
333 tls_os_release_critical(cpu_sr);
334 val = tls_reg_read32(HR_CRYPTO_RNG_RESULT);
335 if (inLen >= randomBytes) {
336 memcpy_s(out, sizeof(out), (char *)&val, randomBytes);
337 out += randomBytes;
338 inLen -= randomBytes;
339 } else {
340 memcpy_s(out, sizeof(out), (char *)&val, inLen);
341 inLen = 0;
342 }
343 }
344
345 tls_reg_write32(HR_CRYPTO_TRNG_CR, 0x40);
346 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
347 tls_crypto_sem_unlock();
348 return ERR_CRY_OK;
349 }
350
tls_crypto_random_bytes_range(unsigned char * out,u32 len,u32 range)351 int tls_crypto_random_bytes_range(unsigned char *out, u32 len, u32 range)
352 {
353 unsigned int val, i;
354
355 val = tls_reg_read32(HR_CRYPTO_SEC_CFG);
356 for (i = 0; i< len; i++) {
357 val = tls_reg_read32(HR_CRYPTO_RNG_RESULT);
358 if (range == 0) {
359 }
360 out[i] = val % range;
361 }
362 return ERR_CRY_OK;
363 }
364
365 /**
366 * @brief This function initializes a RC4 encryption algorithm,
367 * i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data.
368 *
369 * @param[in] ctx Pointer to the Cipher Context.
370 * @param[in] key Pointer to the key.
371 * @param[in] keylen the length of key.
372 *
373 * @retval 0 success
374 * @retval other failed
375
376 *
377 * @note The first parameter ctx must be a structure which is allocated externally.
378 * And all of Context parameters in the initializing methods should be allocated externally too.
379 */
tls_crypto_rc4_init(psCipherContext_t * ctx,const unsigned char * key,u32 keylen)380 int tls_crypto_rc4_init(psCipherContext_t *ctx, const unsigned char *key, u32 keylen)
381 {
382 if (keylen != 16 && keylen != 32) {
383 return ERR_FAILURE;
384 }
385 memcpy_s(ctx->arc4.state, sizeof(ctx->arc4.state), key, keylen);
386 ctx->arc4.byteCount = keylen;
387 return ERR_CRY_OK;
388 }
389
390 /**
391 * @brief This function encrypts a variable length data stream according to RC4.
392 * The RC4 algorithm it generates a "keystream"
393 * which is simply XORed with the plaintext to produce the ciphertext stream.
394 * Decryption is exactly the same as encryption.
395 * This function also decrypts a variable length data stream according to RC4.
396 *
397 * @param[in] ctx Pointer to the Cipher Context.
398 * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length.
399 * @param[in] out Pointer to the resulting ciphertext data stream.
400 * @param[in] len Length of the plaintext data stream in octets.
401 *
402 * @retval 0 success
403 * @retval other failed
404 *
405 * @note None
406 */
tls_crypto_rc4(psCipherContext_t * ctx,unsigned char * in,unsigned char * out,u32 len)407 int tls_crypto_rc4(psCipherContext_t *ctx, unsigned char *in, unsigned char *out, u32 len)
408 {
409 unsigned int sec_cfg;
410 unsigned char *key = ctx->arc4.state;
411 u32 keylen = ctx->arc4.byteCount;
412 tls_crypto_sem_lock();
413 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
414 tls_crypto_set_key(key, keylen);
415 tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in);
416 tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out);
417 sec_cfg = (CRYPTO_METHOD_RC4 << 16) | (1 << SOFT_RESET_RC4) | (len & 0xFFFF);
418 if (keylen == 32) {
419 sec_cfg |= (1 << 31);
420 }
421 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
422 CRYPTO_LOG("[%d]:rc4[%d] start\n", sys_count, len);
423 g_crypto_ctx.gpsec_complete = 0;
424 tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1); // start crypto
425 while (!g_crypto_ctx.gpsec_complete) {
426 }
427 g_crypto_ctx.gpsec_complete = 0;
428 CRYPTO_LOG("[%d]:rc4 end status: %x\n", sys_count, tls_reg_read32(HR_CRYPTO_SEC_STS));
429 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
430 tls_crypto_sem_unlock();
431 return ERR_CRY_OK;
432 }
433
434 /**
435 * @brief This function initializes a AES encryption algorithm,
436 * i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data.
437 *
438 * @param[in] ctx Pointer to the Cipher Context.
439 * @param[in] IV Pointer to the Initialization Vector
440 * @param[in] key Pointer to the key.
441 * @param[in] keylen the length of key.
442 * @param[in] cbc the encryption mode, AES supports ECB/CBC/CTR modes.
443 *
444 * @retval 0 success
445 * @retval other failed
446 *
447 * @note None
448 */
tls_crypto_aes_init(psCipherContext_t * ctx,const unsigned char * IV,const unsigned char * key,u32 keylen,CRYPTO_MODE cbc)449 int tls_crypto_aes_init(psCipherContext_t *ctx, const unsigned char *IV,
450 const unsigned char *key, u32 keylen, CRYPTO_MODE cbc)
451 {
452 if (keylen != 16)
453 return ERR_FAILURE;
454
455 memcpy_s(ctx->aes.key.skey, sizeof(ctx->aes.key.skey), key, keylen);
456 ctx->aes.key.type = cbc;
457 ctx->aes.key.rounds = 16;
458 if (IV) {
459 for (int x = 0; x < ctx->aes.key.rounds; x++) {
460 ctx->aes.IV[x] = IV[x];
461 }
462 }
463 return ERR_CRY_OK;
464 }
465
466 /**
467 * @brief This function encrypts or decrypts a variable length data stream according to AES.
468 *
469 * @param[in] ctx Pointer to the Cipher Context.
470 * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length.
471 * @param[in] out Pointer to the resulting ciphertext data stream.
472 * @param[in] len Length of the plaintext data stream in octets.
473 * @param[in] dec The cryption way which indicates encryption or decryption.
474 *
475 * @retval 0 success
476 * @retval other failed
477 *
478 * @note None
479 */
tls_crypto_aes_encrypt_decrypt(psCipherContext_t * ctx,unsigned char * in,unsigned char * out,u32 len,CRYPTO_WAY dec)480 int tls_crypto_aes_encrypt_decrypt(psCipherContext_t *ctx, unsigned char *in,
481 unsigned char *out, u32 len, CRYPTO_WAY dec)
482 {
483 unsigned int sec_cfg;
484 unsigned int cpu_sr;
485 u32 keylen = 16;
486 unsigned char *key = (unsigned char *)ctx->aes.key.skey;
487 unsigned char *IV = ctx->aes.IV;
488 CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->aes.key.type & 0xFF);
489 tls_crypto_sem_lock();
490 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
491 tls_crypto_set_key(key, keylen);
492 tls_crypto_set_iv(IV, 16);
493
494 tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in);
495 tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out);
496 sec_cfg = (CRYPTO_METHOD_AES << 16) | (1 << SOFT_RESET_AES) | (dec << 20) | (cbc << 21) | (len & 0xFFFF);
497 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
498 CRYPTO_LOG("[%d]:aes[%d] %s %s start\n", sys_count, len, dec == CRYPTO_WAY_ENCRYPT ? "ENCRYPT" : "DECRYPT",
499 cbc == CRYPTO_MODE_ECB ? "ECB" : (cbc == CRYPTO_MODE_CBC ? "CBC" : (cbc == CRYPTO_MODE_CTR ? "CTR" : "MAC")));
500 cpu_sr = tls_os_set_critical();
501 g_crypto_ctx.gpsec_complete = 0;
502 tls_os_release_critical(cpu_sr);
503 tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1); // start crypto
504 while (TRUE) {
505 cpu_sr = tls_os_set_critical();
506 if (g_crypto_ctx.gpsec_complete)
507 break;
508 tls_os_release_critical(cpu_sr);
509 }
510 g_crypto_ctx.gpsec_complete = 0;
511 tls_os_release_critical(cpu_sr);
512 CRYPTO_LOG("[%d]:aes end %d\n", sys_count, tls_reg_read32(HR_CRYPTO_SEC_STS) & 0xFFFF);
513 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
514 tls_crypto_sem_unlock();
515 return ERR_CRY_OK;
516 }
517
518 /**
519 * @brief This function initializes a 3DES encryption algorithm,
520 * i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data.
521 *
522 * @param[in] ctx Pointer to the Cipher Context.
523 * @param[in] IV Pointer to the Initialization Vector
524 * @param[in] key Pointer to the key.
525 * @param[in] keylen the length of key.
526 * @param[in] cbc the encryption mode, 3DES supports ECB/CBC modes.
527 *
528 * @retval 0 success
529 * @retval other failed
530 *
531 * @note None
532 */
tls_crypto_3des_init(psCipherContext_t * ctx,const unsigned char * IV,const unsigned char * key,u32 keylen,CRYPTO_MODE cbc)533 int tls_crypto_3des_init(psCipherContext_t *ctx, const unsigned char *IV,
534 const unsigned char *key, u32 keylen, CRYPTO_MODE cbc)
535 {
536 if (keylen != DES3_KEY_LEN)
537 return ERR_FAILURE;
538
539 memcpy_s(ctx->des3.key.ek[0], sizeof(ctx->des3.key.ek), key, keylen);
540 ctx->des3.key.ek[1][0] = cbc;
541 ctx->des3.blocklen = DES3_IV_LEN;
542 if (IV) {
543 for (unsigned int x = 0; x < ctx->des3.blocklen; x++) {
544 ctx->des3.IV[x] = IV[x];
545 }
546 }
547
548 return ERR_CRY_OK;
549 }
550
551 /**
552 * @brief This function encrypts or decrypts a variable length data stream according to 3DES.
553 *
554 * @param[in] ctx Pointer to the Cipher Context.
555 * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length.
556 * @param[in] out Pointer to the resulting ciphertext data stream.
557 * @param[in] len Length of the plaintext data stream in octets.
558 * @param[in] dec The cryption way which indicates encryption or decryption.
559 *
560 * @retval 0 success
561 * @retval other failed
562 *
563 * @note None
564 */
tls_crypto_3des_encrypt_decrypt(psCipherContext_t * ctx,unsigned char * in,unsigned char * out,u32 len,CRYPTO_WAY dec)565 int tls_crypto_3des_encrypt_decrypt(psCipherContext_t *ctx, unsigned char *in,
566 unsigned char *out, u32 len, CRYPTO_WAY dec)
567 {
568 unsigned int sec_cfg;
569 u32 keylen = DES3_KEY_LEN;
570 unsigned char *key = (unsigned char *)(unsigned char *)ctx->des3.key.ek[0];
571 unsigned char *IV = ctx->des3.IV;
572 CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->des3.key.ek[1][0] & 0xFF);
573 tls_crypto_sem_lock();
574 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
575 tls_crypto_set_key(key, keylen);
576 tls_crypto_set_iv(IV, DES3_IV_LEN);
577 tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in);
578 tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out);
579 sec_cfg = (CRYPTO_METHOD_3DES << 16) | (1 << SOFT_RESET_DES) | (dec << 20) | (cbc << 21) | (len & 0xFFFF);
580 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
581 CRYPTO_LOG("[%d]:3des[%d] %s %s start\n", sys_count, len, dec == CRYPTO_WAY_ENCRYPT ? "ENCRYPT" : "DECRYPT",
582 cbc == CRYPTO_MODE_ECB ? "ECB" : "CBC");
583 g_crypto_ctx.gpsec_complete = 0;
584 tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1); // start crypto
585 while (!g_crypto_ctx.gpsec_complete) {
586 }
587 g_crypto_ctx.gpsec_complete = 0;
588 CRYPTO_LOG("[%d]:3des end %d\n", sys_count, tls_reg_read32(HR_CRYPTO_SEC_STS) & 0xFFFF);
589 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
590 tls_crypto_sem_unlock();
591 return ERR_CRY_OK;
592 }
593
594 /**
595 * @brief This function initializes a DES encryption algorithm,
596 * i.e. fills the psCipherContext_t structure pointed to by ctx with necessary data.
597 *
598 * @param[in] ctx Pointer to the Cipher Context.
599 * @param[in] IV Pointer to the Initialization Vector
600 * @param[in] key Pointer to the key.
601 * @param[in] keylen the length of key.
602 * @param[in] cbc the encryption mode, DES supports ECB/CBC modes.
603 *
604 * @retval 0 success
605 * @retval other failed
606 *
607 * @note None
608 */
tls_crypto_des_init(psCipherContext_t * ctx,const unsigned char * IV,const unsigned char * key,u32 keylen,CRYPTO_MODE cbc)609 int tls_crypto_des_init(psCipherContext_t *ctx, const unsigned char *IV,
610 const unsigned char *key, u32 keylen, CRYPTO_MODE cbc)
611 {
612 if (keylen != DES_KEY_LEN)
613 return ERR_FAILURE;
614 memcpy_s(ctx->des3.key.ek[0], sizeof(ctx->des3.key.ek), key, keylen);
615 ctx->des3.key.ek[1][0] = cbc;
616 ctx->des3.blocklen = DES3_IV_LEN;
617 if (IV) {
618 for (unsigned int x = 0; x < ctx->des3.blocklen; x++) {
619 ctx->des3.IV[x] = IV[x];
620 }
621 }
622 return ERR_CRY_OK;
623 }
624
625 /**
626 * @brief This function encrypts or decrypts a variable length data stream according to DES.
627 *
628 * @param[in] ctx Pointer to the Cipher Context.
629 * @param[in] in Pointer to the input plaintext data stream(or the encrypted text data stream) of variable length.
630 * @param[in] out Pointer to the resulting ciphertext data stream.
631 * @param[in] len Length of the plaintext data stream in octets.
632 * @param[in] dec The cryption way which indicates encryption or decryption.
633 *
634 * @retval 0 success
635 * @retval other failed
636 *
637 * @note None
638 */
tls_crypto_des_encrypt_decrypt(psCipherContext_t * ctx,unsigned char * in,unsigned char * out,u32 len,CRYPTO_WAY dec)639 int tls_crypto_des_encrypt_decrypt(psCipherContext_t *ctx, unsigned char *in,
640 unsigned char *out, u32 len, CRYPTO_WAY dec)
641 {
642 unsigned int sec_cfg;
643 u32 keylen = DES_KEY_LEN;
644 unsigned char *key = (unsigned char *)ctx->des3.key.ek[0];
645 unsigned char *IV = ctx->des3.IV;
646 CRYPTO_MODE cbc = (CRYPTO_MODE)(ctx->des3.key.ek[1][0] & 0xFF);
647 tls_crypto_sem_lock();
648 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
649 tls_crypto_set_key(key, keylen);
650 tls_crypto_set_iv(IV, DES3_IV_LEN);
651 tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in);
652 tls_reg_write32(HR_CRYPTO_DEST_ADDR, (unsigned int)out);
653 sec_cfg = (CRYPTO_METHOD_DES << 16) | (1 << SOFT_RESET_DES) | (dec << 20) | (cbc << 21) | (len & 0xFFFF);
654 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
655 CRYPTO_LOG("[%d]:des[%d] %s %s start\n", sys_count, len, dec == CRYPTO_WAY_ENCRYPT ? "ENCRYPT" : "DECRYPT",
656 cbc == CRYPTO_MODE_ECB ? "ECB" : "CBC");
657 g_crypto_ctx.gpsec_complete = 0;
658 tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1); // start crypto
659 while (!g_crypto_ctx.gpsec_complete) {
660 }
661 g_crypto_ctx.gpsec_complete = 0;
662 CRYPTO_LOG("[%d]:des end %d\n", sys_count, tls_reg_read32(HR_CRYPTO_SEC_STS) & 0xFFFF);
663 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
664 tls_crypto_sem_unlock();
665
666 return ERR_CRY_OK;
667 }
668
669 /**
670 * @brief This function initializes a CRC algorithm,
671 * i.e. fills the psCrcContext_t structure pointed to by ctx with necessary data.
672 *
673 * @param[in] ctx Pointer to the CRC Context.
674 * @param[in] key The initialization key.
675 * @param[in] crc_type The CRC type, supports CRC8/CRC16 MODBUS/CRC16 CCITT/CRC32
676 * @param[in] mode Set input or outpu reflect.
677 * @param[in] dec The cryption way which indicates encryption or decryption.
678 * see OUTPUT_REFLECT
679 * see INPUT_REFLECT
680 *
681 * @retval 0 success
682 * @retval other failed
683 *
684 * @note None
685 */
tls_crypto_crc_init(psCrcContext_t * ctx,u32 key,CRYPTO_CRC_TYPE crc_type,u8 mode)686 int tls_crypto_crc_init(psCrcContext_t *ctx, u32 key, CRYPTO_CRC_TYPE crc_type, u8 mode)
687 {
688 ctx->state = key;
689 ctx->type = crc_type;
690 ctx->mode = mode;
691 return ERR_CRY_OK;
692 }
693
694 /**
695 * @brief This function updates the CRC value with a variable length bytes.
696 * This function may be called as many times as necessary, so the message may be processed in blocks.
697 *
698 * @param[in] ctx Pointer to the CRC Context.
699 * @param[in] in Pointer to a variable length bytes
700 * @param[in] len The bytes 's length
701 *
702 * @retval 0 success
703 * @retval other failed
704 *
705 * @note None
706 */
tls_crypto_crc_update(psCrcContext_t * ctx,unsigned char * in,u32 len)707 int tls_crypto_crc_update(psCrcContext_t *ctx, unsigned char *in, u32 len)
708 {
709 unsigned int sec_cfg;
710 unsigned int cpu_sr;
711 tls_crypto_sem_lock();
712 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
713 sec_cfg = (CRYPTO_METHOD_CRC << 16) | (ctx->type << 21) | (ctx->mode << 23) | (len & 0xFFFF);
714 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
715 if (ctx->mode & OUTPUT_REFLECT) {
716 u8 ch_crc = 16;
717 u32 state = 0;
718 switch (ctx->type) {
719 case CRYPTO_CRC_TYPE_8:
720 ch_crc = 8;
721 break;
722 case CRYPTO_CRC_TYPE_16_MODBUS:
723 ch_crc = 16;
724 break;
725 case CRYPTO_CRC_TYPE_16_CCITT:
726 ch_crc = 16;
727 break;
728 case CRYPTO_CRC_TYPE_32:
729 ch_crc = 32;
730 break;
731 default:
732 break;
733 }
734 state = Reflect(ctx->state, ch_crc);
735 tls_reg_write32(HR_CRYPTO_CRC_KEY, state);
736 } else
737 tls_reg_write32(HR_CRYPTO_CRC_KEY, ctx->state);
738
739 tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)in);
740 CRYPTO_LOG("[%d]:crc update[%d] start\n", sys_count, len);
741 cpu_sr = tls_os_set_critical();
742 g_crypto_ctx.gpsec_complete = 0;
743 tls_os_release_critical(cpu_sr);
744 tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1); // start crypto
745 while (TRUE) {
746 cpu_sr = tls_os_set_critical();
747 if (g_crypto_ctx.gpsec_complete)
748 break;
749 tls_os_release_critical(cpu_sr);
750 }
751 g_crypto_ctx.gpsec_complete = 0;
752 tls_os_release_critical(cpu_sr);
753 CRYPTO_LOG("[%d]:crc update end %d\n", sys_count, tls_reg_read32(HR_CRYPTO_SEC_STS) & 0xFFFF);
754 ctx->state = tls_reg_read32(HR_CRYPTO_CRC_RESULT);
755 tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x4); // clear crc fifo
756 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
757 tls_crypto_sem_unlock();
758 return ERR_CRY_OK;
759 }
760
761 /**
762 * @brief This function ends a CRC operation and produces a CRC value.
763 *
764 * @param[in] ctx Pointer to the CRC Context.
765 * @param[in] crc_val Pointer to the CRC value.
766 *
767 * @retval 0 success
768 * @retval other failed
769 *
770 * @note None
771 */
tls_crypto_crc_final(psCrcContext_t * ctx,u32 * crc_val)772 int tls_crypto_crc_final(psCrcContext_t *ctx, u32 *crc_val)
773 {
774 *crc_val = ctx->state;
775 return ERR_CRY_OK;
776 }
777
hd_sha1_compress(psDigestContext_t * md)778 static void hd_sha1_compress(psDigestContext_t *md)
779 {
780 unsigned int sec_cfg;
781 unsigned int cpu_sr;
782 tls_crypto_sem_lock();
783 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
784 tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)md->u.sha1.buf);
785
786 sec_cfg = (CRYPTO_METHOD_SHA1 << 16) | (64 & 0xFFFF);
787 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
788 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST0, md->u.sha1.state[0]);
789 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST1, md->u.sha1.state[1]);
790 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST2, md->u.sha1.state[2]);
791 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST3, md->u.sha1.state[3]);
792 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST4, md->u.sha1.state[4]);
793 cpu_sr = tls_os_set_critical();
794 g_crypto_ctx.gpsec_complete = 0;
795 tls_os_release_critical(cpu_sr);
796 tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1); // start crypto
797 while (TRUE) {
798 cpu_sr = tls_os_set_critical();
799 if (g_crypto_ctx.gpsec_complete)
800 break;
801 tls_os_release_critical(cpu_sr);
802 }
803 g_crypto_ctx.gpsec_complete = 0;
804 tls_os_release_critical(cpu_sr);
805 for (int i = 0; i < 5; i++) {
806 md->u.sha1.state[i] = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4 * i));
807 }
808 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
809 tls_crypto_sem_unlock();
810 }
811
812 /**
813 * @brief This function initializes Message-Diggest context for usage in SHA1 algorithm,
814 * starts a new SHA1 operation and writes a new Digest Context.
815 *
816 * @param[in] md Pointer to the SHA1 Digest Context.
817 *
818 * @retval 0 success
819 * @retval other failed
820 *
821 * @note None
822 */
tls_crypto_sha1_init(psDigestContext_t * md)823 void tls_crypto_sha1_init(psDigestContext_t *md)
824 {
825 md->u.sha1.state[0] = 0x67452301UL;
826 md->u.sha1.state[1] = 0xefcdab89UL;
827 md->u.sha1.state[2] = 0x98badcfeUL;
828 md->u.sha1.state[3] = 0x10325476UL;
829 md->u.sha1.state[4] = 0xc3d2e1f0UL;
830 md->u.sha1.curlen = 0;
831 #ifdef HAVE_NATIVE_INT64
832 md->u.sha1.length = 0;
833 #else
834 md->u.sha1.lengthHi = 0;
835 md->u.sha1.lengthLo = 0;
836 #endif /* HAVE_NATIVE_INT64 */
837 }
838
839 /**
840 * @brief Process a message block using SHA1 algorithm.
841 * This function performs a SHA1 block update operation. It continues an SHA1 message-digest operation,
842 * by processing InputLen-byte length message block pointed to by buf,
843 * and by updating the SHA1 context pointed to by md.
844 * This function may be called as many times as necessary, so the message may be processed in blocks.
845 *
846 * @param[in] md Pointer to the SHA1 Digest Context.
847 * @param[in] buf InputLen-byte length message block
848 * @param[in] len The buf 's length
849 *
850 * @returnl None
851 *
852 * @note None
853 */
tls_crypto_sha1_update(psDigestContext_t * md,const unsigned char * buf,u32 len)854 void tls_crypto_sha1_update(psDigestContext_t *md, const unsigned char *buf, u32 len)
855 {
856 u32 n;
857 while (len > 0) {
858 n = min(len, (64 - md->u.sha1.curlen)); // 64
859 memcpy_s(md->u.sha1.buf + md->u.sha1.curlen, sizeof(md->u.sha1.buf +md->u.sha1.curlen), buf, (size_t)n);
860 md->u.sha1.curlen += n;
861 buf += n;
862 len -= n;
863
864 /* is 64 bytes full? */
865 if (md->u.sha1.curlen == 64) {
866 hd_sha1_compress(md);
867 #ifdef HAVE_NATIVE_INT64
868 md->u.sha1.length += 512; // 512
869 #else
870 n = (md->u.sha1.lengthLo + 512) & 0xFFFFFFFFL;
871 if (n < md->u.sha1.lengthLo) {
872 md->u.sha1.lengthHi++;
873 }
874 md->u.sha1.lengthLo = n;
875 #endif /* HAVE_NATIVE_INT64 */
876 md->u.sha1.curlen = 0;
877 }
878 }
879 }
880
881 /**
882 * @brief This function ends a SHA1 operation and produces a Message-Digest.
883 * This function finalizes SHA1 algorithm, i.e. ends an SHA1 Message-Digest operation,
884 * writing the Message-Digest in the 20-byte buffer pointed to by hash
885 * in according to the information stored in context.
886 *
887 * @param[in] md Pointer to the SHA1 Digest Context.
888 * @param[in] hash Pointer to the Message-Digest
889 *
890 * @retval 20 success, return the hash size.
891 * @retval <0 failed
892
893 *
894 * @note None
895 */
tls_crypto_sha1_final(psDigestContext_t * md,unsigned char * hash)896 int tls_crypto_sha1_final(psDigestContext_t *md, unsigned char *hash)
897 {
898 s32 i;
899 u32 val;
900 #ifndef HAVE_NATIVE_INT64
901 u32 n;
902 #endif
903 if (md->u.sha1.curlen >= sizeof(md->u.sha1.buf) || hash == NULL) {
904 return ERR_ARG_FAIL;
905 }
906
907 /*
908 increase the length of the message
909 */
910 #ifdef HAVE_NATIVE_INT64
911 md->u.sha1.length += md->u.sha1.curlen << 3;
912 #else
913 n = (md->u.sha1.lengthLo + (md->u.sha1.curlen << 3)) & 0xFFFFFFFFL;
914 if (n < md->u.sha1.lengthLo) {
915 md->u.sha1.lengthHi++;
916 }
917 md->u.sha1.lengthHi += (md->u.sha1.curlen >> 29);
918 md->u.sha1.lengthLo = n;
919 #endif /* HAVE_NATIVE_INT64 */
920
921 /*
922 append the '1' bit
923 */
924 md->u.sha1.buf[md->u.sha1.curlen++] = (unsigned char)0x80;
925
926 /*
927 if the length is currently above 56 bytes we append zeros then compress.
928 Then we can fall back to padding zeros and length encoding like normal.
929 */
930 if (md->u.sha1.curlen > 56) {
931 while (md->u.sha1.curlen < 64) {
932 md->u.sha1.buf[md->u.sha1.curlen++] = (unsigned char)0;
933 }
934 hd_sha1_compress(md);
935 md->u.sha1.curlen = 0;
936 }
937
938 /*
939 pad upto 56 bytes of zeroes
940 */
941 while (md->u.sha1.curlen < 56) {
942 md->u.sha1.buf[md->u.sha1.curlen++] = (unsigned char)0;
943 }
944
945 /*
946 store length
947 */
948 #ifdef HAVE_NATIVE_INT64
949 STORE64H(md->u.sha1.length, md->u.sha1.buf + 56);
950 #else
951 STORE32H(md->u.sha1.lengthHi, md->u.sha1.buf + 56);
952 STORE32H(md->u.sha1.lengthLo, md->u.sha1.buf + 60);
953 #endif /* HAVE_NATIVE_INT64 */
954 hd_sha1_compress(md);
955
956 /*
957 copy output
958 */
959 for (i = 0; i < 5; i++) {
960 val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4 * i));
961 STORE32H(val, hash + (4 * i));
962 }
963 memset_s(md, sizeof(md), 0x0, sizeof(psSha1_t));
964
965 return SHA1_HASH_SIZE;
966 }
967
hd_md5_compress(psDigestContext_t * md)968 static void hd_md5_compress(psDigestContext_t *md)
969 {
970 unsigned int sec_cfg;
971 tls_crypto_sem_lock();
972 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
973 tls_reg_write32(HR_CRYPTO_SRC_ADDR, (unsigned int)md->u.md5.buf);
974 sec_cfg = (CRYPTO_METHOD_MD5 << 16) | (64 & 0xFFFF);
975 tls_reg_write32(HR_CRYPTO_SEC_CFG, sec_cfg);
976 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST0, md->u.md5.state[0]);
977 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST1, md->u.md5.state[1]);
978 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST2, md->u.md5.state[2]);
979 tls_reg_write32(HR_CRYPTO_SHA1_DIGEST3, md->u.md5.state[3]);
980 g_crypto_ctx.gpsec_complete = 0;
981 tls_reg_write32(HR_CRYPTO_SEC_CTRL, 0x1); // start crypto
982 while (!g_crypto_ctx.gpsec_complete) {
983 }
984 g_crypto_ctx.gpsec_complete = 0;
985 for (unsigned int i = 0; i < 4; i++) {
986 unsigned int val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4 * i));
987 md->u.md5.state[i] = val;
988 }
989
990 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_GPSEC);
991 tls_crypto_sem_unlock();
992 }
993
994 /**
995 * @brief This function initializes Message-Diggest context for usage in MD5 algorithm,
996 * starts a new MD5 operation and writes a new Digest Context.
997 * This function begins a MD5 Message-Diggest Algorithm,
998 * i.e. fills the psDigestContext_t structure pointed to by md with necessary data.
999 * MD5 is the algorithm which takes as input a message of arbitrary length and produces as output
1000 * a 128-bit "fingerprint" or "message digest" of the input.
1001 * It is conjectured that it is computationally infeasible to produce two messages having
1002 * the same message digest,
1003 * or to produce any message having a given prespecified target message digest.
1004 *
1005 * @param[in] md MD5 Digest Context.
1006 *
1007 * @return None
1008 *
1009 * @note None
1010 */
tls_crypto_md5_init(psDigestContext_t * md)1011 void tls_crypto_md5_init(psDigestContext_t *md)
1012 {
1013 md->u.md5.state[0] = 0x67452301UL;
1014 md->u.md5.state[1] = 0xefcdab89UL;
1015 md->u.md5.state[2] = 0x98badcfeUL; // 2数组state的第三个
1016 md->u.md5.state[3] = 0x10325476UL;
1017 md->u.md5.curlen = 0;
1018 #ifdef HAVE_NATIVE_INT64
1019 md->u.md5.length = 0;
1020 #else
1021 md->u.md5.lengthHi = 0;
1022 md->u.md5.lengthLo = 0;
1023 #endif /* HAVE_NATIVE_INT64 */
1024 }
1025
1026 /**
1027 * @brief Process a message block using MD5 algorithm.
1028 * This function performs a MD5 block update operation. It continues an MD5 message-digest operation,
1029 * by processing InputLen-byte length message block pointed to by buf,
1030 * and by updating the MD5 context pointed to by md.
1031 * This function may be called as many times as necessary, so the message may be processed in blocks.
1032 *
1033 * @param[in] md MD5 Digest Context.
1034 * @param[in] buf InputLen-byte length message block
1035 * @param[in] len The buf 's length
1036 *
1037 * @return None
1038 *
1039 * @note None
1040 */
tls_crypto_md5_update(psDigestContext_t * md,const unsigned char * buf,u32 len)1041 void tls_crypto_md5_update(psDigestContext_t *md, const unsigned char *buf, u32 len)
1042 {
1043 u32 n;
1044
1045 while (len > 0) {
1046 n = min(len, (64 - md->u.md5.curlen));
1047 memcpy_s(md->u.md5.buf + md->u.md5.curlen, sizeof(md->u.md5.buf +md->u.md5.curlen), buf, (size_t)n);
1048 md->u.md5.curlen += n;
1049 buf += n;
1050 len -= n;
1051
1052 /*
1053 is 64 bytes full?
1054 */
1055 if (md->u.md5.curlen == 64) {
1056 hd_md5_compress(md);
1057 #ifdef HAVE_NATIVE_INT64
1058 md->u.md5.length += 512;
1059 #else
1060 n = (md->u.md5.lengthLo + 512) & 0xFFFFFFFFL;
1061 if (n < md->u.md5.lengthLo) {
1062 md->u.md5.lengthHi++;
1063 }
1064 md->u.md5.lengthLo = n;
1065 #endif /* HAVE_NATIVE_INT64 */
1066 md->u.md5.curlen = 0;
1067 }
1068 }
1069 }
1070
1071 /**
1072 * @brief This function ends a MD5 operation and produces a Message-Digest.
1073 * This function finalizes MD5 algorithm, i.e. ends an MD5 Message-Digest operation,
1074 * writing the Message-Digest in the 16-byte buffer pointed to by hash in according
1075 * to the information stored in context.
1076 *
1077 * @param[in] md MD5 Digest Context.
1078 * @param[in] hash the Message-Digest
1079 *
1080 * @retval 16 success, return the hash size.
1081 * @retval <0 failed
1082 *
1083 * @note None
1084 */
tls_crypto_md5_final(psDigestContext_t * md,unsigned char * hash)1085 s32 tls_crypto_md5_final(psDigestContext_t *md, unsigned char *hash)
1086 {
1087 s32 i;
1088 u32 val;
1089 #ifndef HAVE_NATIVE_INT64
1090 u32 n;
1091 #endif
1092
1093 if (hash == NULL) {
1094 CRYPTO_LOG("NULL hash storage passed to psMd5Final\n");
1095 return PS_ARG_FAIL;
1096 }
1097
1098 /*
1099 increase the length of the message
1100 */
1101 #ifdef HAVE_NATIVE_INT64
1102 md->u.md5.length += md->u.md5.curlen << 3;
1103 #else
1104 n = (md->u.md5.lengthLo + (md->u.md5.curlen << 3)) & 0xFFFFFFFFL;
1105 if (n < md->u.md5.lengthLo) {
1106 md->u.md5.lengthHi++;
1107 }
1108 md->u.md5.lengthHi += (md->u.md5.curlen >> 29);
1109 md->u.md5.lengthLo = n;
1110 #endif /* HAVE_NATIVE_INT64 */
1111
1112 /*
1113 append the '1' bit
1114 */
1115 md->u.md5.buf[md->u.md5.curlen++] = (unsigned char)0x80;
1116
1117 /*
1118 if the length is currently above 56 bytes we append zeros then compress.
1119 Then we can fall back to padding zeros and length encoding like normal.
1120 */
1121 if (md->u.md5.curlen > 56) {
1122 while (md->u.md5.curlen < 64) {
1123 md->u.md5.buf[md->u.md5.curlen++] = (unsigned char)0;
1124 }
1125 hd_md5_compress(md);
1126 md->u.md5.curlen = 0;
1127 }
1128
1129 /*
1130 pad upto 56 bytes of zeroes
1131 */
1132 while (md->u.md5.curlen < 56) {
1133 md->u.md5.buf[md->u.md5.curlen++] = (unsigned char)0;
1134 }
1135 /*
1136 store length
1137 */
1138 #ifdef HAVE_NATIVE_INT64
1139 STORE64L(md->u.md5.length, md->u.md5.buf + 56);
1140 #else
1141 STORE32L(md->u.md5.lengthLo, md->u.md5.buf + 56);
1142 STORE32L(md->u.md5.lengthHi, md->u.md5.buf + 60);
1143 #endif /* HAVE_NATIVE_INT64 */
1144 hd_md5_compress(md);
1145
1146 /*
1147 copy output
1148 */
1149 for (i = 0; i < 4; i++) {
1150 val = tls_reg_read32(HR_CRYPTO_SHA1_DIGEST0 + (4 * i));
1151 STORE32L(val, hash + (4 * i));
1152 }
1153 memset_s(md, sizeof(md), 0x0, sizeof(psMd5_t));
1154
1155 return MD5_HASH_SIZE;
1156 }
1157
rsaMonMulSetLen(const u32 len)1158 static void rsaMonMulSetLen(const u32 len)
1159 {
1160 RSAN = len;
1161 }
rsaMonMulWriteMc(const u32 mc)1162 static void rsaMonMulWriteMc(const u32 mc)
1163 {
1164 u32 val = 0;
1165 RSAMC = mc;
1166 val = RSAMC;
1167 if (val == mc) {
1168 return;
1169 }
1170 }
rsaMonMulWriteA(const u32 * const in)1171 static void rsaMonMulWriteA(const u32 *const in)
1172 {
1173 memcpy_s((u32 *)&RSAXBUF, sizeof(&RSAXBUF), in, RSAN * sizeof(u32));
1174 }
rsaMonMulWriteB(const u32 * const in)1175 static void rsaMonMulWriteB(const u32 *const in)
1176 {
1177 memcpy_s((u32 *)&RSAYBUF, sizeof(&RSAYBUF), in, RSAN * sizeof(u32));
1178 }
rsaMonMulWriteM(const u32 * const in)1179 static void rsaMonMulWriteM(const u32 *const in)
1180 {
1181 memcpy_s((u32 *)&RSAMBUF, sizeof(&RSAMBUF), in, RSAN * sizeof(u32));
1182 }
rsaMonMulReadA(u32 * const in)1183 static void rsaMonMulReadA(u32 *const in)
1184 {
1185 memcpy_s(in, sizeof(in), (u32 *)&RSAXBUF, RSAN * sizeof(u32));
1186 }
rsaMonMulReadB(u32 * const in)1187 static void rsaMonMulReadB(u32 *const in)
1188 {
1189 memcpy_s(in, sizeof(in), (u32 *)&RSAYBUF, RSAN * sizeof(u32));
1190 }
rsaMonMulReadD(u32 * const in)1191 static void rsaMonMulReadD(u32 *const in)
1192 {
1193 memcpy_s(in, sizeof(in), (u32 *)&RSADBUF, RSAN * sizeof(u32));
1194 }
rsaMulModRead(unsigned char w,hstm_int * a)1195 static int rsaMulModRead(unsigned char w, hstm_int *a)
1196 {
1197 u32 in[64];
1198 int err = 0;
1199 memset_s(in, sizeof(in), 0, 64 * sizeof(u32));
1200 switch (w) {
1201 case 'A':
1202 rsaMonMulReadA(in);
1203 break;
1204 case 'B':
1205 rsaMonMulReadB(in);
1206 break;
1207 case 'D':
1208 rsaMonMulReadD(in);
1209 break;
1210 default:
1211 break;
1212 }
1213 pstm_reverse((unsigned char *)in, RSAN * sizeof(u32));
1214 /* this a should be initialized outside. */
1215 if ((err = pstm_read_unsigned_bin(a, (unsigned char *)in, RSAN * sizeof(u32))) != ERR_CRY_OK) {
1216 pstm_clear(a);
1217 return err;
1218 }
1219 return 0;
1220 }
rsaMulModDump(unsigned char w)1221 static void rsaMulModDump(unsigned char w)
1222 {
1223 int addr = 0;
1224 switch (w) {
1225 case 'A':
1226 addr = 0;
1227 break;
1228 case 'B':
1229 addr = 0x100;
1230 break;
1231 case 'D':
1232 addr = 0x300;
1233 break;
1234 default:
1235 break;
1236 }
1237 printf("%c", w);
1238 dumpUint32(" Val:", ((volatile u32*) (RSA_BASE_ADDRESS + addr)), RSAN);
1239 }
1240
rsaMulModWrite(unsigned char w,hstm_int * a)1241 static void rsaMulModWrite(unsigned char w, hstm_int *a)
1242 {
1243 u32 in[64];
1244 memset_s(in, sizeof(in), 0, 64 * sizeof(u32));
1245 pstm_to_unsigned_bin_nr(NULL, a, (unsigned char *)in);
1246 switch (w) {
1247 case 'A':
1248 rsaMonMulWriteA(in);
1249 break;
1250 case 'B':
1251 rsaMonMulWriteB(in);
1252 break;
1253 case 'M':
1254 rsaMonMulWriteM(in);
1255 break;
1256 default:
1257 break;
1258 }
1259 }
rsaMonMulAA(void)1260 static void rsaMonMulAA(void)
1261 {
1262 u32 cpu_sr = tls_os_set_critical();
1263 g_crypto_ctx.rsa_complete = 0;
1264 tls_os_release_critical(cpu_sr);
1265 RSACON = 0x2c;
1266 while (TRUE) {
1267 cpu_sr = tls_os_set_critical();
1268 if (g_crypto_ctx.rsa_complete)
1269 break;
1270 tls_os_release_critical(cpu_sr);
1271 }
1272 g_crypto_ctx.rsa_complete = 0;
1273 tls_os_release_critical(cpu_sr);
1274 }
rsaMonMulDD(void)1275 static void rsaMonMulDD(void)
1276 {
1277 u32 cpu_sr = tls_os_set_critical();
1278 g_crypto_ctx.rsa_complete = 0;
1279 tls_os_release_critical(cpu_sr);
1280 RSACON = 0x20;
1281 while (TRUE) {
1282 cpu_sr = tls_os_set_critical();
1283 if (g_crypto_ctx.rsa_complete)
1284 break;
1285 tls_os_release_critical(cpu_sr);
1286 }
1287 g_crypto_ctx.rsa_complete = 0;
1288 tls_os_release_critical(cpu_sr);
1289 }
rsaMonMulAB(void)1290 static void rsaMonMulAB(void)
1291 {
1292 u32 cpu_sr = tls_os_set_critical();
1293 g_crypto_ctx.rsa_complete = 0;
1294 tls_os_release_critical(cpu_sr);
1295 RSACON = 0x24;
1296 while (TRUE) {
1297 cpu_sr = tls_os_set_critical();
1298 if (g_crypto_ctx.rsa_complete)
1299 break;
1300 tls_os_release_critical(cpu_sr);
1301 }
1302 g_crypto_ctx.rsa_complete = 0;
1303 tls_os_release_critical(cpu_sr);
1304 }
rsaMonMulBD(void)1305 static void rsaMonMulBD(void)
1306 {
1307 u32 cpu_sr = tls_os_set_critical();
1308 g_crypto_ctx.rsa_complete = 0;
1309 tls_os_release_critical(cpu_sr);
1310 RSACON = 0x28;
1311 while (TRUE) {
1312 cpu_sr = tls_os_set_critical();
1313 if (g_crypto_ctx.rsa_complete)
1314 break;
1315 tls_os_release_critical(cpu_sr);
1316 }
1317 g_crypto_ctx.rsa_complete = 0;
1318 tls_os_release_critical(cpu_sr);
1319 }
1320 /******************************************************************************
1321 compute mc, s.t. mc * in = 0xffffffff
1322 ******************************************************************************/
rsaCalMc(u32 * mc,const u32 in)1323 static void rsaCalMc(u32 *mc, const u32 in)
1324 {
1325 u32 y = 1;
1326 u32 i = 31;
1327 u32 left = 1;
1328 u32 right = 0;
1329 for (i = 31; i != 0; i--) {
1330 left <<= 1; /* 2^(i-1) */
1331 right = (in * y) & left; /* (n*y) mod 2^i */
1332 if (right) {
1333 y += left;
1334 }
1335 }
1336 *mc = ~y + 1;
1337 }
1338
1339 /**
1340 * @brief This function implements the large module power multiplication algorithm.
1341 * res = a**e (mod n)
1342 *
1343 * @param[in] a Pointer to a bignumber.
1344 * @param[in] e Pointer to a bignumber.
1345 * @param[in] n Pointer to a bignumber.
1346 * @param[out] res Pointer to the result bignumber.
1347 *
1348 * @retval 0 success
1349 * @retval other failed
1350 *
1351 * @note None
1352 */
tls_crypto_exptmod(hstm_int * a,hstm_int * e,hstm_int * n,hstm_int * res)1353 int tls_crypto_exptmod(hstm_int *a, hstm_int *e, hstm_int *n, hstm_int *res)
1354 {
1355 int i = 0;
1356 u32 k = 0, mc = 0, dp0;
1357 volatile u8 monmulFlag = 0;
1358 hstm_int R, X, Y;
1359
1360 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_RSA);
1361
1362 #ifndef CONFIG_KERNEL_NONE
1363 tls_fls_sem_lock();
1364 #endif
1365 pstm_init(NULL, &X);
1366 pstm_init(NULL, &Y);
1367 pstm_init(NULL, &R);
1368 k = pstm_count_bits(n); // n->used * DIGIT_BIT; // pstm_count_bits(n);
1369 k = ((k / 32) + (k % 32 > 0 ? 1 : 0)) * 32;
1370
1371 pstm_2expt(&X, (int16)k); // X = 2^k
1372 pstm_mod(NULL, &X, n, &R); // R = 2^k % n
1373
1374 pstm_mulmod(NULL, a, &R, n, &X); // X = A * R
1375 pstm_copy(&R, &Y);
1376 if (n->used > 1) {
1377 #if (DIGIT_BIT < 32)
1378 dp0 = 0xFFFFFFFF & ((n->dp[0]) | (u32)(n->dp[1] << DIGIT_BIT));
1379 #else
1380 dp0 = (n->dp[0]);
1381 #endif
1382 } else
1383 dp0 = n->dp[0];
1384 rsaCalMc(&mc, dp0);
1385 k = pstm_count_bits(n);
1386 rsaMonMulSetLen(k / 32 + (k % 32 == 0 ? 0 : 1));
1387 rsaMonMulWriteMc(mc);
1388 rsaMulModWrite('M', n);
1389 rsaMulModWrite('B', &X);
1390 rsaMulModWrite('A', &Y);
1391 k = pstm_count_bits(e);
1392 for (i = k - 1; i >= 0; i--) {
1393 if (monmulFlag == 0) {
1394 rsaMonMulAA();
1395 monmulFlag = 1;
1396 } else {
1397 rsaMonMulDD();
1398 monmulFlag = 0;
1399 }
1400
1401 if (pstm_get_bit(e, i)) {
1402 if (monmulFlag == 0) {
1403 rsaMonMulAB();
1404 monmulFlag = 1;
1405 } else {
1406 rsaMonMulBD();
1407 monmulFlag = 0;
1408 }
1409 }
1410 }
1411 pstm_set(&R, 1);
1412 rsaMulModWrite('B', &R);
1413 if (monmulFlag == 0) {
1414 rsaMonMulAB();
1415 rsaMulModRead('D', res);
1416 } else {
1417 rsaMonMulBD();
1418 rsaMulModRead('A', res);
1419 }
1420 pstm_clamp(res);
1421 pstm_clear(&X);
1422 pstm_clear(&Y);
1423 pstm_clear(&R);
1424 #ifndef CONFIG_KERNEL_NONE
1425 tls_fls_sem_unlock();
1426 #endif
1427 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_RSA);
1428
1429 return 0;
1430 }
1431
1432 /**
1433 * @brief This function initializes the encryption module.
1434 *
1435 * @param None
1436 *
1437 * @return None
1438 *
1439 * @note None
1440 */
tls_crypto_init(void)1441 int tls_crypto_init(void)
1442 {
1443 #ifndef CONFIG_KERNEL_NONE
1444 int err = 0;
1445 if (g_crypto_ctx.gpsec_lock != NULL) {
1446 return 0;
1447 }
1448 err = tls_os_sem_create(&g_crypto_ctx.gpsec_lock, 1);
1449 if (err != TLS_OS_SUCCESS) {
1450 TLS_DBGPRT_ERR("create semaphore @gpsec_lock fail!\n");
1451 return -1;
1452 }
1453 #endif
1454 tls_irq_enable(RSA_IRQn);
1455 tls_irq_enable(CRYPTION_IRQn);
1456 return 0;
1457 }
1458
1459