diff --git a/configure b/configure index bf6c773b5dd..234f476ac64 100755 --- a/configure +++ b/configure @@ -15878,6 +15878,16 @@ fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRNLEN $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 @@ -16050,6 +16060,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 7bfdc3ec82c..fd6ae577577 100644 --- a/configure.ac +++ b/configure.ac @@ -1796,7 +1796,7 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [#include ]) ]) # fi AC_CHECK_DECLS(fdatasync, [], [], [#include ]) -AC_CHECK_DECLS([strlcat, strlcpy, strnlen]) +AC_CHECK_DECLS([strlcat, strlcpy, strnlen, timingsafe_bcmp]) # We can't use AC_CHECK_FUNCS to detect these functions, because it # won't handle deployment target restrictions on macOS @@ -1818,6 +1818,7 @@ AC_REPLACE_FUNCS(m4_normalize([ strlcat strlcpy strnlen + timingsafe_bcmp ])) AC_REPLACE_FUNCS(pthread_barrier_wait) diff --git a/meson.build b/meson.build index 73e30a17090..fc3236839c7 100644 --- a/meson.build +++ b/meson.build @@ -2484,6 +2484,7 @@ decl_checks = [ ['strlcat', 'string.h'], ['strlcpy', 'string.h'], ['strnlen', 'string.h'], + ['timingsafe_bcmp', 'string.h'], ] # Need to check for function declarations for these functions, because @@ -2772,6 +2773,7 @@ func_checks = [ ['strsignal'], ['sync_file_range'], ['syncfs'], + ['timingsafe_bcmp'], ['uselocale'], ['wcstombs_l'], ] diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index ee75c7da5ae..5bd30dd3949 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -135,6 +135,10 @@ don't. */ #undef HAVE_DECL_STRNLEN +/* Define to 1 if you have the declaration of `timingsafe_bcmp', and to 0 if + you don't. */ +#undef HAVE_DECL_TIMINGSAFE_BCMP + /* Define to 1 if you have the header file. */ #undef HAVE_EDITLINE_HISTORY_H @@ -467,6 +471,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H +/* Define to 1 if you have the `timingsafe_bcmp' function. */ +#undef HAVE_TIMINGSAFE_BCMP + /* Define to 1 if your compiler understands `typeof' or something similar. */ #undef HAVE_TYPEOF diff --git a/src/include/port.h b/src/include/port.h index 6796533ac90..a90d0cf32f3 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -465,6 +465,10 @@ extern bool pg_get_user_name(uid_t user_id, char *buffer, size_t buflen); extern bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen); #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 90f837248de..565324af595 100644 --- a/src/port/meson.build +++ b/src/port/meson.build @@ -70,6 +70,7 @@ replace_funcs_neg = [ ['strlcat'], ['strlcpy'], ['strnlen'], + ['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 +}