mirror of https://github.com/wolfSSL/wolfBoot.git
Address PR review on the encrypted write and sector copy paths
ext_flash_encrypt_write() writes whole ENCRYPT_BLOCK_SIZE blocks:
- A length that is not a multiple of the block size dropped the trailing
bytes, since the remainder loop rounds down. Merge them into the block
that already backs them, as the unaligned head is handled.
- len == 0 fell through to a read-modify-write of the containing block,
re-encrypting it in place. Return early instead.
wolfBoot_copy_sector() checked the reads added in F-7987 for a negative
return, but ext_flash_read() and ext_flash_check_read() return the number
of bytes read (docs/HAL.md), so a short read was accepted and a partially
filled buffer copied on. Require the full FLASHBUFFER_SIZE.
Add unit-update-flash-enc coverage for the two write cases.
pull/851/head
parent
31a9adc6d2
commit
fca6bf0fa6
|
|
@ -2587,6 +2587,13 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
|
|||
uint8_t ENCRYPT_CACHE[NVM_CACHE_SIZE] XALIGNED_STACK(32);
|
||||
#endif
|
||||
|
||||
/* A zero-length request must not turn into a read-modify-write of the
|
||||
* containing block. */
|
||||
if (len < 0)
|
||||
return -1;
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
row_offset = address & (ENCRYPT_BLOCK_SIZE - 1);
|
||||
if (row_offset != 0) {
|
||||
row_address = address & ~(ENCRYPT_BLOCK_SIZE - 1);
|
||||
|
|
@ -2657,6 +2664,20 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
|
|||
step -= chunk;
|
||||
}
|
||||
|
||||
/* Trailing bytes that do not fill a whole block. "address" is block
|
||||
* aligned here, so merge them into the block that already backs them,
|
||||
* the same way the unaligned head above is handled. */
|
||||
step = sz & (ENCRYPT_BLOCK_SIZE - 1);
|
||||
if (step > 0) {
|
||||
if (ext_flash_read(address, block, ENCRYPT_BLOCK_SIZE)
|
||||
!= ENCRYPT_BLOCK_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
XMEMCPY(block, data, step);
|
||||
crypto_encrypt(enc_block, block, ENCRYPT_BLOCK_SIZE);
|
||||
ret = ext_flash_write(address, enc_block, ENCRYPT_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -323,14 +323,16 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
|
|||
if (dst->part == PART_SWAP && SWAP_EXT) {
|
||||
if (ext_flash_read((uintptr_t)(src->hdr) + src_sector_offset +
|
||||
pos,
|
||||
(void *)buffer, FLASHBUFFER_SIZE) < 0) {
|
||||
(void *)buffer, FLASHBUFFER_SIZE)
|
||||
!= FLASHBUFFER_SIZE) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (ext_flash_check_read((uintptr_t)(src->hdr) +
|
||||
src_sector_offset + pos,
|
||||
(void *)buffer, FLASHBUFFER_SIZE) < 0) {
|
||||
(void *)buffer, FLASHBUFFER_SIZE)
|
||||
!= FLASHBUFFER_SIZE) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -601,6 +601,67 @@ static int add_payload_encrypted(uint8_t part, uint32_t version, uint32_t size,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef EXT_ENCRYPTED
|
||||
/* ext_flash_encrypt_write() writes whole ENCRYPT_BLOCK_SIZE blocks. A request
|
||||
* whose length is not a multiple of the block size used to drop the trailing
|
||||
* bytes, and a zero-length request used to rewrite the containing block. */
|
||||
START_TEST (test_encrypt_write_keeps_trailing_partial_block)
|
||||
{
|
||||
uintptr_t base = (uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
|
||||
int len = (2 * ENCRYPT_BLOCK_SIZE) + 5;
|
||||
uint8_t out[(2 * ENCRYPT_BLOCK_SIZE) + 5];
|
||||
uint8_t in[(2 * ENCRYPT_BLOCK_SIZE) + 5];
|
||||
int i, ret;
|
||||
|
||||
reset_mock_stats();
|
||||
prepare_flash();
|
||||
for (i = 0; i < len; i++)
|
||||
in[i] = (uint8_t)(0x30 + i);
|
||||
|
||||
ext_flash_unlock();
|
||||
ret = ext_flash_encrypt_write(base, in, len);
|
||||
ext_flash_lock();
|
||||
ck_assert_int_ge(ret, 0);
|
||||
|
||||
memset(out, 0, sizeof(out));
|
||||
ck_assert_int_eq(ext_flash_decrypt_read(base, out, len), len);
|
||||
ck_assert_int_eq(memcmp(out, in, len), 0);
|
||||
|
||||
cleanup_flash();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_encrypt_write_zero_length_leaves_flash_untouched)
|
||||
{
|
||||
uintptr_t base = (uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS;
|
||||
uint8_t before[ENCRYPT_BLOCK_SIZE];
|
||||
uint8_t after[ENCRYPT_BLOCK_SIZE];
|
||||
uint8_t in[ENCRYPT_BLOCK_SIZE];
|
||||
int i, ret;
|
||||
|
||||
reset_mock_stats();
|
||||
prepare_flash();
|
||||
for (i = 0; i < ENCRYPT_BLOCK_SIZE; i++)
|
||||
in[i] = (uint8_t)(0x70 + i);
|
||||
|
||||
ext_flash_unlock();
|
||||
ck_assert_int_ge(ext_flash_encrypt_write(base, in, ENCRYPT_BLOCK_SIZE), 0);
|
||||
ck_assert_int_eq(ext_flash_read(base, before, ENCRYPT_BLOCK_SIZE),
|
||||
ENCRYPT_BLOCK_SIZE);
|
||||
|
||||
ret = ext_flash_encrypt_write(base, in, 0);
|
||||
ext_flash_lock();
|
||||
ck_assert_int_eq(ret, 0);
|
||||
|
||||
ck_assert_int_eq(ext_flash_read(base, after, ENCRYPT_BLOCK_SIZE),
|
||||
ENCRYPT_BLOCK_SIZE);
|
||||
ck_assert_int_eq(memcmp(before, after, ENCRYPT_BLOCK_SIZE), 0);
|
||||
|
||||
cleanup_flash();
|
||||
}
|
||||
END_TEST
|
||||
#endif /* EXT_ENCRYPTED */
|
||||
|
||||
START_TEST (test_empty_panic)
|
||||
{
|
||||
reset_mock_stats();
|
||||
|
|
@ -1604,6 +1665,9 @@ Suite *wolfboot_suite(void)
|
|||
TCase *fallback_verify = tcase_create("Fallback verify");
|
||||
#endif
|
||||
#endif
|
||||
#ifdef EXT_ENCRYPTED
|
||||
TCase *encrypt_write_bounds = tcase_create("Encrypted write bounds");
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef UNIT_TEST_FALLBACK_ONLY
|
||||
|
|
@ -1612,6 +1676,11 @@ Suite *wolfboot_suite(void)
|
|||
tcase_add_test(fallback_verify, test_final_swap_propagates_encrypt_key_read_failure);
|
||||
tcase_add_test(fallback_verify, test_final_swap_propagates_encrypt_key_persist_failure);
|
||||
suite_add_tcase(s, fallback_verify);
|
||||
tcase_add_test(encrypt_write_bounds,
|
||||
test_encrypt_write_keeps_trailing_partial_block);
|
||||
tcase_add_test(encrypt_write_bounds,
|
||||
test_encrypt_write_zero_length_leaves_flash_untouched);
|
||||
suite_add_tcase(s, encrypt_write_bounds);
|
||||
#endif
|
||||
return s;
|
||||
#else
|
||||
|
|
|
|||
Loading…
Reference in New Issue