14void hardened_memcpy(uint32_t *restrict dest,
const uint32_t *restrict src,
17 random_order_init(&order, word_len);
20 size_t expected_count = random_order_len(&order);
25 uintptr_t src_addr = (uintptr_t)src;
26 uintptr_t dest_addr = (uintptr_t)dest;
36 uintptr_t decoy_addr = (uintptr_t)&decoys;
40 size_t byte_len = word_len *
sizeof(uint32_t);
41 for (; launderw(count) < expected_count; count = launderw(count) + 1) {
47 size_t byte_idx = launderw(random_order_advance(&order)) *
sizeof(uint32_t);
57 uintptr_t srcp = src_addr + byte_idx;
58 uintptr_t destp = dest_addr + byte_idx;
59 uintptr_t decoy1 = decoy_addr + (byte_idx %
sizeof(decoys));
62 ((byte_idx + (
sizeof(decoys) / 2) +
sizeof(uint32_t)) %
sizeof(decoys));
71 void *src = (
void *)launderw(
72 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), srcp, decoy1));
73 void *dest = (
void *)launderw(
74 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), destp, decoy2));
77 write_32(read_32(src), dest);
83void hardened_memshred(uint32_t *dest,
size_t word_len) {
85 random_order_init(&order, word_len);
88 size_t expected_count = random_order_len(&order);
90 uintptr_t data_addr = (uintptr_t)dest;
93 uintptr_t decoy_addr = (uintptr_t)&decoys;
95 size_t byte_len = word_len *
sizeof(uint32_t);
96 for (; count < expected_count; count = launderw(count) + 1) {
97 size_t byte_idx = launderw(random_order_advance(&order)) *
sizeof(uint32_t);
100 uintptr_t datap = data_addr + byte_idx;
101 uintptr_t decoy = decoy_addr + (byte_idx %
sizeof(decoys));
103 void *data = (
void *)launderw(
104 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), datap, decoy));
117 random_order_init(&order, word_len);
120 size_t expected_count = random_order_len(&order);
122 uintptr_t lhs_addr = (uintptr_t)lhs;
123 uintptr_t rhs_addr = (uintptr_t)rhs;
128 uint32_t decoys[8] = {
129 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
130 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
132 uintptr_t decoy_addr = (uintptr_t)&decoys;
135 uint32_t ones = UINT32_MAX;
139 size_t byte_len = word_len *
sizeof(uint32_t);
140 for (; count < expected_count; count = launderw(count) + 1) {
141 size_t byte_idx = launderw(random_order_advance(&order)) *
sizeof(uint32_t);
144 uintptr_t ap = lhs_addr + byte_idx;
145 uintptr_t bp = rhs_addr + byte_idx;
146 uintptr_t decoy1 = decoy_addr + (byte_idx %
sizeof(decoys));
149 ((byte_idx + (
sizeof(decoys) / 2) +
sizeof(uint32_t)) %
sizeof(decoys));
151 void *av = (
void *)launderw(
152 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), ap, decoy1));
153 void *bv = (
void *)launderw(
154 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), bp, decoy2));
156 uint32_t a = read_32(av);
157 uint32_t b = read_32(bv);
164 zeros = launder32(zeros) | (launder32(a) ^ b);
168 ones = launder32(ones) & (launder32(a) ^ ~b);
173 if (launder32(zeros) == 0) {
178 HARDENED_CHECK_NE(ones, UINT32_MAX);
182void hardened_xor(uint32_t *restrict x,
const uint32_t *restrict y,
186 random_order_init(&order, word_len);
188 size_t expected_count = random_order_len(&order);
192 hardened_memshred(decoys,
ARRAYSIZE(decoys));
195 uintptr_t x_addr = (uintptr_t)x;
196 uintptr_t y_addr = (uintptr_t)y;
197 uintptr_t decoy_addr = (uintptr_t)&decoys;
201 size_t byte_len = word_len *
sizeof(uint32_t);
202 for (; launderw(count) < expected_count; count = launderw(count) + 1) {
203 size_t byte_idx = launderw(random_order_advance(&order)) *
sizeof(uint32_t);
210 uintptr_t xp = x_addr + byte_idx;
211 uintptr_t yp = y_addr + byte_idx;
212 uintptr_t decoy1 = decoy_addr + (byte_idx %
sizeof(decoys));
215 ((byte_idx + (
sizeof(decoys) / 2) +
sizeof(uint32_t)) %
sizeof(decoys));
218 void *xv = (
void *)launderw(
219 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), xp, decoy1));
220 void *yv = (
void *)launderw(
221 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), yp, decoy2));
224 write_32(read_32(xv) ^ read_32(yv), xv);
230void hardened_mmio_write(uint32_t dest,
const uint32_t *src,
size_t word_len) {
232 random_order_init(&order, word_len);
235 size_t expected_count = random_order_len(&order);
239 uintptr_t src_addr = (uintptr_t)src;
240 volatile uintptr_t dest_addr = (
volatile uintptr_t)dest;
243 uintptr_t decoy_addr = (uintptr_t)&decoys;
245 size_t byte_len = word_len *
sizeof(uint32_t);
246 for (; launderw(count) < expected_count; count = launderw(count) + 1) {
247 size_t byte_idx = launderw(random_order_advance(&order)) *
sizeof(uint32_t);
251 uintptr_t srcp = src_addr + byte_idx;
252 volatile uintptr_t destp = dest_addr + byte_idx;
253 uintptr_t decoy1 = decoy_addr + (byte_idx %
sizeof(decoys));
254 volatile uintptr_t decoy2 =
256 ((byte_idx + (
sizeof(decoys) / 2) +
sizeof(uint32_t)) %
sizeof(decoys));
258 void *src = (
void *)launderw(
259 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), srcp, decoy1));
260 volatile void *dest = (
volatile void *)launderw(
261 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), destp, decoy2));
263 *((
volatile uint32_t *)dest) = read_32(src);
269void hardened_mmio_read(uint32_t *dest, uint32_t src,
size_t word_len) {
271 random_order_init(&order, word_len);
274 size_t expected_count = random_order_len(&order);
278 volatile uintptr_t src_addr = (
volatile uintptr_t)src;
279 uintptr_t dest_addr = (uintptr_t)dest;
282 uintptr_t decoy_addr = (uintptr_t)&decoys;
284 size_t byte_len = word_len *
sizeof(uint32_t);
285 for (; launderw(count) < expected_count; count = launderw(count) + 1) {
286 size_t byte_idx = launderw(random_order_advance(&order)) *
sizeof(uint32_t);
290 volatile uintptr_t srcp = src_addr + byte_idx;
291 uintptr_t destp = dest_addr + byte_idx;
292 volatile uintptr_t decoy1 = decoy_addr + (byte_idx %
sizeof(decoys));
295 ((byte_idx + (
sizeof(decoys) / 2) +
sizeof(uint32_t)) %
sizeof(decoys));
297 volatile void *src = (
volatile void *)launderw(
298 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), srcp, decoy1));
299 void *dest = (
void *)launderw(
300 ct_cmovw(ct_sltuw(launderw(byte_idx), byte_len), destp, decoy2));
302 write_32(*((
volatile uint32_t *)src), dest);