Skip to content

Commit 08c8bdd

Browse files
authored
Merge pull request #802 from rizlik/fix_oob_ramboot
fix: bound unauthenticated image size before RAM load
2 parents 1ba037a + 4a1fc49 commit 08c8bdd

4 files changed

Lines changed: 488 additions & 8 deletions

File tree

src/libwolfboot.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2376,6 +2376,17 @@ int RAMFUNCTION ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len
23762376
#endif /* __WOLFBOOT */
23772377

23782378
#if defined(MMU)
2379+
/* The decrypt loop in wolfBoot_ram_decrypt() copies in ENCRYPT_BLOCK_SIZE
2380+
* granules, rounding the final write up to a block boundary. The size bound is
2381+
* only safe if the RAM load region is itself block-aligned; assert that where
2382+
* the region size is a compile-time constant (a macro in every such config). */
2383+
#if defined(WOLFBOOT_FIXED_PARTITIONS) && defined(WOLFBOOT_PARTITION_SIZE)
2384+
typedef char wolfBoot_ramboot_blockalign_check[
2385+
((WOLFBOOT_PARTITION_SIZE) % ENCRYPT_BLOCK_SIZE == 0) ? 1 : -1];
2386+
#elif defined(WOLFBOOT_RAMBOOT_MAX_SIZE)
2387+
typedef char wolfBoot_ramboot_blockalign_check[
2388+
((WOLFBOOT_RAMBOOT_MAX_SIZE) % ENCRYPT_BLOCK_SIZE == 0) ? 1 : -1];
2389+
#endif
23792390
/**
23802391
* @brief Decrypt data from RAM.
23812392
*
@@ -2406,7 +2417,32 @@ int wolfBoot_ram_decrypt(uint8_t *src, uint8_t *dst)
24062417
wolfBoot_printf("Error decrypting header at %p!\n", src);
24072418
return -1;
24082419
}
2409-
len = *((uint32_t*)(dec_hdr + sizeof(uint32_t)));
2420+
/* dec_hdr is a byte buffer: copy the little-endian length field without an
2421+
* unaligned cast, then convert to native byte order. */
2422+
XMEMCPY(&len, dec_hdr + sizeof(uint32_t), sizeof(len));
2423+
len = im2n(len);
2424+
2425+
#if !defined(WOLFBOOT_FIXED_PARTITIONS) && !defined(WOLFBOOT_RAMBOOT_MAX_SIZE)
2426+
# error "WOLFBOOT_FIXED_PARTITIONS or WOLFBOOT_RAMBOOT_MAX_SIZE required to bound the RAM load"
2427+
#endif
2428+
/* Bound the UNAUTHENTICATED image length before it drives the copy into the
2429+
* RAM load region: the image is loaded to RAM before its signature is
2430+
* verified, so this length (read from the not-yet-authenticated header) is
2431+
* attacker-influenceable and must be range checked first. When both are
2432+
* configured, WOLFBOOT_RAMBOOT_MAX_SIZE takes precedence: it is the explicit
2433+
* cap on the RAM load region and may be tighter than the partition size. */
2434+
#if defined(WOLFBOOT_RAMBOOT_MAX_SIZE)
2435+
if (len > WOLFBOOT_RAMBOOT_MAX_SIZE) {
2436+
wolfBoot_printf("Invalid encrypted image size %u at %p\n", len, src);
2437+
return -1;
2438+
}
2439+
#elif defined(WOLFBOOT_FIXED_PARTITIONS)
2440+
if (WOLFBOOT_PARTITION_SIZE <= IMAGE_HEADER_SIZE ||
2441+
len > (uint32_t)(WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) {
2442+
wolfBoot_printf("Invalid encrypted image size %u at %p\n", len, src);
2443+
return -1;
2444+
}
2445+
#endif
24102446

24112447
/* decrypt content */
24122448
while (dst_offset < (len + IMAGE_HEADER_SIZE)) {

src/update_ram.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,23 @@ int wolfBoot_ramboot(struct wolfBoot_image *img, uint8_t *src, uint8_t *dst)
9191

9292
/* determine size of partition */
9393
img_size = wolfBoot_image_size((uint8_t*)dst);
94-
#if defined(WOLFBOOT_NO_PARTITIONS)
95-
# ifndef WOLFBOOT_RAMBOOT_MAX_SIZE
96-
# error "WOLFBOOT_RAMBOOT_MAX_SIZE required when WOLFBOOT_NO_PARTITIONS=1"
97-
# endif
94+
#if !defined(WOLFBOOT_FIXED_PARTITIONS) && !defined(WOLFBOOT_RAMBOOT_MAX_SIZE)
95+
# error "WOLFBOOT_FIXED_PARTITIONS or WOLFBOOT_RAMBOOT_MAX_SIZE required to bound the RAM load"
96+
#endif
97+
/* Bound the UNAUTHENTICATED image length before it drives the copy into the
98+
* RAM load region: the image is loaded to RAM before its signature is
99+
* verified, so this length (read from the not-yet-authenticated header) is
100+
* attacker-influenceable and must be range checked first. When both are
101+
* configured, WOLFBOOT_RAMBOOT_MAX_SIZE takes precedence: it is the explicit
102+
* cap on the RAM load region and may be tighter than the partition size. */
103+
#if defined(WOLFBOOT_RAMBOOT_MAX_SIZE)
98104
if (img_size > WOLFBOOT_RAMBOOT_MAX_SIZE) {
99105
wolfBoot_printf("Invalid image size %u at %p\n", img_size, src);
100106
return -1;
101107
}
102-
#elif defined(WOLFBOOT_PARTITION_SIZE)
103-
if (img_size > (WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) {
108+
#elif defined(WOLFBOOT_FIXED_PARTITIONS)
109+
if (WOLFBOOT_PARTITION_SIZE <= IMAGE_HEADER_SIZE ||
110+
img_size > (uint32_t)(WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) {
104111
wolfBoot_printf("Invalid image size %u at %p\n", img_size, src);
105112
return -1;
106113
}

tools/unit-tests/Makefile

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ TESTS:=unit-parser unit-fdt unit-extflash unit-string unit-spi-flash unit-aes128
5151
unit-enc-nvm-flagshome unit-delta unit-gzip unit-update-flash unit-update-flash-delta \
5252
unit-update-flash-hook \
5353
unit-update-flash-self-update \
54-
unit-update-flash-enc unit-update-ram unit-update-ram-nofixed unit-update-ram-noramboot unit-update-flash-hwswap unit-pkcs11_store unit-psa_store unit-disk \
54+
unit-update-flash-enc unit-update-ram unit-update-ram-enc unit-update-ram-enc-nopart unit-update-ram-nofixed unit-update-ram-noramboot unit-update-flash-hwswap unit-pkcs11_store unit-psa_store unit-disk \
5555
unit-update-disk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-fwtpm-stub unit-tpm-rsa-exp \
5656
unit-image-nopart unit-image-sha384 unit-image-sha3-384 unit-store-sbrk \
5757
unit-tpm-blob unit-policy-create unit-policy-sign unit-rot-auth unit-sdhci-response-bits \
@@ -165,6 +165,20 @@ unit-update-ram-noramboot:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TE
165165
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT \
166166
-DPART_SWAP_EXT -DPART_BOOT_EXT -DWOLFBOOT_DUALBOOT -DNO_XIP -DWOLFBOOT_NO_RAMBOOT \
167167
-DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT -DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE
168+
unit-update-ram-enc:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
169+
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT \
170+
-DPART_SWAP_EXT -DPART_BOOT_EXT -DWOLFBOOT_DUALBOOT -DNO_XIP -DMMU \
171+
-DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA -DHAVE_CHACHA \
172+
-DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT -DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE
173+
# Same source as unit-update-ram-enc, but with a WOLFBOOT_RAMBOOT_MAX_SIZE that
174+
# is tighter than the partition cap (NO_PARTITIONS / RAM-load-region flavour),
175+
# so the bound check is exercised through its RAMBOOT_MAX_SIZE branch.
176+
unit-update-ram-enc-nopart:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
177+
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT \
178+
-DPART_SWAP_EXT -DPART_BOOT_EXT -DWOLFBOOT_DUALBOOT -DNO_XIP -DMMU \
179+
-DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA -DHAVE_CHACHA \
180+
-DWOLFBOOT_NO_PARTITIONS -DWOLFBOOT_RAMBOOT_MAX_SIZE=0x1000 \
181+
-DWOLFBOOT_ORIGIN=MOCK_ADDRESS_BOOT -DBOOTLOADER_PARTITION_SIZE=WOLFBOOT_PARTITION_SIZE
168182
unit-update-ram-nofixed:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN \
169183
-DUNIT_TEST_AUTH -DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH \
170184
-DPART_UPDATE_EXT -DPART_SWAP_EXT -DPART_BOOT_EXT -DWOLFBOOT_DUALBOOT \
@@ -473,6 +487,18 @@ unit-update-flash-enc: ../../include/target.h unit-update-flash.c
473487
unit-update-ram: ../../include/target.h unit-update-ram.c
474488
gcc -o $@ unit-update-ram.c ../../src/image.c $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c $(CFLAGS) $(LDFLAGS)
475489

490+
unit-update-ram-enc: ../../include/target.h unit-update-ram-enc.c
491+
gcc -o $@ unit-update-ram-enc.c \
492+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c \
493+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/chacha.c \
494+
$(CFLAGS) $(LDFLAGS)
495+
496+
unit-update-ram-enc-nopart: ../../include/target.h unit-update-ram-enc.c
497+
gcc -o $@ unit-update-ram-enc.c \
498+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c \
499+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/chacha.c \
500+
$(CFLAGS) $(LDFLAGS)
501+
476502
unit-update-ram-nofixed: ../../include/target.h unit-update-ram-nofixed.c
477503
gcc -o $@ unit-update-ram-nofixed.c ../../src/image.c $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c $(CFLAGS) $(LDFLAGS)
478504

0 commit comments

Comments
 (0)