233 lines
7.9 KiB
C
233 lines
7.9 KiB
C
/* *
|
|
* Copyright (c) CompanyNameMagicTag 2018-2019. All rights reserved.
|
|
* Description: boot security
|
|
* Author: CompanyName
|
|
* Create: 2018-10-31
|
|
*/
|
|
|
|
#include "upg_secure_boot.h"
|
|
|
|
EXT_PRV td_u32 flash_boot_verify_sign_alg(const sign_alg *alg)
|
|
{
|
|
if ((alg->hash_alg == EXT_HASH_ALG_SHA256) && (alg->sign_alg <= EXT_MODE_PKCS_PSS)) {
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
return EXT_ERR_UPG_SECURE_BOOT_26;
|
|
}
|
|
|
|
EXT_PRV td_u32 flash_boot_verify_bootloader(EXT_CONST bootloader_section_and_len *sec_and_len, const td_u8 *mod_n,
|
|
const td_u8 *exp_e, const td_u8 *signature, td_u8 sign_alg_type)
|
|
{
|
|
td_u32 ret;
|
|
td_u8 hash[SHA_256_LENGTH];
|
|
td_u8 *hash_point = hash;
|
|
(td_void)memset_s(hash, SHA_256_LENGTH, 0, SHA_256_LENGTH);
|
|
|
|
ret = (td_u32)uapi_hash_sha256(sec_and_len->code_section, sec_and_len->section_length, hash);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_24;
|
|
}
|
|
|
|
ret = (td_u32)uapi_rsa_verify(mod_n, exp_e, RSA_2048_LENGTH, (ext_rsa_padding_mode)sign_alg_type,
|
|
hash_point, signature);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_25;
|
|
}
|
|
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
EXT_PRV td_u32 flash_boot_verify_root_pub_key(const root_pub_key *root_pubk)
|
|
{
|
|
td_u32 ret;
|
|
td_u8 hash[SHA_256_LENGTH];
|
|
td_u8 efuse_hash[SHA_256_LENGTH];
|
|
td_u8 *efuse_hash_point = efuse_hash;
|
|
|
|
(td_void)memset_s(hash, SHA_256_LENGTH, 0, SHA_256_LENGTH);
|
|
ret = (td_u32)uapi_hash_sha256((td_u8 *)root_pubk, sizeof(root_pub_key), hash);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_11;
|
|
}
|
|
|
|
(td_void)memset_s(efuse_hash, SHA_256_LENGTH, 0, SHA_256_LENGTH);
|
|
ret = (td_u32)uapi_efuse_read(EXT_EFUSE_ROOT_PUBKEY_RW_ID, efuse_hash_point);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_12;
|
|
}
|
|
|
|
if (memcmp(hash, efuse_hash, SHA_256_LENGTH) != 0) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_13;
|
|
}
|
|
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
EXT_PRV td_u32 flash_boot_verify_sub_key(EXT_CONST root_pub_key *root_pubk, EXT_CONST sub_key_info *sub_key)
|
|
{
|
|
td_u32 ret;
|
|
td_u32 category = (td_u32)-1;
|
|
td_u8 hash[SHA_256_LENGTH];
|
|
td_u8 *hash_point = hash;
|
|
ret = (td_u32)uapi_efuse_read(EXT_EFUSE_SUBKEY_CAT_RW_ID, (td_u8 *)&category);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
/* read 'category' failed. */
|
|
return EXT_ERR_UPG_SECURE_BOOT_14;
|
|
}
|
|
if ((sub_key->category != category) || (sub_key->length != RSA_2048_LENGTH) ||
|
|
(sub_key->sign_length != RSA_4096_LENGTH)) {
|
|
/* 'category' not match. */
|
|
return EXT_ERR_UPG_SECURE_BOOT_15;
|
|
}
|
|
ret = flash_boot_verify_sign_alg(&sub_key->sign_alg);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
if (sub_key->key_id > 31) { /* if more than 31, 'key_id' is invalid. */
|
|
return EXT_ERR_UPG_SECURE_BOOT_16;
|
|
}
|
|
(td_void)memset_s(hash, SHA_256_LENGTH, 0, SHA_256_LENGTH);
|
|
ret = (td_u32)uapi_hash_sha256((td_u8 *)sub_key, sizeof(sub_key_info) - RSA_4096_LENGTH, hash);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_17;
|
|
}
|
|
ret = (td_u32)uapi_rsa_verify(root_pubk->mod_n, root_pubk->exp_e, RSA_4096_LENGTH,
|
|
(ext_rsa_padding_mode)sub_key->sign_alg.sign_alg, hash_point, sub_key->sign);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_18;
|
|
}
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
EXT_PRV td_u32 flash_boot_verify_maintenance_key(const sub_key_info *sub_key, const maintenance_key *m_key)
|
|
{
|
|
td_u8 die_id[DIE_ID_LENGTH];
|
|
td_u8 hash[SHA_256_LENGTH];
|
|
td_u8 *hash_point = hash;
|
|
td_u8 *die_id_point = die_id;
|
|
(td_void)memset_s(die_id, DIE_ID_LENGTH, 0, DIE_ID_LENGTH);
|
|
if ((td_u32)uapi_efuse_read(EXT_EFUSE_DIE_RO_ID, die_id_point) != EXT_ERR_SUCCESS) {
|
|
/* read 'DIE ID' failed. */
|
|
return EXT_ERR_UPG_SECURE_BOOT_19;
|
|
}
|
|
if (memcmp(m_key->die_id, die_id, DIE_ID_LENGTH) != 0) {
|
|
/* 'DIE id' not match. */
|
|
return EXT_ERR_UPG_SECURE_BOOT_20;
|
|
}
|
|
if ((m_key->die_id_length != DIE_ID_LENGTH) || (m_key->key_length != RSA_2048_LENGTH * 2) /* 2*256 */
|
|
|| (m_key->sign_length != RSA_2048_LENGTH)) {
|
|
/* 'length' error. */
|
|
return EXT_ERR_UPG_SECURE_BOOT_21;
|
|
}
|
|
if (flash_boot_verify_sign_alg(&m_key->sign_alg) != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_26;
|
|
}
|
|
(td_void)memset_s(hash, SHA_256_LENGTH, 0, SHA_256_LENGTH);
|
|
if ((td_u32)uapi_hash_sha256((td_u8 *)m_key, sizeof(maintenance_key) - RSA_2048_LENGTH, hash) != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_22;
|
|
}
|
|
if ((td_u32)uapi_rsa_verify(sub_key->mod_n, sub_key->exp_e, RSA_2048_LENGTH,
|
|
(ext_rsa_padding_mode)m_key->sign_alg.sign_alg, hash_point, m_key->sign) != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_23;
|
|
}
|
|
return EXT_ERR_SUCCESS;
|
|
}
|
|
|
|
EXT_PRV td_u32 flash_boot_verify_proc(td_u8 *data, const boot_header *header)
|
|
{
|
|
td_u32 ret;
|
|
td_u8 *mod_n = TD_NULL;
|
|
td_u8 *exp_e = TD_NULL;
|
|
root_pub_key *root_pubk = TD_NULL;
|
|
sub_key_info *sub_key = TD_NULL;
|
|
|
|
root_pubk = (root_pub_key *)(data + header->root_pubk_offset);
|
|
|
|
if (header->root_pubk_length != sizeof(root_pub_key)) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_3;
|
|
}
|
|
|
|
ret = flash_boot_verify_root_pub_key(root_pubk);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
sub_key = (sub_key_info *)(data + header->sub_key_offset);
|
|
if (header->sub_key_length != sizeof(sub_key_info)) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_5;
|
|
}
|
|
|
|
ret = flash_boot_verify_sub_key(root_pubk, sub_key);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_6;
|
|
}
|
|
|
|
mod_n = sub_key->mod_n;
|
|
exp_e = sub_key->exp_e;
|
|
|
|
if (header->maintenance_key_offset != 0) {
|
|
maintenance_key *m_key = (maintenance_key *)(data + header->maintenance_key_offset);
|
|
ret = flash_boot_verify_maintenance_key(sub_key, m_key);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_7;
|
|
}
|
|
|
|
mod_n = m_key->mod_n;
|
|
exp_e = m_key->exp_e;
|
|
}
|
|
|
|
bootloader_section_and_len sec_and_len = { data + header->code_section_offset, header->code_section_length };
|
|
ret =
|
|
flash_boot_verify_bootloader(&sec_and_len, mod_n, exp_e, data + header->sign_offset, header->sign_alg.sign_alg);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_8;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
td_u32 flash_boot_security_boot_verify(td_pvoid flash_boot_addr) /* absolute address */
|
|
{
|
|
td_u32 ret;
|
|
td_u8 *data = (td_u8 *)flash_boot_addr;
|
|
boot_header *header = flash_boot_addr;
|
|
boot_code_head *code_head = TD_NULL;
|
|
td_u8 secure_flag = 0;
|
|
|
|
boot_msg1("verify1=", (uintptr_t)flash_boot_addr);
|
|
|
|
if ((header->preamble != FLASH_BOOT_PREAMBLE) || (header->head_magic != FLASH_BOOT_HEAD_MAGIC)) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_1;
|
|
}
|
|
|
|
ret = (td_u32)uapi_efuse_read(EXT_EFUSE_SECURE_BOOT_RW_ID, &secure_flag);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_2;
|
|
}
|
|
|
|
code_head = (boot_code_head *)(data + header->code_section_offset);
|
|
|
|
if (secure_flag == 1) {
|
|
td_u32 nv_counter = 0;
|
|
|
|
ret = flash_boot_verify_proc(data, header);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
ret = (td_u32)uapi_efuse_read(EXT_EFUSE_INSECURE_VERSION_RW_ID, (td_u8 *)&nv_counter);
|
|
if (ret != EXT_ERR_SUCCESS) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_9;
|
|
}
|
|
|
|
boot_msg0("verify11");
|
|
|
|
/* DEVELOPE: highest bit equal to 1; OUTSIDE: highest bit equal to 1; efuse highest bit equal to 1; */
|
|
if (((~nv_counter) & code_head->version) != code_head->version) {
|
|
return EXT_ERR_UPG_SECURE_BOOT_10;
|
|
}
|
|
}
|
|
return EXT_ERR_SUCCESS;
|
|
}
|