cybersecurity · intermediate · ~12 min · safe pentest lab
The OR-fold pattern that removes data-dependent branching.
Compare two byte buffers like memcmp, but without an early exit that would leak where the first mismatch is.
Implement int ct_memcmp(const void *a, const void *b, size_t n) that compares the first n bytes of a and b in constant time.
a, b: two buffers the grader passes (may include high-bit bytes).n: the number of bytes to compare.Returns int: 0 if the first n bytes are equal, non-zero otherwise.
ct_memcmp("hello", "hello", 5) -> 0
ct_memcmp("hello", "hellp", 5) != 0 (last byte differs)
ct_memcmp("hello", "iello", 5) != 0 (first byte differs)
ct_memcmp(NULL, NULL, 0) -> 0 (vacuously equal)
ct_memcmp(NULL, "a", 1) != 0
n == 0 returns 0 (equal).a or b with n > 0 returns non-zero.unsigned char).break or return inside the loop, and no branch whose condition depends on the compared data (apart from the loop bound). Accumulate acc |= a[i] ^ b[i] and return acc.Crypto's most common defence: comparing a tag with memcmp leaks where the mismatch is. The fix is three lines and an OR-fold.
Two const buffers a and b and a byte count n.
An int: 0 if the first n bytes are equal, non-zero otherwise.
No early exit; no data-dependent branching; NULL with n>0 is non-zero.
#include <stddef.h>
int ct_memcmp(const void *a, const void *b, size_t n) {
/* TODO */
(void)a; (void)b; (void)n;
return -1;
}
Adding if (acc) break;. Returning int from a char * cast (signed widening). Forgetting the n==0 case.
n == 0. NULL with n > 0. Bytes with the high bit set.
O(n) — always exactly n iterations.
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.