1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-06-27     thread-liu   first version
9  */
10 
11 #include <board.h>
12 
13 #include "drv_crypto.h"
14 #include <hwcrypto.h>
15 #include <string.h>
16 #include <stdlib.h>
17 
18 #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
dump_hex(const rt_uint8_t * ptr,rt_size_t buflen)19 static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
20 {
21     unsigned char *buf = (unsigned char *)ptr;
22     int i, j;
23 
24     for (i = 0; i < buflen; i += 16)
25     {
26         rt_kprintf("%08X: ", i);
27 
28         for (j = 0; j < 16; j++)
29         {
30             if (i + j < buflen)
31             {
32                 rt_kprintf("%02X ", buf[i + j]);
33             }
34             else
35             {
36                 rt_kprintf("   ");
37             }
38         }
39         rt_kprintf(" ");
40 
41         for (j = 0; j < 16; j++)
42         {
43             if (i + j < buflen)
44             {
45                 rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
46             }
47         }
48         rt_kprintf("\n");
49     }
50 }
51 
52 #if defined(BSP_USING_RNG)
hw_rng_sample(int random_num)53 static rt_err_t hw_rng_sample(int random_num)
54 {
55     rt_err_t result = RT_EOK;
56     int i = 0, num0 = 0, num1 = 0;
57 
58     if (random_num == 0)
59     {
60         return -RT_ERROR;
61     }
62 
63     for (i = 0; i< random_num; i++)
64     {
65         result = rt_hwcrypto_rng_update();
66         rt_kprintf("%d ", result);
67         result%2 ? num1++ : num0++;
68     }
69     rt_kprintf("\neven numbers : %d, odd numbers: %d\n",num1, num0);
70 
71     return RT_EOK;
72 }
73 #endif
74 
75 #if defined(BSP_USING_CRC)
hw_crc_sample(uint8_t * temp,int size)76 static void hw_crc_sample(uint8_t *temp, int size)
77 {
78     struct rt_hwcrypto_ctx *ctx;
79     rt_uint32_t result = 0;
80 
81     struct hwcrypto_crc_cfg cfg =
82     {
83         .last_val = 0xFFFFFFFF,
84         .poly     = 0x04C11DB7,
85         .width    = 32,
86         .xorout   = 0x00000000,
87         .flags    = 0,
88     };
89 
90     ctx = rt_hwcrypto_crc_create(rt_hwcrypto_dev_default(), HWCRYPTO_CRC_CRC32);
91     rt_hwcrypto_crc_cfg(ctx, &cfg);
92 
93     result = rt_hwcrypto_crc_update(ctx, temp, size);
94 
95     rt_kprintf("crc result: %x \n", result);
96 
97     rt_hwcrypto_crc_destroy(ctx);
98 }
99 #endif
100 
101 #if defined(BSP_USING_HASH)
hw_hash_sample()102 static void hw_hash_sample()
103 {
104     struct rt_hwcrypto_ctx *ctx = RT_NULL;
105     const uint8_t hash_input[] = "RT-Thread was born in 2006, it is an open source, neutral, and community-based real-time operating system (RTOS).";
106 
107     static uint8_t sha1_output[20];
108     static uint8_t sha1_except[20] = {0xff, 0x3c, 0x95, 0x54, 0x95, 0xf0, 0xad,
109                                     0x02, 0x1b, 0xa8, 0xbc, 0xa2, 0x2e, 0xa5,
110                                     0xb0, 0x62, 0x1b, 0xdf, 0x7f, 0xec};
111 
112     static uint8_t md5_output[16];
113     static uint8_t md5_except[16] = {0x40, 0x86, 0x03, 0x80, 0x0d, 0x8c, 0xb9,
114                                    0x4c, 0xd6, 0x7d, 0x28, 0xfc, 0xf6, 0xc3,
115                                    0xac, 0x8b};
116 
117     static uint8_t sha224_output[28];
118     static uint8_t sha224_except[28] = {0x6f, 0x62, 0x52, 0x7d, 0x80, 0xe6,
119                                         0x9f, 0x82, 0x78, 0x7a, 0x46, 0x91,
120                                         0xb0, 0xe9, 0x64, 0x89, 0xe6, 0xc3,
121                                         0x6b, 0x7e, 0xcf, 0xca, 0x11, 0x42,
122                                         0xc8, 0x77, 0x13, 0x79};
123     static uint8_t sha256_output[32];
124     static uint8_t sha256_except[32] = {0x74, 0x19, 0xb9, 0x0e, 0xd1, 0x46,
125                                         0x37, 0x0a, 0x55, 0x18, 0x26, 0x6c,
126                                         0x50, 0xd8, 0x71, 0x34, 0xfa, 0x1f,
127                                         0x5f, 0x5f, 0xe4, 0x9a, 0xe9, 0x40,
128                                         0x0a, 0x7d, 0xa0, 0x26, 0x1b, 0x86,
129                                         0x67, 0x45};
130     rt_kprintf("======================== Hash Test start ========================\n");
131     rt_kprintf("Hash Test string: \n");
132     dump_hex(hash_input, sizeof(hash_input));
133 
134     /* sh1 test*/
135     rt_kprintf("\n============ SHA1 Test Start ============\n");
136     ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_SHA1);
137     if (ctx == RT_NULL)
138     {
139         rt_kprintf("create hash[%08x] context err!\n", HWCRYPTO_TYPE_SHA1);
140         return ;
141     }
142     rt_kprintf("Create sha1 type success!\n");
143     rt_kprintf("Except sha1 result:\n");
144     dump_hex(sha1_except, sizeof(sha1_except));
145 
146     /* start sha1 */
147     rt_hwcrypto_hash_update(ctx, hash_input, rt_strlen((char const *)hash_input));
148     /* get sha1 result */
149     rt_hwcrypto_hash_finish(ctx, sha1_output, rt_strlen((char const *)sha1_output));
150 
151     rt_kprintf("Actual sha1 result:\n");
152     dump_hex(sha1_output, sizeof(sha1_output));
153 
154     if(rt_memcmp(sha1_output, sha1_except, sizeof(sha1_except)/sizeof(sha1_except[0])) != 0)
155     {
156         rt_kprintf("Hash type sha1 Test error, The actual result is not equal to the except result\n");
157     }
158     else
159     {
160         rt_kprintf("Hash type sha1 Test success, The actual result is equal to the except result\n");
161     }
162     /* deinit hash*/
163     rt_hwcrypto_hash_destroy(ctx);
164     rt_kprintf("============ SHA1 Test Over ============\n");
165 
166     /* md5 test*/
167     rt_kprintf("\n============ MD5 Test Start ============\n");
168     ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_MD5);
169     if (ctx == RT_NULL)
170     {
171         rt_kprintf("create hash[%08x] context err!\n", HWCRYPTO_TYPE_MD5);
172         return ;
173     }
174     rt_kprintf("Create md5 type success!\n");
175     rt_kprintf("Except md5 result:\n");
176     dump_hex(md5_except, sizeof(md5_except));
177 
178     /* start md5 */
179     rt_hwcrypto_hash_update(ctx, hash_input, rt_strlen((char const *)hash_input));
180     /* get md5 result */
181     rt_hwcrypto_hash_finish(ctx, md5_output, rt_strlen((char const *)md5_output));
182 
183     rt_kprintf("Actual md5 result:\n");
184     dump_hex(md5_output, sizeof(md5_output));
185 
186     if(rt_memcmp(md5_output, md5_except, sizeof(md5_except)/sizeof(md5_except[0])) != 0)
187     {
188         rt_kprintf("Hash type md5 Test error, The actual result is not equal to the except result\n");
189     }
190     else
191     {
192         rt_kprintf("Hash type md5 Test success, The actual result is equal to the except result\n");
193     }
194     /* deinit hash*/
195     rt_hwcrypto_hash_destroy(ctx);
196     rt_kprintf("============ MD5 Test Over ============\n");
197 
198     /* sha224 test */
199     rt_kprintf("\n============ SHA224 Test Start ============\n");
200     ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_SHA224);
201     if (ctx == RT_NULL)
202     {
203         rt_kprintf("create hash[%08x] context err!\n", HWCRYPTO_TYPE_SHA224);
204         return ;
205     }
206     rt_kprintf("Create sha224 type success!\n");
207     rt_kprintf("Except sha224 result:\n");
208     dump_hex(sha224_except, sizeof(sha224_except));
209 
210     /* start sha224 */
211     rt_hwcrypto_hash_update(ctx, hash_input, rt_strlen((char const *)hash_input));
212     /* get sha224 result */
213     rt_hwcrypto_hash_finish(ctx, sha224_output, rt_strlen((char const *)sha224_output));
214 
215     rt_kprintf("Actual sha224 result:\n");
216     dump_hex(sha224_output, sizeof(sha224_output));
217 
218     if(rt_memcmp(sha224_output, sha224_except, sizeof(sha224_except)/sizeof(sha224_except[0])) != 0)
219     {
220         rt_kprintf("Hash type sha224 Test error, The actual result is not equal to the except result\n");
221     }
222     else
223     {
224         rt_kprintf("Hash type sha224 Test success, The actual result is equal to the except result\n");
225     }
226     rt_hwcrypto_hash_destroy(ctx);
227     rt_kprintf("============ SHA224 Test Over ============\n");
228 
229     /* sha256 test*/
230     rt_kprintf("\n============ SHA256 Test Start ============\n");
231     ctx = rt_hwcrypto_hash_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_SHA256);
232     if (ctx == RT_NULL)
233     {
234         rt_kprintf("create hash[%08x] context err!\n", HWCRYPTO_TYPE_SHA256);
235         return ;
236     }
237 
238     rt_kprintf("Create sha256 type success!\n");
239     rt_kprintf("Except sha256 result:\n");
240     dump_hex(sha256_except, sizeof(sha256_except));
241 
242     /* start sha256 */
243     rt_hwcrypto_hash_update(ctx, hash_input, rt_strlen((char const *)hash_input));
244     /* get sha256 result */
245     rt_hwcrypto_hash_finish(ctx, sha256_output, rt_strlen((char const *)sha256_output));
246 
247     rt_kprintf("Actual sha256 result\n");
248     dump_hex(sha256_output, sizeof(sha256_output));
249 
250     if(rt_memcmp(sha256_output, sha256_except, sizeof(sha256_except)/sizeof(sha256_except[0])) != 0)
251     {
252         rt_kprintf("Hash type sha256 Test error, The actual result is not equal to the except result\n");
253     }
254     else
255     {
256         rt_kprintf("Hash type sha256 Test success, The actual result is equal to the except result\n");
257     }
258     /* destory */
259     rt_hwcrypto_hash_destroy(ctx);
260     rt_kprintf("============ SHA256 Test Over ============\n");
261     rt_kprintf("======================== Hash Test over! ========================\n");
262 }
263 #endif
264 
265 #if defined(BSP_USING_CRYP)
266 /* key*/
267 static const rt_uint8_t cryp_key[16] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
268 
hw_aes_cbc(const rt_uint8_t in[32],rt_uint8_t out[32],hwcrypto_mode mode)269 static void hw_aes_cbc(const rt_uint8_t in[32], rt_uint8_t out[32], hwcrypto_mode mode)
270 {
271     struct rt_hwcrypto_ctx *ctx;
272 
273     ctx = rt_hwcrypto_symmetric_create(rt_hwcrypto_dev_default(), HWCRYPTO_TYPE_AES_CBC);
274     if (ctx == RT_NULL)
275     {
276         rt_kprintf("create AES-CBC context err!");
277         return;
278     }
279     rt_hwcrypto_symmetric_setkey(ctx, cryp_key, 128);
280     rt_hwcrypto_symmetric_crypt(ctx, mode, 32, in, out);
281     rt_hwcrypto_symmetric_destroy(ctx);
282 }
283 
hw_cryp_sample()284 static void hw_cryp_sample()
285 {
286     rt_uint8_t buf_in[32];
287     rt_uint8_t buf_out[32];
288     int i;
289 
290     /* Populating test data */
291     for (i = 0; i < sizeof(buf_in); i++)
292     {
293         buf_in[i] = i;
294     }
295 
296     /* dump primitive data */
297     rt_kprintf("key : \n");
298     dump_hex(cryp_key, sizeof(cryp_key));
299     rt_kprintf("primitive data : \n");
300     dump_hex(buf_in, sizeof(buf_in));
301 
302     rt_memset(buf_out, 0, sizeof(buf_out));
303 
304     /* encrypt */
305     hw_aes_cbc(buf_in, buf_out, HWCRYPTO_MODE_ENCRYPT);
306     /* dump encrypt data */
307     rt_kprintf("AES-enc : \n");
308     dump_hex(buf_out, sizeof(buf_out));
309 
310     rt_memset(buf_in, 0, sizeof(buf_in));
311 
312     /* decrypt */
313     hw_aes_cbc(buf_out, buf_in, HWCRYPTO_MODE_DECRYPT);
314 
315     /* dump decrypt data */
316     rt_kprintf("AES-dec : \n");
317     dump_hex(buf_in, sizeof(buf_in));
318 }
319 #endif
320 
crypto(int argc,char ** argv)321 static int crypto(int argc, char **argv)
322 {
323     int result = RT_EOK;
324     static rt_device_t device = RT_NULL;
325     char *result_str;
326 
327     if (argc > 1)
328     {
329         if (!strcmp(argv[1], "probe"))
330         {
331             if (argc == 3)
332             {
333                 char *dev_name = argv[2];
334                 device = rt_device_find(dev_name);
335                 result_str = (device == RT_NULL) ? "failure" : "success";
336                 rt_kprintf("probe %s %s \n", argv[2], result_str);
337             }
338             else
339             {
340                 rt_kprintf("crypto probe <crypto_name>   - probe crypto by name\n");
341             }
342         }
343         else
344         {
345             if (device == RT_NULL)
346             {
347                 rt_kprintf("Please using 'crypto probe <crypto_name>' first\n");
348                 return -RT_ERROR;
349             }
350             if (!strcmp(argv[1], "rng"))
351             {
352 #if defined (BSP_USING_RNG)
353                 if (argc == 3)
354                 {
355                     result = hw_rng_sample(atoi(argv[2]));
356                     if(result != RT_EOK)
357                     {
358                         rt_kprintf("please input a  legal number, not <%d>\n", atoi(argv[2]));
359                     }
360                 }
361                 else
362                 {
363                     rt_kprintf("rng <number>        - generate <number> digital\n");
364                 }
365 
366 #else
367                 rt_kprintf("please enable RNG first!\n");
368 #endif
369             }
370             else if (!strcmp(argv[1], "crc"))
371             {
372 #if defined (BSP_USING_CRC)
373                 int size = 0, i = 0;
374                 if (argc > 3)
375                 {
376                     size = argc - 2;
377                     uint8_t *data = rt_malloc(size);
378                     if (data)
379                     {
380                         for (i = 0; i < size; i++)
381                         {
382                             data[i] = strtol(argv[2 + i], NULL, 0);
383                         }
384                         hw_crc_sample(data, size);
385                         rt_free(data);
386                     }
387                     else
388                     {
389                         rt_kprintf("Low memory!\n");
390                     }
391                 }
392                 else
393                 {
394                     rt_kprintf("crypto crc data1 ... dataN          - calculate data1 ... dataN crc\n");
395                 }
396 #else
397                 rt_kprintf("please enable CRC first!\n");
398 #endif
399             }
400             else if (!strcmp(argv[1], "hash"))
401             {
402 #if defined (BSP_USING_HASH)
403                 if (argc == 3)
404                 {
405                     hw_hash_sample();
406                 }
407                 else
408                 {
409                     rt_kprintf("crypto hash sample          - hash use sample\n");
410                 }
411 #else
412          rt_kprintf("please enable CRC first!\n");
413 #endif
414             }
415             else if (!strcmp(argv[1], "cryp"))
416             {
417 #if defined (BSP_USING_CRYP)
418                 if (argc == 3)
419                 {
420                     hw_cryp_sample();
421                 }
422                 else
423                 {
424                     rt_kprintf("crypto cryp sample          - encrypt and decrypt data sample\n");
425                 }
426 #else
427          rt_kprintf("please enable CRYP first!\n");
428 #endif
429             }
430             else
431             {
432                 rt_kprintf("Unknown command. Please enter 'crypto' for help\n");
433             }
434         }
435     }
436     else
437     {
438         rt_kprintf("Usage: \n");
439         rt_kprintf("crypto probe <crypto_name>                  - probe crypto by name\n");
440         rt_kprintf("crypto rng number                           - generate numbers digital\n");
441         rt_kprintf("crypto crc data1 ... dataN                  - calculate data1 ... dataN crc\n");
442         rt_kprintf("crypto hash sample                          - hash use sample\n");
443         rt_kprintf("crypto cryp sample                          - encrypt and decrypt data\n");
444         result = -RT_ERROR;
445     }
446 
447     return result;
448 }
449 MSH_CMD_EXPORT(crypto, crypto function);
450