Merge pull request #53 from romanz/zkp-trezor
Changes necessary for usage on Trezor
This commit is contained in:
commit
1c830b4c9a
@ -8,6 +8,7 @@ else
|
|||||||
JNI_LIB =
|
JNI_LIB =
|
||||||
endif
|
endif
|
||||||
include_HEADERS = include/secp256k1.h
|
include_HEADERS = include/secp256k1.h
|
||||||
|
include_HEADERS += include/secp256k1_preallocated.h
|
||||||
noinst_HEADERS =
|
noinst_HEADERS =
|
||||||
noinst_HEADERS += src/scalar.h
|
noinst_HEADERS += src/scalar.h
|
||||||
noinst_HEADERS += src/scalar_4x64.h
|
noinst_HEADERS += src/scalar_4x64.h
|
||||||
|
116
configure.ac
116
configure.ac
@ -85,42 +85,42 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])],
|
|||||||
])
|
])
|
||||||
|
|
||||||
AC_ARG_ENABLE(benchmark,
|
AC_ARG_ENABLE(benchmark,
|
||||||
AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is yes)]),
|
AS_HELP_STRING([--enable-benchmark],[compile benchmark [default=yes]]),
|
||||||
[use_benchmark=$enableval],
|
[use_benchmark=$enableval],
|
||||||
[use_benchmark=yes])
|
[use_benchmark=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE(coverage,
|
AC_ARG_ENABLE(coverage,
|
||||||
AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]),
|
AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis [default=no]]),
|
||||||
[enable_coverage=$enableval],
|
[enable_coverage=$enableval],
|
||||||
[enable_coverage=no])
|
[enable_coverage=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(tests,
|
AC_ARG_ENABLE(tests,
|
||||||
AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]),
|
AS_HELP_STRING([--enable-tests],[compile tests [default=yes]]),
|
||||||
[use_tests=$enableval],
|
[use_tests=$enableval],
|
||||||
[use_tests=yes])
|
[use_tests=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE(openssl_tests,
|
AC_ARG_ENABLE(openssl_tests,
|
||||||
AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests, if OpenSSL is available (default is auto)]),
|
AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests [default=auto]]),
|
||||||
[enable_openssl_tests=$enableval],
|
[enable_openssl_tests=$enableval],
|
||||||
[enable_openssl_tests=auto])
|
[enable_openssl_tests=auto])
|
||||||
|
|
||||||
AC_ARG_ENABLE(experimental,
|
AC_ARG_ENABLE(experimental,
|
||||||
AS_HELP_STRING([--enable-experimental],[allow experimental configure options (default is no)]),
|
AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]),
|
||||||
[use_experimental=$enableval],
|
[use_experimental=$enableval],
|
||||||
[use_experimental=no])
|
[use_experimental=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(exhaustive_tests,
|
AC_ARG_ENABLE(exhaustive_tests,
|
||||||
AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]),
|
AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests [default=yes]]),
|
||||||
[use_exhaustive_tests=$enableval],
|
[use_exhaustive_tests=$enableval],
|
||||||
[use_exhaustive_tests=yes])
|
[use_exhaustive_tests=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE(endomorphism,
|
AC_ARG_ENABLE(endomorphism,
|
||||||
AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]),
|
AS_HELP_STRING([--enable-endomorphism],[enable endomorphism [default=no]]),
|
||||||
[use_endomorphism=$enableval],
|
[use_endomorphism=$enableval],
|
||||||
[use_endomorphism=no])
|
[use_endomorphism=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(ecmult_static_precomputation,
|
AC_ARG_ENABLE(ecmult_static_precomputation,
|
||||||
AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is yes)]),
|
AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing [default=auto]]),
|
||||||
[use_ecmult_static_precomputation=$enableval],
|
[use_ecmult_static_precomputation=$enableval],
|
||||||
[use_ecmult_static_precomputation=auto])
|
[use_ecmult_static_precomputation=auto])
|
||||||
|
|
||||||
@ -140,46 +140,61 @@ AC_ARG_ENABLE(module_musig,
|
|||||||
[enable_module_musig=no])
|
[enable_module_musig=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(module_recovery,
|
AC_ARG_ENABLE(module_recovery,
|
||||||
AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]),
|
AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]),
|
||||||
[enable_module_recovery=$enableval],
|
[enable_module_recovery=$enableval],
|
||||||
[enable_module_recovery=no])
|
[enable_module_recovery=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(module_generator,
|
AC_ARG_ENABLE(module_generator,
|
||||||
AS_HELP_STRING([--enable-module-generator],[enable NUMS generator module (default is no)]),
|
AS_HELP_STRING([--enable-module-generator],[enable NUMS generator module [default=no]]),
|
||||||
[enable_module_generator=$enableval],
|
[enable_module_generator=$enableval],
|
||||||
[enable_module_generator=no])
|
[enable_module_generator=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(module_rangeproof,
|
AC_ARG_ENABLE(module_rangeproof,
|
||||||
AS_HELP_STRING([--enable-module-rangeproof],[enable Pedersen / zero-knowledge range proofs module (default is no)]),
|
AS_HELP_STRING([--enable-module-rangeproof],[enable Pedersen / zero-knowledge range proofs module [default=no]]),
|
||||||
[enable_module_rangeproof=$enableval],
|
[enable_module_rangeproof=$enableval],
|
||||||
[enable_module_rangeproof=no])
|
[enable_module_rangeproof=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(module_whitelist,
|
AC_ARG_ENABLE(module_whitelist,
|
||||||
AS_HELP_STRING([--enable-module-whitelist],[enable key whitelisting module (default is no)]),
|
AS_HELP_STRING([--enable-module-whitelist],[enable key whitelisting module [default=no]]),
|
||||||
[enable_module_whitelist=$enableval],
|
[enable_module_whitelist=$enableval],
|
||||||
[enable_module_whitelist=no])
|
[enable_module_whitelist=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(external_default_callbacks,
|
||||||
|
AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]),
|
||||||
|
[use_external_default_callbacks=$enableval],
|
||||||
|
[use_external_default_callbacks=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(jni,
|
AC_ARG_ENABLE(jni,
|
||||||
AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is no)]),
|
AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni [default=no]]),
|
||||||
[use_jni=$enableval],
|
[use_jni=$enableval],
|
||||||
[use_jni=no])
|
[use_jni=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(module_surjectionproof,
|
AC_ARG_ENABLE(module_surjectionproof,
|
||||||
AS_HELP_STRING([--enable-module-surjectionproof],[enable surjection proof module (default is no)]),
|
AS_HELP_STRING([--enable-module-surjectionproof],[enable surjection proof module [default=no]]),
|
||||||
[enable_module_surjectionproof=$enableval],
|
[enable_module_surjectionproof=$enableval],
|
||||||
[enable_module_surjectionproof=no])
|
[enable_module_surjectionproof=no])
|
||||||
|
|
||||||
AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto],
|
AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto],
|
||||||
[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto])
|
[finite field implementation to use [default=auto]])],[req_field=$withval], [req_field=auto])
|
||||||
|
|
||||||
AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto],
|
AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto],
|
||||||
[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto])
|
[bignum implementation to use [default=auto]])],[req_bignum=$withval], [req_bignum=auto])
|
||||||
|
|
||||||
AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto],
|
AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto],
|
||||||
[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto])
|
[scalar implementation to use [default=auto]])],[req_scalar=$withval], [req_scalar=auto])
|
||||||
|
|
||||||
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|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])
|
[assembly optimizations to use (experimental: arm) [default=auto]])],[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_CHECK_TYPES([__int128])
|
||||||
|
|
||||||
@ -408,6 +423,32 @@ case $set_scalar in
|
|||||||
;;
|
;;
|
||||||
esac
|
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
|
if test x"$use_tests" = x"yes"; then
|
||||||
SECP_OPENSSL_CHECK
|
SECP_OPENSSL_CHECK
|
||||||
if test x"$has_openssl_ec" = x"yes"; then
|
if test x"$has_openssl_ec" = x"yes"; then
|
||||||
@ -507,17 +548,9 @@ if test x"$use_external_asm" = x"yes"; then
|
|||||||
AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used])
|
AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_MSG_NOTICE([Using static precomputation: $set_precomp])
|
if test x"$use_external_default_callbacks" = x"yes"; then
|
||||||
AC_MSG_NOTICE([Using assembly optimizations: $set_asm])
|
AC_DEFINE(USE_EXTERNAL_DEFAULT_CALLBACKS, 1, [Define this symbol if an external implementation of the default callbacks is used])
|
||||||
AC_MSG_NOTICE([Using field implementation: $set_field])
|
fi
|
||||||
AC_MSG_NOTICE([Using bignum implementation: $set_bignum])
|
|
||||||
AC_MSG_NOTICE([Using scalar implementation: $set_scalar])
|
|
||||||
AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism])
|
|
||||||
AC_MSG_NOTICE([Building benchmarks: $use_benchmark])
|
|
||||||
AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage])
|
|
||||||
AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
|
|
||||||
AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery])
|
|
||||||
AC_MSG_NOTICE([Using jni: $use_jni])
|
|
||||||
|
|
||||||
if test x"$enable_experimental" = x"yes"; then
|
if test x"$enable_experimental" = x"yes"; then
|
||||||
AC_MSG_NOTICE([******])
|
AC_MSG_NOTICE([******])
|
||||||
@ -610,3 +643,26 @@ unset PKG_CONFIG_PATH
|
|||||||
PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP"
|
PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP"
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Build Options:"
|
||||||
|
echo " with endomorphism = $use_endomorphism"
|
||||||
|
echo " with ecmult precomp = $set_precomp"
|
||||||
|
echo " with external callbacks = $use_external_default_callbacks"
|
||||||
|
echo " with jni = $use_jni"
|
||||||
|
echo " with benchmarks = $use_benchmark"
|
||||||
|
echo " with coverage = $enable_coverage"
|
||||||
|
echo " module ecdh = $enable_module_ecdh"
|
||||||
|
echo " module recovery = $enable_module_recovery"
|
||||||
|
echo
|
||||||
|
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"
|
||||||
|
echo " CPPFLAGS = $CPPFLAGS"
|
||||||
|
echo " LDFLAGS = $LDFLAGS"
|
||||||
|
echo
|
||||||
|
@ -33,9 +33,10 @@ extern "C" {
|
|||||||
* verification).
|
* verification).
|
||||||
*
|
*
|
||||||
* A constructed context can safely be used from multiple threads
|
* A constructed context can safely be used from multiple threads
|
||||||
* simultaneously, but API call that take a non-const pointer to a context
|
* simultaneously, but API calls that take a non-const pointer to a context
|
||||||
* need exclusive access to it. In particular this is the case for
|
* need exclusive access to it. In particular this is the case for
|
||||||
* secp256k1_context_destroy and secp256k1_context_randomize.
|
* secp256k1_context_destroy, secp256k1_context_preallocated_destroy,
|
||||||
|
* and secp256k1_context_randomize.
|
||||||
*
|
*
|
||||||
* Regarding randomization, either do it once at creation time (in which case
|
* Regarding randomization, either do it once at creation time (in which case
|
||||||
* you do not need any locking for the other calls), or use a read-write lock.
|
* you do not need any locking for the other calls), or use a read-write lock.
|
||||||
@ -163,7 +164,8 @@ typedef int (*secp256k1_nonce_function)(
|
|||||||
#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9)
|
#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9)
|
||||||
#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8)
|
#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8)
|
||||||
|
|
||||||
/** Flags to pass to secp256k1_context_create. */
|
/** Flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and
|
||||||
|
* secp256k1_context_preallocated_create. */
|
||||||
#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
|
#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
|
||||||
#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
|
#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
|
||||||
#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
|
#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
|
||||||
@ -186,7 +188,11 @@ typedef int (*secp256k1_nonce_function)(
|
|||||||
*/
|
*/
|
||||||
SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp;
|
SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp;
|
||||||
|
|
||||||
/** Create a secp256k1 context object.
|
/** Create a secp256k1 context object (in dynamically allocated memory).
|
||||||
|
*
|
||||||
|
* This function uses malloc to allocate memory. It is guaranteed that malloc is
|
||||||
|
* called at most once for every call of this function. If you need to avoid dynamic
|
||||||
|
* memory allocation entirely, see the functions in secp256k1_preallocated.h.
|
||||||
*
|
*
|
||||||
* Returns: a newly created context object.
|
* Returns: a newly created context object.
|
||||||
* In: flags: which parts of the context to initialize.
|
* In: flags: which parts of the context to initialize.
|
||||||
@ -197,7 +203,11 @@ SECP256K1_API secp256k1_context* secp256k1_context_create(
|
|||||||
unsigned int flags
|
unsigned int flags
|
||||||
) SECP256K1_WARN_UNUSED_RESULT;
|
) SECP256K1_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/** Copies a secp256k1 context object.
|
/** Copy a secp256k1 context object (into dynamically allocated memory).
|
||||||
|
*
|
||||||
|
* This function uses malloc to allocate memory. It is guaranteed that malloc is
|
||||||
|
* called at most once for every call of this function. If you need to avoid dynamic
|
||||||
|
* memory allocation entirely, see the functions in secp256k1_preallocated.h.
|
||||||
*
|
*
|
||||||
* Returns: a newly created context object.
|
* Returns: a newly created context object.
|
||||||
* Args: ctx: an existing context to copy (cannot be NULL)
|
* Args: ctx: an existing context to copy (cannot be NULL)
|
||||||
@ -206,10 +216,18 @@ SECP256K1_API secp256k1_context* secp256k1_context_clone(
|
|||||||
const secp256k1_context* ctx
|
const secp256k1_context* ctx
|
||||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/** Destroy a secp256k1 context object.
|
/** Destroy a secp256k1 context object (created in dynamically allocated memory).
|
||||||
*
|
*
|
||||||
* The context pointer may not be used afterwards.
|
* The context pointer may not be used afterwards.
|
||||||
* Args: ctx: an existing context to destroy (cannot be NULL)
|
*
|
||||||
|
* The context to destroy must have been created using secp256k1_context_create
|
||||||
|
* or secp256k1_context_clone. If the context has instead been created using
|
||||||
|
* secp256k1_context_preallocated_create or secp256k1_context_preallocated_clone, the
|
||||||
|
* behaviour is undefined. In that case, secp256k1_context_preallocated_destroy must
|
||||||
|
* be used instead.
|
||||||
|
*
|
||||||
|
* Args: ctx: an existing context to destroy, constructed using
|
||||||
|
* secp256k1_context_create or secp256k1_context_clone
|
||||||
*/
|
*/
|
||||||
SECP256K1_API void secp256k1_context_destroy(
|
SECP256K1_API void secp256k1_context_destroy(
|
||||||
secp256k1_context* ctx
|
secp256k1_context* ctx
|
||||||
@ -229,11 +247,28 @@ SECP256K1_API void secp256k1_context_destroy(
|
|||||||
* to cause a crash, though its return value and output arguments are
|
* to cause a crash, though its return value and output arguments are
|
||||||
* undefined.
|
* undefined.
|
||||||
*
|
*
|
||||||
|
* When this function has not been called (or called with fn=NULL), then the
|
||||||
|
* default handler will be used. The library provides a default handler which
|
||||||
|
* writes the message to stderr and calls abort. This default handler can be
|
||||||
|
* replaced at link time if the preprocessor macro
|
||||||
|
* USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build
|
||||||
|
* has been configured with --enable-external-default-callbacks. Then the
|
||||||
|
* following two symbols must be provided to link against:
|
||||||
|
* - void secp256k1_default_illegal_callback_fn(const char* message, void* data);
|
||||||
|
* - void secp256k1_default_error_callback_fn(const char* message, void* data);
|
||||||
|
* The library can call these default handlers even before a proper callback data
|
||||||
|
* pointer could have been using secp256k1_context_set_illegal_callback or
|
||||||
|
* secp256k1_context_set_illegal_callback, e.g., when the creation of a context
|
||||||
|
* fails. In this case, the corresponding default handler will be called with
|
||||||
|
* the data pointer argument set to NULL.
|
||||||
|
*
|
||||||
* Args: ctx: an existing context object (cannot be NULL)
|
* Args: ctx: an existing context object (cannot be NULL)
|
||||||
* In: fun: a pointer to a function to call when an illegal argument is
|
* In: fun: a pointer to a function to call when an illegal argument is
|
||||||
* passed to the API, taking a message and an opaque pointer
|
* passed to the API, taking a message and an opaque pointer.
|
||||||
* (NULL restores a default handler that calls abort).
|
* (NULL restores the default handler.)
|
||||||
* data: the opaque pointer to pass to fun above.
|
* data: the opaque pointer to pass to fun above.
|
||||||
|
*
|
||||||
|
* See also secp256k1_context_set_error_callback.
|
||||||
*/
|
*/
|
||||||
SECP256K1_API void secp256k1_context_set_illegal_callback(
|
SECP256K1_API void secp256k1_context_set_illegal_callback(
|
||||||
secp256k1_context* ctx,
|
secp256k1_context* ctx,
|
||||||
@ -253,9 +288,12 @@ SECP256K1_API void secp256k1_context_set_illegal_callback(
|
|||||||
*
|
*
|
||||||
* Args: ctx: an existing context object (cannot be NULL)
|
* Args: ctx: an existing context object (cannot be NULL)
|
||||||
* In: fun: a pointer to a function to call when an internal error occurs,
|
* In: fun: a pointer to a function to call when an internal error occurs,
|
||||||
* taking a message and an opaque pointer (NULL restores a default
|
* taking a message and an opaque pointer (NULL restores the
|
||||||
* handler that calls abort).
|
* default handler, see secp256k1_context_set_illegal_callback
|
||||||
|
* for details).
|
||||||
* data: the opaque pointer to pass to fun above.
|
* data: the opaque pointer to pass to fun above.
|
||||||
|
*
|
||||||
|
* See also secp256k1_context_set_illegal_callback.
|
||||||
*/
|
*/
|
||||||
SECP256K1_API void secp256k1_context_set_error_callback(
|
SECP256K1_API void secp256k1_context_set_error_callback(
|
||||||
secp256k1_context* ctx,
|
secp256k1_context* ctx,
|
||||||
@ -615,7 +653,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
|
|||||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||||
|
|
||||||
/** Updates the context randomization to protect against side-channel leakage.
|
/** Updates the context randomization to protect against side-channel leakage.
|
||||||
* Returns: 1: randomization successfully updated
|
* Returns: 1: randomization successfully updated or nothing to randomize
|
||||||
* 0: error
|
* 0: error
|
||||||
* Args: ctx: pointer to a context object (cannot be NULL)
|
* Args: ctx: pointer to a context object (cannot be NULL)
|
||||||
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
|
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
|
||||||
@ -630,8 +668,14 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
|
|||||||
* that it does not affect function results, but shields against attacks which
|
* that it does not affect function results, but shields against attacks which
|
||||||
* rely on any input-dependent behaviour.
|
* rely on any input-dependent behaviour.
|
||||||
*
|
*
|
||||||
|
* This function has currently an effect only on contexts initialized for signing
|
||||||
|
* because randomization is currently used only for signing. However, this is not
|
||||||
|
* guaranteed and may change in the future. It is safe to call this function on
|
||||||
|
* contexts not initialized for signing; then it will have no effect and return 1.
|
||||||
|
*
|
||||||
* You should call this after secp256k1_context_create or
|
* You should call this after secp256k1_context_create or
|
||||||
* secp256k1_context_clone, and may call this repeatedly afterwards.
|
* secp256k1_context_clone (and secp256k1_context_preallocated_create or
|
||||||
|
* secp256k1_context_clone, resp.), and you may call this repeatedly afterwards.
|
||||||
*/
|
*/
|
||||||
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
|
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
|
||||||
secp256k1_context* ctx,
|
secp256k1_context* ctx,
|
||||||
|
128
include/secp256k1_preallocated.h
Normal file
128
include/secp256k1_preallocated.h
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#ifndef SECP256K1_PREALLOCATED_H
|
||||||
|
#define SECP256K1_PREALLOCATED_H
|
||||||
|
|
||||||
|
#include "secp256k1.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The module provided by this header file is intended for settings in which it
|
||||||
|
* is not possible or desirable to rely on dynamic memory allocation. It provides
|
||||||
|
* functions for creating, cloning, and destroying secp256k1 context objects in a
|
||||||
|
* contiguous fixed-size block of memory provided by the caller.
|
||||||
|
*
|
||||||
|
* Context objects created by functions in this module can be used like contexts
|
||||||
|
* objects created by functions in secp256k1.h, i.e., they can be passed to any
|
||||||
|
* API function that excepts a context object (see secp256k1.h for details). The
|
||||||
|
* only exception is that context objects created by functions in this module
|
||||||
|
* must be destroyed using secp256k1_context_preallocated_destroy (in this
|
||||||
|
* module) instead of secp256k1_context_destroy (in secp256k1.h).
|
||||||
|
*
|
||||||
|
* It is guaranteed that functions in by this module will not call malloc or its
|
||||||
|
* friends realloc, calloc, and free.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Determine the memory size of a secp256k1 context object to be created in
|
||||||
|
* caller-provided memory.
|
||||||
|
*
|
||||||
|
* The purpose of this function is to determine how much memory must be provided
|
||||||
|
* to secp256k1_context_preallocated_create.
|
||||||
|
*
|
||||||
|
* Returns: the required size of the caller-provided memory block
|
||||||
|
* In: flags: which parts of the context to initialize.
|
||||||
|
*/
|
||||||
|
SECP256K1_API size_t secp256k1_context_preallocated_size(
|
||||||
|
unsigned int flags
|
||||||
|
) SECP256K1_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
/** Create a secp256k1 context object in caller-provided memory.
|
||||||
|
*
|
||||||
|
* The caller must provide a pointer to a rewritable contiguous block of memory
|
||||||
|
* of size at least secp256k1_context_preallocated_size(flags) bytes, suitably
|
||||||
|
* aligned to hold an object of any type.
|
||||||
|
*
|
||||||
|
* The block of memory is exclusively owned by the created context object during
|
||||||
|
* the lifetime of this context object, which begins with the call to this
|
||||||
|
* function and ends when a call to secp256k1_context_preallocated_destroy
|
||||||
|
* (which destroys the context object again) returns. During the lifetime of the
|
||||||
|
* context object, the caller is obligated not to access this block of memory,
|
||||||
|
* i.e., the caller may not read or write the memory, e.g., by copying the memory
|
||||||
|
* contents to a different location or trying to create a second context object
|
||||||
|
* in the memory. In simpler words, the prealloc pointer (or any pointer derived
|
||||||
|
* from it) should not be used during the lifetime of the context object.
|
||||||
|
*
|
||||||
|
* Returns: a newly created context object.
|
||||||
|
* In: prealloc: a pointer to a rewritable contiguous block of memory of
|
||||||
|
* size at least secp256k1_context_preallocated_size(flags)
|
||||||
|
* bytes, as detailed above (cannot be NULL)
|
||||||
|
* flags: which parts of the context to initialize.
|
||||||
|
*
|
||||||
|
* See also secp256k1_context_randomize (in secp256k1.h)
|
||||||
|
* and secp256k1_context_preallocated_destroy.
|
||||||
|
*/
|
||||||
|
SECP256K1_API secp256k1_context* secp256k1_context_preallocated_create(
|
||||||
|
void* prealloc,
|
||||||
|
unsigned int flags
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
/** Determine the memory size of a secp256k1 context object to be copied into
|
||||||
|
* caller-provided memory.
|
||||||
|
*
|
||||||
|
* Returns: the required size of the caller-provided memory block.
|
||||||
|
* In: ctx: an existing context to copy (cannot be NULL)
|
||||||
|
*/
|
||||||
|
SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
|
||||||
|
const secp256k1_context* ctx
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
/** Copy a secp256k1 context object into caller-provided memory.
|
||||||
|
*
|
||||||
|
* The caller must provide a pointer to a rewritable contiguous block of memory
|
||||||
|
* of size at least secp256k1_context_preallocated_size(flags) bytes, suitably
|
||||||
|
* aligned to hold an object of any type.
|
||||||
|
*
|
||||||
|
* The block of memory is exclusively owned by the created context object during
|
||||||
|
* the lifetime of this context object, see the description of
|
||||||
|
* secp256k1_context_preallocated_create for details.
|
||||||
|
*
|
||||||
|
* Returns: a newly created context object.
|
||||||
|
* Args: ctx: an existing context to copy (cannot be NULL)
|
||||||
|
* In: prealloc: a pointer to a rewritable contiguous block of memory of
|
||||||
|
* size at least secp256k1_context_preallocated_size(flags)
|
||||||
|
* bytes, as detailed above (cannot be NULL)
|
||||||
|
*/
|
||||||
|
SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
|
||||||
|
const secp256k1_context* ctx,
|
||||||
|
void* prealloc
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
/** Destroy a secp256k1 context object that has been created in
|
||||||
|
* caller-provided memory.
|
||||||
|
*
|
||||||
|
* The context pointer may not be used afterwards.
|
||||||
|
*
|
||||||
|
* The context to destroy must have been created using
|
||||||
|
* secp256k1_context_preallocated_create or secp256k1_context_preallocated_clone.
|
||||||
|
* If the context has instead been created using secp256k1_context_create or
|
||||||
|
* secp256k1_context_clone, the behaviour is undefined. In that case,
|
||||||
|
* secp256k1_context_destroy must be used instead.
|
||||||
|
*
|
||||||
|
* If required, it is the responsibility of the caller to deallocate the block
|
||||||
|
* of memory properly after this function returns, e.g., by calling free on the
|
||||||
|
* preallocated pointer given to secp256k1_context_preallocated_create or
|
||||||
|
* secp256k1_context_preallocated_clone.
|
||||||
|
*
|
||||||
|
* Args: ctx: an existing context to destroy, constructed using
|
||||||
|
* secp256k1_context_preallocated_create or
|
||||||
|
* secp256k1_context_preallocated_clone (cannot be NULL)
|
||||||
|
*/
|
||||||
|
SECP256K1_API void secp256k1_context_preallocated_destroy(
|
||||||
|
secp256k1_context* ctx
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SECP256K1_PREALLOCATED_H */
|
@ -10,7 +10,10 @@
|
|||||||
#ifdef USE_BASIC_CONFIG
|
#ifdef USE_BASIC_CONFIG
|
||||||
|
|
||||||
#undef USE_ASM_X86_64
|
#undef USE_ASM_X86_64
|
||||||
|
#undef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||||
#undef USE_ENDOMORPHISM
|
#undef USE_ENDOMORPHISM
|
||||||
|
#undef USE_EXTERNAL_ASM
|
||||||
|
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||||
#undef USE_FIELD_10X26
|
#undef USE_FIELD_10X26
|
||||||
#undef USE_FIELD_5X52
|
#undef USE_FIELD_5X52
|
||||||
#undef USE_FIELD_INV_BUILTIN
|
#undef USE_FIELD_INV_BUILTIN
|
||||||
|
@ -20,10 +20,10 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
} secp256k1_ecmult_context;
|
} secp256k1_ecmult_context;
|
||||||
|
|
||||||
|
static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
||||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx);
|
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx);
|
||||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb);
|
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc);
|
||||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst,
|
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src);
|
||||||
const secp256k1_ecmult_context *src, const secp256k1_callback *cb);
|
|
||||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx);
|
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx);
|
||||||
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx);
|
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx);
|
||||||
|
|
||||||
|
@ -61,6 +61,10 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w, int size)
|
|||||||
int bit;
|
int bit;
|
||||||
secp256k1_scalar neg_s;
|
secp256k1_scalar neg_s;
|
||||||
int not_neg_one;
|
int not_neg_one;
|
||||||
|
|
||||||
|
VERIFY_CHECK(w > 0);
|
||||||
|
VERIFY_CHECK(size > 0);
|
||||||
|
|
||||||
/* Note that we cannot handle even numbers by negating them to be odd, as is
|
/* Note that we cannot handle even numbers by negating them to be odd, as is
|
||||||
* done in other implementations, since if our scalars were specified to have
|
* done in other implementations, since if our scalars were specified to have
|
||||||
* width < 256 for performance reasons, their negations would have width 256
|
* width < 256 for performance reasons, their negations would have width 256
|
||||||
@ -93,7 +97,7 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w, int size)
|
|||||||
|
|
||||||
/* 4 */
|
/* 4 */
|
||||||
u_last = secp256k1_scalar_shr_int(&s, w);
|
u_last = secp256k1_scalar_shr_int(&s, w);
|
||||||
while (word * w < size) {
|
do {
|
||||||
int sign;
|
int sign;
|
||||||
int even;
|
int even;
|
||||||
|
|
||||||
@ -109,7 +113,7 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w, int size)
|
|||||||
wnaf[word++] = u_last * global_sign;
|
wnaf[word++] = u_last * global_sign;
|
||||||
|
|
||||||
u_last = u;
|
u_last = u;
|
||||||
}
|
} while (word * w < size);
|
||||||
wnaf[word] = u * global_sign;
|
wnaf[word] = u * global_sign;
|
||||||
|
|
||||||
VERIFY_CHECK(secp256k1_scalar_is_zero(&s));
|
VERIFY_CHECK(secp256k1_scalar_is_zero(&s));
|
||||||
|
@ -28,10 +28,10 @@ typedef struct {
|
|||||||
secp256k1_gej initial;
|
secp256k1_gej initial;
|
||||||
} secp256k1_ecmult_gen_context;
|
} secp256k1_ecmult_gen_context;
|
||||||
|
|
||||||
|
static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx);
|
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx);
|
||||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb);
|
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, void **prealloc);
|
||||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst,
|
static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context* src);
|
||||||
const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb);
|
|
||||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx);
|
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx);
|
||||||
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx);
|
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx);
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#ifndef SECP256K1_ECMULT_GEN_IMPL_H
|
#ifndef SECP256K1_ECMULT_GEN_IMPL_H
|
||||||
#define SECP256K1_ECMULT_GEN_IMPL_H
|
#define SECP256K1_ECMULT_GEN_IMPL_H
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
#include "scalar.h"
|
#include "scalar.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "ecmult_gen.h"
|
#include "ecmult_gen.h"
|
||||||
@ -14,23 +15,32 @@
|
|||||||
#ifdef USE_ECMULT_STATIC_PRECOMPUTATION
|
#ifdef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||||
#include "ecmult_static_context.h"
|
#include "ecmult_static_context.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||||
|
static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = ROUND_TO_ALIGN(sizeof(*((secp256k1_ecmult_gen_context*) NULL)->prec));
|
||||||
|
#else
|
||||||
|
static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) {
|
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) {
|
||||||
ctx->prec = NULL;
|
ctx->prec = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_callback* cb) {
|
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, void **prealloc) {
|
||||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||||
secp256k1_ge prec[1024];
|
secp256k1_ge prec[1024];
|
||||||
secp256k1_gej gj;
|
secp256k1_gej gj;
|
||||||
secp256k1_gej nums_gej;
|
secp256k1_gej nums_gej;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
size_t const prealloc_size = SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||||
|
void* const base = *prealloc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ctx->prec != NULL) {
|
if (ctx->prec != NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||||
ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec));
|
ctx->prec = (secp256k1_ge_storage (*)[64][16])manual_alloc(prealloc, prealloc_size, base, prealloc_size);
|
||||||
|
|
||||||
/* get the generator */
|
/* get the generator */
|
||||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||||
@ -85,7 +95,7 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)cb;
|
(void)prealloc;
|
||||||
ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context;
|
ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context;
|
||||||
#endif
|
#endif
|
||||||
secp256k1_ecmult_gen_blind(ctx, NULL);
|
secp256k1_ecmult_gen_blind(ctx, NULL);
|
||||||
@ -95,27 +105,18 @@ static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_cont
|
|||||||
return ctx->prec != NULL;
|
return ctx->prec != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst,
|
static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context *src) {
|
||||||
const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) {
|
|
||||||
if (src->prec == NULL) {
|
|
||||||
dst->prec = NULL;
|
|
||||||
} else {
|
|
||||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
||||||
dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec));
|
if (src->prec != NULL) {
|
||||||
memcpy(dst->prec, src->prec, sizeof(*dst->prec));
|
/* We cast to void* first to suppress a -Wcast-align warning in clang. */
|
||||||
#else
|
dst->prec = (secp256k1_ge_storage (*)[64][16])(void*)((unsigned char*)dst + ((unsigned char*)src->prec - (unsigned char*)src));
|
||||||
(void)cb;
|
|
||||||
dst->prec = src->prec;
|
|
||||||
#endif
|
|
||||||
dst->initial = src->initial;
|
|
||||||
dst->blind = src->blind;
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
(void)dst, (void)src;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
|
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) {
|
||||||
#ifndef USE_ECMULT_STATIC_PRECOMPUTATION
|
|
||||||
free(ctx->prec);
|
|
||||||
#endif
|
|
||||||
secp256k1_scalar_clear(&ctx->blind);
|
secp256k1_scalar_clear(&ctx->blind);
|
||||||
secp256k1_gej_clear(&ctx->initial);
|
secp256k1_gej_clear(&ctx->initial);
|
||||||
ctx->prec = NULL;
|
ctx->prec = NULL;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include "scalar.h"
|
#include "scalar.h"
|
||||||
#include "ecmult.h"
|
#include "ecmult.h"
|
||||||
@ -30,16 +31,34 @@
|
|||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
/* optimal for 128-bit and 256-bit exponents. */
|
/* optimal for 128-bit and 256-bit exponents. */
|
||||||
#define WINDOW_A 5
|
# define WINDOW_A 5
|
||||||
/** larger numbers may result in slightly better performance, at the cost of
|
/** Larger values for ECMULT_WINDOW_SIZE result in possibly better
|
||||||
exponentially larger precomputed tables. */
|
* performance at the cost of an exponentially larger precomputed
|
||||||
#ifdef USE_ENDOMORPHISM
|
* table. The exact table size is
|
||||||
/** Two tables for window size 15: 1.375 MiB. */
|
* (1 << (WINDOW_G - 2)) * sizeof(secp256k1_ge_storage) bytes,
|
||||||
#define WINDOW_G 15
|
* where sizeof(secp256k1_ge_storage) is typically 64 bytes but can
|
||||||
#else
|
* be larger due to platform-specific padding and alignment.
|
||||||
/** One table for window size 16: 1.375 MiB. */
|
*/
|
||||||
#define WINDOW_G 16
|
# ifdef USE_ENDOMORPHISM
|
||||||
|
# define WINDOW_G ((ECMULT_WINDOW_SIZE)-1)
|
||||||
|
# else
|
||||||
|
# define WINDOW_G (ECMULT_WINDOW_SIZE)
|
||||||
|
# endif
|
||||||
#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
|
#endif
|
||||||
|
|
||||||
#ifdef USE_ENDOMORPHISM
|
#ifdef USE_ENDOMORPHISM
|
||||||
@ -293,6 +312,13 @@ static void secp256k1_ecmult_odd_multiples_table_storage_var(const int n, secp25
|
|||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE =
|
||||||
|
ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
|
||||||
|
#ifdef USE_ENDOMORPHISM
|
||||||
|
+ ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G))
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
|
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
|
||||||
ctx->pre_g = NULL;
|
ctx->pre_g = NULL;
|
||||||
#ifdef USE_ENDOMORPHISM
|
#ifdef USE_ENDOMORPHISM
|
||||||
@ -300,8 +326,10 @@ static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) {
|
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc) {
|
||||||
secp256k1_gej gj;
|
secp256k1_gej gj;
|
||||||
|
void* const base = *prealloc;
|
||||||
|
size_t const prealloc_size = SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
||||||
|
|
||||||
if (ctx->pre_g != NULL) {
|
if (ctx->pre_g != NULL) {
|
||||||
return;
|
return;
|
||||||
@ -310,7 +338,12 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const
|
|||||||
/* get the generator */
|
/* get the generator */
|
||||||
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
|
||||||
|
|
||||||
ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
|
{
|
||||||
|
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 */
|
/* precompute the tables with odd multiples */
|
||||||
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
|
secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj);
|
||||||
@ -320,7 +353,10 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const
|
|||||||
secp256k1_gej g_128j;
|
secp256k1_gej g_128j;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
|
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 */
|
/* calculate 2^128*generator */
|
||||||
g_128j = gj;
|
g_128j = gj;
|
||||||
@ -332,22 +368,13 @@ static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst,
|
static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src) {
|
||||||
const secp256k1_ecmult_context *src, const secp256k1_callback *cb) {
|
if (src->pre_g != NULL) {
|
||||||
if (src->pre_g == NULL) {
|
dst->pre_g = (secp256k1_ge_storage (*)[])((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src));
|
||||||
dst->pre_g = NULL;
|
|
||||||
} else {
|
|
||||||
size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
|
|
||||||
dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size);
|
|
||||||
memcpy(dst->pre_g, src->pre_g, size);
|
|
||||||
}
|
}
|
||||||
#ifdef USE_ENDOMORPHISM
|
#ifdef USE_ENDOMORPHISM
|
||||||
if (src->pre_g_128 == NULL) {
|
if (src->pre_g_128 != NULL) {
|
||||||
dst->pre_g_128 = NULL;
|
dst->pre_g_128 = (secp256k1_ge_storage (*)[])((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src));
|
||||||
} else {
|
|
||||||
size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G);
|
|
||||||
dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size);
|
|
||||||
memcpy(dst->pre_g_128, src->pre_g_128, size);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -357,10 +384,6 @@ static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) {
|
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) {
|
||||||
free(ctx->pre_g);
|
|
||||||
#ifdef USE_ENDOMORPHISM
|
|
||||||
free(ctx->pre_g_128);
|
|
||||||
#endif
|
|
||||||
secp256k1_ecmult_context_init(ctx);
|
secp256k1_ecmult_context_init(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "basic-config.h"
|
#include "basic-config.h"
|
||||||
#include "include/secp256k1.h"
|
#include "include/secp256k1.h"
|
||||||
|
#include "util.h"
|
||||||
#include "field_impl.h"
|
#include "field_impl.h"
|
||||||
#include "scalar_impl.h"
|
#include "scalar_impl.h"
|
||||||
#include "group_impl.h"
|
#include "group_impl.h"
|
||||||
@ -26,6 +27,7 @@ static const secp256k1_callback default_error_callback = {
|
|||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
secp256k1_ecmult_gen_context ctx;
|
secp256k1_ecmult_gen_context ctx;
|
||||||
|
void *prealloc, *base;
|
||||||
int inner;
|
int inner;
|
||||||
int outer;
|
int outer;
|
||||||
FILE* fp;
|
FILE* fp;
|
||||||
@ -45,8 +47,10 @@ int main(int argc, char **argv) {
|
|||||||
fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n");
|
fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n");
|
||||||
fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n");
|
fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n");
|
||||||
|
|
||||||
|
base = checked_malloc(&default_error_callback, SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE);
|
||||||
|
prealloc = base;
|
||||||
secp256k1_ecmult_gen_context_init(&ctx);
|
secp256k1_ecmult_gen_context_init(&ctx);
|
||||||
secp256k1_ecmult_gen_context_build(&ctx, &default_error_callback);
|
secp256k1_ecmult_gen_context_build(&ctx, &prealloc);
|
||||||
for(outer = 0; outer != 64; outer++) {
|
for(outer = 0; outer != 64; outer++) {
|
||||||
fprintf(fp,"{\n");
|
fprintf(fp,"{\n");
|
||||||
for(inner = 0; inner != 16; inner++) {
|
for(inner = 0; inner != 16; inner++) {
|
||||||
@ -65,6 +69,7 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
fprintf(fp,"};\n");
|
fprintf(fp,"};\n");
|
||||||
secp256k1_ecmult_gen_context_clear(&ctx);
|
secp256k1_ecmult_gen_context_clear(&ctx);
|
||||||
|
free(base);
|
||||||
|
|
||||||
fprintf(fp, "#undef SC\n");
|
fprintf(fp, "#undef SC\n");
|
||||||
fprintf(fp, "#endif\n");
|
fprintf(fp, "#endif\n");
|
||||||
|
@ -7,14 +7,9 @@
|
|||||||
#ifndef _SECP256K1_SCRATCH_IMPL_H_
|
#ifndef _SECP256K1_SCRATCH_IMPL_H_
|
||||||
#define _SECP256K1_SCRATCH_IMPL_H_
|
#define _SECP256K1_SCRATCH_IMPL_H_
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
#include "scratch.h"
|
#include "scratch.h"
|
||||||
|
|
||||||
/* Using 16 bytes alignment because common architectures never have alignment
|
|
||||||
* requirements above 8 for any of the types we care about. In addition we
|
|
||||||
* leave some room because currently we don't care about a few bytes.
|
|
||||||
* TODO: Determine this at configure time. */
|
|
||||||
#define ALIGNMENT 16
|
|
||||||
|
|
||||||
static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size) {
|
static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size) {
|
||||||
secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret));
|
secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret));
|
||||||
if (ret != NULL) {
|
if (ret != NULL) {
|
||||||
@ -71,7 +66,7 @@ static void secp256k1_scratch_deallocate_frame(secp256k1_scratch* scratch) {
|
|||||||
static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) {
|
static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) {
|
||||||
void *ret;
|
void *ret;
|
||||||
size_t frame = scratch->frame - 1;
|
size_t frame = scratch->frame - 1;
|
||||||
size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT;
|
size = ROUND_TO_ALIGN(size);
|
||||||
|
|
||||||
if (scratch->frame == 0 || size + scratch->offset[frame] > scratch->frame_size[frame]) {
|
if (scratch->frame == 0 || size + scratch->offset[frame] > scratch->frame_size[frame]) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
141
src/secp256k1.c
141
src/secp256k1.c
@ -5,6 +5,7 @@
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#include "include/secp256k1.h"
|
#include "include/secp256k1.h"
|
||||||
|
#include "include/secp256k1_preallocated.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "num_impl.h"
|
#include "num_impl.h"
|
||||||
@ -36,28 +37,39 @@
|
|||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
static void default_illegal_callback_fn(const char* str, void* data) {
|
#define ARG_CHECK_NO_RETURN(cond) do { \
|
||||||
|
if (EXPECT(!(cond), 0)) { \
|
||||||
|
secp256k1_callback_call(&ctx->illegal_callback, #cond); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
static void secp256k1_default_illegal_callback_fn(const char* str, void* data) {
|
||||||
(void)data;
|
(void)data;
|
||||||
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
|
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
static void secp256k1_default_error_callback_fn(const char* str, void* data) {
|
||||||
static const secp256k1_callback default_illegal_callback = {
|
|
||||||
default_illegal_callback_fn,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static void default_error_callback_fn(const char* str, void* data) {
|
|
||||||
(void)data;
|
(void)data;
|
||||||
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void secp256k1_default_illegal_callback_fn(const char* str, void* data);
|
||||||
|
void secp256k1_default_error_callback_fn(const char* str, void* data);
|
||||||
|
#endif
|
||||||
|
|
||||||
static const secp256k1_callback default_error_callback = {
|
static const secp256k1_callback default_illegal_callback = {
|
||||||
default_error_callback_fn,
|
secp256k1_default_illegal_callback_fn,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const secp256k1_callback default_error_callback = {
|
||||||
|
secp256k1_default_error_callback_fn,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
struct secp256k1_context_struct {
|
struct secp256k1_context_struct {
|
||||||
secp256k1_ecmult_context ecmult_ctx;
|
secp256k1_ecmult_context ecmult_ctx;
|
||||||
@ -69,20 +81,55 @@ struct secp256k1_context_struct {
|
|||||||
static const secp256k1_context secp256k1_context_no_precomp_ = {
|
static const secp256k1_context secp256k1_context_no_precomp_ = {
|
||||||
{ 0 },
|
{ 0 },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
{ default_illegal_callback_fn, 0 },
|
{ secp256k1_default_illegal_callback_fn, 0 },
|
||||||
{ default_error_callback_fn, 0 }
|
{ secp256k1_default_error_callback_fn, 0 }
|
||||||
};
|
};
|
||||||
const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
|
const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_;
|
||||||
|
|
||||||
secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
size_t secp256k1_context_preallocated_size(unsigned int flags) {
|
||||||
secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context));
|
size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context));
|
||||||
|
|
||||||
|
if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) {
|
||||||
|
secp256k1_callback_call(&default_illegal_callback,
|
||||||
|
"Invalid flags");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
||||||
|
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||||
|
}
|
||||||
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
|
||||||
|
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) {
|
||||||
|
size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context));
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
|
||||||
|
ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE;
|
||||||
|
}
|
||||||
|
if (secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)) {
|
||||||
|
ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) {
|
||||||
|
void* const base = prealloc;
|
||||||
|
size_t prealloc_size;
|
||||||
|
secp256k1_context* ret;
|
||||||
|
|
||||||
|
VERIFY_CHECK(prealloc != NULL);
|
||||||
|
prealloc_size = secp256k1_context_preallocated_size(flags);
|
||||||
|
ret = (secp256k1_context*)manual_alloc(&prealloc, sizeof(secp256k1_context), base, prealloc_size);
|
||||||
ret->illegal_callback = default_illegal_callback;
|
ret->illegal_callback = default_illegal_callback;
|
||||||
ret->error_callback = default_error_callback;
|
ret->error_callback = default_error_callback;
|
||||||
|
|
||||||
if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) {
|
if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) {
|
||||||
secp256k1_callback_call(&ret->illegal_callback,
|
secp256k1_callback_call(&ret->illegal_callback,
|
||||||
"Invalid flags");
|
"Invalid flags");
|
||||||
free(ret);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,47 +137,79 @@ secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
|||||||
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
|
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
|
||||||
|
|
||||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) {
|
||||||
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback);
|
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc);
|
||||||
}
|
}
|
||||||
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
|
if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) {
|
||||||
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback);
|
secp256k1_ecmult_context_build(&ret->ecmult_ctx, &prealloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (secp256k1_context*) ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
secp256k1_context* secp256k1_context_create(unsigned int flags) {
|
||||||
|
size_t const prealloc_size = secp256k1_context_preallocated_size(flags);
|
||||||
|
secp256k1_context* ctx = (secp256k1_context*)checked_malloc(&default_error_callback, prealloc_size);
|
||||||
|
if (EXPECT(secp256k1_context_preallocated_create(ctx, flags) == NULL, 0)) {
|
||||||
|
free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context* ctx, void* prealloc) {
|
||||||
|
size_t prealloc_size;
|
||||||
|
secp256k1_context* ret;
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
ARG_CHECK(prealloc != NULL);
|
||||||
|
|
||||||
|
prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
|
||||||
|
ret = (secp256k1_context*)prealloc;
|
||||||
|
memcpy(ret, ctx, prealloc_size);
|
||||||
|
secp256k1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx);
|
||||||
|
secp256k1_ecmult_context_finalize_memcpy(&ret->ecmult_ctx, &ctx->ecmult_ctx);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
|
secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) {
|
||||||
secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context));
|
secp256k1_context* ret;
|
||||||
ret->illegal_callback = ctx->illegal_callback;
|
size_t prealloc_size;
|
||||||
ret->error_callback = ctx->error_callback;
|
|
||||||
secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback);
|
VERIFY_CHECK(ctx != NULL);
|
||||||
secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback);
|
prealloc_size = secp256k1_context_preallocated_clone_size(ctx);
|
||||||
|
ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size);
|
||||||
|
ret = secp256k1_context_preallocated_clone(ctx, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void secp256k1_context_destroy(secp256k1_context* ctx) {
|
void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) {
|
||||||
CHECK(ctx != secp256k1_context_no_precomp);
|
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
|
||||||
if (ctx != NULL) {
|
if (ctx != NULL) {
|
||||||
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
|
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
|
||||||
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void secp256k1_context_destroy(secp256k1_context* ctx) {
|
||||||
|
if (ctx != NULL) {
|
||||||
|
secp256k1_context_preallocated_destroy(ctx);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
|
void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
|
||||||
CHECK(ctx != secp256k1_context_no_precomp);
|
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
|
||||||
if (fun == NULL) {
|
if (fun == NULL) {
|
||||||
fun = default_illegal_callback_fn;
|
fun = secp256k1_default_illegal_callback_fn;
|
||||||
}
|
}
|
||||||
ctx->illegal_callback.fn = fun;
|
ctx->illegal_callback.fn = fun;
|
||||||
ctx->illegal_callback.data = data;
|
ctx->illegal_callback.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
|
void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) {
|
||||||
CHECK(ctx != secp256k1_context_no_precomp);
|
ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp);
|
||||||
if (fun == NULL) {
|
if (fun == NULL) {
|
||||||
fun = default_error_callback_fn;
|
fun = secp256k1_default_error_callback_fn;
|
||||||
}
|
}
|
||||||
ctx->error_callback.fn = fun;
|
ctx->error_callback.fn = fun;
|
||||||
ctx->error_callback.data = data;
|
ctx->error_callback.data = data;
|
||||||
@ -601,9 +680,9 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey
|
|||||||
|
|
||||||
int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) {
|
int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) {
|
||||||
VERIFY_CHECK(ctx != NULL);
|
VERIFY_CHECK(ctx != NULL);
|
||||||
CHECK(ctx != secp256k1_context_no_precomp);
|
if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) {
|
||||||
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32);
|
||||||
secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32);
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
122
src/tests.c
122
src/tests.c
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "secp256k1.c"
|
#include "secp256k1.c"
|
||||||
#include "include/secp256k1.h"
|
#include "include/secp256k1.h"
|
||||||
|
#include "include/secp256k1_preallocated.h"
|
||||||
#include "testrand_impl.h"
|
#include "testrand_impl.h"
|
||||||
|
|
||||||
#ifdef ENABLE_OPENSSL_TESTS
|
#ifdef ENABLE_OPENSSL_TESTS
|
||||||
@ -183,23 +184,47 @@ void run_util_tests(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_context_tests(void) {
|
void run_context_tests(int use_prealloc) {
|
||||||
secp256k1_pubkey pubkey;
|
secp256k1_pubkey pubkey;
|
||||||
secp256k1_pubkey zero_pubkey;
|
secp256k1_pubkey zero_pubkey;
|
||||||
secp256k1_ecdsa_signature sig;
|
secp256k1_ecdsa_signature sig;
|
||||||
unsigned char ctmp[32];
|
unsigned char ctmp[32];
|
||||||
int32_t ecount;
|
int32_t ecount;
|
||||||
int32_t ecount2;
|
int32_t ecount2;
|
||||||
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
|
secp256k1_context *none;
|
||||||
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
secp256k1_context *sign;
|
||||||
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
secp256k1_context *vrfy;
|
||||||
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
secp256k1_context *both;
|
||||||
|
void *none_prealloc = NULL;
|
||||||
|
void *sign_prealloc = NULL;
|
||||||
|
void *vrfy_prealloc = NULL;
|
||||||
|
void *both_prealloc = NULL;
|
||||||
|
|
||||||
secp256k1_gej pubj;
|
secp256k1_gej pubj;
|
||||||
secp256k1_ge pub;
|
secp256k1_ge pub;
|
||||||
secp256k1_scalar msg, key, nonce;
|
secp256k1_scalar msg, key, nonce;
|
||||||
secp256k1_scalar sigr, sigs;
|
secp256k1_scalar sigr, sigs;
|
||||||
|
|
||||||
|
if (use_prealloc) {
|
||||||
|
none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
|
||||||
|
sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
|
||||||
|
vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
|
||||||
|
both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
|
||||||
|
CHECK(none_prealloc != NULL);
|
||||||
|
CHECK(sign_prealloc != NULL);
|
||||||
|
CHECK(vrfy_prealloc != NULL);
|
||||||
|
CHECK(both_prealloc != NULL);
|
||||||
|
none = secp256k1_context_preallocated_create(none_prealloc, SECP256K1_CONTEXT_NONE);
|
||||||
|
sign = secp256k1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN);
|
||||||
|
vrfy = secp256k1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY);
|
||||||
|
both = secp256k1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||||
|
} else {
|
||||||
|
none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
|
||||||
|
sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||||
|
vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||||
|
both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||||
|
}
|
||||||
|
|
||||||
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
|
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
|
||||||
|
|
||||||
ecount = 0;
|
ecount = 0;
|
||||||
@ -209,14 +234,57 @@ void run_context_tests(void) {
|
|||||||
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL);
|
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL);
|
||||||
CHECK(vrfy->error_callback.fn != sign->error_callback.fn);
|
CHECK(vrfy->error_callback.fn != sign->error_callback.fn);
|
||||||
|
|
||||||
|
/* check if sizes for cloning are consistent */
|
||||||
|
CHECK(secp256k1_context_preallocated_clone_size(none) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE));
|
||||||
|
CHECK(secp256k1_context_preallocated_clone_size(sign) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN));
|
||||||
|
CHECK(secp256k1_context_preallocated_clone_size(vrfy) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY));
|
||||||
|
CHECK(secp256k1_context_preallocated_clone_size(both) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY));
|
||||||
|
|
||||||
/*** clone and destroy all of them to make sure cloning was complete ***/
|
/*** clone and destroy all of them to make sure cloning was complete ***/
|
||||||
{
|
{
|
||||||
secp256k1_context *ctx_tmp;
|
secp256k1_context *ctx_tmp;
|
||||||
|
|
||||||
ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp);
|
if (use_prealloc) {
|
||||||
ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp);
|
/* clone into a non-preallocated context and then again into a new preallocated one. */
|
||||||
ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp);
|
ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_preallocated_destroy(ctx_tmp);
|
||||||
ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp);
|
free(none_prealloc); none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(none_prealloc != NULL);
|
||||||
|
ctx_tmp = none; none = secp256k1_context_preallocated_clone(none, none_prealloc); secp256k1_context_destroy(ctx_tmp);
|
||||||
|
|
||||||
|
ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_preallocated_destroy(ctx_tmp);
|
||||||
|
free(sign_prealloc); sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(sign_prealloc != NULL);
|
||||||
|
ctx_tmp = sign; sign = secp256k1_context_preallocated_clone(sign, sign_prealloc); secp256k1_context_destroy(ctx_tmp);
|
||||||
|
|
||||||
|
ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_preallocated_destroy(ctx_tmp);
|
||||||
|
free(vrfy_prealloc); vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(vrfy_prealloc != NULL);
|
||||||
|
ctx_tmp = vrfy; vrfy = secp256k1_context_preallocated_clone(vrfy, vrfy_prealloc); secp256k1_context_destroy(ctx_tmp);
|
||||||
|
|
||||||
|
ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_preallocated_destroy(ctx_tmp);
|
||||||
|
free(both_prealloc); both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(both_prealloc != NULL);
|
||||||
|
ctx_tmp = both; both = secp256k1_context_preallocated_clone(both, both_prealloc); secp256k1_context_destroy(ctx_tmp);
|
||||||
|
} else {
|
||||||
|
/* clone into a preallocated context and then again into a new non-preallocated one. */
|
||||||
|
void *prealloc_tmp;
|
||||||
|
|
||||||
|
prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(prealloc_tmp != NULL);
|
||||||
|
ctx_tmp = none; none = secp256k1_context_preallocated_clone(none, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
|
||||||
|
ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_preallocated_destroy(ctx_tmp);
|
||||||
|
free(prealloc_tmp);
|
||||||
|
|
||||||
|
prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(prealloc_tmp != NULL);
|
||||||
|
ctx_tmp = sign; sign = secp256k1_context_preallocated_clone(sign, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
|
||||||
|
ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_preallocated_destroy(ctx_tmp);
|
||||||
|
free(prealloc_tmp);
|
||||||
|
|
||||||
|
prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL);
|
||||||
|
ctx_tmp = vrfy; vrfy = secp256k1_context_preallocated_clone(vrfy, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
|
||||||
|
ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_preallocated_destroy(ctx_tmp);
|
||||||
|
free(prealloc_tmp);
|
||||||
|
|
||||||
|
prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL);
|
||||||
|
ctx_tmp = both; both = secp256k1_context_preallocated_clone(both, prealloc_tmp); secp256k1_context_destroy(ctx_tmp);
|
||||||
|
ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_preallocated_destroy(ctx_tmp);
|
||||||
|
free(prealloc_tmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that the error callback makes it across the clone. */
|
/* Verify that the error callback makes it across the clone. */
|
||||||
@ -264,17 +332,17 @@ void run_context_tests(void) {
|
|||||||
CHECK(ecount == 3);
|
CHECK(ecount == 3);
|
||||||
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
|
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
|
||||||
CHECK(ecount == 3);
|
CHECK(ecount == 3);
|
||||||
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
|
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 1);
|
||||||
CHECK(ecount == 4);
|
CHECK(ecount == 3);
|
||||||
|
CHECK(secp256k1_context_randomize(vrfy, NULL) == 1);
|
||||||
|
CHECK(ecount == 3);
|
||||||
|
CHECK(secp256k1_context_randomize(sign, ctmp) == 1);
|
||||||
|
CHECK(ecount2 == 14);
|
||||||
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
|
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
|
||||||
CHECK(ecount2 == 14);
|
CHECK(ecount2 == 14);
|
||||||
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
|
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
|
||||||
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
|
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
|
||||||
|
|
||||||
/* This shouldn't leak memory, due to already-set tests. */
|
|
||||||
secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL);
|
|
||||||
secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL);
|
|
||||||
|
|
||||||
/* obtain a working nonce */
|
/* obtain a working nonce */
|
||||||
do {
|
do {
|
||||||
random_scalar_order_test(&nonce);
|
random_scalar_order_test(&nonce);
|
||||||
@ -289,12 +357,25 @@ void run_context_tests(void) {
|
|||||||
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg));
|
||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
secp256k1_context_destroy(none);
|
if (use_prealloc) {
|
||||||
secp256k1_context_destroy(sign);
|
secp256k1_context_preallocated_destroy(none);
|
||||||
secp256k1_context_destroy(vrfy);
|
secp256k1_context_preallocated_destroy(sign);
|
||||||
secp256k1_context_destroy(both);
|
secp256k1_context_preallocated_destroy(vrfy);
|
||||||
|
secp256k1_context_preallocated_destroy(both);
|
||||||
|
free(none_prealloc);
|
||||||
|
free(sign_prealloc);
|
||||||
|
free(vrfy_prealloc);
|
||||||
|
free(both_prealloc);
|
||||||
|
} else {
|
||||||
|
secp256k1_context_destroy(none);
|
||||||
|
secp256k1_context_destroy(sign);
|
||||||
|
secp256k1_context_destroy(vrfy);
|
||||||
|
secp256k1_context_destroy(both);
|
||||||
|
}
|
||||||
/* Defined as no-op. */
|
/* Defined as no-op. */
|
||||||
secp256k1_context_destroy(NULL);
|
secp256k1_context_destroy(NULL);
|
||||||
|
secp256k1_context_preallocated_destroy(NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_scratch_tests(void) {
|
void run_scratch_tests(void) {
|
||||||
@ -5192,7 +5273,8 @@ int main(int argc, char **argv) {
|
|||||||
printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]);
|
printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]);
|
||||||
|
|
||||||
/* initialize */
|
/* initialize */
|
||||||
run_context_tests();
|
run_context_tests(0);
|
||||||
|
run_context_tests(1);
|
||||||
run_scratch_tests();
|
run_scratch_tests();
|
||||||
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||||
if (secp256k1_rand_bits(1)) {
|
if (secp256k1_rand_bits(1)) {
|
||||||
|
41
src/util.h
41
src/util.h
@ -110,6 +110,47 @@ SECP256K1_INLINE static int secp256k1_clz64_var(uint64_t x) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__BIGGEST_ALIGNMENT__)
|
||||||
|
#define ALIGNMENT __BIGGEST_ALIGNMENT__
|
||||||
|
#else
|
||||||
|
/* Using 16 bytes alignment because common architectures never have alignment
|
||||||
|
* requirements above 8 for any of the types we care about. In addition we
|
||||||
|
* leave some room because currently we don't care about a few bytes. */
|
||||||
|
#define ALIGNMENT 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ROUND_TO_ALIGN(size) (((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT)
|
||||||
|
|
||||||
|
/* Assume there is a contiguous memory object with bounds [base, base + max_size)
|
||||||
|
* of which the memory range [base, *prealloc_ptr) is already allocated for usage,
|
||||||
|
* where *prealloc_ptr is an aligned pointer. In that setting, this functions
|
||||||
|
* reserves the subobject [*prealloc_ptr, *prealloc_ptr + alloc_size) of
|
||||||
|
* alloc_size bytes by increasing *prealloc_ptr accordingly, taking into account
|
||||||
|
* alignment requirements.
|
||||||
|
*
|
||||||
|
* The function returns an aligned pointer to the newly allocated subobject.
|
||||||
|
*
|
||||||
|
* This is useful for manual memory management: if we're simply given a block
|
||||||
|
* [base, base + max_size), the caller can use this function to allocate memory
|
||||||
|
* in this block and keep track of the current allocation state with *prealloc_ptr.
|
||||||
|
*
|
||||||
|
* It is VERIFY_CHECKed that there is enough space left in the memory object and
|
||||||
|
* *prealloc_ptr is aligned relative to base.
|
||||||
|
*/
|
||||||
|
static SECP256K1_INLINE void *manual_alloc(void** prealloc_ptr, size_t alloc_size, void* base, size_t max_size) {
|
||||||
|
size_t aligned_alloc_size = ROUND_TO_ALIGN(alloc_size);
|
||||||
|
void* ret;
|
||||||
|
VERIFY_CHECK(prealloc_ptr != NULL);
|
||||||
|
VERIFY_CHECK(*prealloc_ptr != NULL);
|
||||||
|
VERIFY_CHECK(base != NULL);
|
||||||
|
VERIFY_CHECK((unsigned char*)*prealloc_ptr >= (unsigned char*)base);
|
||||||
|
VERIFY_CHECK(((unsigned char*)*prealloc_ptr - (unsigned char*)base) % ALIGNMENT == 0);
|
||||||
|
VERIFY_CHECK((unsigned char*)*prealloc_ptr - (unsigned char*)base + aligned_alloc_size <= max_size);
|
||||||
|
ret = *prealloc_ptr;
|
||||||
|
*((unsigned char**)prealloc_ptr) += aligned_alloc_size;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Macro for restrict, when available and not in a VERIFY build. */
|
/* Macro for restrict, when available and not in a VERIFY build. */
|
||||||
#if defined(SECP256K1_BUILD) && defined(VERIFY)
|
#if defined(SECP256K1_BUILD) && defined(VERIFY)
|
||||||
# define SECP256K1_RESTRICT
|
# define SECP256K1_RESTRICT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user