/* * Copyright (c) CompanyNameMagicTag 2018-2020. All rights reserved. * Description:BT BOOTLOADER UTILS * Author: * Create: 2018-10-15 */ #include "sha256.h" #ifdef SECURITY_ROM #include "memory_config.h" #else #include "flash.h" #include "application_version.h" #endif #include "memory_core.h" #ifdef EFUSE_INTERFACE_REPLACE #include "efuse.h" #else #include "otp.h" #endif #include "build_version.h" #include "securec.h" #include "otp_map.h" #include "panic.h" #include "uart.h" #include "arch_barrier.h" #include "bootloader_utils.h" #if (!(defined BUILD_APPLICATION_ROM)) #define SECURE_BOOT_CORE_STR_SECURE "Boot: Signed\r\n" #define SECURE_BOOT_CORE_STR_INSECURE "Boot: Unsigned\r\n" #define CRLF_STR "\r\n" #endif #define SSB_RAM_START APP_ITCM_ORIGIN #define CRC_MASK 0xff000000 #define CRC_RIGHT_SHIFT_BIT 24 #define SSB_LENGTH_MASK 0xffffff #ifndef SHA256_SIGNATURE_LEN #define SHA256_SIGNATURE_LEN 32 #endif #ifndef SHA_BLOCK_SIZE #define SHA_BLOCK_SIZE 256 #endif #define SSB_IAMGE_MIN_LEN FLASH_PAGE_SIZE /** Vector active mask for the ICSR register */ #if CHIP_SOCMN1 || CHIP_BS25 || CHIP_WS63 || CHIP_BS21 || CHIP_WS53 #define ICSR_VECTACTIVE_MASK 0x62 #elif (CHIP_BRANDY == 1) #define ICSR_VECTACTIVE_MASK 0x21 #else #error "ICSR_VECTACTIVE_MASK not defined" #endif /** Vector key for the AIRCR register */ #define AIRCR_VECTKEY 0x5FA #define SSB_SHA256_CRC_START_BYTE_LEN 1 /* Sets the cpu in a known state before continuing */ void bootloader_utils_cpu_init(void) { #if (ARCH == CM3) || (ARCH == CM7) // Disable SysTick interrupt SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // Reset if it is in interrupt context if ((SCB->ICSR & ICSR_VECTACTIVE_MASK) != 0) { dsb(); SCB->AIRCR = ((AIRCR_VECTKEY << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk); dsb(); } // Disable the maskable interrupts and enable global interrupts NVIC->ICER[0] = 0xffffffff; /* enable global interrupts */ __set_PRIMASK(0); #endif } void bootloader_utils_print_boot_message(uart_bus_t uart_bus) { #if (!(defined BUILD_APPLICATION_ROM) && !(defined UNIT_TEST)) if (uart_bus != UART_BUS_NONE) { uapi_uart_write(uart_bus, (uint8_t *)CRLF_STR, (uint16_t)strlen(CRLF_STR), 0); uapi_uart_write(uart_bus, (uint8_t *)SECURE_BOOT_CORE_STR_INSECURE, (uint16_t)strlen(SECURE_BOOT_CORE_STR_INSECURE), 0); } #else UNUSED(uart_bus); #endif } void bootloader_utils_init_modules(void) { } bool bootloader_utils_core_has_code(core_images_e cimage) { memory_map *mem_map; mem_map = memory_get_cached_core_map(cimage); if (mem_map == NULL) { panic(PANIC_CODELOADER, __LINE__); return false; //lint !e527 unreachable code } return *((uint32_t *)(uintptr_t)(mem_map->code_addr)) != 0xFFFFFFFF; } uint32_t bootloader_utils_get_rom_version(void) { build_version_info_rom *version_info; uint32_t version_location = ROM_START + VERSION_INFORMATION_OFFSET; version_info = (build_version_info_rom *)((uintptr_t)version_location); return version_info->version; } #if defined(BUILD_APPLICATION_SSB) uint32_t bootloader_utils_get_ssb_version(void) { build_version_info *version_info = NULL; uint32_t version_location = APP_ITCM_ORIGIN + VERSION_INFORMATION_OFFSET; version_info = (build_version_info *)((uintptr_t)version_location); return version_info->version; } #endif uint32_t bootloader_utils_get_flash_version(void) { build_version_info *version_info = NULL; uint32_t version_location; memory_map *map = memory_get_cached_core_map(CORE_IMAGES_BT); if (map == NULL) { return 0; } version_location = map->code_addr + VERSION_INFORMATION_OFFSET; version_info = (build_version_info *)((uintptr_t)version_location); return version_info->version; } bool bootloader_utils_is_code_in_flash(void) { #ifndef SECURITY_ROM build_version_info *version_info = (build_version_info *)VERSION_INFORMATION_OFFSET; return ((version_info->version & APPLICATION_CORE_FLASH_BUILD) == APPLICATION_CORE_FLASH_BUILD); #else return true; #endif } bool bootloader_utils_ssb_get_length(uint32_t *length) { uint8_t ssb_length_crc; uint8_t calc_crc = 0; bool valid_ssb_length = false; uint32_t ssb_length = 0; *length = 0; #if CORE == MASTER_BY_ALL uint32_t ssb_len_otp_addr = OTP_SSB_CODE_SIZE_START; #elif CORE == SECURITY uint32_t ssb_len_otp_addr = OTP_SEC_SSB_CODE_SIZE_START; #endif // Check that the SSB length CRC matches SSB length #ifdef EFUSE_INTERFACE_REPLACE if (uapi_efuse_read_buffer((uint8_t *)&ssb_length, ssb_len_otp_addr, sizeof(uint32_t)) == ERRCODE_SUCC) { ssb_length_crc = (ssb_length & CRC_MASK) >> CRC_RIGHT_SHIFT_BIT; // mask off CRC byte, top 8 bits, and shift ssb_length &= SSB_LENGTH_MASK; // mask out CRC byte if (uapi_efuse_calc_crc((uint8_t *)&ssb_length, OTP_SSB_CODE_SIZE_LENGTH, &calc_crc) == ERRCODE_SUCC) { if ((uint8_t)ssb_length_crc == calc_crc) { valid_ssb_length = true; *length = ssb_length; } } } #else if (otp_read_buffer((uint8_t *)&ssb_length, ssb_len_otp_addr, sizeof(uint32_t)) == OTP_RET_SUCC) { ssb_length_crc = (ssb_length & CRC_MASK) >> CRC_RIGHT_SHIFT_BIT; // mask off CRC byte, top 8 bits, and shift ssb_length &= SSB_LENGTH_MASK; // mask out CRC byte if (otp_calc_crc((uint8_t *)&ssb_length, OTP_SSB_CODE_SIZE_LENGTH, &calc_crc) == OTP_RET_SUCC) { if ((uint8_t)ssb_length_crc == calc_crc) { valid_ssb_length = true; *length = ssb_length; } } } #endif return valid_ssb_length; } bool bootloader_utils_ssb_get_sha(uint8_t *sha, const uint8_t max_sha_len) { bool valid_sha = false; uint8_t sha_crc = 0; uint8_t calc_crc = 0; UNUSED(max_sha_len); #if CORE == MASTER_BY_ALL uint32_t ssb_sha256_start = OTP_SSB_SHA256_START; uint32_t ssb_sha256_crc_start = OTP_SSB_SHA256_CRC; #elif CORE == SECURITY uint32_t ssb_sha256_start = OTP_SEC_SSB_SHA256_START; uint32_t ssb_sha256_crc_start = OTP_SEC_SSB_SHA256_CRC; #endif // Get SHA & SHA CRC and compare #ifdef EFUSE_INTERFACE_REPLACE if (uapi_efuse_read_buffer(sha, ssb_sha256_start, OTP_SSB_SHA256_LENGTH) == ERRCODE_SUCC) { if (uapi_efuse_read_buffer(&sha_crc, ssb_sha256_crc_start, SSB_SHA256_CRC_START_BYTE_LEN) == ERRCODE_SUCC) { if (uapi_efuse_calc_crc(sha, OTP_SSB_SHA256_LENGTH, &calc_crc) != ERRCODE_SUCC) { return valid_sha; } if (calc_crc == sha_crc) { valid_sha = true; } } } #else if (otp_read_buffer(sha, ssb_sha256_start, OTP_SSB_SHA256_LENGTH) == OTP_RET_SUCC) { if (otp_read_byte(&sha_crc, ssb_sha256_crc_start) == OTP_RET_SUCC) { if (otp_calc_crc(sha, OTP_SSB_SHA256_LENGTH, &calc_crc) != OTP_RET_SUCC) { return valid_sha; } if (calc_crc == sha_crc) { valid_sha = true; } } } #endif return valid_sha; } static bool iflash_core_check_sha256_region(const uint8_t *stored_sha256, uint32_t buffer_len, uint32_t start, uint32_t length) { errcode_t ret; bool valid_sha = false; uint8_t result[SHA256_HASH_SIZE] = { 0 }; ret = uapi_drv_cipher_sha256((uint8_t*)(uintptr_t)start, length, result, sizeof(result)); if (ret != ERRCODE_SUCC) { return false; } if (memcmp(result, stored_sha256, SHA256_HASH_SIZE) == 0) { valid_sha = true; } UNUSED(buffer_len); return valid_sha; } /* * 1. Check that the SSB length CRC matches SSB length * 2. Check that the SHA CRC matches the SHA. Not set will always fail. * 3. Then check that the SHA matches the image. */ bool bootloader_utils_ssb_sha256_validate(void) { uint32_t ssb_length; uint8_t stored_sha256[OTP_SSB_SHA256_LENGTH]; bool ssb_valid = false; bool ssb_valid_length; ssb_valid_length = bootloader_utils_ssb_get_length(&ssb_length); if (!ssb_valid_length) { return false; } #ifndef SECURITY_ROM if (ssb_length > SSB_FLASH_REGION_LENGTH) { return false; } #else if (ssb_length > SEC_SSB_FLASH_REGION_LENGTH) { return false; } #endif if (ssb_length < SSB_IAMGE_MIN_LEN) { return false; } // get sha and if valid, check image if (bootloader_utils_ssb_get_sha(stored_sha256, sizeof(stored_sha256))) { // check ram code #ifndef SECURITY_ROM if (iflash_core_check_sha256_region(stored_sha256, sizeof(stored_sha256), SSB_RAM_START, ssb_length)) { // the ssb image content of the max length was read before, so here we need to clear unsafe redundant info memset_s((uint8_t *)(uintptr_t)(SSB_RAM_START + ssb_length), (uint32_t)(SSB_FLASH_REGION_LENGTH - ssb_length), 0, (uint32_t)(SSB_FLASH_REGION_LENGTH - ssb_length)); ssb_valid = true; } #else errcode_t ret; uint8_t sha256[SHA256_HASH_SIZE] = { 0 }; ret = uapi_drv_cipher_sha256((uint8_t*)(uintptr_t)SEC_RAM_ORIGIN, ssb_length, sha256, sizeof(sha256)); if (ret != ERRCODE_SUCC) { return false; } if (memcmp(sha256, stored_sha256, SHA256_HASH_SIZE) == 0) { PRINT("SSB sha256 check success!" NEWLINE); // the ssb image content of the max length was read before, so here we need to clear unsafe redundant info memset_s((uint8_t *)(uintptr_t)(SEC_RAM_ORIGIN + ssb_length), (uint32_t)(SEC_SSB_FLASH_REGION_LENGTH - ssb_length), 0, (uint32_t)(SEC_SSB_FLASH_REGION_LENGTH - ssb_length)); ssb_valid = true; } #endif } return ssb_valid; }