Add config option for caching of validation state of an image in primary slot for single loader
Signed-off-by: Wouter Cappelle <wouter.cappelle@crodeon.com>
diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c
index 7209474..7c1d0d9 100644
--- a/boot/boot_serial/src/boot_serial.c
+++ b/boot/boot_serial/src/boot_serial.c
@@ -333,6 +333,14 @@
if (data_len > flash_area_get_size(fap)) {
goto out_invalid_data;
}
+#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE)
+ /* We are using swap state at end of flash area to store validation
+ * result. Make sure the user cannot write it from an image to skip validation.
+ */
+ if (data_len > (flash_area_get_size(fap) - BOOT_MAGIC_SZ)) {
+ goto out_invalid_data;
+ }
+#endif
#ifndef MCUBOOT_ERASE_PROGRESSIVELY
rc = flash_area_erase(fap, 0, flash_area_get_size(fap));
if (rc) {
diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig
index 1d16b03..0d32431 100644
--- a/boot/zephyr/Kconfig
+++ b/boot/zephyr/Kconfig
@@ -182,6 +182,18 @@
every boot, but can mitigate against some changes that are
able to modify the flash image itself.
+config BOOT_VALIDATE_SLOT0_ONCE
+ bool "Validate image in the primary slot just once after after upgrade"
+ depends on !BOOT_VALIDATE_SLOT0 && SINGLE_APPLICATION_SLOT
+ default n
+ help
+ If y, the bootloader attempts to validate the signature of the
+ primary slot only once after an upgrade of the main slot.
+ It caches the result in the magic area, which makes it an unsecure
+ method. This option is usefull for lowering the boot up time for
+ low end devices with as a compromise lowering the security level.
+ If unsure, leave at the default value.
+
if !SINGLE_APPLICATION_SLOT
choice BOOT_IMAGE_UPGRADE_MODE
prompt "Image upgrade modes"
diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h
index a737a17..2539b5f 100644
--- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h
+++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h
@@ -61,6 +61,10 @@
#define MCUBOOT_VALIDATE_PRIMARY_SLOT
#endif
+#ifdef CONFIG_BOOT_VALIDATE_SLOT0_ONCE
+#define MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE
+#endif
+
#ifdef CONFIG_BOOT_UPGRADE_ONLY
#define MCUBOOT_OVERWRITE_ONLY
#define MCUBOOT_OVERWRITE_ONLY_FAST
diff --git a/boot/zephyr/single_loader.c b/boot/zephyr/single_loader.c
index 643977f..260f9cc 100644
--- a/boot/zephyr/single_loader.c
+++ b/boot/zephyr/single_loader.c
@@ -58,6 +58,37 @@
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT || MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE*/
+inline static fih_int
+boot_image_validate_once(const struct flash_area *fa_p,
+ struct image_header *hdr)
+{
+ static struct boot_swap_state state;
+ int rc;
+ fih_int fih_rc = FIH_FAILURE;
+
+ memset(&state, 0, sizeof(struct boot_swap_state));
+ rc = boot_read_swap_state(fa_p, &state);
+ if (rc != 0)
+ FIH_RET(FIH_FAILURE);
+ if (state.magic != BOOT_MAGIC_GOOD
+ || state.image_ok != BOOT_FLAG_SET) {
+ /* At least validate the image once */
+ FIH_CALL(boot_image_validate, fih_rc, fa_p, hdr);
+ if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
+ FIH_RET(FIH_FAILURE);
+ }
+ if (state.magic != BOOT_MAGIC_GOOD) {
+ rc = boot_write_magic(fa_p);
+ if (rc != 0)
+ FIH_RET(FIH_FAILURE);
+ }
+ rc = boot_write_image_ok(fa_p);
+ if (rc != 0)
+ FIH_RET(FIH_FAILURE);
+ }
+ FIH_RET(FIH_SUCCESS);
+}
+
/**
* Attempts to load image header from flash; verifies flash header fields.
*
@@ -421,6 +452,11 @@
if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
goto out;
}
+#elif defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE)
+ FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr);
+ if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
+ goto out;
+ }
#else
fih_rc = FIH_SUCCESS;
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */