cybersecurity · intermediate · ~12 min · safe pentest lab

Constant-time byte equality

The OR-fold pattern that removes data-dependent branching.

Challenge

Compare two byte buffers like memcmp, but without an early exit that would leak where the first mismatch is.

Task

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.

Input

  • a, b: two buffers the grader passes (may include high-bit bytes).
  • n: the number of bytes to compare.

Output

Returns int: 0 if the first n bytes are equal, non-zero otherwise.

Example

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

Edge cases

  • n == 0 returns 0 (equal).
  • A NULL a or b with n > 0 returns non-zero.
  • Bytes with the high bit set must compare correctly (cast to unsigned char).

Rules

  • No early 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.

Why this matters

Crypto's most common defence: comparing a tag with memcmp leaks where the mismatch is. The fix is three lines and an OR-fold.

Input format

Two const buffers a and b and a byte count n.

Output format

An int: 0 if the first n bytes are equal, non-zero otherwise.

Constraints

No early exit; no data-dependent branching; NULL with n>0 is non-zero.

Starter code

#include <stddef.h>
int ct_memcmp(const void *a, const void *b, size_t n) {
    /* TODO */
    (void)a; (void)b; (void)n;
    return -1;
}

Common mistakes

Adding if (acc) break;. Returning int from a char * cast (signed widening). Forgetting the n==0 case.

Edge cases to handle

n == 0. NULL with n > 0. Bytes with the high bit set.

Complexity

O(n) — always exactly n iterations.

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.