This commit is contained in:
DesWurstes 2018-06-05 10:40:40 +00:00 committed by GitHub
commit fc3f004a0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
70 changed files with 2370 additions and 694 deletions

View file

@ -128,7 +128,7 @@ int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, unsigned char *point,
if (overflow || secp256k1_scalar_is_zero(&s)) { if (overflow || secp256k1_scalar_is_zero(&s)) {
ret = 0; ret = 0;
} else { } else {
secp256k1_ecmult_const(&res, &ge, &s); secp256k1_ecmult_const(&res, &ge, &s, 256);
secp256k1_ge_set_gej(&ge, &res); secp256k1_ge_set_gej(&ge, &res);
/* Note: can't use secp256k1_pubkey_save here because it is not constant time. */ /* Note: can't use secp256k1_pubkey_save here because it is not constant time. */
secp256k1_fe_normalize(&ge.x); secp256k1_fe_normalize(&ge.x);

View file

@ -1,5 +1,6 @@
bench_inv bench_inv
bench_ecdh bench_ecdh
bench_ecmult
bench_sign bench_sign
bench_verify bench_verify
bench_schnorr_verify bench_schnorr_verify

View file

@ -11,7 +11,7 @@ cache:
- src/java/guava/ - src/java/guava/
env: env:
global: global:
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no JNI=no
- GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar
matrix: matrix:
- SCALAR=32bit RECOVERY=yes - SCALAR=32bit RECOVERY=yes
@ -29,7 +29,7 @@ env:
- BUILD=distcheck - BUILD=distcheck
- EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC
- EXTRAFLAGS=CFLAGS=-O0 - EXTRAFLAGS=CFLAGS=-O0
- BUILD=check-java ECDH=yes EXPERIMENTAL=yes - BUILD=check-java JNI=yes ECDH=yes EXPERIMENTAL=yes
matrix: matrix:
fast_finish: true fast_finish: true
include: include:
@ -65,5 +65,5 @@ before_script: ./autogen.sh
script: script:
- if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi
- if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi
- ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 $BUILD
os: linux os: linux

View file

@ -42,6 +42,8 @@ noinst_HEADERS += src/field_5x52_asm_impl.h
noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h
noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h
noinst_HEADERS += src/util.h noinst_HEADERS += src/util.h
noinst_HEADERS += src/scratch.h
noinst_HEADERS += src/scratch_impl.h
noinst_HEADERS += src/testrand.h noinst_HEADERS += src/testrand.h
noinst_HEADERS += src/testrand_impl.h noinst_HEADERS += src/testrand_impl.h
noinst_HEADERS += src/hash.h noinst_HEADERS += src/hash.h
@ -79,7 +81,7 @@ libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES)
noinst_PROGRAMS = noinst_PROGRAMS =
if USE_BENCHMARK if USE_BENCHMARK
noinst_PROGRAMS += bench_verify bench_sign bench_internal noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_ecmult
bench_verify_SOURCES = src/bench_verify.c bench_verify_SOURCES = src/bench_verify.c
bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
bench_sign_SOURCES = src/bench_sign.c bench_sign_SOURCES = src/bench_sign.c
@ -87,6 +89,9 @@ bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB)
bench_internal_SOURCES = src/bench_internal.c bench_internal_SOURCES = src/bench_internal.c
bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB)
bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES)
bench_ecmult_SOURCES = src/bench_ecmult.c
bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB)
bench_ecmult_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES)
endif endif
TESTS = TESTS =
@ -159,6 +164,7 @@ $(gen_context_BIN): $(gen_context_OBJECTS)
$(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h
$(tests_OBJECTS): src/ecmult_static_context.h $(tests_OBJECTS): src/ecmult_static_context.h
$(bench_internal_OBJECTS): src/ecmult_static_context.h $(bench_internal_OBJECTS): src/ecmult_static_context.h
$(bench_ecmult_OBJECTS): src/ecmult_static_context.h
src/ecmult_static_context.h: $(gen_context_BIN) src/ecmult_static_context.h: $(gen_context_BIN)
./$(gen_context_BIN) ./$(gen_context_BIN)

View file

@ -1,5 +1,5 @@
# =========================================================================== # ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html # https://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html
# =========================================================================== # ===========================================================================
# #
# SYNOPSIS # SYNOPSIS
@ -44,7 +44,7 @@
# and this notice are preserved. This file is offered as-is, without any # and this notice are preserved. This file is offered as-is, without any
# warranty. # warranty.
#serial 10 #serial 14
AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR])
AC_DEFUN([AX_JNI_INCLUDE_DIR],[ AC_DEFUN([AX_JNI_INCLUDE_DIR],[
@ -66,8 +66,16 @@ else
fi fi
case "$host_os" in case "$host_os" in
darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` darwin*) # Apple Java headers are inside the Xcode bundle.
_JINC="$_JTOPDIR/Headers";; macos_version=$(sw_vers -productVersion | sed -n -e 's/^@<:@0-9@:>@*.\(@<:@0-9@:>@*\).@<:@0-9@:>@*/\1/p')
if @<:@ "$macos_version" -gt "7" @:>@; then
_JTOPDIR="$(xcrun --show-sdk-path)/System/Library/Frameworks/JavaVM.framework"
_JINC="$_JTOPDIR/Headers"
else
_JTOPDIR="/System/Library/Frameworks/JavaVM.framework"
_JINC="$_JTOPDIR/Headers"
fi
;;
*) _JINC="$_JTOPDIR/include";; *) _JINC="$_JTOPDIR/include";;
esac esac
_AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) _AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR])
@ -76,13 +84,12 @@ _AS_ECHO_LOG([_JINC=$_JINC])
# On Mac OS X 10.6.4, jni.h is a symlink: # On Mac OS X 10.6.4, jni.h is a symlink:
# /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h # /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h
# -> ../../CurrentJDK/Headers/jni.h. # -> ../../CurrentJDK/Headers/jni.h.
AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path,
[ [
if test -f "$_JINC/jni.h"; then if test -f "$_JINC/jni.h"; then
ac_cv_jni_header_path="$_JINC" ac_cv_jni_header_path="$_JINC"
JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path"
else else
_JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'`
if test -f "$_JTOPDIR/include/jni.h"; then if test -f "$_JTOPDIR/include/jni.h"; then
ac_cv_jni_header_path="$_JTOPDIR/include" ac_cv_jni_header_path="$_JTOPDIR/include"
@ -90,16 +97,14 @@ else
else else
ac_cv_jni_header_path=none ac_cv_jni_header_path=none
fi fi
fi fi
]) ])
# get the likely subdirectories for system specific java includes # get the likely subdirectories for system specific java includes
case "$host_os" in case "$host_os" in
bsdi*) _JNI_INC_SUBDIRS="bsdos";; bsdi*) _JNI_INC_SUBDIRS="bsdos";;
darwin*) _JNI_INC_SUBDIRS="darwin";;
freebsd*) _JNI_INC_SUBDIRS="freebsd";; freebsd*) _JNI_INC_SUBDIRS="freebsd";;
darwin*) _JNI_INC_SUBDIRS="darwin";;
linux*) _JNI_INC_SUBDIRS="linux genunix";; linux*) _JNI_INC_SUBDIRS="linux genunix";;
osf*) _JNI_INC_SUBDIRS="alpha";; osf*) _JNI_INC_SUBDIRS="alpha";;
solaris*) _JNI_INC_SUBDIRS="solaris";; solaris*) _JNI_INC_SUBDIRS="solaris";;

View file

@ -48,7 +48,6 @@ if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then
EC_KEY_free(eckey); EC_KEY_free(eckey);
ECDSA_SIG *sig_openssl; ECDSA_SIG *sig_openssl;
sig_openssl = ECDSA_SIG_new(); sig_openssl = ECDSA_SIG_new();
(void)sig_openssl->r;
ECDSA_SIG_free(sig_openssl); ECDSA_SIG_free(sig_openssl);
]])],[has_openssl_ec=yes],[has_openssl_ec=no]) ]])],[has_openssl_ec=yes],[has_openssl_ec=no])
AC_MSG_RESULT([$has_openssl_ec]) AC_MSG_RESULT([$has_openssl_ec])

View file

@ -85,9 +85,9 @@ 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 no)]), AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is yes)]),
[use_benchmark=$enableval], [use_benchmark=$enableval],
[use_benchmark=no]) [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]),
@ -135,9 +135,9 @@ AC_ARG_ENABLE(module_recovery,
[enable_module_recovery=no]) [enable_module_recovery=no])
AC_ARG_ENABLE(jni, AC_ARG_ENABLE(jni,
AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is no)]),
[use_jni=$enableval], [use_jni=$enableval],
[use_jni=auto]) [use_jni=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]) [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto])
@ -447,6 +447,7 @@ AC_MSG_NOTICE([Using field implementation: $set_field])
AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) AC_MSG_NOTICE([Using bignum implementation: $set_bignum])
AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) AC_MSG_NOTICE([Using scalar implementation: $set_scalar])
AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) 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 for coverage analysis: $enable_coverage])
AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery])

View file

@ -48,14 +48,14 @@
* 8.3.1. * 8.3.1.
*/ */
#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ #ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H
#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ #define SECP256K1_CONTRIB_LAX_DER_PARSING_H
#include <secp256k1.h> #include <secp256k1.h>
# ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
# endif #endif
/** Parse a signature in "lax DER" format /** Parse a signature in "lax DER" format
* *
@ -88,4 +88,4 @@ int ecdsa_signature_parse_der_lax(
} }
#endif #endif
#endif #endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */

View file

@ -25,14 +25,14 @@
* library are sufficient. * library are sufficient.
*/ */
#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ #ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H
#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ #define SECP256K1_CONTRIB_BER_PRIVATEKEY_H
#include <secp256k1.h> #include <secp256k1.h>
# ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
# endif #endif
/** Export a private key in DER format. /** Export a private key in DER format.
* *
@ -87,4 +87,4 @@ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der(
} }
#endif #endif
#endif #endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */

View file

@ -1,9 +1,9 @@
#ifndef _SECP256K1_ #ifndef SECP256K1_H
# define _SECP256K1_ #define SECP256K1_H
# ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
# endif #endif
#include <stddef.h> #include <stddef.h>
@ -42,6 +42,19 @@ extern "C" {
*/ */
typedef struct secp256k1_context_struct secp256k1_context; typedef struct secp256k1_context_struct secp256k1_context;
/** Opaque data structure that holds rewriteable "scratch space"
*
* The purpose of this structure is to replace dynamic memory allocations,
* because we target architectures where this may not be available. It is
* essentially a resizable (within specified parameters) block of bytes,
* which is initially created either by memory allocation or TODO as a pointer
* into some fixed rewritable space.
*
* Unlike the context object, this cannot safely be shared between threads
* without additional synchronization logic.
*/
typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space;
/** Opaque data structure that holds a parsed and valid public key. /** Opaque data structure that holds a parsed and valid public key.
* *
* The exact representation of data inside is implementation defined and not * The exact representation of data inside is implementation defined and not
@ -61,7 +74,7 @@ typedef struct {
* however guaranteed to be 64 bytes in size, and can be safely copied/moved. * however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, or * If you need to convert to a format suitable for storage, transmission, or
* comparison, use the secp256k1_ecdsa_signature_serialize_* and * comparison, use the secp256k1_ecdsa_signature_serialize_* and
* secp256k1_ecdsa_signature_serialize_* functions. * secp256k1_ecdsa_signature_parse_* functions.
*/ */
typedef struct { typedef struct {
unsigned char data[64]; unsigned char data[64];
@ -159,10 +172,19 @@ typedef int (*secp256k1_nonce_function)(
#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) #define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION)
/** Prefix byte used to tag various encoded curvepoints for specific purposes */
#define SECP256K1_TAG_PUBKEY_EVEN 0x02
#define SECP256K1_TAG_PUBKEY_ODD 0x03
#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04
#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06
#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07
/** Create a secp256k1 context object. /** Create a secp256k1 context object.
* *
* 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.
*
* See also secp256k1_context_randomize.
*/ */
SECP256K1_API secp256k1_context* secp256k1_context_create( SECP256K1_API secp256k1_context* secp256k1_context_create(
unsigned int flags unsigned int flags
@ -234,6 +256,26 @@ SECP256K1_API void secp256k1_context_set_error_callback(
const void* data const void* data
) SECP256K1_ARG_NONNULL(1); ) SECP256K1_ARG_NONNULL(1);
/** Create a secp256k1 scratch space object.
*
* Returns: a newly created scratch space.
* Args: ctx: an existing context object (cannot be NULL)
* In: max_size: maximum amount of memory to allocate
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space* secp256k1_scratch_space_create(
const secp256k1_context* ctx,
size_t max_size
) SECP256K1_ARG_NONNULL(1);
/** Destroy a secp256k1 scratch space.
*
* The pointer may not be used afterwards.
* Args: scratch: space to destroy
*/
SECP256K1_API void secp256k1_scratch_space_destroy(
secp256k1_scratch_space* scratch
);
/** Parse a variable-length public key into the pubkey object. /** Parse a variable-length public key into the pubkey object.
* *
* Returns: 1 if the public key was fully valid. * Returns: 1 if the public key was fully valid.
@ -485,6 +527,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
const unsigned char *seckey const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Negates a private key in place.
*
* Returns: 1 always
* Args: ctx: pointer to a context object
* In/Out: seckey: pointer to the 32-byte private key to be negated (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
const secp256k1_context* ctx,
unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
/** Negates a public key in place.
*
* Returns: 1 always
* Args: ctx: pointer to a context object
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
/** Tweak a private key by adding tweak to it. /** Tweak a private key by adding tweak to it.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
* uniformly random 32-byte arrays, or if the resulting private key * uniformly random 32-byte arrays, or if the resulting private key
@ -543,11 +607,24 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
const unsigned char *tweak const unsigned char *tweak
) 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. /** Updates the context randomization to protect against side-channel leakage.
* Returns: 1: randomization successfully updated * Returns: 1: randomization successfully updated
* 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)
*
* While secp256k1 code is written to be constant-time no matter what secret
* values are, it's possible that a future compiler may output code which isn't,
* and also that the CPU may not emit the same radio frequencies or draw the same
* amount power for all values.
*
* This function provides a seed which is combined into the blinding value: that
* blinding value is added before each multiplication (and removed afterwards) so
* that it does not affect function results, but shields against attacks which
* rely on any input-dependent behaviour.
*
* You should call this after secp256k1_context_create or
* secp256k1_context_clone, and 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,
@ -570,8 +647,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
size_t n size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); ) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
# ifdef __cplusplus #ifdef __cplusplus
} }
# endif
#endif #endif
#endif /* SECP256K1_H */

View file

@ -1,11 +1,11 @@
#ifndef _SECP256K1_ECDH_ #ifndef SECP256K1_ECDH_H
# define _SECP256K1_ECDH_ #define SECP256K1_ECDH_H
# include "secp256k1.h" #include "secp256k1.h"
# ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
# endif #endif
/** Compute an EC Diffie-Hellman secret in constant time /** Compute an EC Diffie-Hellman secret in constant time
* Returns: 1: exponentiation was successful * Returns: 1: exponentiation was successful
@ -24,8 +24,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const unsigned char *privkey const unsigned char *privkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
# ifdef __cplusplus #ifdef __cplusplus
} }
# endif
#endif #endif
#endif /* SECP256K1_ECDH_H */

View file

@ -1,11 +1,11 @@
#ifndef _SECP256K1_RECOVERY_ #ifndef SECP256K1_RECOVERY_H
# define _SECP256K1_RECOVERY_ #define SECP256K1_RECOVERY_H
# include "secp256k1.h" #include "secp256k1.h"
# ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
# endif #endif
/** Opaque data structured that holds a parsed ECDSA signature, /** Opaque data structured that holds a parsed ECDSA signature,
* supporting pubkey recovery. * supporting pubkey recovery.
@ -103,8 +103,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
const unsigned char *msg32 const unsigned char *msg32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
# ifdef __cplusplus #ifdef __cplusplus
} }
# endif
#endif #endif
#endif /* SECP256K1_RECOVERY_H */

View file

@ -3,7 +3,7 @@
# to independently set assumptions on input or intermediary variables. # to independently set assumptions on input or intermediary variables.
# #
# The general approach is: # The general approach is:
# * A constraint is a tuple of two sets of of symbolic expressions: # * A constraint is a tuple of two sets of symbolic expressions:
# the first of which are required to evaluate to zero, the second of which # the first of which are required to evaluate to zero, the second of which
# are required to evaluate to nonzero. # are required to evaluate to nonzero.
# - A constraint is said to be conflicting if any of its nonzero expressions # - A constraint is said to be conflicting if any of its nonzero expressions
@ -17,7 +17,7 @@
# - A constraint describing the requirements of the law, called "require" # - A constraint describing the requirements of the law, called "require"
# * Implementations are transliterated into functions that operate as well on # * Implementations are transliterated into functions that operate as well on
# algebraic input points, and are called once per combination of branches # algebraic input points, and are called once per combination of branches
# exectured. Each execution returns: # executed. Each execution returns:
# - A constraint describing the assumptions this implementation requires # - A constraint describing the assumptions this implementation requires
# (such as Z1=1), called "assumeFormula" # (such as Z1=1), called "assumeFormula"
# - A constraint describing the assumptions this specific branch requires, # - A constraint describing the assumptions this specific branch requires,

View file

@ -11,7 +11,7 @@ Note:
- To avoid unnecessary loads and make use of available registers, two - To avoid unnecessary loads and make use of available registers, two
'passes' have every time been interleaved, with the odd passes accumulating c' and d' 'passes' have every time been interleaved, with the odd passes accumulating c' and d'
which will be added to c and d respectively in the the even passes which will be added to c and d respectively in the even passes
*/ */
@ -23,7 +23,7 @@ Note:
.eabi_attribute 10, 0 @ Tag_FP_arch = none .eabi_attribute 10, 0 @ Tag_FP_arch = none
.eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte
.eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP
.eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Agressive Speed .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Aggressive Speed
.eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6 .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6
.text .text

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_BASIC_CONFIG_ #ifndef SECP256K1_BASIC_CONFIG_H
#define _SECP256K1_BASIC_CONFIG_ #define SECP256K1_BASIC_CONFIG_H
#ifdef USE_BASIC_CONFIG #ifdef USE_BASIC_CONFIG
@ -28,5 +28,6 @@
#define USE_FIELD_10X26 1 #define USE_FIELD_10X26 1
#define USE_SCALAR_8X32 1 #define USE_SCALAR_8X32 1
#endif // USE_BASIC_CONFIG #endif /* USE_BASIC_CONFIG */
#endif // _SECP256K1_BASIC_CONFIG_
#endif /* SECP256K1_BASIC_CONFIG_H */

View file

@ -4,10 +4,11 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_BENCH_H_ #ifndef SECP256K1_BENCH_H
#define _SECP256K1_BENCH_H_ #define SECP256K1_BENCH_H
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <math.h> #include <math.h>
#include "sys/time.h" #include "sys/time.h"
@ -23,7 +24,7 @@ void print_number(double x) {
if (y < 0.0) { if (y < 0.0) {
y = -y; y = -y;
} }
while (y < 100.0) { while (y > 0 && y < 100.0) {
y *= 10.0; y *= 10.0;
c++; c++;
} }
@ -63,4 +64,19 @@ void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), v
printf("us\n"); printf("us\n");
} }
#endif int have_flag(int argc, char** argv, char *flag) {
char** argm = argv + argc;
argv++;
if (argv == argm) {
return 1;
}
while (argv != NULL && argv != argm) {
if (strcmp(*argv, flag) == 0) {
return 1;
}
argv++;
}
return 0;
}
#endif /* SECP256K1_BENCH_H */

View file

@ -15,11 +15,11 @@ typedef struct {
secp256k1_context *ctx; secp256k1_context *ctx;
secp256k1_pubkey point; secp256k1_pubkey point;
unsigned char scalar[32]; unsigned char scalar[32];
} bench_ecdh_t; } bench_ecdh_data;
static void bench_ecdh_setup(void* arg) { static void bench_ecdh_setup(void* arg) {
int i; int i;
bench_ecdh_t *data = (bench_ecdh_t*)arg; bench_ecdh_data *data = (bench_ecdh_data*)arg;
const unsigned char point[] = { const unsigned char point[] = {
0x03, 0x03,
0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06,
@ -39,7 +39,7 @@ static void bench_ecdh_setup(void* arg) {
static void bench_ecdh(void* arg) { static void bench_ecdh(void* arg) {
int i; int i;
unsigned char res[32]; unsigned char res[32];
bench_ecdh_t *data = (bench_ecdh_t*)arg; bench_ecdh_data *data = (bench_ecdh_data*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1);
@ -47,7 +47,7 @@ static void bench_ecdh(void* arg) {
} }
int main(void) { int main(void) {
bench_ecdh_t data; bench_ecdh_data data;
run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000);
return 0; return 0;

View file

@ -0,0 +1,196 @@
/**********************************************************************
* Copyright (c) 2017 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#include <stdio.h>
#include "include/secp256k1.h"
#include "util.h"
#include "hash_impl.h"
#include "num_impl.h"
#include "field_impl.h"
#include "group_impl.h"
#include "scalar_impl.h"
#include "ecmult_impl.h"
#include "bench.h"
#include "secp256k1.c"
#define POINTS 32768
#define ITERS 10000
typedef struct {
/* Setup once in advance */
secp256k1_context* ctx;
secp256k1_scratch_space* scratch;
secp256k1_scalar* scalars;
secp256k1_ge* pubkeys;
secp256k1_scalar* seckeys;
secp256k1_gej* expected_output;
secp256k1_ecmult_multi_func ecmult_multi;
/* Changes per test */
size_t count;
int includes_g;
/* Changes per test iteration */
size_t offset1;
size_t offset2;
/* Test output. */
secp256k1_gej* output;
} bench_data;
static int bench_callback(secp256k1_scalar* sc, secp256k1_ge* ge, size_t idx, void* arg) {
bench_data* data = (bench_data*)arg;
if (data->includes_g) ++idx;
if (idx == 0) {
*sc = data->scalars[data->offset1];
*ge = secp256k1_ge_const_g;
} else {
*sc = data->scalars[(data->offset1 + idx) % POINTS];
*ge = data->pubkeys[(data->offset2 + idx - 1) % POINTS];
}
return 1;
}
static void bench_ecmult(void* arg) {
bench_data* data = (bench_data*)arg;
size_t count = data->count;
int includes_g = data->includes_g;
size_t iters = 1 + ITERS / count;
size_t iter;
for (iter = 0; iter < iters; ++iter) {
data->ecmult_multi(&data->ctx->ecmult_ctx, data->scratch, &data->output[iter], data->includes_g ? &data->scalars[data->offset1] : NULL, bench_callback, arg, count - includes_g);
data->offset1 = (data->offset1 + count) % POINTS;
data->offset2 = (data->offset2 + count - 1) % POINTS;
}
}
static void bench_ecmult_setup(void* arg) {
bench_data* data = (bench_data*)arg;
data->offset1 = (data->count * 0x537b7f6f + 0x8f66a481) % POINTS;
data->offset2 = (data->count * 0x7f6f537b + 0x6a1a8f49) % POINTS;
}
static void bench_ecmult_teardown(void* arg) {
bench_data* data = (bench_data*)arg;
size_t iters = 1 + ITERS / data->count;
size_t iter;
/* Verify the results in teardown, to avoid doing comparisons while benchmarking. */
for (iter = 0; iter < iters; ++iter) {
secp256k1_gej tmp;
secp256k1_gej_add_var(&tmp, &data->output[iter], &data->expected_output[iter], NULL);
CHECK(secp256k1_gej_is_infinity(&tmp));
}
}
static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) {
secp256k1_sha256 sha256;
unsigned char c[11] = {'e', 'c', 'm', 'u', 'l', 't', 0, 0, 0, 0};
unsigned char buf[32];
int overflow = 0;
c[6] = num;
c[7] = num >> 8;
c[8] = num >> 16;
c[9] = num >> 24;
secp256k1_sha256_initialize(&sha256);
secp256k1_sha256_write(&sha256, c, sizeof(c));
secp256k1_sha256_finalize(&sha256, buf);
secp256k1_scalar_set_b32(scalar, buf, &overflow);
CHECK(!overflow);
}
static void run_test(bench_data* data, size_t count, int includes_g) {
char str[32];
static const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0);
size_t iters = 1 + ITERS / count;
size_t iter;
data->count = count;
data->includes_g = includes_g;
/* Compute (the negation of) the expected results directly. */
data->offset1 = (data->count * 0x537b7f6f + 0x8f66a481) % POINTS;
data->offset2 = (data->count * 0x7f6f537b + 0x6a1a8f49) % POINTS;
for (iter = 0; iter < iters; ++iter) {
secp256k1_scalar tmp;
secp256k1_scalar total = data->scalars[(data->offset1++) % POINTS];
size_t i = 0;
for (i = 0; i + 1 < count; ++i) {
secp256k1_scalar_mul(&tmp, &data->seckeys[(data->offset2++) % POINTS], &data->scalars[(data->offset1++) % POINTS]);
secp256k1_scalar_add(&total, &total, &tmp);
}
secp256k1_scalar_negate(&total, &total);
secp256k1_ecmult(&data->ctx->ecmult_ctx, &data->expected_output[iter], NULL, &zero, &total);
}
/* Run the benchmark. */
sprintf(str, includes_g ? "ecmult_%ig" : "ecmult_%i", (int)count);
run_benchmark(str, bench_ecmult, bench_ecmult_setup, bench_ecmult_teardown, data, 10, count * (1 + ITERS / count));
}
int main(int argc, char **argv) {
bench_data data;
int i, p;
secp256k1_gej* pubkeys_gej;
size_t scratch_size;
if (argc > 1) {
if(have_flag(argc, argv, "pippenger_wnaf")) {
printf("Using pippenger_wnaf:\n");
data.ecmult_multi = secp256k1_ecmult_pippenger_batch_single;
} else if(have_flag(argc, argv, "strauss_wnaf")) {
printf("Using strauss_wnaf:\n");
data.ecmult_multi = secp256k1_ecmult_strauss_batch_single;
}
} else {
data.ecmult_multi = secp256k1_ecmult_multi_var;
}
/* Allocate stuff */
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16;
data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size);
data.scalars = malloc(sizeof(secp256k1_scalar) * POINTS);
data.seckeys = malloc(sizeof(secp256k1_scalar) * POINTS);
data.pubkeys = malloc(sizeof(secp256k1_ge) * POINTS);
data.expected_output = malloc(sizeof(secp256k1_gej) * (ITERS + 1));
data.output = malloc(sizeof(secp256k1_gej) * (ITERS + 1));
/* Generate a set of scalars, and private/public keypairs. */
pubkeys_gej = malloc(sizeof(secp256k1_gej) * POINTS);
secp256k1_gej_set_ge(&pubkeys_gej[0], &secp256k1_ge_const_g);
secp256k1_scalar_set_int(&data.seckeys[0], 1);
for (i = 0; i < POINTS; ++i) {
generate_scalar(i, &data.scalars[i]);
if (i) {
secp256k1_gej_double_var(&pubkeys_gej[i], &pubkeys_gej[i - 1], NULL);
secp256k1_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]);
}
}
secp256k1_ge_set_all_gej_var(data.pubkeys, pubkeys_gej, POINTS, &data.ctx->error_callback);
free(pubkeys_gej);
for (i = 1; i <= 8; ++i) {
run_test(&data, i, 1);
}
for (p = 0; p <= 11; ++p) {
for (i = 9; i <= 16; ++i) {
run_test(&data, i << p, 1);
}
}
secp256k1_context_destroy(data.ctx);
secp256k1_scratch_space_destroy(data.scratch);
free(data.scalars);
free(data.pubkeys);
free(data.seckeys);
free(data.output);
free(data.expected_output);
return(0);
}

View file

@ -25,10 +25,10 @@ typedef struct {
secp256k1_gej gej_x, gej_y; secp256k1_gej gej_x, gej_y;
unsigned char data[64]; unsigned char data[64];
int wnaf[256]; int wnaf[256];
} bench_inv_t; } bench_inv;
void bench_setup(void* arg) { void bench_setup(void* arg) {
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
static const unsigned char init_x[32] = { static const unsigned char init_x[32] = {
0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13,
@ -58,7 +58,7 @@ void bench_setup(void* arg) {
void bench_scalar_add(void* arg) { void bench_scalar_add(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000000; i++) { for (i = 0; i < 2000000; i++) {
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
@ -67,7 +67,7 @@ void bench_scalar_add(void* arg) {
void bench_scalar_negate(void* arg) { void bench_scalar_negate(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000000; i++) { for (i = 0; i < 2000000; i++) {
secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x);
@ -76,7 +76,7 @@ void bench_scalar_negate(void* arg) {
void bench_scalar_sqr(void* arg) { void bench_scalar_sqr(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) { for (i = 0; i < 200000; i++) {
secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x);
@ -85,7 +85,7 @@ void bench_scalar_sqr(void* arg) {
void bench_scalar_mul(void* arg) { void bench_scalar_mul(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) { for (i = 0; i < 200000; i++) {
secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y);
@ -95,7 +95,7 @@ void bench_scalar_mul(void* arg) {
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
void bench_scalar_split(void* arg) { void bench_scalar_split(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_scalar l, r; secp256k1_scalar l, r;
@ -107,7 +107,7 @@ void bench_scalar_split(void* arg) {
void bench_scalar_inverse(void* arg) { void bench_scalar_inverse(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000; i++) { for (i = 0; i < 2000; i++) {
secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x);
@ -117,7 +117,7 @@ void bench_scalar_inverse(void* arg) {
void bench_scalar_inverse_var(void* arg) { void bench_scalar_inverse_var(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000; i++) { for (i = 0; i < 2000; i++) {
secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x);
@ -127,7 +127,7 @@ void bench_scalar_inverse_var(void* arg) {
void bench_field_normalize(void* arg) { void bench_field_normalize(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000000; i++) { for (i = 0; i < 2000000; i++) {
secp256k1_fe_normalize(&data->fe_x); secp256k1_fe_normalize(&data->fe_x);
@ -136,7 +136,7 @@ void bench_field_normalize(void* arg) {
void bench_field_normalize_weak(void* arg) { void bench_field_normalize_weak(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 2000000; i++) { for (i = 0; i < 2000000; i++) {
secp256k1_fe_normalize_weak(&data->fe_x); secp256k1_fe_normalize_weak(&data->fe_x);
@ -145,7 +145,7 @@ void bench_field_normalize_weak(void* arg) {
void bench_field_mul(void* arg) { void bench_field_mul(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) { for (i = 0; i < 200000; i++) {
secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y);
@ -154,7 +154,7 @@ void bench_field_mul(void* arg) {
void bench_field_sqr(void* arg) { void bench_field_sqr(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) { for (i = 0; i < 200000; i++) {
secp256k1_fe_sqr(&data->fe_x, &data->fe_x); secp256k1_fe_sqr(&data->fe_x, &data->fe_x);
@ -163,7 +163,7 @@ void bench_field_sqr(void* arg) {
void bench_field_inverse(void* arg) { void bench_field_inverse(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_fe_inv(&data->fe_x, &data->fe_x); secp256k1_fe_inv(&data->fe_x, &data->fe_x);
@ -173,7 +173,7 @@ void bench_field_inverse(void* arg) {
void bench_field_inverse_var(void* arg) { void bench_field_inverse_var(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); secp256k1_fe_inv_var(&data->fe_x, &data->fe_x);
@ -183,7 +183,7 @@ void bench_field_inverse_var(void* arg) {
void bench_field_sqrt(void* arg) { void bench_field_sqrt(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); secp256k1_fe_sqrt(&data->fe_x, &data->fe_x);
@ -193,7 +193,7 @@ void bench_field_sqrt(void* arg) {
void bench_group_double_var(void* arg) { void bench_group_double_var(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) { for (i = 0; i < 200000; i++) {
secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL);
@ -202,7 +202,7 @@ void bench_group_double_var(void* arg) {
void bench_group_add_var(void* arg) { void bench_group_add_var(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) { for (i = 0; i < 200000; i++) {
secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL);
@ -211,7 +211,7 @@ void bench_group_add_var(void* arg) {
void bench_group_add_affine(void* arg) { void bench_group_add_affine(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) { for (i = 0; i < 200000; i++) {
secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y);
@ -220,7 +220,7 @@ void bench_group_add_affine(void* arg) {
void bench_group_add_affine_var(void* arg) { void bench_group_add_affine_var(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 200000; i++) { for (i = 0; i < 200000; i++) {
secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL);
@ -229,7 +229,7 @@ void bench_group_add_affine_var(void* arg) {
void bench_group_jacobi_var(void* arg) { void bench_group_jacobi_var(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_gej_has_quad_y_var(&data->gej_x); secp256k1_gej_has_quad_y_var(&data->gej_x);
@ -238,7 +238,7 @@ void bench_group_jacobi_var(void* arg) {
void bench_ecmult_wnaf(void* arg) { void bench_ecmult_wnaf(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A);
@ -248,10 +248,10 @@ void bench_ecmult_wnaf(void* arg) {
void bench_wnaf_const(void* arg) { void bench_wnaf_const(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A, 256);
secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y);
} }
} }
@ -259,8 +259,8 @@ void bench_wnaf_const(void* arg) {
void bench_sha256(void* arg) { void bench_sha256(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_sha256_t sha; secp256k1_sha256 sha;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_sha256_initialize(&sha); secp256k1_sha256_initialize(&sha);
@ -271,8 +271,8 @@ void bench_sha256(void* arg) {
void bench_hmac_sha256(void* arg) { void bench_hmac_sha256(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_hmac_sha256_t hmac; secp256k1_hmac_sha256 hmac;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); secp256k1_hmac_sha256_initialize(&hmac, data->data, 32);
@ -283,8 +283,8 @@ void bench_hmac_sha256(void* arg) {
void bench_rfc6979_hmac_sha256(void* arg) { void bench_rfc6979_hmac_sha256(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_rfc6979_hmac_sha256_t rng; secp256k1_rfc6979_hmac_sha256 rng;
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64);
@ -311,7 +311,7 @@ void bench_context_sign(void* arg) {
#ifndef USE_NUM_NONE #ifndef USE_NUM_NONE
void bench_num_jacobi(void* arg) { void bench_num_jacobi(void* arg) {
int i; int i;
bench_inv_t *data = (bench_inv_t*)arg; bench_inv *data = (bench_inv*)arg;
secp256k1_num nx, norder; secp256k1_num nx, norder;
secp256k1_scalar_get_num(&nx, &data->scalar_x); secp256k1_scalar_get_num(&nx, &data->scalar_x);
@ -324,23 +324,8 @@ void bench_num_jacobi(void* arg) {
} }
#endif #endif
int have_flag(int argc, char** argv, char *flag) {
char** argm = argv + argc;
argv++;
if (argv == argm) {
return 1;
}
while (argv != NULL && argv != argm) {
if (strcmp(*argv, flag) == 0) {
return 1;
}
argv++;
}
return 0;
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
bench_inv_t data; bench_inv data;
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000);
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000);
if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000);

View file

@ -13,11 +13,11 @@ typedef struct {
secp256k1_context *ctx; secp256k1_context *ctx;
unsigned char msg[32]; unsigned char msg[32];
unsigned char sig[64]; unsigned char sig[64];
} bench_recover_t; } bench_recover_data;
void bench_recover(void* arg) { void bench_recover(void* arg) {
int i; int i;
bench_recover_t *data = (bench_recover_t*)arg; bench_recover_data *data = (bench_recover_data*)arg;
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
unsigned char pubkeyc[33]; unsigned char pubkeyc[33];
@ -38,7 +38,7 @@ void bench_recover(void* arg) {
void bench_recover_setup(void* arg) { void bench_recover_setup(void* arg) {
int i; int i;
bench_recover_t *data = (bench_recover_t*)arg; bench_recover_data *data = (bench_recover_data*)arg;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
data->msg[i] = 1 + i; data->msg[i] = 1 + i;
@ -49,7 +49,7 @@ void bench_recover_setup(void* arg) {
} }
int main(void) { int main(void) {
bench_recover_t data; bench_recover_data data;
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);

View file

@ -1,73 +0,0 @@
/**********************************************************************
* Copyright (c) 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#include <stdio.h>
#include <string.h>
#include "include/secp256k1.h"
#include "include/secp256k1_schnorr.h"
#include "util.h"
#include "bench.h"
typedef struct {
unsigned char key[32];
unsigned char sig[64];
unsigned char pubkey[33];
size_t pubkeylen;
} benchmark_schnorr_sig_t;
typedef struct {
secp256k1_context *ctx;
unsigned char msg[32];
benchmark_schnorr_sig_t sigs[64];
int numsigs;
} benchmark_schnorr_verify_t;
static void benchmark_schnorr_init(void* arg) {
int i, k;
benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg;
for (i = 0; i < 32; i++) {
data->msg[i] = 1 + i;
}
for (k = 0; k < data->numsigs; k++) {
secp256k1_pubkey pubkey;
for (i = 0; i < 32; i++) {
data->sigs[k].key[i] = 33 + i + k;
}
secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL);
data->sigs[k].pubkeylen = 33;
CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key));
CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED));
}
}
static void benchmark_schnorr_verify(void* arg) {
int i;
benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg;
for (i = 0; i < 20000 / data->numsigs; i++) {
secp256k1_pubkey pubkey;
data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF);
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen));
CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0));
data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF);
}
}
int main(void) {
benchmark_schnorr_verify_t data;
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
data.numsigs = 1;
run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000);
secp256k1_context_destroy(data.ctx);
return 0;
}

View file

@ -12,11 +12,11 @@ typedef struct {
secp256k1_context* ctx; secp256k1_context* ctx;
unsigned char msg[32]; unsigned char msg[32];
unsigned char key[32]; unsigned char key[32];
} bench_sign_t; } bench_sign;
static void bench_sign_setup(void* arg) { static void bench_sign_setup(void* arg) {
int i; int i;
bench_sign_t *data = (bench_sign_t*)arg; bench_sign *data = (bench_sign*)arg;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
data->msg[i] = i + 1; data->msg[i] = i + 1;
@ -26,9 +26,9 @@ static void bench_sign_setup(void* arg) {
} }
} }
static void bench_sign(void* arg) { static void bench_sign_run(void* arg) {
int i; int i;
bench_sign_t *data = (bench_sign_t*)arg; bench_sign *data = (bench_sign*)arg;
unsigned char sig[74]; unsigned char sig[74];
for (i = 0; i < 20000; i++) { for (i = 0; i < 20000; i++) {
@ -45,11 +45,11 @@ static void bench_sign(void* arg) {
} }
int main(void) { int main(void) {
bench_sign_t data; bench_sign data;
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000); run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, 20000);
secp256k1_context_destroy(data.ctx); secp256k1_context_destroy(data.ctx);
return 0; return 0;

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_ECDSA_ #ifndef SECP256K1_ECDSA_H
#define _SECP256K1_ECDSA_ #define SECP256K1_ECDSA_H
#include <stddef.h> #include <stddef.h>
@ -18,4 +18,4 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message);
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid);
#endif #endif /* SECP256K1_ECDSA_H */

View file

@ -5,8 +5,8 @@
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_ECDSA_IMPL_H_ #ifndef SECP256K1_ECDSA_IMPL_H
#define _SECP256K1_ECDSA_IMPL_H_ #define SECP256K1_ECDSA_IMPL_H
#include "scalar.h" #include "scalar.h"
#include "field.h" #include "field.h"
@ -81,8 +81,6 @@ static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned cha
return -1; return -1;
} }
while (lenleft > 0) { while (lenleft > 0) {
if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) {
}
ret = (ret << 8) | **sigp; ret = (ret << 8) | **sigp;
if (ret + lenleft > (size_t)(sigend - *sigp)) { if (ret + lenleft > (size_t)(sigend - *sigp)) {
/* Result exceeds the length of the passed array. */ /* Result exceeds the length of the passed array. */
@ -312,4 +310,4 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec
return 1; return 1;
} }
#endif #endif /* SECP256K1_ECDSA_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_ECKEY_ #ifndef SECP256K1_ECKEY_H
#define _SECP256K1_ECKEY_ #define SECP256K1_ECKEY_H
#include <stddef.h> #include <stddef.h>
@ -22,4 +22,4 @@ static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx,
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak);
#endif #endif /* SECP256K1_ECKEY_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_ECKEY_IMPL_H_ #ifndef SECP256K1_ECKEY_IMPL_H
#define _SECP256K1_ECKEY_IMPL_H_ #define SECP256K1_ECKEY_IMPL_H
#include "eckey.h" #include "eckey.h"
@ -15,16 +15,17 @@
#include "ecmult_gen.h" #include "ecmult_gen.h"
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) {
secp256k1_fe x; secp256k1_fe x;
return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03); return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
secp256k1_fe x, y; secp256k1_fe x, y;
if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) { if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) {
return 0; return 0;
} }
secp256k1_ge_set_xy(elem, &x, &y); secp256k1_ge_set_xy(elem, &x, &y);
if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) { if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) &&
secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
return 0; return 0;
} }
return secp256k1_ge_is_valid_var(elem); return secp256k1_ge_is_valid_var(elem);
@ -42,10 +43,10 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *p
secp256k1_fe_get_b32(&pub[1], &elem->x); secp256k1_fe_get_b32(&pub[1], &elem->x);
if (compressed) { if (compressed) {
*size = 33; *size = 33;
pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
} else { } else {
*size = 65; *size = 65;
pub[0] = 0x04; pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED;
secp256k1_fe_get_b32(&pub[33], &elem->y); secp256k1_fe_get_b32(&pub[33], &elem->y);
} }
return 1; return 1;
@ -96,4 +97,4 @@ static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx,
return 1; return 1;
} }
#endif #endif /* SECP256K1_ECKEY_IMPL_H */

View file

@ -1,14 +1,16 @@
/********************************************************************** /**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille * * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra *
* Distributed under the MIT software license, see the accompanying * * Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_ECMULT_ #ifndef SECP256K1_ECMULT_H
#define _SECP256K1_ECMULT_ #define SECP256K1_ECMULT_H
#include "num.h" #include "num.h"
#include "group.h" #include "group.h"
#include "scalar.h"
#include "scratch.h"
typedef struct { typedef struct {
/* For accelerating the computation of a*P + b*G: */ /* For accelerating the computation of a*P + b*G: */
@ -28,4 +30,18 @@ static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx
/** Double multiply: R = na*A + ng*G */ /** Double multiply: R = na*A + ng*G */
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng);
#endif typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data);
/**
* Multi-multiply: R = inp_g_sc * G + sum_i ni * Ai.
* Chooses the right algorithm for a given number of points and scratch space
* size. Resets and overwrites the given scratch space. If the points do not
* fit in the scratch space the algorithm is repeatedly run with batches of
* points.
* Returns: 1 on success (including when inp_g_sc is NULL and n is 0)
* 0 if there is not enough scratch space for a single point or
* callback returns 0
*/
static int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n);
#endif /* SECP256K1_ECMULT_H */

View file

@ -4,12 +4,14 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_ECMULT_CONST_ #ifndef SECP256K1_ECMULT_CONST_H
#define _SECP256K1_ECMULT_CONST_ #define SECP256K1_ECMULT_CONST_H
#include "scalar.h" #include "scalar.h"
#include "group.h" #include "group.h"
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); /* Here `bits` should be set to the maximum bitlength of the _absolute value_ of `q`, plus
* one because we internally sometimes add 2 to the number during the WNAF conversion. */
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q, int bits);
#endif #endif /* SECP256K1_ECMULT_CONST_H */

View file

@ -4,21 +4,14 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_ECMULT_CONST_IMPL_ #ifndef SECP256K1_ECMULT_CONST_IMPL_H
#define _SECP256K1_ECMULT_CONST_IMPL_ #define SECP256K1_ECMULT_CONST_IMPL_H
#include "scalar.h" #include "scalar.h"
#include "group.h" #include "group.h"
#include "ecmult_const.h" #include "ecmult_const.h"
#include "ecmult_impl.h" #include "ecmult_impl.h"
#ifdef USE_ENDOMORPHISM
#define WNAF_BITS 128
#else
#define WNAF_BITS 256
#endif
#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w))
/* This is like `ECMULT_TABLE_GET_GE` but is constant time */ /* This is like `ECMULT_TABLE_GET_GE` but is constant time */
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ #define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \
int m; \ int m; \
@ -42,11 +35,12 @@
} while(0) } while(0)
/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val) /** Convert a number to WNAF notation.
* with the following guarantees: * The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val.
* It has the following guarantees:
* - each wnaf[i] an odd integer between -(1 << w) and (1 << w) * - each wnaf[i] an odd integer between -(1 << w) and (1 << w)
* - each wnaf[i] is nonzero * - each wnaf[i] is nonzero
* - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w * - the number of words set is always WNAF_SIZE(w) + 1
* *
* Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar
* Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.)
@ -54,7 +48,7 @@
* *
* Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 * Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335
*/ */
static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w, int size) {
int global_sign; int global_sign;
int skew = 0; int skew = 0;
int word = 0; int word = 0;
@ -73,9 +67,14 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) {
* and we'd lose any performance benefit. Instead, we use a technique from * and we'd lose any performance benefit. Instead, we use a technique from
* Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even) * Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even)
* or 2 (for odd) to the number we are encoding, returning a skew value indicating * or 2 (for odd) to the number we are encoding, returning a skew value indicating
* this, and having the caller compensate after doing the multiplication. */ * this, and having the caller compensate after doing the multiplication.
*
/* Negative numbers will be negated to keep their bit representation below the maximum width */ * In fact, we _do_ want to negate numbers to minimize their bit-lengths (and in
* particular, to ensure that the outputs from the endomorphism-split fit into
* 128 bits). If we negate, the parity of our number flips, inverting which of
* {1, 2} we want to add to the scalar when ensuring that it's odd. Further
* complicating things, -1 interacts badly with `secp256k1_scalar_cadd_bit` and
* we need to special-case it in this logic. */
flip = secp256k1_scalar_is_high(&s); flip = secp256k1_scalar_is_high(&s);
/* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */
bit = flip ^ !secp256k1_scalar_is_even(&s); bit = flip ^ !secp256k1_scalar_is_even(&s);
@ -94,7 +93,7 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) {
/* 4 */ /* 4 */
u_last = secp256k1_scalar_shr_int(&s, w); u_last = secp256k1_scalar_shr_int(&s, w);
while (word * w < WNAF_BITS) { while (word * w < size) {
int sign; int sign;
int even; int even;
@ -114,37 +113,44 @@ static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) {
wnaf[word] = u * global_sign; wnaf[word] = u * global_sign;
VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); VERIFY_CHECK(secp256k1_scalar_is_zero(&s));
VERIFY_CHECK(word == WNAF_SIZE(w)); VERIFY_CHECK(word == WNAF_SIZE_BITS(size, w));
return skew; return skew;
} }
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar, int size) {
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) {
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge tmpa; secp256k1_ge tmpa;
secp256k1_fe Z; secp256k1_fe Z;
int skew_1; int skew_1;
int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)];
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)];
int skew_lam; int skew_lam;
secp256k1_scalar q_1, q_lam; secp256k1_scalar q_1, q_lam;
#endif #endif
int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)];
int i; int i;
secp256k1_scalar sc = *scalar; secp256k1_scalar sc = *scalar;
/* build wnaf representation for q. */ /* build wnaf representation for q. */
int rsize = size;
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
if (size > 128) {
rsize = 128;
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc);
skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1, 128);
skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1, 128);
#else } else
skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1);
#endif #endif
{
skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1, size);
#ifdef USE_ENDOMORPHISM
skew_lam = 0;
#endif
}
/* Calculate odd multiples of a. /* Calculate odd multiples of a.
* All multiples are brought to the same Z 'denominator', which is stored * All multiples are brought to the same Z 'denominator', which is stored
@ -158,26 +164,30 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
secp256k1_fe_normalize_weak(&pre_a[i].y); secp256k1_fe_normalize_weak(&pre_a[i].y);
} }
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
if (size > 128) {
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
} }
}
#endif #endif
/* first loop iteration (separated out so we can directly set r, rather /* first loop iteration (separated out so we can directly set r, rather
* than having it start at infinity, get doubled several times, then have * than having it start at infinity, get doubled several times, then have
* its new value added to it) */ * its new value added to it) */
i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; i = wnaf_1[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
VERIFY_CHECK(i != 0); VERIFY_CHECK(i != 0);
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
secp256k1_gej_set_ge(r, &tmpa); secp256k1_gej_set_ge(r, &tmpa);
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; if (size > 128) {
i = wnaf_lam[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
VERIFY_CHECK(i != 0); VERIFY_CHECK(i != 0);
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
secp256k1_gej_add_ge(r, r, &tmpa); secp256k1_gej_add_ge(r, r, &tmpa);
}
#endif #endif
/* remaining loop iterations */ /* remaining loop iterations */
for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { for (i = WNAF_SIZE_BITS(rsize, WINDOW_A - 1) - 1; i >= 0; i--) {
int n; int n;
int j; int j;
for (j = 0; j < WINDOW_A - 1; ++j) { for (j = 0; j < WINDOW_A - 1; ++j) {
@ -189,10 +199,12 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
VERIFY_CHECK(n != 0); VERIFY_CHECK(n != 0);
secp256k1_gej_add_ge(r, r, &tmpa); secp256k1_gej_add_ge(r, r, &tmpa);
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
if (size > 128) {
n = wnaf_lam[i]; n = wnaf_lam[i];
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
VERIFY_CHECK(n != 0); VERIFY_CHECK(n != 0);
secp256k1_gej_add_ge(r, r, &tmpa); secp256k1_gej_add_ge(r, r, &tmpa);
}
#endif #endif
} }
@ -212,14 +224,18 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
secp256k1_ge_set_gej(&correction, &tmpj); secp256k1_ge_set_gej(&correction, &tmpj);
secp256k1_ge_to_storage(&correction_1_stor, a); secp256k1_ge_to_storage(&correction_1_stor, a);
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
if (size > 128) {
secp256k1_ge_to_storage(&correction_lam_stor, a); secp256k1_ge_to_storage(&correction_lam_stor, a);
}
#endif #endif
secp256k1_ge_to_storage(&a2_stor, &correction); secp256k1_ge_to_storage(&a2_stor, &correction);
/* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */
secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2);
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
if (size > 128) {
secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2);
}
#endif #endif
/* Apply the correction */ /* Apply the correction */
@ -228,12 +244,14 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
secp256k1_gej_add_ge(r, r, &correction); secp256k1_gej_add_ge(r, r, &correction);
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
if (size > 128) {
secp256k1_ge_from_storage(&correction, &correction_lam_stor); secp256k1_ge_from_storage(&correction, &correction_lam_stor);
secp256k1_ge_neg(&correction, &correction); secp256k1_ge_neg(&correction, &correction);
secp256k1_ge_mul_lambda(&correction, &correction); secp256k1_ge_mul_lambda(&correction, &correction);
secp256k1_gej_add_ge(r, r, &correction); secp256k1_gej_add_ge(r, r, &correction);
}
#endif #endif
} }
} }
#endif #endif /* SECP256K1_ECMULT_CONST_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_ECMULT_GEN_ #ifndef SECP256K1_ECMULT_GEN_H
#define _SECP256K1_ECMULT_GEN_ #define SECP256K1_ECMULT_GEN_H
#include "scalar.h" #include "scalar.h"
#include "group.h" #include "group.h"
@ -40,4 +40,4 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp25
static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32);
#endif #endif /* SECP256K1_ECMULT_GEN_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#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 "scalar.h" #include "scalar.h"
#include "group.h" #include "group.h"
@ -161,7 +161,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
secp256k1_gej gb; secp256k1_gej gb;
secp256k1_fe s; secp256k1_fe s;
unsigned char nonce32[32]; unsigned char nonce32[32];
secp256k1_rfc6979_hmac_sha256_t rng; secp256k1_rfc6979_hmac_sha256 rng;
int retry; int retry;
unsigned char keydata[64] = {0}; unsigned char keydata[64] = {0};
if (seed32 == NULL) { if (seed32 == NULL) {
@ -207,4 +207,4 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
secp256k1_gej_clear(&gb); secp256k1_gej_clear(&gb);
} }
#endif #endif /* SECP256K1_ECMULT_GEN_IMPL_H */

View file

@ -1,13 +1,14 @@
/********************************************************************** /*****************************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille * * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra, Jonas Nick *
* Distributed under the MIT software license, see the accompanying * * Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php. *
**********************************************************************/ *****************************************************************************/
#ifndef _SECP256K1_ECMULT_IMPL_H_ #ifndef SECP256K1_ECMULT_IMPL_H
#define _SECP256K1_ECMULT_IMPL_H_ #define SECP256K1_ECMULT_IMPL_H
#include <string.h> #include <string.h>
#include <stdint.h>
#include "group.h" #include "group.h"
#include "scalar.h" #include "scalar.h"
@ -41,9 +42,36 @@
#endif #endif
#endif #endif
#ifdef USE_ENDOMORPHISM
#define WNAF_BITS 128
#else
#define WNAF_BITS 256
#endif
#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w))
#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w)
/** The number of entries a table with precomputed multiples needs to have. */ /** The number of entries a table with precomputed multiples needs to have. */
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) #define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
/* The number of objects allocated on the scratch space for ecmult_multi algorithms */
#define PIPPENGER_SCRATCH_OBJECTS 6
#define STRAUSS_SCRATCH_OBJECTS 6
#define PIPPENGER_MAX_BUCKET_WINDOW 12
/* Minimum number of points for which pippenger_wnaf is faster than strauss wnaf */
#ifdef USE_ENDOMORPHISM
#define ECMULT_PIPPENGER_THRESHOLD 88
#else
#define ECMULT_PIPPENGER_THRESHOLD 160
#endif
#ifdef USE_ENDOMORPHISM
#define ECMULT_MAX_POINTS_PER_BATCH 5000000
#else
#define ECMULT_MAX_POINTS_PER_BATCH 10000000
#endif
/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain /** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain
* the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will
* contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z.
@ -283,50 +311,78 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a,
return last_set_bit + 1; return last_set_bit + 1;
} }
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { struct secp256k1_strauss_point_state {
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge tmpa;
secp256k1_fe Z;
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_scalar na_1, na_lam; secp256k1_scalar na_1, na_lam;
/* Splitted G factors. */
secp256k1_scalar ng_1, ng_128;
int wnaf_na_1[130]; int wnaf_na_1[130];
int wnaf_na_lam[130]; int wnaf_na_lam[130];
int bits_na_1; int bits_na_1;
int bits_na_lam; int bits_na_lam;
int wnaf_ng_1[129];
int bits_ng_1;
int wnaf_ng_128[129];
int bits_ng_128;
#else #else
int wnaf_na[256]; int wnaf_na[256];
int bits_na; int bits_na;
#endif
size_t input_pos;
};
struct secp256k1_strauss_state {
secp256k1_gej* prej;
secp256k1_fe* zr;
secp256k1_ge* pre_a;
#ifdef USE_ENDOMORPHISM
secp256k1_ge* pre_a_lam;
#endif
struct secp256k1_strauss_point_state* ps;
};
static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, int num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_ge tmpa;
secp256k1_fe Z;
#ifdef USE_ENDOMORPHISM
/* Splitted G factors. */
secp256k1_scalar ng_1, ng_128;
int wnaf_ng_1[129];
int bits_ng_1 = 0;
int wnaf_ng_128[129];
int bits_ng_128 = 0;
#else
int wnaf_ng[256]; int wnaf_ng[256];
int bits_ng; int bits_ng = 0;
#endif #endif
int i; int i;
int bits; int bits = 0;
int np;
int no = 0;
for (np = 0; np < num; ++np) {
if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) {
continue;
}
state->ps[no].input_pos = np;
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
/* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */
secp256k1_scalar_split_lambda(&na_1, &na_lam, na); secp256k1_scalar_split_lambda(&state->ps[no].na_1, &state->ps[no].na_lam, &na[np]);
/* build wnaf representation for na_1 and na_lam. */ /* build wnaf representation for na_1 and na_lam. */
bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 130, &state->ps[no].na_1, WINDOW_A);
bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 130, &state->ps[no].na_lam, WINDOW_A);
VERIFY_CHECK(bits_na_1 <= 130); VERIFY_CHECK(state->ps[no].bits_na_1 <= 130);
VERIFY_CHECK(bits_na_lam <= 130); VERIFY_CHECK(state->ps[no].bits_na_lam <= 130);
bits = bits_na_1; if (state->ps[no].bits_na_1 > bits) {
if (bits_na_lam > bits) { bits = state->ps[no].bits_na_1;
bits = bits_na_lam; }
if (state->ps[no].bits_na_lam > bits) {
bits = state->ps[no].bits_na_lam;
} }
#else #else
/* build wnaf representation for na. */ /* build wnaf representation for na. */
bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); state->ps[no].bits_na = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na, 256, &na[np], WINDOW_A);
bits = bits_na; if (state->ps[no].bits_na > bits) {
bits = state->ps[no].bits_na;
}
#endif #endif
++no;
}
/* Calculate odd multiples of a. /* Calculate odd multiples of a.
* All multiples are brought to the same Z 'denominator', which is stored * All multiples are brought to the same Z 'denominator', which is stored
@ -338,13 +394,32 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
* of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same
* isomorphism to efficiently add with a known Z inverse. * isomorphism to efficiently add with a known Z inverse.
*/ */
secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); if (no > 0) {
/* Compute the odd multiples in Jacobian form. */
#ifdef USE_ENDOMORPHISM secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej, state->zr, &a[state->ps[0].input_pos]);
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { for (np = 1; np < no; ++np) {
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); secp256k1_gej tmp = a[state->ps[np].input_pos];
#ifdef VERIFY
secp256k1_fe_normalize_var(&(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z));
#endif
secp256k1_gej_rescale(&tmp, &(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z));
secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &tmp);
secp256k1_fe_mul(state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), state->zr + np * ECMULT_TABLE_SIZE(WINDOW_A), &(a[state->ps[np].input_pos].z));
}
/* Bring them to the same Z denominator. */
secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, &Z, state->prej, state->zr);
} else {
secp256k1_fe_set_int(&Z, 1);
} }
#ifdef USE_ENDOMORPHISM
for (np = 0; np < no; ++np) {
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
secp256k1_ge_mul_lambda(&state->pre_a_lam[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i]);
}
}
if (ng) {
/* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */
secp256k1_scalar_split_128(&ng_1, &ng_128, ng); secp256k1_scalar_split_128(&ng_1, &ng_128, ng);
@ -357,11 +432,14 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
if (bits_ng_128 > bits) { if (bits_ng_128 > bits) {
bits = bits_ng_128; bits = bits_ng_128;
} }
}
#else #else
if (ng) {
bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G);
if (bits_ng > bits) { if (bits_ng > bits) {
bits = bits_ng; bits = bits_ng;
} }
}
#endif #endif
secp256k1_gej_set_infinity(r); secp256k1_gej_set_infinity(r);
@ -370,14 +448,16 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
int n; int n;
secp256k1_gej_double_var(r, r, NULL); secp256k1_gej_double_var(r, r, NULL);
#ifdef USE_ENDOMORPHISM #ifdef USE_ENDOMORPHISM
if (i < bits_na_1 && (n = wnaf_na_1[i])) { for (np = 0; np < no; ++np) {
ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); if (i < state->ps[np].bits_na_1 && (n = state->ps[np].wnaf_na_1[i])) {
ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
} }
if (i < bits_na_lam && (n = wnaf_na_lam[i])) { if (i < state->ps[np].bits_na_lam && (n = state->ps[np].wnaf_na_lam[i])) {
ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); ECMULT_TABLE_GET_GE(&tmpa, state->pre_a_lam + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
} }
}
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
@ -387,10 +467,12 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
} }
#else #else
if (i < bits_na && (n = wnaf_na[i])) { for (np = 0; np < no; ++np) {
ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); if (i < state->ps[np].bits_na && (n = state->ps[np].wnaf_na[i])) {
ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A);
secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); secp256k1_gej_add_ge_var(r, r, &tmpa, NULL);
} }
}
if (i < bits_ng && (n = wnaf_ng[i])) { if (i < bits_ng && (n = wnaf_ng[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z);
@ -403,4 +485,543 @@ static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej
} }
} }
static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
struct secp256k1_strauss_point_state ps[1];
#ifdef USE_ENDOMORPHISM
secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
#endif #endif
struct secp256k1_strauss_state state;
state.prej = prej;
state.zr = zr;
state.pre_a = pre_a;
#ifdef USE_ENDOMORPHISM
state.pre_a_lam = pre_a_lam;
#endif
state.ps = ps;
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng);
}
static size_t secp256k1_strauss_scratch_size(size_t n_points) {
#ifdef USE_ENDOMORPHISM
static const size_t point_size = (2 * sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar);
#else
static const size_t point_size = (sizeof(secp256k1_ge) + sizeof(secp256k1_gej) + sizeof(secp256k1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct secp256k1_strauss_point_state) + sizeof(secp256k1_gej) + sizeof(secp256k1_scalar);
#endif
return n_points*point_size;
}
static int secp256k1_ecmult_strauss_batch(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
secp256k1_gej* points;
secp256k1_scalar* scalars;
struct secp256k1_strauss_state state;
size_t i;
secp256k1_gej_set_infinity(r);
if (inp_g_sc == NULL && n_points == 0) {
return 1;
}
if (!secp256k1_scratch_allocate_frame(scratch, secp256k1_strauss_scratch_size(n_points), STRAUSS_SCRATCH_OBJECTS)) {
return 0;
}
points = (secp256k1_gej*)secp256k1_scratch_alloc(scratch, n_points * sizeof(secp256k1_gej));
scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(scratch, n_points * sizeof(secp256k1_scalar));
state.prej = (secp256k1_gej*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_gej));
state.zr = (secp256k1_fe*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe));
#ifdef USE_ENDOMORPHISM
state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(scratch, n_points * 2 * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
state.pre_a_lam = state.pre_a + n_points * ECMULT_TABLE_SIZE(WINDOW_A);
#else
state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge));
#endif
state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(scratch, n_points * sizeof(struct secp256k1_strauss_point_state));
for (i = 0; i < n_points; i++) {
secp256k1_ge point;
if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) {
secp256k1_scratch_deallocate_frame(scratch);
return 0;
}
secp256k1_gej_set_ge(&points[i], &point);
}
secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc);
secp256k1_scratch_deallocate_frame(scratch);
return 1;
}
/* Wrapper for secp256k1_ecmult_multi_func interface */
static int secp256k1_ecmult_strauss_batch_single(const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_strauss_batch(actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
}
static size_t secp256k1_strauss_max_points(secp256k1_scratch *scratch) {
return secp256k1_scratch_max_allocation(scratch, STRAUSS_SCRATCH_OBJECTS) / secp256k1_strauss_scratch_size(1);
}
/** Convert a number to WNAF notation.
* The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val.
* It has the following guarantees:
* - each wnaf[i] is either 0 or an odd integer between -(1 << w) and (1 << w)
* - the number of words set is always WNAF_SIZE(w)
* - the returned skew is 0 or 1
*/
static int secp256k1_wnaf_fixed(int *wnaf, const secp256k1_scalar *s, int w) {
int skew = 0;
int pos;
int max_pos;
int last_w;
const secp256k1_scalar *work = s;
if (secp256k1_scalar_is_zero(s)) {
for (pos = 0; pos < WNAF_SIZE(w); pos++) {
wnaf[pos] = 0;
}
return 0;
}
if (secp256k1_scalar_is_even(s)) {
skew = 1;
}
wnaf[0] = secp256k1_scalar_get_bits_var(work, 0, w) + skew;
/* Compute last window size. Relevant when window size doesn't divide the
* number of bits in the scalar */
last_w = WNAF_BITS - (WNAF_SIZE(w) - 1) * w;
/* Store the position of the first nonzero word in max_pos to allow
* skipping leading zeros when calculating the wnaf. */
for (pos = WNAF_SIZE(w) - 1; pos > 0; pos--) {
int val = secp256k1_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w);
if(val != 0) {
break;
}
wnaf[pos] = 0;
}
max_pos = pos;
pos = 1;
while (pos <= max_pos) {
int val = secp256k1_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w);
if ((val & 1) == 0) {
wnaf[pos - 1] -= (1 << w);
wnaf[pos] = (val + 1);
} else {
wnaf[pos] = val;
}
/* Set a coefficient to zero if it is 1 or -1 and the proceeding digit
* is strictly negative or strictly positive respectively. Only change
* coefficients at previous positions because above code assumes that
* wnaf[pos - 1] is odd.
*/
if (pos >= 2 && ((wnaf[pos - 1] == 1 && wnaf[pos - 2] < 0) || (wnaf[pos - 1] == -1 && wnaf[pos - 2] > 0))) {
if (wnaf[pos - 1] == 1) {
wnaf[pos - 2] += 1 << w;
} else {
wnaf[pos - 2] -= 1 << w;
}
wnaf[pos - 1] = 0;
}
++pos;
}
return skew;
}
struct secp256k1_pippenger_point_state {
int skew_na;
size_t input_pos;
};
struct secp256k1_pippenger_state {
int *wnaf_na;
struct secp256k1_pippenger_point_state* ps;
};
/*
* pippenger_wnaf computes the result of a multi-point multiplication as
* follows: The scalars are brought into wnaf with n_wnaf elements each. Then
* for every i < n_wnaf, first each point is added to a "bucket" corresponding
* to the point's wnaf[i]. Second, the buckets are added together such that
* r += 1*bucket[0] + 3*bucket[1] + 5*bucket[2] + ...
*/
static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *r, const secp256k1_scalar *sc, const secp256k1_ge *pt, size_t num) {
size_t n_wnaf = WNAF_SIZE(bucket_window+1);
size_t np;
size_t no = 0;
int i;
int j;
for (np = 0; np < num; ++np) {
if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) {
continue;
}
state->ps[no].input_pos = np;
state->ps[no].skew_na = secp256k1_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1);
no++;
}
secp256k1_gej_set_infinity(r);
if (no == 0) {
return 1;
}
for (i = n_wnaf - 1; i >= 0; i--) {
secp256k1_gej running_sum;
for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) {
secp256k1_gej_set_infinity(&buckets[j]);
}
for (np = 0; np < no; ++np) {
int n = state->wnaf_na[np*n_wnaf + i];
struct secp256k1_pippenger_point_state point_state = state->ps[np];
secp256k1_ge tmp;
int idx;
if (i == 0) {
/* correct for wnaf skew */
int skew = point_state.skew_na;
if (skew) {
secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]);
secp256k1_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL);
}
}
if (n > 0) {
idx = (n - 1)/2;
secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL);
} else if (n < 0) {
idx = -(n + 1)/2;
secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]);
secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL);
}
}
for(j = 0; j < bucket_window; j++) {
secp256k1_gej_double_var(r, r, NULL);
}
secp256k1_gej_set_infinity(&running_sum);
/* Accumulate the sum: bucket[0] + 3*bucket[1] + 5*bucket[2] + 7*bucket[3] + ...
* = bucket[0] + bucket[1] + bucket[2] + bucket[3] + ...
* + 2 * (bucket[1] + 2*bucket[2] + 3*bucket[3] + ...)
* using an intermediate running sum:
* running_sum = bucket[0] + bucket[1] + bucket[2] + ...
*
* The doubling is done implicitly by deferring the final window doubling (of 'r').
*/
for(j = ECMULT_TABLE_SIZE(bucket_window+2) - 1; j > 0; j--) {
secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL);
secp256k1_gej_add_var(r, r, &running_sum, NULL);
}
secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL);
secp256k1_gej_double_var(r, r, NULL);
secp256k1_gej_add_var(r, r, &running_sum, NULL);
}
return 1;
}
/**
* Returns optimal bucket_window (number of bits of a scalar represented by a
* set of buckets) for a given number of points.
*/
static int secp256k1_pippenger_bucket_window(size_t n) {
#ifdef USE_ENDOMORPHISM
if (n <= 1) {
return 1;
} else if (n <= 4) {
return 2;
} else if (n <= 20) {
return 3;
} else if (n <= 57) {
return 4;
} else if (n <= 136) {
return 5;
} else if (n <= 235) {
return 6;
} else if (n <= 1260) {
return 7;
} else if (n <= 4420) {
return 9;
} else if (n <= 7880) {
return 10;
} else if (n <= 16050) {
return 11;
} else {
return PIPPENGER_MAX_BUCKET_WINDOW;
}
#else
if (n <= 1) {
return 1;
} else if (n <= 11) {
return 2;
} else if (n <= 45) {
return 3;
} else if (n <= 100) {
return 4;
} else if (n <= 275) {
return 5;
} else if (n <= 625) {
return 6;
} else if (n <= 1850) {
return 7;
} else if (n <= 3400) {
return 8;
} else if (n <= 9630) {
return 9;
} else if (n <= 17900) {
return 10;
} else if (n <= 32800) {
return 11;
} else {
return PIPPENGER_MAX_BUCKET_WINDOW;
}
#endif
}
/**
* Returns the maximum optimal number of points for a bucket_window.
*/
static size_t secp256k1_pippenger_bucket_window_inv(int bucket_window) {
switch(bucket_window) {
#ifdef USE_ENDOMORPHISM
case 1: return 1;
case 2: return 4;
case 3: return 20;
case 4: return 57;
case 5: return 136;
case 6: return 235;
case 7: return 1260;
case 8: return 1260;
case 9: return 4420;
case 10: return 7880;
case 11: return 16050;
case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX;
#else
case 1: return 1;
case 2: return 11;
case 3: return 45;
case 4: return 100;
case 5: return 275;
case 6: return 625;
case 7: return 1850;
case 8: return 3400;
case 9: return 9630;
case 10: return 17900;
case 11: return 32800;
case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX;
#endif
}
return 0;
}
#ifdef USE_ENDOMORPHISM
SECP256K1_INLINE static void secp256k1_ecmult_endo_split(secp256k1_scalar *s1, secp256k1_scalar *s2, secp256k1_ge *p1, secp256k1_ge *p2) {
secp256k1_scalar tmp = *s1;
secp256k1_scalar_split_lambda(s1, s2, &tmp);
secp256k1_ge_mul_lambda(p2, p1);
if (secp256k1_scalar_is_high(s1)) {
secp256k1_scalar_negate(s1, s1);
secp256k1_ge_neg(p1, p1);
}
if (secp256k1_scalar_is_high(s2)) {
secp256k1_scalar_negate(s2, s2);
secp256k1_ge_neg(p2, p2);
}
}
#endif
/**
* Returns the scratch size required for a given number of points (excluding
* base point G) without considering alignment.
*/
static size_t secp256k1_pippenger_scratch_size(size_t n_points, int bucket_window) {
#ifdef USE_ENDOMORPHISM
size_t entries = 2*n_points + 2;
#else
size_t entries = n_points + 1;
#endif
size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int);
return ((1<<bucket_window) * sizeof(secp256k1_gej) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size);
}
static int secp256k1_ecmult_pippenger_batch(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) {
/* Use 2(n+1) with the endomorphism, n+1 without, when calculating batch
* sizes. The reason for +1 is that we add the G scalar to the list of
* other scalars. */
#ifdef USE_ENDOMORPHISM
size_t entries = 2*n_points + 2;
#else
size_t entries = n_points + 1;
#endif
secp256k1_ge *points;
secp256k1_scalar *scalars;
secp256k1_gej *buckets;
struct secp256k1_pippenger_state *state_space;
size_t idx = 0;
size_t point_idx = 0;
int i, j;
int bucket_window;
(void)ctx;
secp256k1_gej_set_infinity(r);
if (inp_g_sc == NULL && n_points == 0) {
return 1;
}
bucket_window = secp256k1_pippenger_bucket_window(n_points);
if (!secp256k1_scratch_allocate_frame(scratch, secp256k1_pippenger_scratch_size(n_points, bucket_window), PIPPENGER_SCRATCH_OBJECTS)) {
return 0;
}
points = (secp256k1_ge *) secp256k1_scratch_alloc(scratch, entries * sizeof(*points));
scalars = (secp256k1_scalar *) secp256k1_scratch_alloc(scratch, entries * sizeof(*scalars));
state_space = (struct secp256k1_pippenger_state *) secp256k1_scratch_alloc(scratch, sizeof(*state_space));
state_space->ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(scratch, entries * sizeof(*state_space->ps));
state_space->wnaf_na = (int *) secp256k1_scratch_alloc(scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int));
buckets = (secp256k1_gej *) secp256k1_scratch_alloc(scratch, (1<<bucket_window) * sizeof(*buckets));
if (inp_g_sc != NULL) {
scalars[0] = *inp_g_sc;
points[0] = secp256k1_ge_const_g;
idx++;
#ifdef USE_ENDOMORPHISM
secp256k1_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]);
idx++;
#endif
}
while (point_idx < n_points) {
if (!cb(&scalars[idx], &points[idx], point_idx + cb_offset, cbdata)) {
secp256k1_scratch_deallocate_frame(scratch);
return 0;
}
idx++;
#ifdef USE_ENDOMORPHISM
secp256k1_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]);
idx++;
#endif
point_idx++;
}
secp256k1_ecmult_pippenger_wnaf(buckets, bucket_window, state_space, r, scalars, points, idx);
/* Clear data */
for(i = 0; (size_t)i < idx; i++) {
secp256k1_scalar_clear(&scalars[i]);
state_space->ps[i].skew_na = 0;
for(j = 0; j < WNAF_SIZE(bucket_window+1); j++) {
state_space->wnaf_na[i * WNAF_SIZE(bucket_window+1) + j] = 0;
}
}
for(i = 0; i < 1<<bucket_window; i++) {
secp256k1_gej_clear(&buckets[i]);
}
secp256k1_scratch_deallocate_frame(scratch);
return 1;
}
/* Wrapper for secp256k1_ecmult_multi_func interface */
static int secp256k1_ecmult_pippenger_batch_single(const secp256k1_ecmult_context *actx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
return secp256k1_ecmult_pippenger_batch(actx, scratch, r, inp_g_sc, cb, cbdata, n, 0);
}
/**
* Returns the maximum number of points in addition to G that can be used with
* a given scratch space. The function ensures that fewer points may also be
* used.
*/
static size_t secp256k1_pippenger_max_points(secp256k1_scratch *scratch) {
size_t max_alloc = secp256k1_scratch_max_allocation(scratch, PIPPENGER_SCRATCH_OBJECTS);
int bucket_window;
size_t res = 0;
for (bucket_window = 1; bucket_window <= PIPPENGER_MAX_BUCKET_WINDOW; bucket_window++) {
size_t n_points;
size_t max_points = secp256k1_pippenger_bucket_window_inv(bucket_window);
size_t space_for_points;
size_t space_overhead;
size_t entry_size = sizeof(secp256k1_ge) + sizeof(secp256k1_scalar) + sizeof(struct secp256k1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int);
#ifdef USE_ENDOMORPHISM
entry_size = 2*entry_size;
#endif
space_overhead = ((1<<bucket_window) * sizeof(secp256k1_gej) + entry_size + sizeof(struct secp256k1_pippenger_state));
if (space_overhead > max_alloc) {
break;
}
space_for_points = max_alloc - space_overhead;
n_points = space_for_points/entry_size;
n_points = n_points > max_points ? max_points : n_points;
if (n_points > res) {
res = n_points;
}
if (n_points < max_points) {
/* A larger bucket_window may support even more points. But if we
* would choose that then the caller couldn't safely use any number
* smaller than what this function returns */
break;
}
}
return res;
}
typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t);
static int secp256k1_ecmult_multi_var(const secp256k1_ecmult_context *ctx, secp256k1_scratch *scratch, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n) {
size_t i;
int (*f)(const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t);
size_t max_points;
size_t n_batches;
size_t n_batch_points;
secp256k1_gej_set_infinity(r);
if (inp_g_sc == NULL && n == 0) {
return 1;
} else if (n == 0) {
secp256k1_scalar szero;
secp256k1_scalar_set_int(&szero, 0);
secp256k1_ecmult(ctx, r, r, &szero, inp_g_sc);
return 1;
}
max_points = secp256k1_pippenger_max_points(scratch);
if (max_points == 0) {
return 0;
} else if (max_points > ECMULT_MAX_POINTS_PER_BATCH) {
max_points = ECMULT_MAX_POINTS_PER_BATCH;
}
n_batches = (n+max_points-1)/max_points;
n_batch_points = (n+n_batches-1)/n_batches;
if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) {
f = secp256k1_ecmult_pippenger_batch;
} else {
max_points = secp256k1_strauss_max_points(scratch);
if (max_points == 0) {
return 0;
}
n_batches = (n+max_points-1)/max_points;
n_batch_points = (n+n_batches-1)/n_batches;
f = secp256k1_ecmult_strauss_batch;
}
for(i = 0; i < n_batches; i++) {
size_t nbp = n < n_batch_points ? n : n_batch_points;
size_t offset = n_batch_points*i;
secp256k1_gej tmp;
if (!f(ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) {
return 0;
}
secp256k1_gej_add_var(r, r, &tmp, NULL);
n -= nbp;
}
return 1;
}
#endif /* SECP256K1_ECMULT_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_FIELD_ #ifndef SECP256K1_FIELD_H
#define _SECP256K1_FIELD_ #define SECP256K1_FIELD_H
/** Field element module. /** Field element module.
* *
@ -129,4 +129,4 @@ static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_f
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
#endif #endif /* SECP256K1_FIELD_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_FIELD_REPR_ #ifndef SECP256K1_FIELD_REPR_H
#define _SECP256K1_FIELD_REPR_ #define SECP256K1_FIELD_REPR_H
#include <stdint.h> #include <stdint.h>
@ -44,4 +44,5 @@ typedef struct {
#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}
#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] #define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0]
#endif
#endif /* SECP256K1_FIELD_REPR_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ #ifndef SECP256K1_FIELD_REPR_IMPL_H
#define _SECP256K1_FIELD_REPR_IMPL_H_ #define SECP256K1_FIELD_REPR_IMPL_H
#include "util.h" #include "util.h"
#include "num.h" #include "num.h"
@ -321,17 +321,17 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
} }
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
int i; r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24);
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22);
r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20);
for (i=0; i<32; i++) { r->n[3] = (uint32_t)((a[22] >> 6) & 0x3) | ((uint32_t)a[21] << 2) | ((uint32_t)a[20] << 10) | ((uint32_t)a[19] << 18);
int j; r->n[4] = (uint32_t)a[18] | ((uint32_t)a[17] << 8) | ((uint32_t)a[16] << 16) | ((uint32_t)(a[15] & 0x3) << 24);
for (j=0; j<4; j++) { r->n[5] = (uint32_t)((a[15] >> 2) & 0x3f) | ((uint32_t)a[14] << 6) | ((uint32_t)a[13] << 14) | ((uint32_t)(a[12] & 0xf) << 22);
int limb = (8*i+2*j)/26; r->n[6] = (uint32_t)((a[12] >> 4) & 0xf) | ((uint32_t)a[11] << 4) | ((uint32_t)a[10] << 12) | ((uint32_t)(a[9] & 0x3f) << 20);
int shift = (8*i+2*j)%26; r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18);
r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24);
} r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14);
}
if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) {
return 0; return 0;
} }
@ -345,21 +345,42 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
int i;
#ifdef VERIFY #ifdef VERIFY
VERIFY_CHECK(a->normalized); VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a); secp256k1_fe_verify(a);
#endif #endif
for (i=0; i<32; i++) { r[0] = (a->n[9] >> 14) & 0xff;
int j; r[1] = (a->n[9] >> 6) & 0xff;
int c = 0; r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3);
for (j=0; j<4; j++) { r[3] = (a->n[8] >> 16) & 0xff;
int limb = (8*i+2*j)/26; r[4] = (a->n[8] >> 8) & 0xff;
int shift = (8*i+2*j)%26; r[5] = a->n[8] & 0xff;
c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); r[6] = (a->n[7] >> 18) & 0xff;
} r[7] = (a->n[7] >> 10) & 0xff;
r[31-i] = c; r[8] = (a->n[7] >> 2) & 0xff;
} r[9] = ((a->n[7] & 0x3) << 6) | ((a->n[6] >> 20) & 0x3f);
r[10] = (a->n[6] >> 12) & 0xff;
r[11] = (a->n[6] >> 4) & 0xff;
r[12] = ((a->n[6] & 0xf) << 4) | ((a->n[5] >> 22) & 0xf);
r[13] = (a->n[5] >> 14) & 0xff;
r[14] = (a->n[5] >> 6) & 0xff;
r[15] = ((a->n[5] & 0x3f) << 2) | ((a->n[4] >> 24) & 0x3);
r[16] = (a->n[4] >> 16) & 0xff;
r[17] = (a->n[4] >> 8) & 0xff;
r[18] = a->n[4] & 0xff;
r[19] = (a->n[3] >> 18) & 0xff;
r[20] = (a->n[3] >> 10) & 0xff;
r[21] = (a->n[3] >> 2) & 0xff;
r[22] = ((a->n[3] & 0x3) << 6) | ((a->n[2] >> 20) & 0x3f);
r[23] = (a->n[2] >> 12) & 0xff;
r[24] = (a->n[2] >> 4) & 0xff;
r[25] = ((a->n[2] & 0xf) << 4) | ((a->n[1] >> 22) & 0xf);
r[26] = (a->n[1] >> 14) & 0xff;
r[27] = (a->n[1] >> 6) & 0xff;
r[28] = ((a->n[1] & 0x3f) << 2) | ((a->n[0] >> 24) & 0x3);
r[29] = (a->n[0] >> 16) & 0xff;
r[30] = (a->n[0] >> 8) & 0xff;
r[31] = a->n[0] & 0xff;
} }
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
@ -1137,4 +1158,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
#endif #endif
} }
#endif #endif /* SECP256K1_FIELD_REPR_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_FIELD_REPR_ #ifndef SECP256K1_FIELD_REPR_H
#define _SECP256K1_FIELD_REPR_ #define SECP256K1_FIELD_REPR_H
#include <stdint.h> #include <stdint.h>
@ -44,4 +44,4 @@ typedef struct {
(d6) | (((uint64_t)(d7)) << 32) \ (d6) | (((uint64_t)(d7)) << 32) \
}} }}
#endif #endif /* SECP256K1_FIELD_REPR_H */

View file

@ -11,8 +11,8 @@
* - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly
*/ */
#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ #ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ #define SECP256K1_FIELD_INNER5X52_IMPL_H
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
/** /**
@ -499,4 +499,4 @@ __asm__ __volatile__(
); );
} }
#endif #endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ #ifndef SECP256K1_FIELD_REPR_IMPL_H
#define _SECP256K1_FIELD_REPR_IMPL_H_ #define SECP256K1_FIELD_REPR_IMPL_H
#if defined HAVE_CONFIG_H #if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h" #include "libsecp256k1-config.h"
@ -284,16 +284,40 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
} }
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
int i; r->n[0] = (uint64_t)a[31]
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | ((uint64_t)a[30] << 8)
for (i=0; i<32; i++) { | ((uint64_t)a[29] << 16)
int j; | ((uint64_t)a[28] << 24)
for (j=0; j<2; j++) { | ((uint64_t)a[27] << 32)
int limb = (8*i+4*j)/52; | ((uint64_t)a[26] << 40)
int shift = (8*i+4*j)%52; | ((uint64_t)(a[25] & 0xF) << 48);
r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; r->n[1] = (uint64_t)((a[25] >> 4) & 0xF)
} | ((uint64_t)a[24] << 4)
} | ((uint64_t)a[23] << 12)
| ((uint64_t)a[22] << 20)
| ((uint64_t)a[21] << 28)
| ((uint64_t)a[20] << 36)
| ((uint64_t)a[19] << 44);
r->n[2] = (uint64_t)a[18]
| ((uint64_t)a[17] << 8)
| ((uint64_t)a[16] << 16)
| ((uint64_t)a[15] << 24)
| ((uint64_t)a[14] << 32)
| ((uint64_t)a[13] << 40)
| ((uint64_t)(a[12] & 0xF) << 48);
r->n[3] = (uint64_t)((a[12] >> 4) & 0xF)
| ((uint64_t)a[11] << 4)
| ((uint64_t)a[10] << 12)
| ((uint64_t)a[9] << 20)
| ((uint64_t)a[8] << 28)
| ((uint64_t)a[7] << 36)
| ((uint64_t)a[6] << 44);
r->n[4] = (uint64_t)a[5]
| ((uint64_t)a[4] << 8)
| ((uint64_t)a[3] << 16)
| ((uint64_t)a[2] << 24)
| ((uint64_t)a[1] << 32)
| ((uint64_t)a[0] << 40);
if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) {
return 0; return 0;
} }
@ -307,21 +331,42 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
int i;
#ifdef VERIFY #ifdef VERIFY
VERIFY_CHECK(a->normalized); VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a); secp256k1_fe_verify(a);
#endif #endif
for (i=0; i<32; i++) { r[0] = (a->n[4] >> 40) & 0xFF;
int j; r[1] = (a->n[4] >> 32) & 0xFF;
int c = 0; r[2] = (a->n[4] >> 24) & 0xFF;
for (j=0; j<2; j++) { r[3] = (a->n[4] >> 16) & 0xFF;
int limb = (8*i+4*j)/52; r[4] = (a->n[4] >> 8) & 0xFF;
int shift = (8*i+4*j)%52; r[5] = a->n[4] & 0xFF;
c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); r[6] = (a->n[3] >> 44) & 0xFF;
} r[7] = (a->n[3] >> 36) & 0xFF;
r[31-i] = c; r[8] = (a->n[3] >> 28) & 0xFF;
} r[9] = (a->n[3] >> 20) & 0xFF;
r[10] = (a->n[3] >> 12) & 0xFF;
r[11] = (a->n[3] >> 4) & 0xFF;
r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4);
r[13] = (a->n[2] >> 40) & 0xFF;
r[14] = (a->n[2] >> 32) & 0xFF;
r[15] = (a->n[2] >> 24) & 0xFF;
r[16] = (a->n[2] >> 16) & 0xFF;
r[17] = (a->n[2] >> 8) & 0xFF;
r[18] = a->n[2] & 0xFF;
r[19] = (a->n[1] >> 44) & 0xFF;
r[20] = (a->n[1] >> 36) & 0xFF;
r[21] = (a->n[1] >> 28) & 0xFF;
r[22] = (a->n[1] >> 20) & 0xFF;
r[23] = (a->n[1] >> 12) & 0xFF;
r[24] = (a->n[1] >> 4) & 0xFF;
r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4);
r[26] = (a->n[0] >> 40) & 0xFF;
r[27] = (a->n[0] >> 32) & 0xFF;
r[28] = (a->n[0] >> 24) & 0xFF;
r[29] = (a->n[0] >> 16) & 0xFF;
r[30] = (a->n[0] >> 8) & 0xFF;
r[31] = a->n[0] & 0xFF;
} }
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
@ -448,4 +493,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
#endif #endif
} }
#endif #endif /* SECP256K1_FIELD_REPR_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ #ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ #define SECP256K1_FIELD_INNER5X52_IMPL_H
#include <stdint.h> #include <stdint.h>
@ -274,4 +274,4 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
} }
#endif #endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_FIELD_IMPL_H_ #ifndef SECP256K1_FIELD_IMPL_H
#define _SECP256K1_FIELD_IMPL_H_ #define SECP256K1_FIELD_IMPL_H
#if defined HAVE_CONFIG_H #if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h" #include "libsecp256k1-config.h"
@ -312,4 +312,4 @@ static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) {
#endif #endif
} }
#endif #endif /* SECP256K1_FIELD_IMPL_H */

View file

@ -41,7 +41,7 @@ int main(int argc, char **argv) {
fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n");
fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n");
fprintf(fp, "#include \"group.h\"\n"); fprintf(fp, "#include \"src/group.h\"\n");
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");

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_GROUP_ #ifndef SECP256K1_GROUP_H
#define _SECP256K1_GROUP_ #define SECP256K1_GROUP_H
#include "num.h" #include "num.h"
#include "field.h" #include "field.h"
@ -79,6 +79,9 @@ static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej
* stored in globalz. */ * stored in globalz. */
static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr); static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr);
/** Set a group element (affine) equal to the point at infinity. */
static void secp256k1_ge_set_infinity(secp256k1_ge *r);
/** Set a group element (jacobian) equal to the point at infinity. */ /** Set a group element (jacobian) equal to the point at infinity. */
static void secp256k1_gej_set_infinity(secp256k1_gej *r); static void secp256k1_gej_set_infinity(secp256k1_gej *r);
@ -141,4 +144,4 @@ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_g
/** Rescale a jacobian point by b which must be non-zero. Constant-time. */ /** Rescale a jacobian point by b which must be non-zero. Constant-time. */
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);
#endif #endif /* SECP256K1_GROUP_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_GROUP_IMPL_H_ #ifndef SECP256K1_GROUP_IMPL_H
#define _SECP256K1_GROUP_IMPL_H_ #define SECP256K1_GROUP_IMPL_H
#include "num.h" #include "num.h"
#include "field.h" #include "field.h"
@ -200,6 +200,12 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r) {
secp256k1_fe_clear(&r->z); secp256k1_fe_clear(&r->z);
} }
static void secp256k1_ge_set_infinity(secp256k1_ge *r) {
r->infinity = 1;
secp256k1_fe_clear(&r->x);
secp256k1_fe_clear(&r->y);
}
static void secp256k1_gej_clear(secp256k1_gej *r) { static void secp256k1_gej_clear(secp256k1_gej *r) {
r->infinity = 0; r->infinity = 0;
secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->x);
@ -697,4 +703,4 @@ static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
return secp256k1_fe_is_quad_var(&yz); return secp256k1_fe_is_quad_var(&yz);
} }
#endif #endif /* SECP256K1_GROUP_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_HASH_ #ifndef SECP256K1_HASH_H
#define _SECP256K1_HASH_ #define SECP256K1_HASH_H
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@ -14,28 +14,28 @@ typedef struct {
uint32_t s[8]; uint32_t s[8];
uint32_t buf[16]; /* In big endian */ uint32_t buf[16]; /* In big endian */
size_t bytes; size_t bytes;
} secp256k1_sha256_t; } secp256k1_sha256;
static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); static void secp256k1_sha256_initialize(secp256k1_sha256 *hash);
static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32);
typedef struct { typedef struct {
secp256k1_sha256_t inner, outer; secp256k1_sha256 inner, outer;
} secp256k1_hmac_sha256_t; } secp256k1_hmac_sha256;
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size);
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size);
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32);
typedef struct { typedef struct {
unsigned char v[32]; unsigned char v[32];
unsigned char k[32]; unsigned char k[32];
int retry; int retry;
} secp256k1_rfc6979_hmac_sha256_t; } secp256k1_rfc6979_hmac_sha256;
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen); static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen);
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen);
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng);
#endif #endif /* SECP256K1_HASH_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_HASH_IMPL_H_ #ifndef SECP256K1_HASH_IMPL_H
#define _SECP256K1_HASH_IMPL_H_ #define SECP256K1_HASH_IMPL_H
#include "hash.h" #include "hash.h"
@ -33,7 +33,7 @@
#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) #define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
#endif #endif
static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) {
hash->s[0] = 0x6a09e667ul; hash->s[0] = 0x6a09e667ul;
hash->s[1] = 0xbb67ae85ul; hash->s[1] = 0xbb67ae85ul;
hash->s[2] = 0x3c6ef372ul; hash->s[2] = 0x3c6ef372ul;
@ -128,14 +128,15 @@ static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) {
s[7] += h; s[7] += h;
} }
static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) {
size_t bufsize = hash->bytes & 0x3F; size_t bufsize = hash->bytes & 0x3F;
hash->bytes += len; hash->bytes += len;
while (bufsize + len >= 64) { while (bufsize + len >= 64) {
/* Fill the buffer, and process it. */ /* Fill the buffer, and process it. */
memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize); size_t chunk_len = 64 - bufsize;
data += 64 - bufsize; memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len);
len -= 64 - bufsize; data += chunk_len;
len -= chunk_len;
secp256k1_sha256_transform(hash->s, hash->buf); secp256k1_sha256_transform(hash->s, hash->buf);
bufsize = 0; bufsize = 0;
} }
@ -145,7 +146,7 @@ static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char
} }
} }
static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) {
static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t sizedesc[2]; uint32_t sizedesc[2];
uint32_t out[8]; uint32_t out[8];
@ -161,14 +162,14 @@ static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *o
memcpy(out32, (const unsigned char*)out, 32); memcpy(out32, (const unsigned char*)out, 32);
} }
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) {
int n; size_t n;
unsigned char rkey[64]; unsigned char rkey[64];
if (keylen <= 64) { if (keylen <= sizeof(rkey)) {
memcpy(rkey, key, keylen); memcpy(rkey, key, keylen);
memset(rkey + keylen, 0, 64 - keylen); memset(rkey + keylen, 0, sizeof(rkey) - keylen);
} else { } else {
secp256k1_sha256_t sha256; secp256k1_sha256 sha256;
secp256k1_sha256_initialize(&sha256); secp256k1_sha256_initialize(&sha256);
secp256k1_sha256_write(&sha256, key, keylen); secp256k1_sha256_write(&sha256, key, keylen);
secp256k1_sha256_finalize(&sha256, rkey); secp256k1_sha256_finalize(&sha256, rkey);
@ -176,24 +177,24 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, cons
} }
secp256k1_sha256_initialize(&hash->outer); secp256k1_sha256_initialize(&hash->outer);
for (n = 0; n < 64; n++) { for (n = 0; n < sizeof(rkey); n++) {
rkey[n] ^= 0x5c; rkey[n] ^= 0x5c;
} }
secp256k1_sha256_write(&hash->outer, rkey, 64); secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey));
secp256k1_sha256_initialize(&hash->inner); secp256k1_sha256_initialize(&hash->inner);
for (n = 0; n < 64; n++) { for (n = 0; n < sizeof(rkey); n++) {
rkey[n] ^= 0x5c ^ 0x36; rkey[n] ^= 0x5c ^ 0x36;
} }
secp256k1_sha256_write(&hash->inner, rkey, 64); secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey));
memset(rkey, 0, 64); memset(rkey, 0, sizeof(rkey));
} }
static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) {
secp256k1_sha256_write(&hash->inner, data, size); secp256k1_sha256_write(&hash->inner, data, size);
} }
static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) {
unsigned char temp[32]; unsigned char temp[32];
secp256k1_sha256_finalize(&hash->inner, temp); secp256k1_sha256_finalize(&hash->inner, temp);
secp256k1_sha256_write(&hash->outer, temp, 32); secp256k1_sha256_write(&hash->outer, temp, 32);
@ -202,8 +203,8 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsign
} }
static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) { static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) {
secp256k1_hmac_sha256_t hmac; secp256k1_hmac_sha256 hmac;
static const unsigned char zero[1] = {0x00}; static const unsigned char zero[1] = {0x00};
static const unsigned char one[1] = {0x01}; static const unsigned char one[1] = {0x01};
@ -232,11 +233,11 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2
rng->retry = 0; rng->retry = 0;
} }
static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) {
/* RFC6979 3.2.h. */ /* RFC6979 3.2.h. */
static const unsigned char zero[1] = {0x00}; static const unsigned char zero[1] = {0x00};
if (rng->retry) { if (rng->retry) {
secp256k1_hmac_sha256_t hmac; secp256k1_hmac_sha256 hmac;
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
secp256k1_hmac_sha256_write(&hmac, zero, 1); secp256k1_hmac_sha256_write(&hmac, zero, 1);
@ -247,7 +248,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256
} }
while (outlen > 0) { while (outlen > 0) {
secp256k1_hmac_sha256_t hmac; secp256k1_hmac_sha256 hmac;
int now = outlen; int now = outlen;
secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32);
secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32);
@ -263,7 +264,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256
rng->retry = 1; rng->retry = 1;
} }
static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) {
memset(rng->k, 0, 32); memset(rng->k, 0, 32);
memset(rng->v, 0, 32); memset(rng->v, 0, 32);
rng->retry = 0; rng->retry = 0;
@ -278,4 +279,4 @@ static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256
#undef Maj #undef Maj
#undef Ch #undef Ch
#endif #endif /* SECP256K1_HASH_IMPL_H */

View file

@ -52,7 +52,7 @@ public class NativeSecp256k1Test {
} }
/** /**
* This tests secret key verify() for a invalid secretkey * This tests secret key verify() for an invalid secretkey
*/ */
public static void testSecKeyVerifyNeg() throws AssertFailException{ public static void testSecKeyVerifyNeg() throws AssertFailException{
boolean result = false; boolean result = false;

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_MODULE_ECDH_MAIN_ #ifndef SECP256K1_MODULE_ECDH_MAIN_H
#define _SECP256K1_MODULE_ECDH_MAIN_ #define SECP256K1_MODULE_ECDH_MAIN_H
#include "include/secp256k1_ecdh.h" #include "include/secp256k1_ecdh.h"
#include "ecmult_const_impl.h" #include "ecmult_const_impl.h"
@ -28,9 +28,9 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se
} else { } else {
unsigned char x[32]; unsigned char x[32];
unsigned char y[1]; unsigned char y[1];
secp256k1_sha256_t sha; secp256k1_sha256 sha;
secp256k1_ecmult_const(&res, &pt, &s); secp256k1_ecmult_const(&res, &pt, &s, 256);
secp256k1_ge_set_gej(&pt, &res); secp256k1_ge_set_gej(&pt, &res);
/* Compute a hash of the point in compressed form /* Compute a hash of the point in compressed form
* Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not * Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not
@ -51,4 +51,4 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se
return ret; return ret;
} }
#endif #endif /* SECP256K1_MODULE_ECDH_MAIN_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_MODULE_ECDH_TESTS_ #ifndef SECP256K1_MODULE_ECDH_TESTS_H
#define _SECP256K1_MODULE_ECDH_TESTS_ #define SECP256K1_MODULE_ECDH_TESTS_H
void test_ecdh_api(void) { void test_ecdh_api(void) {
/* Setup context that just counts errors */ /* Setup context that just counts errors */
@ -44,7 +44,7 @@ void test_ecdh_generator_basepoint(void) {
s_one[31] = 1; s_one[31] = 1;
/* Check against pubkey creation when the basepoint is the generator */ /* Check against pubkey creation when the basepoint is the generator */
for (i = 0; i < 100; ++i) { for (i = 0; i < 100; ++i) {
secp256k1_sha256_t sha; secp256k1_sha256 sha;
unsigned char s_b32[32]; unsigned char s_b32[32];
unsigned char output_ecdh[32]; unsigned char output_ecdh[32];
unsigned char output_ser[32]; unsigned char output_ser[32];
@ -102,4 +102,4 @@ void run_ecdh_tests(void) {
test_bad_scalar(); test_bad_scalar();
} }
#endif #endif /* SECP256K1_MODULE_ECDH_TESTS_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ #ifndef SECP256K1_MODULE_RECOVERY_MAIN_H
#define _SECP256K1_MODULE_RECOVERY_MAIN_ #define SECP256K1_MODULE_RECOVERY_MAIN_H
#include "include/secp256k1_recovery.h" #include "include/secp256k1_recovery.h"
@ -190,4 +190,4 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk
} }
} }
#endif #endif /* SECP256K1_MODULE_RECOVERY_MAIN_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ #ifndef SECP256K1_MODULE_RECOVERY_TESTS_H
#define _SECP256K1_MODULE_RECOVERY_TESTS_ #define SECP256K1_MODULE_RECOVERY_TESTS_H
static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) {
(void) msg32; (void) msg32;
@ -390,4 +390,4 @@ void run_recovery_tests(void) {
test_ecdsa_recovery_edge_cases(); test_ecdsa_recovery_edge_cases();
} }
#endif #endif /* SECP256K1_MODULE_RECOVERY_TESTS_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_NUM_ #ifndef SECP256K1_NUM_H
#define _SECP256K1_NUM_ #define SECP256K1_NUM_H
#ifndef USE_NUM_NONE #ifndef USE_NUM_NONE
@ -71,4 +71,4 @@ static void secp256k1_num_negate(secp256k1_num *r);
#endif #endif
#endif #endif /* SECP256K1_NUM_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_NUM_REPR_ #ifndef SECP256K1_NUM_REPR_H
#define _SECP256K1_NUM_REPR_ #define SECP256K1_NUM_REPR_H
#include <gmp.h> #include <gmp.h>
@ -17,4 +17,4 @@ typedef struct {
int limbs; int limbs;
} secp256k1_num; } secp256k1_num;
#endif #endif /* SECP256K1_NUM_REPR_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_NUM_REPR_IMPL_H_ #ifndef SECP256K1_NUM_REPR_IMPL_H
#define _SECP256K1_NUM_REPR_IMPL_H_ #define SECP256K1_NUM_REPR_IMPL_H
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -285,4 +285,4 @@ static void secp256k1_num_negate(secp256k1_num *r) {
r->neg ^= 1; r->neg ^= 1;
} }
#endif #endif /* SECP256K1_NUM_REPR_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_NUM_IMPL_H_ #ifndef SECP256K1_NUM_IMPL_H
#define _SECP256K1_NUM_IMPL_H_ #define SECP256K1_NUM_IMPL_H
#if defined HAVE_CONFIG_H #if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h" #include "libsecp256k1-config.h"
@ -21,4 +21,4 @@
#error "Please select num implementation" #error "Please select num implementation"
#endif #endif
#endif #endif /* SECP256K1_NUM_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_SCALAR_ #ifndef SECP256K1_SCALAR_H
#define _SECP256K1_SCALAR_ #define SECP256K1_SCALAR_H
#include "num.h" #include "num.h"
@ -103,4 +103,4 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */
static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift);
#endif #endif /* SECP256K1_SCALAR_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_ #ifndef SECP256K1_SCALAR_REPR_H
#define _SECP256K1_SCALAR_REPR_ #define SECP256K1_SCALAR_REPR_H
#include <stdint.h> #include <stdint.h>
@ -16,4 +16,4 @@ typedef struct {
#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}}
#endif #endif /* SECP256K1_SCALAR_REPR_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ #ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define _SECP256K1_SCALAR_REPR_IMPL_H_ #define SECP256K1_SCALAR_REPR_IMPL_H
/* Limbs of the secp256k1 order. */ /* Limbs of the secp256k1 order. */
#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) #define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL)
@ -946,4 +946,4 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1);
} }
#endif #endif /* SECP256K1_SCALAR_REPR_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_ #ifndef SECP256K1_SCALAR_REPR_H
#define _SECP256K1_SCALAR_REPR_ #define SECP256K1_SCALAR_REPR_H
#include <stdint.h> #include <stdint.h>
@ -16,4 +16,4 @@ typedef struct {
#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}}
#endif #endif /* SECP256K1_SCALAR_REPR_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ #ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define _SECP256K1_SCALAR_REPR_IMPL_H_ #define SECP256K1_SCALAR_REPR_IMPL_H
/* Limbs of the secp256k1 order. */ /* Limbs of the secp256k1 order. */
#define SECP256K1_N_0 ((uint32_t)0xD0364141UL) #define SECP256K1_N_0 ((uint32_t)0xD0364141UL)
@ -718,4 +718,4 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r,
secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1);
} }
#endif #endif /* SECP256K1_SCALAR_REPR_IMPL_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_SCALAR_IMPL_H_ #ifndef SECP256K1_SCALAR_IMPL_H
#define _SECP256K1_SCALAR_IMPL_H_ #define SECP256K1_SCALAR_IMPL_H
#include "group.h" #include "group.h"
#include "scalar.h" #include "scalar.h"
@ -66,88 +66,79 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar
#else #else
secp256k1_scalar *t; secp256k1_scalar *t;
int i; int i;
/* First compute x ^ (2^N - 1) for some values of N. */ /* First compute xN as x ^ (2^N - 1) for some values of N,
secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; * and uM as x ^ M for some values of M. */
secp256k1_scalar x2, x3, x6, x8, x14, x28, x56, x112, x126;
secp256k1_scalar u2, u5, u9, u11, u13;
secp256k1_scalar_sqr(&x2, x); secp256k1_scalar_sqr(&u2, x);
secp256k1_scalar_mul(&x2, &x2, x); secp256k1_scalar_mul(&x2, &u2, x);
secp256k1_scalar_mul(&u5, &u2, &x2);
secp256k1_scalar_mul(&x3, &u5, &u2);
secp256k1_scalar_mul(&u9, &x3, &u2);
secp256k1_scalar_mul(&u11, &u9, &u2);
secp256k1_scalar_mul(&u13, &u11, &u2);
secp256k1_scalar_sqr(&x3, &x2); secp256k1_scalar_sqr(&x6, &u13);
secp256k1_scalar_mul(&x3, &x3, x);
secp256k1_scalar_sqr(&x4, &x3);
secp256k1_scalar_mul(&x4, &x4, x);
secp256k1_scalar_sqr(&x6, &x4);
secp256k1_scalar_sqr(&x6, &x6); secp256k1_scalar_sqr(&x6, &x6);
secp256k1_scalar_mul(&x6, &x6, &x2); secp256k1_scalar_mul(&x6, &x6, &u11);
secp256k1_scalar_sqr(&x7, &x6); secp256k1_scalar_sqr(&x8, &x6);
secp256k1_scalar_mul(&x7, &x7, x); secp256k1_scalar_sqr(&x8, &x8);
secp256k1_scalar_mul(&x8, &x8, &x2);
secp256k1_scalar_sqr(&x8, &x7); secp256k1_scalar_sqr(&x14, &x8);
secp256k1_scalar_mul(&x8, &x8, x); for (i = 0; i < 5; i++) {
secp256k1_scalar_sqr(&x14, &x14);
secp256k1_scalar_sqr(&x15, &x8);
for (i = 0; i < 6; i++) {
secp256k1_scalar_sqr(&x15, &x15);
} }
secp256k1_scalar_mul(&x15, &x15, &x7); secp256k1_scalar_mul(&x14, &x14, &x6);
secp256k1_scalar_sqr(&x30, &x15); secp256k1_scalar_sqr(&x28, &x14);
for (i = 0; i < 14; i++) { for (i = 0; i < 13; i++) {
secp256k1_scalar_sqr(&x30, &x30); secp256k1_scalar_sqr(&x28, &x28);
} }
secp256k1_scalar_mul(&x30, &x30, &x15); secp256k1_scalar_mul(&x28, &x28, &x14);
secp256k1_scalar_sqr(&x60, &x30); secp256k1_scalar_sqr(&x56, &x28);
for (i = 0; i < 29; i++) { for (i = 0; i < 27; i++) {
secp256k1_scalar_sqr(&x60, &x60); secp256k1_scalar_sqr(&x56, &x56);
} }
secp256k1_scalar_mul(&x60, &x60, &x30); secp256k1_scalar_mul(&x56, &x56, &x28);
secp256k1_scalar_sqr(&x120, &x60); secp256k1_scalar_sqr(&x112, &x56);
for (i = 0; i < 59; i++) { for (i = 0; i < 55; i++) {
secp256k1_scalar_sqr(&x120, &x120); secp256k1_scalar_sqr(&x112, &x112);
} }
secp256k1_scalar_mul(&x120, &x120, &x60); secp256k1_scalar_mul(&x112, &x112, &x56);
secp256k1_scalar_sqr(&x127, &x120); secp256k1_scalar_sqr(&x126, &x112);
for (i = 0; i < 6; i++) { for (i = 0; i < 13; i++) {
secp256k1_scalar_sqr(&x127, &x127); secp256k1_scalar_sqr(&x126, &x126);
} }
secp256k1_scalar_mul(&x127, &x127, &x7); secp256k1_scalar_mul(&x126, &x126, &x14);
/* Then accumulate the final result (t starts at x127). */ /* Then accumulate the final result (t starts at x126). */
t = &x127; t = &x126;
for (i = 0; i < 2; i++) { /* 0 */ for (i = 0; i < 3; i++) {
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, x); /* 1 */ secp256k1_scalar_mul(t, t, &u5); /* 101 */
for (i = 0; i < 4; i++) { /* 0 */ for (i = 0; i < 4; i++) { /* 0 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x3); /* 111 */ secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (i = 0; i < 2; i++) { /* 0 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 2; i++) { /* 0 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 2; i++) { /* 0 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 4; i++) { /* 0 */ for (i = 0; i < 4; i++) { /* 0 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x3); /* 111 */ secp256k1_scalar_mul(t, t, &u5); /* 101 */
for (i = 0; i < 3; i++) { /* 0 */ for (i = 0; i < 5; i++) { /* 0 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x2); /* 11 */ secp256k1_scalar_mul(t, t, &u11); /* 1011 */
for (i = 0; i < 4; i++) {
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, &u11); /* 1011 */
for (i = 0; i < 4; i++) { /* 0 */ for (i = 0; i < 4; i++) { /* 0 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
@ -156,38 +147,26 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x3); /* 111 */ secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (i = 0; i < 4; i++) { /* 00 */ for (i = 0; i < 6; i++) { /* 00 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x2); /* 11 */ secp256k1_scalar_mul(t, t, &u13); /* 1101 */
for (i = 0; i < 2; i++) { /* 0 */ for (i = 0; i < 4; i++) { /* 0 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, x); /* 1 */ secp256k1_scalar_mul(t, t, &u5); /* 101 */
for (i = 0; i < 2; i++) { /* 0 */ for (i = 0; i < 3; i++) {
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, x); /* 1 */ secp256k1_scalar_mul(t, t, &x3); /* 111 */
for (i = 0; i < 5; i++) { /* 0 */ for (i = 0; i < 5; i++) { /* 0 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x4); /* 1111 */ secp256k1_scalar_mul(t, t, &u9); /* 1001 */
for (i = 0; i < 2; i++) { /* 0 */ for (i = 0; i < 6; i++) { /* 000 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, x); /* 1 */ secp256k1_scalar_mul(t, t, &u5); /* 101 */
for (i = 0; i < 3; i++) { /* 00 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 4; i++) { /* 000 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 2; i++) { /* 0 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 10; i++) { /* 0000000 */ for (i = 0; i < 10; i++) { /* 0000000 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
@ -200,50 +179,34 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ secp256k1_scalar_mul(t, t, &x8); /* 11111111 */
for (i = 0; i < 2; i++) { /* 0 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 3; i++) { /* 00 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 3; i++) { /* 00 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 5; i++) { /* 0 */ for (i = 0; i < 5; i++) { /* 0 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x4); /* 1111 */ secp256k1_scalar_mul(t, t, &u9); /* 1001 */
for (i = 0; i < 2; i++) { /* 0 */ for (i = 0; i < 6; i++) { /* 00 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, x); /* 1 */ secp256k1_scalar_mul(t, t, &u11); /* 1011 */
for (i = 0; i < 5; i++) { /* 000 */ for (i = 0; i < 4; i++) {
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, &u13); /* 1101 */
for (i = 0; i < 5; i++) {
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x2); /* 11 */ secp256k1_scalar_mul(t, t, &x2); /* 11 */
for (i = 0; i < 4; i++) { /* 00 */ for (i = 0; i < 6; i++) { /* 00 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x2); /* 11 */ secp256k1_scalar_mul(t, t, &u13); /* 1101 */
for (i = 0; i < 2; i++) { /* 0 */ for (i = 0; i < 10; i++) { /* 000000 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, x); /* 1 */ secp256k1_scalar_mul(t, t, &u13); /* 1101 */
for (i = 0; i < 8; i++) { /* 000000 */ for (i = 0; i < 4; i++) {
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
secp256k1_scalar_mul(t, t, &x2); /* 11 */ secp256k1_scalar_mul(t, t, &u9); /* 1001 */
for (i = 0; i < 3; i++) { /* 0 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, &x2); /* 11 */
for (i = 0; i < 3; i++) { /* 00 */
secp256k1_scalar_sqr(t, t);
}
secp256k1_scalar_mul(t, t, x); /* 1 */
for (i = 0; i < 6; i++) { /* 00000 */ for (i = 0; i < 6; i++) { /* 00000 */
secp256k1_scalar_sqr(t, t); secp256k1_scalar_sqr(t, t);
} }
@ -367,4 +330,4 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar
#endif #endif
#endif #endif
#endif #endif /* SECP256K1_SCALAR_IMPL_H */

View file

@ -4,12 +4,12 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_ #ifndef SECP256K1_SCALAR_REPR_H
#define _SECP256K1_SCALAR_REPR_ #define SECP256K1_SCALAR_REPR_H
#include <stdint.h> #include <stdint.h>
/** A scalar modulo the group order of the secp256k1 curve. */ /** A scalar modulo the group order of the secp256k1 curve. */
typedef uint32_t secp256k1_scalar; typedef uint32_t secp256k1_scalar;
#endif #endif /* SECP256K1_SCALAR_REPR_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ #ifndef SECP256K1_SCALAR_REPR_IMPL_H
#define _SECP256K1_SCALAR_REPR_IMPL_H_ #define SECP256K1_SCALAR_REPR_IMPL_H
#include "scalar.h" #include "scalar.h"
@ -111,4 +111,4 @@ SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const
return *a == *b; return *a == *b;
} }
#endif #endif /* SECP256K1_SCALAR_REPR_IMPL_H */

View file

@ -0,0 +1,39 @@
/**********************************************************************
* Copyright (c) 2017 Andrew Poelstra *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCRATCH_
#define _SECP256K1_SCRATCH_
#define SECP256K1_SCRATCH_MAX_FRAMES 5
/* The typedef is used internally; the struct name is used in the public API
* (where it is exposed as a different typedef) */
typedef struct secp256k1_scratch_space_struct {
void *data[SECP256K1_SCRATCH_MAX_FRAMES];
size_t offset[SECP256K1_SCRATCH_MAX_FRAMES];
size_t frame_size[SECP256K1_SCRATCH_MAX_FRAMES];
size_t frame;
size_t max_size;
const secp256k1_callback* error_callback;
} secp256k1_scratch;
static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size);
static void secp256k1_scratch_destroy(secp256k1_scratch* scratch);
/** Attempts to allocate a new stack frame with `n` available bytes. Returns 1 on success, 0 on failure */
static int secp256k1_scratch_allocate_frame(secp256k1_scratch* scratch, size_t n, size_t objects);
/** Deallocates a stack frame */
static void secp256k1_scratch_deallocate_frame(secp256k1_scratch* scratch);
/** Returns the maximum allocation the scratch space will allow */
static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t n_objects);
/** Returns a pointer into the most recently allocated frame, or NULL if there is insufficient available space */
static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t n);
#endif

View file

@ -0,0 +1,86 @@
/**********************************************************************
* Copyright (c) 2017 Andrew Poelstra *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#ifndef _SECP256K1_SCRATCH_IMPL_H_
#define _SECP256K1_SCRATCH_IMPL_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) {
secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret));
if (ret != NULL) {
memset(ret, 0, sizeof(*ret));
ret->max_size = max_size;
ret->error_callback = error_callback;
}
return ret;
}
static void secp256k1_scratch_destroy(secp256k1_scratch* scratch) {
if (scratch != NULL) {
VERIFY_CHECK(scratch->frame == 0);
free(scratch);
}
}
static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t objects) {
size_t i = 0;
size_t allocated = 0;
for (i = 0; i < scratch->frame; i++) {
allocated += scratch->frame_size[i];
}
if (scratch->max_size - allocated <= objects * ALIGNMENT) {
return 0;
}
return scratch->max_size - allocated - objects * ALIGNMENT;
}
static int secp256k1_scratch_allocate_frame(secp256k1_scratch* scratch, size_t n, size_t objects) {
VERIFY_CHECK(scratch->frame < SECP256K1_SCRATCH_MAX_FRAMES);
if (n <= secp256k1_scratch_max_allocation(scratch, objects)) {
n += objects * ALIGNMENT;
scratch->data[scratch->frame] = checked_malloc(scratch->error_callback, n);
if (scratch->data[scratch->frame] == NULL) {
return 0;
}
scratch->frame_size[scratch->frame] = n;
scratch->offset[scratch->frame] = 0;
scratch->frame++;
return 1;
} else {
return 0;
}
}
static void secp256k1_scratch_deallocate_frame(secp256k1_scratch* scratch) {
VERIFY_CHECK(scratch->frame > 0);
scratch->frame -= 1;
free(scratch->data[scratch->frame]);
}
static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) {
void *ret;
size_t frame = scratch->frame - 1;
size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT;
if (scratch->frame == 0 || size + scratch->offset[frame] > scratch->frame_size[frame]) {
return NULL;
}
ret = (void *) ((unsigned char *) scratch->data[frame] + scratch->offset[frame]);
memset(ret, 0, size);
scratch->offset[frame] += size;
return ret;
}
#endif

View file

@ -17,6 +17,7 @@
#include "ecdsa_impl.h" #include "ecdsa_impl.h"
#include "eckey_impl.h" #include "eckey_impl.h"
#include "hash_impl.h" #include "hash_impl.h"
#include "scratch_impl.h"
#define ARG_CHECK(cond) do { \ #define ARG_CHECK(cond) do { \
if (EXPECT(!(cond), 0)) { \ if (EXPECT(!(cond), 0)) { \
@ -114,13 +115,22 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co
ctx->error_callback.data = data; ctx->error_callback.data = data;
} }
secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) {
VERIFY_CHECK(ctx != NULL);
return secp256k1_scratch_create(&ctx->error_callback, max_size);
}
void secp256k1_scratch_space_destroy(secp256k1_scratch_space* scratch) {
secp256k1_scratch_destroy(scratch);
}
static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) {
if (sizeof(secp256k1_ge_storage) == 64) { if (sizeof(secp256k1_ge_storage) == 64) {
/* When the secp256k1_ge_storage type is exactly 64 byte, use its /* When the secp256k1_ge_storage type is exactly 64 byte, use its
* representation inside secp256k1_pubkey, as conversion is very fast. * representation inside secp256k1_pubkey, as conversion is very fast.
* Note that secp256k1_pubkey_save must use the same representation. */ * Note that secp256k1_pubkey_save must use the same representation. */
secp256k1_ge_storage s; secp256k1_ge_storage s;
memcpy(&s, &pubkey->data[0], 64); memcpy(&s, &pubkey->data[0], sizeof(s));
secp256k1_ge_from_storage(ge, &s); secp256k1_ge_from_storage(ge, &s);
} else { } else {
/* Otherwise, fall back to 32-byte big endian for X and Y. */ /* Otherwise, fall back to 32-byte big endian for X and Y. */
@ -137,7 +147,7 @@ static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) {
if (sizeof(secp256k1_ge_storage) == 64) { if (sizeof(secp256k1_ge_storage) == 64) {
secp256k1_ge_storage s; secp256k1_ge_storage s;
secp256k1_ge_to_storage(&s, ge); secp256k1_ge_to_storage(&s, ge);
memcpy(&pubkey->data[0], &s, 64); memcpy(&pubkey->data[0], &s, sizeof(s));
} else { } else {
VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); VERIFY_CHECK(!secp256k1_ge_is_infinity(ge));
secp256k1_fe_normalize_var(&ge->x); secp256k1_fe_normalize_var(&ge->x);
@ -307,10 +317,15 @@ int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_s
secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m));
} }
static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) {
memcpy(buf + *offset, data, len);
*offset += len;
}
static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) {
unsigned char keydata[112]; unsigned char keydata[112];
int keylen = 64; unsigned int offset = 0;
secp256k1_rfc6979_hmac_sha256_t rng; secp256k1_rfc6979_hmac_sha256 rng;
unsigned int i; unsigned int i;
/* We feed a byte array to the PRNG as input, consisting of: /* We feed a byte array to the PRNG as input, consisting of:
* - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d.
@ -320,17 +335,15 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m
* different argument mixtures to emulate each other and result in the same * different argument mixtures to emulate each other and result in the same
* nonces. * nonces.
*/ */
memcpy(keydata, key32, 32); buffer_append(keydata, &offset, key32, 32);
memcpy(keydata + 32, msg32, 32); buffer_append(keydata, &offset, msg32, 32);
if (data != NULL) { if (data != NULL) {
memcpy(keydata + 64, data, 32); buffer_append(keydata, &offset, data, 32);
keylen = 96;
} }
if (algo16 != NULL) { if (algo16 != NULL) {
memcpy(keydata + keylen, algo16, 16); buffer_append(keydata, &offset, algo16, 16);
keylen += 16;
} }
secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset);
memset(keydata, 0, sizeof(keydata)); memset(keydata, 0, sizeof(keydata));
for (i = 0; i <= counter; i++) { for (i = 0; i <= counter; i++) {
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
@ -424,6 +437,33 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p
return ret; return ret;
} }
int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) {
secp256k1_scalar sec;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(seckey != NULL);
secp256k1_scalar_set_b32(&sec, seckey, NULL);
secp256k1_scalar_negate(&sec, &sec);
secp256k1_scalar_get_b32(seckey, &sec);
return 1;
}
int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) {
int ret = 0;
secp256k1_ge p;
VERIFY_CHECK(ctx != NULL);
ARG_CHECK(pubkey != NULL);
ret = secp256k1_pubkey_load(ctx, &p, pubkey);
memset(pubkey, 0, sizeof(*pubkey));
if (ret) {
secp256k1_ge_neg(&p, &p);
secp256k1_pubkey_save(pubkey, &p);
}
return ret;
}
int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
secp256k1_scalar term; secp256k1_scalar term;
secp256k1_scalar sec; secp256k1_scalar sec;
@ -552,10 +592,6 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *
# include "modules/ecdh/main_impl.h" # include "modules/ecdh/main_impl.h"
#endif #endif
#ifdef ENABLE_MODULE_SCHNORR
# include "modules/schnorr/main_impl.h"
#endif
#ifdef ENABLE_MODULE_RECOVERY #ifdef ENABLE_MODULE_RECOVERY
# include "modules/recovery/main_impl.h" # include "modules/recovery/main_impl.h"
#endif #endif

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_TESTRAND_H_ #ifndef SECP256K1_TESTRAND_H
#define _SECP256K1_TESTRAND_H_ #define SECP256K1_TESTRAND_H
#if defined HAVE_CONFIG_H #if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h" #include "libsecp256k1-config.h"
@ -35,4 +35,4 @@ static void secp256k1_rand256_test(unsigned char *b32);
/** Generate pseudorandom bytes with long sequences of zero and one bits. */ /** Generate pseudorandom bytes with long sequences of zero and one bits. */
static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len); static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len);
#endif #endif /* SECP256K1_TESTRAND_H */

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_TESTRAND_IMPL_H_ #ifndef SECP256K1_TESTRAND_IMPL_H
#define _SECP256K1_TESTRAND_IMPL_H_ #define SECP256K1_TESTRAND_IMPL_H
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -13,7 +13,7 @@
#include "testrand.h" #include "testrand.h"
#include "hash.h" #include "hash.h"
static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng; static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng;
static uint32_t secp256k1_test_rng_precomputed[8]; static uint32_t secp256k1_test_rng_precomputed[8];
static int secp256k1_test_rng_precomputed_used = 8; static int secp256k1_test_rng_precomputed_used = 8;
static uint64_t secp256k1_test_rng_integer; static uint64_t secp256k1_test_rng_integer;
@ -107,4 +107,4 @@ static void secp256k1_rand256_test(unsigned char *b32) {
secp256k1_rand_bytes_test(b32, 32); secp256k1_rand_bytes_test(b32, 32);
} }
#endif #endif /* SECP256K1_TESTRAND_IMPL_H */

View file

@ -10,6 +10,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <time.h> #include <time.h>
@ -22,6 +23,9 @@
#include "openssl/ec.h" #include "openssl/ec.h"
#include "openssl/ecdsa.h" #include "openssl/ecdsa.h"
#include "openssl/obj_mac.h" #include "openssl/obj_mac.h"
# if OPENSSL_VERSION_NUMBER < 0x10100000L
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) {*pr = sig->r; *ps = sig->s;}
# endif
#endif #endif
#include "contrib/lax_der_parsing.c" #include "contrib/lax_der_parsing.c"
@ -135,6 +139,7 @@ void random_scalar_order(secp256k1_scalar *num) {
void run_context_tests(void) { void run_context_tests(void) {
secp256k1_pubkey pubkey; secp256k1_pubkey 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;
@ -149,6 +154,8 @@ void run_context_tests(void) {
secp256k1_scalar msg, key, nonce; secp256k1_scalar msg, key, nonce;
secp256k1_scalar sigr, sigs; secp256k1_scalar sigr, sigs;
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
ecount = 0; ecount = 0;
ecount2 = 10; ecount2 = 10;
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
@ -201,12 +208,20 @@ void run_context_tests(void) {
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);
CHECK(ecount2 == 13); CHECK(ecount2 == 13);
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1);
CHECK(ecount == 2); CHECK(ecount == 2);
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
CHECK(ecount == 2);
CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
CHECK(ecount2 == 14);
CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
CHECK(ecount == 3); CHECK(ecount == 3);
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
CHECK(ecount == 3);
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
CHECK(ecount == 4);
CHECK(secp256k1_context_randomize(sign, NULL) == 1); CHECK(secp256k1_context_randomize(sign, NULL) == 1);
CHECK(ecount2 == 13); 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);
@ -236,6 +251,44 @@ void run_context_tests(void) {
secp256k1_context_destroy(NULL); secp256k1_context_destroy(NULL);
} }
void run_scratch_tests(void) {
int32_t ecount = 0;
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_scratch_space *scratch;
/* Test public API */
secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
scratch = secp256k1_scratch_space_create(none, 1000);
CHECK(scratch != NULL);
CHECK(ecount == 0);
/* Test internal API */
CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000);
CHECK(secp256k1_scratch_max_allocation(scratch, 1) < 1000);
/* Allocating 500 bytes with no frame fails */
CHECK(secp256k1_scratch_alloc(scratch, 500) == NULL);
CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000);
/* ...but pushing a new stack frame does affect the max allocation */
CHECK(secp256k1_scratch_allocate_frame(scratch, 500, 1 == 1));
CHECK(secp256k1_scratch_max_allocation(scratch, 1) < 500); /* 500 - ALIGNMENT */
CHECK(secp256k1_scratch_alloc(scratch, 500) != NULL);
CHECK(secp256k1_scratch_alloc(scratch, 500) == NULL);
CHECK(secp256k1_scratch_allocate_frame(scratch, 500, 1) == 0);
/* ...and this effect is undone by popping the frame */
secp256k1_scratch_deallocate_frame(scratch);
CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000);
CHECK(secp256k1_scratch_alloc(scratch, 500) == NULL);
/* cleanup */
secp256k1_scratch_space_destroy(scratch);
secp256k1_context_destroy(none);
}
/***** HASH TESTS *****/ /***** HASH TESTS *****/
void run_sha256_tests(void) { void run_sha256_tests(void) {
@ -258,7 +311,7 @@ void run_sha256_tests(void) {
int i; int i;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
unsigned char out[32]; unsigned char out[32];
secp256k1_sha256_t hasher; secp256k1_sha256 hasher;
secp256k1_sha256_initialize(&hasher); secp256k1_sha256_initialize(&hasher);
secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
secp256k1_sha256_finalize(&hasher, out); secp256k1_sha256_finalize(&hasher, out);
@ -301,7 +354,7 @@ void run_hmac_sha256_tests(void) {
}; };
int i; int i;
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
secp256k1_hmac_sha256_t hasher; secp256k1_hmac_sha256 hasher;
unsigned char out[32]; unsigned char out[32];
secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i]));
secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i]));
@ -333,7 +386,7 @@ void run_rfc6979_hmac_sha256_tests(void) {
{0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94}
}; };
secp256k1_rfc6979_hmac_sha256_t rng; secp256k1_rfc6979_hmac_sha256 rng;
unsigned char out[32]; unsigned char out[32];
int i; int i;
@ -1879,9 +1932,9 @@ void test_ge(void) {
* *
* When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well.
*/ */
secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs));
secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs));
secp256k1_fe *zinv = (secp256k1_fe *)malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); secp256k1_fe *zinv = (secp256k1_fe *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs));
secp256k1_fe zf; secp256k1_fe zf;
secp256k1_fe zfi2, zfi3; secp256k1_fe zfi2, zfi3;
@ -1919,7 +1972,7 @@ void test_ge(void) {
/* Compute z inverses. */ /* Compute z inverses. */
{ {
secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); secp256k1_fe *zs = checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs));
for (i = 0; i < 4 * runs + 1; i++) { for (i = 0; i < 4 * runs + 1; i++) {
if (i == 0) { if (i == 0) {
/* The point at infinity does not have a meaningful z inverse. Any should do. */ /* The point at infinity does not have a meaningful z inverse. Any should do. */
@ -2020,7 +2073,7 @@ void test_ge(void) {
/* Test adding all points together in random order equals infinity. */ /* Test adding all points together in random order equals infinity. */
{ {
secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY;
secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); secp256k1_gej *gej_shuffled = (secp256k1_gej *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej));
for (i = 0; i < 4 * runs + 1; i++) { for (i = 0; i < 4 * runs + 1; i++) {
gej_shuffled[i] = gej[i]; gej_shuffled[i] = gej[i];
} }
@ -2041,9 +2094,9 @@ void test_ge(void) {
/* Test batch gej -> ge conversion with and without known z ratios. */ /* Test batch gej -> ge conversion with and without known z ratios. */
{ {
secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); secp256k1_fe *zr = (secp256k1_fe *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_fe));
secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); secp256k1_ge *ge_set_table = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge));
secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge));
for (i = 0; i < 4 * runs + 1; i++) { for (i = 0; i < 4 * runs + 1; i++) {
/* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */
if (i < 4 * runs) { if (i < 4 * runs) {
@ -2393,7 +2446,7 @@ void ecmult_const_random_mult(void) {
0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956
); );
secp256k1_gej b; secp256k1_gej b;
secp256k1_ecmult_const(&b, &a, &xn); secp256k1_ecmult_const(&b, &a, &xn, 256);
CHECK(secp256k1_ge_is_valid_var(&a)); CHECK(secp256k1_ge_is_valid_var(&a));
ge_equals_gej(&expected_b, &b); ge_equals_gej(&expected_b, &b);
@ -2409,12 +2462,12 @@ void ecmult_const_commutativity(void) {
random_scalar_order_test(&a); random_scalar_order_test(&a);
random_scalar_order_test(&b); random_scalar_order_test(&b);
secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a, 256);
secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b, 256);
secp256k1_ge_set_gej(&mid1, &res1); secp256k1_ge_set_gej(&mid1, &res1);
secp256k1_ge_set_gej(&mid2, &res2); secp256k1_ge_set_gej(&mid2, &res2);
secp256k1_ecmult_const(&res1, &mid1, &b); secp256k1_ecmult_const(&res1, &mid1, &b, 256);
secp256k1_ecmult_const(&res2, &mid2, &a); secp256k1_ecmult_const(&res2, &mid2, &a, 256);
secp256k1_ge_set_gej(&mid1, &res1); secp256k1_ge_set_gej(&mid1, &res1);
secp256k1_ge_set_gej(&mid2, &res2); secp256k1_ge_set_gej(&mid2, &res2);
ge_equals_ge(&mid1, &mid2); ge_equals_ge(&mid1, &mid2);
@ -2430,13 +2483,13 @@ void ecmult_const_mult_zero_one(void) {
secp256k1_scalar_negate(&negone, &one); secp256k1_scalar_negate(&negone, &one);
random_group_element_test(&point); random_group_element_test(&point);
secp256k1_ecmult_const(&res1, &point, &zero); secp256k1_ecmult_const(&res1, &point, &zero, 3);
secp256k1_ge_set_gej(&res2, &res1); secp256k1_ge_set_gej(&res2, &res1);
CHECK(secp256k1_ge_is_infinity(&res2)); CHECK(secp256k1_ge_is_infinity(&res2));
secp256k1_ecmult_const(&res1, &point, &one); secp256k1_ecmult_const(&res1, &point, &one, 2);
secp256k1_ge_set_gej(&res2, &res1); secp256k1_ge_set_gej(&res2, &res1);
ge_equals_ge(&res2, &point); ge_equals_ge(&res2, &point);
secp256k1_ecmult_const(&res1, &point, &negone); secp256k1_ecmult_const(&res1, &point, &negone, 256);
secp256k1_gej_neg(&res1, &res1); secp256k1_gej_neg(&res1, &res1);
secp256k1_ge_set_gej(&res2, &res1); secp256k1_ge_set_gej(&res2, &res1);
ge_equals_ge(&res2, &point); ge_equals_ge(&res2, &point);
@ -2462,7 +2515,7 @@ void ecmult_const_chain_multiply(void) {
for (i = 0; i < 100; ++i) { for (i = 0; i < 100; ++i) {
secp256k1_ge tmp; secp256k1_ge tmp;
secp256k1_ge_set_gej(&tmp, &point); secp256k1_ge_set_gej(&tmp, &point);
secp256k1_ecmult_const(&point, &tmp, &scalar); secp256k1_ecmult_const(&point, &tmp, &scalar, 256);
} }
secp256k1_ge_set_gej(&res, &point); secp256k1_ge_set_gej(&res, &point);
ge_equals_gej(&res, &expected_point); ge_equals_gej(&res, &expected_point);
@ -2475,6 +2528,395 @@ void run_ecmult_const_tests(void) {
ecmult_const_chain_multiply(); ecmult_const_chain_multiply();
} }
typedef struct {
secp256k1_scalar *sc;
secp256k1_ge *pt;
} ecmult_multi_data;
static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
ecmult_multi_data *data = (ecmult_multi_data*) cbdata;
*sc = data->sc[idx];
*pt = data->pt[idx];
return 1;
}
static int ecmult_multi_false_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
(void)sc;
(void)pt;
(void)idx;
(void)cbdata;
return 0;
}
void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi_func ecmult_multi) {
int ncount;
secp256k1_scalar szero;
secp256k1_scalar sc[32];
secp256k1_ge pt[32];
secp256k1_gej r;
secp256k1_gej r2;
ecmult_multi_data data;
secp256k1_scratch *scratch_empty;
data.sc = sc;
data.pt = pt;
secp256k1_scalar_set_int(&szero, 0);
/* No points to multiply */
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, NULL, ecmult_multi_callback, &data, 0));
/* Check 1- and 2-point multiplies against ecmult */
for (ncount = 0; ncount < count; ncount++) {
secp256k1_ge ptg;
secp256k1_gej ptgj;
random_scalar_order(&sc[0]);
random_scalar_order(&sc[1]);
random_group_element_test(&ptg);
secp256k1_gej_set_ge(&ptgj, &ptg);
pt[0] = ptg;
pt[1] = secp256k1_ge_const_g;
/* only G scalar */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &szero, &sc[0]);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
/* 1-point */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 1));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
/* Try to multiply 1 point, but scratch space is empty */
scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0);
CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1));
secp256k1_scratch_destroy(scratch_empty);
/* Try to multiply 1 point, but callback returns false */
CHECK(!ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_false_callback, &data, 1));
/* 2-point */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 2));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
/* 2-point with G scalar */
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &ptgj, &sc[0], &sc[1]);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
}
/* Check infinite outputs of various forms */
for (ncount = 0; ncount < count; ncount++) {
secp256k1_ge ptg;
size_t i, j;
size_t sizes[] = { 2, 10, 32 };
for (j = 0; j < 3; j++) {
for (i = 0; i < 32; i++) {
random_scalar_order(&sc[i]);
secp256k1_ge_set_infinity(&pt[i]);
}
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
for (j = 0; j < 3; j++) {
for (i = 0; i < 32; i++) {
random_group_element_test(&ptg);
pt[i] = ptg;
secp256k1_scalar_set_int(&sc[i], 0);
}
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
for (j = 0; j < 3; j++) {
random_group_element_test(&ptg);
for (i = 0; i < 16; i++) {
random_scalar_order(&sc[2*i]);
secp256k1_scalar_negate(&sc[2*i + 1], &sc[2*i]);
pt[2 * i] = ptg;
pt[2 * i + 1] = ptg;
}
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
random_scalar_order(&sc[0]);
for (i = 0; i < 16; i++) {
random_group_element_test(&ptg);
sc[2*i] = sc[0];
sc[2*i+1] = sc[0];
pt[2 * i] = ptg;
secp256k1_ge_neg(&pt[2*i+1], &pt[2*i]);
}
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j]));
CHECK(secp256k1_gej_is_infinity(&r));
}
random_group_element_test(&ptg);
secp256k1_scalar_set_int(&sc[0], 0);
pt[0] = ptg;
for (i = 1; i < 32; i++) {
pt[i] = ptg;
random_scalar_order(&sc[i]);
secp256k1_scalar_add(&sc[0], &sc[0], &sc[i]);
secp256k1_scalar_negate(&sc[i], &sc[i]);
}
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32));
CHECK(secp256k1_gej_is_infinity(&r));
}
/* Check random points, constant scalar */
for (ncount = 0; ncount < count; ncount++) {
size_t i;
secp256k1_gej_set_infinity(&r);
random_scalar_order(&sc[0]);
for (i = 0; i < 20; i++) {
secp256k1_ge ptg;
sc[i] = sc[0];
random_group_element_test(&ptg);
pt[i] = ptg;
secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL);
}
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r, &sc[0], &szero);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
}
/* Check random scalars, constant point */
for (ncount = 0; ncount < count; ncount++) {
size_t i;
secp256k1_ge ptg;
secp256k1_gej p0j;
secp256k1_scalar rs;
secp256k1_scalar_set_int(&rs, 0);
random_group_element_test(&ptg);
for (i = 0; i < 20; i++) {
random_scalar_order(&sc[i]);
pt[i] = ptg;
secp256k1_scalar_add(&rs, &rs, &sc[i]);
}
secp256k1_gej_set_ge(&p0j, &pt[0]);
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &p0j, &rs, &szero);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_gej_neg(&r2, &r2);
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
}
/* Sanity check that zero scalars don't cause problems */
secp256k1_scalar_clear(&sc[0]);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20));
secp256k1_scalar_clear(&sc[1]);
secp256k1_scalar_clear(&sc[2]);
secp256k1_scalar_clear(&sc[3]);
secp256k1_scalar_clear(&sc[4]);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6));
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 5));
CHECK(secp256k1_gej_is_infinity(&r));
/* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */
{
const size_t TOP = 8;
size_t s0i, s1i;
size_t t0i, t1i;
secp256k1_ge ptg;
secp256k1_gej ptgj;
random_group_element_test(&ptg);
secp256k1_gej_set_ge(&ptgj, &ptg);
for(t0i = 0; t0i < TOP; t0i++) {
for(t1i = 0; t1i < TOP; t1i++) {
secp256k1_gej t0p, t1p;
secp256k1_scalar t0, t1;
secp256k1_scalar_set_int(&t0, (t0i + 1) / 2);
secp256k1_scalar_cond_negate(&t0, t0i & 1);
secp256k1_scalar_set_int(&t1, (t1i + 1) / 2);
secp256k1_scalar_cond_negate(&t1, t1i & 1);
secp256k1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero);
secp256k1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero);
for(s0i = 0; s0i < TOP; s0i++) {
for(s1i = 0; s1i < TOP; s1i++) {
secp256k1_scalar tmp1, tmp2;
secp256k1_gej expected, actual;
secp256k1_ge_set_gej(&pt[0], &t0p);
secp256k1_ge_set_gej(&pt[1], &t1p);
secp256k1_scalar_set_int(&sc[0], (s0i + 1) / 2);
secp256k1_scalar_cond_negate(&sc[0], s0i & 1);
secp256k1_scalar_set_int(&sc[1], (s1i + 1) / 2);
secp256k1_scalar_cond_negate(&sc[1], s1i & 1);
secp256k1_scalar_mul(&tmp1, &t0, &sc[0]);
secp256k1_scalar_mul(&tmp2, &t1, &sc[1]);
secp256k1_scalar_add(&tmp1, &tmp1, &tmp2);
secp256k1_ecmult(&ctx->ecmult_ctx, &expected, &ptgj, &tmp1, &szero);
CHECK(ecmult_multi(&ctx->ecmult_ctx, scratch, &actual, &szero, ecmult_multi_callback, &data, 2));
secp256k1_gej_neg(&expected, &expected);
secp256k1_gej_add_var(&actual, &actual, &expected, NULL);
CHECK(secp256k1_gej_is_infinity(&actual));
}
}
}
}
}
}
void test_secp256k1_pippenger_bucket_window_inv(void) {
int i;
CHECK(secp256k1_pippenger_bucket_window_inv(0) == 0);
for(i = 1; i <= PIPPENGER_MAX_BUCKET_WINDOW; i++) {
#ifdef USE_ENDOMORPHISM
/* Bucket_window of 8 is not used with endo */
if (i == 8) {
continue;
}
#endif
CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)) == i);
if (i != PIPPENGER_MAX_BUCKET_WINDOW) {
CHECK(secp256k1_pippenger_bucket_window(secp256k1_pippenger_bucket_window_inv(i)+1) > i);
}
}
}
/**
* Probabilistically test the function returning the maximum number of possible points
* for a given scratch space.
*/
void test_ecmult_multi_pippenger_max_points(void) {
size_t scratch_size = secp256k1_rand_int(256);
size_t max_size = secp256k1_pippenger_scratch_size(secp256k1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12);
secp256k1_scratch *scratch;
size_t n_points_supported;
int bucket_window = 0;
for(; scratch_size < max_size; scratch_size+=256) {
scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size);
CHECK(scratch != NULL);
n_points_supported = secp256k1_pippenger_max_points(scratch);
if (n_points_supported == 0) {
secp256k1_scratch_destroy(scratch);
continue;
}
bucket_window = secp256k1_pippenger_bucket_window(n_points_supported);
CHECK(secp256k1_scratch_allocate_frame(scratch, secp256k1_pippenger_scratch_size(n_points_supported, bucket_window), PIPPENGER_SCRATCH_OBJECTS));
secp256k1_scratch_deallocate_frame(scratch);
secp256k1_scratch_destroy(scratch);
}
CHECK(bucket_window == PIPPENGER_MAX_BUCKET_WINDOW);
}
/**
* Run secp256k1_ecmult_multi_var with num points and a scratch space restricted to
* 1 <= i <= num points.
*/
void test_ecmult_multi_batching(void) {
static const int n_points = 2*ECMULT_PIPPENGER_THRESHOLD;
secp256k1_scalar scG;
secp256k1_scalar szero;
secp256k1_scalar *sc = (secp256k1_scalar *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_scalar) * n_points);
secp256k1_ge *pt = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * n_points);
secp256k1_gej r;
secp256k1_gej r2;
ecmult_multi_data data;
int i;
secp256k1_scratch *scratch;
secp256k1_gej_set_infinity(&r2);
secp256k1_scalar_set_int(&szero, 0);
/* Get random scalars and group elements and compute result */
random_scalar_order(&scG);
secp256k1_ecmult(&ctx->ecmult_ctx, &r2, &r2, &szero, &scG);
for(i = 0; i < n_points; i++) {
secp256k1_ge ptg;
secp256k1_gej ptgj;
random_group_element_test(&ptg);
secp256k1_gej_set_ge(&ptgj, &ptg);
pt[i] = ptg;
random_scalar_order(&sc[i]);
secp256k1_ecmult(&ctx->ecmult_ctx, &ptgj, &ptgj, &sc[i], NULL);
secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL);
}
data.sc = sc;
data.pt = pt;
/* Test with empty scratch space */
scratch = secp256k1_scratch_create(&ctx->error_callback, 0);
CHECK(!secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, 1));
secp256k1_scratch_destroy(scratch);
/* Test with space for 1 point in pippenger. That's not enough because
* ecmult_multi selects strauss which requires more memory. */
scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT);
CHECK(!secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, 1));
secp256k1_scratch_destroy(scratch);
secp256k1_gej_neg(&r2, &r2);
for(i = 1; i <= n_points; i++) {
if (i > ECMULT_PIPPENGER_THRESHOLD) {
int bucket_window = secp256k1_pippenger_bucket_window(i);
size_t scratch_size = secp256k1_pippenger_scratch_size(i, bucket_window);
scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT);
} else {
size_t scratch_size = secp256k1_strauss_scratch_size(i);
scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT);
}
CHECK(secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points));
secp256k1_gej_add_var(&r, &r, &r2, NULL);
CHECK(secp256k1_gej_is_infinity(&r));
secp256k1_scratch_destroy(scratch);
}
free(sc);
free(pt);
}
void run_ecmult_multi_tests(void) {
secp256k1_scratch *scratch;
test_secp256k1_pippenger_bucket_window_inv();
test_ecmult_multi_pippenger_max_points();
scratch = secp256k1_scratch_create(&ctx->error_callback, 819200);
test_ecmult_multi(scratch, secp256k1_ecmult_multi_var);
test_ecmult_multi(scratch, secp256k1_ecmult_pippenger_batch_single);
test_ecmult_multi(scratch, secp256k1_ecmult_strauss_batch_single);
secp256k1_scratch_destroy(scratch);
/* Run test_ecmult_multi with space for exactly one point */
scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_strauss_scratch_size(1) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT);
test_ecmult_multi(scratch, secp256k1_ecmult_multi_var);
secp256k1_scratch_destroy(scratch);
test_ecmult_multi_batching();
}
void test_wnaf(const secp256k1_scalar *number, int w) { void test_wnaf(const secp256k1_scalar *number, int w) {
secp256k1_scalar x, two, t; secp256k1_scalar x, two, t;
int wnaf[256]; int wnaf[256];
@ -2529,6 +2971,7 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) {
int wnaf[256] = {0}; int wnaf[256] = {0};
int i; int i;
int skew; int skew;
int bits = 256;
secp256k1_scalar num = *number; secp256k1_scalar num = *number;
secp256k1_scalar_set_int(&x, 0); secp256k1_scalar_set_int(&x, 0);
@ -2538,10 +2981,11 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) {
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i) {
secp256k1_scalar_shr_int(&num, 8); secp256k1_scalar_shr_int(&num, 8);
} }
bits = 128;
#endif #endif
skew = secp256k1_wnaf_const(wnaf, num, w); skew = secp256k1_wnaf_const(wnaf, num, w, bits);
for (i = WNAF_SIZE(w); i >= 0; --i) { for (i = WNAF_SIZE_BITS(bits, w); i >= 0; --i) {
secp256k1_scalar t; secp256k1_scalar t;
int v = wnaf[i]; int v = wnaf[i];
CHECK(v != 0); /* check nonzero */ CHECK(v != 0); /* check nonzero */
@ -2563,6 +3007,110 @@ void test_constant_wnaf(const secp256k1_scalar *number, int w) {
CHECK(secp256k1_scalar_eq(&x, &num)); CHECK(secp256k1_scalar_eq(&x, &num));
} }
void test_fixed_wnaf(const secp256k1_scalar *number, int w) {
secp256k1_scalar x, shift;
int wnaf[256] = {0};
int i;
int skew;
secp256k1_scalar num = *number;
secp256k1_scalar_set_int(&x, 0);
secp256k1_scalar_set_int(&shift, 1 << w);
/* With USE_ENDOMORPHISM on we only consider 128-bit numbers */
#ifdef USE_ENDOMORPHISM
for (i = 0; i < 16; ++i) {
secp256k1_scalar_shr_int(&num, 8);
}
#endif
skew = secp256k1_wnaf_fixed(wnaf, &num, w);
for (i = WNAF_SIZE(w)-1; i >= 0; --i) {
secp256k1_scalar t;
int v = wnaf[i];
CHECK(v == 0 || v & 1); /* check parity */
CHECK(v > -(1 << w)); /* check range above */
CHECK(v < (1 << w)); /* check range below */
secp256k1_scalar_mul(&x, &x, &shift);
if (v >= 0) {
secp256k1_scalar_set_int(&t, v);
} else {
secp256k1_scalar_set_int(&t, -v);
secp256k1_scalar_negate(&t, &t);
}
secp256k1_scalar_add(&x, &x, &t);
}
/* If skew is 1 then add 1 to num */
secp256k1_scalar_cadd_bit(&num, 0, skew == 1);
CHECK(secp256k1_scalar_eq(&x, &num));
}
/* Checks that the first 8 elements of wnaf are equal to wnaf_expected and the
* rest is 0.*/
void test_fixed_wnaf_small_helper(int *wnaf, int *wnaf_expected, int w) {
int i;
for (i = WNAF_SIZE(w)-1; i >= 8; --i) {
CHECK(wnaf[i] == 0);
}
for (i = 7; i >= 0; --i) {
CHECK(wnaf[i] == wnaf_expected[i]);
}
}
void test_fixed_wnaf_small(void) {
int w = 4;
int wnaf[256] = {0};
int i;
int skew;
secp256k1_scalar num;
secp256k1_scalar_set_int(&num, 0);
skew = secp256k1_wnaf_fixed(wnaf, &num, w);
for (i = WNAF_SIZE(w)-1; i >= 0; --i) {
int v = wnaf[i];
CHECK(v == 0);
}
CHECK(skew == 0);
secp256k1_scalar_set_int(&num, 1);
skew = secp256k1_wnaf_fixed(wnaf, &num, w);
for (i = WNAF_SIZE(w)-1; i >= 1; --i) {
int v = wnaf[i];
CHECK(v == 0);
}
CHECK(wnaf[0] == 1);
CHECK(skew == 0);
{
int wnaf_expected[8] = { 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf };
secp256k1_scalar_set_int(&num, 0xffffffff);
skew = secp256k1_wnaf_fixed(wnaf, &num, w);
test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w);
CHECK(skew == 0);
}
{
int wnaf_expected[8] = { -1, -1, -1, -1, -1, -1, -1, 0xf };
secp256k1_scalar_set_int(&num, 0xeeeeeeee);
skew = secp256k1_wnaf_fixed(wnaf, &num, w);
test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w);
CHECK(skew == 1);
}
{
int wnaf_expected[8] = { 1, 0, 1, 0, 1, 0, 1, 0 };
secp256k1_scalar_set_int(&num, 0x01010101);
skew = secp256k1_wnaf_fixed(wnaf, &num, w);
test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w);
CHECK(skew == 0);
}
{
int wnaf_expected[8] = { -0xf, 0, 0xf, -0xf, 0, 0xf, 1, 0 };
secp256k1_scalar_set_int(&num, 0x01ef1ef1);
skew = secp256k1_wnaf_fixed(wnaf, &num, w);
test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w);
CHECK(skew == 0);
}
}
void run_wnaf(void) { void run_wnaf(void) {
int i; int i;
secp256k1_scalar n = {{0}}; secp256k1_scalar n = {{0}};
@ -2573,12 +3121,15 @@ void run_wnaf(void) {
test_constant_wnaf(&n, 4); test_constant_wnaf(&n, 4);
n.d[0] = 2; n.d[0] = 2;
test_constant_wnaf(&n, 4); test_constant_wnaf(&n, 4);
/* Test 0 */
test_fixed_wnaf_small();
/* Random tests */ /* Random tests */
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
random_scalar_order(&n); random_scalar_order(&n);
test_wnaf(&n, 4+(i%10)); test_wnaf(&n, 4+(i%10));
test_constant_wnaf_negate(&n); test_constant_wnaf_negate(&n);
test_constant_wnaf(&n, 4 + (i % 10)); test_constant_wnaf(&n, 4 + (i % 10));
test_fixed_wnaf(&n, 4 + (i % 10));
} }
secp256k1_scalar_set_int(&n, 0); secp256k1_scalar_set_int(&n, 0);
CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1);
@ -3165,7 +3716,7 @@ void run_eckey_edge_case_test(void) {
VG_CHECK(&pubkey, sizeof(pubkey)); VG_CHECK(&pubkey, sizeof(pubkey));
CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0);
pubkey_negone = pubkey; pubkey_negone = pubkey;
/* Tweak of zero leaves the value changed. */ /* Tweak of zero leaves the value unchanged. */
memset(ctmp2, 0, 32); memset(ctmp2, 0, 32);
CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1);
CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40);
@ -3436,6 +3987,7 @@ void test_ecdsa_end_to_end(void) {
unsigned char pubkeyc[65]; unsigned char pubkeyc[65];
size_t pubkeyclen = 65; size_t pubkeyclen = 65;
secp256k1_pubkey pubkey; secp256k1_pubkey pubkey;
secp256k1_pubkey pubkey_tmp;
unsigned char seckey[300]; unsigned char seckey[300];
size_t seckeylen = 300; size_t seckeylen = 300;
@ -3457,6 +4009,13 @@ void test_ecdsa_end_to_end(void) {
memset(&pubkey, 0, sizeof(pubkey)); memset(&pubkey, 0, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1);
/* Verify negation changes the key and changes it back */
memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey));
CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0);
CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0);
/* Verify private key import and export. */ /* Verify private key import and export. */
CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1));
CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);
@ -3648,6 +4207,7 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_
#ifdef ENABLE_OPENSSL_TESTS #ifdef ENABLE_OPENSSL_TESTS
ECDSA_SIG *sig_openssl; ECDSA_SIG *sig_openssl;
const BIGNUM *r = NULL, *s = NULL;
const unsigned char *sigptr; const unsigned char *sigptr;
unsigned char roundtrip_openssl[2048]; unsigned char roundtrip_openssl[2048];
int len_openssl = 2048; int len_openssl = 2048;
@ -3699,15 +4259,16 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_
sigptr = sig; sigptr = sig;
parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL); parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL);
if (parsed_openssl) { if (parsed_openssl) {
valid_openssl = !BN_is_negative(sig_openssl->r) && !BN_is_negative(sig_openssl->s) && BN_num_bits(sig_openssl->r) > 0 && BN_num_bits(sig_openssl->r) <= 256 && BN_num_bits(sig_openssl->s) > 0 && BN_num_bits(sig_openssl->s) <= 256; ECDSA_SIG_get0(sig_openssl, &r, &s);
valid_openssl = !BN_is_negative(r) && !BN_is_negative(s) && BN_num_bits(r) > 0 && BN_num_bits(r) <= 256 && BN_num_bits(s) > 0 && BN_num_bits(s) <= 256;
if (valid_openssl) { if (valid_openssl) {
unsigned char tmp[32] = {0}; unsigned char tmp[32] = {0};
BN_bn2bin(sig_openssl->r, tmp + 32 - BN_num_bytes(sig_openssl->r)); BN_bn2bin(r, tmp + 32 - BN_num_bytes(r));
valid_openssl = memcmp(tmp, max_scalar, 32) < 0; valid_openssl = memcmp(tmp, max_scalar, 32) < 0;
} }
if (valid_openssl) { if (valid_openssl) {
unsigned char tmp[32] = {0}; unsigned char tmp[32] = {0};
BN_bn2bin(sig_openssl->s, tmp + 32 - BN_num_bytes(sig_openssl->s)); BN_bn2bin(s, tmp + 32 - BN_num_bytes(s));
valid_openssl = memcmp(tmp, max_scalar, 32) < 0; valid_openssl = memcmp(tmp, max_scalar, 32) < 0;
} }
} }
@ -4383,10 +4944,6 @@ void run_ecdsa_openssl(void) {
# include "modules/ecdh/tests_impl.h" # include "modules/ecdh/tests_impl.h"
#endif #endif
#ifdef ENABLE_MODULE_SCHNORR
# include "modules/schnorr/tests_impl.h"
#endif
#ifdef ENABLE_MODULE_RECOVERY #ifdef ENABLE_MODULE_RECOVERY
# include "modules/recovery/tests_impl.h" # include "modules/recovery/tests_impl.h"
#endif #endif
@ -4415,7 +4972,7 @@ int main(int argc, char **argv) {
} }
} else { } else {
FILE *frand = fopen("/dev/urandom", "r"); FILE *frand = fopen("/dev/urandom", "r");
if ((frand == NULL) || !fread(&seed16, sizeof(seed16), 1, frand)) { if ((frand == NULL) || fread(&seed16, sizeof(seed16), 1, frand) != sizeof(seed16)) {
uint64_t t = time(NULL) * (uint64_t)1337; uint64_t t = time(NULL) * (uint64_t)1337;
seed16[0] ^= t; seed16[0] ^= t;
seed16[1] ^= t >> 8; seed16[1] ^= t >> 8;
@ -4426,8 +4983,10 @@ int main(int argc, char **argv) {
seed16[6] ^= t >> 48; seed16[6] ^= t >> 48;
seed16[7] ^= t >> 56; seed16[7] ^= t >> 56;
} }
if (frand) {
fclose(frand); fclose(frand);
} }
}
secp256k1_rand_seed(seed16); secp256k1_rand_seed(seed16);
printf("test count = %i\n", count); printf("test count = %i\n", count);
@ -4435,6 +4994,7 @@ int main(int argc, char **argv) {
/* initialize */ /* initialize */
run_context_tests(); run_context_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)) {
secp256k1_rand256(run32); secp256k1_rand256(run32);
@ -4476,6 +5036,7 @@ int main(int argc, char **argv) {
run_ecmult_constants(); run_ecmult_constants();
run_ecmult_gen_blind(); run_ecmult_gen_blind();
run_ecmult_const_tests(); run_ecmult_const_tests();
run_ecmult_multi_tests();
run_ec_combine(); run_ec_combine();
/* endomorphism tests */ /* endomorphism tests */
@ -4504,11 +5065,6 @@ int main(int argc, char **argv) {
run_ecdsa_openssl(); run_ecdsa_openssl();
#endif #endif
#ifdef ENABLE_MODULE_SCHNORR
/* Schnorr tests */
run_schnorr_tests();
#endif
#ifdef ENABLE_MODULE_RECOVERY #ifdef ENABLE_MODULE_RECOVERY
/* ECDSA pubkey recovery tests */ /* ECDSA pubkey recovery tests */
run_recovery_tests(); run_recovery_tests();

View file

@ -174,7 +174,7 @@ void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *gr
ge_equals_gej(&group[(i * r_log + j) % order], &tmp); ge_equals_gej(&group[(i * r_log + j) % order], &tmp);
if (i > 0) { if (i > 0) {
secp256k1_ecmult_const(&tmp, &group[i], &ng); secp256k1_ecmult_const(&tmp, &group[i], &ng, 256);
ge_equals_gej(&group[(i * j) % order], &tmp); ge_equals_gej(&group[(i * j) % order], &tmp);
} }
} }
@ -182,6 +182,46 @@ void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *gr
} }
} }
typedef struct {
secp256k1_scalar sc[2];
secp256k1_ge pt[2];
} ecmult_multi_data;
static int ecmult_multi_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *cbdata) {
ecmult_multi_data *data = (ecmult_multi_data*) cbdata;
*sc = data->sc[idx];
*pt = data->pt[idx];
return 1;
}
void test_exhaustive_ecmult_multi(const secp256k1_context *ctx, const secp256k1_ge *group, int order) {
int i, j, k, x, y;
secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 4096);
for (i = 0; i < order; i++) {
for (j = 0; j < order; j++) {
for (k = 0; k < order; k++) {
for (x = 0; x < order; x++) {
for (y = 0; y < order; y++) {
secp256k1_gej tmp;
secp256k1_scalar g_sc;
ecmult_multi_data data;
secp256k1_scalar_set_int(&data.sc[0], i);
secp256k1_scalar_set_int(&data.sc[1], j);
secp256k1_scalar_set_int(&g_sc, k);
data.pt[0] = group[x];
data.pt[1] = group[y];
secp256k1_ecmult_multi_var(&ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2);
ge_equals_gej(&group[(i * x + j * y + k) % order], &tmp);
}
}
}
}
}
secp256k1_scratch_destroy(scratch);
}
void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) { void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) {
secp256k1_fe x; secp256k1_fe x;
unsigned char x_bin[32]; unsigned char x_bin[32];
@ -456,6 +496,7 @@ int main(void) {
#endif #endif
test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER);
test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER);
test_exhaustive_ecmult_multi(ctx, group, EXHAUSTIVE_TEST_ORDER);
test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER);
test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER);

View file

@ -4,8 +4,8 @@
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/ **********************************************************************/
#ifndef _SECP256K1_UTIL_H_ #ifndef SECP256K1_UTIL_H
#define _SECP256K1_UTIL_H_ #define SECP256K1_UTIL_H
#if defined HAVE_CONFIG_H #if defined HAVE_CONFIG_H
#include "libsecp256k1-config.h" #include "libsecp256k1-config.h"
@ -76,6 +76,14 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_
return ret; return ret;
} }
static SECP256K1_INLINE void *checked_realloc(const secp256k1_callback* cb, void *ptr, size_t size) {
void *ret = realloc(ptr, size);
if (ret == NULL) {
secp256k1_callback_call(cb, "Out of memory");
}
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
@ -110,4 +118,4 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_
SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t;
#endif #endif
#endif #endif /* SECP256K1_UTIL_H */