Skip to content

Commit 00a9572

Browse files
jpbland1danielinux
authored andcommitted
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
1 parent ffc7a43 commit 00a9572

6 files changed

Lines changed: 374 additions & 65 deletions

File tree

include/encrypt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ void aes_set_iv(uint8_t *nonce, uint32_t address);
6464
#endif /* ENCRYPT_WITH_CHACHA */
6565

6666
/* Internal read/write functions (not exported in the libwolfboot API) */
67+
int ext_flash_encrypt_write_ex(uintptr_t address,
68+
const uint8_t *data, int len, int forcedEnc);
6769
int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len);
6870
int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len);
6971

include/image.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -616,10 +616,18 @@ static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off,
616616
}
617617

618618
static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off,
619-
const void *data, uint32_t size)
619+
const void *data, uint32_t size, int forcedEncrypt)
620620
{
621-
if (PART_IS_EXT(img))
622-
return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, size);
621+
if (PART_IS_EXT(img)) {
622+
#if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST))
623+
if (forcedEncrypt == 1)
624+
return ext_flash_encrypt_write_ex((uintptr_t)(img->hdr) + off, data,
625+
size, forcedEncrypt);
626+
else
627+
#endif
628+
return ext_flash_check_write((uintptr_t)(img->hdr) + off, data,
629+
size);
630+
}
623631
else
624632
return hal_flash_write((uintptr_t)(img->hdr) + off, data, size);
625633
}
@@ -657,7 +665,7 @@ static inline int wb_flash_write_verify_word(struct wolfBoot_image *img,
657665
# define PARTN_IS_EXT(x) (0)
658666
# define wb_flash_erase(im, of, siz) \
659667
hal_flash_erase(((uintptr_t)(((im)->hdr)) + of), siz)
660-
# define wb_flash_write(im, of, dat, siz) \
668+
# define wb_flash_write(im, of, dat, siz, I) \
661669
hal_flash_write(((uintptr_t)((im)->hdr)) + of, dat, siz)
662670

663671
#endif /* EXT_FLASH */

include/wolfboot/wolfboot.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,15 @@ extern "C" {
244244
#ifndef WOLFBOOT_FLAGS_INVERT
245245
#define IMG_STATE_NEW 0xFF
246246
#define IMG_STATE_UPDATING 0x70
247+
#define IMG_STATE_FINAL_SWAP 0x30
247248
#define IMG_STATE_TESTING 0x10
248249
#define IMG_STATE_SUCCESS 0x00
249250
#define FLASH_BYTE_ERASED 0xFF
250251
#define FLASH_WORD_ERASED 0xFFFFFFFFUL
251252
#else
252253
#define IMG_STATE_NEW 0x00
253254
#define IMG_STATE_UPDATING 0x8F
255+
#define IMG_STATE_FINAL_SWAP 0xBF
254256
#define IMG_STATE_TESTING 0xEF
255257
#define IMG_STATE_SUCCESS 0xFF
256258
#define FLASH_BYTE_ERASED 0x00
@@ -314,9 +316,15 @@ int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr);
314316
#endif
315317

316318
int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce);
319+
int wolfBoot_backup_encrypt_key(const uint8_t* key, const uint8_t* nonce);
317320
int wolfBoot_get_encrypt_key(uint8_t *key, uint8_t *nonce);
318321
int wolfBoot_erase_encrypt_key(void);
319322

323+
#ifdef FLAGS_HOME
324+
int wolfBoot_flags_home_set_final_swap();
325+
int wolfBoot_flags_home_get_final_swap();
326+
#endif
327+
320328
#ifdef __cplusplus
321329
}
322330
#endif

src/libwolfboot.c

Lines changed: 155 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
195195
uintptr_t off;
196196
uint8_t *base;
197197
uint8_t* addrErase;
198+
uint32_t word_0;
199+
uint32_t word_1;
198200

199201
/* if FLAGS_HOME check both boot and update for changes */
200202
#ifdef FLAGS_HOME
@@ -215,8 +217,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
215217
#endif
216218

217219
#ifdef EXT_ENCRYPTED
218-
uint32_t word_0;
219-
uint32_t word_1;
220220
#ifndef FLAGS_HOME
221221
if (part == PART_BOOT)
222222
#endif
@@ -239,6 +239,36 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
239239
}
240240
#endif
241241

242+
/* check magic in case the sector is corrupt */
243+
word_0 = *((uint32_t*)(base - sizeof(uint32_t)));
244+
word_1 = *((uint32_t*)(base - WOLFBOOT_SECTOR_SIZE - sizeof(uint32_t)));
245+
246+
if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
247+
sel = 0;
248+
goto finish;
249+
}
250+
else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) {
251+
sel = 1;
252+
goto finish;
253+
}
254+
255+
/* try the update magic as well */
256+
#ifdef FLAGS_HOME
257+
/* check magic in case the sector is corrupt */
258+
word_0 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - sizeof(uint32_t)));
259+
word_1 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - WOLFBOOT_SECTOR_SIZE -
260+
sizeof(uint32_t)));
261+
262+
if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
263+
sel = 0;
264+
goto finish;
265+
}
266+
else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) {
267+
sel = 1;
268+
goto finish;
269+
}
270+
#endif
271+
242272
/* Default to last sector if no match is found */
243273
sel = 0;
244274

@@ -1347,21 +1377,37 @@ static int RAMFUNCTION hal_set_key(const uint8_t *k, const uint8_t *nonce)
13471377
addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1));
13481378
addr_off = addr & (WOLFBOOT_SECTOR_SIZE - 1);
13491379
#ifdef NVM_FLASH_WRITEONCE
1380+
/* we read from the populated sector, now write to the erased sector */
13501381
sel_sec = nvm_select_fresh_sector(PART_BOOT);
13511382
addr_align -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
13521383
#endif
13531384
hal_flash_unlock();
13541385
/* casting to unsigned long to abide compilers on 64bit architectures */
13551386
XMEMCPY(ENCRYPT_CACHE,
1356-
(void*)(unsigned long)(addr_align) ,
1387+
(void*)(unsigned long)(addr_align),
13571388
WOLFBOOT_SECTOR_SIZE);
1389+
#ifdef NVM_FLASH_WRITEONCE
1390+
/* we read from the populated sector, now write to the erased sector */
1391+
addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1));
1392+
addr_align -= (!sel_sec * WOLFBOOT_SECTOR_SIZE);
1393+
#else
1394+
/* erase the old key */
13581395
ret = hal_flash_erase(addr_align, WOLFBOOT_SECTOR_SIZE);
13591396
if (ret != 0)
13601397
return ret;
1398+
#endif
13611399
XMEMCPY(ENCRYPT_CACHE + addr_off, k, ENCRYPT_KEY_SIZE);
13621400
XMEMCPY(ENCRYPT_CACHE + addr_off + ENCRYPT_KEY_SIZE, nonce,
13631401
ENCRYPT_NONCE_SIZE);
13641402
ret = hal_flash_write(addr_align, ENCRYPT_CACHE, WOLFBOOT_SECTOR_SIZE);
1403+
#ifdef NVM_FLASH_WRITEONCE
1404+
/* now erase the old populated sector */
1405+
if (ret != 0)
1406+
return ret;
1407+
addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1));
1408+
addr_align -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
1409+
ret = hal_flash_erase(addr_align, WOLFBOOT_SECTOR_SIZE);
1410+
#endif
13651411
hal_flash_lock();
13661412
return ret;
13671413
#endif
@@ -1385,36 +1431,71 @@ int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key,
13851431
return 0;
13861432
}
13871433

1434+
int RAMFUNCTION wolfBoot_backup_encrypt_key(const uint8_t* key,
1435+
const uint8_t* nonce)
1436+
{
1437+
#ifndef MMU
1438+
uint32_t magic[2] = {WOLFBOOT_MAGIC, WOLFBOOT_MAGIC_TRAIL};
1439+
1440+
hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS, key,
1441+
ENCRYPT_KEY_SIZE);
1442+
hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS +
1443+
ENCRYPT_KEY_SIZE, nonce, ENCRYPT_NONCE_SIZE);
1444+
/* write magic so we know we finished in case of a powerfail */
1445+
hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS +
1446+
ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE, (uint8_t*)magic, sizeof(magic));
1447+
#endif
1448+
return 0;
1449+
}
1450+
13881451
#ifndef UNIT_TEST
13891452
/**
1390-
* @brief Set the encryption key.
1453+
* @brief Get the encryption key.
13911454
*
1392-
* This function sets the encryption key and nonce used for encrypting the
1393-
* firmware image. It stores the key and nonce in the designated memory location.
1455+
* This function gets the encryption key and nonce used for encrypting the
1456+
* firmware image.
13941457
*
1395-
* @param key Pointer to the encryption key.
1458+
* @param k Pointer to the encryption key.
13961459
* @param nonce Pointer to the encryption nonce.
13971460
*
13981461
* @return 0 if successful.
13991462
*
14001463
*/
14011464
int RAMFUNCTION wolfBoot_get_encrypt_key(uint8_t *k, uint8_t *nonce)
14021465
{
1466+
int ret = 0;
14031467
#if defined(MMU)
14041468
XMEMCPY(k, ENCRYPT_KEY, ENCRYPT_KEY_SIZE);
14051469
XMEMCPY(nonce, ENCRYPT_KEY + ENCRYPT_KEY_SIZE, ENCRYPT_NONCE_SIZE);
14061470
#else
1407-
uint8_t *mem = (uint8_t *)(ENCRYPT_TMP_SECRET_OFFSET +
1408-
WOLFBOOT_PARTITION_BOOT_ADDRESS);
1409-
int sel_sec = 0;
1410-
#ifdef NVM_FLASH_WRITEONCE
1411-
sel_sec = nvm_select_fresh_sector(PART_BOOT);
1412-
mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
1413-
#endif
1471+
uint8_t* mem;
1472+
uint32_t magic[2];
1473+
1474+
/* see if we've backed up the key, this will only matter for final swap */
1475+
XMEMCPY(magic, (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS +
1476+
ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE, sizeof(magic));
1477+
1478+
if (magic[0] == WOLFBOOT_MAGIC && magic[1] == WOLFBOOT_MAGIC_TRAIL) {
1479+
mem = (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS;
1480+
/* not a failure but finalize needs to know that it's safe to erase and
1481+
* write the key to the normal spot */
1482+
ret = 1;
1483+
}
1484+
else {
1485+
mem = (uint8_t *)(ENCRYPT_TMP_SECRET_OFFSET +
1486+
WOLFBOOT_PARTITION_BOOT_ADDRESS);
1487+
1488+
#ifdef NVM_FLASH_WRITEONCE
1489+
int sel_sec = 0;
1490+
sel_sec = nvm_select_fresh_sector(PART_BOOT);
1491+
mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
1492+
#endif
1493+
}
1494+
14141495
XMEMCPY(k, mem, ENCRYPT_KEY_SIZE);
14151496
XMEMCPY(nonce, mem + ENCRYPT_KEY_SIZE, ENCRYPT_NONCE_SIZE);
14161497
#endif
1417-
return 0;
1498+
return ret;
14181499
}
14191500
#endif
14201501
/**
@@ -1626,10 +1707,12 @@ static uint8_t RAMFUNCTION part_address(uintptr_t a)
16261707
* @param address The address in the external flash to write the data to.
16271708
* @param data Pointer to the data buffer to be written.
16281709
* @param len The length of the data to be written.
1710+
* @param forcedEnc force writing encryption, used during final swap
16291711
*
16301712
* @return int 0 if successful, -1 on failure.
16311713
*/
1632-
int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
1714+
int RAMFUNCTION ext_flash_encrypt_write_ex(uintptr_t address,
1715+
const uint8_t *data, int len, int forcedEnc)
16331716
{
16341717
uint8_t block[ENCRYPT_BLOCK_SIZE];
16351718
uint8_t enc_block[ENCRYPT_BLOCK_SIZE];
@@ -1664,7 +1747,9 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
16641747
break;
16651748
case PART_SWAP:
16661749
/* data is coming from update and is already encrypted */
1667-
return ext_flash_write(address, data, len);
1750+
if (forcedEnc == 0)
1751+
return ext_flash_write(address, data, len);
1752+
break;
16681753
default:
16691754
return -1;
16701755
}
@@ -1694,6 +1779,23 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
16941779

16951780
return ext_flash_write(address, ENCRYPT_CACHE, step);
16961781
}
1782+
1783+
/**
1784+
* @brief Write encrypted data to an external flash.
1785+
*
1786+
* This function calls ext_flash_encrypt_write_ex with forced encryption off
1787+
*
1788+
* @param address The address in the external flash to write the data to.
1789+
* @param data Pointer to the data buffer to be written.
1790+
* @param len The length of the data to be written.
1791+
*
1792+
* @return int 0 if successful, -1 on failure.
1793+
*/
1794+
int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
1795+
{
1796+
return ext_flash_encrypt_write_ex(address, data, len, 0);
1797+
}
1798+
16971799
/**
16981800
* @brief Read and decrypt data from an external flash.
16991801
*
@@ -1840,3 +1942,39 @@ int wolfBoot_ram_decrypt(uint8_t *src, uint8_t *dst)
18401942
}
18411943
#endif /* MMU */
18421944
#endif /* EXT_ENCRYPTED */
1945+
1946+
#ifdef FLAGS_HOME
1947+
/* we need to write a marker to update since the boot and update flags are all
1948+
* in the same sector so write magic to the first sector of boot */
1949+
int wolfBoot_flags_home_set_final_swap()
1950+
{
1951+
/* EXT_ENCRYPTED uses the first sector to store the key and magic, don't
1952+
* overwrite it */
1953+
#ifndef EXT_ENCRYPTED
1954+
uint32_t magic[2] = {WOLFBOOT_MAGIC, WOLFBOOT_MAGIC_TRAIL};
1955+
uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
1956+
1957+
hal_flash_write(addr, (uint8_t*)magic, sizeof(magic));
1958+
#endif /* !EXT_ENCRYPTED */
1959+
1960+
return 0;
1961+
}
1962+
1963+
int wolfBoot_flags_home_get_final_swap()
1964+
{
1965+
uint32_t magic[2];
1966+
uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
1967+
1968+
/* if encryption is on magic will be after the key and nonce */
1969+
#ifdef EXT_ENCRYPTED
1970+
addr += ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE;
1971+
#endif
1972+
1973+
XMEMCPY((uint8_t*)magic, (uint8_t*)addr, sizeof(magic));
1974+
1975+
if (magic[0] == WOLFBOOT_MAGIC && magic[1] == WOLFBOOT_MAGIC_TRAIL)
1976+
return 1;
1977+
1978+
return 0;
1979+
}
1980+
#endif /* FLAGS_HOME */

0 commit comments

Comments
 (0)