179 lines
5.4 KiB
C
179 lines
5.4 KiB
C
|
|
/*
|
||
|
|
* Copyright (c) CompanyNameMagicTag 2018-2019. All rights reserved.
|
||
|
|
* Description: Upgrade base funciton - secure check.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "upg_base_secure_check.h"
|
||
|
|
#include "upg_base_tool.h"
|
||
|
|
|
||
|
|
#include <soc_mdm_cipher.h>
|
||
|
|
#include <soc_mdm_flash.h>
|
||
|
|
#include <soc_mdm_mem.h>
|
||
|
|
#include <soc_stdlib.h>
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
extern "C" {
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static inline td_void rsa_gen_exp_e(td_u8 *key_e, td_u32 key_len)
|
||
|
|
{
|
||
|
|
(td_void)memset_s((key_e), (key_len), 0x0, (key_len));
|
||
|
|
(key_e)[(key_len) - 1] = 0x01;
|
||
|
|
(key_e)[(key_len) - 3] = 0x01; // last 3 index
|
||
|
|
}
|
||
|
|
|
||
|
|
#define upg_base_free(p) \
|
||
|
|
if ((p) != TD_NULL) { \
|
||
|
|
uapi_free(EXT_MOD_ID_DRV_UPG, (p)); \
|
||
|
|
(p) = TD_NULL; \
|
||
|
|
}
|
||
|
|
|
||
|
|
EXT_PRV td_bool upg_secure_is_secure_efuse(td_void)
|
||
|
|
{
|
||
|
|
td_u8 data = 0;
|
||
|
|
td_u32 ret;
|
||
|
|
|
||
|
|
ret = uapi_efuse_read(EXT_EFUSE_SECURE_BOOT_RW_ID, &data);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
return TD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (data & 0x1) {
|
||
|
|
return TD_TRUE;
|
||
|
|
} else {
|
||
|
|
return TD_FALSE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
EXT_PRV td_u32 upg_secure_get_boot_key(td_u8 *key_n, td_u32 key_len)
|
||
|
|
{
|
||
|
|
td_u32 boot_key_addr = *(volatile unsigned int *)(DW21_SYSCTRL_SC_GEN_REG2_REG);
|
||
|
|
|
||
|
|
if (boot_key_addr == 0) {
|
||
|
|
return EXT_ERR_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return uapi_flash_read(boot_key_addr, key_len, key_n);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXT_PRV td_u32 upg_check_secure_pubkey(EXT_CONST ext_upg_secure_info *secure_info,
|
||
|
|
td_u8 *key_n, td_u8 *key_e, td_u32 key_len)
|
||
|
|
{
|
||
|
|
upg_rsa_verify_param param;
|
||
|
|
|
||
|
|
memset_s(¶m, sizeof(param), 0, sizeof(param));
|
||
|
|
param.flash_addr[0] = (uintptr_t)secure_info->key_n_2;
|
||
|
|
param.total_size[0] = (uintptr_t)key_len;
|
||
|
|
param.buffer_count = 1; /* 1 segment */
|
||
|
|
param.key_n = key_n;
|
||
|
|
param.key_e = key_e;
|
||
|
|
param.key_len = key_len;
|
||
|
|
param.sign = (td_u8 *)secure_info->signature_1;
|
||
|
|
param.pad_mode = (ext_rsa_padding_mode)secure_info->sign_alg;
|
||
|
|
return uapi_rsa_verify_flash_content(¶m);
|
||
|
|
}
|
||
|
|
|
||
|
|
EXT_PRV td_u32 upg_check_secure_file_data(td_u32 flash_addr, EXT_CONST ext_21_upg_head *upg_head,
|
||
|
|
ext_upg_secure_info *secure_info, td_u8 *key_e, td_u32 key_len)
|
||
|
|
{
|
||
|
|
upg_rsa_verify_param param;
|
||
|
|
|
||
|
|
memset_s(¶m, sizeof(param), 0, sizeof(param));
|
||
|
|
|
||
|
|
/* (Checksum, security header) partial verification */
|
||
|
|
param.flash_addr[0] = flash_addr + EXT_UPG_HEAD_CHECK_SUM_START_OFFSET;
|
||
|
|
param.total_size[0] = (uintptr_t)(upg_head->secure_info_offset - EXT_UPG_HEAD_CHECK_SUM_START_OFFSET);
|
||
|
|
param.flash_flag[0] = TD_TRUE;
|
||
|
|
|
||
|
|
/* (Security header, file tail) Partial verification */
|
||
|
|
param.flash_addr[1] = flash_addr + upg_head->secure_info_offset + upg_head->secure_info_size;
|
||
|
|
param.total_size[1] = upg_head->file_len - (upg_head->secure_info_offset + upg_head->secure_info_size);
|
||
|
|
param.flash_flag[1] = TD_TRUE;
|
||
|
|
|
||
|
|
param.buffer_count = 2; /* 2 segments */
|
||
|
|
param.key_n = secure_info->key_n_2;
|
||
|
|
param.key_e = key_e;
|
||
|
|
param.key_len = key_len;
|
||
|
|
param.sign = secure_info->signature_2;
|
||
|
|
param.pad_mode = (ext_rsa_padding_mode)secure_info->sign_alg;
|
||
|
|
|
||
|
|
return uapi_rsa_verify_flash_content(¶m);
|
||
|
|
}
|
||
|
|
|
||
|
|
td_u32 upg_check_secure_head(td_u32 flash_addr, EXT_CONST ext_21_upg_head *upg_head)
|
||
|
|
{
|
||
|
|
td_u32 ret;
|
||
|
|
ext_upg_secure_info *secure_info = TD_NULL;
|
||
|
|
|
||
|
|
td_u8 *key_n = TD_NULL;
|
||
|
|
td_u8 *key_e = TD_NULL;
|
||
|
|
td_u32 key_len = EXT_RSA_2048_LEN;
|
||
|
|
|
||
|
|
/* If the EFUSE is not verified, a success message is returned. */
|
||
|
|
if (upg_secure_is_secure_efuse() == TD_FALSE) {
|
||
|
|
return EXT_ERR_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* No security header return fail */
|
||
|
|
if (upg_head->secure_info_offset == 0 || upg_head->secure_info_size == 0) {
|
||
|
|
return EXT_ERR_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Memory space required for security verification */
|
||
|
|
key_n = uapi_malloc(EXT_MOD_ID_DRV_UPG, key_len);
|
||
|
|
key_e = uapi_malloc(EXT_MOD_ID_DRV_UPG, key_len);
|
||
|
|
secure_info = uapi_malloc(EXT_MOD_ID_DRV_UPG, sizeof(ext_upg_secure_info));
|
||
|
|
if ((key_n == TD_NULL) || (key_e == TD_NULL) || (secure_info == TD_NULL)) {
|
||
|
|
ret = EXT_ERR_FAILURE;
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = upg_secure_get_boot_key(key_n, key_len);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = uapi_rsa_init((td_u8 *)TD_NULL, (td_u16)key_len);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Generate p_key_e */
|
||
|
|
rsa_gen_exp_e(key_e, key_len);
|
||
|
|
|
||
|
|
/* Read the security header. */
|
||
|
|
ret = uapi_flash_read(flash_addr + upg_head->secure_info_offset, sizeof(ext_upg_secure_info), (td_u8 *)secure_info);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Use the public key in the boot code to verify the signature of the public key in the security header. */
|
||
|
|
ret = upg_check_secure_pubkey(secure_info, key_n, key_e, key_len);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* The security header splits the file into two parts and needs to be checked by segment.
|
||
|
|
* Use the public key in the security header to verify the upgrade file.
|
||
|
|
* The verification content contains all contents
|
||
|
|
* except the security header and file hash.
|
||
|
|
*/
|
||
|
|
ret = upg_check_secure_file_data(flash_addr, upg_head, secure_info, key_e, key_len);
|
||
|
|
if (ret != EXT_ERR_SUCCESS) {
|
||
|
|
goto END;
|
||
|
|
}
|
||
|
|
|
||
|
|
END:
|
||
|
|
|
||
|
|
upg_base_free(secure_info);
|
||
|
|
upg_base_free(key_e);
|
||
|
|
upg_base_free(key_n);
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
}
|
||
|
|
#endif
|