@@ -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 */
14011464int 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