Skip to content

Commit 5684525

Browse files
committed
Fix corruption of last boot sector with encryption
As reported by @reza-hdd in #589: > When Firmware is large enough to consume all the allocated boot partition sectors, in the the final swap and erase operations (_wolfBoot_swap_and_final_erase_) the last sector of FW in Boot partition, which is used as a temporary sector for a copy operation, gets corrupted after being copied in external Swap partition and copied back. It looks like the contents are copied to the external Swap partition without being encrypted, but get decrypted when it is read back. This was due to the function wolfBoot_copy_sector() assuming that all copies having an external SWAP as destination would not need any encryption, as the "normal" case during update is to copy already encrypted sectors from UPDATE->SWAP. In the final state, after the update is successfully applied, the mechanism saves a copy of the last sector from BOOT->SWAP. In this case, if the application is big enough, an extra function is needed to encrypt the content of this last sector before writing it to SWAP. Restoring the backup is OK (normal case SWAP->BOOT, decryption was already there as also noted by the reporter).
1 parent 3801b49 commit 5684525

File tree

3 files changed

+92
-14
lines changed

3 files changed

+92
-14
lines changed

include/wolfboot/wolfboot.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ int wolfBoot_ram_decrypt(uint8_t *src, uint8_t *dst);
407407
int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr);
408408
#endif
409409

410+
int wolfBoot_initialize_encryption(void);
410411
int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce);
411412
int wolfBoot_get_encrypt_key(uint8_t *key, uint8_t *nonce);
412413
int wolfBoot_erase_encrypt_key(void);

src/libwolfboot.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464

6565
#if defined(EXT_ENCRYPTED)
6666
static int encrypt_initialized = 0;
67+
6768
static uint8_t encrypt_iv_nonce[ENCRYPT_NONCE_SIZE] XALIGNED(4);
6869
#if defined(__WOLFBOOT)
6970
#include "encrypt.h"
@@ -73,8 +74,26 @@ static uint8_t encrypt_iv_nonce[ENCRYPT_NONCE_SIZE] XALIGNED(4);
7374
#define XMEMCPY memcpy
7475
#define XMEMCMP memcmp
7576
#endif
77+
78+
#ifdef __WOLFBOOT
79+
int wolfBoot_initialize_encryption(void)
80+
{
81+
if (!encrypt_initialized) {
82+
if (crypto_init() != 0) {
83+
return -1;
84+
}
85+
encrypt_initialized = 1;
86+
}
87+
return 0;
88+
}
7689
#endif
7790

91+
#else
92+
#define wolfBoot_initialize_encryption() (0)
93+
#endif /* EXT_ENCRYPTED */
94+
95+
96+
7897
#if defined(EXT_FLASH) && defined(EXT_ENCRYPTED)
7998
#define ENCRYPT_TMP_SECRET_OFFSET (WOLFBOOT_PARTITION_SIZE - \
8099
(TRAILER_SKIP + ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE))
@@ -1039,9 +1058,8 @@ uint32_t wolfBoot_get_blob_version(uint8_t *blob)
10391058
if (blob == NULL)
10401059
return 0;
10411060
#if defined(EXT_ENCRYPTED) && defined(MMU)
1042-
if (!encrypt_initialized)
1043-
if (crypto_init() < 0)
1044-
return 0;
1061+
if (wolfBoot_initialize_encryption() < 0)
1062+
return 0;
10451063
decrypt_header(blob);
10461064
img_bin = dec_hdr;
10471065
#endif
@@ -1073,9 +1091,8 @@ uint16_t wolfBoot_get_blob_type(uint8_t *blob)
10731091
uint32_t *magic = NULL;
10741092
uint8_t *img_bin = blob;
10751093
#if defined(EXT_ENCRYPTED) && defined(MMU)
1076-
if (!encrypt_initialized)
1077-
if (crypto_init() < 0)
1078-
return 0;
1094+
if (wolfBoot_initialize_encryption() < 0)
1095+
return 0;
10791096
decrypt_header(blob);
10801097
img_bin = dec_hdr;
10811098
#endif
@@ -1111,9 +1128,8 @@ uint32_t wolfBoot_get_blob_diffbase_version(uint8_t *blob)
11111128
uint32_t *magic = NULL;
11121129
uint8_t *img_bin = blob;
11131130
#if defined(EXT_ENCRYPTED) && defined(MMU)
1114-
if (!encrypt_initialized)
1115-
if (crypto_init() < 0)
1116-
return 0;
1131+
if (wolfBoot_initialize_encryption() < 0)
1132+
return 0;
11171133
decrypt_header(blob);
11181134
img_bin = dec_hdr;
11191135
#endif
@@ -1790,10 +1806,9 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
17901806
ENCRYPT_BLOCK_SIZE) {
17911807
return ext_flash_write(address, data, len);
17921808
}
1793-
if (!encrypt_initialized) {
1794-
if (crypto_init() < 0)
1795-
return -1;
1796-
}
1809+
if (wolfBoot_initialize_encryption() < 0)
1810+
return -1;
1811+
17971812
crypto_set_iv(encrypt_iv_nonce, iv_counter);
17981813
break;
17991814
case PART_SWAP:

src/update_flash.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "hal.h"
2929
#include "spi_flash.h"
3030
#include "wolfboot/wolfboot.h"
31+
#include "target.h"
3132

3233
#include "delta.h"
3334
#include "printf.h"
@@ -152,7 +153,11 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
152153
dst_sector_offset = 0;
153154

154155
#ifdef EXT_ENCRYPTED
156+
if (wolfBoot_initialize_encryption() < 0) {
157+
return -1;
158+
}
155159
wolfBoot_get_encrypt_key(key, nonce);
160+
156161
if (src->part == PART_SWAP)
157162
iv_counter = dst_sector_offset;
158163
else
@@ -202,6 +207,56 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
202207
return pos;
203208
}
204209

210+
#ifdef EXT_ENCRYPTED
211+
static int RAMFUNCTION wolfBoot_backup_last_boot_sector(uint32_t sector)
212+
{
213+
uint32_t pos = 0;
214+
uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
215+
uint32_t dst_sector_offset = 0;
216+
uint8_t key[ENCRYPT_KEY_SIZE];
217+
uint8_t nonce[ENCRYPT_NONCE_SIZE];
218+
uint32_t iv_counter;
219+
uint8_t block[ENCRYPT_BLOCK_SIZE], encrypted_block[ENCRYPT_BLOCK_SIZE];
220+
struct wolfBoot_image src[1], dst[1];
221+
222+
wolfBoot_open_image(src, PART_BOOT);
223+
wolfBoot_open_image(dst, PART_SWAP);
224+
225+
226+
wolfBoot_printf("Copy sector %d (part %d->%d)\n",
227+
sector, src->part, dst->part);
228+
229+
wolfBoot_get_encrypt_key(key, nonce);
230+
wolfBoot_printf("In function wolfBoot_backup_last_boot_sector (sector # %lu)\n", sector);
231+
232+
iv_counter = src_sector_offset;
233+
iv_counter /= ENCRYPT_BLOCK_SIZE;
234+
if (wolfBoot_initialize_encryption() < 0)
235+
return -1;
236+
crypto_set_iv(nonce, iv_counter);
237+
238+
/* Erase swap space */
239+
wb_flash_erase(dst, dst_sector_offset, WOLFBOOT_SECTOR_SIZE);
240+
if (PART_IS_EXT(dst)) {
241+
uint32_t sz = 0;
242+
uint32_t step = 0;
243+
uint8_t *orig = (uint8_t *)(WOLFBOOT_PARTITION_BOOT_ADDRESS) + src_sector_offset;
244+
while (pos < WOLFBOOT_SECTOR_SIZE) {
245+
uint32_t len = ENCRYPT_BLOCK_SIZE;
246+
XMEMCPY(block, orig + pos, ENCRYPT_BLOCK_SIZE);
247+
crypto_encrypt(encrypted_block, block, ENCRYPT_BLOCK_SIZE);
248+
wb_flash_write(dst, dst_sector_offset + pos, encrypted_block, ENCRYPT_BLOCK_SIZE);
249+
step++;
250+
pos += ENCRYPT_BLOCK_SIZE;
251+
}
252+
return 0;
253+
} else
254+
return wolfBoot_copy_sector(src, dst, sector);
255+
}
256+
#else
257+
#define wolfBoot_backup_last_boot_sector(sec) wolfBoot_copy_sector(boot, swap, sec)
258+
#endif
259+
205260
#if !defined(DISABLE_BACKUP) && !defined(CUSTOM_PARTITION_TRAILER)
206261

207262
#ifdef EXT_ENCRYPTED
@@ -293,11 +348,13 @@ static int RAMFUNCTION wolfBoot_swap_and_final_erase(int resume)
293348
if (updateState != IMG_STATE_FINAL_FLAGS) {
294349
/* First, backup the staging sector (sector at tmpBootPos) into swap partition */
295350
/* This sector will be modified with the magic trailer, so we need to preserve it */
296-
wolfBoot_copy_sector(boot, swap, tmpBootPos / WOLFBOOT_SECTOR_SIZE);
351+
wolfBoot_backup_last_boot_sector(tmpBootPos / WOLFBOOT_SECTOR_SIZE);
352+
wolfBoot_printf("Copied boot sector to swap\n");
297353
/* Mark update as being in final swap phase to allow resumption if power fails */
298354
wolfBoot_set_partition_state(PART_UPDATE, IMG_STATE_FINAL_FLAGS);
299355
}
300356
#ifdef EXT_ENCRYPTED
357+
wolfBoot_printf("In function wolfBoot_final_swap: swapDone = %d\n", swapDone);
301358
if (swapDone == 0) {
302359
/* For encrypted images: Get the encryption key and IV */
303360
wolfBoot_get_encrypt_key((uint8_t*)tmpBuffer,
@@ -321,6 +378,7 @@ static int RAMFUNCTION wolfBoot_swap_and_final_erase(int resume)
321378
#endif
322379
/* Restore the original contents of the staging sector (with the magic trailer if encrypted) */
323380
if (tmpBootPos < boot->fw_size + IMAGE_HEADER_SIZE) {
381+
wolfBoot_printf("Restoring last boot sector from swap\n");
324382
wolfBoot_copy_sector(swap, boot, tmpBootPos / WOLFBOOT_SECTOR_SIZE);
325383
}
326384
else {
@@ -461,6 +519,10 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
461519
#ifdef EXT_ENCRYPTED
462520
uint32_t iv_counter = sector * WOLFBOOT_SECTOR_SIZE + len;
463521
int wr_ret;
522+
if (wolfBoot_initialize_encryption() < 0) {
523+
ret = -1;
524+
goto out;
525+
}
464526
iv_counter /= ENCRYPT_BLOCK_SIZE;
465527
/* Encrypt + send */
466528
crypto_set_iv(nonce, iv_counter);

0 commit comments

Comments
 (0)