The diff below adds timingsafe_bcmp() to libc, updates kern.9 to
mention that it's already in libkern, and removes the original from
OpenSSH.

I've already individually built libc and ssh on amd64 and they still
build fine.  I'm going to do a full userland rebuild now to double
check, but thought I'd send this out now to start getting review /
collecting oks.


Index: include/string.h
===================================================================
RCS file: /cvs/src/include/string.h,v
retrieving revision 1.19
diff -u -p -r1.19 string.h
--- include/string.h    18 May 2010 22:24:55 -0000      1.19
+++ include/string.h    22 Sep 2010 13:00:05 -0000
@@ -124,6 +124,7 @@ size_t       strlcpy(char *, const char *, si
 void    strmode(int, char *);
 char   *strsep(char **, const char *);
 char   *strsignal(int);
+int     timingsafe_bcmp(const void *, const void *, size_t);
 #endif 
 __END_DECLS
 
Index: lib/libc/string/timingsafe_bcmp.c
===================================================================
RCS file: lib/libc/string/timingsafe_bcmp.c
diff -N lib/libc/string/timingsafe_bcmp.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libc/string/timingsafe_bcmp.c   22 Sep 2010 13:00:05 -0000
@@ -0,0 +1,33 @@
+/*     $OpenBSD$       */
+/*
+ * Copyright (c) 2010 Damien Miller.  All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <string.h>
+#else
+#include <lib/libkern/libkern.h>
+#endif
+
+int
+timingsafe_bcmp(const void *b1, const void *b2, size_t n)
+{
+       const unsigned char *p1 = b1, *p2 = b2;
+       int ret = 0;
+
+       for (; n > 0; n--)
+               ret |= *p1++ ^ *p2++;
+       return (ret != 0);
+}
Index: lib/libc/string/Makefile.inc
===================================================================
RCS file: /cvs/src/lib/libc/string/Makefile.inc,v
retrieving revision 1.22
diff -u -p -r1.22 Makefile.inc
--- lib/libc/string/Makefile.inc        18 May 2010 22:24:55 -0000      1.22
+++ lib/libc/string/Makefile.inc        22 Sep 2010 13:00:05 -0000
@@ -9,7 +9,8 @@ SRCS+=  bm.c memccpy.c memrchr.c strcasec
        wcscat.c wcschr.c wcscmp.c wcscpy.c wcscspn.c wcslcat.c wcslcpy.c \
        wcslen.c wcsncat.c wcsncmp.c wcsncpy.c wcspbrk.c wcsrchr.c wcsspn.c \
        wcsstr.c wcstok.c wcswcs.c wcswidth.c wmemchr.c wmemcmp.c wmemcpy.c \
-       wmemmove.c wmemset.c
+       wmemmove.c wmemset.c \
+       timingsafe_bcmp.c
 
 # machine-dependent net sources
 # m-d Makefile.inc must include sources for:
@@ -178,3 +179,4 @@ MLINKS+=wmemchr.3 wcspbrk.3
 MLINKS+=wmemchr.3 wcsrchr.3
 MLINKS+=wmemchr.3 wcsspn.3
 MLINKS+=wmemchr.3 wcsstr.3
+MLINKS+=bcmp.3 timingsafe_bcmp.3
Index: lib/libc/string/bcmp.3
===================================================================
RCS file: /cvs/src/lib/libc/string/bcmp.3,v
retrieving revision 1.7
diff -u -p -r1.7 bcmp.3
--- lib/libc/string/bcmp.3      31 May 2007 19:19:32 -0000      1.7
+++ lib/libc/string/bcmp.3      22 Sep 2010 13:00:05 -0000
@@ -33,12 +33,15 @@
 .Dt BCMP 3
 .Os
 .Sh NAME
-.Nm bcmp
+.Nm bcmp ,
+.Nm timingsafe_bcmp
 .Nd compare byte string
 .Sh SYNOPSIS
 .Fd #include <string.h>
 .Ft int
 .Fn bcmp "const void *b1" "const void *b2" "size_t len"
+.Ft int
+.Fn timingsafe_bcmp "const void *b1" "const void *b2" "size_t len"
 .Sh DESCRIPTION
 The
 .Fn bcmp
@@ -53,6 +56,20 @@ bytes long.
 Zero-length strings are always identical.
 .Pp
 The strings may overlap.
+.Pp
+The
+.Fn timingsafe_bcmp
+function has the same semantics as
+.Fn bcmp ,
+but its running time is independent of the contents of
+.Fa b1
+and
+.Fa b2 ,
+making it safe to use for comparing secret values such as cryptographic MACs.
+In contrast,
+.Fn bcmp
+returns after finding the first differing byte,
+making it vulnerable to timing attacks.
 .Sh SEE ALSO
 .Xr memcmp 3 ,
 .Xr strcasecmp 3 ,
@@ -64,3 +81,8 @@ A
 .Fn bcmp
 function first appeared in
 .Bx 4.2 .
+.Pp
+The
+.Fn timingsafe_bcmp
+function first appeared in
+.Ox 4.9 .
Index: lib/libc/Makefile.inc
===================================================================
RCS file: /cvs/src/lib/libc/Makefile.inc,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile.inc
--- lib/libc/Makefile.inc       27 Jul 2010 16:59:03 -0000      1.15
+++ lib/libc/Makefile.inc       22 Sep 2010 13:00:05 -0000
@@ -62,7 +62,7 @@ CFLAGS+=-DNLS
 LIBKERN=       ${LIBCSRCDIR}/../../sys/lib/libkern
 
 KSRCS= bcmp.c bzero.c ffs.c strcat.c strcmp.c strcpy.c strlen.c strncmp.c \
-       strncpy.c htonl.c htons.c ntohl.c ntohs.c
+       strncpy.c htonl.c htons.c ntohl.c ntohs.c timingsafe_bcmp.c
 .if (${MACHINE_CPU} != "alpha")
 KSRCS+=        adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c 
iordi3.c \
        lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \
Index: share/man/man9/Makefile
===================================================================
RCS file: /cvs/src/share/man/man9/Makefile,v
retrieving revision 1.158
diff -u -p -r1.158 Makefile
--- share/man/man9/Makefile     7 Aug 2010 20:30:21 -0000       1.158
+++ share/man/man9/Makefile     22 Sep 2010 13:00:05 -0000
@@ -183,7 +183,7 @@ MLINKS+=kern.9 imax.9 kern.9 imin.9 kern
        kern.9 memchr.9 kern.9 memcmp.9 kern.9 ffs.9 \
        kern.9 strlen.9 kern.9 strncpy.9 kern.9 strlcpy.9 kern.9 strlcat.9 \
        kern.9 strcmp.9 kern.9 strncmp.9 kern.9 strncasecmp.9 \
-       kern.9 srandom.9 kern.9 getsn.9
+       kern.9 srandom.9 kern.9 timingsafe_bcmp.9 kern.9 getsn.9
 MLINKS+=knote.9 KNOTE.9
 MLINKS+=kthread.9 kthread_create.9 kthread.9 kthread_exit.9 \
        kthread.9 kthread_create_deferred.9
Index: share/man/man9/kern.9
===================================================================
RCS file: /cvs/src/share/man/man9/kern.9,v
retrieving revision 1.12
diff -u -p -r1.12 kern.9
--- share/man/man9/kern.9       31 May 2007 19:20:00 -0000      1.12
+++ share/man/man9/kern.9       22 Sep 2010 13:00:05 -0000
@@ -116,6 +116,8 @@ enabled.
 .Fn scanc "u_int size" "const u_char *cp" "const u_char *table" "int mask"
 .Ft int
 .Fn bcmp "const void *b1" "const void *b2" "size_t len"
+.Ft int
+.Fn timingsafe_bcmp "const void *b1" "const void *b2" "size_t len"
 .Ft void *
 .Fn memchr "const void *b" "int c" "size_t len"
 .Ft int
@@ -150,6 +152,7 @@ is not present in the string.
 .Pp
 The remaining functions have the same semantics as their libc counterparts,
 .Xr bcmp 3 ,
+.Xr timingsafe_bcmp 3 ,
 .Xr memchr 3 ,
 .Xr memcmp 3
 and
Index: usr.bin/ssh/misc.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/misc.c,v
retrieving revision 1.80
diff -u -p -r1.80 misc.c
--- usr.bin/ssh/misc.c  21 Jul 2010 02:10:58 -0000      1.80
+++ usr.bin/ssh/misc.c  22 Sep 2010 13:00:05 -0000
@@ -829,14 +829,3 @@ ms_to_timeval(struct timeval *tv, int ms
        tv->tv_sec = ms / 1000;
        tv->tv_usec = (ms % 1000) * 1000;
 }
-
-int
-timingsafe_bcmp(const void *b1, const void *b2, size_t n)
-{
-       const unsigned char *p1 = b1, *p2 = b2;
-       int ret = 0;
-
-       for (; n > 0; n--)
-               ret |= *p1++ ^ *p2++;
-       return (ret != 0);
-}
Index: usr.bin/ssh/misc.h
===================================================================
RCS file: /cvs/src/usr.bin/ssh/misc.h,v
retrieving revision 1.43
diff -u -p -r1.43 misc.h
--- usr.bin/ssh/misc.h  13 Jul 2010 23:13:16 -0000      1.43
+++ usr.bin/ssh/misc.h  22 Sep 2010 13:00:05 -0000
@@ -35,7 +35,6 @@ char  *tohex(const void *, size_t);
 void    sanitise_stdfd(void);
 void    ms_subtract_diff(struct timeval *, int *);
 void    ms_to_timeval(struct timeval *, int);
-int     timingsafe_bcmp(const void *, const void *, size_t);
 
 struct passwd *pwcopy(struct passwd *);
 const char *ssh_gai_strerror(int);

Reply via email to