diff --git a/configure b/configure index 3d0e701c745..3c19e7e60ec 100755 --- a/configure +++ b/configure @@ -15927,6 +15927,16 @@ fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRSEP $ac_have_decl _ACEOF +ac_fn_c_check_decl "$LINENO" "timingsafe_bcmp" "ac_cv_have_decl_timingsafe_bcmp" "$ac_includes_default" +if test "x$ac_cv_have_decl_timingsafe_bcmp" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TIMINGSAFE_BCMP $ac_have_decl +_ACEOF # We can't use AC_CHECK_FUNCS to detect these functions, because it @@ -16099,6 +16109,19 @@ esac fi +ac_fn_c_check_func "$LINENO" "timingsafe_bcmp" "ac_cv_func_timingsafe_bcmp" +if test "x$ac_cv_func_timingsafe_bcmp" = xyes; then : + $as_echo "#define HAVE_TIMINGSAFE_BCMP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" timingsafe_bcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS timingsafe_bcmp.$ac_objext" + ;; +esac + +fi + ac_fn_c_check_func "$LINENO" "pthread_barrier_wait" "ac_cv_func_pthread_barrier_wait" diff --git a/configure.ac b/configure.ac index 47a287926bc..65db0673f8a 100644 --- a/configure.ac +++ b/configure.ac @@ -1805,7 +1805,7 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [#include ]) ]) # fi AC_CHECK_DECLS(fdatasync, [], [], [#include ]) -AC_CHECK_DECLS([strlcat, strlcpy, strnlen, strsep]) +AC_CHECK_DECLS([strlcat, strlcpy, strnlen, strsep, timingsafe_bcmp]) # We can't use AC_CHECK_FUNCS to detect these functions, because it # won't handle deployment target restrictions on macOS @@ -1826,6 +1826,7 @@ AC_REPLACE_FUNCS(m4_normalize([ strlcpy strnlen strsep + timingsafe_bcmp ])) AC_REPLACE_FUNCS(pthread_barrier_wait) diff --git a/meson.build b/meson.build index ba7916d1493..e8b872d29ad 100644 --- a/meson.build +++ b/meson.build @@ -2569,6 +2569,7 @@ decl_checks = [ ['strlcpy', 'string.h'], ['strnlen', 'string.h'], ['strsep', 'string.h'], + ['timingsafe_bcmp', 'string.h'], ] # Need to check for function declarations for these functions, because @@ -2826,6 +2827,7 @@ func_checks = [ ['strsignal'], ['sync_file_range'], ['syncfs'], + ['timingsafe_bcmp'], ['uselocale'], ['wcstombs_l'], ] diff --git a/src/include/port.h b/src/include/port.h index 3faae03d246..3964d3b1293 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -464,6 +464,10 @@ extern size_t strnlen(const char *str, size_t maxlen); extern char *strsep(char **stringp, const char *delim); #endif +#if !HAVE_DECL_TIMINGSAFE_BCMP +extern int timingsafe_bcmp(const void *b1, const void *b2, size_t len); +#endif + /* * Callers should use the qsort() macro defined below instead of calling * pg_qsort() directly. diff --git a/src/port/meson.build b/src/port/meson.build index cf7f07644b9..51041e75609 100644 --- a/src/port/meson.build +++ b/src/port/meson.build @@ -73,6 +73,7 @@ replace_funcs_neg = [ ['strlcpy'], ['strnlen'], ['strsep'], + ['timingsafe_bcmp'], ] if host_system != 'windows' diff --git a/src/port/timingsafe_bcmp.c b/src/port/timingsafe_bcmp.c new file mode 100644 index 00000000000..288865f50d1 --- /dev/null +++ b/src/port/timingsafe_bcmp.c @@ -0,0 +1,43 @@ +/* + * src/port/timingsafe_bcmp.c + * + * $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 "c.h" + +#ifdef USE_SSL +#include +#endif + +int +timingsafe_bcmp(const void *b1, const void *b2, size_t n) +{ +#ifdef USE_SSL + return CRYPTO_memcmp(b1, b2, n); +#else + const unsigned char *p1 = b1, + *p2 = b2; + int ret = 0; + + for (; n > 0; n--) + ret |= *p1++ ^ *p2++; + return (ret != 0); +#endif +}