Originally from Niels, with minor changes to avoid compiler warnings.
camellia256-meta.c \
cast128.c cast128-meta.c cbc.c \
ccm.c ccm-aes128.c ccm-aes192.c ccm-aes256.c cfb.c \
+ cnd-memcpy.c \
chacha-crypt.c chacha-core-internal.c \
chacha-poly1305.c chacha-poly1305-meta.c \
chacha-set-key.c chacha-set-nonce.c \
--- /dev/null
+/* cnd-memcpy.c
+
+ Copyright (C) 2018 Niels Möller
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+
+ GNU Nettle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "memops.h"
+
+void
+cnd_memcpy(int cnd, volatile void *dst, const volatile void *src, size_t n)
+{
+ const volatile unsigned char *sp = src;
+ volatile unsigned char *dp = dst;
+ volatile unsigned char c;
+ volatile unsigned char m;
+ size_t i;
+
+ m = -(unsigned char) cnd;
+
+ for (i = 0; i < n; i++)
+ {
+ c = (sp[i] & m);
+ c |= (dp[i] & ~m);
+ dp[i] = c;
+ }
+}
#endif
/* Name mangling */
+#define cnd_memcpy nettle_cnd_memcpy
#define memeql_sec nettle_memeql_sec
int
memeql_sec (const void *a, const void *b, size_t n);
+/* Side-channel silent conditional memcpy. cnd must be 0 (nop) or 1
+ (copy). */
+void
+cnd_memcpy(int cnd, volatile void *dst, const volatile void *src, size_t n);
+
#ifdef __cplusplus
}
#endif
/cfb-test
/chacha-poly1305-test
/chacha-test
+/cnd-memcpy-test
/ctr-test
/curve25519-dh-test
/cxx-test
chacha-test$(EXEEXT): chacha-test.$(OBJEXT)
$(LINK) chacha-test.$(OBJEXT) $(TEST_OBJS) -o chacha-test$(EXEEXT)
+cnd-memcpy-test$(EXEEXT): cnd-memcpy-test.$(OBJEXT)
+ $(LINK) cnd-memcpy-test.$(OBJEXT) $(TEST_OBJS) -o cnd-memcpy-test$(EXEEXT)
+
des-test$(EXEEXT): des-test.$(OBJEXT)
$(LINK) des-test.$(OBJEXT) $(TEST_OBJS) -o des-test$(EXEEXT)
blowfish-test.c cast128-test.c \
base16-test.c base64-test.c \
camellia-test.c chacha-test.c \
+ cnd-memcpy-test.c \
des-test.c des3-test.c des-compat-test.c \
md2-test.c md4-test.c md5-test.c md5-compat-test.c \
memeql-test.c memxor-test.c gosthash94-test.c \
--- /dev/null
+#include "testutils.h"
+#include "knuth-lfib.h"
+#include "memops.h"
+
+#if HAVE_VALGRIND_MEMCHECK_H
+# include <valgrind/memcheck.h>
+static void
+cnd_memcpy_for_test(int cnd, void *dst, const void *src, size_t n)
+{
+ /* Makes valgrind trigger on any branches depending on the input
+ data. */
+ VALGRIND_MAKE_MEM_UNDEFINED (dst, n);
+ VALGRIND_MAKE_MEM_UNDEFINED (src, n);
+ VALGRIND_MAKE_MEM_UNDEFINED (&cnd, sizeof(cnd));
+
+ cnd_memcpy (cnd, dst, src, n);
+ VALGRIND_MAKE_MEM_DEFINED (src, n);
+ VALGRIND_MAKE_MEM_DEFINED (dst, n);
+}
+#else
+#define cnd_memcpy_for_test cnd_memcpy
+#endif
+
+#define MAX_SIZE 50
+void
+test_main(void)
+{
+ uint8_t src[MAX_SIZE];
+ uint8_t dst[MAX_SIZE];
+ uint8_t res[MAX_SIZE];
+ struct knuth_lfib_ctx random_ctx;
+
+ knuth_lfib_init (&random_ctx, 11);
+
+ size_t size;
+ for (size = 1; size < 50; size++)
+ {
+ knuth_lfib_random (&random_ctx, size, src);
+ knuth_lfib_random (&random_ctx, size, dst);
+ memcpy (res, dst, size);
+ cnd_memcpy_for_test (0, res, src, size);
+
+ ASSERT (memcmp (res, dst, size) == 0);
+ cnd_memcpy_for_test (1, res, src, size);
+ ASSERT (memcmp (res, src, size) == 0);
+ }
+}