From: Chris Porter Date: Tue, 11 Jun 2013 22:02:42 +0000 (+0100) Subject: Fix timing attacks in HMAC functions. X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/0bd91417bf01303f9cd8310b083fc6af48119203 Fix timing attacks in HMAC functions. --- diff --git a/chanserv/authcmds/reset.c b/chanserv/authcmds/reset.c index 54421652..cdea413e 100644 --- a/chanserv/authcmds/reset.c +++ b/chanserv/authcmds/reset.c @@ -41,7 +41,7 @@ int csa_doreset(void *source, int cargc, char **cargv) { return CMD_ERROR; } - if(strcasecmp(cargv[1], csc_generateresetcode(rup->lockuntil, rup->username))) { + if(hmac_strcmp(cargv[1], csc_generateresetcode(rup->lockuntil, rup->username))) { chanservstdmessage(sender, QM_BADRESETCODE); return CMD_ERROR; } diff --git a/chanserv/chanservcrypto.c b/chanserv/chanservcrypto.c index 05f70058..ba40f437 100644 --- a/chanserv/chanservcrypto.c +++ b/chanserv/chanservcrypto.c @@ -119,7 +119,7 @@ int crsha1(char *username, const char *password, const char *challenge, const ch hmac_printhex(digest, hexbuf, sizeof(digest)); - if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response)) + if(!hmac_strcmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response)) return 1; return 0; @@ -148,7 +148,7 @@ int crsha256(char *username, const char *password, const char *challenge, const hmacsha256_update(&hmac, (unsigned char *)challenge, strlen(challenge)); hmacsha256_final(&hmac, digest); - if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response)) + if(!hmac_strcmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response)) return 1; return 0; @@ -177,7 +177,7 @@ int crmd5(char *username, const char *password, const char *challenge, const cha hmacmd5_update(&hmac, (unsigned char *)challenge, strlen(challenge)); hmacmd5_final(&hmac, digest); - if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response)) + if(!hmac_strcmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response)) return 1; return 0; @@ -194,7 +194,7 @@ int crlegacymd5(char *username, const char *password, const char *challenge, con MD5Update(&ctx, (unsigned char *)challenge, strlen(challenge)); MD5Final(digest, &ctx); - if(!strcasecmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response)) + if(!hmac_strcmp(hmac_printhex(digest, hexbuf, sizeof(digest)), response)) return 1; return 0; @@ -242,7 +242,7 @@ int cs_checkhashpass(const char *username, const char *password, const char *jun MD5Update(&ctx, (unsigned char *)buf, strlen(buf)); MD5Final(digest, &ctx); - if(strcasecmp(hash, hmac_printhex(digest, hexbuf, sizeof(digest)))) + if(hmac_strcmp(hash, hmac_printhex(digest, hexbuf, sizeof(digest)))) return 0; return 1; @@ -286,7 +286,7 @@ int csc_verifyqticket(char *data, char *digest) { hmac_printhex(digestbuf, hexbuf, sizeof(digestbuf)); - if(!strcasecmp(hexbuf, digest)) + if(!hmac_strcmp(hexbuf, digest)) return 0; return 1; diff --git a/lib/hmac.c b/lib/hmac.c index d4c255b7..ee11d76e 100644 --- a/lib/hmac.c +++ b/lib/hmac.c @@ -130,3 +130,19 @@ char *hmac_printhex(unsigned char *data, char *out, size_t len) { *o = '\0'; return out; } + +int hmac_strcmp(char *a, char *b) { + int result = 1; + + if(!a || !b) + return 1; + + if(strlen(a) != strlen(b)) + return 1; + + while(*a) + result&=(tolower(*a++) == tolower(*b++)); + + return !result; +} + diff --git a/lib/hmac.h b/lib/hmac.h index 6c149d2b..3a5a0936 100644 --- a/lib/hmac.h +++ b/lib/hmac.h @@ -27,3 +27,5 @@ void hmacmd5_update(hmacmd5 *c, unsigned char *message, int messagelen); void hmacmd5_init(hmacmd5 *c, unsigned char *key, int keylen); char *hmac_printhex(unsigned char *data, char *out, size_t len); + +int hmac_strcmp(char *a, char *b); diff --git a/ticketauth/ticketauth.c b/ticketauth/ticketauth.c index da8b3533..40bd8b5d 100644 --- a/ticketauth/ticketauth.c +++ b/ticketauth/ticketauth.c @@ -68,7 +68,7 @@ int ta_ticketauth(void *source, int cargc, char **cargv) { /* hahahaha */ snprintf(buffer, sizeof(buffer), "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15], digest[16], digest[17], digest[18], digest[19], digest[20], digest[21], digest[22], digest[23], digest[24], digest[25], digest[26], digest[27], digest[28], digest[29], digest[30], digest[31]); - if(strcasecmp(buffer, uhmac)) { + if(hmac_strcmp(buffer, uhmac)) { controlwall(NO_OPER, NL_MISC, "%s!%s@%s attempted to TICKETAUTH as %s (bad HMAC)", np->nick, np->ident, np->host->name->content, acc); controlreply(np, "Bad HMAC."); return CMD_ERROR; diff --git a/trusts/trusts_slave.c b/trusts/trusts_slave.c index c62f1456..38029029 100644 --- a/trusts/trusts_slave.c +++ b/trusts/trusts_slave.c @@ -235,7 +235,7 @@ static int xsb_trfini(void *source, int argc, char **argv) { } SHA1Final(digest, &s); - if(strcasecmp(hmac_printhex(digest, digestbuf, SHA1_DIGESTSIZE), buf)) { + if(hmac_strcmp(hmac_printhex(digest, digestbuf, SHA1_DIGESTSIZE), buf)) { abandonreplication("digest mismatch"); return CMD_ERROR; }