mcu_hi3321_watch/middleware/utils/update/common/upg_verify.c
2025-05-26 20:15:20 +08:00

741 lines
26 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) @CompanyNameMagicTag 2021-2021. All rights reserved.
* Description: UPG verification functions source file
*/
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <securec.h>
#include "common_def.h"
#include "upg_definitions.h"
#include "upg_otp_reg.h"
#include "errcode.h"
#include "upg_config.h"
#include "upg_debug.h"
#include "upg_common.h"
#include "upg_common_porting.h"
#include "upg_porting.h"
#include "upg_alloc.h"
#if (UPG_CFG_VERIFICATION_MODE_RSA == YES)
#include "pke.h"
#include "cipher_api.h"
#elif ((UPG_CFG_VERIFICATION_MODE_ECC == YES) || (UPG_CFG_VERIFICATION_MODE_SM2_SM3 == YES))
#include "cipher.h"
#endif
#if (UPG_CFG_MEMORY_DCACHE_ENABLED == YES)
#include "soc_osal.h"
#endif
#include "upg_verify.h"
#if (UPG_CFG_VERIFICATION_SUPPORT == YES)
#define ECC_KEY_OFFSET 32
#define UPG_SM2_ID "\x31\x32\x33\x34\x35\x36\x37\x38\x31\x32\x33\x34\x35\x36\x37\x38"
#define UPG_SM2_ID_LEN 0x10
#define RSA_N_KEY_LEN 512
#define RSA_E_KEY_LEN 512
#define RSA_SIG_LEN 512
#define ECC_X_KEY_LEN 32
#define ECC_Y_KEY_LEN 32
#define ECC_KEY_LEN 32
#define ECC_R_SIG_LEN 32
#define ECC_S_SIG_LEN 32
#define ECC_SIG_LEN 32
#if (defined(CONFIG_APPS_CORE) || defined(CONFIG_MAIN_CORE))
#define UPG_VERIFY_CIPHER_BUF_ATTR UAPI_DRV_CIPHER_BUF_NONSECURE
#else
#define UPG_VERIFY_CIPHER_BUF_ATTR UAPI_DRV_CIPHER_BUF_SECURE
#endif /* CONFIG_APPS_CORE */
STATIC uapi_upg_user_defined_check g_user_defined_check_func = NULL;
STATIC uintptr_t g_user_defined_param = 0;
errcode_t verify_hash_cmp(const uint8_t *hash, const uint8_t *hash_res, uint32_t hash_len)
{
if (memcmp(hash, hash_res, hash_len) != 0) {
upg_msg0("upg_verify_hash: memcmp hash fail.");
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
STATIC errcode_t hash_operation(uapi_drv_cipher_buf_attr_t *src_buf, uint32_t src_len, uint8_t *data_sha,
uapi_drv_cipher_hash_attr_t *hash_attr)
{
errcode_t ret;
uint32_t handle;
uint32_t out_length = SHA_256_LENGTH;
ret = uapi_drv_cipher_hash_start(&handle, hash_attr);
if (ret != ERRCODE_SUCC) {
upg_msg1("uapi_drv_cipher_hash_start fail ret = ", ret);
return ret;
}
#if (UPG_CFG_MEMORY_DCACHE_ENABLED == YES)
osal_dcache_region_wb(NULL, (unsigned long)(uintptr_t)src_buf->address, src_len);
#endif
ret = uapi_drv_cipher_hash_update(handle, src_buf, src_len);
if (ret != ERRCODE_SUCC) {
upg_msg1("uapi_drv_cipher_hash_update fail ret = ", ret);
return ret;
}
return uapi_drv_cipher_hash_finish(handle, data_sha, &out_length);
}
STATIC errcode_t upg_verify_hash(uintptr_t verify_data, uint32_t verify_size, const uint8_t *hash, uint32_t hash_len)
{
uint8_t hash_res[SHA_256_LENGTH] = {0};
uapi_drv_cipher_hash_attr_t hash_attr;
uapi_drv_cipher_buf_attr_t src_buf;
hash_attr.hash_type = UAPI_DRV_CIPHER_HASH_TYPE_SHA256;
hash_attr.keyslot_handle = 0;
src_buf.phys_addr = verify_data;
src_buf.buf_sec = UAPI_DRV_CIPHER_BUF_SECURE;
uint8_t *data_sha = &(hash_res[0]);
errcode_t ret_val = hash_operation(&src_buf, verify_size, data_sha, &hash_attr);
if (ret_val != ERRCODE_SUCC) {
upg_msg1("upg_verify_hash: hash_operation fail ret_val = ", ret_val);
return ERRCODE_FAIL;
}
ret_val = verify_hash_cmp(hash, hash_res, hash_len);
if (ret_val != ERRCODE_SUCC) {
upg_msg0("upg_verify_hash: memcmp hash fail.");
return ERRCODE_FAIL;
}
upg_msg0("upg_verify_hash OK");
return ERRCODE_SUCC;
}
STATIC errcode_t calc_hash_by_type(uint32_t src_addr, uint32_t src_len, uint8_t *data_sha,
uint32_t data_sha_len, uapi_drv_cipher_hash_type_t hash_type)
{
uapi_drv_cipher_hash_attr_t hash_attr;
uapi_drv_cipher_buf_attr_t src_buf;
if (data_sha_len != SHA_256_LENGTH) {
return ERRCODE_FAIL;
}
hash_attr.hash_type = hash_type;
hash_attr.keyslot_handle = 0;
src_buf.phys_addr = (uintptr_t)src_addr;
src_buf.buf_sec = UAPI_DRV_CIPHER_BUF_SECURE;
return hash_operation(&src_buf, src_len, data_sha, &hash_attr);
}
errcode_t calc_hash(uint32_t src_addr, uint32_t src_len, uint8_t *data_sha,
uint32_t data_sha_len)
{
return calc_hash_by_type(src_addr, src_len, data_sha, data_sha_len, UAPI_DRV_CIPHER_HASH_TYPE_SHA256);
}
#if (UPG_CFG_VERIFICATION_MODE_SM2_SM3 == YES) // SM2&SM3
STATIC errcode_t verify_signature(const uapi_drv_cipher_pke_data_t *data, uapi_drv_cipher_pke_ecc_point_t *pub_key,
const uapi_drv_cipher_pke_ecc_sig_t *sign)
{
uint8_t data_hash[SHA_256_LENGTH];
uapi_drv_cipher_pke_data_t hash;
uapi_drv_cipher_pke_data_t sm2_id;
uapi_drv_cipher_pke_msg_t pke_msg;
uapi_drv_cipher_pke_ecc_curve_type_t curve_type = UAPI_DRV_CIPHER_PKE_ECC_TYPE_SM2;
int32_t ret = ERRCODE_FAIL;
/* Initialise hash arrays and structs */
ret = memset_s(data_hash, SHA_256_LENGTH, 0x5a, SHA_256_LENGTH);
hash.data = data_hash;
hash.length = SHA_256_LENGTH;
#if (UPG_CFG_VERIFICATION_MODE_SM3_ONLY == YES)
uapi_drv_cipher_hash_type_t hash_type = UAPI_DRV_CIPHER_HASH_TYPE_SM3;
ret = calc_hash_by_type((uintptr_t)data->data, data->length, data_hash, SHA_256_LENGTH, hash_type);
if (ret != ERRCODE_SUCC) {
upg_msg1("sm3 calc_hash fail ret = ", ret);
return ret;
}
return verify_hash_cmp((uint8_t *)sign, data_hash, SHA_256_LENGTH);
#endif
sm2_id.data = (uint8_t *)UPG_SM2_ID;
sm2_id.length = UPG_SM2_ID_LEN;
pke_msg.data = data->data;
pke_msg.length = data->length;
pke_msg.buf_sec = UAPI_DRV_CIPHER_PKE_BUF_SECURE;
ret = uapi_drv_cipher_pke_sm2_dsa_hash(&sm2_id, pub_key, &pke_msg, &hash);
if (ret != ERRCODE_SUCC) {
upg_msg1("calc_hash fail ret = ", ret);
return ret;
}
return uapi_drv_cipher_pke_ecdsa_verify(curve_type, pub_key, &hash, sign);
}
#elif (UPG_CFG_VERIFICATION_MODE_ECC == YES) // ECC
STATIC errcode_t verify_signature(const uapi_drv_cipher_pke_data_t *data, uapi_drv_cipher_pke_ecc_point_t *pub_key,
const uapi_drv_cipher_pke_ecc_sig_t *sign)
{
uint8_t data_hash[SHA_256_LENGTH];
uapi_drv_cipher_pke_data_t hash;
uapi_drv_cipher_pke_ecc_curve_type_t curve_type = UAPI_DRV_CIPHER_PKE_ECC_TYPE_RFC5639_P256;
uapi_drv_cipher_hash_type_t hash_type = UAPI_DRV_CIPHER_HASH_TYPE_SHA256;
int32_t ret = ERRCODE_FAIL;
/* Initialise hash arrays and structs */
memset_s(data_hash, SHA_256_LENGTH, 0x5a, SHA_256_LENGTH);
hash.data = data_hash;
hash.length = SHA_256_LENGTH;
ret = calc_hash_by_type((uintptr_t)data->data, data->length, data_hash, SHA_256_LENGTH, hash_type);
#if (UPG_CFG_VERIFICATION_MODE_SHA256_ONLY == YES)
if (ret != ERRCODE_SUCC) {
upg_msg1("sha 256 calc_hash fail ret = ", ret);
return ret;
}
return verify_hash_cmp((uint8_t *)sign, data_hash, SHA_256_LENGTH);
#endif
if (ret != ERRCODE_SUCC) {
upg_msg1("calc_hash fail ret = ", ret);
return ret;
}
return uapi_drv_cipher_pke_ecdsa_verify(curve_type, pub_key, &hash, sign);
}
#elif (UPG_CFG_VERIFICATION_MODE_RSA == YES) // RSA
STATIC errcode_t verify_signature(const uapi_drv_cipher_pke_data_t *data, uapi_drv_cipher_pke_rsa_pub_key_t *pub_key,
const uapi_drv_cipher_pke_data_t *sign)
{
uint8_t data_hash[SHA_256_LENGTH];
uapi_drv_cipher_pke_data_t hash;
uapi_drv_cipher_pke_rsa_pub_key_t pub_key_tmp = {0};
uapi_drv_cipher_pke_rsa_scheme_t scheme = UAPI_DRV_CIPHER_PKE_RSA_SCHEME_PKCS1_V21;
errcode_t ret = ERRCODE_SUCC;
/* Initialise hash arrays and structs */
(void)memset_s(data_hash, sizeof(data_hash), 0x5a, SHA_256_LENGTH);
hash.data = data_hash;
hash.length = SHA_256_LENGTH;
ret = calc_hash((uintptr_t)data->data, data->length, data_hash, SHA_256_LENGTH);
if (ret != ERRCODE_SUCC) {
upg_msg1("calc_hash fail ret = ", ret);
return ret;
}
uint8_t *e_in = upg_malloc(RSA_E_KEY_LEN);
if (e_in == NULL) {
return ERRCODE_MALLOC;
}
uint8_t e_value[] = {0x0, 0x1, 0x0, 0x1};
uint32_t offset = RSA_E_KEY_LEN - (uint32_t)sizeof(e_value);
memset_s(e_in, RSA_N_KEY_LEN, 0, RSA_N_KEY_LEN);
memcpy_s(e_in + offset, RSA_E_KEY_LEN - offset, e_value, sizeof(e_value));
pub_key_tmp.len = pub_key->len;
pub_key_tmp.n = pub_key->n;
pub_key_tmp.e = e_in;
ret = uapi_drv_cipher_pke_rsa_verify(&pub_key_tmp, scheme, UAPI_DRV_CIPHER_PKE_HASH_TYPE_SHA256, &hash, sign);
if (ret != ERRCODE_SUCC) {
upg_free(e_in);
upg_msg1("uapi_drv_cipher_pke_rsa_verify fail ret : ", ret);
return ret;
}
upg_msg0("verify_signature success");
upg_free(e_in);
return ret;
}
errcode_t secure_authenticate(const uint8_t *key, const upg_auth_data_t *data, uint8_t *sign_buff)
{
volatile errcode_t ret = ERRCODE_FAIL;
uapi_drv_cipher_pke_rsa_pub_key_t pub_key;
uapi_drv_cipher_pke_data_t sign;
if ((key == NULL) || (data == NULL) || (sign_buff == NULL)) {
return ERRCODE_FAIL;
}
pub_key.n = (uint8_t *)key;
pub_key.e = (uint8_t *)key + RSA_N_KEY_LEN;
pub_key.len = RSA_N_KEY_LEN;
sign.data = sign_buff;
sign.length = RSA_SIG_LEN;
ret = verify_signature((const uapi_drv_cipher_pke_data_t *)data, &pub_key, &sign);
if (ret != ERRCODE_SUCC) {
upg_msg1("verify_signature is fail, ret = ", ret);
}
return ret;
}
STATIC errcode_t verify_fota_key_area(uint32_t type, upg_key_area_data_t *key_area, uint8_t *public_key)
{
unused(type);
if (key_area->signature_length == SHA_256_LENGTH) {
upg_msg0("verify_fota_key_area -> verify SHA256");
uint32_t key_area_len = (uint32_t)sizeof(upg_key_area_data_t) - RSA_SIG_LEN;
return upg_verify_hash((uintptr_t)key_area, key_area_len, key_area->sig_fota_key_area, SHA_256_LENGTH);
}
upg_msg0("verify_fota_key_area -> verify signed");
uapi_drv_cipher_pke_data_t data;
/* Verify app key area with flash root public key */
data.data = (uint8_t *)key_area;
data.length = (uint32_t)sizeof(upg_key_area_data_t) - RSA_SIG_LEN;
return secure_authenticate(public_key, (upg_auth_data_t *)&data, key_area->sig_fota_key_area);
}
#endif
#if (UPG_CFG_VERIFICATION_MODE_ECC == YES || UPG_CFG_VERIFICATION_MODE_SM2_SM3 == YES)
errcode_t secure_authenticate(const uint8_t *key, const upg_auth_data_t *data, uint8_t *sign_buff)
{
volatile errcode_t ret = ERRCODE_FAIL;
uapi_drv_cipher_pke_data_t v_out;
uapi_drv_cipher_pke_ecc_point_t pub_key;
uapi_drv_cipher_pke_ecc_sig_t sign;
if ((key == NULL) || (data == NULL) || (sign_buff == NULL)) {
return ERRCODE_FAIL;
}
pub_key.x = (uint8_t *)key;
pub_key.y = (uint8_t *)key + ECC_X_KEY_LEN;
pub_key.length = ECC_KEY_LEN;
sign.r = sign_buff;
sign.s = sign_buff + ECC_R_SIG_LEN;
sign.length = ECC_SIG_LEN;
ret = verify_signature((uapi_drv_cipher_pke_data_t *)data, &pub_key, &sign);
if (ret != ERRCODE_SUCC) {
upg_msg1("verify_signature is fail, ret = ", ret);
}
return ret;
}
STATIC errcode_t verify_fota_key_area(uint32_t type, upg_key_area_data_t *key_area, uint8_t *public_key)
{
unused(type);
upg_auth_data_t data;
/* Verify app key area with flash root public key */
data.data = (uint8_t *)key_area;
data.length = sizeof(upg_key_area_data_t) - ECC_SIG_LEN;
return secure_authenticate(public_key, &data, key_area->sig_fota_key_area);
}
#endif
STATIC errcode_t verify_fota_info(uint32_t type, upg_fota_info_data_t *fota_info, uint8_t *public_key)
{
unused(type);
if (fota_info->signature_length == SHA_256_LENGTH) {
upg_msg0("verify_fota_info -> verify SHA256");
uint32_t fota_info_len = (uint32_t)sizeof(upg_fota_info_data_t) - RSA_SIG_LEN;
return upg_verify_hash((uintptr_t)fota_info, fota_info_len, fota_info->sign_fota_info, SHA_256_LENGTH);
}
upg_msg0("verify_fota_info -> verify signed");
upg_auth_data_t data;
data.data = (uint8_t *)fota_info;
data.length = (uint32_t)sizeof(upg_fota_info_data_t) - RSA_SIG_LEN;
return secure_authenticate(public_key, &data, fota_info->sign_fota_info);
}
STATIC errcode_t upg_check_fota_image_id(const upg_key_area_data_t *upg_key_info, const upg_fota_info_data_t *fota_info)
{
if (upg_key_info->image_id != UPG_IMAGE_ID_KEY_AREA) {
return ERRCODE_FAIL;
}
if (fota_info->image_id != UPG_IMAGE_ID_FOTA_INFO_AREA) {
return ERRCODE_FAIL;
}
return ERRCODE_SUCC;
}
void uapi_upg_register_user_defined_verify_func(uapi_upg_user_defined_check func, uintptr_t param)
{
g_user_defined_check_func = func;
g_user_defined_param = param;
}
/*
步骤一使用Root_Public_Key校验Key Area的签名
步骤二使用存储在升级包Key Area的FOTA_External_Public_Key校验FOTA Info区签名
步骤三如用户注册了定义字段的校验函数则校验自定义字段user_defined如未注册此步骤默认校验通过
*/
errcode_t uapi_upg_verify_file_head(const upg_package_header_t *pkg_header)
{
upg_key_area_data_t *key_area = (upg_key_area_data_t *)&(pkg_header->key_area);
uint32_t type = key_area->image_id;
uint8_t *public_key = NULL;
if (upg_is_inited() == false) {
return ERRCODE_UPG_NOT_INIT;
}
public_key = upg_get_root_public_key();
if (public_key == NULL) {
return ERRCODE_UPG_VERIFICATION_KEY_ERROR;
}
upg_fota_info_data_t *fota_info = (upg_fota_info_data_t *)&(pkg_header->info_area);
errcode_t ret = upg_check_fota_image_id(key_area, fota_info);
if (ret != ERRCODE_SUCC) {
/* image id 不正确就不用校验了,直接返回失败 */
upg_msg0("upg verify: image ID error\r\n");
return ret;
}
/* 步骤一 */
ret = verify_fota_key_area(type, key_area, public_key);
if (ret != ERRCODE_SUCC) {
upg_msg1("upg verify: key area error. ret = ", ret);
return ret;
}
/* 步骤二 */
ret = verify_fota_info(fota_info->image_id, fota_info, key_area->fota_external_public_key);
if (ret != ERRCODE_SUCC) {
upg_msg1("upg verify: fota info error. ret = ", ret);
return ret;
}
ret = upg_check_fota_information(pkg_header);
if (ret != ERRCODE_SUCC) {
upg_msg1("upg verify: upg_check_fota_information. ret = ", ret);
return ret;
}
/* 步骤三 */
if (g_user_defined_check_func != NULL) {
ret = g_user_defined_check_func(fota_info->user_defined, sizeof(fota_info->user_defined), g_user_defined_param);
}
return ret;
}
/*
步骤一使用Root_Public_Key校验Key Area的签名
步骤二使用存储在升级包Key Area的FOTA_External_Public_Key校验FOTA Info区签名
步骤三如用户注册了定义字段的校验函数则校验自定义字段user_defined如未注册此步骤默认校验通过
步骤四使用存储在FOTA Info区的Image_Hash_Table中的HASH值校验Image_Hash_Table
步骤五使用保存在Image_Hash_Table中的每个镜像Header的HASH值校验对应的Image_Header
步骤六使用保存在Image_Header中的新镜像HASH值校验对应的新镜像。
步骤七如果为差分升级镜像的Image_Header中保存了旧版本镜像的HASH值根据这个HASH值校验flash上的旧镜像是否是制作差分包
时用的旧镜像。非差分镜像,可忽略此步骤
步骤八校验防回滚版本号只有镜像中的防回滚版本号大于等于OTP中的防回滚版本号时才能升级
*/
errcode_t uapi_upg_verify_file(const upg_package_header_t *pkg_header)
{
upg_image_hash_node_t *img_hash_table = NULL;
if (upg_is_inited() == false) {
return ERRCODE_UPG_NOT_INIT;
}
/* 步骤一,步骤二,步骤三 */
errcode_t ret = uapi_upg_verify_file_head(pkg_header);
if (ret != ERRCODE_SUCC) {
upg_set_temporary_result(UPG_RESULT_VERIFY_HEAD_FAILED);
return ret;
}
upg_msg0("upg verify head OK");
ret = upg_get_pkg_image_hash_table(pkg_header, &img_hash_table);
if (ret != ERRCODE_SUCC || img_hash_table == NULL) {
upg_msg0("upg_get_pkg_image_hash_table fail\r\n");
return ret;
}
upg_fota_info_data_t *fota_info = (upg_fota_info_data_t *)&(pkg_header->info_area);
/* 步骤四 使用存储在FOTA Info区的Image_Hash_Table中的HASH值校验Image_Hash_Table */
/* 由于ImageHashTable为了16字节对齐有填充字段此处的长度不能使用image_num * sizeof(upg_image_hash_node_t)) */
ret = upg_verify_hash((uintptr_t)img_hash_table, fota_info->image_hash_table_length,
fota_info->image_hash_table_hash, sizeof(fota_info->image_hash_table_hash));
if (ret != ERRCODE_SUCC) {
upg_set_temporary_result(UPG_RESULT_VERIFY_HASH_TABLE_FAILED);
upg_free(img_hash_table);
return ret;
}
/* 循环遍历校验每个升级image
步骤五至八
*/
upg_image_header_t *img_header = NULL;
for (uint32_t i = 0; i < fota_info->image_num; i++) {
ret = upg_get_pkg_image_header((const upg_image_hash_node_t *)&(img_hash_table[i]), &img_header);
if (ret != ERRCODE_SUCC || img_header == NULL) {
upg_msg0("upg_get_pkg_image_header fail");
break;
}
ret = uapi_upg_verify_file_image((const upg_image_header_t *)img_header,
(const uint8_t *)img_hash_table[i].image_hash, SHA_256_LENGTH, true);
if (ret != ERRCODE_SUCC) {
break;
}
/* 步骤八:校验防回滚版本号只有镜像中的防回滚版本号大于等于OTP中的防回滚版本号时才能升级 */
#if (UPG_CFG_ANTI_ROLLBACK_SUPPORT == YES)
ret = upg_anti_rollback_version_verify(pkg_header, img_header);
if (ret != ERRCODE_SUCC) {
upg_set_temporary_result(UPG_RESULT_VERIFY_VERSION_FAILED);
break;
}
#endif
upg_free(img_header);
img_header = NULL;
}
upg_free(img_hash_table);
upg_free(img_header);
return ret;
}
#if (UPG_CFG_DIRECT_FLASH_ACCESS == NO)
STATIC errcode_t upg_verify_image_multi_segment_data(const upg_image_header_t *img_header)
{
errcode_t ret_val;
uint32_t handle;
uint32_t out_length = SHA_256_LENGTH;
uapi_drv_cipher_hash_attr_t hash_attr = {NULL, 0, 0, UAPI_DRV_CIPHER_HASH_TYPE_SHA256, 0, 0};
uapi_drv_cipher_buf_attr_t src_buf;
uint32_t read_len;
uint32_t image_offset = 0;
uint8_t data_sha[SHA_256_LENGTH] = {0};
uint32_t aligned_image_len = upg_aligned(img_header->image_len, 16); /* 16-byte alignment */
ret_val = uapi_drv_cipher_hash_start(&handle, &hash_attr);
if (ret_val != ERRCODE_SUCC) {
upg_msg0("uapi_drv_cipher_hash_start fail \r\n");
return ret_val;
}
uint8_t *image_data = (uint8_t *)upg_malloc(VERIFY_BUFF_LEN);
if (image_data == NULL) {
return ERRCODE_MALLOC;
}
do {
read_len = (image_offset + VERIFY_BUFF_LEN < aligned_image_len) ?
VERIFY_BUFF_LEN : (aligned_image_len - image_offset);
ret_val = upg_copy_pkg_image_data(img_header, image_offset, &read_len, image_data);
if (ret_val != ERRCODE_SUCC) {
upg_free(image_data);
return ret_val;
}
src_buf.phys_addr = (uintptr_t)image_data;
src_buf.buf_sec = UAPI_DRV_CIPHER_BUF_SECURE;
ret_val = uapi_drv_cipher_hash_update(handle, &src_buf, read_len);
if (ret_val != ERRCODE_SUCC) {
upg_free(image_data);
return ret_val;
}
image_offset += read_len;
} while (image_offset < aligned_image_len);
upg_free(image_data);
ret_val = uapi_drv_cipher_hash_finish(handle, data_sha, &out_length);
if (ret_val != ERRCODE_SUCC) {
return ret_val;
}
return verify_hash_cmp(img_header->image_hash, data_sha, SHA_256_LENGTH);
}
#endif /* #if UPG_CFG_DIRECT_FLASH_ACCESS */
STATIC errcode_t upg_verify_image_data(const upg_image_header_t *img_header)
{
#if (UPG_CFG_DIRECT_FLASH_ACCESS == NO)
return upg_verify_image_multi_segment_data(img_header);
#else
uint8_t *image_data = NULL;
errcode_t ret;
uint32_t aligned_image_len = upg_aligned(img_header->image_len, 16); /* 16-byte alignment */
ret = upg_get_pkg_image_data(img_header, 0, &aligned_image_len, &image_data);
if (ret != ERRCODE_SUCC || image_data == NULL) {
return ret;
}
ret = upg_verify_hash((uintptr_t)image_data, aligned_image_len,
img_header->image_hash, sizeof(img_header->image_hash));
if (ret != ERRCODE_SUCC) {
return ret;
}
return ERRCODE_SUCC;
#endif /* #if UPG_CFG_DIRECT_FLASH_ACCESS */
}
STATIC errcode_t upg_verify_old_image(const upg_image_header_t *img_header)
{
errcode_t ret;
uint32_t handle;
uint32_t out_length = SHA_256_LENGTH;
uapi_drv_cipher_hash_attr_t hash_attr = { .hash_type = UAPI_DRV_CIPHER_HASH_TYPE_SHA256 };
uapi_drv_cipher_buf_attr_t src_buf;
uint32_t read_len;
uint32_t image_offset = 0;
uint8_t data_sha[SHA_256_LENGTH] = {0};
uint32_t image_len = img_header->old_image_len;
ret = uapi_drv_cipher_hash_start(&handle, &hash_attr);
if (ret != ERRCODE_SUCC) {
upg_msg0("uapi_drv_cipher_hash_start fail \r\n");
return ret;
}
uint8_t *old_image_data = (uint8_t *)upg_malloc(VERIFY_BUFF_LEN);
if (old_image_data == NULL) {
return ERRCODE_MALLOC;
}
do {
read_len = (image_offset + VERIFY_BUFF_LEN < image_len) ?
VERIFY_BUFF_LEN : (image_len - image_offset);
ret = upg_read_old_image_data(image_offset, old_image_data, &read_len, img_header->image_id);
if (ret != ERRCODE_SUCC) {
upg_free(old_image_data);
return ret;
}
src_buf.phys_addr = (uintptr_t)old_image_data;
src_buf.buf_sec = UPG_VERIFY_CIPHER_BUF_ATTR;
ret = uapi_drv_cipher_hash_update(handle, &src_buf, read_len);
if (ret != ERRCODE_SUCC) {
upg_free(old_image_data);
return ret;
}
image_offset += read_len;
} while (image_offset < image_len);
upg_free(old_image_data);
ret = uapi_drv_cipher_hash_finish(handle, data_sha, &out_length);
if (ret != ERRCODE_SUCC) {
return ret;
}
return verify_hash_cmp(img_header->old_image_hash, data_sha, SHA_256_LENGTH);
}
/*
步骤五使用保存在Image_Hash_Table中的每个镜像Header的HASH值校验对应的Image_Header
步骤六使用保存在Image_Header中的新镜像HASH值校验对应的新镜像。
步骤七如果为差分升级镜像的Image_Header中保存了旧版本镜像的HASH值根据这个HASH值校验flash上的旧镜像是否是制作差分包
时用的旧镜像。非差分镜像,可忽略此步骤
步骤八校验防回滚版本号只有镜像中的防回滚版本号大于等于OTP中的防回滚版本号时才能升级
*/
errcode_t uapi_upg_verify_file_image(const upg_image_header_t *img_header,
const uint8_t *hash, uint32_t hash_len, bool verify_old)
{
uint32_t ret;
/* 校验HeaderMagic有效性 */
if (img_header->header_magic != UPG_IMAGE_HRADER_MAGIC) {
upg_msg1("upg verify: file image check error. header_magic = ", img_header->header_magic);
upg_set_temporary_result(UPG_RESULT_VERIFY_IMAGE_FAILED);
return ERRCODE_FAIL;
}
/* 步骤五: 使用保存在Image_Hash_Table中的每个镜像Header的HASH值校验对应的Image_Header */
ret = upg_verify_hash((uintptr_t)img_header, sizeof(upg_image_header_t), hash, hash_len);
if (ret != ERRCODE_SUCC) {
upg_set_temporary_result(UPG_RESULT_VERIFY_IMAGE_FAILED);
return ret;
}
/* 步骤六: 使用保存在Image_Header中的新镜像HASH值校验对应的新镜像。 */
ret = upg_verify_image_data(img_header);
if (ret != ERRCODE_SUCC) {
upg_set_temporary_result(UPG_RESULT_VERIFY_IMAGE_FAILED);
return ret;
}
/* 步骤七:如果为差分升级镜像的Image_Header中保存了旧版本镜像的HASH值根据这个HASH值校验flash上的旧镜像是否是制作差分包
时用的旧镜像。非差分镜像,可忽略此步骤
*/
if (verify_old && img_header->decompress_flag == DECOMPRESS_FLAG_DIFF) {
ret = upg_verify_old_image(img_header);
if (ret != ERRCODE_SUCC) {
upg_set_temporary_result(UPG_RESULT_VERIFY_OLD_IMAGE_FAILED);
return ret;
}
}
upg_msg1("upg verify: image check OK. image_id = ", img_header->image_id);
/* 步骤八:校验防回滚版本号只有镜像中的防回滚版本号大于等于OTP中的防回滚版本号时才能升级 */
return ERRCODE_SUCC;
}
errcode_t uapi_upg_check_head_integrity(const upg_package_header_t *pkg_header)
{
upg_key_area_data_t *key_area = (upg_key_area_data_t *)&(pkg_header->key_area);
upg_fota_info_data_t *fota_info = (upg_fota_info_data_t *)&(pkg_header->info_area);
upg_image_hash_node_t *img_hash_table = NULL;
if (upg_is_inited() == false) {
return ERRCODE_UPG_NOT_INIT;
}
errcode_t ret = upg_check_fota_image_id(key_area, fota_info);
if (ret != ERRCODE_SUCC) {
/* image id 不正确就不用校验了,直接返回失败 */
upg_msg0("upg verify: image ID error\r\n");
return ret;
}
/* 校验FOTA info */
ret = verify_fota_info(fota_info->image_id, fota_info, key_area->fota_external_public_key);
if (ret != ERRCODE_SUCC) {
upg_msg1("upg verify: fota info error. ret = ", ret);
return ret;
}
ret = upg_get_pkg_image_hash_table(pkg_header, &img_hash_table);
if (ret != ERRCODE_SUCC || img_hash_table == NULL) {
upg_msg0("upg_get_pkg_image_hash_table fail\r\n");
return ret;
}
/* 步骤四 使用存储在FOTA Info区的Image_Hash_Table中的HASH值校验Image_Hash_Table */
/* 由于ImageHashTable为了16字节对齐有填充字段此处的长度不能使用image_num * sizeof(upg_image_hash_node_t)) */
ret = upg_verify_hash((uintptr_t)img_hash_table,
fota_info->image_hash_table_length,
fota_info->image_hash_table_hash,
sizeof(fota_info->image_hash_table_hash));
if (ret != ERRCODE_SUCC) {
upg_free(img_hash_table);
upg_msg1("upg verify: verify hash table failed. ret = ", ret);
return ret;
}
upg_free(img_hash_table);
return ERRCODE_SUCC;
}
#endif