Commit bb7a39d1 authored by Wouter Cappelle's avatar Wouter Cappelle Committed by David Brown
Browse files

Add config option for caching of validation state of an image in primary slot for single loader

parent b6d5cf35
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -333,6 +333,14 @@ bs_upload(char *buf, int len)
        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) {
+12 −0
Original line number Diff line number Diff line
@@ -182,6 +182,18 @@ config BOOT_VALIDATE_SLOT0
	  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"
+4 −0
Original line number Diff line number Diff line
@@ -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
+36 −0
Original line number Diff line number Diff line
@@ -58,6 +58,37 @@ boot_image_validate(const struct flash_area *fa_p,
#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 @@ boot_go(struct boot_rsp *rsp)
    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 */
+9 −0
Original line number Diff line number Diff line
@@ -1147,6 +1147,15 @@ an image:
    keys will then be iterated over looking for the matching key, which then
    will then be used to verify the image contents.

For low performance MCU's where the validation is a heavy process at boot
(~1-2 seconds on a arm-cortex-M0), the `MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE`
could be used. This option will cache the validation result as described above
into the magic area of the primary slot. The next boot, the validation will be
skipped if the previous validation was succesfull. This option is reducing the
security level since if an attacker could modify the contents of the flash after
a good image has been validated, the attacker could run his own image without
running validation again. Enabling this option should be done with care.

## [Security](#security)

As indicated above, the final step of the integrity check is signature