⬢ DragonFlyBSD Kernel Audit
DF-3390 / fix.diff
← back to finding ↓ download raw
--- a/sys/net/wg/wg_noise.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/net/wg/wg_noise.c	2026-10-26 04:01:54.544244130 +0000
@@ -27,6 +27,7 @@
  */
 
 #include <sys/param.h>
+#include <sys/libkern.h>
 #include <sys/systm.h>
 #include <sys/bitops.h> /* ilog2() */
 #include <sys/endian.h>
@@ -1085,6 +1086,30 @@
 	return (ok);
 }
 
+/*
+ * Constant-time lexicographic (== numeric for big-endian) compare over
+ * NOISE_TIMESTAMP_LEN bytes; returns <0, 0, >0 like memcmp without
+ * short-circuiting.  Mirrors OpenBSD fixedtime_bcmp hardening.
+ */
+static int
+noise_tai64n_cmp(const uint8_t *a, const uint8_t *b)
+{
+	const volatile uint8_t *x = a, *y = b;
+	uint8_t gt = 0, lt = 0, eq = 1;
+	size_t i;
+
+	for (i = 0; i < NOISE_TIMESTAMP_LEN; i++) {
+		uint16_t df, db;
+
+		df = (uint16_t)x[i] - y[i];
+		db = (uint16_t)y[i] - x[i];
+		gt |= (uint8_t)(df >> 8) & eq;
+		lt |= (uint8_t)(db >> 8) & eq;
+		eq &= (uint8_t)(~((db | (uint16_t)(0 - db)) >> 8)) & 1;
+	}
+	return (int)(gt - lt);
+}
+
 struct noise_remote *
 noise_consume_initiation(struct noise_local *l, uint32_t s_idx,
 			 uint8_t ue[NOISE_PUBLIC_KEY_LEN],
@@ -1139,8 +1164,9 @@
 	 */
 	lockmgr(&r->r_handshake_lock, LK_EXCLUSIVE);
 
-	/* Replay */
-	if (memcmp(timestamp, r->r_timestamp, NOISE_TIMESTAMP_LEN) > 0)
+	/* Replay (constant-time compare: reject-on-less must not leak
+	 * the position of the first differing byte) */
+	if (noise_tai64n_cmp(timestamp, r->r_timestamp) > 0)
 		memcpy(r->r_timestamp, timestamp, NOISE_TIMESTAMP_LEN);
 	else
 		goto error_set;