changeset 4489:fbc041e8e8ee draft

auth: Use consttime_memequal(3) to compare hashes This stops any attacker from trying to infer secrets from latency. Thanks to Maxime Villard <max@m00nbsd.net>
author Roy Marples <roy@marples.name>
date Fri, 26 Apr 2019 15:16:44 +0100
parents 2f4811ec407b
children 8aeb92e98c71
files auth.c compat/consttime_memequal.h configure
diffstat 3 files changed, 50 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/auth.c	Wed Apr 24 12:35:34 2019 +0100
+++ b/auth.c	Fri Apr 26 15:16:44 2019 +0100
@@ -336,7 +336,7 @@
 	}
 
 	free(mm);
-	if (memcmp(d, &hmac, dlen)) {
+	if (consttime_memequal(d, &hmac, dlen)) {
 		errno = EPERM;
 		return NULL;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/compat/consttime_memequal.h	Fri Apr 26 15:16:44 2019 +0100
@@ -0,0 +1,28 @@
+/*
+ * Written by Matthias Drochner <drochner@NetBSD.org>.
+ * Public domain.
+ */
+
+#ifndef CONSTTIME_MEMEQUAL_H
+#define CONSTTIME_MEMEQUAL_H
+inline static int
+consttime_memequal(const void *b1, const void *b2, size_t len)
+{
+	const unsigned char *c1 = b1, *c2 = b2;
+	unsigned int res = 0;
+
+	while (len--)
+		res |= *c1++ ^ *c2++;
+
+	/*
+	 * Map 0 to 1 and [1, 256) to 0 using only constant-time
+	 * arithmetic.
+	 *
+	 * This is not simply `!res' because although many CPUs support
+	 * branchless conditional moves and many compilers will take
+	 * advantage of them, certain compilers generate branches on
+	 * certain CPUs for `!res'.
+	 */
+	return (1 & ((res - 1) >> 8));
+}
+#endif /* CONSTTIME_MEMEQUAL_H */
--- a/configure	Wed Apr 24 12:35:34 2019 +0100
+++ b/configure	Fri Apr 26 15:16:44 2019 +0100
@@ -820,6 +820,27 @@
 	echo "#include		\"compat/strtoi.h\"" >>$CONFIG_H
 fi
 
+if [ -z "$CONSTTIME_MEMEQUAL" ]; then
+	printf "Testing for consttime_memequal ... "
+	cat <<EOF >_consttime_memequal.c
+#include <string.h>
+int main(void) {
+	return consttime_memequal("deadbeef", "deadbeef", 8);
+}
+EOF
+	if $XCC _consttime_memequal.c -o _consttime_memequal 2>&3; then
+		CONSTTIME_MEMEQUAL=yes
+	else
+		CONSTTIME_MEMEQUAL=no
+	fi
+	echo "$CONSTTIME_MEMEQUAL"
+	rm -f _consttime_memequal.c _consttime_memequal
+fi
+if [ "$CONSTTIME_MEMEQUAL" = no ]; then
+	echo "#include			\"compat/consttime_memequal.h\"" \
+	    >>$CONFIG_H
+fi
+
 if [ -z "$DPRINTF" ]; then
 	printf "Testing for dprintf ... "
 	cat <<EOF >_dprintf.c