From 12006ca8ed08eb0858fe75f07623b5670c07b625 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Wed, 26 Mar 2025 04:03:00 +0800
Subject: [PATCH 4/4] Restore timingsafe

---
 Makefile                                      |  9 ++-
 missing.h                                     |  2 +
 src/lib/libc/string/timingsafe_bcmp.c         | 30 ++++++++
 src/lib/libc/string/timingsafe_memcmp.c       | 47 +++++++++++++
 src/regress/lib/libc/timingsafe/CVS/Entries   |  3 +
 .../lib/libc/timingsafe/CVS/Repository        |  1 +
 src/regress/lib/libc/timingsafe/CVS/Root      |  1 +
 src/regress/lib/libc/timingsafe/Makefile      |  5 ++
 src/regress/lib/libc/timingsafe/timingsafe.c  | 68 +++++++++++++++++++
 9 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 src/lib/libc/string/timingsafe_bcmp.c
 create mode 100644 src/lib/libc/string/timingsafe_memcmp.c
 create mode 100644 src/regress/lib/libc/timingsafe/CVS/Entries
 create mode 100644 src/regress/lib/libc/timingsafe/CVS/Repository
 create mode 100644 src/regress/lib/libc/timingsafe/CVS/Root
 create mode 100644 src/regress/lib/libc/timingsafe/Makefile
 create mode 100644 src/regress/lib/libc/timingsafe/timingsafe.c

diff --git Makefile Makefile
index ecf00fd..341cdb4 100644
--- Makefile
+++ Makefile
@@ -12,6 +12,7 @@ SRCS+= src/lib/libc/gen/readpassphrase.c
 SRCS+= src/lib/libc/hash/sha2.c
 SRCS+= src/lib/libc/net/base64.c
 SRCS+= src/lib/libc/string/explicit_bzero.c
+SRCS+= src/lib/libc/string/timingsafe_bcmp.c
 SRCS+= src/lib/libutil/bcrypt_pbkdf.c
 SRCS+= src/lib/libutil/ohash.c
 SRCS+= src/usr.bin/signify/crypto_api.c
@@ -115,9 +116,15 @@ REGRESS_BZ_SRCS+= src/regress/lib/libc/explicit_bzero/explicit_bzero.c
 explicit_bzero: ${REGRESS_BZ_SRCS}
 	${CC} ${CFLAGS} -o $@ ${REGRESS_BZ_SRCS}
 
+REGRESS_TS_SRCS=  src/lib/libc/string/timingsafe_bcmp.c
+REGRESS_TS_SRCS+= src/lib/libc/string/timingsafe_memcmp.c
+REGRESS_TS_SRCS+= src/regress/lib/libc/timingsafe/timingsafe.c
+timingsafe: ${REGRESS_TS_SRCS}
+	${CC} ${CFLAGS} -o $@ ${REGRESS_TS_SRCS}
+
 check: test
 
-test: signify explicit_bzero
+test: signify explicit_bzero timingsafe
 	@sh ./regress.sh
 
 
diff --git missing.h missing.h
index 4925153..2f456f2 100644
--- missing.h
+++ missing.h
@@ -2,3 +2,5 @@
 
 void explicit_bzero(void *, size_t);
 void freezero(void *, size_t);
+int timingsafe_bcmp(const void *, const void *, size_t);
+int timingsafe_memcmp(const void *, const void *, size_t);
diff --git src/lib/libc/string/timingsafe_bcmp.c src/lib/libc/string/timingsafe_bcmp.c
new file mode 100644
index 0000000..0409ec3
--- /dev/null
+++ src/lib/libc/string/timingsafe_bcmp.c
@@ -0,0 +1,30 @@
+/*	$OpenBSD: timingsafe_bcmp.c,v 1.3 2015/08/31 02:53:57 guenther Exp $	*/
+/*
+ * 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.
+ */
+
+#include <string.h>
+
+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);
+}
+DEF_WEAK(timingsafe_bcmp);
diff --git src/lib/libc/string/timingsafe_memcmp.c src/lib/libc/string/timingsafe_memcmp.c
new file mode 100644
index 0000000..373f8cb
--- /dev/null
+++ src/lib/libc/string/timingsafe_memcmp.c
@@ -0,0 +1,47 @@
+/*	$OpenBSD: timingsafe_memcmp.c,v 1.2 2015/08/31 02:53:57 guenther Exp $	*/
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * 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.
+ */
+
+#include <limits.h>
+#include <string.h>
+
+int
+timingsafe_memcmp(const void *b1, const void *b2, size_t len)
+{
+        const unsigned char *p1 = b1, *p2 = b2;
+        size_t i;
+        int res = 0, done = 0;
+
+        for (i = 0; i < len; i++) {
+                /* lt is -1 if p1[i] < p2[i]; else 0. */
+                int lt = (p1[i] - p2[i]) >> CHAR_BIT;
+
+                /* gt is -1 if p1[i] > p2[i]; else 0. */
+                int gt = (p2[i] - p1[i]) >> CHAR_BIT;
+
+                /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */
+                int cmp = lt - gt;
+
+                /* set res = cmp if !done. */
+                res |= cmp & ~done;
+
+                /* set done if p1[i] != p2[i]. */
+                done |= lt | gt;
+        }
+
+        return (res);
+}
+DEF_WEAK(timingsafe_memcmp);
diff --git src/regress/lib/libc/timingsafe/CVS/Entries src/regress/lib/libc/timingsafe/CVS/Entries
new file mode 100644
index 0000000..69c9466
--- /dev/null
+++ src/regress/lib/libc/timingsafe/CVS/Entries
@@ -0,0 +1,3 @@
+/Makefile/1.1/Fri Jun 13 01:55:02 2014//
+/timingsafe.c/1.3/Sat Jun 21 22:57:15 2014//
+D
diff --git src/regress/lib/libc/timingsafe/CVS/Repository src/regress/lib/libc/timingsafe/CVS/Repository
new file mode 100644
index 0000000..c390889
--- /dev/null
+++ src/regress/lib/libc/timingsafe/CVS/Repository
@@ -0,0 +1 @@
+src/regress/lib/libc/timingsafe
diff --git src/regress/lib/libc/timingsafe/CVS/Root src/regress/lib/libc/timingsafe/CVS/Root
new file mode 100644
index 0000000..844b841
--- /dev/null
+++ src/regress/lib/libc/timingsafe/CVS/Root
@@ -0,0 +1 @@
+anoncvs@anoncvs3.usa.openbsd.org:/cvs
diff --git src/regress/lib/libc/timingsafe/Makefile src/regress/lib/libc/timingsafe/Makefile
new file mode 100644
index 0000000..9a679b6
--- /dev/null
+++ src/regress/lib/libc/timingsafe/Makefile
@@ -0,0 +1,5 @@
+#	$OpenBSD: Makefile,v 1.1 2014/06/13 01:55:02 matthew Exp $
+
+PROG=	timingsafe
+
+.include <bsd.regress.mk>
diff --git src/regress/lib/libc/timingsafe/timingsafe.c src/regress/lib/libc/timingsafe/timingsafe.c
new file mode 100644
index 0000000..f6605f8
--- /dev/null
+++ src/regress/lib/libc/timingsafe/timingsafe.c
@@ -0,0 +1,68 @@
+/*	$OpenBSD: timingsafe.c,v 1.3 2014/06/21 22:57:15 tedu Exp $	*/
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * 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.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ASSERT_EQ(a, b) assert((a) == (b))
+
+enum {
+	N = 8
+};
+
+static unsigned char bufone[N], buftwo[N];
+
+void
+check()
+{
+	int cmp = memcmp(bufone, buftwo, N);
+
+	/* Check for reflexivity. */
+	ASSERT_EQ(0, timingsafe_bcmp(bufone, bufone, N));
+	ASSERT_EQ(0, timingsafe_bcmp(buftwo, buftwo, N));
+	ASSERT_EQ(0, timingsafe_memcmp(bufone, bufone, N));
+	ASSERT_EQ(0, timingsafe_memcmp(buftwo, buftwo, N));
+
+	/* Check that timingsafe_bcmp returns 0 iff memcmp returns 0. */
+	ASSERT_EQ(cmp == 0, timingsafe_bcmp(bufone, buftwo, N) == 0);
+
+	/* Check that timingsafe_memcmp returns cmp... */
+	ASSERT_EQ(cmp < 0, timingsafe_memcmp(bufone, buftwo, N) < 0);
+
+	/* ... or -cmp if the argument order is swapped. */
+	ASSERT_EQ(-cmp < 0, timingsafe_memcmp(buftwo, bufone, N) < 0);
+}
+
+int
+main()
+{
+	int i, j;
+
+	for (i = 0; i < 10000; i++) {
+		arc4random_buf(bufone, N);
+		arc4random_buf(buftwo, N);
+
+		check();
+		for (j = 0; j < N; j++) {
+			buftwo[j] = bufone[j];
+			check();
+		}
+	}
+
+	return (0);
+}
-- 
2.48.0

