Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,14 @@ tools/unit-tests/unit-ubootenv
tools/unit-tests/unit-cm4-sdhci
tools/unit-tests/unit-imx95-ahab
tools/unit-tests/unit-cm4-rauc-slot
tools/unit-tests/stm32h7s_write_extract.h
tools/unit-tests/unit-flash-erase-h7s
tools/unit-tests/unit-flash-erase-mcxw
tools/unit-tests/unit-linux-loader-initrd
tools/unit-tests/unit-stm32h7s-write
tools/unit-tests/unit-update-disk-fit-ramdisk
tools/unit-tests/unit-update-disk-golden
tools/unit-tests/unit-update-ram-fit
tools/unit-tests/__pycache__/*


Expand Down
2 changes: 2 additions & 0 deletions config/examples/sim-self-update-monolithic.config
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ DEBUG=1
RAM_CODE=1
SELF_UPDATE_MONOLITHIC=1
WOLFBOOT_VERSION=1
# Sign the debug-stripped app so it fits the BOOT share of the install span
STRIP_ELF=1

# Asymmetric layout: BOOT only holds the app; UPDATE stages the monolithic
# payload. UPDATE (0x80000) matches the install span (bootloader region
Expand Down
1 change: 1 addition & 0 deletions include/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,7 @@ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part);
int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, uint8_t* addr);
#endif
int wolfBoot_open_image_address(struct wolfBoot_image* img, uint8_t* image);
int wolfBoot_image_part_matches(struct wolfBoot_image *img);
#ifdef WOLFBOOT_SELF_HEADER
int wolfBoot_open_self(struct wolfBoot_image *img);
int wolfBoot_open_self_address(struct wolfBoot_image *img, uint8_t *hdr,
Expand Down
24 changes: 24 additions & 0 deletions src/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,30 @@ int wolfBoot_open_self_address(struct wolfBoot_image* img, uint8_t* hdr,
}
#endif

/**
* @brief Check that an opened image targets this wolfBoot's partition.
* @param img The opened image (hdr must point to a valid header).
* @return 0 if the image targets this core's partition, -1 otherwise.
*/
int wolfBoot_image_part_matches(struct wolfBoot_image *img)
{
uint8_t *type_field = NULL;
uint16_t image_type;

if (img == NULL || img->hdr == NULL) {
return -1;
}
if (wolfBoot_find_header(img->hdr + IMAGE_HEADER_OFFSET, HDR_IMG_TYPE,
&type_field) != WOLFBOOT_HDR_U16_SZ) {
return -1;
}
image_type = (uint16_t)(type_field[0] + (type_field[1] << 8));
if ((image_type & HDR_IMG_TYPE_PART_MASK) != HDR_IMG_TYPE_APP) {
return -1;
}
return 0;
}

/**
* @brief Verify the integrity of the image using the stored SHA hash.
*
Expand Down
12 changes: 12 additions & 0 deletions src/update_disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,18 @@ void RAMFUNCTION wolfBoot_start(void)
continue;
}

/* The image must target this core's partition: the key mask only
* restricts which partition ids the signing key may claim, not
* which core boots the image. Reject before the payload read so a
* foreign image never drives the disk read into the RAM load
* region. */
if (wolfBoot_image_part_matches(&os_image) < 0) {
Comment thread
danielinux marked this conversation as resolved.
wolfBoot_printf("Image partition mismatch for %s\r\n",
part_name);
selected ^= 1;
continue;
}

/* Bound the UNAUTHENTICATED image length before it drives the disk
* read into the RAM load region. An attacker controlling the boot
* media could otherwise declare an arbitrary fw_size and overrun the
Expand Down
4 changes: 4 additions & 0 deletions src/update_flash_hwswap.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ void RAMFUNCTION wolfBoot_start(void)
}
#endif
if ((wolfBoot_open_image(&fw_image, active) < 0)
/* The image must target this core's partition; the key mask
* alone does not bind the claimed role to the execution
* context. Short-circuits when the open above failed. */
|| (wolfBoot_image_part_matches(&fw_image) < 0)
#ifndef WOLFBOOT_SKIP_BOOT_VERIFY
|| (wolfBoot_verify_integrity(&fw_image) < 0)
|| (wolfBoot_verify_authenticity(&fw_image) < 0)
Expand Down
11 changes: 11 additions & 0 deletions src/update_ram.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,17 @@ void RAMFUNCTION wolfBoot_start(void)
goto backup_on_failure;
}

/* The image must target the partition this wolfBoot instance is
* responsible for booting: the key mask only restricts which
* partition ids the signing key may claim, not which core boots
* the image. Runs even with WOLFBOOT_SKIP_BOOT_VERIFY, as it is a
* header binding check, not a crypto verification. */
ret = wolfBoot_image_part_matches(&os_image);
if (ret < 0) {
wolfBoot_printf("Image partition mismatch\n");
goto backup_on_failure;
}

#ifndef WOLFBOOT_SKIP_BOOT_VERIFY
/* Verify image integrity (hash check) */
wolfBoot_printf("Checking integrity...");
Expand Down
85 changes: 85 additions & 0 deletions tools/unit-tests/unit-image.c
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,83 @@ START_TEST(test_verify_authenticity_allows_permitted_key_mask)
END_TEST
#endif /* WOLFBOOT_FIXED_PARTITIONS */

#if defined(WOLFBOOT_SIGN_ECC256) && defined(WOLFBOOT_HASH_SHA256)
START_TEST(test_image_part_matches_app)
{
struct wolfBoot_image test_img;
uint8_t buf[sizeof(test_img_v200000000_signed_bin)];
int ret;

memcpy(buf, test_img_v200000000_signed_bin, sizeof(buf));

find_header_mocked = 0;
memset(&test_img, 0, sizeof(test_img));
test_img.hdr = buf;
ret = wolfBoot_image_part_matches(&test_img);
ck_assert_int_eq(ret, 0);
}
END_TEST

START_TEST(test_image_part_matches_rejects_foreign)
{
struct wolfBoot_image test_img;
uint8_t buf[sizeof(test_img_v200000000_signed_bin)];
int ret;

memcpy(buf, test_img_v200000000_signed_bin, sizeof(buf));
patch_image_type_part(buf, sizeof(buf), 2);

find_header_mocked = 0;
memset(&test_img, 0, sizeof(test_img));
test_img.hdr = buf;
ret = wolfBoot_image_part_matches(&test_img);
ck_assert_int_eq(ret, -1);
}
END_TEST

START_TEST(test_image_part_matches_rejects_wolfboot)
{
struct wolfBoot_image test_img;
uint8_t buf[sizeof(test_img_v200000000_signed_bin)];
int ret;

memcpy(buf, test_img_v200000000_signed_bin, sizeof(buf));
patch_image_type_part(buf, sizeof(buf), HDR_IMG_TYPE_WOLFBOOT);

find_header_mocked = 0;
memset(&test_img, 0, sizeof(test_img));
test_img.hdr = buf;
ret = wolfBoot_image_part_matches(&test_img);
ck_assert_int_eq(ret, -1);
}
END_TEST

START_TEST(test_image_part_matches_null)
{
struct wolfBoot_image test_img;
uint8_t buf[sizeof(test_img_v200000000_signed_bin)];
int ret;

ret = wolfBoot_image_part_matches(NULL);
ck_assert_int_eq(ret, -1);

memcpy(buf, test_img_v200000000_signed_bin, sizeof(buf));
memset(&test_img, 0, sizeof(test_img));
ret = wolfBoot_image_part_matches(&test_img);
ck_assert_int_eq(ret, -1);

/* type field lookup fails (missing HDR_IMG_TYPE) */
test_img.hdr = buf;
find_header_mocked = 1;
find_header_fail = 1;
ret = wolfBoot_image_part_matches(&test_img);
ck_assert_int_eq(ret, -1);
find_header_fail = 0;
find_header_mocked = 0;
}
END_TEST
#endif /* WOLFBOOT_SIGN_ECC256 && WOLFBOOT_HASH_SHA256 */

#if defined(UNIT_IMAGE_HYBRID_ONLY) && defined(SIGN_HYBRID) && \
defined(WOLFBOOT_SIGN_SECONDARY_ECC256)
START_TEST(test_verify_authenticity_hybrid_direct_call_uses_verified_sha)
Expand Down Expand Up @@ -1383,6 +1460,14 @@ Suite *wolfboot_suite(void)
tcase_add_test(tcase_verify_authenticity,
test_verify_authenticity_allows_permitted_key_mask);
#endif /* WOLFBOOT_FIXED_PARTITIONS */
#if defined(WOLFBOOT_HASH_SHA256)
tcase_add_test(tcase_verify_authenticity, test_image_part_matches_app);
tcase_add_test(tcase_verify_authenticity,
test_image_part_matches_rejects_foreign);
tcase_add_test(tcase_verify_authenticity,
test_image_part_matches_rejects_wolfboot);
tcase_add_test(tcase_verify_authenticity, test_image_part_matches_null);
#endif /* WOLFBOOT_HASH_SHA256 */
suite_add_tcase(s, tcase_verify_authenticity);
#endif

Expand Down
7 changes: 7 additions & 0 deletions tools/unit-tests/unit-update-disk-confirm.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ static int mock_verify_integrity_ret;
static int mock_integrity_saw_not_ext;
static int mock_authenticity_saw_not_ext;
static int mock_verify_authenticity_ret;
static int mock_image_part_matches_ret;
static int mock_state_writes;

ChaCha chacha;
Expand Down Expand Up @@ -256,6 +257,12 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image* img)
return mock_verify_authenticity_ret;
}

int wolfBoot_image_part_matches(struct wolfBoot_image* img)
{
(void)img;
return mock_image_part_matches_ret;
}

int wolfBoot_get_dts_size(void *dts_addr, uint32_t capacity)
{
(void)capacity;
Expand Down
6 changes: 6 additions & 0 deletions tools/unit-tests/unit-update-disk-failover.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image* img)
return 0;
}

int wolfBoot_image_part_matches(struct wolfBoot_image* img)
{
(void)img;
return 0;
}

int wolfBoot_get_dts_size(void *dts_addr, uint32_t capacity)
{
(void)capacity; (void)dts_addr;
Expand Down
6 changes: 6 additions & 0 deletions tools/unit-tests/unit-update-disk-fit.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image* img)
return 0;
}

int wolfBoot_image_part_matches(struct wolfBoot_image* img)
{
(void)img;
return 0;
}

/* The loaded payload is treated as a FIT container, and the sub-image
* returned by fit_load_image() is a flat device tree whose parsed
* size is mock_dts_size. */
Expand Down
6 changes: 6 additions & 0 deletions tools/unit-tests/unit-update-disk-fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,12 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
return mock_verify_authenticity_ret;
}

int wolfBoot_image_part_matches(struct wolfBoot_image *img)
{
(void)img;
return 0;
}

/* Parses the single version TLV that build_image() writes. */
uint32_t wolfBoot_get_blob_version(uint8_t *blob)
{
Expand Down
6 changes: 6 additions & 0 deletions tools/unit-tests/unit-update-disk-fsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image* img)
return 0;
}

int wolfBoot_image_part_matches(struct wolfBoot_image* img)
{
(void)img;
return 0;
}

int wolfBoot_get_dts_size(void *dts_addr, uint32_t capacity)
{
(void)capacity;
Expand Down
6 changes: 6 additions & 0 deletions tools/unit-tests/unit-update-disk-golden.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image* img)
return 0;
}

int wolfBoot_image_part_matches(struct wolfBoot_image* img)
{
(void)img;
return 0;
}

int wolfBoot_get_dts_size(void *dts_addr, uint32_t capacity)
{
(void)capacity; (void)dts_addr;
Expand Down
7 changes: 7 additions & 0 deletions tools/unit-tests/unit-update-disk-oob.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static int mock_do_boot_called;
static const uint32_t *mock_boot_address;
static int mock_verify_integrity_ret;
static int mock_verify_authenticity_ret;
static int mock_image_part_matches_ret;
static int mock_flash_protect_called;
static haladdr_t mock_flash_protect_addr;
static int mock_flash_protect_len;
Expand Down Expand Up @@ -215,6 +216,12 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image* img)
return mock_verify_authenticity_ret;
}

int wolfBoot_image_part_matches(struct wolfBoot_image* img)
{
(void)img;
return mock_image_part_matches_ret;
}

int wolfBoot_get_dts_size(void *dts_addr, uint32_t capacity)
{
(void)capacity;
Expand Down
Loading
Loading