# HG changeset patch # User Matt Johnston # Date 1380810330 -28800 # Node ID a625f9e135a418b08c61588bd5ab7a6b89b3186f # Parent 84e4259dae3e4acdf86e575117f5f79dae746be5 Constant time memcmp for the hmac and password crypt diff -r 84e4259dae3e -r a625f9e135a4 dbutil.c --- a/dbutil.c Sat Sep 21 00:34:36 2013 +0800 +++ b/dbutil.c Thu Oct 03 22:25:30 2013 +0800 @@ -884,3 +884,16 @@ return DROPBEAR_SUCCESS; } } + +int constant_time_memcmp(const void* a, const void *b, size_t n) +{ + const char *xa = a, *xb = b; + uint8_t c = 0; + size_t i; + for (i = 0; i < n; i++) + { + c |= (xa[i] ^ xb[i]); + } + return c; +} + diff -r 84e4259dae3e -r a625f9e135a4 dbutil.h --- a/dbutil.h Sat Sep 21 00:34:36 2013 +0800 +++ b/dbutil.h Thu Oct 03 22:25:30 2013 +0800 @@ -94,4 +94,7 @@ /* Dropbear assertion */ #define dropbear_assert(X) do { if (!(X)) { fail_assert(#X, __FILE__, __LINE__); } } while (0) +/* Returns 0 if a and b have the same contents */ +int constant_time_memcmp(const void* a, const void *b, size_t n); + #endif /* _DBUTIL_H_ */ diff -r 84e4259dae3e -r a625f9e135a4 packet.c --- a/packet.c Sat Sep 21 00:34:36 2013 +0800 +++ b/packet.c Thu Oct 03 22:25:30 2013 +0800 @@ -376,7 +376,7 @@ /* compare the hash */ buf_setpos(ses.readbuf, contents_len); - if (memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) { + if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) { return DROPBEAR_FAILURE; } else { return DROPBEAR_SUCCESS; diff -r 84e4259dae3e -r a625f9e135a4 svr-authpasswd.c --- a/svr-authpasswd.c Sat Sep 21 00:34:36 2013 +0800 +++ b/svr-authpasswd.c Thu Oct 03 22:25:30 2013 +0800 @@ -33,6 +33,17 @@ #ifdef ENABLE_SVR_PASSWORD_AUTH +static int constant_time_strcmp(const char* a, const char* b) { + size_t la = strlen(a); + size_t lb = strlen(b); + + if (la != lb) { + return 1; + } + + return constant_time_memcmp(a, b, la); +} + /* Process a password auth request, sending success or failure messages as * appropriate */ void svr_auth_password() { @@ -82,7 +93,7 @@ return; } - if (strcmp(testcrypt, passwdcrypt) == 0) { + if (constant_time_strcmp(testcrypt, passwdcrypt) == 0) { /* successful authentication */ dropbear_log(LOG_NOTICE, "Password auth succeeded for '%s' from %s",