[multiple] move const time cmp funcs to ck.[ch]
http_auth_const_time_memeq_pad() -> ck_memeq_const_time() http_auth_const_time_memeq() -> ck_memeq_const_time_fixed_len()personal/stbuehler/tests-path
parent
0286bdef0c
commit
62ccda8592
43
src/ck.c
43
src/ck.c
|
@ -254,3 +254,46 @@ ck_strerror_s (char * const s, const rsize_t maxsize, const errno_t errnum)
|
|||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ck_memeq_const_time (const void *a, const size_t alen, const void *b, const size_t blen)
|
||||
{
|
||||
/* constant time memory compare for equality */
|
||||
/* rounds to next multiple of 64 to avoid potentially leaking exact
|
||||
* string lengths when subject to high precision timing attacks
|
||||
*/
|
||||
/* Note: some libs provide similar funcs but might not obscure length, e.g.
|
||||
* OpenSSL:
|
||||
* int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len)
|
||||
* Note: some OS provide similar funcs but might not obscure length, e.g.
|
||||
* OpenBSD: int timingsafe_bcmp(const void *b1, const void *b2, size_t len)
|
||||
* NetBSD: int consttime_memequal(void *b1, void *b2, size_t len)
|
||||
*/
|
||||
const volatile unsigned char * const av = (const unsigned char *)a;
|
||||
const volatile unsigned char * const bv = (const unsigned char *)b;
|
||||
size_t lim = ((alen >= blen ? alen : blen) + 0x3F) & ~0x3F;
|
||||
int diff = (alen != blen); /*(never match if string length mismatch)*/
|
||||
for (size_t i = 0, j = 0; lim; --lim) {
|
||||
diff |= (av[i] ^ bv[j]);
|
||||
i += (i < alen);
|
||||
j += (j < blen);
|
||||
}
|
||||
return (0 == diff);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ck_memeq_const_time_fixed_len (const void *a, const void *b, const size_t len)
|
||||
{
|
||||
/* constant time memory compare for equality for fixed len (e.g. digests)
|
||||
* (padding not necessary for digests, which have fixed, defined lengths) */
|
||||
/* caller should prefer ck_memeq_const_time() if not operating on digests */
|
||||
const volatile unsigned char * const av = (const unsigned char *)a;
|
||||
const volatile unsigned char * const bv = (const unsigned char *)b;
|
||||
int diff = 0;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
diff |= (av[i] ^ bv[i]);
|
||||
}
|
||||
return (0 == diff);
|
||||
}
|
||||
|
|
10
src/ck.h
10
src/ck.h
|
@ -42,6 +42,16 @@ static inline errno_t ck_memzero(void *s, rsize_t n) {
|
|||
|
||||
errno_t ck_strerror_s (char *s, rsize_t maxsize, errno_t errnum);
|
||||
|
||||
/*(ck_memeq_const_time() is not from C11 Annex K)
|
||||
* constant time memory compare for equality
|
||||
* rounds to next multiple of 64 to avoid potentially leaking exact
|
||||
* string lengths when subject to high precision timing attacks */
|
||||
int ck_memeq_const_time (const void *a, size_t alen, const void *b, size_t blen);
|
||||
|
||||
/*(ck_memeq_const_time_fixed_len() is not from C11 Annex K)
|
||||
* constant time memory compare for equality for fixed len (e.g. digests)
|
||||
* (padding not necessary for digests, which have fixed, defined lengths) */
|
||||
int ck_memeq_const_time_fixed_len (const void *a, const void *b, size_t len);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
|
@ -58,57 +58,6 @@ void http_auth_backend_set (const http_auth_backend_t *backend)
|
|||
}
|
||||
|
||||
|
||||
int http_auth_const_time_memeq (const void *a, const void *b, const size_t len)
|
||||
{
|
||||
/* constant time memory compare, unless compiler figures it out
|
||||
* (similar to mod_secdownload.c:const_time_memeq()) */
|
||||
/* caller should prefer http_auth_const_time_memeq_pad()
|
||||
* if not operating on digests, which have defined lengths */
|
||||
/* Note: some libs provide similar funcs, e.g.
|
||||
* OpenSSL:
|
||||
* int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len)
|
||||
* Note: some OS provide similar funcs, e.g.
|
||||
* OpenBSD: int timingsafe_bcmp(const void *b1, const void *b2, size_t len)
|
||||
* NetBSD: int consttime_memequal(void *b1, void *b2, size_t len)
|
||||
*/
|
||||
const volatile unsigned char * const av = (const unsigned char *)a;
|
||||
const volatile unsigned char * const bv = (const unsigned char *)b;
|
||||
int diff = 0;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
diff |= (av[i] ^ bv[i]);
|
||||
}
|
||||
return (0 == diff);
|
||||
}
|
||||
|
||||
|
||||
int http_auth_const_time_memeq_pad (const void *a, const size_t alen, const void *b, const size_t blen)
|
||||
{
|
||||
/* constant time memory compare, unless compiler figures it out
|
||||
* (similar to mod_secdownload.c:const_time_memeq()) */
|
||||
/* round to next multiple of 64 to avoid potentially leaking exact
|
||||
* password length when subject to high precision timing attacks)
|
||||
* (not necessary when comparing digests, which have defined lengths)
|
||||
*/
|
||||
/* Note: some libs provide similar funcs but might not obscure length, e.g.
|
||||
* OpenSSL:
|
||||
* int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len)
|
||||
* Note: some OS provide similar funcs but might not obscure length, e.g.
|
||||
* OpenBSD: int timingsafe_bcmp(const void *b1, const void *b2, size_t len)
|
||||
* NetBSD: int consttime_memequal(void *b1, void *b2, size_t len)
|
||||
*/
|
||||
const volatile unsigned char * const av = (const unsigned char *)a;
|
||||
const volatile unsigned char * const bv = (const unsigned char *)b;
|
||||
size_t lim = ((alen >= blen ? alen : blen) + 0x3F) & ~0x3F;
|
||||
int diff = (alen != blen); /*(never match if string length mismatch)*/
|
||||
for (size_t i = 0, j = 0; lim; --lim) {
|
||||
diff |= (av[i] ^ bv[j]);
|
||||
i += (i < alen);
|
||||
j += (j < blen);
|
||||
}
|
||||
return (0 == diff);
|
||||
}
|
||||
|
||||
|
||||
void http_auth_dumbdata_reset (void)
|
||||
{
|
||||
memset(http_auth_schemes, 0, sizeof(http_auth_schemes));
|
||||
|
|
|
@ -88,12 +88,6 @@ const http_auth_backend_t * http_auth_backend_get (const buffer *name);
|
|||
__attribute_cold__
|
||||
void http_auth_backend_set (const http_auth_backend_t *backend);
|
||||
|
||||
__attribute_pure__
|
||||
int http_auth_const_time_memeq (const void *a, const void *b, size_t len);
|
||||
|
||||
__attribute_pure__
|
||||
int http_auth_const_time_memeq_pad (const void *a, size_t alen, const void *b, size_t blen);
|
||||
|
||||
void http_auth_setenv(request_st *r, const char *username, size_t ulen, const char *auth_type, size_t alen);
|
||||
|
||||
int http_auth_digest_hex2bin (const char *hexstr, size_t len, unsigned char *bin, size_t binlen);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "sys-crypto-md.h" /* USE_LIB_CRYPTO */
|
||||
|
||||
#include "base.h"
|
||||
#include "ck.h"
|
||||
#include "plugin.h"
|
||||
#include "plugin_config.h"
|
||||
#include "http_auth.h"
|
||||
|
@ -795,8 +796,7 @@ static handler_t mod_auth_check_basic(request_st * const r, void *p_d, const str
|
|||
ae = http_auth_cache_query(sptree, ndx);
|
||||
if (ae && ae->require == require
|
||||
&& buffer_is_equal_string(username, ae->username, ae->ulen))
|
||||
rc = http_auth_const_time_memeq_pad(ae->pwdigest, ae->dlen,
|
||||
pw, pwlen)
|
||||
rc = ck_memeq_const_time(ae->pwdigest, ae->dlen, pw, pwlen)
|
||||
? HANDLER_GO_ON
|
||||
: HANDLER_ERROR;
|
||||
else /*(not found or hash collision)*/
|
||||
|
@ -1473,7 +1473,7 @@ static handler_t mod_auth_check_digest(request_st * const r, void *p_d, const st
|
|||
|
||||
mod_auth_digest_mutate(&ai,m,uri,nonce,cnonce,nc,qop);
|
||||
|
||||
if (!http_auth_const_time_memeq(rdigest, ai.digest, ai.dlen)) {
|
||||
if (!ck_memeq_const_time_fixed_len(rdigest, ai.digest, ai.dlen)) {
|
||||
/*safe_memclear(ai.digest, ai.dlen);*//* skip clear since mutated */
|
||||
/* digest not ok */
|
||||
log_error(r->conf.errh, __FILE__, __LINE__,
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "sys-crypto-md.h"
|
||||
#include "safe_memclear.h"
|
||||
#include "base.h"
|
||||
#include "ck.h"
|
||||
#include "http_auth.h"
|
||||
#include "fdevent.h"
|
||||
#include "log.h"
|
||||
|
@ -403,7 +404,7 @@ mod_authn_dbi_password_cmp (const char *userpw, unsigned long userpwlen, http_au
|
|||
/*(compare 16-byte MD5 binary instead of converting to hex strings
|
||||
* in order to then have to do case-insensitive hex str comparison)*/
|
||||
return (0 == http_auth_digest_hex2bin(userpw, 32, md5pw, sizeof(md5pw)))
|
||||
? http_auth_const_time_memeq(HA1, md5pw, sizeof(md5pw)) ? 0 : 1
|
||||
? ck_memeq_const_time_fixed_len(HA1, md5pw, sizeof(md5pw)) ? 0 : 1
|
||||
: -1;
|
||||
}
|
||||
#ifdef USE_LIB_CRYPTO
|
||||
|
@ -423,7 +424,7 @@ mod_authn_dbi_password_cmp (const char *userpw, unsigned long userpwlen, http_au
|
|||
/*(compare 32-byte binary digest instead of converting to hex strings
|
||||
* in order to then have to do case-insensitive hex str comparison)*/
|
||||
return (0 == http_auth_digest_hex2bin(userpw, 64, shapw, sizeof(shapw)))
|
||||
? http_auth_const_time_memeq(HA1, shapw, sizeof(shapw)) ? 0 : 1
|
||||
? ck_memeq_const_time_fixed_len(HA1, shapw, sizeof(shapw)) ? 0 : 1
|
||||
: -1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "safe_memclear.h"
|
||||
|
||||
#include "base.h"
|
||||
#include "ck.h"
|
||||
#include "plugin.h"
|
||||
#include "fdevent.h"
|
||||
#include "http_auth.h"
|
||||
|
@ -302,7 +303,7 @@ static handler_t mod_authn_file_htdigest_basic(request_st * const r, void *p_d,
|
|||
|
||||
mod_authn_file_digest(&ai, pw, strlen(pw));
|
||||
|
||||
int rc = (http_auth_const_time_memeq(htdigest, ai.digest, ai.dlen)
|
||||
int rc = (ck_memeq_const_time_fixed_len(htdigest, ai.digest, ai.dlen)
|
||||
&& http_auth_match_rules(require, username->ptr, NULL, NULL));
|
||||
|
||||
safe_memclear(htdigest, ai.dlen);
|
||||
|
@ -394,7 +395,9 @@ static handler_t mod_authn_file_plain_basic(request_st * const r, void *p_d, con
|
|||
mod_authn_file_patch_config(r, p);
|
||||
rc = mod_authn_file_htpasswd_get(p->conf.auth_plain_userfile, CONST_BUF_LEN(username), password_buf, r->conf.errh);
|
||||
if (0 == rc) {
|
||||
rc = http_auth_const_time_memeq_pad(CONST_BUF_LEN(password_buf), pw, strlen(pw)) ? 0 : -1;
|
||||
rc = ck_memeq_const_time(CONST_BUF_LEN(password_buf), pw, strlen(pw))
|
||||
? 0
|
||||
: -1;
|
||||
}
|
||||
safe_memclear(password_buf->ptr, password_buf->size);
|
||||
buffer_free(password_buf);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <mysql.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "ck.h"
|
||||
#include "http_auth.h"
|
||||
#include "log.h"
|
||||
#include "plugin.h"
|
||||
|
@ -317,7 +318,7 @@ static int mod_authn_mysql_password_cmp(const char *userpw, unsigned long userpw
|
|||
/*(compare 16-byte MD5 binary instead of converting to hex strings
|
||||
* in order to then have to do case-insensitive hex str comparison)*/
|
||||
return (0 == http_auth_digest_hex2bin(userpw, 32, md5pw, sizeof(md5pw)))
|
||||
? http_auth_const_time_memeq(HA1, md5pw, sizeof(md5pw)) ? 0 : 1
|
||||
? ck_memeq_const_time_fixed_len(HA1, md5pw, sizeof(md5pw)) ? 0 : 1
|
||||
: -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "log.h"
|
||||
#include "buffer.h"
|
||||
#include "base64.h"
|
||||
#include "ck.h"
|
||||
#include "http_auth.h"
|
||||
|
||||
#include "plugin.h"
|
||||
|
@ -159,8 +160,8 @@ static int secdl_verify_mac(plugin_config *config, const char* protected_path, c
|
|||
li_MD5_Update(&Md5Ctx, ts_str, 8);
|
||||
li_MD5_Final(HA1, &Md5Ctx);
|
||||
|
||||
return http_auth_const_time_memeq((char *)HA1,
|
||||
(char *)md5bin, sizeof(md5bin));
|
||||
return ck_memeq_const_time_fixed_len((char *)HA1,
|
||||
(char *)md5bin,sizeof(md5bin));
|
||||
}
|
||||
#ifdef USE_LIB_CRYPTO
|
||||
case SECDL_HMAC_SHA1:
|
||||
|
@ -179,7 +180,7 @@ static int secdl_verify_mac(plugin_config *config, const char* protected_path, c
|
|||
li_to_base64_no_padding(base64_digest, 28, digest, 20, BASE64_URL);
|
||||
|
||||
return (27 == maclen)
|
||||
&& http_auth_const_time_memeq(mac, base64_digest, 27);
|
||||
&& ck_memeq_const_time_fixed_len(mac, base64_digest, 27);
|
||||
}
|
||||
break;
|
||||
case SECDL_HMAC_SHA256:
|
||||
|
@ -198,7 +199,7 @@ static int secdl_verify_mac(plugin_config *config, const char* protected_path, c
|
|||
li_to_base64_no_padding(base64_digest, 44, digest, 32, BASE64_URL);
|
||||
|
||||
return (43 == maclen)
|
||||
&& http_auth_const_time_memeq(mac, base64_digest, 43);
|
||||
&& ck_memeq_const_time_fixed_len(mac, base64_digest, 43);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue