]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Add consttime_memequal() function
authorGuillem Jover <guillem@hadrons.org>
Fri, 17 Oct 2025 21:47:55 +0000 (23:47 +0200)
committerGuillem Jover <guillem@hadrons.org>
Sat, 16 May 2026 15:49:08 +0000 (17:49 +0200)
Import from NetBSD.

COPYING
configure.ac
include/bsd/string.h
man/Makefile.am
man/consttime_memequal.3bsd [new file with mode: 0644]
man/libbsd.7
src/Makefile.am
src/consttime_memequal.c [new file with mode: 0644]
src/libbsd.map.in

diff --git a/COPYING b/COPYING
index 69ad593e16748f617bff214354c99a657ed0ab49..d4a4bedebb00ee2b02fc6b0c08509334b0a031b9 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -164,6 +164,7 @@ License: libutil-David-Nugent
 Files:
  include/bsd/stringlist.h
  man/arc4random.3bsd
+ man/consttime_memequal.3bsd
  man/explicit_memset.3bsd
  man/fmtcheck.3bsd
  man/humanize_number.3bsd
@@ -363,6 +364,7 @@ License: Expat
 
 Files:
  src/chacha_private.h
+ src/consttime_memequal.c
  src/explicit_bzero.c
  src/explicit_memset.c
 Copyright:
index 51c47d0840d5a93ff2afe275069104029f4f3c6c..1c1181ba675eb679f50229ad08eda4a150a687ea 100644 (file)
@@ -50,6 +50,7 @@ abi_arc4random_stir=unknown
 abi_asprintf=unknown
 abi_bsd_getopt=unknown
 abi_closefrom=unknown
+abi_consttime_memequal=unknown
 abi_err=unknown
 abi_errc=unknown
 abi_expand_number=unknown
@@ -101,6 +102,7 @@ AS_CASE([$host_os],
     # DROP: On glibc >= 2.34.
     #abi_closefrom=no
     abi_closefrom=yes
+    abi_consttime_memequal=yes
     abi_err=no
     abi_errc=yes
     abi_expand_number=yes
@@ -161,6 +163,7 @@ AS_CASE([$host_os],
     #abi_bsd_getopt=no
     abi_bsd_getopt=yes
     abi_closefrom=yes
+    abi_consttime_memequal=yes
     abi_err=no
     abi_errc=yes
     abi_expand_number=yes
@@ -226,6 +229,7 @@ AS_CASE([$host_os],
     abi_asprintf=no
     abi_bsd_getopt=no
     abi_closefrom=yes
+    abi_consttime_memequal=yes
     abi_err=no
     abi_errc=no
     abi_expand_number=yes
@@ -275,6 +279,7 @@ AS_CASE([$host_os],
     abi_asprintf=no
     abi_bsd_getopt=yes
     abi_closefrom=no
+    abi_consttime_memequal=yes
     abi_err=no
     abi_errc=yes
     abi_expand_number=yes
@@ -324,6 +329,7 @@ AS_CASE([$host_os],
     abi_asprintf=yes
     abi_bsd_getopt=yes
     abi_closefrom=yes
+    abi_consttime_memequal=yes
     abi_err=yes
     abi_errc=yes
     abi_expand_number=yes
@@ -573,6 +579,7 @@ LIBBSD_SELECT_ABI([arc4random_stir], [arc4random_stir()/arc4random_addrandom()])
 LIBBSD_SELECT_ABI([asprintf], [vasprintf()/asprintf()])
 LIBBSD_SELECT_ABI([bsd_getopt], [BSD getopt()])
 LIBBSD_SELECT_ABI([closefrom], [closefrom()])
+LIBBSD_SELECT_ABI([consttime_memequal], [consttime_memequal()])
 LIBBSD_SELECT_ABI([err_h], [err.h header])
 LIBBSD_SELECT_ABI([err], [err API])
 LIBBSD_SELECT_ABI([errc], [errc API])
index 6eeff46030815510cc3af8602da09eedb545a3e6..73ee757b6cfbc759894b048a92aeaf530d3b57f8 100644 (file)
@@ -59,6 +59,8 @@ void explicit_bzero(void *buf, size_t len);
 
 #if !defined(__NetBSD__)
 void *explicit_memset(void *buf, int c, size_t len);
+
+int consttime_memequal(const void *buf1, const void *buf2, size_t len);
 #endif
 __END_DECLS
 
index a5f4eec840c6a70fc228cda6e5e5a0d7ee61ea4e..f50e057c667e59f950825eb5432339cb341f092e 100644 (file)
@@ -250,6 +250,12 @@ dist_man_MANS += \
        # EOL
 endif
 
+if ABI_CONSTTIME_MEMEQUAL
+dist_man_MANS += \
+       consttime_memequal.3bsd \
+       # EOL
+endif
+
 if ABI_FGETLN
 dist_man_MANS += \
        fgetln.3bsd \
diff --git a/man/consttime_memequal.3bsd b/man/consttime_memequal.3bsd
new file mode 100644 (file)
index 0000000..09db3bd
--- /dev/null
@@ -0,0 +1,97 @@
+.\"    $NetBSD: consttime_memequal.3,v 1.5 2015/03/23 07:41:16 apb Exp $
+.\"
+.\" Copyright (c) 2013 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This documentation is derived from text contributed to The NetBSD
+.\" Foundation by Taylor R. Campbell.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd March 23, 2015
+.Dt consttime_memequal 3bsd
+.Os
+.Sh NAME
+.Nm consttime_memequal
+.Nd compare byte strings for equality without timing leaks
+.Sh LIBRARY
+.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
+.ds doc-str-Lb-libbsd \*[str-Lb-libbsd]
+.Lb libbsd
+.Sh SYNOPSIS
+.In string.h
+.Ft int
+.Fn consttime_memequal "void *b1" "void *b2" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn consttime_memequal
+function compares
+.Fa len
+bytes of memory at
+.Fa b1
+and
+.Fa b2
+for equality, returning 0 if they are distinct and 1 if they are
+identical.
+.Pp
+The time taken by
+.Fn consttime_memequal
+depends on
+.Fa len ,
+but not on the data at
+.Fa b1
+or
+.Fa b2 .
+Thus,
+.Fn consttime_memequal
+is appropriate for comparing cryptographic secrets, hashes, message
+authentication codes, etc., without leaking information about them
+through a timing side channel.
+In crypto literature,
+.Fn consttime_memequal
+is said to take
+.Sq constant time ,
+meaning time that does not vary depending on the data it processes.
+.Pp
+Note that unlike
+.Xr memcmp 3 ,
+.Fn consttime_memequal
+does not return a lexicographic ordering on the data at
+.Fa b1
+and
+.Fa b2 ;
+it tells only whether they are equal.
+.Nx
+does not provide a
+.Fn consttime_memcmp
+function, because all known use cases that require
+.Sq constant time
+memory comparison also require only comparison for equality,
+not lexicographic ordering.
+.Sh SEE ALSO
+.Xr explicit_memset 3bsd ,
+.Xr memcmp 3
+.Sh HISTORY
+The
+.Fn consttime_memequal
+function appeared in
+.Nx 7.0 .
index 83e2e09ec7cfa5ed829eac95ea90c30ad5ea57e6..7b30b1688f0894d44505205b1045ff8c7b0d00f9 100644 (file)
@@ -268,6 +268,7 @@ These functions are provided by
 .Xr bitstring 3bsd ,
 .Xr byteorder 3bsd ,
 .Xr closefrom 3bsd ,
+.Xr consttime_memequal 3bsd ,
 .Xr errc 3bsd ,
 .Xr expand_number 3bsd ,
 .Xr explicit_bzero 3bsd ,
index caaea89f789ba8e8bc97338512a96f1ae36648a2..bfcb8b1d794621e614e4c88aa8c8262d7a7845a8 100644 (file)
@@ -152,6 +152,12 @@ libbsd_la_SOURCES += \
        # EOL
 endif
 
+if ABI_CONSTTIME_MEMEQUAL
+libbsd_la_SOURCES += \
+       consttime_memequal.c \
+       # EOL
+endif
+
 if ABI_FGETLN
 libbsd_la_SOURCES += \
        fgetln.c \
diff --git a/src/consttime_memequal.c b/src/consttime_memequal.c
new file mode 100644 (file)
index 0000000..d10a509
--- /dev/null
@@ -0,0 +1,29 @@
+/* $NetBSD: consttime_memequal.c,v 1.6 2015/03/18 20:11:35 riastradh Exp $ */
+
+/*
+ * Written by Matthias Drochner <drochner@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <string.h>
+
+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));
+}
index fe79b21ba41fe180b2ca0db2e60453298c2ccca1..0e613fb84495fbcc11298d24bec8779f78543917 100644 (file)
@@ -322,4 +322,8 @@ LIBBSD_0.13.0 {
 #if LIBBSD_ABI_EXPLICIT_MEMSET
     explicit_memset;
 #endif
+
+#if LIBBSD_ABI_CONSTTIME_MEMEQUAL
+    consttime_memequal;
+#endif
 } LIBBSD_0.12.0;