subsys/mgmt/hawkbit: Check the hash of stored firmware

Previously, the hash of the firmware is checked while we are
downloading the firmware. This isn't ideal as the validity of
the firmware written into the flash is not verified and can be
corrupted. Furthermore, checking while downloading will have an
negative impact to the download speed as the CPU need to do
more work during the data transfer.

This PR removes the previous verify-hash-while-download
implementation and use the flash_img_check API instead.

Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
This commit is contained in:
Yong Cong Sin 2022-02-26 13:20:37 +08:00 committed by Carles Cufí
commit 313c49ec21
2 changed files with 17 additions and 48 deletions

View file

@ -7,8 +7,6 @@ menuconfig HAWKBIT
select FLASH select FLASH
select REBOOT select REBOOT
select HWINFO select HWINFO
select MBEDTLS
select MBEDTLS_ENABLE_HEAP
select NET_TCP select NET_TCP
select NET_SOCKETS select NET_SOCKETS
select IMG_MANAGER select IMG_MANAGER
@ -18,6 +16,7 @@ menuconfig HAWKBIT
select JSON_LIBRARY select JSON_LIBRARY
select BOOTLOADER_MCUBOOT select BOOTLOADER_MCUBOOT
select MPU_ALLOW_FLASH_WRITE select MPU_ALLOW_FLASH_WRITE
select IMG_ENABLE_IMAGE_CHECK
select IMG_ERASE_PROGRESSIVELY select IMG_ERASE_PROGRESSIVELY
select NET_SOCKETS_POSIX_NAMES select NET_SOCKETS_POSIX_NAMES
help help

View file

@ -33,8 +33,6 @@ LOG_MODULE_REGISTER(hawkbit, CONFIG_HAWKBIT_LOG_LEVEL);
#include "mgmt/hawkbit.h" #include "mgmt/hawkbit.h"
#include "hawkbit_firmware.h" #include "hawkbit_firmware.h"
#include "mbedtls/md.h"
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
#define CA_CERTIFICATE_TAG 1 #define CA_CERTIFICATE_TAG 1
#include <net/tls_credentials.h> #include <net/tls_credentials.h>
@ -71,7 +69,6 @@ struct hawkbit_download {
int download_progress; int download_progress;
size_t downloaded_size; size_t downloaded_size;
size_t http_content_size; size_t http_content_size;
mbedtls_md_context_t hash_ctx;
uint8_t file_hash[SHA256_HASH_SIZE]; uint8_t file_hash[SHA256_HASH_SIZE];
}; };
@ -805,14 +802,6 @@ static void response_cb(struct http_response *rsp,
body_data = rsp->body_frag_start; body_data = rsp->body_frag_start;
body_len = rsp->body_frag_len; body_len = rsp->body_frag_len;
ret = mbedtls_md_update(&hb_context.dl.hash_ctx, body_data,
body_len);
if (ret != 0) {
LOG_ERR("mbedTLS md update error: %d", ret);
hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR;
break;
}
ret = flash_img_buffered_write( ret = flash_img_buffered_write(
&hb_context.flash_ctx, body_data, body_len, &hb_context.flash_ctx, body_data, body_len,
final_data == HTTP_DATA_FINAL); final_data == HTTP_DATA_FINAL);
@ -1037,8 +1026,7 @@ enum hawkbit_response hawkbit_probe(void)
int ret; int ret;
int32_t action_id; int32_t action_id;
int32_t file_size = 0; int32_t file_size = 0;
uint8_t response_hash[SHA256_HASH_SIZE] = { 0 }; struct flash_img_check fic;
const mbedtls_md_info_t *hash_info;
char device_id[DEVICE_ID_HEX_MAX_SIZE] = { 0 }, char device_id[DEVICE_ID_HEX_MAX_SIZE] = { 0 },
cancel_base[CANCEL_BASE_SIZE] = { 0 }, cancel_base[CANCEL_BASE_SIZE] = { 0 },
download_http[DOWNLOAD_HTTP_SIZE] = { 0 }, download_http[DOWNLOAD_HTTP_SIZE] = { 0 },
@ -1228,67 +1216,49 @@ enum hawkbit_response hawkbit_probe(void)
flash_img_init(&hb_context.flash_ctx); flash_img_init(&hb_context.flash_ctx);
hash_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
if (!hash_info) {
LOG_ERR("Unable to request hash type from mbedTLS");
hb_context.code_status = HAWKBIT_METADATA_ERROR;
goto cleanup;
}
mbedtls_md_init(&hb_context.dl.hash_ctx);
if (mbedtls_md_setup(&hb_context.dl.hash_ctx, hash_info, 0) < 0) {
LOG_ERR("Can't setup mbedTLS hash engine");
mbedtls_md_free(&hb_context.dl.hash_ctx);
hb_context.code_status = HAWKBIT_METADATA_ERROR;
goto free_md;
}
mbedtls_md_starts(&hb_context.dl.hash_ctx);
ret = (int)send_request(HTTP_GET, HAWKBIT_DOWNLOAD, ret = (int)send_request(HTTP_GET, HAWKBIT_DOWNLOAD,
HAWKBIT_STATUS_FINISHED_NONE, HAWKBIT_STATUS_FINISHED_NONE,
HAWKBIT_STATUS_EXEC_NONE); HAWKBIT_STATUS_EXEC_NONE);
mbedtls_md_finish(&hb_context.dl.hash_ctx, response_hash);
if (!ret) { if (!ret) {
LOG_ERR("Send request failed (HAWKBIT_DOWNLOAD): %d", ret); LOG_ERR("Send request failed (HAWKBIT_DOWNLOAD): %d", ret);
hb_context.code_status = HAWKBIT_NETWORKING_ERROR; hb_context.code_status = HAWKBIT_NETWORKING_ERROR;
goto free_md; goto cleanup;
} }
if (hb_context.code_status == HAWKBIT_DOWNLOAD_ERROR) { if (hb_context.code_status == HAWKBIT_DOWNLOAD_ERROR) {
goto free_md; goto cleanup;
} }
/* Check if download finished */
if (!hb_context.final_data_received) { if (!hb_context.final_data_received) {
LOG_ERR("Download is not complete"); LOG_ERR("Download is not complete");
hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR;
goto free_md; goto cleanup;
} }
if (memcmp(response_hash, hb_context.dl.file_hash, mbedtls_md_get_size(hash_info)) != 0) { /* Verify the hash of the stored firmware */
LOG_ERR("Hash mismatch"); fic.match = hb_context.dl.file_hash;
LOG_HEXDUMP_DBG(response_hash, sizeof(response_hash), "resp"); fic.clen = hb_context.dl.downloaded_size;
LOG_HEXDUMP_DBG(hb_context.dl.file_hash, sizeof(hb_context.dl.file_hash), "file"); if (flash_img_check(&hb_context.flash_ctx, &fic, FLASH_AREA_ID(image_1))) {
LOG_ERR("Firmware - flash validation has failed");
hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR;
goto free_md; goto cleanup;
} }
/* Request mcuboot to upgrade */
if (boot_request_upgrade(BOOT_UPGRADE_TEST)) { if (boot_request_upgrade(BOOT_UPGRADE_TEST)) {
LOG_ERR("Failed to mark the image in slot 1 as pending"); LOG_ERR("Failed to mark the image in slot 1 as pending");
hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR; hb_context.code_status = HAWKBIT_DOWNLOAD_ERROR;
goto free_md; goto cleanup;
} }
hb_context.code_status = HAWKBIT_UPDATE_INSTALLED; /* If everything is successful */
hawkbit_device_acid_update(hb_context.json_action_id); hb_context.code_status = HAWKBIT_UPDATE_INSTALLED;
hawkbit_device_acid_update(hb_context.json_action_id);
hb_context.dl.http_content_size = 0; hb_context.dl.http_content_size = 0;
free_md:
mbedtls_md_free(&hb_context.dl.hash_ctx);
cleanup: cleanup:
cleanup_connection(); cleanup_connection();