From d1dec41f7656d7937f1cce64df1cc41121f3e44d Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Thu, 3 Oct 2013 22:25:30 +0800
Subject: [PATCH] Constant time memcmp for the hmac and password crypt

---
 dbutil.c         | 13 +++++++++++++
 dbutil.h         |  3 +++
 packet.c         |  2 +-
 svr-authpasswd.c | 13 ++++++++++++-
 4 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/dbutil.c b/dbutil.c
index 8ee6050c..2589e1a7 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -884,3 +884,16 @@ int m_str_to_uint(const char* str, unsigned int *val) {
 		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 --git a/dbutil.h b/dbutil.h
index 3af79f72..a34ddd75 100644
--- a/dbutil.h
+++ b/dbutil.h
@@ -94,4 +94,7 @@ int m_str_to_uint(const char* str, unsigned int *val);
 /* 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 --git a/packet.c b/packet.c
index d458ccf7..4ebd0d71 100644
--- a/packet.c
+++ b/packet.c
@@ -376,7 +376,7 @@ static int checkmac() {
 
 	/* 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 --git a/svr-authpasswd.c b/svr-authpasswd.c
index 17dd2a1b..7a5a1210 100644
--- a/svr-authpasswd.c
+++ b/svr-authpasswd.c
@@ -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 @@ void svr_auth_password() {
 		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",
-- 
GitLab