Skip to content

Commit 52f21c9

Browse files
hlinnakaJelteF
authored and
Commitfest Bot
committed
Add timingsafe_bcmp(), for constant-time memory comparison
timingsafe_bcmp() should be used instead of memcmp() or a naive for-loop, when comparing passwords or secret tokens, to avoid leaking information about the secret token by timing. This commit just introduces the function but does not change any existing code to use it yet. Co-authored-by: Jelte Fennema-Nio <[email protected]> Discussion: https://www.postgresql.org/message-id/[email protected]
1 parent 764d501 commit 52f21c9

File tree

6 files changed

+75
-1
lines changed

6 files changed

+75
-1
lines changed

configure

+23
Original file line numberDiff line numberDiff line change
@@ -15927,6 +15927,16 @@ fi
1592715927
cat >>confdefs.h <<_ACEOF
1592815928
#define HAVE_DECL_STRSEP $ac_have_decl
1592915929
_ACEOF
15930+
ac_fn_c_check_decl "$LINENO" "timingsafe_bcmp" "ac_cv_have_decl_timingsafe_bcmp" "$ac_includes_default"
15931+
if test "x$ac_cv_have_decl_timingsafe_bcmp" = xyes; then :
15932+
ac_have_decl=1
15933+
else
15934+
ac_have_decl=0
15935+
fi
15936+
15937+
cat >>confdefs.h <<_ACEOF
15938+
#define HAVE_DECL_TIMINGSAFE_BCMP $ac_have_decl
15939+
_ACEOF
1593015940

1593115941

1593215942
# We can't use AC_CHECK_FUNCS to detect these functions, because it
@@ -16087,6 +16097,19 @@ esac
1608716097

1608816098
fi
1608916099

16100+
ac_fn_c_check_func "$LINENO" "timingsafe_bcmp" "ac_cv_func_timingsafe_bcmp"
16101+
if test "x$ac_cv_func_timingsafe_bcmp" = xyes; then :
16102+
$as_echo "#define HAVE_TIMINGSAFE_BCMP 1" >>confdefs.h
16103+
16104+
else
16105+
case " $LIBOBJS " in
16106+
*" timingsafe_bcmp.$ac_objext "* ) ;;
16107+
*) LIBOBJS="$LIBOBJS timingsafe_bcmp.$ac_objext"
16108+
;;
16109+
esac
16110+
16111+
fi
16112+
1609016113

1609116114

1609216115
ac_fn_c_check_func "$LINENO" "pthread_barrier_wait" "ac_cv_func_pthread_barrier_wait"

configure.ac

+2-1
Original file line numberDiff line numberDiff line change
@@ -1806,7 +1806,7 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [#include <fcntl.h>])
18061806
]) # fi
18071807

18081808
AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
1809-
AC_CHECK_DECLS([strlcat, strlcpy, strnlen, strsep])
1809+
AC_CHECK_DECLS([strlcat, strlcpy, strnlen, strsep, timingsafe_bcmp])
18101810

18111811
# We can't use AC_CHECK_FUNCS to detect these functions, because it
18121812
# won't handle deployment target restrictions on macOS
@@ -1826,6 +1826,7 @@ AC_REPLACE_FUNCS(m4_normalize([
18261826
strlcpy
18271827
strnlen
18281828
strsep
1829+
timingsafe_bcmp
18291830
]))
18301831

18311832
AC_REPLACE_FUNCS(pthread_barrier_wait)

meson.build

+2
Original file line numberDiff line numberDiff line change
@@ -2569,6 +2569,7 @@ decl_checks = [
25692569
['strlcpy', 'string.h'],
25702570
['strnlen', 'string.h'],
25712571
['strsep', 'string.h'],
2572+
['timingsafe_bcmp', 'string.h'],
25722573
]
25732574

25742575
# Need to check for function declarations for these functions, because
@@ -2811,6 +2812,7 @@ func_checks = [
28112812
['strsignal'],
28122813
['sync_file_range'],
28132814
['syncfs'],
2815+
['timingsafe_bcmp'],
28142816
['uselocale'],
28152817
['wcstombs_l'],
28162818
]

src/include/port.h

+4
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,10 @@ extern size_t strnlen(const char *str, size_t maxlen);
464464
extern char *strsep(char **stringp, const char *delim);
465465
#endif
466466

467+
#if !HAVE_DECL_TIMINGSAFE_BCMP
468+
extern int timingsafe_bcmp(const void *b1, const void *b2, size_t len);
469+
#endif
470+
467471
/*
468472
* Callers should use the qsort() macro defined below instead of calling
469473
* pg_qsort() directly.

src/port/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ replace_funcs_neg = [
7373
['strlcpy'],
7474
['strnlen'],
7575
['strsep'],
76+
['timingsafe_bcmp'],
7677
]
7778

7879
if host_system != 'windows'

src/port/timingsafe_bcmp.c

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* src/port/timingsafe_bcmp.c
3+
*
4+
* $OpenBSD: timingsafe_bcmp.c,v 1.3 2015/08/31 02:53:57 guenther Exp $
5+
*/
6+
7+
/*
8+
* Copyright (c) 2010 Damien Miller. All rights reserved.
9+
*
10+
* Permission to use, copy, modify, and distribute this software for any
11+
* purpose with or without fee is hereby granted, provided that the above
12+
* copyright notice and this permission notice appear in all copies.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21+
*/
22+
23+
#include "c.h"
24+
25+
#ifdef USE_SSL
26+
#include <openssl/crypto.h>
27+
#endif
28+
29+
int
30+
timingsafe_bcmp(const void *b1, const void *b2, size_t n)
31+
{
32+
#ifdef USE_SSL
33+
return CRYPTO_memcmp(b1, b2, n);
34+
#else
35+
const unsigned char *p1 = b1,
36+
*p2 = b2;
37+
int ret = 0;
38+
39+
for (; n > 0; n--)
40+
ret |= *p1++ ^ *p2++;
41+
return (ret != 0);
42+
#endif
43+
}

0 commit comments

Comments
 (0)