diff --git a/src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 b/src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 index 77fd346a7..7bcbf3200 100644 --- a/src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 +++ b/src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 @@ -1,125 +1,125 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html +# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html # =========================================================================== # # SYNOPSIS # # AX_PROG_CC_FOR_BUILD # # DESCRIPTION # # This macro searches for a C compiler that generates native executables, # that is a C compiler that surely is not a cross-compiler. This can be # useful if you have to generate source code at compile-time like for # example GCC does. # # The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything # needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). # The value of these variables can be overridden by the user by specifying # a compiler with an environment variable (like you do for standard CC). # # It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object # file extensions for the build platform, and GCC_FOR_BUILD to `yes' if # the compiler we found is GCC. All these variables but GCC_FOR_BUILD are # substituted in the Makefile. # # LICENSE # # Copyright (c) 2008 Paolo Bonzini # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 8 AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_CPP])dnl AC_REQUIRE([AC_EXEEXT])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl dnl Use the standard macros, but make them use other variable names dnl pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl pushdef([ac_cv_objext], ac_cv_build_objext)dnl pushdef([ac_exeext], ac_build_exeext)dnl pushdef([ac_objext], ac_build_objext)dnl pushdef([CC], CC_FOR_BUILD)dnl pushdef([CPP], CPP_FOR_BUILD)dnl pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl pushdef([host], build)dnl pushdef([host_alias], build_alias)dnl pushdef([host_cpu], build_cpu)dnl pushdef([host_vendor], build_vendor)dnl pushdef([host_os], build_os)dnl pushdef([ac_cv_host], ac_cv_build)dnl pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl pushdef([ac_cv_host_os], ac_cv_build_os)dnl pushdef([ac_cpp], ac_build_cpp)dnl pushdef([ac_compile], ac_build_compile)dnl pushdef([ac_link], ac_build_link)dnl save_cross_compiling=$cross_compiling save_ac_tool_prefix=$ac_tool_prefix cross_compiling=no ac_tool_prefix= AC_PROG_CC AC_PROG_CPP AC_EXEEXT ac_tool_prefix=$save_ac_tool_prefix cross_compiling=$save_cross_compiling dnl Restore the old definitions dnl popdef([ac_link])dnl popdef([ac_compile])dnl popdef([ac_cpp])dnl popdef([ac_cv_host_os])dnl popdef([ac_cv_host_vendor])dnl popdef([ac_cv_host_cpu])dnl popdef([ac_cv_host_alias])dnl popdef([ac_cv_host])dnl popdef([host_os])dnl popdef([host_vendor])dnl popdef([host_cpu])dnl popdef([host_alias])dnl popdef([host])dnl popdef([LDFLAGS])dnl popdef([CPPFLAGS])dnl popdef([CFLAGS])dnl popdef([CPP])dnl popdef([CC])dnl popdef([ac_objext])dnl popdef([ac_exeext])dnl popdef([ac_cv_objext])dnl popdef([ac_cv_exeext])dnl popdef([ac_cv_prog_cc_g])dnl popdef([ac_cv_prog_cc_cross])dnl popdef([ac_cv_prog_cc_works])dnl popdef([ac_cv_prog_gcc])dnl popdef([ac_cv_prog_CPP])dnl dnl Finally, set Makefile variables dnl BUILD_EXEEXT=$ac_build_exeext BUILD_OBJEXT=$ac_build_objext AC_SUBST(BUILD_EXEEXT)dnl AC_SUBST(BUILD_OBJEXT)dnl AC_SUBST([CFLAGS_FOR_BUILD])dnl AC_SUBST([CPPFLAGS_FOR_BUILD])dnl AC_SUBST([LDFLAGS_FOR_BUILD])dnl ]) diff --git a/src/secp256k1/contrib/lax_der_parsing.c b/src/secp256k1/contrib/lax_der_parsing.c index f71db4b53..c1627e37e 100644 --- a/src/secp256k1/contrib/lax_der_parsing.c +++ b/src/secp256k1/contrib/lax_der_parsing.c @@ -1,149 +1,149 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include #include #include "lax_der_parsing.h" int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { size_t rpos, rlen, spos, slen; size_t pos = 0; size_t lenbyte; unsigned char tmpsig[64] = {0}; int overflow = 0; /* Hack to initialize sig with a correctly-parsed but invalid signature. */ secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); /* Sequence tag byte */ if (pos == inputlen || input[pos] != 0x30) { return 0; } pos++; /* Sequence length bytes */ if (pos == inputlen) { return 0; } lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; if (lenbyte > inputlen - pos) { return 0; } pos += lenbyte; } /* Integer tag byte for R */ if (pos == inputlen || input[pos] != 0x02) { return 0; } pos++; /* Integer length for R */ if (pos == inputlen) { return 0; } lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; if (lenbyte > inputlen - pos) { return 0; } while (lenbyte > 0 && input[pos] == 0) { pos++; lenbyte--; } if (lenbyte >= sizeof(size_t)) { return 0; } rlen = 0; while (lenbyte > 0) { rlen = (rlen << 8) + input[pos]; pos++; lenbyte--; } } else { rlen = lenbyte; } if (rlen > inputlen - pos) { return 0; } rpos = pos; pos += rlen; /* Integer tag byte for S */ if (pos == inputlen || input[pos] != 0x02) { return 0; } pos++; /* Integer length for S */ if (pos == inputlen) { return 0; } lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; if (lenbyte > inputlen - pos) { return 0; } while (lenbyte > 0 && input[pos] == 0) { pos++; lenbyte--; } if (lenbyte >= sizeof(size_t)) { return 0; } slen = 0; while (lenbyte > 0) { slen = (slen << 8) + input[pos]; pos++; lenbyte--; } } else { slen = lenbyte; } if (slen > inputlen - pos) { return 0; } spos = pos; /* Ignore leading zeroes in R */ while (rlen > 0 && input[rpos] == 0) { rlen--; rpos++; } /* Copy R value */ if (rlen > 32) { overflow = 1; } else { memcpy(tmpsig + 32 - rlen, input + rpos, rlen); } /* Ignore leading zeroes in S */ while (slen > 0 && input[spos] == 0) { slen--; spos++; } /* Copy S value */ if (slen > 32) { overflow = 1; } else { memcpy(tmpsig + 64 - slen, input + spos, slen); } if (!overflow) { overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); } if (overflow) { memset(tmpsig, 0, 64); secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); } return 1; } diff --git a/src/secp256k1/contrib/lax_der_parsing.h b/src/secp256k1/contrib/lax_der_parsing.h index 7eaf63bf6..6b7255e28 100644 --- a/src/secp256k1/contrib/lax_der_parsing.h +++ b/src/secp256k1/contrib/lax_der_parsing.h @@ -1,91 +1,91 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ /**** * Please do not link this file directly. It is not part of the libsecp256k1 * project and does not promise any stability in its API, functionality or * presence. Projects which use this code should instead copy this header * and its accompanying .c file directly into their codebase. ****/ /* This file defines a function that parses DER with various errors and * violations. This is not a part of the library itself, because the allowed * violations are chosen arbitrarily and do not follow or establish any * standard. * * In many places it matters that different implementations do not only accept * the same set of valid signatures, but also reject the same set of signatures. * The only means to accomplish that is by strictly obeying a standard, and not * accepting anything else. * * Nonetheless, sometimes there is a need for compatibility with systems that * use signatures which do not strictly obey DER. The snippet below shows how * certain violations are easily supported. You may need to adapt it. * * Do not use this for new systems. Use well-defined DER or compact signatures * instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and * secp256k1_ecdsa_signature_parse_compact). * * The supported violations are: * - All numbers are parsed as nonnegative integers, even though X.609-0207 * section 8.3.3 specifies that integers are always encoded as two's * complement. * - Integers can have length 0, even though section 8.3.1 says they can't. * - Integers with overly long padding are accepted, violation section * 8.3.2. * - 127-byte long length descriptors are accepted, even though section * 8.1.3.5.c says that they are not. * - Trailing garbage data inside or after the signature is ignored. * - The length descriptor of the sequence is ignored. * * Compared to for example OpenSSL, many violations are NOT supported: * - Using overly long tag descriptors for the sequence or integers inside, * violating section 8.1.2.2. * - Encoding primitive integers as constructed values, violating section * 8.3.1. */ #ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H #define SECP256K1_CONTRIB_LAX_DER_PARSING_H #include #ifdef __cplusplus extern "C" { #endif /** Parse a signature in "lax DER" 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: 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. In addition, it will accept signatures * which violate the DER spec in various ways. Its purpose is to allow * validation of the Bitcoin blockchain, which includes non-DER signatures * from before the network rules were updated to enforce DER. Note that * the set of supported violations is a strict subset of what OpenSSL will * accept. * * 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. */ int ecdsa_signature_parse_der_lax( 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); #ifdef __cplusplus } #endif #endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */ diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.c b/src/secp256k1/contrib/lax_der_privatekey_parsing.c index c2e63b4b8..429760fbb 100644 --- a/src/secp256k1/contrib/lax_der_privatekey_parsing.c +++ b/src/secp256k1/contrib/lax_der_privatekey_parsing.c @@ -1,113 +1,113 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014, 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include #include #include "lax_der_privatekey_parsing.h" int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { const unsigned char *end = privkey + privkeylen; int lenb = 0; int len = 0; memset(out32, 0, 32); /* sequence header */ if (end < privkey+1 || *privkey != 0x30) { return 0; } privkey++; /* sequence length constructor */ if (end < privkey+1 || !(*privkey & 0x80)) { return 0; } lenb = *privkey & ~0x80; privkey++; if (lenb < 1 || lenb > 2) { return 0; } if (end < privkey+lenb) { return 0; } /* sequence length */ len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); privkey += lenb; if (end < privkey+len) { return 0; } /* sequence element 0: version number (=1) */ if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { return 0; } privkey += 3; /* sequence element 1: octet string, up to 32 bytes */ if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { return 0; } memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); if (!secp256k1_ec_seckey_verify(ctx, out32)) { memset(out32, 0, 32); return 0; } return 1; } int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { secp256k1_pubkey pubkey; size_t pubkeylen = 0; if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { *privkeylen = 0; return 0; } if (compressed) { static const unsigned char begin[] = { 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 }; static const unsigned char middle[] = { 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, 0xCE,0x3D,0x01,0x01,0x02,0x21,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,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, 0x21,0x02,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,0x02,0x21,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,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 }; unsigned char *ptr = privkey; memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); pubkeylen = 33; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; } else { static const unsigned char begin[] = { 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 }; static const unsigned char middle[] = { 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, 0xCE,0x3D,0x01,0x01,0x02,0x21,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,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, 0x41,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,0x02,0x21,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,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 }; unsigned char *ptr = privkey; memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); pubkeylen = 65; secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; } return 1; } diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.h b/src/secp256k1/contrib/lax_der_privatekey_parsing.h index fece261fb..602c7c556 100644 --- a/src/secp256k1/contrib/lax_der_privatekey_parsing.h +++ b/src/secp256k1/contrib/lax_der_privatekey_parsing.h @@ -1,90 +1,90 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014, 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ /**** * Please do not link this file directly. It is not part of the libsecp256k1 * project and does not promise any stability in its API, functionality or * presence. Projects which use this code should instead copy this header * and its accompanying .c file directly into their codebase. ****/ /* This file contains code snippets that parse DER private keys with * various errors and violations. This is not a part of the library * itself, because the allowed violations are chosen arbitrarily and * do not follow or establish any standard. * * It also contains code to serialize private keys in a compatible * manner. * * These functions are meant for compatibility with applications * that require BER encoded keys. When working with secp256k1-specific * code, the simple 32-byte private keys normally used by the * library are sufficient. */ #ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H #define SECP256K1_CONTRIB_BER_PRIVATEKEY_H #include #ifdef __cplusplus extern "C" { #endif /** Export a private key in DER format. * * Returns: 1 if the private key was valid. * Args: ctx: pointer to a context object, initialized for signing (cannot * be NULL) * Out: privkey: pointer to an array for storing the private key in BER. * Should have space for 279 bytes, and cannot be NULL. * privkeylen: Pointer to an int where the length of the private key in * privkey will be stored. * In: seckey: pointer to a 32-byte secret key to export. * compressed: 1 if the key should be exported in * compressed format, 0 otherwise * * This function is purely meant for compatibility with applications that * require BER encoded keys. When working with secp256k1-specific code, the * simple 32-byte private keys are sufficient. * * Note that this function does not guarantee correct DER output. It is * guaranteed to be parsable by secp256k1_ec_privkey_import_der */ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( const secp256k1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, int compressed ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Import a private key in DER format. * Returns: 1 if a private key was extracted. * Args: ctx: pointer to a context object (cannot be NULL). * Out: seckey: pointer to a 32-byte array for storing the private key. * (cannot be NULL). * In: privkey: pointer to a private key in DER format (cannot be NULL). * privkeylen: length of the DER private key pointed to be privkey. * * This function will accept more than just strict DER, and even allow some BER * violations. The public key stored inside the DER-encoded private key is not * verified for correctness, nor are the curve parameters. Use this function * only if you know in advance it is supposed to contain a secp256k1 private * key. */ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *privkey, size_t privkeylen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); #ifdef __cplusplus } #endif #endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */ diff --git a/src/secp256k1/include/secp256k1_multiset.h b/src/secp256k1/include/secp256k1_multiset.h index feb1afc4e..8712edf95 100644 --- a/src/secp256k1/include/secp256k1_multiset.h +++ b/src/secp256k1/include/secp256k1_multiset.h @@ -1,110 +1,110 @@ -/********************************************************************** - * Copyright (c) 2017 Tomas van der Wansem * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Tomas van der Wansem * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MULTISET__ # define _SECP256K1_MULTISET__ # include "secp256k1.h" # ifdef __cplusplus extern "C" { # endif /** Opaque multiset; this is actually a group element **/ typedef struct { unsigned char d[96]; } secp256k1_multiset; /** Initialize a multiset * The resulting multiset the multiset for no data elements * * Returns: 1: success * 0: invalid parameter * Args: ctx: pointer to a context object (cannot be NULL) * Out: multiset: the resulting multiset */ SECP256K1_API int secp256k1_multiset_init( const secp256k1_context* ctx, secp256k1_multiset *multiset ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); /** Adds an element to a multiset from single data element * * Returns: 1: success * 0: invalid parameter * Args: ctx: pointer to a context object (cannot be NULL) * Out: multiset: the multiset to update * In: input: the data to add * inputLen: the size of the data to add */ SECP256K1_API int secp256k1_multiset_add( const secp256k1_context* ctx, secp256k1_multiset *multiset, const unsigned char *input, size_t inputLen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Removes an element from a multiset * * Returns: 1: success * 0: invalid parameter * Args: ctx: pointer to a context object (cannot be NULL) * Out: multiset: the multiset to update * In: input: the data to remove * inputLen: the size of the data to remove */ SECP256K1_API int secp256k1_multiset_remove( const secp256k1_context* ctx, secp256k1_multiset *multiset, const unsigned char *input, size_t inputLen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Combines two multisets * * Returns: 1: success * 0: invalid parameter * Args: ctx: pointer to a context object (cannot be NULL) * In/Out: multiset: the multiset to which the input must be added * In: input: the multiset to add */ SECP256K1_API int secp256k1_multiset_combine( const secp256k1_context* ctx, secp256k1_multiset *multiset, const secp256k1_multiset *input ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Converts a multiset to a hash * * Returns: 1: success * 0: invalid parameter * Args: ctx: pointer to a context object (cannot be NULL) * Out: hash: the resulting 32-byte hash * In: multiset: the multiset to hash */ SECP256K1_API int secp256k1_multiset_finalize( const secp256k1_context* ctx, unsigned char *resultHash, const secp256k1_multiset *multiset ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); # ifdef __cplusplus } # endif #endif diff --git a/src/secp256k1/sage/group_prover.sage b/src/secp256k1/sage/group_prover.sage index 53ffee24c..b200bfeae 100644 --- a/src/secp256k1/sage/group_prover.sage +++ b/src/secp256k1/sage/group_prover.sage @@ -1,327 +1,327 @@ # This code supports verifying group implementations which have branches # or conditional statements (like cmovs), by allowing each execution path # to independently set assumptions on input or intermediary variables. # # The general approach is: # * A constraint is a tuple of two sets of symbolic expressions: # the first of which are required to evaluate to zero, the second of which # are required to evaluate to nonzero. # - A constraint is said to be conflicting if any of its nonzero expressions # is in the ideal with basis the zero expressions (in other words: when the # zero expressions imply that one of the nonzero expressions are zero). # * There is a list of laws that describe the intended behaviour, including # laws for addition and doubling. Each law is called with the symbolic point # coordinates as arguments, and returns: # - A constraint describing the assumptions under which it is applicable, # called "assumeLaw" # - A constraint describing the requirements of the law, called "require" # * Implementations are transliterated into functions that operate as well on # algebraic input points, and are called once per combination of branches # executed. Each execution returns: # - A constraint describing the assumptions this implementation requires # (such as Z1=1), called "assumeFormula" # - A constraint describing the assumptions this specific branch requires, # but which is by construction guaranteed to cover the entire space by # merging the results from all branches, called "assumeBranch" # - The result of the computation # * All combinations of laws with implementation branches are tried, and: # - If the combination of assumeLaw, assumeFormula, and assumeBranch results # in a conflict, it means this law does not apply to this branch, and it is # skipped. # - For others, we try to prove the require constraints hold, assuming the # information in assumeLaw + assumeFormula + assumeBranch, and if this does # not succeed, we fail. # + To prove an expression is zero, we check whether it belongs to the # ideal with the assumed zero expressions as basis. This test is exact. # + To prove an expression is nonzero, we check whether each of its # factors is contained in the set of nonzero assumptions' factors. # This test is not exact, so various combinations of original and # reduced expressions' factors are tried. # - If we succeed, we print out the assumptions from assumeFormula that # weren't implied by assumeLaw already. Those from assumeBranch are skipped, # as we assume that all constraints in it are complementary with each other. # # Based on the sage verification scripts used in the Explicit-Formulas Database -# by Tanja Lange and others, see http://hyperelliptic.org/EFD +# by Tanja Lange and others, see https://hyperelliptic.org/EFD class fastfrac: """Fractions over rings.""" def __init__(self,R,top,bot=1): """Construct a fractional, given a ring, a numerator, and denominator.""" self.R = R if parent(top) == ZZ or parent(top) == R: self.top = R(top) self.bot = R(bot) elif top.__class__ == fastfrac: self.top = top.top self.bot = top.bot * bot else: self.top = R(numerator(top)) self.bot = R(denominator(top)) * bot def iszero(self,I): """Return whether this fraction is zero given an ideal.""" return self.top in I and self.bot not in I def reduce(self,assumeZero): zero = self.R.ideal(list(map(numerator, assumeZero))) return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot)) def __add__(self,other): """Add two fractions.""" if parent(other) == ZZ: return fastfrac(self.R,self.top + self.bot * other,self.bot) if other.__class__ == fastfrac: return fastfrac(self.R,self.top * other.bot + self.bot * other.top,self.bot * other.bot) return NotImplemented def __sub__(self,other): """Subtract two fractions.""" if parent(other) == ZZ: return fastfrac(self.R,self.top - self.bot * other,self.bot) if other.__class__ == fastfrac: return fastfrac(self.R,self.top * other.bot - self.bot * other.top,self.bot * other.bot) return NotImplemented def __neg__(self): """Return the negation of a fraction.""" return fastfrac(self.R,-self.top,self.bot) def __mul__(self,other): """Multiply two fractions.""" if parent(other) == ZZ: return fastfrac(self.R,self.top * other,self.bot) if other.__class__ == fastfrac: return fastfrac(self.R,self.top * other.top,self.bot * other.bot) return NotImplemented def __rmul__(self,other): """Multiply something else with a fraction.""" return self.__mul__(other) def __truediv__(self,other): """Divide two fractions.""" if parent(other) == ZZ: return fastfrac(self.R,self.top,self.bot * other) if other.__class__ == fastfrac: return fastfrac(self.R,self.top * other.bot,self.bot * other.top) return NotImplemented # Compatibility wrapper for Sage versions based on Python 2 def __div__(self,other): """Divide two fractions.""" return self.__truediv__(other) def __pow__(self,other): """Compute a power of a fraction.""" if parent(other) == ZZ: if other < 0: # Negative powers require flipping top and bottom return fastfrac(self.R,self.bot ^ (-other),self.top ^ (-other)) else: return fastfrac(self.R,self.top ^ other,self.bot ^ other) return NotImplemented def __str__(self): return "fastfrac((" + str(self.top) + ") / (" + str(self.bot) + "))" def __repr__(self): return "%s" % self def numerator(self): return self.top class constraints: """A set of constraints, consisting of zero and nonzero expressions. Constraints can either be used to express knowledge or a requirement. Both the fields zero and nonzero are maps from expressions to description strings. The expressions that are the keys in zero are required to be zero, and the expressions that are the keys in nonzero are required to be nonzero. Note that (a != 0) and (b != 0) is the same as (a*b != 0), so all keys in nonzero could be multiplied into a single key. This is often much less efficient to work with though, so we keep them separate inside the constraints. This allows higher-level code to do fast checks on the individual nonzero elements, or combine them if needed for stronger checks. We can't multiply the different zero elements, as it would suffice for one of the factors to be zero, instead of all of them. Instead, the zero elements are typically combined into an ideal first. """ def __init__(self, **kwargs): if 'zero' in kwargs: self.zero = dict(kwargs['zero']) else: self.zero = dict() if 'nonzero' in kwargs: self.nonzero = dict(kwargs['nonzero']) else: self.nonzero = dict() def negate(self): return constraints(zero=self.nonzero, nonzero=self.zero) def __add__(self, other): zero = self.zero.copy() zero.update(other.zero) nonzero = self.nonzero.copy() nonzero.update(other.nonzero) return constraints(zero=zero, nonzero=nonzero) def __str__(self): return "constraints(zero=%s,nonzero=%s)" % (self.zero, self.nonzero) def __repr__(self): return "%s" % self def conflicts(R, con): """Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" zero = R.ideal(list(map(numerator, con.zero))) if 1 in zero: return True # First a cheap check whether any of the individual nonzero terms conflict on # their own. for nonzero in con.nonzero: if nonzero.iszero(zero): return True # It can be the case that entries in the nonzero set do not individually # conflict with the zero set, but their combination does. For example, knowing # that either x or y is zero is equivalent to having x*y in the zero set. # Having x or y individually in the nonzero set is not a conflict, but both # simultaneously is, so that is the right thing to check for. if reduce(lambda a,b: a * b, con.nonzero, fastfrac(R, 1)).iszero(zero): return True return False def get_nonzero_set(R, assume): """Calculate a simple set of nonzero expressions""" zero = R.ideal(list(map(numerator, assume.zero))) nonzero = set() for nz in map(numerator, assume.nonzero): for (f,n) in nz.factor(): nonzero.add(f) rnz = zero.reduce(nz) for (f,n) in rnz.factor(): nonzero.add(f) return nonzero def prove_nonzero(R, exprs, assume): """Check whether an expression is provably nonzero, given assumptions""" zero = R.ideal(list(map(numerator, assume.zero))) nonzero = get_nonzero_set(R, assume) expl = set() ok = True for expr in exprs: if numerator(expr) in zero: return (False, [exprs[expr]]) allexprs = reduce(lambda a,b: numerator(a)*numerator(b), exprs, 1) for (f, n) in allexprs.factor(): if f not in nonzero: ok = False if ok: return (True, None) ok = True for (f, n) in zero.reduce(numerator(allexprs)).factor(): if f not in nonzero: ok = False if ok: return (True, None) ok = True for expr in exprs: for (f,n) in numerator(expr).factor(): if f not in nonzero: ok = False if ok: return (True, None) ok = True for expr in exprs: for (f,n) in zero.reduce(numerator(expr)).factor(): if f not in nonzero: expl.add(exprs[expr]) if expl: return (False, list(expl)) else: return (True, None) def prove_zero(R, exprs, assume): """Check whether all of the passed expressions are provably zero, given assumptions""" r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) if not r: return (False, map(lambda x: "Possibly zero denominator: %s" % x, e)) zero = R.ideal(list(map(numerator, assume.zero))) nonzero = prod(x for x in assume.nonzero) expl = [] for expr in exprs: if not expr.iszero(zero): expl.append(exprs[expr]) if not expl: return (True, None) return (False, expl) def describe_extra(R, assume, assumeExtra): """Describe what assumptions are added, given existing assumptions""" zerox = assume.zero.copy() zerox.update(assumeExtra.zero) zero = R.ideal(list(map(numerator, assume.zero))) zeroextra = R.ideal(list(map(numerator, zerox))) nonzero = get_nonzero_set(R, assume) ret = set() # Iterate over the extra zero expressions for base in assumeExtra.zero: if base not in zero: add = [] for (f, n) in numerator(base).factor(): if f not in nonzero: add += ["%s" % f] if add: ret.add((" * ".join(add)) + " = 0 [%s]" % assumeExtra.zero[base]) # Iterate over the extra nonzero expressions for nz in assumeExtra.nonzero: nzr = zeroextra.reduce(numerator(nz)) if nzr not in zeroextra: for (f,n) in nzr.factor(): if zeroextra.reduce(f) not in nonzero: ret.add("%s != 0" % zeroextra.reduce(f)) return ", ".join(x for x in ret) def check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require): """Check a set of zero and nonzero requirements, given a set of zero and nonzero assumptions""" assume = assumeLaw + assumeAssert + assumeBranch if conflicts(R, assume): # This formula does not apply return None describe = describe_extra(R, assumeLaw + assumeBranch, assumeAssert) ok, msg = prove_zero(R, require.zero, assume) if not ok: return "FAIL, %s fails (assuming %s)" % (str(msg), describe) res, expl = prove_nonzero(R, require.nonzero, assume) if not res: return "FAIL, %s fails (assuming %s)" % (str(expl), describe) if describe != "": return "OK (assuming %s)" % describe else: return "OK" def concrete_verify(c): for k in c.zero: if k != 0: return (False, c.zero[k]) for k in c.nonzero: if k == 0: return (False, c.nonzero[k]) return (True, None) diff --git a/src/secp256k1/src/asm/field_10x26_arm.s b/src/secp256k1/src/asm/field_10x26_arm.s index 9a5bd0672..5f68cefc4 100644 --- a/src/secp256k1/src/asm/field_10x26_arm.s +++ b/src/secp256k1/src/asm/field_10x26_arm.s @@ -1,913 +1,913 @@ @ vim: set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab syntax=armasm: -/********************************************************************** - * Copyright (c) 2014 Wladimir J. van der Laan * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Wladimir J. van der Laan * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ /* ARM implementation of field_10x26 inner loops. Note: - To avoid unnecessary loads and make use of available registers, two 'passes' have every time been interleaved, with the odd passes accumulating c' and d' which will be added to c and d respectively in the even passes */ .syntax unified @ eabi attributes - see readelf -A .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP .text @ Field constants .set field_R0, 0x3d10 .set field_R1, 0x400 .set field_not_M, 0xfc000000 @ ~M = ~0x3ffffff .align 2 .global secp256k1_fe_mul_inner .type secp256k1_fe_mul_inner, %function @ Arguments: @ r0 r Restrict: can overlap with a, not with b @ r1 a @ r2 b @ Stack (total 4+10*4 = 44) @ sp + #0 saved 'r' pointer @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 secp256k1_fe_mul_inner: stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} sub sp, sp, #48 @ frame=44 + alignment str r0, [sp, #0] @ save result address, we need it only at the end /****************************************** * Main computation code. ****************************************** Allocation: r0,r14,r7,r8 scratch r1 a (pointer) r2 b (pointer) r3:r4 c r5:r6 d r11:r12 c' r9:r10 d' Note: do not write to r[] here, it may overlap with a[] */ /* A - interleaved with B */ ldr r7, [r1, #0*4] @ a[0] ldr r8, [r2, #9*4] @ b[9] ldr r0, [r1, #1*4] @ a[1] umull r5, r6, r7, r8 @ d = a[0] * b[9] ldr r14, [r2, #8*4] @ b[8] umull r9, r10, r0, r8 @ d' = a[1] * b[9] ldr r7, [r1, #2*4] @ a[2] umlal r5, r6, r0, r14 @ d += a[1] * b[8] ldr r8, [r2, #7*4] @ b[7] umlal r9, r10, r7, r14 @ d' += a[2] * b[8] ldr r0, [r1, #3*4] @ a[3] umlal r5, r6, r7, r8 @ d += a[2] * b[7] ldr r14, [r2, #6*4] @ b[6] umlal r9, r10, r0, r8 @ d' += a[3] * b[7] ldr r7, [r1, #4*4] @ a[4] umlal r5, r6, r0, r14 @ d += a[3] * b[6] ldr r8, [r2, #5*4] @ b[5] umlal r9, r10, r7, r14 @ d' += a[4] * b[6] ldr r0, [r1, #5*4] @ a[5] umlal r5, r6, r7, r8 @ d += a[4] * b[5] ldr r14, [r2, #4*4] @ b[4] umlal r9, r10, r0, r8 @ d' += a[5] * b[5] ldr r7, [r1, #6*4] @ a[6] umlal r5, r6, r0, r14 @ d += a[5] * b[4] ldr r8, [r2, #3*4] @ b[3] umlal r9, r10, r7, r14 @ d' += a[6] * b[4] ldr r0, [r1, #7*4] @ a[7] umlal r5, r6, r7, r8 @ d += a[6] * b[3] ldr r14, [r2, #2*4] @ b[2] umlal r9, r10, r0, r8 @ d' += a[7] * b[3] ldr r7, [r1, #8*4] @ a[8] umlal r5, r6, r0, r14 @ d += a[7] * b[2] ldr r8, [r2, #1*4] @ b[1] umlal r9, r10, r7, r14 @ d' += a[8] * b[2] ldr r0, [r1, #9*4] @ a[9] umlal r5, r6, r7, r8 @ d += a[8] * b[1] ldr r14, [r2, #0*4] @ b[0] umlal r9, r10, r0, r8 @ d' += a[9] * b[1] ldr r7, [r1, #0*4] @ a[0] umlal r5, r6, r0, r14 @ d += a[9] * b[0] @ r7,r14 used in B bic r0, r5, field_not_M @ t9 = d & M str r0, [sp, #4 + 4*9] mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 /* B */ umull r3, r4, r7, r14 @ c = a[0] * b[0] adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u0 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u0 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t0 = c & M str r14, [sp, #4 + 0*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u0 * R1 umlal r3, r4, r0, r14 /* C - interleaved with D */ ldr r7, [r1, #0*4] @ a[0] ldr r8, [r2, #2*4] @ b[2] ldr r14, [r2, #1*4] @ b[1] umull r11, r12, r7, r8 @ c' = a[0] * b[2] ldr r0, [r1, #1*4] @ a[1] umlal r3, r4, r7, r14 @ c += a[0] * b[1] ldr r8, [r2, #0*4] @ b[0] umlal r11, r12, r0, r14 @ c' += a[1] * b[1] ldr r7, [r1, #2*4] @ a[2] umlal r3, r4, r0, r8 @ c += a[1] * b[0] ldr r14, [r2, #9*4] @ b[9] umlal r11, r12, r7, r8 @ c' += a[2] * b[0] ldr r0, [r1, #3*4] @ a[3] umlal r5, r6, r7, r14 @ d += a[2] * b[9] ldr r8, [r2, #8*4] @ b[8] umull r9, r10, r0, r14 @ d' = a[3] * b[9] ldr r7, [r1, #4*4] @ a[4] umlal r5, r6, r0, r8 @ d += a[3] * b[8] ldr r14, [r2, #7*4] @ b[7] umlal r9, r10, r7, r8 @ d' += a[4] * b[8] ldr r0, [r1, #5*4] @ a[5] umlal r5, r6, r7, r14 @ d += a[4] * b[7] ldr r8, [r2, #6*4] @ b[6] umlal r9, r10, r0, r14 @ d' += a[5] * b[7] ldr r7, [r1, #6*4] @ a[6] umlal r5, r6, r0, r8 @ d += a[5] * b[6] ldr r14, [r2, #5*4] @ b[5] umlal r9, r10, r7, r8 @ d' += a[6] * b[6] ldr r0, [r1, #7*4] @ a[7] umlal r5, r6, r7, r14 @ d += a[6] * b[5] ldr r8, [r2, #4*4] @ b[4] umlal r9, r10, r0, r14 @ d' += a[7] * b[5] ldr r7, [r1, #8*4] @ a[8] umlal r5, r6, r0, r8 @ d += a[7] * b[4] ldr r14, [r2, #3*4] @ b[3] umlal r9, r10, r7, r8 @ d' += a[8] * b[4] ldr r0, [r1, #9*4] @ a[9] umlal r5, r6, r7, r14 @ d += a[8] * b[3] ldr r8, [r2, #2*4] @ b[2] umlal r9, r10, r0, r14 @ d' += a[9] * b[3] umlal r5, r6, r0, r8 @ d += a[9] * b[2] bic r0, r5, field_not_M @ u1 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u1 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t1 = c & M str r14, [sp, #4 + 1*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u1 * R1 umlal r3, r4, r0, r14 /* D */ adds r3, r3, r11 @ c += c' adc r4, r4, r12 adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u2 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u2 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t2 = c & M str r14, [sp, #4 + 2*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u2 * R1 umlal r3, r4, r0, r14 /* E - interleaved with F */ ldr r7, [r1, #0*4] @ a[0] ldr r8, [r2, #4*4] @ b[4] umull r11, r12, r7, r8 @ c' = a[0] * b[4] ldr r8, [r2, #3*4] @ b[3] umlal r3, r4, r7, r8 @ c += a[0] * b[3] ldr r7, [r1, #1*4] @ a[1] umlal r11, r12, r7, r8 @ c' += a[1] * b[3] ldr r8, [r2, #2*4] @ b[2] umlal r3, r4, r7, r8 @ c += a[1] * b[2] ldr r7, [r1, #2*4] @ a[2] umlal r11, r12, r7, r8 @ c' += a[2] * b[2] ldr r8, [r2, #1*4] @ b[1] umlal r3, r4, r7, r8 @ c += a[2] * b[1] ldr r7, [r1, #3*4] @ a[3] umlal r11, r12, r7, r8 @ c' += a[3] * b[1] ldr r8, [r2, #0*4] @ b[0] umlal r3, r4, r7, r8 @ c += a[3] * b[0] ldr r7, [r1, #4*4] @ a[4] umlal r11, r12, r7, r8 @ c' += a[4] * b[0] ldr r8, [r2, #9*4] @ b[9] umlal r5, r6, r7, r8 @ d += a[4] * b[9] ldr r7, [r1, #5*4] @ a[5] umull r9, r10, r7, r8 @ d' = a[5] * b[9] ldr r8, [r2, #8*4] @ b[8] umlal r5, r6, r7, r8 @ d += a[5] * b[8] ldr r7, [r1, #6*4] @ a[6] umlal r9, r10, r7, r8 @ d' += a[6] * b[8] ldr r8, [r2, #7*4] @ b[7] umlal r5, r6, r7, r8 @ d += a[6] * b[7] ldr r7, [r1, #7*4] @ a[7] umlal r9, r10, r7, r8 @ d' += a[7] * b[7] ldr r8, [r2, #6*4] @ b[6] umlal r5, r6, r7, r8 @ d += a[7] * b[6] ldr r7, [r1, #8*4] @ a[8] umlal r9, r10, r7, r8 @ d' += a[8] * b[6] ldr r8, [r2, #5*4] @ b[5] umlal r5, r6, r7, r8 @ d += a[8] * b[5] ldr r7, [r1, #9*4] @ a[9] umlal r9, r10, r7, r8 @ d' += a[9] * b[5] ldr r8, [r2, #4*4] @ b[4] umlal r5, r6, r7, r8 @ d += a[9] * b[4] bic r0, r5, field_not_M @ u3 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u3 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t3 = c & M str r14, [sp, #4 + 3*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u3 * R1 umlal r3, r4, r0, r14 /* F */ adds r3, r3, r11 @ c += c' adc r4, r4, r12 adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u4 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u4 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t4 = c & M str r14, [sp, #4 + 4*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u4 * R1 umlal r3, r4, r0, r14 /* G - interleaved with H */ ldr r7, [r1, #0*4] @ a[0] ldr r8, [r2, #6*4] @ b[6] ldr r14, [r2, #5*4] @ b[5] umull r11, r12, r7, r8 @ c' = a[0] * b[6] ldr r0, [r1, #1*4] @ a[1] umlal r3, r4, r7, r14 @ c += a[0] * b[5] ldr r8, [r2, #4*4] @ b[4] umlal r11, r12, r0, r14 @ c' += a[1] * b[5] ldr r7, [r1, #2*4] @ a[2] umlal r3, r4, r0, r8 @ c += a[1] * b[4] ldr r14, [r2, #3*4] @ b[3] umlal r11, r12, r7, r8 @ c' += a[2] * b[4] ldr r0, [r1, #3*4] @ a[3] umlal r3, r4, r7, r14 @ c += a[2] * b[3] ldr r8, [r2, #2*4] @ b[2] umlal r11, r12, r0, r14 @ c' += a[3] * b[3] ldr r7, [r1, #4*4] @ a[4] umlal r3, r4, r0, r8 @ c += a[3] * b[2] ldr r14, [r2, #1*4] @ b[1] umlal r11, r12, r7, r8 @ c' += a[4] * b[2] ldr r0, [r1, #5*4] @ a[5] umlal r3, r4, r7, r14 @ c += a[4] * b[1] ldr r8, [r2, #0*4] @ b[0] umlal r11, r12, r0, r14 @ c' += a[5] * b[1] ldr r7, [r1, #6*4] @ a[6] umlal r3, r4, r0, r8 @ c += a[5] * b[0] ldr r14, [r2, #9*4] @ b[9] umlal r11, r12, r7, r8 @ c' += a[6] * b[0] ldr r0, [r1, #7*4] @ a[7] umlal r5, r6, r7, r14 @ d += a[6] * b[9] ldr r8, [r2, #8*4] @ b[8] umull r9, r10, r0, r14 @ d' = a[7] * b[9] ldr r7, [r1, #8*4] @ a[8] umlal r5, r6, r0, r8 @ d += a[7] * b[8] ldr r14, [r2, #7*4] @ b[7] umlal r9, r10, r7, r8 @ d' += a[8] * b[8] ldr r0, [r1, #9*4] @ a[9] umlal r5, r6, r7, r14 @ d += a[8] * b[7] ldr r8, [r2, #6*4] @ b[6] umlal r9, r10, r0, r14 @ d' += a[9] * b[7] umlal r5, r6, r0, r8 @ d += a[9] * b[6] bic r0, r5, field_not_M @ u5 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u5 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t5 = c & M str r14, [sp, #4 + 5*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u5 * R1 umlal r3, r4, r0, r14 /* H */ adds r3, r3, r11 @ c += c' adc r4, r4, r12 adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u6 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u6 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t6 = c & M str r14, [sp, #4 + 6*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u6 * R1 umlal r3, r4, r0, r14 /* I - interleaved with J */ ldr r8, [r2, #8*4] @ b[8] ldr r7, [r1, #0*4] @ a[0] ldr r14, [r2, #7*4] @ b[7] umull r11, r12, r7, r8 @ c' = a[0] * b[8] ldr r0, [r1, #1*4] @ a[1] umlal r3, r4, r7, r14 @ c += a[0] * b[7] ldr r8, [r2, #6*4] @ b[6] umlal r11, r12, r0, r14 @ c' += a[1] * b[7] ldr r7, [r1, #2*4] @ a[2] umlal r3, r4, r0, r8 @ c += a[1] * b[6] ldr r14, [r2, #5*4] @ b[5] umlal r11, r12, r7, r8 @ c' += a[2] * b[6] ldr r0, [r1, #3*4] @ a[3] umlal r3, r4, r7, r14 @ c += a[2] * b[5] ldr r8, [r2, #4*4] @ b[4] umlal r11, r12, r0, r14 @ c' += a[3] * b[5] ldr r7, [r1, #4*4] @ a[4] umlal r3, r4, r0, r8 @ c += a[3] * b[4] ldr r14, [r2, #3*4] @ b[3] umlal r11, r12, r7, r8 @ c' += a[4] * b[4] ldr r0, [r1, #5*4] @ a[5] umlal r3, r4, r7, r14 @ c += a[4] * b[3] ldr r8, [r2, #2*4] @ b[2] umlal r11, r12, r0, r14 @ c' += a[5] * b[3] ldr r7, [r1, #6*4] @ a[6] umlal r3, r4, r0, r8 @ c += a[5] * b[2] ldr r14, [r2, #1*4] @ b[1] umlal r11, r12, r7, r8 @ c' += a[6] * b[2] ldr r0, [r1, #7*4] @ a[7] umlal r3, r4, r7, r14 @ c += a[6] * b[1] ldr r8, [r2, #0*4] @ b[0] umlal r11, r12, r0, r14 @ c' += a[7] * b[1] ldr r7, [r1, #8*4] @ a[8] umlal r3, r4, r0, r8 @ c += a[7] * b[0] ldr r14, [r2, #9*4] @ b[9] umlal r11, r12, r7, r8 @ c' += a[8] * b[0] ldr r0, [r1, #9*4] @ a[9] umlal r5, r6, r7, r14 @ d += a[8] * b[9] ldr r8, [r2, #8*4] @ b[8] umull r9, r10, r0, r14 @ d' = a[9] * b[9] umlal r5, r6, r0, r8 @ d += a[9] * b[8] bic r0, r5, field_not_M @ u7 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u7 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t7 = c & M str r14, [sp, #4 + 7*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u7 * R1 umlal r3, r4, r0, r14 /* J */ adds r3, r3, r11 @ c += c' adc r4, r4, r12 adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u8 = d & M str r0, [sp, #4 + 8*4] mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u8 * R0 umlal r3, r4, r0, r14 /****************************************** * compute and write back result ****************************************** Allocation: r0 r r3:r4 c r5:r6 d r7 t0 r8 t1 r9 t2 r11 u8 r12 t9 r1,r2,r10,r14 scratch Note: do not read from a[] after here, it may overlap with r[] */ ldr r0, [sp, #0] add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 ldmia r1, {r2,r7,r8,r9,r10,r11,r12} add r1, r0, #3*4 stmia r1, {r2,r7,r8,r9,r10} bic r2, r3, field_not_M @ r[8] = c & M str r2, [r0, #8*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u8 * R1 umlal r3, r4, r11, r14 movw r14, field_R0 @ c += d * R0 umlal r3, r4, r5, r14 adds r3, r3, r12 @ c += t9 adc r4, r4, #0 add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 ldmia r1, {r7,r8,r9} ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) str r2, [r0, #9*4] mov r3, r3, lsr #22 @ c >>= 22 orr r3, r3, r4, asl #10 mov r4, r4, lsr #22 movw r14, field_R1 << 4 @ c += d * (R1 << 4) umlal r3, r4, r5, r14 movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) adds r5, r5, r7 @ d.lo += t0 mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) adc r6, r6, 0 @ d.hi += carry bic r2, r5, field_not_M @ r[0] = d & M str r2, [r0, #0*4] mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) adds r5, r5, r8 @ d.lo += t1 adc r6, r6, #0 @ d.hi += carry adds r5, r5, r1 @ d.lo += tmp.lo mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) adc r6, r6, r2 @ d.hi += carry + tmp.hi bic r2, r5, field_not_M @ r[1] = d & M str r2, [r0, #1*4] mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) orr r5, r5, r6, asl #6 add r5, r5, r9 @ d += t2 str r5, [r0, #2*4] @ r[2] = d add sp, sp, #48 ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} .size secp256k1_fe_mul_inner, .-secp256k1_fe_mul_inner .align 2 .global secp256k1_fe_sqr_inner .type secp256k1_fe_sqr_inner, %function @ Arguments: @ r0 r Can overlap with a @ r1 a @ Stack (total 4+10*4 = 44) @ sp + #0 saved 'r' pointer @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 secp256k1_fe_sqr_inner: stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} sub sp, sp, #48 @ frame=44 + alignment str r0, [sp, #0] @ save result address, we need it only at the end /****************************************** * Main computation code. ****************************************** Allocation: r0,r14,r2,r7,r8 scratch r1 a (pointer) r3:r4 c r5:r6 d r11:r12 c' r9:r10 d' Note: do not write to r[] here, it may overlap with a[] */ /* A interleaved with B */ ldr r0, [r1, #1*4] @ a[1]*2 ldr r7, [r1, #0*4] @ a[0] mov r0, r0, asl #1 ldr r14, [r1, #9*4] @ a[9] umull r3, r4, r7, r7 @ c = a[0] * a[0] ldr r8, [r1, #8*4] @ a[8] mov r7, r7, asl #1 umull r5, r6, r7, r14 @ d = a[0]*2 * a[9] ldr r7, [r1, #2*4] @ a[2]*2 umull r9, r10, r0, r14 @ d' = a[1]*2 * a[9] ldr r14, [r1, #7*4] @ a[7] umlal r5, r6, r0, r8 @ d += a[1]*2 * a[8] mov r7, r7, asl #1 ldr r0, [r1, #3*4] @ a[3]*2 umlal r9, r10, r7, r8 @ d' += a[2]*2 * a[8] ldr r8, [r1, #6*4] @ a[6] umlal r5, r6, r7, r14 @ d += a[2]*2 * a[7] mov r0, r0, asl #1 ldr r7, [r1, #4*4] @ a[4]*2 umlal r9, r10, r0, r14 @ d' += a[3]*2 * a[7] ldr r14, [r1, #5*4] @ a[5] mov r7, r7, asl #1 umlal r5, r6, r0, r8 @ d += a[3]*2 * a[6] umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[6] umlal r5, r6, r7, r14 @ d += a[4]*2 * a[5] umlal r9, r10, r14, r14 @ d' += a[5] * a[5] bic r0, r5, field_not_M @ t9 = d & M str r0, [sp, #4 + 9*4] mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 /* B */ adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u0 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u0 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t0 = c & M str r14, [sp, #4 + 0*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u0 * R1 umlal r3, r4, r0, r14 /* C interleaved with D */ ldr r0, [r1, #0*4] @ a[0]*2 ldr r14, [r1, #1*4] @ a[1] mov r0, r0, asl #1 ldr r8, [r1, #2*4] @ a[2] umlal r3, r4, r0, r14 @ c += a[0]*2 * a[1] mov r7, r8, asl #1 @ a[2]*2 umull r11, r12, r14, r14 @ c' = a[1] * a[1] ldr r14, [r1, #9*4] @ a[9] umlal r11, r12, r0, r8 @ c' += a[0]*2 * a[2] ldr r0, [r1, #3*4] @ a[3]*2 ldr r8, [r1, #8*4] @ a[8] umlal r5, r6, r7, r14 @ d += a[2]*2 * a[9] mov r0, r0, asl #1 ldr r7, [r1, #4*4] @ a[4]*2 umull r9, r10, r0, r14 @ d' = a[3]*2 * a[9] ldr r14, [r1, #7*4] @ a[7] umlal r5, r6, r0, r8 @ d += a[3]*2 * a[8] mov r7, r7, asl #1 ldr r0, [r1, #5*4] @ a[5]*2 umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[8] ldr r8, [r1, #6*4] @ a[6] mov r0, r0, asl #1 umlal r5, r6, r7, r14 @ d += a[4]*2 * a[7] umlal r9, r10, r0, r14 @ d' += a[5]*2 * a[7] umlal r5, r6, r0, r8 @ d += a[5]*2 * a[6] umlal r9, r10, r8, r8 @ d' += a[6] * a[6] bic r0, r5, field_not_M @ u1 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u1 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t1 = c & M str r14, [sp, #4 + 1*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u1 * R1 umlal r3, r4, r0, r14 /* D */ adds r3, r3, r11 @ c += c' adc r4, r4, r12 adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u2 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u2 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t2 = c & M str r14, [sp, #4 + 2*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u2 * R1 umlal r3, r4, r0, r14 /* E interleaved with F */ ldr r7, [r1, #0*4] @ a[0]*2 ldr r0, [r1, #1*4] @ a[1]*2 ldr r14, [r1, #2*4] @ a[2] mov r7, r7, asl #1 ldr r8, [r1, #3*4] @ a[3] ldr r2, [r1, #4*4] umlal r3, r4, r7, r8 @ c += a[0]*2 * a[3] mov r0, r0, asl #1 umull r11, r12, r7, r2 @ c' = a[0]*2 * a[4] mov r2, r2, asl #1 @ a[4]*2 umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[3] ldr r8, [r1, #9*4] @ a[9] umlal r3, r4, r0, r14 @ c += a[1]*2 * a[2] ldr r0, [r1, #5*4] @ a[5]*2 umlal r11, r12, r14, r14 @ c' += a[2] * a[2] ldr r14, [r1, #8*4] @ a[8] mov r0, r0, asl #1 umlal r5, r6, r2, r8 @ d += a[4]*2 * a[9] ldr r7, [r1, #6*4] @ a[6]*2 umull r9, r10, r0, r8 @ d' = a[5]*2 * a[9] mov r7, r7, asl #1 ldr r8, [r1, #7*4] @ a[7] umlal r5, r6, r0, r14 @ d += a[5]*2 * a[8] umlal r9, r10, r7, r14 @ d' += a[6]*2 * a[8] umlal r5, r6, r7, r8 @ d += a[6]*2 * a[7] umlal r9, r10, r8, r8 @ d' += a[7] * a[7] bic r0, r5, field_not_M @ u3 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u3 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t3 = c & M str r14, [sp, #4 + 3*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u3 * R1 umlal r3, r4, r0, r14 /* F */ adds r3, r3, r11 @ c += c' adc r4, r4, r12 adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u4 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u4 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t4 = c & M str r14, [sp, #4 + 4*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u4 * R1 umlal r3, r4, r0, r14 /* G interleaved with H */ ldr r7, [r1, #0*4] @ a[0]*2 ldr r0, [r1, #1*4] @ a[1]*2 mov r7, r7, asl #1 ldr r8, [r1, #5*4] @ a[5] ldr r2, [r1, #6*4] @ a[6] umlal r3, r4, r7, r8 @ c += a[0]*2 * a[5] ldr r14, [r1, #4*4] @ a[4] mov r0, r0, asl #1 umull r11, r12, r7, r2 @ c' = a[0]*2 * a[6] ldr r7, [r1, #2*4] @ a[2]*2 umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[5] mov r7, r7, asl #1 ldr r8, [r1, #3*4] @ a[3] umlal r3, r4, r0, r14 @ c += a[1]*2 * a[4] mov r0, r2, asl #1 @ a[6]*2 umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[4] ldr r14, [r1, #9*4] @ a[9] umlal r3, r4, r7, r8 @ c += a[2]*2 * a[3] ldr r7, [r1, #7*4] @ a[7]*2 umlal r11, r12, r8, r8 @ c' += a[3] * a[3] mov r7, r7, asl #1 ldr r8, [r1, #8*4] @ a[8] umlal r5, r6, r0, r14 @ d += a[6]*2 * a[9] umull r9, r10, r7, r14 @ d' = a[7]*2 * a[9] umlal r5, r6, r7, r8 @ d += a[7]*2 * a[8] umlal r9, r10, r8, r8 @ d' += a[8] * a[8] bic r0, r5, field_not_M @ u5 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u5 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t5 = c & M str r14, [sp, #4 + 5*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u5 * R1 umlal r3, r4, r0, r14 /* H */ adds r3, r3, r11 @ c += c' adc r4, r4, r12 adds r5, r5, r9 @ d += d' adc r6, r6, r10 bic r0, r5, field_not_M @ u6 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u6 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t6 = c & M str r14, [sp, #4 + 6*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u6 * R1 umlal r3, r4, r0, r14 /* I interleaved with J */ ldr r7, [r1, #0*4] @ a[0]*2 ldr r0, [r1, #1*4] @ a[1]*2 mov r7, r7, asl #1 ldr r8, [r1, #7*4] @ a[7] ldr r2, [r1, #8*4] @ a[8] umlal r3, r4, r7, r8 @ c += a[0]*2 * a[7] ldr r14, [r1, #6*4] @ a[6] mov r0, r0, asl #1 umull r11, r12, r7, r2 @ c' = a[0]*2 * a[8] ldr r7, [r1, #2*4] @ a[2]*2 umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[7] ldr r8, [r1, #5*4] @ a[5] umlal r3, r4, r0, r14 @ c += a[1]*2 * a[6] ldr r0, [r1, #3*4] @ a[3]*2 mov r7, r7, asl #1 umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[6] ldr r14, [r1, #4*4] @ a[4] mov r0, r0, asl #1 umlal r3, r4, r7, r8 @ c += a[2]*2 * a[5] mov r2, r2, asl #1 @ a[8]*2 umlal r11, r12, r0, r8 @ c' += a[3]*2 * a[5] umlal r3, r4, r0, r14 @ c += a[3]*2 * a[4] umlal r11, r12, r14, r14 @ c' += a[4] * a[4] ldr r8, [r1, #9*4] @ a[9] umlal r5, r6, r2, r8 @ d += a[8]*2 * a[9] @ r8 will be used in J bic r0, r5, field_not_M @ u7 = d & M mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u7 * R0 umlal r3, r4, r0, r14 bic r14, r3, field_not_M @ t7 = c & M str r14, [sp, #4 + 7*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u7 * R1 umlal r3, r4, r0, r14 /* J */ adds r3, r3, r11 @ c += c' adc r4, r4, r12 umlal r5, r6, r8, r8 @ d += a[9] * a[9] bic r0, r5, field_not_M @ u8 = d & M str r0, [sp, #4 + 8*4] mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R0 @ c += u8 * R0 umlal r3, r4, r0, r14 /****************************************** * compute and write back result ****************************************** Allocation: r0 r r3:r4 c r5:r6 d r7 t0 r8 t1 r9 t2 r11 u8 r12 t9 r1,r2,r10,r14 scratch Note: do not read from a[] after here, it may overlap with r[] */ ldr r0, [sp, #0] add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 ldmia r1, {r2,r7,r8,r9,r10,r11,r12} add r1, r0, #3*4 stmia r1, {r2,r7,r8,r9,r10} bic r2, r3, field_not_M @ r[8] = c & M str r2, [r0, #8*4] mov r3, r3, lsr #26 @ c >>= 26 orr r3, r3, r4, asl #6 mov r4, r4, lsr #26 mov r14, field_R1 @ c += u8 * R1 umlal r3, r4, r11, r14 movw r14, field_R0 @ c += d * R0 umlal r3, r4, r5, r14 adds r3, r3, r12 @ c += t9 adc r4, r4, #0 add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 ldmia r1, {r7,r8,r9} ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) str r2, [r0, #9*4] mov r3, r3, lsr #22 @ c >>= 22 orr r3, r3, r4, asl #10 mov r4, r4, lsr #22 movw r14, field_R1 << 4 @ c += d * (R1 << 4) umlal r3, r4, r5, r14 movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) adds r5, r5, r7 @ d.lo += t0 mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) adc r6, r6, 0 @ d.hi += carry bic r2, r5, field_not_M @ r[0] = d & M str r2, [r0, #0*4] mov r5, r5, lsr #26 @ d >>= 26 orr r5, r5, r6, asl #6 mov r6, r6, lsr #26 movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) adds r5, r5, r8 @ d.lo += t1 adc r6, r6, #0 @ d.hi += carry adds r5, r5, r1 @ d.lo += tmp.lo mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) adc r6, r6, r2 @ d.hi += carry + tmp.hi bic r2, r5, field_not_M @ r[1] = d & M str r2, [r0, #1*4] mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) orr r5, r5, r6, asl #6 add r5, r5, r9 @ d += t2 str r5, [r0, #2*4] @ r[2] = d add sp, sp, #48 ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} .size secp256k1_fe_sqr_inner, .-secp256k1_fe_sqr_inner diff --git a/src/secp256k1/src/assumptions.h b/src/secp256k1/src/assumptions.h index 77204de2b..6dc527b28 100644 --- a/src/secp256k1/src/assumptions.h +++ b/src/secp256k1/src/assumptions.h @@ -1,80 +1,80 @@ -/********************************************************************** - * Copyright (c) 2020 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2020 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_ASSUMPTIONS_H #define SECP256K1_ASSUMPTIONS_H #include #include "util.h" /* This library, like most software, relies on a number of compiler implementation defined (but not undefined) behaviours. Although the behaviours we require are essentially universal we test them specifically here to reduce the odds of experiencing an unwelcome surprise. */ struct secp256k1_assumption_checker { /* This uses a trick to implement a static assertion in C89: a type with an array of negative size is not allowed. */ int dummy_array[( /* Bytes are 8 bits. */ (CHAR_BIT == 8) && /* No integer promotion for uint32_t. This ensures that we can multiply uintXX_t values where XX >= 32 without signed overflow, which would be undefined behaviour. */ (UINT_MAX <= UINT32_MAX) && /* Conversions from unsigned to signed outside of the bounds of the signed type are implementation-defined. Verify that they function as reinterpreting the lower bits of the input in two's complement notation. Do this for conversions: - from uint(N)_t to int(N)_t with negative result - from uint(2N)_t to int(N)_t with negative result - from int(2N)_t to int(N)_t with negative result - from int(2N)_t to int(N)_t with positive result */ /* To int8_t. */ ((int8_t)(uint8_t)0xAB == (int8_t)-(int8_t)0x55) && ((int8_t)(uint16_t)0xABCD == (int8_t)-(int8_t)0x33) && ((int8_t)(int16_t)(uint16_t)0xCDEF == (int8_t)(uint8_t)0xEF) && ((int8_t)(int16_t)(uint16_t)0x9234 == (int8_t)(uint8_t)0x34) && /* To int16_t. */ ((int16_t)(uint16_t)0xBCDE == (int16_t)-(int16_t)0x4322) && ((int16_t)(uint32_t)0xA1B2C3D4 == (int16_t)-(int16_t)0x3C2C) && ((int16_t)(int32_t)(uint32_t)0xC1D2E3F4 == (int16_t)(uint16_t)0xE3F4) && ((int16_t)(int32_t)(uint32_t)0x92345678 == (int16_t)(uint16_t)0x5678) && /* To int32_t. */ ((int32_t)(uint32_t)0xB2C3D4E5 == (int32_t)-(int32_t)0x4D3C2B1B) && ((int32_t)(uint64_t)0xA123B456C789D012ULL == (int32_t)-(int32_t)0x38762FEE) && ((int32_t)(int64_t)(uint64_t)0xC1D2E3F4A5B6C7D8ULL == (int32_t)(uint32_t)0xA5B6C7D8) && ((int32_t)(int64_t)(uint64_t)0xABCDEF0123456789ULL == (int32_t)(uint32_t)0x23456789) && /* To int64_t. */ ((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL) && #if defined(SECP256K1_WIDEMUL_INT128) ((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL) && (((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL) && (((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL) && /* To int128_t. */ ((int128_t)(((uint128_t)0xB1234567C8901234ULL << 64) + 0xD5678901E2345678ULL) == (int128_t)(-(int128_t)0x8E1648B3F50E80DCULL * 0x8E1648B3F50E80DDULL + 0x5EA688D5482F9464ULL)) && #endif /* Right shift on negative signed values is implementation defined. Verify that it acts as a right shift in two's complement with sign extension (i.e duplicating the top bit into newly added bits). */ ((((int8_t)0xE8) >> 2) == (int8_t)(uint8_t)0xFA) && ((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A) && ((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48) && ((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL) && #if defined(SECP256K1_WIDEMUL_INT128) ((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)) && #endif 1) * 2 - 1]; }; #endif /* SECP256K1_ASSUMPTIONS_H */ diff --git a/src/secp256k1/src/basic-config.h b/src/secp256k1/src/basic-config.h index b0d82e89b..bb6b58259 100644 --- a/src/secp256k1/src/basic-config.h +++ b/src/secp256k1/src/basic-config.h @@ -1,34 +1,34 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_BASIC_CONFIG_H #define SECP256K1_BASIC_CONFIG_H #ifdef USE_BASIC_CONFIG #undef USE_ASM_X86_64 #undef USE_ECMULT_STATIC_PRECOMPUTATION #undef USE_EXTERNAL_ASM #undef USE_EXTERNAL_DEFAULT_CALLBACKS #undef USE_FIELD_INV_BUILTIN #undef USE_FIELD_INV_NUM #undef USE_NUM_GMP #undef USE_NUM_NONE #undef USE_SCALAR_INV_BUILTIN #undef USE_SCALAR_INV_NUM #undef USE_FORCE_WIDEMUL_INT64 #undef USE_FORCE_WIDEMUL_INT128 #undef ECMULT_WINDOW_SIZE #define USE_NUM_NONE 1 #define USE_FIELD_INV_BUILTIN 1 #define USE_SCALAR_INV_BUILTIN 1 #define USE_WIDEMUL_64 1 #define ECMULT_WINDOW_SIZE 15 #endif /* USE_BASIC_CONFIG */ #endif /* SECP256K1_BASIC_CONFIG_H */ diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h index 9bfed903e..63c55df44 100644 --- a/src/secp256k1/src/bench.h +++ b/src/secp256k1/src/bench.h @@ -1,133 +1,133 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_BENCH_H #define SECP256K1_BENCH_H #include #include #include #include "sys/time.h" static int64_t gettime_i64(void) { struct timeval tv; gettimeofday(&tv, NULL); return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL; } #define FP_EXP (6) #define FP_MULT (1000000LL) /* Format fixed point number. */ void print_number(const int64_t x) { int64_t x_abs, y; int c, i, rounding; size_t ptr; char buffer[30]; if (x == INT64_MIN) { /* Prevent UB. */ printf("ERR"); return; } x_abs = x < 0 ? -x : x; /* Determine how many decimals we want to show (more than FP_EXP makes no * sense). */ y = x_abs; c = 0; while (y > 0LL && y < 100LL * FP_MULT && c < FP_EXP) { y *= 10LL; c++; } /* Round to 'c' decimals. */ y = x_abs; rounding = 0; for (i = c; i < FP_EXP; ++i) { rounding = (y % 10) >= 5; y /= 10; } y += rounding; /* Format and print the number. */ ptr = sizeof(buffer) - 1; buffer[ptr] = 0; if (c != 0) { for (i = 0; i < c; ++i) { buffer[--ptr] = '0' + (y % 10); y /= 10; } buffer[--ptr] = '.'; } do { buffer[--ptr] = '0' + (y % 10); y /= 10; } while (y != 0); if (x < 0) { buffer[--ptr] = '-'; } printf("%s", &buffer[ptr]); } void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void*), void (*teardown)(void*, int), void* data, int count, int iter) { int i; int64_t min = INT64_MAX; int64_t sum = 0; int64_t max = 0; for (i = 0; i < count; i++) { int64_t begin, total; if (setup != NULL) { setup(data); } begin = gettime_i64(); benchmark(data, iter); total = gettime_i64() - begin; if (teardown != NULL) { teardown(data, iter); } if (total < min) { min = total; } if (total > max) { max = total; } sum += total; } printf("%s: min ", name); print_number(min * FP_MULT / iter); printf("us / avg "); print_number(((sum * FP_MULT) / count) / iter); printf("us / max "); print_number(max * FP_MULT / 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; } int get_iters(int default_iters) { char* env = getenv("SECP256K1_BENCH_ITERS"); if (env) { return strtol(env, NULL, 0); } else { return default_iters; } } #endif /* SECP256K1_BENCH_H */ diff --git a/src/secp256k1/src/bench_ecdh.c b/src/secp256k1/src/bench_ecdh.c index f099d3388..ab4b8f424 100644 --- a/src/secp256k1/src/bench_ecdh.c +++ b/src/secp256k1/src/bench_ecdh.c @@ -1,59 +1,59 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include #include "include/secp256k1.h" #include "include/secp256k1_ecdh.h" #include "util.h" #include "bench.h" typedef struct { secp256k1_context *ctx; secp256k1_pubkey point; unsigned char scalar[32]; } bench_ecdh_data; static void bench_ecdh_setup(void* arg) { int i; bench_ecdh_data *data = (bench_ecdh_data*)arg; const unsigned char point[] = { 0x03, 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, 0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, 0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f }; for (i = 0; i < 32; i++) { data->scalar[i] = i + 1; } CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); } static void bench_ecdh(void* arg, int iters) { int i; unsigned char res[32]; bench_ecdh_data *data = (bench_ecdh_data*)arg; for (i = 0; i < iters; i++) { CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar, NULL, NULL) == 1); } } int main(void) { bench_ecdh_data data; int iters = get_iters(20000); /* create a context with no capabilities */ data.ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters); secp256k1_context_destroy(data.ctx); return 0; } diff --git a/src/secp256k1/src/bench_ecmult.c b/src/secp256k1/src/bench_ecmult.c index facd07ef3..85b9e439e 100644 --- a/src/secp256k1/src/bench_ecmult.c +++ b/src/secp256k1/src/bench_ecmult.c @@ -1,214 +1,214 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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 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, int iters) { bench_data* data = (bench_data*)arg; int includes_g = data->includes_g; int iter; int count = data->count; iters = iters / data->count; for (iter = 0; iter < iters; ++iter) { data->ecmult_multi(&data->ctx->error_callback, &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, int iters) { bench_data* data = (bench_data*)arg; int iter; iters = iters / data->count; /* 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, int num_iters) { char str[32]; static const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); size_t iters = 1 + num_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 * iters); } int main(int argc, char **argv) { bench_data data; int i, p; secp256k1_gej* pubkeys_gej; size_t scratch_size; int iters = get_iters(10000); data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size); data.ecmult_multi = secp256k1_ecmult_multi_var; 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 if(have_flag(argc, argv, "simple")) { printf("Using simple algorithm:\n"); data.ecmult_multi = secp256k1_ecmult_multi_var; secp256k1_scratch_space_destroy(data.ctx, data.scratch); data.scratch = NULL; } else { fprintf(stderr, "%s: unrecognized argument '%s'.\n", argv[0], argv[1]); fprintf(stderr, "Use 'pippenger_wnaf', 'strauss_wnaf', 'simple' or no argument to benchmark a combined algorithm.\n"); return 1; } } /* Allocate stuff */ 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); free(pubkeys_gej); for (i = 1; i <= 8; ++i) { run_test(&data, i, 1, iters); } /* This is disabled with low count of iterations because the loop runs 77 times even with iters=1 * and the higher it goes the longer the computation takes(more points) * So we don't run this benchmark with low iterations to prevent slow down */ if (iters > 2) { for (p = 0; p <= 11; ++p) { for (i = 9; i <= 16; ++i) { run_test(&data, i << p, 1, iters); } } } if (data.scratch != NULL) { secp256k1_scratch_space_destroy(data.ctx, data.scratch); } secp256k1_context_destroy(data.ctx); 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 5f2b7a975..7fa6882c1 100644 --- a/src/secp256k1/src/bench_internal.c +++ b/src/secp256k1/src/bench_internal.c @@ -1,431 +1,431 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include #include "include/secp256k1.h" #include "assumptions.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[2]; secp256k1_fe fe[4]; secp256k1_ge ge[2]; secp256k1_gej gej[2]; 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[4][32] = { /* Initializer for scalar[0], fe[0], first half of data, the X coordinate of ge[0], and the (implied affine) X coordinate of gej[0]. */ { 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 }, /* Initializer for scalar[1], fe[1], first half of data, the X coordinate of ge[1], and the (implied affine) X coordinate of gej[1]. */ { 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 }, /* Initializer for fe[2] and the Z coordinate of gej[0]. */ { 0x3d, 0x2d, 0xef, 0xf4, 0x25, 0x98, 0x4f, 0x5d, 0xe2, 0xca, 0x5f, 0x41, 0x3f, 0x3f, 0xce, 0x44, 0xaa, 0x2c, 0x53, 0x8a, 0xc6, 0x59, 0x1f, 0x38, 0x38, 0x23, 0xe4, 0x11, 0x27, 0xc6, 0xa0, 0xe7 }, /* Initializer for fe[3] and the Z coordinate of gej[1]. */ { 0xbd, 0x21, 0xa5, 0xe1, 0x13, 0x50, 0x73, 0x2e, 0x52, 0x98, 0xc8, 0x9e, 0xab, 0x00, 0xa2, 0x68, 0x43, 0xf5, 0xd7, 0x49, 0x80, 0x72, 0xa7, 0xf3, 0xd7, 0x60, 0xe6, 0xab, 0x90, 0x92, 0xdf, 0xc5 } }; secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL); secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL); secp256k1_fe_set_b32(&data->fe[0], init[0]); secp256k1_fe_set_b32(&data->fe[1], init[1]); secp256k1_fe_set_b32(&data->fe[2], init[2]); secp256k1_fe_set_b32(&data->fe[3], init[3]); CHECK(secp256k1_ge_set_xo_var(&data->ge[0], &data->fe[0], 0)); CHECK(secp256k1_ge_set_xo_var(&data->ge[1], &data->fe[1], 1)); secp256k1_gej_set_ge(&data->gej[0], &data->ge[0]); secp256k1_gej_rescale(&data->gej[0], &data->fe[2]); secp256k1_gej_set_ge(&data->gej[1], &data->ge[1]); secp256k1_gej_rescale(&data->gej[1], &data->fe[3]); memcpy(data->data, init[0], 32); memcpy(data->data + 32, init[1], 32); } void bench_scalar_add(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(j <= iters); } void bench_scalar_negate(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_scalar_negate(&data->scalar[0], &data->scalar[0]); } } void bench_scalar_sqr(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_scalar_sqr(&data->scalar[0], &data->scalar[0]); } } void bench_scalar_mul(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_scalar_mul(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } } void bench_scalar_split(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_scalar_split_lambda(&data->scalar[0], &data->scalar[1], &data->scalar[0]); j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(j <= iters); } void bench_scalar_inverse(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_scalar_inverse(&data->scalar[0], &data->scalar[0]); j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(j <= iters); } void bench_scalar_inverse_var(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_scalar_inverse_var(&data->scalar[0], &data->scalar[0]); j += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(j <= iters); } void bench_field_normalize(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_fe_normalize(&data->fe[0]); } } void bench_field_normalize_weak(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_fe_normalize_weak(&data->fe[0]); } } void bench_field_mul(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_fe_mul(&data->fe[0], &data->fe[0], &data->fe[1]); } } void bench_field_sqr(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_fe_sqr(&data->fe[0], &data->fe[0]); } } void bench_field_inverse(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_fe_inv(&data->fe[0], &data->fe[0]); secp256k1_fe_add(&data->fe[0], &data->fe[1]); } } void bench_field_inverse_var(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_fe_inv_var(&data->fe[0], &data->fe[0]); secp256k1_fe_add(&data->fe[0], &data->fe[1]); } } void bench_field_sqrt(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; secp256k1_fe t; for (i = 0; i < iters; i++) { t = data->fe[0]; j += secp256k1_fe_sqrt(&data->fe[0], &t); secp256k1_fe_add(&data->fe[0], &data->fe[1]); } CHECK(j <= iters); } void bench_group_double_var(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_gej_double_var(&data->gej[0], &data->gej[0], NULL); } } void bench_group_add_var(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_gej_add_var(&data->gej[0], &data->gej[0], &data->gej[1], NULL); } } void bench_group_add_affine(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_gej_add_ge(&data->gej[0], &data->gej[0], &data->ge[1]); } } void bench_group_add_affine_var(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { secp256k1_gej_add_ge_var(&data->gej[0], &data->gej[0], &data->ge[1], NULL); } } void bench_group_jacobi_var(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { j += secp256k1_gej_has_quad_y_var(&data->gej[0]); /* Vary the Y and Z coordinates of the input (the X coordinate doesn't matter to secp256k1_gej_has_quad_y_var). Note that the resulting coordinates will generally not correspond to a point on the curve, but this is not a problem for the code being benchmarked here. Adding and normalizing have less overhead than EC operations (which could guarantee the point remains on the curve). */ secp256k1_fe_add(&data->gej[0].y, &data->fe[1]); secp256k1_fe_add(&data->gej[0].z, &data->fe[2]); secp256k1_fe_normalize_var(&data->gej[0].y); secp256k1_fe_normalize_var(&data->gej[0].z); } CHECK(j <= iters); } void bench_group_to_affine_var(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; ++i) { secp256k1_ge_set_gej_var(&data->ge[1], &data->gej[0]); /* Use the output affine X/Y coordinates to vary the input X/Y/Z coordinates. Similar to bench_group_jacobi_var, this approach does not result in coordinates of points on the curve. */ secp256k1_fe_add(&data->gej[0].x, &data->ge[1].y); secp256k1_fe_add(&data->gej[0].y, &data->fe[2]); secp256k1_fe_add(&data->gej[0].z, &data->ge[1].x); secp256k1_fe_normalize_var(&data->gej[0].x); secp256k1_fe_normalize_var(&data->gej[0].y); secp256k1_fe_normalize_var(&data->gej[0].z); } } void bench_ecmult_wnaf(void* arg, int iters) { int i, bits = 0, overflow = 0; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { bits += secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar[0], WINDOW_A); overflow += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(overflow >= 0); CHECK(bits <= 256*iters); } void bench_wnaf_const(void* arg, int iters) { int i, bits = 0, overflow = 0; bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { bits += secp256k1_wnaf_const(data->wnaf, &data->scalar[0], WINDOW_A, 256); overflow += secp256k1_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(overflow >= 0); CHECK(bits <= 256*iters); } void bench_sha256(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_sha256 sha; for (i = 0; i < iters; 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 iters) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_hmac_sha256 hmac; for (i = 0; i < iters; 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 iters) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_rfc6979_hmac_sha256 rng; for (i = 0; i < iters; 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 iters) { int i; (void)arg; for (i = 0; i < iters; i++) { secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY)); } } void bench_context_sign(void* arg, int iters) { int i; (void)arg; for (i = 0; i < iters; i++) { secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN)); } } #ifndef USE_NUM_NONE void bench_num_jacobi(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; secp256k1_num nx, na, norder; secp256k1_scalar_get_num(&nx, &data->scalar[0]); secp256k1_scalar_order_get_num(&norder); secp256k1_scalar_get_num(&na, &data->scalar[1]); for (i = 0; i < iters; i++) { j += secp256k1_num_jacobi(&nx, &norder); secp256k1_num_add(&nx, &nx, &na); } CHECK(j <= iters); } #endif int main(int argc, char **argv) { bench_inv data; int iters = get_iters(20000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, iters*100); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, iters*100); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, iters*10); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, iters*10); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, iters); 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, iters*100); 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, iters*100); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, iters*10); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, iters*10); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, iters); 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, iters); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, iters); 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, iters*10); 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, iters*10); 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, iters*10); 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, iters*10); 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, iters); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "to_affine")) run_benchmark("group_to_affine_var", bench_group_to_affine_var, bench_setup, NULL, &data, 10, iters); if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, iters); if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, iters); if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, iters); if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, iters); 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, iters); if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 1 + iters/1000); if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 1 + iters/100); #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, iters*10); #endif return 0; } diff --git a/src/secp256k1/src/bench_multiset.c b/src/secp256k1/src/bench_multiset.c index bab248dfb..e6df754a0 100644 --- a/src/secp256k1/src/bench_multiset.c +++ b/src/secp256k1/src/bench_multiset.c @@ -1,51 +1,51 @@ -/********************************************************************** - * Copyright (c) 2017 Tomas van der Wansem * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Tomas van der Wansem * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include "include/secp256k1.h" #include "include/secp256k1_multiset.h" #include "util.h" #include "bench.h" secp256k1_context *ctx; #define UNUSED(x) (void)(x) #define BUFSIZE (3 * 32) void bench_multiset(void* arg, int iters) { int it = 0; int n, m; unsigned char result[32]; secp256k1_multiset multiset; UNUSED(arg); secp256k1_multiset_init(ctx, &multiset); for (m = 0; m < iters; m++) { unsigned char buf[BUFSIZE]; for (n = 0; n < BUFSIZE; n++) { buf[n] = it++; } secp256k1_multiset_add(ctx, &multiset, buf, sizeof(buf)); } secp256k1_multiset_finalize(ctx, result, &multiset); } void bench_multiset_setup(void* arg) { UNUSED(arg); } int main(void) { int iters = get_iters(300000); ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); run_benchmark("multiset", bench_multiset, bench_multiset_setup, NULL, NULL, 5, iters); secp256k1_context_destroy(ctx); return 0; } diff --git a/src/secp256k1/src/bench_recover.c b/src/secp256k1/src/bench_recover.c index e952ed121..3f6270ce8 100644 --- a/src/secp256k1/src/bench_recover.c +++ b/src/secp256k1/src/bench_recover.c @@ -1,62 +1,62 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include "include/secp256k1.h" #include "include/secp256k1_recovery.h" #include "util.h" #include "bench.h" typedef struct { secp256k1_context *ctx; unsigned char msg[32]; unsigned char sig[64]; } bench_recover_data; void bench_recover(void* arg, int iters) { int i; bench_recover_data *data = (bench_recover_data*)arg; secp256k1_pubkey pubkey; unsigned char pubkeyc[33]; for (i = 0; i < iters; i++) { int j; size_t pubkeylen = 33; secp256k1_ecdsa_recoverable_signature sig; CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); for (j = 0; j < 32; j++) { data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ data->msg[j] = data->sig[j]; /* Move former R to message. */ data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ } } } void bench_recover_setup(void* arg) { int i; bench_recover_data *data = (bench_recover_data*)arg; for (i = 0; i < 32; i++) { data->msg[i] = 1 + i; } for (i = 0; i < 64; i++) { data->sig[i] = 65 + i; } } int main(void) { bench_recover_data data; int iters = get_iters(20000); data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters); secp256k1_context_destroy(data.ctx); return 0; } diff --git a/src/secp256k1/src/bench_schnorrsig.c b/src/secp256k1/src/bench_schnorrsig.c index 315f5af28..f7f591c41 100644 --- a/src/secp256k1/src/bench_schnorrsig.c +++ b/src/secp256k1/src/bench_schnorrsig.c @@ -1,102 +1,102 @@ -/********************************************************************** - * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include #include #include "include/secp256k1.h" #include "include/secp256k1_schnorrsig.h" #include "util.h" #include "bench.h" typedef struct { secp256k1_context *ctx; int n; const secp256k1_keypair **keypairs; const unsigned char **pk; const unsigned char **sigs; const unsigned char **msgs; } bench_schnorrsig_data; void bench_schnorrsig_sign(void* arg, int iters) { bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; int i; unsigned char msg[32] = "benchmarkexamplemessagetemplate"; unsigned char sig[64]; for (i = 0; i < iters; i++) { msg[0] = i; msg[1] = i >> 8; CHECK(secp256k1_schnorrsig_sign(data->ctx, sig, msg, data->keypairs[i], NULL, NULL)); } } void bench_schnorrsig_verify(void* arg, int iters) { bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg; int i; for (i = 0; i < iters; i++) { secp256k1_xonly_pubkey pk; CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pk[i]) == 1); CHECK(secp256k1_schnorrsig_verify(data->ctx, data->sigs[i], data->msgs[i], &pk)); } } int main(void) { int i; bench_schnorrsig_data data; int iters = get_iters(10000); data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *)); data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); for (i = 0; i < iters; i++) { unsigned char sk[32]; unsigned char *msg = (unsigned char *)malloc(32); unsigned char *sig = (unsigned char *)malloc(64); secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair)); unsigned char *pk_char = (unsigned char *)malloc(32); secp256k1_xonly_pubkey pk; msg[0] = sk[0] = i; msg[1] = sk[1] = i >> 8; msg[2] = sk[2] = i >> 16; msg[3] = sk[3] = i >> 24; memset(&msg[4], 'm', 28); memset(&sk[4], 's', 28); data.keypairs[i] = keypair; data.pk[i] = pk_char; data.msgs[i] = msg; data.sigs[i] = sig; CHECK(secp256k1_keypair_create(data.ctx, keypair, sk)); CHECK(secp256k1_schnorrsig_sign(data.ctx, sig, msg, keypair, NULL, NULL)); CHECK(secp256k1_keypair_xonly_pub(data.ctx, &pk, NULL, keypair)); CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1); } run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters); run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters); for (i = 0; i < iters; i++) { free((void *)data.keypairs[i]); free((void *)data.pk[i]); free((void *)data.msgs[i]); free((void *)data.sigs[i]); } free(data.keypairs); free(data.pk); free(data.msgs); free(data.sigs); secp256k1_context_destroy(data.ctx); return 0; } diff --git a/src/secp256k1/src/bench_sign.c b/src/secp256k1/src/bench_sign.c index 3d725c5de..467041583 100644 --- a/src/secp256k1/src/bench_sign.c +++ b/src/secp256k1/src/bench_sign.c @@ -1,82 +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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include "include/secp256k1.h" #include "util.h" #include "bench.h" #ifdef ENABLE_MODULE_SCHNORR #include "include/secp256k1_schnorr.h" #endif typedef struct { secp256k1_context* ctx; unsigned char msg[32]; unsigned char key[32]; } bench_sign_data; static void bench_sign_setup(void* arg) { int i; bench_sign_data *data = (bench_sign_data*)arg; for (i = 0; i < 32; i++) { data->msg[i] = i + 1; } for (i = 0; i < 32; i++) { data->key[i] = i + 65; } } static void bench_sign_run(void* arg, int iters) { int i; bench_sign_data *data = (bench_sign_data*)arg; unsigned char sig[74]; for (i = 0; i < iters; i++) { size_t siglen = 74; int j; secp256k1_ecdsa_signature signature; CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature)); for (j = 0; j < 32; j++) { data->msg[j] = sig[j]; data->key[j] = sig[j + 32]; } } } #ifdef ENABLE_MODULE_SCHNORR static void bench_schnorr_sign_run(void* arg, int iters) { int i,j; bench_sign_data *data = (bench_sign_data*)arg; unsigned char sig[64]; for (i = 0; i < iters; i++) { CHECK(secp256k1_schnorr_sign(data->ctx, sig, data->msg, data->key, NULL, NULL)); for (j = 0; j < 32; j++) { data->msg[j] = sig[j]; data->key[j] = sig[j + 32]; } } } #endif int main(void) { bench_sign_data data; int iters = get_iters(20000); data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters); #ifdef ENABLE_MODULE_SCHNORR run_benchmark("schnorr_sign", bench_schnorr_sign_run, bench_sign_setup, NULL, &data, 10, iters); #endif secp256k1_context_destroy(data.ctx); return 0; } diff --git a/src/secp256k1/src/bench_verify.c b/src/secp256k1/src/bench_verify.c index 89f60c58d..86c27f905 100644 --- a/src/secp256k1/src/bench_verify.c +++ b/src/secp256k1/src/bench_verify.c @@ -1,143 +1,143 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include #include #include "include/secp256k1.h" #include "util.h" #include "bench.h" #ifdef ENABLE_MODULE_SCHNORR #include "include/secp256k1_schnorr.h" #endif #ifdef ENABLE_OPENSSL_TESTS #include #include #include #endif typedef struct { secp256k1_context *ctx; unsigned char msg[32]; unsigned char key[32]; unsigned char sig[72]; size_t siglen; unsigned char pubkey[33]; size_t pubkeylen; #ifdef ENABLE_OPENSSL_TESTS EC_GROUP* ec_group; #endif } bench_verify_data; static void bench_verify(void* arg, int iters) { int i; bench_verify_data* data = (bench_verify_data*)arg; for (i = 0; i < iters; i++) { secp256k1_pubkey pubkey; secp256k1_ecdsa_signature sig; data->sig[data->siglen - 1] ^= (i & 0xFF); data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0)); data->sig[data->siglen - 1] ^= (i & 0xFF); data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); } } #ifdef ENABLE_OPENSSL_TESTS static void bench_verify_openssl(void* arg, int iters) { int i; bench_verify_data* data = (bench_verify_data*)arg; for (i = 0; i < iters; i++) { data->sig[data->siglen - 1] ^= (i & 0xFF); data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); { EC_KEY *pkey = EC_KEY_new(); const unsigned char *pubkey = &data->pubkey[0]; int result; CHECK(pkey != NULL); result = EC_KEY_set_group(pkey, data->ec_group); CHECK(result); result = (o2i_ECPublicKey(&pkey, &pubkey, data->pubkeylen)) != NULL; CHECK(result); result = ECDSA_verify(0, &data->msg[0], sizeof(data->msg), &data->sig[0], data->siglen, pkey) == (i == 0); CHECK(result); EC_KEY_free(pkey); } data->sig[data->siglen - 1] ^= (i & 0xFF); data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); } } #endif #ifdef ENABLE_MODULE_SCHNORR static void bench_schnorr_verify(void* arg, int iters) { int i; bench_verify_data* data = (bench_verify_data*)arg; for (i = 0; i < iters; i++) { secp256k1_pubkey pubkey; data->sig[data->siglen - 1] ^= (i & 0xFF); data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); CHECK(secp256k1_schnorr_verify(data->ctx, data->sig, data->msg, &pubkey) == (i == 0)); data->sig[data->siglen - 1] ^= (i & 0xFF); data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); } } #endif int main(void) { int i; secp256k1_pubkey pubkey; secp256k1_ecdsa_signature sig; bench_verify_data data; int iters = get_iters(20000); data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); for (i = 0; i < 32; i++) { data.msg[i] = 1 + i; } for (i = 0; i < 32; i++) { data.key[i] = 33 + i; } data.siglen = 72; CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); data.pubkeylen = 33; CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters); #ifdef ENABLE_OPENSSL_TESTS data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); run_benchmark("ecdsa_verify_openssl", bench_verify_openssl, NULL, NULL, &data, 10, iters); EC_GROUP_free(data.ec_group); #endif #ifdef ENABLE_MODULE_SCHNORR CHECK(secp256k1_schnorr_sign(data.ctx, data.sig, data.msg, data.key, NULL, NULL)); data.siglen = 64; run_benchmark("schnorr_verify", bench_schnorr_verify, NULL, NULL, &data, 10, iters); #endif secp256k1_context_destroy(data.ctx); return 0; } diff --git a/src/secp256k1/src/ecdsa.h b/src/secp256k1/src/ecdsa.h index 80590c7cc..d5e54d8ce 100644 --- a/src/secp256k1/src/ecdsa.h +++ b/src/secp256k1/src/ecdsa.h @@ -1,21 +1,21 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_ECDSA_H #define SECP256K1_ECDSA_H #include #include "scalar.h" #include "group.h" #include "ecmult.h" static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); #endif /* SECP256K1_ECDSA_H */ diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h index 5f54b59fa..156a33d11 100644 --- a/src/secp256k1/src/ecdsa_impl.h +++ b/src/secp256k1/src/ecdsa_impl.h @@ -1,315 +1,315 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_ECDSA_IMPL_H #define SECP256K1_ECDSA_IMPL_H #include "scalar.h" #include "field.h" #include "group.h" #include "ecmult.h" #include "ecmult_gen.h" #include "ecdsa.h" /** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1 * sage: for t in xrange(1023, -1, -1): * .. p = 2**256 - 2**32 - t * .. if p.is_prime(): * .. print '%x'%p * .. break * 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f' * sage: a = 0 * sage: b = 7 * sage: F = FiniteField (p) * sage: '%x' % (EllipticCurve ([F (a), F (b)]).order()) * 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141' */ static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL ); /** Difference between field and order, values 'p' and 'n' values defined in * "Standards for Efficient Cryptography" (SEC2) 2.7.1. * sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F * sage: a = 0 * sage: b = 7 * sage: F = FiniteField (p) * sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order()) * '14551231950b75fc4402da1722fc9baee' */ static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL ); static int secp256k1_der_read_len(size_t *len, const unsigned char **sigp, const unsigned char *sigend) { size_t lenleft; unsigned char b1; VERIFY_CHECK(len != NULL); *len = 0; if (*sigp >= sigend) { return 0; } b1 = *((*sigp)++); if (b1 == 0xFF) { /* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */ return 0; } if ((b1 & 0x80) == 0) { /* X.690-0207 8.1.3.4 short form length octets */ *len = b1; return 1; } if (b1 == 0x80) { /* Indefinite length is not allowed in DER. */ return 0; } /* X.690-207 8.1.3.5 long form length octets */ lenleft = b1 & 0x7F; /* lenleft is at least 1 */ if (lenleft > (size_t)(sigend - *sigp)) { return 0; } if (**sigp == 0) { /* Not the shortest possible length encoding. */ return 0; } if (lenleft > sizeof(size_t)) { /* The resulting length would exceed the range of a size_t, so * certainly longer than the passed array size. */ return 0; } while (lenleft > 0) { *len = (*len << 8) | **sigp; (*sigp)++; lenleft--; } if (*len > (size_t)(sigend - *sigp)) { /* Result exceeds the length of the passed array. */ return 0; } if (*len < 128) { /* Not the shortest possible length encoding. */ return 0; } return 1; } static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) { int overflow = 0; unsigned char ra[32] = {0}; size_t rlen; if (*sig == sigend || **sig != 0x02) { /* Not a primitive integer (X.690-0207 8.3.1). */ return 0; } (*sig)++; if (secp256k1_der_read_len(&rlen, sig, sigend) == 0) { return 0; } if (rlen == 0 || *sig + rlen > sigend) { /* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */ return 0; } if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) { /* Excessive 0x00 padding. */ return 0; } if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) { /* Excessive 0xFF padding. */ return 0; } if ((**sig & 0x80) == 0x80) { /* Negative. */ overflow = 1; } /* There is at most one leading zero byte: * if there were two leading zero bytes, we would have failed and returned 0 * because of excessive 0x00 padding already. */ if (rlen > 0 && **sig == 0) { /* Skip leading zero byte */ rlen--; (*sig)++; } if (rlen > 32) { overflow = 1; } if (!overflow) { memcpy(ra + 32 - rlen, *sig, rlen); secp256k1_scalar_set_b32(r, ra, &overflow); } if (overflow) { secp256k1_scalar_set_int(r, 0); } (*sig) += rlen; return 1; } static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) { const unsigned char *sigend = sig + size; size_t rlen; if (sig == sigend || *(sig++) != 0x30) { /* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */ return 0; } if (secp256k1_der_read_len(&rlen, &sig, sigend) == 0) { return 0; } if (rlen != (size_t)(sigend - sig)) { /* Tuple exceeds bounds or garage after tuple. */ return 0; } if (!secp256k1_der_parse_integer(rr, &sig, sigend)) { return 0; } if (!secp256k1_der_parse_integer(rs, &sig, sigend)) { return 0; } if (sig != sigend) { /* Trailing garbage inside tuple. */ return 0; } return 1; } static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) { unsigned char r[33] = {0}, s[33] = {0}; unsigned char *rp = r, *sp = s; size_t lenR = 33, lenS = 33; secp256k1_scalar_get_b32(&r[1], ar); secp256k1_scalar_get_b32(&s[1], as); while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } if (*size < 6+lenS+lenR) { *size = 6 + lenS + lenR; return 0; } *size = 6 + lenS + lenR; sig[0] = 0x30; sig[1] = 4 + lenS + lenR; sig[2] = 0x02; sig[3] = lenR; memcpy(sig+4, rp, lenR); sig[4+lenR] = 0x02; sig[5+lenR] = lenS; memcpy(sig+lenR+6, sp, lenS); return 1; } static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { unsigned char c[32]; secp256k1_scalar sn, u1, u2; #if !defined(EXHAUSTIVE_TEST_ORDER) secp256k1_fe xr; #endif secp256k1_gej pubkeyj; secp256k1_gej pr; if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { return 0; } secp256k1_scalar_inverse_var(&sn, sigs); secp256k1_scalar_mul(&u1, &sn, message); secp256k1_scalar_mul(&u2, &sn, sigr); secp256k1_gej_set_ge(&pubkeyj, pubkey); secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1); if (secp256k1_gej_is_infinity(&pr)) { return 0; } #if defined(EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar computed_r; secp256k1_ge pr_ge; secp256k1_ge_set_gej(&pr_ge, &pr); secp256k1_fe_normalize(&pr_ge.x); secp256k1_fe_get_b32(c, &pr_ge.x); secp256k1_scalar_set_b32(&computed_r, c, NULL); return secp256k1_scalar_eq(sigr, &computed_r); } #else secp256k1_scalar_get_b32(c, sigr); secp256k1_fe_set_b32(&xr, c); /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n) * in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p), * compute the remainder modulo n, and compare it to xr. However: * * xr == X(pr) mod n * <=> exists h. (xr + h * n < p && xr + h * n == X(pr)) * [Since 2 * n > p, h can only be 0 or 1] * <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr)) * [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p] * <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p) * [Multiplying both sides of the equations by pr.z^2 mod p] * <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x) * * Thus, we can avoid the inversion, but we have to check both cases separately. * secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. */ if (secp256k1_gej_eq_x_var(&xr, &pr)) { /* xr * pr.z^2 mod p == pr.x, so the signature is valid. */ return 1; } if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) { /* xr + n >= p, so we can skip testing the second case. */ return 0; } secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe); if (secp256k1_gej_eq_x_var(&xr, &pr)) { /* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */ return 1; } return 0; #endif } static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { unsigned char b[32]; secp256k1_gej rp; secp256k1_ge r; secp256k1_scalar n; int overflow = 0; int high; secp256k1_ecmult_gen(ctx, &rp, nonce); secp256k1_ge_set_gej(&r, &rp); secp256k1_fe_normalize(&r.x); secp256k1_fe_normalize(&r.y); secp256k1_fe_get_b32(b, &r.x); secp256k1_scalar_set_b32(sigr, b, &overflow); if (recid) { /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. */ *recid = (overflow << 1) | secp256k1_fe_is_odd(&r.y); } secp256k1_scalar_mul(&n, sigr, seckey); secp256k1_scalar_add(&n, &n, message); secp256k1_scalar_inverse(sigs, nonce); secp256k1_scalar_mul(sigs, sigs, &n); secp256k1_scalar_clear(&n); secp256k1_gej_clear(&rp); secp256k1_ge_clear(&r); high = secp256k1_scalar_is_high(sigs); secp256k1_scalar_cond_negate(sigs, high); if (recid) { *recid ^= high; } /* P.x = order is on the curve, so technically sig->r could end up being zero, which would be an invalid signature. * This is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. */ return !secp256k1_scalar_is_zero(sigr) & !secp256k1_scalar_is_zero(sigs); } #endif /* SECP256K1_ECDSA_IMPL_H */ diff --git a/src/secp256k1/src/eckey.h b/src/secp256k1/src/eckey.h index b621f1e6c..5be3a64b8 100644 --- a/src/secp256k1/src/eckey.h +++ b/src/secp256k1/src/eckey.h @@ -1,25 +1,25 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_ECKEY_H #define SECP256K1_ECKEY_H #include #include "group.h" #include "scalar.h" #include "ecmult.h" #include "ecmult_gen.h" static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); #endif /* SECP256K1_ECKEY_H */ diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h index e2e72d930..a39cb7965 100644 --- a/src/secp256k1/src/eckey_impl.h +++ b/src/secp256k1/src/eckey_impl.h @@ -1,96 +1,96 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_ECKEY_IMPL_H #define SECP256K1_ECKEY_IMPL_H #include "eckey.h" #include "scalar.h" #include "field.h" #include "group.h" #include "ecmult_gen.h" static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { secp256k1_fe x; return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD); } else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { secp256k1_fe x, y; if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) { return 0; } secp256k1_ge_set_xy(elem, &x, &y); if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && secp256k1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { return 0; } return secp256k1_ge_is_valid_var(elem); } else { return 0; } } static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { if (secp256k1_ge_is_infinity(elem)) { return 0; } secp256k1_fe_normalize_var(&elem->x); secp256k1_fe_normalize_var(&elem->y); secp256k1_fe_get_b32(&pub[1], &elem->x); if (compressed) { *size = 33; pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; } else { *size = 65; pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; secp256k1_fe_get_b32(&pub[33], &elem->y); } return 1; } static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { secp256k1_scalar_add(key, key, tweak); return !secp256k1_scalar_is_zero(key); } static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { secp256k1_gej pt; secp256k1_scalar one; secp256k1_gej_set_ge(&pt, key); secp256k1_scalar_set_int(&one, 1); secp256k1_ecmult(ctx, &pt, &pt, &one, tweak); if (secp256k1_gej_is_infinity(&pt)) { return 0; } secp256k1_ge_set_gej(key, &pt); return 1; } static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) { int ret; ret = !secp256k1_scalar_is_zero(tweak); secp256k1_scalar_mul(key, key, tweak); return ret; } static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { secp256k1_scalar zero; secp256k1_gej pt; if (secp256k1_scalar_is_zero(tweak)) { return 0; } secp256k1_scalar_set_int(&zero, 0); secp256k1_gej_set_ge(&pt, key); secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero); secp256k1_ge_set_gej(key, &pt); return 1; } #endif /* SECP256K1_ECKEY_IMPL_H */ diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h index 09e814641..7aa394a11 100644 --- a/src/secp256k1/src/ecmult.h +++ b/src/secp256k1/src/ecmult.h @@ -1,46 +1,46 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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 */ secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ } secp256k1_ecmult_context; static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE; static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc); static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src); 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. If no scratch space is given then a simple algorithm is used that * simply multiplies the points with the corresponding scalars and adds them up. * 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_callback* error_callback, 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.h b/src/secp256k1/src/ecmult_const.h index 03bb33257..d6f0ea222 100644 --- a/src/secp256k1/src/ecmult_const.h +++ b/src/secp256k1/src/ecmult_const.h @@ -1,20 +1,20 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_ECMULT_CONST_H #define SECP256K1_ECMULT_CONST_H #include "scalar.h" #include "group.h" /** * Multiply: R = q*A (in constant-time) * Here `bits` should be set to the maximum bitlength of the _absolute value_ of `q`, plus * one because we internally sometimes add 2 to the number during the WNAF conversion. */ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q, int bits); #endif /* SECP256K1_ECMULT_CONST_H */ diff --git a/src/secp256k1/src/ecmult_const_impl.h b/src/secp256k1/src/ecmult_const_impl.h index bb9511108..0e1fb965c 100644 --- a/src/secp256k1/src/ecmult_const_impl.h +++ b/src/secp256k1/src/ecmult_const_impl.h @@ -1,254 +1,254 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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" /* This is like `ECMULT_TABLE_GET_GE` but is constant time */ #define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ int m = 0; \ /* Extract the sign-bit for a constant time absolute-value. */ \ int mask = (n) >> (sizeof(n) * CHAR_BIT - 1); \ int abs_n = ((n) + mask) ^ mask; \ int idx_n = abs_n >> 1; \ 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)); \ /* Unconditionally set r->x = (pre)[m].x. r->y = (pre)[m].y. because it's either the correct one \ * or will get replaced in the later iterations, this is needed to make sure `r` is initialized. */ \ (r)->x = (pre)[m].x; \ (r)->y = (pre)[m].y; \ for (m = 1; 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-Verlag 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, const secp256k1_scalar *scalar, int w, int size) { int global_sign; int skew = 0; int word = 0; /* 1 2 3 */ int u_last; int u; int flip; int bit; secp256k1_scalar s; int not_neg_one; VERIFY_CHECK(w > 0); VERIFY_CHECK(size > 0); /* Note that we cannot handle even numbers by negating them to be odd, as is * 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. * * In fact, we _do_ want to negate numbers to minimize their bit-lengths (and in * particular, to ensure that the outputs from the endomorphism-split fit into * 128 bits). If we negate, the parity of our number flips, inverting which of * {1, 2} we want to add to the scalar when ensuring that it's odd. Further * complicating things, -1 interacts badly with `secp256k1_scalar_cadd_bit` and * we need to special-case it in this logic. */ flip = secp256k1_scalar_is_high(scalar); /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ bit = flip ^ !secp256k1_scalar_is_even(scalar); /* We check for negative one, since adding 2 to it will cause an overflow */ secp256k1_scalar_negate(&s, scalar); not_neg_one = !secp256k1_scalar_is_one(&s); s = *scalar; 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); do { int even; /* 4.1 4.4 */ u = secp256k1_scalar_shr_int(&s, w); /* 4.2 */ even = ((u & 1) == 0); /* In contrast to the original algorithm, u_last is always > 0 and * therefore we do not need to check its sign. In particular, it's easy * to see that u_last is never < 0 because u is never < 0. Moreover, * u_last is never = 0 because u is never even after a loop * iteration. The same holds analogously for the initial value of * u_last (in the first loop iteration). */ VERIFY_CHECK(u_last > 0); VERIFY_CHECK((u_last & 1) == 1); u += even; u_last -= even * (1 << w); /* 4.3, adapted for global sign change */ wnaf[word++] = u_last * global_sign; u_last = u; } while (word * w < size); wnaf[word] = u * global_sign; VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); VERIFY_CHECK(word == WNAF_SIZE_BITS(size, w)); return skew; } static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar, int size) { secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ge tmpa; secp256k1_fe Z; int skew_1; 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; int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; int i; /* build wnaf representation for q. */ int rsize = size; if (size > 128) { rsize = 128; /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar); skew_1 = secp256k1_wnaf_const(wnaf_1, &q_1, WINDOW_A - 1, 128); skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128); } else { skew_1 = secp256k1_wnaf_const(wnaf_1, scalar, WINDOW_A - 1, size); skew_lam = 0; } /* 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); } if (size > 128) { for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); } } /* 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_BITS(rsize, WINDOW_A - 1)]; VERIFY_CHECK(i != 0); ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); secp256k1_gej_set_ge(r, &tmpa); if (size > 128) { i = wnaf_lam[WNAF_SIZE_BITS(rsize, 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); } /* remaining loop iterations */ for (i = WNAF_SIZE_BITS(rsize, WINDOW_A - 1) - 1; i >= 0; i--) { int n; int j; for (j = 0; j < WINDOW_A - 1; ++j) { secp256k1_gej_double(r, r); } 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); if (size > 128) { 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); } } secp256k1_fe_mul(&r->z, &r->z, &Z); { /* Correct for wNAF skew */ secp256k1_ge correction = *a; secp256k1_ge_storage correction_1_stor; secp256k1_ge_storage correction_lam_stor; 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); if (size > 128) { secp256k1_ge_to_storage(&correction_lam_stor, a); } 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); if (size > 128) { secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); } /* Apply the correction */ secp256k1_ge_from_storage(&correction, &correction_1_stor); secp256k1_ge_neg(&correction, &correction); secp256k1_gej_add_ge(r, r, &correction); if (size > 128) { 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 /* SECP256K1_ECMULT_CONST_IMPL_H */ diff --git a/src/secp256k1/src/ecmult_gen.h b/src/secp256k1/src/ecmult_gen.h index 30815e5aa..539618dcb 100644 --- a/src/secp256k1/src/ecmult_gen.h +++ b/src/secp256k1/src/ecmult_gen.h @@ -1,50 +1,50 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_ECMULT_GEN_H #define SECP256K1_ECMULT_GEN_H #include "scalar.h" #include "group.h" #if ECMULT_GEN_PREC_BITS != 2 && ECMULT_GEN_PREC_BITS != 4 && ECMULT_GEN_PREC_BITS != 8 # error "Set ECMULT_GEN_PREC_BITS to 2, 4 or 8." #endif #define ECMULT_GEN_PREC_B ECMULT_GEN_PREC_BITS #define ECMULT_GEN_PREC_G (1 << ECMULT_GEN_PREC_B) #define ECMULT_GEN_PREC_N (256 / ECMULT_GEN_PREC_B) typedef struct { /* For accelerating the computation of a*G: * To harden against timing attacks, use the following mechanism: * * Break up the multiplicand into groups of PREC_B bits, called n_0, n_1, n_2, ..., n_(PREC_N-1). * * Compute sum(n_i * (PREC_G)^i * G + U_i, i=0 ... PREC_N-1), where: * * U_i = U * 2^i, for i=0 ... PREC_N-2 * * U_i = U * (1-2^(PREC_N-1)), for i=PREC_N-1 * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0 ... PREC_N-1) = 0. * For each i, and each of the PREC_G possible values of n_i, (n_i * (PREC_G)^i * G + U_i) is * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0 ... PREC_N-1). * None of the resulting prec group elements have a known scalar, and neither do any of * the intermediate sums while computing a*G. */ secp256k1_ge_storage (*prec)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G]; /* prec[j][i] = (PREC_G)^j * i * G + U_i */ secp256k1_scalar blind; secp256k1_gej initial; } secp256k1_ecmult_gen_context; static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx); static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, void **prealloc); static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context* src); static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx); /** Multiply with the generator: R = a*G */ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); #endif /* SECP256K1_ECMULT_GEN_H */ diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h index 30ac16518..384a67fae 100644 --- a/src/secp256k1/src/ecmult_gen_impl.h +++ b/src/secp256k1/src/ecmult_gen_impl.h @@ -1,208 +1,208 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_ECMULT_GEN_IMPL_H #define SECP256K1_ECMULT_GEN_IMPL_H #include "util.h" #include "scalar.h" #include "group.h" #include "ecmult_gen.h" #include "hash_impl.h" #ifdef USE_ECMULT_STATIC_PRECOMPUTATION #include "ecmult_static_context.h" #endif #ifndef USE_ECMULT_STATIC_PRECOMPUTATION static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = ROUND_TO_ALIGN(sizeof(*((secp256k1_ecmult_gen_context*) NULL)->prec)); #else static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = 0; #endif static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) { ctx->prec = NULL; } static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, void **prealloc) { #ifndef USE_ECMULT_STATIC_PRECOMPUTATION secp256k1_ge prec[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G]; secp256k1_gej gj; secp256k1_gej nums_gej; int i, j; size_t const prealloc_size = SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; void* const base = *prealloc; #endif if (ctx->prec != NULL) { return; } #ifndef USE_ECMULT_STATIC_PRECOMPUTATION ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])manual_alloc(prealloc, prealloc_size, base, prealloc_size); /* get the generator */ secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ { static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; secp256k1_fe nums_x; secp256k1_ge nums_ge; int r; r = secp256k1_fe_set_b32(&nums_x, nums_b32); (void)r; VERIFY_CHECK(r); r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); (void)r; VERIFY_CHECK(r); secp256k1_gej_set_ge(&nums_gej, &nums_ge); /* Add G to make the bits in x uniformly distributed. */ secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL); } /* compute prec. */ { secp256k1_gej precj[ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G]; /* Jacobian versions of prec. */ secp256k1_gej gbase; secp256k1_gej numsbase; gbase = gj; /* PREC_G^j * G */ numsbase = nums_gej; /* 2^j * nums. */ for (j = 0; j < ECMULT_GEN_PREC_N; j++) { /* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */ precj[j*ECMULT_GEN_PREC_G] = numsbase; for (i = 1; i < ECMULT_GEN_PREC_G; i++) { secp256k1_gej_add_var(&precj[j*ECMULT_GEN_PREC_G + i], &precj[j*ECMULT_GEN_PREC_G + i - 1], &gbase, NULL); } /* Multiply gbase by PREC_G. */ for (i = 0; i < ECMULT_GEN_PREC_B; i++) { secp256k1_gej_double_var(&gbase, &gbase, NULL); } /* Multiply numbase by 2. */ secp256k1_gej_double_var(&numsbase, &numsbase, NULL); if (j == ECMULT_GEN_PREC_N - 2) { /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ secp256k1_gej_neg(&numsbase, &numsbase); secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); } } secp256k1_ge_set_all_gej_var(prec, precj, ECMULT_GEN_PREC_N * ECMULT_GEN_PREC_G); } for (j = 0; j < ECMULT_GEN_PREC_N; j++) { for (i = 0; i < ECMULT_GEN_PREC_G; i++) { secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*ECMULT_GEN_PREC_G + i]); } } #else (void)prealloc; ctx->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])secp256k1_ecmult_static_context; #endif secp256k1_ecmult_gen_blind(ctx, NULL); } static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) { return ctx->prec != NULL; } static void secp256k1_ecmult_gen_context_finalize_memcpy(secp256k1_ecmult_gen_context *dst, const secp256k1_ecmult_gen_context *src) { #ifndef USE_ECMULT_STATIC_PRECOMPUTATION if (src->prec != NULL) { /* We cast to void* first to suppress a -Wcast-align warning. */ dst->prec = (secp256k1_ge_storage (*)[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G])(void*)((unsigned char*)dst + ((unsigned char*)src->prec - (unsigned char*)src)); } #else (void)dst, (void)src; #endif } static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { secp256k1_scalar_clear(&ctx->blind); secp256k1_gej_clear(&ctx->initial); ctx->prec = NULL; } static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { secp256k1_ge add; secp256k1_ge_storage adds; secp256k1_scalar gnb; int bits; int i, j; memset(&adds, 0, sizeof(adds)); *r = ctx->initial; /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ secp256k1_scalar_add(&gnb, gn, &ctx->blind); add.infinity = 0; for (j = 0; j < ECMULT_GEN_PREC_N; j++) { bits = secp256k1_scalar_get_bits(&gnb, j * ECMULT_GEN_PREC_B, ECMULT_GEN_PREC_B); for (i = 0; i < ECMULT_GEN_PREC_G; i++) { /** This uses a conditional move to avoid any secret data in array indexes. * _Any_ use of secret indexes has been demonstrated to result in timing * sidechannels, even when the cache-line access patterns are uniform. * See also: * "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe * (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and * "Cache Attacks and Countermeasures: the Case of AES", RSA 2006, * by Dag Arne Osvik, Adi Shamir, and Eran Tromer - * (http://www.tau.ac.il/~tromer/papers/cache.pdf) + * (https://www.tau.ac.il/~tromer/papers/cache.pdf) */ secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits); } secp256k1_ge_from_storage(&add, &adds); secp256k1_gej_add_ge(r, r, &add); } bits = 0; secp256k1_ge_clear(&add); secp256k1_scalar_clear(&gnb); } /* Setup blinding values for secp256k1_ecmult_gen. */ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { secp256k1_scalar b; secp256k1_gej gb; secp256k1_fe s; unsigned char nonce32[32]; secp256k1_rfc6979_hmac_sha256 rng; int overflow; unsigned char keydata[64] = {0}; if (seed32 == NULL) { /* When seed is NULL, reset the initial point and blinding value. */ secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g); secp256k1_gej_neg(&ctx->initial, &ctx->initial); secp256k1_scalar_set_int(&ctx->blind, 1); } /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ secp256k1_scalar_get_b32(nonce32, &ctx->blind); /** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, * and guards against weak or adversarial seeds. This is a simpler and safer interface than * asking the caller for blinding values directly and expecting them to retry on failure. */ memcpy(keydata, nonce32, 32); if (seed32 != NULL) { memcpy(keydata + 32, seed32, 32); } secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32); memset(keydata, 0, sizeof(keydata)); /* Accept unobservably small non-uniformity. */ secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); overflow = !secp256k1_fe_set_b32(&s, nonce32); overflow |= secp256k1_fe_is_zero(&s); secp256k1_fe_cmov(&s, &secp256k1_fe_one, overflow); /* Randomize the projection to defend against multiplier sidechannels. */ secp256k1_gej_rescale(&ctx->initial, &s); secp256k1_fe_clear(&s); secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); secp256k1_scalar_set_b32(&b, nonce32, NULL); /* A blinding value of 0 works, but would undermine the projection hardening. */ secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b)); secp256k1_rfc6979_hmac_sha256_finalize(&rng); memset(nonce32, 0, 32); secp256k1_ecmult_gen(ctx, &gb, &b); secp256k1_scalar_negate(&b, &b); ctx->blind = b; ctx->initial = gb; secp256k1_scalar_clear(&b); secp256k1_gej_clear(&gb); } #endif /* SECP256K1_ECMULT_GEN_IMPL_H */ diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h index f7566a8b9..50d92b161 100644 --- a/src/secp256k1/src/ecmult_impl.h +++ b/src/secp256k1/src/ecmult_impl.h @@ -1,1083 +1,1083 @@ -/***************************************************************************** - * 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. * - *****************************************************************************/ +/****************************************************************************** + * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php. * + ******************************************************************************/ #ifndef SECP256K1_ECMULT_IMPL_H #define SECP256K1_ECMULT_IMPL_H #include #include #include "util.h" #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 values for ECMULT_WINDOW_SIZE result in possibly better * performance at the cost of an exponentially larger precomputed * table. The exact table size is * (1 << (WINDOW_G - 2)) * sizeof(secp256k1_ge_storage) bytes, * where sizeof(secp256k1_ge_storage) is typically 64 bytes but can * be larger due to platform-specific padding and alignment. * Two tables of this size are used (due to the endomorphism * optimization). */ # define WINDOW_G ECMULT_WINDOW_SIZE #endif /* Noone will ever need more than a window size of 24. The code might * be correct for larger values of ECMULT_WINDOW_SIZE but this is not * tested. * * The following limitations are known, and there are probably more: * If WINDOW_G > 27 and size_t has 32 bits, then the code is incorrect * because the size of the memory object that we allocate (in bytes) * will not fit in a size_t. * If WINDOW_G > 31 and int has 32 bits, then the code is incorrect * because certain expressions will overflow. */ #if ECMULT_WINDOW_SIZE < 2 || ECMULT_WINDOW_SIZE > 24 # error Set ECMULT_WINDOW_SIZE to an integer in range [2..24]. #endif #define WNAF_BITS 128 #define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w)) #define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w) /** The number of entries a table with precomputed multiples needs to have. */ #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 */ #define ECMULT_PIPPENGER_THRESHOLD 88 #define ECMULT_MAX_POINTS_PER_BATCH 5000000 /** 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. * * 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(const int n, secp256k1_ge_storage *pre, const secp256k1_gej *a) { secp256k1_gej d; secp256k1_ge d_ge, p_ge; secp256k1_gej pj; secp256k1_fe zi; secp256k1_fe zr; secp256k1_fe dx_over_dz_squared; int i; VERIFY_CHECK(!a->infinity); secp256k1_gej_double_var(&d, a, NULL); /* First, we perform all the additions in an isomorphic curve obtained by multiplying * all `z` coordinates by 1/`d.z`. In these coordinates `d` is affine so we can use * `secp256k1_gej_add_ge_var` to perform the additions. For each addition, we store * the resulting y-coordinate and the z-ratio, since we only have enough memory to * store two field elements. These are sufficient to efficiently undo the isomorphism * and recompute all the `x`s. */ d_ge.x = d.x; d_ge.y = d.y; d_ge.infinity = 0; secp256k1_ge_set_gej_zinv(&p_ge, a, &d.z); pj.x = p_ge.x; pj.y = p_ge.y; pj.z = a->z; pj.infinity = 0; for (i = 0; i < (n - 1); i++) { secp256k1_fe_normalize_var(&pj.y); secp256k1_fe_to_storage(&pre[i].y, &pj.y); secp256k1_gej_add_ge_var(&pj, &pj, &d_ge, &zr); secp256k1_fe_normalize_var(&zr); secp256k1_fe_to_storage(&pre[i].x, &zr); } /* Invert d.z in the same batch, preserving pj.z so we can extract 1/d.z */ secp256k1_fe_mul(&zi, &pj.z, &d.z); secp256k1_fe_inv_var(&zi, &zi); /* Directly set `pre[n - 1]` to `pj`, saving the inverted z-coordinate so * that we can combine it with the saved z-ratios to compute the other zs * without any more inversions. */ secp256k1_ge_set_gej_zinv(&p_ge, &pj, &zi); secp256k1_ge_to_storage(&pre[n - 1], &p_ge); /* Compute the actual x-coordinate of D, which will be needed below. */ secp256k1_fe_mul(&d.z, &zi, &pj.z); /* d.z = 1/d.z */ secp256k1_fe_sqr(&dx_over_dz_squared, &d.z); secp256k1_fe_mul(&dx_over_dz_squared, &dx_over_dz_squared, &d.x); /* Going into the second loop, we have set `pre[n-1]` to its final affine * form, but still need to set `pre[i]` for `i` in 0 through `n-2`. We * have `zi = (p.z * d.z)^-1`, where * * `p.z` is the z-coordinate of the point on the isomorphic curve * which was ultimately assigned to `pre[n-1]`. * `d.z` is the multiplier that must be applied to all z-coordinates * to move from our isomorphic curve back to secp256k1; so the * product `p.z * d.z` is the z-coordinate of the secp256k1 * point assigned to `pre[n-1]`. * * All subsequent inverse-z-coordinates can be obtained by multiplying this * factor by successive z-ratios, which is much more efficient than directly * computing each one. * * Importantly, these inverse-zs will be coordinates of points on secp256k1, * while our other stored values come from computations on the isomorphic * curve. So in the below loop, we will take care not to actually use `zi` * or any derived values until we're back on secp256k1. */ i = n - 1; while (i > 0) { secp256k1_fe zi2, zi3; const secp256k1_fe *rzr; i--; secp256k1_ge_from_storage(&p_ge, &pre[i]); /* For each remaining point, we extract the z-ratio from the stored * x-coordinate, compute its z^-1 from that, and compute the full * point from that. */ rzr = &p_ge.x; secp256k1_fe_mul(&zi, &zi, rzr); secp256k1_fe_sqr(&zi2, &zi); secp256k1_fe_mul(&zi3, &zi2, &zi); /* To compute the actual x-coordinate, we use the stored z ratio and * y-coordinate, which we obtained from `secp256k1_gej_add_ge_var` * in the loop above, as well as the inverse of the square of its * z-coordinate. We store the latter in the `zi2` variable, which is * computed iteratively starting from the overall Z inverse then * multiplying by each z-ratio in turn. * * Denoting the z-ratio as `rzr`, we observe that it is equal to `h` * from the inside of the above `gej_add_ge_var` call. This satisfies * * rzr = d_x * z^2 - x * d_z^2 * * where (`d_x`, `d_z`) are Jacobian coordinates of `D` and `(x, z)` * are Jacobian coordinates of our desired point -- except both are on * the isomorphic curve that we were using when we called `gej_add_ge_var`. * To get back to secp256k1, we must multiply both `z`s by `d_z`, or * equivalently divide both `x`s by `d_z^2`. Our equation then becomes * * rzr = d_x * z^2 / d_z^2 - x * * (The left-hand-side, being a ratio of z-coordinates, is unaffected * by the isomorphism.) * * Rearranging to solve for `x`, we have * * x = d_x * z^2 / d_z^2 - rzr * * But what we actually want is the affine coordinate `X = x/z^2`, * which will satisfy * * X = d_x / d_z^2 - rzr / z^2 * = dx_over_dz_squared - rzr * zi2 */ secp256k1_fe_mul(&p_ge.x, rzr, &zi2); secp256k1_fe_negate(&p_ge.x, &p_ge.x, 1); secp256k1_fe_add(&p_ge.x, &dx_over_dz_squared); /* y is stored_y/z^3, as we expect */ secp256k1_fe_mul(&p_ge.y, &p_ge.y, &zi3); /* Store */ secp256k1_ge_to_storage(&pre[i], &p_ge); } } /** 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 { \ *(r) = (pre)[(-(n)-1)/2]; \ secp256k1_fe_negate(&((r)->y), &((r)->y), 1); \ } \ } 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_fe_negate(&((r)->y), &((r)->y), 1); \ } \ } while(0) static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE = ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)) + ROUND_TO_ALIGN(sizeof((*((secp256k1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)) ; static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { ctx->pre_g = NULL; ctx->pre_g_128 = NULL; } static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, void **prealloc) { secp256k1_gej gj; void* const base = *prealloc; size_t const prealloc_size = SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE; if (ctx->pre_g != NULL) { return; } /* get the generator */ secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); { size_t size = sizeof((*ctx->pre_g)[0]) * ((size_t)ECMULT_TABLE_SIZE(WINDOW_G)); /* check for overflow */ VERIFY_CHECK(size / sizeof((*ctx->pre_g)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G))); ctx->pre_g = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size); } /* precompute the tables with odd multiples */ secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj); { secp256k1_gej g_128j; int i; size_t size = sizeof((*ctx->pre_g_128)[0]) * ((size_t) ECMULT_TABLE_SIZE(WINDOW_G)); /* check for overflow */ VERIFY_CHECK(size / sizeof((*ctx->pre_g_128)[0]) == ((size_t)ECMULT_TABLE_SIZE(WINDOW_G))); ctx->pre_g_128 = (secp256k1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size); /* 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); } } static void secp256k1_ecmult_context_finalize_memcpy(secp256k1_ecmult_context *dst, const secp256k1_ecmult_context *src) { if (src->pre_g != NULL) { /* We cast to void* first to suppress a -Wcast-align warning. */ dst->pre_g = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src)); } if (src->pre_g_128 != NULL) { dst->pre_g_128 = (secp256k1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src)); } } 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) { 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; 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])); s = *a; 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; } struct secp256k1_strauss_point_state { secp256k1_scalar na_1, na_lam; int wnaf_na_1[129]; int wnaf_na_lam[129]; int bits_na_1; int bits_na_lam; size_t input_pos; }; struct secp256k1_strauss_state { secp256k1_gej* prej; secp256k1_fe* zr; secp256k1_ge* pre_a; secp256k1_ge* pre_a_lam; 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, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { secp256k1_ge tmpa; secp256k1_fe Z; /* 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; int i; int bits = 0; size_t np; size_t 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; /* 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, 129, &state->ps[no].na_1, WINDOW_A); state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 129, &state->ps[no].na_lam, WINDOW_A); VERIFY_CHECK(state->ps[no].bits_na_1 <= 129); VERIFY_CHECK(state->ps[no].bits_na_lam <= 129); 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; } ++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. */ 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); } for (np = 0; np < no; ++np) { for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { secp256k1_ge_mul_lambda(&state->pre_a_lam[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i]); } } if (ng) { /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ 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; } } secp256k1_gej_set_infinity(r); for (i = bits - 1; i >= 0; i--) { int n; secp256k1_gej_double_var(r, r, 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); } } 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]; secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; struct secp256k1_strauss_state state; state.prej = prej; state.zr = zr; state.pre_a = pre_a; state.pre_a_lam = pre_a_lam; 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) { 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); return n_points*point_size; } static int secp256k1_ecmult_strauss_batch(const secp256k1_callback* error_callback, 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; const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch); secp256k1_gej_set_infinity(r); if (inp_g_sc == NULL && n_points == 0) { return 1; } points = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_gej)); scalars = (secp256k1_scalar*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(secp256k1_scalar)); state.prej = (secp256k1_gej*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_gej)); state.zr = (secp256k1_fe*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_fe)); state.pre_a = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge)); state.pre_a_lam = (secp256k1_ge*)secp256k1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(secp256k1_ge)); state.ps = (struct secp256k1_strauss_point_state*)secp256k1_scratch_alloc(error_callback, scratch, n_points * sizeof(struct secp256k1_strauss_point_state)); if (points == NULL || scalars == NULL || state.prej == NULL || state.zr == NULL || state.pre_a == NULL || state.pre_a_lam == NULL || state.ps == NULL) { secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } for (i = 0; i < n_points; i++) { secp256k1_ge point; if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) { secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } secp256k1_gej_set_ge(&points[i], &point); } secp256k1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc); secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 1; } /* Wrapper for secp256k1_ecmult_multi_func interface */ static int secp256k1_ecmult_strauss_batch_single(const secp256k1_callback* error_callback, 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(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0); } static size_t secp256k1_strauss_max_points(const secp256k1_callback* error_callback, secp256k1_scratch *scratch) { return secp256k1_scratch_max_allocation(error_callback, scratch, STRAUSS_SCRATCH_OBJECTS) / secp256k1_strauss_scratch_size(1); } /** Convert a number to WNAF notation. * The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val. * It has the following guarantees: * - each wnaf[i] is either 0 or an odd integer between -(1 << w) and (1 << w) * - the number of words set is always WNAF_SIZE(w) * - the returned skew is 0 or 1 */ static int secp256k1_wnaf_fixed(int *wnaf, const secp256k1_scalar *s, int w) { int skew = 0; int pos; int max_pos; int last_w; const secp256k1_scalar *work = s; if (secp256k1_scalar_is_zero(s)) { for (pos = 0; pos < WNAF_SIZE(w); pos++) { wnaf[pos] = 0; } return 0; } if (secp256k1_scalar_is_even(s)) { skew = 1; } wnaf[0] = secp256k1_scalar_get_bits_var(work, 0, w) + skew; /* Compute last window size. Relevant when window size doesn't divide the * number of bits in the scalar */ last_w = WNAF_BITS - (WNAF_SIZE(w) - 1) * w; /* Store the position of the first nonzero word in max_pos to allow * skipping leading zeros when calculating the wnaf. */ for (pos = WNAF_SIZE(w) - 1; pos > 0; pos--) { int val = secp256k1_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w); if(val != 0) { break; } wnaf[pos] = 0; } max_pos = pos; pos = 1; while (pos <= max_pos) { int val = secp256k1_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w); if ((val & 1) == 0) { wnaf[pos - 1] -= (1 << w); wnaf[pos] = (val + 1); } else { wnaf[pos] = val; } /* Set a coefficient to zero if it is 1 or -1 and the proceeding digit * is strictly negative or strictly positive respectively. Only change * coefficients at previous positions because above code assumes that * wnaf[pos - 1] is odd. */ if (pos >= 2 && ((wnaf[pos - 1] == 1 && wnaf[pos - 2] < 0) || (wnaf[pos - 1] == -1 && wnaf[pos - 2] > 0))) { if (wnaf[pos - 1] == 1) { wnaf[pos - 2] += 1 << w; } else { wnaf[pos - 2] -= 1 << w; } wnaf[pos - 1] = 0; } ++pos; } return skew; } struct secp256k1_pippenger_point_state { int skew_na; size_t input_pos; }; struct secp256k1_pippenger_state { int *wnaf_na; struct secp256k1_pippenger_point_state* ps; }; /* * pippenger_wnaf computes the result of a multi-point multiplication as * follows: The scalars are brought into wnaf with n_wnaf elements each. Then * for every i < n_wnaf, first each point is added to a "bucket" corresponding * to the point's wnaf[i]. Second, the buckets are added together such that * r += 1*bucket[0] + 3*bucket[1] + 5*bucket[2] + ... */ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *r, const secp256k1_scalar *sc, const secp256k1_ge *pt, size_t num) { size_t n_wnaf = WNAF_SIZE(bucket_window+1); size_t np; size_t no = 0; int i; int j; for (np = 0; np < num; ++np) { if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) { continue; } state->ps[no].input_pos = np; state->ps[no].skew_na = secp256k1_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1); no++; } secp256k1_gej_set_infinity(r); if (no == 0) { return 1; } for (i = n_wnaf - 1; i >= 0; i--) { secp256k1_gej running_sum; for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) { secp256k1_gej_set_infinity(&buckets[j]); } for (np = 0; np < no; ++np) { int n = state->wnaf_na[np*n_wnaf + i]; struct secp256k1_pippenger_point_state point_state = state->ps[np]; secp256k1_ge tmp; int idx; if (i == 0) { /* correct for wnaf skew */ int skew = point_state.skew_na; if (skew) { secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); secp256k1_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL); } } if (n > 0) { idx = (n - 1)/2; secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); } else if (n < 0) { idx = -(n + 1)/2; secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); } } for(j = 0; j < bucket_window; j++) { secp256k1_gej_double_var(r, r, NULL); } secp256k1_gej_set_infinity(&running_sum); /* Accumulate the sum: bucket[0] + 3*bucket[1] + 5*bucket[2] + 7*bucket[3] + ... * = bucket[0] + bucket[1] + bucket[2] + bucket[3] + ... * + 2 * (bucket[1] + 2*bucket[2] + 3*bucket[3] + ...) * using an intermediate running sum: * running_sum = bucket[0] + bucket[1] + bucket[2] + ... * * The doubling is done implicitly by deferring the final window doubling (of 'r'). */ for(j = ECMULT_TABLE_SIZE(bucket_window+2) - 1; j > 0; j--) { secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); secp256k1_gej_add_var(r, r, &running_sum, NULL); } secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL); secp256k1_gej_double_var(r, r, NULL); secp256k1_gej_add_var(r, r, &running_sum, NULL); } return 1; } /** * Returns optimal bucket_window (number of bits of a scalar represented by a * set of buckets) for a given number of points. */ static int secp256k1_pippenger_bucket_window(size_t n) { 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; } } /** * 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) { 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; } return 0; } 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); } } /** * 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) { size_t entries = 2*n_points + 2; 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 (sizeof(secp256k1_gej) << bucket_window) + sizeof(struct secp256k1_pippenger_state) + entries * entry_size; } static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_callback, 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) { const size_t scratch_checkpoint = secp256k1_scratch_checkpoint(error_callback, scratch); /* Use 2(n+1) with the endomorphism, when calculating batch * sizes. The reason for +1 is that we add the G scalar to the list of * other scalars. */ size_t entries = 2*n_points + 2; secp256k1_ge *points; secp256k1_scalar *scalars; secp256k1_gej *buckets; struct secp256k1_pippenger_state *state_space; size_t idx = 0; size_t point_idx = 0; int i, j; int bucket_window; (void)ctx; secp256k1_gej_set_infinity(r); if (inp_g_sc == NULL && n_points == 0) { return 1; } bucket_window = secp256k1_pippenger_bucket_window(n_points); points = (secp256k1_ge *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*points)); scalars = (secp256k1_scalar *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*scalars)); state_space = (struct secp256k1_pippenger_state *) secp256k1_scratch_alloc(error_callback, scratch, sizeof(*state_space)); if (points == NULL || scalars == NULL || state_space == NULL) { secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } state_space->ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps)); state_space->wnaf_na = (int *) secp256k1_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int)); buckets = (secp256k1_gej *) secp256k1_scratch_alloc(error_callback, scratch, (1<ps == NULL || state_space->wnaf_na == NULL || buckets == NULL) { secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } if (inp_g_sc != NULL) { scalars[0] = *inp_g_sc; points[0] = secp256k1_ge_const_g; idx++; secp256k1_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]); idx++; } while (point_idx < n_points) { if (!cb(&scalars[idx], &points[idx], point_idx + cb_offset, cbdata)) { secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } idx++; secp256k1_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]); idx++; point_idx++; } secp256k1_ecmult_pippenger_wnaf(buckets, bucket_window, state_space, r, scalars, points, idx); /* Clear data */ for(i = 0; (size_t)i < idx; i++) { secp256k1_scalar_clear(&scalars[i]); state_space->ps[i].skew_na = 0; for(j = 0; j < WNAF_SIZE(bucket_window+1); j++) { state_space->wnaf_na[i * WNAF_SIZE(bucket_window+1) + j] = 0; } } for(i = 0; i < 1< 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; } /* Computes ecmult_multi by simply multiplying and adding each point. Does not * require a scratch space */ static int secp256k1_ecmult_multi_simple_var(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_scalar *inp_g_sc, secp256k1_ecmult_multi_callback cb, void *cbdata, size_t n_points) { size_t point_idx; secp256k1_scalar szero; secp256k1_gej tmpj; secp256k1_scalar_set_int(&szero, 0); secp256k1_gej_set_infinity(r); secp256k1_gej_set_infinity(&tmpj); /* r = inp_g_sc*G */ secp256k1_ecmult(ctx, r, &tmpj, &szero, inp_g_sc); for (point_idx = 0; point_idx < n_points; point_idx++) { secp256k1_ge point; secp256k1_gej pointj; secp256k1_scalar scalar; if (!cb(&scalar, &point, point_idx, cbdata)) { return 0; } /* r += scalar*point */ secp256k1_gej_set_ge(&pointj, &point); secp256k1_ecmult(ctx, &tmpj, &pointj, &scalar, NULL); secp256k1_gej_add_var(r, r, &tmpj, NULL); } return 1; } /* Compute the number of batches and the batch size given the maximum batch size and the * total number of points */ static int secp256k1_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n_batch_points, size_t max_n_batch_points, size_t n) { if (max_n_batch_points == 0) { return 0; } if (max_n_batch_points > ECMULT_MAX_POINTS_PER_BATCH) { max_n_batch_points = ECMULT_MAX_POINTS_PER_BATCH; } if (n == 0) { *n_batches = 0; *n_batch_points = 0; return 1; } /* Compute ceil(n/max_n_batch_points) and ceil(n/n_batches) */ *n_batches = 1 + (n - 1) / max_n_batch_points; *n_batch_points = 1 + (n - 1) / *n_batches; return 1; } typedef int (*secp256k1_ecmult_multi_func)(const secp256k1_callback* error_callback, 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_callback* error_callback, 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_callback* error_callback, const secp256k1_ecmult_context*, secp256k1_scratch*, secp256k1_gej*, const secp256k1_scalar*, secp256k1_ecmult_multi_callback cb, void*, size_t, size_t); 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; } if (scratch == NULL) { return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n); } /* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than * a threshold use Pippenger's algorithm. Otherwise use Strauss' algorithm. * As a first step check if there's enough space for Pippenger's algo (which requires less space * than Strauss' algo) and if not, use the simple algorithm. */ if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_pippenger_max_points(error_callback, scratch), n)) { return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n); } if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) { f = secp256k1_ecmult_pippenger_batch; } else { if (!secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, secp256k1_strauss_max_points(error_callback, scratch), n)) { return secp256k1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n); } 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(error_callback, 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/field.h b/src/secp256k1/src/field.h index aca1fb72c..0e5c385c8 100644 --- a/src/secp256k1/src/field.h +++ b/src/secp256k1/src/field.h @@ -1,134 +1,134 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_FIELD_H #define SECP256K1_FIELD_H /** Field element module. * * Field elements can be represented in several ways, but code accessing * it (and implementations) need to take certain properties into account: * - Each field element can be normalized or not. * - Each field element has a magnitude, which represents how far away * its representation is away from normalization. Normalized elements * always have a magnitude of 1, but a magnitude of 1 doesn't imply * normality. */ #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #include "util.h" #if defined(SECP256K1_WIDEMUL_INT128) #include "field_5x52.h" #elif defined(SECP256K1_WIDEMUL_INT64) #include "field_10x26.h" #else #error "Please select wide multiplication implementation" #endif /** Normalize a field element. This brings the field element to a canonical representation, reduces * its magnitude to 1, and reduces it modulo field size `p`. */ static void secp256k1_fe_normalize(secp256k1_fe *r); /** Weakly normalize a field element: reduce its magnitude to 1, but don't fully normalize. */ static void secp256k1_fe_normalize_weak(secp256k1_fe *r); /** Normalize a field element, without constant-time guarantee. */ static void secp256k1_fe_normalize_var(secp256k1_fe *r); /** Verify whether a field element represents zero i.e. would normalize to a zero value. The field * implementation may optionally normalize the input, but this should not be relied upon. */ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r); /** Verify whether a field element represents zero i.e. would normalize to a zero value. The field * implementation may optionally normalize the input, but this should not be relied upon. */ static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r); /** Set a field element equal to a small integer. Resulting field element is normalized. */ static void secp256k1_fe_set_int(secp256k1_fe *r, int a); /** Sets a field element equal to zero, initializing all fields. */ static void secp256k1_fe_clear(secp256k1_fe *a); /** Verify whether a field element is zero. Requires the input to be normalized. */ static int secp256k1_fe_is_zero(const secp256k1_fe *a); /** Check the "oddness" of a field element. Requires the input to be normalized. */ static int secp256k1_fe_is_odd(const secp256k1_fe *a); /** Compare two field elements. Requires magnitude-1 inputs. */ static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b); /** Same as secp256k1_fe_equal, but may be variable time. */ static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b); /** Compare two field elements. Requires both inputs to be normalized */ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); /** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a); /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a); /** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input * as an argument. The magnitude of the output is one higher. */ static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m); /** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that * small integer. */ static void secp256k1_fe_mul_int(secp256k1_fe *r, int a); /** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */ static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a); /** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8. * The output magnitude is 1 (but not guaranteed to be normalized). */ static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); /** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8. * The output magnitude is 1 (but not guaranteed to be normalized). */ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a); /** If a has a square root, it is computed in r and 1 is returned. If a does not * have a square root, the root of its negation is computed and 0 is returned. * The input's magnitude can be at most 8. The output magnitude is 1 (but not * guaranteed to be normalized). The result in r will always be a square * itself. */ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a); /** Checks whether a field element is a quadratic residue. */ static int secp256k1_fe_is_quad_var(const secp256k1_fe *a); /** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be * at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a); /** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */ static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a); /** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be * at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and * outputs must not overlap in memory. */ static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len); /** Convert a field element to the storage type. */ static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a); /** Convert a field element back from the storage type. */ static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); #endif /* SECP256K1_FIELD_H */ diff --git a/src/secp256k1/src/field_10x26.h b/src/secp256k1/src/field_10x26.h index 5ff03c8ab..9eb65607f 100644 --- a/src/secp256k1/src/field_10x26.h +++ b/src/secp256k1/src/field_10x26.h @@ -1,50 +1,50 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_FIELD_REPR_H #define SECP256K1_FIELD_REPR_H #include typedef struct { /* X = sum(i=0..9, n[i]*2^(i*26)) mod p * where p = 2^256 - 0x1000003D1 */ uint32_t n[10]; #ifdef VERIFY int magnitude; int normalized; #endif } secp256k1_fe; /* Unpacks a constant into a overlapping multi-limbed FE element. */ #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ (d0) & 0x3FFFFFFUL, \ (((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \ (((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \ (((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \ (((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \ (((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \ (((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \ (((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \ (((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \ (((uint32_t)d7) >> 10) \ } #ifdef VERIFY #define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} #else #define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} #endif typedef struct { uint32_t n[8]; } secp256k1_fe_storage; #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} #define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] #endif /* SECP256K1_FIELD_REPR_H */ diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h index 651500ee8..62bffdc21 100644 --- a/src/secp256k1/src/field_10x26_impl.h +++ b/src/secp256k1/src/field_10x26_impl.h @@ -1,1167 +1,1167 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_FIELD_REPR_IMPL_H #define SECP256K1_FIELD_REPR_IMPL_H #include "util.h" #include "field.h" #ifdef VERIFY static void secp256k1_fe_verify(const secp256k1_fe *a) { const uint32_t *d = a->n; int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; r &= (d[0] <= 0x3FFFFFFUL * m); r &= (d[1] <= 0x3FFFFFFUL * m); r &= (d[2] <= 0x3FFFFFFUL * m); r &= (d[3] <= 0x3FFFFFFUL * m); r &= (d[4] <= 0x3FFFFFFUL * m); r &= (d[5] <= 0x3FFFFFFUL * m); r &= (d[6] <= 0x3FFFFFFUL * m); r &= (d[7] <= 0x3FFFFFFUL * m); r &= (d[8] <= 0x3FFFFFFUL * m); r &= (d[9] <= 0x03FFFFFUL * m); r &= (a->magnitude >= 0); r &= (a->magnitude <= 32); if (a->normalized) { r &= (a->magnitude <= 1); if (r && (d[9] == 0x03FFFFFUL)) { uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2]; if (mid == 0x3FFFFFFUL) { r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL); } } } VERIFY_CHECK(r == 1); } #endif static void secp256k1_fe_normalize(secp256k1_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; /* Reduce t9 at the start so there will be at most a single carry from the first pass */ uint32_t m; uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x3D1UL; t1 += (x << 6); t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t9 >> 23 == 0); /* At most a single final reduction is needed; check if the value is >= the field characteristic */ x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); /* Apply the final reduction (for constant-time behaviour, we do it always) */ t0 += x * 0x3D1UL; t1 += (x << 6); t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ VERIFY_CHECK(t9 >> 22 == x); /* Mask off the possible multiple of 2^256 from the final reduction */ t9 &= 0x03FFFFFUL; r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; #ifdef VERIFY r->magnitude = 1; r->normalized = 1; secp256k1_fe_verify(r); #endif } static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; /* Reduce t9 at the start so there will be at most a single carry from the first pass */ uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x3D1UL; t1 += (x << 6); t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t9 >> 23 == 0); r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; #ifdef VERIFY r->magnitude = 1; secp256k1_fe_verify(r); #endif } static void secp256k1_fe_normalize_var(secp256k1_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; /* Reduce t9 at the start so there will be at most a single carry from the first pass */ uint32_t m; uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x3D1UL; t1 += (x << 6); t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t9 >> 23 == 0); /* At most a single final reduction is needed; check if the value is >= the field characteristic */ x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); if (x) { t0 += 0x3D1UL; t1 += (x << 6); t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ VERIFY_CHECK(t9 >> 22 == x); /* Mask off the possible multiple of 2^256 from the final reduction */ t9 &= 0x03FFFFFUL; } r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; #ifdef VERIFY r->magnitude = 1; r->normalized = 1; secp256k1_fe_verify(r); #endif } static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ uint32_t z0, z1; /* Reduce t9 at the start so there will be at most a single carry from the first pass */ uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x3D1UL; t1 += (x << 6); t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL; t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; z0 |= t9; z1 &= t9 ^ 0x3C00000UL; /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t9 >> 23 == 0); return (z0 == 0) | (z1 == 0x3FFFFFFUL); } static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; uint32_t z0, z1; uint32_t x; t0 = r->n[0]; t9 = r->n[9]; /* Reduce t9 at the start so there will be at most a single carry from the first pass */ x = t9 >> 22; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x3D1UL; /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ z0 = t0 & 0x3FFFFFFUL; z1 = z0 ^ 0x3D0UL; /* Fast return path should catch the majority of cases */ if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL)) { return 0; } t1 = r->n[1]; t2 = r->n[2]; t3 = r->n[3]; t4 = r->n[4]; t5 = r->n[5]; t6 = r->n[6]; t7 = r->n[7]; t8 = r->n[8]; t9 &= 0x03FFFFFUL; t1 += (x << 6); t1 += (t0 >> 26); t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; z0 |= t9; z1 &= t9 ^ 0x3C00000UL; /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t9 >> 23 == 0); return (z0 == 0) | (z1 == 0x3FFFFFFUL); } SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { r->n[0] = a; r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; #ifdef VERIFY r->magnitude = 1; r->normalized = 1; secp256k1_fe_verify(r); #endif } SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { const uint32_t *t = a->n; #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0; } SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif return a->n[0] & 1; } SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { int i; #ifdef VERIFY a->magnitude = 0; a->normalized = 1; #endif for (i=0; i<10; i++) { a->n[i] = 0; } } static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); VERIFY_CHECK(b->normalized); secp256k1_fe_verify(a); secp256k1_fe_verify(b); #endif for (i = 9; i >= 0; i--) { if (a->n[i] > b->n[i]) { return 1; } if (a->n[i] < b->n[i]) { return -1; } } return 0; } static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { int ret; r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24); r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22); r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20); r->n[3] = (uint32_t)((a[22] >> 6) & 0x3) | ((uint32_t)a[21] << 2) | ((uint32_t)a[20] << 10) | ((uint32_t)a[19] << 18); r->n[4] = (uint32_t)a[18] | ((uint32_t)a[17] << 8) | ((uint32_t)a[16] << 16) | ((uint32_t)(a[15] & 0x3) << 24); r->n[5] = (uint32_t)((a[15] >> 2) & 0x3f) | ((uint32_t)a[14] << 6) | ((uint32_t)a[13] << 14) | ((uint32_t)(a[12] & 0xf) << 22); r->n[6] = (uint32_t)((a[12] >> 4) & 0xf) | ((uint32_t)a[11] << 4) | ((uint32_t)a[10] << 12) | ((uint32_t)(a[9] & 0x3f) << 20); r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18); r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24); r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14); ret = !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); #ifdef VERIFY r->magnitude = 1; if (ret) { r->normalized = 1; secp256k1_fe_verify(r); } else { r->normalized = 0; } #endif return ret; } /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif r[0] = (a->n[9] >> 14) & 0xff; r[1] = (a->n[9] >> 6) & 0xff; r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3); r[3] = (a->n[8] >> 16) & 0xff; r[4] = (a->n[8] >> 8) & 0xff; r[5] = a->n[8] & 0xff; r[6] = (a->n[7] >> 18) & 0xff; r[7] = (a->n[7] >> 10) & 0xff; r[8] = (a->n[7] >> 2) & 0xff; r[9] = ((a->n[7] & 0x3) << 6) | ((a->n[6] >> 20) & 0x3f); r[10] = (a->n[6] >> 12) & 0xff; r[11] = (a->n[6] >> 4) & 0xff; r[12] = ((a->n[6] & 0xf) << 4) | ((a->n[5] >> 22) & 0xf); r[13] = (a->n[5] >> 14) & 0xff; r[14] = (a->n[5] >> 6) & 0xff; r[15] = ((a->n[5] & 0x3f) << 2) | ((a->n[4] >> 24) & 0x3); r[16] = (a->n[4] >> 16) & 0xff; r[17] = (a->n[4] >> 8) & 0xff; r[18] = a->n[4] & 0xff; r[19] = (a->n[3] >> 18) & 0xff; r[20] = (a->n[3] >> 10) & 0xff; r[21] = (a->n[3] >> 2) & 0xff; r[22] = ((a->n[3] & 0x3) << 6) | ((a->n[2] >> 20) & 0x3f); r[23] = (a->n[2] >> 12) & 0xff; r[24] = (a->n[2] >> 4) & 0xff; r[25] = ((a->n[2] & 0xf) << 4) | ((a->n[1] >> 22) & 0xf); r[26] = (a->n[1] >> 14) & 0xff; r[27] = (a->n[1] >> 6) & 0xff; r[28] = ((a->n[1] & 0x3f) << 2) | ((a->n[0] >> 24) & 0x3); r[29] = (a->n[0] >> 16) & 0xff; r[30] = (a->n[0] >> 8) & 0xff; r[31] = a->n[0] & 0xff; } SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= m); secp256k1_fe_verify(a); #endif r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0]; r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1]; r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2]; r->n[3] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[3]; r->n[4] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[4]; r->n[5] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[5]; r->n[6] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[6]; r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7]; r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8]; r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; #ifdef VERIFY r->magnitude = m + 1; r->normalized = 0; secp256k1_fe_verify(r); #endif } SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { r->n[0] *= a; r->n[1] *= a; r->n[2] *= a; r->n[3] *= a; r->n[4] *= a; r->n[5] *= a; r->n[6] *= a; r->n[7] *= a; r->n[8] *= a; r->n[9] *= a; #ifdef VERIFY r->magnitude *= a; r->normalized = 0; secp256k1_fe_verify(r); #endif } SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { #ifdef VERIFY secp256k1_fe_verify(a); #endif r->n[0] += a->n[0]; r->n[1] += a->n[1]; r->n[2] += a->n[2]; r->n[3] += a->n[3]; r->n[4] += a->n[4]; r->n[5] += a->n[5]; r->n[6] += a->n[6]; r->n[7] += a->n[7]; r->n[8] += a->n[8]; r->n[9] += a->n[9]; #ifdef VERIFY r->magnitude += a->magnitude; r->normalized = 0; secp256k1_fe_verify(r); #endif } #if defined(USE_EXTERNAL_ASM) /* External assembler implementation */ void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a); #else #ifdef VERIFY #define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) #else #define VERIFY_BITS(x, n) do { } while(0) #endif SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) { uint64_t c, d; uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; uint32_t t9, t1, t0, t2, t3, t4, t5, t6, t7; const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; VERIFY_BITS(a[0], 30); VERIFY_BITS(a[1], 30); VERIFY_BITS(a[2], 30); VERIFY_BITS(a[3], 30); VERIFY_BITS(a[4], 30); VERIFY_BITS(a[5], 30); VERIFY_BITS(a[6], 30); VERIFY_BITS(a[7], 30); VERIFY_BITS(a[8], 30); VERIFY_BITS(a[9], 26); VERIFY_BITS(b[0], 30); VERIFY_BITS(b[1], 30); VERIFY_BITS(b[2], 30); VERIFY_BITS(b[3], 30); VERIFY_BITS(b[4], 30); VERIFY_BITS(b[5], 30); VERIFY_BITS(b[6], 30); VERIFY_BITS(b[7], 30); VERIFY_BITS(b[8], 30); VERIFY_BITS(b[9], 26); /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. * for 0 <= x <= 9, px is a shorthand for sum(a[i]*b[x-i], i=0..x). * for 9 <= x <= 18, px is a shorthand for sum(a[i]*b[x-i], i=(x-9)..9) * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. */ d = (uint64_t)a[0] * b[9] + (uint64_t)a[1] * b[8] + (uint64_t)a[2] * b[7] + (uint64_t)a[3] * b[6] + (uint64_t)a[4] * b[5] + (uint64_t)a[5] * b[4] + (uint64_t)a[6] * b[3] + (uint64_t)a[7] * b[2] + (uint64_t)a[8] * b[1] + (uint64_t)a[9] * b[0]; /* VERIFY_BITS(d, 64); */ /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ t9 = d & M; d >>= 26; VERIFY_BITS(t9, 26); VERIFY_BITS(d, 38); /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ c = (uint64_t)a[0] * b[0]; VERIFY_BITS(c, 60); /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ d += (uint64_t)a[1] * b[9] + (uint64_t)a[2] * b[8] + (uint64_t)a[3] * b[7] + (uint64_t)a[4] * b[6] + (uint64_t)a[5] * b[5] + (uint64_t)a[6] * b[4] + (uint64_t)a[7] * b[3] + (uint64_t)a[8] * b[2] + (uint64_t)a[9] * b[1]; VERIFY_BITS(d, 63); /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ u0 = d & M; d >>= 26; c += u0 * R0; VERIFY_BITS(u0, 26); VERIFY_BITS(d, 37); VERIFY_BITS(c, 61); /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ t0 = c & M; c >>= 26; c += u0 * R1; VERIFY_BITS(t0, 26); VERIFY_BITS(c, 37); /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ c += (uint64_t)a[0] * b[1] + (uint64_t)a[1] * b[0]; VERIFY_BITS(c, 62); /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ d += (uint64_t)a[2] * b[9] + (uint64_t)a[3] * b[8] + (uint64_t)a[4] * b[7] + (uint64_t)a[5] * b[6] + (uint64_t)a[6] * b[5] + (uint64_t)a[7] * b[4] + (uint64_t)a[8] * b[3] + (uint64_t)a[9] * b[2]; VERIFY_BITS(d, 63); /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ u1 = d & M; d >>= 26; c += u1 * R0; VERIFY_BITS(u1, 26); VERIFY_BITS(d, 37); VERIFY_BITS(c, 63); /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ t1 = c & M; c >>= 26; c += u1 * R1; VERIFY_BITS(t1, 26); VERIFY_BITS(c, 38); /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ c += (uint64_t)a[0] * b[2] + (uint64_t)a[1] * b[1] + (uint64_t)a[2] * b[0]; VERIFY_BITS(c, 62); /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ d += (uint64_t)a[3] * b[9] + (uint64_t)a[4] * b[8] + (uint64_t)a[5] * b[7] + (uint64_t)a[6] * b[6] + (uint64_t)a[7] * b[5] + (uint64_t)a[8] * b[4] + (uint64_t)a[9] * b[3]; VERIFY_BITS(d, 63); /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ u2 = d & M; d >>= 26; c += u2 * R0; VERIFY_BITS(u2, 26); VERIFY_BITS(d, 37); VERIFY_BITS(c, 63); /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ t2 = c & M; c >>= 26; c += u2 * R1; VERIFY_BITS(t2, 26); VERIFY_BITS(c, 38); /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ c += (uint64_t)a[0] * b[3] + (uint64_t)a[1] * b[2] + (uint64_t)a[2] * b[1] + (uint64_t)a[3] * b[0]; VERIFY_BITS(c, 63); /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ d += (uint64_t)a[4] * b[9] + (uint64_t)a[5] * b[8] + (uint64_t)a[6] * b[7] + (uint64_t)a[7] * b[6] + (uint64_t)a[8] * b[5] + (uint64_t)a[9] * b[4]; VERIFY_BITS(d, 63); /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ u3 = d & M; d >>= 26; c += u3 * R0; VERIFY_BITS(u3, 26); VERIFY_BITS(d, 37); /* VERIFY_BITS(c, 64); */ /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ t3 = c & M; c >>= 26; c += u3 * R1; VERIFY_BITS(t3, 26); VERIFY_BITS(c, 39); /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ c += (uint64_t)a[0] * b[4] + (uint64_t)a[1] * b[3] + (uint64_t)a[2] * b[2] + (uint64_t)a[3] * b[1] + (uint64_t)a[4] * b[0]; VERIFY_BITS(c, 63); /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ d += (uint64_t)a[5] * b[9] + (uint64_t)a[6] * b[8] + (uint64_t)a[7] * b[7] + (uint64_t)a[8] * b[6] + (uint64_t)a[9] * b[5]; VERIFY_BITS(d, 62); /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ u4 = d & M; d >>= 26; c += u4 * R0; VERIFY_BITS(u4, 26); VERIFY_BITS(d, 36); /* VERIFY_BITS(c, 64); */ /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ t4 = c & M; c >>= 26; c += u4 * R1; VERIFY_BITS(t4, 26); VERIFY_BITS(c, 39); /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ c += (uint64_t)a[0] * b[5] + (uint64_t)a[1] * b[4] + (uint64_t)a[2] * b[3] + (uint64_t)a[3] * b[2] + (uint64_t)a[4] * b[1] + (uint64_t)a[5] * b[0]; VERIFY_BITS(c, 63); /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ d += (uint64_t)a[6] * b[9] + (uint64_t)a[7] * b[8] + (uint64_t)a[8] * b[7] + (uint64_t)a[9] * b[6]; VERIFY_BITS(d, 62); /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ u5 = d & M; d >>= 26; c += u5 * R0; VERIFY_BITS(u5, 26); VERIFY_BITS(d, 36); /* VERIFY_BITS(c, 64); */ /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ t5 = c & M; c >>= 26; c += u5 * R1; VERIFY_BITS(t5, 26); VERIFY_BITS(c, 39); /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ c += (uint64_t)a[0] * b[6] + (uint64_t)a[1] * b[5] + (uint64_t)a[2] * b[4] + (uint64_t)a[3] * b[3] + (uint64_t)a[4] * b[2] + (uint64_t)a[5] * b[1] + (uint64_t)a[6] * b[0]; VERIFY_BITS(c, 63); /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ d += (uint64_t)a[7] * b[9] + (uint64_t)a[8] * b[8] + (uint64_t)a[9] * b[7]; VERIFY_BITS(d, 61); /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ u6 = d & M; d >>= 26; c += u6 * R0; VERIFY_BITS(u6, 26); VERIFY_BITS(d, 35); /* VERIFY_BITS(c, 64); */ /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ t6 = c & M; c >>= 26; c += u6 * R1; VERIFY_BITS(t6, 26); VERIFY_BITS(c, 39); /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ c += (uint64_t)a[0] * b[7] + (uint64_t)a[1] * b[6] + (uint64_t)a[2] * b[5] + (uint64_t)a[3] * b[4] + (uint64_t)a[4] * b[3] + (uint64_t)a[5] * b[2] + (uint64_t)a[6] * b[1] + (uint64_t)a[7] * b[0]; /* VERIFY_BITS(c, 64); */ VERIFY_CHECK(c <= 0x8000007C00000007ULL); /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ d += (uint64_t)a[8] * b[9] + (uint64_t)a[9] * b[8]; VERIFY_BITS(d, 58); /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ u7 = d & M; d >>= 26; c += u7 * R0; VERIFY_BITS(u7, 26); VERIFY_BITS(d, 32); /* VERIFY_BITS(c, 64); */ VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ t7 = c & M; c >>= 26; c += u7 * R1; VERIFY_BITS(t7, 26); VERIFY_BITS(c, 38); /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ c += (uint64_t)a[0] * b[8] + (uint64_t)a[1] * b[7] + (uint64_t)a[2] * b[6] + (uint64_t)a[3] * b[5] + (uint64_t)a[4] * b[4] + (uint64_t)a[5] * b[3] + (uint64_t)a[6] * b[2] + (uint64_t)a[7] * b[1] + (uint64_t)a[8] * b[0]; /* VERIFY_BITS(c, 64); */ VERIFY_CHECK(c <= 0x9000007B80000008ULL); /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += (uint64_t)a[9] * b[9]; VERIFY_BITS(d, 57); /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ u8 = d & M; d >>= 26; c += u8 * R0; VERIFY_BITS(u8, 26); VERIFY_BITS(d, 31); /* VERIFY_BITS(c, 64); */ VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[3] = t3; VERIFY_BITS(r[3], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[4] = t4; VERIFY_BITS(r[4], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[5] = t5; VERIFY_BITS(r[5], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[6] = t6; VERIFY_BITS(r[6], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[7] = t7; VERIFY_BITS(r[7], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[8] = c & M; c >>= 26; c += u8 * R1; VERIFY_BITS(r[8], 26); VERIFY_BITS(c, 39); /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += d * R0 + t9; VERIFY_BITS(c, 45); /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); VERIFY_BITS(r[9], 22); VERIFY_BITS(c, 46); /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d = c * (R0 >> 4) + t0; VERIFY_BITS(d, 56); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[0] = d & M; d >>= 26; VERIFY_BITS(r[0], 26); VERIFY_BITS(d, 30); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += c * (R1 >> 4) + t1; VERIFY_BITS(d, 53); VERIFY_CHECK(d <= 0x10000003FFFFBFULL); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[1] = d & M; d >>= 26; VERIFY_BITS(r[1], 26); VERIFY_BITS(d, 27); VERIFY_CHECK(d <= 0x4000000ULL); /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += t2; VERIFY_BITS(d, 27); /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[2] = d; VERIFY_BITS(r[2], 27); /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a) { uint64_t c, d; uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; uint32_t t9, t0, t1, t2, t3, t4, t5, t6, t7; const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; VERIFY_BITS(a[0], 30); VERIFY_BITS(a[1], 30); VERIFY_BITS(a[2], 30); VERIFY_BITS(a[3], 30); VERIFY_BITS(a[4], 30); VERIFY_BITS(a[5], 30); VERIFY_BITS(a[6], 30); VERIFY_BITS(a[7], 30); VERIFY_BITS(a[8], 30); VERIFY_BITS(a[9], 26); /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. * px is a shorthand for sum(a[i]*a[x-i], i=0..x). * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. */ d = (uint64_t)(a[0]*2) * a[9] + (uint64_t)(a[1]*2) * a[8] + (uint64_t)(a[2]*2) * a[7] + (uint64_t)(a[3]*2) * a[6] + (uint64_t)(a[4]*2) * a[5]; /* VERIFY_BITS(d, 64); */ /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ t9 = d & M; d >>= 26; VERIFY_BITS(t9, 26); VERIFY_BITS(d, 38); /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ c = (uint64_t)a[0] * a[0]; VERIFY_BITS(c, 60); /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ d += (uint64_t)(a[1]*2) * a[9] + (uint64_t)(a[2]*2) * a[8] + (uint64_t)(a[3]*2) * a[7] + (uint64_t)(a[4]*2) * a[6] + (uint64_t)a[5] * a[5]; VERIFY_BITS(d, 63); /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ u0 = d & M; d >>= 26; c += u0 * R0; VERIFY_BITS(u0, 26); VERIFY_BITS(d, 37); VERIFY_BITS(c, 61); /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ t0 = c & M; c >>= 26; c += u0 * R1; VERIFY_BITS(t0, 26); VERIFY_BITS(c, 37); /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ c += (uint64_t)(a[0]*2) * a[1]; VERIFY_BITS(c, 62); /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ d += (uint64_t)(a[2]*2) * a[9] + (uint64_t)(a[3]*2) * a[8] + (uint64_t)(a[4]*2) * a[7] + (uint64_t)(a[5]*2) * a[6]; VERIFY_BITS(d, 63); /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ u1 = d & M; d >>= 26; c += u1 * R0; VERIFY_BITS(u1, 26); VERIFY_BITS(d, 37); VERIFY_BITS(c, 63); /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ t1 = c & M; c >>= 26; c += u1 * R1; VERIFY_BITS(t1, 26); VERIFY_BITS(c, 38); /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ c += (uint64_t)(a[0]*2) * a[2] + (uint64_t)a[1] * a[1]; VERIFY_BITS(c, 62); /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ d += (uint64_t)(a[3]*2) * a[9] + (uint64_t)(a[4]*2) * a[8] + (uint64_t)(a[5]*2) * a[7] + (uint64_t)a[6] * a[6]; VERIFY_BITS(d, 63); /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ u2 = d & M; d >>= 26; c += u2 * R0; VERIFY_BITS(u2, 26); VERIFY_BITS(d, 37); VERIFY_BITS(c, 63); /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ t2 = c & M; c >>= 26; c += u2 * R1; VERIFY_BITS(t2, 26); VERIFY_BITS(c, 38); /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ c += (uint64_t)(a[0]*2) * a[3] + (uint64_t)(a[1]*2) * a[2]; VERIFY_BITS(c, 63); /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ d += (uint64_t)(a[4]*2) * a[9] + (uint64_t)(a[5]*2) * a[8] + (uint64_t)(a[6]*2) * a[7]; VERIFY_BITS(d, 63); /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ u3 = d & M; d >>= 26; c += u3 * R0; VERIFY_BITS(u3, 26); VERIFY_BITS(d, 37); /* VERIFY_BITS(c, 64); */ /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ t3 = c & M; c >>= 26; c += u3 * R1; VERIFY_BITS(t3, 26); VERIFY_BITS(c, 39); /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ c += (uint64_t)(a[0]*2) * a[4] + (uint64_t)(a[1]*2) * a[3] + (uint64_t)a[2] * a[2]; VERIFY_BITS(c, 63); /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ d += (uint64_t)(a[5]*2) * a[9] + (uint64_t)(a[6]*2) * a[8] + (uint64_t)a[7] * a[7]; VERIFY_BITS(d, 62); /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ u4 = d & M; d >>= 26; c += u4 * R0; VERIFY_BITS(u4, 26); VERIFY_BITS(d, 36); /* VERIFY_BITS(c, 64); */ /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ t4 = c & M; c >>= 26; c += u4 * R1; VERIFY_BITS(t4, 26); VERIFY_BITS(c, 39); /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ c += (uint64_t)(a[0]*2) * a[5] + (uint64_t)(a[1]*2) * a[4] + (uint64_t)(a[2]*2) * a[3]; VERIFY_BITS(c, 63); /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ d += (uint64_t)(a[6]*2) * a[9] + (uint64_t)(a[7]*2) * a[8]; VERIFY_BITS(d, 62); /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ u5 = d & M; d >>= 26; c += u5 * R0; VERIFY_BITS(u5, 26); VERIFY_BITS(d, 36); /* VERIFY_BITS(c, 64); */ /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ t5 = c & M; c >>= 26; c += u5 * R1; VERIFY_BITS(t5, 26); VERIFY_BITS(c, 39); /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ c += (uint64_t)(a[0]*2) * a[6] + (uint64_t)(a[1]*2) * a[5] + (uint64_t)(a[2]*2) * a[4] + (uint64_t)a[3] * a[3]; VERIFY_BITS(c, 63); /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ d += (uint64_t)(a[7]*2) * a[9] + (uint64_t)a[8] * a[8]; VERIFY_BITS(d, 61); /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ u6 = d & M; d >>= 26; c += u6 * R0; VERIFY_BITS(u6, 26); VERIFY_BITS(d, 35); /* VERIFY_BITS(c, 64); */ /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ t6 = c & M; c >>= 26; c += u6 * R1; VERIFY_BITS(t6, 26); VERIFY_BITS(c, 39); /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ c += (uint64_t)(a[0]*2) * a[7] + (uint64_t)(a[1]*2) * a[6] + (uint64_t)(a[2]*2) * a[5] + (uint64_t)(a[3]*2) * a[4]; /* VERIFY_BITS(c, 64); */ VERIFY_CHECK(c <= 0x8000007C00000007ULL); /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ d += (uint64_t)(a[8]*2) * a[9]; VERIFY_BITS(d, 58); /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ u7 = d & M; d >>= 26; c += u7 * R0; VERIFY_BITS(u7, 26); VERIFY_BITS(d, 32); /* VERIFY_BITS(c, 64); */ VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ t7 = c & M; c >>= 26; c += u7 * R1; VERIFY_BITS(t7, 26); VERIFY_BITS(c, 38); /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ c += (uint64_t)(a[0]*2) * a[8] + (uint64_t)(a[1]*2) * a[7] + (uint64_t)(a[2]*2) * a[6] + (uint64_t)(a[3]*2) * a[5] + (uint64_t)a[4] * a[4]; /* VERIFY_BITS(c, 64); */ VERIFY_CHECK(c <= 0x9000007B80000008ULL); /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += (uint64_t)a[9] * a[9]; VERIFY_BITS(d, 57); /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ u8 = d & M; d >>= 26; c += u8 * R0; VERIFY_BITS(u8, 26); VERIFY_BITS(d, 31); /* VERIFY_BITS(c, 64); */ VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[3] = t3; VERIFY_BITS(r[3], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[4] = t4; VERIFY_BITS(r[4], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[5] = t5; VERIFY_BITS(r[5], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[6] = t6; VERIFY_BITS(r[6], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[7] = t7; VERIFY_BITS(r[7], 26); /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[8] = c & M; c >>= 26; c += u8 * R1; VERIFY_BITS(r[8], 26); VERIFY_BITS(c, 39); /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += d * R0 + t9; VERIFY_BITS(c, 45); /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); VERIFY_BITS(r[9], 22); VERIFY_BITS(c, 46); /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d = c * (R0 >> 4) + t0; VERIFY_BITS(d, 56); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[0] = d & M; d >>= 26; VERIFY_BITS(r[0], 26); VERIFY_BITS(d, 30); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += c * (R1 >> 4) + t1; VERIFY_BITS(d, 53); VERIFY_CHECK(d <= 0x10000003FFFFBFULL); /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[1] = d & M; d >>= 26; VERIFY_BITS(r[1], 26); VERIFY_BITS(d, 27); VERIFY_CHECK(d <= 0x4000000ULL); /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ d += t2; VERIFY_BITS(d, 27); /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[2] = d; VERIFY_BITS(r[2], 27); /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } #endif static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= 8); VERIFY_CHECK(b->magnitude <= 8); secp256k1_fe_verify(a); secp256k1_fe_verify(b); VERIFY_CHECK(r != b); VERIFY_CHECK(a != b); #endif secp256k1_fe_mul_inner(r->n, a->n, b->n); #ifdef VERIFY r->magnitude = 1; r->normalized = 0; secp256k1_fe_verify(r); #endif } static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= 8); secp256k1_fe_verify(a); #endif secp256k1_fe_sqr_inner(r->n, a->n); #ifdef VERIFY r->magnitude = 1; r->normalized = 0; secp256k1_fe_verify(r); #endif } static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { uint32_t mask0, mask1; VG_CHECK_VERIFY(r->n, sizeof(r->n)); mask0 = flag + ~((uint32_t)0); mask1 = ~mask0; r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1); r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1); #ifdef VERIFY if (flag) { r->magnitude = a->magnitude; r->normalized = a->normalized; } #endif } static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { uint32_t mask0, mask1; VG_CHECK_VERIFY(r->n, sizeof(r->n)); mask0 = flag + ~((uint32_t)0); mask1 = ~mask0; r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); } static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); #endif r->n[0] = a->n[0] | a->n[1] << 26; r->n[1] = a->n[1] >> 6 | a->n[2] << 20; r->n[2] = a->n[2] >> 12 | a->n[3] << 14; r->n[3] = a->n[3] >> 18 | a->n[4] << 8; r->n[4] = a->n[4] >> 24 | a->n[5] << 2 | a->n[6] << 28; r->n[5] = a->n[6] >> 4 | a->n[7] << 22; r->n[6] = a->n[7] >> 10 | a->n[8] << 16; r->n[7] = a->n[8] >> 16 | a->n[9] << 10; } static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { r->n[0] = a->n[0] & 0x3FFFFFFUL; r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL); r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL); r->n[3] = a->n[2] >> 14 | ((a->n[3] << 18) & 0x3FFFFFFUL); r->n[4] = a->n[3] >> 8 | ((a->n[4] << 24) & 0x3FFFFFFUL); r->n[5] = (a->n[4] >> 2) & 0x3FFFFFFUL; r->n[6] = a->n[4] >> 28 | ((a->n[5] << 4) & 0x3FFFFFFUL); r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL); r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL); r->n[9] = a->n[7] >> 10; #ifdef VERIFY r->magnitude = 1; r->normalized = 1; #endif } #endif /* SECP256K1_FIELD_REPR_IMPL_H */ diff --git a/src/secp256k1/src/field_5x52.h b/src/secp256k1/src/field_5x52.h index 6a068484c..50ee3f9ec 100644 --- a/src/secp256k1/src/field_5x52.h +++ b/src/secp256k1/src/field_5x52.h @@ -1,55 +1,55 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_FIELD_REPR_H #define SECP256K1_FIELD_REPR_H #include typedef struct { /* X = sum(i=0..4, n[i]*2^(i*52)) mod p * where p = 2^256 - 0x1000003D1 */ uint64_t n[5]; #ifdef VERIFY int magnitude; int normalized; #endif } secp256k1_fe; /* Unpacks a constant into a overlapping multi-limbed FE element. */ #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ (d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \ ((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \ ((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \ ((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \ ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \ } #ifdef VERIFY #define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} #else #define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} #endif typedef struct { uint64_t n[4]; } secp256k1_fe_storage; #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ (d0) | (((uint64_t)(d1)) << 32), \ (d2) | (((uint64_t)(d3)) << 32), \ (d4) | (((uint64_t)(d5)) << 32), \ (d6) | (((uint64_t)(d7)) << 32) \ }} #define SECP256K1_FE_STORAGE_CONST_GET(d) \ (uint32_t)(d.n[3] >> 32), (uint32_t)d.n[3], \ (uint32_t)(d.n[2] >> 32), (uint32_t)d.n[2], \ (uint32_t)(d.n[1] >> 32), (uint32_t)d.n[1], \ (uint32_t)(d.n[0] >> 32), (uint32_t)d.n[0] #endif /* SECP256K1_FIELD_REPR_H */ diff --git a/src/secp256k1/src/field_5x52_asm_impl.h b/src/secp256k1/src/field_5x52_asm_impl.h index 1fc3171f6..a2118044a 100644 --- a/src/secp256k1/src/field_5x52_asm_impl.h +++ b/src/secp256k1/src/field_5x52_asm_impl.h @@ -1,502 +1,502 @@ -/********************************************************************** - * Copyright (c) 2013-2014 Diederik Huys, 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 Diederik Huys, Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ /** * Changelog: * - March 2013, Diederik Huys: original version * - November 2014, Pieter Wuille: updated to use Peter Dettman's parallel multiplication algorithm * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly */ #ifndef SECP256K1_FIELD_INNER5X52_IMPL_H #define SECP256K1_FIELD_INNER5X52_IMPL_H SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { /** * Registers: rdx:rax = multiplication accumulator * r9:r8 = c * r15:rcx = d * r10-r14 = a0-a4 * rbx = b * rdi = r * rsi = a / t? */ uint64_t tmp1, tmp2, tmp3; __asm__ __volatile__( "movq 0(%%rsi),%%r10\n" "movq 8(%%rsi),%%r11\n" "movq 16(%%rsi),%%r12\n" "movq 24(%%rsi),%%r13\n" "movq 32(%%rsi),%%r14\n" /* d += a3 * b0 */ "movq 0(%%rbx),%%rax\n" "mulq %%r13\n" "movq %%rax,%%rcx\n" "movq %%rdx,%%r15\n" /* d += a2 * b1 */ "movq 8(%%rbx),%%rax\n" "mulq %%r12\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a1 * b2 */ "movq 16(%%rbx),%%rax\n" "mulq %%r11\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d = a0 * b3 */ "movq 24(%%rbx),%%rax\n" "mulq %%r10\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* c = a4 * b4 */ "movq 32(%%rbx),%%rax\n" "mulq %%r14\n" "movq %%rax,%%r8\n" "movq %%rdx,%%r9\n" /* d += (c & M) * R */ "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* c >>= 52 (%%r8 only) */ "shrdq $52,%%r9,%%r8\n" /* t3 (tmp1) = d & M */ "movq %%rcx,%%rsi\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rsi\n" "movq %%rsi,%q1\n" /* d >>= 52 */ "shrdq $52,%%r15,%%rcx\n" "xorq %%r15,%%r15\n" /* d += a4 * b0 */ "movq 0(%%rbx),%%rax\n" "mulq %%r14\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a3 * b1 */ "movq 8(%%rbx),%%rax\n" "mulq %%r13\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a2 * b2 */ "movq 16(%%rbx),%%rax\n" "mulq %%r12\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a1 * b3 */ "movq 24(%%rbx),%%rax\n" "mulq %%r11\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a0 * b4 */ "movq 32(%%rbx),%%rax\n" "mulq %%r10\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += c * R */ "movq %%r8,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* t4 = d & M (%%rsi) */ "movq %%rcx,%%rsi\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rsi\n" /* d >>= 52 */ "shrdq $52,%%r15,%%rcx\n" "xorq %%r15,%%r15\n" /* tx = t4 >> 48 (tmp3) */ "movq %%rsi,%%rax\n" "shrq $48,%%rax\n" "movq %%rax,%q3\n" /* t4 &= (M >> 4) (tmp2) */ "movq $0xffffffffffff,%%rax\n" "andq %%rax,%%rsi\n" "movq %%rsi,%q2\n" /* c = a0 * b0 */ "movq 0(%%rbx),%%rax\n" "mulq %%r10\n" "movq %%rax,%%r8\n" "movq %%rdx,%%r9\n" /* d += a4 * b1 */ "movq 8(%%rbx),%%rax\n" "mulq %%r14\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a3 * b2 */ "movq 16(%%rbx),%%rax\n" "mulq %%r13\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a2 * b3 */ "movq 24(%%rbx),%%rax\n" "mulq %%r12\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a1 * b4 */ "movq 32(%%rbx),%%rax\n" "mulq %%r11\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* u0 = d & M (%%rsi) */ "movq %%rcx,%%rsi\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rsi\n" /* d >>= 52 */ "shrdq $52,%%r15,%%rcx\n" "xorq %%r15,%%r15\n" /* u0 = (u0 << 4) | tx (%%rsi) */ "shlq $4,%%rsi\n" "movq %q3,%%rax\n" "orq %%rax,%%rsi\n" /* c += u0 * (R >> 4) */ "movq $0x1000003d1,%%rax\n" "mulq %%rsi\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* r[0] = c & M */ "movq %%r8,%%rax\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rax\n" "movq %%rax,0(%%rdi)\n" /* c >>= 52 */ "shrdq $52,%%r9,%%r8\n" "xorq %%r9,%%r9\n" /* c += a1 * b0 */ "movq 0(%%rbx),%%rax\n" "mulq %%r11\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* c += a0 * b1 */ "movq 8(%%rbx),%%rax\n" "mulq %%r10\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* d += a4 * b2 */ "movq 16(%%rbx),%%rax\n" "mulq %%r14\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a3 * b3 */ "movq 24(%%rbx),%%rax\n" "mulq %%r13\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a2 * b4 */ "movq 32(%%rbx),%%rax\n" "mulq %%r12\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* c += (d & M) * R */ "movq %%rcx,%%rax\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* d >>= 52 */ "shrdq $52,%%r15,%%rcx\n" "xorq %%r15,%%r15\n" /* r[1] = c & M */ "movq %%r8,%%rax\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rax\n" "movq %%rax,8(%%rdi)\n" /* c >>= 52 */ "shrdq $52,%%r9,%%r8\n" "xorq %%r9,%%r9\n" /* c += a2 * b0 */ "movq 0(%%rbx),%%rax\n" "mulq %%r12\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* c += a1 * b1 */ "movq 8(%%rbx),%%rax\n" "mulq %%r11\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* c += a0 * b2 (last use of %%r10 = a0) */ "movq 16(%%rbx),%%rax\n" "mulq %%r10\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* fetch t3 (%%r10, overwrites a0), t4 (%%rsi) */ "movq %q2,%%rsi\n" "movq %q1,%%r10\n" /* d += a4 * b3 */ "movq 24(%%rbx),%%rax\n" "mulq %%r14\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* d += a3 * b4 */ "movq 32(%%rbx),%%rax\n" "mulq %%r13\n" "addq %%rax,%%rcx\n" "adcq %%rdx,%%r15\n" /* c += (d & M) * R */ "movq %%rcx,%%rax\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* d >>= 52 (%%rcx only) */ "shrdq $52,%%r15,%%rcx\n" /* r[2] = c & M */ "movq %%r8,%%rax\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rax\n" "movq %%rax,16(%%rdi)\n" /* c >>= 52 */ "shrdq $52,%%r9,%%r8\n" "xorq %%r9,%%r9\n" /* c += t3 */ "addq %%r10,%%r8\n" /* c += d * R */ "movq %%rcx,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* r[3] = c & M */ "movq %%r8,%%rax\n" "movq $0xfffffffffffff,%%rdx\n" "andq %%rdx,%%rax\n" "movq %%rax,24(%%rdi)\n" /* c >>= 52 (%%r8 only) */ "shrdq $52,%%r9,%%r8\n" /* c += t4 (%%r8 only) */ "addq %%rsi,%%r8\n" /* r[4] = c */ "movq %%r8,32(%%rdi)\n" : "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) : "b"(b), "D"(r) : "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" ); } SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { /** * Registers: rdx:rax = multiplication accumulator * r9:r8 = c * rcx:rbx = d * r10-r14 = a0-a4 * r15 = M (0xfffffffffffff) * rdi = r * rsi = a / t? */ uint64_t tmp1, tmp2, tmp3; __asm__ __volatile__( "movq 0(%%rsi),%%r10\n" "movq 8(%%rsi),%%r11\n" "movq 16(%%rsi),%%r12\n" "movq 24(%%rsi),%%r13\n" "movq 32(%%rsi),%%r14\n" "movq $0xfffffffffffff,%%r15\n" /* d = (a0*2) * a3 */ "leaq (%%r10,%%r10,1),%%rax\n" "mulq %%r13\n" "movq %%rax,%%rbx\n" "movq %%rdx,%%rcx\n" /* d += (a1*2) * a2 */ "leaq (%%r11,%%r11,1),%%rax\n" "mulq %%r12\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* c = a4 * a4 */ "movq %%r14,%%rax\n" "mulq %%r14\n" "movq %%rax,%%r8\n" "movq %%rdx,%%r9\n" /* d += (c & M) * R */ "andq %%r15,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* c >>= 52 (%%r8 only) */ "shrdq $52,%%r9,%%r8\n" /* t3 (tmp1) = d & M */ "movq %%rbx,%%rsi\n" "andq %%r15,%%rsi\n" "movq %%rsi,%q1\n" /* d >>= 52 */ "shrdq $52,%%rcx,%%rbx\n" "xorq %%rcx,%%rcx\n" /* a4 *= 2 */ "addq %%r14,%%r14\n" /* d += a0 * a4 */ "movq %%r10,%%rax\n" "mulq %%r14\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* d+= (a1*2) * a3 */ "leaq (%%r11,%%r11,1),%%rax\n" "mulq %%r13\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* d += a2 * a2 */ "movq %%r12,%%rax\n" "mulq %%r12\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* d += c * R */ "movq %%r8,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* t4 = d & M (%%rsi) */ "movq %%rbx,%%rsi\n" "andq %%r15,%%rsi\n" /* d >>= 52 */ "shrdq $52,%%rcx,%%rbx\n" "xorq %%rcx,%%rcx\n" /* tx = t4 >> 48 (tmp3) */ "movq %%rsi,%%rax\n" "shrq $48,%%rax\n" "movq %%rax,%q3\n" /* t4 &= (M >> 4) (tmp2) */ "movq $0xffffffffffff,%%rax\n" "andq %%rax,%%rsi\n" "movq %%rsi,%q2\n" /* c = a0 * a0 */ "movq %%r10,%%rax\n" "mulq %%r10\n" "movq %%rax,%%r8\n" "movq %%rdx,%%r9\n" /* d += a1 * a4 */ "movq %%r11,%%rax\n" "mulq %%r14\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* d += (a2*2) * a3 */ "leaq (%%r12,%%r12,1),%%rax\n" "mulq %%r13\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* u0 = d & M (%%rsi) */ "movq %%rbx,%%rsi\n" "andq %%r15,%%rsi\n" /* d >>= 52 */ "shrdq $52,%%rcx,%%rbx\n" "xorq %%rcx,%%rcx\n" /* u0 = (u0 << 4) | tx (%%rsi) */ "shlq $4,%%rsi\n" "movq %q3,%%rax\n" "orq %%rax,%%rsi\n" /* c += u0 * (R >> 4) */ "movq $0x1000003d1,%%rax\n" "mulq %%rsi\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* r[0] = c & M */ "movq %%r8,%%rax\n" "andq %%r15,%%rax\n" "movq %%rax,0(%%rdi)\n" /* c >>= 52 */ "shrdq $52,%%r9,%%r8\n" "xorq %%r9,%%r9\n" /* a0 *= 2 */ "addq %%r10,%%r10\n" /* c += a0 * a1 */ "movq %%r10,%%rax\n" "mulq %%r11\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* d += a2 * a4 */ "movq %%r12,%%rax\n" "mulq %%r14\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* d += a3 * a3 */ "movq %%r13,%%rax\n" "mulq %%r13\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* c += (d & M) * R */ "movq %%rbx,%%rax\n" "andq %%r15,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* d >>= 52 */ "shrdq $52,%%rcx,%%rbx\n" "xorq %%rcx,%%rcx\n" /* r[1] = c & M */ "movq %%r8,%%rax\n" "andq %%r15,%%rax\n" "movq %%rax,8(%%rdi)\n" /* c >>= 52 */ "shrdq $52,%%r9,%%r8\n" "xorq %%r9,%%r9\n" /* c += a0 * a2 (last use of %%r10) */ "movq %%r10,%%rax\n" "mulq %%r12\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* fetch t3 (%%r10, overwrites a0),t4 (%%rsi) */ "movq %q2,%%rsi\n" "movq %q1,%%r10\n" /* c += a1 * a1 */ "movq %%r11,%%rax\n" "mulq %%r11\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* d += a3 * a4 */ "movq %%r13,%%rax\n" "mulq %%r14\n" "addq %%rax,%%rbx\n" "adcq %%rdx,%%rcx\n" /* c += (d & M) * R */ "movq %%rbx,%%rax\n" "andq %%r15,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* d >>= 52 (%%rbx only) */ "shrdq $52,%%rcx,%%rbx\n" /* r[2] = c & M */ "movq %%r8,%%rax\n" "andq %%r15,%%rax\n" "movq %%rax,16(%%rdi)\n" /* c >>= 52 */ "shrdq $52,%%r9,%%r8\n" "xorq %%r9,%%r9\n" /* c += t3 */ "addq %%r10,%%r8\n" /* c += d * R */ "movq %%rbx,%%rax\n" "movq $0x1000003d10,%%rdx\n" "mulq %%rdx\n" "addq %%rax,%%r8\n" "adcq %%rdx,%%r9\n" /* r[3] = c & M */ "movq %%r8,%%rax\n" "andq %%r15,%%rax\n" "movq %%rax,24(%%rdi)\n" /* c >>= 52 (%%r8 only) */ "shrdq $52,%%r9,%%r8\n" /* c += t4 (%%r8 only) */ "addq %%rsi,%%r8\n" /* r[4] = c */ "movq %%r8,32(%%rdi)\n" : "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) : "D"(r) : "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" ); } #endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h index 71a38f915..3465ea324 100644 --- a/src/secp256k1/src/field_5x52_impl.h +++ b/src/secp256k1/src/field_5x52_impl.h @@ -1,501 +1,501 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_FIELD_REPR_IMPL_H #define SECP256K1_FIELD_REPR_IMPL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #include "util.h" #include "field.h" #if defined(USE_ASM_X86_64) #include "field_5x52_asm_impl.h" #else #include "field_5x52_int128_impl.h" #endif /** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F, * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations * accept any input with magnitude at most M, and have different rules for propagating magnitude to their * output. */ #ifdef VERIFY static void secp256k1_fe_verify(const secp256k1_fe *a) { const uint64_t *d = a->n; int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m); r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m); r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m); r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m); r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m); r &= (a->magnitude >= 0); r &= (a->magnitude <= 2048); if (a->normalized) { r &= (a->magnitude <= 1); if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { r &= (d[0] < 0xFFFFEFFFFFC2FULL); } } VERIFY_CHECK(r == 1); } #endif static void secp256k1_fe_normalize(secp256k1_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; /* Reduce t4 at the start so there will be at most a single carry from the first pass */ uint64_t m; uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x1000003D1ULL; t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t4 >> 49 == 0); /* At most a single final reduction is needed; check if the value is >= the field characteristic */ x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) & (t0 >= 0xFFFFEFFFFFC2FULL)); /* Apply the final reduction (for constant-time behaviour, we do it always) */ t0 += x * 0x1000003D1ULL; t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ VERIFY_CHECK(t4 >> 48 == x); /* Mask off the possible multiple of 2^256 from the final reduction */ t4 &= 0x0FFFFFFFFFFFFULL; r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; #ifdef VERIFY r->magnitude = 1; r->normalized = 1; secp256k1_fe_verify(r); #endif } static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; /* Reduce t4 at the start so there will be at most a single carry from the first pass */ uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x1000003D1ULL; t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t4 >> 49 == 0); r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; #ifdef VERIFY r->magnitude = 1; secp256k1_fe_verify(r); #endif } static void secp256k1_fe_normalize_var(secp256k1_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; /* Reduce t4 at the start so there will be at most a single carry from the first pass */ uint64_t m; uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x1000003D1ULL; t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t4 >> 49 == 0); /* At most a single final reduction is needed; check if the value is >= the field characteristic */ x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) & (t0 >= 0xFFFFEFFFFFC2FULL)); if (x) { t0 += 0x1000003D1ULL; t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ VERIFY_CHECK(t4 >> 48 == x); /* Mask off the possible multiple of 2^256 from the final reduction */ t4 &= 0x0FFFFFFFFFFFFULL; } r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; #ifdef VERIFY r->magnitude = 1; r->normalized = 1; secp256k1_fe_verify(r); #endif } static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ uint64_t z0, z1; /* Reduce t4 at the start so there will be at most a single carry from the first pass */ uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x1000003D1ULL; t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL; t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t4 >> 49 == 0); return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); } static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { uint64_t t0, t1, t2, t3, t4; uint64_t z0, z1; uint64_t x; t0 = r->n[0]; t4 = r->n[4]; /* Reduce t4 at the start so there will be at most a single carry from the first pass */ x = t4 >> 48; /* The first pass ensures the magnitude is 1, ... */ t0 += x * 0x1000003D1ULL; /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ z0 = t0 & 0xFFFFFFFFFFFFFULL; z1 = z0 ^ 0x1000003D0ULL; /* Fast return path should catch the majority of cases */ if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) { return 0; } t1 = r->n[1]; t2 = r->n[2]; t3 = r->n[3]; t4 &= 0x0FFFFFFFFFFFFULL; t1 += (t0 >> 52); t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ VERIFY_CHECK(t4 >> 49 == 0); return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); } SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { r->n[0] = a; r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; #ifdef VERIFY r->magnitude = 1; r->normalized = 1; secp256k1_fe_verify(r); #endif } SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { const uint64_t *t = a->n; #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; } SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif return a->n[0] & 1; } SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { int i; #ifdef VERIFY a->magnitude = 0; a->normalized = 1; #endif for (i=0; i<5; i++) { a->n[i] = 0; } } static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); VERIFY_CHECK(b->normalized); secp256k1_fe_verify(a); secp256k1_fe_verify(b); #endif for (i = 4; i >= 0; i--) { if (a->n[i] > b->n[i]) { return 1; } if (a->n[i] < b->n[i]) { return -1; } } return 0; } static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { int ret; r->n[0] = (uint64_t)a[31] | ((uint64_t)a[30] << 8) | ((uint64_t)a[29] << 16) | ((uint64_t)a[28] << 24) | ((uint64_t)a[27] << 32) | ((uint64_t)a[26] << 40) | ((uint64_t)(a[25] & 0xF) << 48); r->n[1] = (uint64_t)((a[25] >> 4) & 0xF) | ((uint64_t)a[24] << 4) | ((uint64_t)a[23] << 12) | ((uint64_t)a[22] << 20) | ((uint64_t)a[21] << 28) | ((uint64_t)a[20] << 36) | ((uint64_t)a[19] << 44); r->n[2] = (uint64_t)a[18] | ((uint64_t)a[17] << 8) | ((uint64_t)a[16] << 16) | ((uint64_t)a[15] << 24) | ((uint64_t)a[14] << 32) | ((uint64_t)a[13] << 40) | ((uint64_t)(a[12] & 0xF) << 48); r->n[3] = (uint64_t)((a[12] >> 4) & 0xF) | ((uint64_t)a[11] << 4) | ((uint64_t)a[10] << 12) | ((uint64_t)a[9] << 20) | ((uint64_t)a[8] << 28) | ((uint64_t)a[7] << 36) | ((uint64_t)a[6] << 44); r->n[4] = (uint64_t)a[5] | ((uint64_t)a[4] << 8) | ((uint64_t)a[3] << 16) | ((uint64_t)a[2] << 24) | ((uint64_t)a[1] << 32) | ((uint64_t)a[0] << 40); ret = !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL)); #ifdef VERIFY r->magnitude = 1; if (ret) { r->normalized = 1; secp256k1_fe_verify(r); } else { r->normalized = 0; } #endif return ret; } /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif r[0] = (a->n[4] >> 40) & 0xFF; r[1] = (a->n[4] >> 32) & 0xFF; r[2] = (a->n[4] >> 24) & 0xFF; r[3] = (a->n[4] >> 16) & 0xFF; r[4] = (a->n[4] >> 8) & 0xFF; r[5] = a->n[4] & 0xFF; r[6] = (a->n[3] >> 44) & 0xFF; r[7] = (a->n[3] >> 36) & 0xFF; r[8] = (a->n[3] >> 28) & 0xFF; r[9] = (a->n[3] >> 20) & 0xFF; r[10] = (a->n[3] >> 12) & 0xFF; r[11] = (a->n[3] >> 4) & 0xFF; r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4); r[13] = (a->n[2] >> 40) & 0xFF; r[14] = (a->n[2] >> 32) & 0xFF; r[15] = (a->n[2] >> 24) & 0xFF; r[16] = (a->n[2] >> 16) & 0xFF; r[17] = (a->n[2] >> 8) & 0xFF; r[18] = a->n[2] & 0xFF; r[19] = (a->n[1] >> 44) & 0xFF; r[20] = (a->n[1] >> 36) & 0xFF; r[21] = (a->n[1] >> 28) & 0xFF; r[22] = (a->n[1] >> 20) & 0xFF; r[23] = (a->n[1] >> 12) & 0xFF; r[24] = (a->n[1] >> 4) & 0xFF; r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4); r[26] = (a->n[0] >> 40) & 0xFF; r[27] = (a->n[0] >> 32) & 0xFF; r[28] = (a->n[0] >> 24) & 0xFF; r[29] = (a->n[0] >> 16) & 0xFF; r[30] = (a->n[0] >> 8) & 0xFF; r[31] = a->n[0] & 0xFF; } SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= m); secp256k1_fe_verify(a); #endif r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2]; r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3]; r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; #ifdef VERIFY r->magnitude = m + 1; r->normalized = 0; secp256k1_fe_verify(r); #endif } SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { r->n[0] *= a; r->n[1] *= a; r->n[2] *= a; r->n[3] *= a; r->n[4] *= a; #ifdef VERIFY r->magnitude *= a; r->normalized = 0; secp256k1_fe_verify(r); #endif } SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { #ifdef VERIFY secp256k1_fe_verify(a); #endif r->n[0] += a->n[0]; r->n[1] += a->n[1]; r->n[2] += a->n[2]; r->n[3] += a->n[3]; r->n[4] += a->n[4]; #ifdef VERIFY r->magnitude += a->magnitude; r->normalized = 0; secp256k1_fe_verify(r); #endif } static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= 8); VERIFY_CHECK(b->magnitude <= 8); secp256k1_fe_verify(a); secp256k1_fe_verify(b); VERIFY_CHECK(r != b); VERIFY_CHECK(a != b); #endif secp256k1_fe_mul_inner(r->n, a->n, b->n); #ifdef VERIFY r->magnitude = 1; r->normalized = 0; secp256k1_fe_verify(r); #endif } static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= 8); secp256k1_fe_verify(a); #endif secp256k1_fe_sqr_inner(r->n, a->n); #ifdef VERIFY r->magnitude = 1; r->normalized = 0; secp256k1_fe_verify(r); #endif } static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { uint64_t mask0, mask1; VG_CHECK_VERIFY(r->n, sizeof(r->n)); mask0 = flag + ~((uint64_t)0); mask1 = ~mask0; r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); #ifdef VERIFY if (flag) { r->magnitude = a->magnitude; r->normalized = a->normalized; } #endif } static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { uint64_t mask0, mask1; VG_CHECK_VERIFY(r->n, sizeof(r->n)); mask0 = flag + ~((uint64_t)0); mask1 = ~mask0; r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); } static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); #endif r->n[0] = a->n[0] | a->n[1] << 52; r->n[1] = a->n[1] >> 12 | a->n[2] << 40; r->n[2] = a->n[2] >> 24 | a->n[3] << 28; r->n[3] = a->n[3] >> 36 | a->n[4] << 16; } static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL; r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL); r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL); r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL); r->n[4] = a->n[3] >> 16; #ifdef VERIFY r->magnitude = 1; r->normalized = 1; #endif } #endif /* SECP256K1_FIELD_REPR_IMPL_H */ diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h index bcbfb92ac..314002ee3 100644 --- a/src/secp256k1/src/field_5x52_int128_impl.h +++ b/src/secp256k1/src/field_5x52_int128_impl.h @@ -1,279 +1,279 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_FIELD_INNER5X52_IMPL_H #define SECP256K1_FIELD_INNER5X52_IMPL_H #include #ifdef VERIFY #define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) #else #define VERIFY_BITS(x, n) do { } while(0) #endif SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { uint128_t c, d; uint64_t t3, t4, tx, u0; uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; VERIFY_BITS(a[0], 56); VERIFY_BITS(a[1], 56); VERIFY_BITS(a[2], 56); VERIFY_BITS(a[3], 56); VERIFY_BITS(a[4], 52); VERIFY_BITS(b[0], 56); VERIFY_BITS(b[1], 56); VERIFY_BITS(b[2], 56); VERIFY_BITS(b[3], 56); VERIFY_BITS(b[4], 52); VERIFY_CHECK(r != b); VERIFY_CHECK(a != b); /* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. * for 0 <= x <= 4, px is a shorthand for sum(a[i]*b[x-i], i=0..x). * for 4 <= x <= 8, px is a shorthand for sum(a[i]*b[x-i], i=(x-4)..4) * Note that [x 0 0 0 0 0] = [x*R]. */ d = (uint128_t)a0 * b[3] + (uint128_t)a1 * b[2] + (uint128_t)a2 * b[1] + (uint128_t)a3 * b[0]; VERIFY_BITS(d, 114); /* [d 0 0 0] = [p3 0 0 0] */ c = (uint128_t)a4 * b[4]; VERIFY_BITS(c, 112); /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ d += (c & M) * R; c >>= 52; VERIFY_BITS(d, 115); VERIFY_BITS(c, 60); /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ t3 = d & M; d >>= 52; VERIFY_BITS(t3, 52); VERIFY_BITS(d, 63); /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ d += (uint128_t)a0 * b[4] + (uint128_t)a1 * b[3] + (uint128_t)a2 * b[2] + (uint128_t)a3 * b[1] + (uint128_t)a4 * b[0]; VERIFY_BITS(d, 115); /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ d += c * R; VERIFY_BITS(d, 116); /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ t4 = d & M; d >>= 52; VERIFY_BITS(t4, 52); VERIFY_BITS(d, 64); /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ tx = (t4 >> 48); t4 &= (M >> 4); VERIFY_BITS(tx, 4); VERIFY_BITS(t4, 48); /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ c = (uint128_t)a0 * b[0]; VERIFY_BITS(c, 112); /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ d += (uint128_t)a1 * b[4] + (uint128_t)a2 * b[3] + (uint128_t)a3 * b[2] + (uint128_t)a4 * b[1]; VERIFY_BITS(d, 115); /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ u0 = d & M; d >>= 52; VERIFY_BITS(u0, 52); VERIFY_BITS(d, 63); /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ u0 = (u0 << 4) | tx; VERIFY_BITS(u0, 56); /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ c += (uint128_t)u0 * (R >> 4); VERIFY_BITS(c, 115); /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ r[0] = c & M; c >>= 52; VERIFY_BITS(r[0], 52); VERIFY_BITS(c, 61); /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ c += (uint128_t)a0 * b[1] + (uint128_t)a1 * b[0]; VERIFY_BITS(c, 114); /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ d += (uint128_t)a2 * b[4] + (uint128_t)a3 * b[3] + (uint128_t)a4 * b[2]; VERIFY_BITS(d, 114); /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ c += (d & M) * R; d >>= 52; VERIFY_BITS(c, 115); VERIFY_BITS(d, 62); /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ r[1] = c & M; c >>= 52; VERIFY_BITS(r[1], 52); VERIFY_BITS(c, 63); /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ c += (uint128_t)a0 * b[2] + (uint128_t)a1 * b[1] + (uint128_t)a2 * b[0]; VERIFY_BITS(c, 114); /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ d += (uint128_t)a3 * b[4] + (uint128_t)a4 * b[3]; VERIFY_BITS(d, 114); /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += (d & M) * R; d >>= 52; VERIFY_BITS(c, 115); VERIFY_BITS(d, 62); /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[2] = c & M; c >>= 52; VERIFY_BITS(r[2], 52); VERIFY_BITS(c, 63); /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += d * R + t3; VERIFY_BITS(c, 100); /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[3] = c & M; c >>= 52; VERIFY_BITS(r[3], 52); VERIFY_BITS(c, 48); /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += t4; VERIFY_BITS(c, 49); /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[4] = c; VERIFY_BITS(r[4], 49); /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { uint128_t c, d; uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; int64_t t3, t4, tx, u0; const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; VERIFY_BITS(a[0], 56); VERIFY_BITS(a[1], 56); VERIFY_BITS(a[2], 56); VERIFY_BITS(a[3], 56); VERIFY_BITS(a[4], 52); /** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. * px is a shorthand for sum(a[i]*a[x-i], i=0..x). * Note that [x 0 0 0 0 0] = [x*R]. */ d = (uint128_t)(a0*2) * a3 + (uint128_t)(a1*2) * a2; VERIFY_BITS(d, 114); /* [d 0 0 0] = [p3 0 0 0] */ c = (uint128_t)a4 * a4; VERIFY_BITS(c, 112); /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ d += (c & M) * R; c >>= 52; VERIFY_BITS(d, 115); VERIFY_BITS(c, 60); /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ t3 = d & M; d >>= 52; VERIFY_BITS(t3, 52); VERIFY_BITS(d, 63); /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ a4 *= 2; d += (uint128_t)a0 * a4 + (uint128_t)(a1*2) * a3 + (uint128_t)a2 * a2; VERIFY_BITS(d, 115); /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ d += c * R; VERIFY_BITS(d, 116); /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ t4 = d & M; d >>= 52; VERIFY_BITS(t4, 52); VERIFY_BITS(d, 64); /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ tx = (t4 >> 48); t4 &= (M >> 4); VERIFY_BITS(tx, 4); VERIFY_BITS(t4, 48); /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ c = (uint128_t)a0 * a0; VERIFY_BITS(c, 112); /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ d += (uint128_t)a1 * a4 + (uint128_t)(a2*2) * a3; VERIFY_BITS(d, 114); /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ u0 = d & M; d >>= 52; VERIFY_BITS(u0, 52); VERIFY_BITS(d, 62); /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ u0 = (u0 << 4) | tx; VERIFY_BITS(u0, 56); /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ c += (uint128_t)u0 * (R >> 4); VERIFY_BITS(c, 113); /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ r[0] = c & M; c >>= 52; VERIFY_BITS(r[0], 52); VERIFY_BITS(c, 61); /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ a0 *= 2; c += (uint128_t)a0 * a1; VERIFY_BITS(c, 114); /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ d += (uint128_t)a2 * a4 + (uint128_t)a3 * a3; VERIFY_BITS(d, 114); /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ c += (d & M) * R; d >>= 52; VERIFY_BITS(c, 115); VERIFY_BITS(d, 62); /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ r[1] = c & M; c >>= 52; VERIFY_BITS(r[1], 52); VERIFY_BITS(c, 63); /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ c += (uint128_t)a0 * a2 + (uint128_t)a1 * a1; VERIFY_BITS(c, 114); /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ d += (uint128_t)a3 * a4; VERIFY_BITS(d, 114); /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += (d & M) * R; d >>= 52; VERIFY_BITS(c, 115); VERIFY_BITS(d, 62); /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[2] = c & M; c >>= 52; VERIFY_BITS(r[2], 52); VERIFY_BITS(c, 63); /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += d * R + t3; VERIFY_BITS(c, 100); /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[3] = c & M; c >>= 52; VERIFY_BITS(r[3], 52); VERIFY_BITS(c, 48); /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ c += t4; VERIFY_BITS(c, 49); /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ r[4] = c; VERIFY_BITS(r[4], 49); /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } #endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h index 18e4d2f30..7ebb6d758 100644 --- a/src/secp256k1/src/field_impl.h +++ b/src/secp256k1/src/field_impl.h @@ -1,320 +1,320 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_FIELD_IMPL_H #define SECP256K1_FIELD_IMPL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #include "util.h" #include "num.h" #if defined(SECP256K1_WIDEMUL_INT128) #include "field_5x52_impl.h" #elif defined(SECP256K1_WIDEMUL_INT64) #include "field_10x26_impl.h" #else #error "Please select wide multiplication implementation" #endif SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { secp256k1_fe na; secp256k1_fe_negate(&na, a, 1); secp256k1_fe_add(&na, b); return secp256k1_fe_normalizes_to_zero(&na); } SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) { secp256k1_fe na; secp256k1_fe_negate(&na, a, 1); secp256k1_fe_add(&na, b); return secp256k1_fe_normalizes_to_zero_var(&na); } static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) { /** Given that p is congruent to 3 mod 4, we can compute the square root of * a mod p as the (p+1)/4'th power of a. * * As (p+1)/4 is an even number, it will have the same result for a and for * (-a). Only one of these two numbers actually has a square root however, * so we test at the end by squaring and comparing to the input. * Also because (p+1)/4 is an even number, the computed square root is * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). */ secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; int j; VERIFY_CHECK(r != a); /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] */ secp256k1_fe_sqr(&x2, a); secp256k1_fe_mul(&x2, &x2, a); secp256k1_fe_sqr(&x3, &x2); secp256k1_fe_mul(&x3, &x3, a); x6 = x3; for (j=0; j<3; j++) { secp256k1_fe_sqr(&x6, &x6); } secp256k1_fe_mul(&x6, &x6, &x3); x9 = x6; for (j=0; j<3; j++) { secp256k1_fe_sqr(&x9, &x9); } secp256k1_fe_mul(&x9, &x9, &x3); x11 = x9; for (j=0; j<2; j++) { secp256k1_fe_sqr(&x11, &x11); } secp256k1_fe_mul(&x11, &x11, &x2); x22 = x11; for (j=0; j<11; j++) { secp256k1_fe_sqr(&x22, &x22); } secp256k1_fe_mul(&x22, &x22, &x11); x44 = x22; for (j=0; j<22; j++) { secp256k1_fe_sqr(&x44, &x44); } secp256k1_fe_mul(&x44, &x44, &x22); x88 = x44; for (j=0; j<44; j++) { secp256k1_fe_sqr(&x88, &x88); } secp256k1_fe_mul(&x88, &x88, &x44); x176 = x88; for (j=0; j<88; j++) { secp256k1_fe_sqr(&x176, &x176); } secp256k1_fe_mul(&x176, &x176, &x88); x220 = x176; for (j=0; j<44; j++) { secp256k1_fe_sqr(&x220, &x220); } secp256k1_fe_mul(&x220, &x220, &x44); x223 = x220; for (j=0; j<3; j++) { secp256k1_fe_sqr(&x223, &x223); } secp256k1_fe_mul(&x223, &x223, &x3); /* The final result is then assembled using a sliding window over the blocks. */ t1 = x223; for (j=0; j<23; j++) { secp256k1_fe_sqr(&t1, &t1); } secp256k1_fe_mul(&t1, &t1, &x22); for (j=0; j<6; j++) { secp256k1_fe_sqr(&t1, &t1); } secp256k1_fe_mul(&t1, &t1, &x2); secp256k1_fe_sqr(&t1, &t1); secp256k1_fe_sqr(r, &t1); /* Check that a square root was actually calculated */ secp256k1_fe_sqr(&t1, r); return secp256k1_fe_equal(&t1, a); } static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) { secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; int j; /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] */ secp256k1_fe_sqr(&x2, a); secp256k1_fe_mul(&x2, &x2, a); secp256k1_fe_sqr(&x3, &x2); secp256k1_fe_mul(&x3, &x3, a); x6 = x3; for (j=0; j<3; j++) { secp256k1_fe_sqr(&x6, &x6); } secp256k1_fe_mul(&x6, &x6, &x3); x9 = x6; for (j=0; j<3; j++) { secp256k1_fe_sqr(&x9, &x9); } secp256k1_fe_mul(&x9, &x9, &x3); x11 = x9; for (j=0; j<2; j++) { secp256k1_fe_sqr(&x11, &x11); } secp256k1_fe_mul(&x11, &x11, &x2); x22 = x11; for (j=0; j<11; j++) { secp256k1_fe_sqr(&x22, &x22); } secp256k1_fe_mul(&x22, &x22, &x11); x44 = x22; for (j=0; j<22; j++) { secp256k1_fe_sqr(&x44, &x44); } secp256k1_fe_mul(&x44, &x44, &x22); x88 = x44; for (j=0; j<44; j++) { secp256k1_fe_sqr(&x88, &x88); } secp256k1_fe_mul(&x88, &x88, &x44); x176 = x88; for (j=0; j<88; j++) { secp256k1_fe_sqr(&x176, &x176); } secp256k1_fe_mul(&x176, &x176, &x88); x220 = x176; for (j=0; j<44; j++) { secp256k1_fe_sqr(&x220, &x220); } secp256k1_fe_mul(&x220, &x220, &x44); x223 = x220; for (j=0; j<3; j++) { secp256k1_fe_sqr(&x223, &x223); } secp256k1_fe_mul(&x223, &x223, &x3); /* The final result is then assembled using a sliding window over the blocks. */ t1 = x223; for (j=0; j<23; j++) { secp256k1_fe_sqr(&t1, &t1); } secp256k1_fe_mul(&t1, &t1, &x22); for (j=0; j<5; j++) { secp256k1_fe_sqr(&t1, &t1); } secp256k1_fe_mul(&t1, &t1, a); for (j=0; j<3; j++) { secp256k1_fe_sqr(&t1, &t1); } secp256k1_fe_mul(&t1, &t1, &x2); for (j=0; j<2; j++) { secp256k1_fe_sqr(&t1, &t1); } secp256k1_fe_mul(r, a, &t1); } static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) { #if defined(USE_FIELD_INV_BUILTIN) secp256k1_fe_inv(r, a); #elif defined(USE_FIELD_INV_NUM) secp256k1_num n, m; static const secp256k1_fe negone = SECP256K1_FE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xFFFFFC2EUL ); /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ static const unsigned char prime[32] = { 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,0x2F }; unsigned char b[32]; int res; secp256k1_fe c = *a; secp256k1_fe_normalize_var(&c); secp256k1_fe_get_b32(b, &c); secp256k1_num_set_bin(&n, b, 32); secp256k1_num_set_bin(&m, prime, 32); secp256k1_num_mod_inverse(&n, &n, &m); secp256k1_num_get_bin(b, 32, &n); res = secp256k1_fe_set_b32(r, b); (void)res; VERIFY_CHECK(res); /* Verify the result is the (unique) valid inverse using non-GMP code. */ secp256k1_fe_mul(&c, &c, r); secp256k1_fe_add(&c, &negone); CHECK(secp256k1_fe_normalizes_to_zero_var(&c)); #else #error "Please select field inverse implementation" #endif } static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len) { secp256k1_fe u; size_t i; if (len < 1) { return; } VERIFY_CHECK((r + len <= a) || (a + len <= r)); r[0] = a[0]; i = 0; while (++i < len) { secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]); } secp256k1_fe_inv_var(&u, &r[--i]); while (i > 0) { size_t j = i--; secp256k1_fe_mul(&r[j], &r[i], &u); secp256k1_fe_mul(&u, &u, &a[j]); } r[0] = u; } static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) { #ifndef USE_NUM_NONE unsigned char b[32]; secp256k1_num n; secp256k1_num m; /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ static const unsigned char prime[32] = { 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,0x2F }; secp256k1_fe c = *a; secp256k1_fe_normalize_var(&c); secp256k1_fe_get_b32(b, &c); secp256k1_num_set_bin(&n, b, 32); secp256k1_num_set_bin(&m, prime, 32); return secp256k1_num_jacobi(&n, &m) >= 0; #else secp256k1_fe r; return secp256k1_fe_sqrt(&r, a); #endif } static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); #endif /* SECP256K1_FIELD_IMPL_H */ diff --git a/src/secp256k1/src/gen_context.c b/src/secp256k1/src/gen_context.c index 97d15c0b2..541d90370 100644 --- a/src/secp256k1/src/gen_context.c +++ b/src/secp256k1/src/gen_context.c @@ -1,88 +1,88 @@ -/********************************************************************** - * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ /* Autotools creates libsecp256k1-config.h, of which ECMULT_GEN_PREC_BITS is needed. */ /* ifndef guard so downstream users can define their own if they do not use autotools. */ #if !defined(ECMULT_GEN_PREC_BITS) #include "libsecp256k1-config.h" #endif #define USE_BASIC_CONFIG 1 #include "basic-config.h" #include "include/secp256k1.h" #include "assumptions.h" #include "util.h" #include "field_impl.h" #include "scalar_impl.h" #include "group_impl.h" #include "ecmult_gen_impl.h" 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 }; int main(int argc, char **argv) { secp256k1_ecmult_gen_context ctx; void *prealloc, *base; int inner; int outer; FILE* fp; (void)argc; (void)argv; fp = fopen("src/ecmult_static_context.h","w"); if (fp == NULL) { fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n"); return -1; } fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); fprintf(fp, "#include \"src/group.h\"\n"); fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); fprintf(fp, "#if ECMULT_GEN_PREC_N != %d || ECMULT_GEN_PREC_G != %d\n", ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G); fprintf(fp, " #error configuration mismatch, invalid ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G. Try deleting ecmult_static_context.h before the build.\n"); fprintf(fp, "#endif\n"); fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G] = {\n"); base = checked_malloc(&default_error_callback, SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE); prealloc = base; secp256k1_ecmult_gen_context_init(&ctx); secp256k1_ecmult_gen_context_build(&ctx, &prealloc); for(outer = 0; outer != ECMULT_GEN_PREC_N; outer++) { fprintf(fp,"{\n"); for(inner = 0; inner != ECMULT_GEN_PREC_G; inner++) { fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner])); if (inner != ECMULT_GEN_PREC_G - 1) { fprintf(fp,",\n"); } else { fprintf(fp,"\n"); } } if (outer != ECMULT_GEN_PREC_N - 1) { fprintf(fp,"},\n"); } else { fprintf(fp,"}\n"); } } fprintf(fp,"};\n"); secp256k1_ecmult_gen_context_clear(&ctx); free(base); fprintf(fp, "#undef SC\n"); fprintf(fp, "#endif\n"); fclose(fp); return 0; } diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h index 36e39ecf0..426c286b7 100644 --- a/src/secp256k1/src/group.h +++ b/src/secp256k1/src/group.h @@ -1,151 +1,151 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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); /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ 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); /** 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. Constant time. */ static void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a); /** Set r equal to the double of a. If rzr is not-NULL this sets *rzr such that 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 this sets *rzr such that 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 this sets *rzr such that 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); /** 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); /** 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. Both *r and *a must be initialized.*/ 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); /** Determine if a point (which is assumed to be on the curve) is in the correct (sub)group of the curve. * * In normal mode, the used group is secp256k1, which has cofactor=1 meaning that every point on the curve is in the * group, and this function returns always true. * * When compiling in exhaustive test mode, a slightly different curve equation is used, leading to a group with a * (very) small subgroup, and that subgroup is what is used for all cryptographic operations. In that mode, this * function checks whether a point that is on the curve is in fact also in that subgroup. */ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge); #endif /* SECP256K1_GROUP_H */ diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h index ce8454230..79177d7d7 100644 --- a/src/secp256k1/src/group_impl.h +++ b/src/secp256k1/src/group_impl.h @@ -1,693 +1,693 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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 exhaustive group test orders and generators are chosen such that: * - The field size is equal to that of secp256k1, so field code is the same. * - The curve equation is of the form y^2=x^3+B for some constant B. * - The subgroup has a generator 2*P, where P.x=1. * - The subgroup has size less than 1000 to permit exhaustive testing. * - The subgroup admits an endomorphism of the form lambda*(x,y) == (beta*x,y). * * These parameters are generated using sage/gen_exhaustive_groups.sage. */ #if defined(EXHAUSTIVE_TEST_ORDER) # if EXHAUSTIVE_TEST_ORDER == 13 static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( 0xc3459c3d, 0x35326167, 0xcd86cce8, 0x07a2417f, 0x5b8bd567, 0xde8538ee, 0x0d507b0c, 0xd128f5bb, 0x8e467fec, 0xcd30000a, 0x6cc1184e, 0x25d382c2, 0xa2f4494e, 0x2fbe9abc, 0x8b64abac, 0xd005fb24 ); static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST( 0x3d3486b2, 0x159a9ca5, 0xc75638be, 0xb23a69bc, 0x946a45ab, 0x24801247, 0xb4ed2b8e, 0x26b6a417 ); # elif EXHAUSTIVE_TEST_ORDER == 199 static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( 0x226e653f, 0xc8df7744, 0x9bacbf12, 0x7d1dcbf9, 0x87f05b2a, 0xe7edbd28, 0x1f564575, 0xc48dcf18, 0xa13872c2, 0xe933bb17, 0x5d9ffd5b, 0xb5b6e10c, 0x57fe3c00, 0xbaaaa15a, 0xe003ec3e, 0x9c269bae ); static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST( 0x2cca28fa, 0xfc614b80, 0x2a3db42b, 0x00ba00b1, 0xbea8d943, 0xdace9ab2, 0x9536daea, 0x0074defb ); # 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 ); static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 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) { secp256k1_fe u; size_t i; size_t last_i = SIZE_MAX; for (i = 0; i < len; i++) { if (!a[i].infinity) { /* Use destination's x coordinates as scratch space */ if (last_i == SIZE_MAX) { r[i].x = a[i].z; } else { secp256k1_fe_mul(&r[i].x, &r[last_i].x, &a[i].z); } last_i = i; } } if (last_i == SIZE_MAX) { return; } secp256k1_fe_inv_var(&u, &r[last_i].x); i = last_i; while (i > 0) { i--; if (!a[i].infinity) { secp256k1_fe_mul(&r[last_i].x, &r[i].x, &u); secp256k1_fe_mul(&u, &u, &a[last_i].z); last_i = i; } } VERIFY_CHECK(!a[last_i].infinity); r[last_i].x = u; 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], &r[i].x); } } } 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; /* Ensure all y values are in weak normal form for fast negation of points */ secp256k1_fe_normalize_weak(&r[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; r->x = *x; secp256k1_fe_sqr(&x2, x); secp256k1_fe_mul(&x3, x, &x2); r->infinity = 0; secp256k1_fe_add(&x3, &secp256k1_fe_const_b); return secp256k1_fe_sqrt(&r->y, &x3); } 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_ge_is_valid_var(const secp256k1_ge *a) { secp256k1_fe y2, x3; 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_add(&x3, &secp256k1_fe_const_b); secp256k1_fe_normalize_weak(&x3); return secp256k1_fe_equal_var(&y2, &x3); } static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a) { /* 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; r->infinity = a->infinity; 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 void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { /** 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). */ if (a->infinity) { r->infinity = 1; 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_gej_double(r, a); } 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); } secp256k1_gej_set_infinity(r); } 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); } secp256k1_gej_set_infinity(r); } 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 { secp256k1_gej_set_infinity(r); } 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); } 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); } 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); } static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) { #ifdef EXHAUSTIVE_TEST_ORDER secp256k1_gej out; int i; /* A very simple EC multiplication ladder that avoids a dependency on ecmult. */ secp256k1_gej_set_infinity(&out); for (i = 0; i < 32; ++i) { secp256k1_gej_double_var(&out, &out, NULL); if ((((uint32_t)EXHAUSTIVE_TEST_ORDER) >> (31 - i)) & 1) { secp256k1_gej_add_ge_var(&out, &out, ge, NULL); } } return secp256k1_gej_is_infinity(&out); #else (void)ge; /* The real secp256k1 group has cofactor 1, so the subgroup is the entire curve. */ return 1; #endif } #endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/src/secp256k1/src/hash.h b/src/secp256k1/src/hash.h index de26e4b89..0947a0969 100644 --- a/src/secp256k1/src/hash.h +++ b/src/secp256k1/src/hash.h @@ -1,41 +1,41 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_HASH_H #define SECP256K1_HASH_H #include #include typedef struct { uint32_t s[8]; uint32_t buf[16]; /* In big endian */ size_t bytes; } secp256k1_sha256; static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); typedef struct { secp256k1_sha256 inner, outer; } secp256k1_hmac_sha256; static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); typedef struct { unsigned char v[32]; unsigned char k[32]; int retry; } secp256k1_rfc6979_hmac_sha256; static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); #endif /* SECP256K1_HASH_H */ diff --git a/src/secp256k1/src/hash_impl.h b/src/secp256k1/src/hash_impl.h index 409772587..f8cd3a163 100644 --- a/src/secp256k1/src/hash_impl.h +++ b/src/secp256k1/src/hash_impl.h @@ -1,297 +1,297 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_HASH_IMPL_H #define SECP256K1_HASH_IMPL_H #include "hash.h" #include "util.h" #include #include #include #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) #define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) #define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) #define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) #define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) #define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) #define Round(a,b,c,d,e,f,g,h,k,w) do { \ uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ (d) += t1; \ (h) = t1 + t2; \ } while(0) #if defined(SECP256K1_BIG_ENDIAN) #define BE32(x) (x) #elif defined(SECP256K1_LITTLE_ENDIAN) #define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) #endif static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { hash->s[0] = 0x6a09e667ul; hash->s[1] = 0xbb67ae85ul; hash->s[2] = 0x3c6ef372ul; hash->s[3] = 0xa54ff53aul; hash->s[4] = 0x510e527ful; hash->s[5] = 0x9b05688cul; hash->s[6] = 0x1f83d9abul; hash->s[7] = 0x5be0cd19ul; hash->bytes = 0; } /** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0])); Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1])); Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2])); Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3])); Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4])); Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5])); Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6])); Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7])); Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8])); Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9])); Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10])); Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11])); Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12])); Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13])); Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14])); Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15])); Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); s[0] += a; s[1] += b; s[2] += c; s[3] += d; s[4] += e; s[5] += f; s[6] += g; s[7] += h; } static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { size_t bufsize = hash->bytes & 0x3F; hash->bytes += len; VERIFY_CHECK(hash->bytes >= len); while (len >= 64 - bufsize) { /* Fill the buffer, and process it. */ size_t chunk_len = 64 - bufsize; memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len); data += chunk_len; len -= chunk_len; secp256k1_sha256_transform(hash->s, hash->buf); bufsize = 0; } if (len) { /* Fill the buffer with what remains. */ memcpy(((unsigned char*)hash->buf) + bufsize, data, len); } } static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) { static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint32_t sizedesc[2]; uint32_t out[8]; int i = 0; sizedesc[0] = BE32(hash->bytes >> 29); sizedesc[1] = BE32(hash->bytes << 3); secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8); for (i = 0; i < 8; i++) { out[i] = BE32(hash->s[i]); hash->s[i] = 0; } memcpy(out32, (const unsigned char*)out, 32); } /* Initializes a sha256 struct and writes the 64 byte string * SHA256(tag)||SHA256(tag) into it. */ static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen) { unsigned char buf[32]; secp256k1_sha256_initialize(hash); secp256k1_sha256_write(hash, tag, taglen); secp256k1_sha256_finalize(hash, buf); secp256k1_sha256_initialize(hash); secp256k1_sha256_write(hash, buf, 32); secp256k1_sha256_write(hash, buf, 32); } static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { size_t n; unsigned char rkey[64]; if (keylen <= sizeof(rkey)) { memcpy(rkey, key, keylen); memset(rkey + keylen, 0, sizeof(rkey) - keylen); } else { secp256k1_sha256 sha256; secp256k1_sha256_initialize(&sha256); secp256k1_sha256_write(&sha256, key, keylen); secp256k1_sha256_finalize(&sha256, rkey); memset(rkey + 32, 0, 32); } secp256k1_sha256_initialize(&hash->outer); for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c; } secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey)); secp256k1_sha256_initialize(&hash->inner); for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c ^ 0x36; } secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); memset(rkey, 0, sizeof(rkey)); } static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { secp256k1_sha256_write(&hash->inner, data, size); } static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) { unsigned char temp[32]; secp256k1_sha256_finalize(&hash->inner, temp); secp256k1_sha256_write(&hash->outer, temp, 32); memset(temp, 0, 32); secp256k1_sha256_finalize(&hash->outer, out32); } static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { secp256k1_hmac_sha256 hmac; static const unsigned char zero[1] = {0x00}; static const unsigned char one[1] = {0x01}; memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */ memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ /* RFC6979 3.2.d. */ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, zero, 1); secp256k1_hmac_sha256_write(&hmac, key, keylen); secp256k1_hmac_sha256_finalize(&hmac, rng->k); secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); /* RFC6979 3.2.f. */ secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, one, 1); secp256k1_hmac_sha256_write(&hmac, key, keylen); secp256k1_hmac_sha256_finalize(&hmac, rng->k); secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); rng->retry = 0; } static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { /* RFC6979 3.2.h. */ static const unsigned char zero[1] = {0x00}; if (rng->retry) { secp256k1_hmac_sha256 hmac; secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_write(&hmac, zero, 1); secp256k1_hmac_sha256_finalize(&hmac, rng->k); secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); } while (outlen > 0) { secp256k1_hmac_sha256 hmac; int now = outlen; secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); if (now > 32) { now = 32; } memcpy(out, rng->v, now); out += now; outlen -= now; } rng->retry = 1; } static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) { memset(rng->k, 0, 32); memset(rng->v, 0, 32); rng->retry = 0; } #undef BE32 #undef Round #undef sigma1 #undef sigma0 #undef Sigma1 #undef Sigma0 #undef Maj #undef Ch #endif /* SECP256K1_HASH_IMPL_H */ diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java index 4b328432d..386fe8c4d 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -1,514 +1,514 @@ /* * Copyright 2013 Google Inc. * Copyright 2014-2016 the libsecp256k1 contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bitcoin; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.math.BigInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import static org.bitcoin.NativeSecp256k1Util.*; /** *

This class holds native methods to handle ECDSA verification.

* *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

* *

To build secp256k1 for use with bitcoinj, run * `./configure --enable-jni --enable-experimental --enable-module-ecdh` * and `make` then copy `.libs/libsecp256k1.so` to your system library path * or point the JVM to the folder containing it with -Djava.library.path *

*/ public class NativeSecp256k1 { private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private static final Lock r = rwl.readLock(); private static final Lock w = rwl.writeLock(); private static ThreadLocal nativeByteBuffer = new ThreadLocal(); /** * Verifies the given secp256k1 signature in native code. * Calling when enabled == false is undefined (probably library not loaded) * * @param data The data which was signed, must be exactly 32 bytes * @param signature The signature * @param pub The public key which did the signing */ public static boolean verify(byte[] data, byte[] signature, byte[] pub) { checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < 520) { byteBuff = ByteBuffer.allocateDirect(520); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(data); byteBuff.put(signature); byteBuff.put(pub); r.lock(); try { return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1; } finally { r.unlock(); } } /** * libsecp256k1 Create an ECDSA signature. * * @param data Message hash, 32 bytes * @param key Secret key, 32 bytes * * Return values * @param sig byte array of signature */ public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ checkArgument(data.length == 32 && sec.length <= 32); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < 32 + 32) { byteBuff = ByteBuffer.allocateDirect(32 + 32); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(data); byteBuff.put(sec); byte[][] retByteArray; r.lock(); try { retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); } finally { r.unlock(); } byte[] sigArr = retByteArray[0]; int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); assertEquals(sigArr.length, sigLen, "Got bad signature length."); return retVal == 0 ? new byte[0] : sigArr; } /** * libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid * * @param seckey ECDSA Secret key, 32 bytes */ public static boolean secKeyVerify(byte[] seckey) { checkArgument(seckey.length == 32); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < seckey.length) { byteBuff = ByteBuffer.allocateDirect(seckey.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(seckey); r.lock(); try { return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; } finally { r.unlock(); } } /** * libsecp256k1 Compute Pubkey - computes public key from secret key * * @param seckey ECDSA Secret key, 32 bytes * * Return values * @param pubkey ECDSA Public key, 33 or 65 bytes */ //TODO add a 'compressed' arg public static byte[] computePubkey(byte[] seckey) throws AssertFailException{ checkArgument(seckey.length == 32); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < seckey.length) { byteBuff = ByteBuffer.allocateDirect(seckey.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(seckey); byte[][] retByteArray; r.lock(); try { retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); } finally { r.unlock(); } byte[] pubArr = retByteArray[0]; int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); return retVal == 0 ? new byte[0]: pubArr; } /** * libsecp256k1 Cleanup - This destroys the secp256k1 context object * This should be called at the end of the program for proper cleanup of the context. */ public static synchronized void cleanup() { w.lock(); try { secp256k1_destroy_context(Secp256k1Context.getContext()); } finally { w.unlock(); } } public static long cloneContext() { r.lock(); try { return secp256k1_ctx_clone(Secp256k1Context.getContext()); } finally { r.unlock(); } } /** * libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it * * @param tweak some bytes to tweak with * @param seckey 32-byte seckey */ public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ checkArgument(privkey.length == 32); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(privkey); byteBuff.put(tweak); byte[][] retByteArray; r.lock(); try { retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); } finally { r.unlock(); } byte[] privArr = retByteArray[0]; int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); assertEquals(privArr.length, privLen, "Got bad pubkey length."); assertEquals(retVal, 1, "Failed return value check."); return privArr; } /** * libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it * * @param tweak some bytes to tweak with * @param seckey 32-byte seckey */ public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ checkArgument(privkey.length == 32); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(privkey); byteBuff.put(tweak); byte[][] retByteArray; r.lock(); try { retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); } finally { r.unlock(); } byte[] privArr = retByteArray[0]; int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); assertEquals(privArr.length, privLen, "Got bad pubkey length."); assertEquals(retVal, 1, "Failed return value check."); return privArr; } /** * libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it * * @param tweak some bytes to tweak with * @param pubkey 32-byte seckey */ public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ checkArgument(pubkey.length == 33 || pubkey.length == 65); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(pubkey); byteBuff.put(tweak); byte[][] retByteArray; r.lock(); try { retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length); } finally { r.unlock(); } byte[] pubArr = retByteArray[0]; int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); assertEquals(retVal, 1, "Failed return value check."); return pubArr; } /** * libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it * * @param tweak some bytes to tweak with * @param pubkey 32-byte seckey */ public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ checkArgument(pubkey.length == 33 || pubkey.length == 65); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(pubkey); byteBuff.put(tweak); byte[][] retByteArray; r.lock(); try { retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length); } finally { r.unlock(); } byte[] pubArr = retByteArray[0]; int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); assertEquals(retVal, 1, "Failed return value check."); return pubArr; } /** * libsecp256k1 create ECDH secret - constant time ECDH calculation * * @param seckey byte array of secret key used in exponentiaion * @param pubkey byte array of public key used in exponentiaion */ public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ checkArgument(seckey.length <= 32 && pubkey.length <= 65); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) { byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(seckey); byteBuff.put(pubkey); byte[][] retByteArray; r.lock(); try { retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); } finally { r.unlock(); } byte[] resArr = retByteArray[0]; int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); assertEquals(resArr.length, 32, "Got bad result length."); assertEquals(retVal, 1, "Failed return value check."); return resArr; } /** * libsecp256k1 randomize - updates the context randomization * * @param seed 32-byte random seed */ public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ checkArgument(seed.length == 32 || seed == null); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < seed.length) { byteBuff = ByteBuffer.allocateDirect(seed.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(seed); w.lock(); try { return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; } finally { w.unlock(); } } /** * libsecp256k1 Create a Schnorr signature. * * @param data Message hash, 32 bytes * @param seckey Secret key, 32 bytes * @return sig byte array of signature */ public static byte[] schnorrSign(byte[] data, byte[] seckey) throws AssertFailException { checkArgument(data.length == 32 && seckey.length <= 32); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < data.length + seckey.length) { byteBuff = ByteBuffer.allocateDirect(32 + 32); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(data); byteBuff.put(seckey); byte[][] retByteArray; r.lock(); try { retByteArray = secp256k1_schnorr_sign(byteBuff, Secp256k1Context.getContext()); } finally { r.unlock(); } byte[] sigArr = retByteArray[0]; int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); assertEquals(sigArr.length, 64, "Got bad signature length."); return retVal == 0 ? new byte[0] : sigArr; } /** * Verifies the given Schnorr signature in native code. * Calling when enabled == false is undefined (probably library not loaded) * * @param data The data which was signed, must be exactly 32 bytes * @param signature The signature is exactly 64 bytes * @param pub The public key which did the signing which is the same ECDSA */ public static boolean schnorrVerify(byte[] data, byte[] signature, byte[] pub) { checkArgument(data.length == 32 && signature.length == 64 && (pub.length == 33 || pub.length == 65)); ByteBuffer byteBuff = nativeByteBuffer.get(); if (byteBuff == null || byteBuff.capacity() < 32 + 64 + pub.length) { byteBuff = ByteBuffer.allocateDirect(32 + 64 + pub.length); byteBuff.order(ByteOrder.nativeOrder()); nativeByteBuffer.set(byteBuff); } byteBuff.rewind(); byteBuff.put(data); byteBuff.put(signature); byteBuff.put(pub); r.lock(); try { return secp256k1_schnorr_verify(byteBuff, Secp256k1Context.getContext(), pub.length) == 1; } finally { r.unlock(); } } private static native long secp256k1_ctx_clone(long context); private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context); private static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context); private static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context); private static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen); private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen); private static native void secp256k1_destroy_context(long context); private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen); private static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context); private static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context); private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context); private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); private static native int secp256k1_schnorr_verify(ByteBuffer byteBuff, long context, int pubLen); private static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context); private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); } diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java index 54c6fcc5b..00bfb4db1 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java @@ -1,51 +1,51 @@ /* * Copyright 2014-2016 the libsecp256k1 contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bitcoin; public class NativeSecp256k1Util{ public static void assertEquals( int val, int val2, String message ) throws AssertFailException{ if( val != val2 ) throw new AssertFailException("FAIL: " + message); } public static void assertEquals( boolean val, boolean val2, String message ) throws AssertFailException{ if( val != val2 ) throw new AssertFailException("FAIL: " + message); else System.out.println("PASS: " + message); } public static void assertEquals( String val, String val2, String message ) throws AssertFailException{ if( !val.equals(val2) ) throw new AssertFailException("FAIL: " + message); else System.out.println("PASS: " + message); } public static void checkArgument(boolean expression) { if (!expression) { throw new IllegalArgumentException(); } } public static class AssertFailException extends Exception { public AssertFailException(String message) { super( message ); } } } diff --git a/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java b/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java index 5c615bb4c..06857fb9b 100644 --- a/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java +++ b/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java @@ -1,51 +1,51 @@ /* * Copyright 2014-2016 the libsecp256k1 contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bitcoin; /** * This class holds the context reference used in native methods * to handle ECDSA operations. */ public class Secp256k1Context { private static final boolean enabled; //true if the library is loaded private static final long context; //ref to pointer to context obj static { //static initializer boolean isEnabled = true; long contextRef = -1; try { System.loadLibrary("secp256k1_jni"); contextRef = secp256k1_init_context(); } catch (UnsatisfiedLinkError e) { System.out.println("UnsatisfiedLinkError: " + e.toString()); isEnabled = false; } enabled = isEnabled; context = contextRef; } public static boolean isEnabled() { return enabled; } public static long getContext() { if(!enabled) return -1; //sanity check return context; } private static native long secp256k1_init_context(); } diff --git a/src/secp256k1/src/modules/ecdh/main_impl.h b/src/secp256k1/src/modules/ecdh/main_impl.h index 07a25b80d..1ac67086b 100644 --- a/src/secp256k1/src/modules/ecdh/main_impl.h +++ b/src/secp256k1/src/modules/ecdh/main_impl.h @@ -1,71 +1,71 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_MODULE_ECDH_MAIN_H #define SECP256K1_MODULE_ECDH_MAIN_H #include "include/secp256k1_ecdh.h" #include "ecmult_const_impl.h" static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { unsigned char version = (y32[31] & 0x01) | 0x02; secp256k1_sha256 sha; (void)data; secp256k1_sha256_initialize(&sha); secp256k1_sha256_write(&sha, &version, 1); secp256k1_sha256_write(&sha, x32, 32); secp256k1_sha256_finalize(&sha, output); return 1; } const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256 = ecdh_hash_function_sha256; const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default = ecdh_hash_function_sha256; int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const secp256k1_pubkey *point, const unsigned char *scalar, secp256k1_ecdh_hash_function hashfp, void *data) { int ret = 0; int overflow = 0; secp256k1_gej res; secp256k1_ge pt; secp256k1_scalar s; unsigned char x[32]; unsigned char y[32]; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output != NULL); ARG_CHECK(point != NULL); ARG_CHECK(scalar != NULL); if (hashfp == NULL) { hashfp = secp256k1_ecdh_hash_function_default; } secp256k1_pubkey_load(ctx, &pt, point); secp256k1_scalar_set_b32(&s, scalar, &overflow); overflow |= secp256k1_scalar_is_zero(&s); secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow); secp256k1_ecmult_const(&res, &pt, &s, 256); secp256k1_ge_set_gej(&pt, &res); /* Compute a hash of the point */ secp256k1_fe_normalize(&pt.x); secp256k1_fe_normalize(&pt.y); secp256k1_fe_get_b32(x, &pt.x); secp256k1_fe_get_b32(y, &pt.y); ret = hashfp(output, x, y, data); memset(x, 0, 32); memset(y, 0, 32); secp256k1_scalar_clear(&s); return !!ret & !overflow; } #endif /* SECP256K1_MODULE_ECDH_MAIN_H */ diff --git a/src/secp256k1/src/modules/ecdh/tests_impl.h b/src/secp256k1/src/modules/ecdh/tests_impl.h index e8d2aeab9..be07447a4 100644 --- a/src/secp256k1/src/modules/ecdh/tests_impl.h +++ b/src/secp256k1/src/modules/ecdh/tests_impl.h @@ -1,132 +1,132 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_MODULE_ECDH_TESTS_H #define SECP256K1_MODULE_ECDH_TESTS_H int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { (void)output; (void)x; (void)y; (void)data; return 0; } int ecdh_hash_function_custom(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { (void)data; /* Save x and y as uncompressed public key */ output[0] = 0x04; memcpy(output + 1, x, 32); memcpy(output + 33, y, 32); return 1; } void test_ecdh_api(void) { /* Setup context that just counts errors */ secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); secp256k1_pubkey point; unsigned char res[32]; unsigned char s_one[32] = { 0 }; int32_t ecount = 0; s_one[31] = 1; secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1); /* Check all NULLs are detected */ CHECK(secp256k1_ecdh(tctx, res, &point, s_one, NULL, NULL) == 1); CHECK(ecount == 0); CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one, NULL, NULL) == 0); CHECK(ecount == 1); CHECK(secp256k1_ecdh(tctx, res, NULL, s_one, NULL, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_ecdh(tctx, res, &point, NULL, NULL, NULL) == 0); CHECK(ecount == 3); CHECK(secp256k1_ecdh(tctx, res, &point, s_one, NULL, NULL) == 1); CHECK(ecount == 3); /* Cleanup */ secp256k1_context_destroy(tctx); } void test_ecdh_generator_basepoint(void) { unsigned char s_one[32] = { 0 }; secp256k1_pubkey point[2]; int i; s_one[31] = 1; /* Check against pubkey creation when the basepoint is the generator */ for (i = 0; i < 100; ++i) { secp256k1_sha256 sha; unsigned char s_b32[32]; unsigned char output_ecdh[65]; unsigned char output_ser[32]; unsigned char point_ser[65]; size_t point_ser_len = sizeof(point_ser); secp256k1_scalar s; random_scalar_order(&s); secp256k1_scalar_get_b32(s_b32, &s); CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); /* compute using ECDH function with custom hash function */ CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1); /* compute "explicitly" */ CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1); /* compare */ CHECK(secp256k1_memcmp_var(output_ecdh, point_ser, 65) == 0); /* compute using ECDH function with default hash function */ CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32, NULL, NULL) == 1); /* compute "explicitly" */ CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); secp256k1_sha256_initialize(&sha); secp256k1_sha256_write(&sha, point_ser, point_ser_len); secp256k1_sha256_finalize(&sha, output_ser); /* compare */ CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0); } } void test_bad_scalar(void) { unsigned char s_zero[32] = { 0 }; unsigned char s_overflow[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 }; unsigned char s_rand[32] = { 0 }; unsigned char output[32]; secp256k1_scalar rand; secp256k1_pubkey point; /* Create random point */ random_scalar_order(&rand); secp256k1_scalar_get_b32(s_rand, &rand); CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1); /* Try to multiply it by bad values */ CHECK(secp256k1_ecdh(ctx, output, &point, s_zero, NULL, NULL) == 0); CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, NULL, NULL) == 0); /* ...and a good one */ s_overflow[31] -= 1; CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, NULL, NULL) == 1); /* Hash function failure results in ecdh failure */ CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0); } void run_ecdh_tests(void) { test_ecdh_api(); test_ecdh_generator_basepoint(); test_bad_scalar(); } #endif /* SECP256K1_MODULE_ECDH_TESTS_H */ diff --git a/src/secp256k1/src/modules/extrakeys/main_impl.h b/src/secp256k1/src/modules/extrakeys/main_impl.h index e365f92aa..e8beaa3f1 100644 --- a/src/secp256k1/src/modules/extrakeys/main_impl.h +++ b/src/secp256k1/src/modules/extrakeys/main_impl.h @@ -1,251 +1,251 @@ -/********************************************************************** - * Copyright (c) 2020 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2020 Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MODULE_EXTRAKEYS_MAIN_ #define _SECP256K1_MODULE_EXTRAKEYS_MAIN_ #include "include/secp256k1.h" #include "include/secp256k1_extrakeys.h" static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) { return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey); } static SECP256K1_INLINE void secp256k1_xonly_pubkey_save(secp256k1_xonly_pubkey *pubkey, secp256k1_ge *ge) { secp256k1_pubkey_save((secp256k1_pubkey *) pubkey, ge); } int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, const unsigned char *input32) { secp256k1_ge pk; secp256k1_fe x; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(input32 != NULL); if (!secp256k1_fe_set_b32(&x, input32)) { return 0; } if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) { return 0; } if (!secp256k1_ge_is_in_correct_subgroup(&pk)) { return 0; } secp256k1_xonly_pubkey_save(pubkey, &pk); return 1; } int secp256k1_xonly_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output32, const secp256k1_xonly_pubkey *pubkey) { secp256k1_ge pk; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output32 != NULL); memset(output32, 0, 32); ARG_CHECK(pubkey != NULL); if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) { return 0; } secp256k1_fe_get_b32(output32, &pk.x); return 1; } /** Keeps a group element as is if it has an even Y and otherwise negates it. * y_parity is set to 0 in the former case and to 1 in the latter case. * Requires that the coordinates of r are normalized. */ static int secp256k1_extrakeys_ge_even_y(secp256k1_ge *r) { int y_parity = 0; VERIFY_CHECK(!secp256k1_ge_is_infinity(r)); if (secp256k1_fe_is_odd(&r->y)) { secp256k1_fe_negate(&r->y, &r->y, 1); y_parity = 1; } return y_parity; } int secp256k1_xonly_pubkey_from_pubkey(const secp256k1_context* ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, const secp256k1_pubkey *pubkey) { secp256k1_ge pk; int tmp; VERIFY_CHECK(ctx != NULL); ARG_CHECK(xonly_pubkey != NULL); ARG_CHECK(pubkey != NULL); if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { return 0; } tmp = secp256k1_extrakeys_ge_even_y(&pk); if (pk_parity != NULL) { *pk_parity = tmp; } secp256k1_xonly_pubkey_save(xonly_pubkey, &pk); return 1; } int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { secp256k1_ge pk; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output_pubkey != NULL); memset(output_pubkey, 0, sizeof(*output_pubkey)); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(internal_pubkey != NULL); ARG_CHECK(tweak32 != NULL); if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) || !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) { return 0; } secp256k1_pubkey_save(output_pubkey, &pk); return 1; } int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { secp256k1_ge pk; unsigned char pk_expected32[32]; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(internal_pubkey != NULL); ARG_CHECK(tweaked_pubkey32 != NULL); ARG_CHECK(tweak32 != NULL); if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) || !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) { return 0; } secp256k1_fe_normalize_var(&pk.x); secp256k1_fe_normalize_var(&pk.y); secp256k1_fe_get_b32(pk_expected32, &pk.x); return secp256k1_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0 && secp256k1_fe_is_odd(&pk.y) == tweaked_pk_parity; } static void secp256k1_keypair_save(secp256k1_keypair *keypair, const secp256k1_scalar *sk, secp256k1_ge *pk) { secp256k1_scalar_get_b32(&keypair->data[0], sk); secp256k1_pubkey_save((secp256k1_pubkey *)&keypair->data[32], pk); } static int secp256k1_keypair_seckey_load(const secp256k1_context* ctx, secp256k1_scalar *sk, const secp256k1_keypair *keypair) { int ret; ret = secp256k1_scalar_set_b32_seckey(sk, &keypair->data[0]); /* We can declassify ret here because sk is only zero if a keypair function * failed (which zeroes the keypair) and its return value is ignored. */ secp256k1_declassify(ctx, &ret, sizeof(ret)); ARG_CHECK(ret); return ret; } /* Load a keypair into pk and sk (if non-NULL). This function declassifies pk * and ARG_CHECKs that the keypair is not invalid. It always initializes sk and * pk with dummy values. */ static int secp256k1_keypair_load(const secp256k1_context* ctx, secp256k1_scalar *sk, secp256k1_ge *pk, const secp256k1_keypair *keypair) { int ret; const secp256k1_pubkey *pubkey = (const secp256k1_pubkey *)&keypair->data[32]; /* Need to declassify the pubkey because pubkey_load ARG_CHECKs if it's * invalid. */ secp256k1_declassify(ctx, pubkey, sizeof(*pubkey)); ret = secp256k1_pubkey_load(ctx, pk, pubkey); if (sk != NULL) { ret = ret && secp256k1_keypair_seckey_load(ctx, sk, keypair); } if (!ret) { *pk = secp256k1_ge_const_g; if (sk != NULL) { *sk = secp256k1_scalar_one; } } return ret; } int secp256k1_keypair_create(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *seckey32) { secp256k1_scalar sk; secp256k1_ge pk; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(keypair != NULL); memset(keypair, 0, sizeof(*keypair)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(seckey32 != NULL); ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32); secp256k1_keypair_save(keypair, &sk, &pk); secp256k1_memczero(keypair, sizeof(*keypair), !ret); secp256k1_scalar_clear(&sk); return ret; } int secp256k1_keypair_pub(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_keypair *keypair) { VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(keypair != NULL); memcpy(pubkey->data, &keypair->data[32], sizeof(*pubkey)); return 1; } int secp256k1_keypair_xonly_pub(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair) { secp256k1_ge pk; int tmp; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(keypair != NULL); if (!secp256k1_keypair_load(ctx, NULL, &pk, keypair)) { return 0; } tmp = secp256k1_extrakeys_ge_even_y(&pk); if (pk_parity != NULL) { *pk_parity = tmp; } secp256k1_xonly_pubkey_save(pubkey, &pk); return 1; } int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *tweak32) { secp256k1_ge pk; secp256k1_scalar sk; int y_parity; int ret; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(keypair != NULL); ARG_CHECK(tweak32 != NULL); ret = secp256k1_keypair_load(ctx, &sk, &pk, keypair); memset(keypair, 0, sizeof(*keypair)); y_parity = secp256k1_extrakeys_ge_even_y(&pk); if (y_parity == 1) { secp256k1_scalar_negate(&sk, &sk); } ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32); ret &= secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32); secp256k1_declassify(ctx, &ret, sizeof(ret)); if (ret) { secp256k1_keypair_save(keypair, &sk, &pk); } secp256k1_scalar_clear(&sk); return ret; } #endif diff --git a/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h b/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h index 0e29bc6b0..d78c315b7 100644 --- a/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h +++ b/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h @@ -1,68 +1,68 @@ -/********************************************************************** - * Copyright (c) 2020 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2020 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_ #define _SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_ #include "src/modules/extrakeys/main_impl.h" #include "include/secp256k1_extrakeys.h" static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp256k1_ge* group) { secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; secp256k1_pubkey pubkey[EXHAUSTIVE_TEST_ORDER - 1]; secp256k1_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; int parities[EXHAUSTIVE_TEST_ORDER - 1]; unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; int i; for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { secp256k1_fe fe; secp256k1_scalar scalar_i; unsigned char buf[33]; int parity; secp256k1_scalar_set_int(&scalar_i, i); secp256k1_scalar_get_b32(buf, &scalar_i); /* Construct pubkey and keypair. */ CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey[i - 1], buf)); /* Construct serialized xonly_pubkey from keypair. */ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parities[i - 1], &keypair[i - 1])); CHECK(secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); /* Parse the xonly_pubkey back and verify it matches the previously serialized value. */ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1])); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); /* Construct the xonly_pubkey from the pubkey, and verify it matches the same. */ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1])); CHECK(parity == parities[i - 1]); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); /* Compare the xonly_pubkey bytes against the precomputed group. */ secp256k1_fe_set_b32(&fe, xonly_pubkey_bytes[i - 1]); CHECK(secp256k1_fe_equal_var(&fe, &group[i].x)); /* Check the parity against the precomputed group. */ fe = group[i].y; secp256k1_fe_normalize_var(&fe); CHECK(secp256k1_fe_is_odd(&fe) == parities[i - 1]); /* Verify that the higher half is identical to the lower half mirrored. */ if (i > EXHAUSTIVE_TEST_ORDER / 2) { CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0); CHECK(parities[i - 1] == 1 - parities[EXHAUSTIVE_TEST_ORDER - i - 1]); } } /* TODO: keypair/xonly_pubkey tweak tests */ } #endif diff --git a/src/secp256k1/src/modules/extrakeys/tests_impl.h b/src/secp256k1/src/modules/extrakeys/tests_impl.h index 5ee135849..5b15968d8 100644 --- a/src/secp256k1/src/modules/extrakeys/tests_impl.h +++ b/src/secp256k1/src/modules/extrakeys/tests_impl.h @@ -1,524 +1,524 @@ -/********************************************************************** - * Copyright (c) 2020 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2020 Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MODULE_EXTRAKEYS_TESTS_ #define _SECP256K1_MODULE_EXTRAKEYS_TESTS_ #include "secp256k1_extrakeys.h" static secp256k1_context* api_test_context(int flags, int *ecount) { secp256k1_context *ctx0 = secp256k1_context_create(flags); secp256k1_context_set_error_callback(ctx0, counting_illegal_callback_fn, ecount); secp256k1_context_set_illegal_callback(ctx0, counting_illegal_callback_fn, ecount); return ctx0; } void test_xonly_pubkey(void) { secp256k1_pubkey pk; secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; secp256k1_ge pk1; secp256k1_ge pk2; secp256k1_fe y; unsigned char sk[32]; unsigned char xy_sk[32]; unsigned char buf32[32]; unsigned char ones32[32]; unsigned char zeros64[64] = { 0 }; int pk_parity; int i; int ecount; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); secp256k1_testrand256(sk); memset(ones32, 0xFF, 32); secp256k1_testrand256(xy_sk); CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); /* Test xonly_pubkey_from_pubkey */ ecount = 0; CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(sign, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, NULL, &pk_parity, &pk) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, NULL) == 0); CHECK(ecount == 2); memset(&pk, 0, sizeof(pk)); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 0); CHECK(ecount == 3); /* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */ memset(sk, 0, sizeof(sk)); sk[0] = 1; CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_memcmp_var(&pk, &xonly_pk, sizeof(pk)) == 0); CHECK(pk_parity == 0); /* Choose a secret key such that pubkey and xonly_pubkey are each others * negation. */ sk[0] = 2; CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_memcmp_var(&xonly_pk, &pk, sizeof(xonly_pk)) != 0); CHECK(pk_parity == 1); secp256k1_pubkey_load(ctx, &pk1, &pk); secp256k1_pubkey_load(ctx, &pk2, (secp256k1_pubkey *) &xonly_pk); CHECK(secp256k1_fe_equal(&pk1.x, &pk2.x) == 1); secp256k1_fe_negate(&y, &pk2.y, 1); CHECK(secp256k1_fe_equal(&pk1.y, &y) == 1); /* Test xonly_pubkey_serialize and xonly_pubkey_parse */ ecount = 0; CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0); CHECK(secp256k1_memcmp_var(buf32, zeros64, 32) == 0); CHECK(ecount == 2); { /* A pubkey filled with 0s will fail to serialize due to pubkey_load * special casing. */ secp256k1_xonly_pubkey pk_tmp; memset(&pk_tmp, 0, sizeof(pk_tmp)); CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &pk_tmp) == 0); } /* pubkey_load called illegal callback */ CHECK(ecount == 3); CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &xonly_pk) == 1); ecount = 0; CHECK(secp256k1_xonly_pubkey_parse(none, NULL, buf32) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, NULL) == 0); CHECK(ecount == 2); /* Serialization and parse roundtrip */ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk_tmp, buf32) == 1); CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0); /* Test parsing invalid field elements */ memset(&xonly_pk, 1, sizeof(xonly_pk)); /* Overflowing field element */ CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, ones32) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); memset(&xonly_pk, 1, sizeof(xonly_pk)); /* There's no point with x-coordinate 0 on secp256k1 */ CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, zeros64) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); /* If a random 32-byte string can not be parsed with ec_pubkey_parse * (because interpreted as X coordinate it does not correspond to a point on * the curve) then xonly_pubkey_parse should fail as well. */ for (i = 0; i < count; i++) { unsigned char rand33[33]; secp256k1_testrand256(&rand33[1]); rand33[0] = SECP256K1_TAG_PUBKEY_EVEN; if (!secp256k1_ec_pubkey_parse(ctx, &pk, rand33, 33)) { memset(&xonly_pk, 1, sizeof(xonly_pk)); CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); } else { CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 1); } } CHECK(ecount == 2); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } void test_xonly_pubkey_tweak(void) { unsigned char zeros64[64] = { 0 }; unsigned char overflows[32]; unsigned char sk[32]; secp256k1_pubkey internal_pk; secp256k1_xonly_pubkey internal_xonly_pk; secp256k1_pubkey output_pk; int pk_parity; unsigned char tweak[32]; int i; int ecount; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); memset(overflows, 0xff, sizeof(overflows)); secp256k1_testrand256(tweak); secp256k1_testrand256(sk); CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); ecount = 0; CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 2); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 3); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0); CHECK(ecount == 4); /* NULL internal_xonly_pk zeroes the output_pk */ CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0); CHECK(ecount == 5); /* NULL tweak zeroes the output_pk */ CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); /* Invalid tweak zeroes the output_pk */ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); /* A zero tweak is fine */ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1); /* Fails if the resulting key was infinity */ for (i = 0; i < count; i++) { secp256k1_scalar scalar_tweak; /* Because sk may be negated before adding, we need to try with tweak = * sk as well as tweak = -sk. */ secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); secp256k1_scalar_get_b32(tweak, &scalar_tweak); CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0) || (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0)); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); } /* Invalid pk with a valid tweak */ memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk)); secp256k1_testrand256(tweak); ecount = 0; CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } void test_xonly_pubkey_tweak_check(void) { unsigned char zeros64[64] = { 0 }; unsigned char overflows[32]; unsigned char sk[32]; secp256k1_pubkey internal_pk; secp256k1_xonly_pubkey internal_xonly_pk; secp256k1_pubkey output_pk; secp256k1_xonly_pubkey output_xonly_pk; unsigned char output_pk32[32]; unsigned char buf32[32]; int pk_parity; unsigned char tweak[32]; int ecount; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); memset(overflows, 0xff, sizeof(overflows)); secp256k1_testrand256(tweak); secp256k1_testrand256(sk); CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); ecount = 0; CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 2); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 3); /* invalid pk_parity value */ CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 3); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0); CHECK(ecount == 4); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0); CHECK(ecount == 5); memset(tweak, 1, sizeof(tweak)); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &output_xonly_pk, &pk_parity, &output_pk) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk32, &output_xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, tweak) == 1); /* Wrong pk_parity */ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, !pk_parity, &internal_xonly_pk, tweak) == 0); /* Wrong public key */ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &internal_xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); /* Overflowing tweak not allowed */ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(ecount == 5); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } /* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1 * additional pubkeys by calling tweak_add. Then verifies every tweak starting * from the last pubkey. */ #define N_PUBKEYS 32 void test_xonly_pubkey_tweak_recursive(void) { unsigned char sk[32]; secp256k1_pubkey pk[N_PUBKEYS]; unsigned char pk_serialized[32]; unsigned char tweak[N_PUBKEYS - 1][32]; int i; secp256k1_testrand256(sk); CHECK(secp256k1_ec_pubkey_create(ctx, &pk[0], sk) == 1); /* Add tweaks */ for (i = 0; i < N_PUBKEYS - 1; i++) { secp256k1_xonly_pubkey xonly_pk; memset(tweak[i], i + 1, sizeof(tweak[i])); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i]) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &pk[i + 1], &xonly_pk, tweak[i]) == 1); } /* Verify tweaks */ for (i = N_PUBKEYS - 1; i > 0; i--) { secp256k1_xonly_pubkey xonly_pk; int pk_parity; CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk[i]) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk_serialized, &xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i - 1]) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk_serialized, pk_parity, &xonly_pk, tweak[i - 1]) == 1); } } #undef N_PUBKEYS void test_keypair(void) { unsigned char sk[32]; unsigned char zeros96[96] = { 0 }; unsigned char overflows[32]; secp256k1_keypair keypair; secp256k1_pubkey pk, pk_tmp; secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; int pk_parity, pk_parity_tmp; int ecount; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); CHECK(sizeof(zeros96) == sizeof(keypair)); memset(overflows, 0xFF, sizeof(overflows)); /* Test keypair_create */ ecount = 0; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(ecount == 2); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0); CHECK(ecount == 3); CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(ecount == 4); /* Invalid secret key */ CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); /* Test keypair_pub */ ecount = 0; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); CHECK(secp256k1_keypair_pub(none, NULL, &keypair) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); /* Using an invalid keypair is fine for keypair_pub */ memset(&keypair, 0, sizeof(keypair)); CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); /* keypair holds the same pubkey as pubkey_create */ CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1); CHECK(secp256k1_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0); /** Test keypair_xonly_pub **/ ecount = 0; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); CHECK(secp256k1_keypair_xonly_pub(none, NULL, &pk_parity, &keypair) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); /* Using an invalid keypair will set the xonly_pk to 0 (first reset * xonly_pk). */ CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); memset(&keypair, 0, sizeof(keypair)); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0); CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); CHECK(ecount == 3); /** keypair holds the same xonly pubkey as pubkey_create **/ CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1); CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0); CHECK(pk_parity == pk_parity_tmp); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } void test_keypair_add(void) { unsigned char sk[32]; secp256k1_keypair keypair; unsigned char overflows[32]; unsigned char zeros96[96] = { 0 }; unsigned char tweak[32]; int i; int ecount = 0; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); CHECK(sizeof(zeros96) == sizeof(keypair)); secp256k1_testrand256(sk); secp256k1_testrand256(tweak); memset(overflows, 0xFF, 32); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 0); CHECK(ecount == 2); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0); CHECK(ecount == 3); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0); CHECK(ecount == 4); /* This does not set the keypair to zeroes */ CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0); /* Invalid tweak zeroes the keypair */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, overflows) == 0); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); /* A zero tweak is fine */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, zeros96) == 1); /* Fails if the resulting keypair was (sk=0, pk=infinity) */ for (i = 0; i < count; i++) { secp256k1_scalar scalar_tweak; secp256k1_keypair keypair_tmp; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); memcpy(&keypair_tmp, &keypair, sizeof(keypair)); /* Because sk may be negated before adding, we need to try with tweak = * sk as well as tweak = -sk. */ secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); secp256k1_scalar_get_b32(tweak, &scalar_tweak); CHECK((secp256k1_keypair_xonly_tweak_add(ctx, &keypair, sk) == 0) || (secp256k1_keypair_xonly_tweak_add(ctx, &keypair_tmp, tweak) == 0)); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0 || secp256k1_memcmp_var(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0); } /* Invalid keypair with a valid tweak */ memset(&keypair, 0, sizeof(keypair)); secp256k1_testrand256(tweak); ecount = 0; CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); /* Only seckey part of keypair invalid */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); memset(&keypair, 0, 32); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); CHECK(ecount == 2); /* Only pubkey part of keypair invalid */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); memset(&keypair.data[32], 0, 64); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); CHECK(ecount == 3); /* Check that the keypair_tweak_add implementation is correct */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); for (i = 0; i < count; i++) { secp256k1_xonly_pubkey internal_pk; secp256k1_xonly_pubkey output_pk; secp256k1_pubkey output_pk_xy; secp256k1_pubkey output_pk_expected; unsigned char pk32[32]; int pk_parity; secp256k1_testrand256(tweak); CHECK(secp256k1_keypair_xonly_pub(ctx, &internal_pk, NULL, &keypair) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &output_pk, &pk_parity, &keypair) == 1); /* Check that it passes xonly_pubkey_tweak_add_check */ CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk32, &output_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk32, pk_parity, &internal_pk, tweak) == 1); /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */ CHECK(secp256k1_keypair_pub(ctx, &output_pk_xy, &keypair) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk_expected, &internal_pk, tweak) == 1); CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); /* Check that the secret key in the keypair is tweaked correctly */ CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, &keypair.data[0]) == 1); CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); } secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } void run_extrakeys_tests(void) { /* xonly key test cases */ test_xonly_pubkey(); test_xonly_pubkey_tweak(); test_xonly_pubkey_tweak_check(); test_xonly_pubkey_tweak_recursive(); /* keypair tests */ test_keypair(); test_keypair_add(); } #endif diff --git a/src/secp256k1/src/modules/multiset/main_impl.h b/src/secp256k1/src/modules/multiset/main_impl.h index 45f33c64a..13986aeef 100644 --- a/src/secp256k1/src/modules/multiset/main_impl.h +++ b/src/secp256k1/src/modules/multiset/main_impl.h @@ -1,210 +1,210 @@ -/********************************************************************** - * Copyright (c) 2017 Tomas van der Wansem * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Tomas van der Wansem * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MODULE_MULTISET_MAIN_ #define _SECP256K1_MODULE_MULTISET_MAIN_ #include "include/secp256k1_multiset.h" #include "hash.h" #include "field.h" #include "group.h" /** Converts a group element (Jacobian) to a multiset. * Requires the field elements to be normalized * Infinite uses special value, z = 0 */ static void multiset_from_gej_var(secp256k1_multiset *target, const secp256k1_gej *input) { if (input->infinity) { memset(&target->d, 0, sizeof(target->d)); } else { secp256k1_fe_get_b32(target->d, &input->x); secp256k1_fe_get_b32(target->d+32, &input->y); secp256k1_fe_get_b32(target->d+64, &input->z); } } /** Converts a multiset to group element (Jacobian) * Infinite uses special value, z = 0 */ static void gej_from_multiset_var(secp256k1_gej *target, const secp256k1_multiset *input) { secp256k1_fe_set_b32(&target->x, input->d); secp256k1_fe_set_b32(&target->y, input->d+32); secp256k1_fe_set_b32(&target->z, input->d+64); target->infinity = secp256k1_fe_is_zero(&target->z) ? 1 : 0; } /** Converts a data element to a group element (affine) * * We use trial-and-rehash which is fast but non-constant time. * Though constant time algo's exist we are not concerned with timing attacks * as we make no attempt to hide the underlying data * * Pass inverse=0 to generate the group element, or inverse=1 to generate its inverse */ static void ge_from_data_var(secp256k1_ge *target, const unsigned char *input, size_t inputLen, int inverse) { secp256k1_sha256 hasher; unsigned char buffer[8+32]; unsigned char trial[32]; uint64_t prefix; /* Hash to buffer, leaving space for 8-byte prefix */ secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, input, inputLen); secp256k1_sha256_finalize(&hasher, buffer+8); /* Loop through trials, with 50% success per loop * We can assume it ends within 2^64. */ for(prefix=0; 1; prefix++) { secp256k1_fe x; /* Set prefix in little-endian */ buffer[0] = prefix & 0xFF; buffer[1] = (prefix>>8) & 0xFF; buffer[2] = (prefix>>16) & 0xFF; buffer[3] = (prefix>>24) & 0xFF; buffer[4] = (prefix>>32) & 0xFF; buffer[5] = (prefix>>40) & 0xFF; buffer[6] = (prefix>>48) & 0xFF; buffer[7] = (prefix>>56) & 0xFF; /* Hash to trial */ secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, buffer, sizeof(buffer)); secp256k1_sha256_finalize(&hasher, trial); if (!secp256k1_fe_set_b32(&x, trial)) { continue; } /* We let y is even be the element and odd be its inverse */ if (!secp256k1_ge_set_xo_var(target, &x, inverse)) { continue; } VERIFY_CHECK(secp256k1_ge_is_valid_var(target)); VERIFY_CHECK(!secp256k1_ge_is_infinity(target)); break; } } /** Adds or removes a data element */ static int multiset_add_remove(const secp256k1_context* ctx, secp256k1_multiset *multiset, const unsigned char *input, size_t inputLen, int remove) { secp256k1_ge newelm; secp256k1_gej source, target; VERIFY_CHECK(ctx != NULL); ARG_CHECK(multiset != NULL); ARG_CHECK(input != NULL); gej_from_multiset_var(&source, multiset); ge_from_data_var(&newelm, input, inputLen, remove); /* * The `target` group element needs to be initialized. * If the result of the addition is infinity, the field elements won't be * set and the `secp256k1_fe_normalize` calls below will branch on * uninitialized data. */ secp256k1_gej_set_infinity(&target); secp256k1_gej_add_ge_var(&target, &source, &newelm, NULL); secp256k1_fe_normalize(&target.x); secp256k1_fe_normalize(&target.y); secp256k1_fe_normalize(&target.z); multiset_from_gej_var(multiset, &target); return 1; } /** Adds a data element to the multiset */ int secp256k1_multiset_add(const secp256k1_context* ctx, secp256k1_multiset *multiset, const unsigned char *input, size_t inputLen) { return multiset_add_remove(ctx, multiset, input, inputLen, 0); } /** Removes a data element from the multiset */ int secp256k1_multiset_remove(const secp256k1_context* ctx, secp256k1_multiset *multiset, const unsigned char *input, size_t inputLen) { return multiset_add_remove(ctx, multiset, input, inputLen, 1); } /** Adds input multiset to multiset */ int secp256k1_multiset_combine(const secp256k1_context* ctx, secp256k1_multiset *multiset, const secp256k1_multiset *input) { secp256k1_gej gej_multiset, gej_input, gej_result; VERIFY_CHECK(ctx != NULL); ARG_CHECK(multiset != NULL); ARG_CHECK(input != NULL); gej_from_multiset_var(&gej_multiset, multiset); gej_from_multiset_var(&gej_input, input); /* * The `gej_result` group element needs to be initialized. * If the result of the addition is infinity, the field elements won't be * set and the `secp256k1_fe_normalize` calls below will branch on * uninitialized data. */ secp256k1_gej_set_infinity(&gej_result); secp256k1_gej_add_var(&gej_result, &gej_multiset, &gej_input, NULL); secp256k1_fe_normalize(&gej_result.x); secp256k1_fe_normalize(&gej_result.y); secp256k1_fe_normalize(&gej_result.z); multiset_from_gej_var(multiset, &gej_result); return 1; } /** Hash the multiset into resultHash */ int secp256k1_multiset_finalize(const secp256k1_context* ctx, unsigned char *resultHash, const secp256k1_multiset *multiset) { secp256k1_sha256 hasher; unsigned char buffer[64]; secp256k1_gej gej; secp256k1_ge ge; VERIFY_CHECK(ctx != NULL); ARG_CHECK(resultHash != NULL); ARG_CHECK(multiset != NULL); gej_from_multiset_var(&gej, multiset); if (gej.infinity) { /* empty set is encoded as zeros */ memset(resultHash, 0x00, 32); return 1; } /* we must normalize to affine first */ secp256k1_ge_set_gej(&ge, &gej); secp256k1_fe_normalize(&ge.x); secp256k1_fe_normalize(&ge.y); secp256k1_fe_get_b32(buffer, &ge.x); secp256k1_fe_get_b32(buffer+32, &ge.y); secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, buffer, sizeof(buffer)); secp256k1_sha256_finalize(&hasher, resultHash); return 1; } /** Inits the multiset with the constant for empty data, * represented by the Jacobian GE infinite */ int secp256k1_multiset_init(const secp256k1_context* ctx, secp256k1_multiset *multiset) { const secp256k1_gej inf = SECP256K1_GEJ_CONST_INFINITY; VERIFY_CHECK(ctx != NULL); multiset_from_gej_var(multiset, &inf); return 1; } #endif /* _SECP256K1_MODULE_MULTISET_MAIN_ */ diff --git a/src/secp256k1/src/modules/multiset/tests_impl.h b/src/secp256k1/src/modules/multiset/tests_impl.h index adafc8a30..404b268c9 100644 --- a/src/secp256k1/src/modules/multiset/tests_impl.h +++ b/src/secp256k1/src/modules/multiset/tests_impl.h @@ -1,347 +1,347 @@ -/********************************************************************** - * Copyright (c) 2017 Tomas van der Wansem * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Tomas van der Wansem * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MODULE_MULTISET_TESTS_ #define _SECP256K1_MODULE_MULTISET_TESTS_ #include "include/secp256k1.h" #include "include/secp256k1_multiset.h" #include "util.h" #include "testrand.h" #define DATALEN 64*3 #define DATACOUNT 100 #define CHECK_EQUAL(a,b) { \ unsigned char hash1[32]; \ unsigned char hash2[32]; \ secp256k1_multiset_finalize(ctx, hash1, (a)); \ secp256k1_multiset_finalize(ctx, hash2, (b)); \ CHECK(memcmp(hash1,hash2,sizeof(hash1))==0); \ } #define CHECK_NOTEQUAL(a,b) { \ unsigned char hash1[32]; \ unsigned char hash2[32]; \ secp256k1_multiset_finalize(ctx, hash1, (a)); \ secp256k1_multiset_finalize(ctx, hash2, (b)); \ CHECK(memcmp(hash1,hash2,sizeof(hash1))!=0); \ } static unsigned char elements[DATACOUNT][DATALEN]; /* Create random data */ static void initdata(void) { int n,m; for(n=0; n < DATACOUNT; n++) { for(m=0; m < DATALEN/4; m++) { uint32_t x = secp256k1_testrand32(); memcpy(&elements[n][m], &x, sizeof(x)); } } } void test_unordered(void) { /* Check if multisets are uneffected by order */ secp256k1_multiset empty, r1,r2,r3; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[1], DATALEN); CHECK_NOTEQUAL(&r1,&r2); /* M(0,1)!=M() */ secp256k1_multiset_add(ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[0], DATALEN); CHECK_EQUAL(&r1,&r2); /* M(0,1)==M(1,0) */ secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); CHECK_EQUAL(&r1,&r2); /* M()==M() */ secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r1, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[2], DATALEN); CHECK_EQUAL(&r1,&r2); /* M(0,1,2)==M(2,0,1) */ CHECK_EQUAL(&r1,&r3); /* M(0,1,2)==M(1,0,2) */ secp256k1_multiset_combine(ctx, &r3, &empty); CHECK_EQUAL(&r1,&r3); /* M(1,0,2)+M()=M(0,1,2) */ secp256k1_multiset_combine(ctx, &r3, &r2); CHECK_NOTEQUAL(&r1,&r3); /* M(1,0,2)+M(0,1,2)!=M(0,1,2) */ } void test_combine(void) { /* Testing if combining is effectively the same as adding the elements */ secp256k1_multiset empty, r1,r2,r3; secp256k1_gej gej_pos, gej_neg; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[1], DATALEN); CHECK_NOTEQUAL(&r1,&r2); /* M(0) != M(1) */ secp256k1_multiset_add(ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[0], DATALEN); CHECK_EQUAL(&r1,&r2); /* M(1,0) == M(0,1) */ secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); CHECK_EQUAL(&r1,&r2); /* M() == M() */ secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r1, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[1], DATALEN); secp256k1_multiset_combine(ctx, &r2, &r3); CHECK_EQUAL(&r1,&r2); /* M(0,1,2) == M(2)+M(0,1) */ secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add(ctx, &r2, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[1], DATALEN); secp256k1_multiset_combine(ctx, &r2, &r3); CHECK_EQUAL(&r1,&r2); /* M(0,1,2) == M(2,0)+M(1) */ secp256k1_multiset_combine(ctx, &r2, &empty); CHECK_EQUAL(&r1,&r2); /* M(0,1,2)+M() == M(0,1,2) */ secp256k1_multiset_combine(ctx, &r2, &r1); CHECK_NOTEQUAL(&r1,&r2); /* M(0,1,2)+M(0,1,2) != M(0,1,2) */ /* Combine multisets so that the combination representation is infinity */ secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); CHECK_EQUAL(&r1, &r2); /* M() == M() */ secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); gej_from_multiset_var(&gej_pos, &r1); secp256k1_gej_neg(&gej_neg, &gej_pos); secp256k1_fe_normalize(&gej_neg.x); secp256k1_fe_normalize(&gej_neg.y); secp256k1_fe_normalize(&gej_neg.z); multiset_from_gej_var(&r2, &gej_neg); /* This is equivalent to a removal due to multisets being associative */ secp256k1_multiset_combine(ctx, &r1, &r2); CHECK_EQUAL(&empty, &r1); /* M() == M(X)+M(-X) == M(X)-M(X) */ } void test_remove(void) { /* Testing removal of elements */ secp256k1_multiset empty, r1,r2,r3; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); CHECK_EQUAL(&r1,&r2); /* M()==M() */ secp256k1_multiset_add (ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[3], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[9], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[8], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[9], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[11], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[10], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[0], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[10], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[3], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[8], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[11], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[9], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[15], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[15], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[9], DATALEN); secp256k1_multiset_remove(ctx, &r3, elements[15], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[0], DATALEN); secp256k1_multiset_remove(ctx, &r3, elements[15], DATALEN); secp256k1_multiset_remove(ctx, &r3, elements[9], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[3], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[8], DATALEN); CHECK_EQUAL(&r1,&r2); /* M(0,1,3,9,8)==M(1,9,11,10,9,3,8)-M(10,11) */ CHECK_EQUAL(&r1,&r3); /* M(0,1,3,9,8)==M(9,15,15,1,9,0,3,8)-M(15,15,9) */ CHECK_NOTEQUAL(&r1,&empty); /* M(0,1,3,9,8)!=M() */ secp256k1_multiset_remove(ctx, &r3, elements[8], DATALEN); CHECK_NOTEQUAL(&r1,&r3); /* M(0,1,3,9,8)-M(8)!=M(0,1,3,9,8) */ secp256k1_multiset_remove(ctx, &r2, elements[0], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[9], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[8], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[1], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[3], DATALEN); CHECK_EQUAL(&r2,&empty); /* M(0,1,3,9,8)-M(0,1,3,9,8)==M() */ } void test_duplicate(void) { /* Test if the multiset properly handles duplicates */ secp256k1_multiset empty, r1,r2,r3; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add (ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[1], DATALEN); CHECK_NOTEQUAL(&r1, &r2); /* M(0,0,1,1)!=M(0,1) */ secp256k1_multiset_add (ctx, &r2, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[1], DATALEN); CHECK_EQUAL(&r1, &r2); /* M(0,0,1,1)!=M(0,0,1,1) */ secp256k1_multiset_add (ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[1], DATALEN); secp256k1_multiset_combine(ctx, &r2, &r3); CHECK_EQUAL(&r1, &r2); /* M(0,0,0,1,1,1)!=M(0,0,1,1)+M(0,1) */ } void test_empty(void) { /* Test if empty set properties hold */ secp256k1_multiset empty, r1,r2; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); CHECK_EQUAL(&empty,&r1); /* M()==M() */ /* empty + empty = empty */ secp256k1_multiset_combine(ctx, &r1, &r2); CHECK_EQUAL(&empty, &r1); /* M()+M()==M() */ } void test_testvector(void) { /* Tests known values from the specification */ const unsigned char d1[113] = { 0x98,0x20,0x51,0xfd,0x1e,0x4b,0xa7,0x44,0xbb,0xbe,0x68,0x0e,0x1f,0xee,0x14,0x67,0x7b,0xa1,0xa3,0xc3,0x54,0x0b,0xf7,0xb1,0xcd,0xb6,0x06,0xe8,0x57,0x23,0x3e,0x0e, 0x00,0x00,0x00,0x00,0x03,0x00,0xf2,0x05,0x2a,0x01,0x00,0x00,0x00,0x43,0x41,0x04,0x96,0xb5,0x38,0xe8,0x53,0x51,0x9c,0x72,0x6a,0x2c,0x91,0xe6,0x1e,0xc1,0x16,0x00, 0xae,0x13,0x90,0x81,0x3a,0x62,0x7c,0x66,0xfb,0x8b,0xe7,0x94,0x7b,0xe6,0x3c,0x52,0xda,0x75,0x89,0x37,0x95,0x15,0xd4,0xe0,0xa6,0x04,0xf8,0x14,0x17,0x81,0xe6,0x22, 0x94,0x72,0x11,0x66,0xbf,0x62,0x1e,0x73,0xa8,0x2c,0xbf,0x23,0x42,0xc8,0x58,0xee,0xac }; const unsigned char d2[113] = { 0xd5,0xfd,0xcc,0x54,0x1e,0x25,0xde,0x1c,0x7a,0x5a,0xdd,0xed,0xf2,0x48,0x58,0xb8,0xbb,0x66,0x5c,0x9f,0x36,0xef,0x74,0x4e,0xe4,0x2c,0x31,0x60,0x22,0xc9,0x0f,0x9b, 0x00,0x00,0x00,0x00,0x05,0x00,0xf2,0x05,0x2a,0x01,0x00,0x00,0x00,0x43,0x41,0x04,0x72,0x11,0xa8,0x24,0xf5,0x5b,0x50,0x52,0x28,0xe4,0xc3,0xd5,0x19,0x4c,0x1f,0xcf, 0xaa,0x15,0xa4,0x56,0xab,0xdf,0x37,0xf9,0xb9,0xd9,0x7a,0x40,0x40,0xaf,0xc0,0x73,0xde,0xe6,0xc8,0x90,0x64,0x98,0x4f,0x03,0x38,0x52,0x37,0xd9,0x21,0x67,0xc1,0x3e, 0x23,0x64,0x46,0xb4,0x17,0xab,0x79,0xa0,0xfc,0xae,0x41,0x2a,0xe3,0x31,0x6b,0x77,0xac }; const unsigned char d3[113] = { 0x44,0xf6,0x72,0x22,0x60,0x90,0xd8,0x5d,0xb9,0xa9,0xf2,0xfb,0xfe,0x5f,0x0f,0x96,0x09,0xb3,0x87,0xaf,0x7b,0xe5,0xb7,0xfb,0xb7,0xa1,0x76,0x7c,0x83,0x1c,0x9e,0x99, 0x00,0x00,0x00,0x00,0x07,0x00,0xf2,0x05,0x2a,0x01,0x00,0x00,0x00,0x43,0x41,0x04,0x94,0xb9,0xd3,0xe7,0x6c,0x5b,0x16,0x29,0xec,0xf9,0x7f,0xff,0x95,0xd7,0xa4,0xbb, 0xda,0xc8,0x7c,0xc2,0x60,0x99,0xad,0xa2,0x80,0x66,0xc6,0xff,0x1e,0xb9,0x19,0x12,0x23,0xcd,0x89,0x71,0x94,0xa0,0x8d,0x0c,0x27,0x26,0xc5,0x74,0x7f,0x1d,0xb4,0x9e, 0x8c,0xf9,0x0e,0x75,0xdc,0x3e,0x35,0x50,0xae,0x9b,0x30,0x08,0x6f,0x3c,0xd5,0xaa,0xac }; /* Expected resulting multisets */ const unsigned char exp_empty[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,0x00 }; const unsigned char exp_m1[32] = { 0x5e,0x29,0x49,0x84,0xc0,0xb6,0xff,0x1c,0x89,0x7b,0xdb,0xb6,0xf7,0xcf,0x3e,0xf8,0x01,0xe2,0xf1,0x3b,0xc7,0x34,0x28,0xaa,0xcd,0xf8,0xcb,0x8d,0x3b,0xd2,0xf0,0xe5 }; const unsigned char exp_m2[32] = { 0x93,0x70,0x80,0xb6,0x6c,0x2b,0x37,0x2d,0x35,0x39,0x88,0xd6,0xc0,0x92,0x22,0x78,0x8f,0x88,0xa5,0x13,0x0a,0x13,0x32,0xeb,0xc1,0x49,0x5a,0xa3,0xa7,0xfa,0xb4,0xfb }; const unsigned char exp_m3[32] = { 0xdd,0xbf,0x2f,0x18,0xaf,0xe0,0xaf,0xa8,0x87,0x28,0x57,0x93,0xa4,0x82,0xa0,0x7f,0xc2,0x2a,0x46,0x28,0x48,0x36,0x78,0x73,0xd7,0x9d,0x72,0xa7,0x33,0x0a,0x96,0x15 }; const unsigned char exp_m1m2[32] = { 0x48,0x09,0x8f,0x4c,0xa9,0xbb,0x5d,0xac,0x27,0x3e,0x56,0x31,0x6d,0xb6,0x41,0x23,0x69,0xed,0x1f,0xa8,0xbe,0xb5,0x79,0x57,0x05,0x32,0xd1,0x63,0x47,0xfe,0xfc,0xcc }; const unsigned char exp_m1m2m3[32] = { 0x47,0xfb,0xdf,0xf4,0x76,0x7c,0x32,0xa4,0xea,0x74,0xca,0x43,0x86,0x59,0x0f,0x62,0x22,0xee,0x83,0x96,0xb8,0xb4,0xf0,0x0e,0xf5,0x6e,0x9b,0x49,0x43,0xf4,0x24,0x93 }; unsigned char m0[32],m1[32],m2[32],m3[32],m1m2[32],m1m2m3[32]; secp256k1_multiset r0,r1,r2,r3; secp256k1_multiset_init(ctx, &r0); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add (ctx, &r1, d1, sizeof(d1)); secp256k1_multiset_add (ctx, &r2, d2, sizeof(d2)); secp256k1_multiset_add (ctx, &r3, d3, sizeof(d3)); secp256k1_multiset_finalize(ctx, m0, &r0); secp256k1_multiset_finalize(ctx, m1, &r1); secp256k1_multiset_finalize(ctx, m2, &r2); secp256k1_multiset_finalize(ctx, m3, &r3); secp256k1_multiset_combine(ctx, &r1, &r2); secp256k1_multiset_finalize(ctx, m1m2, &r1); secp256k1_multiset_combine(ctx, &r1, &r3); secp256k1_multiset_finalize(ctx, m1m2m3, &r1); CHECK(memcmp(m0,exp_empty,32)==0); CHECK(memcmp(m1,exp_m1,32)==0); CHECK(memcmp(m2,exp_m2,32)==0); CHECK(memcmp(m3,exp_m3,32)==0); CHECK(memcmp(m1m2,exp_m1m2,32)==0); CHECK(memcmp(m1m2m3,exp_m1m2m3,32)==0); } void run_multiset_tests(void) { initdata(); test_unordered(); test_combine(); test_remove(); test_empty(); test_duplicate(); test_testvector(); } #endif /* _SECP256K1_MODULE_MULTISET_TESTS_ */ diff --git a/src/secp256k1/src/modules/recovery/main_impl.h b/src/secp256k1/src/modules/recovery/main_impl.h index 14ae479bc..7690eb2b8 100644 --- a/src/secp256k1/src/modules/recovery/main_impl.h +++ b/src/secp256k1/src/modules/recovery/main_impl.h @@ -1,161 +1,161 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_MODULE_RECOVERY_MAIN_H #define SECP256K1_MODULE_RECOVERY_MAIN_H #include "include/secp256k1_recovery.h" static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const secp256k1_ecdsa_recoverable_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); } *recid = sig->data[64]; } static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s, int recid) { 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); } sig->data[64] = recid; } int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { secp256k1_scalar r, s; int ret = 1; int overflow = 0; (void)ctx; ARG_CHECK(sig != NULL); ARG_CHECK(input64 != NULL); ARG_CHECK(recid >= 0 && recid <= 3); secp256k1_scalar_set_b32(&r, &input64[0], &overflow); ret &= !overflow; secp256k1_scalar_set_b32(&s, &input64[32], &overflow); ret &= !overflow; if (ret) { secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); } else { memset(sig, 0, sizeof(*sig)); } return ret; } int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) { secp256k1_scalar r, s; (void)ctx; ARG_CHECK(output64 != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(recid != NULL); secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); secp256k1_scalar_get_b32(&output64[0], &r); secp256k1_scalar_get_b32(&output64[32], &s); return 1; } int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const secp256k1_ecdsa_recoverable_signature* sigin) { secp256k1_scalar r, s; int recid; (void)ctx; ARG_CHECK(sig != NULL); ARG_CHECK(sigin != NULL); secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); secp256k1_ecdsa_signature_save(sig, &r, &s); return 1; } static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) { unsigned char brx[32]; secp256k1_fe fx; secp256k1_ge x; secp256k1_gej xj; secp256k1_scalar rn, u1, u2; secp256k1_gej qj; int r; if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { return 0; } secp256k1_scalar_get_b32(brx, sigr); r = secp256k1_fe_set_b32(&fx, brx); (void)r; VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */ if (recid & 2) { if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) { return 0; } secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe); } if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) { return 0; } secp256k1_gej_set_ge(&xj, &x); secp256k1_scalar_inverse_var(&rn, sigr); secp256k1_scalar_mul(&u1, &rn, message); secp256k1_scalar_negate(&u1, &u1); secp256k1_scalar_mul(&u2, &rn, sigs); secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1); secp256k1_ge_set_gej_var(pubkey, &qj); return !secp256k1_gej_is_infinity(&qj); } int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { secp256k1_scalar r, s; int ret, recid; const unsigned char secp256k1_ecdsa_recoverable_algo16[17] = "ECDSA+Recovery "; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(msghash32 != NULL); ARG_CHECK(signature != NULL); ARG_CHECK(seckey != NULL); ret = secp256k1_ecdsa_sign_inner(ctx, &r, &s, &recid, msghash32, seckey, noncefp, secp256k1_ecdsa_recoverable_algo16, noncedata); secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); return ret; } int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msghash32) { secp256k1_ge q; secp256k1_scalar r, s; secp256k1_scalar m; int recid; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(msghash32 != NULL); ARG_CHECK(signature != NULL); ARG_CHECK(pubkey != NULL); secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ secp256k1_scalar_set_b32(&m, msghash32, NULL); if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { secp256k1_pubkey_save(pubkey, &q); return 1; } else { memset(pubkey, 0, sizeof(*pubkey)); return 0; } } #endif /* SECP256K1_MODULE_RECOVERY_MAIN_H */ diff --git a/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h b/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h index a2f381d77..0ba9409c6 100644 --- a/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h +++ b/src/secp256k1/src/modules/recovery/tests_exhaustive_impl.h @@ -1,149 +1,149 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2016 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H #define SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H #include "src/modules/recovery/main_impl.h" #include "include/secp256k1_recovery.h" void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group) { int i, j, k; uint64_t iter = 0; /* Loop */ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { /* message */ for (j = 1; j < EXHAUSTIVE_TEST_ORDER; j++) { /* key */ if (skip_section(&iter)) continue; for (k = 1; k < EXHAUSTIVE_TEST_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; int overflow; 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, &overflow); CHECK(r == expected_r); CHECK((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER || (k * (EXHAUSTIVE_TEST_ORDER - s)) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER); /* The recid's second bit is for conveying overflow (R.x value >= group order). * In the actual secp256k1 this is an astronomically unlikely event, but in the * small group used here, it will be the case for all points except the ones where * R.x=1 (which the group is specifically selected to have). * Note that this isn't actually useful; full recovery would need to convey * floor(R.x / group_order), but only one bit is used as that is sufficient * in the real group. */ expected_recid = overflow ? 2 : 0; 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) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER) { expected_recid |= secp256k1_fe_is_odd(&r_dot_y_normalized); } else { expected_recid |= !secp256k1_fe_is_odd(&r_dot_y_normalized); } 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, NULL); CHECK(r == expected_r); CHECK((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER || (k * (EXHAUSTIVE_TEST_ORDER - s)) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_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) { /* This is essentially a copy of test_exhaustive_verify, with recovery added */ int s, r, msg, key; uint64_t iter = 0; for (s = 1; s < EXHAUSTIVE_TEST_ORDER; s++) { for (r = 1; r < EXHAUSTIVE_TEST_ORDER; r++) { for (msg = 1; msg < EXHAUSTIVE_TEST_ORDER; msg++) { for (key = 1; key < EXHAUSTIVE_TEST_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]; if (skip_section(&iter)) continue; 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 < EXHAUSTIVE_TEST_ORDER; k++) { secp256k1_scalar check_x_s; r_from_k(&check_x_s, group, k, NULL); 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)); } } } } } static void test_exhaustive_recovery(const secp256k1_context *ctx, const secp256k1_ge *group) { test_exhaustive_recovery_sign(ctx, group); test_exhaustive_recovery_verify(ctx, group); } #endif /* SECP256K1_MODULE_RECOVERY_EXHAUSTIVE_TESTS_H */ diff --git a/src/secp256k1/src/modules/recovery/tests_impl.h b/src/secp256k1/src/modules/recovery/tests_impl.h index dbdfd3908..d7d012621 100644 --- a/src/secp256k1/src/modules/recovery/tests_impl.h +++ b/src/secp256k1/src/modules/recovery/tests_impl.h @@ -1,392 +1,392 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_MODULE_RECOVERY_TESTS_H #define SECP256K1_MODULE_RECOVERY_TESTS_H static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { (void) msg32; (void) key32; (void) algo16; (void) data; /* On the first run, return 0 to force a second run */ if (counter == 0) { memset(nonce32, 0, 32); return 1; } /* On the second run, return an overflow to force a third run */ if (counter == 1) { memset(nonce32, 0xff, 32); return 1; } /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ memset(nonce32, 1, 32); return secp256k1_testrand_bits(1); } void test_ecdsa_recovery_api(void) { /* Setup contexts that just count errors */ 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_pubkey pubkey; secp256k1_pubkey recpubkey; secp256k1_ecdsa_signature normal_sig; secp256k1_ecdsa_recoverable_signature recsig; unsigned char privkey[32] = { 1 }; unsigned char message[32] = { 2 }; int32_t ecount = 0; int recid = 0; unsigned char sig[74]; unsigned char zero_privkey[32] = { 0 }; unsigned char over_privkey[32] = { 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 }; secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); /* Construct and verify corresponding public key. */ CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); /* Check bad contexts and NULLs for signing */ ecount = 0; CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); CHECK(ecount == 1); CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); CHECK(ecount == 1); CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); CHECK(ecount == 3); CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); CHECK(ecount == 4); CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0); CHECK(ecount == 5); /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL); CHECK(ecount == 5); /* These will all fail, but not in ARG_CHECK way */ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); /* This one will succeed. */ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); CHECK(ecount == 5); /* Check signing with a goofy nonce function */ /* Check bad contexts and NULLs for recovery */ ecount = 0; CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); CHECK(ecount == 1); CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); CHECK(ecount == 3); CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); CHECK(ecount == 4); CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); CHECK(ecount == 5); /* Check NULLs for conversion */ CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); ecount = 0; CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); CHECK(ecount == 1); CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); /* Check NULLs for de/serialization */ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); ecount = 0; CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); CHECK(ecount == 1); CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); CHECK(ecount == 2); CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); CHECK(ecount == 3); CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); CHECK(ecount == 4); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); CHECK(ecount == 5); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); CHECK(ecount == 6); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0); CHECK(ecount == 7); /* overflow in signature will fail but not affect ecount */ memcpy(sig, over_privkey, 32); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); CHECK(ecount == 7); /* cleanup */ secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(vrfy); secp256k1_context_destroy(both); } void test_ecdsa_recovery_end_to_end(void) { unsigned char extra[32] = {0x00}; unsigned char privkey[32]; unsigned char message[32]; secp256k1_ecdsa_signature signature[5]; secp256k1_ecdsa_recoverable_signature rsignature[5]; unsigned char sig[74]; secp256k1_pubkey pubkey; secp256k1_pubkey recpubkey; int recid = 0; /* 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); /* Serialize/parse compact and verify/recover. */ extra[0] = 0; CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[0], message, privkey, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[4], message, privkey, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[1], message, privkey, NULL, extra) == 1); extra[31] = 1; CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[2], message, privkey, NULL, extra) == 1); extra[31] = 0; extra[0] = 1; CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); memset(&rsignature[4], 0, sizeof(rsignature[4])); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); /* Parse compact (with recovery id) and recover. */ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1); CHECK(secp256k1_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) == 0); /* Serialize/destroy/parse signature and verify again. */ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); sig[secp256k1_testrand_bits(6)] += 1 + secp256k1_testrand_int(255); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0); /* Recover again */ CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 || secp256k1_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) != 0); } /* Tests several edge cases. */ void test_ecdsa_recovery_edge_cases(void) { const unsigned char msg32[32] = { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', '.', '.', '.' }; const unsigned char sig64[64] = { /* Generated by signing the above message with nonce 'This is the nonce we will use...' * and secret key 0 (which is not valid), resulting in recid 1. */ 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 }; secp256k1_pubkey pubkey; /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ const unsigned char sigb64[64] = { 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, 0x04, 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, 0x04, }; secp256k1_pubkey pubkeyb; secp256k1_ecdsa_recoverable_signature rsig; secp256k1_ecdsa_signature sig; int recid; CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 0)); CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 1)); CHECK(secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 2)); CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 3)); CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); for (recid = 0; recid < 4; recid++) { int i; int recid2; /* (4,4) encoded in DER. */ unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01}; unsigned char sigcder_zs[7] = {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x00}; unsigned char sigbderalt1[39] = { 0x30, 0x25, 0x02, 0x20, 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, 0x04, 0x02, 0x01, 0x04, }; unsigned char sigbderalt2[39] = { 0x30, 0x25, 0x02, 0x01, 0x04, 0x02, 0x20, 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, 0x04, }; unsigned char sigbderalt3[40] = { 0x30, 0x26, 0x02, 0x21, 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, 0x04, 0x02, 0x01, 0x04, }; unsigned char sigbderalt4[40] = { 0x30, 0x26, 0x02, 0x01, 0x04, 0x02, 0x21, 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, 0x04, }; /* (order + r,4) encoded in DER. */ unsigned char sigbderlong[40] = { 0x30, 0x26, 0x02, 0x21, 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, 0x45, 0x02, 0x01, 0x04 }; CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid) == 1); CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 1); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); for (recid2 = 0; recid2 < 4; recid2++) { secp256k1_pubkey pubkey2b; CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1); CHECK(secp256k1_ecdsa_recover(ctx, &pubkey2b, &rsig, msg32) == 1); /* Verifying with (order + r,4) should always fail. */ CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); } /* DER parsing tests. */ /* Zero length r/s. */ CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); /* Leading zeros. */ CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); sigbderalt3[4] = 1; CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); sigbderalt4[7] = 1; CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); /* Damage signature. */ sigbder[7]++; CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); sigbder[7]--; CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, 6) == 0); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder) - 1) == 0); for(i = 0; i < 8; i++) { int c; unsigned char orig = sigbder[i]; /*Try every single-byte change.*/ for (c = 0; c < 256; c++) { if (c == orig ) { continue; } sigbder[i] = c; CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); } sigbder[i] = orig; } } /* Test r/s equal to zero */ { /* (1,1) encoded in DER. */ unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01}; unsigned char sigc64[64] = { 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, 0x01, }; secp256k1_pubkey pubkeyc; CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyc, &rsig, msg32) == 1); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 1); sigcder[4] = 0; sigc64[31] = 0; CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); sigcder[4] = 1; sigcder[7] = 0; sigc64[31] = 1; sigc64[63] = 0; CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); } } void run_recovery_tests(void) { int i; for (i = 0; i < count; i++) { test_ecdsa_recovery_api(); } for (i = 0; i < 64*count; i++) { test_ecdsa_recovery_end_to_end(); } test_ecdsa_recovery_edge_cases(); } #endif /* SECP256K1_MODULE_RECOVERY_TESTS_H */ diff --git a/src/secp256k1/src/modules/schnorr/main_impl.h b/src/secp256k1/src/modules/schnorr/main_impl.h index f8939d5de..d7f9cb6be 100644 --- a/src/secp256k1/src/modules/schnorr/main_impl.h +++ b/src/secp256k1/src/modules/schnorr/main_impl.h @@ -1,77 +1,77 @@ -/********************************************************************** - * Copyright (c) 2017 Amaury Séchet * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Amaury Séchet * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_MODULE_SCHNORR_MAIN #define SECP256K1_MODULE_SCHNORR_MAIN #include "include/secp256k1_schnorr.h" #include "modules/schnorr/schnorr_impl.h" int secp256k1_schnorr_verify( const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msghash32, const secp256k1_pubkey *pubkey ) { secp256k1_ge q; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(msghash32 != NULL); ARG_CHECK(sig64 != NULL); ARG_CHECK(pubkey != NULL); if (!secp256k1_pubkey_load(ctx, &q, pubkey)) { return 0; } return secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &q, msghash32); } int secp256k1_schnorr_sign( const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata ) { secp256k1_scalar sec; secp256k1_pubkey pubkey; secp256k1_ge p; int overflow; int ret = 0; int pubkeyret; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(msghash32 != NULL); ARG_CHECK(sig64 != NULL); ARG_CHECK(seckey != NULL); pubkeyret = secp256k1_ec_pubkey_create(ctx, &pubkey, seckey); secp256k1_declassify(ctx, &pubkeyret, sizeof(pubkeyret)); if (!pubkeyret) { return 0; } secp256k1_declassify(ctx, &pubkey, sizeof(pubkey)); if (!secp256k1_pubkey_load(ctx, &p, &pubkey)) { return 0; } secp256k1_scalar_set_b32(&sec, seckey, &overflow); overflow |= secp256k1_scalar_is_zero(&sec); secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, overflow); ret = secp256k1_schnorr_sig_sign(ctx, sig64, msghash32, &sec, &p, noncefp, ndata); if (!ret) { memset(sig64, 0, 64); } secp256k1_scalar_clear(&sec); return !!ret & !overflow; } #endif diff --git a/src/secp256k1/src/modules/schnorr/schnorr.h b/src/secp256k1/src/modules/schnorr/schnorr.h index 2f550730a..14de6d045 100644 --- a/src/secp256k1/src/modules/schnorr/schnorr.h +++ b/src/secp256k1/src/modules/schnorr/schnorr.h @@ -1,46 +1,46 @@ /*********************************************************************** * Copyright (c) 2017 Amaury SÉCHET * * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php. * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ #ifndef _SECP256K1_MODULE_SCHNORR_H_ #define _SECP256K1_MODULE_SCHNORR_H_ #include "scalar.h" #include "group.h" static int secp256k1_schnorr_sig_verify( const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, const unsigned char *msg32 ); static int secp256k1_schnorr_compute_e( secp256k1_scalar* res, const unsigned char *r, secp256k1_ge *pubkey, const unsigned char *msg32 ); static int secp256k1_schnorr_sig_sign( const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_ge *pubkey, secp256k1_nonce_function noncefp, const void *ndata ); static int secp256k1_schnorr_sig_generate_k( const secp256k1_context* ctx, secp256k1_scalar *k, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_nonce_function noncefp, const void *ndata ); #endif diff --git a/src/secp256k1/src/modules/schnorr/schnorr_impl.h b/src/secp256k1/src/modules/schnorr/schnorr_impl.h index 9918c0bcd..60511ea8f 100644 --- a/src/secp256k1/src/modules/schnorr/schnorr_impl.h +++ b/src/secp256k1/src/modules/schnorr/schnorr_impl.h @@ -1,220 +1,220 @@ /*********************************************************************** * Copyright (c) 2017 Amaury SÉCHET * * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php. * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ #ifndef _SECP256K1_SCHNORR_IMPL_H_ #define _SECP256K1_SCHNORR_IMPL_H_ #include #include "schnorr.h" #include "field.h" #include "group.h" #include "hash.h" #include "ecmult.h" #include "ecmult_gen.h" /** * Custom Schnorr-based signature scheme. * * Signing: * Inputs: * 32-byte message m, * 32-byte scalar key x (!=0) * public key point P, * 32-byte scalar nonce k (!=0) * * Compute point R = k * G. Negate nonce if R.y is not a quadratic residue. * Compute scalar e = Hash(R.x || compressed(P) || m) mod n. * Compute scalar s = k + e * x. * The signature is (R.x, s). * * Verification: * Inputs: * 32-byte message m, * public key point P, * signature: (32-byte r, scalar s) * * Signature is invalid if s >= n or r >= p. * Compute scalar e = Hash(r || compressed(P) || m) mod n. * Option 1 (faster for single verification): * Compute point R = s * G - e * P. * Reject if R is infinity or R.y is not a quadratic residue. * Signature is valid if the serialization of R.x equals r. * Option 2 (allows batch validation): * Decompress x coordinate r into point R, with R.y a quadratic residue. * Reject if R is not on the curve. * Signature is valid if R + e * P - s * G == 0. */ static int secp256k1_schnorr_sig_verify( const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, const unsigned char *msg32 ) { secp256k1_gej Pj, Rj; secp256k1_fe Rx; secp256k1_scalar e, s; int overflow; VERIFY_CHECK(!secp256k1_ge_is_infinity(pubkey)); /* Extract s */ overflow = 0; secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow); if (overflow) { return 0; } /* Extract R.x */ if (!secp256k1_fe_set_b32(&Rx, sig64)) { return 0; } /* Compute e */ secp256k1_schnorr_compute_e(&e, sig64, pubkey, msg32); /* Verify the signature */ secp256k1_scalar_negate(&e, &e); secp256k1_gej_set_ge(&Pj, pubkey); secp256k1_ecmult(ctx, &Rj, &Pj, &e, &s); if (secp256k1_gej_is_infinity(&Rj)) { return 0; } /* Check that R.x is what we expect */ if (!secp256k1_gej_eq_x_var(&Rx, &Rj)) { return 0; } /* Check that jacobi(R.y) is 1 */ if (!secp256k1_gej_has_quad_y_var(&Rj)) { return 0; } /* All good, we have a valid signature. */ return 1; } static int secp256k1_schnorr_compute_e( secp256k1_scalar* e, const unsigned char *r, secp256k1_ge *p, const unsigned char *msg32 ) { int overflow = 0; size_t size = 0; secp256k1_sha256 sha; unsigned char buf[33]; secp256k1_sha256_initialize(&sha); /* R.x */ secp256k1_sha256_write(&sha, r, 32); /* compressed P */ secp256k1_eckey_pubkey_serialize(p, buf, &size, 1); VERIFY_CHECK(size == 33); secp256k1_sha256_write(&sha, buf, 33); /* msg */ secp256k1_sha256_write(&sha, msg32, 32); /* compute e */ secp256k1_sha256_finalize(&sha, buf); secp256k1_scalar_set_b32(e, buf, &overflow); return !overflow & !secp256k1_scalar_is_zero(e); } static int secp256k1_schnorr_sig_sign( const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_ge *pubkey, secp256k1_nonce_function noncefp, const void *ndata ) { secp256k1_ge R; secp256k1_gej Rj; secp256k1_scalar k, e, s; ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); VERIFY_CHECK(!secp256k1_scalar_is_zero(privkey)); VERIFY_CHECK(!secp256k1_ge_is_infinity(pubkey)); if (!secp256k1_schnorr_sig_generate_k(ctx, &k, msg32, privkey, noncefp, ndata)) { return 0; } /* Compute R */ secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Rj, &k); secp256k1_ge_set_gej(&R, &Rj); /* * We declassify R to allow using it as a branch point. * This is fine because R is not a secret. */ secp256k1_declassify(ctx, &R, sizeof(R)); /** Negate the nonce if R.y is not a quadratic residue. */ secp256k1_scalar_cond_negate(&k, !secp256k1_fe_is_quad_var(&R.y)); /* Compute the signature. */ secp256k1_fe_normalize(&R.x); secp256k1_fe_get_b32(sig64, &R.x); secp256k1_schnorr_compute_e(&e, sig64, pubkey, msg32); secp256k1_scalar_mul(&s, &e, privkey); secp256k1_scalar_add(&s, &s, &k); secp256k1_scalar_get_b32(sig64 + 32, &s); /* Cleanup locals that may contain private data. */ secp256k1_scalar_clear(&k); return 1; } static int secp256k1_schnorr_sig_generate_k( const secp256k1_context* ctx, secp256k1_scalar *k, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_nonce_function noncefp, const void *ndata ) { int ret = 0; unsigned int count = 0; unsigned char nonce32[32], seckey[32]; /* Seed used to make sure we generate different values of k for schnorr */ const unsigned char secp256k1_schnorr_algo16[17] = "Schnorr+SHA256 "; if (noncefp == NULL) { noncefp = secp256k1_nonce_function_default; } secp256k1_scalar_get_b32(seckey, privkey); while (1) { int overflow; ret = noncefp(nonce32, msg32, seckey, secp256k1_schnorr_algo16, (void*)ndata, count++); if (!ret) { break; } secp256k1_scalar_set_b32(k, nonce32, &overflow); overflow |= secp256k1_scalar_is_zero(k); /* The nonce is still secret here, but it overflowing or being zero is is less likely than 1:2^255. */ secp256k1_declassify(ctx, &overflow, sizeof(overflow)); if (!overflow) { break; } secp256k1_scalar_clear(k); } /* Cleanup locals that may contain private data. */ memset(seckey, 0, 32); memset(nonce32, 0, 32); return ret; } #endif diff --git a/src/secp256k1/src/modules/schnorr/tests_impl.h b/src/secp256k1/src/modules/schnorr/tests_impl.h index 21e5ffac7..b7daa9801 100644 --- a/src/secp256k1/src/modules/schnorr/tests_impl.h +++ b/src/secp256k1/src/modules/schnorr/tests_impl.h @@ -1,522 +1,522 @@ -/********************************************************************** - * Copyright (c) 2017 Amaury SÉCHET * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Amaury SÉCHET * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_MODULE_SCHNORR_TESTS #define SECP256K1_MODULE_SCHNORR_TESTS #include "include/secp256k1_schnorr.h" void test_schnorr_end_to_end(void) { unsigned char privkey[32]; unsigned char message[32]; unsigned char schnorr_signature[64]; secp256k1_pubkey pubkey; /* Generate a random key and message. */ { secp256k1_scalar key; random_scalar_order_test(&key); secp256k1_scalar_get_b32(privkey, &key); secp256k1_testrand256_test(message); } /* Construct and verify corresponding public key. */ CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); /* Schnorr sign. */ CHECK(secp256k1_schnorr_sign(ctx, schnorr_signature, message, privkey, NULL, NULL) == 1); CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 1); /* Destroy signature and verify again. */ schnorr_signature[secp256k1_testrand_bits(6)] += 1 + secp256k1_testrand_int(255); CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 0); } #define SIG_COUNT 32 void test_schnorr_sign_verify(void) { unsigned char msg32[32]; unsigned char sig64[SIG_COUNT][64]; unsigned char ndata[SIG_COUNT][32]; secp256k1_gej pubkeyj[SIG_COUNT]; secp256k1_ge pubkey[SIG_COUNT]; secp256k1_scalar key[SIG_COUNT]; int i, j; secp256k1_testrand256_test(msg32); for (i = 0; i < SIG_COUNT; i++) { random_scalar_order_test(&key[i]); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj[i], &key[i]); secp256k1_ge_set_gej_var(&pubkey[i], &pubkeyj[i]); secp256k1_fe_normalize(&pubkey[i].x); secp256k1_fe_normalize(&pubkey[i].y); do { secp256k1_testrand256_test(ndata[i]); if (secp256k1_schnorr_sig_sign(ctx, sig64[i], msg32, &key[i], &pubkey[i], NULL, &ndata[i])) { break; } } while(1); CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[i], &pubkey[i], msg32)); /* Apply several random modifications to the sig and check that it * doesn't verify anymore. */ for (j = 0; j < count; j++) { int pos = secp256k1_testrand_bits(6); int mod = 1 + secp256k1_testrand_int(255); sig64[i][pos] ^= mod; CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[i], &pubkey[i], msg32) == 0); sig64[i][pos] ^= mod; } } } #undef SIG_COUNT void run_schnorr_compact_test(void) { { /* Test vector 1 */ static const unsigned char pkbuf[33] = { 0x02, 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, }; static const unsigned char msg[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, 0x00, }; static const unsigned char sig[64] = { 0x78, 0x7A, 0x84, 0x8E, 0x71, 0x04, 0x3D, 0x28, 0x0C, 0x50, 0x47, 0x0E, 0x8E, 0x15, 0x32, 0xB2, 0xDD, 0x5D, 0x20, 0xEE, 0x91, 0x2A, 0x45, 0xDB, 0xDD, 0x2B, 0xD1, 0xDF, 0xBF, 0x18, 0x7E, 0xF6, 0x70, 0x31, 0xA9, 0x88, 0x31, 0x85, 0x9D, 0xC3, 0x4D, 0xFF, 0xEE, 0xDD, 0xA8, 0x68, 0x31, 0x84, 0x2C, 0xCD, 0x00, 0x79, 0xE1, 0xF9, 0x2A, 0xF1, 0x77, 0xF7, 0xF2, 0x2C, 0xC1, 0xDC, 0xED, 0x05, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 2 */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x1E, 0x51, 0xA2, 0x2C, 0xCE, 0xC3, 0x55, 0x99, 0xB8, 0xF2, 0x66, 0x91, 0x22, 0x81, 0xF8, 0x36, 0x5F, 0xFC, 0x2D, 0x03, 0x5A, 0x23, 0x04, 0x34, 0xA1, 0xA6, 0x4D, 0xC5, 0x9F, 0x70, 0x13, 0xFD, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 3 */ static const unsigned char pkbuf[33] = { 0x03, 0xFA, 0xC2, 0x11, 0x4C, 0x2F, 0xBB, 0x09, 0x15, 0x27, 0xEB, 0x7C, 0x64, 0xEC, 0xB1, 0x1F, 0x80, 0x21, 0xCB, 0x45, 0xE8, 0xE7, 0x80, 0x9D, 0x3C, 0x09, 0x38, 0xE4, 0xB8, 0xC0, 0xE5, 0xF8, 0x4B, }; static const unsigned char msg[32] = { 0x5E, 0x2D, 0x58, 0xD8, 0xB3, 0xBC, 0xDF, 0x1A, 0xBA, 0xDE, 0xC7, 0x82, 0x90, 0x54, 0xF9, 0x0D, 0xDA, 0x98, 0x05, 0xAA, 0xB5, 0x6C, 0x77, 0x33, 0x30, 0x24, 0xB9, 0xD0, 0xA5, 0x08, 0xB7, 0x5C, }; static const unsigned char sig[64] = { 0x00, 0xDA, 0x9B, 0x08, 0x17, 0x2A, 0x9B, 0x6F, 0x04, 0x66, 0xA2, 0xDE, 0xFD, 0x81, 0x7F, 0x2D, 0x7A, 0xB4, 0x37, 0xE0, 0xD2, 0x53, 0xCB, 0x53, 0x95, 0xA9, 0x63, 0x86, 0x6B, 0x35, 0x74, 0xBE, 0x00, 0x88, 0x03, 0x71, 0xD0, 0x17, 0x66, 0x93, 0x5B, 0x92, 0xD2, 0xAB, 0x4C, 0xD5, 0xC8, 0xA2, 0xA5, 0x83, 0x7E, 0xC5, 0x7F, 0xED, 0x76, 0x60, 0x77, 0x3A, 0x05, 0xF0, 0xDE, 0x14, 0x23, 0x80, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 4 */ static const unsigned char pkbuf[33] = { 0x03, 0xDE, 0xFD, 0xEA, 0x4C, 0xDB, 0x67, 0x77, 0x50, 0xA4, 0x20, 0xFE, 0xE8, 0x07, 0xEA, 0xCF, 0x21, 0xEB, 0x98, 0x98, 0xAE, 0x79, 0xB9, 0x76, 0x87, 0x66, 0xE4, 0xFA, 0xA0, 0x4A, 0x2D, 0x4A, 0x34, }; static const unsigned char msg[32] = { 0x4D, 0xF3, 0xC3, 0xF6, 0x8F, 0xCC, 0x83, 0xB2, 0x7E, 0x9D, 0x42, 0xC9, 0x04, 0x31, 0xA7, 0x24, 0x99, 0xF1, 0x78, 0x75, 0xC8, 0x1A, 0x59, 0x9B, 0x56, 0x6C, 0x98, 0x89, 0xB9, 0x69, 0x67, 0x03, }; static const unsigned char sig[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x78, 0xCE, 0x56, 0x3F, 0x89, 0xA0, 0xED, 0x94, 0x14, 0xF5, 0xAA, 0x28, 0xAD, 0x0D, 0x96, 0xD6, 0x79, 0x5F, 0x9C, 0x63, 0x02, 0xA8, 0xDC, 0x32, 0xE6, 0x4E, 0x86, 0xA3, 0x33, 0xF2, 0x0E, 0xF5, 0x6E, 0xAC, 0x9B, 0xA3, 0x0B, 0x72, 0x46, 0xD6, 0xD2, 0x5E, 0x22, 0xAD, 0xB8, 0xC6, 0xBE, 0x1A, 0xEB, 0x08, 0xD4, 0x9D, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 4b */ static const unsigned char pkbuf[33] = { 0x03, 0x1B, 0x84, 0xC5, 0x56, 0x7B, 0x12, 0x64, 0x40, 0x99, 0x5D, 0x3E, 0xD5, 0xAA, 0xBA, 0x05, 0x65, 0xD7, 0x1E, 0x18, 0x34, 0x60, 0x48, 0x19, 0xFF, 0x9C, 0x17, 0xF5, 0xE9, 0xD5, 0xDD, 0x07, 0x8F, }; static const unsigned char msg[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, 0x00, }; static const unsigned char sig[64] = { 0x52, 0x81, 0x85, 0x79, 0xAC, 0xA5, 0x97, 0x67, 0xE3, 0x29, 0x1D, 0x91, 0xB7, 0x6B, 0x63, 0x7B, 0xEF, 0x06, 0x20, 0x83, 0x28, 0x49, 0x92, 0xF2, 0xD9, 0x5F, 0x56, 0x4C, 0xA6, 0xCB, 0x4E, 0x35, 0x30, 0xB1, 0xDA, 0x84, 0x9C, 0x8E, 0x83, 0x04, 0xAD, 0xC0, 0xCF, 0xE8, 0x70, 0x66, 0x03, 0x34, 0xB3, 0xCF, 0xC1, 0x8E, 0x82, 0x5E, 0xF1, 0xDB, 0x34, 0xCF, 0xAE, 0x3D, 0xFC, 0x5D, 0x81, 0x87, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 6: R.y is not a quadratic residue */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0xFA, 0x16, 0xAE, 0xE0, 0x66, 0x09, 0x28, 0x0A, 0x19, 0xB6, 0x7A, 0x24, 0xE1, 0x97, 0x7E, 0x46, 0x97, 0x71, 0x2B, 0x5F, 0xD2, 0x94, 0x39, 0x14, 0xEC, 0xD5, 0xF7, 0x30, 0x90, 0x1B, 0x4A, 0xB7, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 7: Negated message hash, R.x mismatch */ static const unsigned char pkbuf[33] = { 0x03, 0xFA, 0xC2, 0x11, 0x4C, 0x2F, 0xBB, 0x09, 0x15, 0x27, 0xEB, 0x7C, 0x64, 0xEC, 0xB1, 0x1F, 0x80, 0x21, 0xCB, 0x45, 0xE8, 0xE7, 0x80, 0x9D, 0x3C, 0x09, 0x38, 0xE4, 0xB8, 0xC0, 0xE5, 0xF8, 0x4B, }; static const unsigned char msg[32] = { 0x5E, 0x2D, 0x58, 0xD8, 0xB3, 0xBC, 0xDF, 0x1A, 0xBA, 0xDE, 0xC7, 0x82, 0x90, 0x54, 0xF9, 0x0D, 0xDA, 0x98, 0x05, 0xAA, 0xB5, 0x6C, 0x77, 0x33, 0x30, 0x24, 0xB9, 0xD0, 0xA5, 0x08, 0xB7, 0x5C, }; static const unsigned char sig[64] = { 0x00, 0xDA, 0x9B, 0x08, 0x17, 0x2A, 0x9B, 0x6F, 0x04, 0x66, 0xA2, 0xDE, 0xFD, 0x81, 0x7F, 0x2D, 0x7A, 0xB4, 0x37, 0xE0, 0xD2, 0x53, 0xCB, 0x53, 0x95, 0xA9, 0x63, 0x86, 0x6B, 0x35, 0x74, 0xBE, 0xD0, 0x92, 0xF9, 0xD8, 0x60, 0xF1, 0x77, 0x6A, 0x1F, 0x74, 0x12, 0xAD, 0x8A, 0x1E, 0xB5, 0x0D, 0xAC, 0xCC, 0x22, 0x2B, 0xC8, 0xC0, 0xE2, 0x6B, 0x20, 0x56, 0xDF, 0x2F, 0x27, 0x3E, 0xFD, 0xEC, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 8: Negated s, R.x mismatch */ static const unsigned char pkbuf[33] = { 0x02, 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, }; static const unsigned char msg[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, 0x00, }; static const unsigned char sig[64] = { 0x78, 0x7A, 0x84, 0x8E, 0x71, 0x04, 0x3D, 0x28, 0x0C, 0x50, 0x47, 0x0E, 0x8E, 0x15, 0x32, 0xB2, 0xDD, 0x5D, 0x20, 0xEE, 0x91, 0x2A, 0x45, 0xDB, 0xDD, 0x2B, 0xD1, 0xDF, 0xBF, 0x18, 0x7E, 0xF6, 0x8F, 0xCE, 0x56, 0x77, 0xCE, 0x7A, 0x62, 0x3C, 0xB2, 0x00, 0x11, 0x22, 0x57, 0x97, 0xCE, 0x7A, 0x8D, 0xE1, 0xDC, 0x6C, 0xCD, 0x4F, 0x75, 0x4A, 0x47, 0xDA, 0x6C, 0x60, 0x0E, 0x59, 0x54, 0x3C, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 9: Negated P, R.x mismatch */ static const unsigned char pkbuf[33] = { 0x03, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x1E, 0x51, 0xA2, 0x2C, 0xCE, 0xC3, 0x55, 0x99, 0xB8, 0xF2, 0x66, 0x91, 0x22, 0x81, 0xF8, 0x36, 0x5F, 0xFC, 0x2D, 0x03, 0x5A, 0x23, 0x04, 0x34, 0xA1, 0xA6, 0x4D, 0xC5, 0x9F, 0x70, 0x13, 0xFD, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 10: s * G = e * P, R = 0 */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x8C, 0x34, 0x28, 0x86, 0x9A, 0x66, 0x3E, 0xD1, 0xE9, 0x54, 0x70, 0x5B, 0x02, 0x0C, 0xBB, 0x3E, 0x7B, 0xB6, 0xAC, 0x31, 0x96, 0x5B, 0x9E, 0xA4, 0xC7, 0x3E, 0x22, 0x7B, 0x17, 0xC5, 0xAF, 0x5A, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 11: R.x not on the curve, R.x mismatch */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x4A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x1E, 0x51, 0xA2, 0x2C, 0xCE, 0xC3, 0x55, 0x99, 0xB8, 0xF2, 0x66, 0x91, 0x22, 0x81, 0xF8, 0x36, 0x5F, 0xFC, 0x2D, 0x03, 0x5A, 0x23, 0x04, 0x34, 0xA1, 0xA6, 0x4D, 0xC5, 0x9F, 0x70, 0x13, 0xFD, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 12: r = p */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[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, 0xFC, 0x2F, 0x1E, 0x51, 0xA2, 0x2C, 0xCE, 0xC3, 0x55, 0x99, 0xB8, 0xF2, 0x66, 0x91, 0x22, 0x81, 0xF8, 0x36, 0x5F, 0xFC, 0x2D, 0x03, 0x5A, 0x23, 0x04, 0x34, 0xA1, 0xA6, 0x4D, 0xC5, 0x9F, 0x70, 0x13, 0xFD, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 13: s = n */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 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_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } } void run_schnorr_tests(void) { int i; for (i = 0; i < 32 * count; i++) { test_schnorr_end_to_end(); } test_schnorr_sign_verify(); run_schnorr_compact_test(); } #endif diff --git a/src/secp256k1/src/modules/schnorrsig/main_impl.h b/src/secp256k1/src/modules/schnorrsig/main_impl.h index da747fe14..902025cb6 100644 --- a/src/secp256k1/src/modules/schnorrsig/main_impl.h +++ b/src/secp256k1/src/modules/schnorrsig/main_impl.h @@ -1,239 +1,239 @@ -/********************************************************************** - * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MODULE_SCHNORRSIG_MAIN_ #define _SECP256K1_MODULE_SCHNORRSIG_MAIN_ #include "include/secp256k1.h" #include "include/secp256k1_schnorrsig.h" #include "hash.h" /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */ static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) { secp256k1_sha256_initialize(sha); sha->s[0] = 0x46615b35ul; sha->s[1] = 0xf4bfbff7ul; sha->s[2] = 0x9f8dc671ul; sha->s[3] = 0x83627ab3ul; sha->s[4] = 0x60217180ul; sha->s[5] = 0x57358661ul; sha->s[6] = 0x21a29e54ul; sha->s[7] = 0x68b07b4cul; sha->bytes = 64; } /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) { secp256k1_sha256_initialize(sha); sha->s[0] = 0x24dd3219ul; sha->s[1] = 0x4eba7e70ul; sha->s[2] = 0xca0fabb9ul; sha->s[3] = 0x0fa3166dul; sha->s[4] = 0x3afbe4b1ul; sha->s[5] = 0x4c44df97ul; sha->s[6] = 0x4aac2739ul; sha->s[7] = 0x249e850aul; sha->bytes = 64; } /* algo16 argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340 * by using the correct tagged hash function. */ static const unsigned char bip340_algo16[16] = "BIP0340/nonce\0\0\0"; static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) { secp256k1_sha256 sha; unsigned char masked_key[32]; int i; if (algo16 == NULL) { return 0; } if (data != NULL) { secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha); secp256k1_sha256_write(&sha, data, 32); secp256k1_sha256_finalize(&sha, masked_key); for (i = 0; i < 32; i++) { masked_key[i] ^= key32[i]; } } /* Tag the hash with algo16 which is important to avoid nonce reuse across * algorithms. If this nonce function is used in BIP-340 signing as defined * in the spec, an optimized tagging implementation is used. */ if (secp256k1_memcmp_var(algo16, bip340_algo16, 16) == 0) { secp256k1_nonce_function_bip340_sha256_tagged(&sha); } else { int algo16_len = 16; /* Remove terminating null bytes */ while (algo16_len > 0 && !algo16[algo16_len - 1]) { algo16_len--; } secp256k1_sha256_initialize_tagged(&sha, algo16, algo16_len); } /* Hash (masked-)key||pk||msg using the tagged hash as per the spec */ if (data != NULL) { secp256k1_sha256_write(&sha, masked_key, 32); } else { secp256k1_sha256_write(&sha, key32, 32); } secp256k1_sha256_write(&sha, xonly_pk32, 32); secp256k1_sha256_write(&sha, msg32, 32); secp256k1_sha256_finalize(&sha, nonce32); return 1; } const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_function_bip340; /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */ static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) { secp256k1_sha256_initialize(sha); sha->s[0] = 0x9cecba11ul; sha->s[1] = 0x23925381ul; sha->s[2] = 0x11679112ul; sha->s[3] = 0xd1627e0ful; sha->s[4] = 0x97c87550ul; sha->s[5] = 0x003cc765ul; sha->s[6] = 0x90f61164ul; sha->s[7] = 0x33e9b66aul; sha->bytes = 64; } static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg32, const unsigned char *pubkey32) { unsigned char buf[32]; secp256k1_sha256 sha; /* tagged hash(r.x, pk.x, msg32) */ secp256k1_schnorrsig_sha256_tagged(&sha); secp256k1_sha256_write(&sha, r32, 32); secp256k1_sha256_write(&sha, pubkey32, 32); secp256k1_sha256_write(&sha, msg32, 32); secp256k1_sha256_finalize(&sha, buf); /* Set scalar e to the challenge hash modulo the curve order as per * BIP340. */ secp256k1_scalar_set_b32(e, buf, NULL); } int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) { secp256k1_scalar sk; secp256k1_scalar e; secp256k1_scalar k; secp256k1_gej rj; secp256k1_ge pk; secp256k1_ge r; unsigned char buf[32] = { 0 }; unsigned char pk_buf[32]; unsigned char seckey[32]; int ret = 1; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(sig64 != NULL); ARG_CHECK(msg32 != NULL); ARG_CHECK(keypair != NULL); if (noncefp == NULL) { noncefp = secp256k1_nonce_function_bip340; } ret &= secp256k1_keypair_load(ctx, &sk, &pk, keypair); /* Because we are signing for a x-only pubkey, the secret key is negated * before signing if the point corresponding to the secret key does not * have an even Y. */ if (secp256k1_fe_is_odd(&pk.y)) { secp256k1_scalar_negate(&sk, &sk); } secp256k1_scalar_get_b32(seckey, &sk); secp256k1_fe_get_b32(pk_buf, &pk.x); ret &= !!noncefp(buf, msg32, seckey, pk_buf, bip340_algo16, ndata); secp256k1_scalar_set_b32(&k, buf, NULL); ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k); secp256k1_ge_set_gej(&r, &rj); /* We declassify r to allow using it as a branch point. This is fine * because r is not a secret. */ secp256k1_declassify(ctx, &r, sizeof(r)); secp256k1_fe_normalize_var(&r.y); if (secp256k1_fe_is_odd(&r.y)) { secp256k1_scalar_negate(&k, &k); } secp256k1_fe_normalize_var(&r.x); secp256k1_fe_get_b32(&sig64[0], &r.x); secp256k1_schnorrsig_challenge(&e, &sig64[0], msg32, pk_buf); secp256k1_scalar_mul(&e, &e, &sk); secp256k1_scalar_add(&e, &e, &k); secp256k1_scalar_get_b32(&sig64[32], &e); secp256k1_memczero(sig64, 64, !ret); secp256k1_scalar_clear(&k); secp256k1_scalar_clear(&sk); memset(seckey, 0, sizeof(seckey)); return ret; } int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg32, const secp256k1_xonly_pubkey *pubkey) { secp256k1_scalar s; secp256k1_scalar e; secp256k1_gej rj; secp256k1_ge pk; secp256k1_gej pkj; secp256k1_fe rx; secp256k1_ge r; unsigned char buf[32]; int overflow; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(sig64 != NULL); ARG_CHECK(msg32 != NULL); ARG_CHECK(pubkey != NULL); if (!secp256k1_fe_set_b32(&rx, &sig64[0])) { return 0; } secp256k1_scalar_set_b32(&s, &sig64[32], &overflow); if (overflow) { return 0; } if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) { return 0; } /* Compute e. */ secp256k1_fe_get_b32(buf, &pk.x); secp256k1_schnorrsig_challenge(&e, &sig64[0], msg32, buf); /* Compute rj = s*G + (-e)*pkj */ secp256k1_scalar_negate(&e, &e); secp256k1_gej_set_ge(&pkj, &pk); secp256k1_ecmult(&ctx->ecmult_ctx, &rj, &pkj, &e, &s); secp256k1_ge_set_gej_var(&r, &rj); if (secp256k1_ge_is_infinity(&r)) { return 0; } secp256k1_fe_normalize_var(&r.y); return !secp256k1_fe_is_odd(&r.y) && secp256k1_fe_equal_var(&rx, &r.x); } #endif diff --git a/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h index 4bf0bc168..7e6a1e791 100644 --- a/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h +++ b/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h @@ -1,206 +1,206 @@ -/********************************************************************** - * Copyright (c) 2020 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2020 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_ #define _SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_ #include "include/secp256k1_schnorrsig.h" #include "src/modules/schnorrsig/main_impl.h" static const unsigned char invalid_pubkey_bytes[][32] = { /* 0 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 2 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }, /* order */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 24) & 0xFF, ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 16) & 0xFF, ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 8) & 0xFF, (EXHAUSTIVE_TEST_ORDER + 0UL) & 0xFF }, /* order + 1 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 24) & 0xFF, ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 16) & 0xFF, ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 8) & 0xFF, (EXHAUSTIVE_TEST_ORDER + 1UL) & 0xFF }, /* field size */ { 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, 0x2F }, /* field size + 1 (note that 1 is legal) */ { 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 }, /* 2^256 - 1 */ { 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 } }; #define NUM_INVALID_KEYS (sizeof(invalid_pubkey_bytes) / sizeof(invalid_pubkey_bytes[0])) static int secp256k1_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void* data) { secp256k1_scalar s; int *idata = data; (void)msg32; (void)key32; (void)xonly_pk32; (void)algo16; secp256k1_scalar_set_int(&s, *idata); secp256k1_scalar_get_b32(nonce32, &s); return 1; } static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, const secp256k1_xonly_pubkey* pubkeys, unsigned char (*xonly_pubkey_bytes)[32], const int* parities) { int d; uint64_t iter = 0; /* Iterate over the possible public keys to verify against (through their corresponding DL d). */ for (d = 1; d <= EXHAUSTIVE_TEST_ORDER / 2; ++d) { int actual_d; unsigned k; unsigned char pk32[32]; memcpy(pk32, xonly_pubkey_bytes[d - 1], 32); actual_d = parities[d - 1] ? EXHAUSTIVE_TEST_ORDER - d : d; /* Iterate over the possible valid first 32 bytes in the signature, through their corresponding DL k. Values above EXHAUSTIVE_TEST_ORDER/2 refer to the entries in invalid_pubkey_bytes. */ for (k = 1; k <= EXHAUSTIVE_TEST_ORDER / 2 + NUM_INVALID_KEYS; ++k) { unsigned char sig64[64]; int actual_k = -1; int e_done[EXHAUSTIVE_TEST_ORDER] = {0}; int e_count_done = 0; if (skip_section(&iter)) continue; if (k <= EXHAUSTIVE_TEST_ORDER / 2) { memcpy(sig64, xonly_pubkey_bytes[k - 1], 32); actual_k = parities[k - 1] ? EXHAUSTIVE_TEST_ORDER - k : k; } else { memcpy(sig64, invalid_pubkey_bytes[k - 1 - EXHAUSTIVE_TEST_ORDER / 2], 32); } /* Randomly generate messages until all challenges have been hit. */ while (e_count_done < EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar e; unsigned char msg32[32]; secp256k1_testrand256(msg32); secp256k1_schnorrsig_challenge(&e, sig64, msg32, pk32); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { /* Iterate over the possible valid last 32 bytes in the signature. 0..order=that s value; order+1=random bytes */ int count_valid = 0, s; for (s = 0; s <= EXHAUSTIVE_TEST_ORDER + 1; ++s) { int expect_valid, valid; if (s <= EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar s_s; secp256k1_scalar_set_int(&s_s, s); secp256k1_scalar_get_b32(sig64 + 32, &s_s); expect_valid = actual_k != -1 && s != EXHAUSTIVE_TEST_ORDER && (s_s == (actual_k + actual_d * e) % EXHAUSTIVE_TEST_ORDER); } else { secp256k1_testrand256(sig64 + 32); expect_valid = 0; } valid = secp256k1_schnorrsig_verify(ctx, sig64, msg32, &pubkeys[d - 1]); CHECK(valid == expect_valid); count_valid += valid; } /* Exactly one s value must verify, unless R is illegal. */ CHECK(count_valid == (actual_k != -1)); /* Don't retry other messages that result in the same challenge. */ e_done[e] = 1; ++e_count_done; } } } } } static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const secp256k1_keypair* keypairs, const int* parities) { int d, k; uint64_t iter = 0; /* Loop over keys. */ for (d = 1; d < EXHAUSTIVE_TEST_ORDER; ++d) { int actual_d = d; if (parities[d - 1]) actual_d = EXHAUSTIVE_TEST_ORDER - d; /* Loop over nonces. */ for (k = 1; k < EXHAUSTIVE_TEST_ORDER; ++k) { int e_done[EXHAUSTIVE_TEST_ORDER] = {0}; int e_count_done = 0; unsigned char msg32[32]; unsigned char sig64[64]; int actual_k = k; if (skip_section(&iter)) continue; if (parities[k - 1]) actual_k = EXHAUSTIVE_TEST_ORDER - k; /* Generate random messages until all challenges have been tried. */ while (e_count_done < EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar e; secp256k1_testrand256(msg32); secp256k1_schnorrsig_challenge(&e, xonly_pubkey_bytes[k - 1], msg32, xonly_pubkey_bytes[d - 1]); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { secp256k1_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER; unsigned char expected_s_bytes[32]; secp256k1_scalar_get_b32(expected_s_bytes, &expected_s); /* Invoke the real function to construct a signature. */ CHECK(secp256k1_schnorrsig_sign(ctx, sig64, msg32, &keypairs[d - 1], secp256k1_hardened_nonce_function_smallint, &k)); /* The first 32 bytes must match the xonly pubkey for the specified k. */ CHECK(secp256k1_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0); /* The last 32 bytes must match the expected s value. */ CHECK(secp256k1_memcmp_var(sig64 + 32, expected_s_bytes, 32) == 0); /* Don't retry other messages that result in the same challenge. */ e_done[e] = 1; ++e_count_done; } } } } } static void test_exhaustive_schnorrsig(const secp256k1_context *ctx) { secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; secp256k1_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; int parity[EXHAUSTIVE_TEST_ORDER - 1]; unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; unsigned i; /* Verify that all invalid_pubkey_bytes are actually invalid. */ for (i = 0; i < NUM_INVALID_KEYS; ++i) { secp256k1_xonly_pubkey pk; CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk, invalid_pubkey_bytes[i])); } /* Construct keypairs and xonly-pubkeys for the entire group. */ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; ++i) { secp256k1_scalar scalar_i; unsigned char buf[32]; secp256k1_scalar_set_int(&scalar_i, i); secp256k1_scalar_get_b32(buf, &scalar_i); CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf)); CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parity[i - 1], &keypair[i - 1])); CHECK(secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); } test_exhaustive_schnorrsig_sign(ctx, xonly_pubkey_bytes, keypair, parity); test_exhaustive_schnorrsig_verify(ctx, xonly_pubkey, xonly_pubkey_bytes, parity); } #endif diff --git a/src/secp256k1/src/modules/schnorrsig/tests_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_impl.h index f522fcb32..e10c45fab 100644 --- a/src/secp256k1/src/modules/schnorrsig/tests_impl.h +++ b/src/secp256k1/src/modules/schnorrsig/tests_impl.h @@ -1,806 +1,806 @@ -/********************************************************************** - * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_MODULE_SCHNORRSIG_TESTS_ #define _SECP256K1_MODULE_SCHNORRSIG_TESTS_ #include "secp256k1_schnorrsig.h" /* Checks that a bit flip in the n_flip-th argument (that has n_bytes many * bytes) changes the hash function */ void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { unsigned char nonces[2][32]; CHECK(nonce_function_bip340(nonces[0], args[0], args[1], args[2], args[3], args[4]) == 1); secp256k1_testrand_flip(args[n_flip], n_bytes); CHECK(nonce_function_bip340(nonces[1], args[0], args[1], args[2], args[3], args[4]) == 1); CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0); } /* Tests for the equality of two sha256 structs. This function only produces a * correct result if an integer multiple of 64 many bytes have been written * into the hash functions. */ void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) { /* Is buffer fully consumed? */ CHECK((sha1->bytes & 0x3F) == 0); CHECK(sha1->bytes == sha2->bytes); CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); } void run_nonce_function_bip340_tests(void) { unsigned char tag[13] = "BIP0340/nonce"; unsigned char aux_tag[11] = "BIP0340/aux"; unsigned char algo16[16] = "BIP0340/nonce\0\0\0"; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; unsigned char nonce[32]; unsigned char msg[32]; unsigned char key[32]; unsigned char pk[32]; unsigned char aux_rand[32]; unsigned char *args[5]; int i; /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged has the expected * state. */ secp256k1_sha256_initialize_tagged(&sha, tag, sizeof(tag)); secp256k1_nonce_function_bip340_sha256_tagged(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged_aux has the expected * state. */ secp256k1_sha256_initialize_tagged(&sha, aux_tag, sizeof(aux_tag)); secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); secp256k1_testrand256(msg); secp256k1_testrand256(key); secp256k1_testrand256(pk); secp256k1_testrand256(aux_rand); /* Check that a bitflip in an argument results in different nonces. */ args[0] = msg; args[1] = key; args[2] = pk; args[3] = algo16; args[4] = aux_rand; for (i = 0; i < count; i++) { nonce_function_bip340_bitflip(args, 0, 32); nonce_function_bip340_bitflip(args, 1, 32); nonce_function_bip340_bitflip(args, 2, 32); /* Flip algo16 special case "BIP0340/nonce" */ nonce_function_bip340_bitflip(args, 3, 16); /* Flip algo16 again */ nonce_function_bip340_bitflip(args, 3, 16); nonce_function_bip340_bitflip(args, 4, 32); } /* NULL algo16 is disallowed */ CHECK(nonce_function_bip340(nonce, msg, key, pk, NULL, NULL) == 0); /* Empty algo16 is fine */ memset(algo16, 0x00, 16); CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1); /* algo16 with terminating null bytes is fine */ algo16[1] = 65; CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1); /* Other algo16 is fine */ memset(algo16, 0xFF, 16); CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1); /* NULL aux_rand argument is allowed. */ CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1); } void test_schnorrsig_api(void) { unsigned char sk1[32]; unsigned char sk2[32]; unsigned char sk3[32]; unsigned char msg[32]; secp256k1_keypair keypairs[3]; secp256k1_keypair invalid_keypair = { 0 }; secp256k1_xonly_pubkey pk[3]; secp256k1_xonly_pubkey zero_pk; unsigned char sig[64]; /** setup **/ 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); int ecount; secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); secp256k1_testrand256(sk1); secp256k1_testrand256(sk2); secp256k1_testrand256(sk3); secp256k1_testrand256(msg); CHECK(secp256k1_keypair_create(ctx, &keypairs[0], sk1) == 1); CHECK(secp256k1_keypair_create(ctx, &keypairs[1], sk2) == 1); CHECK(secp256k1_keypair_create(ctx, &keypairs[2], sk3) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[0], NULL, &keypairs[0]) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[1], NULL, &keypairs[1]) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[2], NULL, &keypairs[2]) == 1); memset(&zero_pk, 0, sizeof(zero_pk)); /** main test body **/ ecount = 0; CHECK(secp256k1_schnorrsig_sign(none, sig, msg, &keypairs[0], NULL, NULL) == 0); CHECK(ecount == 1); CHECK(secp256k1_schnorrsig_sign(vrfy, sig, msg, &keypairs[0], NULL, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL, NULL) == 1); CHECK(ecount == 2); CHECK(secp256k1_schnorrsig_sign(sign, NULL, msg, &keypairs[0], NULL, NULL) == 0); CHECK(ecount == 3); CHECK(secp256k1_schnorrsig_sign(sign, sig, NULL, &keypairs[0], NULL, NULL) == 0); CHECK(ecount == 4); CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, NULL, NULL, NULL) == 0); CHECK(ecount == 5); CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &invalid_keypair, NULL, NULL) == 0); CHECK(ecount == 6); ecount = 0; CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL, NULL) == 1); CHECK(secp256k1_schnorrsig_verify(none, sig, msg, &pk[0]) == 0); CHECK(ecount == 1); CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, &pk[0]) == 0); CHECK(ecount == 2); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, &pk[0]) == 1); CHECK(ecount == 2); CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, &pk[0]) == 0); CHECK(ecount == 3); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, &pk[0]) == 0); CHECK(ecount == 4); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, NULL) == 0); CHECK(ecount == 5); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, &zero_pk) == 0); CHECK(ecount == 6); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(vrfy); secp256k1_context_destroy(both); } /* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the * expected state. */ void test_schnorrsig_sha256_tagged(void) { char tag[17] = "BIP0340/challenge"; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag)); secp256k1_schnorrsig_sha256_tagged(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); } /* Helper function for schnorrsig_bip_vectors * Signs the message and checks that it's the same as expected_sig. */ void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, unsigned char *aux_rand, const unsigned char *msg, const unsigned char *expected_sig) { unsigned char sig[64]; secp256k1_keypair keypair; secp256k1_xonly_pubkey pk, pk_expected; CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, aux_rand)); CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0); CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk_expected, pk_serialized)); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair)); CHECK(secp256k1_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0); CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &pk)); } /* Helper function for schnorrsig_bip_vectors * Checks that both verify and verify_batch (TODO) return the same value as expected. */ void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg32, const unsigned char *sig, int expected) { secp256k1_xonly_pubkey pk; CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk, pk_serialized)); CHECK(expected == secp256k1_schnorrsig_verify(ctx, sig, msg32, &pk)); } /* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See * https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv. */ void test_schnorrsig_bip_vectors(void) { { /* Test vector 0 */ const unsigned char sk[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, 0x03 }; const unsigned char pk[32] = { 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }; unsigned char aux_rand[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, 0x00 }; const unsigned char msg[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, 0x00 }; const unsigned char sig[64] = { 0xE9, 0x07, 0x83, 0x1F, 0x80, 0x84, 0x8D, 0x10, 0x69, 0xA5, 0x37, 0x1B, 0x40, 0x24, 0x10, 0x36, 0x4B, 0xDF, 0x1C, 0x5F, 0x83, 0x07, 0xB0, 0x08, 0x4C, 0x55, 0xF1, 0xCE, 0x2D, 0xCA, 0x82, 0x15, 0x25, 0xF6, 0x6A, 0x4A, 0x85, 0xEA, 0x8B, 0x71, 0xE4, 0x82, 0xA7, 0x4F, 0x38, 0x2D, 0x2C, 0xE5, 0xEB, 0xEE, 0xE8, 0xFD, 0xB2, 0x17, 0x2F, 0x47, 0x7D, 0xF4, 0x90, 0x0D, 0x31, 0x05, 0x36, 0xC0 }; test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig); test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 1 */ const unsigned char sk[32] = { 0xB7, 0xE1, 0x51, 0x62, 0x8A, 0xED, 0x2A, 0x6A, 0xBF, 0x71, 0x58, 0x80, 0x9C, 0xF4, 0xF3, 0xC7, 0x62, 0xE7, 0x16, 0x0F, 0x38, 0xB4, 0xDA, 0x56, 0xA7, 0x84, 0xD9, 0x04, 0x51, 0x90, 0xCF, 0xEF }; const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; unsigned char aux_rand[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 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x68, 0x96, 0xBD, 0x60, 0xEE, 0xAE, 0x29, 0x6D, 0xB4, 0x8A, 0x22, 0x9F, 0xF7, 0x1D, 0xFE, 0x07, 0x1B, 0xDE, 0x41, 0x3E, 0x6D, 0x43, 0xF9, 0x17, 0xDC, 0x8D, 0xCF, 0x8C, 0x78, 0xDE, 0x33, 0x41, 0x89, 0x06, 0xD1, 0x1A, 0xC9, 0x76, 0xAB, 0xCC, 0xB2, 0x0B, 0x09, 0x12, 0x92, 0xBF, 0xF4, 0xEA, 0x89, 0x7E, 0xFC, 0xB6, 0x39, 0xEA, 0x87, 0x1C, 0xFA, 0x95, 0xF6, 0xDE, 0x33, 0x9E, 0x4B, 0x0A }; test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig); test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 2 */ const unsigned char sk[32] = { 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x14, 0xE5, 0xC9 }; const unsigned char pk[32] = { 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 }; unsigned char aux_rand[32] = { 0xC8, 0x7A, 0xA5, 0x38, 0x24, 0xB4, 0xD7, 0xAE, 0x2E, 0xB0, 0x35, 0xA2, 0xB5, 0xBB, 0xBC, 0xCC, 0x08, 0x0E, 0x76, 0xCD, 0xC6, 0xD1, 0x69, 0x2C, 0x4B, 0x0B, 0x62, 0xD7, 0x98, 0xE6, 0xD9, 0x06 }; const unsigned char msg[32] = { 0x7E, 0x2D, 0x58, 0xD8, 0xB3, 0xBC, 0xDF, 0x1A, 0xBA, 0xDE, 0xC7, 0x82, 0x90, 0x54, 0xF9, 0x0D, 0xDA, 0x98, 0x05, 0xAA, 0xB5, 0x6C, 0x77, 0x33, 0x30, 0x24, 0xB9, 0xD0, 0xA5, 0x08, 0xB7, 0x5C }; const unsigned char sig[64] = { 0x58, 0x31, 0xAA, 0xEE, 0xD7, 0xB4, 0x4B, 0xB7, 0x4E, 0x5E, 0xAB, 0x94, 0xBA, 0x9D, 0x42, 0x94, 0xC4, 0x9B, 0xCF, 0x2A, 0x60, 0x72, 0x8D, 0x8B, 0x4C, 0x20, 0x0F, 0x50, 0xDD, 0x31, 0x3C, 0x1B, 0xAB, 0x74, 0x58, 0x79, 0xA5, 0xAD, 0x95, 0x4A, 0x72, 0xC4, 0x5A, 0x91, 0xC3, 0xA5, 0x1D, 0x3C, 0x7A, 0xDE, 0xA9, 0x8D, 0x82, 0xF8, 0x48, 0x1E, 0x0E, 0x1E, 0x03, 0x67, 0x4A, 0x6F, 0x3F, 0xB7 }; test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig); test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 3 */ const unsigned char sk[32] = { 0x0B, 0x43, 0x2B, 0x26, 0x77, 0x93, 0x73, 0x81, 0xAE, 0xF0, 0x5B, 0xB0, 0x2A, 0x66, 0xEC, 0xD0, 0x12, 0x77, 0x30, 0x62, 0xCF, 0x3F, 0xA2, 0x54, 0x9E, 0x44, 0xF5, 0x8E, 0xD2, 0x40, 0x17, 0x10 }; const unsigned char pk[32] = { 0x25, 0xD1, 0xDF, 0xF9, 0x51, 0x05, 0xF5, 0x25, 0x3C, 0x40, 0x22, 0xF6, 0x28, 0xA9, 0x96, 0xAD, 0x3A, 0x0D, 0x95, 0xFB, 0xF2, 0x1D, 0x46, 0x8A, 0x1B, 0x33, 0xF8, 0xC1, 0x60, 0xD8, 0xF5, 0x17 }; unsigned char aux_rand[32] = { 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 }; const unsigned char msg[32] = { 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 }; const unsigned char sig[64] = { 0x7E, 0xB0, 0x50, 0x97, 0x57, 0xE2, 0x46, 0xF1, 0x94, 0x49, 0x88, 0x56, 0x51, 0x61, 0x1C, 0xB9, 0x65, 0xEC, 0xC1, 0xA1, 0x87, 0xDD, 0x51, 0xB6, 0x4F, 0xDA, 0x1E, 0xDC, 0x96, 0x37, 0xD5, 0xEC, 0x97, 0x58, 0x2B, 0x9C, 0xB1, 0x3D, 0xB3, 0x93, 0x37, 0x05, 0xB3, 0x2B, 0xA9, 0x82, 0xAF, 0x5A, 0xF2, 0x5F, 0xD7, 0x88, 0x81, 0xEB, 0xB3, 0x27, 0x71, 0xFC, 0x59, 0x22, 0xEF, 0xC6, 0x6E, 0xA3 }; test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig); test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 4 */ const unsigned char pk[32] = { 0xD6, 0x9C, 0x35, 0x09, 0xBB, 0x99, 0xE4, 0x12, 0xE6, 0x8B, 0x0F, 0xE8, 0x54, 0x4E, 0x72, 0x83, 0x7D, 0xFA, 0x30, 0x74, 0x6D, 0x8B, 0xE2, 0xAA, 0x65, 0x97, 0x5F, 0x29, 0xD2, 0x2D, 0xC7, 0xB9 }; const unsigned char msg[32] = { 0x4D, 0xF3, 0xC3, 0xF6, 0x8F, 0xCC, 0x83, 0xB2, 0x7E, 0x9D, 0x42, 0xC9, 0x04, 0x31, 0xA7, 0x24, 0x99, 0xF1, 0x78, 0x75, 0xC8, 0x1A, 0x59, 0x9B, 0x56, 0x6C, 0x98, 0x89, 0xB9, 0x69, 0x67, 0x03 }; const unsigned char sig[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x78, 0xCE, 0x56, 0x3F, 0x89, 0xA0, 0xED, 0x94, 0x14, 0xF5, 0xAA, 0x28, 0xAD, 0x0D, 0x96, 0xD6, 0x79, 0x5F, 0x9C, 0x63, 0x76, 0xAF, 0xB1, 0x54, 0x8A, 0xF6, 0x03, 0xB3, 0xEB, 0x45, 0xC9, 0xF8, 0x20, 0x7D, 0xEE, 0x10, 0x60, 0xCB, 0x71, 0xC0, 0x4E, 0x80, 0xF5, 0x93, 0x06, 0x0B, 0x07, 0xD2, 0x83, 0x08, 0xD7, 0xF4 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 5 */ const unsigned char pk[32] = { 0xEE, 0xFD, 0xEA, 0x4C, 0xDB, 0x67, 0x77, 0x50, 0xA4, 0x20, 0xFE, 0xE8, 0x07, 0xEA, 0xCF, 0x21, 0xEB, 0x98, 0x98, 0xAE, 0x79, 0xB9, 0x76, 0x87, 0x66, 0xE4, 0xFA, 0xA0, 0x4A, 0x2D, 0x4A, 0x34 }; secp256k1_xonly_pubkey pk_parsed; /* No need to check the signature of the test vector as parsing the pubkey already fails */ CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk_parsed, pk)); } { /* Test vector 6 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0xFF, 0xF9, 0x7B, 0xD5, 0x75, 0x5E, 0xEE, 0xA4, 0x20, 0x45, 0x3A, 0x14, 0x35, 0x52, 0x35, 0xD3, 0x82, 0xF6, 0x47, 0x2F, 0x85, 0x68, 0xA1, 0x8B, 0x2F, 0x05, 0x7A, 0x14, 0x60, 0x29, 0x75, 0x56, 0x3C, 0xC2, 0x79, 0x44, 0x64, 0x0A, 0xC6, 0x07, 0xCD, 0x10, 0x7A, 0xE1, 0x09, 0x23, 0xD9, 0xEF, 0x7A, 0x73, 0xC6, 0x43, 0xE1, 0x66, 0xBE, 0x5E, 0xBE, 0xAF, 0xA3, 0x4B, 0x1A, 0xC5, 0x53, 0xE2 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 7 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x1F, 0xA6, 0x2E, 0x33, 0x1E, 0xDB, 0xC2, 0x1C, 0x39, 0x47, 0x92, 0xD2, 0xAB, 0x11, 0x00, 0xA7, 0xB4, 0x32, 0xB0, 0x13, 0xDF, 0x3F, 0x6F, 0xF4, 0xF9, 0x9F, 0xCB, 0x33, 0xE0, 0xE1, 0x51, 0x5F, 0x28, 0x89, 0x0B, 0x3E, 0xDB, 0x6E, 0x71, 0x89, 0xB6, 0x30, 0x44, 0x8B, 0x51, 0x5C, 0xE4, 0xF8, 0x62, 0x2A, 0x95, 0x4C, 0xFE, 0x54, 0x57, 0x35, 0xAA, 0xEA, 0x51, 0x34, 0xFC, 0xCD, 0xB2, 0xBD }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 8 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x6C, 0xFF, 0x5C, 0x3B, 0xA8, 0x6C, 0x69, 0xEA, 0x4B, 0x73, 0x76, 0xF3, 0x1A, 0x9B, 0xCB, 0x4F, 0x74, 0xC1, 0x97, 0x60, 0x89, 0xB2, 0xD9, 0x96, 0x3D, 0xA2, 0xE5, 0x54, 0x3E, 0x17, 0x77, 0x69, 0x96, 0x17, 0x64, 0xB3, 0xAA, 0x9B, 0x2F, 0xFC, 0xB6, 0xEF, 0x94, 0x7B, 0x68, 0x87, 0xA2, 0x26, 0xE8, 0xD7, 0xC9, 0x3E, 0x00, 0xC5, 0xED, 0x0C, 0x18, 0x34, 0xFF, 0x0D, 0x0C, 0x2E, 0x6D, 0xA6 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 9 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 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, 0x12, 0x3D, 0xDA, 0x83, 0x28, 0xAF, 0x9C, 0x23, 0xA9, 0x4C, 0x1F, 0xEE, 0xCF, 0xD1, 0x23, 0xBA, 0x4F, 0xB7, 0x34, 0x76, 0xF0, 0xD5, 0x94, 0xDC, 0xB6, 0x5C, 0x64, 0x25, 0xBD, 0x18, 0x60, 0x51 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 10 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 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, 0x76, 0x15, 0xFB, 0xAF, 0x5A, 0xE2, 0x88, 0x64, 0x01, 0x3C, 0x09, 0x97, 0x42, 0xDE, 0xAD, 0xB4, 0xDB, 0xA8, 0x7F, 0x11, 0xAC, 0x67, 0x54, 0xF9, 0x37, 0x80, 0xD5, 0xA1, 0x83, 0x7C, 0xF1, 0x97 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 11 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x4A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x69, 0xE8, 0x9B, 0x4C, 0x55, 0x64, 0xD0, 0x03, 0x49, 0x10, 0x6B, 0x84, 0x97, 0x78, 0x5D, 0xD7, 0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F, 0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 12 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[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, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, 0x69, 0xE8, 0x9B, 0x4C, 0x55, 0x64, 0xD0, 0x03, 0x49, 0x10, 0x6B, 0x84, 0x97, 0x78, 0x5D, 0xD7, 0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F, 0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 13 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x6C, 0xFF, 0x5C, 0x3B, 0xA8, 0x6C, 0x69, 0xEA, 0x4B, 0x73, 0x76, 0xF3, 0x1A, 0x9B, 0xCB, 0x4F, 0x74, 0xC1, 0x97, 0x60, 0x89, 0xB2, 0xD9, 0x96, 0x3D, 0xA2, 0xE5, 0x54, 0x3E, 0x17, 0x77, 0x69, 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 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 14 */ const unsigned char pk[32] = { 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 }; secp256k1_xonly_pubkey pk_parsed; /* No need to check the signature of the test vector as parsing the pubkey already fails */ CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk_parsed, pk)); } } /* Nonce function that returns constant 0 */ static int nonce_function_failing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) { (void) msg32; (void) key32; (void) xonly_pk32; (void) algo16; (void) data; (void) nonce32; return 0; } /* Nonce function that sets nonce to 0 */ static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) { (void) msg32; (void) key32; (void) xonly_pk32; (void) algo16; (void) data; memset(nonce32, 0, 32); return 1; } /* Nonce function that sets nonce to 0xFF...0xFF */ static int nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) { (void) msg32; (void) key32; (void) xonly_pk32; (void) algo16; (void) data; memset(nonce32, 0xFF, 32); return 1; } void test_schnorrsig_sign(void) { unsigned char sk[32]; secp256k1_keypair keypair; const unsigned char msg[32] = "this is a msg for a schnorrsig.."; unsigned char sig[64]; unsigned char zeros64[64] = { 0 }; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL) == 1); /* Test different nonce functions */ memset(sig, 1, sizeof(sig)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_failing, NULL) == 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0); memset(&sig, 1, sizeof(sig)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_0, NULL) == 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_overflowing, NULL) == 1); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) != 0); } #define N_SIGS 3 /* Creates N_SIGS valid signatures and verifies them with verify and * verify_batch (TODO). Then flips some bits and checks that verification now * fails. */ void test_schnorrsig_sign_verify(void) { unsigned char sk[32]; unsigned char msg[N_SIGS][32]; unsigned char sig[N_SIGS][64]; size_t i; secp256k1_keypair keypair; secp256k1_xonly_pubkey pk; secp256k1_scalar s; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair)); for (i = 0; i < N_SIGS; i++) { secp256k1_testrand256(msg[i]); CHECK(secp256k1_schnorrsig_sign(ctx, sig[i], msg[i], &keypair, NULL, NULL)); CHECK(secp256k1_schnorrsig_verify(ctx, sig[i], msg[i], &pk)); } { /* Flip a few bits in the signature and in the message and check that * verify and verify_batch (TODO) fail */ size_t sig_idx = secp256k1_testrand_int(N_SIGS); size_t byte_idx = secp256k1_testrand_int(32); unsigned char xorbyte = secp256k1_testrand_int(254)+1; sig[sig_idx][byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk)); sig[sig_idx][byte_idx] ^= xorbyte; byte_idx = secp256k1_testrand_int(32); sig[sig_idx][32+byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk)); sig[sig_idx][32+byte_idx] ^= xorbyte; byte_idx = secp256k1_testrand_int(32); msg[sig_idx][byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk)); msg[sig_idx][byte_idx] ^= xorbyte; /* Check that above bitflips have been reversed correctly */ CHECK(secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk)); } /* Test overflowing s */ CHECK(secp256k1_schnorrsig_sign(ctx, sig[0], msg[0], &keypair, NULL, NULL)); CHECK(secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk)); memset(&sig[0][32], 0xFF, 32); CHECK(!secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk)); /* Test negative s */ CHECK(secp256k1_schnorrsig_sign(ctx, sig[0], msg[0], &keypair, NULL, NULL)); CHECK(secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk)); secp256k1_scalar_set_b32(&s, &sig[0][32], NULL); secp256k1_scalar_negate(&s, &s); secp256k1_scalar_get_b32(&sig[0][32], &s); CHECK(!secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk)); } #undef N_SIGS void test_schnorrsig_taproot(void) { unsigned char sk[32]; secp256k1_keypair keypair; secp256k1_xonly_pubkey internal_pk; unsigned char internal_pk_bytes[32]; secp256k1_xonly_pubkey output_pk; unsigned char output_pk_bytes[32]; unsigned char tweak[32]; int pk_parity; unsigned char msg[32]; unsigned char sig[64]; /* Create output key */ secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &internal_pk, NULL, &keypair) == 1); /* In actual taproot the tweak would be hash of internal_pk */ CHECK(secp256k1_xonly_pubkey_serialize(ctx, tweak, &internal_pk) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &output_pk, &pk_parity, &keypair) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk_bytes, &output_pk) == 1); /* Key spend */ secp256k1_testrand256(msg); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL) == 1); /* Verify key spend */ CHECK(secp256k1_xonly_pubkey_parse(ctx, &output_pk, output_pk_bytes) == 1); CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &output_pk) == 1); /* Script spend */ CHECK(secp256k1_xonly_pubkey_serialize(ctx, internal_pk_bytes, &internal_pk) == 1); /* Verify script spend */ CHECK(secp256k1_xonly_pubkey_parse(ctx, &internal_pk, internal_pk_bytes) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1); } void run_schnorrsig_tests(void) { int i; run_nonce_function_bip340_tests(); test_schnorrsig_api(); test_schnorrsig_sha256_tagged(); test_schnorrsig_bip_vectors(); for (i = 0; i < count; i++) { test_schnorrsig_sign(); test_schnorrsig_sign_verify(); } test_schnorrsig_taproot(); } #endif diff --git a/src/secp256k1/src/num.h b/src/secp256k1/src/num.h index 49f2dd791..59a5cf2d7 100644 --- a/src/secp256k1/src/num.h +++ b/src/secp256k1/src/num.h @@ -1,74 +1,74 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_NUM_H #define SECP256K1_NUM_H #ifndef USE_NUM_NONE #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #if defined(USE_NUM_GMP) #include "num_gmp.h" #else #error "Please select num implementation" #endif /** Copy a number. */ static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a); /** Convert a number's absolute value to a binary big-endian string. * There must be enough place. */ static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a); /** Set a number to the value of a binary big-endian string. */ static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen); /** Compute a modular inverse. The input must be less than the modulus. */ static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m); /** Compute the jacobi symbol (a|b). b must be positive and odd. */ static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b); /** Compare the absolute value of two numbers. */ static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b); /** Test whether two number are equal (including sign). */ static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b); /** Add two (signed) numbers. */ static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); /** Subtract two (signed) numbers. */ static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); /** Multiply two (signed) numbers. */ static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); /** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1, even if r was negative. */ static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m); /** Right-shift the passed number by bits bits. */ static void secp256k1_num_shift(secp256k1_num *r, int bits); /** Check whether a number is zero. */ static int secp256k1_num_is_zero(const secp256k1_num *a); /** Check whether a number is one. */ static int secp256k1_num_is_one(const secp256k1_num *a); /** Check whether a number is strictly negative. */ static int secp256k1_num_is_neg(const secp256k1_num *a); /** Change a number's sign. */ static void secp256k1_num_negate(secp256k1_num *r); #endif #endif /* SECP256K1_NUM_H */ diff --git a/src/secp256k1/src/num_gmp.h b/src/secp256k1/src/num_gmp.h index 3619844bd..cc6c51a5f 100644 --- a/src/secp256k1/src/num_gmp.h +++ b/src/secp256k1/src/num_gmp.h @@ -1,20 +1,20 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_NUM_REPR_H #define SECP256K1_NUM_REPR_H #include #define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS) typedef struct { mp_limb_t data[2*NUM_LIMBS]; int neg; int limbs; } secp256k1_num; #endif /* SECP256K1_NUM_REPR_H */ diff --git a/src/secp256k1/src/num_gmp_impl.h b/src/secp256k1/src/num_gmp_impl.h index 0ae2a8ba0..c07947dd9 100644 --- a/src/secp256k1/src/num_gmp_impl.h +++ b/src/secp256k1/src/num_gmp_impl.h @@ -1,288 +1,288 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_NUM_REPR_IMPL_H #define SECP256K1_NUM_REPR_IMPL_H #include #include #include #include "util.h" #include "num.h" #ifdef VERIFY static void secp256k1_num_sanity(const secp256k1_num *a) { VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0)); } #else #define secp256k1_num_sanity(a) do { } while(0) #endif static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a) { *r = *a; } static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a) { unsigned char tmp[65]; int len = 0; int shift = 0; if (a->limbs>1 || a->data[0] != 0) { len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs); } while (shift < len && tmp[shift] == 0) shift++; VERIFY_CHECK(len-shift <= (int)rlen); memset(r, 0, rlen - len + shift); if (len > shift) { memcpy(r + rlen - len + shift, tmp + shift, len - shift); } memset(tmp, 0, sizeof(tmp)); } static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) { int len; VERIFY_CHECK(alen > 0); VERIFY_CHECK(alen <= 64); len = mpn_set_str(r->data, a, alen, 256); if (len == 0) { r->data[0] = 0; len = 1; } VERIFY_CHECK(len <= NUM_LIMBS*2); r->limbs = len; r->neg = 0; while (r->limbs > 1 && r->data[r->limbs-1]==0) { r->limbs--; } } static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); r->limbs = a->limbs; if (c != 0) { VERIFY_CHECK(r->limbs < 2*NUM_LIMBS); r->data[r->limbs++] = c; } } static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); (void)c; VERIFY_CHECK(c == 0); r->limbs = a->limbs; while (r->limbs > 1 && r->data[r->limbs-1]==0) { r->limbs--; } } static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) { secp256k1_num_sanity(r); secp256k1_num_sanity(m); if (r->limbs >= m->limbs) { mp_limb_t t[2*NUM_LIMBS]; mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs); memset(t, 0, sizeof(t)); r->limbs = m->limbs; while (r->limbs > 1 && r->data[r->limbs-1]==0) { r->limbs--; } } if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { secp256k1_num_sub_abs(r, m, r); r->neg = 0; } } static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m) { int i; mp_limb_t g[NUM_LIMBS+1]; mp_limb_t u[NUM_LIMBS+1]; mp_limb_t v[NUM_LIMBS+1]; mp_size_t sn; mp_size_t gn; secp256k1_num_sanity(a); secp256k1_num_sanity(m); /** mpn_gcdext computes: (G,S) = gcdext(U,V), where * * G = gcd(U,V) * * G = U*S + V*T * * U has equal or more limbs than V, and V has no padding * If we set U to be (a padded version of) a, and V = m: * G = a*S + m*T * G = a*S mod m * Assuming G=1: * S = 1/a mod m */ VERIFY_CHECK(m->limbs <= NUM_LIMBS); VERIFY_CHECK(m->data[m->limbs-1] != 0); for (i = 0; i < m->limbs; i++) { u[i] = (i < a->limbs) ? a->data[i] : 0; v[i] = m->data[i]; } sn = NUM_LIMBS+1; gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs); (void)gn; VERIFY_CHECK(gn == 1); VERIFY_CHECK(g[0] == 1); r->neg = a->neg ^ m->neg; if (sn < 0) { mpn_sub(r->data, m->data, m->limbs, r->data, -sn); r->limbs = m->limbs; while (r->limbs > 1 && r->data[r->limbs-1]==0) { r->limbs--; } } else { r->limbs = sn; } memset(g, 0, sizeof(g)); memset(u, 0, sizeof(u)); memset(v, 0, sizeof(v)); } static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b) { int ret; mpz_t ga, gb; secp256k1_num_sanity(a); secp256k1_num_sanity(b); VERIFY_CHECK(!b->neg && (b->limbs > 0) && (b->data[0] & 1)); mpz_inits(ga, gb, NULL); mpz_import(gb, b->limbs, -1, sizeof(mp_limb_t), 0, 0, b->data); mpz_import(ga, a->limbs, -1, sizeof(mp_limb_t), 0, 0, a->data); if (a->neg) { mpz_neg(ga, ga); } ret = mpz_jacobi(ga, gb); mpz_clears(ga, gb, NULL); return ret; } static int secp256k1_num_is_one(const secp256k1_num *a) { return (a->limbs == 1 && a->data[0] == 1); } static int secp256k1_num_is_zero(const secp256k1_num *a) { return (a->limbs == 1 && a->data[0] == 0); } static int secp256k1_num_is_neg(const secp256k1_num *a) { return (a->limbs > 1 || a->data[0] != 0) && a->neg; } static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b) { if (a->limbs > b->limbs) { return 1; } if (a->limbs < b->limbs) { return -1; } return mpn_cmp(a->data, b->data, a->limbs); } static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b) { if (a->limbs > b->limbs) { return 0; } if (a->limbs < b->limbs) { return 0; } if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) { return 0; } return mpn_cmp(a->data, b->data, a->limbs) == 0; } static void secp256k1_num_subadd(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b, int bneg) { if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */ r->neg = a->neg; if (a->limbs >= b->limbs) { secp256k1_num_add_abs(r, a, b); } else { secp256k1_num_add_abs(r, b, a); } } else { if (secp256k1_num_cmp(a, b) > 0) { r->neg = a->neg; secp256k1_num_sub_abs(r, a, b); } else { r->neg = b->neg ^ bneg; secp256k1_num_sub_abs(r, b, a); } } } static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { secp256k1_num_sanity(a); secp256k1_num_sanity(b); secp256k1_num_subadd(r, a, b, 0); } static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { secp256k1_num_sanity(a); secp256k1_num_sanity(b); secp256k1_num_subadd(r, a, b, 1); } static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { mp_limb_t tmp[2*NUM_LIMBS+1]; secp256k1_num_sanity(a); secp256k1_num_sanity(b); VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1); if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) { r->limbs = 1; r->neg = 0; r->data[0] = 0; return; } if (a->limbs >= b->limbs) { mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs); } else { mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs); } r->limbs = a->limbs + b->limbs; if (r->limbs > 1 && tmp[r->limbs - 1]==0) { r->limbs--; } VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS); mpn_copyi(r->data, tmp, r->limbs); r->neg = a->neg ^ b->neg; memset(tmp, 0, sizeof(tmp)); } static void secp256k1_num_shift(secp256k1_num *r, int bits) { if (bits % GMP_NUMB_BITS) { /* Shift within limbs. */ mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS); } if (bits >= GMP_NUMB_BITS) { int i; /* Shift full limbs. */ for (i = 0; i < r->limbs; i++) { int index = i + (bits / GMP_NUMB_BITS); if (index < r->limbs && index < 2*NUM_LIMBS) { r->data[i] = r->data[index]; } else { r->data[i] = 0; } } } while (r->limbs>1 && r->data[r->limbs-1]==0) { r->limbs--; } } static void secp256k1_num_negate(secp256k1_num *r) { r->neg ^= 1; } #endif /* SECP256K1_NUM_REPR_IMPL_H */ diff --git a/src/secp256k1/src/num_impl.h b/src/secp256k1/src/num_impl.h index c45193b03..880598efe 100644 --- a/src/secp256k1/src/num_impl.h +++ b/src/secp256k1/src/num_impl.h @@ -1,24 +1,24 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_NUM_IMPL_H #define SECP256K1_NUM_IMPL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #include "num.h" #if defined(USE_NUM_GMP) #include "num_gmp_impl.h" #elif defined(USE_NUM_NONE) /* Nothing. */ #else #error "Please select num implementation" #endif #endif /* SECP256K1_NUM_IMPL_H */ diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h index fb3fb187c..0b737f940 100644 --- a/src/secp256k1/src/scalar.h +++ b/src/secp256k1/src/scalar.h @@ -1,117 +1,117 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SCALAR_H #define SECP256K1_SCALAR_H #include "num.h" #include "util.h" #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #if defined(EXHAUSTIVE_TEST_ORDER) #include "scalar_low.h" #elif defined(SECP256K1_WIDEMUL_INT128) #include "scalar_4x64.h" #elif defined(SECP256K1_WIDEMUL_INT64) #include "scalar_8x32.h" #else #error "Please select wide multiplication implementation" #endif /** Clear a scalar to prevent the leak of sensitive data. */ static void secp256k1_scalar_clear(secp256k1_scalar *r); /** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count); /** Access bits from a scalar. Not constant time. */ static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); /** Set a scalar from a big endian byte array. The scalar will be reduced modulo group order `n`. * In: bin: pointer to a 32-byte array. * Out: r: scalar to be set. * overflow: non-zero if the scalar was bigger or equal to `n` before reduction, zero otherwise (can be NULL). */ static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); /** Set a scalar from a big endian byte array and returns 1 if it is a valid * seckey and 0 otherwise. */ static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned char *bin); /** Set a scalar to an unsigned integer. */ static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v); /** Convert a scalar to a byte array. */ static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a); /** Add two scalars together (modulo the group order). Returns whether it overflowed. */ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); /** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); /** Multiply two scalars (modulo the group order). */ static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); /** Shift a scalar right by some amount strictly between 0 and 16, returning * the low bits that were shifted off */ static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n); /** Compute the square of a scalar (modulo the group order). */ static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a); /** Compute the inverse of a scalar (modulo the group order). */ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a); /** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a); /** Compute the complement of a scalar (modulo the group order). */ static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a); /** Check whether a scalar equals zero. */ static int secp256k1_scalar_is_zero(const secp256k1_scalar *a); /** Check whether a scalar equals one. */ static int secp256k1_scalar_is_one(const secp256k1_scalar *a); /** Check whether a scalar, considered as an nonnegative integer, is even. */ static int secp256k1_scalar_is_even(const secp256k1_scalar *a); /** Check whether a scalar is higher than the group order divided by 2. */ static int secp256k1_scalar_is_high(const secp256k1_scalar *a); /** Conditionally negate a number, in constant time. * Returns -1 if the number was negated, 1 otherwise */ static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); #ifndef USE_NUM_NONE /** Convert a scalar to a number. */ static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a); /** Get the order of the group as a number. */ static void secp256k1_scalar_order_get_num(secp256k1_num *r); #endif /** Compare two scalars. */ static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); /** Find r1 and r2 such that r1+r2*2^128 = k. */ static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k); /** Find r1 and r2 such that r1+r2*lambda = k, * where r1 and r2 or their negations are maximum 128 bits long (see secp256k1_ge_mul_lambda). */ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k); /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ static void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag); #endif /* SECP256K1_SCALAR_H */ diff --git a/src/secp256k1/src/scalar_4x64.h b/src/secp256k1/src/scalar_4x64.h index 19c7495d1..700964291 100644 --- a/src/secp256k1/src/scalar_4x64.h +++ b/src/secp256k1/src/scalar_4x64.h @@ -1,19 +1,19 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SCALAR_REPR_H #define SECP256K1_SCALAR_REPR_H #include /** A scalar modulo the group order of the secp256k1 curve. */ typedef struct { uint64_t d[4]; } secp256k1_scalar; #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} #endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h index 73cbd5e18..3eaa0418c 100644 --- a/src/secp256k1/src/scalar_4x64_impl.h +++ b/src/secp256k1/src/scalar_4x64_impl.h @@ -1,958 +1,958 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SCALAR_REPR_IMPL_H #define SECP256K1_SCALAR_REPR_IMPL_H /* Limbs of the secp256k1 order. */ #define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) #define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL) #define SECP256K1_N_2 ((uint64_t)0xFFFFFFFFFFFFFFFEULL) #define SECP256K1_N_3 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) /* Limbs of 2^256 minus the secp256k1 order. */ #define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) #define SECP256K1_N_C_1 (~SECP256K1_N_1) #define SECP256K1_N_C_2 (1) /* Limbs of half the secp256k1 order. */ #define SECP256K1_N_H_0 ((uint64_t)0xDFE92F46681B20A0ULL) #define SECP256K1_N_H_1 ((uint64_t)0x5D576E7357A4501DULL) #define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) #define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { r->d[0] = 0; r->d[1] = 0; r->d[2] = 0; r->d[3] = 0; } SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { r->d[0] = v; r->d[1] = 0; r->d[2] = 0; r->d[3] = 0; } SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); } SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { VERIFY_CHECK(count < 32); VERIFY_CHECK(offset + count <= 256); if ((offset + count - 1) >> 6 == offset >> 6) { return secp256k1_scalar_get_bits(a, offset, count); } else { VERIFY_CHECK((offset >> 6) + 1 < 4); return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1); } } SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { int yes = 0; int no = 0; no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ no |= (a->d[2] < SECP256K1_N_2); yes |= (a->d[2] > SECP256K1_N_2) & ~no; no |= (a->d[1] < SECP256K1_N_1); yes |= (a->d[1] > SECP256K1_N_1) & ~no; yes |= (a->d[0] >= SECP256K1_N_0) & ~no; return yes; } SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) { uint128_t t; VERIFY_CHECK(overflow <= 1); t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0; r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1; r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2; r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint64_t)r->d[3]; r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; return overflow; } static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { int overflow; uint128_t t = (uint128_t)a->d[0] + b->d[0]; r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint128_t)a->d[1] + b->d[1]; r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint128_t)a->d[2] + b->d[2]; r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint128_t)a->d[3] + b->d[3]; r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; overflow = t + secp256k1_scalar_check_overflow(r); VERIFY_CHECK(overflow == 0 || overflow == 1); secp256k1_scalar_reduce(r, overflow); return overflow; } static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { uint128_t t; VERIFY_CHECK(bit < 256); bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */ t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; #ifdef VERIFY VERIFY_CHECK((t >> 64) == 0); VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); #endif } static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { int over; r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56; r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56; r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56; r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56; over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); if (overflow) { *overflow = over; } } static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { bin[0] = a->d[3] >> 56; bin[1] = a->d[3] >> 48; bin[2] = a->d[3] >> 40; bin[3] = a->d[3] >> 32; bin[4] = a->d[3] >> 24; bin[5] = a->d[3] >> 16; bin[6] = a->d[3] >> 8; bin[7] = a->d[3]; bin[8] = a->d[2] >> 56; bin[9] = a->d[2] >> 48; bin[10] = a->d[2] >> 40; bin[11] = a->d[2] >> 32; bin[12] = a->d[2] >> 24; bin[13] = a->d[2] >> 16; bin[14] = a->d[2] >> 8; bin[15] = a->d[2]; bin[16] = a->d[1] >> 56; bin[17] = a->d[1] >> 48; bin[18] = a->d[1] >> 40; bin[19] = a->d[1] >> 32; bin[20] = a->d[1] >> 24; bin[21] = a->d[1] >> 16; bin[22] = a->d[1] >> 8; bin[23] = a->d[1]; bin[24] = a->d[0] >> 56; bin[25] = a->d[0] >> 48; bin[26] = a->d[0] >> 40; bin[27] = a->d[0] >> 32; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; } SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; } static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0); uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1; r->d[0] = t & nonzero; t >>= 64; t += (uint128_t)(~a->d[1]) + SECP256K1_N_1; r->d[1] = t & nonzero; t >>= 64; t += (uint128_t)(~a->d[2]) + SECP256K1_N_2; r->d[2] = t & nonzero; t >>= 64; t += (uint128_t)(~a->d[3]) + SECP256K1_N_3; r->d[3] = t & nonzero; } SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; } static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { int yes = 0; int no = 0; no |= (a->d[3] < SECP256K1_N_H_3); yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */ no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; return yes; } static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { /* If we are flag = 0, mask = 00...00 and this is a no-op; * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ uint64_t mask = !flag - 1; uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1; uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); r->d[0] = t & nonzero; t >>= 64; t += (uint128_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); r->d[1] = t & nonzero; t >>= 64; t += (uint128_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); r->d[2] = t & nonzero; t >>= 64; t += (uint128_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); r->d[3] = t & nonzero; return 2 * (mask == 0) - 1; } /* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ /** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ #define muladd(a,b) { \ uint64_t tl, th; \ { \ uint128_t t = (uint128_t)a * b; \ th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ tl = t; \ } \ c0 += tl; /* overflow is handled on the next line */ \ th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \ c1 += th; /* overflow is handled on the next line */ \ c2 += (c1 < th); /* never overflows by contract (verified in the next line) */ \ VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ } /** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ #define muladd_fast(a,b) { \ uint64_t tl, th; \ { \ uint128_t t = (uint128_t)a * b; \ th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ tl = t; \ } \ c0 += tl; /* overflow is handled on the next line */ \ th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \ c1 += th; /* never overflows by contract (verified in the next line) */ \ VERIFY_CHECK(c1 >= th); \ } /** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ #define muladd2(a,b) { \ uint64_t tl, th, th2, tl2; \ { \ uint128_t t = (uint128_t)a * b; \ th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ tl = t; \ } \ th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \ c2 += (th2 < th); /* never overflows by contract (verified the next line) */ \ VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \ th2 += (tl2 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \ c0 += tl2; /* overflow is handled on the next line */ \ th2 += (c0 < tl2); /* second overflow is handled on the next line */ \ c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ c1 += th2; /* overflow is handled on the next line */ \ c2 += (c1 < th2); /* never overflows by contract (verified the next line) */ \ VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ } /** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ #define sumadd(a) { \ unsigned int over; \ c0 += (a); /* overflow is handled on the next line */ \ over = (c0 < (a)); \ c1 += over; /* overflow is handled on the next line */ \ c2 += (c1 < over); /* never overflows by contract */ \ } /** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ #define sumadd_fast(a) { \ c0 += (a); /* overflow is handled on the next line */ \ c1 += (c0 < (a)); /* never overflows by contract (verified the next line) */ \ VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ VERIFY_CHECK(c2 == 0); \ } /** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */ #define extract(n) { \ (n) = c0; \ c0 = c1; \ c1 = c2; \ c2 = 0; \ } /** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. c2 is required to be zero. */ #define extract_fast(n) { \ (n) = c0; \ c0 = c1; \ c1 = 0; \ VERIFY_CHECK(c2 == 0); \ } static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) { #ifdef USE_ASM_X86_64 /* Reduce 512 bits into 385. */ uint64_t m0, m1, m2, m3, m4, m5, m6; uint64_t p0, p1, p2, p3, p4; uint64_t c; __asm__ __volatile__( /* Preload. */ "movq 32(%%rsi), %%r11\n" "movq 40(%%rsi), %%r12\n" "movq 48(%%rsi), %%r13\n" "movq 56(%%rsi), %%r14\n" /* Initialize r8,r9,r10 */ "movq 0(%%rsi), %%r8\n" "xorq %%r9, %%r9\n" "xorq %%r10, %%r10\n" /* (r8,r9) += n0 * c0 */ "movq %8, %%rax\n" "mulq %%r11\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" /* extract m0 */ "movq %%r8, %q0\n" "xorq %%r8, %%r8\n" /* (r9,r10) += l1 */ "addq 8(%%rsi), %%r9\n" "adcq $0, %%r10\n" /* (r9,r10,r8) += n1 * c0 */ "movq %8, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* (r9,r10,r8) += n0 * c1 */ "movq %9, %%rax\n" "mulq %%r11\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* extract m1 */ "movq %%r9, %q1\n" "xorq %%r9, %%r9\n" /* (r10,r8,r9) += l2 */ "addq 16(%%rsi), %%r10\n" "adcq $0, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += n2 * c0 */ "movq %8, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += n1 * c1 */ "movq %9, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += n0 */ "addq %%r11, %%r10\n" "adcq $0, %%r8\n" "adcq $0, %%r9\n" /* extract m2 */ "movq %%r10, %q2\n" "xorq %%r10, %%r10\n" /* (r8,r9,r10) += l3 */ "addq 24(%%rsi), %%r8\n" "adcq $0, %%r9\n" "adcq $0, %%r10\n" /* (r8,r9,r10) += n3 * c0 */ "movq %8, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* (r8,r9,r10) += n2 * c1 */ "movq %9, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* (r8,r9,r10) += n1 */ "addq %%r12, %%r8\n" "adcq $0, %%r9\n" "adcq $0, %%r10\n" /* extract m3 */ "movq %%r8, %q3\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += n3 * c1 */ "movq %9, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* (r9,r10,r8) += n2 */ "addq %%r13, %%r9\n" "adcq $0, %%r10\n" "adcq $0, %%r8\n" /* extract m4 */ "movq %%r9, %q4\n" /* (r10,r8) += n3 */ "addq %%r14, %%r10\n" "adcq $0, %%r8\n" /* extract m5 */ "movq %%r10, %q5\n" /* extract m6 */ "movq %%r8, %q6\n" : "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6) : "S"(l), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc"); /* Reduce 385 bits into 258. */ __asm__ __volatile__( /* Preload */ "movq %q9, %%r11\n" "movq %q10, %%r12\n" "movq %q11, %%r13\n" /* Initialize (r8,r9,r10) */ "movq %q5, %%r8\n" "xorq %%r9, %%r9\n" "xorq %%r10, %%r10\n" /* (r8,r9) += m4 * c0 */ "movq %12, %%rax\n" "mulq %%r11\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" /* extract p0 */ "movq %%r8, %q0\n" "xorq %%r8, %%r8\n" /* (r9,r10) += m1 */ "addq %q6, %%r9\n" "adcq $0, %%r10\n" /* (r9,r10,r8) += m5 * c0 */ "movq %12, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* (r9,r10,r8) += m4 * c1 */ "movq %13, %%rax\n" "mulq %%r11\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* extract p1 */ "movq %%r9, %q1\n" "xorq %%r9, %%r9\n" /* (r10,r8,r9) += m2 */ "addq %q7, %%r10\n" "adcq $0, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += m6 * c0 */ "movq %12, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += m5 * c1 */ "movq %13, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += m4 */ "addq %%r11, %%r10\n" "adcq $0, %%r8\n" "adcq $0, %%r9\n" /* extract p2 */ "movq %%r10, %q2\n" /* (r8,r9) += m3 */ "addq %q8, %%r8\n" "adcq $0, %%r9\n" /* (r8,r9) += m6 * c1 */ "movq %13, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" /* (r8,r9) += m5 */ "addq %%r12, %%r8\n" "adcq $0, %%r9\n" /* extract p3 */ "movq %%r8, %q3\n" /* (r9) += m6 */ "addq %%r13, %%r9\n" /* extract p4 */ "movq %%r9, %q4\n" : "=&g"(p0), "=&g"(p1), "=&g"(p2), "=g"(p3), "=g"(p4) : "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc"); /* Reduce 258 bits into 256. */ __asm__ __volatile__( /* Preload */ "movq %q5, %%r10\n" /* (rax,rdx) = p4 * c0 */ "movq %7, %%rax\n" "mulq %%r10\n" /* (rax,rdx) += p0 */ "addq %q1, %%rax\n" "adcq $0, %%rdx\n" /* extract r0 */ "movq %%rax, 0(%q6)\n" /* Move to (r8,r9) */ "movq %%rdx, %%r8\n" "xorq %%r9, %%r9\n" /* (r8,r9) += p1 */ "addq %q2, %%r8\n" "adcq $0, %%r9\n" /* (r8,r9) += p4 * c1 */ "movq %8, %%rax\n" "mulq %%r10\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" /* Extract r1 */ "movq %%r8, 8(%q6)\n" "xorq %%r8, %%r8\n" /* (r9,r8) += p4 */ "addq %%r10, %%r9\n" "adcq $0, %%r8\n" /* (r9,r8) += p2 */ "addq %q3, %%r9\n" "adcq $0, %%r8\n" /* Extract r2 */ "movq %%r9, 16(%q6)\n" "xorq %%r9, %%r9\n" /* (r8,r9) += p3 */ "addq %q4, %%r8\n" "adcq $0, %%r9\n" /* Extract r3 */ "movq %%r8, 24(%q6)\n" /* Extract c */ "movq %%r9, %q0\n" : "=g"(c) : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) : "rax", "rdx", "r8", "r9", "r10", "cc", "memory"); #else uint128_t c; uint64_t c0, c1, c2; uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7]; uint64_t m0, m1, m2, m3, m4, m5; uint32_t m6; uint64_t p0, p1, p2, p3; uint32_t p4; /* Reduce 512 bits into 385. */ /* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */ c0 = l[0]; c1 = 0; c2 = 0; muladd_fast(n0, SECP256K1_N_C_0); extract_fast(m0); sumadd_fast(l[1]); muladd(n1, SECP256K1_N_C_0); muladd(n0, SECP256K1_N_C_1); extract(m1); sumadd(l[2]); muladd(n2, SECP256K1_N_C_0); muladd(n1, SECP256K1_N_C_1); sumadd(n0); extract(m2); sumadd(l[3]); muladd(n3, SECP256K1_N_C_0); muladd(n2, SECP256K1_N_C_1); sumadd(n1); extract(m3); muladd(n3, SECP256K1_N_C_1); sumadd(n2); extract(m4); sumadd_fast(n3); extract_fast(m5); VERIFY_CHECK(c0 <= 1); m6 = c0; /* Reduce 385 bits into 258. */ /* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */ c0 = m0; c1 = 0; c2 = 0; muladd_fast(m4, SECP256K1_N_C_0); extract_fast(p0); sumadd_fast(m1); muladd(m5, SECP256K1_N_C_0); muladd(m4, SECP256K1_N_C_1); extract(p1); sumadd(m2); muladd(m6, SECP256K1_N_C_0); muladd(m5, SECP256K1_N_C_1); sumadd(m4); extract(p2); sumadd_fast(m3); muladd_fast(m6, SECP256K1_N_C_1); sumadd_fast(m5); extract_fast(p3); p4 = c0 + m6; VERIFY_CHECK(p4 <= 2); /* Reduce 258 bits into 256. */ /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */ c = p0 + (uint128_t)SECP256K1_N_C_0 * p4; r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; c += p1 + (uint128_t)SECP256K1_N_C_1 * p4; r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; c += p2 + (uint128_t)p4; r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; c += p3; r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; #endif /* Final reduction of r. */ secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); } static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, const secp256k1_scalar *b) { #ifdef USE_ASM_X86_64 const uint64_t *pb = b->d; __asm__ __volatile__( /* Preload */ "movq 0(%%rdi), %%r15\n" "movq 8(%%rdi), %%rbx\n" "movq 16(%%rdi), %%rcx\n" "movq 0(%%rdx), %%r11\n" "movq 8(%%rdx), %%r12\n" "movq 16(%%rdx), %%r13\n" "movq 24(%%rdx), %%r14\n" /* (rax,rdx) = a0 * b0 */ "movq %%r15, %%rax\n" "mulq %%r11\n" /* Extract l0 */ "movq %%rax, 0(%%rsi)\n" /* (r8,r9,r10) = (rdx) */ "movq %%rdx, %%r8\n" "xorq %%r9, %%r9\n" "xorq %%r10, %%r10\n" /* (r8,r9,r10) += a0 * b1 */ "movq %%r15, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* (r8,r9,r10) += a1 * b0 */ "movq %%rbx, %%rax\n" "mulq %%r11\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* Extract l1 */ "movq %%r8, 8(%%rsi)\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += a0 * b2 */ "movq %%r15, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* (r9,r10,r8) += a1 * b1 */ "movq %%rbx, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* (r9,r10,r8) += a2 * b0 */ "movq %%rcx, %%rax\n" "mulq %%r11\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* Extract l2 */ "movq %%r9, 16(%%rsi)\n" "xorq %%r9, %%r9\n" /* (r10,r8,r9) += a0 * b3 */ "movq %%r15, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* Preload a3 */ "movq 24(%%rdi), %%r15\n" /* (r10,r8,r9) += a1 * b2 */ "movq %%rbx, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += a2 * b1 */ "movq %%rcx, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += a3 * b0 */ "movq %%r15, %%rax\n" "mulq %%r11\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* Extract l3 */ "movq %%r10, 24(%%rsi)\n" "xorq %%r10, %%r10\n" /* (r8,r9,r10) += a1 * b3 */ "movq %%rbx, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* (r8,r9,r10) += a2 * b2 */ "movq %%rcx, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* (r8,r9,r10) += a3 * b1 */ "movq %%r15, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* Extract l4 */ "movq %%r8, 32(%%rsi)\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += a2 * b3 */ "movq %%rcx, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* (r9,r10,r8) += a3 * b2 */ "movq %%r15, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* Extract l5 */ "movq %%r9, 40(%%rsi)\n" /* (r10,r8) += a3 * b3 */ "movq %%r15, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" /* Extract l6 */ "movq %%r10, 48(%%rsi)\n" /* Extract l7 */ "movq %%r8, 56(%%rsi)\n" : "+d"(pb) : "S"(l), "D"(a->d) : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory"); #else /* 160 bit accumulator. */ uint64_t c0 = 0, c1 = 0; uint32_t c2 = 0; /* l[0..7] = a[0..3] * b[0..3]. */ muladd_fast(a->d[0], b->d[0]); extract_fast(l[0]); muladd(a->d[0], b->d[1]); muladd(a->d[1], b->d[0]); extract(l[1]); muladd(a->d[0], b->d[2]); muladd(a->d[1], b->d[1]); muladd(a->d[2], b->d[0]); extract(l[2]); muladd(a->d[0], b->d[3]); muladd(a->d[1], b->d[2]); muladd(a->d[2], b->d[1]); muladd(a->d[3], b->d[0]); extract(l[3]); muladd(a->d[1], b->d[3]); muladd(a->d[2], b->d[2]); muladd(a->d[3], b->d[1]); extract(l[4]); muladd(a->d[2], b->d[3]); muladd(a->d[3], b->d[2]); extract(l[5]); muladd_fast(a->d[3], b->d[3]); extract_fast(l[6]); VERIFY_CHECK(c1 == 0); l[7] = c0; #endif } static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { #ifdef USE_ASM_X86_64 __asm__ __volatile__( /* Preload */ "movq 0(%%rdi), %%r11\n" "movq 8(%%rdi), %%r12\n" "movq 16(%%rdi), %%r13\n" "movq 24(%%rdi), %%r14\n" /* (rax,rdx) = a0 * a0 */ "movq %%r11, %%rax\n" "mulq %%r11\n" /* Extract l0 */ "movq %%rax, 0(%%rsi)\n" /* (r8,r9,r10) = (rdx,0) */ "movq %%rdx, %%r8\n" "xorq %%r9, %%r9\n" "xorq %%r10, %%r10\n" /* (r8,r9,r10) += 2 * a0 * a1 */ "movq %%r11, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* Extract l1 */ "movq %%r8, 8(%%rsi)\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += 2 * a0 * a2 */ "movq %%r11, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* (r9,r10,r8) += a1 * a1 */ "movq %%r12, %%rax\n" "mulq %%r12\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* Extract l2 */ "movq %%r9, 16(%%rsi)\n" "xorq %%r9, %%r9\n" /* (r10,r8,r9) += 2 * a0 * a3 */ "movq %%r11, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* (r10,r8,r9) += 2 * a1 * a2 */ "movq %%r12, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" /* Extract l3 */ "movq %%r10, 24(%%rsi)\n" "xorq %%r10, %%r10\n" /* (r8,r9,r10) += 2 * a1 * a3 */ "movq %%r12, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* (r8,r9,r10) += a2 * a2 */ "movq %%r13, %%rax\n" "mulq %%r13\n" "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" /* Extract l4 */ "movq %%r8, 32(%%rsi)\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += 2 * a2 * a3 */ "movq %%r13, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" /* Extract l5 */ "movq %%r9, 40(%%rsi)\n" /* (r10,r8) += a3 * a3 */ "movq %%r14, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" /* Extract l6 */ "movq %%r10, 48(%%rsi)\n" /* Extract l7 */ "movq %%r8, 56(%%rsi)\n" : : "S"(l), "D"(a->d) : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc", "memory"); #else /* 160 bit accumulator. */ uint64_t c0 = 0, c1 = 0; uint32_t c2 = 0; /* l[0..7] = a[0..3] * b[0..3]. */ muladd_fast(a->d[0], a->d[0]); extract_fast(l[0]); muladd2(a->d[0], a->d[1]); extract(l[1]); muladd2(a->d[0], a->d[2]); muladd(a->d[1], a->d[1]); extract(l[2]); muladd2(a->d[0], a->d[3]); muladd2(a->d[1], a->d[2]); extract(l[3]); muladd2(a->d[1], a->d[3]); muladd(a->d[2], a->d[2]); extract(l[4]); muladd2(a->d[2], a->d[3]); extract(l[5]); muladd_fast(a->d[3], a->d[3]); extract_fast(l[6]); VERIFY_CHECK(c1 == 0); l[7] = c0; #endif } #undef sumadd #undef sumadd_fast #undef muladd #undef muladd_fast #undef muladd2 #undef extract #undef extract_fast static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { uint64_t l[8]; secp256k1_scalar_mul_512(l, a, b); secp256k1_scalar_reduce_512(r, l); } static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { int ret; VERIFY_CHECK(n > 0); VERIFY_CHECK(n < 16); ret = r->d[0] & ((1 << n) - 1); r->d[0] = (r->d[0] >> n) + (r->d[1] << (64 - n)); r->d[1] = (r->d[1] >> n) + (r->d[2] << (64 - n)); r->d[2] = (r->d[2] >> n) + (r->d[3] << (64 - n)); r->d[3] = (r->d[3] >> n); return ret; } static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { uint64_t l[8]; secp256k1_scalar_sqr_512(l, a); secp256k1_scalar_reduce_512(r, l); } static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) { r1->d[0] = k->d[0]; r1->d[1] = k->d[1]; r1->d[2] = 0; r1->d[3] = 0; r2->d[0] = k->d[2]; r2->d[1] = k->d[3]; r2->d[2] = 0; r2->d[3] = 0; } SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; } SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { uint64_t l[8]; unsigned int shiftlimbs; unsigned int shiftlow; unsigned int shifthigh; VERIFY_CHECK(shift >= 256); secp256k1_scalar_mul_512(l, a, b); shiftlimbs = shift >> 6; shiftlow = shift & 0x3F; shifthigh = 64 - shiftlow; r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0; secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); } static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { uint64_t mask0, mask1; VG_CHECK_VERIFY(r->d, sizeof(r->d)); mask0 = flag + ~((uint64_t)0); mask1 = ~mask0; r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1); r->d[1] = (r->d[1] & mask0) | (a->d[1] & mask1); r->d[2] = (r->d[2] & mask0) | (a->d[2] & mask1); r->d[3] = (r->d[3] & mask0) | (a->d[3] & mask1); } #endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/src/secp256k1/src/scalar_8x32.h b/src/secp256k1/src/scalar_8x32.h index 2c9a348e2..17863ef93 100644 --- a/src/secp256k1/src/scalar_8x32.h +++ b/src/secp256k1/src/scalar_8x32.h @@ -1,19 +1,19 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SCALAR_REPR_H #define SECP256K1_SCALAR_REPR_H #include /** A scalar modulo the group order of the secp256k1 curve. */ typedef struct { uint32_t d[8]; } secp256k1_scalar; #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} #endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h index 6853f79ec..bf98e01d7 100644 --- a/src/secp256k1/src/scalar_8x32_impl.h +++ b/src/secp256k1/src/scalar_8x32_impl.h @@ -1,734 +1,734 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SCALAR_REPR_IMPL_H #define SECP256K1_SCALAR_REPR_IMPL_H /* Limbs of the secp256k1 order. */ #define SECP256K1_N_0 ((uint32_t)0xD0364141UL) #define SECP256K1_N_1 ((uint32_t)0xBFD25E8CUL) #define SECP256K1_N_2 ((uint32_t)0xAF48A03BUL) #define SECP256K1_N_3 ((uint32_t)0xBAAEDCE6UL) #define SECP256K1_N_4 ((uint32_t)0xFFFFFFFEUL) #define SECP256K1_N_5 ((uint32_t)0xFFFFFFFFUL) #define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL) #define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL) /* Limbs of 2^256 minus the secp256k1 order. */ #define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) #define SECP256K1_N_C_1 (~SECP256K1_N_1) #define SECP256K1_N_C_2 (~SECP256K1_N_2) #define SECP256K1_N_C_3 (~SECP256K1_N_3) #define SECP256K1_N_C_4 (1) /* Limbs of half the secp256k1 order. */ #define SECP256K1_N_H_0 ((uint32_t)0x681B20A0UL) #define SECP256K1_N_H_1 ((uint32_t)0xDFE92F46UL) #define SECP256K1_N_H_2 ((uint32_t)0x57A4501DUL) #define SECP256K1_N_H_3 ((uint32_t)0x5D576E73UL) #define SECP256K1_N_H_4 ((uint32_t)0xFFFFFFFFUL) #define SECP256K1_N_H_5 ((uint32_t)0xFFFFFFFFUL) #define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) #define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { r->d[0] = 0; r->d[1] = 0; r->d[2] = 0; r->d[3] = 0; r->d[4] = 0; r->d[5] = 0; r->d[6] = 0; r->d[7] = 0; } SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { r->d[0] = v; r->d[1] = 0; r->d[2] = 0; r->d[3] = 0; r->d[4] = 0; r->d[5] = 0; r->d[6] = 0; r->d[7] = 0; } SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); } SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { VERIFY_CHECK(count < 32); VERIFY_CHECK(offset + count <= 256); if ((offset + count - 1) >> 5 == offset >> 5) { return secp256k1_scalar_get_bits(a, offset, count); } else { VERIFY_CHECK((offset >> 5) + 1 < 8); return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1); } } SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { int yes = 0; int no = 0; no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ no |= (a->d[6] < SECP256K1_N_6); /* No need for a > check. */ no |= (a->d[5] < SECP256K1_N_5); /* No need for a > check. */ no |= (a->d[4] < SECP256K1_N_4); yes |= (a->d[4] > SECP256K1_N_4) & ~no; no |= (a->d[3] < SECP256K1_N_3) & ~yes; yes |= (a->d[3] > SECP256K1_N_3) & ~no; no |= (a->d[2] < SECP256K1_N_2) & ~yes; yes |= (a->d[2] > SECP256K1_N_2) & ~no; no |= (a->d[1] < SECP256K1_N_1) & ~yes; yes |= (a->d[1] > SECP256K1_N_1) & ~no; yes |= (a->d[0] >= SECP256K1_N_0) & ~no; return yes; } SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_t overflow) { uint64_t t; VERIFY_CHECK(overflow <= 1); t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; r->d[0] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1; r->d[1] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[2] + overflow * SECP256K1_N_C_2; r->d[2] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[3] + overflow * SECP256K1_N_C_3; r->d[3] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[4] + overflow * SECP256K1_N_C_4; r->d[4] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[5]; r->d[5] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[6]; r->d[6] = t & 0xFFFFFFFFUL; t >>= 32; t += (uint64_t)r->d[7]; r->d[7] = t & 0xFFFFFFFFUL; return overflow; } static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { int overflow; uint64_t t = (uint64_t)a->d[0] + b->d[0]; r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[1] + b->d[1]; r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[2] + b->d[2]; r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[3] + b->d[3]; r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[4] + b->d[4]; r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[5] + b->d[5]; r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[6] + b->d[6]; r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[7] + b->d[7]; r->d[7] = t & 0xFFFFFFFFULL; t >>= 32; overflow = t + secp256k1_scalar_check_overflow(r); VERIFY_CHECK(overflow == 0 || overflow == 1); secp256k1_scalar_reduce(r, overflow); return overflow; } static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { uint64_t t; VERIFY_CHECK(bit < 256); bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */ t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F)); r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F)); r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F)); r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F)); r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F)); r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F)); r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F)); r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F)); r->d[7] = t & 0xFFFFFFFFULL; #ifdef VERIFY VERIFY_CHECK((t >> 32) == 0); VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); #endif } static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { int over; r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24; r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24; r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24; r->d[3] = (uint32_t)b32[19] | (uint32_t)b32[18] << 8 | (uint32_t)b32[17] << 16 | (uint32_t)b32[16] << 24; r->d[4] = (uint32_t)b32[15] | (uint32_t)b32[14] << 8 | (uint32_t)b32[13] << 16 | (uint32_t)b32[12] << 24; r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24; r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24; r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24; over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); if (overflow) { *overflow = over; } } static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { bin[0] = a->d[7] >> 24; bin[1] = a->d[7] >> 16; bin[2] = a->d[7] >> 8; bin[3] = a->d[7]; bin[4] = a->d[6] >> 24; bin[5] = a->d[6] >> 16; bin[6] = a->d[6] >> 8; bin[7] = a->d[6]; bin[8] = a->d[5] >> 24; bin[9] = a->d[5] >> 16; bin[10] = a->d[5] >> 8; bin[11] = a->d[5]; bin[12] = a->d[4] >> 24; bin[13] = a->d[4] >> 16; bin[14] = a->d[4] >> 8; bin[15] = a->d[4]; bin[16] = a->d[3] >> 24; bin[17] = a->d[3] >> 16; bin[18] = a->d[3] >> 8; bin[19] = a->d[3]; bin[20] = a->d[2] >> 24; bin[21] = a->d[2] >> 16; bin[22] = a->d[2] >> 8; bin[23] = a->d[2]; bin[24] = a->d[1] >> 24; bin[25] = a->d[1] >> 16; bin[26] = a->d[1] >> 8; bin[27] = a->d[1]; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; } SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; } static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0); uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; r->d[0] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[1]) + SECP256K1_N_1; r->d[1] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[2]) + SECP256K1_N_2; r->d[2] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[3]) + SECP256K1_N_3; r->d[3] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[4]) + SECP256K1_N_4; r->d[4] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[5]) + SECP256K1_N_5; r->d[5] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[6]) + SECP256K1_N_6; r->d[6] = t & nonzero; t >>= 32; t += (uint64_t)(~a->d[7]) + SECP256K1_N_7; r->d[7] = t & nonzero; } SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; } static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { int yes = 0; int no = 0; no |= (a->d[7] < SECP256K1_N_H_7); yes |= (a->d[7] > SECP256K1_N_H_7) & ~no; no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */ no |= (a->d[5] < SECP256K1_N_H_5) & ~yes; /* No need for a > check. */ no |= (a->d[4] < SECP256K1_N_H_4) & ~yes; /* No need for a > check. */ no |= (a->d[3] < SECP256K1_N_H_3) & ~yes; yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; yes |= (a->d[2] > SECP256K1_N_H_2) & ~no; no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; return yes; } static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { /* If we are flag = 0, mask = 00...00 and this is a no-op; * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ uint32_t mask = !flag - 1; uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0); uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); r->d[0] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); r->d[1] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); r->d[2] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); r->d[3] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[4] ^ mask) + (SECP256K1_N_4 & mask); r->d[4] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[5] ^ mask) + (SECP256K1_N_5 & mask); r->d[5] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[6] ^ mask) + (SECP256K1_N_6 & mask); r->d[6] = t & nonzero; t >>= 32; t += (uint64_t)(r->d[7] ^ mask) + (SECP256K1_N_7 & mask); r->d[7] = t & nonzero; return 2 * (mask == 0) - 1; } /* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ /** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ #define muladd(a,b) { \ uint32_t tl, th; \ { \ uint64_t t = (uint64_t)a * b; \ th = t >> 32; /* at most 0xFFFFFFFE */ \ tl = t; \ } \ c0 += tl; /* overflow is handled on the next line */ \ th += (c0 < tl); /* at most 0xFFFFFFFF */ \ c1 += th; /* overflow is handled on the next line */ \ c2 += (c1 < th); /* never overflows by contract (verified in the next line) */ \ VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ } /** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ #define muladd_fast(a,b) { \ uint32_t tl, th; \ { \ uint64_t t = (uint64_t)a * b; \ th = t >> 32; /* at most 0xFFFFFFFE */ \ tl = t; \ } \ c0 += tl; /* overflow is handled on the next line */ \ th += (c0 < tl); /* at most 0xFFFFFFFF */ \ c1 += th; /* never overflows by contract (verified in the next line) */ \ VERIFY_CHECK(c1 >= th); \ } /** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ #define muladd2(a,b) { \ uint32_t tl, th, th2, tl2; \ { \ uint64_t t = (uint64_t)a * b; \ th = t >> 32; /* at most 0xFFFFFFFE */ \ tl = t; \ } \ th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \ c2 += (th2 < th); /* never overflows by contract (verified the next line) */ \ VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \ th2 += (tl2 < tl); /* at most 0xFFFFFFFF */ \ c0 += tl2; /* overflow is handled on the next line */ \ th2 += (c0 < tl2); /* second overflow is handled on the next line */ \ c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ c1 += th2; /* overflow is handled on the next line */ \ c2 += (c1 < th2); /* never overflows by contract (verified the next line) */ \ VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ } /** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ #define sumadd(a) { \ unsigned int over; \ c0 += (a); /* overflow is handled on the next line */ \ over = (c0 < (a)); \ c1 += over; /* overflow is handled on the next line */ \ c2 += (c1 < over); /* never overflows by contract */ \ } /** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ #define sumadd_fast(a) { \ c0 += (a); /* overflow is handled on the next line */ \ c1 += (c0 < (a)); /* never overflows by contract (verified the next line) */ \ VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ VERIFY_CHECK(c2 == 0); \ } /** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */ #define extract(n) { \ (n) = c0; \ c0 = c1; \ c1 = c2; \ c2 = 0; \ } /** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. c2 is required to be zero. */ #define extract_fast(n) { \ (n) = c0; \ c0 = c1; \ c1 = 0; \ VERIFY_CHECK(c2 == 0); \ } static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) { uint64_t c; uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15]; uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12; uint32_t p0, p1, p2, p3, p4, p5, p6, p7, p8; /* 96 bit accumulator. */ uint32_t c0, c1, c2; /* Reduce 512 bits into 385. */ /* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */ c0 = l[0]; c1 = 0; c2 = 0; muladd_fast(n0, SECP256K1_N_C_0); extract_fast(m0); sumadd_fast(l[1]); muladd(n1, SECP256K1_N_C_0); muladd(n0, SECP256K1_N_C_1); extract(m1); sumadd(l[2]); muladd(n2, SECP256K1_N_C_0); muladd(n1, SECP256K1_N_C_1); muladd(n0, SECP256K1_N_C_2); extract(m2); sumadd(l[3]); muladd(n3, SECP256K1_N_C_0); muladd(n2, SECP256K1_N_C_1); muladd(n1, SECP256K1_N_C_2); muladd(n0, SECP256K1_N_C_3); extract(m3); sumadd(l[4]); muladd(n4, SECP256K1_N_C_0); muladd(n3, SECP256K1_N_C_1); muladd(n2, SECP256K1_N_C_2); muladd(n1, SECP256K1_N_C_3); sumadd(n0); extract(m4); sumadd(l[5]); muladd(n5, SECP256K1_N_C_0); muladd(n4, SECP256K1_N_C_1); muladd(n3, SECP256K1_N_C_2); muladd(n2, SECP256K1_N_C_3); sumadd(n1); extract(m5); sumadd(l[6]); muladd(n6, SECP256K1_N_C_0); muladd(n5, SECP256K1_N_C_1); muladd(n4, SECP256K1_N_C_2); muladd(n3, SECP256K1_N_C_3); sumadd(n2); extract(m6); sumadd(l[7]); muladd(n7, SECP256K1_N_C_0); muladd(n6, SECP256K1_N_C_1); muladd(n5, SECP256K1_N_C_2); muladd(n4, SECP256K1_N_C_3); sumadd(n3); extract(m7); muladd(n7, SECP256K1_N_C_1); muladd(n6, SECP256K1_N_C_2); muladd(n5, SECP256K1_N_C_3); sumadd(n4); extract(m8); muladd(n7, SECP256K1_N_C_2); muladd(n6, SECP256K1_N_C_3); sumadd(n5); extract(m9); muladd(n7, SECP256K1_N_C_3); sumadd(n6); extract(m10); sumadd_fast(n7); extract_fast(m11); VERIFY_CHECK(c0 <= 1); m12 = c0; /* Reduce 385 bits into 258. */ /* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */ c0 = m0; c1 = 0; c2 = 0; muladd_fast(m8, SECP256K1_N_C_0); extract_fast(p0); sumadd_fast(m1); muladd(m9, SECP256K1_N_C_0); muladd(m8, SECP256K1_N_C_1); extract(p1); sumadd(m2); muladd(m10, SECP256K1_N_C_0); muladd(m9, SECP256K1_N_C_1); muladd(m8, SECP256K1_N_C_2); extract(p2); sumadd(m3); muladd(m11, SECP256K1_N_C_0); muladd(m10, SECP256K1_N_C_1); muladd(m9, SECP256K1_N_C_2); muladd(m8, SECP256K1_N_C_3); extract(p3); sumadd(m4); muladd(m12, SECP256K1_N_C_0); muladd(m11, SECP256K1_N_C_1); muladd(m10, SECP256K1_N_C_2); muladd(m9, SECP256K1_N_C_3); sumadd(m8); extract(p4); sumadd(m5); muladd(m12, SECP256K1_N_C_1); muladd(m11, SECP256K1_N_C_2); muladd(m10, SECP256K1_N_C_3); sumadd(m9); extract(p5); sumadd(m6); muladd(m12, SECP256K1_N_C_2); muladd(m11, SECP256K1_N_C_3); sumadd(m10); extract(p6); sumadd_fast(m7); muladd_fast(m12, SECP256K1_N_C_3); sumadd_fast(m11); extract_fast(p7); p8 = c0 + m12; VERIFY_CHECK(p8 <= 2); /* Reduce 258 bits into 256. */ /* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */ c = p0 + (uint64_t)SECP256K1_N_C_0 * p8; r->d[0] = c & 0xFFFFFFFFUL; c >>= 32; c += p1 + (uint64_t)SECP256K1_N_C_1 * p8; r->d[1] = c & 0xFFFFFFFFUL; c >>= 32; c += p2 + (uint64_t)SECP256K1_N_C_2 * p8; r->d[2] = c & 0xFFFFFFFFUL; c >>= 32; c += p3 + (uint64_t)SECP256K1_N_C_3 * p8; r->d[3] = c & 0xFFFFFFFFUL; c >>= 32; c += p4 + (uint64_t)p8; r->d[4] = c & 0xFFFFFFFFUL; c >>= 32; c += p5; r->d[5] = c & 0xFFFFFFFFUL; c >>= 32; c += p6; r->d[6] = c & 0xFFFFFFFFUL; c >>= 32; c += p7; r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; /* Final reduction of r. */ secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); } static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, const secp256k1_scalar *b) { /* 96 bit accumulator. */ uint32_t c0 = 0, c1 = 0, c2 = 0; /* l[0..15] = a[0..7] * b[0..7]. */ muladd_fast(a->d[0], b->d[0]); extract_fast(l[0]); muladd(a->d[0], b->d[1]); muladd(a->d[1], b->d[0]); extract(l[1]); muladd(a->d[0], b->d[2]); muladd(a->d[1], b->d[1]); muladd(a->d[2], b->d[0]); extract(l[2]); muladd(a->d[0], b->d[3]); muladd(a->d[1], b->d[2]); muladd(a->d[2], b->d[1]); muladd(a->d[3], b->d[0]); extract(l[3]); muladd(a->d[0], b->d[4]); muladd(a->d[1], b->d[3]); muladd(a->d[2], b->d[2]); muladd(a->d[3], b->d[1]); muladd(a->d[4], b->d[0]); extract(l[4]); muladd(a->d[0], b->d[5]); muladd(a->d[1], b->d[4]); muladd(a->d[2], b->d[3]); muladd(a->d[3], b->d[2]); muladd(a->d[4], b->d[1]); muladd(a->d[5], b->d[0]); extract(l[5]); muladd(a->d[0], b->d[6]); muladd(a->d[1], b->d[5]); muladd(a->d[2], b->d[4]); muladd(a->d[3], b->d[3]); muladd(a->d[4], b->d[2]); muladd(a->d[5], b->d[1]); muladd(a->d[6], b->d[0]); extract(l[6]); muladd(a->d[0], b->d[7]); muladd(a->d[1], b->d[6]); muladd(a->d[2], b->d[5]); muladd(a->d[3], b->d[4]); muladd(a->d[4], b->d[3]); muladd(a->d[5], b->d[2]); muladd(a->d[6], b->d[1]); muladd(a->d[7], b->d[0]); extract(l[7]); muladd(a->d[1], b->d[7]); muladd(a->d[2], b->d[6]); muladd(a->d[3], b->d[5]); muladd(a->d[4], b->d[4]); muladd(a->d[5], b->d[3]); muladd(a->d[6], b->d[2]); muladd(a->d[7], b->d[1]); extract(l[8]); muladd(a->d[2], b->d[7]); muladd(a->d[3], b->d[6]); muladd(a->d[4], b->d[5]); muladd(a->d[5], b->d[4]); muladd(a->d[6], b->d[3]); muladd(a->d[7], b->d[2]); extract(l[9]); muladd(a->d[3], b->d[7]); muladd(a->d[4], b->d[6]); muladd(a->d[5], b->d[5]); muladd(a->d[6], b->d[4]); muladd(a->d[7], b->d[3]); extract(l[10]); muladd(a->d[4], b->d[7]); muladd(a->d[5], b->d[6]); muladd(a->d[6], b->d[5]); muladd(a->d[7], b->d[4]); extract(l[11]); muladd(a->d[5], b->d[7]); muladd(a->d[6], b->d[6]); muladd(a->d[7], b->d[5]); extract(l[12]); muladd(a->d[6], b->d[7]); muladd(a->d[7], b->d[6]); extract(l[13]); muladd_fast(a->d[7], b->d[7]); extract_fast(l[14]); VERIFY_CHECK(c1 == 0); l[15] = c0; } static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar *a) { /* 96 bit accumulator. */ uint32_t c0 = 0, c1 = 0, c2 = 0; /* l[0..15] = a[0..7]^2. */ muladd_fast(a->d[0], a->d[0]); extract_fast(l[0]); muladd2(a->d[0], a->d[1]); extract(l[1]); muladd2(a->d[0], a->d[2]); muladd(a->d[1], a->d[1]); extract(l[2]); muladd2(a->d[0], a->d[3]); muladd2(a->d[1], a->d[2]); extract(l[3]); muladd2(a->d[0], a->d[4]); muladd2(a->d[1], a->d[3]); muladd(a->d[2], a->d[2]); extract(l[4]); muladd2(a->d[0], a->d[5]); muladd2(a->d[1], a->d[4]); muladd2(a->d[2], a->d[3]); extract(l[5]); muladd2(a->d[0], a->d[6]); muladd2(a->d[1], a->d[5]); muladd2(a->d[2], a->d[4]); muladd(a->d[3], a->d[3]); extract(l[6]); muladd2(a->d[0], a->d[7]); muladd2(a->d[1], a->d[6]); muladd2(a->d[2], a->d[5]); muladd2(a->d[3], a->d[4]); extract(l[7]); muladd2(a->d[1], a->d[7]); muladd2(a->d[2], a->d[6]); muladd2(a->d[3], a->d[5]); muladd(a->d[4], a->d[4]); extract(l[8]); muladd2(a->d[2], a->d[7]); muladd2(a->d[3], a->d[6]); muladd2(a->d[4], a->d[5]); extract(l[9]); muladd2(a->d[3], a->d[7]); muladd2(a->d[4], a->d[6]); muladd(a->d[5], a->d[5]); extract(l[10]); muladd2(a->d[4], a->d[7]); muladd2(a->d[5], a->d[6]); extract(l[11]); muladd2(a->d[5], a->d[7]); muladd(a->d[6], a->d[6]); extract(l[12]); muladd2(a->d[6], a->d[7]); extract(l[13]); muladd_fast(a->d[7], a->d[7]); extract_fast(l[14]); VERIFY_CHECK(c1 == 0); l[15] = c0; } #undef sumadd #undef sumadd_fast #undef muladd #undef muladd_fast #undef muladd2 #undef extract #undef extract_fast static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { uint32_t l[16]; secp256k1_scalar_mul_512(l, a, b); secp256k1_scalar_reduce_512(r, l); } static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { int ret; VERIFY_CHECK(n > 0); VERIFY_CHECK(n < 16); ret = r->d[0] & ((1 << n) - 1); r->d[0] = (r->d[0] >> n) + (r->d[1] << (32 - n)); r->d[1] = (r->d[1] >> n) + (r->d[2] << (32 - n)); r->d[2] = (r->d[2] >> n) + (r->d[3] << (32 - n)); r->d[3] = (r->d[3] >> n) + (r->d[4] << (32 - n)); r->d[4] = (r->d[4] >> n) + (r->d[5] << (32 - n)); r->d[5] = (r->d[5] >> n) + (r->d[6] << (32 - n)); r->d[6] = (r->d[6] >> n) + (r->d[7] << (32 - n)); r->d[7] = (r->d[7] >> n); return ret; } static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { uint32_t l[16]; secp256k1_scalar_sqr_512(l, a); secp256k1_scalar_reduce_512(r, l); } static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) { r1->d[0] = k->d[0]; r1->d[1] = k->d[1]; r1->d[2] = k->d[2]; r1->d[3] = k->d[3]; r1->d[4] = 0; r1->d[5] = 0; r1->d[6] = 0; r1->d[7] = 0; r2->d[0] = k->d[4]; r2->d[1] = k->d[5]; r2->d[2] = k->d[6]; r2->d[3] = k->d[7]; r2->d[4] = 0; r2->d[5] = 0; r2->d[6] = 0; r2->d[7] = 0; } SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; } SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { uint32_t l[16]; unsigned int shiftlimbs; unsigned int shiftlow; unsigned int shifthigh; VERIFY_CHECK(shift >= 256); secp256k1_scalar_mul_512(l, a, b); shiftlimbs = shift >> 5; shiftlow = shift & 0x1F; shifthigh = 32 - shiftlow; r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[3] = shift < 416 ? (l[3 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[4 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[4] = shift < 384 ? (l[4 + shiftlimbs] >> shiftlow | (shift < 352 && shiftlow ? (l[5 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0; secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); } static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { uint32_t mask0, mask1; VG_CHECK_VERIFY(r->d, sizeof(r->d)); mask0 = flag + ~((uint32_t)0); mask1 = ~mask0; r->d[0] = (r->d[0] & mask0) | (a->d[0] & mask1); r->d[1] = (r->d[1] & mask0) | (a->d[1] & mask1); r->d[2] = (r->d[2] & mask0) | (a->d[2] & mask1); r->d[3] = (r->d[3] & mask0) | (a->d[3] & mask1); r->d[4] = (r->d[4] & mask0) | (a->d[4] & mask1); r->d[5] = (r->d[5] & mask0) | (a->d[5] & mask1); r->d[6] = (r->d[6] & mask0) | (a->d[6] & mask1); r->d[7] = (r->d[7] & mask0) | (a->d[7] & mask1); } #endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h index fc7589181..61c1fbd58 100644 --- a/src/secp256k1/src/scalar_impl.h +++ b/src/secp256k1/src/scalar_impl.h @@ -1,516 +1,516 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SCALAR_IMPL_H #define SECP256K1_SCALAR_IMPL_H #ifdef VERIFY #include #endif #include "scalar.h" #include "util.h" #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif #if defined(EXHAUSTIVE_TEST_ORDER) #include "scalar_low_impl.h" #elif defined(SECP256K1_WIDEMUL_INT128) #include "scalar_4x64_impl.h" #elif defined(SECP256K1_WIDEMUL_INT64) #include "scalar_8x32_impl.h" #else #error "Please select wide multiplication implementation" #endif static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); static const secp256k1_scalar secp256k1_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); #ifndef USE_NUM_NONE static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a) { unsigned char c[32]; secp256k1_scalar_get_b32(c, a); secp256k1_num_set_bin(r, c, 32); } /** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */ static void secp256k1_scalar_order_get_num(secp256k1_num *r) { #if defined(EXHAUSTIVE_TEST_ORDER) static const unsigned char order[32] = { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,EXHAUSTIVE_TEST_ORDER }; #else static const unsigned char order[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 }; #endif secp256k1_num_set_bin(r, order, 32); } #endif static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned char *bin) { int overflow; secp256k1_scalar_set_b32(r, bin, &overflow); return (!overflow) & (!secp256k1_scalar_is_zero(r)); } static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { #if defined(EXHAUSTIVE_TEST_ORDER) int i; *r = 0; for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) *r = i; /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus * have a composite group order; fix it in exhaustive_tests.c). */ VERIFY_CHECK(*r != 0); } #else secp256k1_scalar *t; int i; /* First compute xN as x ^ (2^N - 1) for some values of N, * and uM as x ^ M for some values of M. */ secp256k1_scalar x2, x3, x6, x8, x14, x28, x56, x112, x126; secp256k1_scalar u2, u5, u9, u11, u13; secp256k1_scalar_sqr(&u2, x); secp256k1_scalar_mul(&x2, &u2, x); secp256k1_scalar_mul(&u5, &u2, &x2); secp256k1_scalar_mul(&x3, &u5, &u2); secp256k1_scalar_mul(&u9, &x3, &u2); secp256k1_scalar_mul(&u11, &u9, &u2); secp256k1_scalar_mul(&u13, &u11, &u2); secp256k1_scalar_sqr(&x6, &u13); secp256k1_scalar_sqr(&x6, &x6); secp256k1_scalar_mul(&x6, &x6, &u11); secp256k1_scalar_sqr(&x8, &x6); secp256k1_scalar_sqr(&x8, &x8); secp256k1_scalar_mul(&x8, &x8, &x2); secp256k1_scalar_sqr(&x14, &x8); for (i = 0; i < 5; i++) { secp256k1_scalar_sqr(&x14, &x14); } secp256k1_scalar_mul(&x14, &x14, &x6); secp256k1_scalar_sqr(&x28, &x14); for (i = 0; i < 13; i++) { secp256k1_scalar_sqr(&x28, &x28); } secp256k1_scalar_mul(&x28, &x28, &x14); secp256k1_scalar_sqr(&x56, &x28); for (i = 0; i < 27; i++) { secp256k1_scalar_sqr(&x56, &x56); } secp256k1_scalar_mul(&x56, &x56, &x28); secp256k1_scalar_sqr(&x112, &x56); for (i = 0; i < 55; i++) { secp256k1_scalar_sqr(&x112, &x112); } secp256k1_scalar_mul(&x112, &x112, &x56); secp256k1_scalar_sqr(&x126, &x112); for (i = 0; i < 13; i++) { secp256k1_scalar_sqr(&x126, &x126); } secp256k1_scalar_mul(&x126, &x126, &x14); /* Then accumulate the final result (t starts at x126). */ t = &x126; for (i = 0; i < 3; i++) { secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u5); /* 101 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u5); /* 101 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u11); /* 1011 */ for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u11); /* 1011 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ for (i = 0; i < 5; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u13); /* 1101 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u5); /* 101 */ for (i = 0; i < 3; i++) { secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u9); /* 1001 */ for (i = 0; i < 6; i++) { /* 000 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u5); /* 101 */ for (i = 0; i < 10; i++) { /* 0000000 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ for (i = 0; i < 9; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u9); /* 1001 */ for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u11); /* 1011 */ for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u13); /* 1101 */ for (i = 0; i < 5; i++) { secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x2); /* 11 */ for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u13); /* 1101 */ for (i = 0; i < 10; i++) { /* 000000 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u13); /* 1101 */ for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &u9); /* 1001 */ for (i = 0; i < 6; i++) { /* 00000 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, x); /* 1 */ for (i = 0; i < 8; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(r, t, &x6); /* 111111 */ } SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { return !(a->d[0] & 1); } #endif static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { #if defined(USE_SCALAR_INV_BUILTIN) secp256k1_scalar_inverse(r, x); #elif defined(USE_SCALAR_INV_NUM) unsigned char b[32]; secp256k1_num n, m; secp256k1_scalar t = *x; secp256k1_scalar_get_b32(b, &t); secp256k1_num_set_bin(&n, b, 32); secp256k1_scalar_order_get_num(&m); secp256k1_num_mod_inverse(&n, &n, &m); secp256k1_num_get_bin(b, 32, &n); secp256k1_scalar_set_b32(r, b, NULL); /* Verify that the inverse was computed correctly, without GMP code. */ secp256k1_scalar_mul(&t, &t, r); CHECK(secp256k1_scalar_is_one(&t)); #else #error "Please select scalar inverse implementation" #endif } /* These parameters are generated using sage/gen_exhaustive_groups.sage. */ #if defined(EXHAUSTIVE_TEST_ORDER) # if EXHAUSTIVE_TEST_ORDER == 13 # define EXHAUSTIVE_TEST_LAMBDA 9 # elif EXHAUSTIVE_TEST_ORDER == 199 # define EXHAUSTIVE_TEST_LAMBDA 92 # else # error No known lambda for the specified exhaustive test group order. # endif /** * Find r1 and r2 given k, such that r1 + r2 * lambda == k mod n; unlike in the * full case we don't bother making r1 and r2 be small, we just want them to be * nontrivial to get full test coverage for the exhaustive tests. We therefore * (arbitrarily) set r2 = k + 5 (mod n) and r1 = k - r2 * lambda (mod n). */ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) { *r2 = (*k + 5) % EXHAUSTIVE_TEST_ORDER; *r1 = (*k + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; } #else /** * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where * lambda is: */ static const secp256k1_scalar secp256k1_const_lambda = SECP256K1_SCALAR_CONST( 0x5363AD4CUL, 0xC05C30E0UL, 0xA5261C02UL, 0x8812645AUL, 0x122E22EAUL, 0x20816678UL, 0xDF02967CUL, 0x1B23BD72UL ); #ifdef VERIFY static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, const secp256k1_scalar *r2, const secp256k1_scalar *k); #endif /* * Both lambda and beta are primitive cube roots of unity. That is lamba^3 == 1 mod n and * beta^3 == 1 mod p, where n is the curve order and p is the field order. * * Futhermore, because (X^3 - 1) = (X - 1)(X^2 + X + 1), the primitive cube roots of unity are * roots of X^2 + X + 1. Therefore lambda^2 + lamba == -1 mod n and beta^2 + beta == -1 mod p. * (The other primitive cube roots of unity are lambda^2 and beta^2 respectively.) * * Let l = -1/2 + i*sqrt(3)/2, the complex root of X^2 + X + 1. We can define a ring * homomorphism phi : Z[l] -> Z_n where phi(a + b*l) == a + b*lambda mod n. The kernel of phi * is a lattice over Z[l] (considering Z[l] as a Z-module). This lattice is generated by a * reduced basis {a1 + b1*l, a2 + b2*l} where * * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3} * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8} * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} * * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1 * and k2 are small in absolute value. * * The algorithm computes c1 = round(b2 * k / n) and c2 = round((-b1) * k / n), and gives * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and * compute r2 = k2 mod n, and r1 = k1 mod n = (k - r2 * lambda) mod n, avoiding the need for * the constants a1 and a2. * * g1, g2 are precomputed constants used to replace division with a rounded multiplication * when decomposing the scalar for an endomorphism-based point multiplication. * * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5. * * The derivation is described in the paper "Efficient Software Implementation of Public-Key * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez), * Section 4.3 (here we use a somewhat higher-precision estimate): * d = a1*b2 - b1*a2 * g1 = round(2^384 * b2/d) * g2 = round(2^384 * (-b1)/d) * * (Note that d is also equal to the curve order, n, here because [a1,b1] and [a2,b2] * can be found as outputs of the Extended Euclidean Algorithm on inputs n and lambda). * * The function below splits k into r1 and r2, such that * - r1 + lambda * r2 == k (mod n) * - either r1 < 2^128 or -r1 mod n < 2^128 * - either r2 < 2^128 or -r2 mod n < 2^128 * * See proof below. */ static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *k) { secp256k1_scalar c1, c2; static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST( 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL ); static const secp256k1_scalar minus_b2 = SECP256K1_SCALAR_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL ); static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST( 0x3086D221UL, 0xA7D46BCDUL, 0xE86C90E4UL, 0x9284EB15UL, 0x3DAA8A14UL, 0x71E8CA7FUL, 0xE893209AUL, 0x45DBB031UL ); static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST( 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C4UL, 0x221208ACUL, 0x9DF506C6UL, 0x1571B4AEUL, 0x8AC47F71UL ); VERIFY_CHECK(r1 != k); VERIFY_CHECK(r2 != k); /* these _var calls are constant time since the shift amount is constant */ secp256k1_scalar_mul_shift_var(&c1, k, &g1, 384); secp256k1_scalar_mul_shift_var(&c2, k, &g2, 384); secp256k1_scalar_mul(&c1, &c1, &minus_b1); secp256k1_scalar_mul(&c2, &c2, &minus_b2); secp256k1_scalar_add(r2, &c1, &c2); secp256k1_scalar_mul(r1, r2, &secp256k1_const_lambda); secp256k1_scalar_negate(r1, r1); secp256k1_scalar_add(r1, r1, k); #ifdef VERIFY secp256k1_scalar_split_lambda_verify(r1, r2, k); #endif } #ifdef VERIFY /* * Proof for secp256k1_scalar_split_lambda's bounds. * * Let * - epsilon1 = 2^256 * |g1/2^384 - b2/d| * - epsilon2 = 2^256 * |g2/2^384 - (-b1)/d| * - c1 = round(k*g1/2^384) * - c2 = round(k*g2/2^384) * * Lemma 1: |c1 - k*b2/d| < 2^-1 + epsilon1 * * |c1 - k*b2/d| * = * |c1 - k*g1/2^384 + k*g1/2^384 - k*b2/d| * <= {triangle inequality} * |c1 - k*g1/2^384| + |k*g1/2^384 - k*b2/d| * = * |c1 - k*g1/2^384| + k*|g1/2^384 - b2/d| * < {rounding in c1 and 0 <= k < 2^256} * 2^-1 + 2^256 * |g1/2^384 - b2/d| * = {definition of epsilon1} * 2^-1 + epsilon1 * * Lemma 2: |c2 - k*(-b1)/d| < 2^-1 + epsilon2 * * |c2 - k*(-b1)/d| * = * |c2 - k*g2/2^384 + k*g2/2^384 - k*(-b1)/d| * <= {triangle inequality} * |c2 - k*g2/2^384| + |k*g2/2^384 - k*(-b1)/d| * = * |c2 - k*g2/2^384| + k*|g2/2^384 - (-b1)/d| * < {rounding in c2 and 0 <= k < 2^256} * 2^-1 + 2^256 * |g2/2^384 - (-b1)/d| * = {definition of epsilon2} * 2^-1 + epsilon2 * * Let * - k1 = k - c1*a1 - c2*a2 * - k2 = - c1*b1 - c2*b2 * * Lemma 3: |k1| < (a1 + a2 + 1)/2 < 2^128 * * |k1| * = {definition of k1} * |k - c1*a1 - c2*a2| * = {(a1*b2 - b1*a2)/n = 1} * |k*(a1*b2 - b1*a2)/n - c1*a1 - c2*a2| * = * |a1*(k*b2/n - c1) + a2*(k*(-b1)/n - c2)| * <= {triangle inequality} * a1*|k*b2/n - c1| + a2*|k*(-b1)/n - c2| * < {Lemma 1 and Lemma 2} * a1*(2^-1 + epslion1) + a2*(2^-1 + epsilon2) * < {rounding up to an integer} * (a1 + a2 + 1)/2 * < {rounding up to a power of 2} * 2^128 * * Lemma 4: |k2| < (-b1 + b2)/2 + 1 < 2^128 * * |k2| * = {definition of k2} * |- c1*a1 - c2*a2| * = {(b1*b2 - b1*b2)/n = 0} * |k*(b1*b2 - b1*b2)/n - c1*b1 - c2*b2| * = * |b1*(k*b2/n - c1) + b2*(k*(-b1)/n - c2)| * <= {triangle inequality} * (-b1)*|k*b2/n - c1| + b2*|k*(-b1)/n - c2| * < {Lemma 1 and Lemma 2} * (-b1)*(2^-1 + epslion1) + b2*(2^-1 + epsilon2) * < {rounding up to an integer} * (-b1 + b2)/2 + 1 * < {rounding up to a power of 2} * 2^128 * * Let * - r2 = k2 mod n * - r1 = k - r2*lambda mod n. * * Notice that r1 is defined such that r1 + r2 * lambda == k (mod n). * * Lemma 5: r1 == k1 mod n. * * r1 * == {definition of r1 and r2} * k - k2*lambda * == {definition of k2} * k - (- c1*b1 - c2*b2)*lambda * == * k + c1*b1*lambda + c2*b2*lambda * == {a1 + b1*lambda == 0 mod n and a2 + b2*lambda == 0 mod n} * k - c1*a1 - c2*a2 * == {definition of k1} * k1 * * From Lemma 3, Lemma 4, Lemma 5 and the definition of r2, we can conclude that * * - either r1 < 2^128 or -r1 mod n < 2^128 * - either r2 < 2^128 or -r2 mod n < 2^128. * * Q.E.D. */ static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, const secp256k1_scalar *r2, const secp256k1_scalar *k) { secp256k1_scalar s; unsigned char buf1[32]; unsigned char buf2[32]; /* (a1 + a2 + 1)/2 is 0xa2a8918ca85bafe22016d0b917e4dd77 */ static const unsigned char k1_bound[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xa8, 0x91, 0x8c, 0xa8, 0x5b, 0xaf, 0xe2, 0x20, 0x16, 0xd0, 0xb9, 0x17, 0xe4, 0xdd, 0x77 }; /* (-b1 + b2)/2 + 1 is 0x8a65287bd47179fb2be08846cea267ed */ static const unsigned char k2_bound[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x65, 0x28, 0x7b, 0xd4, 0x71, 0x79, 0xfb, 0x2b, 0xe0, 0x88, 0x46, 0xce, 0xa2, 0x67, 0xed }; secp256k1_scalar_mul(&s, &secp256k1_const_lambda, r2); secp256k1_scalar_add(&s, &s, r1); VERIFY_CHECK(secp256k1_scalar_eq(&s, k)); secp256k1_scalar_negate(&s, r1); secp256k1_scalar_get_b32(buf1, r1); secp256k1_scalar_get_b32(buf2, &s); VERIFY_CHECK(secp256k1_memcmp_var(buf1, k1_bound, 32) < 0 || secp256k1_memcmp_var(buf2, k1_bound, 32) < 0); secp256k1_scalar_negate(&s, r2); secp256k1_scalar_get_b32(buf1, r2); secp256k1_scalar_get_b32(buf2, &s); VERIFY_CHECK(secp256k1_memcmp_var(buf1, k2_bound, 32) < 0 || secp256k1_memcmp_var(buf2, k2_bound, 32) < 0); } #endif /* VERIFY */ #endif /* !defined(EXHAUSTIVE_TEST_ORDER) */ #endif /* SECP256K1_SCALAR_IMPL_H */ diff --git a/src/secp256k1/src/scalar_low.h b/src/secp256k1/src/scalar_low.h index 2794a7f17..67051bd30 100644 --- a/src/secp256k1/src/scalar_low.h +++ b/src/secp256k1/src/scalar_low.h @@ -1,17 +1,17 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SCALAR_REPR_H #define SECP256K1_SCALAR_REPR_H #include /** A scalar modulo the group order of the secp256k1 curve. */ typedef uint32_t secp256k1_scalar; #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) (d0) #endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/src/secp256k1/src/scalar_low_impl.h b/src/secp256k1/src/scalar_low_impl.h index a615ec074..98ffd1536 100644 --- a/src/secp256k1/src/scalar_low_impl.h +++ b/src/secp256k1/src/scalar_low_impl.h @@ -1,128 +1,128 @@ -/********************************************************************** - * Copyright (c) 2015 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SCALAR_REPR_IMPL_H #define SECP256K1_SCALAR_REPR_IMPL_H #include "scalar.h" #include SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { return !(*a & 1); } SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; } SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { if (offset < 32) return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); else return 0; } SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { return secp256k1_scalar_get_bits(a, offset, count); } SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; return *r < *b; } static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { if (flag && bit < 32) *r += ((uint32_t)1 << bit); #ifdef VERIFY VERIFY_CHECK(bit < 32); /* Verify that adding (1 << bit) will not overflow any in-range scalar *r by overflowing the underlying uint32_t. */ VERIFY_CHECK(((uint32_t)1 << bit) - 1 <= UINT32_MAX - EXHAUSTIVE_TEST_ORDER); VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); #endif } static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { int i; int over = 0; *r = 0; for (i = 0; i < 32; i++) { *r = (*r * 0x100) + b32[i]; if (*r >= EXHAUSTIVE_TEST_ORDER) { over = 1; *r %= EXHAUSTIVE_TEST_ORDER; } } if (overflow) *overflow = over; } static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { memset(bin, 0, 32); bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; } SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { return *a == 0; } static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { if (*a == 0) { *r = 0; } else { *r = EXHAUSTIVE_TEST_ORDER - *a; } } SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { return *a == 1; } static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { return *a > EXHAUSTIVE_TEST_ORDER / 2; } static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { if (flag) secp256k1_scalar_negate(r, r); return flag ? -1 : 1; } static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; } static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { int ret; VERIFY_CHECK(n > 0); VERIFY_CHECK(n < 16); ret = *r & ((1 << n) - 1); *r >>= n; return ret; } static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER; } static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { *r1 = *a; *r2 = 0; } SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { return *a == *b; } static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { uint32_t mask0, mask1; VG_CHECK_VERIFY(r, sizeof(*r)); mask0 = flag + ~((uint32_t)0); mask1 = ~mask0; *r = (*r & mask0) | (*a & mask1); } #endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/src/secp256k1/src/scratch.h b/src/secp256k1/src/scratch.h index 77b35d126..bb3172a2e 100644 --- a/src/secp256k1/src/scratch.h +++ b/src/secp256k1/src/scratch.h @@ -1,42 +1,42 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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 { /** guard against interpreting this object as other types */ unsigned char magic[8]; /** actual allocated data */ void *data; /** amount that has been allocated (i.e. `data + offset` is the next * available pointer) */ size_t alloc_size; /** maximum size available to allocate */ size_t max_size; } secp256k1_scratch; static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size); static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch); /** Returns an opaque object used to "checkpoint" a scratch space. Used * with `secp256k1_scratch_apply_checkpoint` to undo allocations. */ static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch); /** Applies a check point received from `secp256k1_scratch_checkpoint`, * undoing all allocations since that point. */ static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint); /** Returns the maximum allocation the scratch space will allow */ static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t n_objects); /** Returns a pointer into the most recently allocated frame, or NULL if there is insufficient available space */ static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t n); #endif diff --git a/src/secp256k1/src/scratch_impl.h b/src/secp256k1/src/scratch_impl.h index f381e2e32..a2b78f80e 100644 --- a/src/secp256k1/src/scratch_impl.h +++ b/src/secp256k1/src/scratch_impl.h @@ -1,99 +1,99 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2017 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef _SECP256K1_SCRATCH_IMPL_H_ #define _SECP256K1_SCRATCH_IMPL_H_ #include "util.h" #include "scratch.h" static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) { const size_t base_alloc = ROUND_TO_ALIGN(sizeof(secp256k1_scratch)); void *alloc = checked_malloc(error_callback, base_alloc + size); secp256k1_scratch* ret = (secp256k1_scratch *)alloc; if (ret != NULL) { memset(ret, 0, sizeof(*ret)); memcpy(ret->magic, "scratch", 8); ret->data = (void *) ((char *) alloc + base_alloc); ret->max_size = size; } return ret; } static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) { if (scratch != NULL) { VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */ if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return; } memset(scratch->magic, 0, sizeof(scratch->magic)); free(scratch); } } static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return 0; } return scratch->alloc_size; } static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return; } if (checkpoint > scratch->alloc_size) { secp256k1_callback_call(error_callback, "invalid checkpoint"); return; } scratch->alloc_size = checkpoint; } static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t objects) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return 0; } /* Ensure that multiplication will not wrap around */ if (ALIGNMENT > 1 && objects > SIZE_MAX/(ALIGNMENT - 1)) { return 0; } if (scratch->max_size - scratch->alloc_size <= objects * (ALIGNMENT - 1)) { return 0; } return scratch->max_size - scratch->alloc_size - objects * (ALIGNMENT - 1); } static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t size) { void *ret; size_t rounded_size; rounded_size = ROUND_TO_ALIGN(size); /* Check that rounding did not wrap around */ if (rounded_size < size) { return NULL; } size = rounded_size; if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return NULL; } if (size > scratch->max_size - scratch->alloc_size) { return NULL; } ret = (void *) ((char *) scratch->data + scratch->alloc_size); memset(ret, 0, size); scratch->alloc_size += size; return ret; } #endif diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c index 9cce2f857..537cb9ce6 100644 --- a/src/secp256k1/src/secp256k1.c +++ b/src/secp256k1/src/secp256k1.c @@ -1,785 +1,785 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include "include/secp256k1.h" #include "include/secp256k1_preallocated.h" #include "assumptions.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" #include "selftest.h" #if defined(VALGRIND) # include #endif #define ARG_CHECK(cond) do { \ if (EXPECT(!(cond), 0)) { \ secp256k1_callback_call(&ctx->illegal_callback, #cond); \ return 0; \ } \ } while(0) #define ARG_CHECK_NO_RETURN(cond) do { \ if (EXPECT(!(cond), 0)) { \ secp256k1_callback_call(&ctx->illegal_callback, #cond); \ } \ } while(0) #ifndef USE_EXTERNAL_DEFAULT_CALLBACKS #include #include static void secp256k1_default_illegal_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); abort(); } static void secp256k1_default_error_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); abort(); } #else void secp256k1_default_illegal_callback_fn(const char* str, void* data); void secp256k1_default_error_callback_fn(const char* str, void* data); #endif static const secp256k1_callback default_illegal_callback = { secp256k1_default_illegal_callback_fn, NULL }; static const secp256k1_callback default_error_callback = { secp256k1_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; int declassify; }; static const secp256k1_context secp256k1_context_no_precomp_ = { { 0 }, { 0 }, { secp256k1_default_illegal_callback_fn, 0 }, { secp256k1_default_error_callback_fn, 0 }, 0 }; const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_no_precomp_; size_t secp256k1_context_preallocated_size(unsigned int flags) { size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context)); /* A return value of 0 is reserved as an indicator for errors when we call this function internally. */ VERIFY_CHECK(ret != 0); if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { secp256k1_callback_call(&default_illegal_callback, "Invalid flags"); return 0; } if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; } if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE; } return ret; } size_t secp256k1_context_preallocated_clone_size(const secp256k1_context* ctx) { size_t ret = ROUND_TO_ALIGN(sizeof(secp256k1_context)); VERIFY_CHECK(ctx != NULL); if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; } if (secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)) { ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE; } return ret; } secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigned int flags) { void* const base = prealloc; size_t prealloc_size; secp256k1_context* ret; if (!secp256k1_selftest()) { secp256k1_callback_call(&default_error_callback, "self test failed"); } prealloc_size = secp256k1_context_preallocated_size(flags); if (prealloc_size == 0) { return NULL; } VERIFY_CHECK(prealloc != NULL); ret = (secp256k1_context*)manual_alloc(&prealloc, sizeof(secp256k1_context), base, prealloc_size); ret->illegal_callback = default_illegal_callback; ret->error_callback = default_error_callback; secp256k1_ecmult_context_init(&ret->ecmult_ctx); secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); /* Flags have been checked by secp256k1_context_preallocated_size. */ VERIFY_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_CONTEXT); if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc); } if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { secp256k1_ecmult_context_build(&ret->ecmult_ctx, &prealloc); } ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY); return (secp256k1_context*) ret; } secp256k1_context* secp256k1_context_create(unsigned int flags) { size_t const prealloc_size = secp256k1_context_preallocated_size(flags); secp256k1_context* ctx = (secp256k1_context*)checked_malloc(&default_error_callback, prealloc_size); if (EXPECT(secp256k1_context_preallocated_create(ctx, flags) == NULL, 0)) { free(ctx); return NULL; } return ctx; } secp256k1_context* secp256k1_context_preallocated_clone(const secp256k1_context* ctx, void* prealloc) { size_t prealloc_size; secp256k1_context* ret; VERIFY_CHECK(ctx != NULL); ARG_CHECK(prealloc != NULL); prealloc_size = secp256k1_context_preallocated_clone_size(ctx); ret = (secp256k1_context*)prealloc; memcpy(ret, ctx, prealloc_size); secp256k1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx); secp256k1_ecmult_context_finalize_memcpy(&ret->ecmult_ctx, &ctx->ecmult_ctx); return ret; } secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { secp256k1_context* ret; size_t prealloc_size; VERIFY_CHECK(ctx != NULL); prealloc_size = secp256k1_context_preallocated_clone_size(ctx); ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size); ret = secp256k1_context_preallocated_clone(ctx, ret); return ret; } void secp256k1_context_preallocated_destroy(secp256k1_context* ctx) { ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp); if (ctx != NULL) { secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); } } void secp256k1_context_destroy(secp256k1_context* ctx) { if (ctx != NULL) { secp256k1_context_preallocated_destroy(ctx); free(ctx); } } void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp); if (fun == NULL) { fun = secp256k1_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) { ARG_CHECK_NO_RETURN(ctx != secp256k1_context_no_precomp); if (fun == NULL) { fun = secp256k1_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 max_size) { VERIFY_CHECK(ctx != NULL); return secp256k1_scratch_create(&ctx->error_callback, max_size); } void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scratch_space* scratch) { VERIFY_CHECK(ctx != NULL); secp256k1_scratch_destroy(&ctx->error_callback, scratch); } /* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour * of the software. This is setup for use with valgrind but could be substituted with * the appropriate instrumentation for other analysis tools. */ static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, const void *p, size_t len) { #if defined(VALGRIND) if (EXPECT(ctx->declassify,0)) VALGRIND_MAKE_MEM_DEFINED(p, len); #else (void)ctx; (void)p; (void)len; #endif } 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; } if (!secp256k1_ge_is_in_correct_subgroup(&Q)) { 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) ? 33u : 65u)); 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 *msghash32, 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(msghash32 != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(pubkey != NULL); secp256k1_scalar_set_b32(&m, msghash32, 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; static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const unsigned char algo16[17], const void* noncedata) { secp256k1_scalar sec, non, msg; int ret = 0; int is_sec_valid; unsigned char nonce32[32]; unsigned int count = 0; /* Default initialization here is important so we won't pass uninit values to the cmov in the end */ *r = secp256k1_scalar_zero; *s = secp256k1_scalar_zero; if (recid) { *recid = 0; } if (noncefp == NULL) { noncefp = secp256k1_nonce_function_default; } /* Fail if the secret key is invalid. */ is_sec_valid = secp256k1_scalar_set_b32_seckey(&sec, seckey); secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !is_sec_valid); secp256k1_scalar_set_b32(&msg, msg32, NULL); while (1) { int is_nonce_valid; ret = !!noncefp(nonce32, msg32, seckey, algo16, (void*)noncedata, count); if (!ret) { break; } is_nonce_valid = secp256k1_scalar_set_b32_seckey(&non, nonce32); /* The nonce is still secret here, but it being invalid is is less likely than 1:2^255. */ secp256k1_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid)); if (is_nonce_valid) { ret = secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, r, s, &sec, &msg, &non, recid); /* The final signature is no longer a secret, nor is the fact that we were successful or not. */ secp256k1_declassify(ctx, &ret, sizeof(ret)); if (ret) { break; } } count++; } /* We don't want to declassify is_sec_valid and therefore the range of * seckey. As a result is_sec_valid is included in ret only after ret was * used as a branching variable. */ ret &= is_sec_valid; memset(nonce32, 0, 32); secp256k1_scalar_clear(&msg); secp256k1_scalar_clear(&non); secp256k1_scalar_clear(&sec); secp256k1_scalar_cmov(r, &secp256k1_scalar_zero, !ret); secp256k1_scalar_cmov(s, &secp256k1_scalar_zero, !ret); if (recid) { const int zero = 0; secp256k1_int_cmov(recid, &zero, !ret); } return ret; } int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { secp256k1_scalar r, s; int ret; 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(msghash32 != NULL); ARG_CHECK(signature != NULL); ARG_CHECK(seckey != NULL); ret = secp256k1_ecdsa_sign_inner(ctx, &r, &s, NULL, msghash32, seckey, noncefp, secp256k1_ecdsa_der_algo16, noncedata); secp256k1_ecdsa_signature_save(signature, &r, &s); return ret; } int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { secp256k1_scalar sec; int ret; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); secp256k1_scalar_clear(&sec); return ret; } static int secp256k1_ec_pubkey_create_helper(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar *seckey_scalar, secp256k1_ge *p, const unsigned char *seckey) { secp256k1_gej pj; int ret; ret = secp256k1_scalar_set_b32_seckey(seckey_scalar, seckey); secp256k1_scalar_cmov(seckey_scalar, &secp256k1_scalar_one, !ret); secp256k1_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar); secp256k1_ge_set_gej(p, &pj); return ret; } int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { secp256k1_ge p; secp256k1_scalar seckey_scalar; 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); ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey); secp256k1_pubkey_save(pubkey, &p); secp256k1_memczero(pubkey, sizeof(*pubkey), !ret); secp256k1_scalar_clear(&seckey_scalar); return ret; } int secp256k1_ec_seckey_negate(const secp256k1_context* ctx, unsigned char *seckey) { secp256k1_scalar sec; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); secp256k1_scalar_negate(&sec, &sec); secp256k1_scalar_get_b32(seckey, &sec); secp256k1_scalar_clear(&sec); return ret; } int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { return secp256k1_ec_seckey_negate(ctx, seckey); } 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; } static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak32) { secp256k1_scalar term; int overflow = 0; int ret = 0; secp256k1_scalar_set_b32(&term, tweak32, &overflow); ret = (!overflow) & secp256k1_eckey_privkey_tweak_add(sec, &term); secp256k1_scalar_clear(&term); return ret; } int secp256k1_ec_seckey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { secp256k1_scalar sec; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ARG_CHECK(tweak32 != NULL); ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); ret &= secp256k1_ec_seckey_tweak_add_helper(&sec, tweak32); secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); secp256k1_scalar_get_b32(seckey, &sec); secp256k1_scalar_clear(&sec); return ret; } int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak32); } static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak32) { secp256k1_scalar term; int overflow = 0; secp256k1_scalar_set_b32(&term, tweak32, &overflow); return !overflow && secp256k1_eckey_pubkey_tweak_add(ecmult_ctx, p, &term); } int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) { secp256k1_ge p; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(pubkey != NULL); ARG_CHECK(tweak32 != NULL); ret = secp256k1_pubkey_load(ctx, &p, pubkey); memset(pubkey, 0, sizeof(*pubkey)); ret = ret && secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &p, tweak32); if (ret) { secp256k1_pubkey_save(pubkey, &p); } return ret; } int secp256k1_ec_seckey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { secp256k1_scalar factor; secp256k1_scalar sec; int ret = 0; int overflow = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ARG_CHECK(tweak32 != NULL); secp256k1_scalar_set_b32(&factor, tweak32, &overflow); ret = secp256k1_scalar_set_b32_seckey(&sec, seckey); ret &= (!overflow) & secp256k1_eckey_privkey_tweak_mul(&sec, &factor); secp256k1_scalar_cmov(&sec, &secp256k1_scalar_zero, !ret); secp256k1_scalar_get_b32(seckey, &sec); secp256k1_scalar_clear(&sec); secp256k1_scalar_clear(&factor); return ret; } int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { return secp256k1_ec_seckey_tweak_mul(ctx, seckey, tweak32); } int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) { 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(tweak32 != NULL); secp256k1_scalar_set_b32(&factor, tweak32, &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); if (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 #ifdef ENABLE_MODULE_EXTRAKEYS # include "modules/extrakeys/main_impl.h" #endif #ifdef ENABLE_MODULE_SCHNORRSIG # include "modules/schnorrsig/main_impl.h" #endif diff --git a/src/secp256k1/src/selftest.h b/src/secp256k1/src/selftest.h index 0e37510c1..52f1b8442 100644 --- a/src/secp256k1/src/selftest.h +++ b/src/secp256k1/src/selftest.h @@ -1,32 +1,32 @@ -/********************************************************************** - * Copyright (c) 2020 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2020 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_SELFTEST_H #define SECP256K1_SELFTEST_H #include "hash.h" #include static int secp256k1_selftest_sha256(void) { static const char *input63 = "For this sample, this 63-byte string will be used as input data"; static const unsigned char output32[32] = { 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, }; unsigned char out[32]; secp256k1_sha256 hasher; secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); secp256k1_sha256_finalize(&hasher, out); return secp256k1_memcmp_var(out, output32, 32) == 0; } static int secp256k1_selftest(void) { return secp256k1_selftest_sha256(); } #endif /* SECP256K1_SELFTEST_H */ diff --git a/src/secp256k1/src/testrand.h b/src/secp256k1/src/testrand.h index a76003d5b..667d1867b 100644 --- a/src/secp256k1/src/testrand.h +++ b/src/secp256k1/src/testrand.h @@ -1,47 +1,47 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_TESTRAND_H #define SECP256K1_TESTRAND_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif /* A non-cryptographic RNG used only for test infrastructure. */ /** Seed the pseudorandom number generator for testing. */ SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16); /** Generate a pseudorandom number in the range [0..2**32-1]. */ static uint32_t secp256k1_testrand32(void); /** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or * more. */ static uint32_t secp256k1_testrand_bits(int bits); /** Generate a pseudorandom number in the range [0..range-1]. */ static uint32_t secp256k1_testrand_int(uint32_t range); /** Generate a pseudorandom 32-byte array. */ static void secp256k1_testrand256(unsigned char *b32); /** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ static void secp256k1_testrand256_test(unsigned char *b32); /** Generate pseudorandom bytes with long sequences of zero and one bits. */ static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len); /** Flip a single random bit in a byte array */ static void secp256k1_testrand_flip(unsigned char *b, size_t len); /** Initialize the test RNG using (hex encoded) array up to 16 bytes, or randomly if hexseed is NULL. */ static void secp256k1_testrand_init(const char* hexseed); /** Print final test information. */ static void secp256k1_testrand_finish(void); #endif /* SECP256K1_TESTRAND_H */ diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h index 339256632..e643778f3 100644 --- a/src/secp256k1/src/testrand_impl.h +++ b/src/secp256k1/src/testrand_impl.h @@ -1,158 +1,158 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #ifndef SECP256K1_TESTRAND_IMPL_H #define SECP256K1_TESTRAND_IMPL_H #include #include #include #include "testrand.h" #include "hash.h" static secp256k1_rfc6979_hmac_sha256 secp256k1_test_rng; static uint32_t secp256k1_test_rng_precomputed[8]; static int secp256k1_test_rng_precomputed_used = 8; static uint64_t secp256k1_test_rng_integer; static int secp256k1_test_rng_integer_bits_left = 0; SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) { secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16); } SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) { if (secp256k1_test_rng_precomputed_used == 8) { secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed)); secp256k1_test_rng_precomputed_used = 0; } return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++]; } static uint32_t secp256k1_testrand_bits(int bits) { uint32_t ret; if (secp256k1_test_rng_integer_bits_left < bits) { secp256k1_test_rng_integer |= (((uint64_t)secp256k1_testrand32()) << secp256k1_test_rng_integer_bits_left); secp256k1_test_rng_integer_bits_left += 32; } ret = secp256k1_test_rng_integer; secp256k1_test_rng_integer >>= bits; secp256k1_test_rng_integer_bits_left -= bits; ret &= ((~((uint32_t)0)) >> (32 - bits)); return ret; } static uint32_t secp256k1_testrand_int(uint32_t range) { /* We want a uniform integer between 0 and range-1, inclusive. * B is the smallest number such that range <= 2**B. * two mechanisms implemented here: * - generate B bits numbers until one below range is found, and return it * - find the largest multiple M of range that is <= 2**(B+A), generate B+A * bits numbers until one below M is found, and return it modulo range * The second mechanism consumes A more bits of entropy in every iteration, * but may need fewer iterations due to M being closer to 2**(B+A) then * range is to 2**B. The array below (indexed by B) contains a 0 when the * first mechanism is to be used, and the number A otherwise. */ static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0}; uint32_t trange, mult; int bits = 0; if (range <= 1) { return 0; } trange = range - 1; while (trange > 0) { trange >>= 1; bits++; } if (addbits[bits]) { bits = bits + addbits[bits]; mult = ((~((uint32_t)0)) >> (32 - bits)) / range; trange = range * mult; } else { trange = range; mult = 1; } while(1) { uint32_t x = secp256k1_testrand_bits(bits); if (x < trange) { return (mult == 1) ? x : (x % range); } } } static void secp256k1_testrand256(unsigned char *b32) { secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32); } static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len) { size_t bits = 0; memset(bytes, 0, len); while (bits < len * 8) { int now; uint32_t val; now = 1 + (secp256k1_testrand_bits(6) * secp256k1_testrand_bits(5) + 16) / 31; val = secp256k1_testrand_bits(1); while (now > 0 && bits < len * 8) { bytes[bits / 8] |= val << (bits % 8); now--; bits++; } } } static void secp256k1_testrand256_test(unsigned char *b32) { secp256k1_testrand_bytes_test(b32, 32); } static void secp256k1_testrand_flip(unsigned char *b, size_t len) { b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_int(8)); } static void secp256k1_testrand_init(const char* hexseed) { unsigned char seed16[16] = {0}; if (hexseed && strlen(hexseed) != 0) { int pos = 0; while (pos < 16 && hexseed[0] != 0 && hexseed[1] != 0) { unsigned short sh; if ((sscanf(hexseed, "%2hx", &sh)) == 1) { seed16[pos] = sh; } else { break; } hexseed += 2; pos++; } } else { FILE *frand = fopen("/dev/urandom", "r"); if ((frand == NULL) || fread(&seed16, 1, sizeof(seed16), frand) != sizeof(seed16)) { uint64_t t = time(NULL) * (uint64_t)1337; fprintf(stderr, "WARNING: could not read 16 bytes from /dev/urandom; falling back to insecure PRNG\n"); 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); } } 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]); secp256k1_testrand_seed(seed16); } static void secp256k1_testrand_finish(void) { unsigned char run32[32]; secp256k1_testrand256(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]); } #endif /* SECP256K1_TESTRAND_IMPL_H */ diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c index 19c57ede2..ee41a78a2 100644 --- a/src/secp256k1/src/tests.c +++ b/src/secp256k1/src/tests.c @@ -1,5764 +1,5764 @@ -/********************************************************************** - * 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.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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 "include/secp256k1_preallocated.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" 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_testrand256_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_testrand_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); #ifdef VERIFY CHECK(fe->magnitude == n); #endif } 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_testrand_bits(1))) { secp256k1_fe_normalize(&ge->y); break; } } while(1); ge->infinity = 0; } 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_testrand256_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_testrand256(b32); secp256k1_scalar_set_b32(num, b32, &overflow); if (overflow || secp256k1_scalar_is_zero(num)) { continue; } break; } while(1); } void random_scalar_order_b32(unsigned char *b32) { secp256k1_scalar num; random_scalar_order(&num); secp256k1_scalar_get_b32(b32, &num); } void run_context_tests(int use_prealloc) { 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 *sign; secp256k1_context *vrfy; secp256k1_context *both; void *none_prealloc = NULL; void *sign_prealloc = NULL; void *vrfy_prealloc = NULL; void *both_prealloc = NULL; secp256k1_gej pubj; secp256k1_ge pub; secp256k1_scalar msg, key, nonce; secp256k1_scalar sigr, sigs; if (use_prealloc) { none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(none_prealloc != NULL); CHECK(sign_prealloc != NULL); CHECK(vrfy_prealloc != NULL); CHECK(both_prealloc != NULL); none = secp256k1_context_preallocated_create(none_prealloc, SECP256K1_CONTEXT_NONE); sign = secp256k1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN); vrfy = secp256k1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY); both = secp256k1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); } else { none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); } memset(&zero_pubkey, 0, sizeof(zero_pubkey)); 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); /* set error callback (to a function that still aborts in case malloc() fails in secp256k1_context_clone() below) */ secp256k1_context_set_error_callback(sign, secp256k1_default_illegal_callback_fn, NULL); CHECK(sign->error_callback.fn != vrfy->error_callback.fn); CHECK(sign->error_callback.fn == secp256k1_default_illegal_callback_fn); /* check if sizes for cloning are consistent */ CHECK(secp256k1_context_preallocated_clone_size(none) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(secp256k1_context_preallocated_clone_size(sign) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(secp256k1_context_preallocated_clone_size(vrfy) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(secp256k1_context_preallocated_clone_size(both) == secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); /*** clone and destroy all of them to make sure cloning was complete ***/ { secp256k1_context *ctx_tmp; if (use_prealloc) { /* clone into a non-preallocated context and then again into a new preallocated one. */ ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_preallocated_destroy(ctx_tmp); free(none_prealloc); none_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(none_prealloc != NULL); ctx_tmp = none; none = secp256k1_context_preallocated_clone(none, none_prealloc); secp256k1_context_destroy(ctx_tmp); ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_preallocated_destroy(ctx_tmp); free(sign_prealloc); sign_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(sign_prealloc != NULL); ctx_tmp = sign; sign = secp256k1_context_preallocated_clone(sign, sign_prealloc); secp256k1_context_destroy(ctx_tmp); ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_preallocated_destroy(ctx_tmp); free(vrfy_prealloc); vrfy_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(vrfy_prealloc != NULL); ctx_tmp = vrfy; vrfy = secp256k1_context_preallocated_clone(vrfy, vrfy_prealloc); secp256k1_context_destroy(ctx_tmp); ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_preallocated_destroy(ctx_tmp); free(both_prealloc); both_prealloc = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(both_prealloc != NULL); ctx_tmp = both; both = secp256k1_context_preallocated_clone(both, both_prealloc); secp256k1_context_destroy(ctx_tmp); } else { /* clone into a preallocated context and then again into a new non-preallocated one. */ void *prealloc_tmp; prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(prealloc_tmp != NULL); ctx_tmp = none; none = secp256k1_context_preallocated_clone(none, prealloc_tmp); secp256k1_context_destroy(ctx_tmp); ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_preallocated_destroy(ctx_tmp); free(prealloc_tmp); prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(prealloc_tmp != NULL); ctx_tmp = sign; sign = secp256k1_context_preallocated_clone(sign, prealloc_tmp); secp256k1_context_destroy(ctx_tmp); ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_preallocated_destroy(ctx_tmp); free(prealloc_tmp); prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL); ctx_tmp = vrfy; vrfy = secp256k1_context_preallocated_clone(vrfy, prealloc_tmp); secp256k1_context_destroy(ctx_tmp); ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_preallocated_destroy(ctx_tmp); free(prealloc_tmp); prealloc_tmp = malloc(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL); ctx_tmp = both; both = secp256k1_context_preallocated_clone(both, prealloc_tmp); secp256k1_context_destroy(ctx_tmp); ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_preallocated_destroy(ctx_tmp); free(prealloc_tmp); } } /* Verify that the error callback makes it across the clone. */ CHECK(sign->error_callback.fn != vrfy->error_callback.fn); CHECK(sign->error_callback.fn == secp256k1_default_illegal_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) == 1); CHECK(ecount == 3); CHECK(secp256k1_context_randomize(vrfy, NULL) == 1); CHECK(ecount == 3); CHECK(secp256k1_context_randomize(sign, ctmp) == 1); CHECK(ecount2 == 14); CHECK(secp256k1_context_randomize(sign, NULL) == 1); CHECK(ecount2 == 14); secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); secp256k1_context_set_illegal_callback(sign, NULL, 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 */ if (use_prealloc) { secp256k1_context_preallocated_destroy(none); secp256k1_context_preallocated_destroy(sign); secp256k1_context_preallocated_destroy(vrfy); secp256k1_context_preallocated_destroy(both); free(none_prealloc); free(sign_prealloc); free(vrfy_prealloc); free(both_prealloc); } else { secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(vrfy); secp256k1_context_destroy(both); } /* Defined as no-op. */ secp256k1_context_destroy(NULL); secp256k1_context_preallocated_destroy(NULL); } void run_scratch_tests(void) { const size_t adj_alloc = ((500 + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; int32_t ecount = 0; size_t checkpoint; size_t checkpoint_2; secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); secp256k1_scratch_space *scratch; secp256k1_scratch_space local_scratch; /* Test public API */ secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); scratch = secp256k1_scratch_space_create(none, 1000); CHECK(scratch != NULL); CHECK(ecount == 0); /* Test internal API */ CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000); CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1)); CHECK(scratch->alloc_size == 0); CHECK(scratch->alloc_size % ALIGNMENT == 0); /* Allocating 500 bytes succeeds */ checkpoint = secp256k1_scratch_checkpoint(&none->error_callback, scratch); CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) != NULL); CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc); CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1)); CHECK(scratch->alloc_size != 0); CHECK(scratch->alloc_size % ALIGNMENT == 0); /* Allocating another 501 bytes fails */ CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 501) == NULL); CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc); CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1)); CHECK(scratch->alloc_size != 0); CHECK(scratch->alloc_size % ALIGNMENT == 0); /* ...but it succeeds once we apply the checkpoint to undo it */ secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint); CHECK(scratch->alloc_size == 0); CHECK(secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000); CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) != NULL); CHECK(scratch->alloc_size != 0); /* try to apply a bad checkpoint */ checkpoint_2 = secp256k1_scratch_checkpoint(&none->error_callback, scratch); secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint); CHECK(ecount == 0); secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint_2); /* checkpoint_2 is after checkpoint */ CHECK(ecount == 1); secp256k1_scratch_apply_checkpoint(&none->error_callback, scratch, (size_t) -1); /* this is just wildly invalid */ CHECK(ecount == 2); /* try to use badly initialized scratch space */ secp256k1_scratch_space_destroy(none, scratch); memset(&local_scratch, 0, sizeof(local_scratch)); scratch = &local_scratch; CHECK(!secp256k1_scratch_max_allocation(&none->error_callback, scratch, 0)); CHECK(ecount == 3); CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, 500) == NULL); CHECK(ecount == 4); secp256k1_scratch_space_destroy(none, scratch); CHECK(ecount == 5); /* Test that large integers do not wrap around in a bad way */ scratch = secp256k1_scratch_space_create(none, 1000); /* Try max allocation with a large number of objects. Only makes sense if * ALIGNMENT is greater than 1 because otherwise the objects take no extra * space. */ CHECK(ALIGNMENT <= 1 || !secp256k1_scratch_max_allocation(&none->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1)); /* Try allocating SIZE_MAX to test wrap around which only happens if * ALIGNMENT > 1, otherwise it returns NULL anyway because the scratch * space is too small. */ CHECK(secp256k1_scratch_alloc(&none->error_callback, scratch, SIZE_MAX) == NULL); secp256k1_scratch_space_destroy(none, scratch); /* cleanup */ secp256k1_scratch_space_destroy(none, NULL); /* no-op */ 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(secp256k1_memcmp_var(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { int split = secp256k1_testrand_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(secp256k1_memcmp_var(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(secp256k1_memcmp_var(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { int split = secp256k1_testrand_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(secp256k1_memcmp_var(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(secp256k1_memcmp_var(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(secp256k1_memcmp_var(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(secp256k1_memcmp_var(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_testrand32() : secp256k1_testrand_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_testrand_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_testrand_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_testrand_bits(1)) { random_num_negate(&n1); } random_num_order_test(&n2); /* n2 = R2 */ if (secp256k1_testrand_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_testrand_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_testrand_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_testrand_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_testrand_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_set_b32_seckey_tests(void) { unsigned char b32[32]; secp256k1_scalar s1; secp256k1_scalar s2; /* Usually set_b32 and set_b32_seckey give the same result */ random_scalar_order_b32(b32); secp256k1_scalar_set_b32(&s1, b32, NULL); CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 1); CHECK(secp256k1_scalar_eq(&s1, &s2) == 1); memset(b32, 0, sizeof(b32)); CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 0); memset(b32, 0xFF, sizeof(b32)); CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 0); } void run_scalar_tests(void) { int i; for (i = 0; i < 128 * count; i++) { scalar_test(); } for (i = 0; i < count; i++) { run_scalar_set_b32_seckey_tests(); } { /* (-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 { /* Test secp256k1_scalar_set_b32 boundary conditions */ secp256k1_num order; secp256k1_scalar scalar; unsigned char bin[32]; unsigned char bin_tmp[32]; int overflow = 0; /* 2^256-1 - order */ static const secp256k1_scalar all_ones_minus_order = SECP256K1_SCALAR_CONST( 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000001UL, 0x45512319UL, 0x50B75FC4UL, 0x402DA173UL, 0x2FC9BEBEUL ); /* A scalar set to 0s should be 0. */ memset(bin, 0, 32); secp256k1_scalar_set_b32(&scalar, bin, &overflow); CHECK(overflow == 0); CHECK(secp256k1_scalar_is_zero(&scalar)); /* A scalar with value of the curve order should be 0. */ secp256k1_scalar_order_get_num(&order); secp256k1_num_get_bin(bin, 32, &order); secp256k1_scalar_set_b32(&scalar, bin, &overflow); CHECK(overflow == 1); CHECK(secp256k1_scalar_is_zero(&scalar)); /* A scalar with value of the curve order minus one should not overflow. */ bin[31] -= 1; secp256k1_scalar_set_b32(&scalar, bin, &overflow); CHECK(overflow == 0); secp256k1_scalar_get_b32(bin_tmp, &scalar); CHECK(secp256k1_memcmp_var(bin, bin_tmp, 32) == 0); /* A scalar set to all 1s should overflow. */ memset(bin, 0xFF, 32); secp256k1_scalar_set_b32(&scalar, bin, &overflow); CHECK(overflow == 1); CHECK(secp256k1_scalar_eq(&scalar, &all_ones_minus_order)); } #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_testrand256(bin); if (secp256k1_fe_set_b32(x, bin)) { return; } } while(1); } void random_fe_test(secp256k1_fe *x) { unsigned char bin[32]; do { secp256k1_testrand256_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(secp256k1_memcmp_var(b322, b32, 32) == 0); secp256k1_fe_to_storage(&fes2, &fe); CHECK(secp256k1_memcmp_var(&fes2, &fes, sizeof(fes)) == 0); } int fe_secp256k1_memcmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { secp256k1_fe t = *b; #ifdef VERIFY t.magnitude = a->magnitude; t.normalized = a->normalized; #endif return secp256k1_memcmp_var(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); #ifdef VERIFY CHECK(x.normalized && x.magnitude == 1); #endif secp256k1_fe_cmov(&x, &x, 1); CHECK(fe_secp256k1_memcmp_var(&x, &z) != 0); CHECK(fe_secp256k1_memcmp_var(&x, &q) == 0); secp256k1_fe_cmov(&q, &z, 1); #ifdef VERIFY CHECK(!q.normalized && q.magnitude == z.magnitude); #endif CHECK(fe_secp256k1_memcmp_var(&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)); #ifdef VERIFY CHECK(q.normalized && q.magnitude == 1); #endif 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)); #ifdef VERIFY CHECK((q.normalized != (j&1)) && q.magnitude == ((j&1) ? z.magnitude : 1)); #endif } 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(secp256k1_memcmp_var(&xs, &zs, sizeof(xs)) != 0); secp256k1_fe_storage_cmov(&ys, &xs, 1); CHECK(secp256k1_memcmp_var(&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_testrand_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; int runs = 6; /* 25 points are used: * - infinity * - for each of four random points p1 p2 p3 p4, we add the point, its * negation, and then those two again but with randomized Z coordinate. * - The same is then done for lambda*p1 and lambda^2*p1. */ 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); if (i >= runs - 2) { secp256k1_ge_mul_lambda(&g, &ge[1]); } if (i >= runs - 1) { secp256k1_ge_mul_lambda(&g, &g); } 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); /* Constant-time doubling. */ secp256k1_gej_double(&resj, &gej[i2]); 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_testrand_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_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_all_gej_var(ge_set_all, gej, 4 * runs + 1); 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_all[i], &gej[i]); } free(ge_set_all); free(zr); } /* Test batch gej -> ge conversion with many infinities. */ for (i = 0; i < 4 * runs + 1; i++) { random_group_element_test(&ge[i]); /* randomly set half the points to infinity */ if(secp256k1_fe_is_odd(&ge[i].x)) { secp256k1_ge_set_infinity(&ge[i]); } secp256k1_gej_set_ge(&gej[i], &ge[i]); } /* batch invert */ secp256k1_ge_set_all_gej_var(ge, gej, 4 * runs + 1); /* check result */ for (i = 0; i < 4 * runs + 1; i++) { ge_equals_gej(&ge[i], &gej[i]); } free(ge); free(gej); free(zinv); } void test_intialized_inf(void) { secp256k1_ge p; secp256k1_gej pj, npj, infj1, infj2, infj3; secp256k1_fe zinv; /* Test that adding P+(-P) results in a fully initalized infinity*/ random_group_element_test(&p); secp256k1_gej_set_ge(&pj, &p); secp256k1_gej_neg(&npj, &pj); secp256k1_gej_add_var(&infj1, &pj, &npj, NULL); CHECK(secp256k1_gej_is_infinity(&infj1)); CHECK(secp256k1_fe_is_zero(&infj1.x)); CHECK(secp256k1_fe_is_zero(&infj1.y)); CHECK(secp256k1_fe_is_zero(&infj1.z)); secp256k1_gej_add_ge_var(&infj2, &npj, &p, NULL); CHECK(secp256k1_gej_is_infinity(&infj2)); CHECK(secp256k1_fe_is_zero(&infj2.x)); CHECK(secp256k1_fe_is_zero(&infj2.y)); CHECK(secp256k1_fe_is_zero(&infj2.z)); secp256k1_fe_set_int(&zinv, 1); secp256k1_gej_add_zinv_var(&infj3, &npj, &p, &zinv); CHECK(secp256k1_gej_is_infinity(&infj3)); CHECK(secp256k1_fe_is_zero(&infj3.x)); CHECK(secp256k1_fe_is_zero(&infj3.y)); CHECK(secp256k1_fe_is_zero(&infj3.z)); } 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(); test_intialized_inf(); } 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(secp256k1_memcmp_var(&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)); 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); } /* These scalars reach large (in absolute value) outputs when fed to secp256k1_scalar_split_lambda. * * They are computed as: * - For a in [-2, -1, 0, 1, 2]: * - For b in [-3, -1, 1, 3]: * - Output (a*LAMBDA + (ORDER+b)/2) % ORDER */ static const secp256k1_scalar scalars_near_split_bounds[20] = { SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fc), SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fd), SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fe), SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6ff), SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632d), SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632e), SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf7632f), SECP256K1_SCALAR_CONST(0x2c9c52b3, 0x3fa3cf1f, 0x5ad9e3fd, 0x77ed9ba5, 0xb294b893, 0x3722e9a5, 0x00e698ca, 0x4cf76330), SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b209f), SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a0), SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a1), SECP256K1_SCALAR_CONST(0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xd576e735, 0x57a4501d, 0xdfe92f46, 0x681b20a2), SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede11), SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede12), SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede13), SECP256K1_SCALAR_CONST(0xd363ad4c, 0xc05c30e0, 0xa5261c02, 0x88126459, 0xf85915d7, 0x7825b696, 0xbeebc5c2, 0x833ede14), SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a42), SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a43), SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a44), SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a45) }; void test_ecmult_target(const secp256k1_scalar* target, int mode) { /* Mode: 0=ecmult_gen, 1=ecmult, 2=ecmult_const */ secp256k1_scalar n1, n2; secp256k1_ge p; secp256k1_gej pj, p1j, p2j, ptj; static const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); /* Generate random n1,n2 such that n1+n2 = -target. */ random_scalar_order_test(&n1); secp256k1_scalar_add(&n2, &n1, target); secp256k1_scalar_negate(&n2, &n2); /* Generate a random input point. */ if (mode != 0) { random_group_element_test(&p); secp256k1_gej_set_ge(&pj, &p); } /* EC multiplications */ if (mode == 0) { secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &p1j, &n1); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &p2j, &n2); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &ptj, target); } else if (mode == 1) { secp256k1_ecmult(&ctx->ecmult_ctx, &p1j, &pj, &n1, &zero); secp256k1_ecmult(&ctx->ecmult_ctx, &p2j, &pj, &n2, &zero); secp256k1_ecmult(&ctx->ecmult_ctx, &ptj, &pj, target, &zero); } else { secp256k1_ecmult_const(&p1j, &p, &n1, 256); secp256k1_ecmult_const(&p2j, &p, &n2, 256); secp256k1_ecmult_const(&ptj, &p, target, 256); } /* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */ secp256k1_gej_add_var(&ptj, &ptj, &p1j, NULL); secp256k1_gej_add_var(&ptj, &ptj, &p2j, NULL); CHECK(secp256k1_gej_is_infinity(&ptj)); } void run_ecmult_near_split_bound(void) { int i; unsigned j; for (i = 0; i < 4*count; ++i) { for (j = 0; j < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++j) { test_ecmult_target(&scalars_near_split_bounds[j], 0); test_ecmult_target(&scalars_near_split_bounds[j], 1); test_ecmult_target(&scalars_near_split_bounds[j], 2); } } } 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); 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, 256); 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, 256); secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b, 256); secp256k1_ge_set_gej(&mid1, &res1); secp256k1_ge_set_gej(&mid2, &res2); secp256k1_ecmult_const(&res1, &mid1, &b, 256); secp256k1_ecmult_const(&res2, &mid2, &a, 256); 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, 3); secp256k1_ge_set_gej(&res2, &res1); CHECK(secp256k1_ge_is_infinity(&res2)); secp256k1_ecmult_const(&res1, &point, &one, 2); secp256k1_ge_set_gej(&res2, &res1); ge_equals_ge(&res2, &point); secp256k1_ecmult_const(&res1, &point, &negone, 256); 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, 256); } 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; data.sc = sc; data.pt = pt; secp256k1_scalar_set_int(&szero, 0); /* No points to multiply */ CHECK(ecmult_multi(&ctx->error_callback, &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->error_callback, &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->error_callback, &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 callback returns false */ CHECK(!ecmult_multi(&ctx->error_callback, &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->error_callback, &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->error_callback, &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->error_callback, &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->error_callback, &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->error_callback, &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->error_callback, &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->error_callback, &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->error_callback, &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->error_callback, &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 */ for (ncount = 0; ncount < 20; ncount++) { random_scalar_order(&sc[ncount]); random_group_element_test(&pt[ncount]); } secp256k1_scalar_clear(&sc[0]); CHECK(ecmult_multi(&ctx->error_callback, &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->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 6)); CHECK(ecmult_multi(&ctx->error_callback, &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->error_callback, &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_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_multi) { secp256k1_scalar szero; secp256k1_scalar sc; secp256k1_ge pt; secp256k1_gej r; ecmult_multi_data data; secp256k1_scratch *scratch_empty; random_group_element_test(&pt); random_scalar_order(&sc); data.sc = ≻ data.pt = &pt; secp256k1_scalar_set_int(&szero, 0); /* Try to multiply 1 point, but scratch space is empty.*/ scratch_empty = secp256k1_scratch_create(&ctx->error_callback, 0); CHECK(!ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1)); secp256k1_scratch_destroy(&ctx->error_callback, scratch_empty); } 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++) { /* Bucket_window of 8 is not used with endo */ if (i == 8) { continue; } 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_testrand_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) { size_t i; size_t total_alloc; size_t checkpoint; scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size); CHECK(scratch != NULL); checkpoint = secp256k1_scratch_checkpoint(&ctx->error_callback, scratch); n_points_supported = secp256k1_pippenger_max_points(&ctx->error_callback, scratch); if (n_points_supported == 0) { secp256k1_scratch_destroy(&ctx->error_callback, scratch); continue; } bucket_window = secp256k1_pippenger_bucket_window(n_points_supported); /* allocate `total_alloc` bytes over `PIPPENGER_SCRATCH_OBJECTS` many allocations */ total_alloc = secp256k1_pippenger_scratch_size(n_points_supported, bucket_window); for (i = 0; i < PIPPENGER_SCRATCH_OBJECTS - 1; i++) { CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, 1)); total_alloc--; } CHECK(secp256k1_scratch_alloc(&ctx->error_callback, scratch, total_alloc)); secp256k1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint); secp256k1_scratch_destroy(&ctx->error_callback, scratch); } CHECK(bucket_window == PIPPENGER_MAX_BUCKET_WINDOW); } void test_ecmult_multi_batch_size_helper(void) { size_t n_batches, n_batch_points, max_n_batch_points, n; max_n_batch_points = 0; n = 1; CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 0); max_n_batch_points = 1; n = 0; CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == 0); CHECK(n_batch_points == 0); max_n_batch_points = 2; n = 5; CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == 3); CHECK(n_batch_points == 2); max_n_batch_points = ECMULT_MAX_POINTS_PER_BATCH; n = ECMULT_MAX_POINTS_PER_BATCH; CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == 1); CHECK(n_batch_points == ECMULT_MAX_POINTS_PER_BATCH); max_n_batch_points = ECMULT_MAX_POINTS_PER_BATCH + 1; n = ECMULT_MAX_POINTS_PER_BATCH + 1; CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == 2); CHECK(n_batch_points == ECMULT_MAX_POINTS_PER_BATCH/2 + 1); max_n_batch_points = 1; n = SIZE_MAX; CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == SIZE_MAX); CHECK(n_batch_points == 1); max_n_batch_points = 2; n = SIZE_MAX; CHECK(secp256k1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == SIZE_MAX/2 + 1); CHECK(n_batch_points == 2); } /** * 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; secp256k1_gej_neg(&r2, &r2); /* Test with empty scratch space. It should compute the correct result using * ecmult_mult_simple algorithm which doesn't require a scratch space. */ scratch = secp256k1_scratch_create(&ctx->error_callback, 0); CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &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(&ctx->error_callback, scratch); /* Test with space for 1 point in pippenger. That's not enough because * ecmult_multi selects strauss which requires more memory. It should * therefore select the simple algorithm. */ scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &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(&ctx->error_callback, scratch); for(i = 1; i <= n_points; i++) { if (i > ECMULT_PIPPENGER_THRESHOLD) { int bucket_window = secp256k1_pippenger_bucket_window(i); size_t scratch_size = secp256k1_pippenger_scratch_size(i, bucket_window); scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); } else { size_t scratch_size = secp256k1_strauss_scratch_size(i); scratch = secp256k1_scratch_create(&ctx->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); } CHECK(secp256k1_ecmult_multi_var(&ctx->error_callback, &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(&ctx->error_callback, scratch); } free(sc); free(pt); } void run_ecmult_multi_tests(void) { secp256k1_scratch *scratch; test_secp256k1_pippenger_bucket_window_inv(); test_ecmult_multi_pippenger_max_points(); scratch = secp256k1_scratch_create(&ctx->error_callback, 819200); test_ecmult_multi(scratch, secp256k1_ecmult_multi_var); test_ecmult_multi(NULL, secp256k1_ecmult_multi_var); test_ecmult_multi(scratch, secp256k1_ecmult_pippenger_batch_single); test_ecmult_multi_batch_single(secp256k1_ecmult_pippenger_batch_single); test_ecmult_multi(scratch, secp256k1_ecmult_strauss_batch_single); test_ecmult_multi_batch_single(secp256k1_ecmult_strauss_batch_single); secp256k1_scratch_destroy(&ctx->error_callback, scratch); /* Run test_ecmult_multi with space for exactly one point */ scratch = secp256k1_scratch_create(&ctx->error_callback, secp256k1_strauss_scratch_size(1) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); test_ecmult_multi(scratch, secp256k1_ecmult_multi_var); secp256k1_scratch_destroy(&ctx->error_callback, scratch); test_ecmult_multi_batch_size_helper(); 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; int bits = 256; secp256k1_scalar num = *number; secp256k1_scalar scalar_skew; secp256k1_scalar_set_int(&x, 0); secp256k1_scalar_set_int(&shift, 1 << w); for (i = 0; i < 16; ++i) { secp256k1_scalar_shr_int(&num, 8); } bits = 128; skew = secp256k1_wnaf_const(wnaf, &num, w, bits); for (i = WNAF_SIZE_BITS(bits, 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_set_int(&scalar_skew, 1 << (skew == 2)); secp256k1_scalar_add(&num, &num, &scalar_skew); 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); for (i = 0; i < 16; ++i) { secp256k1_scalar_shr_int(&num, 8); } skew = secp256k1_wnaf_fixed(wnaf, &num, w); for (i = WNAF_SIZE(w)-1; i >= 0; --i) { secp256k1_scalar t; int v = wnaf[i]; CHECK(v == 0 || v & 1); /* check parity */ CHECK(v > -(1 << w)); /* check range above */ CHECK(v < (1 << w)); /* check range below */ secp256k1_scalar_mul(&x, &x, &shift); if (v >= 0) { secp256k1_scalar_set_int(&t, v); } else { secp256k1_scalar_set_int(&t, -v); secp256k1_scalar_negate(&t, &t); } secp256k1_scalar_add(&x, &x, &t); } /* If skew is 1 then add 1 to num */ secp256k1_scalar_cadd_bit(&num, 0, skew == 1); CHECK(secp256k1_scalar_eq(&x, &num)); } /* Checks that the first 8 elements of wnaf are equal to wnaf_expected and the * rest is 0.*/ void test_fixed_wnaf_small_helper(int *wnaf, int *wnaf_expected, int w) { int i; for (i = WNAF_SIZE(w)-1; i >= 8; --i) { CHECK(wnaf[i] == 0); } for (i = 7; i >= 0; --i) { CHECK(wnaf[i] == wnaf_expected[i]); } } void test_fixed_wnaf_small(void) { int w = 4; int wnaf[256] = {0}; int i; int skew; secp256k1_scalar num; secp256k1_scalar_set_int(&num, 0); skew = secp256k1_wnaf_fixed(wnaf, &num, w); for (i = WNAF_SIZE(w)-1; i >= 0; --i) { int v = wnaf[i]; CHECK(v == 0); } CHECK(skew == 0); secp256k1_scalar_set_int(&num, 1); skew = secp256k1_wnaf_fixed(wnaf, &num, w); for (i = WNAF_SIZE(w)-1; i >= 1; --i) { int v = wnaf[i]; CHECK(v == 0); } CHECK(wnaf[0] == 1); CHECK(skew == 0); { int wnaf_expected[8] = { 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf }; secp256k1_scalar_set_int(&num, 0xffffffff); skew = secp256k1_wnaf_fixed(wnaf, &num, w); test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); CHECK(skew == 0); } { int wnaf_expected[8] = { -1, -1, -1, -1, -1, -1, -1, 0xf }; secp256k1_scalar_set_int(&num, 0xeeeeeeee); skew = secp256k1_wnaf_fixed(wnaf, &num, w); test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); CHECK(skew == 1); } { int wnaf_expected[8] = { 1, 0, 1, 0, 1, 0, 1, 0 }; secp256k1_scalar_set_int(&num, 0x01010101); skew = secp256k1_wnaf_fixed(wnaf, &num, w); test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); CHECK(skew == 0); } { int wnaf_expected[8] = { -0xf, 0, 0xf, -0xf, 0, 0xf, 1, 0 }; secp256k1_scalar_set_int(&num, 0x01ef1ef1); skew = secp256k1_wnaf_fixed(wnaf, &num, w); test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); CHECK(skew == 0); } } void run_wnaf(void) { int i; secp256k1_scalar n = {{0}}; test_constant_wnaf(&n, 4); /* 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 -1, because it's a special case in wnaf_const */ n = secp256k1_scalar_one; secp256k1_scalar_negate(&n, &n); test_constant_wnaf(&n, 4); /* Test -2, which may not lead to overflows in wnaf_const */ secp256k1_scalar_add(&n, &secp256k1_scalar_one, &secp256k1_scalar_one); secp256k1_scalar_negate(&n, &n); test_constant_wnaf(&n, 4); /* Test (1/2) - 1 = 1/-2 and 1/2 = (1/-2) + 1 as corner cases of negation handling in wnaf_const */ secp256k1_scalar_inverse(&n, &n); test_constant_wnaf(&n, 4); secp256k1_scalar_add(&n, &n, &secp256k1_scalar_one); test_constant_wnaf(&n, 4); /* Test 0 for fixed wnaf */ test_fixed_wnaf_small(); /* 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_testrand256(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(); } } /***** ENDOMORPHISH TESTS *****/ void test_scalar_split(const secp256k1_scalar* full) { secp256k1_scalar s, s1, slam; const unsigned char zero[32] = {0}; unsigned char tmp[32]; secp256k1_scalar_split_lambda(&s1, &slam, full); /* check slam*lambda + s1 == full */ secp256k1_scalar_mul(&s, &secp256k1_const_lambda, &slam); secp256k1_scalar_add(&s, &s, &s1); CHECK(secp256k1_scalar_eq(&s, 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(secp256k1_memcmp_var(zero, tmp, 16) == 0); secp256k1_scalar_get_b32(tmp, &slam); CHECK(secp256k1_memcmp_var(zero, tmp, 16) == 0); } void run_endomorphism_tests(void) { unsigned i; static secp256k1_scalar s; test_scalar_split(&secp256k1_scalar_zero); test_scalar_split(&secp256k1_scalar_one); secp256k1_scalar_negate(&s,&secp256k1_scalar_one); test_scalar_split(&s); test_scalar_split(&secp256k1_const_lambda); secp256k1_scalar_add(&s, &secp256k1_const_lambda, &secp256k1_scalar_one); test_scalar_split(&s); for (i = 0; i < 100U * count; ++i) { secp256k1_scalar full; random_scalar_order_test(&full); test_scalar_split(&full); } for (i = 0; i < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++i) { test_scalar_split(&scalars_near_split_bounds[i]); } } 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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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); CHECK(secp256k1_ec_pubkey_parse(secp256k1_context_no_precomp, &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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); pubkey_negone = pubkey; /* Tweak of zero leaves the value unchanged. */ memset(ctmp2, 0, 32); CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, ctmp2) == 1); CHECK(secp256k1_memcmp_var(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); memcpy(&pubkey2, &pubkey, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Multiply tweak of zero zeroizes the output. */ CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, ctmp2) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing seckey, the seckey is zeroized. */ memcpy(ctmp, orderc, 32); memset(ctmp2, 0, 32); ctmp2[31] = 0x01; CHECK(secp256k1_ec_seckey_verify(ctx, ctmp2) == 1); CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, ctmp2) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, ctmp2) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); /* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing tweak, the seckey is zeroized. */ memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, orderc) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; CHECK(secp256k1_ec_seckey_tweak_mul(ctx, ctmp, orderc) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; /* If pubkey_tweak_add or pubkey_tweak_mul are called with an overflowing tweak, the pubkey is zeroized. */ CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* If the resulting key in secp256k1_ec_seckey_tweak_add and * secp256k1_ec_pubkey_tweak_add is 0 the functions fail and in the latter * case the pubkey is zeroized. */ memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; memset(ctmp2, 0, 32); ctmp2[31] = 1; CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp2, ctmp) == 0); CHECK(secp256k1_memcmp_var(zeros, ctmp2, 32) == 0); ctmp2[31] = 1; CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); CHECK(secp256k1_memcmp_var(&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_seckey_tweak_add(ctx, ctmp2, ctmp) == 1); CHECK(secp256k1_memcmp_var(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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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_seckey_tweak_add(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); CHECK(secp256k1_ec_seckey_tweak_add(ctx, ctmp, NULL) == 0); CHECK(ecount == 2); ecount = 0; memset(ctmp2, 0, 32); ctmp2[31] = 1; CHECK(secp256k1_ec_seckey_tweak_mul(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); CHECK(secp256k1_ec_seckey_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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); CHECK(ecount == 1); CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); CHECK(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(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(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); CHECK(ecount == 3); secp256k1_context_set_illegal_callback(ctx, NULL, NULL); } void run_eckey_negate_test(void) { unsigned char seckey[32]; unsigned char seckey_tmp[32]; random_scalar_order_b32(seckey); memcpy(seckey_tmp, seckey, 32); /* Verify negation changes the key and changes it back */ CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) != 0); CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); /* Check that privkey alias gives same result */ CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 1); CHECK(secp256k1_ec_privkey_negate(ctx, seckey_tmp) == 1); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); /* Negating all 0s fails */ memset(seckey, 0, 32); memset(seckey_tmp, 0, 32); CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 0); /* Check that seckey is not modified */ CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); /* Negating an overflowing seckey fails and the seckey is zeroed. In this * test, the seckey has 16 random bytes to ensure that ec_seckey_negate * doesn't just set seckey to a constant value in case of failure. */ random_scalar_order_b32(seckey); memset(seckey, 0xFF, 16); memset(seckey_tmp, 0, 32); CHECK(secp256k1_ec_seckey_negate(ctx, seckey) == 0); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); } 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 getrec; /* Initialize recid to suppress a false positive -Wconditional-uninitialized in clang. VG_UNDEF ensures that valgrind will still treat the variable as uninitialized. */ int recid = -1; VG_UNDEF(&recid, sizeof(recid)); 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_testrand_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 secp256k1_memcmp_var(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_testrand_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(secp256k1_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); CHECK(secp256k1_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); /* Verify private key import and export. */ CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_testrand_bits(1) == 1)); CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); CHECK(secp256k1_memcmp_var(privkey, privkey2, 32) == 0); /* Optionally tweak the keys using addition. */ if (secp256k1_testrand_int(3) == 0) { int ret1; int ret2; int ret3; unsigned char rnd[32]; unsigned char privkey_tmp[32]; secp256k1_pubkey pubkey2; secp256k1_testrand256_test(rnd); memcpy(privkey_tmp, privkey, 32); ret1 = secp256k1_ec_seckey_tweak_add(ctx, privkey, rnd); ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); /* Check that privkey alias gives same result */ ret3 = secp256k1_ec_privkey_tweak_add(ctx, privkey_tmp, rnd); CHECK(ret1 == ret2); CHECK(ret2 == ret3); if (ret1 == 0) { return; } CHECK(secp256k1_memcmp_var(privkey, privkey_tmp, 32) == 0); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Optionally tweak the keys using multiplication. */ if (secp256k1_testrand_int(3) == 0) { int ret1; int ret2; int ret3; unsigned char rnd[32]; unsigned char privkey_tmp[32]; secp256k1_pubkey pubkey2; secp256k1_testrand256_test(rnd); memcpy(privkey_tmp, privkey, 32); ret1 = secp256k1_ec_seckey_tweak_mul(ctx, privkey, rnd); ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); /* Check that privkey alias gives same result */ ret3 = secp256k1_ec_privkey_tweak_mul(ctx, privkey_tmp, rnd); CHECK(ret1 == ret2); CHECK(ret2 == ret3); if (ret1 == 0) { return; } CHECK(secp256k1_memcmp_var(privkey, privkey_tmp, 32) == 0); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); CHECK(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&signature[0], &signature[4], sizeof(signature[0])) == 0); CHECK(secp256k1_memcmp_var(&signature[0], &signature[1], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[0], &signature[2], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[0], &signature[3], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[1], &signature[2], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&signature[1], &signature[3], sizeof(signature[0])) != 0); CHECK(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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_testrand_int(siglen)] += 1 + secp256k1_testrand_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_testrand_bits(2) == 0 ? 65 : 33; if (secp256k1_testrand_bits(2) == 0) { len = secp256k1_testrand_bits(6); } if (len == 65) { in[0] = secp256k1_testrand_bits(1) ? 4 : (secp256k1_testrand_bits(1) ? 6 : 7); } else { in[0] = secp256k1_testrand_bits(1) ? 2 : 3; } if (secp256k1_testrand_bits(3) == 0) { in[0] = secp256k1_testrand_bits(8); } if (len > 1) { secp256k1_testrand256(&in[1]); } if (len > 33) { secp256k1_testrand256(&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(secp256k1_memcmp_var(&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_testrand_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(secp256k1_memcmp_var(&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 = (secp256k1_memcmp_var(compact_der, zeroes, 32) != 0) && (secp256k1_memcmp_var(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) && secp256k1_memcmp_var(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 = (secp256k1_memcmp_var(compact_der_lax, zeroes, 32) != 0) && (secp256k1_memcmp_var(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) && secp256k1_memcmp_var(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 |= ((len_der != len_der_lax) || (secp256k1_memcmp_var(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 = secp256k1_memcmp_var(tmp, max_scalar, 32) < 0; } if (valid_openssl) { unsigned char tmp[32] = {0}; BN_bn2bin(s, tmp + 32 - BN_num_bytes(s)); valid_openssl = secp256k1_memcmp_var(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) && (secp256k1_memcmp_var(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 |= ((len_der != (size_t)len_openssl) || (secp256k1_memcmp_var(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_testrand_bits(3); if (action < 1 && *len > 3) { /* Delete a byte. */ pos = secp256k1_testrand_int(*len); memmove(sig + pos, sig + pos + 1, *len - pos - 1); (*len)--; return; } else if (action < 2 && *len < 2048) { /* Insert a byte. */ pos = secp256k1_testrand_int(1 + *len); memmove(sig + pos + 1, sig + pos, *len - pos); sig[pos] = secp256k1_testrand_bits(8); (*len)++; return; } else if (action < 4) { /* Modify a byte. */ sig[secp256k1_testrand_int(*len)] += 1 + secp256k1_testrand_int(255); return; } else { /* action < 8 */ /* Modify a bit. */ sig[secp256k1_testrand_int(*len)] ^= 1 << secp256k1_testrand_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_testrand_bits(2) == 0; *certainly_der = der; *certainly_not_der = 0; indet = der ? 0 : secp256k1_testrand_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_testrand_bits(3) != 0); /* The length of the number in bytes (the first byte of which will always be nonzero) */ nlen[n] = nlow[n] ? secp256k1_testrand_int(33) : 32 + secp256k1_testrand_int(200) * secp256k1_testrand_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_testrand_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_testrand_bits(7) : 1 + secp256k1_testrand_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_testrand_int(3) : secp256k1_testrand_int(300 - nlen[n]) * secp256k1_testrand_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_testrand_int(127 - nlenlen[n]) * secp256k1_testrand_int(16) * secp256k1_testrand_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_testrand_int(980 - tlen) * secp256k1_testrand_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_testrand_int(990 - tlen) * secp256k1_testrand_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_testrand_int(127 - tlenlen) * secp256k1_testrand_int(16) * secp256k1_testrand_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_testrand_bytes_test(sig + *len, nlen[n]); *len += nlen[n]; nlen[n] = 0; } /* Generate random garbage inside tuple. */ secp256k1_testrand_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_testrand_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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(&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(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); CHECK(secp256k1_memcmp_var(nonce, nonce3, 32) != 0); CHECK(secp256k1_memcmp_var(nonce, nonce4, 32) != 0); CHECK(secp256k1_memcmp_var(nonce2, nonce3, 32) != 0); CHECK(secp256k1_memcmp_var(nonce2, nonce4, 32) != 0); CHECK(secp256k1_memcmp_var(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_testrand_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_testrand256_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 #ifdef ENABLE_MODULE_EXTRAKEYS # include "modules/extrakeys/tests_impl.h" #endif #ifdef ENABLE_MODULE_SCHNORRSIG # include "modules/schnorrsig/tests_impl.h" #endif void run_secp256k1_memczero_test(void) { unsigned char buf1[6] = {1, 2, 3, 4, 5, 6}; unsigned char buf2[sizeof(buf1)]; /* secp256k1_memczero(..., ..., 0) is a noop. */ memcpy(buf2, buf1, sizeof(buf1)); secp256k1_memczero(buf1, sizeof(buf1), 0); CHECK(secp256k1_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); /* secp256k1_memczero(..., ..., 1) zeros the buffer. */ memset(buf2, 0, sizeof(buf2)); secp256k1_memczero(buf1, sizeof(buf1) , 1); CHECK(secp256k1_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); } void int_cmov_test(void) { int r = INT_MAX; int a = 0; secp256k1_int_cmov(&r, &a, 0); CHECK(r == INT_MAX); r = 0; a = INT_MAX; secp256k1_int_cmov(&r, &a, 1); CHECK(r == INT_MAX); a = 0; secp256k1_int_cmov(&r, &a, 1); CHECK(r == 0); a = 1; secp256k1_int_cmov(&r, &a, 1); CHECK(r == 1); r = 1; a = 0; secp256k1_int_cmov(&r, &a, 0); CHECK(r == 1); } void fe_cmov_test(void) { static const secp256k1_fe zero = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0); static const secp256k1_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); static const secp256k1_fe max = SECP256K1_FE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); secp256k1_fe r = max; secp256k1_fe a = zero; secp256k1_fe_cmov(&r, &a, 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); r = zero; a = max; secp256k1_fe_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); a = zero; secp256k1_fe_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0); a = one; secp256k1_fe_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); r = one; a = zero; secp256k1_fe_cmov(&r, &a, 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); } void fe_storage_cmov_test(void) { static const secp256k1_fe_storage zero = SECP256K1_FE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 0); static const secp256k1_fe_storage one = SECP256K1_FE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 1); static const secp256k1_fe_storage max = SECP256K1_FE_STORAGE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); secp256k1_fe_storage r = max; secp256k1_fe_storage a = zero; secp256k1_fe_storage_cmov(&r, &a, 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); r = zero; a = max; secp256k1_fe_storage_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); a = zero; secp256k1_fe_storage_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0); a = one; secp256k1_fe_storage_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); r = one; a = zero; secp256k1_fe_storage_cmov(&r, &a, 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); } void scalar_cmov_test(void) { static const secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); static const secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); static const secp256k1_scalar max = SECP256K1_SCALAR_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); secp256k1_scalar r = max; secp256k1_scalar a = zero; secp256k1_scalar_cmov(&r, &a, 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); r = zero; a = max; secp256k1_scalar_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); a = zero; secp256k1_scalar_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0); a = one; secp256k1_scalar_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); r = one; a = zero; secp256k1_scalar_cmov(&r, &a, 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); } void ge_storage_cmov_test(void) { static const secp256k1_ge_storage zero = SECP256K1_GE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); static const secp256k1_ge_storage one = SECP256K1_GE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); static const secp256k1_ge_storage max = SECP256K1_GE_STORAGE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); secp256k1_ge_storage r = max; secp256k1_ge_storage a = zero; secp256k1_ge_storage_cmov(&r, &a, 0); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); r = zero; a = max; secp256k1_ge_storage_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &max, sizeof(r)) == 0); a = zero; secp256k1_ge_storage_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &zero, sizeof(r)) == 0); a = one; secp256k1_ge_storage_cmov(&r, &a, 1); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); r = one; a = zero; secp256k1_ge_storage_cmov(&r, &a, 0); CHECK(secp256k1_memcmp_var(&r, &one, sizeof(r)) == 0); } void run_cmov_tests(void) { int_cmov_test(); fe_cmov_test(); fe_storage_cmov_test(); scalar_cmov_test(); ge_storage_cmov_test(); } int main(int argc, char **argv) { /* Disable buffering for stdout to improve reliability of getting * diagnostic information. Happens right at the start of main because * setbuf must be used before any other operation on the stream. */ setbuf(stdout, NULL); /* Also disable buffering for stderr because it's not guaranteed that it's * unbuffered on all systems. */ setbuf(stderr, NULL); /* find iteration count */ if (argc > 1) { count = strtol(argv[1], NULL, 0); } else { const char* env = getenv("SECP256K1_TEST_ITERS"); if (env) { count = strtol(env, NULL, 0); } } if (count <= 0) { fputs("An iteration count of 0 or less is not allowed.\n", stderr); return EXIT_FAILURE; } printf("test count = %i\n", count); /* find random seed */ secp256k1_testrand_init(argc > 2 ? argv[2] : NULL); /* initialize */ run_context_tests(0); run_context_tests(1); run_scratch_tests(); ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); if (secp256k1_testrand_bits(1)) { unsigned char rand32[32]; secp256k1_testrand256(rand32); CHECK(secp256k1_context_randomize(ctx, secp256k1_testrand_bits(1) ? rand32 : 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_near_split_bound(); run_ecmult_chain(); run_ecmult_constants(); run_ecmult_gen_blind(); run_ecmult_const_tests(); run_ecmult_multi_tests(); run_ec_combine(); /* endomorphism tests */ run_endomorphism_tests(); /* EC point parser test */ run_ec_pubkey_parse_test(); /* EC key edge cases */ run_eckey_edge_case_test(); /* EC key arithmetic test */ run_eckey_negate_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 #ifdef ENABLE_MODULE_EXTRAKEYS run_extrakeys_tests(); #endif #ifdef ENABLE_MODULE_SCHNORRSIG run_schnorrsig_tests(); #endif /* util tests */ run_secp256k1_memczero_test(); run_cmov_tests(); secp256k1_testrand_finish(); /* 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 f4d5b8e17..2bb538144 100644 --- a/src/secp256k1/src/tests_exhaustive.c +++ b/src/secp256k1/src/tests_exhaustive.c @@ -1,454 +1,454 @@ /*********************************************************************** - * 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.* - **********************************************************************/ + * Copyright (c) 2016 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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 #endif #include "include/secp256k1.h" #include "assumptions.h" #include "group.h" #include "secp256k1.c" #include "testrand_impl.h" static int count = 2; /** 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_testrand256(bin); if (secp256k1_fe_set_b32(x, bin)) { return; } } while(1); } /** END stolen from tests.c */ static uint32_t num_cores = 1; static uint32_t this_core = 0; SECP256K1_INLINE static int skip_section(uint64_t* iter) { if (num_cores == 1) return 0; *iter += 0xe7037ed1a0b428dbULL; return ((((uint32_t)*iter ^ (*iter >> 32)) * num_cores) >> 32) != this_core; } 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; } void test_exhaustive_endomorphism(const secp256k1_ge *group) { int i; for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { secp256k1_ge res; secp256k1_ge_mul_lambda(&res, &group[i]); ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); } } void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj) { int i, j; uint64_t iter = 0; /* Sanity-check (and check infinity functions) */ CHECK(secp256k1_ge_is_infinity(&group[0])); CHECK(secp256k1_gej_is_infinity(&groupj[0])); for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { CHECK(!secp256k1_ge_is_infinity(&group[i])); CHECK(!secp256k1_gej_is_infinity(&groupj[i])); } /* Check all addition formulae */ for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { secp256k1_fe fe_inv; if (skip_section(&iter)) continue; secp256k1_fe_inv(&fe_inv, &groupj[j].z); for (i = 0; i < EXHAUSTIVE_TEST_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) % EXHAUSTIVE_TEST_ORDER], &tmp); /* add_ge */ if (j > 0) { secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); ge_equals_gej(&group[(i + j) % EXHAUSTIVE_TEST_ORDER], &tmp); } /* add_ge_var */ secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); ge_equals_gej(&group[(i + j) % EXHAUSTIVE_TEST_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) % EXHAUSTIVE_TEST_ORDER], &tmp); } } /* Check doubling */ for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { secp256k1_gej tmp; secp256k1_gej_double(&tmp, &groupj[i]); ge_equals_gej(&group[(2 * i) % EXHAUSTIVE_TEST_ORDER], &tmp); secp256k1_gej_double_var(&tmp, &groupj[i], NULL); ge_equals_gej(&group[(2 * i) % EXHAUSTIVE_TEST_ORDER], &tmp); } /* Check negation */ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { secp256k1_ge tmp; secp256k1_gej tmpj; secp256k1_ge_neg(&tmp, &group[i]); ge_equals_ge(&group[EXHAUSTIVE_TEST_ORDER - i], &tmp); secp256k1_gej_neg(&tmpj, &groupj[i]); ge_equals_gej(&group[EXHAUSTIVE_TEST_ORDER - i], &tmpj); } } void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj) { int i, j, r_log; uint64_t iter = 0; for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) { for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { if (skip_section(&iter)) continue; for (i = 0; i < EXHAUSTIVE_TEST_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) % EXHAUSTIVE_TEST_ORDER], &tmp); if (i > 0) { secp256k1_ecmult_const(&tmp, &group[i], &ng, 256); ge_equals_gej(&group[(i * j) % EXHAUSTIVE_TEST_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 i, j, k, x, y; uint64_t iter = 0; secp256k1_scratch *scratch = secp256k1_scratch_create(&ctx->error_callback, 4096); for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { for (k = 0; k < EXHAUSTIVE_TEST_ORDER; k++) { for (x = 0; x < EXHAUSTIVE_TEST_ORDER; x++) { if (skip_section(&iter)) continue; for (y = 0; y < EXHAUSTIVE_TEST_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->error_callback, &ctx->ecmult_ctx, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2); ge_equals_gej(&group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER], &tmp); } } } } } secp256k1_scratch_destroy(&ctx->error_callback, scratch); } void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k, int* overflow) { 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, overflow); } void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group) { int s, r, msg, key; uint64_t iter = 0; for (s = 1; s < EXHAUSTIVE_TEST_ORDER; s++) { for (r = 1; r < EXHAUSTIVE_TEST_ORDER; r++) { for (msg = 1; msg < EXHAUSTIVE_TEST_ORDER; msg++) { for (key = 1; key < EXHAUSTIVE_TEST_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]; if (skip_section(&iter)) continue; 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 < EXHAUSTIVE_TEST_ORDER; k++) { secp256k1_scalar check_x_s; r_from_k(&check_x_s, group, k, NULL); 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 i, j, k; uint64_t iter = 0; /* Loop */ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { /* message */ for (j = 1; j < EXHAUSTIVE_TEST_ORDER; j++) { /* key */ if (skip_section(&iter)) continue; for (k = 1; k < EXHAUSTIVE_TEST_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, NULL); CHECK(r == expected_r); CHECK((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER || (k * (EXHAUSTIVE_TEST_ORDER - s)) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_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 #include "src/modules/recovery/tests_exhaustive_impl.h" #endif #ifdef ENABLE_MODULE_EXTRAKEYS #include "src/modules/extrakeys/tests_exhaustive_impl.h" #endif #ifdef ENABLE_MODULE_SCHNORRSIG #include "src/modules/schnorrsig/tests_exhaustive_impl.h" #endif int main(int argc, char** argv) { int i; secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; unsigned char rand32[32]; secp256k1_context *ctx; /* Disable buffering for stdout to improve reliability of getting * diagnostic information. Happens right at the start of main because * setbuf must be used before any other operation on the stream. */ setbuf(stdout, NULL); /* Also disable buffering for stderr because it's not guaranteed that it's * unbuffered on all systems. */ setbuf(stderr, NULL); printf("Exhaustive tests for order %lu\n", (unsigned long)EXHAUSTIVE_TEST_ORDER); /* find iteration count */ if (argc > 1) { count = strtol(argv[1], NULL, 0); } printf("test count = %i\n", count); /* find random seed */ secp256k1_testrand_init(argc > 2 ? argv[2] : NULL); /* set up split processing */ if (argc > 4) { num_cores = strtol(argv[3], NULL, 0); this_core = strtol(argv[4], NULL, 0); if (num_cores < 1 || this_core >= num_cores) { fprintf(stderr, "Usage: %s [count] [seed] [numcores] [thiscore]\n", argv[0]); return 1; } printf("running tests for core %lu (out of [0..%lu])\n", (unsigned long)this_core, (unsigned long)num_cores - 1); } while (count--) { /* Build context */ ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); secp256k1_testrand256(rand32); CHECK(secp256k1_context_randomize(ctx, rand32)); /* 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++) { secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); secp256k1_ge_set_gej(&group[i], &groupj[i]); if (count != 0) { /* Set a different random z-value for each Jacobian point, except z=1 is used in the last iteration. */ secp256k1_fe z; random_fe(&z); 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 */ test_exhaustive_endomorphism(group); test_exhaustive_addition(group, groupj); test_exhaustive_ecmult(ctx, group, groupj); test_exhaustive_ecmult_multi(ctx, group); test_exhaustive_sign(ctx, group); test_exhaustive_verify(ctx, group); #ifdef ENABLE_MODULE_RECOVERY test_exhaustive_recovery(ctx, group); #endif #ifdef ENABLE_MODULE_EXTRAKEYS test_exhaustive_extrakeys(ctx, group); #endif #ifdef ENABLE_MODULE_SCHNORRSIG test_exhaustive_schnorrsig(ctx); #endif secp256k1_context_destroy(ctx); } secp256k1_testrand_finish(); printf("no problems found\n"); return 0; } diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h index 2a9eb5a8d..931f71c84 100644 --- a/src/secp256k1/src/util.h +++ b/src/secp256k1/src/util.h @@ -1,279 +1,279 @@ -/********************************************************************** - * 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 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://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 #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 #if SECP256K1_GNUC_PREREQ(3, 0) #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 /* Define `VG_UNDEF` and `VG_CHECK` when VALGRIND is defined */ #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 /* Like `VG_CHECK` but on VERIFY only */ #if defined(VERIFY) #define VG_CHECK_VERIFY(x,y) VG_CHECK((x), (y)) #else #define VG_CHECK_VERIFY(x,y) #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; } #if defined(__BIGGEST_ALIGNMENT__) #define ALIGNMENT __BIGGEST_ALIGNMENT__ #else /* Using 16 bytes alignment because common architectures never have alignment * requirements above 8 for any of the types we care about. In addition we * leave some room because currently we don't care about a few bytes. */ #define ALIGNMENT 16 #endif #define ROUND_TO_ALIGN(size) (((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT) /* Assume there is a contiguous memory object with bounds [base, base + max_size) * of which the memory range [base, *prealloc_ptr) is already allocated for usage, * where *prealloc_ptr is an aligned pointer. In that setting, this functions * reserves the subobject [*prealloc_ptr, *prealloc_ptr + alloc_size) of * alloc_size bytes by increasing *prealloc_ptr accordingly, taking into account * alignment requirements. * * The function returns an aligned pointer to the newly allocated subobject. * * This is useful for manual memory management: if we're simply given a block * [base, base + max_size), the caller can use this function to allocate memory * in this block and keep track of the current allocation state with *prealloc_ptr. * * It is VERIFY_CHECKed that there is enough space left in the memory object and * *prealloc_ptr is aligned relative to base. */ static SECP256K1_INLINE void *manual_alloc(void** prealloc_ptr, size_t alloc_size, void* base, size_t max_size) { size_t aligned_alloc_size = ROUND_TO_ALIGN(alloc_size); void* ret; VERIFY_CHECK(prealloc_ptr != NULL); VERIFY_CHECK(*prealloc_ptr != NULL); VERIFY_CHECK(base != NULL); VERIFY_CHECK((unsigned char*)*prealloc_ptr >= (unsigned char*)base); VERIFY_CHECK(((unsigned char*)*prealloc_ptr - (unsigned char*)base) % ALIGNMENT == 0); VERIFY_CHECK((unsigned char*)*prealloc_ptr - (unsigned char*)base + aligned_alloc_size <= max_size); ret = *prealloc_ptr; *((unsigned char**)prealloc_ptr) += aligned_alloc_size; return ret; } /* Macro for restrict, when available and not in a VERIFY build. */ #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(__GNUC__) # define SECP256K1_GNUC_EXT __extension__ #else # define SECP256K1_GNUC_EXT #endif /* If SECP256K1_{LITTLE,BIG}_ENDIAN is not explicitly provided, infer from various other system macros. */ #if !defined(SECP256K1_LITTLE_ENDIAN) && !defined(SECP256K1_BIG_ENDIAN) /* Inspired by https://github.com/rofl0r/endianness.h/blob/9853923246b065a3b52d2c43835f3819a62c7199/endianness.h#L52L73 */ # if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ defined(_X86_) || defined(__x86_64__) || defined(__i386__) || \ defined(__i486__) || defined(__i586__) || defined(__i686__) || \ defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) || \ defined(__ARMEL__) || defined(__AARCH64EL__) || \ (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \ (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN == 1) || \ defined(_M_IX86) || defined(_M_AMD64) || defined(_M_ARM) /* MSVC */ # define SECP256K1_LITTLE_ENDIAN # endif # if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) || \ defined(__MICROBLAZEEB__) || defined(__ARMEB__) || defined(__AARCH64EB__) || \ (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \ (defined(_BIG_ENDIAN) && _BIG_ENDIAN == 1) # define SECP256K1_BIG_ENDIAN # endif #endif #if defined(SECP256K1_LITTLE_ENDIAN) == defined(SECP256K1_BIG_ENDIAN) # error Please make sure that either SECP256K1_LITTLE_ENDIAN or SECP256K1_BIG_ENDIAN is set, see src/util.h. #endif /* Zero memory if flag == 1. Flag must be 0 or 1. Constant time. */ static SECP256K1_INLINE void secp256k1_memczero(void *s, size_t len, int flag) { unsigned char *p = (unsigned char *)s; /* Access flag with a volatile-qualified lvalue. This prevents clang from figuring out (after inlining) that flag can take only be 0 or 1, which leads to variable time code. */ volatile int vflag = flag; unsigned char mask = -(unsigned char) vflag; while (len) { *p &= ~mask; p++; len--; } } /** Semantics like memcmp. Variable-time. * * We use this to avoid possible compiler bugs with memcmp, e.g. * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189 */ static SECP256K1_INLINE int secp256k1_memcmp_var(const void *s1, const void *s2, size_t n) { const unsigned char *p1 = s1, *p2 = s2; size_t i; for (i = 0; i < n; i++) { int diff = p1[i] - p2[i]; if (diff != 0) { return diff; } } return 0; } /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) { unsigned int mask0, mask1, r_masked, a_masked; /* Access flag with a volatile-qualified lvalue. This prevents clang from figuring out (after inlining) that flag can take only be 0 or 1, which leads to variable time code. */ volatile int vflag = flag; /* Casting a negative int to unsigned and back to int is implementation defined behavior */ VERIFY_CHECK(*r >= 0 && *a >= 0); mask0 = (unsigned int)vflag + ~0u; mask1 = ~mask0; r_masked = ((unsigned int)*r & mask0); a_masked = ((unsigned int)*a & mask1); *r = (int)(r_masked | a_masked); } /* If USE_FORCE_WIDEMUL_{INT128,INT64} is set, use that wide multiplication implementation. * Otherwise use the presence of __SIZEOF_INT128__ to decide. */ #if defined(USE_FORCE_WIDEMUL_INT128) # define SECP256K1_WIDEMUL_INT128 1 #elif defined(USE_FORCE_WIDEMUL_INT64) # define SECP256K1_WIDEMUL_INT64 1 #elif defined(UINT128_MAX) || defined(__SIZEOF_INT128__) # define SECP256K1_WIDEMUL_INT128 1 #else # define SECP256K1_WIDEMUL_INT64 1 #endif #if defined(SECP256K1_WIDEMUL_INT128) # if !defined(UINT128_MAX) && defined(__SIZEOF_INT128__) SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; SECP256K1_GNUC_EXT typedef __int128 int128_t; #define UINT128_MAX ((uint128_t)(-1)) #define INT128_MAX ((int128_t)(UINT128_MAX >> 1)) #define INT128_MIN (-INT128_MAX - 1) /* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */ # endif #endif #endif /* SECP256K1_UTIL_H */ diff --git a/src/secp256k1/src/valgrind_ctime_test.c b/src/secp256k1/src/valgrind_ctime_test.c index b90439e8c..73c8435f6 100644 --- a/src/secp256k1/src/valgrind_ctime_test.c +++ b/src/secp256k1/src/valgrind_ctime_test.c @@ -1,170 +1,170 @@ -/********************************************************************** - * Copyright (c) 2020 Gregory Maxwell * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2020 Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include #include "include/secp256k1.h" #include "assumptions.h" #include "util.h" #ifdef ENABLE_MODULE_ECDH # include "include/secp256k1_ecdh.h" #endif #ifdef ENABLE_MODULE_RECOVERY # include "include/secp256k1_recovery.h" #endif #ifdef ENABLE_MODULE_SCHNORR # include "include/secp256k1_schnorr.h" #endif #ifdef ENABLE_MODULE_EXTRAKEYS # include "include/secp256k1_extrakeys.h" #endif #ifdef ENABLE_MODULE_SCHNORRSIG #include "include/secp256k1_schnorrsig.h" #endif int main(void) { secp256k1_context* ctx; secp256k1_ecdsa_signature signature; secp256k1_pubkey pubkey; size_t siglen = 74; size_t outputlen = 33; int i; int ret; unsigned char msg[32]; unsigned char key[32]; unsigned char sig[74]; unsigned char spubkey[33]; #ifdef ENABLE_MODULE_RECOVERY secp256k1_ecdsa_recoverable_signature recoverable_signature; int recid; #endif #ifdef ENABLE_MODULE_EXTRAKEYS secp256k1_keypair keypair; #endif if (!RUNNING_ON_VALGRIND) { fprintf(stderr, "This test can only usefully be run inside valgrind.\n"); fprintf(stderr, "Usage: libtool --mode=execute valgrind ./valgrind_ctime_test\n"); exit(1); } /** In theory, testing with a single secret input should be sufficient: * If control flow depended on secrets the tool would generate an error. */ for (i = 0; i < 32; i++) { key[i] = i + 65; } for (i = 0; i < 32; i++) { msg[i] = i + 1; } ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_DECLASSIFY); /* Test keygen. */ VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_ec_pubkey_create(ctx, &pubkey, key); VALGRIND_MAKE_MEM_DEFINED(&pubkey, sizeof(secp256k1_pubkey)); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret); CHECK(secp256k1_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); /* Test signing. */ VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_ecdsa_sign(ctx, &signature, msg, key, NULL, NULL); VALGRIND_MAKE_MEM_DEFINED(&signature, sizeof(secp256k1_ecdsa_signature)); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret); CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature)); #ifdef ENABLE_MODULE_ECDH /* Test ECDH. */ VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_ecdh(ctx, msg, &pubkey, key, NULL, NULL); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); #endif #ifdef ENABLE_MODULE_RECOVERY /* Test signing a recoverable signature. */ VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_ecdsa_sign_recoverable(ctx, &recoverable_signature, msg, key, NULL, NULL); VALGRIND_MAKE_MEM_DEFINED(&recoverable_signature, sizeof(recoverable_signature)); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret); CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recoverable_signature)); CHECK(recid >= 0 && recid <= 3); #endif #if ENABLE_MODULE_SCHNORR /* Test schnorr signing. */ VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_schnorr_sign(ctx, sig, msg, key, NULL, NULL); VALGRIND_MAKE_MEM_DEFINED(&sig, sizeof(64)); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret); #endif VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_ec_seckey_verify(ctx, key); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_ec_seckey_negate(ctx, key); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); VALGRIND_MAKE_MEM_UNDEFINED(key, 32); VALGRIND_MAKE_MEM_UNDEFINED(msg, 32); ret = secp256k1_ec_seckey_tweak_add(ctx, key, msg); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); VALGRIND_MAKE_MEM_UNDEFINED(key, 32); VALGRIND_MAKE_MEM_UNDEFINED(msg, 32); ret = secp256k1_ec_seckey_tweak_mul(ctx, key, msg); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); /* Test context randomisation. Do this last because it leaves the context tainted. */ VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_context_randomize(ctx, key); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret); /* Test keypair_create and keypair_xonly_tweak_add. */ #ifdef ENABLE_MODULE_EXTRAKEYS VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_keypair_create(ctx, &keypair, key); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); /* The tweak is not treated as a secret in keypair_tweak_add */ VALGRIND_MAKE_MEM_DEFINED(msg, 32); ret = secp256k1_keypair_xonly_tweak_add(ctx, &keypair, msg); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); #endif #ifdef ENABLE_MODULE_SCHNORRSIG VALGRIND_MAKE_MEM_UNDEFINED(key, 32); ret = secp256k1_keypair_create(ctx, &keypair, key); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); ret = secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL); VALGRIND_MAKE_MEM_DEFINED(&ret, sizeof(ret)); CHECK(ret == 1); #endif secp256k1_context_destroy(ctx); return 0; } diff --git a/src/secp256k1/travis/build_autotools.sh b/src/secp256k1/travis/build_autotools.sh index 92366e731..d601f7bb9 100755 --- a/src/secp256k1/travis/build_autotools.sh +++ b/src/secp256k1/travis/build_autotools.sh @@ -1,102 +1,102 @@ #!/usr/bin/env bash export LC_ALL=C set -ex # FIXME The java tests will fail on macOS with autotools due to the # libsepc256k1_jni library referencing the libsecp256k1 library with an absolute # path. This needs to be rewritten with install_name_tool to use relative paths # via the @variables supported by the macOS loader. if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$JNI" = "yes" ] then echo "Skipping the java tests built with autotools on OSX" exit 0 fi if [ -n "$HOST" ]; then USE_HOST="--host=$HOST" fi if [ "x$HOST" = "xi686-linux-gnu" ]; then CC="$CC -m32" fi if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$TRAVIS_COMPILER" = "gcc" ] then CC="gcc-9" fi $CC --version ./autogen.sh mkdir buildautotools pushd buildautotools ../configure \ --enable-experimental=$EXPERIMENTAL \ --with-test-override-wide-multiply=$WIDEMUL \ --with-bignum=$BIGNUM \ --with-asm=$ASM \ --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION \ --with-ecmult-gen-precision=$ECMULTGENPRECISION \ --enable-module-ecdh=$ECDH \ --enable-module-multiset=$MULTISET \ --enable-module-recovery=$RECOVERY \ --enable-module-schnorr=$SCHNORR \ --enable-module-schnorrsig=$SCHNORRSIG \ --enable-jni=$JNI \ --enable-openssl-tests=$OPENSSL_TESTS \ --with-valgrind=$WITH_VALGRIND \ $AUTOTOOLS_EXTRA_FLAGS \ $USE_HOST print_logs() { cat tests.log || : cat exhaustive_tests.log || : cat valgrind_ctime_test.log || : cat bench.log || : } trap 'print_logs' ERR make -j2 $AUTOTOOLS_TARGET if [ "$RUN_VALGRIND" = "yes" ]; then # the `--error-exitcode` is required to make the test fail if valgrind found # errors, otherwise it'll return 0 - # (http://valgrind.org/docs/manual/manual-core.html) + # (https://www.valgrind.org/docs/manual/manual-core.html) valgrind --error-exitcode=42 ./tests 16 valgrind --error-exitcode=42 ./exhaustive_tests fi if [ "$BENCH" = "yes" ]; then if [ "$RUN_VALGRIND" = "yes" ]; then # Using the local `libtool` because on macOS the system's libtool has # nothing to do with GNU libtool EXEC='./libtool --mode=execute valgrind --error-exitcode=42'; else EXEC= ; fi $EXEC ./bench_ecmult >> bench.log 2>&1 $EXEC ./bench_internal >> bench.log 2>&1 $EXEC ./bench_sign >> bench.log 2>&1 $EXEC ./bench_verify >> bench.log 2>&1 if [ "$RECOVERY" == "yes" ]; then $EXEC ./bench_recover >> bench.log 2>&1 fi if [ "$ECDH" == "yes" ]; then $EXEC ./bench_ecdh >> bench.log 2>&1 fi if [ "$MULTISET" == "yes" ]; then $EXEC ./bench_multiset >> bench.log 2>&1 fi if [ "$SCHNORRSIG" == "yes" ]; then $EXEC ./bench_schnorrsig >> bench.log 2>&1 fi fi if [ "$CTIMETEST" = "yes" ]; then ./libtool --mode=execute valgrind --error-exitcode=42 ./valgrind_ctime_test > valgrind_ctime_test.log 2>&1 fi popd