Skip to content

Commit

Permalink
update: don't set IV on SWAP based on SWAP address.
Browse files Browse the repository at this point in the history
New update logic when using encrypted external flash:

- an update sector is copied to swap. No decryption and re-encryption is done in
this step. This is important, because the swap address never changes and
otherwise the data will be encrypted, one sector at the time, with the same
IV. It's also a performance improvement.

- a boot sector is copied to update. In this step the boot sector is encrypted

- the swap sector is copied into boot. In this step the swap sector is decrypted

This commit moves the set_iv logic into wolfBoot_copy_sector to account for
this.
  • Loading branch information
rizlik committed Feb 7, 2022
1 parent 0f96138 commit b7026a5
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 19 deletions.
21 changes: 5 additions & 16 deletions src/libwolfboot.c
Expand Up @@ -892,19 +892,14 @@ int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
part = part_address(address);
switch(part) {
case PART_UPDATE:
iv_counter = (address - WOLFBOOT_PARTITION_UPDATE_ADDRESS) / ENCRYPT_BLOCK_SIZE;
/* Do not encrypt last sectors */
if (iv_counter >= (START_FLAGS_OFFSET - ENCRYPT_BLOCK_SIZE) / ENCRYPT_BLOCK_SIZE) {
/* do not encrypt flag sector */
if (address - WOLFBOOT_PARTITION_UPDATE_ADDRESS >= START_FLAGS_OFFSET) {
return ext_flash_write(address, data, len);
}
break;
case PART_SWAP:
{
uint32_t row_number;
row_number = (address - WOLFBOOT_PARTITION_SWAP_ADDRESS) / ENCRYPT_BLOCK_SIZE;
iv_counter = row_number;
break;
}
/* data is coming from update and is already encrypted */
return ext_flash_write(address, data, len);
default:
return -1;
}
Expand All @@ -913,7 +908,6 @@ int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
if (ext_flash_read(row_address, block, ENCRYPT_BLOCK_SIZE) != ENCRYPT_BLOCK_SIZE)
return -1;
XMEMCPY(block + row_offset, data, step);
crypto_set_iv(encrypt_iv_nonce, iv_counter);
crypto_encrypt(enc_block, block, ENCRYPT_BLOCK_SIZE);
ext_flash_write(row_address, enc_block, ENCRYPT_BLOCK_SIZE);
address += step;
Expand All @@ -922,7 +916,6 @@ int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
iv_counter++;
}
for (i = 0; i < sz / ENCRYPT_BLOCK_SIZE; i++) {
crypto_set_iv(encrypt_iv_nonce, iv_counter);
XMEMCPY(block, data + (ENCRYPT_BLOCK_SIZE * i), ENCRYPT_BLOCK_SIZE);
crypto_encrypt(ENCRYPT_CACHE + (ENCRYPT_BLOCK_SIZE * i), block, ENCRYPT_BLOCK_SIZE);
iv_counter++;
Expand Down Expand Up @@ -958,12 +951,10 @@ int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len)
if (iv_counter >= (START_FLAGS_OFFSET - ENCRYPT_BLOCK_SIZE) / ENCRYPT_BLOCK_SIZE) {
return ext_flash_read(address, data, len);
}
crypto_set_iv(encrypt_iv_nonce, iv_counter);
break;
case PART_SWAP:
{
uint32_t row_number;
row_number = (address - WOLFBOOT_PARTITION_SWAP_ADDRESS) / ENCRYPT_BLOCK_SIZE;
iv_counter = row_number;
break;
}
default:
Expand All @@ -974,7 +965,6 @@ int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len)
int step = ENCRYPT_BLOCK_SIZE - row_offset;
if (ext_flash_read(row_address, block, ENCRYPT_BLOCK_SIZE) != ENCRYPT_BLOCK_SIZE)
return -1;
crypto_set_iv(encrypt_iv_nonce, iv_counter);
crypto_decrypt(dec_block, block, ENCRYPT_BLOCK_SIZE);
XMEMCPY(data, dec_block + row_offset, step);
address += step;
Expand All @@ -985,7 +975,6 @@ int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len)
if (ext_flash_read(address, data, sz) != sz)
return -1;
for (i = 0; i < sz / ENCRYPT_BLOCK_SIZE; i++) {
crypto_set_iv(encrypt_iv_nonce, iv_counter);
XMEMCPY(block, data + (ENCRYPT_BLOCK_SIZE * i), ENCRYPT_BLOCK_SIZE);
crypto_decrypt(data + (ENCRYPT_BLOCK_SIZE * i), block, ENCRYPT_BLOCK_SIZE);
iv_counter++;
Expand Down
35 changes: 32 additions & 3 deletions src/update_flash.c
Expand Up @@ -120,13 +120,31 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w
uint32_t pos = 0;
uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
uint32_t dst_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
#ifdef EXT_ENCRYPTED
uint8_t key[ENCRYPT_KEY_SIZE];
uint8_t nonce[ENCRYPT_NONCE_SIZE];
uint32_t iv_counter;
#endif

if (src == dst)
return 0;

if (src->part == PART_SWAP)
src_sector_offset = 0;
if (dst->part == PART_SWAP)
dst_sector_offset = 0;

#ifdef EXT_ENCRYPTED
wolfBoot_get_encrypt_key(key, nonce);
if(src->part == PART_SWAP)
iv_counter = dst_sector_offset;
else
iv_counter = src_sector_offset;

iv_counter /= ENCRYPT_BLOCK_SIZE;
crypto_set_iv(nonce, iv_counter);
#endif

#ifdef EXT_FLASH
if (PART_IS_EXT(src)) {
#ifndef BUFFER_DECLARED
Expand All @@ -135,9 +153,20 @@ 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)) {
ext_flash_check_read((uintptr_t)(src->hdr) + src_sector_offset + pos, (void *)buffer, FLASHBUFFER_SIZE);
wb_flash_write(dst, dst_sector_offset + pos, buffer, FLASHBUFFER_SIZE);
if (src_sector_offset + pos <
(src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) {
/* bypass decryption, copy encrypted data into swap */
if (dst->part == PART_SWAP) {
ext_flash_read((uintptr_t)(src->hdr) + src_sector_offset + pos,
(void *)buffer, FLASHBUFFER_SIZE);
} else {
ext_flash_check_read((uintptr_t)(src->hdr) + src_sector_offset +
pos,
(void *)buffer, FLASHBUFFER_SIZE);
}

wb_flash_write(dst,
dst_sector_offset + pos, buffer, FLASHBUFFER_SIZE);
}
pos += FLASHBUFFER_SIZE;
}
Expand Down

0 comments on commit b7026a5

Please sign in to comment.