Skip to content

Commit bd02eea

Browse files
authored
Merge pull request #694 from danielinux/add-extra-verify-enc-fallback
Added extra verify step in encrypted fallback
2 parents 5a6b8c6 + 6d9ff5c commit bd02eea

5 files changed

Lines changed: 252 additions & 13 deletions

File tree

src/libwolfboot.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ static int encrypt_initialized = 0;
6868

6969
static uint8_t encrypt_iv_nonce[ENCRYPT_NONCE_SIZE] XALIGNED(4);
7070
static uint32_t encrypt_iv_offset = 0;
71+
static int fallback_iv_forced = 0;
7172

7273
#define FALLBACK_IV_OFFSET 0x00100000U
7374
#if !defined(XMEMSET)
@@ -1395,6 +1396,13 @@ int RAMFUNCTION wolfBoot_enable_fallback_iv(int enable)
13951396
return prev;
13961397
}
13971398

1399+
int RAMFUNCTION wolfBoot_force_fallback_iv(int enable)
1400+
{
1401+
int prev = fallback_iv_forced;
1402+
fallback_iv_forced = enable ? 1 : 0;
1403+
return prev;
1404+
}
1405+
13981406
void RAMFUNCTION wolfBoot_crypto_set_iv(const uint8_t *nonce, uint32_t iv_counter)
13991407
{
14001408
#if defined(ENCRYPT_WITH_CHACHA)
@@ -2174,6 +2182,8 @@ int RAMFUNCTION ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len
21742182
return -1;
21752183
}
21762184
}
2185+
if (fallback_iv_forced)
2186+
encrypt_iv_offset = FALLBACK_IV_OFFSET;
21772187
wolfBoot_crypto_set_iv(encrypt_iv_nonce, iv_counter);
21782188
break;
21792189
case PART_SWAP:

src/update_flash.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131

3232
#include "delta.h"
3333
#include "printf.h"
34+
#ifdef EXT_ENCRYPTED
35+
int wolfBoot_force_fallback_iv(int enable);
36+
#endif
3437
#ifdef WOLFBOOT_TPM
3538
#include "tpm.h"
3639
#endif
@@ -779,14 +782,22 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
779782
return -1;
780783
}
781784
} else {
782-
/*
783-
* When we recover an already-encrypted fallback image, the
784-
* manifest still contains hashes computed with the original IV
785-
* stream. Skip the redundant integrity/authenticity checks here
786-
* and let the bootloader verify the restored image after the swap.
787-
*/
788-
update.sha_ok = 1;
789-
update.signature_ok = 1;
785+
#ifdef EXT_ENCRYPTED
786+
int prev = wolfBoot_force_fallback_iv(1);
787+
#endif
788+
if (!update.hdr_ok
789+
|| (wolfBoot_verify_integrity(&update) < 0)
790+
|| (wolfBoot_verify_authenticity(&update) < 0)) {
791+
#ifdef EXT_ENCRYPTED
792+
wolfBoot_force_fallback_iv(prev);
793+
#endif
794+
wolfBoot_printf("Update verify failed: Hdr %d, Hash %d, Sig %d\n",
795+
update.hdr_ok, update.sha_ok, update.signature_ok);
796+
return -1;
797+
}
798+
#ifdef EXT_ENCRYPTED
799+
wolfBoot_force_fallback_iv(prev);
800+
#endif
790801
}
791802
PART_SANITY_CHECK(&update);
792803

tools/unit-tests/Makefile

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ LDFLAGS+=-ftest-coverage
2828
TESTS:=unit-parser unit-extflash unit-string unit-spi-flash unit-aes128 \
2929
unit-aes256 unit-chacha20 unit-pci unit-mock-state unit-sectorflags \
3030
unit-image unit-nvm unit-nvm-flagshome unit-enc-nvm \
31-
unit-enc-nvm-flagshome unit-delta unit-update-flash unit-update-ram \
32-
unit-pkcs11_store
31+
unit-enc-nvm-flagshome unit-delta unit-update-flash \
32+
unit-update-flash-enc unit-update-ram unit-pkcs11_store
3333

3434
all: $(TESTS)
3535

@@ -137,6 +137,16 @@ unit-delta: ../../include/target.h unit-delta.c
137137
unit-update-flash: ../../include/target.h unit-update-flash.c
138138
gcc -o $@ unit-update-flash.c ../../src/image.c $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c $(CFLAGS) $(LDFLAGS)
139139

140+
unit-update-flash-enc:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \
141+
-DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT \
142+
-DPART_SWAP_EXT -DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA -DHAVE_CHACHA \
143+
-DCUSTOM_ENCRYPT_KEY -DUNIT_TEST_FALLBACK_ONLY
144+
unit-update-flash-enc: ../../include/target.h unit-update-flash.c
145+
gcc -o $@ unit-update-flash.c ../../src/image.c \
146+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c \
147+
$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/chacha.c \
148+
$(CFLAGS) $(LDFLAGS)
149+
140150
unit-update-ram: ../../include/target.h unit-update-ram.c
141151
gcc -o $@ unit-update-ram.c ../../src/image.c $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sha256.c $(CFLAGS) $(LDFLAGS)
142152

tools/unit-tests/unit-mock-flash.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,22 @@ int ext_flash_write(uintptr_t address, const uint8_t *data, int len)
163163
int i;
164164
uint8_t *a = (uint8_t *)address;
165165
ck_assert_msg(!ext_locked, "Attempting to write to a locked FLASH");
166+
ck_assert_msg(len >= 0, "ext_flash_write invalid len %d", len);
167+
ck_assert_msg(
168+
((address >= WOLFBOOT_PARTITION_BOOT_ADDRESS) &&
169+
(address < WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE) &&
170+
((uintptr_t)len <=
171+
WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE - address)) ||
172+
((address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
173+
(address < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE) &&
174+
((uintptr_t)len <=
175+
WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - address)) ||
176+
((address >= WOLFBOOT_PARTITION_SWAP_ADDRESS) &&
177+
(address < WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE) &&
178+
((uintptr_t)len <=
179+
WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE - address)),
180+
"ext_flash_write address out of range: %p len %d",
181+
(void*)address, len);
166182
for (i = 0; i < len; i++) {
167183
a[i] = data[i];
168184
}
@@ -190,6 +206,11 @@ void ext_flash_lock(void)
190206
ext_locked++;
191207
}
192208

209+
void ext_flash_reset_lock(void)
210+
{
211+
ext_locked = 1;
212+
}
213+
193214

194215
/* A simple mock memory */
195216
static int mmap_file(const char *path, uint8_t *address, uint32_t len,

tools/unit-tests/unit-update-flash.c

Lines changed: 190 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,32 @@ static void reset_mock_stats(void);
5252
static void prepare_flash(void);
5353
static void cleanup_flash(void);
5454

55+
#ifdef CUSTOM_ENCRYPT_KEY
56+
int wolfBoot_get_encrypt_key(uint8_t *k, uint8_t *nonce)
57+
{
58+
int i;
59+
for (i = 0; i < ENCRYPT_KEY_SIZE; i++) {
60+
k[i] = (uint8_t)(i + 1);
61+
}
62+
for (i = 0; i < ENCRYPT_NONCE_SIZE; i++) {
63+
nonce[i] = (uint8_t)(0xA5 + i);
64+
}
65+
return 0;
66+
}
67+
68+
int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce)
69+
{
70+
(void)key;
71+
(void)nonce;
72+
return 0;
73+
}
74+
75+
int wolfBoot_erase_encrypt_key(void)
76+
{
77+
return 0;
78+
}
79+
#endif
80+
5581
START_TEST (test_boot_success_sets_state)
5682
{
5783
uint8_t state = 0;
@@ -90,6 +116,7 @@ static void reset_mock_stats(void)
90116
{
91117
wolfBoot_staged_ok = 0;
92118
wolfBoot_panicked = 0;
119+
ext_flash_reset_lock();
93120
}
94121

95122

@@ -198,6 +225,123 @@ static int add_payload(uint8_t part, uint32_t version, uint32_t size)
198225

199226
}
200227

228+
#ifdef EXT_ENCRYPTED
229+
static int build_image_buffer(uint8_t part, uint32_t version, uint32_t size,
230+
uint8_t *buf, uint32_t buf_sz)
231+
{
232+
uint32_t word;
233+
uint16_t word16;
234+
uint32_t total = size + IMAGE_HEADER_SIZE;
235+
int i;
236+
int ret;
237+
wc_Sha256 sha;
238+
uint8_t digest[SHA256_DIGEST_SIZE];
239+
240+
if (buf_sz < total)
241+
return -1;
242+
243+
memset(buf, 0xFF, buf_sz);
244+
245+
ret = wc_InitSha256_ex(&sha, NULL, INVALID_DEVID);
246+
if (ret != 0)
247+
return ret;
248+
249+
memcpy(buf, "WOLF", 4);
250+
memcpy(buf + 4, &size, 4);
251+
252+
word = 4 << 16 | HDR_VERSION;
253+
memcpy(buf + 8, &word, 4);
254+
memcpy(buf + 12, &version, 4);
255+
256+
word = 2 << 16 | HDR_IMG_TYPE;
257+
memcpy(buf + 16, &word, 4);
258+
word16 = HDR_IMG_TYPE_AUTH_NONE | HDR_IMG_TYPE_APP;
259+
memcpy(buf + 20, &word16, 2);
260+
261+
ret = wc_Sha256Update(&sha, buf, DIGEST_TLV_OFF_IN_HDR);
262+
if (ret != 0)
263+
return ret;
264+
265+
srandom(part);
266+
for (i = IMAGE_HEADER_SIZE; i < (int)total; i += 4) {
267+
uint32_t rnd = (random() << 16) | random();
268+
memcpy(buf + i, &rnd, 4);
269+
}
270+
for (i = IMAGE_HEADER_SIZE; i < (int)total; i += WOLFBOOT_SHA_BLOCK_SIZE) {
271+
int len = WOLFBOOT_SHA_BLOCK_SIZE;
272+
if ((int)total - i < len)
273+
len = (int)total - i;
274+
ret = wc_Sha256Update(&sha, buf + i, len);
275+
if (ret != 0)
276+
return ret;
277+
}
278+
279+
ret = wc_Sha256Final(&sha, digest);
280+
if (ret != 0)
281+
return ret;
282+
wc_Sha256Free(&sha);
283+
284+
word = SHA256_DIGEST_SIZE << 16 | HDR_SHA256;
285+
memcpy(buf + DIGEST_TLV_OFF_IN_HDR, &word, 4);
286+
memcpy(buf + DIGEST_TLV_OFF_IN_HDR + 4, digest, SHA256_DIGEST_SIZE);
287+
288+
return 0;
289+
}
290+
291+
static int add_payload_encrypted(uint8_t part, uint32_t version, uint32_t size,
292+
int use_fallback_iv)
293+
{
294+
uint32_t total = size + IMAGE_HEADER_SIZE;
295+
uint8_t *buf = NULL;
296+
uintptr_t base = (uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
297+
int ret;
298+
int prev = 0;
299+
300+
if (part == PART_BOOT)
301+
base = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
302+
else if (part == PART_UPDATE)
303+
base = (uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
304+
else
305+
return -1;
306+
307+
buf = malloc(total);
308+
if (!buf)
309+
return -1;
310+
311+
ret = build_image_buffer(part, version, size, buf, total);
312+
if (ret != 0) {
313+
free(buf);
314+
return ret;
315+
}
316+
317+
if (use_fallback_iv)
318+
prev = wolfBoot_enable_fallback_iv(1);
319+
320+
ext_flash_unlock();
321+
{
322+
uint32_t off = 0;
323+
while (off < total) {
324+
uint32_t chunk = total - off;
325+
if (chunk > WOLFBOOT_SECTOR_SIZE)
326+
chunk = WOLFBOOT_SECTOR_SIZE;
327+
if (use_fallback_iv)
328+
wolfBoot_enable_fallback_iv(1);
329+
ret = ext_flash_encrypt_write(base + off, buf + off, chunk);
330+
if (ret != 0)
331+
break;
332+
off += chunk;
333+
}
334+
}
335+
ext_flash_lock();
336+
337+
if (use_fallback_iv)
338+
wolfBoot_enable_fallback_iv(prev);
339+
340+
free(buf);
341+
return ret;
342+
}
343+
#endif
344+
201345
START_TEST (test_empty_panic)
202346
{
203347
reset_mock_stats();
@@ -210,6 +354,31 @@ START_TEST (test_empty_panic)
210354
}
211355
END_TEST
212356

357+
#ifdef EXT_ENCRYPTED
358+
START_TEST (test_fallback_image_verification_rejects_corruption)
359+
{
360+
int ret;
361+
uint8_t bad = 0x00;
362+
363+
reset_mock_stats();
364+
prepare_flash();
365+
366+
add_payload(PART_BOOT, 1, TEST_SIZE_SMALL);
367+
ret = add_payload_encrypted(PART_UPDATE, 2, TEST_SIZE_SMALL, 1);
368+
ck_assert_int_eq(ret, 0);
369+
370+
ext_flash_unlock();
371+
ext_flash_write((uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS +
372+
IMAGE_HEADER_SIZE + 16, &bad, 1);
373+
ext_flash_lock();
374+
375+
ret = wolfBoot_update(1);
376+
ck_assert_int_eq(ret, -1);
377+
378+
cleanup_flash();
379+
}
380+
END_TEST
381+
#endif
213382

214383
START_TEST (test_sunnyday_noupdate)
215384
{
@@ -498,6 +667,9 @@ Suite *wolfboot_suite(void)
498667
Suite *s = suite_create("wolfboot");
499668

500669
/* Test cases */
670+
#ifdef UNIT_TEST_FALLBACK_ONLY
671+
TCase *fallback_verify = tcase_create("Fallback verify");
672+
#else
501673
TCase *empty_panic = tcase_create("Empty partition panic test");
502674
TCase *sunnyday_noupdate =
503675
tcase_create("Sunny day test with no update available");
@@ -521,9 +693,19 @@ Suite *wolfboot_suite(void)
521693
TCase *swap_resume = tcase_create("Swap resume noop");
522694
TCase *diffbase_version = tcase_create("Diffbase version lookup");
523695
TCase *boot_success = tcase_create("Boot success state");
696+
#ifdef EXT_ENCRYPTED
697+
TCase *fallback_verify = tcase_create("Fallback verify");
698+
#endif
699+
#endif
524700

525701

526-
702+
#ifdef UNIT_TEST_FALLBACK_ONLY
703+
#ifdef EXT_ENCRYPTED
704+
tcase_add_test(fallback_verify, test_fallback_image_verification_rejects_corruption);
705+
suite_add_tcase(s, fallback_verify);
706+
#endif
707+
return s;
708+
#else
527709
tcase_add_test(empty_panic, test_empty_panic);
528710
tcase_add_test(sunnyday_noupdate, test_sunnyday_noupdate);
529711
tcase_add_test(forward_update_samesize, test_forward_update_samesize);
@@ -541,8 +723,9 @@ Suite *wolfboot_suite(void)
541723
tcase_add_test(swap_resume, test_swap_resume_noop);
542724
tcase_add_test(diffbase_version, test_diffbase_version_reads);
543725
tcase_add_test(boot_success, test_boot_success_sets_state);
544-
545-
726+
#ifdef EXT_ENCRYPTED
727+
tcase_add_test(fallback_verify, test_fallback_image_verification_rejects_corruption);
728+
#endif
546729

547730
suite_add_tcase(s, empty_panic);
548731
suite_add_tcase(s, sunnyday_noupdate);
@@ -561,6 +744,10 @@ Suite *wolfboot_suite(void)
561744
suite_add_tcase(s, swap_resume);
562745
suite_add_tcase(s, diffbase_version);
563746
suite_add_tcase(s, boot_success);
747+
#ifdef EXT_ENCRYPTED
748+
suite_add_tcase(s, fallback_verify);
749+
#endif
750+
#endif
564751

565752

566753

0 commit comments

Comments
 (0)