add option for rollback protection
Depends on 'MCUBOOT_OVERWRITE_ONLY' option since swap info is not protected by signature Signed-off-by: Håkon Øye Amundsen <haakon.amundsen@nordicsemi.no>
This commit is contained in:
parent
e2acfaede5
commit
2d1bac164f
|
@ -510,6 +510,42 @@ boot_check_header_erased(struct boot_loader_state *state, int slot)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if (BOOT_IMAGE_NUMBER > 1) || \
|
||||
(defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION))
|
||||
/**
|
||||
* Check if the version of the image is not older than required.
|
||||
*
|
||||
* @param req Required minimal image version.
|
||||
* @param ver Version of the image to be checked.
|
||||
*
|
||||
* @return 0 if the version is sufficient, nonzero otherwise.
|
||||
*/
|
||||
static int
|
||||
boot_is_version_sufficient(struct image_version *req,
|
||||
struct image_version *ver)
|
||||
{
|
||||
if (ver->iv_major > req->iv_major) {
|
||||
return 0;
|
||||
}
|
||||
if (ver->iv_major < req->iv_major) {
|
||||
return BOOT_EBADVERSION;
|
||||
}
|
||||
/* The major version numbers are equal. */
|
||||
if (ver->iv_minor > req->iv_minor) {
|
||||
return 0;
|
||||
}
|
||||
if (ver->iv_minor < req->iv_minor) {
|
||||
return BOOT_EBADVERSION;
|
||||
}
|
||||
/* The minor version numbers are equal. */
|
||||
if (ver->iv_revision < req->iv_revision) {
|
||||
return BOOT_EBADVERSION;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check that there is a valid image in a slot
|
||||
*
|
||||
|
@ -541,6 +577,24 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
|
|||
goto out;
|
||||
}
|
||||
|
||||
#if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION)
|
||||
if (slot != BOOT_PRIMARY_SLOT) {
|
||||
/* Check if version of secondary slot is sufficient */
|
||||
rc = boot_is_version_sufficient(
|
||||
&boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver,
|
||||
&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver);
|
||||
if (rc != 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) {
|
||||
BOOT_LOG_ERR("insufficient version in secondary slot");
|
||||
flash_area_erase(fap, 0, fap->fa_size);
|
||||
/* Image in the secondary slot does not satisfy version requirement.
|
||||
* Erase the image and continue booting from the primary slot.
|
||||
*/
|
||||
rc = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!boot_is_header_valid(hdr, fap) || boot_image_check(state, hdr, fap, bs)) {
|
||||
if (slot != BOOT_PRIMARY_SLOT) {
|
||||
flash_area_erase(fap, 0, fap->fa_size);
|
||||
|
@ -552,7 +606,7 @@ boot_validate_slot(struct boot_loader_state *state, int slot,
|
|||
BOOT_LOG_ERR("Image in the %s slot is not valid!",
|
||||
(slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
|
||||
#endif
|
||||
rc = -1;
|
||||
rc = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -966,39 +1020,6 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs)
|
|||
#endif
|
||||
|
||||
#if (BOOT_IMAGE_NUMBER > 1)
|
||||
/**
|
||||
* Check if the version of the image is not older than required.
|
||||
*
|
||||
* @param req Required minimal image version.
|
||||
* @param ver Version of the image to be checked.
|
||||
*
|
||||
* @return 0 if the version is sufficient, nonzero otherwise.
|
||||
*/
|
||||
static int
|
||||
boot_is_version_sufficient(struct image_version *req,
|
||||
struct image_version *ver)
|
||||
{
|
||||
if (ver->iv_major > req->iv_major) {
|
||||
return 0;
|
||||
}
|
||||
if (ver->iv_major < req->iv_major) {
|
||||
return BOOT_EBADVERSION;
|
||||
}
|
||||
/* The major version numbers are equal. */
|
||||
if (ver->iv_minor > req->iv_minor) {
|
||||
return 0;
|
||||
}
|
||||
if (ver->iv_minor < req->iv_minor) {
|
||||
return BOOT_EBADVERSION;
|
||||
}
|
||||
/* The minor version numbers are equal. */
|
||||
if (ver->iv_revision < req->iv_revision) {
|
||||
return BOOT_EBADVERSION;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the image dependency whether it is satisfied and modify
|
||||
* the swap type if necessary.
|
||||
|
|
|
@ -346,4 +346,14 @@ config UPDATEABLE_IMAGE_NUMBER
|
|||
help
|
||||
Enables support of multi image update.
|
||||
|
||||
config MCUBOOT_DOWNGRADE_PREVENTION
|
||||
bool "Downgrade prevention"
|
||||
depends on BOOT_UPGRADE_ONLY
|
||||
help
|
||||
Prevent downgrades by enforcing incrementing version numbers.
|
||||
When this option is set, any upgrade must have greater major version
|
||||
or greater minor version with equal major version. This mechanism
|
||||
only protects against some attacks against version downgrades (for
|
||||
example, a JTAG could be used to write an older version).
|
||||
|
||||
source "$ZEPHYR_BASE/Kconfig.zephyr"
|
||||
|
|
|
@ -89,6 +89,10 @@
|
|||
#define MCUBOOT_IMAGE_NUMBER 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_DOWNGRADE_PREVENTION
|
||||
#define MCUBOOT_DOWNGRADE_PREVENTION 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enabling this option uses newer flash map APIs. This saves RAM and
|
||||
* avoids deprecated API usage.
|
||||
|
|
|
@ -942,3 +942,11 @@ state after dependency check.
|
|||
|
||||
For more information on adding dependency entries to an image,
|
||||
see: [imgtool](imgtool.md).
|
||||
|
||||
## [Downgrade Prevention](#downgrade-prevention)
|
||||
|
||||
Downgrade prevention is a feature which enforces that the new image must have a
|
||||
higher version number than the image it is replacing. This feature is enabled
|
||||
with the `MCUBOOT_DOWNGRADE_PREVENTION` option. Downgrade prevention is only
|
||||
available when the overwrite-based image update strategy is used
|
||||
(i.e. `MCUBOOT_OVERWRITE_ONLY` is set).
|
||||
|
|
Loading…
Reference in New Issue