Skip to content

Commit a910645

Browse files
authored
Fixes to delta updates, reinforced size checks, improved hardening (wolfSSL#716)
Fixes to delta updates, reinforced size checks, improved hardening
2 parents 1c0c379 + fb4dd67 commit a910645

26 files changed

+1089
-57
lines changed

src/boot_x86_fsp.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ const uint8_t __attribute__((section(".sig_wolfboot_raw")))
8282
#define FSP_STATUS_RESET_REQUIRED_WARM 0x40000002
8383
#define MEMORY_4GB (4ULL * 1024 * 1024 * 1024)
8484
#define ENDLINE "\r\n"
85+
/* Standard PCI capabilities live in conventional config space at 0x40-0xFC,
86+
* on 4-byte alignment, so there are at most 48 distinct capability headers. */
87+
#define PCI_MAX_STANDARD_CAPABILITIES 48
8588

8689

8790
/* compile time alignment checks */
@@ -257,13 +260,23 @@ static void jump_into_wolfboot(void)
257260
/* The image needs to be already verified */
258261
int wolfBoot_image_measure(uint8_t *image)
259262
{
260-
uint16_t hash_len;
261-
uint8_t *hash;
263+
struct wolfBoot_image img;
264+
int ret;
262265

263-
hash_len = wolfBoot_find_header(image + IMAGE_HEADER_OFFSET,
264-
WOLFBOOT_SHA_HDR, &hash);
265-
wolfBoot_print_hexstr(hash, hash_len, 0);
266-
return wolfBoot_tpm2_extend(WOLFBOOT_MEASURED_PCR_A, hash, __LINE__);
266+
memset(&img, 0, sizeof(img));
267+
ret = wolfBoot_open_image_address(&img, image);
268+
if (ret != 0) {
269+
return ret;
270+
}
271+
272+
ret = wolfBoot_verify_integrity(&img);
273+
if (ret != 0 || img.sha_hash == NULL) {
274+
return -1;
275+
}
276+
277+
wolfBoot_print_hexstr(img.sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, 0);
278+
return wolfBoot_tpm2_extend(WOLFBOOT_MEASURED_PCR_A, img.sha_hash,
279+
__LINE__);
267280
}
268281
#endif /* WOLFBOOT_MEASURED_BOOT */
269282

@@ -332,19 +345,21 @@ static int pci_get_capability(uint8_t bus, uint8_t dev, uint8_t fun,
332345
uint8_t cap_id, uint8_t *cap_off)
333346
{
334347
uint8_t r8, id;
348+
uint8_t cap_count = 0;
335349
uint32_t r32;
336350

337351
r32 = pci_config_read16(bus, dev, fun, PCI_STATUS_OFFSET);
338352
if (!(r32 & PCI_STATUS_CAP_LIST))
339353
return -1;
340354
r8 = pci_config_read8(bus, dev, fun, PCI_CAP_OFFSET);
341-
while (r8 != 0) {
355+
while ((r8 != 0) && (cap_count < PCI_MAX_STANDARD_CAPABILITIES)) {
342356
id = pci_config_read8(bus, dev, fun, r8);
343357
if (id == cap_id) {
344358
*cap_off = r8;
345359
return 0;
346360
}
347361
r8 = pci_config_read8(bus, dev, fun, r8 + 1);
362+
cap_count++;
348363
}
349364
return -1;
350365
}

src/delta.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,17 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
135135
continue;
136136
}
137137
if (*pp == ESC) {
138+
if ((ctx->patch_size - ctx->p_off) < 2)
139+
return -1;
138140
if (*(pp + 1) == ESC) {
139141
*(dst + dst_off) = ESC;
140142
/* Two bytes of the patch have been consumed to produce ESC */
141143
ctx->p_off += 2;
142144
dst_off++;
143145
continue;
144146
} else {
147+
if ((ctx->patch_size - ctx->p_off) < BLOCK_HDR_SIZE)
148+
return -1;
145149
hdr = (struct block_hdr *)pp;
146150
src_off = (hdr->off[0] << 16) + (hdr->off[1] << 8) +
147151
hdr->off[2];

src/gpt.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@
3434

3535
#include "gpt.h"
3636

37+
static uint32_t gpt_crc32(const uint8_t *data, uint32_t len)
38+
{
39+
uint32_t crc = 0xFFFFFFFFU;
40+
uint32_t i;
41+
uint32_t j;
42+
43+
for (i = 0; i < len; i++) {
44+
crc ^= data[i];
45+
for (j = 0; j < 8; j++) {
46+
uint32_t mask = -(crc & 1U);
47+
crc = (crc >> 1) ^ (0xEDB88320U & mask);
48+
}
49+
}
50+
51+
return ~crc;
52+
}
53+
3754
/**
3855
* @brief Check MBR for protective GPT partition entry.
3956
*
@@ -98,6 +115,7 @@ int gpt_check_mbr_protective(const uint8_t *mbr_sector, uint32_t *gpt_lba)
98115
int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr)
99116
{
100117
const struct guid_ptable *src;
118+
struct guid_ptable tmp;
101119

102120
if (sector == NULL || hdr == NULL) {
103121
return -1;
@@ -110,6 +128,16 @@ int gpt_parse_header(const uint8_t *sector, struct guid_ptable *hdr)
110128
return -1;
111129
}
112130

131+
if (src->hdr_size < 0x5C || src->hdr_size > GPT_SECTOR_SIZE) {
132+
return -1;
133+
}
134+
135+
memcpy(&tmp, src, sizeof(tmp));
136+
tmp.hdr_crc32 = 0;
137+
if (gpt_crc32((const uint8_t *)&tmp, src->hdr_size) != src->hdr_crc32) {
138+
return -1;
139+
}
140+
113141
/* Copy header to output */
114142
memcpy(hdr, src, sizeof(struct guid_ptable));
115143

src/image.c

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@
5858
/* Globals */
5959
static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE] XALIGNED(4);
6060

61+
static int image_CT_compare(const uint8_t *expected, const uint8_t *actual,
62+
uint32_t len)
63+
{
64+
uint8_t diff = 0;
65+
uint32_t i;
66+
67+
for (i = 0; i < len; i++) {
68+
diff |= expected[i] ^ actual[i];
69+
}
70+
71+
return diff == 0;
72+
}
73+
6174
#if defined(WOLFBOOT_CERT_CHAIN_VERIFY) && \
6275
(defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \
6376
defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER))
@@ -367,6 +380,9 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot,
367380
static inline int DecodeAsn1Tag(const uint8_t* input, int inputSz, int* inOutIdx,
368381
int* tag_len, uint8_t tag)
369382
{
383+
if (*inOutIdx < 0 || *inOutIdx >= inputSz || (*inOutIdx + 1) >= inputSz) {
384+
return -1;
385+
}
370386
if (input[*inOutIdx] != tag) {
371387
return -1;
372388
}
@@ -1492,6 +1508,12 @@ int wolfBoot_open_self_address(struct wolfBoot_image* img, uint8_t* hdr,
14921508

14931509
img->hdr = hdr;
14941510
img->fw_size = wolfBoot_image_size(hdr);
1511+
#ifdef WOLFBOOT_FIXED_PARTITIONS
1512+
if (img->fw_size > (WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE)) {
1513+
img->fw_size = WOLFBOOT_PARTITION_SIZE - IMAGE_HEADER_SIZE;
1514+
return -1;
1515+
}
1516+
#endif
14951517
img->fw_base = image;
14961518
img->part = PART_SELF;
14971519
img->hdr_ok = 1;
@@ -1518,7 +1540,7 @@ int wolfBoot_verify_integrity(struct wolfBoot_image *img)
15181540
return -1;
15191541
if (image_hash(img, digest) != 0)
15201542
return -1;
1521-
if (memcmp(digest, stored_sha, stored_sha_len) != 0)
1543+
if (!image_CT_compare(digest, stored_sha, stored_sha_len))
15221544
return -1;
15231545
img->sha_ok = 1;
15241546
img->sha_hash = stored_sha;
@@ -2366,6 +2388,21 @@ uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
23662388

23672389
#if !defined(WOLFBOOT_NO_SIGN) && !defined(WOLFBOOT_RENESAS_SCEPROTECT)
23682390

2391+
/* Compare fixed-size key hints without early exit to avoid leaking hash prefix
2392+
* matches through lookup timing. */
2393+
static int keyslot_CT_hint_matches(const uint8_t *expected,
2394+
const uint8_t *actual)
2395+
{
2396+
uint8_t diff = 0;
2397+
uint32_t i;
2398+
2399+
for (i = 0; i < WOLFBOOT_SHA_DIGEST_SIZE; i++) {
2400+
diff |= expected[i] ^ actual[i];
2401+
}
2402+
2403+
return diff == 0;
2404+
}
2405+
23692406
/**
23702407
* @brief Get the key slot ID by SHA hash.
23712408
*
@@ -2378,13 +2415,14 @@ uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
23782415
int keyslot_id_by_sha(const uint8_t *hint)
23792416
{
23802417
int id;
2418+
int match_id = -1;
23812419

23822420
for (id = 0; id < keystore_num_pubkeys(); id++) {
23832421
key_hash(id, digest);
2384-
if (memcmp(digest, hint, WOLFBOOT_SHA_DIGEST_SIZE) == 0) {
2385-
return id;
2422+
if ((match_id < 0) && keyslot_CT_hint_matches(digest, hint)) {
2423+
match_id = id;
23862424
}
23872425
}
2388-
return -1;
2426+
return match_id;
23892427
}
23902428
#endif /* !WOLFBOOT_NO_SIGN && !WOLFBOOT_RENESAS_SCEPROTECT */

src/libwolfboot.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ int wolfBoot_initialize_encryption(void)
107107
(2 * WOLFBOOT_SECTOR_SIZE)))
108108
/* MAGIC (4B) + PART_FLAG (1B) + (N_SECTORS / 2) */
109109
#define START_FLAGS_OFFSET (ENCRYPT_TMP_SECRET_OFFSET - TRAILER_OVERHEAD)
110-
#define SECTOR_FLAGS_SIZE WOLFBOOT_SECTOR_SIZE - (4 + 1 + \
111-
ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE)
110+
#define SECTOR_FLAGS_SIZE (WOLFBOOT_SECTOR_SIZE - (4 + 1 + \
111+
ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE))
112112
/* MAGIC (4B) + PART_FLAG (1B) + ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE */
113113
#else
114114
#define ENCRYPT_TMP_SECRET_OFFSET (WOLFBOOT_PARTITION_SIZE - (TRAILER_SKIP))

src/pkcs11_store.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,8 +506,8 @@ int wolfPKCS11_Store_Write(void* store, unsigned char* buffer, int len)
506506
% WOLFBOOT_SECTOR_SIZE;
507507
sector_base = (uintptr_t)handle->buffer + handle->in_buffer_offset - in_sector_offset;
508508
in_sector_len = WOLFBOOT_SECTOR_SIZE - in_sector_offset;
509-
if (in_sector_len > (uint32_t)len)
510-
in_sector_len = len;
509+
if (in_sector_len > (uint32_t)(len - written))
510+
in_sector_len = len - written;
511511

512512
/* Cache the corresponding sector */
513513
memcpy(cached_sector, (void *)(uintptr_t)sector_base, WOLFBOOT_SECTOR_SIZE);

src/psa_store.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,8 +512,8 @@ int wolfPSA_Store_Write(void* store, unsigned char* buffer, int len)
512512
% WOLFBOOT_SECTOR_SIZE;
513513
sector_base = (uintptr_t)handle->buffer + handle->in_buffer_offset - in_sector_offset;
514514
in_sector_len = WOLFBOOT_SECTOR_SIZE - in_sector_offset;
515-
if (in_sector_len > (uint32_t)len)
516-
in_sector_len = len;
515+
if (in_sector_len > (uint32_t)(len - written))
516+
in_sector_len = len - written;
517517

518518
/* Cache the corresponding sector */
519519
memcpy(cached_sector, (void *)(uintptr_t)sector_base, WOLFBOOT_SECTOR_SIZE);

src/qspi_flash.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,10 @@ int spi_flash_read(uint32_t address, void *data, int len)
417417
int spi_flash_write(uint32_t address, const void *data, int len)
418418
{
419419
int ret = 0;
420+
int remaining = len;
420421
uint32_t xferSz, page, pages;
421422
uintptr_t addr;
423+
uint8_t* ptr = (uint8_t*)data;
422424

423425
#ifdef DEBUG_QSPI
424426
wolfBoot_printf("QSPI Flash Write: Len %d, %p -> 0x%x\n",
@@ -430,13 +432,12 @@ int spi_flash_write(uint32_t address, const void *data, int len)
430432
for (page = 0; page < pages; page++) {
431433
ret = qspi_write_enable();
432434
if (ret == 0) {
433-
uint8_t* ptr;
434-
xferSz = len;
435-
if (xferSz > FLASH_PAGE_SIZE)
435+
xferSz = (uint32_t)remaining;
436+
if (xferSz > FLASH_PAGE_SIZE) {
436437
xferSz = FLASH_PAGE_SIZE;
438+
}
437439

438440
addr = address + (page * FLASH_PAGE_SIZE);
439-
ptr = ((uint8_t*)data + (page * FLASH_PAGE_SIZE));
440441

441442
/* ------ Write Flash (page at a time) ------ */
442443
ret = qspi_transfer(QSPI_MODE_WRITE, FLASH_WRITE_CMD,
@@ -459,6 +460,8 @@ int spi_flash_write(uint32_t address, const void *data, int len)
459460
break;
460461
}
461462
/* write disable is automatic */
463+
remaining -= (int)xferSz;
464+
ptr += xferSz;
462465
}
463466
}
464467

src/string.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ void uart_vprintf(const char* fmt, va_list argp)
361361
if (*fmtp == '0' && maxdigits == 0) {
362362
zeropad = 1;
363363
}
364-
maxdigits <<= 8;
364+
maxdigits *= 10;
365365
maxdigits += (*fmtp - '0');
366366
fmtp++;
367367
}

src/tpm.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ int wolfBoot_load_pubkey(const uint8_t* pubkey_hint, WOLFTPM2_KEY* pubKey,
382382
defined(WOLFBOOT_SIGN_RSA3072) || \
383383
defined(WOLFBOOT_SIGN_RSA4096)
384384
uint32_t inOutIdx = 0;
385+
uint32_t exponent = 0;
386+
uint32_t j;
385387
const uint8_t*n = NULL, *e = NULL;
386388
uint32_t nSz = 0, eSz = 0;
387389
if (key_type != AUTH_KEY_RSA2048 && key_type != AUTH_KEY_RSA3072 &&
@@ -395,10 +397,19 @@ int wolfBoot_load_pubkey(const uint8_t* pubkey_hint, WOLFTPM2_KEY* pubKey,
395397
&e, &eSz /* exponent */
396398
);
397399
}
400+
if (rc == 0) {
401+
if (eSz == 0 || eSz > sizeof(exponent))
402+
rc = -1;
403+
}
404+
if (rc == 0) {
405+
for (j = 0; j < eSz; j++) {
406+
exponent = (exponent << 8) | e[j];
407+
}
408+
}
398409
if (rc == 0) {
399410
/* Load public key into TPM */
400411
rc = wolfTPM2_LoadRsaPublicKey_ex(&wolftpm_dev, pubKey,
401-
n, nSz, *((uint32_t*)e),
412+
n, nSz, exponent,
402413
TPM_ALG_NULL, WOLFBOOT_TPM_HASH_ALG);
403414
}
404415
#else

0 commit comments

Comments
 (0)