diff --git a/src/secp256k1/CMakeLists.txt b/src/secp256k1/CMakeLists.txt index b3cdd7f491..4c45c31569 100644 --- a/src/secp256k1/CMakeLists.txt +++ b/src/secp256k1/CMakeLists.txt @@ -1,236 +1,237 @@ # Copyright (c) 2017 The Bitcoin developers cmake_minimum_required(VERSION 3.5) project(secp256k1 LANGUAGES C) # Add path for custom modules when building as a standalone project list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules) include(AddCompilerFlags) # libsecp256k1 use a different set of flags. add_c_compiler_flags( -pedantic -Wall -Wextra -Wcast-align -Wshadow -Wno-unused-function -Wno-overlength-strings -std=c89 -Wnested-externs -Wstrict-prototypes -Wno-long-long ) # Default visibility is hidden on all targets. set(CMAKE_C_VISIBILITY_PRESET hidden) include_directories( . src # For the config ${CMAKE_CURRENT_BINARY_DIR}/src ) # The library add_library(secp256k1 src/secp256k1.c) target_include_directories(secp256k1 PUBLIC include) # We need to link in GMP find_package(GMP) if(GMP_FOUND) target_include_directories(secp256k1 PUBLIC ${GMP_INCLUDE_DIR}) target_link_libraries(secp256k1 ${GMP_LIBRARY}) set(USE_NUM_GMP 1) set(USE_FIELD_INV_NUM 1) set(USE_SCALAR_INV_NUM 1) else() set(USE_NUM_NONE 1) set(USE_FIELD_INV_BUILTIN 1) set(USE_SCALAR_INV_BUILTIN 1) endif() # We check if amd64 asm is supported. check_c_source_compiles(" #include int main() { uint64_t a = 11, tmp; __asm__ __volatile__(\"movq \$0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\"); return 0; } " USE_ASM_X86_64) # We make sure __int128 is defined include(CheckTypeSize) check_type_size(__int128 SIZEOF___INT128) if(SIZEOF___INT128 EQUAL 16) set(HAVE___INT128 1) else() # If we do not support __int128, we should be falling back # on 32bits implementations for field and scalar. endif() # Detect if we are on a 32 or 64 bits platform and chose # scalar and field implementation accordingly. if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64 bits implementation require either __int128 or asm support. if (HAVE___INT128 OR USE_ASM_X86_64) set(USE_SCALAR_4X64 1) set(USE_FIELD_5X52 1) else() message(SEND_ERROR "Compiler does not support __int128 or inline assembly") endif() else() set(USE_SCALAR_8X32 1) set(USE_FIELD_10X26 1) endif() # Executable internal to secp256k1 need to have the HAVE_CONFIG_H define set. # For convenience, we wrap this into a function. function(link_secp256k1_internal NAME) target_link_libraries(${NAME} secp256k1) target_compile_definitions(${NAME} PRIVATE HAVE_CONFIG_H SECP256K1_BUILD) endfunction(link_secp256k1_internal) # Phony target to build benchmarks add_custom_target(bench-secp256k1) function(add_secp256k1_bench NAME) set(EXECUTABLE_NAME "${NAME}-bench") add_executable(${EXECUTABLE_NAME} EXCLUDE_FROM_ALL ${ARGN}) link_secp256k1_internal(${EXECUTABLE_NAME}) set(BENCH_NAME "bench-secp256k1-${NAME}") add_custom_target(${BENCH_NAME} COMMAND ${EXECUTABLE_NAME} USES_TERMINAL) add_dependencies(bench-secp256k1 ${BENCH_NAME}) endfunction(add_secp256k1_bench) # ECDH module option(SECP256K1_ENABLE_MODULE_ECDH "Build libsecp256k1's ECDH module" OFF) if(SECP256K1_ENABLE_MODULE_ECDH) set(ENABLE_MODULE_ECDH 1) add_secp256k1_bench(ecdh src/bench_ecdh.c) endif() # MultiSet module option(SECP256K1_ENABLE_MODULE_MULTISET "Build libsecp256k1's MULTISET module" ON) if(SECP256K1_ENABLE_MODULE_MULTISET) set(ENABLE_MODULE_MULTISET 1) add_secp256k1_bench(multiset src/bench_multiset.c) endif() # Recovery module option(SECP256K1_ENABLE_MODULE_RECOVERY "Build libsecp256k1's recovery module" ON) if(SECP256K1_ENABLE_MODULE_RECOVERY) set(ENABLE_MODULE_RECOVERY 1) add_secp256k1_bench(recover src/bench_recover.c) endif() # Schnorr module option(SECP256K1_ENABLE_MODULE_SCHNORR "Build libsecp256k1's Schnorr module" ON) if(SECP256K1_ENABLE_MODULE_SCHNORR) set(ENABLE_MODULE_SCHNORR 1) endif() # Static precomputation for elliptic curve multiplication option(SECP256K1_ECMULT_STATIC_PRECOMPUTATION "Precompute libsecp256k1's elliptic curve multiplication tables" ON) if(SECP256K1_ECMULT_STATIC_PRECOMPUTATION) set(USE_ECMULT_STATIC_PRECOMPUTATION 1) include(NativeExecutable) add_native_executable(gen_context src/gen_context.c) add_custom_command( OUTPUT src/ecmult_static_context.h COMMAND gen_context ) target_sources(secp256k1 PRIVATE src/ecmult_static_context.h) endif() # Generate the config configure_file(src/libsecp256k1-config.h.cmake.in src/libsecp256k1-config.h ESCAPE_QUOTES) target_compile_definitions(secp256k1 PRIVATE HAVE_CONFIG_H SECP256K1_BUILD) # Build the Java binding option(SECP256K1_ENABLE_JNI "Enable the Java Native Interface binding" OFF) if(SECP256K1_ENABLE_JNI) if(NOT SECP256K1_ENABLE_MODULE_ECDH) message(FATAL_ERROR "The secp256k1 JNI support requires ECDH. Try again with -DSECP256K1_ENABLE_MODULE_ECDH=ON.") endif() find_package(Java REQUIRED) find_package(JNI REQUIRED) include(UseJava) add_library(secp256k1_jni SHARED src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c ) target_include_directories(secp256k1_jni PUBLIC ${JNI_INCLUDE_DIRS}) # As per CMake documentation: the POSITION_INDEPENDENT_CODE property is set # when a target is created. It defaults to True for SHARED or MODULE library # targets and False otherwise. # The secp256ki_jni library being shared, the property is set and it will # build with PIC enabled. But the secp256k1 dependency might not have the # property set, so it's associated source files won't be built with PIC # enabled. That would cause the linker to fail. # Forcing the property for the secp256k1 library fixes the issue. set_target_properties(secp256k1 PROPERTIES POSITION_INDEPENDENT_CODE ON) link_secp256k1_internal(secp256k1_jni) endif() # Tests option(SECP256K1_BUILD_TEST "Build secp256k1's unit tests" ON) if(SECP256K1_BUILD_TEST) include(TestSuite) create_test_suite(secp256k1) function(create_secp256k1_test NAME FILES) add_test_to_suite(secp256k1 ${NAME} EXCLUDE_FROM_ALL ${FILES}) link_secp256k1_internal(${NAME}) endfunction() create_secp256k1_test(tests src/tests.c) target_compile_definitions(tests PRIVATE VERIFY) create_secp256k1_test(exhaustive_tests src/tests_exhaustive.c) # This should not be enabled at the same time as coverage is. # TODO: support coverage. target_compile_definitions(exhaustive_tests PRIVATE VERIFY) if(SECP256K1_ENABLE_JNI) set(SECP256k1_JNI_TEST_JAR "secp256k1-jni-test") set(CMAKE_JNI_TARGET TRUE) add_jar(secp256k1-jni-test-jar SOURCES src/java/org/bitcoin/NativeSecp256k1.java src/java/org/bitcoin/NativeSecp256k1Test.java src/java/org/bitcoin/NativeSecp256k1Util.java src/java/org/bitcoin/Secp256k1Context.java ENTRY_POINT org/bitcoin/NativeSecp256k1Test OUTPUT_NAME "${SECP256k1_JNI_TEST_JAR}" ) add_dependencies(secp256k1-jni-test-jar secp256k1_jni) add_custom_target(check-secp256k1-java COMMAND "${Java_JAVA_EXECUTABLE}" "-Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}" "-jar" "${SECP256k1_JNI_TEST_JAR}.jar" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" ) add_dependencies(check-secp256k1-java secp256k1-jni-test-jar) add_dependencies(check-secp256k1 check-secp256k1-java) endif() endif(SECP256K1_BUILD_TEST) # Benchmarks add_secp256k1_bench(verify src/bench_verify.c) add_secp256k1_bench(sign src/bench_sign.c) add_secp256k1_bench(internal src/bench_internal.c) +add_secp256k1_bench(ecmult src/bench_ecmult.c) diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am index f256dc0110..2af38ef2a0 100644 --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -1,180 +1,186 @@ ACLOCAL_AMFLAGS = -I build-aux/m4 SECP256K1_LIB = libsecp256k1.la lib_LTLIBRARIES = $(SECP256K1_LIB) if USE_JNI lib_LTLIBRARIES += libsecp256k1_jni.la endif include_HEADERS = include/secp256k1.h noinst_HEADERS = noinst_HEADERS += src/scalar.h noinst_HEADERS += src/scalar_4x64.h noinst_HEADERS += src/scalar_8x32.h noinst_HEADERS += src/scalar_low.h noinst_HEADERS += src/scalar_impl.h noinst_HEADERS += src/scalar_4x64_impl.h noinst_HEADERS += src/scalar_8x32_impl.h noinst_HEADERS += src/scalar_low_impl.h noinst_HEADERS += src/group.h noinst_HEADERS += src/group_impl.h noinst_HEADERS += src/num_gmp.h noinst_HEADERS += src/num_gmp_impl.h noinst_HEADERS += src/ecdsa.h noinst_HEADERS += src/ecdsa_impl.h noinst_HEADERS += src/eckey.h noinst_HEADERS += src/eckey_impl.h noinst_HEADERS += src/ecmult.h noinst_HEADERS += src/ecmult_impl.h noinst_HEADERS += src/ecmult_const.h noinst_HEADERS += src/ecmult_const_impl.h noinst_HEADERS += src/ecmult_gen.h noinst_HEADERS += src/ecmult_gen_impl.h noinst_HEADERS += src/num.h noinst_HEADERS += src/num_impl.h noinst_HEADERS += src/field_10x26.h noinst_HEADERS += src/field_10x26_impl.h noinst_HEADERS += src/field_5x52.h noinst_HEADERS += src/field_5x52_impl.h noinst_HEADERS += src/field_5x52_int128_impl.h noinst_HEADERS += src/field_5x52_asm_impl.h noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.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_impl.h noinst_HEADERS += src/hash.h noinst_HEADERS += src/hash_impl.h noinst_HEADERS += src/field.h noinst_HEADERS += src/field_impl.h noinst_HEADERS += src/bench.h noinst_HEADERS += contrib/lax_der_parsing.h noinst_HEADERS += contrib/lax_der_parsing.c noinst_HEADERS += contrib/lax_der_privatekey_parsing.h noinst_HEADERS += contrib/lax_der_privatekey_parsing.c if USE_EXTERNAL_ASM COMMON_LIB = libsecp256k1_common.la noinst_LTLIBRARIES = $(COMMON_LIB) else COMMON_LIB = endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsecp256k1.pc if USE_EXTERNAL_ASM if USE_ASM_ARM libsecp256k1_common_la_SOURCES = src/asm/field_10x26_arm.s endif endif libsecp256k1_la_SOURCES = src/secp256k1.c libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) libsecp256k1_jni_la_LIBADD = $(SECP256K1_LIB) noinst_PROGRAMS = 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_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_sign_SOURCES = src/bench_sign.c bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_internal_SOURCES = src/bench_internal.c bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) bench_internal_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) +bench_ecmult_SOURCES = src/bench_ecmult.c +bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_ecmult_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) endif TESTS = if USE_TESTS noinst_PROGRAMS += tests tests_SOURCES = src/tests.c tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) if !ENABLE_COVERAGE tests_CPPFLAGS += -DVERIFY endif tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) tests_LDFLAGS = -static TESTS += tests endif if USE_EXHAUSTIVE_TESTS noinst_PROGRAMS += exhaustive_tests exhaustive_tests_SOURCES = src/tests_exhaustive.c exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) if !ENABLE_COVERAGE exhaustive_tests_CPPFLAGS += -DVERIFY endif exhaustive_tests_LDADD = $(SECP_LIBS) exhaustive_tests_LDFLAGS = -static TESTS += exhaustive_tests endif JAVA_ROOT=src/java JAVA_ORG=org/bitcoin JAVA_SRC=$(top_srcdir)/$(JAVA_ROOT)/$(JAVA_ORG) JAVA_BUILD=$(top_builddir)/$(JAVA_ROOT) JAVA_FILES= \ $(JAVA_SRC)/NativeSecp256k1.java \ $(JAVA_SRC)/NativeSecp256k1Test.java \ $(JAVA_SRC)/NativeSecp256k1Util.java \ $(JAVA_SRC)/Secp256k1Context.java if USE_JNI .stamp-java: $(JAVA_FILES) @echo Compiling $^ $(AM_V_at)javac -d "$(JAVA_BUILD)" $^ @touch $@ if USE_TESTS check-java: libsecp256k1_jni.la .stamp-java $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -enableassertions -cp "$(JAVA_BUILD)" $(JAVA_ORG)/NativeSecp256k1Test endif endif if USE_ECMULT_STATIC_PRECOMPUTATION CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function gen_context_OBJECTS = gen_context.o gen_context_BIN = gen_context$(BUILD_EXEEXT) gen_%.o: src/gen_%.c $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ $(gen_context_BIN): $(gen_context_OBJECTS) $(CC_FOR_BUILD) $^ -o $@ $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(tests_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) ./$(gen_context_BIN) CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVA_BUILD)/$(JAVA_ORG)/*.class .stamp-java endif EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) if ENABLE_MODULE_ECDH include src/modules/ecdh/Makefile.am.include endif if ENABLE_MODULE_MULTISET include src/modules/multiset/Makefile.am.include endif if ENABLE_MODULE_RECOVERY include src/modules/recovery/Makefile.am.include endif if ENABLE_MODULE_SCHNORR include src/modules/schnorr/Makefile.am.include endif diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h index 732dd19f21..91cdd3672f 100644 --- a/src/secp256k1/include/secp256k1.h +++ b/src/secp256k1/include/secp256k1.h @@ -1,621 +1,656 @@ #ifndef SECP256K1_H #define SECP256K1_H #ifdef __cplusplus extern "C" { #endif #include /* These rules specify the order of arguments in API calls: * * 1. Context pointers go first, followed by output arguments, combined * output/input arguments, and finally input-only arguments. * 2. Array lengths always immediately the follow the argument whose length * they describe, even if this violates rule 1. * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated * later go first. This means: signatures, public nonces, private nonces, * messages, public keys, secret keys, tweaks. * 4. Arguments that are not data pointers go last, from more complex to less * complex: function pointers, algorithm names, messages, void pointers, * counts, flags, booleans. * 5. Opaque data pointers follow the function pointer they are to be passed to. */ /** Opaque data structure that holds context information (precomputed tables etc.). * * The purpose of context structures is to cache large precomputed data tables * that are expensive to construct, and also to maintain the randomization data * for blinding. * * Do not create a new context object for each operation, as construction is * far slower than all other API calls (~100 times slower than an ECDSA * verification). * * A constructed context can safely be used from multiple threads * simultaneously, but API call that take a non-const pointer to a context * need exclusive access to it. In particular this is the case for * secp256k1_context_destroy and secp256k1_context_randomize. * * Regarding randomization, either do it once at creation time (in which case * you do not need any locking for the other calls), or use a read-write lock. */ 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. * * The exact representation of data inside is implementation defined and not * guaranteed to be portable between different platforms or versions. It is * 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 * comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. */ typedef struct { unsigned char data[64]; } secp256k1_pubkey; /** Opaque data structured that holds a parsed ECDSA signature. * * The exact representation of data inside is implementation defined and not * guaranteed to be portable between different platforms or versions. It is * 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 * comparison, use the secp256k1_ecdsa_signature_serialize_* and * secp256k1_ecdsa_signature_parse_* functions. */ typedef struct { unsigned char data[64]; } secp256k1_ecdsa_signature; /** A pointer to a function to deterministically generate a nonce. * * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. * Out: nonce32: pointer to a 32-byte array to be filled by the function. * In: msg32: the 32-byte message hash being verified (will not be NULL) * key32: pointer to a 32-byte secret key (will not be NULL) * algo16: pointer to a 16-byte array describing the signature * algorithm (will be NULL for ECDSA for compatibility). * data: Arbitrary data pointer that is passed through. * attempt: how many iterations we have tried to find a nonce. * This will almost always be 0, but different attempt values * are required to result in a different nonce. * * Except for test cases, this function should compute some cryptographic hash of * the message, the algorithm, the key and the attempt. */ typedef int (*secp256k1_nonce_function)( unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int attempt ); # if !defined(SECP256K1_GNUC_PREREQ) # if defined(__GNUC__)&&defined(__GNUC_MINOR__) # define SECP256K1_GNUC_PREREQ(_maj,_min) \ ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) # else # define SECP256K1_GNUC_PREREQ(_maj,_min) 0 # endif # endif # if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) # if SECP256K1_GNUC_PREREQ(2,7) # define SECP256K1_INLINE __inline__ # elif (defined(_MSC_VER)) # define SECP256K1_INLINE __inline # else # define SECP256K1_INLINE # endif # else # define SECP256K1_INLINE inline # endif #ifndef SECP256K1_API # if defined(_WIN32) # ifdef SECP256K1_BUILD # define SECP256K1_API __declspec(dllexport) # else # define SECP256K1_API # endif # elif defined(__GNUC__) && defined(SECP256K1_BUILD) # define SECP256K1_API __attribute__ ((visibility ("default"))) # else # define SECP256K1_API # endif #endif /**Warning attributes * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out * some paranoid null checks. */ # if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) # define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) # else # define SECP256K1_WARN_UNUSED_RESULT # endif # if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) # define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) # else # define SECP256K1_ARG_NONNULL(_x) # endif /** All flags' lower 8 bits indicate what they're for. Do not use directly. */ #define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) #define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) #define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) /** The higher bits contain the actual data. Do not use directly. */ #define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) #define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) #define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) /** Flags to pass to secp256k1_context_create. */ #define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) #define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) #define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) /** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_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. * * Returns: a newly created context object. * In: flags: which parts of the context to initialize. * * See also secp256k1_context_randomize. */ SECP256K1_API secp256k1_context* secp256k1_context_create( unsigned int flags ) SECP256K1_WARN_UNUSED_RESULT; /** Copies a secp256k1 context object. * * Returns: a newly created context object. * Args: ctx: an existing context to copy (cannot be NULL) */ SECP256K1_API secp256k1_context* secp256k1_context_clone( const secp256k1_context* ctx ) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; /** Destroy a secp256k1 context object. * * The context pointer may not be used afterwards. * Args: ctx: an existing context to destroy (cannot be NULL) */ SECP256K1_API void secp256k1_context_destroy( secp256k1_context* ctx ); /** Set a callback function to be called when an illegal argument is passed to * an API call. It will only trigger for violations that are mentioned * explicitly in the header. * * The philosophy is that these shouldn't be dealt with through a * specific return value, as calling code should not have branches to deal with * the case that this code itself is broken. * * On the other hand, during debug stage, one would want to be informed about * such mistakes, and the default (crashing) may be inadvisable. * When this callback is triggered, the API function called is guaranteed not * to cause a crash, though its return value and output arguments are * undefined. * * Args: ctx: an existing context object (cannot be NULL) * In: fun: a pointer to a function to call when an illegal argument is * passed to the API, taking a message and an opaque pointer * (NULL restores a default handler that calls abort). * data: the opaque pointer to pass to fun above. */ SECP256K1_API void secp256k1_context_set_illegal_callback( secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data ) SECP256K1_ARG_NONNULL(1); /** Set a callback function to be called when an internal consistency check * fails. The default is crashing. * * This can only trigger in case of a hardware failure, miscompilation, * memory corruption, serious bug in the library, or other error would can * otherwise result in undefined behaviour. It will not trigger due to mere * incorrect usage of the API (see secp256k1_context_set_illegal_callback * for that). After this callback returns, anything may happen, including * crashing. * * Args: ctx: an existing context object (cannot be NULL) * In: fun: a pointer to a function to call when an internal error occurs, * taking a message and an opaque pointer (NULL restores a default * handler that calls abort). * data: the opaque pointer to pass to fun above. */ SECP256K1_API void secp256k1_context_set_error_callback( secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data ) 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: init_size: initial amount of memory to allocate + * 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 init_size, + 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. * * Returns: 1 if the public key was fully valid. * 0 if the public key could not be parsed or is invalid. * Args: ctx: a secp256k1 context object. * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a * parsed version of input. If not, its value is undefined. * In: input: pointer to a serialized public key * inputlen: length of the array pointed to by input * * This function supports parsing compressed (33 bytes, header byte 0x02 or * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header * byte 0x06 or 0x07) format public keys. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Serialize a pubkey object into a serialized byte sequence. * * Returns: 1 always. * Args: ctx: a secp256k1 context object. * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if * compressed==1) byte array to place the serialized key * in. * In/Out: outputlen: a pointer to an integer which is initially set to the * size of output, and is overwritten with the written * size. * In: pubkey: a pointer to a secp256k1_pubkey containing an * initialized public key. * flags: SECP256K1_EC_COMPRESSED if serialization should be in * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. */ SECP256K1_API int secp256k1_ec_pubkey_serialize( const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Parse an ECDSA signature in compact (64 bytes) format. * * Returns: 1 when the signature could be parsed, 0 otherwise. * Args: ctx: a secp256k1 context object * Out: sig: a pointer to a signature object * In: input64: a pointer to the 64-byte array to parse * * The signature must consist of a 32-byte big endian R value, followed by a * 32-byte big endian S value. If R or S fall outside of [0..order-1], the * encoding is invalid. R and S with value 0 are allowed in the encoding. * * After the call, sig will always be initialized. If parsing failed or R or * S are zero, the resulting sig value is guaranteed to fail validation for any * message and public key. */ SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Parse a DER ECDSA signature. * * Returns: 1 when the signature could be parsed, 0 otherwise. * Args: ctx: a secp256k1 context object * Out: sig: a pointer to a signature object * In: input: a pointer to the signature to be parsed * inputlen: the length of the array pointed to be input * * This function will accept any valid DER encoded signature, even if the * encoded numbers are out of range. * * After the call, sig will always be initialized. If parsing failed or the * encoded numbers are out of range, signature validation with it is * guaranteed to fail for every message and public key. */ SECP256K1_API int secp256k1_ecdsa_signature_parse_der( const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Serialize an ECDSA signature in DER format. * * Returns: 1 if enough space was available to serialize, 0 otherwise * Args: ctx: a secp256k1 context object * Out: output: a pointer to an array to store the DER serialization * In/Out: outputlen: a pointer to a length integer. Initially, this integer * should be set to the length of output. After the call * it will be set to the length of the serialization (even * if 0 was returned). * In: sig: a pointer to an initialized signature object */ SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Serialize an ECDSA signature in compact (64 byte) format. * * Returns: 1 * Args: ctx: a secp256k1 context object * Out: output64: a pointer to a 64-byte array to store the compact serialization * In: sig: a pointer to an initialized signature object * * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. */ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Verify an ECDSA signature. * * Returns: 1: correct signature * 0: incorrect or unparseable signature * Args: ctx: a secp256k1 context object, initialized for verification. * In: sig: the signature being verified (cannot be NULL) * msg32: the 32-byte message hash being verified (cannot be NULL) * pubkey: pointer to an initialized public key to verify with (cannot be NULL) * * To avoid accepting malleable signatures, only ECDSA signatures in lower-S * form are accepted. * * If you need to accept ECDSA signatures from sources that do not obey this * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to * validation, but be aware that doing so results in malleable signatures. * * For details, see the comments for that function. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Convert a signature to a normalized lower-S form. * * Returns: 1 if sigin was not normalized, 0 if it already was. * Args: ctx: a secp256k1 context object * Out: sigout: a pointer to a signature to fill with the normalized form, * or copy if the input was already normalized. (can be NULL if * you're only interested in whether the input was already * normalized). * In: sigin: a pointer to a signature to check/normalize (cannot be NULL, * can be identical to sigout) * * With ECDSA a third-party can forge a second distinct signature of the same * message, given a single initial signature, but without knowing the key. This * is done by negating the S value modulo the order of the curve, 'flipping' * the sign of the random point R which is not included in the signature. * * Forgery of the same message isn't universally problematic, but in systems * where message malleability or uniqueness of signatures is important this can * cause issues. This forgery can be blocked by all verifiers forcing signers * to use a normalized form. * * The lower-S form reduces the size of signatures slightly on average when * variable length encodings (such as DER) are used and is cheap to verify, * making it a good choice. Security of always using lower-S is assured because * anyone can trivially modify a signature after the fact to enforce this * property anyway. * * The lower S value is always between 0x1 and * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, * inclusive. * * No other forms of ECDSA malleability are known and none seem likely, but * there is no formal proof that ECDSA, even with this additional restriction, * is free of other malleability. Commonly used serialization schemes will also * accept various non-unique encodings, so care should be taken when this * property is required for an application. * * The secp256k1_ecdsa_sign function will by default create signatures in the * lower-S form, and secp256k1_ecdsa_verify will not accept others. In case * signatures come from a system that cannot enforce this property, * secp256k1_ecdsa_signature_normalize must be called before verification. */ SECP256K1_API int secp256k1_ecdsa_signature_normalize( const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); /** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of * extra entropy. */ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; /** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; /** Create an ECDSA signature. * * Returns: 1: signature created * 0: the nonce generation function failed, or the private key was invalid. * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) * In: msg32: the 32-byte message hash being signed (cannot be NULL) * seckey: pointer to a 32-byte secret key (cannot be NULL) * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) * * The created signature is always in lower-S form. See * secp256k1_ecdsa_signature_normalize for more details. */ SECP256K1_API int secp256k1_ecdsa_sign( const secp256k1_context* ctx, secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Verify an ECDSA secret key. * * Returns: 1: secret key is valid * 0: secret key is invalid * Args: ctx: pointer to a context object (cannot be NULL) * In: seckey: pointer to a 32-byte secret key (cannot be NULL) */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( const secp256k1_context* ctx, const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); /** Compute the public key for a secret key. * * Returns: 1: secret was valid, public key stores * 0: secret was invalid, try again * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) * Out: pubkey: pointer to the created public key (cannot be NULL) * In: seckey: pointer to a 32-byte private key (cannot be NULL) */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey ) 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. * 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 * would be invalid (only when the tweak is the complement of the * private key). 1 otherwise. * Args: ctx: pointer to a context object (cannot be NULL). * In/Out: seckey: pointer to a 32-byte private key. * In: tweak: pointer to a 32-byte tweak. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Tweak a public key by adding tweak times the generator to it. * 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 public key * would be invalid (only when the tweak is the complement of the * corresponding private key). 1 otherwise. * Args: ctx: pointer to a context object initialized for validation * (cannot be NULL). * In/Out: pubkey: pointer to a public key object. * In: tweak: pointer to a 32-byte tweak. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Tweak a private key by multiplying it by a tweak. * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. * Args: ctx: pointer to a context object (cannot be NULL). * In/Out: seckey: pointer to a 32-byte private key. * In: tweak: pointer to a 32-byte tweak. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Tweak a public key by multiplying it by a tweak value. * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. * Args: ctx: pointer to a context object initialized for validation * (cannot be NULL). * In/Out: pubkey: pointer to a public key obkect. * In: tweak: pointer to a 32-byte tweak. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Updates the context randomization to protect against side-channel leakage. * Returns: 1: randomization successfully updated * 0: error * Args: ctx: pointer to a context object (cannot be NULL) * 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_context* ctx, const unsigned char *seed32 ) SECP256K1_ARG_NONNULL(1); /** Add a number of public keys together. * Returns: 1: the sum of the public keys is valid. * 0: the sum of the public keys is not valid. * Args: ctx: pointer to a context object * Out: out: pointer to a public key object for placing the resulting public key * (cannot be NULL) * In: ins: pointer to array of pointers to public keys (cannot be NULL) * n: the number of public keys to add together (must be at least 1) */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( const secp256k1_context* ctx, secp256k1_pubkey *out, const secp256k1_pubkey * const * ins, size_t n ) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); #ifdef __cplusplus } #endif #endif /* SECP256K1_H */ diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h index d5ebe01301..5b59783f68 100644 --- a/src/secp256k1/src/bench.h +++ b/src/secp256k1/src/bench.h @@ -1,66 +1,82 @@ /********************************************************************** * 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.* **********************************************************************/ #ifndef SECP256K1_BENCH_H #define SECP256K1_BENCH_H #include +#include #include #include "sys/time.h" static double gettimedouble(void) { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_usec * 0.000001 + tv.tv_sec; } void print_number(double x) { double y = x; int c = 0; if (y < 0.0) { y = -y; } while (y > 0 && y < 100.0) { y *= 10.0; c++; } printf("%.*f", c, x); } void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) { int i; double min = HUGE_VAL; double sum = 0.0; double max = 0.0; for (i = 0; i < count; i++) { double begin, total; if (setup != NULL) { setup(data); } begin = gettimedouble(); benchmark(data); total = gettimedouble() - begin; if (teardown != NULL) { teardown(data); } if (total < min) { min = total; } if (total > max) { max = total; } sum += total; } printf("%s: min ", name); print_number(min * 1000000.0 / iter); printf("us / avg "); print_number((sum / count) * 1000000.0 / iter); printf("us / max "); print_number(max * 1000000.0 / iter); printf("us\n"); } +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 */ diff --git a/src/secp256k1/src/bench_ecmult.c b/src/secp256k1/src/bench_ecmult.c new file mode 100644 index 0000000000..3a7bfe379c --- /dev/null +++ b/src/secp256k1/src/bench_ecmult.c @@ -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 + +#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, 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); +} diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c index 9b30c50d0b..996aa8b0f1 100644 --- a/src/secp256k1/src/bench_internal.c +++ b/src/secp256k1/src/bench_internal.c @@ -1,382 +1,367 @@ /********************************************************************** * Copyright (c) 2014-2015 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #include #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_const_impl.h" #include "ecmult_impl.h" #include "bench.h" #include "secp256k1.c" typedef struct { secp256k1_scalar scalar_x, scalar_y; secp256k1_fe fe_x, fe_y; secp256k1_ge ge_x, ge_y; secp256k1_gej gej_x, gej_y; unsigned char data[64]; int wnaf[256]; } bench_inv; void bench_setup(void* arg) { bench_inv *data = (bench_inv*)arg; static const unsigned char init_x[32] = { 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83 }; static const unsigned char init_y[32] = { 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83, 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5, 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9, 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3 }; secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL); secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL); secp256k1_fe_set_b32(&data->fe_x, init_x); secp256k1_fe_set_b32(&data->fe_y, init_y); CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0)); CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1)); secp256k1_gej_set_ge(&data->gej_x, &data->ge_x); secp256k1_gej_set_ge(&data->gej_y, &data->ge_y); memcpy(data->data, init_x, 32); memcpy(data->data + 32, init_y, 32); } void bench_scalar_add(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_scalar_negate(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); } } void bench_scalar_sqr(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); } } void bench_scalar_mul(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } #ifdef USE_ENDOMORPHISM void bench_scalar_split(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_scalar l, r; secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } #endif void bench_scalar_inverse(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000; i++) { secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_scalar_inverse_var(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000; i++) { secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_field_normalize(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { secp256k1_fe_normalize(&data->fe_x); } } void bench_field_normalize_weak(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { secp256k1_fe_normalize_weak(&data->fe_x); } } void bench_field_mul(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); } } void bench_field_sqr(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_fe_sqr(&data->fe_x, &data->fe_x); } } void bench_field_inverse(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_inv(&data->fe_x, &data->fe_x); secp256k1_fe_add(&data->fe_x, &data->fe_y); } } void bench_field_inverse_var(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); secp256k1_fe_add(&data->fe_x, &data->fe_y); } } void bench_field_sqrt(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); secp256k1_fe_add(&data->fe_x, &data->fe_y); } } void bench_group_double_var(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); } } void bench_group_add_var(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); } } void bench_group_add_affine(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); } } void bench_group_add_affine_var(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); } } void bench_group_jacobi_var(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_gej_has_quad_y_var(&data->gej_x); } } void bench_ecmult_wnaf(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_wnaf_const(void* arg) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_sha256(void* arg) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_sha256 sha; for (i = 0; i < 20000; i++) { secp256k1_sha256_initialize(&sha); secp256k1_sha256_write(&sha, data->data, 32); secp256k1_sha256_finalize(&sha, data->data); } } void bench_hmac_sha256(void* arg) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_hmac_sha256 hmac; for (i = 0; i < 20000; i++) { secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); secp256k1_hmac_sha256_write(&hmac, data->data, 32); secp256k1_hmac_sha256_finalize(&hmac, data->data); } } void bench_rfc6979_hmac_sha256(void* arg) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_rfc6979_hmac_sha256 rng; for (i = 0; i < 20000; i++) { secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); } } void bench_context_verify(void* arg) { int i; (void)arg; for (i = 0; i < 20; i++) { secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY)); } } void bench_context_sign(void* arg) { int i; (void)arg; for (i = 0; i < 200; i++) { secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN)); } } #ifndef USE_NUM_NONE void bench_num_jacobi(void* arg) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_num nx, norder; secp256k1_scalar_get_num(&nx, &data->scalar_x); secp256k1_scalar_order_get_num(&norder); secp256k1_scalar_get_num(&norder, &data->scalar_y); for (i = 0; i < 200000; i++) { secp256k1_num_jacobi(&nx, &norder); } } #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) { 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, "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, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, 200000); #ifdef USE_ENDOMORPHISM if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, 20000); #endif if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 20); if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 200); #ifndef USE_NUM_NONE if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, 200000); #endif return 0; } diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h index 6d44aba60b..ea1cd8a21f 100644 --- a/src/secp256k1/src/ecmult.h +++ b/src/secp256k1/src/ecmult.h @@ -1,31 +1,47 @@ /********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * + * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #ifndef SECP256K1_ECMULT_H #define SECP256K1_ECMULT_H #include "num.h" #include "group.h" +#include "scalar.h" +#include "scratch.h" typedef struct { /* For accelerating the computation of a*P + b*G: */ secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ #ifdef USE_ENDOMORPHISM secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ #endif } secp256k1_ecmult_context; static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb); static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src, const secp256k1_callback *cb); static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx); static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx); /** 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); +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 */ diff --git a/src/secp256k1/src/ecmult_const_impl.h b/src/secp256k1/src/ecmult_const_impl.h index 7d7a172b7b..fae50020b7 100644 --- a/src/secp256k1/src/ecmult_const_impl.h +++ b/src/secp256k1/src/ecmult_const_impl.h @@ -1,240 +1,233 @@ /********************************************************************** * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #ifndef SECP256K1_ECMULT_CONST_IMPL_H #define SECP256K1_ECMULT_CONST_IMPL_H #include "scalar.h" #include "group.h" #include "ecmult_const.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 */ #define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ int m; \ int abs_n = (n) * (((n) > 0) * 2 - 1); \ int idx_n = abs_n / 2; \ secp256k1_fe neg_y; \ VERIFY_CHECK(((n) & 1) == 1); \ VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \ VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \ for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \ /* This loop is used to avoid secret data in array indices. See * the comment in ecmult_gen_impl.h for rationale. */ \ secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \ secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \ } \ (r)->infinity = 0; \ secp256k1_fe_negate(&neg_y, &(r)->y, 1); \ secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \ } while(0) /** 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] an odd integer between -(1 << w) and (1 << w) * - each wnaf[i] is nonzero * - 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 * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) * CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003 * * 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) { int global_sign; int skew = 0; int word = 0; /* 1 2 3 */ int u_last; int u; int flip; int bit; secp256k1_scalar neg_s; int not_neg_one; /* Note that we cannot handle even numbers by negating them to be odd, as is * done in other implementations, since if our scalars were specified to have * width < 256 for performance reasons, their negations would have width 256 * 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) * 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. */ /* Negative numbers will be negated to keep their bit representation below the maximum width */ flip = secp256k1_scalar_is_high(&s); /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ bit = flip ^ !secp256k1_scalar_is_even(&s); /* We check for negative one, since adding 2 to it will cause an overflow */ secp256k1_scalar_negate(&neg_s, &s); not_neg_one = !secp256k1_scalar_is_one(&neg_s); secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects * that we added two to it and flipped it. In fact for -1 these operations are * identical. We only flipped, but since skewing is required (in the sense that * the skew must be 1 or 2, never zero) and flipping is not, we need to change * our flags to claim that we only skewed. */ global_sign = secp256k1_scalar_cond_negate(&s, flip); global_sign *= not_neg_one * 2 - 1; skew = 1 << bit; /* 4 */ u_last = secp256k1_scalar_shr_int(&s, w); while (word * w < WNAF_BITS) { int sign; int even; /* 4.1 4.4 */ u = secp256k1_scalar_shr_int(&s, w); /* 4.2 */ even = ((u & 1) == 0); sign = 2 * (u_last > 0) - 1; u += sign * even; u_last -= sign * even * (1 << w); /* 4.3, adapted for global sign change */ wnaf[word++] = u_last * global_sign; u_last = u; } wnaf[word] = u * global_sign; VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); VERIFY_CHECK(word == WNAF_SIZE(w)); return skew; } 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 tmpa; secp256k1_fe Z; int skew_1; int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; #ifdef USE_ENDOMORPHISM secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; int skew_lam; secp256k1_scalar q_1, q_lam; #endif int i; secp256k1_scalar sc = *scalar; /* build wnaf representation for q. */ #ifdef USE_ENDOMORPHISM /* 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); skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); #else skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1); #endif /* Calculate odd multiples of a. * All multiples are brought to the same Z 'denominator', which is stored * in Z. Due to secp256k1' isomorphism we can do all operations pretending * that the Z coordinate was 1, use affine addition formulae, and correct * the Z coordinate of the result once at the end. */ secp256k1_gej_set_ge(r, a); secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r); for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { secp256k1_fe_normalize_weak(&pre_a[i].y); } #ifdef USE_ENDOMORPHISM for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); } #endif /* first loop iteration (separated out so we can directly set r, rather * than having it start at infinity, get doubled several times, then have * its new value added to it) */ i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; VERIFY_CHECK(i != 0); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); secp256k1_gej_set_ge(r, &tmpa); #ifdef USE_ENDOMORPHISM i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; VERIFY_CHECK(i != 0); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); secp256k1_gej_add_ge(r, r, &tmpa); #endif /* remaining loop iterations */ for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { int n; int j; for (j = 0; j < WINDOW_A - 1; ++j) { secp256k1_gej_double_nonzero(r, r, NULL); } n = wnaf_1[i]; ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); VERIFY_CHECK(n != 0); secp256k1_gej_add_ge(r, r, &tmpa); #ifdef USE_ENDOMORPHISM n = wnaf_lam[i]; ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); VERIFY_CHECK(n != 0); secp256k1_gej_add_ge(r, r, &tmpa); #endif } secp256k1_fe_mul(&r->z, &r->z, &Z); { /* Correct for wNAF skew */ secp256k1_ge correction = *a; secp256k1_ge_storage correction_1_stor; #ifdef USE_ENDOMORPHISM secp256k1_ge_storage correction_lam_stor; #endif secp256k1_ge_storage a2_stor; secp256k1_gej tmpj; secp256k1_gej_set_ge(&tmpj, &correction); secp256k1_gej_double_var(&tmpj, &tmpj, NULL); secp256k1_ge_set_gej(&correction, &tmpj); secp256k1_ge_to_storage(&correction_1_stor, a); #ifdef USE_ENDOMORPHISM secp256k1_ge_to_storage(&correction_lam_stor, a); #endif secp256k1_ge_to_storage(&a2_stor, &correction); /* 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); #ifdef USE_ENDOMORPHISM secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); #endif /* Apply the correction */ secp256k1_ge_from_storage(&correction, &correction_1_stor); secp256k1_ge_neg(&correction, &correction); secp256k1_gej_add_ge(r, r, &correction); #ifdef USE_ENDOMORPHISM secp256k1_ge_from_storage(&correction, &correction_lam_stor); secp256k1_ge_neg(&correction, &correction); secp256k1_ge_mul_lambda(&correction, &correction); secp256k1_gej_add_ge(r, r, &correction); #endif } } #endif /* SECP256K1_ECMULT_CONST_IMPL_H */ diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h index 93d3794cb4..a9eb77d8b8 100644 --- a/src/secp256k1/src/ecmult_impl.h +++ b/src/secp256k1/src/ecmult_impl.h @@ -1,406 +1,1011 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/***************************************************************************** + * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php. * + *****************************************************************************/ #ifndef SECP256K1_ECMULT_IMPL_H #define SECP256K1_ECMULT_IMPL_H #include +#include #include "group.h" #include "scalar.h" #include "ecmult.h" #if defined(EXHAUSTIVE_TEST_ORDER) /* We need to lower these values for exhaustive tests because * the tables cannot have infinities in them (this breaks the * affine-isomorphism stuff which tracks z-ratios) */ # if EXHAUSTIVE_TEST_ORDER > 128 # define WINDOW_A 5 # define WINDOW_G 8 # elif EXHAUSTIVE_TEST_ORDER > 8 # define WINDOW_A 4 # define WINDOW_G 4 # else # define WINDOW_A 2 # define WINDOW_G 2 # endif #else /* optimal for 128-bit and 256-bit exponents. */ #define WINDOW_A 5 /** larger numbers may result in slightly better performance, at the cost of exponentially larger precomputed tables. */ #ifdef USE_ENDOMORPHISM /** Two tables for window size 15: 1.375 MiB. */ #define WINDOW_G 15 #else /** One table for window size 16: 1.375 MiB. */ #define WINDOW_G 16 #endif #endif +#ifdef USE_ENDOMORPHISM + #define WNAF_BITS 128 +#else + #define WNAF_BITS 256 +#endif +#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) + /** The number of entries a table with precomputed multiples needs to have. */ #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 * 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. * Prej's Z values are undefined, except for the last value. */ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { secp256k1_gej d; secp256k1_ge a_ge, d_ge; int i; VERIFY_CHECK(!a->infinity); secp256k1_gej_double_var(&d, a, NULL); /* * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate * of 'd', and scale the 1P starting value's x/y coordinates without changing its z. */ d_ge.x = d.x; d_ge.y = d.y; d_ge.infinity = 0; secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); prej[0].x = a_ge.x; prej[0].y = a_ge.y; prej[0].z = a->z; prej[0].infinity = 0; zr[0] = d.z; for (i = 1; i < n; i++) { secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]); } /* * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only * the final point's z coordinate is actually used though, so just update that. */ secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z); } /** Fill a table 'pre' with precomputed odd multiples of a. * * There are two versions of this function: * - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its * resulting point set to a single constant Z denominator, stores the X and Y * coordinates as ge_storage points in pre, and stores the global Z in rz. * It only operates on tables sized for WINDOW_A wnaf multiples. * - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its * resulting point set to actually affine points, and stores those in pre. * It operates on tables of any size, but uses heap-allocated temporaries. * * To compute a*P + b*G, we compute a table for P using the first function, * and for G using the second (which requires an inverse, but it only needs to * happen once). */ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; /* Compute the odd multiples in Jacobian form. */ secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); /* Bring them to the same Z denominator. */ secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); } static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage *pre, const secp256k1_gej *a, const secp256k1_callback *cb) { secp256k1_gej *prej = (secp256k1_gej*)checked_malloc(cb, sizeof(secp256k1_gej) * n); secp256k1_ge *prea = (secp256k1_ge*)checked_malloc(cb, sizeof(secp256k1_ge) * n); secp256k1_fe *zr = (secp256k1_fe*)checked_malloc(cb, sizeof(secp256k1_fe) * n); int i; /* Compute the odd multiples in Jacobian form. */ secp256k1_ecmult_odd_multiples_table(n, prej, zr, a); /* Convert them in batch to affine coordinates. */ secp256k1_ge_set_table_gej_var(prea, prej, zr, n); /* Convert them to compact storage form. */ for (i = 0; i < n; i++) { secp256k1_ge_to_storage(&pre[i], &prea[i]); } free(prea); free(prej); free(zr); } /** The following two macro retrieves a particular odd multiple from a table * of precomputed multiples. */ #define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \ VERIFY_CHECK(((n) & 1) == 1); \ VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ if ((n) > 0) { \ *(r) = (pre)[((n)-1)/2]; \ } else { \ secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \ } \ } while(0) #define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \ VERIFY_CHECK(((n) & 1) == 1); \ VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ if ((n) > 0) { \ secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \ } else { \ secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \ secp256k1_ge_neg((r), (r)); \ } \ } while(0) static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { ctx->pre_g = NULL; #ifdef USE_ENDOMORPHISM ctx->pre_g_128 = NULL; #endif } static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) { secp256k1_gej gj; if (ctx->pre_g != NULL) { return; } /* get the generator */ secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); /* precompute the tables with odd multiples */ secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb); #ifdef USE_ENDOMORPHISM { secp256k1_gej g_128j; int i; ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); /* calculate 2^128*generator */ g_128j = gj; for (i = 0; i < 128; i++) { secp256k1_gej_double_var(&g_128j, &g_128j, NULL); } secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb); } #endif } static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src, const secp256k1_callback *cb) { if (src->pre_g == NULL) { dst->pre_g = NULL; } else { size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); memcpy(dst->pre_g, src->pre_g, size); } #ifdef USE_ENDOMORPHISM if (src->pre_g_128 == NULL) { dst->pre_g_128 = NULL; } else { size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); memcpy(dst->pre_g_128, src->pre_g_128, size); } #endif } static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) { return ctx->pre_g != NULL; } static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) { free(ctx->pre_g); #ifdef USE_ENDOMORPHISM free(ctx->pre_g_128); #endif secp256k1_ecmult_context_init(ctx); } /** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), * with the following guarantees: * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) * - two non-zero entries in wnaf are separated by at least w-1 zeroes. * - the number of set values in wnaf is returned. This number is at most 256, and at most one more * than the number of bits in the (absolute value) of the input. */ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) { secp256k1_scalar s = *a; int last_set_bit = -1; int bit = 0; int sign = 1; int carry = 0; VERIFY_CHECK(wnaf != NULL); VERIFY_CHECK(0 <= len && len <= 256); VERIFY_CHECK(a != NULL); VERIFY_CHECK(2 <= w && w <= 31); memset(wnaf, 0, len * sizeof(wnaf[0])); if (secp256k1_scalar_get_bits(&s, 255, 1)) { secp256k1_scalar_negate(&s, &s); sign = -1; } while (bit < len) { int now; int word; if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { bit++; continue; } now = w; if (now > len - bit) { now = len - bit; } word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; carry = (word >> (w-1)) & 1; word -= carry << w; wnaf[bit] = sign * word; last_set_bit = bit; bit += now; } #ifdef VERIFY CHECK(carry == 0); while (bit < 256) { CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0); } #endif 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) { - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge tmpa; - secp256k1_fe Z; +struct secp256k1_strauss_point_state { #ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_scalar na_1, na_lam; - /* Splitted G factors. */ - secp256k1_scalar ng_1, ng_128; int wnaf_na_1[130]; int wnaf_na_lam[130]; int bits_na_1; int bits_na_lam; - int wnaf_ng_1[129]; - int bits_ng_1; - int wnaf_ng_128[129]; - int bits_ng_128; #else int wnaf_na[256]; 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 bits_ng; + int bits_ng = 0; #endif 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 - /* 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); - - /* build wnaf representation for na_1 and na_lam. */ - bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); - bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); - VERIFY_CHECK(bits_na_1 <= 130); - VERIFY_CHECK(bits_na_lam <= 130); - bits = bits_na_1; - if (bits_na_lam > bits) { - bits = bits_na_lam; - } + /* 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(&state->ps[no].na_1, &state->ps[no].na_lam, &na[np]); + + /* build wnaf representation for na_1 and na_lam. */ + state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 130, &state->ps[no].na_1, 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(state->ps[no].bits_na_1 <= 130); + VERIFY_CHECK(state->ps[no].bits_na_lam <= 130); + if (state->ps[no].bits_na_1 > bits) { + bits = state->ps[no].bits_na_1; + } + if (state->ps[no].bits_na_lam > bits) { + bits = state->ps[no].bits_na_lam; + } #else - /* build wnaf representation for na. */ - bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); - bits = bits_na; + /* build wnaf representation for na. */ + state->ps[no].bits_na = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na, 256, &na[np], WINDOW_A); + if (state->ps[no].bits_na > bits) { + bits = state->ps[no].bits_na; + } #endif + ++no; + } /* Calculate odd multiples of a. * All multiples are brought to the same Z 'denominator', which is stored * in Z. Due to secp256k1' isomorphism we can do all operations pretending * that the Z coordinate was 1, use affine addition formulae, and correct * the Z coordinate of the result once at the end. * The exception is the precomputed G table points, which are actually * affine. Compared to the base used for other points, they have a Z ratio * 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. */ - secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); + if (no > 0) { + /* Compute the odd multiples in Jacobian form. */ + secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->prej, state->zr, &a[state->ps[0].input_pos]); + for (np = 1; np < no; ++np) { + 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 (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + 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]); + } } - /* 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); + 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) */ + secp256k1_scalar_split_128(&ng_1, &ng_128, ng); - /* Build wnaf representation for ng_1 and ng_128 */ - bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); - bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); - if (bits_ng_1 > bits) { - bits = bits_ng_1; - } - if (bits_ng_128 > bits) { - bits = bits_ng_128; + /* Build wnaf representation for ng_1 and ng_128 */ + bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); + bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); + if (bits_ng_1 > bits) { + bits = bits_ng_1; + } + if (bits_ng_128 > bits) { + bits = bits_ng_128; + } } #else - bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); - if (bits_ng > bits) { - bits = bits_ng; + if (ng) { + bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); + if (bits_ng > bits) { + bits = bits_ng; + } } #endif secp256k1_gej_set_infinity(r); for (i = bits - 1; i >= 0; i--) { int n; secp256k1_gej_double_var(r, r, NULL); #ifdef USE_ENDOMORPHISM - if (i < bits_na_1 && (n = wnaf_na_1[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_na_lam && (n = wnaf_na_lam[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + for (np = 0; np < no; ++np) { + 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); + } + if (i < state->ps[np].bits_na_lam && (n = state->ps[np].wnaf_na_lam[i])) { + 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); + } } if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); } if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); } #else - if (i < bits_na && (n = wnaf_na[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + for (np = 0; np < no; ++np) { + 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); + } } if (i < bits_ng && (n = wnaf_ng[i])) { ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); } #endif } if (!r->infinity) { secp256k1_fe_mul(&r->z, &r->z, &Z); } } +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 + 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_resize(scratch, secp256k1_strauss_scratch_size(n_points), STRAUSS_SCRATCH_OBJECTS)) { + return 0; + } + secp256k1_scratch_reset(scratch); + 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)) return 0; + secp256k1_gej_set_ge(&points[i], &point); + } + secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc); + 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 without endomorphism, or 0 or 1 with endomorphism + */ +static int secp256k1_wnaf_fixed(int *wnaf, const secp256k1_scalar *s, int w) { + int sign = 0; + int skew = 0; + int pos = 1; +#ifndef USE_ENDOMORPHISM + secp256k1_scalar neg_s; +#endif + const secp256k1_scalar *work = s; + + if (secp256k1_scalar_is_zero(s)) { + while (pos * w < WNAF_BITS) { + wnaf[pos] = 0; + ++pos; + } + return 0; + } + + if (secp256k1_scalar_is_even(s)) { +#ifdef USE_ENDOMORPHISM + skew = 1; +#else + secp256k1_scalar_negate(&neg_s, s); + work = &neg_s; + sign = -1; +#endif + } + + wnaf[0] = (secp256k1_scalar_get_bits_var(work, 0, w) + skew + sign) ^ sign; + + while (pos * w < WNAF_BITS) { + int now = w; + int val; + if (now + pos * w > WNAF_BITS) { + now = WNAF_BITS - pos * w; + } + val = secp256k1_scalar_get_bits_var(work, pos * w, now); + if ((val & 1) == 0) { + wnaf[pos - 1] -= ((1 << w) + sign) ^ sign; + wnaf[pos] = (val + 1 + sign) ^ sign; + } else { + wnaf[pos] = (val + sign) ^ sign; + } + ++pos; + } + VERIFY_CHECK(pos == WNAF_SIZE(w)); + + 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; + +#ifdef USE_ENDOMORPHISM + 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); + } + } +#endif + 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<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<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< 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 */ diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h index ea1302deb8..3947ea2dda 100644 --- a/src/secp256k1/src/group.h +++ b/src/secp256k1/src/group.h @@ -1,144 +1,147 @@ /********************************************************************** * Copyright (c) 2013, 2014 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #ifndef SECP256K1_GROUP_H #define SECP256K1_GROUP_H #include "num.h" #include "field.h" /** A group element of the secp256k1 curve, in affine coordinates. */ typedef struct { secp256k1_fe x; secp256k1_fe y; int infinity; /* whether this represents the point at infinity */ } secp256k1_ge; #define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} #define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} /** A group element of the secp256k1 curve, in jacobian coordinates. */ typedef struct { secp256k1_fe x; /* actual X: x/z^2 */ secp256k1_fe y; /* actual Y: y/z^3 */ secp256k1_fe z; int infinity; /* whether this represents the point at infinity */ } secp256k1_gej; #define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} #define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} typedef struct { secp256k1_fe_storage x; secp256k1_fe_storage y; } secp256k1_ge_storage; #define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} #define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) /** Set a group element equal to the point with given X and Y coordinates */ static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y); /** Set a group element (affine) equal to the point with the given X coordinate * and a Y coordinate that is a quadratic residue modulo p. The return value * is true iff a coordinate with the given X coordinate exists. */ static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x); /** Set a group element (affine) equal to the point with the given X coordinate, and given oddness * for Y. Return value indicates whether the result is valid. */ static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd); /** Check whether a group element is the point at infinity. */ static int secp256k1_ge_is_infinity(const secp256k1_ge *a); /** Check whether a group element is valid (i.e., on the curve). */ static int secp256k1_ge_is_valid_var(const secp256k1_ge *a); static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); /** Set a group element equal to another which is given in jacobian coordinates */ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); /** Set a batch of group elements equal to the inputs given in jacobian coordinates */ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb); /** Set a batch of group elements equal to the inputs given in jacobian * coordinates (with known z-ratios). zr must contain the known z-ratios such * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */ static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len); /** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to * the same global z "denominator". zr must contain the known z-ratios such * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y * coordinates of the result are stored in r, the common z coordinate is * 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); +/** 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. */ static void secp256k1_gej_set_infinity(secp256k1_gej *r); /** Set a group element (jacobian) equal to another which is given in affine coordinates. */ static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); /** Compare the X coordinate of a group element (jacobian). */ static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a); /** Check whether a group element is the point at infinity. */ static int secp256k1_gej_is_infinity(const secp256k1_gej *a); /** Check whether a group element's y coordinate is a quadratic residue. */ static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a); /** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). * a may not be zero. Constant time. */ static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); /** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); /** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr); /** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b); /** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr); /** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv); #ifdef USE_ENDOMORPHISM /** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); #endif /** Clear a secp256k1_gej to prevent leaking sensitive information. */ static void secp256k1_gej_clear(secp256k1_gej *r); /** Clear a secp256k1_ge to prevent leaking sensitive information. */ static void secp256k1_ge_clear(secp256k1_ge *r); /** Convert a group element to the storage type. */ static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a); /** Convert a group element back from the storage type. */ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); /** 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); #endif /* SECP256K1_GROUP_H */ diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h index b31b6c12ef..b1ace87b6f 100644 --- a/src/secp256k1/src/group_impl.h +++ b/src/secp256k1/src/group_impl.h @@ -1,700 +1,706 @@ /********************************************************************** * Copyright (c) 2013, 2014 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #ifndef SECP256K1_GROUP_IMPL_H #define SECP256K1_GROUP_IMPL_H #include "num.h" #include "field.h" #include "group.h" /* These points can be generated in sage as follows: * * 0. Setup a worksheet with the following parameters. * b = 4 # whatever CURVE_B will be set to * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) * C = EllipticCurve ([F (0), F (b)]) * * 1. Determine all the small orders available to you. (If there are * no satisfactory ones, go back and change b.) * print C.order().factor(limit=1000) * * 2. Choose an order as one of the prime factors listed in the above step. * (You can also multiply some to get a composite order, though the * tests will crash trying to invert scalars during signing.) We take a * random point and scale it to drop its order to the desired value. * There is some probability this won't work; just try again. * order = 199 * P = C.random_point() * P = (int(P.order()) / int(order)) * P * assert(P.order() == order) * * 3. Print the values. You'll need to use a vim macro or something to * split the hex output into 4-byte chunks. * print "%x %x" % P.xy() */ #if defined(EXHAUSTIVE_TEST_ORDER) # if EXHAUSTIVE_TEST_ORDER == 199 const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( 0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069, 0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18, 0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868, 0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED ); const int CURVE_B = 4; # elif EXHAUSTIVE_TEST_ORDER == 13 const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( 0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0, 0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15, 0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e, 0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac ); const int CURVE_B = 2; # else # error No known generator for the specified exhaustive test group order. # endif #else /** Generator for secp256k1, value 'g' defined in * "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( 0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL, 0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL, 0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL, 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL ); const int CURVE_B = 7; #endif static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { secp256k1_fe zi2; secp256k1_fe zi3; secp256k1_fe_sqr(&zi2, zi); secp256k1_fe_mul(&zi3, &zi2, zi); secp256k1_fe_mul(&r->x, &a->x, &zi2); secp256k1_fe_mul(&r->y, &a->y, &zi3); r->infinity = a->infinity; } static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { r->infinity = 0; r->x = *x; r->y = *y; } static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { return a->infinity; } static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { *r = *a; secp256k1_fe_normalize_weak(&r->y); secp256k1_fe_negate(&r->y, &r->y, 1); } static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; r->infinity = a->infinity; secp256k1_fe_inv(&a->z, &a->z); secp256k1_fe_sqr(&z2, &a->z); secp256k1_fe_mul(&z3, &a->z, &z2); secp256k1_fe_mul(&a->x, &a->x, &z2); secp256k1_fe_mul(&a->y, &a->y, &z3); secp256k1_fe_set_int(&a->z, 1); r->x = a->x; r->y = a->y; } static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { secp256k1_fe z2, z3; r->infinity = a->infinity; if (a->infinity) { return; } secp256k1_fe_inv_var(&a->z, &a->z); secp256k1_fe_sqr(&z2, &a->z); secp256k1_fe_mul(&z3, &a->z, &z2); secp256k1_fe_mul(&a->x, &a->x, &z2); secp256k1_fe_mul(&a->y, &a->y, &z3); secp256k1_fe_set_int(&a->z, 1); r->x = a->x; r->y = a->y; } static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb) { secp256k1_fe *az; secp256k1_fe *azi; size_t i; size_t count = 0; az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len); for (i = 0; i < len; i++) { if (!a[i].infinity) { az[count++] = a[i].z; } } azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count); secp256k1_fe_inv_all_var(azi, az, count); free(az); count = 0; for (i = 0; i < len; i++) { r[i].infinity = a[i].infinity; if (!a[i].infinity) { secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]); } } free(azi); } static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len) { size_t i = len - 1; secp256k1_fe zi; if (len > 0) { /* Compute the inverse of the last z coordinate, and use it to compute the last affine output. */ secp256k1_fe_inv(&zi, &a[i].z); secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); /* Work out way backwards, using the z-ratios to scale the x/y values. */ while (i > 0) { secp256k1_fe_mul(&zi, &zi, &zr[i]); i--; secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); } } } 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) { size_t i = len - 1; secp256k1_fe zs; if (len > 0) { /* The z of the final point gives us the "global Z" for the table. */ r[i].x = a[i].x; r[i].y = a[i].y; *globalz = a[i].z; r[i].infinity = 0; zs = zr[i]; /* Work our way backwards, using the z-ratios to scale the x/y values. */ while (i > 0) { if (i != len - 1) { secp256k1_fe_mul(&zs, &zs, &zr[i]); } i--; secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs); } } } static void secp256k1_gej_set_infinity(secp256k1_gej *r) { r->infinity = 1; secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); 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) { r->infinity = 0; secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); secp256k1_fe_clear(&r->z); } static void secp256k1_ge_clear(secp256k1_ge *r) { r->infinity = 0; secp256k1_fe_clear(&r->x); secp256k1_fe_clear(&r->y); } static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { secp256k1_fe x2, x3, c; r->x = *x; secp256k1_fe_sqr(&x2, x); secp256k1_fe_mul(&x3, x, &x2); r->infinity = 0; secp256k1_fe_set_int(&c, CURVE_B); secp256k1_fe_add(&c, &x3); return secp256k1_fe_sqrt(&r->y, &c); } static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { if (!secp256k1_ge_set_xquad(r, x)) { return 0; } secp256k1_fe_normalize_var(&r->y); if (secp256k1_fe_is_odd(&r->y) != odd) { secp256k1_fe_negate(&r->y, &r->y, 1); } return 1; } static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { r->infinity = a->infinity; r->x = a->x; r->y = a->y; secp256k1_fe_set_int(&r->z, 1); } static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { secp256k1_fe r, r2; VERIFY_CHECK(!a->infinity); secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); r2 = a->x; secp256k1_fe_normalize_weak(&r2); return secp256k1_fe_equal_var(&r, &r2); } static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { r->infinity = a->infinity; r->x = a->x; r->y = a->y; r->z = a->z; secp256k1_fe_normalize_weak(&r->y); secp256k1_fe_negate(&r->y, &r->y, 1); } static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { return a->infinity; } static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { secp256k1_fe y2, x3, z2, z6; if (a->infinity) { return 0; } /** y^2 = x^3 + 7 * (Y/Z^3)^2 = (X/Z^2)^3 + 7 * Y^2 / Z^6 = X^3 / Z^6 + 7 * Y^2 = X^3 + 7*Z^6 */ secp256k1_fe_sqr(&y2, &a->y); secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); secp256k1_fe_sqr(&z2, &a->z); secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); secp256k1_fe_mul_int(&z6, CURVE_B); secp256k1_fe_add(&x3, &z6); secp256k1_fe_normalize_weak(&x3); return secp256k1_fe_equal_var(&y2, &x3); } static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { secp256k1_fe y2, x3, c; if (a->infinity) { return 0; } /* y^2 = x^3 + 7 */ secp256k1_fe_sqr(&y2, &a->y); secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); secp256k1_fe_set_int(&c, CURVE_B); secp256k1_fe_add(&x3, &c); secp256k1_fe_normalize_weak(&x3); return secp256k1_fe_equal_var(&y2, &x3); } static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate. * * Note that there is an implementation described at * https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l * which trades a multiply for a square, but in practice this is actually slower, * mainly because it requires more normalizations. */ secp256k1_fe t1,t2,t3,t4; /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. * * Having said this, if this function receives a point on a sextic twist, e.g. by * a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6, * since -6 does have a cube root mod p. For this point, this function will not set * the infinity flag even though the point doubles to infinity, and the result * point will be gibberish (z = 0 but infinity = 0). */ r->infinity = a->infinity; if (r->infinity) { if (rzr != NULL) { secp256k1_fe_set_int(rzr, 1); } return; } if (rzr != NULL) { *rzr = a->y; secp256k1_fe_normalize_weak(rzr); secp256k1_fe_mul_int(rzr, 2); } secp256k1_fe_mul(&r->z, &a->z, &a->y); secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ secp256k1_fe_sqr(&t1, &a->x); secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ secp256k1_fe_sqr(&t3, &a->y); secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ secp256k1_fe_sqr(&t4, &t3); secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ r->x = t3; secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ } static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); secp256k1_gej_double_var(r, a, rzr); } static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; if (a->infinity) { VERIFY_CHECK(rzr == NULL); *r = *b; return; } if (b->infinity) { if (rzr != NULL) { secp256k1_fe_set_int(rzr, 1); } *r = *a; return; } r->infinity = 0; secp256k1_fe_sqr(&z22, &b->z); secp256k1_fe_sqr(&z12, &a->z); secp256k1_fe_mul(&u1, &a->x, &z22); secp256k1_fe_mul(&u2, &b->x, &z12); secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); if (secp256k1_fe_normalizes_to_zero_var(&h)) { if (secp256k1_fe_normalizes_to_zero_var(&i)) { secp256k1_gej_double_var(r, a, rzr); } else { if (rzr != NULL) { secp256k1_fe_set_int(rzr, 0); } r->infinity = 1; } return; } secp256k1_fe_sqr(&i2, &i); secp256k1_fe_sqr(&h2, &h); secp256k1_fe_mul(&h3, &h, &h2); secp256k1_fe_mul(&h, &h, &b->z); if (rzr != NULL) { *rzr = h; } secp256k1_fe_mul(&r->z, &a->z, &h); secp256k1_fe_mul(&t, &u1, &h2); r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); secp256k1_fe_add(&r->y, &h3); } static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { /* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; if (a->infinity) { VERIFY_CHECK(rzr == NULL); secp256k1_gej_set_ge(r, b); return; } if (b->infinity) { if (rzr != NULL) { secp256k1_fe_set_int(rzr, 1); } *r = *a; return; } r->infinity = 0; secp256k1_fe_sqr(&z12, &a->z); u1 = a->x; secp256k1_fe_normalize_weak(&u1); secp256k1_fe_mul(&u2, &b->x, &z12); s1 = a->y; secp256k1_fe_normalize_weak(&s1); secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); if (secp256k1_fe_normalizes_to_zero_var(&h)) { if (secp256k1_fe_normalizes_to_zero_var(&i)) { secp256k1_gej_double_var(r, a, rzr); } else { if (rzr != NULL) { secp256k1_fe_set_int(rzr, 0); } r->infinity = 1; } return; } secp256k1_fe_sqr(&i2, &i); secp256k1_fe_sqr(&h2, &h); secp256k1_fe_mul(&h3, &h, &h2); if (rzr != NULL) { *rzr = h; } secp256k1_fe_mul(&r->z, &a->z, &h); secp256k1_fe_mul(&t, &u1, &h2); r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); secp256k1_fe_add(&r->y, &h3); } static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { /* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; if (b->infinity) { *r = *a; return; } if (a->infinity) { secp256k1_fe bzinv2, bzinv3; r->infinity = b->infinity; secp256k1_fe_sqr(&bzinv2, bzinv); secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv); secp256k1_fe_mul(&r->x, &b->x, &bzinv2); secp256k1_fe_mul(&r->y, &b->y, &bzinv3); secp256k1_fe_set_int(&r->z, 1); return; } r->infinity = 0; /** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to * secp256k1's isomorphism we can multiply the Z coordinates on both sides * by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1). * This means that (rx,ry,rz) can be calculated as * (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz. * The variable az below holds the modified Z coordinate for a, which is used * for the computation of rx and ry, but not for rz. */ secp256k1_fe_mul(&az, &a->z, bzinv); secp256k1_fe_sqr(&z12, &az); u1 = a->x; secp256k1_fe_normalize_weak(&u1); secp256k1_fe_mul(&u2, &b->x, &z12); s1 = a->y; secp256k1_fe_normalize_weak(&s1); secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az); secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); if (secp256k1_fe_normalizes_to_zero_var(&h)) { if (secp256k1_fe_normalizes_to_zero_var(&i)) { secp256k1_gej_double_var(r, a, NULL); } else { r->infinity = 1; } return; } secp256k1_fe_sqr(&i2, &i); secp256k1_fe_sqr(&h2, &h); secp256k1_fe_mul(&h3, &h, &h2); r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); secp256k1_fe_mul(&t, &u1, &h2); r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); secp256k1_fe_add(&r->y, &h3); } static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) { /* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */ static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; secp256k1_fe m_alt, rr_alt; int infinity, degenerate; VERIFY_CHECK(!b->infinity); VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); /** In: * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. * we find as solution for a unified addition/doubling formula: * lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. * x3 = lambda^2 - (x1 + x2) * 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). * * Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: * U1 = X1*Z2^2, U2 = X2*Z1^2 * S1 = Y1*Z2^3, S2 = Y2*Z1^3 * Z = Z1*Z2 * T = U1+U2 * M = S1+S2 * Q = T*M^2 * R = T^2-U1*U2 * X3 = 4*(R^2-Q) * Y3 = 4*(R*(3*Q-2*R^2)-M^4) * Z3 = 2*M*Z * (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) * * This formula has the benefit of being the same for both addition * of distinct points and doubling. However, it breaks down in the * case that either point is infinity, or that y1 = -y2. We handle * these cases in the following ways: * * - If b is infinity we simply bail by means of a VERIFY_CHECK. * * - If a is infinity, we detect this, and at the end of the * computation replace the result (which will be meaningless, * but we compute to be constant-time) with b.x : b.y : 1. * * - If a = -b, we have y1 = -y2, which is a degenerate case. * But here the answer is infinity, so we simply set the * infinity flag of the result, overriding the computed values * without even needing to cmov. * * - If y1 = -y2 but x1 != x2, which does occur thanks to certain * properties of our curve (specifically, 1 has nontrivial cube * roots in our field, and the curve equation has no x coefficient) * then the answer is not infinity but also not given by the above * equation. In this case, we cmov in place an alternate expression * for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these * expressions for lambda are defined, they are equal, and can be * obtained from each other by multiplication by (y1 + y2)/(y1 + y2) * then substitution of x^3 + 7 for y^2 (using the curve equation). * For all pairs of nonzero points (a, b) at least one is defined, * so this covers everything. */ secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ /** If lambda = R/M = 0/0 we have a problem (except in the "trivial" * case that Z = z1z2 = 0, and this is special-cased later on). */ degenerate = secp256k1_fe_normalizes_to_zero(&m) & secp256k1_fe_normalizes_to_zero(&rr); /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. * This means either x1 == beta*x2 or beta*x1 == x2, where beta is * a nontrivial cube root of one. In either case, an alternate * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), * so we set R/M equal to this. */ rr_alt = s1; secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); secp256k1_fe_cmov(&m_alt, &m, !degenerate); /* Now Ralt / Malt = lambda and is guaranteed not to be 0/0. * From here on out Ralt and Malt represent the numerator * and denominator of lambda; R and M represent the explicit * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */ /* These two lines use the observation that either M == Malt or M == 0, * so M^3 * Malt is either Malt^4 (which is computed by squaring), or * zero (which is "computed" by cmov). So the cost is one squaring * versus two multiplications. */ secp256k1_fe_sqr(&n, &n); secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */ infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */ secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */ secp256k1_fe_normalize_weak(&t); r->x = t; /* r->x = Ralt^2-Q (1) */ secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */ secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */ secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */ secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */ secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */ secp256k1_fe_normalize_weak(&r->y); secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */ secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */ /** In case a->infinity == 1, replace r with (b->x, b->y, 1). */ secp256k1_fe_cmov(&r->x, &b->x, a->infinity); secp256k1_fe_cmov(&r->y, &b->y, a->infinity); secp256k1_fe_cmov(&r->z, &fe_1, a->infinity); r->infinity = infinity; } static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { /* Operations: 4 mul, 1 sqr */ secp256k1_fe zz; VERIFY_CHECK(!secp256k1_fe_is_zero(s)); secp256k1_fe_sqr(&zz, s); secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ secp256k1_fe_mul(&r->y, &r->y, &zz); secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ } static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { secp256k1_fe x, y; VERIFY_CHECK(!a->infinity); x = a->x; secp256k1_fe_normalize(&x); y = a->y; secp256k1_fe_normalize(&y); secp256k1_fe_to_storage(&r->x, &x); secp256k1_fe_to_storage(&r->y, &y); } static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) { secp256k1_fe_from_storage(&r->x, &a->x); secp256k1_fe_from_storage(&r->y, &a->y); r->infinity = 0; } static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { secp256k1_fe_storage_cmov(&r->x, &a->x, flag); secp256k1_fe_storage_cmov(&r->y, &a->y, flag); } #ifdef USE_ENDOMORPHISM static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { static const secp256k1_fe beta = SECP256K1_FE_CONST( 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul ); *r = *a; secp256k1_fe_mul(&r->x, &r->x, &beta); } #endif static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { secp256k1_fe yz; if (a->infinity) { return 0; } /* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as * that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z is */ secp256k1_fe_mul(&yz, &a->y, &a->z); return secp256k1_fe_is_quad_var(&yz); } #endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/src/secp256k1/src/scratch.h b/src/secp256k1/src/scratch.h new file mode 100644 index 0000000000..aba56e215e --- /dev/null +++ b/src/secp256k1/src/scratch.h @@ -0,0 +1,35 @@ +/********************************************************************** + * 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_ + +/* 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; + size_t offset; + size_t init_size; + size_t max_size; + const secp256k1_callback* error_callback; +} secp256k1_scratch; + +static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t init_size, size_t max_size); +static void secp256k1_scratch_destroy(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); + +/** Attempts to allocate so that there are `n` available bytes. Returns 1 on success, 0 on failure */ +static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t n_objects); + +/** Returns a pointer into the scratch space or NULL if there is insufficient available space */ +static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t n); + +/** Resets the returned pointer to the beginning of space */ +static void secp256k1_scratch_reset(secp256k1_scratch* scratch); + +#endif diff --git a/src/secp256k1/src/scratch_impl.h b/src/secp256k1/src/scratch_impl.h new file mode 100644 index 0000000000..9bd68fe100 --- /dev/null +++ b/src/secp256k1/src/scratch_impl.h @@ -0,0 +1,77 @@ +/********************************************************************** + * 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 init_size, size_t max_size) { + secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret)); + if (ret != NULL) { + ret->data = checked_malloc(error_callback, init_size); + if (ret->data == NULL) { + free (ret); + return NULL; + } + ret->offset = 0; + ret->init_size = init_size; + ret->max_size = max_size; + ret->error_callback = error_callback; + } + return ret; +} + +static void secp256k1_scratch_destroy(secp256k1_scratch* scratch) { + if (scratch != NULL) { + free(scratch->data); + free(scratch); + } +} + +static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t objects) { + if (scratch->max_size <= objects * ALIGNMENT) { + return 0; + } + return scratch->max_size - objects * ALIGNMENT; +} + +static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t objects) { + n += objects * ALIGNMENT; + if (n > scratch->init_size && n <= scratch->max_size) { + void *tmp = checked_realloc(scratch->error_callback, scratch->data, n); + if (tmp == NULL) { + return 0; + } + scratch->init_size = n; + scratch->data = tmp; + } + return n <= scratch->max_size; +} + +static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) { + void *ret; + size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; + if (size + scratch->offset > scratch->init_size) { + return NULL; + } + ret = (void *) ((unsigned char *) scratch->data + scratch->offset); + memset(ret, 0, size); + scratch->offset += size; + return ret; +} + +static void secp256k1_scratch_reset(secp256k1_scratch* scratch) { + scratch->offset = 0; +} + +#endif diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c index 294eddac10..b6f5316fa5 100644 --- a/src/secp256k1/src/secp256k1.c +++ b/src/secp256k1/src/secp256k1.c @@ -1,596 +1,608 @@ /********************************************************************** * Copyright (c) 2013-2015 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #include "include/secp256k1.h" #include "util.h" #include "num_impl.h" #include "field_impl.h" #include "scalar_impl.h" #include "group_impl.h" #include "ecmult_impl.h" #include "ecmult_const_impl.h" #include "ecmult_gen_impl.h" #include "ecdsa_impl.h" #include "eckey_impl.h" #include "hash_impl.h" +#include "scratch_impl.h" #define ARG_CHECK(cond) do { \ if (EXPECT(!(cond), 0)) { \ secp256k1_callback_call(&ctx->illegal_callback, #cond); \ return 0; \ } \ } while(0) static void default_illegal_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); abort(); } static const secp256k1_callback default_illegal_callback = { default_illegal_callback_fn, NULL }; static void default_error_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); abort(); } static const secp256k1_callback default_error_callback = { default_error_callback_fn, NULL }; struct secp256k1_context_struct { secp256k1_ecmult_context ecmult_ctx; secp256k1_ecmult_gen_context ecmult_gen_ctx; secp256k1_callback illegal_callback; secp256k1_callback error_callback; }; secp256k1_context* secp256k1_context_create(unsigned int flags) { secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context)); ret->illegal_callback = default_illegal_callback; ret->error_callback = default_error_callback; if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { secp256k1_callback_call(&ret->illegal_callback, "Invalid flags"); free(ret); return NULL; } secp256k1_ecmult_context_init(&ret->ecmult_ctx); secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); } if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); } return ret; } secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context)); ret->illegal_callback = ctx->illegal_callback; ret->error_callback = ctx->error_callback; secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); return ret; } void secp256k1_context_destroy(secp256k1_context* ctx) { if (ctx != NULL) { secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); free(ctx); } } void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { if (fun == NULL) { fun = default_illegal_callback_fn; } ctx->illegal_callback.fn = fun; ctx->illegal_callback.data = data; } void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { if (fun == NULL) { fun = default_error_callback_fn; } ctx->error_callback.fn = fun; ctx->error_callback.data = data; } +secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t init_size, size_t max_size) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(max_size >= init_size); + + return secp256k1_scratch_create(&ctx->error_callback, init_size, 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) { if (sizeof(secp256k1_ge_storage) == 64) { /* When the secp256k1_ge_storage type is exactly 64 byte, use its * representation inside secp256k1_pubkey, as conversion is very fast. * Note that secp256k1_pubkey_save must use the same representation. */ secp256k1_ge_storage s; memcpy(&s, &pubkey->data[0], sizeof(s)); secp256k1_ge_from_storage(ge, &s); } else { /* Otherwise, fall back to 32-byte big endian for X and Y. */ secp256k1_fe x, y; secp256k1_fe_set_b32(&x, pubkey->data); secp256k1_fe_set_b32(&y, pubkey->data + 32); secp256k1_ge_set_xy(ge, &x, &y); } ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); return 1; } static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { if (sizeof(secp256k1_ge_storage) == 64) { secp256k1_ge_storage s; secp256k1_ge_to_storage(&s, ge); memcpy(&pubkey->data[0], &s, sizeof(s)); } else { VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); secp256k1_fe_normalize_var(&ge->x); secp256k1_fe_normalize_var(&ge->y); secp256k1_fe_get_b32(pubkey->data, &ge->x); secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); } } int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { secp256k1_ge Q; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(input != NULL); if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { return 0; } secp256k1_pubkey_save(pubkey, &Q); secp256k1_ge_clear(&Q); return 1; } int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { secp256k1_ge Q; size_t len; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(outputlen != NULL); ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); len = *outputlen; *outputlen = 0; ARG_CHECK(output != NULL); memset(output, 0, len); ARG_CHECK(pubkey != NULL); ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); if (ret) { *outputlen = len; } } return ret; } static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { (void)ctx; if (sizeof(secp256k1_scalar) == 32) { /* When the secp256k1_scalar type is exactly 32 byte, use its * representation inside secp256k1_ecdsa_signature, as conversion is very fast. * Note that secp256k1_ecdsa_signature_save must use the same representation. */ memcpy(r, &sig->data[0], 32); memcpy(s, &sig->data[32], 32); } else { secp256k1_scalar_set_b32(r, &sig->data[0], NULL); secp256k1_scalar_set_b32(s, &sig->data[32], NULL); } } static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { if (sizeof(secp256k1_scalar) == 32) { memcpy(&sig->data[0], r, 32); memcpy(&sig->data[32], s, 32); } else { secp256k1_scalar_get_b32(&sig->data[0], r); secp256k1_scalar_get_b32(&sig->data[32], s); } } int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { secp256k1_scalar r, s; VERIFY_CHECK(ctx != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(input != NULL); if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { secp256k1_ecdsa_signature_save(sig, &r, &s); return 1; } else { memset(sig, 0, sizeof(*sig)); return 0; } } int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) { secp256k1_scalar r, s; int ret = 1; int overflow = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(input64 != NULL); secp256k1_scalar_set_b32(&r, &input64[0], &overflow); ret &= !overflow; secp256k1_scalar_set_b32(&s, &input64[32], &overflow); ret &= !overflow; if (ret) { secp256k1_ecdsa_signature_save(sig, &r, &s); } else { memset(sig, 0, sizeof(*sig)); } return ret; } int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { secp256k1_scalar r, s; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output != NULL); ARG_CHECK(outputlen != NULL); ARG_CHECK(sig != NULL); secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); } int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) { secp256k1_scalar r, s; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output64 != NULL); ARG_CHECK(sig != NULL); secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); secp256k1_scalar_get_b32(&output64[0], &r); secp256k1_scalar_get_b32(&output64[32], &s); return 1; } int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) { secp256k1_scalar r, s; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(sigin != NULL); secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin); ret = secp256k1_scalar_is_high(&s); if (sigout != NULL) { if (ret) { secp256k1_scalar_negate(&s, &s); } secp256k1_ecdsa_signature_save(sigout, &r, &s); } return ret; } int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { secp256k1_ge q; secp256k1_scalar r, s; secp256k1_scalar m; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(msg32 != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(pubkey != NULL); secp256k1_scalar_set_b32(&m, msg32, NULL); secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); return (!secp256k1_scalar_is_high(&s) && secp256k1_pubkey_load(ctx, &q, pubkey) && 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) { unsigned char keydata[112]; unsigned int offset = 0; secp256k1_rfc6979_hmac_sha256 rng; unsigned int i; /* 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. * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. * - optionally 16 extra bytes with the algorithm name. * Because the arguments have distinct fixed lengths it is not possible for * different argument mixtures to emulate each other and result in the same * nonces. */ buffer_append(keydata, &offset, key32, 32); buffer_append(keydata, &offset, msg32, 32); if (data != NULL) { buffer_append(keydata, &offset, data, 32); } if (algo16 != NULL) { buffer_append(keydata, &offset, algo16, 16); } secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); memset(keydata, 0, sizeof(keydata)); for (i = 0; i <= counter; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); return 1; } const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { secp256k1_scalar r, s; secp256k1_scalar sec, non, msg; int ret = 0; int overflow = 0; const unsigned char secp256k1_ecdsa_der_algo16[17] = "ECDSA+DER "; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(msg32 != NULL); ARG_CHECK(signature != NULL); ARG_CHECK(seckey != NULL); if (noncefp == NULL) { noncefp = secp256k1_nonce_function_default; } secp256k1_scalar_set_b32(&sec, seckey, &overflow); /* Fail if the secret key is invalid. */ if (!overflow && !secp256k1_scalar_is_zero(&sec)) { unsigned char nonce32[32]; unsigned int count = 0; secp256k1_scalar_set_b32(&msg, msg32, NULL); while (1) { ret = noncefp(nonce32, msg32, seckey, secp256k1_ecdsa_der_algo16, (void*)noncedata, count); if (!ret) { break; } secp256k1_scalar_set_b32(&non, nonce32, &overflow); if (!overflow && !secp256k1_scalar_is_zero(&non)) { if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { break; } } count++; } memset(nonce32, 0, 32); secp256k1_scalar_clear(&msg); secp256k1_scalar_clear(&non); secp256k1_scalar_clear(&sec); } if (ret) { secp256k1_ecdsa_signature_save(signature, &r, &s); } else { memset(signature, 0, sizeof(*signature)); } return ret; } int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { secp256k1_scalar sec; int ret; int overflow; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); secp256k1_scalar_set_b32(&sec, seckey, &overflow); ret = !overflow && !secp256k1_scalar_is_zero(&sec); secp256k1_scalar_clear(&sec); return ret; } int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { secp256k1_gej pj; secp256k1_ge p; secp256k1_scalar sec; int overflow; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(seckey != NULL); secp256k1_scalar_set_b32(&sec, seckey, &overflow); ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); if (ret) { secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); secp256k1_ge_set_gej(&p, &pj); secp256k1_pubkey_save(pubkey, &p); } secp256k1_scalar_clear(&sec); 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) { secp256k1_scalar term; secp256k1_scalar sec; int ret = 0; int overflow = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ARG_CHECK(tweak != NULL); secp256k1_scalar_set_b32(&term, tweak, &overflow); secp256k1_scalar_set_b32(&sec, seckey, NULL); ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term); memset(seckey, 0, 32); if (ret) { secp256k1_scalar_get_b32(seckey, &sec); } secp256k1_scalar_clear(&sec); secp256k1_scalar_clear(&term); return ret; } int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { secp256k1_ge p; secp256k1_scalar term; int ret = 0; int overflow = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(pubkey != NULL); ARG_CHECK(tweak != NULL); secp256k1_scalar_set_b32(&term, tweak, &overflow); ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); memset(pubkey, 0, sizeof(*pubkey)); if (ret) { if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { secp256k1_pubkey_save(pubkey, &p); } else { ret = 0; } } return ret; } int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { secp256k1_scalar factor; secp256k1_scalar sec; int ret = 0; int overflow = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ARG_CHECK(tweak != NULL); secp256k1_scalar_set_b32(&factor, tweak, &overflow); secp256k1_scalar_set_b32(&sec, seckey, NULL); ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor); memset(seckey, 0, 32); if (ret) { secp256k1_scalar_get_b32(seckey, &sec); } secp256k1_scalar_clear(&sec); secp256k1_scalar_clear(&factor); return ret; } int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { secp256k1_ge p; secp256k1_scalar factor; int ret = 0; int overflow = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(pubkey != NULL); ARG_CHECK(tweak != NULL); secp256k1_scalar_set_b32(&factor, tweak, &overflow); ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); memset(pubkey, 0, sizeof(*pubkey)); if (ret) { if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { secp256k1_pubkey_save(pubkey, &p); } else { ret = 0; } } return ret; } int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); return 1; } int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { size_t i; secp256k1_gej Qj; secp256k1_ge Q; ARG_CHECK(pubnonce != NULL); memset(pubnonce, 0, sizeof(*pubnonce)); ARG_CHECK(n >= 1); ARG_CHECK(pubnonces != NULL); secp256k1_gej_set_infinity(&Qj); for (i = 0; i < n; i++) { secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); secp256k1_gej_add_ge(&Qj, &Qj, &Q); } if (secp256k1_gej_is_infinity(&Qj)) { return 0; } secp256k1_ge_set_gej(&Q, &Qj); secp256k1_pubkey_save(pubnonce, &Q); return 1; } #ifdef ENABLE_MODULE_ECDH # include "modules/ecdh/main_impl.h" #endif #ifdef ENABLE_MODULE_MULTISET # include "modules/multiset/main_impl.h" #endif #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/main_impl.h" #endif #ifdef ENABLE_MODULE_SCHNORR # include "modules/schnorr/main_impl.h" #endif diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c index 3d33b9be01..576c2be6e5 100644 --- a/src/secp256k1/src/tests.c +++ b/src/secp256k1/src/tests.c @@ -1,4560 +1,5044 @@ /********************************************************************** * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #include #include #include #include #include "secp256k1.c" #include "include/secp256k1.h" #include "testrand_impl.h" #ifdef ENABLE_OPENSSL_TESTS #include "openssl/bn.h" #include "openssl/ec.h" #include "openssl/ecdsa.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 #include "contrib/lax_der_parsing.c" #include "contrib/lax_der_privatekey_parsing.c" #if !defined(VG_CHECK) # if defined(VALGRIND) # include # define VG_UNDEF(x,y) VALGRIND_MAKE_MEM_UNDEFINED((x),(y)) # define VG_CHECK(x,y) VALGRIND_CHECK_MEM_IS_DEFINED((x),(y)) # else # define VG_UNDEF(x,y) # define VG_CHECK(x,y) # endif #endif static int count = 64; static secp256k1_context *ctx = NULL; static void counting_illegal_callback_fn(const char* str, void* data) { /* Dummy callback function that just counts. */ int32_t *p; (void)str; p = data; (*p)++; } static void uncounting_illegal_callback_fn(const char* str, void* data) { /* Dummy callback function that just counts (backwards). */ int32_t *p; (void)str; p = data; (*p)--; } void random_field_element_test(secp256k1_fe *fe) { do { unsigned char b32[32]; secp256k1_rand256_test(b32); if (secp256k1_fe_set_b32(fe, b32)) { break; } } while(1); } void random_field_element_magnitude(secp256k1_fe *fe) { secp256k1_fe zero; int n = secp256k1_rand_int(9); secp256k1_fe_normalize(fe); if (n == 0) { return; } secp256k1_fe_clear(&zero); secp256k1_fe_negate(&zero, &zero, 0); secp256k1_fe_mul_int(&zero, n - 1); secp256k1_fe_add(fe, &zero); VERIFY_CHECK(fe->magnitude == n); } void random_group_element_test(secp256k1_ge *ge) { secp256k1_fe fe; do { random_field_element_test(&fe); if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_rand_bits(1))) { secp256k1_fe_normalize(&ge->y); break; } } while(1); } void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { secp256k1_fe z2, z3; do { random_field_element_test(&gej->z); if (!secp256k1_fe_is_zero(&gej->z)) { break; } } while(1); secp256k1_fe_sqr(&z2, &gej->z); secp256k1_fe_mul(&z3, &z2, &gej->z); secp256k1_fe_mul(&gej->x, &ge->x, &z2); secp256k1_fe_mul(&gej->y, &ge->y, &z3); gej->infinity = ge->infinity; } void random_scalar_order_test(secp256k1_scalar *num) { do { unsigned char b32[32]; int overflow = 0; secp256k1_rand256_test(b32); secp256k1_scalar_set_b32(num, b32, &overflow); if (overflow || secp256k1_scalar_is_zero(num)) { continue; } break; } while(1); } void random_scalar_order(secp256k1_scalar *num) { do { unsigned char b32[32]; int overflow = 0; secp256k1_rand256(b32); secp256k1_scalar_set_b32(num, b32, &overflow); if (overflow || secp256k1_scalar_is_zero(num)) { continue; } break; } while(1); } void run_context_tests(void) { secp256k1_pubkey pubkey; secp256k1_pubkey zero_pubkey; secp256k1_ecdsa_signature sig; unsigned char ctmp[32]; int32_t ecount; int32_t ecount2; secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); secp256k1_gej pubj; secp256k1_ge pub; secp256k1_scalar msg, key, nonce; secp256k1_scalar sigr, sigs; memset(&zero_pubkey, 0, sizeof(zero_pubkey)); ecount = 0; ecount2 = 10; secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2); secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL); CHECK(vrfy->error_callback.fn != sign->error_callback.fn); /*** clone and destroy all of them to make sure cloning was complete ***/ { secp256k1_context *ctx_tmp; ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp); ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp); ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp); ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp); } /* Verify that the error callback makes it across the clone. */ CHECK(vrfy->error_callback.fn != sign->error_callback.fn); /* And that it resets back to default. */ secp256k1_context_set_error_callback(sign, NULL, NULL); CHECK(vrfy->error_callback.fn == sign->error_callback.fn); /*** attempt to use them ***/ random_scalar_order_test(&msg); random_scalar_order_test(&key); secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key); secp256k1_ge_set_gej(&pub, &pubj); /* Verify context-type checking illegal-argument errors. */ memset(ctmp, 1, 32); CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0); CHECK(ecount == 1); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0); CHECK(ecount == 2); VG_UNDEF(&sig, sizeof(sig)); CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1); VG_CHECK(&sig, sizeof(sig)); CHECK(ecount2 == 10); CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0); CHECK(ecount2 == 11); CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1); CHECK(ecount == 2); CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0); CHECK(ecount2 == 12); CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1); CHECK(ecount == 2); CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); CHECK(ecount2 == 13); CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1); CHECK(ecount == 2); 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(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(ecount2 == 14); secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); secp256k1_context_set_illegal_callback(sign, NULL, NULL); /* This shouldn't leak memory, due to already-set tests. */ secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL); secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL); /* obtain a working nonce */ do { random_scalar_order_test(&nonce); } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); /* try signing */ CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); /* try verifying */ CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg)); CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg)); /* cleanup */ secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(vrfy); secp256k1_context_destroy(both); /* Defined as no-op. */ 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, 100, 10); + CHECK(scratch == NULL); + CHECK(ecount == 1); + + scratch = secp256k1_scratch_space_create(none, 100, 100); + CHECK(scratch != NULL); + CHECK(ecount == 1); + secp256k1_scratch_space_destroy(scratch); + + scratch = secp256k1_scratch_space_create(none, 100, 1000); + CHECK(scratch != NULL); + CHECK(ecount == 1); + + /* Test internal API */ + CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000); + CHECK(secp256k1_scratch_max_allocation(scratch, 1) < 1000); + CHECK(secp256k1_scratch_resize(scratch, 50, 1) == 1); /* no-op */ + CHECK(secp256k1_scratch_resize(scratch, 200, 1) == 1); + CHECK(secp256k1_scratch_resize(scratch, 950, 1) == 1); + CHECK(secp256k1_scratch_resize(scratch, 1000, 1) == 0); + CHECK(secp256k1_scratch_resize(scratch, 2000, 1) == 0); + CHECK(secp256k1_scratch_max_allocation(scratch, 0) == 1000); + + /* cleanup */ + secp256k1_scratch_space_destroy(scratch); + secp256k1_context_destroy(none); +} + /***** HASH TESTS *****/ void run_sha256_tests(void) { static const char *inputs[8] = { "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "For this sample, this 63-byte string will be used as input data", "This is exactly 64 bytes long, not counting the terminating byte" }; static const unsigned char outputs[8][32] = { {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}, {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}, {0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50}, {0xf3, 0x0c, 0xeb, 0x2b, 0xb2, 0x82, 0x9e, 0x79, 0xe4, 0xca, 0x97, 0x53, 0xd3, 0x5a, 0x8e, 0xcc, 0x00, 0x26, 0x2d, 0x16, 0x4c, 0xc0, 0x77, 0x08, 0x02, 0x95, 0x38, 0x1c, 0xbd, 0x64, 0x3f, 0x0d}, {0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30}, {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}, {0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42}, {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8} }; int i; for (i = 0; i < 8; i++) { unsigned char out[32]; secp256k1_sha256 hasher; secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); secp256k1_sha256_finalize(&hasher, out); CHECK(memcmp(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { int split = secp256k1_rand_int(strlen(inputs[i])); secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); secp256k1_sha256_finalize(&hasher, out); CHECK(memcmp(out, outputs[i], 32) == 0); } } } void run_hmac_sha256_tests(void) { static const char *keys[6] = { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "\x4a\x65\x66\x65", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" }; static const char *inputs[6] = { "\x48\x69\x20\x54\x68\x65\x72\x65", "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69\x72\x73\x74", "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e" }; static const unsigned char outputs[6][32] = { {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7}, {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43}, {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe}, {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b}, {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54}, {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} }; int i; for (i = 0; i < 6; i++) { secp256k1_hmac_sha256 hasher; unsigned char out[32]; 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_finalize(&hasher, out); CHECK(memcmp(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { int split = secp256k1_rand_int(strlen(inputs[i])); secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); secp256k1_hmac_sha256_finalize(&hasher, out); CHECK(memcmp(out, outputs[i], 32) == 0); } } } void run_rfc6979_hmac_sha256_tests(void) { static const unsigned char key1[65] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5, 0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3, 0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5, 0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a, 0}; static const unsigned char out1[3][32] = { {0x4f, 0xe2, 0x95, 0x25, 0xb2, 0x08, 0x68, 0x09, 0x15, 0x9a, 0xcd, 0xf0, 0x50, 0x6e, 0xfb, 0x86, 0xb0, 0xec, 0x93, 0x2c, 0x7b, 0xa4, 0x42, 0x56, 0xab, 0x32, 0x1e, 0x42, 0x1e, 0x67, 0xe9, 0xfb}, {0x2b, 0xf0, 0xff, 0xf1, 0xd3, 0xc3, 0x78, 0xa2, 0x2d, 0xc5, 0xde, 0x1d, 0x85, 0x65, 0x22, 0x32, 0x5c, 0x65, 0xb5, 0x04, 0x49, 0x1a, 0x0c, 0xbd, 0x01, 0xcb, 0x8f, 0x3a, 0xa6, 0x7f, 0xfd, 0x4a}, {0xf5, 0x28, 0xb4, 0x10, 0xcb, 0x54, 0x1f, 0x77, 0x00, 0x0d, 0x7a, 0xfb, 0x6c, 0x5b, 0x53, 0xc5, 0xc4, 0x71, 0xea, 0xb4, 0x3e, 0x46, 0x6d, 0x9a, 0xc5, 0x19, 0x0c, 0x39, 0xc8, 0x2f, 0xd8, 0x2e} }; static const unsigned char key2[64] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; static const unsigned char out2[3][32] = { {0x9c, 0x23, 0x6c, 0x16, 0x5b, 0x82, 0xae, 0x0c, 0xd5, 0x90, 0x65, 0x9e, 0x10, 0x0b, 0x6b, 0xab, 0x30, 0x36, 0xe7, 0xba, 0x8b, 0x06, 0x74, 0x9b, 0xaf, 0x69, 0x81, 0xe1, 0x6f, 0x1a, 0x2b, 0x95}, {0xdf, 0x47, 0x10, 0x61, 0x62, 0x5b, 0xc0, 0xea, 0x14, 0xb6, 0x82, 0xfe, 0xee, 0x2c, 0x9c, 0x02, 0xf2, 0x35, 0xda, 0x04, 0x20, 0x4c, 0x1d, 0x62, 0xa1, 0x53, 0x6c, 0x6e, 0x17, 0xae, 0xd7, 0xa9}, {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 rng; unsigned char out[32]; int i; secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); for (i = 0; i < 3; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); CHECK(memcmp(out, out1[i], 32) == 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); for (i = 0; i < 3; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); CHECK(memcmp(out, out1[i], 32) != 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); for (i = 0; i < 3; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); CHECK(memcmp(out, out2[i], 32) == 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); } /***** RANDOM TESTS *****/ void test_rand_bits(int rand32, int bits) { /* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to * get a false negative chance below once in a billion */ static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316}; /* We try multiplying the results with various odd numbers, which shouldn't * influence the uniform distribution modulo a power of 2. */ static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011}; /* We only select up to 6 bits from the output to analyse */ unsigned int usebits = bits > 6 ? 6 : bits; unsigned int maxshift = bits - usebits; /* For each of the maxshift+1 usebits-bit sequences inside a bits-bit number, track all observed outcomes, one per bit in a uint64_t. */ uint64_t x[6][27] = {{0}}; unsigned int i, shift, m; /* Multiply the output of all rand calls with the odd number m, which should not change the uniformity of its distribution. */ for (i = 0; i < rounds[usebits]; i++) { uint32_t r = (rand32 ? secp256k1_rand32() : secp256k1_rand_bits(bits)); CHECK((((uint64_t)r) >> bits) == 0); for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { uint32_t rm = r * mults[m]; for (shift = 0; shift <= maxshift; shift++) { x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1))); } } } for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { for (shift = 0; shift <= maxshift; shift++) { /* Test that the lower usebits bits of x[shift] are 1 */ CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0); } } } /* Subrange must be a whole divisor of range, and at most 64 */ void test_rand_int(uint32_t range, uint32_t subrange) { /* (1-1/subrange)^rounds < 1/10^9 */ int rounds = (subrange * 2073) / 100; int i; uint64_t x = 0; CHECK((range % subrange) == 0); for (i = 0; i < rounds; i++) { uint32_t r = secp256k1_rand_int(range); CHECK(r < range); r = r % subrange; x |= (((uint64_t)1) << r); } /* Test that the lower subrange bits of x are 1. */ CHECK(((~x) << (64 - subrange)) == 0); } void run_rand_bits(void) { size_t b; test_rand_bits(1, 32); for (b = 1; b <= 32; b++) { test_rand_bits(0, b); } } void run_rand_int(void) { static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432}; static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64}; unsigned int m, s; for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) { for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) { test_rand_int(ms[m] * ss[s], ss[s]); } } } /***** NUM TESTS *****/ #ifndef USE_NUM_NONE void random_num_negate(secp256k1_num *num) { if (secp256k1_rand_bits(1)) { secp256k1_num_negate(num); } } void random_num_order_test(secp256k1_num *num) { secp256k1_scalar sc; random_scalar_order_test(&sc); secp256k1_scalar_get_num(num, &sc); } void random_num_order(secp256k1_num *num) { secp256k1_scalar sc; random_scalar_order(&sc); secp256k1_scalar_get_num(num, &sc); } void test_num_negate(void) { secp256k1_num n1; secp256k1_num n2; random_num_order_test(&n1); /* n1 = R */ random_num_negate(&n1); secp256k1_num_copy(&n2, &n1); /* n2 = R */ secp256k1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */ CHECK(secp256k1_num_is_zero(&n1)); secp256k1_num_copy(&n1, &n2); /* n1 = R */ secp256k1_num_negate(&n1); /* n1 = -R */ CHECK(!secp256k1_num_is_zero(&n1)); secp256k1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */ CHECK(secp256k1_num_is_zero(&n1)); secp256k1_num_copy(&n1, &n2); /* n1 = R */ secp256k1_num_negate(&n1); /* n1 = -R */ CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2)); secp256k1_num_negate(&n1); /* n1 = R */ CHECK(secp256k1_num_eq(&n1, &n2)); } void test_num_add_sub(void) { int i; secp256k1_scalar s; secp256k1_num n1; secp256k1_num n2; secp256k1_num n1p2, n2p1, n1m2, n2m1; random_num_order_test(&n1); /* n1 = R1 */ if (secp256k1_rand_bits(1)) { random_num_negate(&n1); } random_num_order_test(&n2); /* n2 = R2 */ if (secp256k1_rand_bits(1)) { random_num_negate(&n2); } secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ CHECK(secp256k1_num_eq(&n1p2, &n2p1)); CHECK(!secp256k1_num_eq(&n1p2, &n1m2)); secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ CHECK(secp256k1_num_eq(&n2m1, &n1m2)); CHECK(!secp256k1_num_eq(&n2m1, &n1)); secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ CHECK(secp256k1_num_eq(&n2m1, &n1)); CHECK(!secp256k1_num_eq(&n2p1, &n1)); secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ CHECK(secp256k1_num_eq(&n2p1, &n1)); /* check is_one */ secp256k1_scalar_set_int(&s, 1); secp256k1_scalar_get_num(&n1, &s); CHECK(secp256k1_num_is_one(&n1)); /* check that 2^n + 1 is never 1 */ secp256k1_scalar_get_num(&n2, &s); for (i = 0; i < 250; ++i) { secp256k1_num_add(&n1, &n1, &n1); /* n1 *= 2 */ secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = n1 + 1 */ CHECK(!secp256k1_num_is_one(&n1p2)); } } void test_num_mod(void) { int i; secp256k1_scalar s; secp256k1_num order, n; /* check that 0 mod anything is 0 */ random_scalar_order_test(&s); secp256k1_scalar_get_num(&order, &s); secp256k1_scalar_set_int(&s, 0); secp256k1_scalar_get_num(&n, &s); secp256k1_num_mod(&n, &order); CHECK(secp256k1_num_is_zero(&n)); /* check that anything mod 1 is 0 */ secp256k1_scalar_set_int(&s, 1); secp256k1_scalar_get_num(&order, &s); secp256k1_scalar_get_num(&n, &s); secp256k1_num_mod(&n, &order); CHECK(secp256k1_num_is_zero(&n)); /* check that increasing the number past 2^256 does not break this */ random_scalar_order_test(&s); secp256k1_scalar_get_num(&n, &s); /* multiply by 2^8, which'll test this case with high probability */ for (i = 0; i < 8; ++i) { secp256k1_num_add(&n, &n, &n); } secp256k1_num_mod(&n, &order); CHECK(secp256k1_num_is_zero(&n)); } void test_num_jacobi(void) { secp256k1_scalar sqr; secp256k1_scalar small; secp256k1_scalar five; /* five is not a quadratic residue */ secp256k1_num order, n; int i; /* squares mod 5 are 1, 4 */ const int jacobi5[10] = { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1 }; /* check some small values with 5 as the order */ secp256k1_scalar_set_int(&five, 5); secp256k1_scalar_get_num(&order, &five); for (i = 0; i < 10; ++i) { secp256k1_scalar_set_int(&small, i); secp256k1_scalar_get_num(&n, &small); CHECK(secp256k1_num_jacobi(&n, &order) == jacobi5[i]); } /** test large values with 5 as group order */ secp256k1_scalar_get_num(&order, &five); /* we first need a scalar which is not a multiple of 5 */ do { secp256k1_num fiven; random_scalar_order_test(&sqr); secp256k1_scalar_get_num(&fiven, &five); secp256k1_scalar_get_num(&n, &sqr); secp256k1_num_mod(&n, &fiven); } while (secp256k1_num_is_zero(&n)); /* next force it to be a residue. 2 is a nonresidue mod 5 so we can * just multiply by two, i.e. add the number to itself */ if (secp256k1_num_jacobi(&n, &order) == -1) { secp256k1_num_add(&n, &n, &n); } /* test residue */ CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* test nonresidue */ secp256k1_num_add(&n, &n, &n); CHECK(secp256k1_num_jacobi(&n, &order) == -1); /** test with secp group order as order */ secp256k1_scalar_order_get_num(&order); random_scalar_order_test(&sqr); secp256k1_scalar_sqr(&sqr, &sqr); /* test residue */ secp256k1_scalar_get_num(&n, &sqr); CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* test nonresidue */ secp256k1_scalar_mul(&sqr, &sqr, &five); secp256k1_scalar_get_num(&n, &sqr); CHECK(secp256k1_num_jacobi(&n, &order) == -1); /* test multiple of the order*/ CHECK(secp256k1_num_jacobi(&order, &order) == 0); /* check one less than the order */ secp256k1_scalar_set_int(&small, 1); secp256k1_scalar_get_num(&n, &small); secp256k1_num_sub(&n, &order, &n); CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* sage confirms this is 1 */ } void run_num_smalltests(void) { int i; for (i = 0; i < 100*count; i++) { test_num_negate(); test_num_add_sub(); test_num_mod(); test_num_jacobi(); } } #endif /***** SCALAR TESTS *****/ void scalar_test(void) { secp256k1_scalar s; secp256k1_scalar s1; secp256k1_scalar s2; #ifndef USE_NUM_NONE secp256k1_num snum, s1num, s2num; secp256k1_num order, half_order; #endif unsigned char c[32]; /* Set 's' to a random scalar, with value 'snum'. */ random_scalar_order_test(&s); /* Set 's1' to a random scalar, with value 's1num'. */ random_scalar_order_test(&s1); /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ random_scalar_order_test(&s2); secp256k1_scalar_get_b32(c, &s2); #ifndef USE_NUM_NONE secp256k1_scalar_get_num(&snum, &s); secp256k1_scalar_get_num(&s1num, &s1); secp256k1_scalar_get_num(&s2num, &s2); secp256k1_scalar_order_get_num(&order); half_order = order; secp256k1_num_shift(&half_order, 1); #endif { int i; /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ secp256k1_scalar n; secp256k1_scalar_set_int(&n, 0); for (i = 0; i < 256; i += 4) { secp256k1_scalar t; int j; secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); for (j = 0; j < 4; j++) { secp256k1_scalar_add(&n, &n, &n); } secp256k1_scalar_add(&n, &n, &t); } CHECK(secp256k1_scalar_eq(&n, &s)); } { /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ secp256k1_scalar n; int i = 0; secp256k1_scalar_set_int(&n, 0); while (i < 256) { secp256k1_scalar t; int j; int now = secp256k1_rand_int(15) + 1; if (now + i > 256) { now = 256 - i; } secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); for (j = 0; j < now; j++) { secp256k1_scalar_add(&n, &n, &n); } secp256k1_scalar_add(&n, &n, &t); i += now; } CHECK(secp256k1_scalar_eq(&n, &s)); } #ifndef USE_NUM_NONE { /* Test that adding the scalars together is equal to adding their numbers together modulo the order. */ secp256k1_num rnum; secp256k1_num r2num; secp256k1_scalar r; secp256k1_num_add(&rnum, &snum, &s2num); secp256k1_num_mod(&rnum, &order); secp256k1_scalar_add(&r, &s, &s2); secp256k1_scalar_get_num(&r2num, &r); CHECK(secp256k1_num_eq(&rnum, &r2num)); } { /* Test that multiplying the scalars is equal to multiplying their numbers modulo the order. */ secp256k1_scalar r; secp256k1_num r2num; secp256k1_num rnum; secp256k1_num_mul(&rnum, &snum, &s2num); secp256k1_num_mod(&rnum, &order); secp256k1_scalar_mul(&r, &s, &s2); secp256k1_scalar_get_num(&r2num, &r); CHECK(secp256k1_num_eq(&rnum, &r2num)); /* The result can only be zero if at least one of the factors was zero. */ CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); /* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */ CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); } { secp256k1_scalar neg; secp256k1_num negnum; secp256k1_num negnum2; /* Check that comparison with zero matches comparison with zero on the number. */ CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); /* Check that comparison with the half order is equal to testing for high scalar. */ CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &half_order) > 0)); secp256k1_scalar_negate(&neg, &s); secp256k1_num_sub(&negnum, &order, &snum); secp256k1_num_mod(&negnum, &order); /* Check that comparison with the half order is equal to testing for high scalar after negation. */ CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &half_order) > 0)); /* Negating should change the high property, unless the value was already zero. */ CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s)); secp256k1_scalar_get_num(&negnum2, &neg); /* Negating a scalar should be equal to (order - n) mod order on the number. */ CHECK(secp256k1_num_eq(&negnum, &negnum2)); secp256k1_scalar_add(&neg, &neg, &s); /* Adding a number to its negation should result in zero. */ CHECK(secp256k1_scalar_is_zero(&neg)); secp256k1_scalar_negate(&neg, &neg); /* Negating zero should still result in zero. */ CHECK(secp256k1_scalar_is_zero(&neg)); } { /* Test secp256k1_scalar_mul_shift_var. */ secp256k1_scalar r; secp256k1_num one; secp256k1_num rnum; secp256k1_num rnum2; unsigned char cone[1] = {0x01}; unsigned int shift = 256 + secp256k1_rand_int(257); secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift); secp256k1_num_mul(&rnum, &s1num, &s2num); secp256k1_num_shift(&rnum, shift - 1); secp256k1_num_set_bin(&one, cone, 1); secp256k1_num_add(&rnum, &rnum, &one); secp256k1_num_shift(&rnum, 1); secp256k1_scalar_get_num(&rnum2, &r); CHECK(secp256k1_num_eq(&rnum, &rnum2)); } { /* test secp256k1_scalar_shr_int */ secp256k1_scalar r; int i; random_scalar_order_test(&r); for (i = 0; i < 100; ++i) { int low; int shift = 1 + secp256k1_rand_int(15); int expected = r.d[0] % (1 << shift); low = secp256k1_scalar_shr_int(&r, shift); CHECK(expected == low); } } #endif { /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ if (!secp256k1_scalar_is_zero(&s)) { secp256k1_scalar inv; #ifndef USE_NUM_NONE secp256k1_num invnum; secp256k1_num invnum2; #endif secp256k1_scalar_inverse(&inv, &s); #ifndef USE_NUM_NONE secp256k1_num_mod_inverse(&invnum, &snum, &order); secp256k1_scalar_get_num(&invnum2, &inv); CHECK(secp256k1_num_eq(&invnum, &invnum2)); #endif secp256k1_scalar_mul(&inv, &inv, &s); /* Multiplying a scalar with its inverse must result in one. */ CHECK(secp256k1_scalar_is_one(&inv)); secp256k1_scalar_inverse(&inv, &inv); /* Inverting one must result in one. */ CHECK(secp256k1_scalar_is_one(&inv)); #ifndef USE_NUM_NONE secp256k1_scalar_get_num(&invnum, &inv); CHECK(secp256k1_num_is_one(&invnum)); #endif } } { /* Test commutativity of add. */ secp256k1_scalar r1, r2; secp256k1_scalar_add(&r1, &s1, &s2); secp256k1_scalar_add(&r2, &s2, &s1); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { secp256k1_scalar r1, r2; secp256k1_scalar b; int i; /* Test add_bit. */ int bit = secp256k1_rand_bits(8); secp256k1_scalar_set_int(&b, 1); CHECK(secp256k1_scalar_is_one(&b)); for (i = 0; i < bit; i++) { secp256k1_scalar_add(&b, &b, &b); } r1 = s1; r2 = s1; if (!secp256k1_scalar_add(&r1, &r1, &b)) { /* No overflow happened. */ secp256k1_scalar_cadd_bit(&r2, bit, 1); CHECK(secp256k1_scalar_eq(&r1, &r2)); /* cadd is a noop when flag is zero */ secp256k1_scalar_cadd_bit(&r2, bit, 0); CHECK(secp256k1_scalar_eq(&r1, &r2)); } } { /* Test commutativity of mul. */ secp256k1_scalar r1, r2; secp256k1_scalar_mul(&r1, &s1, &s2); secp256k1_scalar_mul(&r2, &s2, &s1); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test associativity of add. */ secp256k1_scalar r1, r2; secp256k1_scalar_add(&r1, &s1, &s2); secp256k1_scalar_add(&r1, &r1, &s); secp256k1_scalar_add(&r2, &s2, &s); secp256k1_scalar_add(&r2, &s1, &r2); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test associativity of mul. */ secp256k1_scalar r1, r2; secp256k1_scalar_mul(&r1, &s1, &s2); secp256k1_scalar_mul(&r1, &r1, &s); secp256k1_scalar_mul(&r2, &s2, &s); secp256k1_scalar_mul(&r2, &s1, &r2); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test distributitivity of mul over add. */ secp256k1_scalar r1, r2, t; secp256k1_scalar_add(&r1, &s1, &s2); secp256k1_scalar_mul(&r1, &r1, &s); secp256k1_scalar_mul(&r2, &s1, &s); secp256k1_scalar_mul(&t, &s2, &s); secp256k1_scalar_add(&r2, &r2, &t); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test square. */ secp256k1_scalar r1, r2; secp256k1_scalar_sqr(&r1, &s1); secp256k1_scalar_mul(&r2, &s1, &s1); CHECK(secp256k1_scalar_eq(&r1, &r2)); } { /* Test multiplicative identity. */ secp256k1_scalar r1, v1; secp256k1_scalar_set_int(&v1,1); secp256k1_scalar_mul(&r1, &s1, &v1); CHECK(secp256k1_scalar_eq(&r1, &s1)); } { /* Test additive identity. */ secp256k1_scalar r1, v0; secp256k1_scalar_set_int(&v0,0); secp256k1_scalar_add(&r1, &s1, &v0); CHECK(secp256k1_scalar_eq(&r1, &s1)); } { /* Test zero product property. */ secp256k1_scalar r1, v0; secp256k1_scalar_set_int(&v0,0); secp256k1_scalar_mul(&r1, &s1, &v0); CHECK(secp256k1_scalar_eq(&r1, &v0)); } } void run_scalar_tests(void) { int i; for (i = 0; i < 128 * count; i++) { scalar_test(); } { /* (-1)+1 should be zero. */ secp256k1_scalar s, o; secp256k1_scalar_set_int(&s, 1); CHECK(secp256k1_scalar_is_one(&s)); secp256k1_scalar_negate(&o, &s); secp256k1_scalar_add(&o, &o, &s); CHECK(secp256k1_scalar_is_zero(&o)); secp256k1_scalar_negate(&o, &o); CHECK(secp256k1_scalar_is_zero(&o)); } #ifndef USE_NUM_NONE { /* A scalar with value of the curve order should be 0. */ secp256k1_num order; secp256k1_scalar zero; unsigned char bin[32]; int overflow = 0; secp256k1_scalar_order_get_num(&order); secp256k1_num_get_bin(bin, 32, &order); secp256k1_scalar_set_b32(&zero, bin, &overflow); CHECK(overflow == 1); CHECK(secp256k1_scalar_is_zero(&zero)); } #endif { /* Does check_overflow check catch all ones? */ static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); CHECK(secp256k1_scalar_check_overflow(&overflowed)); } { /* Static test vectors. * These were reduced from ~10^12 random vectors based on comparison-decision * and edge-case coverage on 32-bit and 64-bit implementations. * The responses were generated with Sage 5.9. */ secp256k1_scalar x; secp256k1_scalar y; secp256k1_scalar z; secp256k1_scalar zz; secp256k1_scalar one; secp256k1_scalar r1; secp256k1_scalar r2; #if defined(USE_SCALAR_INV_NUM) secp256k1_scalar zzv; #endif int overflow; unsigned char chal[33][2][32] = { {{0xff, 0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff}, {0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff}}, {{0xef, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x80, 0xff}}, {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00}, {0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff}}, {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf3, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff}}, {{0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xfc, 0x9f, 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0x0f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0xff}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0}, {0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, {{0x00, 0xf8, 0xff, 0x03, 0xff, 0xff, 0xff, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0x0f, 0xfc, 0xff}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, {{0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0x7f}, {0xff, 0xcf, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0x01, 0xfc, 0xff, 0x01, 0x00, 0xfe, 0xff}, {0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00}}, {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0xff, 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7e, 0x00, 0x00}}, {{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x07, 0x00}, {0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60}}, {{0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x80, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, {0xff, 0xff, 0x1f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00}}, {{0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xcf, 0xff, 0x1f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00}, {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x1f, 0x00, 0xfe}}, {{0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff}}, {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, {0xff, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, {{0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff}, {0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xc0, 0xf1, 0x7f, 0x00}}, {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00}, {0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0xff, 0xff}}, {{0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0x03, 0xe0, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xf0, 0x07, 0x00, 0x3c, 0x80, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0xff, 0x00, 0x00, 0x00}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, 0xfe, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0xfe, 0xff}}, {{0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf0}, {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff}}, {{0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}, {0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}} }; unsigned char res[33][2][32] = { {{0x0c, 0x3b, 0x0a, 0xca, 0x8d, 0x1a, 0x2f, 0xb9, 0x8a, 0x7b, 0x53, 0x5a, 0x1f, 0xc5, 0x22, 0xa1, 0x07, 0x2a, 0x48, 0xea, 0x02, 0xeb, 0xb3, 0xd6, 0x20, 0x1e, 0x86, 0xd0, 0x95, 0xf6, 0x92, 0x35}, {0xdc, 0x90, 0x7a, 0x07, 0x2e, 0x1e, 0x44, 0x6d, 0xf8, 0x15, 0x24, 0x5b, 0x5a, 0x96, 0x37, 0x9c, 0x37, 0x7b, 0x0d, 0xac, 0x1b, 0x65, 0x58, 0x49, 0x43, 0xb7, 0x31, 0xbb, 0xa7, 0xf4, 0x97, 0x15}}, {{0xf1, 0xf7, 0x3a, 0x50, 0xe6, 0x10, 0xba, 0x22, 0x43, 0x4d, 0x1f, 0x1f, 0x7c, 0x27, 0xca, 0x9c, 0xb8, 0xb6, 0xa0, 0xfc, 0xd8, 0xc0, 0x05, 0x2f, 0xf7, 0x08, 0xe1, 0x76, 0xdd, 0xd0, 0x80, 0xc8}, {0xe3, 0x80, 0x80, 0xb8, 0xdb, 0xe3, 0xa9, 0x77, 0x00, 0xb0, 0xf5, 0x2e, 0x27, 0xe2, 0x68, 0xc4, 0x88, 0xe8, 0x04, 0xc1, 0x12, 0xbf, 0x78, 0x59, 0xe6, 0xa9, 0x7c, 0xe1, 0x81, 0xdd, 0xb9, 0xd5}}, {{0x96, 0xe2, 0xee, 0x01, 0xa6, 0x80, 0x31, 0xef, 0x5c, 0xd0, 0x19, 0xb4, 0x7d, 0x5f, 0x79, 0xab, 0xa1, 0x97, 0xd3, 0x7e, 0x33, 0xbb, 0x86, 0x55, 0x60, 0x20, 0x10, 0x0d, 0x94, 0x2d, 0x11, 0x7c}, {0xcc, 0xab, 0xe0, 0xe8, 0x98, 0x65, 0x12, 0x96, 0x38, 0x5a, 0x1a, 0xf2, 0x85, 0x23, 0x59, 0x5f, 0xf9, 0xf3, 0xc2, 0x81, 0x70, 0x92, 0x65, 0x12, 0x9c, 0x65, 0x1e, 0x96, 0x00, 0xef, 0xe7, 0x63}}, {{0xac, 0x1e, 0x62, 0xc2, 0x59, 0xfc, 0x4e, 0x5c, 0x83, 0xb0, 0xd0, 0x6f, 0xce, 0x19, 0xf6, 0xbf, 0xa4, 0xb0, 0xe0, 0x53, 0x66, 0x1f, 0xbf, 0xc9, 0x33, 0x47, 0x37, 0xa9, 0x3d, 0x5d, 0xb0, 0x48}, {0x86, 0xb9, 0x2a, 0x7f, 0x8e, 0xa8, 0x60, 0x42, 0x26, 0x6d, 0x6e, 0x1c, 0xa2, 0xec, 0xe0, 0xe5, 0x3e, 0x0a, 0x33, 0xbb, 0x61, 0x4c, 0x9f, 0x3c, 0xd1, 0xdf, 0x49, 0x33, 0xcd, 0x72, 0x78, 0x18}}, {{0xf7, 0xd3, 0xcd, 0x49, 0x5c, 0x13, 0x22, 0xfb, 0x2e, 0xb2, 0x2f, 0x27, 0xf5, 0x8a, 0x5d, 0x74, 0xc1, 0x58, 0xc5, 0xc2, 0x2d, 0x9f, 0x52, 0xc6, 0x63, 0x9f, 0xba, 0x05, 0x76, 0x45, 0x7a, 0x63}, {0x8a, 0xfa, 0x55, 0x4d, 0xdd, 0xa3, 0xb2, 0xc3, 0x44, 0xfd, 0xec, 0x72, 0xde, 0xef, 0xc0, 0x99, 0xf5, 0x9f, 0xe2, 0x52, 0xb4, 0x05, 0x32, 0x58, 0x57, 0xc1, 0x8f, 0xea, 0xc3, 0x24, 0x5b, 0x94}}, {{0x05, 0x83, 0xee, 0xdd, 0x64, 0xf0, 0x14, 0x3b, 0xa0, 0x14, 0x4a, 0x3a, 0x41, 0x82, 0x7c, 0xa7, 0x2c, 0xaa, 0xb1, 0x76, 0xbb, 0x59, 0x64, 0x5f, 0x52, 0xad, 0x25, 0x29, 0x9d, 0x8f, 0x0b, 0xb0}, {0x7e, 0xe3, 0x7c, 0xca, 0xcd, 0x4f, 0xb0, 0x6d, 0x7a, 0xb2, 0x3e, 0xa0, 0x08, 0xb9, 0xa8, 0x2d, 0xc2, 0xf4, 0x99, 0x66, 0xcc, 0xac, 0xd8, 0xb9, 0x72, 0x2a, 0x4a, 0x3e, 0x0f, 0x7b, 0xbf, 0xf4}}, {{0x8c, 0x9c, 0x78, 0x2b, 0x39, 0x61, 0x7e, 0xf7, 0x65, 0x37, 0x66, 0x09, 0x38, 0xb9, 0x6f, 0x70, 0x78, 0x87, 0xff, 0xcf, 0x93, 0xca, 0x85, 0x06, 0x44, 0x84, 0xa7, 0xfe, 0xd3, 0xa4, 0xe3, 0x7e}, {0xa2, 0x56, 0x49, 0x23, 0x54, 0xa5, 0x50, 0xe9, 0x5f, 0xf0, 0x4d, 0xe7, 0xdc, 0x38, 0x32, 0x79, 0x4f, 0x1c, 0xb7, 0xe4, 0xbb, 0xf8, 0xbb, 0x2e, 0x40, 0x41, 0x4b, 0xcc, 0xe3, 0x1e, 0x16, 0x36}}, {{0x0c, 0x1e, 0xd7, 0x09, 0x25, 0x40, 0x97, 0xcb, 0x5c, 0x46, 0xa8, 0xda, 0xef, 0x25, 0xd5, 0xe5, 0x92, 0x4d, 0xcf, 0xa3, 0xc4, 0x5d, 0x35, 0x4a, 0xe4, 0x61, 0x92, 0xf3, 0xbf, 0x0e, 0xcd, 0xbe}, {0xe4, 0xaf, 0x0a, 0xb3, 0x30, 0x8b, 0x9b, 0x48, 0x49, 0x43, 0xc7, 0x64, 0x60, 0x4a, 0x2b, 0x9e, 0x95, 0x5f, 0x56, 0xe8, 0x35, 0xdc, 0xeb, 0xdc, 0xc7, 0xc4, 0xfe, 0x30, 0x40, 0xc7, 0xbf, 0xa4}}, {{0xd4, 0xa0, 0xf5, 0x81, 0x49, 0x6b, 0xb6, 0x8b, 0x0a, 0x69, 0xf9, 0xfe, 0xa8, 0x32, 0xe5, 0xe0, 0xa5, 0xcd, 0x02, 0x53, 0xf9, 0x2c, 0xe3, 0x53, 0x83, 0x36, 0xc6, 0x02, 0xb5, 0xeb, 0x64, 0xb8}, {0x1d, 0x42, 0xb9, 0xf9, 0xe9, 0xe3, 0x93, 0x2c, 0x4c, 0xee, 0x6c, 0x5a, 0x47, 0x9e, 0x62, 0x01, 0x6b, 0x04, 0xfe, 0xa4, 0x30, 0x2b, 0x0d, 0x4f, 0x71, 0x10, 0xd3, 0x55, 0xca, 0xf3, 0x5e, 0x80}}, {{0x77, 0x05, 0xf6, 0x0c, 0x15, 0x9b, 0x45, 0xe7, 0xb9, 0x11, 0xb8, 0xf5, 0xd6, 0xda, 0x73, 0x0c, 0xda, 0x92, 0xea, 0xd0, 0x9d, 0xd0, 0x18, 0x92, 0xce, 0x9a, 0xaa, 0xee, 0x0f, 0xef, 0xde, 0x30}, {0xf1, 0xf1, 0xd6, 0x9b, 0x51, 0xd7, 0x77, 0x62, 0x52, 0x10, 0xb8, 0x7a, 0x84, 0x9d, 0x15, 0x4e, 0x07, 0xdc, 0x1e, 0x75, 0x0d, 0x0c, 0x3b, 0xdb, 0x74, 0x58, 0x62, 0x02, 0x90, 0x54, 0x8b, 0x43}}, {{0xa6, 0xfe, 0x0b, 0x87, 0x80, 0x43, 0x67, 0x25, 0x57, 0x5d, 0xec, 0x40, 0x50, 0x08, 0xd5, 0x5d, 0x43, 0xd7, 0xe0, 0xaa, 0xe0, 0x13, 0xb6, 0xb0, 0xc0, 0xd4, 0xe5, 0x0d, 0x45, 0x83, 0xd6, 0x13}, {0x40, 0x45, 0x0a, 0x92, 0x31, 0xea, 0x8c, 0x60, 0x8c, 0x1f, 0xd8, 0x76, 0x45, 0xb9, 0x29, 0x00, 0x26, 0x32, 0xd8, 0xa6, 0x96, 0x88, 0xe2, 0xc4, 0x8b, 0xdb, 0x7f, 0x17, 0x87, 0xcc, 0xc8, 0xf2}}, {{0xc2, 0x56, 0xe2, 0xb6, 0x1a, 0x81, 0xe7, 0x31, 0x63, 0x2e, 0xbb, 0x0d, 0x2f, 0x81, 0x67, 0xd4, 0x22, 0xe2, 0x38, 0x02, 0x25, 0x97, 0xc7, 0x88, 0x6e, 0xdf, 0xbe, 0x2a, 0xa5, 0x73, 0x63, 0xaa}, {0x50, 0x45, 0xe2, 0xc3, 0xbd, 0x89, 0xfc, 0x57, 0xbd, 0x3c, 0xa3, 0x98, 0x7e, 0x7f, 0x36, 0x38, 0x92, 0x39, 0x1f, 0x0f, 0x81, 0x1a, 0x06, 0x51, 0x1f, 0x8d, 0x6a, 0xff, 0x47, 0x16, 0x06, 0x9c}}, {{0x33, 0x95, 0xa2, 0x6f, 0x27, 0x5f, 0x9c, 0x9c, 0x64, 0x45, 0xcb, 0xd1, 0x3c, 0xee, 0x5e, 0x5f, 0x48, 0xa6, 0xaf, 0xe3, 0x79, 0xcf, 0xb1, 0xe2, 0xbf, 0x55, 0x0e, 0xa2, 0x3b, 0x62, 0xf0, 0xe4}, {0x14, 0xe8, 0x06, 0xe3, 0xbe, 0x7e, 0x67, 0x01, 0xc5, 0x21, 0x67, 0xd8, 0x54, 0xb5, 0x7f, 0xa4, 0xf9, 0x75, 0x70, 0x1c, 0xfd, 0x79, 0xdb, 0x86, 0xad, 0x37, 0x85, 0x83, 0x56, 0x4e, 0xf0, 0xbf}}, {{0xbc, 0xa6, 0xe0, 0x56, 0x4e, 0xef, 0xfa, 0xf5, 0x1d, 0x5d, 0x3f, 0x2a, 0x5b, 0x19, 0xab, 0x51, 0xc5, 0x8b, 0xdd, 0x98, 0x28, 0x35, 0x2f, 0xc3, 0x81, 0x4f, 0x5c, 0xe5, 0x70, 0xb9, 0xeb, 0x62}, {0xc4, 0x6d, 0x26, 0xb0, 0x17, 0x6b, 0xfe, 0x6c, 0x12, 0xf8, 0xe7, 0xc1, 0xf5, 0x2f, 0xfa, 0x91, 0x13, 0x27, 0xbd, 0x73, 0xcc, 0x33, 0x31, 0x1c, 0x39, 0xe3, 0x27, 0x6a, 0x95, 0xcf, 0xc5, 0xfb}}, {{0x30, 0xb2, 0x99, 0x84, 0xf0, 0x18, 0x2a, 0x6e, 0x1e, 0x27, 0xed, 0xa2, 0x29, 0x99, 0x41, 0x56, 0xe8, 0xd4, 0x0d, 0xef, 0x99, 0x9c, 0xf3, 0x58, 0x29, 0x55, 0x1a, 0xc0, 0x68, 0xd6, 0x74, 0xa4}, {0x07, 0x9c, 0xe7, 0xec, 0xf5, 0x36, 0x73, 0x41, 0xa3, 0x1c, 0xe5, 0x93, 0x97, 0x6a, 0xfd, 0xf7, 0x53, 0x18, 0xab, 0xaf, 0xeb, 0x85, 0xbd, 0x92, 0x90, 0xab, 0x3c, 0xbf, 0x30, 0x82, 0xad, 0xf6}}, {{0xc6, 0x87, 0x8a, 0x2a, 0xea, 0xc0, 0xa9, 0xec, 0x6d, 0xd3, 0xdc, 0x32, 0x23, 0xce, 0x62, 0x19, 0xa4, 0x7e, 0xa8, 0xdd, 0x1c, 0x33, 0xae, 0xd3, 0x4f, 0x62, 0x9f, 0x52, 0xe7, 0x65, 0x46, 0xf4}, {0x97, 0x51, 0x27, 0x67, 0x2d, 0xa2, 0x82, 0x87, 0x98, 0xd3, 0xb6, 0x14, 0x7f, 0x51, 0xd3, 0x9a, 0x0b, 0xd0, 0x76, 0x81, 0xb2, 0x4f, 0x58, 0x92, 0xa4, 0x86, 0xa1, 0xa7, 0x09, 0x1d, 0xef, 0x9b}}, {{0xb3, 0x0f, 0x2b, 0x69, 0x0d, 0x06, 0x90, 0x64, 0xbd, 0x43, 0x4c, 0x10, 0xe8, 0x98, 0x1c, 0xa3, 0xe1, 0x68, 0xe9, 0x79, 0x6c, 0x29, 0x51, 0x3f, 0x41, 0xdc, 0xdf, 0x1f, 0xf3, 0x60, 0xbe, 0x33}, {0xa1, 0x5f, 0xf7, 0x1d, 0xb4, 0x3e, 0x9b, 0x3c, 0xe7, 0xbd, 0xb6, 0x06, 0xd5, 0x60, 0x06, 0x6d, 0x50, 0xd2, 0xf4, 0x1a, 0x31, 0x08, 0xf2, 0xea, 0x8e, 0xef, 0x5f, 0x7d, 0xb6, 0xd0, 0xc0, 0x27}}, {{0x62, 0x9a, 0xd9, 0xbb, 0x38, 0x36, 0xce, 0xf7, 0x5d, 0x2f, 0x13, 0xec, 0xc8, 0x2d, 0x02, 0x8a, 0x2e, 0x72, 0xf0, 0xe5, 0x15, 0x9d, 0x72, 0xae, 0xfc, 0xb3, 0x4f, 0x02, 0xea, 0xe1, 0x09, 0xfe}, {0x00, 0x00, 0x00, 0x00, 0xfa, 0x0a, 0x3d, 0xbc, 0xad, 0x16, 0x0c, 0xb6, 0xe7, 0x7c, 0x8b, 0x39, 0x9a, 0x43, 0xbb, 0xe3, 0xc2, 0x55, 0x15, 0x14, 0x75, 0xac, 0x90, 0x9b, 0x7f, 0x9a, 0x92, 0x00}}, {{0x8b, 0xac, 0x70, 0x86, 0x29, 0x8f, 0x00, 0x23, 0x7b, 0x45, 0x30, 0xaa, 0xb8, 0x4c, 0xc7, 0x8d, 0x4e, 0x47, 0x85, 0xc6, 0x19, 0xe3, 0x96, 0xc2, 0x9a, 0xa0, 0x12, 0xed, 0x6f, 0xd7, 0x76, 0x16}, {0x45, 0xaf, 0x7e, 0x33, 0xc7, 0x7f, 0x10, 0x6c, 0x7c, 0x9f, 0x29, 0xc1, 0xa8, 0x7e, 0x15, 0x84, 0xe7, 0x7d, 0xc0, 0x6d, 0xab, 0x71, 0x5d, 0xd0, 0x6b, 0x9f, 0x97, 0xab, 0xcb, 0x51, 0x0c, 0x9f}}, {{0x9e, 0xc3, 0x92, 0xb4, 0x04, 0x9f, 0xc8, 0xbb, 0xdd, 0x9e, 0xc6, 0x05, 0xfd, 0x65, 0xec, 0x94, 0x7f, 0x2c, 0x16, 0xc4, 0x40, 0xac, 0x63, 0x7b, 0x7d, 0xb8, 0x0c, 0xe4, 0x5b, 0xe3, 0xa7, 0x0e}, {0x43, 0xf4, 0x44, 0xe8, 0xcc, 0xc8, 0xd4, 0x54, 0x33, 0x37, 0x50, 0xf2, 0x87, 0x42, 0x2e, 0x00, 0x49, 0x60, 0x62, 0x02, 0xfd, 0x1a, 0x7c, 0xdb, 0x29, 0x6c, 0x6d, 0x54, 0x53, 0x08, 0xd1, 0xc8}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, {{0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}, {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, {{0x28, 0x56, 0xac, 0x0e, 0x4f, 0x98, 0x09, 0xf0, 0x49, 0xfa, 0x7f, 0x84, 0xac, 0x7e, 0x50, 0x5b, 0x17, 0x43, 0x14, 0x89, 0x9c, 0x53, 0xa8, 0x94, 0x30, 0xf2, 0x11, 0x4d, 0x92, 0x14, 0x27, 0xe8}, {0x39, 0x7a, 0x84, 0x56, 0x79, 0x9d, 0xec, 0x26, 0x2c, 0x53, 0xc1, 0x94, 0xc9, 0x8d, 0x9e, 0x9d, 0x32, 0x1f, 0xdd, 0x84, 0x04, 0xe8, 0xe2, 0x0a, 0x6b, 0xbe, 0xbb, 0x42, 0x40, 0x67, 0x30, 0x6c}}, {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, 0x40, 0x2d, 0xa1, 0x73, 0x2f, 0xc9, 0xbe, 0xbd}, {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, {{0x1c, 0xc4, 0xf7, 0xda, 0x0f, 0x65, 0xca, 0x39, 0x70, 0x52, 0x92, 0x8e, 0xc3, 0xc8, 0x15, 0xea, 0x7f, 0x10, 0x9e, 0x77, 0x4b, 0x6e, 0x2d, 0xdf, 0xe8, 0x30, 0x9d, 0xda, 0xe8, 0x9a, 0x65, 0xae}, {0x02, 0xb0, 0x16, 0xb1, 0x1d, 0xc8, 0x57, 0x7b, 0xa2, 0x3a, 0xa2, 0xa3, 0x38, 0x5c, 0x8f, 0xeb, 0x66, 0x37, 0x91, 0xa8, 0x5f, 0xef, 0x04, 0xf6, 0x59, 0x75, 0xe1, 0xee, 0x92, 0xf6, 0x0e, 0x30}}, {{0x8d, 0x76, 0x14, 0xa4, 0x14, 0x06, 0x9f, 0x9a, 0xdf, 0x4a, 0x85, 0xa7, 0x6b, 0xbf, 0x29, 0x6f, 0xbc, 0x34, 0x87, 0x5d, 0xeb, 0xbb, 0x2e, 0xa9, 0xc9, 0x1f, 0x58, 0xd6, 0x9a, 0x82, 0xa0, 0x56}, {0xd4, 0xb9, 0xdb, 0x88, 0x1d, 0x04, 0xe9, 0x93, 0x8d, 0x3f, 0x20, 0xd5, 0x86, 0xa8, 0x83, 0x07, 0xdb, 0x09, 0xd8, 0x22, 0x1f, 0x7f, 0xf1, 0x71, 0xc8, 0xe7, 0x5d, 0x47, 0xaf, 0x8b, 0x72, 0xe9}}, {{0x83, 0xb9, 0x39, 0xb2, 0xa4, 0xdf, 0x46, 0x87, 0xc2, 0xb8, 0xf1, 0xe6, 0x4c, 0xd1, 0xe2, 0xa9, 0xe4, 0x70, 0x30, 0x34, 0xbc, 0x52, 0x7c, 0x55, 0xa6, 0xec, 0x80, 0xa4, 0xe5, 0xd2, 0xdc, 0x73}, {0x08, 0xf1, 0x03, 0xcf, 0x16, 0x73, 0xe8, 0x7d, 0xb6, 0x7e, 0x9b, 0xc0, 0xb4, 0xc2, 0xa5, 0x86, 0x02, 0x77, 0xd5, 0x27, 0x86, 0xa5, 0x15, 0xfb, 0xae, 0x9b, 0x8c, 0xa9, 0xf9, 0xf8, 0xa8, 0x4a}}, {{0x8b, 0x00, 0x49, 0xdb, 0xfa, 0xf0, 0x1b, 0xa2, 0xed, 0x8a, 0x9a, 0x7a, 0x36, 0x78, 0x4a, 0xc7, 0xf7, 0xad, 0x39, 0xd0, 0x6c, 0x65, 0x7a, 0x41, 0xce, 0xd6, 0xd6, 0x4c, 0x20, 0x21, 0x6b, 0xc7}, {0xc6, 0xca, 0x78, 0x1d, 0x32, 0x6c, 0x6c, 0x06, 0x91, 0xf2, 0x1a, 0xe8, 0x43, 0x16, 0xea, 0x04, 0x3c, 0x1f, 0x07, 0x85, 0xf7, 0x09, 0x22, 0x08, 0xba, 0x13, 0xfd, 0x78, 0x1e, 0x3f, 0x6f, 0x62}}, {{0x25, 0x9b, 0x7c, 0xb0, 0xac, 0x72, 0x6f, 0xb2, 0xe3, 0x53, 0x84, 0x7a, 0x1a, 0x9a, 0x98, 0x9b, 0x44, 0xd3, 0x59, 0xd0, 0x8e, 0x57, 0x41, 0x40, 0x78, 0xa7, 0x30, 0x2f, 0x4c, 0x9c, 0xb9, 0x68}, {0xb7, 0x75, 0x03, 0x63, 0x61, 0xc2, 0x48, 0x6e, 0x12, 0x3d, 0xbf, 0x4b, 0x27, 0xdf, 0xb1, 0x7a, 0xff, 0x4e, 0x31, 0x07, 0x83, 0xf4, 0x62, 0x5b, 0x19, 0xa5, 0xac, 0xa0, 0x32, 0x58, 0x0d, 0xa7}}, {{0x43, 0x4f, 0x10, 0xa4, 0xca, 0xdb, 0x38, 0x67, 0xfa, 0xae, 0x96, 0xb5, 0x6d, 0x97, 0xff, 0x1f, 0xb6, 0x83, 0x43, 0xd3, 0xa0, 0x2d, 0x70, 0x7a, 0x64, 0x05, 0x4c, 0xa7, 0xc1, 0xa5, 0x21, 0x51}, {0xe4, 0xf1, 0x23, 0x84, 0xe1, 0xb5, 0x9d, 0xf2, 0xb8, 0x73, 0x8b, 0x45, 0x2b, 0x35, 0x46, 0x38, 0x10, 0x2b, 0x50, 0xf8, 0x8b, 0x35, 0xcd, 0x34, 0xc8, 0x0e, 0xf6, 0xdb, 0x09, 0x35, 0xf0, 0xda}}, {{0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}, {0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} }; secp256k1_scalar_set_int(&one, 1); for (i = 0; i < 33; i++) { secp256k1_scalar_set_b32(&x, chal[i][0], &overflow); CHECK(!overflow); secp256k1_scalar_set_b32(&y, chal[i][1], &overflow); CHECK(!overflow); secp256k1_scalar_set_b32(&r1, res[i][0], &overflow); CHECK(!overflow); secp256k1_scalar_set_b32(&r2, res[i][1], &overflow); CHECK(!overflow); secp256k1_scalar_mul(&z, &x, &y); CHECK(!secp256k1_scalar_check_overflow(&z)); CHECK(secp256k1_scalar_eq(&r1, &z)); if (!secp256k1_scalar_is_zero(&y)) { secp256k1_scalar_inverse(&zz, &y); CHECK(!secp256k1_scalar_check_overflow(&zz)); #if defined(USE_SCALAR_INV_NUM) secp256k1_scalar_inverse_var(&zzv, &y); CHECK(secp256k1_scalar_eq(&zzv, &zz)); #endif secp256k1_scalar_mul(&z, &z, &zz); CHECK(!secp256k1_scalar_check_overflow(&z)); CHECK(secp256k1_scalar_eq(&x, &z)); secp256k1_scalar_mul(&zz, &zz, &y); CHECK(!secp256k1_scalar_check_overflow(&zz)); CHECK(secp256k1_scalar_eq(&one, &zz)); } secp256k1_scalar_mul(&z, &x, &x); CHECK(!secp256k1_scalar_check_overflow(&z)); secp256k1_scalar_sqr(&zz, &x); CHECK(!secp256k1_scalar_check_overflow(&zz)); CHECK(secp256k1_scalar_eq(&zz, &z)); CHECK(secp256k1_scalar_eq(&r2, &zz)); } } } /***** FIELD TESTS *****/ void random_fe(secp256k1_fe *x) { unsigned char bin[32]; do { secp256k1_rand256(bin); if (secp256k1_fe_set_b32(x, bin)) { return; } } while(1); } void random_fe_test(secp256k1_fe *x) { unsigned char bin[32]; do { secp256k1_rand256_test(bin); if (secp256k1_fe_set_b32(x, bin)) { return; } } while(1); } void random_fe_non_zero(secp256k1_fe *nz) { int tries = 10; while (--tries >= 0) { random_fe(nz); secp256k1_fe_normalize(nz); if (!secp256k1_fe_is_zero(nz)) { break; } } /* Infinitesimal probability of spurious failure here */ CHECK(tries >= 0); } void random_fe_non_square(secp256k1_fe *ns) { secp256k1_fe r; random_fe_non_zero(ns); if (secp256k1_fe_sqrt(&r, ns)) { secp256k1_fe_negate(ns, ns, 1); } } int check_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { secp256k1_fe an = *a; secp256k1_fe bn = *b; secp256k1_fe_normalize_weak(&an); secp256k1_fe_normalize_var(&bn); return secp256k1_fe_equal_var(&an, &bn); } int check_fe_inverse(const secp256k1_fe *a, const secp256k1_fe *ai) { secp256k1_fe x; secp256k1_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); secp256k1_fe_mul(&x, a, ai); return check_fe_equal(&x, &one); } void run_field_convert(void) { static const unsigned char b32[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40 }; static const secp256k1_fe_storage fes = SECP256K1_FE_STORAGE_CONST( 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL ); static const secp256k1_fe fe = SECP256K1_FE_CONST( 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL ); secp256k1_fe fe2; unsigned char b322[32]; secp256k1_fe_storage fes2; /* Check conversions to fe. */ CHECK(secp256k1_fe_set_b32(&fe2, b32)); CHECK(secp256k1_fe_equal_var(&fe, &fe2)); secp256k1_fe_from_storage(&fe2, &fes); CHECK(secp256k1_fe_equal_var(&fe, &fe2)); /* Check conversion from fe. */ secp256k1_fe_get_b32(b322, &fe); CHECK(memcmp(b322, b32, 32) == 0); secp256k1_fe_to_storage(&fes2, &fe); CHECK(memcmp(&fes2, &fes, sizeof(fes)) == 0); } int fe_memcmp(const secp256k1_fe *a, const secp256k1_fe *b) { secp256k1_fe t = *b; #ifdef VERIFY t.magnitude = a->magnitude; t.normalized = a->normalized; #endif return memcmp(a, &t, sizeof(secp256k1_fe)); } void run_field_misc(void) { secp256k1_fe x; secp256k1_fe y; secp256k1_fe z; secp256k1_fe q; secp256k1_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); int i, j; for (i = 0; i < 5*count; i++) { secp256k1_fe_storage xs, ys, zs; random_fe(&x); random_fe_non_zero(&y); /* Test the fe equality and comparison operations. */ CHECK(secp256k1_fe_cmp_var(&x, &x) == 0); CHECK(secp256k1_fe_equal_var(&x, &x)); z = x; secp256k1_fe_add(&z,&y); /* Test fe conditional move; z is not normalized here. */ q = x; secp256k1_fe_cmov(&x, &z, 0); VERIFY_CHECK(!x.normalized && x.magnitude == z.magnitude); secp256k1_fe_cmov(&x, &x, 1); CHECK(fe_memcmp(&x, &z) != 0); CHECK(fe_memcmp(&x, &q) == 0); secp256k1_fe_cmov(&q, &z, 1); VERIFY_CHECK(!q.normalized && q.magnitude == z.magnitude); CHECK(fe_memcmp(&q, &z) == 0); secp256k1_fe_normalize_var(&x); secp256k1_fe_normalize_var(&z); CHECK(!secp256k1_fe_equal_var(&x, &z)); secp256k1_fe_normalize_var(&q); secp256k1_fe_cmov(&q, &z, (i&1)); VERIFY_CHECK(q.normalized && q.magnitude == 1); for (j = 0; j < 6; j++) { secp256k1_fe_negate(&z, &z, j+1); secp256k1_fe_normalize_var(&q); secp256k1_fe_cmov(&q, &z, (j&1)); VERIFY_CHECK(!q.normalized && q.magnitude == (j+2)); } secp256k1_fe_normalize_var(&z); /* Test storage conversion and conditional moves. */ secp256k1_fe_to_storage(&xs, &x); secp256k1_fe_to_storage(&ys, &y); secp256k1_fe_to_storage(&zs, &z); secp256k1_fe_storage_cmov(&zs, &xs, 0); secp256k1_fe_storage_cmov(&zs, &zs, 1); CHECK(memcmp(&xs, &zs, sizeof(xs)) != 0); secp256k1_fe_storage_cmov(&ys, &xs, 1); CHECK(memcmp(&xs, &ys, sizeof(xs)) == 0); secp256k1_fe_from_storage(&x, &xs); secp256k1_fe_from_storage(&y, &ys); secp256k1_fe_from_storage(&z, &zs); /* Test that mul_int, mul, and add agree. */ secp256k1_fe_add(&y, &x); secp256k1_fe_add(&y, &x); z = x; secp256k1_fe_mul_int(&z, 3); CHECK(check_fe_equal(&y, &z)); secp256k1_fe_add(&y, &x); secp256k1_fe_add(&z, &x); CHECK(check_fe_equal(&z, &y)); z = x; secp256k1_fe_mul_int(&z, 5); secp256k1_fe_mul(&q, &x, &fe5); CHECK(check_fe_equal(&z, &q)); secp256k1_fe_negate(&x, &x, 1); secp256k1_fe_add(&z, &x); secp256k1_fe_add(&q, &x); CHECK(check_fe_equal(&y, &z)); CHECK(check_fe_equal(&q, &y)); } } void run_field_inv(void) { secp256k1_fe x, xi, xii; int i; for (i = 0; i < 10*count; i++) { random_fe_non_zero(&x); secp256k1_fe_inv(&xi, &x); CHECK(check_fe_inverse(&x, &xi)); secp256k1_fe_inv(&xii, &xi); CHECK(check_fe_equal(&x, &xii)); } } void run_field_inv_var(void) { secp256k1_fe x, xi, xii; int i; for (i = 0; i < 10*count; i++) { random_fe_non_zero(&x); secp256k1_fe_inv_var(&xi, &x); CHECK(check_fe_inverse(&x, &xi)); secp256k1_fe_inv_var(&xii, &xi); CHECK(check_fe_equal(&x, &xii)); } } void run_field_inv_all_var(void) { secp256k1_fe x[16], xi[16], xii[16]; int i; /* Check it's safe to call for 0 elements */ secp256k1_fe_inv_all_var(xi, x, 0); for (i = 0; i < count; i++) { size_t j; size_t len = secp256k1_rand_int(15) + 1; for (j = 0; j < len; j++) { random_fe_non_zero(&x[j]); } secp256k1_fe_inv_all_var(xi, x, len); for (j = 0; j < len; j++) { CHECK(check_fe_inverse(&x[j], &xi[j])); } secp256k1_fe_inv_all_var(xii, xi, len); for (j = 0; j < len; j++) { CHECK(check_fe_equal(&x[j], &xii[j])); } } } void run_sqr(void) { secp256k1_fe x, s; { int i; secp256k1_fe_set_int(&x, 1); secp256k1_fe_negate(&x, &x, 1); for (i = 1; i <= 512; ++i) { secp256k1_fe_mul_int(&x, 2); secp256k1_fe_normalize(&x); secp256k1_fe_sqr(&s, &x); } } } void test_sqrt(const secp256k1_fe *a, const secp256k1_fe *k) { secp256k1_fe r1, r2; int v = secp256k1_fe_sqrt(&r1, a); CHECK((v == 0) == (k == NULL)); if (k != NULL) { /* Check that the returned root is +/- the given known answer */ secp256k1_fe_negate(&r2, &r1, 1); secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k); secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2); CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2)); } } void run_sqrt(void) { secp256k1_fe ns, x, s, t; int i; /* Check sqrt(0) is 0 */ secp256k1_fe_set_int(&x, 0); secp256k1_fe_sqr(&s, &x); test_sqrt(&s, &x); /* Check sqrt of small squares (and their negatives) */ for (i = 1; i <= 100; i++) { secp256k1_fe_set_int(&x, i); secp256k1_fe_sqr(&s, &x); test_sqrt(&s, &x); secp256k1_fe_negate(&t, &s, 1); test_sqrt(&t, NULL); } /* Consistency checks for large random values */ for (i = 0; i < 10; i++) { int j; random_fe_non_square(&ns); for (j = 0; j < count; j++) { random_fe(&x); secp256k1_fe_sqr(&s, &x); test_sqrt(&s, &x); secp256k1_fe_negate(&t, &s, 1); test_sqrt(&t, NULL); secp256k1_fe_mul(&t, &s, &ns); test_sqrt(&t, NULL); } } } /***** GROUP TESTS *****/ void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { CHECK(a->infinity == b->infinity); if (a->infinity) { return; } CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); } /* This compares jacobian points including their Z, not just their geometric meaning. */ int gej_xyz_equals_gej(const secp256k1_gej *a, const secp256k1_gej *b) { secp256k1_gej a2; secp256k1_gej b2; int ret = 1; ret &= a->infinity == b->infinity; if (ret && !a->infinity) { a2 = *a; b2 = *b; secp256k1_fe_normalize(&a2.x); secp256k1_fe_normalize(&a2.y); secp256k1_fe_normalize(&a2.z); secp256k1_fe_normalize(&b2.x); secp256k1_fe_normalize(&b2.y); secp256k1_fe_normalize(&b2.z); ret &= secp256k1_fe_cmp_var(&a2.x, &b2.x) == 0; ret &= secp256k1_fe_cmp_var(&a2.y, &b2.y) == 0; ret &= secp256k1_fe_cmp_var(&a2.z, &b2.z) == 0; } return ret; } void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { secp256k1_fe z2s; secp256k1_fe u1, u2, s1, s2; CHECK(a->infinity == b->infinity); if (a->infinity) { return; } /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ secp256k1_fe_sqr(&z2s, &b->z); secp256k1_fe_mul(&u1, &a->x, &z2s); u2 = b->x; secp256k1_fe_normalize_weak(&u2); secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); s2 = b->y; secp256k1_fe_normalize_weak(&s2); CHECK(secp256k1_fe_equal_var(&u1, &u2)); CHECK(secp256k1_fe_equal_var(&s1, &s2)); } void test_ge(void) { int i, i1; #ifdef USE_ENDOMORPHISM int runs = 6; #else int runs = 4; #endif /* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4). * The second in each pair of identical points uses a random Z coordinate in the Jacobian form. * All magnitudes are randomized. * All 17*17 combinations of points are added to each other, using all applicable methods. * * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. */ secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); secp256k1_fe *zinv = (secp256k1_fe *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs)); secp256k1_fe zf; secp256k1_fe zfi2, zfi3; secp256k1_gej_set_infinity(&gej[0]); secp256k1_ge_clear(&ge[0]); secp256k1_ge_set_gej_var(&ge[0], &gej[0]); for (i = 0; i < runs; i++) { int j; secp256k1_ge g; random_group_element_test(&g); #ifdef USE_ENDOMORPHISM if (i >= runs - 2) { secp256k1_ge_mul_lambda(&g, &ge[1]); } if (i >= runs - 1) { secp256k1_ge_mul_lambda(&g, &g); } #endif ge[1 + 4 * i] = g; ge[2 + 4 * i] = g; secp256k1_ge_neg(&ge[3 + 4 * i], &g); secp256k1_ge_neg(&ge[4 + 4 * i], &g); secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); for (j = 0; j < 4; j++) { random_field_element_magnitude(&ge[1 + j + 4 * i].x); random_field_element_magnitude(&ge[1 + j + 4 * i].y); random_field_element_magnitude(&gej[1 + j + 4 * i].x); random_field_element_magnitude(&gej[1 + j + 4 * i].y); random_field_element_magnitude(&gej[1 + j + 4 * i].z); } } /* Compute z inverses. */ { secp256k1_fe *zs = checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs)); for (i = 0; i < 4 * runs + 1; i++) { if (i == 0) { /* The point at infinity does not have a meaningful z inverse. Any should do. */ do { random_field_element_test(&zs[i]); } while(secp256k1_fe_is_zero(&zs[i])); } else { zs[i] = gej[i].z; } } secp256k1_fe_inv_all_var(zinv, zs, 4 * runs + 1); free(zs); } /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ do { random_field_element_test(&zf); } while(secp256k1_fe_is_zero(&zf)); random_field_element_magnitude(&zf); secp256k1_fe_inv_var(&zfi3, &zf); secp256k1_fe_sqr(&zfi2, &zfi3); secp256k1_fe_mul(&zfi3, &zfi3, &zfi2); for (i1 = 0; i1 < 1 + 4 * runs; i1++) { int i2; for (i2 = 0; i2 < 1 + 4 * runs; i2++) { /* Compute reference result using gej + gej (var). */ secp256k1_gej refj, resj; secp256k1_ge ref; secp256k1_fe zr; secp256k1_gej_add_var(&refj, &gej[i1], &gej[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); /* Check Z ratio. */ if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&refj)) { secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); CHECK(secp256k1_fe_equal_var(&zrz, &refj.z)); } secp256k1_ge_set_gej_var(&ref, &refj); /* Test gej + ge with Z ratio result (var). */ secp256k1_gej_add_ge_var(&resj, &gej[i1], &ge[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); ge_equals_gej(&ref, &resj); if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&resj)) { secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); CHECK(secp256k1_fe_equal_var(&zrz, &resj.z)); } /* Test gej + ge (var, with additional Z factor). */ { secp256k1_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ secp256k1_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); secp256k1_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); random_field_element_magnitude(&ge2_zfi.x); random_field_element_magnitude(&ge2_zfi.y); secp256k1_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); ge_equals_gej(&ref, &resj); } /* Test gej + ge (const). */ if (i2 != 0) { /* secp256k1_gej_add_ge does not support its second argument being infinity. */ secp256k1_gej_add_ge(&resj, &gej[i1], &ge[i2]); ge_equals_gej(&ref, &resj); } /* Test doubling (var). */ if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 == ((i2 + 3)%4)/2)) { secp256k1_fe zr2; /* Normal doubling with Z ratio result. */ secp256k1_gej_double_var(&resj, &gej[i1], &zr2); ge_equals_gej(&ref, &resj); /* Check Z ratio. */ secp256k1_fe_mul(&zr2, &zr2, &gej[i1].z); CHECK(secp256k1_fe_equal_var(&zr2, &resj.z)); /* Normal doubling. */ secp256k1_gej_double_var(&resj, &gej[i2], NULL); ge_equals_gej(&ref, &resj); } /* Test adding opposites. */ if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) { CHECK(secp256k1_ge_is_infinity(&ref)); } /* Test adding infinity. */ if (i1 == 0) { CHECK(secp256k1_ge_is_infinity(&ge[i1])); CHECK(secp256k1_gej_is_infinity(&gej[i1])); ge_equals_gej(&ref, &gej[i2]); } if (i2 == 0) { CHECK(secp256k1_ge_is_infinity(&ge[i2])); CHECK(secp256k1_gej_is_infinity(&gej[i2])); ge_equals_gej(&ref, &gej[i1]); } } } /* Test adding all points together in random order equals infinity. */ { secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; 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++) { gej_shuffled[i] = gej[i]; } for (i = 0; i < 4 * runs + 1; i++) { int swap = i + secp256k1_rand_int(4 * runs + 1 - i); if (swap != i) { secp256k1_gej t = gej_shuffled[i]; gej_shuffled[i] = gej_shuffled[swap]; gej_shuffled[swap] = t; } } for (i = 0; i < 4 * runs + 1; i++) { secp256k1_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); } CHECK(secp256k1_gej_is_infinity(&sum)); free(gej_shuffled); } /* Test batch gej -> ge conversion with and without known z ratios. */ { secp256k1_fe *zr = (secp256k1_fe *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_fe)); 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 *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); for (i = 0; i < 4 * runs + 1; i++) { /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ if (i < 4 * runs) { secp256k1_fe_mul(&zr[i + 1], &zinv[i], &gej[i + 1].z); } } secp256k1_ge_set_table_gej_var(ge_set_table, gej, zr, 4 * runs + 1); secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1, &ctx->error_callback); for (i = 0; i < 4 * runs + 1; i++) { secp256k1_fe s; random_fe_non_zero(&s); secp256k1_gej_rescale(&gej[i], &s); ge_equals_gej(&ge_set_table[i], &gej[i]); ge_equals_gej(&ge_set_all[i], &gej[i]); } free(ge_set_table); free(ge_set_all); free(zr); } free(ge); free(gej); free(zinv); } void test_add_neg_y_diff_x(void) { /* The point of this test is to check that we can add two points * whose y-coordinates are negatives of each other but whose x * coordinates differ. If the x-coordinates were the same, these * points would be negatives of each other and their sum is * infinity. This is cool because it "covers up" any degeneracy * in the addition algorithm that would cause the xy coordinates * of the sum to be wrong (since infinity has no xy coordinates). * HOWEVER, if the x-coordinates are different, infinity is the * wrong answer, and such degeneracies are exposed. This is the * root of https://github.com/bitcoin-core/secp256k1/issues/257 * which this test is a regression test for. * * These points were generated in sage as * # secp256k1 params * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) * C = EllipticCurve ([F (0), F (7)]) * G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) * N = FiniteField(G.order()) * * # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F) * x = polygen(N) * lam = (1 - x^3).roots()[1][0] * * # random "bad pair" * P = C.random_element() * Q = -int(lam) * P * print " P: %x %x" % P.xy() * print " Q: %x %x" % Q.xy() * print "P + Q: %x %x" % (P + Q).xy() */ secp256k1_gej aj = SECP256K1_GEJ_CONST( 0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30, 0x0643d79f, 0x05a59614, 0x2f8ec030, 0xd58977cb, 0x001e337a, 0x38093dcd, 0x6c0f386d, 0x0b1293a8, 0x4d72c879, 0xd7681924, 0x44e6d2f3, 0x9190117d ); secp256k1_gej bj = SECP256K1_GEJ_CONST( 0xc7b74206, 0x1f788cd9, 0xabd0937d, 0x164a0d86, 0x95f6ff75, 0xf19a4ce9, 0xd013bd7b, 0xbf92d2a7, 0xffe1cc85, 0xc7f6c232, 0x93f0c792, 0xf4ed6c57, 0xb28d3786, 0x2897e6db, 0xbb192d0b, 0x6e6feab2 ); secp256k1_gej sumj = SECP256K1_GEJ_CONST( 0x671a63c0, 0x3efdad4c, 0x389a7798, 0x24356027, 0xb3d69010, 0x278625c3, 0x5c86d390, 0x184a8f7a, 0x5f6409c2, 0x2ce01f2b, 0x511fd375, 0x25071d08, 0xda651801, 0x70e95caf, 0x8f0d893c, 0xbed8fbbe ); secp256k1_ge b; secp256k1_gej resj; secp256k1_ge res; secp256k1_ge_set_gej(&b, &bj); secp256k1_gej_add_var(&resj, &aj, &bj, NULL); secp256k1_ge_set_gej(&res, &resj); ge_equals_gej(&res, &sumj); secp256k1_gej_add_ge(&resj, &aj, &b); secp256k1_ge_set_gej(&res, &resj); ge_equals_gej(&res, &sumj); secp256k1_gej_add_ge_var(&resj, &aj, &b, NULL); secp256k1_ge_set_gej(&res, &resj); ge_equals_gej(&res, &sumj); } void run_ge(void) { int i; for (i = 0; i < count * 32; i++) { test_ge(); } test_add_neg_y_diff_x(); } void test_ec_combine(void) { secp256k1_scalar sum = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); secp256k1_pubkey data[6]; const secp256k1_pubkey* d[6]; secp256k1_pubkey sd; secp256k1_pubkey sd2; secp256k1_gej Qj; secp256k1_ge Q; int i; for (i = 1; i <= 6; i++) { secp256k1_scalar s; random_scalar_order_test(&s); secp256k1_scalar_add(&sum, &sum, &s); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &s); secp256k1_ge_set_gej(&Q, &Qj); secp256k1_pubkey_save(&data[i - 1], &Q); d[i - 1] = &data[i - 1]; secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sum); secp256k1_ge_set_gej(&Q, &Qj); secp256k1_pubkey_save(&sd, &Q); CHECK(secp256k1_ec_pubkey_combine(ctx, &sd2, d, i) == 1); CHECK(memcmp(&sd, &sd2, sizeof(sd)) == 0); } } void run_ec_combine(void) { int i; for (i = 0; i < count * 8; i++) { test_ec_combine(); } } void test_group_decompress(const secp256k1_fe* x) { /* The input itself, normalized. */ secp256k1_fe fex = *x; secp256k1_fe fez; /* Results of set_xquad_var, set_xo_var(..., 0), set_xo_var(..., 1). */ secp256k1_ge ge_quad, ge_even, ge_odd; secp256k1_gej gej_quad; /* Return values of the above calls. */ int res_quad, res_even, res_odd; secp256k1_fe_normalize_var(&fex); res_quad = secp256k1_ge_set_xquad(&ge_quad, &fex); res_even = secp256k1_ge_set_xo_var(&ge_even, &fex, 0); res_odd = secp256k1_ge_set_xo_var(&ge_odd, &fex, 1); CHECK(res_quad == res_even); CHECK(res_quad == res_odd); if (res_quad) { secp256k1_fe_normalize_var(&ge_quad.x); secp256k1_fe_normalize_var(&ge_odd.x); secp256k1_fe_normalize_var(&ge_even.x); secp256k1_fe_normalize_var(&ge_quad.y); secp256k1_fe_normalize_var(&ge_odd.y); secp256k1_fe_normalize_var(&ge_even.y); /* No infinity allowed. */ CHECK(!ge_quad.infinity); CHECK(!ge_even.infinity); CHECK(!ge_odd.infinity); /* Check that the x coordinates check out. */ CHECK(secp256k1_fe_equal_var(&ge_quad.x, x)); CHECK(secp256k1_fe_equal_var(&ge_even.x, x)); CHECK(secp256k1_fe_equal_var(&ge_odd.x, x)); /* Check that the Y coordinate result in ge_quad is a square. */ CHECK(secp256k1_fe_is_quad_var(&ge_quad.y)); /* Check odd/even Y in ge_odd, ge_even. */ CHECK(secp256k1_fe_is_odd(&ge_odd.y)); CHECK(!secp256k1_fe_is_odd(&ge_even.y)); /* Check secp256k1_gej_has_quad_y_var. */ secp256k1_gej_set_ge(&gej_quad, &ge_quad); CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); do { random_fe_test(&fez); } while (secp256k1_fe_is_zero(&fez)); secp256k1_gej_rescale(&gej_quad, &fez); CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); secp256k1_gej_neg(&gej_quad, &gej_quad); CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); do { random_fe_test(&fez); } while (secp256k1_fe_is_zero(&fez)); secp256k1_gej_rescale(&gej_quad, &fez); CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); secp256k1_gej_neg(&gej_quad, &gej_quad); CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); } } void run_group_decompress(void) { int i; for (i = 0; i < count * 4; i++) { secp256k1_fe fe; random_fe_test(&fe); test_group_decompress(&fe); } } /***** ECMULT TESTS *****/ void run_ecmult_chain(void) { /* random starting point A (on the curve) */ secp256k1_gej a = SECP256K1_GEJ_CONST( 0x8b30bbe9, 0xae2a9906, 0x96b22f67, 0x0709dff3, 0x727fd8bc, 0x04d3362c, 0x6c7bf458, 0xe2846004, 0xa357ae91, 0x5c4a6528, 0x1309edf2, 0x0504740f, 0x0eb33439, 0x90216b4f, 0x81063cb6, 0x5f2f7e0f ); /* two random initial factors xn and gn */ secp256k1_scalar xn = SECP256K1_SCALAR_CONST( 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c, 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407 ); secp256k1_scalar gn = SECP256K1_SCALAR_CONST( 0xa1e58d22, 0x553dcd42, 0xb2398062, 0x5d4c57a9, 0x6e9323d4, 0x2b3152e5, 0xca2c3990, 0xedc7c9de ); /* two small multipliers to be applied to xn and gn in every iteration: */ static const secp256k1_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); static const secp256k1_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); /* accumulators with the resulting coefficients to A and G */ secp256k1_scalar ae = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); secp256k1_scalar ge = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); /* actual points */ secp256k1_gej x; secp256k1_gej x2; int i; /* the point being computed */ x = a; for (i = 0; i < 200*count; i++) { /* in each iteration, compute X = xn*X + gn*G; */ secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn); /* also compute ae and ge: the actual accumulated factors for A and G */ /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ secp256k1_scalar_mul(&ae, &ae, &xn); secp256k1_scalar_mul(&ge, &ge, &xn); secp256k1_scalar_add(&ge, &ge, &gn); /* modify xn and gn */ secp256k1_scalar_mul(&xn, &xn, &xf); secp256k1_scalar_mul(&gn, &gn, &gf); /* verify */ if (i == 19999) { /* expected result after 19999 iterations */ secp256k1_gej rp = SECP256K1_GEJ_CONST( 0xD6E96687, 0xF9B10D09, 0x2A6F3543, 0x9D86CEBE, 0xA4535D0D, 0x409F5358, 0x6440BD74, 0xB933E830, 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D, 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88 ); secp256k1_gej_neg(&rp, &rp); secp256k1_gej_add_var(&rp, &rp, &x, NULL); CHECK(secp256k1_gej_is_infinity(&rp)); } } /* redo the computation, but directly with the resulting ae and ge coefficients: */ secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge); secp256k1_gej_neg(&x2, &x2); secp256k1_gej_add_var(&x2, &x2, &x, NULL); CHECK(secp256k1_gej_is_infinity(&x2)); } void test_point_times_order(const secp256k1_gej *point) { /* X * (point + G) + (order-X) * (pointer + G) = 0 */ secp256k1_scalar x; secp256k1_scalar nx; secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); secp256k1_gej res1, res2; secp256k1_ge res3; unsigned char pub[65]; size_t psize = 65; random_scalar_order_test(&x); secp256k1_scalar_negate(&nx, &x); secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */ secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ secp256k1_gej_add_var(&res1, &res1, &res2, NULL); CHECK(secp256k1_gej_is_infinity(&res1)); CHECK(secp256k1_gej_is_valid_var(&res1) == 0); secp256k1_ge_set_gej(&res3, &res1); CHECK(secp256k1_ge_is_infinity(&res3)); CHECK(secp256k1_ge_is_valid_var(&res3) == 0); CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); psize = 65; CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); /* check zero/one edge cases */ secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero); secp256k1_ge_set_gej(&res3, &res1); CHECK(secp256k1_ge_is_infinity(&res3)); secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero); secp256k1_ge_set_gej(&res3, &res1); ge_equals_gej(&res3, point); secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one); secp256k1_ge_set_gej(&res3, &res1); ge_equals_ge(&res3, &secp256k1_ge_const_g); } void run_point_times_order(void) { int i; secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); static const secp256k1_fe xr = SECP256K1_FE_CONST( 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C, 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45 ); for (i = 0; i < 500; i++) { secp256k1_ge p; if (secp256k1_ge_set_xo_var(&p, &x, 1)) { secp256k1_gej j; CHECK(secp256k1_ge_is_valid_var(&p)); secp256k1_gej_set_ge(&j, &p); CHECK(secp256k1_gej_is_valid_var(&j)); test_point_times_order(&j); } secp256k1_fe_sqr(&x, &x); } secp256k1_fe_normalize_var(&x); CHECK(secp256k1_fe_equal_var(&x, &xr)); } void ecmult_const_random_mult(void) { /* random starting point A (on the curve) */ secp256k1_ge a = SECP256K1_GE_CONST( 0x6d986544, 0x57ff52b8, 0xcf1b8126, 0x5b802a5b, 0xa97f9263, 0xb1e88044, 0x93351325, 0x91bc450a, 0x535c59f7, 0x325e5d2b, 0xc391fbe8, 0x3c12787c, 0x337e4a98, 0xe82a9011, 0x0123ba37, 0xdd769c7d ); /* random initial factor xn */ secp256k1_scalar xn = SECP256K1_SCALAR_CONST( 0x649d4f77, 0xc4242df7, 0x7f2079c9, 0x14530327, 0xa31b876a, 0xd2d8ce2a, 0x2236d5c6, 0xd7b2029b ); /* expected xn * A (from sage) */ secp256k1_ge expected_b = SECP256K1_GE_CONST( 0x23773684, 0x4d209dc7, 0x098a786f, 0x20d06fcd, 0x070a38bf, 0xc11ac651, 0x03004319, 0x1e2a8786, 0xed8c3b8e, 0xc06dd57b, 0xd06ea66e, 0x45492b0f, 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 ); secp256k1_gej b; secp256k1_ecmult_const(&b, &a, &xn); CHECK(secp256k1_ge_is_valid_var(&a)); ge_equals_gej(&expected_b, &b); } void ecmult_const_commutativity(void) { secp256k1_scalar a; secp256k1_scalar b; secp256k1_gej res1; secp256k1_gej res2; secp256k1_ge mid1; secp256k1_ge mid2; random_scalar_order_test(&a); random_scalar_order_test(&b); secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); secp256k1_ge_set_gej(&mid1, &res1); secp256k1_ge_set_gej(&mid2, &res2); secp256k1_ecmult_const(&res1, &mid1, &b); secp256k1_ecmult_const(&res2, &mid2, &a); secp256k1_ge_set_gej(&mid1, &res1); secp256k1_ge_set_gej(&mid2, &res2); ge_equals_ge(&mid1, &mid2); } void ecmult_const_mult_zero_one(void) { secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); secp256k1_scalar negone; secp256k1_gej res1; secp256k1_ge res2; secp256k1_ge point; secp256k1_scalar_negate(&negone, &one); random_group_element_test(&point); secp256k1_ecmult_const(&res1, &point, &zero); secp256k1_ge_set_gej(&res2, &res1); CHECK(secp256k1_ge_is_infinity(&res2)); secp256k1_ecmult_const(&res1, &point, &one); secp256k1_ge_set_gej(&res2, &res1); ge_equals_ge(&res2, &point); secp256k1_ecmult_const(&res1, &point, &negone); secp256k1_gej_neg(&res1, &res1); secp256k1_ge_set_gej(&res2, &res1); ge_equals_ge(&res2, &point); } void ecmult_const_chain_multiply(void) { /* Check known result (randomly generated test problem from sage) */ const secp256k1_scalar scalar = SECP256K1_SCALAR_CONST( 0x4968d524, 0x2abf9b7a, 0x466abbcf, 0x34b11b6d, 0xcd83d307, 0x827bed62, 0x05fad0ce, 0x18fae63b ); const secp256k1_gej expected_point = SECP256K1_GEJ_CONST( 0x5494c15d, 0x32099706, 0xc2395f94, 0x348745fd, 0x757ce30e, 0x4e8c90fb, 0xa2bad184, 0xf883c69f, 0x5d195d20, 0xe191bf7f, 0x1be3e55f, 0x56a80196, 0x6071ad01, 0xf1462f66, 0xc997fa94, 0xdb858435 ); secp256k1_gej point; secp256k1_ge res; int i; secp256k1_gej_set_ge(&point, &secp256k1_ge_const_g); for (i = 0; i < 100; ++i) { secp256k1_ge tmp; secp256k1_ge_set_gej(&tmp, &point); secp256k1_ecmult_const(&point, &tmp, &scalar); } secp256k1_ge_set_gej(&res, &point); ge_equals_gej(&res, &expected_point); } void run_ecmult_const_tests(void) { ecmult_const_mult_zero_one(); ecmult_const_random_mult(); ecmult_const_commutativity(); 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); + secp256k1_scratch_reset(scratch); + + /* 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, 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, 0, 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_resize(scratch, secp256k1_pippenger_scratch_size(n_points_supported, bucket_window), PIPPENGER_SCRATCH_OBJECTS)); + 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, 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, 0, 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, 0, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); + } else { + size_t scratch_size = secp256k1_strauss_scratch_size(i); + scratch = secp256k1_scratch_create(&ctx->error_callback, 0, 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, 0, 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, 0, 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) { secp256k1_scalar x, two, t; int wnaf[256]; int zeroes = -1; int i; int bits; secp256k1_scalar_set_int(&x, 0); secp256k1_scalar_set_int(&two, 2); bits = secp256k1_ecmult_wnaf(wnaf, 256, number, w); CHECK(bits <= 256); for (i = bits-1; i >= 0; i--) { int v = wnaf[i]; secp256k1_scalar_mul(&x, &x, &two); if (v) { CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ zeroes=0; CHECK((v & 1) == 1); /* check non-zero elements are odd */ CHECK(v <= (1 << (w-1)) - 1); /* check range below */ CHECK(v >= -(1 << (w-1)) - 1); /* check range above */ } else { CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ zeroes++; } 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); } CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */ } void test_constant_wnaf_negate(const secp256k1_scalar *number) { secp256k1_scalar neg1 = *number; secp256k1_scalar neg2 = *number; int sign1 = 1; int sign2 = 1; if (!secp256k1_scalar_get_bits(&neg1, 0, 1)) { secp256k1_scalar_negate(&neg1, &neg1); sign1 = -1; } sign2 = secp256k1_scalar_cond_negate(&neg2, secp256k1_scalar_is_even(&neg2)); CHECK(sign1 == sign2); CHECK(secp256k1_scalar_eq(&neg1, &neg2)); } void test_constant_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_const(wnaf, num, w); for (i = WNAF_SIZE(w); i >= 0; --i) { secp256k1_scalar t; int v = wnaf[i]; CHECK(v != 0); /* check nonzero */ CHECK(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); } /* Skew num because when encoding numbers as odd we use an offset */ secp256k1_scalar_cadd_bit(&num, skew == 2, 1); 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); /* check nonzero */ + CHECK(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)); +} + +void test_fixed_wnaf_zero(int w) { + 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); +} + void run_wnaf(void) { int i; secp256k1_scalar n = {{0}}; /* Sanity check: 1 and 2 are the smallest odd and even numbers and should * have easier-to-diagnose failure modes */ n.d[0] = 1; test_constant_wnaf(&n, 4); n.d[0] = 2; test_constant_wnaf(&n, 4); + /* Test 0 */ + test_fixed_wnaf_zero(4); /* Random tests */ for (i = 0; i < count; i++) { random_scalar_order(&n); test_wnaf(&n, 4+(i%10)); test_constant_wnaf_negate(&n); test_constant_wnaf(&n, 4 + (i % 10)); + test_fixed_wnaf(&n, 4 + (i % 10)); } secp256k1_scalar_set_int(&n, 0); CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); CHECK(secp256k1_scalar_is_zero(&n)); CHECK(secp256k1_scalar_cond_negate(&n, 0) == 1); CHECK(secp256k1_scalar_is_zero(&n)); } void test_ecmult_constants(void) { /* Test ecmult_gen() for [0..36) and [order-36..0). */ secp256k1_scalar x; secp256k1_gej r; secp256k1_ge ng; int i; int j; secp256k1_ge_neg(&ng, &secp256k1_ge_const_g); for (i = 0; i < 36; i++ ) { secp256k1_scalar_set_int(&x, i); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); for (j = 0; j < i; j++) { if (j == i - 1) { ge_equals_gej(&secp256k1_ge_const_g, &r); } secp256k1_gej_add_ge(&r, &r, &ng); } CHECK(secp256k1_gej_is_infinity(&r)); } for (i = 1; i <= 36; i++ ) { secp256k1_scalar_set_int(&x, i); secp256k1_scalar_negate(&x, &x); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); for (j = 0; j < i; j++) { if (j == i - 1) { ge_equals_gej(&ng, &r); } secp256k1_gej_add_ge(&r, &r, &secp256k1_ge_const_g); } CHECK(secp256k1_gej_is_infinity(&r)); } } void run_ecmult_constants(void) { test_ecmult_constants(); } void test_ecmult_gen_blind(void) { /* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */ secp256k1_scalar key; secp256k1_scalar b; unsigned char seed32[32]; secp256k1_gej pgej; secp256k1_gej pgej2; secp256k1_gej i; secp256k1_ge pge; random_scalar_order_test(&key); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej, &key); secp256k1_rand256(seed32); b = ctx->ecmult_gen_ctx.blind; i = ctx->ecmult_gen_ctx.initial; secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); CHECK(!secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej2, &key); CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); CHECK(!gej_xyz_equals_gej(&i, &ctx->ecmult_gen_ctx.initial)); secp256k1_ge_set_gej(&pge, &pgej); ge_equals_gej(&pge, &pgej2); } void test_ecmult_gen_blind_reset(void) { /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ secp256k1_scalar b; secp256k1_gej initial; secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); b = ctx->ecmult_gen_ctx.blind; initial = ctx->ecmult_gen_ctx.initial; secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); CHECK(secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); CHECK(gej_xyz_equals_gej(&initial, &ctx->ecmult_gen_ctx.initial)); } void run_ecmult_gen_blind(void) { int i; test_ecmult_gen_blind_reset(); for (i = 0; i < 10; i++) { test_ecmult_gen_blind(); } } #ifdef USE_ENDOMORPHISM /***** ENDOMORPHISH TESTS *****/ void test_scalar_split(void) { secp256k1_scalar full; secp256k1_scalar s1, slam; const unsigned char zero[32] = {0}; unsigned char tmp[32]; random_scalar_order_test(&full); secp256k1_scalar_split_lambda(&s1, &slam, &full); /* check that both are <= 128 bits in size */ if (secp256k1_scalar_is_high(&s1)) { secp256k1_scalar_negate(&s1, &s1); } if (secp256k1_scalar_is_high(&slam)) { secp256k1_scalar_negate(&slam, &slam); } secp256k1_scalar_get_b32(tmp, &s1); CHECK(memcmp(zero, tmp, 16) == 0); secp256k1_scalar_get_b32(tmp, &slam); CHECK(memcmp(zero, tmp, 16) == 0); } void run_endomorphism_tests(void) { test_scalar_split(); } #endif void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { unsigned char pubkeyc[65]; secp256k1_pubkey pubkey; secp256k1_ge ge; size_t pubkeyclen; int32_t ecount; ecount = 0; secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); for (pubkeyclen = 3; pubkeyclen <= 65; pubkeyclen++) { /* Smaller sizes are tested exhaustively elsewhere. */ int32_t i; memcpy(&pubkeyc[1], input, 64); VG_UNDEF(&pubkeyc[pubkeyclen], 65 - pubkeyclen); for (i = 0; i < 256; i++) { /* Try all type bytes. */ int xpass; int ypass; int ysign; pubkeyc[0] = i; /* What sign does this point have? */ ysign = (input[63] & 1) + 2; /* For the current type (i) do we expect parsing to work? Handled all of compressed/uncompressed/hybrid. */ xpass = xvalid && (pubkeyclen == 33) && ((i & 254) == 2); /* Do we expect a parse and re-serialize as uncompressed to give a matching y? */ ypass = xvalid && yvalid && ((i & 4) == ((pubkeyclen == 65) << 2)) && ((i == 4) || ((i & 251) == ysign)) && ((pubkeyclen == 33) || (pubkeyclen == 65)); if (xpass || ypass) { /* These cases must parse. */ unsigned char pubkeyo[65]; size_t outl; memset(&pubkey, 0, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); ecount = 0; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); outl = 65; VG_UNDEF(pubkeyo, 65); CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); VG_CHECK(pubkeyo, outl); CHECK(outl == 33); CHECK(memcmp(&pubkeyo[1], &pubkeyc[1], 32) == 0); CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0])); if (ypass) { /* This test isn't always done because we decode with alternative signs, so the y won't match. */ CHECK(pubkeyo[0] == ysign); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); memset(&pubkey, 0, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); secp256k1_pubkey_save(&pubkey, &ge); VG_CHECK(&pubkey, sizeof(pubkey)); outl = 65; VG_UNDEF(pubkeyo, 65); CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); VG_CHECK(pubkeyo, outl); CHECK(outl == 65); CHECK(pubkeyo[0] == 4); CHECK(memcmp(&pubkeyo[1], input, 64) == 0); } CHECK(ecount == 0); } else { /* These cases must fail to parse. */ memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); } } } secp256k1_context_set_illegal_callback(ctx, NULL, NULL); } void run_ec_pubkey_parse_test(void) { #define SECP256K1_EC_PARSE_TEST_NVALID (12) const unsigned char valid[SECP256K1_EC_PARSE_TEST_NVALID][64] = { { /* Point with leading and trailing zeros in x and y serialization. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xef, 0xa1, 0x7b, 0x77, 0x61, 0xe1, 0xe4, 0x27, 0x06, 0x98, 0x9f, 0xb4, 0x83, 0xb8, 0xd2, 0xd4, 0x9b, 0xf7, 0x8f, 0xae, 0x98, 0x03, 0xf0, 0x99, 0xb8, 0x34, 0xed, 0xeb, 0x00 }, { /* Point with x equal to a 3rd root of unity.*/ 0x7a, 0xe9, 0x6a, 0x2b, 0x65, 0x7c, 0x07, 0x10, 0x6e, 0x64, 0x47, 0x9e, 0xac, 0x34, 0x34, 0xe9, 0x9c, 0xf0, 0x49, 0x75, 0x12, 0xf5, 0x89, 0x95, 0xc1, 0x39, 0x6c, 0x28, 0x71, 0x95, 0x01, 0xee, 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, }, { /* Point with largest x. (1/2) */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, 0x0e, 0x99, 0x4b, 0x14, 0xea, 0x72, 0xf8, 0xc3, 0xeb, 0x95, 0xc7, 0x1e, 0xf6, 0x92, 0x57, 0x5e, 0x77, 0x50, 0x58, 0x33, 0x2d, 0x7e, 0x52, 0xd0, 0x99, 0x5c, 0xf8, 0x03, 0x88, 0x71, 0xb6, 0x7d, }, { /* Point with largest x. (2/2) */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, 0xf1, 0x66, 0xb4, 0xeb, 0x15, 0x8d, 0x07, 0x3c, 0x14, 0x6a, 0x38, 0xe1, 0x09, 0x6d, 0xa8, 0xa1, 0x88, 0xaf, 0xa7, 0xcc, 0xd2, 0x81, 0xad, 0x2f, 0x66, 0xa3, 0x07, 0xfb, 0x77, 0x8e, 0x45, 0xb2, }, { /* Point with smallest x. (1/2) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, }, { /* Point with smallest x. (2/2) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, }, { /* Point with largest y. (1/3) */ 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, }, { /* Point with largest y. (2/3) */ 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, }, { /* Point with largest y. (3/3) */ 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, }, { /* Point with smallest y. (1/3) */ 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { /* Point with smallest y. (2/3) */ 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { /* Point with smallest y. (3/3) */ 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }; #define SECP256K1_EC_PARSE_TEST_NXVALID (4) const unsigned char onlyxvalid[SECP256K1_EC_PARSE_TEST_NXVALID][64] = { { /* Valid if y overflow ignored (y = 1 mod p). (1/3) */ 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, }, { /* Valid if y overflow ignored (y = 1 mod p). (2/3) */ 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, }, { /* Valid if y overflow ignored (y = 1 mod p). (3/3)*/ 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, }, { /* x on curve, y is from y^2 = x^3 + 8. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 } }; #define SECP256K1_EC_PARSE_TEST_NINVALID (7) const unsigned char invalid[SECP256K1_EC_PARSE_TEST_NINVALID][64] = { { /* x is third root of -8, y is -1 * (x^3+7); also on the curve for y^2 = x^3 + 9. */ 0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { /* Valid if x overflow ignored (x = 1 mod p). */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, }, { /* Valid if x overflow ignored (x = 1 mod p). */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, }, { /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, 0xf4, 0x84, 0x14, 0x5c, 0xb0, 0x14, 0x9b, 0x82, 0x5d, 0xff, 0x41, 0x2f, 0xa0, 0x52, 0xa8, 0x3f, 0xcb, 0x72, 0xdb, 0x61, 0xd5, 0x6f, 0x37, 0x70, 0xce, 0x06, 0x6b, 0x73, 0x49, 0xa2, 0xaa, 0x28, }, { /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, 0x0b, 0x7b, 0xeb, 0xa3, 0x4f, 0xeb, 0x64, 0x7d, 0xa2, 0x00, 0xbe, 0xd0, 0x5f, 0xad, 0x57, 0xc0, 0x34, 0x8d, 0x24, 0x9e, 0x2a, 0x90, 0xc8, 0x8f, 0x31, 0xf9, 0x94, 0x8b, 0xb6, 0x5d, 0x52, 0x07, }, { /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x53, 0x7e, 0xef, 0xdf, 0xc1, 0x60, 0x6a, 0x07, 0x27, 0xcd, 0x69, 0xb4, 0xa7, 0x33, 0x3d, 0x38, 0xed, 0x44, 0xe3, 0x93, 0x2a, 0x71, 0x79, 0xee, 0xcb, 0x4b, 0x6f, 0xba, 0x93, 0x60, 0xdc, }, { /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xac, 0x81, 0x10, 0x20, 0x3e, 0x9f, 0x95, 0xf8, 0xd8, 0x32, 0x96, 0x4b, 0x58, 0xcc, 0xc2, 0xc7, 0x12, 0xbb, 0x1c, 0x6c, 0xd5, 0x8e, 0x86, 0x11, 0x34, 0xb4, 0x8f, 0x45, 0x6c, 0x9b, 0x53 } }; const unsigned char pubkeyc[66] = { /* Serialization of G. */ 0x04, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8, 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8, 0x00 }; unsigned char sout[65]; unsigned char shortkey[2]; secp256k1_ge ge; secp256k1_pubkey pubkey; size_t len; int32_t i; int32_t ecount; int32_t ecount2; ecount = 0; /* Nothing should be reading this far into pubkeyc. */ VG_UNDEF(&pubkeyc[65], 1); secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); /* Zero length claimed, fail, zeroize, no illegal arg error. */ memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; VG_UNDEF(shortkey, 2); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 0) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); /* Length one claimed, fail, zeroize, no illegal arg error. */ for (i = 0; i < 256 ; i++) { memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; shortkey[0] = i; VG_UNDEF(&shortkey[1], 1); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 1) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); } /* Length two claimed, fail, zeroize, no illegal arg error. */ for (i = 0; i < 65536 ; i++) { memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; shortkey[0] = i & 255; shortkey[1] = i >> 8; VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 2) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); } memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; VG_UNDEF(&pubkey, sizeof(pubkey)); /* 33 bytes claimed on otherwise valid input starting with 0x04, fail, zeroize output, no illegal arg error. */ CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 33) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); /* NULL pubkey, illegal arg error. Pubkey isn't rewritten before this step, since it's NULL into the parser. */ CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, pubkeyc, 65) == 0); CHECK(ecount == 2); /* NULL input string. Illegal arg and zeroize output. */ memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, NULL, 65) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 1); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 2); /* 64 bytes claimed on input starting with 0x04, fail, zeroize output, no illegal arg error. */ memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 64) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); /* 66 bytes claimed, fail, zeroize output, no illegal arg error. */ memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 66) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); /* Valid parse. */ memset(&pubkey, 0, sizeof(pubkey)); ecount = 0; VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(ecount == 0); VG_UNDEF(&ge, sizeof(ge)); CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); VG_CHECK(&ge.x, sizeof(ge.x)); VG_CHECK(&ge.y, sizeof(ge.y)); VG_CHECK(&ge.infinity, sizeof(ge.infinity)); ge_equals_ge(&secp256k1_ge_const_g, &ge); CHECK(ecount == 0); /* secp256k1_ec_pubkey_serialize illegal args. */ ecount = 0; len = 65; CHECK(secp256k1_ec_pubkey_serialize(ctx, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); CHECK(ecount == 1); CHECK(len == 0); CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); CHECK(ecount == 2); len = 65; VG_UNDEF(sout, 65); CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED) == 0); VG_CHECK(sout, 65); CHECK(ecount == 3); CHECK(len == 0); len = 65; CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, ~0) == 0); CHECK(ecount == 4); CHECK(len == 0); len = 65; VG_UNDEF(sout, 65); CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); VG_CHECK(sout, 65); CHECK(ecount == 4); CHECK(len == 65); /* Multiple illegal args. Should still set arg error only once. */ ecount = 0; ecount2 = 11; CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); CHECK(ecount == 1); /* Does the illegal arg callback actually change the behavior? */ secp256k1_context_set_illegal_callback(ctx, uncounting_illegal_callback_fn, &ecount2); CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); CHECK(ecount == 1); CHECK(ecount2 == 10); secp256k1_context_set_illegal_callback(ctx, NULL, NULL); /* Try a bunch of prefabbed points with all possible encodings. */ for (i = 0; i < SECP256K1_EC_PARSE_TEST_NVALID; i++) { ec_pubkey_parse_pointtest(valid[i], 1, 1); } for (i = 0; i < SECP256K1_EC_PARSE_TEST_NXVALID; i++) { ec_pubkey_parse_pointtest(onlyxvalid[i], 1, 0); } for (i = 0; i < SECP256K1_EC_PARSE_TEST_NINVALID; i++) { ec_pubkey_parse_pointtest(invalid[i], 0, 0); } } void run_eckey_edge_case_test(void) { const unsigned char orderc[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 }; const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00}; unsigned char ctmp[33]; unsigned char ctmp2[33]; secp256k1_pubkey pubkey; secp256k1_pubkey pubkey2; secp256k1_pubkey pubkey_one; secp256k1_pubkey pubkey_negone; const secp256k1_pubkey *pubkeys[3]; size_t len; int32_t ecount; /* Group order is too large, reject. */ CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); /* Maximum value is too large, reject. */ memset(ctmp, 255, 32); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); memset(&pubkey, 1, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); /* Zero is too small, reject. */ memset(ctmp, 0, 32); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); memset(&pubkey, 1, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); /* One must be accepted. */ ctmp[31] = 0x01; CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); memset(&pubkey, 0, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); pubkey_one = pubkey; /* Group order + 1 is too large, reject. */ memcpy(ctmp, orderc, 32); ctmp[31] = 0x42; CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); memset(&pubkey, 1, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); /* -1 must be accepted. */ ctmp[31] = 0x40; CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); memset(&pubkey, 0, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); pubkey_negone = pubkey; /* Tweak of zero leaves the value unchanged. */ memset(ctmp2, 0, 32); CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); memcpy(&pubkey2, &pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Multiply tweak of zero zeroizes the output. */ CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0); CHECK(memcmp(zeros, ctmp, 32) == 0); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* Overflowing key tweak zeroizes. */ memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0); CHECK(memcmp(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0); CHECK(memcmp(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* Private key tweaks results in a key of zero. */ ctmp2[31] = 1; CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0); CHECK(memcmp(zeros, ctmp2, 32) == 0); ctmp2[31] = 1; CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* Tweak computation wraps and results in a key of 1. */ ctmp2[31] = 2; CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1); CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); ctmp2[31] = 2; CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); ctmp2[31] = 1; CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Tweak mul * 2 = 1+1. */ CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); ctmp2[31] = 2; CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Test argument errors. */ ecount = 0; secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); CHECK(ecount == 0); /* Zeroize pubkey on parse error. */ memset(&pubkey, 0, 32); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); CHECK(ecount == 1); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); memset(&pubkey2, 0, 32); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0); CHECK(ecount == 2); CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0); /* Plain argument errors. */ ecount = 0; CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); CHECK(ecount == 0); CHECK(secp256k1_ec_seckey_verify(ctx, NULL) == 0); CHECK(ecount == 1); ecount = 0; memset(ctmp2, 0, 32); ctmp2[31] = 4; CHECK(secp256k1_ec_pubkey_tweak_add(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, NULL) == 0); CHECK(ecount == 2); ecount = 0; memset(ctmp2, 0, 32); ctmp2[31] = 4; CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0); CHECK(ecount == 2); ecount = 0; memset(ctmp2, 0, 32); CHECK(secp256k1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0); CHECK(ecount == 2); ecount = 0; memset(ctmp2, 0, 32); ctmp2[31] = 1; CHECK(secp256k1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0); CHECK(ecount == 2); ecount = 0; CHECK(secp256k1_ec_pubkey_create(ctx, NULL, ctmp) == 0); CHECK(ecount == 1); memset(&pubkey, 1, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); CHECK(ecount == 2); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); /* secp256k1_ec_pubkey_combine tests. */ ecount = 0; pubkeys[0] = &pubkey_one; VG_UNDEF(&pubkeys[0], sizeof(secp256k1_pubkey *)); VG_UNDEF(&pubkeys[1], sizeof(secp256k1_pubkey *)); VG_UNDEF(&pubkeys[2], sizeof(secp256k1_pubkey *)); memset(&pubkey, 255, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(ecount == 1); CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(ecount == 2); memset(&pubkey, 255, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(ecount == 3); pubkeys[0] = &pubkey_negone; memset(&pubkey, 255, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(ecount == 3); len = 33; CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); CHECK(memcmp(ctmp, ctmp2, 33) == 0); /* Result is infinity. */ pubkeys[0] = &pubkey_one; pubkeys[1] = &pubkey_negone; memset(&pubkey, 255, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(ecount == 3); /* Passes through infinity but comes out one. */ pubkeys[2] = &pubkey_one; memset(&pubkey, 255, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(ecount == 3); len = 33; CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); CHECK(memcmp(ctmp, ctmp2, 33) == 0); /* Adds to two. */ pubkeys[1] = &pubkey_one; memset(&pubkey, 255, sizeof(secp256k1_pubkey)); VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1); VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(ecount == 3); secp256k1_context_set_illegal_callback(ctx, NULL, NULL); } void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { secp256k1_scalar nonce; do { random_scalar_order_test(&nonce); } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); } void test_ecdsa_sign_verify(void) { secp256k1_gej pubj; secp256k1_ge pub; secp256k1_scalar one; secp256k1_scalar msg, key; secp256k1_scalar sigr, sigs; int recid; int getrec; random_scalar_order_test(&msg); random_scalar_order_test(&key); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key); secp256k1_ge_set_gej(&pub, &pubj); getrec = secp256k1_rand_bits(1); random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL); if (getrec) { CHECK(recid >= 0 && recid < 4); } CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_add(&msg, &msg, &one); CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); } void run_ecdsa_sign_verify(void) { int i; for (i = 0; i < 10*count; i++) { test_ecdsa_sign_verify(); } } /** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */ static int precomputed_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)key32; (void)algo16; memcpy(nonce32, data, 32); return (counter == 0); } static int nonce_function_test_fail(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { /* Dummy nonce generator that has a fatal error on the first counter value. */ if (counter == 0) { return 0; } return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 1); } static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { /* Dummy nonce generator that produces unacceptable nonces for the first several counter values. */ if (counter < 3) { memset(nonce32, counter==0 ? 0 : 255, 32); if (counter == 2) { nonce32[31]--; } return 1; } if (counter < 5) { static const unsigned char order[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 }; memcpy(nonce32, order, 32); if (counter == 4) { nonce32[31]++; } return 1; } /* Retry rate of 6979 is negligible esp. as we only call this in deterministic tests. */ /* If someone does fine a case where it retries for secp256k1, we'd like to know. */ if (counter > 5) { return 0; } return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); } int is_empty_signature(const secp256k1_ecdsa_signature *sig) { static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0}; return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0; } void test_ecdsa_end_to_end(void) { unsigned char extra[32] = {0x00}; unsigned char privkey[32]; unsigned char message[32]; unsigned char privkey2[32]; secp256k1_ecdsa_signature signature[6]; secp256k1_scalar r, s; unsigned char sig[74]; size_t siglen = 74; unsigned char pubkeyc[65]; size_t pubkeyclen = 65; secp256k1_pubkey pubkey; secp256k1_pubkey pubkey_tmp; unsigned char seckey[300]; size_t seckeylen = 300; /* Generate a random key and message. */ { secp256k1_scalar msg, key; random_scalar_order_test(&msg); random_scalar_order_test(&key); secp256k1_scalar_get_b32(privkey, &key); secp256k1_scalar_get_b32(message, &msg); } /* Construct and verify corresponding public key. */ CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); /* Verify exporting and importing public key. */ CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); memset(&pubkey, 0, sizeof(pubkey)); 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. */ 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(memcmp(privkey, privkey2, 32) == 0); /* Optionally tweak the keys using addition. */ if (secp256k1_rand_int(3) == 0) { int ret1; int ret2; unsigned char rnd[32]; secp256k1_pubkey pubkey2; secp256k1_rand256_test(rnd); ret1 = secp256k1_ec_privkey_tweak_add(ctx, privkey, rnd); ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); CHECK(ret1 == ret2); if (ret1 == 0) { return; } CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Optionally tweak the keys using multiplication. */ if (secp256k1_rand_int(3) == 0) { int ret1; int ret2; unsigned char rnd[32]; secp256k1_pubkey pubkey2; secp256k1_rand256_test(rnd); ret1 = secp256k1_ec_privkey_tweak_mul(ctx, privkey, rnd); ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); CHECK(ret1 == ret2); if (ret1 == 0) { return; } CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Sign. */ CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_sign(ctx, &signature[4], message, privkey, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_sign(ctx, &signature[1], message, privkey, NULL, extra) == 1); extra[31] = 1; CHECK(secp256k1_ecdsa_sign(ctx, &signature[2], message, privkey, NULL, extra) == 1); extra[31] = 0; extra[0] = 1; CHECK(secp256k1_ecdsa_sign(ctx, &signature[3], message, privkey, NULL, extra) == 1); CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0); CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0); CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0); CHECK(memcmp(&signature[0], &signature[3], sizeof(signature[0])) != 0); CHECK(memcmp(&signature[1], &signature[2], sizeof(signature[0])) != 0); CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0); CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 0); /* Verify. */ CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[2], message, &pubkey) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[3], message, &pubkey) == 1); /* Test lower-S form, malleate, verify and fail, test again, malleate again */ CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[0])); secp256k1_ecdsa_signature_load(ctx, &r, &s, &signature[0]); secp256k1_scalar_negate(&s, &s); secp256k1_ecdsa_signature_save(&signature[5], &r, &s); CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 0); CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); CHECK(secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); CHECK(!secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); secp256k1_scalar_negate(&s, &s); secp256k1_ecdsa_signature_save(&signature[5], &r, &s); CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); CHECK(memcmp(&signature[5], &signature[0], 64) == 0); /* Serialize/parse DER and verify again */ CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); memset(&signature[0], 0, sizeof(signature[0])); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); /* Serialize/destroy/parse DER and verify again. */ siglen = 74; CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); sig[secp256k1_rand_int(siglen)] += 1 + secp256k1_rand_int(255); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 || secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 0); } void test_random_pubkeys(void) { secp256k1_ge elem; secp256k1_ge elem2; unsigned char in[65]; /* Generate some randomly sized pubkeys. */ size_t len = secp256k1_rand_bits(2) == 0 ? 65 : 33; if (secp256k1_rand_bits(2) == 0) { len = secp256k1_rand_bits(6); } if (len == 65) { in[0] = secp256k1_rand_bits(1) ? 4 : (secp256k1_rand_bits(1) ? 6 : 7); } else { in[0] = secp256k1_rand_bits(1) ? 2 : 3; } if (secp256k1_rand_bits(3) == 0) { in[0] = secp256k1_rand_bits(8); } if (len > 1) { secp256k1_rand256(&in[1]); } if (len > 33) { secp256k1_rand256(&in[33]); } if (secp256k1_eckey_pubkey_parse(&elem, in, len)) { unsigned char out[65]; unsigned char firstb; int res; size_t size = len; firstb = in[0]; /* If the pubkey can be parsed, it should round-trip... */ CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); CHECK(size == len); CHECK(memcmp(&in[1], &out[1], len-1) == 0); /* ... except for the type of hybrid inputs. */ if ((in[0] != 6) && (in[0] != 7)) { CHECK(in[0] == out[0]); } size = 65; CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); CHECK(size == 65); CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); ge_equals_ge(&elem,&elem2); /* Check that the X9.62 hybrid type is checked. */ in[0] = secp256k1_rand_bits(1) ? 6 : 7; res = secp256k1_eckey_pubkey_parse(&elem2, in, size); if (firstb == 2 || firstb == 3) { if (in[0] == firstb + 4) { CHECK(res); } else { CHECK(!res); } } if (res) { ge_equals_ge(&elem,&elem2); CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); CHECK(memcmp(&in[1], &out[1], 64) == 0); } } } void run_random_pubkeys(void) { int i; for (i = 0; i < 10*count; i++) { test_random_pubkeys(); } } void run_ecdsa_end_to_end(void) { int i; for (i = 0; i < 64*count; i++) { test_ecdsa_end_to_end(); } } int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) { static const unsigned char zeroes[32] = {0}; #ifdef ENABLE_OPENSSL_TESTS static const unsigned char max_scalar[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40 }; #endif int ret = 0; secp256k1_ecdsa_signature sig_der; unsigned char roundtrip_der[2048]; unsigned char compact_der[64]; size_t len_der = 2048; int parsed_der = 0, valid_der = 0, roundtrips_der = 0; secp256k1_ecdsa_signature sig_der_lax; unsigned char roundtrip_der_lax[2048]; unsigned char compact_der_lax[64]; size_t len_der_lax = 2048; int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0; #ifdef ENABLE_OPENSSL_TESTS ECDSA_SIG *sig_openssl; const BIGNUM *r = NULL, *s = NULL; const unsigned char *sigptr; unsigned char roundtrip_openssl[2048]; int len_openssl = 2048; int parsed_openssl, valid_openssl = 0, roundtrips_openssl = 0; #endif parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen); if (parsed_der) { ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0; valid_der = (memcmp(compact_der, zeroes, 32) != 0) && (memcmp(compact_der + 32, zeroes, 32) != 0); } if (valid_der) { ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1; roundtrips_der = (len_der == siglen) && memcmp(roundtrip_der, sig, siglen) == 0; } parsed_der_lax = ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen); if (parsed_der_lax) { ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10; valid_der_lax = (memcmp(compact_der_lax, zeroes, 32) != 0) && (memcmp(compact_der_lax + 32, zeroes, 32) != 0); } if (valid_der_lax) { ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; roundtrips_der_lax = (len_der_lax == siglen) && memcmp(roundtrip_der_lax, sig, siglen) == 0; } if (certainly_der) { ret |= (!parsed_der) << 2; } if (certainly_not_der) { ret |= (parsed_der) << 17; } if (valid_der) { ret |= (!roundtrips_der) << 3; } if (valid_der) { ret |= (!roundtrips_der_lax) << 12; ret |= (len_der != len_der_lax) << 13; ret |= (memcmp(roundtrip_der_lax, roundtrip_der, len_der) != 0) << 14; } ret |= (roundtrips_der != roundtrips_der_lax) << 15; if (parsed_der) { ret |= (!parsed_der_lax) << 16; } #ifdef ENABLE_OPENSSL_TESTS sig_openssl = ECDSA_SIG_new(); sigptr = sig; parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL); if (parsed_openssl) { 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) { unsigned char tmp[32] = {0}; BN_bn2bin(r, tmp + 32 - BN_num_bytes(r)); valid_openssl = memcmp(tmp, max_scalar, 32) < 0; } if (valid_openssl) { unsigned char tmp[32] = {0}; BN_bn2bin(s, tmp + 32 - BN_num_bytes(s)); valid_openssl = memcmp(tmp, max_scalar, 32) < 0; } } len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL); if (len_openssl <= 2048) { unsigned char *ptr = roundtrip_openssl; CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl); roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (memcmp(roundtrip_openssl, sig, siglen) == 0); } else { len_openssl = 0; } ECDSA_SIG_free(sig_openssl); ret |= (parsed_der && !parsed_openssl) << 4; ret |= (valid_der && !valid_openssl) << 5; ret |= (roundtrips_openssl && !parsed_der) << 6; ret |= (roundtrips_der != roundtrips_openssl) << 7; if (roundtrips_openssl) { ret |= (len_der != (size_t)len_openssl) << 8; ret |= (memcmp(roundtrip_der, roundtrip_openssl, len_der) != 0) << 9; } #endif return ret; } static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { size_t i; for (i = 0; i < ptrlen; i++) { int shift = ptrlen - 1 - i; if (shift >= 4) { ptr[i] = 0; } else { ptr[i] = (val >> shift) & 0xFF; } } } static void damage_array(unsigned char *sig, size_t *len) { int pos; int action = secp256k1_rand_bits(3); if (action < 1 && *len > 3) { /* Delete a byte. */ pos = secp256k1_rand_int(*len); memmove(sig + pos, sig + pos + 1, *len - pos - 1); (*len)--; return; } else if (action < 2 && *len < 2048) { /* Insert a byte. */ pos = secp256k1_rand_int(1 + *len); memmove(sig + pos + 1, sig + pos, *len - pos); sig[pos] = secp256k1_rand_bits(8); (*len)++; return; } else if (action < 4) { /* Modify a byte. */ sig[secp256k1_rand_int(*len)] += 1 + secp256k1_rand_int(255); return; } else { /* action < 8 */ /* Modify a bit. */ sig[secp256k1_rand_int(*len)] ^= 1 << secp256k1_rand_bits(3); return; } } static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly_der, int* certainly_not_der) { int der; int nlow[2], nlen[2], nlenlen[2], nhbit[2], nhbyte[2], nzlen[2]; size_t tlen, elen, glen; int indet; int n; *len = 0; der = secp256k1_rand_bits(2) == 0; *certainly_der = der; *certainly_not_der = 0; indet = der ? 0 : secp256k1_rand_int(10) == 0; for (n = 0; n < 2; n++) { /* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */ nlow[n] = der ? 1 : (secp256k1_rand_bits(3) != 0); /* The length of the number in bytes (the first byte of which will always be nonzero) */ nlen[n] = nlow[n] ? secp256k1_rand_int(33) : 32 + secp256k1_rand_int(200) * secp256k1_rand_int(8) / 8; CHECK(nlen[n] <= 232); /* The top bit of the number. */ nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_rand_bits(1)); /* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */ nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_rand_bits(7) : 1 + secp256k1_rand_int(127)); /* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */ nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_rand_int(3) : secp256k1_rand_int(300 - nlen[n]) * secp256k1_rand_int(8) / 8); if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) { *certainly_not_der = 1; } CHECK(nlen[n] + nzlen[n] <= 300); /* The length of the length descriptor for the number. 0 means short encoding, anything else is long encoding. */ nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2); if (!der) { /* nlenlen[n] max 127 bytes */ int add = secp256k1_rand_int(127 - nlenlen[n]) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; nlenlen[n] += add; if (add != 0) { *certainly_not_der = 1; } } CHECK(nlen[n] + nzlen[n] + nlenlen[n] <= 427); } /* The total length of the data to go, so far */ tlen = 2 + nlenlen[0] + nlen[0] + nzlen[0] + 2 + nlenlen[1] + nlen[1] + nzlen[1]; CHECK(tlen <= 856); /* The length of the garbage inside the tuple. */ elen = (der || indet) ? 0 : secp256k1_rand_int(980 - tlen) * secp256k1_rand_int(8) / 8; if (elen != 0) { *certainly_not_der = 1; } tlen += elen; CHECK(tlen <= 980); /* The length of the garbage after the end of the tuple. */ glen = der ? 0 : secp256k1_rand_int(990 - tlen) * secp256k1_rand_int(8) / 8; if (glen != 0) { *certainly_not_der = 1; } CHECK(tlen + glen <= 990); /* Write the tuple header. */ sig[(*len)++] = 0x30; if (indet) { /* Indeterminate length */ sig[(*len)++] = 0x80; *certainly_not_der = 1; } else { int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2); if (!der) { int add = secp256k1_rand_int(127 - tlenlen) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; tlenlen += add; if (add != 0) { *certainly_not_der = 1; } } if (tlenlen == 0) { /* Short length notation */ sig[(*len)++] = tlen; } else { /* Long length notation */ sig[(*len)++] = 128 + tlenlen; assign_big_endian(sig + *len, tlenlen, tlen); *len += tlenlen; } tlen += tlenlen; } tlen += 2; CHECK(tlen + glen <= 1119); for (n = 0; n < 2; n++) { /* Write the integer header. */ sig[(*len)++] = 0x02; if (nlenlen[n] == 0) { /* Short length notation */ sig[(*len)++] = nlen[n] + nzlen[n]; } else { /* Long length notation. */ sig[(*len)++] = 128 + nlenlen[n]; assign_big_endian(sig + *len, nlenlen[n], nlen[n] + nzlen[n]); *len += nlenlen[n]; } /* Write zero padding */ while (nzlen[n] > 0) { sig[(*len)++] = 0x00; nzlen[n]--; } if (nlen[n] == 32 && !nlow[n]) { /* Special extra 16 0xFF bytes in "high" 32-byte numbers */ int i; for (i = 0; i < 16; i++) { sig[(*len)++] = 0xFF; } nlen[n] -= 16; } /* Write first byte of number */ if (nlen[n] > 0) { sig[(*len)++] = nhbyte[n]; nlen[n]--; } /* Generate remaining random bytes of number */ secp256k1_rand_bytes_test(sig + *len, nlen[n]); *len += nlen[n]; nlen[n] = 0; } /* Generate random garbage inside tuple. */ secp256k1_rand_bytes_test(sig + *len, elen); *len += elen; /* Generate end-of-contents bytes. */ if (indet) { sig[(*len)++] = 0; sig[(*len)++] = 0; tlen += 2; } CHECK(tlen + glen <= 1121); /* Generate random garbage outside tuple. */ secp256k1_rand_bytes_test(sig + *len, glen); *len += glen; tlen += glen; CHECK(tlen <= 1121); CHECK(tlen == *len); } void run_ecdsa_der_parse(void) { int i,j; for (i = 0; i < 200 * count; i++) { unsigned char buffer[2048]; size_t buflen = 0; int certainly_der = 0; int certainly_not_der = 0; random_ber_signature(buffer, &buflen, &certainly_der, &certainly_not_der); CHECK(buflen <= 2048); for (j = 0; j < 16; j++) { int ret = 0; if (j > 0) { damage_array(buffer, &buflen); /* We don't know anything anymore about the DERness of the result */ certainly_der = 0; certainly_not_der = 0; } ret = test_ecdsa_der_parse(buffer, buflen, certainly_der, certainly_not_der); if (ret != 0) { size_t k; fprintf(stderr, "Failure %x on ", ret); for (k = 0; k < buflen; k++) { fprintf(stderr, "%02x ", buffer[k]); } fprintf(stderr, "\n"); } CHECK(ret == 0); } } } /* Tests several edge cases. */ void test_ecdsa_edge_cases(void) { int t; secp256k1_ecdsa_signature sig; /* Test the case where ECDSA recomputes a point that is infinity. */ { secp256k1_gej keyj; secp256k1_ge key; secp256k1_scalar msg; secp256k1_scalar sr, ss; secp256k1_scalar_set_int(&ss, 1); secp256k1_scalar_negate(&ss, &ss); secp256k1_scalar_inverse(&ss, &ss); secp256k1_scalar_set_int(&sr, 1); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr); secp256k1_ge_set_gej(&key, &keyj); msg = ss; CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Verify signature with r of zero fails. */ { const unsigned char pubkey_mods_zero[33] = { 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 }; secp256k1_ge key; secp256k1_scalar msg; secp256k1_scalar sr, ss; secp256k1_scalar_set_int(&ss, 1); secp256k1_scalar_set_int(&msg, 0); secp256k1_scalar_set_int(&sr, 0); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Verify signature with s of zero fails. */ { const unsigned char pubkey[33] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; secp256k1_ge key; secp256k1_scalar msg; secp256k1_scalar sr, ss; secp256k1_scalar_set_int(&ss, 0); secp256k1_scalar_set_int(&msg, 0); secp256k1_scalar_set_int(&sr, 1); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Verify signature with message 0 passes. */ { const unsigned char pubkey[33] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; const unsigned char pubkey2[33] = { 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x43 }; secp256k1_ge key; secp256k1_ge key2; secp256k1_scalar msg; secp256k1_scalar sr, ss; secp256k1_scalar_set_int(&ss, 2); secp256k1_scalar_set_int(&msg, 0); secp256k1_scalar_set_int(&sr, 2); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); secp256k1_scalar_negate(&ss, &ss); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); secp256k1_scalar_set_int(&ss, 1); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); } /* Verify signature with message 1 passes. */ { const unsigned char pubkey[33] = { 0x02, 0x14, 0x4e, 0x5a, 0x58, 0xef, 0x5b, 0x22, 0x6f, 0xd2, 0xe2, 0x07, 0x6a, 0x77, 0xcf, 0x05, 0xb4, 0x1d, 0xe7, 0x4a, 0x30, 0x98, 0x27, 0x8c, 0x93, 0xe6, 0xe6, 0x3c, 0x0b, 0xc4, 0x73, 0x76, 0x25 }; const unsigned char pubkey2[33] = { 0x02, 0x8a, 0xd5, 0x37, 0xed, 0x73, 0xd9, 0x40, 0x1d, 0xa0, 0x33, 0xd2, 0xdc, 0xf0, 0xaf, 0xae, 0x34, 0xcf, 0x5f, 0x96, 0x4c, 0x73, 0x28, 0x0f, 0x92, 0xc0, 0xf6, 0x9d, 0xd9, 0xb2, 0x09, 0x10, 0x62 }; const unsigned char csr[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb }; secp256k1_ge key; secp256k1_ge key2; secp256k1_scalar msg; secp256k1_scalar sr, ss; secp256k1_scalar_set_int(&ss, 1); secp256k1_scalar_set_int(&msg, 1); secp256k1_scalar_set_b32(&sr, csr, NULL); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); secp256k1_scalar_negate(&ss, &ss); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); secp256k1_scalar_set_int(&ss, 2); secp256k1_scalar_inverse_var(&ss, &ss); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); } /* Verify signature with message -1 passes. */ { const unsigned char pubkey[33] = { 0x03, 0xaf, 0x97, 0xff, 0x7d, 0x3a, 0xf6, 0xa0, 0x02, 0x94, 0xbd, 0x9f, 0x4b, 0x2e, 0xd7, 0x52, 0x28, 0xdb, 0x49, 0x2a, 0x65, 0xcb, 0x1e, 0x27, 0x57, 0x9c, 0xba, 0x74, 0x20, 0xd5, 0x1d, 0x20, 0xf1 }; const unsigned char csr[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee }; secp256k1_ge key; secp256k1_scalar msg; secp256k1_scalar sr, ss; secp256k1_scalar_set_int(&ss, 1); secp256k1_scalar_set_int(&msg, 1); secp256k1_scalar_negate(&msg, &msg); secp256k1_scalar_set_b32(&sr, csr, NULL); CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); secp256k1_scalar_negate(&ss, &ss); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); secp256k1_scalar_set_int(&ss, 3); secp256k1_scalar_inverse_var(&ss, &ss); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Signature where s would be zero. */ { secp256k1_pubkey pubkey; size_t siglen; int32_t ecount; unsigned char signature[72]; static const unsigned char nonce[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; static const unsigned char nonce2[32] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 }; const unsigned char key[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; unsigned char msg[32] = { 0x86, 0x41, 0x99, 0x81, 0x06, 0x23, 0x44, 0x53, 0xaa, 0x5f, 0x9d, 0x6a, 0x31, 0x78, 0xf4, 0xf7, 0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62, 0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9, }; ecount = 0; secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 0); CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 0); msg[31] = 0xaa; CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 1); CHECK(ecount == 0); CHECK(secp256k1_ecdsa_sign(ctx, NULL, msg, key, precomputed_nonce_function, nonce2) == 0); CHECK(ecount == 1); CHECK(secp256k1_ecdsa_sign(ctx, &sig, NULL, key, precomputed_nonce_function, nonce2) == 0); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, NULL, precomputed_nonce_function, nonce2) == 0); CHECK(ecount == 3); CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, key) == 1); CHECK(secp256k1_ecdsa_verify(ctx, NULL, msg, &pubkey) == 0); CHECK(ecount == 4); CHECK(secp256k1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0); CHECK(ecount == 5); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, NULL) == 0); CHECK(ecount == 6); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1); CHECK(ecount == 6); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); CHECK(ecount == 7); /* That pubkeyload fails via an ARGCHECK is a little odd but makes sense because pubkeys are an opaque data type. */ CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 0); CHECK(ecount == 8); siglen = 72; CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0); CHECK(ecount == 9); CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0); CHECK(ecount == 10); CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0); CHECK(ecount == 11); CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1); CHECK(ecount == 11); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, NULL, signature, siglen) == 0); CHECK(ecount == 12); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, NULL, siglen) == 0); CHECK(ecount == 13); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, signature, siglen) == 1); CHECK(ecount == 13); siglen = 10; /* Too little room for a signature does not fail via ARGCHECK. */ CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0); CHECK(ecount == 13); ecount = 0; CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, NULL) == 0); CHECK(ecount == 1); CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, NULL, &sig) == 0); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, NULL) == 0); CHECK(ecount == 3); CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, &sig) == 1); CHECK(ecount == 3); CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, NULL, signature) == 0); CHECK(ecount == 4); CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, NULL) == 0); CHECK(ecount == 5); CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 1); CHECK(ecount == 5); memset(signature, 255, 64); CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 0); CHECK(ecount == 5); secp256k1_context_set_illegal_callback(ctx, NULL, NULL); } /* Nonce function corner cases. */ for (t = 0; t < 2; t++) { static const unsigned char zero[32] = {0x00}; int i; unsigned char key[32]; unsigned char msg[32]; secp256k1_ecdsa_signature sig2; secp256k1_scalar sr[512], ss; const unsigned char *extra; extra = t == 0 ? NULL : zero; memset(msg, 0, 32); msg[31] = 1; /* High key results in signature failure. */ memset(key, 0xFF, 32); CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); CHECK(is_empty_signature(&sig)); /* Zero key results in signature failure. */ memset(key, 0, 32); CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); CHECK(is_empty_signature(&sig)); /* Nonce function failure results in signature failure. */ key[31] = 1; CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_fail, extra) == 0); CHECK(is_empty_signature(&sig)); /* The retry loop successfully makes its way to the first good value. */ CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_retry, extra) == 1); CHECK(!is_empty_signature(&sig)); CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); CHECK(!is_empty_signature(&sig2)); CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); /* The default nonce function is deterministic. */ CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); /* The default nonce function changes output with different messages. */ for(i = 0; i < 256; i++) { int j; msg[0] = i; CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); for (j = 0; j < i; j++) { CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); } } msg[0] = 0; msg[31] = 2; /* The default nonce function changes output with different keys. */ for(i = 256; i < 512; i++) { int j; key[0] = i - 256; CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); for (j = 0; j < i; j++) { CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); } } key[0] = 0; } { /* Check that optional nonce arguments do not have equivalent effect. */ const unsigned char zeros[32] = {0}; unsigned char nonce[32]; unsigned char nonce2[32]; unsigned char nonce3[32]; unsigned char nonce4[32]; VG_UNDEF(nonce,32); VG_UNDEF(nonce2,32); VG_UNDEF(nonce3,32); VG_UNDEF(nonce4,32); CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1); VG_CHECK(nonce,32); CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1); VG_CHECK(nonce2,32); CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1); VG_CHECK(nonce3,32); CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); VG_CHECK(nonce4,32); CHECK(memcmp(nonce, nonce2, 32) != 0); CHECK(memcmp(nonce, nonce3, 32) != 0); CHECK(memcmp(nonce, nonce4, 32) != 0); CHECK(memcmp(nonce2, nonce3, 32) != 0); CHECK(memcmp(nonce2, nonce4, 32) != 0); CHECK(memcmp(nonce3, nonce4, 32) != 0); } /* Privkey export where pubkey is the point at infinity. */ { unsigned char privkey[300]; unsigned char seckey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, }; size_t outlen = 300; CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0)); outlen = 300; CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 1)); } } void run_ecdsa_edge_cases(void) { test_ecdsa_edge_cases(); } #ifdef ENABLE_OPENSSL_TESTS EC_KEY *get_openssl_key(const unsigned char *key32) { unsigned char privkey[300]; size_t privkeylen; const unsigned char* pbegin = privkey; int compr = secp256k1_rand_bits(1); EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); CHECK(ec_privkey_export_der(ctx, privkey, &privkeylen, key32, compr)); CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); CHECK(EC_KEY_check_key(ec_key)); return ec_key; } void test_ecdsa_openssl(void) { secp256k1_gej qj; secp256k1_ge q; secp256k1_scalar sigr, sigs; secp256k1_scalar one; secp256k1_scalar msg2; secp256k1_scalar key, msg; EC_KEY *ec_key; unsigned int sigsize = 80; size_t secp_sigsize = 80; unsigned char message[32]; unsigned char signature[80]; unsigned char key32[32]; secp256k1_rand256_test(message); secp256k1_scalar_set_b32(&msg, message, NULL); random_scalar_order_test(&key); secp256k1_scalar_get_b32(key32, &key); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &qj, &key); secp256k1_ge_set_gej(&q, &qj); ec_key = get_openssl_key(key32); CHECK(ec_key != NULL); CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize)); CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg)); secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_add(&msg2, &msg, &one); CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2)); random_sign(&sigr, &sigs, &key, &msg, NULL); CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs)); CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); EC_KEY_free(ec_key); } void run_ecdsa_openssl(void) { int i; for (i = 0; i < 10*count; i++) { test_ecdsa_openssl(); } } #endif #ifdef ENABLE_MODULE_ECDH # include "modules/ecdh/tests_impl.h" #endif #ifdef ENABLE_MODULE_MULTISET # include "modules/multiset/tests_impl.h" #endif #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/tests_impl.h" #endif #ifdef ENABLE_MODULE_SCHNORR # include "modules/schnorr/tests_impl.h" #endif int main(int argc, char **argv) { unsigned char seed16[16] = {0}; unsigned char run32[32] = {0}; /* find iteration count */ if (argc > 1) { count = strtol(argv[1], NULL, 0); } /* find random seed */ if (argc > 2) { int pos = 0; const char* ch = argv[2]; while (pos < 16 && ch[0] != 0 && ch[1] != 0) { unsigned short sh; if (sscanf(ch, "%2hx", &sh)) { seed16[pos] = sh; } else { break; } ch += 2; pos++; } } else { FILE *frand = fopen("/dev/urandom", "r"); if ((frand == NULL) || fread(&seed16, sizeof(seed16), 1, frand) != sizeof(seed16)) { uint64_t t = time(NULL) * (uint64_t)1337; seed16[0] ^= t; seed16[1] ^= t >> 8; seed16[2] ^= t >> 16; seed16[3] ^= t >> 24; seed16[4] ^= t >> 32; seed16[5] ^= t >> 40; seed16[6] ^= t >> 48; seed16[7] ^= t >> 56; } if (frand) { fclose(frand); } } secp256k1_rand_seed(seed16); printf("test count = %i\n", count); printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); /* initialize */ run_context_tests(); + run_scratch_tests(); ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); if (secp256k1_rand_bits(1)) { secp256k1_rand256(run32); CHECK(secp256k1_context_randomize(ctx, secp256k1_rand_bits(1) ? run32 : NULL)); } run_rand_bits(); run_rand_int(); run_sha256_tests(); run_hmac_sha256_tests(); run_rfc6979_hmac_sha256_tests(); #ifndef USE_NUM_NONE /* num tests */ run_num_smalltests(); #endif /* scalar tests */ run_scalar_tests(); /* field tests */ run_field_inv(); run_field_inv_var(); run_field_inv_all_var(); run_field_misc(); run_field_convert(); run_sqr(); run_sqrt(); /* group tests */ run_ge(); run_group_decompress(); /* ecmult tests */ run_wnaf(); run_point_times_order(); run_ecmult_chain(); run_ecmult_constants(); run_ecmult_gen_blind(); run_ecmult_const_tests(); + run_ecmult_multi_tests(); run_ec_combine(); /* endomorphism tests */ #ifdef USE_ENDOMORPHISM run_endomorphism_tests(); #endif /* EC point parser test */ run_ec_pubkey_parse_test(); /* EC key edge cases */ run_eckey_edge_case_test(); #ifdef ENABLE_MODULE_ECDH /* ecdh tests */ run_ecdh_tests(); #endif /* ecdsa tests */ run_random_pubkeys(); run_ecdsa_der_parse(); run_ecdsa_sign_verify(); run_ecdsa_end_to_end(); run_ecdsa_edge_cases(); #ifdef ENABLE_OPENSSL_TESTS run_ecdsa_openssl(); #endif #ifdef ENABLE_MODULE_MULTISET run_multiset_tests(); #endif #ifdef ENABLE_MODULE_RECOVERY /* ECDSA pubkey recovery tests */ run_recovery_tests(); #endif #ifdef ENABLE_MODULE_SCHNORR /* Schnorr signature tests */ run_schnorr_tests(); #endif secp256k1_rand256(run32); printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); /* shutdown */ secp256k1_context_destroy(ctx); printf("no problems found\n"); return 0; } diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c index b040bb0733..141645eaeb 100644 --- a/src/secp256k1/src/tests_exhaustive.c +++ b/src/secp256k1/src/tests_exhaustive.c @@ -1,470 +1,511 @@ /*********************************************************************** * Copyright (c) 2016 Andrew Poelstra * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #include #include #include #undef USE_ECMULT_STATIC_PRECOMPUTATION #ifndef EXHAUSTIVE_TEST_ORDER /* see group_impl.h for allowable values */ #define EXHAUSTIVE_TEST_ORDER 13 #define EXHAUSTIVE_TEST_LAMBDA 9 /* cube root of 1 mod 13 */ #endif #include "include/secp256k1.h" #include "group.h" #include "secp256k1.c" #include "testrand_impl.h" #ifdef ENABLE_MODULE_RECOVERY #include "src/modules/recovery/main_impl.h" #include "include/secp256k1_recovery.h" #endif /** stolen from tests.c */ void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { CHECK(a->infinity == b->infinity); if (a->infinity) { return; } CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); } void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { secp256k1_fe z2s; secp256k1_fe u1, u2, s1, s2; CHECK(a->infinity == b->infinity); if (a->infinity) { return; } /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ secp256k1_fe_sqr(&z2s, &b->z); secp256k1_fe_mul(&u1, &a->x, &z2s); u2 = b->x; secp256k1_fe_normalize_weak(&u2); secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); s2 = b->y; secp256k1_fe_normalize_weak(&s2); CHECK(secp256k1_fe_equal_var(&u1, &u2)); CHECK(secp256k1_fe_equal_var(&s1, &s2)); } void random_fe(secp256k1_fe *x) { unsigned char bin[32]; do { secp256k1_rand256(bin); if (secp256k1_fe_set_b32(x, bin)) { return; } } while(1); } /** END stolen from tests.c */ int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int attempt) { secp256k1_scalar s; int *idata = data; (void)msg32; (void)key32; (void)algo16; /* Some nonces cannot be used because they'd cause s and/or r to be zero. * The signing function has retry logic here that just re-calls the nonce * function with an increased `attempt`. So if attempt > 0 this means we * need to change the nonce to avoid an infinite loop. */ if (attempt > 0) { *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; } secp256k1_scalar_set_int(&s, *idata); secp256k1_scalar_get_b32(nonce32, &s); return 1; } #ifdef USE_ENDOMORPHISM void test_exhaustive_endomorphism(const secp256k1_ge *group, int order) { int i; for (i = 0; i < order; i++) { secp256k1_ge res; secp256k1_ge_mul_lambda(&res, &group[i]); ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); } } #endif void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { int i, j; /* Sanity-check (and check infinity functions) */ CHECK(secp256k1_ge_is_infinity(&group[0])); CHECK(secp256k1_gej_is_infinity(&groupj[0])); for (i = 1; i < order; i++) { CHECK(!secp256k1_ge_is_infinity(&group[i])); CHECK(!secp256k1_gej_is_infinity(&groupj[i])); } /* Check all addition formulae */ for (j = 0; j < order; j++) { secp256k1_fe fe_inv; secp256k1_fe_inv(&fe_inv, &groupj[j].z); for (i = 0; i < order; i++) { secp256k1_ge zless_gej; secp256k1_gej tmp; /* add_var */ secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); ge_equals_gej(&group[(i + j) % order], &tmp); /* add_ge */ if (j > 0) { secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); ge_equals_gej(&group[(i + j) % order], &tmp); } /* add_ge_var */ secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); ge_equals_gej(&group[(i + j) % order], &tmp); /* add_zinv_var */ zless_gej.infinity = groupj[j].infinity; zless_gej.x = groupj[j].x; zless_gej.y = groupj[j].y; secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); ge_equals_gej(&group[(i + j) % order], &tmp); } } /* Check doubling */ for (i = 0; i < order; i++) { secp256k1_gej tmp; if (i > 0) { secp256k1_gej_double_nonzero(&tmp, &groupj[i], NULL); ge_equals_gej(&group[(2 * i) % order], &tmp); } secp256k1_gej_double_var(&tmp, &groupj[i], NULL); ge_equals_gej(&group[(2 * i) % order], &tmp); } /* Check negation */ for (i = 1; i < order; i++) { secp256k1_ge tmp; secp256k1_gej tmpj; secp256k1_ge_neg(&tmp, &group[i]); ge_equals_ge(&group[order - i], &tmp); secp256k1_gej_neg(&tmpj, &groupj[i]); ge_equals_gej(&group[order - i], &tmpj); } } void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { int i, j, r_log; for (r_log = 1; r_log < order; r_log++) { for (j = 0; j < order; j++) { for (i = 0; i < order; i++) { secp256k1_gej tmp; secp256k1_scalar na, ng; secp256k1_scalar_set_int(&na, i); secp256k1_scalar_set_int(&ng, j); secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); ge_equals_gej(&group[(i * r_log + j) % order], &tmp); if (i > 0) { secp256k1_ecmult_const(&tmp, &group[i], &ng); ge_equals_gej(&group[(i * j) % order], &tmp); } } } } } +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, 1024, 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) { secp256k1_fe x; unsigned char x_bin[32]; k %= EXHAUSTIVE_TEST_ORDER; x = group[k].x; secp256k1_fe_normalize(&x); secp256k1_fe_get_b32(x_bin, &x); secp256k1_scalar_set_b32(r, x_bin, NULL); } void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { int s, r, msg, key; for (s = 1; s < order; s++) { for (r = 1; r < order; r++) { for (msg = 1; msg < order; msg++) { for (key = 1; key < order; key++) { secp256k1_ge nonconst_ge; secp256k1_ecdsa_signature sig; secp256k1_pubkey pk; secp256k1_scalar sk_s, msg_s, r_s, s_s; secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; int k, should_verify; unsigned char msg32[32]; secp256k1_scalar_set_int(&s_s, s); secp256k1_scalar_set_int(&r_s, r); secp256k1_scalar_set_int(&msg_s, msg); secp256k1_scalar_set_int(&sk_s, key); /* Verify by hand */ /* Run through every k value that gives us this r and check that *one* works. * Note there could be none, there could be multiple, ECDSA is weird. */ should_verify = 0; for (k = 0; k < order; k++) { secp256k1_scalar check_x_s; r_from_k(&check_x_s, group, k); if (r_s == check_x_s) { secp256k1_scalar_set_int(&s_times_k_s, k); secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); } } /* nb we have a "high s" rule */ should_verify &= !secp256k1_scalar_is_high(&s_s); /* Verify by calling verify */ secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s); memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); secp256k1_pubkey_save(&pk, &nonconst_ge); secp256k1_scalar_get_b32(msg32, &msg_s); CHECK(should_verify == secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); } } } } } void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { int i, j, k; /* Loop */ for (i = 1; i < order; i++) { /* message */ for (j = 1; j < order; j++) { /* key */ for (k = 1; k < order; k++) { /* nonce */ const int starting_k = k; secp256k1_ecdsa_signature sig; secp256k1_scalar sk, msg, r, s, expected_r; unsigned char sk32[32], msg32[32]; secp256k1_scalar_set_int(&msg, i); secp256k1_scalar_set_int(&sk, j); secp256k1_scalar_get_b32(sk32, &sk); secp256k1_scalar_get_b32(msg32, &msg); secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); /* Note that we compute expected_r *after* signing -- this is important * because our nonce-computing function function might change k during * signing. */ r_from_k(&expected_r, group, k); CHECK(r == expected_r); CHECK((k * s) % order == (i + r * j) % order || (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); /* Overflow means we've tried every possible nonce */ if (k < starting_k) { break; } } } } /* We would like to verify zero-knowledge here by counting how often every * possible (s, r) tuple appears, but because the group order is larger * than the field order, when coercing the x-values to scalar values, some * appear more often than others, so we are actually not zero-knowledge. * (This effect also appears in the real code, but the difference is on the * order of 1/2^128th the field order, so the deviation is not useful to a * computationally bounded attacker.) */ } #ifdef ENABLE_MODULE_RECOVERY void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { int i, j, k; /* Loop */ for (i = 1; i < order; i++) { /* message */ for (j = 1; j < order; j++) { /* key */ for (k = 1; k < order; k++) { /* nonce */ const int starting_k = k; secp256k1_fe r_dot_y_normalized; secp256k1_ecdsa_recoverable_signature rsig; secp256k1_ecdsa_signature sig; secp256k1_scalar sk, msg, r, s, expected_r; unsigned char sk32[32], msg32[32]; int expected_recid; int recid; secp256k1_scalar_set_int(&msg, i); secp256k1_scalar_set_int(&sk, j); secp256k1_scalar_get_b32(sk32, &sk); secp256k1_scalar_get_b32(msg32, &msg); secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); /* Check directly */ secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); r_from_k(&expected_r, group, k); CHECK(r == expected_r); CHECK((k * s) % order == (i + r * j) % order || (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); /* In computing the recid, there is an overflow condition that is disabled in * scalar_low_impl.h `secp256k1_scalar_set_b32` because almost every r.y value * will exceed the group order, and our signing code always holds out for r * values that don't overflow, so with a proper overflow check the tests would * loop indefinitely. */ r_dot_y_normalized = group[k].y; secp256k1_fe_normalize(&r_dot_y_normalized); /* Also the recovery id is flipped depending if we hit the low-s branch */ if ((k * s) % order == (i + r * j) % order) { expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; } else { expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; } CHECK(recid == expected_recid); /* Convert to a standard sig then check */ secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); /* Note that we compute expected_r *after* signing -- this is important * because our nonce-computing function function might change k during * signing. */ r_from_k(&expected_r, group, k); CHECK(r == expected_r); CHECK((k * s) % order == (i + r * j) % order || (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); /* Overflow means we've tried every possible nonce */ if (k < starting_k) { break; } } } } } void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { /* This is essentially a copy of test_exhaustive_verify, with recovery added */ int s, r, msg, key; for (s = 1; s < order; s++) { for (r = 1; r < order; r++) { for (msg = 1; msg < order; msg++) { for (key = 1; key < order; key++) { secp256k1_ge nonconst_ge; secp256k1_ecdsa_recoverable_signature rsig; secp256k1_ecdsa_signature sig; secp256k1_pubkey pk; secp256k1_scalar sk_s, msg_s, r_s, s_s; secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; int recid = 0; int k, should_verify; unsigned char msg32[32]; secp256k1_scalar_set_int(&s_s, s); secp256k1_scalar_set_int(&r_s, r); secp256k1_scalar_set_int(&msg_s, msg); secp256k1_scalar_set_int(&sk_s, key); secp256k1_scalar_get_b32(msg32, &msg_s); /* Verify by hand */ /* Run through every k value that gives us this r and check that *one* works. * Note there could be none, there could be multiple, ECDSA is weird. */ should_verify = 0; for (k = 0; k < order; k++) { secp256k1_scalar check_x_s; r_from_k(&check_x_s, group, k); if (r_s == check_x_s) { secp256k1_scalar_set_int(&s_times_k_s, k); secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); } } /* nb we have a "high s" rule */ should_verify &= !secp256k1_scalar_is_high(&s_s); /* We would like to try recovering the pubkey and checking that it matches, * but pubkey recovery is impossible in the exhaustive tests (the reason * being that there are 12 nonzero r values, 12 nonzero points, and no * overlap between the sets, so there are no valid signatures). */ /* Verify by converting to a standard signature and calling verify */ secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); secp256k1_pubkey_save(&pk, &nonconst_ge); CHECK(should_verify == secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); } } } } } #endif int main(void) { int i; secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; /* Build context */ secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); /* TODO set z = 1, then do num_tests runs with random z values */ /* Generate the entire group */ secp256k1_gej_set_infinity(&groupj[0]); secp256k1_ge_set_gej(&group[0], &groupj[0]); for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { /* Set a different random z-value for each Jacobian point */ secp256k1_fe z; random_fe(&z); secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); secp256k1_ge_set_gej(&group[i], &groupj[i]); secp256k1_gej_rescale(&groupj[i], &z); /* Verify against ecmult_gen */ { secp256k1_scalar scalar_i; secp256k1_gej generatedj; secp256k1_ge generated; secp256k1_scalar_set_int(&scalar_i, i); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); secp256k1_ge_set_gej(&generated, &generatedj); CHECK(group[i].infinity == 0); CHECK(generated.infinity == 0); CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x)); CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y)); } } /* Run the tests */ #ifdef USE_ENDOMORPHISM test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); #endif test_exhaustive_addition(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_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); #ifdef ENABLE_MODULE_RECOVERY test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); #endif secp256k1_context_destroy(ctx); return 0; } diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h index b0441d8e30..e0147500f9 100644 --- a/src/secp256k1/src/util.h +++ b/src/secp256k1/src/util.h @@ -1,113 +1,121 @@ /********************************************************************** * Copyright (c) 2013, 2014 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ #ifndef SECP256K1_UTIL_H #define SECP256K1_UTIL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #include #include #include typedef struct { void (*fn)(const char *text, void* data); const void* data; } secp256k1_callback; static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) { cb->fn(text, (void*)cb->data); } #ifdef DETERMINISTIC #define TEST_FAILURE(msg) do { \ fprintf(stderr, "%s\n", msg); \ abort(); \ } while(0); #else #define TEST_FAILURE(msg) do { \ fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ abort(); \ } while(0) #endif #ifdef HAVE_BUILTIN_EXPECT #define EXPECT(x,c) __builtin_expect((x),(c)) #else #define EXPECT(x,c) (x) #endif #ifdef DETERMINISTIC #define CHECK(cond) do { \ if (EXPECT(!(cond), 0)) { \ TEST_FAILURE("test condition failed"); \ } \ } while(0) #else #define CHECK(cond) do { \ if (EXPECT(!(cond), 0)) { \ TEST_FAILURE("test condition failed: " #cond); \ } \ } while(0) #endif /* Like assert(), but when VERIFY is defined, and side-effect safe. */ #if defined(COVERAGE) #define VERIFY_CHECK(check) #define VERIFY_SETUP(stmt) #elif defined(VERIFY) #define VERIFY_CHECK CHECK #define VERIFY_SETUP(stmt) do { stmt; } while(0) #else #define VERIFY_CHECK(cond) do { (void)(cond); } while(0) #define VERIFY_SETUP(stmt) #endif static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) { void *ret = malloc(size); if (ret == NULL) { secp256k1_callback_call(cb, "Out of memory"); } 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. */ #if defined(SECP256K1_BUILD) && defined(VERIFY) # define SECP256K1_RESTRICT #else # if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) # if SECP256K1_GNUC_PREREQ(3,0) # define SECP256K1_RESTRICT __restrict__ # elif (defined(_MSC_VER) && _MSC_VER >= 1400) # define SECP256K1_RESTRICT __restrict # else # define SECP256K1_RESTRICT # endif # else # define SECP256K1_RESTRICT restrict # endif #endif #if defined(_WIN32) # define I64FORMAT "I64d" # define I64uFORMAT "I64u" #else # define I64FORMAT "lld" # define I64uFORMAT "llu" #endif #if defined(HAVE___INT128) # if defined(__GNUC__) # define SECP256K1_GNUC_EXT __extension__ # else # define SECP256K1_GNUC_EXT # endif SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; #endif #endif /* SECP256K1_UTIL_H */