Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions sw/device/lib/base/hardened_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,34 @@ hardened_bool_t consttime_memeq_byte(const void *lhs, const void *rhs,
uint32_t zeros = 0;
uint32_t ones = UINT32_MAX;

size_t it = 0;
const unsigned char *lh = (const unsigned char *)lhs;
const unsigned char *rh = (const unsigned char *)rhs;
for (; it < len; ++it, ++lh, ++rh) {
const unsigned char a = *lh;
const unsigned char b = *rh;
random_order_t order;
random_order_init(&order, len);

size_t count = 0;

uintptr_t lhs_addr = (uintptr_t)lhs;
uintptr_t rhs_addr = (uintptr_t)rhs;

for (; launderw(count) < len; count = launderw(count) + 1) {
size_t byte_idx = launderw(random_order_advance(&order));
barrierw(byte_idx);

uint8_t *a = (uint8_t *)launderw(lhs_addr + byte_idx);
uint8_t *b = (uint8_t *)launderw(rhs_addr + byte_idx);

// Launder one of the operands, so that the compiler cannot cache the result
// of the xor for use in the next operation.
//
// We launder `zeroes` so that compiler cannot learn that `zeroes` has
// strictly more bits set at the end of the loop.
zeros = launder32(zeros) | (launder32((uint32_t)a) ^ b);
zeros = launder32(zeros) | (launder32((uint32_t)*a) ^ *b);

// Same as above. The compiler can cache the value of `a[offset]`, but it
// has no chance to strength-reduce this operation.
ones = launder32(ones) & (launder32((uint32_t)a) ^ ~b);
ones = launder32(ones) & (launder32((uint32_t)*a) ^ ~*b);
}

HARDENED_CHECK_EQ(it, len);
HARDENED_CHECK_EQ(count, len);

if (launder32(zeros) == 0) {
HARDENED_CHECK_EQ(ones, UINT32_MAX);
Expand Down Expand Up @@ -257,14 +265,17 @@ status_t randomized_bytecopy(void *restrict dest, const void *restrict src,
barrierw(byte_idx);

uint8_t *src_byte_idx = (uint8_t *)launderw(src_addr + byte_idx);
// TODO(#8815) byte writes vs. word-wise integrity.
uint8_t *dest_byte_idx = (uint8_t *)launderw(dest_addr + byte_idx);

*(dest_byte_idx) = *(src_byte_idx);
}
RANDOM_ORDER_HARDENED_CHECK_DONE(order);
HARDENED_CHECK_EQ(count, byte_len);

// Check if copying the data was successful.
HARDENED_CHECK_EQ(consttime_memeq_byte(dest, src, byte_len),
kHardenedBoolTrue);

return OTCRYPTO_OK;
}

Expand Down
4 changes: 3 additions & 1 deletion sw/device/lib/base/hardened_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ status_t hardened_xor_in_place(uint32_t *OT_RESTRICT x,
* Copy memory between non-overlapping regions with a randomized byte traversal.
*
* CAUTION! This function is not considered as secure as `hardened_memcpy` due
* to the byte-sized memory accesses vs. 32b word accesses.
* to the byte-sized memory accesses vs. 32b word accesses. After copying the
* data, this function uses `consttime_memeq_byte()` to check if the data was
* copied correctly.
*
* @param dest the region to copy to.
* @param src the region to copy from.
Expand Down
Loading