diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index f47ec4e2a0..ffd2456a79 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -2246,18 +2246,26 @@ boot_update_hw_rollback_protection(struct boot_loader_state *state) { #ifdef MCUBOOT_HW_ROLLBACK_PROT int rc; + uint8_t image_index; + struct boot_swap_state swap_state; + + image_index = BOOT_CURR_IMG(state); + + rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(image_index), &swap_state); + if (rc != 0) { + return rc; + } /* Update the stored security counter with the active image's security - * counter value. It will only be updated if the new security counter is - * greater than the stored value. - * - * In case of a successful image swapping when the swap type is TEST the - * security counter can be increased only after a reset, when the swap - * type is NONE and the image has marked itself "OK" (the image_ok flag - * has been set). This way a "revert" can be performed when it's - * necessary. - */ - if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) { + * counter value. It will only be updated if the new security counter is + * greater than the stored value. + * + * In case of a successful image swapping when the swap type is TEST the + * security counter can be increased only after a reset, when the image has + * marked itself "OK" (the image_ok flag has been set). This way a "revert" + * can be performed when it's necessary. + */ + if (swap_state.magic != BOOT_MAGIC_GOOD || swap_state.image_ok == BOOT_FLAG_SET) { rc = boot_update_security_counter(state, BOOT_PRIMARY_SLOT, BOOT_PRIMARY_SLOT); if (rc != 0) { BOOT_LOG_ERR("Security counter update failed after image " diff --git a/sim/mcuboot-sys/src/api.rs b/sim/mcuboot-sys/src/api.rs index 0a098ffb3f..56c685cd7f 100644 --- a/sim/mcuboot-sys/src/api.rs +++ b/sim/mcuboot-sys/src/api.rs @@ -388,3 +388,13 @@ pub extern "C" fn sim_get_nv_counter_for_image(image_index: u32, security_counte }); return rc; } + +pub fn sim_reset_nv_counters() { + NV_COUNTER_CTX.with(|ctx| { + let mut counter_storage = ctx.borrow_mut(); + + for i in 0..counter_storage.storage.len() { + counter_storage.storage[i] = 0; + } + }); +} diff --git a/sim/mcuboot-sys/src/c.rs b/sim/mcuboot-sys/src/c.rs index 9d2a321b7e..2643866ae5 100644 --- a/sim/mcuboot-sys/src/c.rs +++ b/sim/mcuboot-sys/src/c.rs @@ -166,6 +166,10 @@ pub fn get_security_counter(image_index: u32) -> u32 { return counter_val; } +pub fn reset_security_counters() { + api::sim_reset_nv_counters(); +} + mod raw { use crate::area::CAreaDesc; use crate::api::{BootRsp, CSimContext}; diff --git a/sim/src/image.rs b/sim/src/image.rs index a8f3604712..14e59d6224 100644 --- a/sim/src/image.rs +++ b/sim/src/image.rs @@ -239,7 +239,7 @@ impl ImagesBuilder { let upgr = match deps.depends[image_num] { DepType::NoUpgrade => install_no_image(), _ => install_image(&mut flash, &self.areadesc, &slots, 1, - maximal(46928), &ram, &*dep, ImageManipulation::BadSignature, Some(0)) + maximal(46928), &ram, &*dep, ImageManipulation::BadSignature, Some(1)) }; (prim, upgr) } else { @@ -248,7 +248,7 @@ impl ImagesBuilder { let upgr = match deps.depends[image_num] { DepType::NoUpgrade => install_no_image(), _ => install_image(&mut flash, &self.areadesc, &slots, 1, - maximal(46928), &ram, &*dep, img_manipulation, Some(0)) + maximal(46928), &ram, &*dep, img_manipulation, Some(1)) }; (prim, upgr) }; @@ -289,6 +289,10 @@ impl ImagesBuilder { } }; + // As a side effect, the upgrade performed above has updated the security counters. Reset + // them to their original value. + c::reset_security_counters(); + images.total_count = Some(total_count); images } diff --git a/sim/tests/core.rs b/sim/tests/core.rs index c246aa848b..0e7687ad78 100644 --- a/sim/tests/core.rs +++ b/sim/tests/core.rs @@ -21,6 +21,7 @@ use std::{ env, sync::atomic::{AtomicUsize, Ordering}, }; +use mcuboot_sys::c; /// A single test, after setting up logging and such. Within the $body, /// $arg will be bound to each device. @@ -90,6 +91,7 @@ test_shell!(dependency_combos, r, { let image = r.clone().make_image(&dep, true); dump_image(&image, "dependency_combos"); assert!(!image.run_check_deps(&dep)); + c::reset_security_counters(); } });