Secure Coding in C · intermediate · ~12 min

Constant-time byte comparison

Implement an equality check whose runtime does not depend on where the inputs first differ.

Overview

Walk every byte, fold XOR into one accumulator, return non-zero iff any byte differed.

Why it matters

Crypto's most common defence pattern. One missing fold-line is a real, exploitable leak.

Lesson

Why this matters

Compare a MAC tag with memcmp and you've handed an attacker a timing side channel: the comparison exits early on the first mismatched byte, so the time it takes to fail is a leak about how far in the match got. Crypto code uses a constant-time compare that always touches every byte.

This is one of the most-cited defensive patterns. It's three lines.

The shape

unsigned char acc = 0;
for (size_t i = 0; i < n; i++) acc |= a[i] ^ b[i];
return acc;  /* zero iff a and b are equal in all n bytes */

The trick: XOR every byte-pair, OR the result into an accumulator. The accumulator stays 0 iff every pair was equal. The loop is the same length whether the inputs match early or late.

Your job

Implement int ct_memcmp(const void *a, const void *b, size_t n). Return 0 if all n bytes match, non-zero otherwise. Constant-time. NULL a or b (with n > 0) → 1.

Common mistakes

  • Adding an if (acc != 0) break; "optimisation" — that's exactly the leak you were trying to avoid.
  • Returning the accumulator's signed value; cast to unsigned char first.

What this is NOT

  • A faster memcmp. It's strictly slower for matching inputs — that's the point.
  • A crypto comparison wrapper. Libsodium / OpenSSL ship their own vetted versions; this exercise is to internalise the shape.

Summary

Three lines, no early exit, no branches on data.

Practice with these exercises