• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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