2

libsodium verifies that the HMAC is correct with the following code:

return crypto_verify_32(h, correct) | (-(h == correct)) | sodium_memcmp(correct, h, 32);

where crypto_verify_32 is

for (i = 0; i < n; i++) {
    d |= x[i] ^ y[i];
}
return (1 & ((d - 1) >> 8)) - 1;

and sodium_memcmp is

for (i = 0U; i < len; i++) {
    d |= b1[i] ^ b2[i];
}
return (1 & ((d - 1) >> 8)) - 1;

Why not using a simple memcmp?

1 Answers1

5

memcmp() is not constant-time. The property called "constant-time" does not mean (confusingly) that every runs in a constant amount of time; an algorithm implementation is said to be "constant-time" if it does not leak information about secret data through timing-based side channels.

In the case of memcmp(), the leak is simple: memcmp() looks at bytes in increasing address order, and stops at the first index where bytes differ. Thus, the execution time, and the memory access pattern, if observed by attackers, may reveal how many bytes are identical. If the attacker can repeat the experiment with various purported "HMAC" values, he can use that leak to learn the complete true HMAC value, which can be a very bad thing in some contexts.

For more on the subject, see this page in BearSSL documentation.

Thomas Pornin
  • 86,974
  • 16
  • 242
  • 314