diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 9be80f0d..68913948 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -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. diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 24dcab4c..e59fad78 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -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, diff --git a/boot/mynewt/mcuboot_config/include/mcuboot_config/mcuboot_config.h b/boot/mynewt/mcuboot_config/include/mcuboot_config/mcuboot_config.h index 980eda9d..f02e40d5 100644 --- a/boot/mynewt/mcuboot_config/include/mcuboot_config/mcuboot_config.h +++ b/boot/mynewt/mcuboot_config/include/mcuboot_config/mcuboot_config.h @@ -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 diff --git a/boot/mynewt/mcuboot_config/syscfg.yml b/boot/mynewt/mcuboot_config/syscfg.yml index 74570f21..b2e58689 100644 --- a/boot/mynewt/mcuboot_config/syscfg.yml +++ b/boot/mynewt/mcuboot_config/syscfg.yml @@ -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