Make WINDOW_G configurable

This makes WINDOW_G a configurable value in the range of [3..24].
The upper limit of 24 is a defensive choice. The code is probably
correct for values up to 33 but those larger values yield in huge
tables (>= 256MiB), which are i) unlikely to be really beneficial
in practice and ii) increasingly difficult to test.
This commit is contained in:
Tim Ruffing 2019-03-06 13:12:33 +01:00
parent 9c1dda828f
commit a364c95419
2 changed files with 74 additions and 11 deletions

View File

@ -186,6 +186,16 @@ AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto],
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto]
[Specify assembly optimizations to use. Default is auto (experimental: arm)])],[req_asm=$withval], [req_asm=auto])
# Default is window size 16 (or window size 15 with endomorphism) which needs 1.375 MiB. */
AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
[window size for ecmult precomputation for verification, specified as integer in range [3..24].]
[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.]
[The table will store 2^(SIZE-2) * 64 bytes of data but can be larger in memory due]
[to platform-specific padding and alignment. "auto" is a reasonable setting for desktop machines]
[(currently 15 if the endomorphism optimization is disabled and 16 if it is enabled). [default=auto]]
)],
[req_ecmult_window=$withval], [req_ecmult_window=auto])
AC_CHECK_TYPES([__int128])
AC_MSG_CHECKING([for __builtin_expect])
@ -413,6 +423,32 @@ case $set_scalar in
;;
esac
#set ecmult window size
if test x"$req_ecmult_window" = x"auto"; then
if test x"$use_endomorphism" = x"yes"; then
set_ecmult_window=16
else
set_ecmult_window=15
fi
else
set_ecmult_window=$req_ecmult_window
fi
error_window_size=['window size for ecmult precomputation not an integer in range [3..24] or "auto"']
case $set_ecmult_window in
''|*[[!0-9]]*)
# no valid integer
AC_MSG_ERROR($error_window_size)
;;
*)
if test "$set_ecmult_window" -lt 3 -o "$set_ecmult_window" -gt 24 ; then
# not in range
AC_MSG_ERROR($error_window_size)
fi
AC_DEFINE_UNQUOTED(ECMULT_WINDOW_SIZE, $set_ecmult_window, [Set window size for ecmult precomputation])
;;
esac
if test x"$use_tests" = x"yes"; then
SECP_OPENSSL_CHECK
if test x"$has_openssl_ec" = x"yes"; then
@ -623,6 +659,7 @@ echo " asm = $set_asm"
echo " bignum = $set_bignum"
echo " field = $set_field"
echo " scalar = $set_scalar"
echo " ecmult window size = $set_ecmult_window"
echo
echo " CC = $CC"
echo " CFLAGS = $CFLAGS"

View File

@ -31,16 +31,34 @@
# endif
#else
/* optimal for 128-bit and 256-bit exponents. */
#define WINDOW_A 5
/** larger numbers may result in slightly better performance, at the cost of
exponentially larger precomputed tables. */
#ifdef USE_ENDOMORPHISM
/** Two tables for window size 15: 1.375 MiB. */
#define WINDOW_G 15
#else
/** One table for window size 16: 1.375 MiB. */
#define WINDOW_G 16
# define WINDOW_A 5
/** Larger values for ECMULT_WINDOW_SIZE result in possibly better
* performance at the cost of an exponentially larger precomputed
* table. The exact table size is
* (1 << (WINDOW_G - 2)) * sizeof(secp256k1_ge_storage) bytes,
* where sizeof(secp256k1_ge_storage) is typically 64 bytes but can
* be larger due to platform-specific padding and alignment.
*/
# ifdef USE_ENDOMORPHISM
# define WINDOW_G ((ECMULT_WINDOW_SIZE)-1)
# else
# define WINDOW_G (ECMULT_WINDOW_SIZE)
# endif
#endif
/* Noone will ever need more than a window size of 24. The code might
* be correct for larger values of ECMULT_WINDOW_SIZE but this is not
* not tested.
*
* The following limitations are known, and there are probably more:
* If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect
* because the size of the memory object that we allocate (in bytes)
* will not fit in a size_t.
* If WINDOW_G > 31 and int has 32 bits, then the code is incorrect
* because certain expressions will overflow.
* */
#if ECMULT_WINDOW_SIZE < 3 || ECMULT_WINDOW_SIZE > 24
# error Set ECMULT_WINDOW_SIZE to an integer in range [3..24].
#endif
#ifdef USE_ENDOMORPHISM
@ -320,7 +338,12 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void *
/* get the generator */
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
ctx->pre_g = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
{
size_t size = sizeof((*ctx->pre_g)[0]) * ((size_t)ECMULT_TABLE_SIZE(WINDOW_G));
/* check for overflow */
VERIFY_CHECK(size / sizeof((*ctx->pre_g)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
ctx->pre_g = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, size, base, prealloc_size);
}
/* precompute the tables with odd multiples */
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
@ -330,7 +353,10 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void *
secp256k1_gej g_128j;
int i;
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size);
size_t size = sizeof((*ctx->pre_g_128)[0]) * ((size_t) ECMULT_TABLE_SIZE(WINDOW_G));
/* check for overflow */
VERIFY_CHECK(size / sizeof((*ctx->pre_g_128)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)));
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, size, base, prealloc_size);
/* calculate 2^128*generator */
g_128j = gj;