fix powerfail problems with NVM_FLASH_WRITEONCE combinations

simplify the erase address logic within nvm_select_fresh_sector
add several checks to nvm_select_fresh_sector:
    when FLAGS_HOME is enabled, add a check for both the boot and update partition flags
    when EXT_ENCRYPTED is enabled, add a check for the encryption key, always perform this check when FLAGS_HOME is enabled
update aes_init and chacha_init to properly account for NVM_FLASH_WRITEONCE
pull/348/head
John Bland 2023-08-21 01:30:49 -04:00
parent c32f05c9fb
commit 4a9973ce06
1 changed files with 62 additions and 8 deletions

View File

@ -154,17 +154,55 @@ static const uint32_t wolfboot_magic_trail = WOLFBOOT_MAGIC_TRAIL;
static uint8_t NVM_CACHE[NVM_CACHE_SIZE] __attribute__((aligned(16))); static uint8_t NVM_CACHE[NVM_CACHE_SIZE] __attribute__((aligned(16)));
static int nvm_cached_sector = 0; static int nvm_cached_sector = 0;
static int nvm_select_fresh_sector(int part) static int RAMFUNCTION nvm_select_fresh_sector(int part)
{ {
int sel; int sel;
uintptr_t off; uintptr_t off;
uint8_t *base; uint8_t *base;
uint8_t *addr_align; uint8_t* addrErase;
if (part == PART_BOOT) /* if FLAGS_HOME check both boot and update for changes */
#ifdef FLAGS_HOME
base = (uint8_t *)PART_BOOT_ENDFLAGS;
addrErase = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS +
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
#else
if (part == PART_BOOT) {
base = (uint8_t *)PART_BOOT_ENDFLAGS; base = (uint8_t *)PART_BOOT_ENDFLAGS;
else addrErase = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS +
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
}
else {
base = (uint8_t *)PART_UPDATE_ENDFLAGS; base = (uint8_t *)PART_UPDATE_ENDFLAGS;
addrErase = (uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS +
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
}
#endif
#ifdef EXT_ENCRYPTED
uint32_t word_0;
uint32_t word_1;
#ifndef FLAGS_HOME
if (part == PART_BOOT)
#endif
{
word_0 = *((uint32_t *)(ENCRYPT_TMP_SECRET_OFFSET +
WOLFBOOT_PARTITION_BOOT_ADDRESS));
word_1 = *((uint32_t *)(ENCRYPT_TMP_SECRET_OFFSET +
WOLFBOOT_PARTITION_BOOT_ADDRESS - WOLFBOOT_SECTOR_SIZE));
if (word_0 == FLASH_WORD_ERASED && word_1 !=
FLASH_WORD_ERASED) {
sel = 1;
goto finish;
}
else if (word_0 != FLASH_WORD_ERASED && word_1 ==
FLASH_WORD_ERASED) {
sel = 0;
goto finish;
}
}
#endif
/* Default to last sector if no match is found */ /* Default to last sector if no match is found */
sel = 0; sel = 0;
@ -184,6 +222,14 @@ static int nvm_select_fresh_sector(int part)
} }
else if ((byte_0 == FLASH_BYTE_ERASED) && else if ((byte_0 == FLASH_BYTE_ERASED) &&
(byte_1 == FLASH_BYTE_ERASED)) { (byte_1 == FLASH_BYTE_ERASED)) {
#ifdef FLAGS_HOME
/* if we're still checking boot flags, check update flags */
if (base - off > (uint8_t*)PART_UPDATE_ENDFLAGS) {
base = (uint8_t *)PART_UPDATE_ENDFLAGS;
off = 0;
continue;
}
#endif
/* First time boot? Assume no pending update */ /* First time boot? Assume no pending update */
if(off == 1) { if(off == 1) {
sel=0; sel=0;
@ -196,12 +242,12 @@ static int nvm_select_fresh_sector(int part)
break; break;
} }
} }
finish:
/* Erase the non-selected partition */ /* Erase the non-selected partition */
addr_align = (uint8_t *)((((uintptr_t)base - ((1 + (!sel)) * WOLFBOOT_SECTOR_SIZE))) addrErase -= WOLFBOOT_SECTOR_SIZE * (!sel);
& ((~(NVM_CACHE_SIZE - 1)))); if (*((uint32_t*)(addrErase + WOLFBOOT_SECTOR_SIZE - sizeof(uint32_t)))
if (*((uint32_t*)(addr_align + WOLFBOOT_SECTOR_SIZE - sizeof(uint32_t)))
!= FLASH_WORD_ERASED) { != FLASH_WORD_ERASED) {
hal_flash_erase((uintptr_t)addr_align, WOLFBOOT_SECTOR_SIZE); hal_flash_erase((uintptr_t)addrErase, WOLFBOOT_SECTOR_SIZE);
} }
return sel; return sel;
} }
@ -1076,6 +1122,10 @@ int RAMFUNCTION chacha_init(void)
uint8_t ff[ENCRYPT_KEY_SIZE]; uint8_t ff[ENCRYPT_KEY_SIZE];
uint8_t* stored_nonce; 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; stored_nonce = key + ENCRYPT_KEY_SIZE;
XMEMSET(&chacha, 0, sizeof(chacha)); XMEMSET(&chacha, 0, sizeof(chacha));
@ -1111,6 +1161,10 @@ int aes_init(void)
uint8_t iv_buf[ENCRYPT_NONCE_SIZE]; uint8_t iv_buf[ENCRYPT_NONCE_SIZE];
uint8_t* stored_nonce; 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; stored_nonce = key + ENCRYPT_KEY_SIZE;
XMEMSET(&aes_enc, 0, sizeof(aes_enc)); XMEMSET(&aes_enc, 0, sizeof(aes_enc));