/* * Copyright (c) 2021 Novatek Inc. * */ #include #include #include DECLARE_GLOBAL_DATA_PTR; #define _ALIGNED(x) __attribute__((aligned(x))) #define CACHE_LINE_SIZE CONFIG_SYS_CACHELINE_SIZE static uint8_t AES_IV[] = { 0x0B, 0x7C, 0xFC, 0x71, 0x08, 0x11, 0xC2, 0x21, 0x6F, 0x4F, 0xAC, 0xBA, 0xBF, 0x4F, 0x28, 0x8B }; static uint8_t AES_KEY[] = { 0x31, 0xD1, 0x32, 0x61, 0xBB, 0xA9, 0x28, 0xFD, 0xF6, 0x9D, 0x8D, 0xD3, 0xFB, 0xE1, 0x23, 0xEC, 0x6A, 0xAD, 0x01, 0x7D, 0x1C, 0xFC, 0xE9, 0x36, 0x05, 0x9C, 0x60, 0x1A, 0x33, 0xA5, 0x14, 0x09 }; static uint8_t _ALIGNED(CACHE_LINE_SIZE) AES_PLAINTEXT[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 }; static uint8_t _ALIGNED(CACHE_LINE_SIZE) AES128_ECB_CIPHERTEXT[] = { 0xCB, 0x4E, 0x39, 0x2D, 0xAC, 0x11, 0x40, 0xFB, 0x4E, 0xD6, 0x31, 0xCD, 0xCC, 0x2C, 0x21, 0x7B, 0x30, 0xCF, 0xCF, 0xB5, 0xAB, 0xFD, 0x1B, 0x99, 0x19, 0xB6, 0x9F, 0x1A, 0x37, 0x51, 0x5A, 0xCA }; static uint8_t _ALIGNED(CACHE_LINE_SIZE) AES128_CBC_CIPHERTEXT[] = { 0x83, 0xC3, 0xEF, 0x24, 0xE4, 0xD4, 0x19, 0xEE, 0x64, 0x3E, 0x8C, 0xA3, 0x98, 0x16, 0x05, 0x20, 0xBA, 0x8D, 0x5F, 0x5D, 0x13, 0xBA, 0x30, 0x5F, 0xC5, 0x4F, 0x70, 0x5C, 0x89, 0x3C, 0x3A, 0x5A }; static uint8_t _ALIGNED(CACHE_LINE_SIZE) AES256_ECB_CIPHERTEXT[] = { 0xC6, 0xE6, 0x0C, 0xC6, 0xF1, 0x3D, 0x6C, 0x73, 0x93, 0x5A, 0x80, 0x92, 0x12, 0x14, 0x0F, 0xC5, 0xA0, 0x07, 0xDB, 0xFD, 0x63, 0xD3, 0xD2, 0x5E, 0x0B, 0x08, 0xD0, 0xD3, 0x6C, 0xA7, 0x23, 0xC3 }; static uint8_t _ALIGNED(CACHE_LINE_SIZE) AES256_CBC_CIPHERTEXT[] = { 0x3A, 0xBD, 0xEB, 0x54, 0xAA, 0x71, 0x78, 0xC8, 0xC2, 0x5E, 0xC4, 0x88, 0xA5, 0x63, 0x35, 0xBB, 0x96, 0x51, 0x5B, 0x8C, 0x84, 0x5C, 0x56, 0x1B, 0x1E, 0x94, 0x1F, 0xF3, 0x1E, 0x0B, 0x13, 0x4B }; #ifdef CONFIG_NVT_FPGA_EMULATION /* efuse test key */ static uint32_t EFUSE_TEST_KEY[20] = { 0x01020304, 0x05060708, 0x09101112, 0x13141516, ///< Key#0 0x9b0daa24, 0xb431aef1, 0xc4e45128, 0x1e1d71d1, ///< Key#1 0xc5814d95, 0xe52bcc5a, 0xc374c8dd, 0x5ccfaf9f, ///< Key#2 0x00000000, 0x00000000, 0x00000000, 0x00000000, ///< Key#3 0x00000000, 0x00000000, 0x00000000, 0x00000000 ///< Key#4 }; #endif #define EFUSE_KEY_0_OFFSET 0 #define EFUSE_KEY_1_OFFSET 4 #define EFUSE_KEY_2_OFFSET 8 #define EFUSE_KEY_3_OFFSET 12 #define EFUSE_KEY_4_OFFSET 16 /****************************************************************** NA51090 efuse key section 640bit => 20 word ============================================================= key# offset word[0] word[1] word[2] word[3] ============================================================= key#0 [ 0] xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx => 128bit key#1 [ 4] xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx => 128bit key#2 [ 8] xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx => 128bit key#3 [12] xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx => 128bit key#4 [16] xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx => 128bit *******************************************************************/ /** * do_nvt_crypto() - Handle the "nvt_crypto" command-line command * @cmdtp: Command data struct pointer * @flag: Command flag * @argc: Command-line argument count * @argv: Array of command-line arguments * * Returns zero on success, CMD_RET_USAGE in case of misuse and negative * on error. */ static int do_nvt_crypto(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int ret = 0; int key_size; int opmode; int dma_mode; NVT_CRYPTO_KEY_SRC_T key_src; uint32_t key_ofs; uint8_t *ciphertext; uint8_t _ALIGNED(CACHE_LINE_SIZE) dst_buf[32]; ///< start address must alignment to 64 for cache operation in dma mode struct nvt_crypto_pio_t crypto; /* Check argument */ if (argc < 6) return CMD_RET_USAGE; /* Key Length */ if (!strncmp(argv[1], "aes128", 6)) key_size = NVT_CRYPTO_AES_128_KEY_SIZE; else if (!strncmp(argv[1], "aes256", 6)) key_size = NVT_CRYPTO_AES_256_KEY_SIZE; else return CMD_RET_USAGE; /* OPmode */ if (!strncmp(argv[2], "ecb", 3)) { opmode = NVT_CRYPTO_OPMODE_ECB; ciphertext = (key_size == NVT_CRYPTO_AES_128_KEY_SIZE) ? AES128_ECB_CIPHERTEXT : AES256_ECB_CIPHERTEXT; } else if (!strncmp(argv[2], "cbc", 3)) { opmode = NVT_CRYPTO_OPMODE_CBC; ciphertext = (key_size == NVT_CRYPTO_AES_128_KEY_SIZE) ? AES128_CBC_CIPHERTEXT : AES256_CBC_CIPHERTEXT; } else return CMD_RET_USAGE; /* Key Source */ if (key_size == NVT_CRYPTO_AES_128_KEY_SIZE) { if (!strncmp(argv[3], "ekey0", 5)) { key_src = NVT_CRYPTO_KEY_SRC_EFUSE; key_ofs = EFUSE_KEY_0_OFFSET; } else if (!strncmp(argv[3], "ekey1", 5)) { key_src = NVT_CRYPTO_KEY_SRC_EFUSE; key_ofs = EFUSE_KEY_1_OFFSET; } else if (!strncmp(argv[3], "ekey2", 5)) { key_src = NVT_CRYPTO_KEY_SRC_EFUSE; key_ofs = EFUSE_KEY_2_OFFSET; } else if (!strncmp(argv[3], "ekey3", 5)) { key_src = NVT_CRYPTO_KEY_SRC_EFUSE; key_ofs = EFUSE_KEY_3_OFFSET; } else if (!strncmp(argv[3], "ekey4", 5)) { key_src = NVT_CRYPTO_KEY_SRC_EFUSE; key_ofs = EFUSE_KEY_4_OFFSET; } else if (!strncmp(argv[3], "ukey", 4)) { key_src = NVT_CRYPTO_KEY_SRC_DATA; key_ofs = 0; } else return CMD_RET_USAGE; } else { if (!strncmp(argv[3], "ukey", 4)) { key_src = NVT_CRYPTO_KEY_SRC_DATA; key_ofs = 0; } else return CMD_RET_USAGE; } /* PIO/DMA */ if (!strncmp(argv[4], "pio", 3)) { dma_mode = 0; } else if (!strncmp(argv[4], "dma", 3)) { dma_mode = 1; } else return CMD_RET_USAGE; /* Command */ if (strncmp(argv[5], "verify", 6)) return CMD_RET_USAGE; /* Open Crypto Device */ ret = nvt_crypto_open(); if (ret < 0) { printf("nvt crypto open failed!\n"); return CMD_RET_FAILURE; } if (key_src == NVT_CRYPTO_KEY_SRC_DATA) { /* AES Encryption */ crypto.encrypt = 1; crypto.opmode = opmode; crypto.src = AES_PLAINTEXT; crypto.dst = dst_buf; crypto.key = AES_KEY; crypto.iv = (opmode == NVT_CRYPTO_OPMODE_CBC) ? AES_IV : NULL; crypto.key_src = key_src; crypto.key_ofs = key_ofs; crypto.src_size = sizeof(AES_PLAINTEXT); crypto.dst_size = sizeof(dst_buf); crypto.key_size = key_size; crypto.iv_size = (opmode == NVT_CRYPTO_OPMODE_CBC) ? sizeof(AES_IV) : 0; ret = (dma_mode) ? nvt_crypto_dma_aes(&crypto) : nvt_crypto_pio_aes(&crypto); if (ret < 0) { printf("nvt crypto %s %s encrypt failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto exit; } /* Output Data Compare */ if (memcmp(dst_buf, ciphertext, sizeof(dst_buf))) { printf("nvt crypto %s %s encryption compare failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto exit; } /* AES Decryption */ crypto.encrypt = 0; crypto.opmode = opmode; crypto.src = ciphertext; crypto.dst = dst_buf; crypto.key = AES_KEY; crypto.iv = (opmode == NVT_CRYPTO_OPMODE_CBC) ? AES_IV : NULL; crypto.key_src = key_src; crypto.key_ofs = key_ofs; crypto.src_size = sizeof(dst_buf); crypto.dst_size = sizeof(dst_buf); crypto.key_size = key_size; crypto.iv_size = (opmode == NVT_CRYPTO_OPMODE_CBC) ? sizeof(AES_IV) : 0; ret = (dma_mode) ? nvt_crypto_dma_aes(&crypto) : nvt_crypto_pio_aes(&crypto); if (ret < 0) { printf("nvt crypto %s %s decrypt failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto exit; } /* Output Data Compare */ if (memcmp(dst_buf, AES_PLAINTEXT, sizeof(dst_buf))) { printf("nvt crypto %s %s decryption compare failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto exit; } } else { uint8_t *src = NULL; uint8_t *dst = NULL; uint32_t data_size = 0x2000; /* allocate source data buffer */ src = malloc_cache_aligned(data_size); if (!src) { printf("nvt crypto %s %s ekey verify to allocate source buffer failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto freemem; } /* allocate destination data buffer */ dst = malloc_cache_aligned(data_size); if (!dst) { printf("nvt crypto %s %s ekey verify to allocate destination buffer failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto freemem; } /* AES Encryption with efuse key */ crypto.encrypt = 1; crypto.opmode = opmode; crypto.src = src; crypto.dst = dst; crypto.key = NULL; crypto.iv = (opmode == NVT_CRYPTO_OPMODE_CBC) ? AES_IV : NULL; crypto.key_src = key_src; crypto.key_ofs = key_ofs; crypto.src_size = data_size; crypto.dst_size = data_size; crypto.key_size = key_size; crypto.iv_size = (opmode == NVT_CRYPTO_OPMODE_CBC) ? sizeof(AES_IV) : 0; ret = (dma_mode) ? nvt_crypto_dma_aes(&crypto) : nvt_crypto_pio_aes(&crypto); if (ret < 0) { printf("nvt crypto %s %s ekey encrypt failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto freemem; } /* AES Decryption with efuse test key */ crypto.encrypt = 0; crypto.opmode = opmode; crypto.src = dst; crypto.dst = dst; #ifdef CONFIG_NVT_FPGA_EMULATION crypto.key = (uint8_t *)&EFUSE_TEST_KEY[key_ofs]; crypto.iv = (opmode == NVT_CRYPTO_OPMODE_CBC) ? AES_IV : NULL; crypto.key_src = NVT_CRYPTO_KEY_SRC_DATA; crypto.key_ofs = 0; #else crypto.key = NULL; crypto.iv = (opmode == NVT_CRYPTO_OPMODE_CBC) ? AES_IV : NULL; crypto.key_src = key_src; crypto.key_ofs = key_ofs; #endif crypto.src_size = data_size; crypto.dst_size = data_size; crypto.key_size = key_size; crypto.iv_size = (opmode == NVT_CRYPTO_OPMODE_CBC) ? sizeof(AES_IV) : 0; ret = (dma_mode) ? nvt_crypto_dma_aes(&crypto) : nvt_crypto_pio_aes(&crypto); if (ret < 0) { printf("nvt crypto %s %s ekey decrypt failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto freemem; } /* Output Data Compare */ if (memcmp(src, dst, data_size)) { printf("nvt crypto %s %s ekey decryption compare failed!\n", argv[1], argv[2]); ret = CMD_RET_FAILURE; goto freemem; } freemem: if (src) free(src); if (dst) free(dst); if (ret != 0) goto exit; } printf("nvt crypto %s %s verify passed!\n", argv[1], argv[2]); exit: /* Close Crypto Device */ nvt_crypto_close(); return ret; } /***************************************************/ U_BOOT_CMD( nvt_crypto, 6, 0, do_nvt_crypto, "nvt_crypto operation", "\nnvt_crypto aes128 [ecb/cbc] [ekey0-4/ukey] [pio/dma] verify - for verify aes128 encryption/decryption" "\nnvt_crypto aes256 [ecb/cbc] [ekey0-4/ukey] [pio/dma] verify - for verify aes256 encryption/decryption" );