diff --git a/src/mod_authn_file.c b/src/mod_authn_file.c index 1e16075e..174a4c78 100644 --- a/src/mod_authn_file.c +++ b/src/mod_authn_file.c @@ -356,7 +356,7 @@ static handler_t mod_authn_file_htdigest_basic(server *srv, connection *con, voi mod_authn_file_digest(&ai, pw, strlen(pw)); - return (0 == memcmp(htdigest, ai.digest, ai.dlen) + return (0 == safe_memcmp(htdigest, ai.digest, ai.dlen) && http_auth_match_rules(require, username->ptr, NULL, NULL)) ? HANDLER_GO_ON : HANDLER_ERROR; diff --git a/src/safe_memclear.c b/src/safe_memclear.c index 15617a46..1072c86d 100644 --- a/src/safe_memclear.c +++ b/src/safe_memclear.c @@ -47,3 +47,21 @@ void safe_memclear(void *s, size_t n) { safe_memset(s, 0, n); #endif } + +// Safer version of memcmp against timing attacks, +// the volatile pragma guaranting it. +// Semantically different than its counterpart though +// as not a real comparison call but bytes differences counting. +int safe_memcmp(const void *a, const void *b, size_t n) { + const volatile uint8_t *ua = (const volatile uint8_t *)a; + const volatile uint8_t *ub = (const volatile uint8_t *)b; + uint8_t res = 0; + int d = n; + + while (d >= 0) { + --d; + res |= ua[d] ^ ub[d]; + } + + return (int)res; +} diff --git a/src/safe_memclear.h b/src/safe_memclear.h index 9fd25636..dc590c5e 100644 --- a/src/safe_memclear.h +++ b/src/safe_memclear.h @@ -3,5 +3,6 @@ #include "first.h" void safe_memclear(void *s, size_t n); +int safe_memcmp(const void *a, const void *b, size_t n); #endif