Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schnorrsig valgrind #10

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8fcee9a
add chacha20 function
apoelstra Apr 3, 2018
6bd9424
Add schnorrsig module which implements BIP-schnorr [0] compatible sig…
apoelstra May 9, 2018
639a859
f use tagged hashes in nonce derivation and signature hash
jonasnick Aug 29, 2019
2e76c5d
f don't allow counter != 0 in nonce function
jonasnick Aug 29, 2019
7eeb3aa
f add xonly pubkey struct which is serialized as 32 byte and whose
jonasnick Aug 27, 2019
add8e78
f use xonly_pubkeys in schnorrsig sign and verify
jonasnick Sep 9, 2019
2e4ed39
f add tweak functions for xonly_pubkeys
jonasnick Sep 9, 2019
84fe427
f address some of pieter's comments
jonasnick Oct 24, 2019
e28b61c
f const casting
jonasnick Oct 24, 2019
5764b2b
f test that pubkey is zeroed after xonly_pubkey_parse returned 0
jonasnick Oct 29, 2019
74bb3b4
f don't use secp256k1_pubkeys in xonly_tweak api and instead use is_p…
jonasnick Nov 1, 2019
dfce048
f remove xonly_pubkey_to_pubkey
jonasnick Nov 1, 2019
2b36bf7
f sign -> is_positive
jonasnick Nov 1, 2019
26f95c5
f feed seckey that is actually signed with (i.e. perhaps negated) int…
jonasnick Nov 2, 2019
538052c
f reenable test vectors
jonasnick Nov 2, 2019
7e4ea97
f trigger travis
jonasnick Nov 2, 2019
b5fcf54
f uninitialized memory in tests
jonasnick Nov 3, 2019
affa6e8
f rename is_positive in xonly_pubkey api to has_square_y
jonasnick Nov 5, 2019
44881b2
f rename is_positive in schnorrsig module to has_square_y
jonasnick Nov 5, 2019
9d53733
f add new bip-schnorr test vector 14
jonasnick Nov 5, 2019
4743c1b
valgrind test
jonasnick Nov 7, 2019
a111b58
Fix ASM setting in travis
jonasnick Nov 5, 2019
540ef2d
switch to gcc
jonasnick Nov 7, 2019
0659590
fix typo
jonasnick Nov 7, 2019
9e8fe70
f typo
jonasnick Nov 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
bench_inv
bench_ecdh
bench_ecmult
bench_schnorrsig
bench_sign
bench_verify
bench_schnorr_verify
bench_recover
bench_internal
tests
Expand Down
67 changes: 30 additions & 37 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,67 +4,60 @@ addons:
apt:
packages: libgmp-dev
compiler:
- clang
- gcc
cache:
directories:
- src/java/guava/
env:
global:
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no JNI=no
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no JNI=no JNI=no SCHNORRSIG=no
- GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar
matrix:
- SCALAR=32bit RECOVERY=yes
- SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes
- SCALAR=64bit
- FIELD=64bit RECOVERY=yes
- FIELD=64bit ENDOMORPHISM=yes
- FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes
- FIELD=64bit ASM=x86_64
- FIELD=64bit ENDOMORPHISM=yes ASM=x86_64
- FIELD=32bit ENDOMORPHISM=yes
- BIGNUM=no
- BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes
- BIGNUM=no STATICPRECOMPUTATION=no
- BUILD=distcheck
- EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC
- EXTRAFLAGS=CFLAGS=-O0
- BUILD=check-java JNI=yes ECDH=yes EXPERIMENTAL=yes
- ECMULTGENPRECISION=2
- ECMULTGENPRECISION=8
matrix:
fast_finish: true
include:
- compiler: clang
env: HOST=i686-linux-gnu ENDOMORPHISM=yes
addons:
apt:
packages:
- gcc-multilib
- libgmp-dev:i386
- compiler: clang
env: HOST=i686-linux-gnu
- compiler: gcc
env:
- DVALGRIND=1
- CFLAGS=" -fno-omit-frame-pointer -g"
- ASM=no BIGNUM=no EXTRAFLAGS="--disable-openssl-tests"
- EXPERIMENTAL=yes RECOVERY=yes ECDH=yes SCHNORRSIG=yes
- ENDOMORPHISM=no
- TESTRUNS=1
addons:
apt:
packages:
- gcc-multilib
- valgrind
- compiler: gcc
env: HOST=i686-linux-gnu ENDOMORPHISM=yes
env:
- DVALGRIND=1
- CFLAGS="-fno-omit-frame-pointer -g"
- ASM=no BIGNUM=no EXTRAFLAGS="--disable-openssl-tests"
- EXPERIMENTAL=yes RECOVERY=yes ECDH=yes SCHNORRSIG=yes
- ENDOMORPHISM=no
- TESTRUNS=8
addons:
apt:
packages:
- gcc-multilib
- valgrind
- compiler: gcc
env: HOST=i686-linux-gnu
env:
- DVALGRIND=1
- CFLAGS="-fno-omit-frame-pointer -g"
- ASM=no BIGNUM=no EXTRAFLAGS="--disable-openssl-tests"
- EXPERIMENTAL=yes RECOVERY=yes ECDH=yes SCHNORRSIG=yes
- ENDOMORPHISM=no
- TESTRUNS=64
addons:
apt:
packages:
- gcc-multilib
- libgmp-dev:i386
- valgrind

before_install: mkdir -p `dirname $GUAVA_JAR`
install: if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi
before_script: ./autogen.sh
script:
- if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi
- if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi
- ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --with-ecmult-gen-precision=$ECMULTGENPRECISION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 $BUILD
- ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-asm=$ASM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --with-ecmult-gen-precision=$ECMULTGENPRECISION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-module-schnorrsig=$SCHNORRSIG --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 && valgrind --max-stackframe=2500000 ./tests $TESTRUNS && valgrind --max-stackframe=2500000 ./exhaustive_tests
after_script:
- cat ./config.log
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include
endif

if ENABLE_MODULE_SCHNORRSIG
include src/modules/schnorrsig/Makefile.am.include
endif

if ENABLE_MODULE_RECOVERY
include src/modules/recovery/Makefile.am.include
endif
15 changes: 15 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ AC_ARG_ENABLE(module_ecdh,
[enable_module_ecdh=$enableval],
[enable_module_ecdh=no])

AC_ARG_ENABLE(module_schnorrsig,
AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module (experimental)]),
[enable_module_schnorrsig=$enableval],
[enable_module_schnorrsig=no])

AC_ARG_ENABLE(module_recovery,
AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]),
[enable_module_recovery=$enableval],
Expand Down Expand Up @@ -512,6 +517,10 @@ if test x"$enable_module_ecdh" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module])
fi

if test x"$enable_module_schnorrsig" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_SCHNORRSIG, 1, [Define this symbol to enable the schnorrsig module])
fi

if test x"$enable_module_recovery" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module])
fi
Expand All @@ -531,11 +540,15 @@ if test x"$enable_experimental" = x"yes"; then
AC_MSG_NOTICE([WARNING: experimental build])
AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.])
AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
AC_MSG_NOTICE([Building schnorrsig module: $enable_module_schnorrsig])
AC_MSG_NOTICE([******])
else
if test x"$enable_module_ecdh" = x"yes"; then
AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.])
fi
if test x"$enable_module_schnorrsig" = x"yes"; then
AC_MSG_ERROR([schnorrsig module is experimental. Use --enable-experimental to allow.])
fi
if test x"$set_asm" = x"arm"; then
AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.])
fi
Expand All @@ -554,6 +567,7 @@ AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"])
AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])
AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"])
AM_CONDITIONAL([USE_JNI], [test x"$use_jni" = x"yes"])
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"])
Expand All @@ -576,6 +590,7 @@ echo " with benchmarks = $use_benchmark"
echo " with coverage = $enable_coverage"
echo " module ecdh = $enable_module_ecdh"
echo " module recovery = $enable_module_recovery"
echo " module schnorrsig = $enable_module_schnorrsig"
echo
echo " asm = $set_asm"
echo " bignum = $set_bignum"
Expand Down
171 changes: 170 additions & 1 deletion include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
/** Verify an ECDSA signature.
*
* Returns: 1: correct signature
* 0: incorrect or unparseable signature
* 0: incorrect signature
* Args: ctx: a secp256k1 context object, initialized for verification.
* In: sig: the signature being verified (cannot be NULL)
* msg32: the 32-byte message hash being verified (cannot be NULL)
Expand Down Expand Up @@ -523,6 +523,18 @@ SECP256K1_API int secp256k1_ecdsa_signature_normalize(
*/
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;

/** An implementation of the nonce generation function as defined in BIP-schnorr.
*
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
* extra entropy. If the data pointer is NULL and this function is used in
* schnorrsig_sign, it produces BIP-schnorr compliant signatures.
* When this function is used in ecdsa_sign, it generates a nonce using an
* analogue of the bip-schnorr nonce generation algorithm, but with tag
* "BIPSchnorrNULL" instead of "BIPSchnorrDerive".
* The attempt argument must be 0 or the function will fail and return 0.
*/
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_bipschnorr;

/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default;

Expand Down Expand Up @@ -701,6 +713,163 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Opaque data structure that holds a parsed and valid "x-only" public key.
* An x-only pubkey encodes a point whose Y coordinate is square. It is
* serialized using only its X coordinate (32 bytes). See bip-schnorr for more
* information about x-only pubkeys.
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, or
* comparison, use secp256k1_xonly_pubkey_serialize and
* secp256k1_xonly_pubkey_parse.
*/
typedef struct {
unsigned char data[64];
} secp256k1_xonly_pubkey;

/** Parse a 32-byte public key into a xonly_pubkey object.
*
* Returns: 1 if the public key was fully valid.
* 0 if the public key could not be parsed or is invalid.
*
* Args: ctx: a secp256k1 context object.
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
* parsed version of input. If not, its value is undefined.
* In: input32: pointer to a serialized xonly public key
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(
const secp256k1_context* ctx,
secp256k1_xonly_pubkey* pubkey,
const unsigned char *input32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Serialize a xonly pubkey object into a byte sequence.
*
* Returns: 1 always.
*
* Args: ctx: a secp256k1 context object.
* Out: output32: a pointer to a 32-byte byte array to place the
* serialized key in.
* In: pubkey: a pointer to a secp256k1_xonly_pubkey containing an
* initialized public key.
*/
SECP256K1_API int secp256k1_xonly_pubkey_serialize(
const secp256k1_context* ctx,
unsigned char *output32,
const secp256k1_xonly_pubkey* pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Compute the xonly public key for a secret key. Same as ec_pubkey_create, but
* for xonly public keys.
*
* Returns: 1 if secret was valid, public key stores
* 0 if secret was invalid, try again
*
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* Out: pubkey: pointer to the created xonly public key (cannot be NULL)
* In: seckey: pointer to a 32-byte private key (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_create(
const secp256k1_context* ctx,
secp256k1_xonly_pubkey *pubkey,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Converts a secp256k1_pubkey into a secp256k1_xonly_pubkey.
*
* Returns: 1 if the public key was successfully converted
* 0 otherwise
*
* Args: ctx: pointer to a context object
* Out: xonly_pubkey: pointer to an x-only public key object for placing the
* converted public key (cannot be NULL)
* has_square_y: pointer to an integer that will be set to 1 if the pubkey
* encodes a point with a square Y coordinate, and set to 0
* otherwise. (can be NULL)
* In: pubkey: pointer to a public key that is converted (cannot be
* NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey(
const secp256k1_context* ctx,
secp256k1_xonly_pubkey *xonly_pubkey,
int *has_square_y,
const secp256k1_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);

/** Tweak the private key of an x-only pubkey by adding a tweak to it. The public
* key of the resulting private key will be the same as the output of
* secp256k1_xonly_pubkey_tweak_add called with the same tweak and corresponding
* input public key.
*
* If the public key corresponds to a point with square Y, tweak32 is added to
* the seckey (modulo the group order). Otherwise, tweak32 is added to the
* negation of the seckey (modulo the group order).
*
* Returns: 1 if the tweak was successfully added to seckey
* 0 if the tweak was out of range or the resulting private key would be
* invalid (only when the tweak is the complement of the private key) or
* seckey is 0.
*
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* In/Out: seckey: pointer to a 32-byte private key
* In: tweak32: pointer to a 32-byte tweak
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_privkey_tweak_add(
const secp256k1_context* ctx,
unsigned char *seckey,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Tweak an x-only public key by adding tweak times the generator to it.
*
* Returns: 1 if tweak times the generator was successfully added to pubkey
* 0 if the tweak was out of range or the resulting public key would be
* invalid (only when the tweak is the complement of the corresponding
* private key).
*
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL)
* Out: output_pubkey: pointer to a public key object (cannot be NULL)
* has_square_y: pointer to an integer that will be set to 1 if the
* output_pubkey has a square Y coordinate, and set to 0
* otherwise (cannot be NULL)
* In: internal_pubkey: pointer to an x-only public key object to apply the
* tweak to (cannot be NULL)
* tweak32: pointer to a 32-byte tweak (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
const secp256k1_context* ctx,
secp256k1_xonly_pubkey *output_pubkey,
int *has_square_y,
const secp256k1_xonly_pubkey *internal_pubkey,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Verifies that output_pubkey and has_square_y is the result of calling
* secp256k1_xonly_pubkey_tweak_add with internal_pubkey and tweak32.
*
* Returns: 1 if output_pubkey is the result of tweaking the internal_pubkey with
* tweak32
* 0 otherwise
*
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL)
* In: output_pubkey: pointer to a public key object (cannot be NULL)
* has_square_y: 1 if output_pubkey has a square Y coordinate and 0 otherwise.
* internal_pubkey: pointer to an x-only public key object to apply the
* tweak to (cannot be NULL)
* tweak32: pointer to a 32-byte tweak (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_verify(
const secp256k1_context* ctx,
const secp256k1_xonly_pubkey *output_pubkey,
int has_square_y,
const secp256k1_xonly_pubkey *internal_pubkey,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

#ifdef __cplusplus
}
#endif
Expand Down
Loading