mirror of https://github.com/wolfSSL/wolfBoot.git
armored: harden fw_base against fault injection
parent
277cbbe4f8
commit
eca9a20b3b
|
|
@ -173,6 +173,7 @@ struct wolfBoot_image {
|
|||
uint32_t sha_ok;
|
||||
uint32_t canary_FEEDCAFE;
|
||||
uint32_t not_sha_ok;
|
||||
uintptr_t not_fw_base; /* complement of fw_base, for FI hardening */
|
||||
uint32_t not_ext; /* image is no longer external */
|
||||
};
|
||||
|
||||
|
|
@ -229,6 +230,18 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_sha_ok(
|
|||
img->not_sha_ok = 1UL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the image entry base together with its complement, so that a single
|
||||
* fault on the pointer that do_boot() jumps through can be detected by
|
||||
* FW_BASE_SANITY_CHECK() before the branch is taken.
|
||||
*/
|
||||
static void NOINLINEFUNCTION wolfBoot_image_set_fw_base(
|
||||
struct wolfBoot_image *img, void *base)
|
||||
{
|
||||
img->fw_base = (uint8_t *)base;
|
||||
img->not_fw_base = ~(uintptr_t)base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Final sanity check, performed just before do_boot, or before starting an
|
||||
* update that has been verified.
|
||||
|
|
@ -757,6 +770,40 @@ static void NOINLINEFUNCTION wolfBoot_image_clear_sha_ok(
|
|||
asm volatile("cmp r2, #0xFFFFFFFE":::"cc"); \
|
||||
asm volatile("bne .-12")
|
||||
|
||||
/**
|
||||
* Hardened assertion that the image entry base is consistent with its stored
|
||||
* complement (fw_base == ~not_fw_base), performed immediately before do_boot()
|
||||
* dereferences fw_base. A single fault on either the pointer or the loads
|
||||
* fails the check safely (spins) instead of redirecting the boot jump.
|
||||
*/
|
||||
#define FW_BASE_SANITY_CHECK(p) \
|
||||
/* Redundant set of r2=0 */ \
|
||||
asm volatile("mov r2, #0":::"r2"); \
|
||||
asm volatile("mov r2, #0":::"r2"); \
|
||||
asm volatile("mov r2, #0":::"r2"); \
|
||||
asm volatile("mov r2, #0":::"r2"); \
|
||||
asm volatile("mov r2, #0":::"r2"); \
|
||||
/* r2 = fw_base, r0 = ~not_fw_base (== expected fw_base) */ \
|
||||
asm volatile("mov r2, %0" ::"r"((uintptr_t)(p)->fw_base):"r2"); \
|
||||
asm volatile("mov r0, %0" ::"r"((p)->not_fw_base):"r0"); \
|
||||
asm volatile("mvn r0, r0":::"r0"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("bne ."); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("bne .-4"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("bne .-8"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("cmp r2, r0":::"cc"); \
|
||||
asm volatile("bne .-12")
|
||||
|
||||
/**
|
||||
* ECC / Ed / PQ signature verification.
|
||||
* Those verify functions set an additional value 'p_res'
|
||||
|
|
@ -1521,6 +1568,11 @@ static void UNUSEDFUNCTION wolfBoot_image_clear_sha_ok(
|
|||
{
|
||||
img->sha_ok = 0;
|
||||
}
|
||||
static void UNUSEDFUNCTION wolfBoot_image_set_fw_base(
|
||||
struct wolfBoot_image *img, void *base)
|
||||
{
|
||||
img->fw_base = (uint8_t *)base;
|
||||
}
|
||||
|
||||
#define likely(x) (x)
|
||||
#define unlikely(x) (x)
|
||||
|
|
@ -1560,6 +1612,8 @@ static void UNUSEDFUNCTION wolfBoot_image_clear_sha_ok(
|
|||
if ((p)->sha_ok != 1) \
|
||||
wolfBoot_panic()
|
||||
|
||||
#define FW_BASE_SANITY_CHECK(p) do{} while(0)
|
||||
|
||||
#define CONFIRM_MASK_VALID(id, mask) \
|
||||
if ((mask & (1UL << id)) != (1UL << id)) \
|
||||
wolfBoot_panic()
|
||||
|
|
|
|||
|
|
@ -1424,7 +1424,7 @@ int wolfBoot_open_image_address(struct wolfBoot_image *img, uint8_t *image)
|
|||
}
|
||||
#endif
|
||||
img->hdr_ok = 1;
|
||||
img->fw_base = img->hdr + IMAGE_HEADER_SIZE;
|
||||
wolfBoot_image_set_fw_base(img, img->hdr + IMAGE_HEADER_SIZE);
|
||||
#ifdef EXT_FLASH
|
||||
img->hdr_cache = image;
|
||||
#endif
|
||||
|
|
@ -1488,7 +1488,7 @@ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part)
|
|||
if (part == PART_SWAP) {
|
||||
img->hdr = (void*)WOLFBOOT_PARTITION_SWAP_ADDRESS;
|
||||
img->hdr_ok = 1;
|
||||
img->fw_base = img->hdr;
|
||||
wolfBoot_image_set_fw_base(img, img->hdr);
|
||||
img->fw_size = WOLFBOOT_SECTOR_SIZE;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1507,7 +1507,7 @@ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part)
|
|||
if (ret < 0)
|
||||
return -1;
|
||||
img->hdr_ok = 1;
|
||||
img->fw_base = img->hdr;
|
||||
wolfBoot_image_set_fw_base(img, img->hdr);
|
||||
img->fw_size = (uint32_t)ret;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1620,7 +1620,7 @@ int wolfBoot_open_self_address(struct wolfBoot_image* img, uint8_t* hdr,
|
|||
return -1;
|
||||
}
|
||||
#endif
|
||||
img->fw_base = image;
|
||||
wolfBoot_image_set_fw_base(img, image);
|
||||
img->part = PART_SELF;
|
||||
img->hdr_ok = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -1270,7 +1270,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
|
|||
wolfBoot_printf(
|
||||
"Scattered image correctly verified. Setting entry point to %lx\n",
|
||||
entry);
|
||||
boot.fw_base = (void*)entry;
|
||||
wolfBoot_image_set_fw_base(&boot, (void*)entry);
|
||||
#endif
|
||||
/* Direct Swap without power fail safety */
|
||||
|
||||
|
|
@ -1618,7 +1618,7 @@ void RAMFUNCTION wolfBoot_start(void)
|
|||
wolfBoot_printf(
|
||||
"Scattered image correctly verified. Setting entry point to %lx\n",
|
||||
entry);
|
||||
boot.fw_base = (void*)entry;
|
||||
wolfBoot_image_set_fw_base(&boot, (void*)entry);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1650,6 +1650,7 @@ void RAMFUNCTION wolfBoot_start(void)
|
|||
#endif
|
||||
#ifndef WOLFBOOT_SKIP_BOOT_VERIFY
|
||||
PART_SANITY_CHECK(&boot);
|
||||
FW_BASE_SANITY_CHECK(&boot);
|
||||
#endif
|
||||
do_boot((void *)boot.fw_base);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue