/** * @file sdrv_crypto_init.c * @brief Semidrive CRYPTO init source file. * * @copyright Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #define EFUSEC_EHSM_CFG_OFFSET 0x1300 #define EFUSEC_SEIP_SECSTORAGE_SEL_OFFSET 0x12c9 #define RSTGEN_POLLs 0x10000 #define INIT_EFUSE_FOR_TEST 0 uint32_t sdrv_crypto_type = 0; void init_efuse_for_test(void) { unsigned int data; /*Step1 wati efuse init done (not busy)*/ printf("[seip test] Polling for efusec busy released\n"); /*bit[10] busy*/ data = readl(APB_EFUSEC_BASE + 0x0); if ((data & (1 << 10)) == 0) { printf("efusec is ready\n"); } else { printf("[seip test] Efusec still busy, check delay time or efusec " "behavior\n"); return; } /*Step2 write otp*/ printf("[seip test] Initializing OTP...\n"); /*Self_Ctrl_For_Boot*/ /*seip_control field, seip_mode_sel = 10 CACC mode 00 MAILBOX mode * 0x3F000000*/ #if CONFIG_OSR_CRYPTO_TEST_CACC writel(0x3F020000, APB_EFUSEC_BASE + 0x1300); printf("[seip test] CACC MODE SELECT...\n"); #else writel(0x00000000, APB_EFUSEC_BASE + 0x1300); printf("[seip test] MIALBOX MODE SELECT...\n"); #endif /*life cycle mode*/ writel(0x57C1EC96, APB_EFUSEC_BASE + 0x1304); /*analog timming 1*/ writel(0x00000000, APB_EFUSEC_BASE + 0x1308); writel(0x00000000, APB_EFUSEC_BASE + 0x130C); /*secure flag*/ writel(0xFFFFFFFF, APB_EFUSEC_BASE + 0x1310); /*PKD Public Key Digest 8x32*/ writel(0x5C4CE1B2, APB_EFUSEC_BASE + 0x1080); writel(0x5BDFC679, APB_EFUSEC_BASE + 0x1084); writel(0x7EFEF485, APB_EFUSEC_BASE + 0x1088); writel(0x267ADBD8, APB_EFUSEC_BASE + 0x108c); writel(0xE0A79D2B, APB_EFUSEC_BASE + 0x1090); writel(0xA90ECB7C, APB_EFUSEC_BASE + 0x1094); writel(0x8C7B74F4, APB_EFUSEC_BASE + 0x1098); writel(0xF3A4A8CD, APB_EFUSEC_BASE + 0x109c); /*SSK CTRL0 CTRL1*/ writel(0x20009100, APB_EFUSEC_BASE + 0x1318); writel(0x81910000, APB_EFUSEC_BASE + 0x131C); /*analog timming 2*/ writel(0x00000000, APB_EFUSEC_BASE + 0x1314); /*FSRK*/ writel(0x01cca048, APB_EFUSEC_BASE + 0x10c0); writel(0x13e16fc6, APB_EFUSEC_BASE + 0x10c4); writel(0x468c8fc3, APB_EFUSEC_BASE + 0x10c8); writel(0x9b33e294, APB_EFUSEC_BASE + 0x10cc); /*Debug Passphrase(DPK)*/ writel(0x555a8f01, APB_EFUSEC_BASE + 0x10E0); writel(0x97445894, APB_EFUSEC_BASE + 0x10E4); writel(0xe4f7ffc0, APB_EFUSEC_BASE + 0x10E8); writel(0xfc163902, APB_EFUSEC_BASE + 0x10EC); writel(0x69bffe04, APB_EFUSEC_BASE + 0x10F0); writel(0x6afaab9f, APB_EFUSEC_BASE + 0x10F4); writel(0xb2909223, APB_EFUSEC_BASE + 0x10F8); writel(0x605c925b, APB_EFUSEC_BASE + 0x10FC); /*SSRK*/ writel(0x6f5a1159, APB_EFUSEC_BASE + 0x10d0); writel(0xc4c128be, APB_EFUSEC_BASE + 0x10d4); writel(0x51d3ab6d, APB_EFUSEC_BASE + 0x10d8); writel(0x79dfe324, APB_EFUSEC_BASE + 0x10dc); /*Firmware Update Key(fuk)*/ writel(0xe526a831, APB_EFUSEC_BASE + 0x1100); writel(0x91d949bb, APB_EFUSEC_BASE + 0x1104); writel(0xe981ea4b, APB_EFUSEC_BASE + 0x1108); writel(0x482b906c, APB_EFUSEC_BASE + 0x110c); writel(0x51422e72, APB_EFUSEC_BASE + 0x1110); writel(0x84e87752, APB_EFUSEC_BASE + 0x1114); writel(0x38da4eec, APB_EFUSEC_BASE + 0x1118); writel(0x588dfa57, APB_EFUSEC_BASE + 0x111c); /*Flash Decryption Key(fdk)*/ writel(0x045ade7e, APB_EFUSEC_BASE + 0x1120); writel(0xc994f43a, APB_EFUSEC_BASE + 0x1124); writel(0xefaeeaea, APB_EFUSEC_BASE + 0x1128); writel(0xb0a913c3, APB_EFUSEC_BASE + 0x112c); writel(0x51422e72, APB_EFUSEC_BASE + 0x1130); writel(0x84e87752, APB_EFUSEC_BASE + 0x1134); writel(0x38da4eec, APB_EFUSEC_BASE + 0x1138); writel(0x588dfa57, APB_EFUSEC_BASE + 0x113c); /*SSK2 (GP_KEY0)*/ writel(0xb7125e26, APB_EFUSEC_BASE + 0x1140); writel(0xdc6dea26, APB_EFUSEC_BASE + 0x1144); writel(0x67aadb08, APB_EFUSEC_BASE + 0x1148); writel(0x7f5d3ac6, APB_EFUSEC_BASE + 0x114c); writel(0x84b3ba9b, APB_EFUSEC_BASE + 0x1150); writel(0x9407ff29, APB_EFUSEC_BASE + 0x1154); writel(0x9bc6c26d, APB_EFUSEC_BASE + 0x1158); writel(0x93da36b5, APB_EFUSEC_BASE + 0x115c); /*SSK3 (GD_KEY1)*/ writel(0xc2c6cf73, APB_EFUSEC_BASE + 0x1160); writel(0x3a6a7aee, APB_EFUSEC_BASE + 0x1164); writel(0x6419d405, APB_EFUSEC_BASE + 0x1168); writel(0x098bea55, APB_EFUSEC_BASE + 0x116c); writel(0x51422e72, APB_EFUSEC_BASE + 0x1170); writel(0x84e87752, APB_EFUSEC_BASE + 0x1174); writel(0x38da4eec, APB_EFUSEC_BASE + 0x1178); writel(0x588dfa57, APB_EFUSEC_BASE + 0x117c); /*SSK4 (GD_KEY2)*/ writel(0x512fdc13, APB_EFUSEC_BASE + 0x1180); writel(0x5f9dd394, APB_EFUSEC_BASE + 0x1184); writel(0xcd43a99b, APB_EFUSEC_BASE + 0x1188); writel(0x3364117f, APB_EFUSEC_BASE + 0x118c); writel(0x7f3b7c37, APB_EFUSEC_BASE + 0x1190); writel(0x2f59b8c8, APB_EFUSEC_BASE + 0x1194); writel(0xa5487ae8, APB_EFUSEC_BASE + 0x1198); writel(0x1b9cc114, APB_EFUSEC_BASE + 0x119c); /*CRC (KCRC)*/ writel(0xD274ED53, APB_EFUSEC_BASE + 0x12a0); writel(0x7C1985E9, APB_EFUSEC_BASE + 0x12a4); writel(0xDF4C8867, APB_EFUSEC_BASE + 0x12a8); writel(0xB05F2E42, APB_EFUSEC_BASE + 0x12ac); writel(0x8F6AF678, APB_EFUSEC_BASE + 0x12b0); writel(0x179935B0, APB_EFUSEC_BASE + 0x12b4); writel(0x17797D10, APB_EFUSEC_BASE + 0x12b8); writel(0x4EE0CBE3, APB_EFUSEC_BASE + 0x12bc); writeb(0x01, APB_EFUSEC_BASE + 0x12c9); printf("[seip test] init_efuse_shadow_register_default completed\n"); } /*write i_kbuf_ctrl*/ void write_kbuf_ctrl(unsigned int data) { int reg = 0; int rdata = 0; rdata = readl(APB_EFUSEC_BASE + 0x12C8); reg = (rdata & 0xFFFF) | (data << 16); writel(reg, APB_EFUSEC_BASE + 0x12C8); } /*write keys with default algorithm*/ void check_efuse_shadow_register_for_test(void) { int rdata; printf("AHB Reading and Checking Key..........\n"); /*read key through AHB*/ /*FSRT READY KEY*/ write_kbuf_ctrl(0xe78a); /*sys_tb_ctrl_delay_us_for_sim_only(2);*/ rdata = readl(0x021de800); if (rdata != 0x107119e7) { printf("FISRT KEY ERROR! 1rdata =0x%x\n", rdata); } rdata = readl(0x021de804); if (rdata != 0x5fe88b1e) { printf("FISRT KEY ERROR! 2rdata =0x%x\n", rdata); } rdata = readl(0x021de808); if (rdata != 0x8922e4ae) { printf("FISRT KEY ERROR! 3rdata =0x%x\n", rdata); } rdata = readl(0x021de80c); if (rdata != 0xceae16cf) { printf("FISRT KEY ERROR! 4rdata =0x%x\n", rdata); } rdata = readl(0x021de810); if (rdata != 0x00000000) { printf("FISRT KEY ERROR! 5rdata =0x%x\n", rdata); } rdata = readl(0x021de814); if (rdata != 0x00000000) { printf("FISRT KEY ERROR! 6rdata =0x%x\n", rdata); } rdata = readl(0x021de818); if (rdata != 0x00000000) { printf("FISRT KEY ERROR! 7rdata =0x%x\n", rdata); } rdata = readl(0x021de81c); if (rdata != 0x00000000) { printf("FISRT KEY ERROR! 8rdata =0x%x\n", rdata); } /*DEBUG PASSPHRASE KEY*/ write_kbuf_ctrl(0x5d4); rdata = readl(0x021de820); if (rdata != 0x0ee9f560) { printf("DEBUG PASSPHRASE ERROR!1rdata =0x%x\n", rdata); } rdata = readl(0x021de824); if (rdata != 0x9a22ecba) { printf("DEBUG PASSPHRASE ERROR!2rdata =0x%x\n", rdata); } rdata = readl(0x021de828); if (rdata != 0xa3a43744) { printf("DEBUG PASSPHRASE ERROR!3rdata =0x%x\n", rdata); } rdata = readl(0x021de82c); if (rdata != 0x8a9d9b8d) { printf("DEBUG PASSPHRASE ERROR!4rdata =0x%x\n", rdata); } rdata = readl(0x021de830); if (rdata != 0x00000000) { printf("DEBUG PASSPHRASE ERROR!5rdata =0x%x\n", rdata); } rdata = readl(0x021de834); if (rdata != 0x00000000) { printf("DEBUG PASSPHRASE ERROR!6rdata =0x%x\n", rdata); } rdata = readl(0x021de838); if (rdata != 0x00000000) { printf("DEBUG PASSPHRASE ERROR!7rdata =0x%x\n", rdata); } rdata = readl(0x021de83c); if (rdata != 0x00000000) { printf("DEBUG PASSPHRASE ERROR!8rdata =0x%x\n", rdata); } /*SSRK*/ write_kbuf_ctrl(0x2355); rdata = readl(0x021de840); if (rdata != 0xf30e2676) { printf("SECOND KEY ERROR!1rdata =0x%x\n", rdata); } rdata = readl(0x021de844); if (rdata != 0xeac1222c) { printf("SECOND KEY ERROR!2rdata =0x%x\n", rdata); } rdata = readl(0x021de848); if (rdata != 0x02e596c5) { printf("SECOND KEY ERROR!3rdata =0x%x\n", rdata); } rdata = readl(0x021de84c); if (rdata != 0x79a8eb9f) { printf("SECOND KEY ERROR!4rdata =0x%x\n", rdata); } rdata = readl(0x021de850); if (rdata != 0x00000000) { printf("SECOND KEY ERROR!5rdata =0x%x\n", rdata); } rdata = readl(0x021de854); if (rdata != 0x00000000) { printf("SECOND KEY ERROR!6rdata =0x%x\n", rdata); } rdata = readl(0x021de858); if (rdata != 0x00000000) { printf("SECOND KEY ERROR!7rdata =0x%x\n", rdata); } rdata = readl(0x021de85c); if (rdata != 0x00000000) { printf("SECOND KEY ERROR!8rdata =0x%x\n", rdata); } /*FIRMWARE UPDATE KEY*/ write_kbuf_ctrl(0xa55a); rdata = readl(0x021de860); if (rdata != 0x45a4079f) { printf("FIREMWARE UPDATE KEY ERROR!1rdata =0x%x\n", rdata); } rdata = readl(0x021de864); if (rdata != 0x92fcde09) { printf("FIREMWARE UPDATE KEY ERROR!2rdata =0x%x\n", rdata); } rdata = readl(0x021de868); if (rdata != 0x2a553d1f) { printf("FIREMWARE UPDATE KEY ERROR!3rdata =0x%x\n", rdata); } rdata = readl(0x021de86c); if (rdata != 0x8e06c0cb) { printf("FIREMWARE UPDATE KEY ERROR!4rdata =0x%x\n", rdata); } rdata = readl(0x021de870); if (rdata != 0x00000000) { printf("FIREMWARE UPDATE KEY ERROR!5rdata =0x%x\n", rdata); } rdata = readl(0x021de874); if (rdata != 0x00000000) { printf("FIREMWARE UPDATE KEY ERROR!6rdata =0x%x\n", rdata); } rdata = readl(0x021de878); if (rdata != 0x00000000) { printf("FIREMWARE UPDATE KEY ERROR!7rdata =0x%x\n", rdata); } rdata = readl(0x021de87c); if (rdata != 0x00000000) { printf("FIREMWARE UPDATE KEY ERROR!8rdata =0x%x\n", rdata); } /*FLASH DECRYPTION KEY*/ write_kbuf_ctrl(0x2ca1); rdata = readl(0x021de880); if (rdata != 0x104bab38) { printf("FLASH DECRYPTION KEY ERROR!1rdata =0x%x\n", rdata); } rdata = readl(0x021de884); if (rdata != 0xebe73c79) { printf("FLASH DECRYPTION KEY ERROR!2rdata =0x%x\n", rdata); } rdata = readl(0x021de888); if (rdata != 0x1cb5491c) { printf("FLASH DECRYPTION KEY ERROR!3rdata =0x%x\n", rdata); } rdata = readl(0x021de88c); if (rdata != 0x52e8dc31) { printf("FLASH DECRYPTION KEY ERROR!4rdata =0x%x\n", rdata); } rdata = readl(0x021de890); if (rdata != 0x00000000) { printf("FLASH DECRYPTION KEY ERROR!5rdata =0x%x\n", rdata); } rdata = readl(0x021de894); if (rdata != 0x00000000) { printf("FLASH DECRYPTION KEY ERROR!6rdata =0x%x\n", rdata); } rdata = readl(0x021de898); if (rdata != 0x00000000) { printf("FLASH DECRYPTION KEY ERROR!7rdata =0x%x\n", rdata); } rdata = readl(0x021de89c); if (rdata != 0x00000000) { printf("FLASH DECRYPTION KEY ERROR!8rdata =0x%x\n", rdata); } /*SSK2*/ write_kbuf_ctrl(0xcb5b); rdata = readl(0x021de8a0); if (rdata != 0x8d7972b0) { printf("SSK2 ERROR!1rdata =0x%x\n", rdata); } rdata = readl(0x021de8a4); if (rdata != 0xcccb6db2) { printf("SSK2 ERROR!2rdata =0x%x\n", rdata); } rdata = readl(0x021de8a8); if (rdata != 0x36948442) { printf("SSK2 ERROR!3rdata =0x%x\n", rdata); } rdata = readl(0x021de8ac); if (rdata != 0xc4f5b5f0) { printf("SSK2 ERROR!4rdata =0x%x\n", rdata); } rdata = readl(0x021de8b0); if (rdata != 0x697770aa) { printf("SSK2 ERROR!5rdata =0x%x\n", rdata); } rdata = readl(0x021de8b4); if (rdata != 0x08a35e00) { printf("SSK2 ERROR!6rdata =0x%x\n", rdata); } rdata = readl(0x021de8b8); if (rdata != 0xbc9c08b3) { printf("SSK2 ERROR!7rdata =0x%x\n", rdata); } rdata = readl(0x021de8bc); if (rdata != 0x362d70f8) { printf("SSK2 ERROR!8rdata =0x%x\n", rdata); } /*SSK3*/ write_kbuf_ctrl(0x38d1); rdata = readl(0x021de8c0); if (rdata != 0x95d63843) { printf("SSK3 ERROR!1rdata =0x%x\n", rdata); } rdata = readl(0x021de8c4); if (rdata != 0xc1698e12) { printf("SSK3 ERROR!2rdata =0x%x\n", rdata); } rdata = readl(0x021de8c8); if (rdata != 0x5d6dec1b) { printf("SSK3 ERROR!3rdata =0x%x\n", rdata); } rdata = readl(0x021de8cc); if (rdata != 0x1cf9cfe3) { printf("SSK3 ERROR!4rdata =0x%x\n", rdata); } rdata = readl(0x021de8d0); if (rdata != 0x00000000) { printf("SSK3 ERROR!5rdata =0x%x\n", rdata); } rdata = readl(0x021de8d4); if (rdata != 0x00000000) { printf("SSK3 ERROR!6rdata =0x%x\n", rdata); } rdata = readl(0x021de8d8); if (rdata != 0x00000000) { printf("SSK3 ERROR!7rdata =0x%x\n", rdata); } rdata = readl(0x021de8dc); if (rdata != 0x00000000) { printf("SSK3 ERROR!8rdata =0x%x\n", rdata); } /*SSK4*/ write_kbuf_ctrl(0x7841); rdata = readl(0x021de8e0); if (rdata != 0x3cacc647) { printf("SSK4 ERROR!1rdata =0x%x\n", rdata); } rdata = readl(0x021de8e4); if (rdata != 0xec7f7074) { printf("SSK4 ERROR!2rdata =0x%x\n", rdata); } rdata = readl(0x021de8e8); if (rdata != 0xfa2d7f2f) { printf("SSK4 ERROR!3rdata =0x%x\n", rdata); } rdata = readl(0x021de8ec); if (rdata != 0x55b12764) { printf("SSK4 ERROR!4rdata =0x%x\n", rdata); } rdata = readl(0x021de8f0); if (rdata != 0x51c6c3f2) { printf("SSK4 ERROR!5rdata =0x%x\n", rdata); } rdata = readl(0x021de8f4); if (rdata != 0x7e542a12) { printf("SSK4 ERROR!6rdata =0x%x\n", rdata); } rdata = readl(0x021de8f8); if (rdata != 0x922d9146) { printf("SSK4 ERROR!7rdata =0x%x\n", rdata); } rdata = readl(0x021de8fc); if (rdata != 0x55711916) { printf("SSK4 ERROR!8rdata =0x%x\n", rdata); } rdata = readl(0x021def00); printf("SSK_CTRL0 rdata =0x%x\n", rdata); rdata = readl(0x021def04); printf("SSK_CTRL1 rdata =0x%x\n", rdata); printf("[seip test] KEY CHECK DONE!\n"); } void sdrv_crypto_set_type(uint32_t crypto_type) { sdrv_crypto_type = crypto_type; } /** * @brief Get the type of CRYPTO type. * * This function return crypto type * * @return The result of CRYPTO type. */ uint32_t sdrv_crypto_get_type(void) { return sdrv_crypto_type; } static void set_sec_storage(void) { uint32_t rdata = 0; #ifdef CONFIG_E3L scr_signal_t signal = SCR_SF_SEIP_KEY_SEC_STORAGE_SCR_1_0; #else scr_signal_t signal = SCR_AP_SEIP_KEY_SEC_STORAGE_SCR_1_0; #endif sdrv_scr_t g_scr_ctrl = { #ifdef CONFIG_E3L .base = APB_SCR_SF_BASE, #else .base = APB_SCR_AP_BASE, #endif }; /* before reset seip, must set fuse and scr config */ /* if fuse config ssk4 from sec storage, set */ rdata = readb(APB_EFUSEC_BASE + EFUSEC_SEIP_SECSTORAGE_SEL_OFFSET); if ((rdata & 0x1) == 0) { scr_set(&g_scr_ctrl, &signal, 2); } } static uint32_t hsm_init(void) { Crypto_HsmInitReturnType ret = CRYPTO_HSM_INIT_OK; uint32_t rdata = 0; uint32_t rdata_lifecycle = 0; uint32_t tms = 0; #if INIT_EFUSE_FOR_TEST init_efuse_for_test(); #endif /* add return value */ rdata = readl(APB_EFUSEC_BASE+ EFUSEC_EHSM_CFG_OFFSET); rdata |= 0x80000000; writel(rdata, APB_EFUSEC_BASE+ EFUSEC_EHSM_CFG_OFFSET); set_sec_storage(); sdrv_rstgen_reset(&rstsig_seip); udelay(10); /*polling status seip boot_done*/ tms = 0; do { rdata = readl(APB_SEIP_BASE + 0x14); if (tms >= RSTGEN_POLLs) { return CRYPTO_HSM_INIT_BOOT_TIMEOUT; } } while ((rdata & 0x100) == 0 && (tms++ < RSTGEN_POLLs)); /* if fuse config offset 16, seip_mode_sel = 10 CACC mode, 00 MAILBOX mode */ rdata = readl(APB_EFUSEC_BASE + EFUSEC_EHSM_CFG_OFFSET); /*get hsm life cycle value*/ rdata_lifecycle = readl(APB_EFUSEC_BASE + 0x1304); /* wait for seip ready for mailbox */ if ((rdata & 0x30000) == 0x0) { if(rdata_lifecycle == 0x0){ /*test mode not rsp value*/ }else{ while (rSOCMBOX_RSP_D0 == 0x0) { } rSOCMBOX_INT_STA = 0x02; if (rSOCMBOX_RSP_D0 == SEIP_FW_VER_SUCCESS) { } else { ret = CRYPTO_HSM_INIT_BOOT_FAIL; } } sdrv_crypto_set_type(SDRV_CRYPTO_TYPE_MAILBOX); } else { sdrv_crypto_set_type(SDRV_CRYPTO_TYPE_CACC); } return ret; } /** * @brief Sdrv CRYPTO initialization. * * This function init hsm * * @return E_OK or error code. */ sdrv_crypto_error_status_e sdrv_crypto_init(void) { uint32_t hsm_init_sta = 0; sdrv_crypto_error_status_e ret; uint8_t count; count = RETRY_COUNT; do { hsm_init_sta = hsm_init(); if (hsm_init_sta == CRYPTO_HSM_INIT_OK) { ret = E_OK; break; } else if (hsm_init_sta == CRYPTO_HSM_INIT_BOOT_FAIL) { ret = E_NOT_OK; } else { ret = E_NOT_OK; break; } count--; } while (count); return ret; }