From 4a3d9ca7cd83f419e44b0bad87cebeb349cf67f1 Mon Sep 17 00:00:00 2001 From: John Bland Date: Tue, 22 Aug 2023 21:44:31 -0400 Subject: [PATCH 1/9] add powerfail during final sector erase, exposing the problems of losing the encryption key when the power fails before the key can be written back, failing to select the correct NVM_FLASH_WRITEONCE sector when a sector is corrupt, and losing the testing state when the power fails before the partition state can be set. these issues are addressed in the next commit --- tools/scripts/sim-update-powerfail-resume.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/scripts/sim-update-powerfail-resume.sh b/tools/scripts/sim-update-powerfail-resume.sh index e3980d03d..3c2d71e6e 100755 --- a/tools/scripts/sim-update-powerfail-resume.sh +++ b/tools/scripts/sim-update-powerfail-resume.sh @@ -9,6 +9,9 @@ fi ./wolfboot.elf powerfail 15000 get_version 2>/dev/null ./wolfboot.elf powerfail 18000 get_version 2>/dev/null ./wolfboot.elf powerfail 1a000 get_version 2>/dev/null +# fail on the last sector to stop the encrypt key save and state update +./wolfboot.elf powerfail 3e000 get_version 2>/dev/null +./wolfboot.elf powerfail 3f000 get_version 2>/dev/null V=`./wolfboot.elf get_version 2>/dev/null` if [ "x$V" != "x2" ]; then @@ -20,6 +23,8 @@ fi ./wolfboot.elf powerfail 11000 get_version 2>/dev/null ./wolfboot.elf powerfail 14000 get_version 2>/dev/null ./wolfboot.elf powerfail 1e000 get_version 2>/dev/null +./wolfboot.elf powerfail 3e000 get_version 2>/dev/null +./wolfboot.elf powerfail 3f000 get_version 2>/dev/null V=`./wolfboot.elf get_version 2>/dev/null` if [ "x$V" != "x1" ]; then From feded3469654755b458212524e49f991d05db78f Mon Sep 17 00:00:00 2001 From: John Bland Date: Tue, 22 Aug 2023 21:59:23 -0400 Subject: [PATCH 2/9] change the final steps of wolfBoot_update into repeatable steps so that power failure wont erase the encryption key and wont cause skipping the testing phase of boot. this is done by marking the update partition as final swap when erasing the final sector and backing up the key in boot sector 0 after swaping the real boot sector 0 to swap. then when a power failure occurs the encryption key will be available in either boot sector 0 or the normal location. the intermediate phase also prevents skipping the testing phase since the last sector, which holds the boot state, is erased and then set repeatably, since the final swap state is set on the update partition --- include/encrypt.h | 2 + include/image.h | 16 ++- include/wolfboot/wolfboot.h | 8 ++ src/libwolfboot.c | 172 +++++++++++++++++++++++--- src/update_flash.c | 234 ++++++++++++++++++++++++++++++------ test-app/app_sim.c | 7 +- 6 files changed, 374 insertions(+), 65 deletions(-) diff --git a/include/encrypt.h b/include/encrypt.h index be909ee60..0812ea939 100644 --- a/include/encrypt.h +++ b/include/encrypt.h @@ -64,6 +64,8 @@ void aes_set_iv(uint8_t *nonce, uint32_t address); #endif /* ENCRYPT_WITH_CHACHA */ /* Internal read/write functions (not exported in the libwolfboot API) */ +int ext_flash_encrypt_write_ex(uintptr_t address, + const uint8_t *data, int len, int forcedEnc); int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len); int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len); diff --git a/include/image.h b/include/image.h index dfade4b95..8f915bcd5 100644 --- a/include/image.h +++ b/include/image.h @@ -616,10 +616,18 @@ static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off, } static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off, - const void *data, uint32_t size) + const void *data, uint32_t size, int forcedEncrypt) { - if (PART_IS_EXT(img)) - return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, size); + if (PART_IS_EXT(img)) { +#if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST)) + if (forcedEncrypt == 1) + return ext_flash_encrypt_write_ex((uintptr_t)(img->hdr) + off, data, + size, forcedEncrypt); + else +#endif + return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, + size); + } else return hal_flash_write((uintptr_t)(img->hdr) + off, data, size); } @@ -657,7 +665,7 @@ static inline int wb_flash_write_verify_word(struct wolfBoot_image *img, # define PARTN_IS_EXT(x) (0) # define wb_flash_erase(im, of, siz) \ hal_flash_erase(((uintptr_t)(((im)->hdr)) + of), siz) -# define wb_flash_write(im, of, dat, siz) \ +# define wb_flash_write(im, of, dat, siz, I) \ hal_flash_write(((uintptr_t)((im)->hdr)) + of, dat, siz) #endif /* EXT_FLASH */ diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index 88ee03101..d6224edf9 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -244,6 +244,7 @@ extern "C" { #ifndef WOLFBOOT_FLAGS_INVERT #define IMG_STATE_NEW 0xFF #define IMG_STATE_UPDATING 0x70 +#define IMG_STATE_FINAL_SWAP 0x30 #define IMG_STATE_TESTING 0x10 #define IMG_STATE_SUCCESS 0x00 #define FLASH_BYTE_ERASED 0xFF @@ -251,6 +252,7 @@ extern "C" { #else #define IMG_STATE_NEW 0x00 #define IMG_STATE_UPDATING 0x8F +#define IMG_STATE_FINAL_SWAP 0xBF #define IMG_STATE_TESTING 0xEF #define IMG_STATE_SUCCESS 0xFF #define FLASH_BYTE_ERASED 0x00 @@ -314,9 +316,15 @@ int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr); #endif int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce); +int wolfBoot_backup_encrypt_key(const uint8_t* key, const uint8_t* nonce); int wolfBoot_get_encrypt_key(uint8_t *key, uint8_t *nonce); int wolfBoot_erase_encrypt_key(void); +#ifdef FLAGS_HOME +int wolfBoot_flags_home_set_final_swap(); +int wolfBoot_flags_home_get_final_swap(); +#endif + #ifdef __cplusplus } #endif diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 1bd646c94..e9a955478 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -195,6 +195,8 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part) uintptr_t off; uint8_t *base; uint8_t* addrErase; + uint32_t word_0; + uint32_t word_1; /* if FLAGS_HOME check both boot and update for changes */ #ifdef FLAGS_HOME @@ -215,8 +217,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part) #endif #ifdef EXT_ENCRYPTED - uint32_t word_0; - uint32_t word_1; #ifndef FLAGS_HOME if (part == PART_BOOT) #endif @@ -239,6 +239,36 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part) } #endif + /* check magic in case the sector is corrupt */ + word_0 = *((uint32_t*)(base - sizeof(uint32_t))); + word_1 = *((uint32_t*)(base - WOLFBOOT_SECTOR_SIZE - sizeof(uint32_t))); + + if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) { + sel = 0; + goto finish; + } + else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) { + sel = 1; + goto finish; + } + +/* try the update magic as well */ +#ifdef FLAGS_HOME + /* check magic in case the sector is corrupt */ + word_0 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - sizeof(uint32_t))); + word_1 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - WOLFBOOT_SECTOR_SIZE - + sizeof(uint32_t))); + + if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) { + sel = 0; + goto finish; + } + else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) { + sel = 1; + goto finish; + } +#endif + /* Default to last sector if no match is found */ sel = 0; @@ -1347,21 +1377,37 @@ static int RAMFUNCTION hal_set_key(const uint8_t *k, const uint8_t *nonce) addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1)); addr_off = addr & (WOLFBOOT_SECTOR_SIZE - 1); #ifdef NVM_FLASH_WRITEONCE + /* we read from the populated sector, now write to the erased sector */ sel_sec = nvm_select_fresh_sector(PART_BOOT); addr_align -= (sel_sec * WOLFBOOT_SECTOR_SIZE); #endif hal_flash_unlock(); /* casting to unsigned long to abide compilers on 64bit architectures */ XMEMCPY(ENCRYPT_CACHE, - (void*)(unsigned long)(addr_align) , + (void*)(unsigned long)(addr_align), WOLFBOOT_SECTOR_SIZE); +#ifdef NVM_FLASH_WRITEONCE + /* we read from the populated sector, now write to the erased sector */ + addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1)); + addr_align -= (!sel_sec * WOLFBOOT_SECTOR_SIZE); +#else + /* erase the old key */ ret = hal_flash_erase(addr_align, WOLFBOOT_SECTOR_SIZE); if (ret != 0) return ret; +#endif XMEMCPY(ENCRYPT_CACHE + addr_off, k, ENCRYPT_KEY_SIZE); XMEMCPY(ENCRYPT_CACHE + addr_off + ENCRYPT_KEY_SIZE, nonce, ENCRYPT_NONCE_SIZE); ret = hal_flash_write(addr_align, ENCRYPT_CACHE, WOLFBOOT_SECTOR_SIZE); +#ifdef NVM_FLASH_WRITEONCE + /* now erase the old populated sector */ + if (ret != 0) + return ret; + addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1)); + addr_align -= (sel_sec * WOLFBOOT_SECTOR_SIZE); + ret = hal_flash_erase(addr_align, WOLFBOOT_SECTOR_SIZE); +#endif hal_flash_lock(); return ret; #endif @@ -1385,14 +1431,31 @@ int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key, return 0; } +int RAMFUNCTION wolfBoot_backup_encrypt_key(const uint8_t* key, + const uint8_t* nonce) +{ +#ifndef MMU + uint32_t magic[2] = {WOLFBOOT_MAGIC, WOLFBOOT_MAGIC_TRAIL}; + + hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS, key, + ENCRYPT_KEY_SIZE); + hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS + + ENCRYPT_KEY_SIZE, nonce, ENCRYPT_NONCE_SIZE); + /* write magic so we know we finished in case of a powerfail */ + hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS + + ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE, (uint8_t*)magic, sizeof(magic)); +#endif + return 0; +} + #ifndef UNIT_TEST /** - * @brief Set the encryption key. + * @brief Get the encryption key. * - * This function sets the encryption key and nonce used for encrypting the - * firmware image. It stores the key and nonce in the designated memory location. + * This function gets the encryption key and nonce used for encrypting the + * firmware image. * - * @param key Pointer to the encryption key. + * @param k Pointer to the encryption key. * @param nonce Pointer to the encryption nonce. * * @return 0 if successful. @@ -1400,21 +1463,39 @@ int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key, */ int RAMFUNCTION wolfBoot_get_encrypt_key(uint8_t *k, uint8_t *nonce) { + int ret = 0; #if defined(MMU) XMEMCPY(k, ENCRYPT_KEY, ENCRYPT_KEY_SIZE); XMEMCPY(nonce, ENCRYPT_KEY + ENCRYPT_KEY_SIZE, ENCRYPT_NONCE_SIZE); #else - uint8_t *mem = (uint8_t *)(ENCRYPT_TMP_SECRET_OFFSET + - WOLFBOOT_PARTITION_BOOT_ADDRESS); - int sel_sec = 0; - #ifdef NVM_FLASH_WRITEONCE - sel_sec = nvm_select_fresh_sector(PART_BOOT); - mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE); - #endif + uint8_t* mem; + uint32_t magic[2]; + + /* see if we've backed up the key, this will only matter for final swap */ + XMEMCPY(magic, (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS + + ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE, sizeof(magic)); + + if (magic[0] == WOLFBOOT_MAGIC && magic[1] == WOLFBOOT_MAGIC_TRAIL) { + mem = (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS; + /* not a failure but finalize needs to know that it's safe to erase and + * write the key to the normal spot */ + ret = 1; + } + else { + mem = (uint8_t *)(ENCRYPT_TMP_SECRET_OFFSET + + WOLFBOOT_PARTITION_BOOT_ADDRESS); + +#ifdef NVM_FLASH_WRITEONCE + int sel_sec = 0; + sel_sec = nvm_select_fresh_sector(PART_BOOT); + mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE); +#endif + } + XMEMCPY(k, mem, ENCRYPT_KEY_SIZE); XMEMCPY(nonce, mem + ENCRYPT_KEY_SIZE, ENCRYPT_NONCE_SIZE); #endif - return 0; + return ret; } #endif /** @@ -1626,10 +1707,12 @@ static uint8_t RAMFUNCTION part_address(uintptr_t a) * @param address The address in the external flash to write the data to. * @param data Pointer to the data buffer to be written. * @param len The length of the data to be written. + * @param forcedEnc force writing encryption, used during final swap * * @return int 0 if successful, -1 on failure. */ -int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len) +int RAMFUNCTION ext_flash_encrypt_write_ex(uintptr_t address, + const uint8_t *data, int len, int forcedEnc) { uint8_t block[ENCRYPT_BLOCK_SIZE]; uint8_t enc_block[ENCRYPT_BLOCK_SIZE]; @@ -1664,7 +1747,9 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, break; case PART_SWAP: /* data is coming from update and is already encrypted */ - return ext_flash_write(address, data, len); + if (forcedEnc == 0) + return ext_flash_write(address, data, len); + break; default: return -1; } @@ -1694,6 +1779,23 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, return ext_flash_write(address, ENCRYPT_CACHE, step); } + +/** + * @brief Write encrypted data to an external flash. + * + * This function calls ext_flash_encrypt_write_ex with forced encryption off + * + * @param address The address in the external flash to write the data to. + * @param data Pointer to the data buffer to be written. + * @param len The length of the data to be written. + * + * @return int 0 if successful, -1 on failure. + */ +int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len) +{ + return ext_flash_encrypt_write_ex(address, data, len, 0); +} + /** * @brief Read and decrypt data from an external flash. * @@ -1840,3 +1942,39 @@ int wolfBoot_ram_decrypt(uint8_t *src, uint8_t *dst) } #endif /* MMU */ #endif /* EXT_ENCRYPTED */ + +#ifdef FLAGS_HOME +/* we need to write a marker to update since the boot and update flags are all + * in the same sector so write magic to the first sector of boot */ +int wolfBoot_flags_home_set_final_swap() +{ +/* EXT_ENCRYPTED uses the first sector to store the key and magic, don't + * overwrite it */ +#ifndef EXT_ENCRYPTED + uint32_t magic[2] = {WOLFBOOT_MAGIC, WOLFBOOT_MAGIC_TRAIL}; + uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS; + + hal_flash_write(addr, (uint8_t*)magic, sizeof(magic)); +#endif /* !EXT_ENCRYPTED */ + + return 0; +} + +int wolfBoot_flags_home_get_final_swap() +{ + uint32_t magic[2]; + uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS; + +/* if encryption is on magic will be after the key and nonce */ +#ifdef EXT_ENCRYPTED + addr += ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE; +#endif + + XMEMCPY((uint8_t*)magic, (uint8_t*)addr, sizeof(magic)); + + if (magic[0] == WOLFBOOT_MAGIC && magic[1] == WOLFBOOT_MAGIC_TRAIL) + return 1; + + return 0; +} +#endif /* FLAGS_HOME */ diff --git a/src/update_flash.c b/src/update_flash.c index 98373c861..81a1682e9 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -123,7 +123,8 @@ void wolfBoot_check_self_update(void) } #endif /* RAM_CODE for self_update */ -static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct wolfBoot_image *dst, uint32_t sector) +static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, + struct wolfBoot_image *dst, uint32_t sector, int forcedEncrypt) { uint32_t pos = 0; uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE); @@ -173,8 +174,8 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w (void *)buffer, FLASHBUFFER_SIZE); } - wb_flash_write(dst, - dst_sector_offset + pos, buffer, FLASHBUFFER_SIZE); + wb_flash_write(dst, dst_sector_offset + pos, buffer, + FLASHBUFFER_SIZE, forcedEncrypt); } pos += FLASHBUFFER_SIZE; } @@ -183,15 +184,108 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w #endif wb_flash_erase(dst, dst_sector_offset, WOLFBOOT_SECTOR_SIZE); while (pos < WOLFBOOT_SECTOR_SIZE) { - if (src_sector_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) { + if (src_sector_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + + FLASHBUFFER_SIZE)) { uint8_t *orig = (uint8_t*)(src->hdr + src_sector_offset + pos); - wb_flash_write(dst, dst_sector_offset + pos, orig, FLASHBUFFER_SIZE); + wb_flash_write(dst, dst_sector_offset + pos, orig, FLASHBUFFER_SIZE, + forcedEncrypt); } pos += FLASHBUFFER_SIZE; } return pos; } +static int wolfBoot_finalize(struct wolfBoot_image *boot, + struct wolfBoot_image *update, struct wolfBoot_image *swap) +{ + uint8_t st; + uint32_t sector = (WOLFBOOT_PARTITION_SIZE / WOLFBOOT_SECTOR_SIZE) - 1; + +#ifdef FLAGS_HOME + /* set the UPDATE state as FINAL_SWAP in case it was erased in a later + * step last boot */ + st = IMG_STATE_FINAL_SWAP; + wolfBoot_set_partition_state(PART_UPDATE, st); +#endif + +#ifdef EXT_ENCRYPTED + int ret = 0; + uint8_t key[ENCRYPT_KEY_SIZE]; + uint8_t nonce[ENCRYPT_NONCE_SIZE]; + + /* get the encryption key, this will check the backup */ + ret = wolfBoot_get_encrypt_key(key, nonce); + + /* key came from the backup, this means it's safe and neccassary to erase + * and re-write the key to the normal spot */ + if (ret == 1) { + hal_flash_lock(); + + wolfBoot_set_encrypt_key(key, nonce); + + hal_flash_unlock(); + } + + /* erase the first sector of boot */ + wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE); + + /* backup the key */ + wolfBoot_backup_encrypt_key(key, nonce); +#elif defined(FLAGS_HOME) + /* erase the first sector of boot */ + wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE); + + /* write magic to sector 0 so we know it's final swap */ + wolfBoot_flags_home_set_final_swap(); +#endif + +#ifdef NVM_FLASH_WRITEONCE + /* erase the alternate sector */ + wb_flash_erase(boot, (sector - 1) * WOLFBOOT_SECTOR_SIZE, + WOLFBOOT_SECTOR_SIZE); +#endif + + /* erase the last sector of boot */ + wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); + +#ifdef EXT_ENCRYPTED + hal_flash_lock(); + + /* write the key back to the last sector */ + wolfBoot_set_encrypt_key(key, nonce); + + hal_flash_unlock(); +#endif + +#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME) + /* decrypt and copy the first sector back to boot */ + wolfBoot_copy_sector(swap, boot, 0, 0); +#endif + + /* set the boot state to testing */ + st = IMG_STATE_TESTING; + wolfBoot_set_partition_state(PART_BOOT, st); + +#ifdef NVM_FLASH_WRITEONCE + /* erase the alternate sector */ + wb_flash_erase(update, (sector - 1) * WOLFBOOT_SECTOR_SIZE, + WOLFBOOT_SECTOR_SIZE); +#endif + + /* erase the last sector of update */ + wb_flash_erase(update, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); + + /* erase swap */ + wb_flash_erase(swap, 0, WOLFBOOT_SECTOR_SIZE); + +#ifdef EXT_FLASH + ext_flash_lock(); +#endif + hal_flash_lock(); + + return 0; +} + #ifdef DELTA_UPDATES #ifndef DELTA_BLOCK_SIZE @@ -276,7 +370,7 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, goto out; } #else - wb_flash_write(swap, len, delta_blk, ret); + wb_flash_write(swap, len, delta_blk, ret, 0); #endif len += ret; } else if (ret == 0) { @@ -301,7 +395,7 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, } } if (flag == SECT_FLAG_SWAPPING) { - wolfBoot_copy_sector(swap, boot, sector); + wolfBoot_copy_sector(swap, boot, sector, 0); flag = SECT_FLAG_UPDATED; if (((sector + 1) * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); @@ -329,27 +423,36 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, sector++; } ret = 0; - while((sector * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE) { - hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS + - sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); + /* erase to the last sector, writeonce has 2 sectors */ + while((sector * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE - + WOLFBOOT_SECTOR_SIZE +#ifdef NVM_FLASH_WRITEONCE + * 2 +#endif + ) { + wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); sector++; } - st = IMG_STATE_TESTING; - wolfBoot_set_partition_state(PART_BOOT, st); - /* On success, reset all flags on update partition */ - wb_flash_erase(update, WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE, - WOLFBOOT_SECTOR_SIZE); -out: - wb_flash_erase(swap, 0, WOLFBOOT_SECTOR_SIZE); -#ifdef EXT_FLASH - ext_flash_lock(); +#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME) + /* copy the first sector of boot to swap so we can use it for the final + * swap, force encryption */ + wolfBoot_copy_sector(boot, swap, 0, 1); #endif - hal_flash_lock(); + /* set the UPDATE state as FINAL_SWAP */ + st = IMG_STATE_FINAL_SWAP; + wolfBoot_set_partition_state(PART_UPDATE, st); -/* Save the encryption key after swapping */ -#ifdef EXT_ENCRYPTED - wolfBoot_set_encrypt_key(key, nonce); +#ifdef FLAGS_HOME + /* erase the first sector of boot */ + wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE); + + /* set final swap */ + wolfBoot_flags_home_set_final_swap(); #endif + + /* finalize the boot sector */ + wolfBoot_finalize(boot, update, swap); +out: return ret; } @@ -406,6 +509,26 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) wolfBoot_open_image(&boot, PART_BOOT); wolfBoot_open_image(&swap, PART_SWAP); +#ifndef DISABLE_BACKUP + /* if we were on the final swap just finish it */ + if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0 && + st == IMG_STATE_FINAL_SWAP) +#ifdef FLAGS_HOME + || wolfBoot_flags_home_get_final_swap() +#endif + ) { + + hal_flash_unlock(); +#ifdef EXT_FLASH + ext_flash_unlock(); +#endif + + wolfBoot_finalize(&boot, &update, &swap); + + return 0; + } +#endif + /* get total size */ total_size = wolfBoot_get_total_size(&boot, &update); @@ -474,12 +597,6 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) ext_flash_unlock(); #endif - -/* Read encryption key/IV before starting the update */ -#ifdef EXT_ENCRYPTED - wolfBoot_get_encrypt_key(key, nonce); -#endif - #ifndef DISABLE_BACKUP /* Interruptible swap * The status is saved in the sector flags of the update partition. @@ -488,7 +605,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) while ((sector * sector_size) < total_size) { if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) { flag = SECT_FLAG_SWAPPING; - wolfBoot_copy_sector(&update, &swap, sector); + wolfBoot_copy_sector(&update, &swap, sector, 0); if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); } @@ -497,8 +614,8 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) if (size > sector_size) size = sector_size; flag = SECT_FLAG_BACKUP; - wolfBoot_copy_sector(&boot, &update, sector); - if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) + wolfBoot_copy_sector(&boot, &update, sector, 0); + if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); } if (flag == SECT_FLAG_BACKUP) { @@ -506,7 +623,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) if (size > sector_size) size = sector_size; flag = SECT_FLAG_UPDATED; - wolfBoot_copy_sector(&swap, &boot, sector); + wolfBoot_copy_sector(&swap, &boot, sector, 0); if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); } @@ -531,16 +648,45 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) return -1; } } - while((sector * sector_size) < WOLFBOOT_PARTITION_SIZE) { + + /* erase to the last sector, writeonce has 2 sectors */ + while((sector * sector_size) < WOLFBOOT_PARTITION_SIZE - + sector_size +#ifdef NVM_FLASH_WRITEONCE + * 2 +#endif + ) { wb_flash_erase(&boot, sector * sector_size, sector_size); wb_flash_erase(&update, sector * sector_size, sector_size); sector++; } - wb_flash_erase(&swap, 0, WOLFBOOT_SECTOR_SIZE); - st = IMG_STATE_TESTING; - wolfBoot_set_partition_state(PART_BOOT, st); +#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME) + /* copy the first sector of boot to swap so we can use it for the final + * swap, force encryption */ + wolfBoot_copy_sector(&boot, &swap, 0, 1); +#endif + + /* set the UPDATE state as FINAL_SWAP */ + st = IMG_STATE_FINAL_SWAP; + wolfBoot_set_partition_state(PART_UPDATE, st); + +#ifdef FLAGS_HOME + /* erase the first sector of boot */ + wb_flash_erase(&boot, 0, WOLFBOOT_SECTOR_SIZE); + + /* set final swap */ + wolfBoot_flags_home_set_final_swap(); +#endif + + /* finalize the boot sector */ + wolfBoot_finalize(&boot, &update, &swap); #else /* DISABLE_BACKUP */ #warning "Backup mechanism disabled! Update installation will not be interruptible" + /* Read encryption key/IV before starting the update */ +#ifdef EXT_ENCRYPTED + wolfBoot_get_encrypt_key(key, nonce); +#endif + /* Directly copy the content of the UPDATE partition into the BOOT partition. * This mechanism is not fail-safe, and will brick your device if interrupted * before the copy is finished. @@ -548,7 +694,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) while ((sector * sector_size) < total_size) { if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) { flag = SECT_FLAG_SWAPPING; - wolfBoot_copy_sector(&update, &boot, sector); + wolfBoot_copy_sector(&update, &boot, sector, 0); if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); } @@ -560,7 +706,6 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) } st = IMG_STATE_SUCCESS; wolfBoot_set_partition_state(PART_BOOT, st); -#endif #ifdef EXT_FLASH ext_flash_lock(); @@ -571,6 +716,8 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) #ifdef EXT_ENCRYPTED wolfBoot_set_encrypt_key(key, nonce); #endif + +#endif /* DISABLE_BACKUP */ return 0; } @@ -711,7 +858,14 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_update_trigger(); } wolfBoot_update(1); - } else if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && (st == IMG_STATE_UPDATING)) { + /* Check for new updates in the UPDATE partition or if we were + * interrupted during the final sector write */ + } else if (((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && + (st == IMG_STATE_UPDATING || st == IMG_STATE_FINAL_SWAP)) +#ifdef FLAGS_HOME + || wolfBoot_flags_home_get_final_swap() +#endif + ) { /* Check for new updates in the UPDATE partition */ wolfBoot_update(0); } diff --git a/test-app/app_sim.c b/test-app/app_sim.c index 454fb779e..b977daabd 100644 --- a/test-app/app_sim.c +++ b/test-app/app_sim.c @@ -56,6 +56,9 @@ int do_cmd(const char *cmd) return 0; } if (strcmp(cmd, "update_trigger") == 0) { +#if EXT_ENCRYPTED + wolfBoot_set_encrypt_key((uint8_t *)enc_key,(uint8_t *)(enc_key + 32)); +#endif wolfBoot_update_trigger(); return 0; } @@ -74,10 +77,6 @@ int main(int argc, char *argv[]) { hal_init(); -#if EXT_ENCRYPTED - wolfBoot_set_encrypt_key((uint8_t *)enc_key,(uint8_t *)(enc_key + 32)); -#endif - for (i = 1; i < argc; ++i) { ret = do_cmd(argv[i]); if (ret < 0) From 84e2d115a74ca2259c4760ad9e89a1db2383b242 Mon Sep 17 00:00:00 2001 From: John Bland Date: Tue, 22 Aug 2023 22:40:41 -0400 Subject: [PATCH 3/9] add missing FINAL_SWAP check --- src/update_flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/update_flash.c b/src/update_flash.c index 81a1682e9..5b44d07d0 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -852,7 +852,7 @@ void RAMFUNCTION wolfBoot_start(void) * wolfBoot_update_trigger is called and thus it shouldn't be called * if an update is already in progress */ #if defined(NVM_FLASH_WRITEONCE) || defined(WOLFBOOT_FLAGS_INVERT) - if ((wolfBoot_get_partition_state(PART_UPDATE, &st) != 0) || (st != IMG_STATE_UPDATING)) + if ((wolfBoot_get_partition_state(PART_UPDATE, &st) != 0) || (st != IMG_STATE_UPDATING && st != IMG_STATE_FINAL_SWAP)) #endif { wolfBoot_update_trigger(); From 1a2294ceb0c7c5515df7100873b956afefdfc2d3 Mon Sep 17 00:00:00 2001 From: John Bland Date: Tue, 22 Aug 2023 23:09:38 -0400 Subject: [PATCH 4/9] make aes_init and chacha_init read the backup key --- src/libwolfboot.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/libwolfboot.c b/src/libwolfboot.c index e9a955478..b128c4c72 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -1539,16 +1539,12 @@ int RAMFUNCTION chacha_init(void) #if defined(MMU) || defined(UNIT_TEST) uint8_t *key = ENCRYPT_KEY; #else - uint8_t *key = (uint8_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + - ENCRYPT_TMP_SECRET_OFFSET); + uint8_t key[ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE]; + wolfBoot_get_encrypt_key(key, key + ENCRYPT_KEY_SIZE); #endif uint8_t ff[ENCRYPT_KEY_SIZE]; uint8_t* stored_nonce; -#ifdef NVM_FLASH_WRITEONCE - key -= WOLFBOOT_SECTOR_SIZE * nvm_select_fresh_sector(PART_BOOT); -#endif - stored_nonce = key + ENCRYPT_KEY_SIZE; XMEMSET(&chacha, 0, sizeof(chacha)); @@ -1585,17 +1581,13 @@ int aes_init(void) #if defined(MMU) || defined(UNIT_TEST) uint8_t *key = ENCRYPT_KEY; #else - uint8_t *key = (uint8_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + - ENCRYPT_TMP_SECRET_OFFSET); + uint8_t key[ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE]; + wolfBoot_get_encrypt_key(key, key + ENCRYPT_KEY_SIZE); #endif uint8_t ff[ENCRYPT_KEY_SIZE]; uint8_t iv_buf[ENCRYPT_NONCE_SIZE]; uint8_t* stored_nonce; -#ifdef NVM_FLASH_WRITEONCE - key -= WOLFBOOT_SECTOR_SIZE * nvm_select_fresh_sector(PART_BOOT); -#endif - stored_nonce = key + ENCRYPT_KEY_SIZE; XMEMSET(&aes_enc, 0, sizeof(aes_enc)); From face02e86a4a0c2a3986bb2023227009d8f21e67 Mon Sep 17 00:00:00 2001 From: John Bland Date: Tue, 22 Aug 2023 23:19:04 -0400 Subject: [PATCH 5/9] footprint update --- tools/test.mk | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tools/test.mk b/tools/test.mk index 65d8527d6..eb5ecd7ec 100644 --- a/tools/test.mk +++ b/tools/test.mk @@ -942,29 +942,29 @@ test-all: clean test-size-all: - make test-size SIGN=NONE LIMIT=4732 + make test-size SIGN=NONE LIMIT=4778 make keysclean - make test-size SIGN=ED25519 LIMIT=11398 + make test-size SIGN=ED25519 LIMIT=11462 make keysclean - make test-size SIGN=ECC256 LIMIT=22270 + make test-size SIGN=ECC256 LIMIT=22322 make keysclean - make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13706 + make test-size SIGN=ECC256 NO_ASM=1 LIMIT=13758 make keysclean - make test-size SIGN=RSA2048 LIMIT=11948 + make test-size SIGN=RSA2048 LIMIT=11242 make keysclean - make test-size SIGN=RSA2048 NO_ASM=1 LIMIT=11202 + make test-size SIGN=RSA2048 NO_ASM=1 LIMIT=11218 make keysclean - make test-size SIGN=RSA4096 LIMIT=13307 + make test-size SIGN=RSA4096 LIMIT=11602 make keysclean - make test-size SIGN=RSA4096 NO_ASM=1 LIMIT=11502 + make test-size SIGN=RSA4096 NO_ASM=1 LIMIT=11522 make keysclean - make test-size SIGN=ECC384 LIMIT=17566 + make test-size SIGN=ECC384 LIMIT=17618 make keysclean - make test-size SIGN=ECC384 NO_ASM=1 LIMIT=15172 + make test-size SIGN=ECC384 NO_ASM=1 LIMIT=15190 make keysclean - make test-size SIGN=ED448 LIMIT=13420 + make test-size SIGN=ED448 LIMIT=13470 make keysclean - make test-size SIGN=RSA3072 LIMIT=12612 + make test-size SIGN=RSA3072 LIMIT=11442 make keysclean - make test-size SIGN=RSA3072 NO_ASM=1 LIMIT=11294 + make test-size SIGN=RSA3072 NO_ASM=1 LIMIT=11314 make keysclean From d1a9ccfcab64d6dc2d2fba8bc104e18f77654c29 Mon Sep 17 00:00:00 2001 From: John Bland Date: Sun, 8 Oct 2023 18:57:30 -0400 Subject: [PATCH 6/9] remove complicated key saving process and instead leave the encryption key for wolfBoot_success to erase. FINAL_SWAP was also stopping the case where the partition was put into testing before the update sector status flags could be erased. now, don't erase the update sector flags. instead put the update partition in IMG_STATE_FINAL_FLAGS state before putting the boot partition in IMG_STATE_TESTING. Then only erase the update sector flags on wolfBoot_update_trigger. under this scheme, the sector flags are intact if the power failed before we could set IMG_STATE_TESTING but are wiped if we do need to swap over after after wolfBoot_success fails to be called --- include/encrypt.h | 2 - include/image.h | 16 +-- include/wolfboot/wolfboot.h | 10 +- lib/wolfTPM | 2 +- lib/wolfssl | 2 +- src/libwolfboot.c | 151 ++++++------------------- src/update_flash.c | 219 ++++++++---------------------------- 7 files changed, 87 insertions(+), 315 deletions(-) diff --git a/include/encrypt.h b/include/encrypt.h index 0812ea939..be909ee60 100644 --- a/include/encrypt.h +++ b/include/encrypt.h @@ -64,8 +64,6 @@ void aes_set_iv(uint8_t *nonce, uint32_t address); #endif /* ENCRYPT_WITH_CHACHA */ /* Internal read/write functions (not exported in the libwolfboot API) */ -int ext_flash_encrypt_write_ex(uintptr_t address, - const uint8_t *data, int len, int forcedEnc); int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len); int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len); diff --git a/include/image.h b/include/image.h index 8f915bcd5..dfade4b95 100644 --- a/include/image.h +++ b/include/image.h @@ -616,18 +616,10 @@ static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off, } static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off, - const void *data, uint32_t size, int forcedEncrypt) + const void *data, uint32_t size) { - if (PART_IS_EXT(img)) { -#if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST)) - if (forcedEncrypt == 1) - return ext_flash_encrypt_write_ex((uintptr_t)(img->hdr) + off, data, - size, forcedEncrypt); - else -#endif - return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, - size); - } + if (PART_IS_EXT(img)) + return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, size); else return hal_flash_write((uintptr_t)(img->hdr) + off, data, size); } @@ -665,7 +657,7 @@ static inline int wb_flash_write_verify_word(struct wolfBoot_image *img, # define PARTN_IS_EXT(x) (0) # define wb_flash_erase(im, of, siz) \ hal_flash_erase(((uintptr_t)(((im)->hdr)) + of), siz) -# define wb_flash_write(im, of, dat, siz, I) \ +# define wb_flash_write(im, of, dat, siz) \ hal_flash_write(((uintptr_t)((im)->hdr)) + of, dat, siz) #endif /* EXT_FLASH */ diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index d6224edf9..b9ec4c32d 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -244,7 +244,7 @@ extern "C" { #ifndef WOLFBOOT_FLAGS_INVERT #define IMG_STATE_NEW 0xFF #define IMG_STATE_UPDATING 0x70 -#define IMG_STATE_FINAL_SWAP 0x30 +#define IMG_STATE_FINAL_FLAGS 0x30 #define IMG_STATE_TESTING 0x10 #define IMG_STATE_SUCCESS 0x00 #define FLASH_BYTE_ERASED 0xFF @@ -252,7 +252,7 @@ extern "C" { #else #define IMG_STATE_NEW 0x00 #define IMG_STATE_UPDATING 0x8F -#define IMG_STATE_FINAL_SWAP 0xBF +#define IMG_STATE_FINAL_FLAGS 0xBF #define IMG_STATE_TESTING 0xEF #define IMG_STATE_SUCCESS 0xFF #define FLASH_BYTE_ERASED 0x00 @@ -316,15 +316,9 @@ int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr); #endif int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce); -int wolfBoot_backup_encrypt_key(const uint8_t* key, const uint8_t* nonce); int wolfBoot_get_encrypt_key(uint8_t *key, uint8_t *nonce); int wolfBoot_erase_encrypt_key(void); -#ifdef FLAGS_HOME -int wolfBoot_flags_home_set_final_swap(); -int wolfBoot_flags_home_get_final_swap(); -#endif - #ifdef __cplusplus } #endif diff --git a/lib/wolfTPM b/lib/wolfTPM index 549783056..cc88dcd4a 160000 --- a/lib/wolfTPM +++ b/lib/wolfTPM @@ -1 +1 @@ -Subproject commit 5497830567222e9a278e5a69aaeef32d5f3fc890 +Subproject commit cc88dcd4abb191fdccf29950b9f11e65b1bf757e diff --git a/lib/wolfssl b/lib/wolfssl index cd02d5140..05b692d01 160000 --- a/lib/wolfssl +++ b/lib/wolfssl @@ -1 +1 @@ -Subproject commit cd02d5140fccd2478dcd4845d1b7cef6be881dde +Subproject commit 05b692d01cb2fa172d8a86e04a1dbbdb5eb88703 diff --git a/src/libwolfboot.c b/src/libwolfboot.c index b128c4c72..1cdf25fe2 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -741,20 +741,16 @@ void RAMFUNCTION wolfBoot_erase_partition(uint8_t part) void RAMFUNCTION wolfBoot_update_trigger(void) { uint8_t st = IMG_STATE_UPDATING; -#if defined(NVM_FLASH_WRITEONCE) || defined(WOLFBOOT_FLAGS_INVERT) uintptr_t lastSector = PART_UPDATE_ENDFLAGS - (PART_UPDATE_ENDFLAGS % WOLFBOOT_SECTOR_SIZE); +#ifdef NVM_FLASH_WRITEONCE + uint8_t selSec = 0; +#endif -#ifndef FLAGS_HOME /* if PART_UPDATE_ENDFLAGS stradles a sector, (all non FLAGS_HOME builds) * align it to the correct sector */ if (PART_UPDATE_ENDFLAGS % WOLFBOOT_SECTOR_SIZE == 0) lastSector -= WOLFBOOT_SECTOR_SIZE; -#endif -#endif -#ifdef NVM_FLASH_WRITEONCE - uint8_t selSec = 0; -#endif /* erase the sector flags */ if (FLAGS_UPDATE_EXT()) { @@ -767,11 +763,12 @@ void RAMFUNCTION wolfBoot_update_trigger(void) * partition based on how many flags are non-erased * FLAGS_INVERT needs erased flags because the bin-assemble's fill byte may * not match what's in wolfBoot */ -#if defined(NVM_FLASH_WRITEONCE) || defined(WOLFBOOT_FLAGS_INVERT) if (FLAGS_UPDATE_EXT()) { ext_flash_erase(lastSector, SECTOR_FLAGS_SIZE); } else { -#ifdef NVM_FLASH_WRITEONCE +#ifndef NVM_FLASH_WRITEONCE + hal_flash_erase(lastSector, SECTOR_FLAGS_SIZE); +#else selSec = nvm_select_fresh_sector(PART_UPDATE); XMEMCPY(NVM_CACHE, (uint8_t*)(lastSector - WOLFBOOT_SECTOR_SIZE * selSec), @@ -783,11 +780,8 @@ void RAMFUNCTION wolfBoot_update_trigger(void) /* erase the previously selected sector */ hal_flash_erase(lastSector - WOLFBOOT_SECTOR_SIZE * selSec, WOLFBOOT_SECTOR_SIZE); -#elif defined(WOLFBOOT_FLAGS_INVERT) - hal_flash_erase(lastSector, SECTOR_FLAGS_SIZE); #endif } -#endif wolfBoot_set_partition_state(PART_UPDATE, st); @@ -812,10 +806,16 @@ void RAMFUNCTION wolfBoot_success(void) if (FLAGS_BOOT_EXT()) { ext_flash_unlock(); wolfBoot_set_partition_state(PART_BOOT, st); + /* set update so IMG_STATE_FINAL_FLAGS isn't triggering pointless calls + * to wolfBoot update */ + wolfBoot_set_partition_state(PART_UPDATE, st); ext_flash_lock(); } else { hal_flash_unlock(); wolfBoot_set_partition_state(PART_BOOT, st); + /* set update so IMG_STATE_FINAL_FLAGS isn't triggering pointless calls + * to wolfBoot update */ + wolfBoot_set_partition_state(PART_UPDATE, st); hal_flash_lock(); } #ifdef EXT_ENCRYPTED @@ -1431,23 +1431,6 @@ int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key, return 0; } -int RAMFUNCTION wolfBoot_backup_encrypt_key(const uint8_t* key, - const uint8_t* nonce) -{ -#ifndef MMU - uint32_t magic[2] = {WOLFBOOT_MAGIC, WOLFBOOT_MAGIC_TRAIL}; - - hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS, key, - ENCRYPT_KEY_SIZE); - hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS + - ENCRYPT_KEY_SIZE, nonce, ENCRYPT_NONCE_SIZE); - /* write magic so we know we finished in case of a powerfail */ - hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS + - ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE, (uint8_t*)magic, sizeof(magic)); -#endif - return 0; -} - #ifndef UNIT_TEST /** * @brief Get the encryption key. @@ -1463,39 +1446,21 @@ int RAMFUNCTION wolfBoot_backup_encrypt_key(const uint8_t* key, */ int RAMFUNCTION wolfBoot_get_encrypt_key(uint8_t *k, uint8_t *nonce) { - int ret = 0; #if defined(MMU) XMEMCPY(k, ENCRYPT_KEY, ENCRYPT_KEY_SIZE); XMEMCPY(nonce, ENCRYPT_KEY + ENCRYPT_KEY_SIZE, ENCRYPT_NONCE_SIZE); #else - uint8_t* mem; - uint32_t magic[2]; - - /* see if we've backed up the key, this will only matter for final swap */ - XMEMCPY(magic, (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS + - ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE, sizeof(magic)); - - if (magic[0] == WOLFBOOT_MAGIC && magic[1] == WOLFBOOT_MAGIC_TRAIL) { - mem = (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS; - /* not a failure but finalize needs to know that it's safe to erase and - * write the key to the normal spot */ - ret = 1; - } - else { - mem = (uint8_t *)(ENCRYPT_TMP_SECRET_OFFSET + - WOLFBOOT_PARTITION_BOOT_ADDRESS); - -#ifdef NVM_FLASH_WRITEONCE - int sel_sec = 0; - sel_sec = nvm_select_fresh_sector(PART_BOOT); - mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE); -#endif - } - + uint8_t *mem = (uint8_t *)(ENCRYPT_TMP_SECRET_OFFSET + + WOLFBOOT_PARTITION_BOOT_ADDRESS); + int sel_sec = 0; + #ifdef NVM_FLASH_WRITEONCE + sel_sec = nvm_select_fresh_sector(PART_BOOT); + mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE); + #endif XMEMCPY(k, mem, ENCRYPT_KEY_SIZE); XMEMCPY(nonce, mem + ENCRYPT_KEY_SIZE, ENCRYPT_NONCE_SIZE); #endif - return ret; + return 0; } #endif /** @@ -1539,12 +1504,16 @@ int RAMFUNCTION chacha_init(void) #if defined(MMU) || defined(UNIT_TEST) uint8_t *key = ENCRYPT_KEY; #else - uint8_t key[ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE]; - wolfBoot_get_encrypt_key(key, key + ENCRYPT_KEY_SIZE); + uint8_t *key = (uint8_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + + ENCRYPT_TMP_SECRET_OFFSET); #endif uint8_t ff[ENCRYPT_KEY_SIZE]; uint8_t* stored_nonce; +#ifdef NVM_FLASH_WRITEONCE + key -= WOLFBOOT_SECTOR_SIZE * nvm_select_fresh_sector(PART_BOOT); +#endif + stored_nonce = key + ENCRYPT_KEY_SIZE; XMEMSET(&chacha, 0, sizeof(chacha)); @@ -1581,13 +1550,17 @@ int aes_init(void) #if defined(MMU) || defined(UNIT_TEST) uint8_t *key = ENCRYPT_KEY; #else - uint8_t key[ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE]; - wolfBoot_get_encrypt_key(key, key + ENCRYPT_KEY_SIZE); + uint8_t *key = (uint8_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS + + ENCRYPT_TMP_SECRET_OFFSET); #endif uint8_t ff[ENCRYPT_KEY_SIZE]; uint8_t iv_buf[ENCRYPT_NONCE_SIZE]; uint8_t* stored_nonce; +#ifdef NVM_FLASH_WRITEONCE + key -= WOLFBOOT_SECTOR_SIZE * nvm_select_fresh_sector(PART_BOOT); +#endif + stored_nonce = key + ENCRYPT_KEY_SIZE; XMEMSET(&aes_enc, 0, sizeof(aes_enc)); @@ -1703,8 +1676,8 @@ static uint8_t RAMFUNCTION part_address(uintptr_t a) * * @return int 0 if successful, -1 on failure. */ -int RAMFUNCTION ext_flash_encrypt_write_ex(uintptr_t address, - const uint8_t *data, int len, int forcedEnc) +int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, + int len) { uint8_t block[ENCRYPT_BLOCK_SIZE]; uint8_t enc_block[ENCRYPT_BLOCK_SIZE]; @@ -1739,9 +1712,7 @@ int RAMFUNCTION ext_flash_encrypt_write_ex(uintptr_t address, break; case PART_SWAP: /* data is coming from update and is already encrypted */ - if (forcedEnc == 0) - return ext_flash_write(address, data, len); - break; + return ext_flash_write(address, data, len); default: return -1; } @@ -1772,22 +1743,6 @@ int RAMFUNCTION ext_flash_encrypt_write_ex(uintptr_t address, return ext_flash_write(address, ENCRYPT_CACHE, step); } -/** - * @brief Write encrypted data to an external flash. - * - * This function calls ext_flash_encrypt_write_ex with forced encryption off - * - * @param address The address in the external flash to write the data to. - * @param data Pointer to the data buffer to be written. - * @param len The length of the data to be written. - * - * @return int 0 if successful, -1 on failure. - */ -int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len) -{ - return ext_flash_encrypt_write_ex(address, data, len, 0); -} - /** * @brief Read and decrypt data from an external flash. * @@ -1934,39 +1889,3 @@ int wolfBoot_ram_decrypt(uint8_t *src, uint8_t *dst) } #endif /* MMU */ #endif /* EXT_ENCRYPTED */ - -#ifdef FLAGS_HOME -/* we need to write a marker to update since the boot and update flags are all - * in the same sector so write magic to the first sector of boot */ -int wolfBoot_flags_home_set_final_swap() -{ -/* EXT_ENCRYPTED uses the first sector to store the key and magic, don't - * overwrite it */ -#ifndef EXT_ENCRYPTED - uint32_t magic[2] = {WOLFBOOT_MAGIC, WOLFBOOT_MAGIC_TRAIL}; - uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS; - - hal_flash_write(addr, (uint8_t*)magic, sizeof(magic)); -#endif /* !EXT_ENCRYPTED */ - - return 0; -} - -int wolfBoot_flags_home_get_final_swap() -{ - uint32_t magic[2]; - uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS; - -/* if encryption is on magic will be after the key and nonce */ -#ifdef EXT_ENCRYPTED - addr += ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE; -#endif - - XMEMCPY((uint8_t*)magic, (uint8_t*)addr, sizeof(magic)); - - if (magic[0] == WOLFBOOT_MAGIC && magic[1] == WOLFBOOT_MAGIC_TRAIL) - return 1; - - return 0; -} -#endif /* FLAGS_HOME */ diff --git a/src/update_flash.c b/src/update_flash.c index 5b44d07d0..775e60c7f 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -124,7 +124,7 @@ void wolfBoot_check_self_update(void) #endif /* RAM_CODE for self_update */ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, - struct wolfBoot_image *dst, uint32_t sector, int forcedEncrypt) + struct wolfBoot_image *dst, uint32_t sector) { uint32_t pos = 0; uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE); @@ -175,7 +175,7 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, } wb_flash_write(dst, dst_sector_offset + pos, buffer, - FLASHBUFFER_SIZE, forcedEncrypt); + FLASHBUFFER_SIZE); } pos += FLASHBUFFER_SIZE; } @@ -187,105 +187,13 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, if (src_sector_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) { uint8_t *orig = (uint8_t*)(src->hdr + src_sector_offset + pos); - wb_flash_write(dst, dst_sector_offset + pos, orig, FLASHBUFFER_SIZE, - forcedEncrypt); + wb_flash_write(dst, dst_sector_offset + pos, orig, FLASHBUFFER_SIZE); } pos += FLASHBUFFER_SIZE; } return pos; } -static int wolfBoot_finalize(struct wolfBoot_image *boot, - struct wolfBoot_image *update, struct wolfBoot_image *swap) -{ - uint8_t st; - uint32_t sector = (WOLFBOOT_PARTITION_SIZE / WOLFBOOT_SECTOR_SIZE) - 1; - -#ifdef FLAGS_HOME - /* set the UPDATE state as FINAL_SWAP in case it was erased in a later - * step last boot */ - st = IMG_STATE_FINAL_SWAP; - wolfBoot_set_partition_state(PART_UPDATE, st); -#endif - -#ifdef EXT_ENCRYPTED - int ret = 0; - uint8_t key[ENCRYPT_KEY_SIZE]; - uint8_t nonce[ENCRYPT_NONCE_SIZE]; - - /* get the encryption key, this will check the backup */ - ret = wolfBoot_get_encrypt_key(key, nonce); - - /* key came from the backup, this means it's safe and neccassary to erase - * and re-write the key to the normal spot */ - if (ret == 1) { - hal_flash_lock(); - - wolfBoot_set_encrypt_key(key, nonce); - - hal_flash_unlock(); - } - - /* erase the first sector of boot */ - wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE); - - /* backup the key */ - wolfBoot_backup_encrypt_key(key, nonce); -#elif defined(FLAGS_HOME) - /* erase the first sector of boot */ - wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE); - - /* write magic to sector 0 so we know it's final swap */ - wolfBoot_flags_home_set_final_swap(); -#endif - -#ifdef NVM_FLASH_WRITEONCE - /* erase the alternate sector */ - wb_flash_erase(boot, (sector - 1) * WOLFBOOT_SECTOR_SIZE, - WOLFBOOT_SECTOR_SIZE); -#endif - - /* erase the last sector of boot */ - wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); - -#ifdef EXT_ENCRYPTED - hal_flash_lock(); - - /* write the key back to the last sector */ - wolfBoot_set_encrypt_key(key, nonce); - - hal_flash_unlock(); -#endif - -#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME) - /* decrypt and copy the first sector back to boot */ - wolfBoot_copy_sector(swap, boot, 0, 0); -#endif - - /* set the boot state to testing */ - st = IMG_STATE_TESTING; - wolfBoot_set_partition_state(PART_BOOT, st); - -#ifdef NVM_FLASH_WRITEONCE - /* erase the alternate sector */ - wb_flash_erase(update, (sector - 1) * WOLFBOOT_SECTOR_SIZE, - WOLFBOOT_SECTOR_SIZE); -#endif - - /* erase the last sector of update */ - wb_flash_erase(update, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); - - /* erase swap */ - wb_flash_erase(swap, 0, WOLFBOOT_SECTOR_SIZE); - -#ifdef EXT_FLASH - ext_flash_lock(); -#endif - hal_flash_lock(); - - return 0; -} - #ifdef DELTA_UPDATES #ifndef DELTA_BLOCK_SIZE @@ -370,7 +278,7 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, goto out; } #else - wb_flash_write(swap, len, delta_blk, ret, 0); + wb_flash_write(swap, len, delta_blk, ret); #endif len += ret; } else if (ret == 0) { @@ -395,7 +303,7 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, } } if (flag == SECT_FLAG_SWAPPING) { - wolfBoot_copy_sector(swap, boot, sector, 0); + wolfBoot_copy_sector(swap, boot, sector); flag = SECT_FLAG_UPDATED; if (((sector + 1) * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); @@ -433,26 +341,19 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); sector++; } -#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME) - /* copy the first sector of boot to swap so we can use it for the final - * swap, force encryption */ - wolfBoot_copy_sector(boot, swap, 0, 1); -#endif - /* set the UPDATE state as FINAL_SWAP */ - st = IMG_STATE_FINAL_SWAP; + /* mark that our sector flags aren't reliable in testing mode */ + st = IMG_STATE_FINAL_FLAGS; wolfBoot_set_partition_state(PART_UPDATE, st); - -#ifdef FLAGS_HOME - /* erase the first sector of boot */ - wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE); - - /* set final swap */ - wolfBoot_flags_home_set_final_swap(); -#endif - - /* finalize the boot sector */ - wolfBoot_finalize(boot, update, swap); + /* mark boot partition as testing */ + st = IMG_STATE_TESTING; + wolfBoot_set_partition_state(PART_BOOT, st); out: + wb_flash_erase(swap, 0, WOLFBOOT_SECTOR_SIZE); +#ifdef EXT_FLASH + ext_flash_lock(); +#endif + hal_flash_lock(); + /* encryption key was not erased, will be erased by success */ return ret; } @@ -493,7 +394,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) struct wolfBoot_image boot, update, swap; uint16_t update_type; uint32_t fw_size; -#ifdef EXT_ENCRYPTED +#if defined(DISABLE_BACKUP) && defined(EXT_ENCRYPTED) uint8_t key[ENCRYPT_KEY_SIZE]; uint8_t nonce[ENCRYPT_NONCE_SIZE]; #endif @@ -509,26 +410,6 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) wolfBoot_open_image(&boot, PART_BOOT); wolfBoot_open_image(&swap, PART_SWAP); -#ifndef DISABLE_BACKUP - /* if we were on the final swap just finish it */ - if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0 && - st == IMG_STATE_FINAL_SWAP) -#ifdef FLAGS_HOME - || wolfBoot_flags_home_get_final_swap() -#endif - ) { - - hal_flash_unlock(); -#ifdef EXT_FLASH - ext_flash_unlock(); -#endif - - wolfBoot_finalize(&boot, &update, &swap); - - return 0; - } -#endif - /* get total size */ total_size = wolfBoot_get_total_size(&boot, &update); @@ -605,7 +486,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) while ((sector * sector_size) < total_size) { if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) { flag = SECT_FLAG_SWAPPING; - wolfBoot_copy_sector(&update, &swap, sector, 0); + wolfBoot_copy_sector(&update, &swap, sector); if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); } @@ -614,7 +495,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) if (size > sector_size) size = sector_size; flag = SECT_FLAG_BACKUP; - wolfBoot_copy_sector(&boot, &update, sector, 0); + wolfBoot_copy_sector(&boot, &update, sector); if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); } @@ -623,7 +504,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) if (size > sector_size) size = sector_size; flag = SECT_FLAG_UPDATED; - wolfBoot_copy_sector(&swap, &boot, sector, 0); + wolfBoot_copy_sector(&swap, &boot, sector); if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); } @@ -648,7 +529,6 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) return -1; } } - /* erase to the last sector, writeonce has 2 sectors */ while((sector * sector_size) < WOLFBOOT_PARTITION_SIZE - sector_size @@ -660,26 +540,18 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) wb_flash_erase(&update, sector * sector_size, sector_size); sector++; } -#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME) - /* copy the first sector of boot to swap so we can use it for the final - * swap, force encryption */ - wolfBoot_copy_sector(&boot, &swap, 0, 1); -#endif - - /* set the UPDATE state as FINAL_SWAP */ - st = IMG_STATE_FINAL_SWAP; + /* mark that our sector flags aren't reliable in testing mode */ + st = IMG_STATE_FINAL_FLAGS; wolfBoot_set_partition_state(PART_UPDATE, st); - -#ifdef FLAGS_HOME - /* erase the first sector of boot */ - wb_flash_erase(&boot, 0, WOLFBOOT_SECTOR_SIZE); - - /* set final swap */ - wolfBoot_flags_home_set_final_swap(); + /* mark boot partition as testing */ + st = IMG_STATE_TESTING; + wolfBoot_set_partition_state(PART_BOOT, st); + wb_flash_erase(&swap, 0, WOLFBOOT_SECTOR_SIZE); + /* encryption key was not erased, will be erased by success */ +#ifdef EXT_FLASH + ext_flash_lock(); #endif - - /* finalize the boot sector */ - wolfBoot_finalize(&boot, &update, &swap); + hal_flash_lock(); #else /* DISABLE_BACKUP */ #warning "Backup mechanism disabled! Update installation will not be interruptible" /* Read encryption key/IV before starting the update */ @@ -694,7 +566,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) while ((sector * sector_size) < total_size) { if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) { flag = SECT_FLAG_SWAPPING; - wolfBoot_copy_sector(&update, &boot, sector, 0); + wolfBoot_copy_sector(&update, &boot, sector); if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE) wolfBoot_set_update_sector_flag(sector, flag); } @@ -833,7 +705,10 @@ int wolfBoot_unlock_disk(void) void RAMFUNCTION wolfBoot_start(void) { - uint8_t st; + int bootRet; + int updateRet; + uint8_t bootState; + uint8_t updateState; struct wolfBoot_image boot; #if defined(ARCH_SIM) && defined(WOLFBOOT_TPM) && defined(WOLFBOOT_TPM_SEAL) @@ -844,28 +719,22 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_check_self_update(); #endif + bootRet = wolfBoot_get_partition_state(PART_BOOT, &bootState); + updateRet = wolfBoot_get_partition_state(PART_UPDATE, &updateState); + /* Check if the BOOT partition is still in TESTING, * to trigger fallback. */ - if ((wolfBoot_get_partition_state(PART_BOOT, &st) == 0) && (st == IMG_STATE_TESTING)) { - /* these flags require erasing the sector flags when - * wolfBoot_update_trigger is called and thus it shouldn't be called - * if an update is already in progress */ -#if defined(NVM_FLASH_WRITEONCE) || defined(WOLFBOOT_FLAGS_INVERT) - if ((wolfBoot_get_partition_state(PART_UPDATE, &st) != 0) || (st != IMG_STATE_UPDATING && st != IMG_STATE_FINAL_SWAP)) -#endif - { + if (bootRet == 0 && bootState == IMG_STATE_TESTING) { + /* wolfBoot_update_trigger now erases all the sector flags, only trigger + * if we're not already updating */ + if (updateRet || updateState != IMG_STATE_UPDATING) { wolfBoot_update_trigger(); } wolfBoot_update(1); /* Check for new updates in the UPDATE partition or if we were - * interrupted during the final sector write */ - } else if (((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && - (st == IMG_STATE_UPDATING || st == IMG_STATE_FINAL_SWAP)) -#ifdef FLAGS_HOME - || wolfBoot_flags_home_get_final_swap() -#endif - ) { + * interrupted during the flags setting */ + } else if (updateRet == 0 && (updateState == IMG_STATE_UPDATING || updateState == IMG_STATE_FINAL_FLAGS)) { /* Check for new updates in the UPDATE partition */ wolfBoot_update(0); } From 5cc38edcc21c3eb3e483d359b660424453ed7705 Mon Sep 17 00:00:00 2001 From: John Bland Date: Sun, 8 Oct 2023 19:40:53 -0400 Subject: [PATCH 7/9] fix extra fallback due to non-triggered power fail --- tools/scripts/sim-update-powerfail-resume.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/scripts/sim-update-powerfail-resume.sh b/tools/scripts/sim-update-powerfail-resume.sh index 3c2d71e6e..ea99e71a6 100755 --- a/tools/scripts/sim-update-powerfail-resume.sh +++ b/tools/scripts/sim-update-powerfail-resume.sh @@ -11,9 +11,12 @@ fi ./wolfboot.elf powerfail 1a000 get_version 2>/dev/null # fail on the last sector to stop the encrypt key save and state update ./wolfboot.elf powerfail 3e000 get_version 2>/dev/null -./wolfboot.elf powerfail 3f000 get_version 2>/dev/null +# may not trigger on non NVM_FLASH_WRITEONCE +V=`./wolfboot.elf powerfail 3f000 get_version` 2>/dev/null +if [ "x$V" != "x2" ]; then + V=`./wolfboot.elf get_version 2>/dev/null` +fi -V=`./wolfboot.elf get_version 2>/dev/null` if [ "x$V" != "x2" ]; then echo "Failed update (V: $V)" exit 1 @@ -24,9 +27,12 @@ fi ./wolfboot.elf powerfail 14000 get_version 2>/dev/null ./wolfboot.elf powerfail 1e000 get_version 2>/dev/null ./wolfboot.elf powerfail 3e000 get_version 2>/dev/null -./wolfboot.elf powerfail 3f000 get_version 2>/dev/null +# may not trigger on non NVM_FLASH_WRITEONCE +V=`./wolfboot.elf powerfail 3f000 get_version` 2>/dev/null +if [ "x$V" != "x1" ]; then + V=`./wolfboot.elf get_version 2>/dev/null` +fi -V=`./wolfboot.elf get_version 2>/dev/null` if [ "x$V" != "x1" ]; then echo "Failed fallback (V: $V)" exit 1 From b32d4126f68d15c79641245a1a13cd7cb4068240 Mon Sep 17 00:00:00 2001 From: John Bland Date: Sun, 8 Oct 2023 19:47:17 -0400 Subject: [PATCH 8/9] restore correct wolfTPM and wolfssl versions --- lib/wolfTPM | 2 +- lib/wolfssl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/wolfTPM b/lib/wolfTPM index cc88dcd4a..549783056 160000 --- a/lib/wolfTPM +++ b/lib/wolfTPM @@ -1 +1 @@ -Subproject commit cc88dcd4abb191fdccf29950b9f11e65b1bf757e +Subproject commit 5497830567222e9a278e5a69aaeef32d5f3fc890 diff --git a/lib/wolfssl b/lib/wolfssl index 05b692d01..cd02d5140 160000 --- a/lib/wolfssl +++ b/lib/wolfssl @@ -1 +1 @@ -Subproject commit 05b692d01cb2fa172d8a86e04a1dbbdb5eb88703 +Subproject commit cd02d5140fccd2478dcd4845d1b7cef6be881dde From 2d92d541acbe2faabb793248fbfb035ac6100d87 Mon Sep 17 00:00:00 2001 From: John Bland Date: Thu, 12 Oct 2023 17:37:02 -0400 Subject: [PATCH 9/9] add double fallback to update powerfail test since NVM_FLASH_WRITEONCE can powerfail after FLAGS_FINAL and TESTING partition states have been set --- .github/workflows/test-powerfail-simulator.yml | 2 +- tools/scripts/sim-update-powerfail-resume.sh | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-powerfail-simulator.yml b/.github/workflows/test-powerfail-simulator.yml index db414566f..fe3e857a7 100644 --- a/.github/workflows/test-powerfail-simulator.yml +++ b/.github/workflows/test-powerfail-simulator.yml @@ -181,7 +181,7 @@ jobs: - name: Build wolfboot.elf run: | - make && make test-sim-internal-flash-with-delta-update + make clean && make test-sim-internal-flash-with-delta-update - name: Run sunny day update test (DELTA) run: | diff --git a/tools/scripts/sim-update-powerfail-resume.sh b/tools/scripts/sim-update-powerfail-resume.sh index ea99e71a6..277442b5c 100755 --- a/tools/scripts/sim-update-powerfail-resume.sh +++ b/tools/scripts/sim-update-powerfail-resume.sh @@ -15,6 +15,10 @@ fi V=`./wolfboot.elf powerfail 3f000 get_version` 2>/dev/null if [ "x$V" != "x2" ]; then V=`./wolfboot.elf get_version 2>/dev/null` + # if we failed on the final boot state write we need to double fallback + if [ "x$V" == "x1" ]; then + V=`./wolfboot.elf get_version 2>/dev/null` + fi fi if [ "x$V" != "x2" ]; then