Skip to content

Commit 09be391

Browse files
hlinnakaJelteF
andcommitted
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 <github-tech@jeltef.nl> Discussion: https://www.postgresql.org/message-id/7b86da3b-9356-4e50-aa1b-56570825e234@iki.fi
1 parent 85d799b commit 09be391

File tree

6 files changed

+75
-1
lines changed

6 files changed

+75
-1
lines changed

configure

Lines changed: 23 additions & 0 deletions
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
@@ -16099,6 +16109,19 @@ esac
1609916109

1610016110
fi
1610116111

16112+
ac_fn_c_check_func "$LINENO" "timingsafe_bcmp" "ac_cv_func_timingsafe_bcmp"
16113+
if test "x$ac_cv_func_timingsafe_bcmp" = xyes; then :
16114+
$as_echo "#define HAVE_TIMINGSAFE_BCMP 1" >>confdefs.h
16115+
16116+
else
16117+
case " $LIBOBJS " in
16118+
*" timingsafe_bcmp.$ac_objext "* ) ;;
16119+
*) LIBOBJS="$LIBOBJS timingsafe_bcmp.$ac_objext"
16120+
;;
16121+
esac
16122+
16123+
fi
16124+
1610216125

1610316126

1610416127
ac_fn_c_check_func "$LINENO" "pthread_barrier_wait" "ac_cv_func_pthread_barrier_wait"

configure.ac

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1805,7 +1805,7 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [#include <fcntl.h>])
18051805
]) # fi
18061806

18071807
AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
1808-
AC_CHECK_DECLS([strlcat, strlcpy, strnlen, strsep])
1808+
AC_CHECK_DECLS([strlcat, strlcpy, strnlen, strsep, timingsafe_bcmp])
18091809

18101810
# We can't use AC_CHECK_FUNCS to detect these functions, because it
18111811
# 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

Lines changed: 2 additions & 0 deletions
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
@@ -2826,6 +2827,7 @@ func_checks = [
28262827
['strsignal'],
28272828
['sync_file_range'],
28282829
['syncfs'],
2830+
['timingsafe_bcmp'],
28292831
['uselocale'],
28302832
['wcstombs_l'],
28312833
]

src/include/port.h

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 43 additions & 0 deletions
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)