/** ****************************************************************************** * @file blsp_boot_parser.c * @version V1.2 * @date * @brief This file is the peripheral case c file ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2018 Bouffalo Lab

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of Bouffalo Lab nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ #include "blsp_common.h" #include "bflb_platform.h" #include "blsp_bootinfo.h" #include "blsp_boot_parser.h" #include "softcrc.h" #include "blsp_port.h" /** @addtogroup BL606_BLSP_Boot2 * @{ */ /** @addtogroup BLSP_BOOT_PARSER * @{ */ /** @defgroup BLSP_BOOT_PARSER_Private_Macros * @{ */ /*@} end of group BLSP_BOOT_PARSER_Private_Macros */ /** @defgroup BLSP_BOOT_PARSER_Private_Types * @{ */ /*@} end of group BLSP_BOOT_PARSER_Private_Types */ /** @defgroup BLSP_BOOT_PARSER_Private_Variables * @{ */ static uint32_t g_sha_tmp_buf[16] = { 0 }; static uint32_t g_padding[16] = { 0 }; SEC_Eng_SHA256_Ctx g_sha_ctx; extern uint32_t g_user_hash_ignored; /*@} end of group BLSP_BOOT_PARSER_Private_Variables */ /** @defgroup BLSP_BOOT_PARSER_Global_Variables * @{ */ /*@} end of group BLSP_BOOT_PARSER_Global_Variables */ /** @defgroup BLSP_BOOT_PARSER_Private_Fun_Declaration * @{ */ /*@} end of group BLSP_BOOT_PARSER_Private_Fun_Declaration */ /** @defgroup BLSP_BOOT_PARSER_Private_Functions_User_Define * @{ */ /*@} end of group BLSP_BOOT_PARSER_Private_Functions_User_Define */ /** @defgroup BLSP_BOOT_PARSER_Private_Functions * @{ */ /****************************************************************************/ /** * @brief Check if the input public key is the same as burned in the efuse * * @param cpu_type: CPU Type * @param pkhash: Public key hash pointer * * @return 1 for valid and 0 for invalid * *******************************************************************************/ static uint32_t blsp_boot_parse_is_pkhash_valid(uint8_t cpu_type, uint8_t *pkhash) { if (cpu_type == BFLB_BOOT2_CPU_0) { if (0 == memcmp(g_efuse_cfg.pk_hash_cpu0, pkhash, BFLB_BOOT2_PK_HASH_SIZE)) { return 1; } } else if (cpu_type == BFLB_BOOT2_CPU_1) { if (0 == memcmp(g_efuse_cfg.pk_hash_cpu1, pkhash, BFLB_BOOT2_PK_HASH_SIZE)) { return 1; } } return 0; } /*@} end of group BLSP_BOOT_PARSER_Private_Functions */ /** @defgroup BLSP_BOOT_PARSER_Public_Functions * @{ */ /****************************************************************************/ /** * @brief Check if the input public key is the same as burned in the efuse * * @param g_boot_img_cfg: Boot image config pointer * @param data: Image data pointer * * @return boot_error_code type * *******************************************************************************/ int32_t blsp_boot_parse_bootheader(boot_image_config *g_boot_img_cfg, uint8_t *data) { boot_header_config *header = (boot_header_config *)data; uint32_t crc; uint32_t crc_pass = 0; uint32_t i = 0; uint32_t *phash = (uint32_t *)header->hash; if (header->bootCfg.bval.crcIgnore == 1 && header->crc32 == BFLB_BOOT2_DEADBEEF_VAL) { MSG_DBG("Crc ignored\r\n"); crc_pass = 1; } else { crc = BFLB_Soft_CRC32((uint8_t *)header, sizeof(boot_header_config) - sizeof(header->crc32)); if (header->crc32 == crc) { crc_pass = 1; } } if (crc_pass) { if (header->bootCfg.bval.notLoadInBoot) { return BFLB_BOOT2_IMG_BOOTHEADER_NOT_LOAD_ERROR; } /* Get which CPU's img it is*/ for (i = 0; i < BFLB_BOOT2_CPU_MAX; i++) { if (0 == memcmp((void *)&header->magicCode, BFLB_BOOT2_CPU0_MAGIC, sizeof(header->magicCode))) { break; } else if (0 == memcmp((void *)&header->magicCode, BFLB_BOOT2_CPU1_MAGIC, sizeof(header->magicCode))) { break; } } if (i == BFLB_BOOT2_CPU_MAX) { /* No cpu img magic match */ MSG_ERR("Magic code error\r\n"); return BFLB_BOOT2_IMG_BOOTHEADER_MAGIC_ERROR; } g_boot_img_cfg->cpu_type = i; g_boot_img_cfg->entry_point = 0; /* Set image valid 0 as default */ g_boot_img_cfg->img_valid = 0; /* Deal with pll config */ /* Encrypt and sign */ g_boot_img_cfg->encrypt_type = header->bootCfg.bval.encrypt_type; g_boot_img_cfg->sign_type = header->bootCfg.bval.sign; g_boot_img_cfg->key_sel = header->bootCfg.bval.key_sel; /* Xip relative */ g_boot_img_cfg->no_segment = header->bootCfg.bval.no_segment; g_boot_img_cfg->cache_enable = header->bootCfg.bval.cache_enable; g_boot_img_cfg->aes_region_lock = header->bootCfg.bval.aes_region_lock; g_boot_img_cfg->halt_cpu1 = header->bootCfg.bval.halt_cpu1; g_boot_img_cfg->cache_way_disable = header->bootCfg.bval.cache_way_disable; g_boot_img_cfg->hash_ignore = header->bootCfg.bval.hash_ignore; /* Firmware len*/ g_boot_img_cfg->img_segment_info.img_len = header->img_segment_info.img_len; /* Boot entry and flash offset */ g_boot_img_cfg->entry_point = header->bootEntry; g_boot_img_cfg->img_start.flash_offset = header->img_start.flash_offset; MSG_DBG("sign %d,encrypt:%d\r\n", g_boot_img_cfg->sign_type, g_boot_img_cfg->encrypt_type); /* Check encrypt and sign match*/ if (g_efuse_cfg.encrypted[i] != 0) { if (g_boot_img_cfg->encrypt_type == 0) { MSG_ERR("Encrypt not fit\r\n"); return BFLB_BOOT2_IMG_BOOTHEADER_ENCRYPT_NOTFIT; } } if (g_efuse_cfg.sign[i] ^ g_boot_img_cfg->sign_type) { MSG_ERR("sign not fit\r\n"); g_boot_img_cfg->sign_type = g_efuse_cfg.sign[i]; return BFLB_BOOT2_IMG_BOOTHEADER_SIGN_NOTFIT; } if (g_ps_mode == BFLB_PSM_HBN && (!g_efuse_cfg.hbn_check_sign)) { /* In HBN Mode, if user select to ignore hash and sign*/ g_boot_img_cfg->hash_ignore = 1; } else if ((g_boot_img_cfg->hash_ignore == 1 && *phash != BFLB_BOOT2_DEADBEEF_VAL) || g_efuse_cfg.sign[i] != 0) { /* If signed or user not really want to ignore, hash can't be ignored*/ g_boot_img_cfg->hash_ignore = 0; } if (g_user_hash_ignored) { g_boot_img_cfg->hash_ignore = 1; } ARCH_MemCpy_Fast(g_boot_img_cfg->img_hash, header->hash, sizeof(header->hash)); if (g_boot_img_cfg->img_segment_info.img_len == 0) { return BFLB_BOOT2_IMG_SEGMENT_CNT_ERROR; } /* Start hash here*/ Sec_Eng_SHA256_Init(&g_sha_ctx, SEC_ENG_SHA_ID0, SEC_ENG_SHA256, g_sha_tmp_buf, g_padding); Sec_Eng_SHA_Start(SEC_ENG_SHA_ID0); } else { MSG_ERR("bootheader crc error\r\n"); blsp_dump_data((uint8_t *)&crc, 4); return BFLB_BOOT2_IMG_BOOTHEADER_CRC_ERROR; } return BFLB_BOOT2_SUCCESS; } /****************************************************************************/ /** * @brief Parse public key * * @param g_boot_img_cfg: Boot image config pointer * @param data: Public key data pointer * @param own: 1 for current CPU, 0 for other(s) * * @return boot_error_code type * *******************************************************************************/ int32_t blsp_boot_parse_pkey(boot_image_config *g_boot_img_cfg, uint8_t *data, uint8_t own) { boot_pk_config *cfg = (boot_pk_config *)data; uint32_t pk_hash[BFLB_BOOT2_PK_HASH_SIZE / 4]; if (cfg->crc32 == BFLB_Soft_CRC32((uint8_t *)cfg, sizeof(boot_pk_config) - 4)) { /* Check public key with data info in OTP*/ Sec_Eng_SHA256_Update(&g_sha_ctx, SEC_ENG_SHA_ID0, data, BFLB_BOOT2_ECC_KEYXSIZE + BFLB_BOOT2_ECC_KEYYSIZE); Sec_Eng_SHA256_Finish(&g_sha_ctx, SEC_ENG_SHA_ID0, (uint8_t *)pk_hash); Sec_Eng_SHA256_Init(&g_sha_ctx, SEC_ENG_SHA_ID0, SEC_ENG_SHA256, g_sha_tmp_buf, g_padding); Sec_Eng_SHA_Start(SEC_ENG_SHA_ID0); /* Check pk is valid */ if (own == 1) { if (1 != blsp_boot_parse_is_pkhash_valid(g_boot_img_cfg->cpu_type, (uint8_t *)pk_hash)) { MSG_ERR("PK sha error\r\n"); return BFLB_BOOT2_IMG_PK_HASH_ERROR; } } if (own == 1) { ARCH_MemCpy_Fast(g_boot_img_cfg->eckye_x, cfg->eckye_x, sizeof(cfg->eckye_x)); ARCH_MemCpy_Fast(g_boot_img_cfg->eckey_y, cfg->eckey_y, sizeof(cfg->eckey_y)); } } else { MSG_ERR("PK crc error\r\n"); return BFLB_BOOT2_IMG_PK_CRC_ERROR; } return BFLB_BOOT2_SUCCESS; } /****************************************************************************/ /** * @brief Parse signature * * @param g_boot_img_cfg: Boot image config pointer * @param data: Signature data pointer * @param own: 1 for current CPU, 0 for other(s) * * @return boot_error_code type * *******************************************************************************/ int32_t blsp_boot_parse_signature(boot_image_config *g_boot_img_cfg, uint8_t *data, uint8_t own) { boot_sign_config *cfg = (boot_sign_config *)data; uint32_t crc; if (cfg->sig_len > sizeof(g_boot_img_cfg->signature)) { return BFLB_BOOT2_IMG_SIGNATURE_LEN_ERROR; } /* CRC include sig_len*/ crc = BFLB_Soft_CRC32((uint8_t *)&cfg->sig_len, cfg->sig_len + sizeof(cfg->sig_len)); if (memcmp(&crc, &cfg->signature[cfg->sig_len], 4) == 0) { if (own == 1) { ARCH_MemCpy_Fast(g_boot_img_cfg->signature, cfg->signature, cfg->sig_len); g_boot_img_cfg->sig_len = cfg->sig_len; } else { ARCH_MemCpy_Fast(g_boot_img_cfg->signature2, cfg->signature, cfg->sig_len); g_boot_img_cfg->sig_len2 = cfg->sig_len; } } else { MSG_ERR("SIG crc error\r\n"); return BFLB_BOOT2_IMG_SIGNATURE_CRC_ERROR; } return BFLB_BOOT2_SUCCESS; } /****************************************************************************/ /** * @brief Parse ASE IV * * @param g_boot_img_cfg: Boot image config pointer * @param data: AES IV data pointer * * @return boot_error_code type * *******************************************************************************/ int32_t blsp_boot_parse_aesiv(boot_image_config *g_boot_img_cfg, uint8_t *data) { boot_aes_config *cfg = (boot_aes_config *)data; if (cfg->crc32 == BFLB_Soft_CRC32(cfg->aes_iv, sizeof(cfg->aes_iv))) { memcpy(g_boot_img_cfg->aes_iv, cfg->aes_iv, sizeof(boot_aes_config)); /* Update image hash */ if (!g_boot_img_cfg->hash_ignore) { Sec_Eng_SHA256_Update(&g_sha_ctx, SEC_ENG_SHA_ID0, data, sizeof(boot_aes_config)); } } else { MSG_ERR("AES IV crc error\r\n"); return BFLB_BOOT2_IMG_AES_IV_CRC_ERROR; } return BFLB_BOOT2_SUCCESS; } #if 0 /****************************************************************************//** * @brief Check signature is valid * * @param g_boot_img_cfg: Boot image config pointer * * @return boot_error_code type * *******************************************************************************/ int32_t blsp_boot_parser_check_signature(boot_image_config *g_boot_img_cfg) { int32_t ret = 0; uint64_t startTime = 0; BFLB_ECDSA_Handle_t ecdsaHandle; MSG_DBG("%d,%d\r\n", g_ps_mode, g_efuse_cfg.hbn_check_sign); if(g_ps_mode == BFLB_PSM_HBN && (!g_efuse_cfg.hbn_check_sign)) { return BFLB_BOOT2_SUCCESS; } if(g_boot_img_cfg->sign_type) { MSG_DBG("Check sig1\r\n"); startTime = bflb_platform_get_time_ms(); bflb_ecdsa_init(&ecdsaHandle, ECP_SECP256R1); ecdsaHandle.publicKeyx = (uint32_t *)g_boot_img_cfg->eckye_x; ecdsaHandle.publicKeyy = (uint32_t *)g_boot_img_cfg->eckey_y; bflb_ecdsa_verify(&ecdsaHandle, (uint32_t *)g_boot_img_cfg->img_hash, sizeof(g_boot_img_cfg->img_hash) / 4, (uint32_t *)g_boot_img_cfg->signature, (uint32_t *)&g_boot_img_cfg->signature[32]); //ret=bflb_ecdsa_verify(0,(uint32_t *)g_boot_img_cfg->img_hash,sizeof(g_boot_img_cfg->img_hash), // (uint32_t *)g_boot_img_cfg->eckye_x,(uint32_t *)g_boot_img_cfg->eckey_y, // (uint32_t *)g_boot_img_cfg->signature,(uint32_t *)&g_boot_img_cfg->signature[32]); if(ret != 0) { MSG_ERR("verify failed\n"); return BFLB_BOOT2_IMG_SIGN_ERROR; } MSG_DBG("Time=%d ms\r\n", (unsigned int)(bflb_platform_get_time_ms() - startTime)); } MSG_DBG("Success\r\n"); return BFLB_BOOT2_SUCCESS; } #endif /****************************************************************************/ /** * @brief Check hash is valid * * @param g_boot_img_cfg: Boot image config pointer * * @return boot_error_code type * *******************************************************************************/ int32_t blsp_boot_parser_check_hash(boot_image_config *g_boot_img_cfg) { uint32_t img_hash_cal[BFLB_BOOT2_HASH_SIZE / 4]; if (!g_boot_img_cfg->hash_ignore) { Sec_Eng_SHA256_Finish(&g_sha_ctx, SEC_ENG_SHA_ID0, (uint8_t *)img_hash_cal); if (memcmp(img_hash_cal, g_boot_img_cfg->img_hash, sizeof(g_boot_img_cfg->img_hash)) != 0) { MSG_ERR("Hash error\r\n"); blsp_dump_data(img_hash_cal, BFLB_BOOT2_HASH_SIZE); blsp_dump_data(g_boot_img_cfg->img_hash, BFLB_BOOT2_HASH_SIZE); return BFLB_BOOT2_IMG_HASH_ERROR; } else { MSG_DBG("Success\r\n"); } } return BFLB_BOOT2_SUCCESS; } /*@} end of group BLSP_BOOT_PARSER_Public_Functions */ /*@} end of group BLSP_BOOT_PARSER */ /*@} end of group BL606_BLSP_Boot2 */