From 0e1d311168f8c847d66ed03d18f678ac2c767d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> Date: Tue, 14 Nov 2023 19:54:18 +0100 Subject: [PATCH] Add side-channel test for ecdsa-sign-test. --- ChangeLog | 19 +++++++++++++++++++ configure.ac | 9 +++++++++ ecc-internal.h | 8 ++++++++ ecc-mod-arith.c | 12 ++++++------ ecc-mod-inv.c | 10 +++++----- ecc-mod.c | 4 ++-- testsuite/Makefile.in | 3 ++- testsuite/ecdsa-sign-test.c | 10 ++++++++++ testsuite/sc-ecdsa-sign-test | 6 ++++++ 9 files changed, 67 insertions(+), 14 deletions(-) create mode 100755 testsuite/sc-ecdsa-sign-test diff --git a/ChangeLog b/ChangeLog index be68bab2..27655667 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2023-11-14 Niels Möller <nisse@lysator.liu.se> + + Add a first side-channel test for the ECC code. + * configure.ac: New option --enable-extra-asserts. Enables asserts + that are disabled by default, due to conflict with tests of + side-channel silence. + (WITH_EXTRA_ASSERTS): Corresponding new define. + * ecc-internal.h (assert_maybe): Conditionally define this assert + macro, depending on WITH_EXTRA_ASSERTS. + * ecc-mod-arith.c: Convert most asserts to assert_maybe. + * ecc-mod-inv.c (ecc_mod_inv): Likewise. + * ecc-mod.c (ecc_mod): Likewise. + * testsuite/ecdsa-sign-test.c (test_ecdsa): Add calls to + mark_bytes_undefined and mark_bytes_defined. + (test_main): Skip test if both side channel tests and extra + asserts are enabled. + * testsuite/sc-ecdsa-sign-test: New testcase. + * testsuite/Makefile.in (TS_SC): Add sc-ecdsa-sign-test. + 2023-11-12 Niels Möller <nisse@lysator.liu.se> * gmp-glue.h (GMP_LIMB_BITS) [NETTLE_USE_MINI_GMP]: Define as alias for diff --git a/configure.ac b/configure.ac index 867767a6..c0709498 100644 --- a/configure.ac +++ b/configure.ac @@ -116,6 +116,10 @@ AC_ARG_ENABLE(s390x-msa, AS_HELP_STRING([--enable-s390x-msa], [Enable message-security assist extensions on z/Architecture. (default=no)]),, [enable_s390x_msa=no]) +AC_ARG_ENABLE(extra-asserts, + AS_HELP_STRING([--enable-extra-asserts], [Enable additional asserts in ECC code (incompatible side-channel tests)]),, + [enable_extra_asserts=no]) + AC_ARG_ENABLE(mini-gmp, AS_HELP_STRING([--enable-mini-gmp], [Enable mini-gmp, used instead of libgmp.]),, [enable_mini_gmp=no]) @@ -132,6 +136,11 @@ fi AC_SUBST([NETTLE_USE_MINI_GMP]) AC_SUBST([HOGWEED_EXTRA_SYMBOLS]) +AH_TEMPLATE([WITH_EXTRA_ASSERTS], [Defined to enable additional asserts]) +if test "$enable_extra_asserts" = yes ; then + AC_DEFINE(WITH_EXTRA_ASSERTS) +fi + LSH_RPATH_INIT([`echo $with_lib_path | sed 's/:/ /g'` \ `echo $exec_prefix | sed "s@^NONE@$prefix/lib@g" | sed "s@^NONE@$ac_default_prefix/lib@g"` \ /usr/local/lib /sw/local/lib /sw/lib \ diff --git a/ecc-internal.h b/ecc-internal.h index 53359b57..17c51c31 100644 --- a/ecc-internal.h +++ b/ecc-internal.h @@ -85,6 +85,14 @@ #define curve25519_eh_to_x _nettle_curve25519_eh_to_x #define curve448_eh_to_x _nettle_curve448_eh_to_x +/* For asserts that are incompatible with sc tests. Currently used + only by ECC code. */ +#if WITH_EXTRA_ASSERTS +#define assert_maybe(x) assert(x) +#else +#define assert_maybe(x) +#endif + extern const struct ecc_curve _nettle_secp_192r1; extern const struct ecc_curve _nettle_secp_224r1; extern const struct ecc_curve _nettle_secp_256r1; diff --git a/ecc-mod-arith.c b/ecc-mod-arith.c index 3b9bcb47..2c39a816 100644 --- a/ecc-mod-arith.c +++ b/ecc-mod-arith.c @@ -76,7 +76,7 @@ ecc_mod_add (const struct ecc_modulo *m, mp_limb_t *rp, cy = mpn_add_n (rp, ap, bp, m->size); cy = mpn_cnd_add_n (cy, rp, rp, m->B, m->size); cy = mpn_cnd_add_n (cy, rp, rp, m->B, m->size); - assert (cy == 0); + assert_maybe (cy == 0); } void @@ -100,7 +100,7 @@ ecc_mod_sub (const struct ecc_modulo *m, mp_limb_t *rp, */ cy = mpn_cnd_sub_n (cy, rp, rp, m->Bm2m, m->size); cy = mpn_cnd_sub_n (cy, rp, rp, m->B, m->size); - assert (cy == 0); + assert_maybe (cy == 0); } void @@ -112,10 +112,10 @@ ecc_mod_mul_1 (const struct ecc_modulo *m, mp_limb_t *rp, assert (b <= 0xffffffff); hi = mpn_mul_1 (rp, ap, m->size, b); hi = mpn_addmul_1 (rp, m->B, m->size, hi); - assert (hi <= 1); + assert_maybe (hi <= 1); hi = mpn_cnd_add_n (hi, rp, rp, m->B, m->size); /* Sufficient if b < B^size / p */ - assert (hi == 0); + assert_maybe (hi == 0); } void @@ -142,10 +142,10 @@ ecc_mod_submul_1 (const struct ecc_modulo *m, mp_limb_t *rp, assert (b <= 0xffffffff); hi = mpn_submul_1 (rp, ap, m->size, b); hi = mpn_submul_1 (rp, m->B, m->size, hi); - assert (hi <= 1); + assert_maybe (hi <= 1); hi = mpn_cnd_sub_n (hi, rp, rp, m->B, m->size); /* Sufficient roughly if b < B^size / p */ - assert (hi == 0); + assert_maybe (hi == 0); } void diff --git a/ecc-mod-inv.c b/ecc-mod-inv.c index 254fb697..5d1f8475 100644 --- a/ecc-mod-inv.c +++ b/ecc-mod-inv.c @@ -135,7 +135,7 @@ ecc_mod_inv (const struct ecc_modulo *m, also v = orig_a^{-1} (mod m) */ - assert (bp[0] & 1); + assert_maybe (bp[0] & 1); odd = ap[0] & 1; swap = mpn_cnd_sub_n (odd, ap, ap, bp, n); @@ -145,15 +145,15 @@ ecc_mod_inv (const struct ecc_modulo *m, mpn_cnd_swap (swap, up, vp, n); cy = mpn_cnd_sub_n (odd, up, up, vp, n); cy -= mpn_cnd_add_n (cy, up, up, m->m, n); - assert (cy == 0); + assert_maybe (cy == 0); cy = mpn_rshift (ap, ap, n, 1); - assert (cy == 0); + assert_maybe (cy == 0); cy = mpn_rshift (up, up, n, 1); cy = mpn_cnd_add_n (cy, up, up, m->mp1h, n); - assert (cy == 0); + assert_maybe (cy == 0); } - assert ( (ap[0] | ap[n-1]) == 0); + assert_maybe ( (ap[0] | ap[n-1]) == 0); #undef ap #undef bp #undef up diff --git a/ecc-mod.c b/ecc-mod.c index 7532d1ec..74314b8d 100644 --- a/ecc-mod.c +++ b/ecc-mod.c @@ -82,7 +82,7 @@ ecc_mod (const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp) hi = mpn_add_n (xp + rn - sn, xp + rn - sn, xp + rn, sn); hi = mpn_cnd_add_n (hi, xp + rn - mn, xp + rn - mn, m->B, mn); - assert (hi == 0); + assert_maybe (hi == 0); } } @@ -111,6 +111,6 @@ ecc_mod (const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp) else { hi = mpn_cnd_add_n (hi, rp, xp, m->B, mn); - assert (hi == 0); + assert_maybe (hi == 0); } } diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 0cb896ff..fb2b4031 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -67,7 +67,8 @@ TS_C = $(TS_NETTLE) @IF_HOGWEED@ $(TS_HOGWEED) TS_CXX = @IF_CXX@ $(CXX_SOURCES:.cxx=$(EXEEXT)) TARGETS = $(TS_C) $(TS_CXX) TS_SC = sc-cnd-memcpy-test sc-gcm-test sc-memeql-test \ - @IF_HOGWEED@ sc-pkcs1-sec-decrypt-test sc-rsa-sec-decrypt-test + @IF_HOGWEED@ sc-pkcs1-sec-decrypt-test sc-rsa-sec-decrypt-test sc-ecdsa-sign-test + TS_SH = symbols-test @IF_VALGRIND@ $(TS_SC) TS_ALL = $(TARGETS) $(TS_SH) @IF_DLOPEN_TEST@ dlopen-test$(EXEEXT) diff --git a/testsuite/ecdsa-sign-test.c b/testsuite/ecdsa-sign-test.c index b8a100b6..a3c43568 100644 --- a/testsuite/ecdsa-sign-test.c +++ b/testsuite/ecdsa-sign-test.c @@ -28,9 +28,15 @@ test_ecdsa (const struct ecc_curve *ecc, mpz_limbs_copy (zp, z, ecc->p.size); mpz_limbs_copy (kp, k, ecc->p.size); + mark_bytes_undefined (sizeof(mp_limb_t) * ecc->p.size, zp); + mark_bytes_undefined (sizeof(mp_limb_t) * ecc->p.size, kp); + ecc_ecdsa_sign (ecc, zp, kp, h->length, h->data, rp, sp, scratch); + mark_bytes_defined (sizeof(mp_limb_t) * ecc->p.size, rp); + mark_bytes_defined (sizeof(mp_limb_t) * ecc->p.size, sp); + mpz_set_str (ref.r, r, 16); mpz_set_str (ref.s, s, 16); @@ -64,6 +70,10 @@ test_ecdsa (const struct ecc_curve *ecc, void test_main (void) { +#if WITH_EXTRA_ASSERTS + if (test_side_channel) + SKIP(); +#endif /* Producing the signature for corresponding test in ecdsa-verify-test.c, with special u1 and u2. */ test_ecdsa (&_nettle_secp_224r1, diff --git a/testsuite/sc-ecdsa-sign-test b/testsuite/sc-ecdsa-sign-test new file mode 100755 index 00000000..c1fbf0e2 --- /dev/null +++ b/testsuite/sc-ecdsa-sign-test @@ -0,0 +1,6 @@ +#! /bin/sh + +srcdir=`dirname $0` +. "${srcdir}/sc-valgrind.sh" + +with_valgrind ./ecdsa-sign-test -- GitLab