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
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -182,21 +182,31 @@ tools/unit-tests/unit-policy-create
tools/unit-tests/unit-sign-encrypted-output
tools/unit-tests/unit-update-flash-delta
tools/unit-tests/unit-update-flash-self-update
tools/unit-tests/unit-update-flash-hook
tools/unit-tests/unit-loader-tpm-init
tools/unit-tests/unit-update-ram-nofixed
tools/unit-tests/unit-uart-flash
tools/unit-tests/unit-max-space
tools/unit-tests/unit-sdhci-disk-unaligned
tools/unit-tests/unit-fwtpm-stub
tools/unit-tests/unit-gzip
tools/unit-tests/unit-fit-gzip
tools/unit-tests/unit-fit-nogzip
tools/unit-tests/unit-flash-erase-h7
tools/unit-tests/unit-keygen-xmss-params
tools/unit-tests/unit-linux-loader-e820
tools/unit-tests/unit-linux-loader-syssize
tools/unit-tests/unit-mpusize
tools/unit-tests/unit-otp-keystore
tools/unit-tests/unit-tpm-api-names


# Elf preprocessing tools
tools/squashelf/**
!tools/squashelf/squashelf.c
!tools/squashelf/Makefile
!tools/squashelf/README.md
!tools/squashelf/test-range-overflow.py

# Generated configuration files
.config
Expand Down
11 changes: 10 additions & 1 deletion hal/imx_rt.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,16 @@ int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
asm volatile("cpsid i");
int write_success = 0;
for (i = 0; i < len; i+= CONFIG_FLASH_PAGE_SIZE) {
memcpy(wbuf, data + i, CONFIG_FLASH_PAGE_SIZE);
/* The NOR program command always writes a full page. Bound the copy
* to the bytes actually provided by the caller so sub-page writes
* (e.g. the 1-byte trailer updates) do not overread the source buffer.
* Pad the remainder of the page with the erased value (0xFF), which is
* a no-op for NOR programming and preserves existing flash contents. */
int chunk = len - i;
if (chunk > (int)CONFIG_FLASH_PAGE_SIZE)
chunk = (int)CONFIG_FLASH_PAGE_SIZE;
memset(wbuf, 0xFF, sizeof(wbuf));
memcpy(wbuf, data + i, chunk);
status = g_bootloaderTree->flexSpiNorDriver->program(
CONFIG_FLASH_FLEXSPI_INSTANCE,
FLEXSPI_CONFIG,
Expand Down
15 changes: 13 additions & 2 deletions hal/stm32h7.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/

#ifndef WOLFBOOT_UNIT_TEST_FLASH_ERASE
#include "hal/stm32h7.h"
#endif

#ifndef WOLFBOOT_UNIT_TEST_FLASH_ERASE
static uint32_t stm32h7_cache[STM32H7_WORD_SIZE / sizeof(uint32_t)];

#define FLASH_BANK_1 0
Expand Down Expand Up @@ -194,6 +197,7 @@ void RAMFUNCTION hal_flash_lock(void)
if ((FLASH_CR2 & FLASH_CR_LOCK) == 0)
FLASH_CR2 |= FLASH_CR_LOCK;
}
#endif /* !WOLFBOOT_UNIT_TEST_FLASH_ERASE */

int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
{
Expand All @@ -220,9 +224,14 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
(p <= (FLASH_TOP - FLASHMEM_ADDRESS_SPACE))) {
uint32_t reg = FLASH_CR2 &
(~((FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT) | FLASH_CR_PSIZE));
p-= (FLASH_BANK2_BASE);
/* Sector index within bank 2: subtract the bank-2 base expressed in
* the same relative-offset convention as p (FLASH_BANK2_BASE_REL),
* not the absolute FLASH_BANK2_BASE which would underflow. Use a
* temporary so the loop variable p is not corrupted. */
uint32_t sector = (p - FLASH_BANK2_BASE_REL) >> 17;
FLASH_CR2 = reg |
(((p >> 17) << FLASH_CR_SNB_SHIFT) | FLASH_CR_SER | 0x00);
(((sector & FLASH_CR_SNB_MASK) << FLASH_CR_SNB_SHIFT) |
FLASH_CR_SER | 0x00);
DMB();
FLASH_CR2 |= FLASH_CR_STRT;
flash_wait_complete(FLASH_BANK_2);
Expand All @@ -231,6 +240,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
return 0;
}

#ifndef WOLFBOOT_UNIT_TEST_FLASH_ERASE
#ifdef DEBUG_UART
static int uart_init(void)
{
Expand Down Expand Up @@ -622,3 +632,4 @@ int hal_flash_otp_read(uint32_t flashAddress, void* data, uint32_t length)
}

#endif /* FLASH_OTP_KEYSTORE */
#endif /* !WOLFBOOT_UNIT_TEST_FLASH_ERASE */
40 changes: 31 additions & 9 deletions src/boot_arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ extern unsigned int _end_bss;

extern uint32_t *END_STACK;

#ifndef WOLFBOOT_UNIT_TEST_MPU
extern void main(void);
#endif
#ifdef TARGET_va416x0
extern void SysTick_Handler(void);
#endif
Expand Down Expand Up @@ -94,7 +96,17 @@ static void mpu_on(void)
#define MPUSIZE_16K (0x0d << 1)
#define MPUSIZE_32K (0x0e << 1)
#define MPUSIZE_64K (0x0f << 1)
/* ... */
#define MPUSIZE_128K (0x10 << 1)
#define MPUSIZE_256K (0x11 << 1)
#define MPUSIZE_512K (0x12 << 1)
#define MPUSIZE_1M (0x13 << 1)
#define MPUSIZE_2M (0x14 << 1)
#define MPUSIZE_4M (0x15 << 1)
#define MPUSIZE_8M (0x16 << 1)
#define MPUSIZE_16M (0x17 << 1)
#define MPUSIZE_32M (0x18 << 1)
#define MPUSIZE_64M (0x19 << 1)
#define MPUSIZE_128M (0x1a << 1)
#define MPUSIZE_256M (0x1b << 1)
#define MPUSIZE_512M (0x1c << 1)
#define MPUSIZE_1G (0x1d << 1)
Expand All @@ -103,14 +115,17 @@ static void mpu_on(void)

static uint32_t mpusize(uint32_t size)
{
if (size <= (8 * 1024))
return MPUSIZE_8K;
if (size <= (16 * 1024))
return MPUSIZE_16K;
if (size <= (32 * 1024))
return MPUSIZE_32K;
if (size <= (64 * 1024))
return MPUSIZE_64K;
uint32_t rasr = MPUSIZE_8K;
uint32_t limit = (8 * 1024);

while ((size > limit) && (limit < (128 * 1024 * 1024))) {
limit <<= 1;
rasr += 2;
}

if (size <= limit)
return rasr;

return MPUSIZE_ERR;
}

Expand Down Expand Up @@ -175,6 +190,11 @@ static void RAMFUNCTION mpu_off(void)
#define mpu_off() do{}while(0)
#endif /* !WOLFBOOT_NO_MPU */

#ifndef WOLFBOOT_UNIT_TEST_MPU
/* The remainder of this file is Cortex-M/-R reset/boot code that relies on
* ARM inline assembly and therefore cannot be compiled for the host. The MPU
* size helpers above are pure arithmetic and are exercised by the host unit
* test tools/unit-tests/unit-mpusize.c, which defines WOLFBOOT_UNIT_TEST_MPU. */

#ifdef CORTEX_R5
#define MINITGCR ((volatile uint32_t *)0xFFFFFF5C)
Expand Down Expand Up @@ -710,3 +730,5 @@ void RAMFUNCTION arch_reboot(void)
wolfBoot_panic();
}
#endif /* RAM_CODE */

#endif /* !WOLFBOOT_UNIT_TEST_MPU */
10 changes: 10 additions & 0 deletions src/flash_otp_keystore.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@

#include <stdint.h>
#include <string.h>
#ifndef WOLFBOOT_UNIT_TEST_OTP_KEYSTORE
#include "wolfboot/wolfboot.h"
#endif
#include "keystore.h"
#ifndef WOLFBOOT_UNIT_TEST_OTP_KEYSTORE
#include "hal.h"
#endif
#include "otp_keystore.h"

#if defined(FLASH_OTP_KEYSTORE) && !defined(WOLFBOOT_NO_SIGN)
Expand Down Expand Up @@ -70,6 +74,12 @@ int keystore_get_size(int id)
SIZEOF_KEYSTORE_SLOT) != 0)
return -1;
slot = (struct keystore_slot *)otp_slot_item_cache;
/* The pubkey is cached in a fixed-size buffer holding at most
* KEYSTORE_PUBKEY_SIZE bytes. A larger pubkey_size read from a corrupted or
* mis-provisioned OTP slot would make callers read past the buffer, so
* reject it like other invalid OTP fields. */
if (slot->pubkey_size > KEYSTORE_PUBKEY_SIZE)
return -1;
return slot->pubkey_size;
}

Expand Down
10 changes: 9 additions & 1 deletion src/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@
#define PCI_IO32_BASE 0x2000
#endif /* PCI_IO32_BASE */

#ifndef PCI_IO32_LIMIT
/* x86 IO space is 16-bit: valid IO addresses are 0x0000-0xFFFF. IO BARs must
* not be allocated past this ceiling, otherwise the 8-bit bridge IO base/limit
* registers (which only carry address bits [15:8]) silently truncate the high
* bits, mis-programming the window onto the legacy IO range (PIC/PIT/RTC). */
#define PCI_IO32_LIMIT 0x10000
#endif /* PCI_IO32_LIMIT */

#define PCI_ENUM_MAX_DEV 32
#define PCI_ENUM_MAX_FUN 8
#define PCI_ENUM_MAX_BARS 6
Expand Down Expand Up @@ -474,7 +482,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
if ((bar_align & PCI_DATA_HI16_MASK) == 0)
bar_align |= PCI_DATA_HI16_MASK;
base = &info->io;
limit = 0xffffffff;
limit = PCI_IO32_LIMIT;
}

PCI_DEBUG_PRINTF("PCI enum: %s %x:%x.%x bar: %d val: %x (%s %s)\r\n",
Expand Down
32 changes: 32 additions & 0 deletions tools/keytools/sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -2508,6 +2508,38 @@ static int base_diff(const char *f_base, uint8_t *pubkey, uint32_t pubkey_sz, in
}
len3++;
}
/* make_header_delta() below calls make_header_ex(is_diff=1), which may grow
* CMD.header_sz to fit the delta TLVs plus certificate chain. Resolve that
* expansion here, using the same logic, so patch_inv_off reflects the header
* size actually written; otherwise HDR_IMG_DELTA_INVERSE would encode a
* stale, too-small offset and break inverse-patch rollback. */
if (CMD.cert_chain_file != NULL) {
struct stat cc_stat;
if ((stat(CMD.cert_chain_file, &cc_stat) == 0) &&
(cc_stat.st_size >= 0)) {
if ((uintmax_t)cc_stat.st_size > (uintmax_t)UINT16_MAX) {
printf("Error: Certificate chain too large for TLV encoding "
"(%ju > %u)\n", (uintmax_t)cc_stat.st_size, UINT16_MAX);
goto cleanup;
}
else {
uint32_t required_space = header_required_size(1,
(uint32_t)cc_stat.st_size, 0);
if (CMD.header_sz < required_space) {
uint32_t new_size = 256;
while (new_size < required_space) {
if (new_size > (UINT32_MAX / 2U)) {
printf("Error: Header size overflow while sizing "
"certificate chain\n");
goto cleanup;
}
new_size *= 2;
}
CMD.header_sz = new_size;
}
}
}
}
patch_inv_off = (uint32_t)len3 + CMD.header_sz;
patch_inv_sz = 0;

Expand Down
4 changes: 2 additions & 2 deletions tools/keytools/sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -764,9 +764,9 @@ def make_header(image_file, fw_version, extra_fields=[]):
base_version = re.split("_", (re.split("_v", delta_base_file)[1]))[0]
header = make_header(tmp_outfile, fw_version,
[[HDR_IMG_DELTA_BASE, 4, struct.pack("<L", int(base_version))],
[HDR_IMG_DELTA_SIZE, 2, struct.pack("<H", delta_size)],
[HDR_IMG_DELTA_SIZE, 4, struct.pack("<L", delta_size)],
[HDR_IMG_DELTA_INVERSE, 4, struct.pack("<L", inv_off + WOLFBOOT_HEADER_SIZE)],
[HDR_IMG_DELTA_INVERSE_SIZE, 2, struct.pack("<H", delta_inv_size)]
[HDR_IMG_DELTA_INVERSE_SIZE, 4, struct.pack("<L", delta_inv_size)]
])
outfile = open(delta_output_image_file, 'wb')
outfile.write(header)
Expand Down
5 changes: 4 additions & 1 deletion tools/squashelf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ else
CFLAGS+=$(OPTIMIZE)
endif

.PHONY: clean all debug
.PHONY: clean all debug test

all: $(TARGET)

debug: CFLAGS+=$(DEBUG_FLAGS)
debug: all

test: $(TARGET)
python3 test-range-overflow.py ./$(TARGET)

$(TARGET): $(TARGET).o
@echo "Building squashelf tool"
$(CC) -o $@ $< $(LDFLAGS) $(CFLAGS_EXTRA)
Expand Down
22 changes: 21 additions & 1 deletion tools/squashelf/squashelf.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,27 @@ int main(int argCount, char** argValues)
/* Apply range filter if specified */
if (hasRange) {
uint64_t segmentStart = p_paddr;
uint64_t segmentEnd = p_paddr + p_memsz - 1;
uint64_t segmentEnd;

/* Guard against uint64_t overflow when computing the segment
* end (CWE-190). Both fields come straight from the (possibly
* crafted) program header; if p_paddr + p_memsz - 1 wrapped, the
* range check could spuriously include an out-of-range segment
* or drop a valid one. Treat such a segment as out-of-range. */
if (p_memsz == 0) {
segmentEnd = p_paddr;
}
else if (p_paddr > UINT64_MAX - (p_memsz - 1)) {
fprintf(stderr,
"Skipping segment %zu (LMA 0x%lx, size 0x%lx) - "
"address range overflows 64-bit space\n",
i, (unsigned long)p_paddr,
(unsigned long)p_memsz);
continue;
}
else {
segmentEnd = p_paddr + p_memsz - 1;
}

/* Check if segment start and end are both within any range */
bool startInRange =
Expand Down
Loading
Loading