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