diff options
author | Jerome Forissier <jerome.forissier@linaro.org> | 2019-02-08 17:30:26 +0100 |
---|---|---|
committer | Jérôme Forissier <jerome.forissier@linaro.org> | 2019-02-25 14:23:58 +0100 |
commit | b7da54b3f039908dacf92a4719b9206ffc5644d3 (patch) | |
tree | b02a81dc7bafb3ed152e8b7c538f6e79a31be040 /lib | |
parent | ea81076f7896de7278dcd62b47b99d5dc3351caf (diff) |
libutils: Import isc_tsmemcmp() from NTP as consttime_memcmp()
This patch imports a constant-time byte sequence comparison function
from the NTP source tree [1]. Contrary to our buf_compare_ct() function,
which has only two possible outcomes (zero or non-zero), the new function
is a direct replacement for memcmp() because it returns three possible
states (< 0, 0, > 0).
Link: [1] http://bk.ntp.org/ntp-stable/lib/isc/tsmemcmp.c
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Suggested-by: Jens Wiklander <jens.wiklander@linaro.org>
Reviewed-by: Joakim Bech <joakim.bech@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libutils/ext/consttime_memcmp.c | 51 | ||||
-rw-r--r-- | lib/libutils/ext/include/string_ext.h | 7 | ||||
-rw-r--r-- | lib/libutils/ext/sub.mk | 1 |
3 files changed, 59 insertions, 0 deletions
diff --git a/lib/libutils/ext/consttime_memcmp.c b/lib/libutils/ext/consttime_memcmp.c new file mode 100644 index 00000000..d0bba7ef --- /dev/null +++ b/lib/libutils/ext/consttime_memcmp.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2019 Linaro Limited + * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 <limits.h> +#include <string_ext.h> + +/* Making a portable memcmp that has no internal branches and loops always + * once for every byte without early-out shortcut has a few challenges. + * + * Inspired by 'timingsafe_memcmp()' from the BSD system and + * https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/string/timingsafe_memcmp.c + * + * Sadly, that one is not portable C: It makes assumptions on the representation + * of negative integers and assumes sign-preserving right-shift of negative + * signed values. This is a rewrite from scratch that should not suffer from + * such issues. + * + * 2015-12-12, J. Perlinger (perlinger-at-ntp-dot-org) + */ +int consttime_memcmp(const void *p1, const void *p2, size_t nb) { + const unsigned char *ucp1 = p1; + const unsigned char *ucp2 = p2; + unsigned int isLT = 0u; + unsigned int isGT = 0u; + volatile unsigned int mask = (1u << CHAR_BIT); + + for (/*NOP*/; 0 != nb; --nb, ++ucp1, ++ucp2) { + isLT |= mask & + ((unsigned int)*ucp1 - (unsigned int)*ucp2); + isGT |= mask & + ((unsigned int)*ucp2 - (unsigned int)*ucp1); + mask &= ~(isLT | isGT); + } + return (int)(isGT >> CHAR_BIT) - (int)(isLT >> CHAR_BIT); +} diff --git a/lib/libutils/ext/include/string_ext.h b/lib/libutils/ext/include/string_ext.h index 9358f38e..81901e27 100644 --- a/lib/libutils/ext/include/string_ext.h +++ b/lib/libutils/ext/include/string_ext.h @@ -31,6 +31,13 @@ size_t strlcat(char *dst, const char *src, size_t size); */ int buf_compare_ct(const void *s1, const void *s2, size_t n); +/* + * A constant-time version of memcmp(). Might be slightly slower than + * buf_compare_ct(), but complies with the memcmp() specification which + * requires three possible outcomes for the comparison (< 0, 0 and > 0). + */ +int consttime_memcmp(const void *p1, const void *p2, size_t nb); + /* Variant of strdup() that uses nex_malloc() instead of malloc() */ char *nex_strdup(const char *s); diff --git a/lib/libutils/ext/sub.mk b/lib/libutils/ext/sub.mk index 5e3cb6aa..7d568925 100644 --- a/lib/libutils/ext/sub.mk +++ b/lib/libutils/ext/sub.mk @@ -7,5 +7,6 @@ srcs-y += buf_compare_ct.c srcs-y += trace.c srcs-y += mempool.c srcs-y += nex_strdup.c +srcs-y += consttime_memcmp.c subdirs-$(arch_arm) += arch/$(ARCH) |