Add downgrade prevention for swaps
Currently, downgrade prevention was limited to overwrite only builds (version check) or devices with hardware storage for security counter. This extends downgrade prevention to be used when swap update is selected. Unlike MCUBOOT_HW_ROLLBACK_PROT option it does not require user code to provide external way to store security counter. Security counter from slot 1 image is used for comparison. With security counter usage it is possible to have limited software rollback if security counter was not incremented. It is possible to use image version where strict rule for image version comparison prevents any downgrades. Downgrade prevention is also added to mynewt configuration. If image in slot 1 is marked as pending and downgrade prevention is in place, image will be deleted to avoid check on next boot. Signed-off-by: Jerzy Kasenberg <jerzy.kasenberg@codecoup.pl>
This commit is contained in:
parent
4e2cdfe82f
commit
e3f895d7ef
|
@ -268,7 +268,6 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len)
|
|||
#endif /* !MCUBOOT_HW_KEY */
|
||||
#endif
|
||||
|
||||
#ifdef MCUBOOT_HW_ROLLBACK_PROT
|
||||
/**
|
||||
* Reads the value of an image's security counter.
|
||||
*
|
||||
|
@ -328,7 +327,6 @@ bootutil_get_img_security_cnt(struct image_header *hdr,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MCUBOOT_HW_ROLLBACK_PROT */
|
||||
|
||||
/*
|
||||
* Verify the integrity of the image.
|
||||
|
|
|
@ -616,7 +616,7 @@ boot_check_header_erased(struct boot_loader_state *state, int slot)
|
|||
#if (BOOT_IMAGE_NUMBER > 1) || \
|
||||
defined(MCUBOOT_DIRECT_XIP) || \
|
||||
defined(MCUBOOT_RAM_LOAD) || \
|
||||
(defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION))
|
||||
defined(MCUBOOT_DOWNGRADE_PREVENTION)
|
||||
/**
|
||||
* Compare image version numbers not including the build number
|
||||
*
|
||||
|
@ -1905,6 +1905,60 @@ boot_update_hw_rollback_protection(struct boot_loader_state *state)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks test swap downgrade prevention conditions.
|
||||
*
|
||||
* Function called only for swap upgrades test run. It may prevent
|
||||
* swap if slot 1 image has <= version number or < security counter
|
||||
*
|
||||
* @param state Boot loader status information.
|
||||
*
|
||||
* @return 0 - image can be swapped, -1 downgrade prevention
|
||||
*/
|
||||
static int
|
||||
check_downgrade_prevention(struct boot_loader_state *state)
|
||||
{
|
||||
#if defined(MCUBOOT_DOWNGRADE_PREVENTION) && \
|
||||
(defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH))
|
||||
uint32_t security_counter[2];
|
||||
int rc;
|
||||
|
||||
if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) {
|
||||
/* If there was security no counter in slot 0, allow swap */
|
||||
rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 0).hdr),
|
||||
BOOT_IMG(state, 0).area,
|
||||
&security_counter[0]);
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
}
|
||||
/* If there is no security counter in slot 1, or it's lower than
|
||||
* that of slot 0, prevent downgrade */
|
||||
rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 1).hdr),
|
||||
BOOT_IMG(state, 1).area,
|
||||
&security_counter[1]);
|
||||
if (rc != 0 || security_counter[0] > security_counter[1]) {
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rc = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver,
|
||||
&boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver);
|
||||
}
|
||||
if (rc < 0) {
|
||||
/* Image in slot 0 prevents downgrade, delete image in slot 1 */
|
||||
BOOT_LOG_INF("Image in slot 1 erased due to downgrade prevention");
|
||||
flash_area_erase(BOOT_IMG(state, 1).area, 0,
|
||||
flash_area_get_size(BOOT_IMG(state, 1).area));
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
#else
|
||||
(void)state;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
fih_int
|
||||
context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
|
||||
{
|
||||
|
@ -2033,7 +2087,13 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
|
|||
case BOOT_SWAP_TYPE_NONE:
|
||||
break;
|
||||
|
||||
case BOOT_SWAP_TYPE_TEST: /* fallthrough */
|
||||
case BOOT_SWAP_TYPE_TEST:
|
||||
if (check_downgrade_prevention(state) != 0) {
|
||||
/* Downgrade prevented */
|
||||
BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case BOOT_SWAP_TYPE_PERM: /* fallthrough */
|
||||
case BOOT_SWAP_TYPE_REVERT:
|
||||
rc = BOOT_HOOK_CALL(boot_perform_update_hook, BOOT_HOOK_REGULAR,
|
||||
|
|
|
@ -85,6 +85,19 @@
|
|||
#if MYNEWT_VAL(BOOTUTIL_BOOTSTRAP)
|
||||
#define MCUBOOT_BOOTSTRAP 1
|
||||
#endif
|
||||
#if MYNEWT_VAL_CHOICE(BOOTUTIL_DOWNGRADE_PREVENTION, version)
|
||||
#define MCUBOOT_DOWNGRADE_PREVENTION 1
|
||||
/* MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER is used later as bool value so it is
|
||||
* always defined, (unlike MCUBOOT_DOWNGRADE_PREVENTION which is only used in
|
||||
* preprocessor condition and my be not defined) */
|
||||
#define MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER 0
|
||||
#elif MYNEWT_VAL_CHOICE(BOOTUTIL_DOWNGRADE_PREVENTION, security_counter)
|
||||
#define MCUBOOT_DOWNGRADE_PREVENTION 1
|
||||
#define MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER 1
|
||||
#endif
|
||||
#if MYNEWT_VAL(BOOTUTIL_HW_DOWNGRADE_PREVENTION)
|
||||
#define MCUBOOT_HW_ROLLBACK_PROT 1
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(MCUBOOT_MEASURED_BOOT)
|
||||
#define MCUBOOT_MEASURED_BOOT 1
|
||||
|
|
|
@ -76,6 +76,34 @@ syscfg.defs:
|
|||
BOOTUTIL_MAX_IMG_SECTORS:
|
||||
description: 'Maximum number of sectors that are swapped.'
|
||||
value: 128
|
||||
BOOTUTIL_DOWNGRADE_PREVENTION:
|
||||
description: >
|
||||
Select downgrade prevention strategy.
|
||||
- none downgrades are allowed
|
||||
- version:
|
||||
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).
|
||||
- security_counter:
|
||||
security counter is used for version eligibility check instead of pure
|
||||
version. When this option is set, any upgrade must have greater or
|
||||
equal security counter value.
|
||||
Because of the acceptance of equal values it allows for software
|
||||
downgrades to some extent.
|
||||
choices:
|
||||
- none
|
||||
- version
|
||||
- security_counter
|
||||
value: none
|
||||
BOOTUTIL_HW_ROLLBACK_PROT:
|
||||
description: >
|
||||
Prevent undesirable/malicious software downgrades. When this option is
|
||||
set, any upgrade must have greater or equal security counter value.
|
||||
Because of the acceptance of equal values it allows for software
|
||||
downgrade to some extent
|
||||
value: 0
|
||||
BOOTUTIL_HAVE_LOGGING:
|
||||
description: 'Enable serial logging'
|
||||
value: 0
|
||||
|
|
Loading…
Reference in New Issue