/* * Copyright (c) @CompanyNameMagicTag 2021-2021. All rights reserved. * Description: UPG verification functions source file */ #include #include #include #include #include #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