dfu: img_util: Add flash integrity check
Flash memory can be write but there is no way to check flash integrity. Add flash_img_check method that verify flash integrity. This is useful to avoid firmware reboot and test. Another use is ensure that firmware upgrade routines from internet server to flash slot are performing properly. This uses flash_area_check_int_sha256 method to check a SHA-256 hash. On sucess match, zero is returned, otherwise a negative errno value. Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
This commit is contained in:
parent
eb0f571790
commit
4d35d3d83a
7 changed files with 131 additions and 1 deletions
|
@ -20,6 +20,19 @@ struct flash_img_context {
|
|||
struct stream_flash_ctx stream;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_IMG_ENABLE_IMAGE_CHECK)
|
||||
/**
|
||||
* @brief Structure for verify flash region integrity
|
||||
*
|
||||
* Match vector length is fixed and depends on size from hash algorithm used
|
||||
* to verify flash integrity. The current available algorithm is SHA-256.
|
||||
*/
|
||||
struct flash_img_check {
|
||||
const uint8_t *match; /** Match vector data */
|
||||
size_t clen; /** Content to be compared */
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize context needed for writing the image to the flash.
|
||||
*
|
||||
|
@ -68,6 +81,23 @@ size_t flash_img_bytes_written(struct flash_img_context *ctx);
|
|||
int flash_img_buffered_write(struct flash_img_context *ctx, const uint8_t *data,
|
||||
size_t len, bool flush);
|
||||
|
||||
#if defined(CONFIG_IMG_ENABLE_IMAGE_CHECK)
|
||||
/**
|
||||
* @brief Verify flash memory length bytes integrity from a flash area. The
|
||||
* start point is indicated by an offset value.
|
||||
*
|
||||
* @param[in] ctx context.
|
||||
* @param[in] fic flash img check data.
|
||||
* @param[in] area_id flash area id of partition where the image should be
|
||||
* verified.
|
||||
*
|
||||
* @return 0 on success, negative errno code on fail
|
||||
*/
|
||||
int flash_img_check(struct flash_img_context *ctx,
|
||||
const struct flash_img_check *fic,
|
||||
uint8_t area_id);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -59,6 +59,17 @@ config IMG_ERASE_PROGRESSIVELY
|
|||
on some hardware that has long erase times, to prevent long wait
|
||||
times at the beginning of the DFU process.
|
||||
|
||||
config IMG_ENABLE_IMAGE_CHECK
|
||||
bool "Enable image check functions"
|
||||
depends on MCUBOOT_IMG_MANAGER
|
||||
select FLASH_AREA_CHECK_INTEGRITY
|
||||
help
|
||||
If enabled, there will be available the function to check flash
|
||||
integrity. It can be used to verify flash integrity after received
|
||||
a new firmware. This is useful to avoid firmware reboot and test.
|
||||
Another use is to ensure that firmware upgrade routines from internet
|
||||
server to flash slot are performing properly.
|
||||
|
||||
module = IMG_MANAGER
|
||||
module-str = image manager
|
||||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 2020 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017 Linaro Limited
|
||||
* Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -83,3 +84,36 @@ int flash_img_init(struct flash_img_context *ctx)
|
|||
{
|
||||
return flash_img_init_id(ctx, FLASH_AREA_IMAGE_SECONDARY);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IMG_ENABLE_IMAGE_CHECK)
|
||||
int flash_img_check(struct flash_img_context *ctx,
|
||||
const struct flash_img_check *fic,
|
||||
uint8_t area_id)
|
||||
{
|
||||
struct flash_area_check fac;
|
||||
int rc;
|
||||
|
||||
if (!ctx || !fic) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = flash_area_open(area_id,
|
||||
(const struct flash_area **)&(ctx->flash_area));
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
fac.match = fic->match;
|
||||
fac.clen = fic->clen;
|
||||
fac.off = 0;
|
||||
fac.rbuf = ctx->buf;
|
||||
fac.rblen = sizeof(ctx->buf);
|
||||
|
||||
rc = flash_area_check_int_sha256(ctx->flash_area, &fac);
|
||||
|
||||
flash_area_close(ctx->flash_area);
|
||||
ctx->flash_area = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,7 @@ CONFIG_ZTEST=y
|
|||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_IMG_MANAGER=y
|
||||
CONFIG_IMG_ENABLE_IMAGE_CHECK=y
|
||||
CONFIG_MCUBOOT_IMG_MANAGER=y
|
||||
CONFIG_IMG_BLOCK_BUF_SIZE=512
|
||||
CONFIG_ARM_MPU=n
|
||||
|
|
|
@ -2,5 +2,6 @@ CONFIG_ZTEST=y
|
|||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_IMG_MANAGER=y
|
||||
CONFIG_IMG_ENABLE_IMAGE_CHECK=y
|
||||
CONFIG_MCUBOOT_IMG_MANAGER=y
|
||||
CONFIG_IMG_BLOCK_BUF_SIZE=512
|
||||
|
|
|
@ -2,5 +2,6 @@ CONFIG_ZTEST=y
|
|||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_IMG_MANAGER=y
|
||||
CONFIG_IMG_ENABLE_IMAGE_CHECK=y
|
||||
CONFIG_MCUBOOT_IMG_MANAGER=y
|
||||
CONFIG_IMG_BLOCK_BUF_SIZE=512
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -107,11 +108,62 @@ void test_collecting(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void test_check_flash(void)
|
||||
{
|
||||
/* echo $'0123456789abcdef\nfedcba9876543201' > tst.sha
|
||||
* hexdump tst.sha
|
||||
*/
|
||||
uint8_t tst_vec[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
|
||||
0x0a, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x39,
|
||||
0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
|
||||
0x30, 0x0a };
|
||||
/* sha256sum tst.sha */
|
||||
uint8_t tst_sha[] = { 0xc6, 0xb6, 0x7c, 0x46, 0xe7, 0x2e, 0x14, 0x17,
|
||||
0x49, 0xa4, 0xd2, 0xf1, 0x38, 0x58, 0xb2, 0xa7,
|
||||
0x54, 0xaf, 0x6d, 0x39, 0x50, 0x6b, 0xd5, 0x41,
|
||||
0x90, 0xf6, 0x18, 0x1a, 0xe0, 0xc2, 0x7f, 0x98 };
|
||||
|
||||
struct flash_img_check fic = { NULL, 0 };
|
||||
struct flash_img_context ctx;
|
||||
int ret;
|
||||
|
||||
ret = flash_img_init_id(&ctx, FLASH_AREA_ID(image_1));
|
||||
zassert_true(ret == 0, "Flash img init 1");
|
||||
ret = flash_area_erase(ctx.flash_area, 0, ctx.flash_area->fa_size);
|
||||
zassert_true(ret == 0, "Flash erase failure (%d)\n", ret);
|
||||
ret = flash_img_buffered_write(&ctx, tst_vec, sizeof(tst_vec), true);
|
||||
zassert_true(ret == 0, "Flash img buffered write\n");
|
||||
|
||||
ret = flash_img_check(NULL, NULL, 0);
|
||||
zassert_true(ret == -EINVAL, "Flash img check params 1, 2\n");
|
||||
ret = flash_img_check(NULL, &fic, 0);
|
||||
zassert_true(ret == -EINVAL, "Flash img check params 2\n");
|
||||
ret = flash_img_check(&ctx, NULL, 0);
|
||||
zassert_true(ret == -EINVAL, "Flash img check params 1\n");
|
||||
|
||||
ret = flash_img_check(&ctx, &fic, FLASH_AREA_ID(image_1));
|
||||
zassert_true(ret == -EINVAL, "Flash img check fic match\n");
|
||||
fic.match = tst_sha;
|
||||
ret = flash_img_check(&ctx, &fic, FLASH_AREA_ID(image_1));
|
||||
zassert_true(ret == -EINVAL, "Flash img check fic len\n");
|
||||
fic.clen = sizeof(tst_vec);
|
||||
|
||||
ret = flash_img_check(&ctx, &fic, FLASH_AREA_ID(image_1));
|
||||
zassert_true(ret == 0, "Flash img check\n");
|
||||
tst_sha[0] = 0x00;
|
||||
ret = flash_img_check(&ctx, &fic, FLASH_AREA_ID(image_1));
|
||||
zassert_false(ret == 0, "Flash img check wrong sha\n");
|
||||
|
||||
flash_area_close(ctx.flash_area);
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(test_util,
|
||||
ztest_unit_test(test_collecting),
|
||||
ztest_unit_test(test_init_id)
|
||||
ztest_unit_test(test_init_id),
|
||||
ztest_unit_test(test_check_flash)
|
||||
);
|
||||
ztest_run_test_suite(test_util);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue