xref: /rk3399_rockchip-uboot/cmd/crypto.c (revision 25fbb41f6739e72525dd4ae75a35dd90ede3426f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <command.h>
8 #include <crypto.h>
9 #include <dm.h>
10 #include <u-boot/md5.h>
11 #include <u-boot/sha1.h>
12 #include <u-boot/sha256.h>
13 #include <u-boot/sha512.h>
14 #include <rockchip/crypto_fix_test_data.h>
15 
16 #define PERF_TOTAL_SIZE			(128 * 1024 * 1024)
17 #define PERF_BUFF_SIZE			(4 * 1024 * 1024)
18 
19 #define CALC_RATE_MPBS(bytes, ms)	(((bytes) / 1024) / (ms))
20 
21 struct hash_test_data {
22 	const char	*algo_name;
23 	const char	*mode_name;
24 	u32		algo;
25 	const u8	*data;
26 	u32		data_len;
27 	const u8	*hash;
28 	u32		hash_len;
29 	const u8	*key;
30 	u32		key_len;
31 };
32 
33 struct cipher_test_data {
34 	const char	*algo_name;
35 	const char	*mode_name;
36 	u32		algo;
37 	u32		mode;
38 	const u8	*key;
39 	const u8	*twk_key;
40 	u32		key_len;
41 	const u8	*iv;
42 	u32		iv_len;
43 	const u8	*plain;
44 	u32		plain_len;
45 	const u8	*cipher;
46 	u32		cipher_len;
47 };
48 
49 struct rsa_test_data {
50 	const char	*algo_name;
51 	const char	*mode_name;
52 	u32		algo;
53 	const u8	*n;
54 	u32		n_len;
55 	const u8	*e;
56 	u32		e_len;
57 	const u8	*d;
58 	u32		d_len;
59 	const u8	*c;
60 	u32		c_len;
61 	const u8	*sign_in;
62 	u32		sign_in_len;
63 	const u8	*sign_out;
64 	u32		sign_out_len;
65 };
66 
67 #define HASH_TEST(algo_type, data_in, hash_val) {\
68 	.algo_name = "HASH", \
69 	.mode_name = #algo_type, \
70 	.algo      = CRYPTO_##algo_type, \
71 	.data      = (data_in),\
72 	.data_len  = sizeof(data_in), \
73 	.hash      = (hash_val), \
74 	.hash_len  = sizeof(hash_val) \
75 }
76 
77 #define HMAC_TEST(algo_type, data_in, hash_val, hmac_key) {\
78 	.algo_name = "HMAC", \
79 	.mode_name = #algo_type, \
80 	.algo      = CRYPTO_HMAC_##algo_type, \
81 	.data      = (data_in),\
82 	.data_len  = sizeof(data_in), \
83 	.hash      = (hash_val), \
84 	.hash_len  = sizeof(hash_val), \
85 	.key       = (hmac_key), \
86 	.key_len   = sizeof(hmac_key)\
87 }
88 
89 #define CIPHER_XTS_TEST(algo_type, mode_type, key1, key2, iv_val, in, out) { \
90 	.algo_name  = #algo_type, \
91 	.mode_name  = #mode_type, \
92 	.algo       = CRYPTO_##algo_type,\
93 	.mode       = RK_MODE_##mode_type, \
94 	.key        = (key1), \
95 	.twk_key    = (key2), \
96 	.key_len    = sizeof(key1), \
97 	.iv         = (iv_val), \
98 	.iv_len     = sizeof(iv_val), \
99 	.plain      = (in), \
100 	.plain_len  = sizeof(in), \
101 	.cipher     = (out), \
102 	.cipher_len = sizeof(out) \
103 }
104 
105 #define CIPHER_TEST(algo, mode, key, iv, plain, cipher) \
106 		CIPHER_XTS_TEST(algo, mode, key, NULL, iv, plain, cipher)
107 
108 #define RSA_TEST(nbits, bn, be, bc, bd, in, out) { \
109 	.algo_name    = "RSA", \
110 	.mode_name    = #nbits, \
111 	.algo         = CRYPTO_RSA##nbits, \
112 	.n            = (bn), \
113 	.n_len        = sizeof(bn), \
114 	.e            = (be), \
115 	.e_len        = sizeof(be), \
116 	.d            = (bd), \
117 	.d_len        = sizeof(bd), \
118 	.c            = (bc), \
119 	.c_len        = sizeof(bc), \
120 	.sign_in      = (in), \
121 	.sign_in_len  = sizeof(in), \
122 	.sign_out     = (out), \
123 	.sign_out_len = sizeof(out) \
124 }
125 
126 #define EMPTY_TEST() {}
127 
128 const struct hash_test_data hash_data_set[] = {
129 	HASH_TEST(MD5,    foo_data, hash_md5),
130 	HASH_TEST(SHA1,   foo_data, hash_sha1),
131 	HASH_TEST(SHA256, foo_data, hash_sha256),
132 	HASH_TEST(SHA512, foo_data, hash_sha512),
133 	HASH_TEST(SM3,    foo_data, hash_sm3),
134 
135 #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
136 	EMPTY_TEST(),
137 	HMAC_TEST(MD5,    foo_data, hmac_md5,    hmac_key),
138 	HMAC_TEST(SHA1,   foo_data, hmac_sha1,   hmac_key),
139 	HMAC_TEST(SHA256, foo_data, hmac_sha256, hmac_key),
140 	HMAC_TEST(SHA512, foo_data, hmac_sha512, hmac_key),
141 	HMAC_TEST(SM3,    foo_data, hmac_sm3,    hmac_key),
142 #endif
143 };
144 
145 const struct cipher_test_data cipher_data_set[] = {
146 #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
147 	CIPHER_TEST(DES, ECB, des_key, des_iv, foo_data, des_ecb_cipher),
148 	CIPHER_TEST(DES, CBC, des_key, des_iv, foo_data, des_cbc_cipher),
149 	CIPHER_TEST(DES, CFB, des_key, des_iv, foo_data, des_cfb_cipher),
150 	CIPHER_TEST(DES, OFB, des_key, des_iv, foo_data, des_ofb_cipher),
151 
152 	EMPTY_TEST(),
153 	CIPHER_TEST(DES, ECB, tdes_key, tdes_iv, foo_data, tdes_ecb_cipher),
154 	CIPHER_TEST(DES, CBC, tdes_key, tdes_iv, foo_data, tdes_cbc_cipher),
155 	CIPHER_TEST(DES, CFB, tdes_key, tdes_iv, foo_data, tdes_cfb_cipher),
156 	CIPHER_TEST(DES, OFB, tdes_key, tdes_iv, foo_data, tdes_ofb_cipher),
157 
158 	EMPTY_TEST(),
159 	CIPHER_TEST(AES, ECB, aes_key, aes_iv, foo_data, aes_ecb_cipher),
160 	CIPHER_TEST(AES, CBC, aes_key, aes_iv, foo_data, aes_cbc_cipher),
161 	CIPHER_TEST(AES, CFB, aes_key, aes_iv, foo_data, aes_cfb_cipher),
162 	CIPHER_TEST(AES, OFB, aes_key, aes_iv, foo_data, aes_ofb_cipher),
163 	CIPHER_TEST(AES, CTS, aes_key, aes_iv, foo_data, aes_cts_cipher),
164 	CIPHER_TEST(AES, CTR, aes_key, aes_iv, foo_data, aes_ctr_cipher),
165 	CIPHER_XTS_TEST(AES, XTS, aes_key, aes_twk_key,
166 			aes_iv, foo_data, aes_xts_cipher),
167 
168 	EMPTY_TEST(),
169 	CIPHER_TEST(SM4, ECB, sm4_key, sm4_iv, foo_data, sm4_ecb_cipher),
170 	CIPHER_TEST(SM4, CBC, sm4_key, sm4_iv, foo_data, sm4_cbc_cipher),
171 	CIPHER_TEST(SM4, CFB, sm4_key, sm4_iv, foo_data, sm4_cfb_cipher),
172 	CIPHER_TEST(SM4, OFB, sm4_key, sm4_iv, foo_data, sm4_ofb_cipher),
173 	CIPHER_TEST(SM4, CTS, sm4_key, sm4_iv, foo_data, sm4_cts_cipher),
174 	CIPHER_TEST(SM4, CTR, sm4_key, sm4_iv, foo_data, sm4_ctr_cipher),
175 	CIPHER_XTS_TEST(SM4, XTS, sm4_key, sm4_twk_key,
176 			sm4_iv, foo_data, sm4_xts_cipher),
177 #else
178 	EMPTY_TEST(),
179 #endif
180 };
181 
182 const struct rsa_test_data rsa_data_set[] = {
183 #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
184 
185 #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
186 	RSA_TEST(2048, rsa2048_n, rsa2048_e, rsa2048_c, rsa2048_d,
187 		 rsa2048_sign_in, rsa2048_sign_out),
188 #else
189 	RSA_TEST(4096, rsa4096_n, rsa4096_e, NULL, rsa4096_d,
190 		 rsa4096_sign_in, rsa4096_sign_out),
191 #endif
192 
193 #else
194 	EMPTY_TEST(),
195 #endif
196 };
197 
198 static void dump_hex(const char *name, const u8 *array, u32 len)
199 {
200 	int i;
201 
202 	printf("[%s]: %uByte", name, len);
203 	for (i = 0; i < len; i++) {
204 		if (i % 32 == 0)
205 			printf("\n");
206 		printf("%02x ", array[i]);
207 	}
208 	printf("\n");
209 }
210 
211 static inline void print_result_MBps(const char *algo_name,
212 				     const char *mode_name,
213 				     const char *crypt, ulong MBps,
214 				     const u8 *expect, const u8 *actual,
215 				     u32 len)
216 {
217 	if (memcmp(expect, actual, len) == 0) {
218 		printf("[%s] %-8s%-8s PASS    (%luMBps)\n",
219 		       algo_name, mode_name, crypt, MBps);
220 	} else {
221 		printf("[%s] %-8s%-8s FAIL\n",
222 		       algo_name, mode_name, crypt);
223 		dump_hex("expect", expect, len);
224 		dump_hex("actual", actual, len);
225 	}
226 }
227 
228 static inline void print_result_ms(const char *algo_name, const char *mode_name,
229 				   const char *crypt, ulong time_cost,
230 				   const u8 *expect, const u8 *actual, u32 len)
231 {
232 	if (memcmp(expect, actual, len) == 0) {
233 		printf("[%s] %-8s%-8s PASS    (%lums)\n",
234 		       algo_name, mode_name, crypt, time_cost);
235 	} else {
236 		printf("[%s] %-8s%-8s FAIL\n",
237 		       algo_name, mode_name, crypt);
238 		dump_hex("expect", expect, len);
239 		dump_hex("actual", actual, len);
240 	}
241 }
242 
243 int test_hash_perf(struct udevice *dev, u32 algo,
244 		   const u8 *key, u32 key_len, ulong *MBps)
245 {
246 	u32 total_size = PERF_TOTAL_SIZE;
247 	u32 data_size = PERF_BUFF_SIZE;
248 	sha_context ctx;
249 	u8 *data = NULL;
250 	u8 hash_out[64];
251 	int ret, i;
252 
253 	*MBps = 0;
254 
255 	ctx.algo = algo;
256 	ctx.length = total_size;
257 
258 	data = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
259 	if (!data) {
260 		printf("%s, %d: memalign %u error!\n",
261 		       __func__, __LINE__, data_size);
262 		return -EINVAL;
263 	}
264 
265 	memset(data, 0xab, data_size);
266 
267 	ulong start = get_timer(0);
268 
269 	if (key)
270 		ret = crypto_hmac_init(dev, &ctx, (u8 *)key, key_len);
271 	else
272 		ret = crypto_sha_init(dev, &ctx);
273 
274 	if (ret) {
275 		printf("crypto_sha_init error ret = %d!\n", ret);
276 		goto exit;
277 	}
278 
279 	for (i = 0; i < total_size / data_size; i++) {
280 		ret = crypto_sha_update(dev, (u32 *)data, data_size);
281 		if (ret) {
282 			printf("crypto_sha_update error!\n");
283 			goto exit;
284 		}
285 	}
286 
287 	ret = crypto_sha_final(dev, &ctx, hash_out);
288 	if (ret) {
289 		printf("crypto_sha_final error ret = %d!\n", ret);
290 		goto exit;
291 	}
292 
293 	ulong time_cost = get_timer(start);
294 
295 	*MBps = CALC_RATE_MPBS(total_size, time_cost);
296 
297 exit:
298 	free(data);
299 
300 	return ret;
301 }
302 
303 int test_cipher_perf(struct udevice *dev, cipher_context *ctx,
304 		     ulong *MBps, bool enc)
305 {
306 	u32 total_size = PERF_TOTAL_SIZE;
307 	u32 data_size = PERF_BUFF_SIZE;
308 	u8 *plain = NULL, *cipher = NULL;
309 	int ret, i;
310 
311 	*MBps = 0;
312 
313 	plain = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
314 	if (!plain) {
315 		printf("%s, %d: memalign %u error!\n",
316 		       __func__, __LINE__, data_size);
317 		return -EINVAL;
318 	}
319 
320 	cipher = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
321 	if (!cipher) {
322 		printf("%s, %d: memalign %u error!\n",
323 		       __func__, __LINE__, data_size);
324 		free(plain);
325 		return -EINVAL;
326 	}
327 
328 	memset(plain, 0xab, data_size);
329 
330 	ulong start = get_timer(0);
331 
332 	for (i = 0; i < total_size / data_size; i++) {
333 		ret = crypto_cipher(dev, ctx, plain, cipher, data_size, enc);
334 		if (ret) {
335 			printf("crypto_aes error!\n");
336 			goto exit;
337 		}
338 	}
339 
340 	ulong time_cost = get_timer(start);
341 
342 	*MBps = CALC_RATE_MPBS(total_size, time_cost);
343 exit:
344 	free(plain);
345 	free(cipher);
346 
347 	return ret;
348 }
349 
350 int test_hash_result(void)
351 {
352 	const struct hash_test_data *test_data = NULL;
353 	sha_context csha_ctx;
354 	struct udevice *dev;
355 	unsigned int i;
356 	u8 out[64];
357 	int ret;
358 
359 	printf("\n=================== hash & hmac test ===================\n");
360 
361 	for (i = 0; i < ARRAY_SIZE(hash_data_set); i++) {
362 		test_data = &hash_data_set[i];
363 		if (test_data->algo == 0) {
364 			printf("\n");
365 			continue;
366 		}
367 
368 		dev = crypto_get_device(test_data->algo);
369 		if (!dev) {
370 			printf("[%s] %-16s unsupported!!!\n",
371 			       test_data->algo_name,
372 			       test_data->mode_name);
373 			continue;
374 		}
375 
376 		csha_ctx.algo   = test_data->algo;
377 		csha_ctx.length = test_data->data_len;
378 
379 		memset(out, 0x00, sizeof(out));
380 		if (test_data->key) {
381 			ret = crypto_hmac_init(dev, &csha_ctx,
382 					       (u8 *)test_data->key,
383 					       test_data->key_len);
384 			ret |= crypto_hmac_update(dev, (void *)test_data->data,
385 						  test_data->data_len);
386 			ret |= crypto_hmac_final(dev, &csha_ctx, out);
387 			if (ret) {
388 				printf("hmac calc error ret = %d\n", ret);
389 				goto error;
390 			}
391 		} else {
392 			ret = crypto_sha_init(dev, &csha_ctx);
393 			ret |= crypto_sha_update(dev, (void *)test_data->data,
394 						 test_data->data_len);
395 			ret |= crypto_sha_final(dev, &csha_ctx, out);
396 			if (ret) {
397 				printf("hash calc error ret = %d\n", ret);
398 				goto error;
399 			}
400 		}
401 
402 		ulong MBps = 0;
403 
404 		test_hash_perf(dev, test_data->algo,
405 			       test_data->key, test_data->key_len, &MBps);
406 		print_result_MBps(test_data->algo_name, test_data->mode_name,
407 				  "", MBps, test_data->hash, out,
408 				  test_data->hash_len);
409 		printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
410 	}
411 
412 	return 0;
413 error:
414 	printf("%s %s test error!\n",
415 	       test_data->algo_name, test_data->mode_name);
416 	return ret;
417 }
418 
419 int test_cipher_result(void)
420 {
421 	const struct cipher_test_data *test_data = NULL;
422 	struct udevice *dev;
423 	cipher_context ctx;
424 	u8 out[256];
425 	int ret;
426 	u32 i;
427 
428 	printf("\n===================== cipher test ======================\n");
429 
430 	for (i = 0; i < ARRAY_SIZE(cipher_data_set); i++) {
431 		test_data = &cipher_data_set[i];
432 		if (test_data->algo == 0) {
433 			printf("\n");
434 			continue;
435 		}
436 
437 		dev = crypto_get_device(test_data->algo);
438 		if (!dev) {
439 			printf("[%s] %-16s unsupported!!!\n",
440 			       test_data->algo_name, test_data->mode_name);
441 			continue;
442 		}
443 
444 		memset(&ctx, 0x00, sizeof(ctx));
445 
446 		ctx.algo    = test_data->algo;
447 		ctx.mode    = test_data->mode;
448 		ctx.key     = test_data->key;
449 		ctx.twk_key = test_data->twk_key;
450 		ctx.key_len = test_data->key_len;
451 		ctx.iv      = test_data->iv;
452 		ctx.iv_len  = test_data->iv_len;
453 
454 		ulong MBps = 0;
455 
456 		test_cipher_perf(dev, &ctx, &MBps, true);
457 
458 		ret = crypto_cipher(dev, &ctx, test_data->plain,
459 				    out, test_data->plain_len, true);
460 		if (ret)
461 			goto error;
462 
463 		print_result_MBps(test_data->algo_name, test_data->mode_name,
464 				  "encrypt", MBps, test_data->cipher, out,
465 				  test_data->cipher_len);
466 
467 		test_cipher_perf(dev, &ctx, &MBps, false);
468 
469 		ret = crypto_cipher(dev, &ctx, test_data->cipher,
470 				    out, test_data->cipher_len, false);
471 		if (ret)
472 			goto error;
473 
474 		print_result_MBps(test_data->algo_name, test_data->mode_name,
475 				  "decrypt", MBps, test_data->plain, out,
476 				  test_data->plain_len);
477 		printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
478 	}
479 	return 0;
480 error:
481 	printf("%s %s test error!\n",
482 	       test_data->algo_name, test_data->mode_name);
483 	return ret;
484 }
485 
486 int test_rsa_result(void)
487 {
488 	const struct rsa_test_data *test_data = NULL;
489 	u8 *hard_out = NULL, *e_tmp;
490 	u32 data_size = 4096 / 8;
491 	ulong start, time_cost;
492 	struct udevice *dev;
493 	rsa_key rsa_key;
494 	int ret, i;
495 
496 	hard_out = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
497 	if (!hard_out) {
498 		printf("%s, %d: memalign %u error!\n",
499 		       __func__, __LINE__, data_size);
500 		return -EINVAL;
501 	}
502 
503 	e_tmp = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
504 	if (!e_tmp) {
505 		printf("%s, %d: memalign %u error!\n",
506 		       __func__, __LINE__, data_size);
507 		return -EINVAL;
508 	}
509 
510 	printf("\n====================== rsa test ========================\n");
511 	for (i = 0; i < ARRAY_SIZE(rsa_data_set); i++) {
512 		test_data = &rsa_data_set[i];
513 		if (test_data->algo == 0) {
514 			printf("\n");
515 			continue;
516 		}
517 
518 		dev = crypto_get_device(test_data->algo);
519 		if (!dev) {
520 			printf("[%s] %-16s unsupported!!!\n",
521 			       test_data->algo_name, test_data->mode_name);
522 			continue;
523 		}
524 
525 		/* sign test */
526 		memset(&rsa_key, 0x00, sizeof(rsa_key));
527 		rsa_key.algo = test_data->algo;
528 		rsa_key.n = (u32 *)test_data->n;
529 		rsa_key.e = (u32 *)test_data->d;
530 #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
531 		rsa_key.c = (u32 *)test_data->c;
532 #endif
533 
534 		start = get_timer(0);
535 		ret = crypto_rsa_verify(dev, &rsa_key,
536 					(u8 *)test_data->sign_in, hard_out);
537 		if (ret) {
538 			printf("sign test error, ret = %d\n", ret);
539 			goto error;
540 		}
541 		time_cost = get_timer(start);
542 		print_result_ms(test_data->algo_name, test_data->mode_name,
543 				"sign", time_cost, test_data->sign_out,
544 				hard_out, test_data->n_len);
545 
546 		/* verify test */
547 		memset(&rsa_key, 0x00, sizeof(rsa_key));
548 		memset(e_tmp, 0x00, data_size);
549 		memcpy(e_tmp, test_data->e, test_data->e_len);
550 		rsa_key.algo = test_data->algo;
551 		rsa_key.n = (u32 *)test_data->n;
552 		rsa_key.e = (u32 *)e_tmp;
553 #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
554 		rsa_key.c = (u32 *)test_data->c;
555 #endif
556 
557 		start = get_timer(0);
558 		ret = crypto_rsa_verify(dev, &rsa_key,
559 					(u8 *)test_data->sign_out, hard_out);
560 		if (ret) {
561 			printf("verify test error, ret = %d\n", ret);
562 			goto error;
563 		}
564 		time_cost = get_timer(start);
565 
566 		print_result_ms(test_data->algo_name, test_data->mode_name,
567 				"verify", time_cost, test_data->sign_in,
568 				hard_out, test_data->n_len);
569 
570 		printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
571 	}
572 
573 	free(hard_out);
574 	free(e_tmp);
575 
576 	return 0;
577 error:
578 	free(hard_out);
579 	free(e_tmp);
580 	printf("%s %s test error!\n",
581 	       test_data->algo_name, test_data->mode_name);
582 	return ret;
583 }
584 
585 static int test_all_result(void)
586 {
587 	int ret = 0;
588 
589 	ret = test_hash_result();
590 	if (ret)
591 		goto exit;
592 
593 	ret = test_cipher_result();
594 	if (ret)
595 		goto exit;
596 
597 	ret = test_rsa_result();
598 	if (ret)
599 		goto exit;
600 
601 exit:
602 	return 0;
603 }
604 
605 static int do_crypto(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
606 {
607 	return test_all_result();
608 }
609 
610 U_BOOT_CMD(
611 	crypto, 1, 1, do_crypto,
612 	"crypto test",
613 	""
614 );
615