diff --git a/.gitignore b/.gitignore index 2c96eb1b6..06584376f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ target/ Cargo.lock + +#IntelliJ project files +.idea +*.iml + +CMakeLists.txt +cmake-build-debug diff --git a/.travis.yml b/.travis.yml index 3f1e0a43d..83f2bb9ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,53 @@ language: rust -sudo: false +cache: + directories: + - cargo_web -matrix: - include: - - rust: stable - - rust: beta - - rust: nightly +rust: + - stable + - beta + - nightly + - 1.22.0 +os: + - linux + - windows -install: - - | - pip install 'travis-cargo<0.2' --user && - export PATH=$HOME/.local/bin:$PATH +addons: + chrome: stable -script: - - | - travis-cargo build && - travis-cargo build -- --release && - travis-cargo test && - travis-cargo test -- --release && - travis-cargo bench && - travis-cargo --only stable doc +matrix: + exclude: + - rust: 1.22.0 + os: windows +script: + - cargo build --verbose --no-default-features + - cargo build --verbose --no-default-features --features="serde" + - cargo build --verbose --no-default-features --features="lowmemory" + - cargo build --verbose --no-default-features --features="rand" + - cargo build --verbose --no-default-features --features="rand serde recovery endomorphism" + - cargo build --verbose --no-default-features --features="fuzztarget recovery" + - cargo build --verbose --features=rand + - cargo test --no-run --features=fuzztarget + - cargo test --verbose --features=rand + - cargo test --verbose --features="rand rand-std" + - cargo test --verbose --features="rand serde" + - cargo test --verbose --features="rand serde recovery endomorphism" + - cargo build --verbose + - cargo test --verbose + - cargo build --verbose --release + - cargo test --verbose --release + - cargo run --example sign_verify + - cargo run --example sign_verify_recovery --features=recovery + - cargo run --example generate_keys --features=rand + - if [ ${TRAVIS_RUST_VERSION} == "stable" ]; then cargo doc --verbose --features="rand,serde,recovery,endomorphism"; fi + - if [ ${TRAVIS_RUST_VERSION} == "nightly" ]; then cargo test --verbose --benches --features=unstable; fi + - if [ ${TRAVIS_RUST_VERSION} == "nightly" -a "$TRAVIS_OS_NAME" = "linux" ]; then + cd no_std_test && + cargo run --release | grep -q "Verified Successfully"; + fi + - if [ ${TRAVIS_RUST_VERSION} == "stable" -a "$TRAVIS_OS_NAME" = "linux" ]; then + CARGO_TARGET_DIR=cargo_web cargo install --verbose --force cargo-web && + cargo web build --verbose --target=asmjs-unknown-emscripten && + cargo web test --verbose --target=asmjs-unknown-emscripten; + fi diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..a100a8b86 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,118 @@ + +# 0.17.2 +- Fix linking in the `fuzztarget` feature. + +# 0.17.1 + +- Correctly prefix the secp256k1-sys links field in Cargo.toml. + +# 0.17.0 + +- Move FFI into secp256k1-sys crate. +- Add `external-symbols` feature for not building upstream. +- Add functions to create a context from a raw pointer. +- Support passing custom hash functions to ECDH. +- Wrap Secp256k1 from raw context in a ManuallyDrop. + +# 0.15.4 - 2019-09-06 + +- Add `rand-std` feature. +- Pin the cc build-dep version to `< 1.0.42` to remain + compatible with rustc 1.22.0. +- Changed all `as_*ptr()` to a new safer `CPtr` trait + +# 0.15.2 - 2019-08-08 + +- Add feature `lowmemory` that reduces the EC mult window size to require + significantly less memory for the validation context (~680B instead of + ~520kB), at the cost of slower validation. It does not affect the speed of + signing, nor the size of the signing context. + +# 0.15.0 - 2019-07-25 + +* Implement hex human-readable serde for PublicKey +* Implement fmt::LowerHex for SecretKey and PublicKey +* Relax `cc` dependency requirements +* Add links manifest key to prevent cross-version linkage + +# 0.14.1 - 2019-07-14 + +* Implemented FFI functions: `secp256k1_context_create` and `secp256k1_context_destroy` in rust. + +# 0.14.0 - 2019-07-08 + +* [Feature-gate endormorphism optimization](https://github.com/rust-bitcoin/rust-secp256k1/pull/120) + because of a lack of clarity with respect to patents +* Got full no-std support including eliminating all use of libc in C bindings. + [PR 1](https://github.com/rust-bitcoin/rust-secp256k1/pull/115) + [PR 2](https://github.com/rust-bitcoin/rust-secp256k1/pull/125). + This library should be usable in bare-metal environments and with rust-wasm. + Thanks to Elichai Turkel for driving this forward! +* Update upstream libsecp256k1 version to 143dc6e9ee31852a60321b23eea407d2006171da + +# 0.13.0 - 2019-05-21 + +* Update minimum supported rust compiler 1.22. +* Replace `serialize_der` function with `SerializedSignature` struct. +* Allow building without a standard library (`no_std`). `std` feature is on by default. +* Add human readable serialization to `Signatures` and `SecretKeys`. +* Stop displaying 0 bytes if a `Signature` is less than 72 bytes. +* Only compile recovery module if feature `recovery` is set (non-default). +* Update `rand` dependency from 0.4 to 0.6 and add `rand_core` 0.4 dependency. +* Relax `cc` dependency requirements. + +# 0.12.2 - 2019-01-18 + +* Fuzzer bug fix + +# 0.12.1 - 2019-01-15 + +* Minor bug fixes +* Fixed `cc` crate version to maintain minimum compiler version without breakage +* Removed `libc` dependency as it our uses have been subsumed into stdlib + +# 0.12.0 - 2018-12-03 + +* **Overhaul API to remove context object when no precomputation is needed** +* Add `ThirtyTwoByteHash` trait which allows infallible conversions to `Message`s +* Disallow 0-valued `Message` objects since signatures on them are forgeable for all keys +* Remove `ops::Index` implementations for `Signature` +* Remove depecated constants and unsafe `ZERO_KEY` constant + +# 0.11.5 - 2018-11-09 + +* Use `pub extern crate` to export dependencies whose types are exported + +# 0.11.4 - 2018-11-04 + +* Add `FromStr` and `Display` for `Signature` and both key types +* Fix `build.rs` for Windows and rustfmt configuration for docs.rs +* Correct endianness issue for `Signature` `Debug` output + +# 0.11.3 - 2018-10-28 + +* No changes, just fixed docs.rs configuration + +# 0.11.2 - 2018-09-11 + +* Correct endianness issue in RFC6979 nonce generation + +# 0.11.1 - 2018-08-22 + +* Put `PublicKey::combine` back because it is currently needed to implement Lightning BOLT 3 + +# 0.11.0 - 2018-08-22 + +* Update `rand` to 0.4 and `gcc` 0.3 to `cc` 1.0. (`rand` 0.5 exists but has a lot of breaking changes and no longer compiles with 1.14.0.) +* Remove `PublicKey::combine` from API since it cannot be used with anything else in the API +* Detect whether 64-bit compilation is possible, and do it if we can (big performance improvement) + +# 0.10.0 - 2018-07-25 + +* A [complete API overhaul](https://github.com/rust-bitcoin/rust-secp256k1/pull/27) to move many runtime errors into compiletime errors +* Update [libsecp256k1 to `1e6f1f5ad5e7f1e3ef79313ec02023902bf8`](https://github.com/rust-bitcoin/rust-secp256k1/pull/32). Should be no visible changes. +* [Remove `PublicKey::new()` and `PublicKey::is_valid()`](https://github.com/rust-bitcoin/rust-secp256k1/pull/37) since `new` was unsafe and it should now be impossible to create invalid `PublicKey` objects through the API +* [Reintroduce serde support](https://github.com/rust-bitcoin/rust-secp256k1/pull/38) behind a feature gate using serde 1.0 +* Clean up build process and various typos + + diff --git a/Cargo.toml b/Cargo.toml index 582078290..da4fbed3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,20 +1,21 @@ [package] name = "secp256k1" -version = "0.5.4" +version = "0.17.2" authors = [ "Dawid Ciężarkiewicz ", "Andrew Poelstra " ] license = "CC0-1.0" -homepage = "https://github.com/apoelstra/rust-secp256k1/" -repository = "https://github.com/apoelstra/rust-secp256k1/" -documentation = "https://www.wpsoftware.net/rustdoc/secp256k1/" +homepage = "https://github.com/rust-bitcoin/rust-secp256k1/" +repository = "https://github.com/rust-bitcoin/rust-secp256k1/" +documentation = "https://docs.rs/secp256k1/" description = "Rust bindings for Pieter Wuille's `libsecp256k1` library. Implements ECDSA for the SECG elliptic curve group secp256k1 and related utilities." keywords = [ "crypto", "ECDSA", "secp256k1", "libsecp256k1", "bitcoin" ] readme = "README.md" +autoexamples = false # Remove when edition 2018 https://github.com/rust-lang/cargo/issues/5330 -build = "build.rs" -[build-dependencies] -gcc = "0.3" +# Should make docs.rs show all functions, even those behind non-default features +[package.metadata.docs.rs] +features = [ "rand", "rand-std", "serde", "recovery", "endomorphism" ] [lib] name = "secp256k1" @@ -22,15 +23,46 @@ path = "src/lib.rs" [features] unstable = [] -default = [] -dev = ["clippy"] +default = ["std"] +std = ["secp256k1-sys/std"] +rand-std = ["rand/std"] +recovery = ["secp256k1-sys/recovery"] +endomorphism = ["secp256k1-sys/endomorphism"] +lowmemory = ["secp256k1-sys/lowmemory"] + +# Use this feature to not compile the bundled libsecp256k1 C symbols, +# but use external ones. Use this only if you know what you are doing! +external-symbols = ["secp256k1-sys/external-symbols"] + +# Do not use this feature! HAZMAT. (meant for Fuzzing only. this is *BROKEN CRYPTOGRAPHY*) +fuzztarget = ["secp256k1-sys/fuzztarget"] [dependencies] -arrayvec = "0.3" -clippy = {version = "0.0", optional = true} -rand = "0.3" -libc = "0.1" -rustc-serialize = "0.3" -serde = "0.6" -serde_json = "0.6" +secp256k1-sys = { version = "0.1.1", default-features = false, path = "./secp256k1-sys" } + +[dev-dependencies] +rand = "0.6" +rand_core = "0.4" +serde_test = "1.0" +bitcoin_hashes = "0.7" + +[dependencies.rand] +version = "0.6" +optional = true +default-features = false + +[dependencies.serde] +version = "1.0" +optional = true +default-features = false + +[[example]] +name = "sign_verify_recovery" +required-features = ["recovery"] + +[[example]] +name = "sign_verify" +[[example]] +name = "generate_keys" +required-features = ["rand"] diff --git a/README.md b/README.md index 1665fb6db..5ae0e0949 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ -[![Build Status](https://travis-ci.org/apoelstra/rust-secp256k1.png?branch=master)](https://travis-ci.org/apoelstra/rust-secp256k1) +[![Build Status](https://travis-ci.org/rust-bitcoin/rust-secp256k1.png?branch=master)](https://travis-ci.org/rust-bitcoin/rust-secp256k1) + +[Full documentation](https://docs.rs/secp256k1/) ### rust-secp256k1 -`rust-secp256k1` is a wrapper around ![libsecp256k1](https://github.com/bitcoin/secp256k1), -a C library by Peter Wuille for producing ECDSA signatures using the SECG curve +`rust-secp256k1` is a wrapper around ![libsecp256k1](https://github.com/bitcoin-core/secp256k1), +a C library by Pieter Wuille for producing ECDSA signatures using the SECG curve `secp256k1`. This library * exposes type-safe Rust bindings for all `libsecp256k1` functions * implements key generation @@ -11,5 +13,11 @@ a C library by Peter Wuille for producing ECDSA signatures using the SECG curve * implements many unit tests, adding to those already present in `libsecp256k1` * makes no allocations (except in unit tests) for efficiency and use in freestanding implementations -[Full documentation](https://www.wpsoftware.net/rustdoc/secp256k1/) +### Contributing + +Contributions to this library are welcome. A few guidelines: +* Any breaking changes must have an accompanied entry in CHANGELOG.md +* No new dependencies, please. +* No crypto should be implemented in Rust, with the possible exception of hash functions. Cryptographic contributions should be directed upstream to libsecp256k1. +* This library should always compile with any combination of features on **Rust 1.22**. diff --git a/build.rs b/build.rs deleted file mode 100644 index db708633a..000000000 --- a/build.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Bitcoin secp256k1 bindings -// Written in 2015 by -// Andrew Poelstra -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. -// If not, see . -// - -//! # Build script - -// Coding conventions -#![deny(non_upper_case_globals)] -#![deny(non_camel_case_types)] -#![deny(non_snake_case)] -#![deny(unused_mut)] -#![warn(missing_docs)] - -extern crate gcc; - -fn main() { - let mut base_config = gcc::Config::new(); - base_config.include("depend/secp256k1/") - .include("depend/secp256k1/include") - .include("depend/secp256k1/src") - .flag("-g") - // TODO these three should be changed to use libgmp, at least until secp PR 290 is merged - .define("USE_NUM_NONE", Some("1")) - .define("USE_FIELD_INV_BUILTIN", Some("1")) - .define("USE_SCALAR_INV_BUILTIN", Some("1")) - // TODO these should use 64-bit variants on 64-bit systems - .define("USE_FIELD_10X26", Some("1")) - .define("USE_SCALAR_8X32", Some("1")) - .define("USE_ENDOMORPHISM", Some("1")) - // These all are OK. - .define("ENABLE_MODULE_ECDH", Some("1")) - .define("ENABLE_MODULE_SCHNORR", Some("1")) - .define("ENABLE_MODULE_RECOVERY", Some("1")); - - // secp256k1 - base_config.file("depend/secp256k1/contrib/lax_der_parsing.c") - .file("depend/secp256k1/src/secp256k1.c") - .compile("libsecp256k1.a"); -} - diff --git a/depend/secp256k1/Makefile.am b/depend/secp256k1/Makefile.am deleted file mode 100644 index 41fc09f2d..000000000 --- a/depend/secp256k1/Makefile.am +++ /dev/null @@ -1,111 +0,0 @@ -ACLOCAL_AMFLAGS = -I build-aux/m4 - -lib_LTLIBRARIES = libsecp256k1.la -include_HEADERS = include/secp256k1.h -noinst_HEADERS = -noinst_HEADERS += src/scalar.h -noinst_HEADERS += src/scalar_4x64.h -noinst_HEADERS += src/scalar_8x32.h -noinst_HEADERS += src/scalar_impl.h -noinst_HEADERS += src/scalar_4x64_impl.h -noinst_HEADERS += src/scalar_8x32_impl.h -noinst_HEADERS += src/group.h -noinst_HEADERS += src/group_impl.h -noinst_HEADERS += src/num_gmp.h -noinst_HEADERS += src/num_gmp_impl.h -noinst_HEADERS += src/ecdsa.h -noinst_HEADERS += src/ecdsa_impl.h -noinst_HEADERS += src/eckey.h -noinst_HEADERS += src/eckey_impl.h -noinst_HEADERS += src/ecmult.h -noinst_HEADERS += src/ecmult_impl.h -noinst_HEADERS += src/ecmult_const.h -noinst_HEADERS += src/ecmult_const_impl.h -noinst_HEADERS += src/ecmult_gen.h -noinst_HEADERS += src/ecmult_gen_impl.h -noinst_HEADERS += src/num.h -noinst_HEADERS += src/num_impl.h -noinst_HEADERS += src/field_10x26.h -noinst_HEADERS += src/field_10x26_impl.h -noinst_HEADERS += src/field_5x52.h -noinst_HEADERS += src/field_5x52_impl.h -noinst_HEADERS += src/field_5x52_int128_impl.h -noinst_HEADERS += src/field_5x52_asm_impl.h -noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h -noinst_HEADERS += src/util.h -noinst_HEADERS += src/testrand.h -noinst_HEADERS += src/testrand_impl.h -noinst_HEADERS += src/hash.h -noinst_HEADERS += src/hash_impl.h -noinst_HEADERS += src/field.h -noinst_HEADERS += src/field_impl.h -noinst_HEADERS += src/bench.h -noinst_HEADERS += contrib/lax_der_parsing.h -noinst_HEADERS += contrib/lax_der_parsing.c -noinst_HEADERS += contrib/lax_der_privatekey_parsing.h -noinst_HEADERS += contrib/lax_der_privatekey_parsing.c - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libsecp256k1.pc - -libsecp256k1_la_SOURCES = src/secp256k1.c -libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) -libsecp256k1_la_LIBADD = $(SECP_LIBS) - - -noinst_PROGRAMS = -if USE_BENCHMARK -noinst_PROGRAMS += bench_verify bench_sign bench_internal -bench_verify_SOURCES = src/bench_verify.c -bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) -bench_sign_SOURCES = src/bench_sign.c -bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) -bench_internal_SOURCES = src/bench_internal.c -bench_internal_LDADD = $(SECP_LIBS) -bench_internal_CPPFLAGS = $(SECP_INCLUDES) -endif - -if USE_TESTS -noinst_PROGRAMS += tests -tests_SOURCES = src/tests.c -tests_CPPFLAGS = -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) -tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) -tests_LDFLAGS = -static -TESTS = tests -endif - -if USE_ECMULT_STATIC_PRECOMPUTATION -CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) -CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function - -gen_context_OBJECTS = gen_context.o -gen_context_BIN = gen_context$(BUILD_EXEEXT) -gen_%.o: src/gen_%.c - $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ - -$(gen_context_BIN): $(gen_context_OBJECTS) - $(CC_FOR_BUILD) $^ -o $@ - -$(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h -$(tests_OBJECTS): src/ecmult_static_context.h -$(bench_internal_OBJECTS): src/ecmult_static_context.h - -src/ecmult_static_context.h: $(gen_context_BIN) - ./$(gen_context_BIN) - -CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h -endif - -EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h - -if ENABLE_MODULE_ECDH -include src/modules/ecdh/Makefile.am.include -endif - -if ENABLE_MODULE_SCHNORR -include src/modules/schnorr/Makefile.am.include -endif - -if ENABLE_MODULE_RECOVERY -include src/modules/recovery/Makefile.am.include -endif diff --git a/depend/secp256k1/include/secp256k1_ecdh.h b/depend/secp256k1/include/secp256k1_ecdh.h deleted file mode 100644 index 4b84d7a96..000000000 --- a/depend/secp256k1/include/secp256k1_ecdh.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _SECP256K1_ECDH_ -# define _SECP256K1_ECDH_ - -# include "secp256k1.h" - -# ifdef __cplusplus -extern "C" { -# endif - -/** Compute an EC Diffie-Hellman secret in constant time - * Returns: 1: exponentiation was successful - * 0: scalar was invalid (zero or overflow) - * Args: ctx: pointer to a context object (cannot be NULL) - * Out: result: a 32-byte array which will be populated by an ECDH - * secret computed from the point and scalar - * In: pubkey: a pointer to a secp256k1_pubkey containing an - * initialized public key - * privkey: a 32-byte scalar with which to multiply the point - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( - const secp256k1_context* ctx, - unsigned char *result, - const secp256k1_pubkey *pubkey, - const unsigned char *privkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/depend/secp256k1/include/secp256k1_schnorr.h b/depend/secp256k1/include/secp256k1_schnorr.h deleted file mode 100644 index dc32fec1e..000000000 --- a/depend/secp256k1/include/secp256k1_schnorr.h +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef _SECP256K1_SCHNORR_ -# define _SECP256K1_SCHNORR_ - -# include "secp256k1.h" - -# ifdef __cplusplus -extern "C" { -# endif - -/** Create a signature using a custom EC-Schnorr-SHA256 construction. It - * produces non-malleable 64-byte signatures which support public key recovery - * batch validation, and multiparty signing. - * Returns: 1: signature created - * 0: the nonce generation function failed, or the private key was - * invalid. - * Args: ctx: pointer to a context object, initialized for signing - * (cannot be NULL) - * Out: sig64: pointer to a 64-byte array where the signature will be - * placed (cannot be NULL) - * In: msg32: the 32-byte message hash being signed (cannot be NULL) - * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, - * secp256k1_nonce_function_default is used - * ndata: pointer to arbitrary data used by the nonce generation - * function (can be NULL) - */ -SECP256K1_API int secp256k1_schnorr_sign( - const secp256k1_context* ctx, - unsigned char *sig64, - const unsigned char *msg32, - const unsigned char *seckey, - secp256k1_nonce_function noncefp, - const void *ndata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Verify a signature created by secp256k1_schnorr_sign. - * Returns: 1: correct signature - * 0: incorrect signature - * Args: ctx: a secp256k1 context object, initialized for verification. - * In: sig64: the 64-byte signature being verified (cannot be NULL) - * msg32: the 32-byte message hash being verified (cannot be NULL) - * pubkey: the public key to verify with (cannot be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_verify( - const secp256k1_context* ctx, - const unsigned char *sig64, - const unsigned char *msg32, - const secp256k1_pubkey *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Recover an EC public key from a Schnorr signature created using - * secp256k1_schnorr_sign. - * Returns: 1: public key successfully recovered (which guarantees a correct - * signature). - * 0: otherwise. - * Args: ctx: pointer to a context object, initialized for - * verification (cannot be NULL) - * Out: pubkey: pointer to a pubkey to set to the recovered public key - * (cannot be NULL). - * In: sig64: signature as 64 byte array (cannot be NULL) - * msg32: the 32-byte message hash assumed to be signed (cannot - * be NULL) - */ -SECP256K1_API int secp256k1_schnorr_recover( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const unsigned char *sig64, - const unsigned char *msg32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Generate a nonce pair deterministically for use with - * secp256k1_schnorr_partial_sign. - * Returns: 1: valid nonce pair was generated. - * 0: otherwise (nonce generation function failed) - * Args: ctx: pointer to a context object, initialized for signing - * (cannot be NULL) - * Out: pubnonce: public side of the nonce (cannot be NULL) - * privnonce32: private side of the nonce (32 byte) (cannot be NULL) - * In: msg32: the 32-byte message hash assumed to be signed (cannot - * be NULL) - * sec32: the 32-byte private key (cannot be NULL) - * noncefp: pointer to a nonce generation function. If NULL, - * secp256k1_nonce_function_default is used - * noncedata: pointer to arbitrary data used by the nonce generation - * function (can be NULL) - * - * Do not use the output as a private/public key pair for signing/validation. - */ -SECP256K1_API int secp256k1_schnorr_generate_nonce_pair( - const secp256k1_context* ctx, - secp256k1_pubkey *pubnonce, - unsigned char *privnonce32, - const unsigned char *msg32, - const unsigned char *sec32, - secp256k1_nonce_function noncefp, - const void* noncedata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Produce a partial Schnorr signature, which can be combined using - * secp256k1_schnorr_partial_combine, to end up with a full signature that is - * verifiable using secp256k1_schnorr_verify. - * Returns: 1: signature created successfully. - * 0: no valid signature exists with this combination of keys, nonces - * and message (chance around 1 in 2^128) - * -1: invalid private key, nonce, or public nonces. - * Args: ctx: pointer to context object, initialized for signing (cannot - * be NULL) - * Out: sig64: pointer to 64-byte array to put partial signature in - * In: msg32: pointer to 32-byte message to sign - * sec32: pointer to 32-byte private key - * pubnonce_others: pointer to pubkey containing the sum of the other's - * nonces (see secp256k1_ec_pubkey_combine) - * secnonce32: pointer to 32-byte array containing our nonce - * - * The intended procedure for creating a multiparty signature is: - * - Each signer S[i] with private key x[i] and public key Q[i] runs - * secp256k1_schnorr_generate_nonce_pair to produce a pair (k[i],R[i]) of - * private/public nonces. - * - All signers communicate their public nonces to each other (revealing your - * private nonce can lead to discovery of your private key, so it should be - * considered secret). - * - All signers combine all the public nonces they received (excluding their - * own) using secp256k1_ec_pubkey_combine to obtain an - * Rall[i] = sum(R[0..i-1,i+1..n]). - * - All signers produce a partial signature using - * secp256k1_schnorr_partial_sign, passing in their own private key x[i], - * their own private nonce k[i], and the sum of the others' public nonces - * Rall[i]. - * - All signers communicate their partial signatures to each other. - * - Someone combines all partial signatures using - * secp256k1_schnorr_partial_combine, to obtain a full signature. - * - The resulting signature is validatable using secp256k1_schnorr_verify, with - * public key equal to the result of secp256k1_ec_pubkey_combine of the - * signers' public keys (sum(Q[0..n])). - * - * Note that secp256k1_schnorr_partial_combine and secp256k1_ec_pubkey_combine - * function take their arguments in any order, and it is possible to - * pre-combine several inputs already with one call, and add more inputs later - * by calling the function again (they are commutative and associative). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_sign( - const secp256k1_context* ctx, - unsigned char *sig64, - const unsigned char *msg32, - const unsigned char *sec32, - const secp256k1_pubkey *pubnonce_others, - const unsigned char *secnonce32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); - -/** Combine multiple Schnorr partial signatures. - * Returns: 1: the passed signatures were successfully combined. - * 0: the resulting signature is not valid (chance of 1 in 2^256) - * -1: some inputs were invalid, or the signatures were not created - * using the same set of nonces - * Args: ctx: pointer to a context object - * Out: sig64: pointer to a 64-byte array to place the combined signature - * (cannot be NULL) - * In: sig64sin: pointer to an array of n pointers to 64-byte input - * signatures - * n: the number of signatures to combine (at least 1) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_partial_combine( - const secp256k1_context* ctx, - unsigned char *sig64, - const unsigned char * const * sig64sin, - size_t n -) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/depend/secp256k1/src/bench_schnorr_verify.c b/depend/secp256k1/src/bench_schnorr_verify.c deleted file mode 100644 index 5f137dda2..000000000 --- a/depend/secp256k1/src/bench_schnorr_verify.c +++ /dev/null @@ -1,73 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "include/secp256k1.h" -#include "include/secp256k1_schnorr.h" -#include "util.h" -#include "bench.h" - -typedef struct { - unsigned char key[32]; - unsigned char sig[64]; - unsigned char pubkey[33]; - size_t pubkeylen; -} benchmark_schnorr_sig_t; - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - benchmark_schnorr_sig_t sigs[64]; - int numsigs; -} benchmark_schnorr_verify_t; - -static void benchmark_schnorr_init(void* arg) { - int i, k; - benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = 1 + i; - } - for (k = 0; k < data->numsigs; k++) { - secp256k1_pubkey pubkey; - for (i = 0; i < 32; i++) { - data->sigs[k].key[i] = 33 + i + k; - } - secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL); - data->sigs[k].pubkeylen = 33; - CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); - } -} - -static void benchmark_schnorr_verify(void* arg) { - int i; - benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; - - for (i = 0; i < 20000 / data->numsigs; i++) { - secp256k1_pubkey pubkey; - data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen)); - CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0)); - data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); - } -} - - - -int main(void) { - benchmark_schnorr_verify_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - data.numsigs = 1; - run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000); - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/depend/secp256k1/src/ecdsa.h b/depend/secp256k1/src/ecdsa.h deleted file mode 100644 index 54ae101b9..000000000 --- a/depend/secp256k1/src/ecdsa.h +++ /dev/null @@ -1,21 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECDSA_ -#define _SECP256K1_ECDSA_ - -#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 diff --git a/depend/secp256k1/src/eckey.h b/depend/secp256k1/src/eckey.h deleted file mode 100644 index 42739a3be..000000000 --- a/depend/secp256k1/src/eckey.h +++ /dev/null @@ -1,25 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECKEY_ -#define _SECP256K1_ECKEY_ - -#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 diff --git a/depend/secp256k1/src/eckey_impl.h b/depend/secp256k1/src/eckey_impl.h deleted file mode 100644 index ce38071ac..000000000 --- a/depend/secp256k1/src/eckey_impl.h +++ /dev/null @@ -1,99 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_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] == 0x02 || pub[0] == 0x03)) { - secp256k1_fe x; - return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03); - } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { - 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] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) { - 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] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); - } else { - *size = 65; - pub[0] = 0x04; - 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); - if (secp256k1_scalar_is_zero(key)) { - return 0; - } - return 1; -} - -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) { - if (secp256k1_scalar_is_zero(tweak)) { - return 0; - } - - secp256k1_scalar_mul(key, key, tweak); - return 1; -} - -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 diff --git a/depend/secp256k1/src/ecmult.h b/depend/secp256k1/src/ecmult.h deleted file mode 100644 index 20484134f..000000000 --- a/depend/secp256k1/src/ecmult.h +++ /dev/null @@ -1,31 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_ -#define _SECP256K1_ECMULT_ - -#include "num.h" -#include "group.h" - -typedef struct { - /* For accelerating the computation of a*P + b*G: */ - secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ -#ifdef USE_ENDOMORPHISM - secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ -#endif -} secp256k1_ecmult_context; - -static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); -static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb); -static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, - const secp256k1_ecmult_context *src, const secp256k1_callback *cb); -static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx); -static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx); - -/** Double multiply: R = na*A + ng*G */ -static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); - -#endif diff --git a/depend/secp256k1/src/ecmult_const_impl.h b/depend/secp256k1/src/ecmult_const_impl.h deleted file mode 100644 index 90ac94770..000000000 --- a/depend/secp256k1/src/ecmult_const_impl.h +++ /dev/null @@ -1,260 +0,0 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_CONST_IMPL_ -#define _SECP256K1_ECMULT_CONST_IMPL_ - -#include "scalar.h" -#include "group.h" -#include "ecmult_const.h" -#include "ecmult_impl.h" - -#ifdef USE_ENDOMORPHISM - #define WNAF_BITS 128 -#else - #define WNAF_BITS 256 -#endif -#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) - -/* This is like `ECMULT_TABLE_GET_GE` but is constant time */ -#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ - int m; \ - int abs_n = (n) * (((n) > 0) * 2 - 1); \ - int idx_n = abs_n / 2; \ - secp256k1_fe neg_y; \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \ - VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \ - for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \ - /* This loop is used to avoid secret data in array indices. See - * the comment in ecmult_gen_impl.h for rationale. */ \ - secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \ - secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \ - } \ - (r)->infinity = 0; \ - secp256k1_fe_negate(&neg_y, &(r)->y, 1); \ - secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \ -} while(0) - - -/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val) - * with 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 returned; this is always (WNAF_BITS + w - 1) / w - * - * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar - * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) - * CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003 - * - * Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 - */ -static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { - int global_sign; - int skew = 0; - int word = 0; - /* 1 2 3 */ - int u_last; - int u; - -#ifdef USE_ENDOMORPHISM - int flip; - int bit; - secp256k1_scalar neg_s; - int not_neg_one; - /* If we are using the endomorphism, we cannot handle even numbers by negating - * them, since we are working with 128-bit numbers whose negations would be 256 - * bits, eliminating the performance advantage. 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, then compensating after the - * multiplication. */ - /* Negative 128-bit numbers will be negated, since otherwise they are 256-bit */ - flip = secp256k1_scalar_is_high(&s); - /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ - bit = flip ^ (s.d[0] & 1); - /* We check for negative one, since adding 2 to it will cause an overflow */ - secp256k1_scalar_negate(&neg_s, &s); - not_neg_one = !secp256k1_scalar_is_one(&neg_s); - secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); - /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects - * that we added two to it and flipped it. In fact for -1 these operations are - * identical. We only flipped, but since skewing is required (in the sense that - * the skew must be 1 or 2, never zero) and flipping is not, we need to change - * our flags to claim that we only skewed. */ - global_sign = secp256k1_scalar_cond_negate(&s, flip); - global_sign *= not_neg_one * 2 - 1; - skew = 1 << bit; -#else - /* Otherwise, we just negate to force oddness */ - int is_even = secp256k1_scalar_is_even(&s); - global_sign = secp256k1_scalar_cond_negate(&s, is_even); -#endif - - /* 4 */ - u_last = secp256k1_scalar_shr_int(&s, w); - while (word * w < WNAF_BITS) { - int sign; - int even; - - /* 4.1 4.4 */ - u = secp256k1_scalar_shr_int(&s, w); - /* 4.2 */ - even = ((u & 1) == 0); - sign = 2 * (u_last > 0) - 1; - u += sign * even; - u_last -= sign * even * (1 << w); - - /* 4.3, adapted for global sign change */ - wnaf[word++] = u_last * global_sign; - - u_last = u; - } - wnaf[word] = u * global_sign; - - VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); - VERIFY_CHECK(word == WNAF_SIZE(w)); - return skew; -} - - -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) { - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge tmpa; - secp256k1_fe Z; - -#ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; - int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; - int skew_1; - int skew_lam; - secp256k1_scalar q_1, q_lam; -#else - int wnaf[1 + WNAF_SIZE(WINDOW_A - 1)]; -#endif - - int i; - secp256k1_scalar sc = *scalar; - - /* build wnaf representation for q. */ -#ifdef USE_ENDOMORPHISM - /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); - /* no need for zero correction when using endomorphism since even - * numbers have one added to them anyway */ - skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); - skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); -#else - int is_zero = secp256k1_scalar_is_zero(scalar); - /* the wNAF ladder cannot handle zero, so bump this to one .. we will - * correct the result after the fact */ - sc.d[0] += is_zero; - VERIFY_CHECK(!secp256k1_scalar_is_zero(&sc)); - - secp256k1_wnaf_const(wnaf, sc, WINDOW_A - 1); -#endif - - /* Calculate odd multiples of a. - * All multiples are brought to the same Z 'denominator', which is stored - * in Z. Due to secp256k1' isomorphism we can do all operations pretending - * that the Z coordinate was 1, use affine addition formulae, and correct - * the Z coordinate of the result once at the end. - */ - secp256k1_gej_set_ge(r, a); - secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r); - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_fe_normalize_weak(&pre_a[i].y); - } -#ifdef USE_ENDOMORPHISM - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); - } -#endif - - /* first loop iteration (separated out so we can directly set r, rather - * than having it start at infinity, get doubled several times, then have - * its new value added to it) */ -#ifdef USE_ENDOMORPHISM - i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); - secp256k1_gej_set_ge(r, &tmpa); - - i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); - secp256k1_gej_add_ge(r, r, &tmpa); -#else - i = wnaf[WNAF_SIZE(WINDOW_A - 1)]; - VERIFY_CHECK(i != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); - secp256k1_gej_set_ge(r, &tmpa); -#endif - /* remaining loop iterations */ - for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { - int n; - int j; - for (j = 0; j < WINDOW_A - 1; ++j) { - secp256k1_gej_double_nonzero(r, r, NULL); - } -#ifdef USE_ENDOMORPHISM - 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); - - 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); -#else - n = wnaf[i]; - VERIFY_CHECK(n != 0); - ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge(r, r, &tmpa); -#endif - } - - secp256k1_fe_mul(&r->z, &r->z, &Z); - -#ifdef USE_ENDOMORPHISM - { - /* 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); - 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); - 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); - - 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); - } -#else - /* correct for zero */ - r->infinity |= is_zero; -#endif -} - -#endif diff --git a/depend/secp256k1/src/ecmult_gen.h b/depend/secp256k1/src/ecmult_gen.h deleted file mode 100644 index eb2cc9ead..000000000 --- a/depend/secp256k1/src/ecmult_gen.h +++ /dev/null @@ -1,43 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_GEN_ -#define _SECP256K1_ECMULT_GEN_ - -#include "scalar.h" -#include "group.h" - -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 4 bits, called n_0, n_1, n_2, ..., n_63. - * * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: - * * U_i = U * 2^i (for i=0..62) - * * U_i = U * (1-2^63) (for i=63) - * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. - * For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is - * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). - * 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)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */ - secp256k1_scalar blind; - secp256k1_gej initial; -} secp256k1_ecmult_gen_context; - -static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx); -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb); -static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, - const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb); -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 diff --git a/depend/secp256k1/src/ecmult_gen_impl.h b/depend/secp256k1/src/ecmult_gen_impl.h deleted file mode 100644 index b63c4d866..000000000 --- a/depend/secp256k1/src/ecmult_gen_impl.h +++ /dev/null @@ -1,210 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ -#define _SECP256K1_ECMULT_GEN_IMPL_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 -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, const secp256k1_callback* cb) { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - secp256k1_ge prec[1024]; - secp256k1_gej gj; - secp256k1_gej nums_gej; - int i, j; -#endif - - if (ctx->prec != NULL) { - return; - } -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec)); - - /* 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[1024]; /* Jacobian versions of prec. */ - secp256k1_gej gbase; - secp256k1_gej numsbase; - gbase = gj; /* 16^j * G */ - numsbase = nums_gej; /* 2^j * nums. */ - for (j = 0; j < 64; j++) { - /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ - precj[j*16] = numsbase; - for (i = 1; i < 16; i++) { - secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL); - } - /* Multiply gbase by 16. */ - for (i = 0; i < 4; i++) { - secp256k1_gej_double_var(&gbase, &gbase, NULL); - } - /* Multiply numbase by 2. */ - secp256k1_gej_double_var(&numsbase, &numsbase, NULL); - if (j == 62) { - /* 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(1024, prec, precj, cb); - } - for (j = 0; j < 64; j++) { - for (i = 0; i < 16; i++) { - secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); - } - } -#else - (void)cb; - ctx->prec = (secp256k1_ge_storage (*)[64][16])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_clone(secp256k1_ecmult_gen_context *dst, - const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) { - if (src->prec == NULL) { - dst->prec = NULL; - } else { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec)); - memcpy(dst->prec, src->prec, sizeof(*dst->prec)); -#else - (void)cb; - dst->prec = src->prec; -#endif - dst->initial = src->initial; - dst->blind = src->blind; - } -} - -static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { -#ifndef USE_ECMULT_STATIC_PRECOMPUTATION - free(ctx->prec); -#endif - secp256k1_scalar_clear(&ctx->blind); - secp256k1_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 < 64; j++) { - bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4); - for (i = 0; i < 16; 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) - */ - 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_t rng; - int retry; - 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)); - /* Retry for out of range results to achieve uniformity. */ - do { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - retry = !secp256k1_fe_set_b32(&s, nonce32); - retry |= secp256k1_fe_is_zero(&s); - } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */ - /* Randomize the projection to defend against multiplier sidechannels. */ - secp256k1_gej_rescale(&ctx->initial, &s); - secp256k1_fe_clear(&s); - do { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - secp256k1_scalar_set_b32(&b, nonce32, &retry); - /* A blinding value of 0 works, but would undermine the projection hardening. */ - retry |= secp256k1_scalar_is_zero(&b); - } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */ - 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 diff --git a/depend/secp256k1/src/ecmult_impl.h b/depend/secp256k1/src/ecmult_impl.h deleted file mode 100644 index e6e5f4718..000000000 --- a/depend/secp256k1/src/ecmult_impl.h +++ /dev/null @@ -1,389 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_ECMULT_IMPL_H_ -#define _SECP256K1_ECMULT_IMPL_H_ - -#include "group.h" -#include "scalar.h" -#include "ecmult.h" - -/* optimal for 128-bit and 256-bit exponents. */ -#define WINDOW_A 5 - -/** larger numbers may result in slightly better performance, at the cost of - exponentially larger precomputed tables. */ -#ifdef USE_ENDOMORPHISM -/** Two tables for window size 15: 1.375 MiB. */ -#define WINDOW_G 15 -#else -/** One table for window size 16: 1.375 MiB. */ -#define WINDOW_G 16 -#endif - -/** The number of entries a table with precomputed multiples needs to have. */ -#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) - -/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain - * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will - * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. - * Prej's Z values are undefined, except for the last value. - */ -static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { - secp256k1_gej d; - secp256k1_ge a_ge, d_ge; - int i; - - VERIFY_CHECK(!a->infinity); - - secp256k1_gej_double_var(&d, a, NULL); - - /* - * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate - * of 'd', and scale the 1P starting value's x/y coordinates without changing its z. - */ - d_ge.x = d.x; - d_ge.y = d.y; - d_ge.infinity = 0; - - secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); - prej[0].x = a_ge.x; - prej[0].y = a_ge.y; - prej[0].z = a->z; - prej[0].infinity = 0; - - zr[0] = d.z; - for (i = 1; i < n; i++) { - secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]); - } - - /* - * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only - * the final point's z coordinate is actually used though, so just update that. - */ - secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z); -} - -/** Fill a table 'pre' with precomputed odd multiples of a. - * - * There are two versions of this function: - * - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its - * resulting point set to a single constant Z denominator, stores the X and Y - * coordinates as ge_storage points in pre, and stores the global Z in rz. - * It only operates on tables sized for WINDOW_A wnaf multiples. - * - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its - * resulting point set to actually affine points, and stores those in pre. - * It operates on tables of any size, but uses heap-allocated temporaries. - * - * To compute a*P + b*G, we compute a table for P using the first function, - * and for G using the second (which requires an inverse, but it only needs to - * happen once). - */ -static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { - secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; - - /* Compute the odd multiples in Jacobian form. */ - secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); - /* Bring them to the same Z denominator. */ - secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); -} - -static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage *pre, const secp256k1_gej *a, const secp256k1_callback *cb) { - secp256k1_gej *prej = (secp256k1_gej*)checked_malloc(cb, sizeof(secp256k1_gej) * n); - secp256k1_ge *prea = (secp256k1_ge*)checked_malloc(cb, sizeof(secp256k1_ge) * n); - secp256k1_fe *zr = (secp256k1_fe*)checked_malloc(cb, sizeof(secp256k1_fe) * n); - int i; - - /* Compute the odd multiples in Jacobian form. */ - secp256k1_ecmult_odd_multiples_table(n, prej, zr, a); - /* Convert them in batch to affine coordinates. */ - secp256k1_ge_set_table_gej_var(n, prea, prej, zr); - /* Convert them to compact storage form. */ - for (i = 0; i < n; i++) { - secp256k1_ge_to_storage(&pre[i], &prea[i]); - } - - free(prea); - free(prej); - free(zr); -} - -/** The following two macro retrieves a particular odd multiple from a table - * of precomputed multiples. */ -#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - if ((n) > 0) { \ - *(r) = (pre)[((n)-1)/2]; \ - } else { \ - secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \ - } \ -} while(0) - -#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \ - VERIFY_CHECK(((n) & 1) == 1); \ - VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ - VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ - if ((n) > 0) { \ - secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \ - } else { \ - secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \ - secp256k1_ge_neg((r), (r)); \ - } \ -} while(0) - -static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { - ctx->pre_g = NULL; -#ifdef USE_ENDOMORPHISM - ctx->pre_g_128 = NULL; -#endif -} - -static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) { - secp256k1_gej gj; - - if (ctx->pre_g != NULL) { - return; - } - - /* get the generator */ - secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); - - ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); - - /* precompute the tables with odd multiples */ - secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb); - -#ifdef USE_ENDOMORPHISM - { - secp256k1_gej g_128j; - int i; - - ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); - - /* calculate 2^128*generator */ - g_128j = gj; - for (i = 0; i < 128; i++) { - secp256k1_gej_double_var(&g_128j, &g_128j, NULL); - } - secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb); - } -#endif -} - -static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, - const secp256k1_ecmult_context *src, const secp256k1_callback *cb) { - if (src->pre_g == NULL) { - dst->pre_g = NULL; - } else { - size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); - dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); - memcpy(dst->pre_g, src->pre_g, size); - } -#ifdef USE_ENDOMORPHISM - if (src->pre_g_128 == NULL) { - dst->pre_g_128 = NULL; - } else { - size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); - dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); - memcpy(dst->pre_g_128, src->pre_g_128, size); - } -#endif -} - -static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) { - return ctx->pre_g != NULL; -} - -static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) { - free(ctx->pre_g); -#ifdef USE_ENDOMORPHISM - free(ctx->pre_g_128); -#endif - secp256k1_ecmult_context_init(ctx); -} - -/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), - * with the following guarantees: - * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) - * - two non-zero entries in wnaf are separated by at least w-1 zeroes. - * - the number of set values in wnaf is returned. This number is at most 256, and at most one more - * than the number of bits in the (absolute value) of the input. - */ -static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) { - secp256k1_scalar s = *a; - int last_set_bit = -1; - int bit = 0; - int sign = 1; - int carry = 0; - - VERIFY_CHECK(wnaf != NULL); - VERIFY_CHECK(0 <= len && len <= 256); - VERIFY_CHECK(a != NULL); - VERIFY_CHECK(2 <= w && w <= 31); - - memset(wnaf, 0, len * sizeof(wnaf[0])); - - if (secp256k1_scalar_get_bits(&s, 255, 1)) { - secp256k1_scalar_negate(&s, &s); - sign = -1; - } - - while (bit < len) { - int now; - int word; - if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { - bit++; - continue; - } - - now = w; - if (now > len - bit) { - now = len - bit; - } - - word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; - - carry = (word >> (w-1)) & 1; - word -= carry << w; - - wnaf[bit] = sign * word; - last_set_bit = bit; - - bit += now; - } -#ifdef VERIFY - CHECK(carry == 0); - while (bit < 256) { - CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0); - } -#endif - return last_set_bit + 1; -} - -static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { - secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ge tmpa; - secp256k1_fe Z; -#ifdef USE_ENDOMORPHISM - secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_scalar na_1, na_lam; - /* Splitted G factors. */ - secp256k1_scalar ng_1, ng_128; - int wnaf_na_1[130]; - int wnaf_na_lam[130]; - int bits_na_1; - int bits_na_lam; - int wnaf_ng_1[129]; - int bits_ng_1; - int wnaf_ng_128[129]; - int bits_ng_128; -#else - int wnaf_na[256]; - int bits_na; - int wnaf_ng[256]; - int bits_ng; -#endif - int i; - int bits; - -#ifdef USE_ENDOMORPHISM - /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ - secp256k1_scalar_split_lambda(&na_1, &na_lam, na); - - /* build wnaf representation for na_1 and na_lam. */ - bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); - bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); - VERIFY_CHECK(bits_na_1 <= 130); - VERIFY_CHECK(bits_na_lam <= 130); - bits = bits_na_1; - if (bits_na_lam > bits) { - bits = bits_na_lam; - } -#else - /* build wnaf representation for na. */ - bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); - bits = bits_na; -#endif - - /* Calculate odd multiples of a. - * All multiples are brought to the same Z 'denominator', which is stored - * in Z. Due to secp256k1' isomorphism we can do all operations pretending - * that the Z coordinate was 1, use affine addition formulae, and correct - * the Z coordinate of the result once at the end. - * The exception is the precomputed G table points, which are actually - * affine. Compared to the base used for other points, they have a Z ratio - * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same - * isomorphism to efficiently add with a known Z inverse. - */ - secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); - -#ifdef USE_ENDOMORPHISM - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); - } - - /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ - secp256k1_scalar_split_128(&ng_1, &ng_128, ng); - - /* Build wnaf representation for ng_1 and ng_128 */ - bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); - bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); - if (bits_ng_1 > bits) { - bits = bits_ng_1; - } - if (bits_ng_128 > bits) { - bits = bits_ng_128; - } -#else - bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); - if (bits_ng > bits) { - bits = bits_ng; - } -#endif - - secp256k1_gej_set_infinity(r); - - for (i = bits - 1; i >= 0; i--) { - int n; - secp256k1_gej_double_var(r, r, NULL); -#ifdef USE_ENDOMORPHISM - if (i < bits_na_1 && (n = wnaf_na_1[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_na_lam && (n = wnaf_na_lam[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } - if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } -#else - if (i < bits_na && (n = wnaf_na[i])) { - ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); - secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); - } - if (i < bits_ng && (n = wnaf_ng[i])) { - ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); - secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); - } -#endif - } - - if (!r->infinity) { - secp256k1_fe_mul(&r->z, &r->z, &Z); - } -} - -#endif diff --git a/depend/secp256k1/src/field_impl.h b/depend/secp256k1/src/field_impl.h deleted file mode 100644 index 77f4aae2f..000000000 --- a/depend/secp256k1/src/field_impl.h +++ /dev/null @@ -1,283 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_FIELD_IMPL_H_ -#define _SECP256K1_FIELD_IMPL_H_ - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#include "util.h" - -#if defined(USE_FIELD_10X26) -#include "field_10x26_impl.h" -#elif defined(USE_FIELD_5X52) -#include "field_5x52_impl.h" -#else -#error "Please select field implementation" -#endif - -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_var(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; - - /** 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_var(&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(size_t len, secp256k1_fe *r, const secp256k1_fe *a) { - 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; -} - -#endif diff --git a/depend/secp256k1/src/group_impl.h b/depend/secp256k1/src/group_impl.h deleted file mode 100644 index 42e2f6e6e..000000000 --- a/depend/secp256k1/src/group_impl.h +++ /dev/null @@ -1,626 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_GROUP_IMPL_H_ -#define _SECP256K1_GROUP_IMPL_H_ - -#include - -#include "num.h" -#include "field.h" -#include "group.h" - -/** 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 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(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_callback *cb) { - secp256k1_fe *az; - secp256k1_fe *azi; - size_t i; - size_t count = 0; - az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len); - for (i = 0; i < len; i++) { - if (!a[i].infinity) { - az[count++] = a[i].z; - } - } - - azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count); - secp256k1_fe_inv_all_var(count, azi, az); - free(az); - - count = 0; - for (i = 0; i < len; i++) { - r[i].infinity = a[i].infinity; - if (!a[i].infinity) { - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]); - } - } - free(azi); -} - -static void secp256k1_ge_set_table_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr) { - size_t i = len - 1; - secp256k1_fe zi; - - if (len > 0) { - /* Compute the inverse of the last z coordinate, and use it to compute the last affine output. */ - secp256k1_fe_inv(&zi, &a[i].z); - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); - - /* Work out way backwards, using the z-ratios to scale the x/y values. */ - while (i > 0) { - secp256k1_fe_mul(&zi, &zi, &zr[i]); - i--; - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); - } - } -} - -static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) { - size_t i = len - 1; - secp256k1_fe zs; - - if (len > 0) { - /* The z of the final point gives us the "global Z" for the table. */ - r[i].x = a[i].x; - r[i].y = a[i].y; - *globalz = a[i].z; - r[i].infinity = 0; - zs = zr[i]; - - /* Work our way backwards, using the z-ratios to scale the x/y values. */ - while (i > 0) { - if (i != len - 1) { - secp256k1_fe_mul(&zs, &zs, &zr[i]); - } - i--; - secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs); - } - } -} - -static void secp256k1_gej_set_infinity(secp256k1_gej *r) { - r->infinity = 1; - secp256k1_fe_set_int(&r->x, 0); - secp256k1_fe_set_int(&r->y, 0); - secp256k1_fe_set_int(&r->z, 0); -} - -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_var(secp256k1_ge *r, const secp256k1_fe *x) { - secp256k1_fe x2, x3, c; - r->x = *x; - secp256k1_fe_sqr(&x2, x); - secp256k1_fe_mul(&x3, x, &x2); - r->infinity = 0; - secp256k1_fe_set_int(&c, 7); - secp256k1_fe_add(&c, &x3); - return secp256k1_fe_sqrt_var(&r->y, &c); -} - -static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { - if (!secp256k1_ge_set_xquad_var(r, x)) { - return 0; - } - secp256k1_fe_normalize_var(&r->y); - if (secp256k1_fe_is_odd(&r->y) != odd) { - secp256k1_fe_negate(&r->y, &r->y, 1); - } - return 1; - -} - -static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { - r->infinity = a->infinity; - r->x = a->x; - r->y = a->y; - secp256k1_fe_set_int(&r->z, 1); -} - -static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { - secp256k1_fe r, r2; - VERIFY_CHECK(!a->infinity); - secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); - r2 = a->x; secp256k1_fe_normalize_weak(&r2); - return secp256k1_fe_equal_var(&r, &r2); -} - -static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { - r->infinity = a->infinity; - r->x = a->x; - r->y = a->y; - r->z = a->z; - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_negate(&r->y, &r->y, 1); -} - -static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { - return a->infinity; -} - -static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { - secp256k1_fe y2, x3, z2, z6; - if (a->infinity) { - return 0; - } - /** y^2 = x^3 + 7 - * (Y/Z^3)^2 = (X/Z^2)^3 + 7 - * Y^2 / Z^6 = X^3 / Z^6 + 7 - * Y^2 = X^3 + 7*Z^6 - */ - secp256k1_fe_sqr(&y2, &a->y); - secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_sqr(&z2, &a->z); - secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); - secp256k1_fe_mul_int(&z6, 7); - secp256k1_fe_add(&x3, &z6); - secp256k1_fe_normalize_weak(&x3); - return secp256k1_fe_equal_var(&y2, &x3); -} - -static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { - secp256k1_fe y2, x3, c; - if (a->infinity) { - return 0; - } - /* y^2 = x^3 + 7 */ - secp256k1_fe_sqr(&y2, &a->y); - secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); - secp256k1_fe_set_int(&c, 7); - secp256k1_fe_add(&x3, &c); - secp256k1_fe_normalize_weak(&x3); - return secp256k1_fe_equal_var(&y2, &x3); -} - -static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { - /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate */ - secp256k1_fe t1,t2,t3,t4; - /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, - * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have - * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. - */ - r->infinity = a->infinity; - if (r->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - return; - } - - if (rzr != NULL) { - *rzr = a->y; - secp256k1_fe_normalize_weak(rzr); - secp256k1_fe_mul_int(rzr, 2); - } - - secp256k1_fe_mul(&r->z, &a->z, &a->y); - secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ - secp256k1_fe_sqr(&t1, &a->x); - secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ - secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ - secp256k1_fe_sqr(&t3, &a->y); - secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ - secp256k1_fe_sqr(&t4, &t3); - secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ - secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ - r->x = t3; - secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ - secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ - secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ - secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ - secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ - secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ - secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ - secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ - secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ -} - -static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { - VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); - secp256k1_gej_double_var(r, a, rzr); -} - -static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { - /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ - secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - - if (a->infinity) { - VERIFY_CHECK(rzr == NULL); - *r = *b; - return; - } - - if (b->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - *r = *a; - return; - } - - r->infinity = 0; - secp256k1_fe_sqr(&z22, &b->z); - secp256k1_fe_sqr(&z12, &a->z); - secp256k1_fe_mul(&u1, &a->x, &z22); - secp256k1_fe_mul(&u2, &b->x, &z12); - secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, rzr); - } else { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 0); - } - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - secp256k1_fe_mul(&h, &h, &b->z); - if (rzr != NULL) { - *rzr = h; - } - secp256k1_fe_mul(&r->z, &a->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - -static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { - /* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ - secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - if (a->infinity) { - VERIFY_CHECK(rzr == NULL); - secp256k1_gej_set_ge(r, b); - return; - } - if (b->infinity) { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 1); - } - *r = *a; - return; - } - r->infinity = 0; - - secp256k1_fe_sqr(&z12, &a->z); - u1 = a->x; secp256k1_fe_normalize_weak(&u1); - secp256k1_fe_mul(&u2, &b->x, &z12); - s1 = a->y; secp256k1_fe_normalize_weak(&s1); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, rzr); - } else { - if (rzr != NULL) { - secp256k1_fe_set_int(rzr, 0); - } - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - if (rzr != NULL) { - *rzr = h; - } - secp256k1_fe_mul(&r->z, &a->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - -static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { - /* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ - secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; - - if (b->infinity) { - *r = *a; - return; - } - if (a->infinity) { - secp256k1_fe bzinv2, bzinv3; - r->infinity = b->infinity; - secp256k1_fe_sqr(&bzinv2, bzinv); - secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv); - secp256k1_fe_mul(&r->x, &b->x, &bzinv2); - secp256k1_fe_mul(&r->y, &b->y, &bzinv3); - secp256k1_fe_set_int(&r->z, 1); - return; - } - r->infinity = 0; - - /** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to - * secp256k1's isomorphism we can multiply the Z coordinates on both sides - * by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1). - * This means that (rx,ry,rz) can be calculated as - * (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz. - * The variable az below holds the modified Z coordinate for a, which is used - * for the computation of rx and ry, but not for rz. - */ - secp256k1_fe_mul(&az, &a->z, bzinv); - - secp256k1_fe_sqr(&z12, &az); - u1 = a->x; secp256k1_fe_normalize_weak(&u1); - secp256k1_fe_mul(&u2, &b->x, &z12); - s1 = a->y; secp256k1_fe_normalize_weak(&s1); - secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az); - secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); - secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); - if (secp256k1_fe_normalizes_to_zero_var(&h)) { - if (secp256k1_fe_normalizes_to_zero_var(&i)) { - secp256k1_gej_double_var(r, a, NULL); - } else { - r->infinity = 1; - } - return; - } - secp256k1_fe_sqr(&i2, &i); - secp256k1_fe_sqr(&h2, &h); - secp256k1_fe_mul(&h3, &h, &h2); - r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); - secp256k1_fe_mul(&t, &u1, &h2); - r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); - secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); - secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); - secp256k1_fe_add(&r->y, &h3); -} - - -static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) { - /* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */ - static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; - secp256k1_fe m_alt, rr_alt; - int infinity, degenerate; - VERIFY_CHECK(!b->infinity); - VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); - - /** In: - * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. - * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. - * we find as solution for a unified addition/doubling formula: - * lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. - * x3 = lambda^2 - (x1 + x2) - * 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). - * - * Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: - * U1 = X1*Z2^2, U2 = X2*Z1^2 - * S1 = Y1*Z2^3, S2 = Y2*Z1^3 - * Z = Z1*Z2 - * T = U1+U2 - * M = S1+S2 - * Q = T*M^2 - * R = T^2-U1*U2 - * X3 = 4*(R^2-Q) - * Y3 = 4*(R*(3*Q-2*R^2)-M^4) - * Z3 = 2*M*Z - * (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) - * - * This formula has the benefit of being the same for both addition - * of distinct points and doubling. However, it breaks down in the - * case that either point is infinity, or that y1 = -y2. We handle - * these cases in the following ways: - * - * - If b is infinity we simply bail by means of a VERIFY_CHECK. - * - * - If a is infinity, we detect this, and at the end of the - * computation replace the result (which will be meaningless, - * but we compute to be constant-time) with b.x : b.y : 1. - * - * - If a = -b, we have y1 = -y2, which is a degenerate case. - * But here the answer is infinity, so we simply set the - * infinity flag of the result, overriding the computed values - * without even needing to cmov. - * - * - If y1 = -y2 but x1 != x2, which does occur thanks to certain - * properties of our curve (specifically, 1 has nontrivial cube - * roots in our field, and the curve equation has no x coefficient) - * then the answer is not infinity but also not given by the above - * equation. In this case, we cmov in place an alternate expression - * for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these - * expressions for lambda are defined, they are equal, and can be - * obtained from each other by multiplication by (y1 + y2)/(y1 + y2) - * then substitution of x^3 + 7 for y^2 (using the curve equation). - * For all pairs of nonzero points (a, b) at least one is defined, - * so this covers everything. - */ - - secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ - u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ - secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ - s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ - secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ - secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ - t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ - m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ - secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ - secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ - secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ - secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ - /** If lambda = R/M = 0/0 we have a problem (except in the "trivial" - * case that Z = z1z2 = 0, and this is special-cased later on). */ - degenerate = secp256k1_fe_normalizes_to_zero(&m) & - secp256k1_fe_normalizes_to_zero(&rr); - /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. - * This means either x1 == beta*x2 or beta*x1 == x2, where beta is - * a nontrivial cube root of one. In either case, an alternate - * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), - * so we set R/M equal to this. */ - rr_alt = s1; - secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ - secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ - - secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); - secp256k1_fe_cmov(&m_alt, &m, !degenerate); - /* Now Ralt / Malt = lambda and is guaranteed not to be 0/0. - * From here on out Ralt and Malt represent the numerator - * and denominator of lambda; R and M represent the explicit - * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ - secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ - secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */ - /* These two lines use the observation that either M == Malt or M == 0, - * so M^3 * Malt is either Malt^4 (which is computed by squaring), or - * zero (which is "computed" by cmov). So the cost is one squaring - * versus two multiplications. */ - secp256k1_fe_sqr(&n, &n); - secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ - secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ - secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */ - infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); - secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */ - secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ - secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */ - secp256k1_fe_normalize_weak(&t); - r->x = t; /* r->x = Ralt^2-Q (1) */ - secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */ - secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */ - secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */ - secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */ - secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */ - secp256k1_fe_normalize_weak(&r->y); - secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */ - secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */ - - /** In case a->infinity == 1, replace r with (b->x, b->y, 1). */ - secp256k1_fe_cmov(&r->x, &b->x, a->infinity); - secp256k1_fe_cmov(&r->y, &b->y, a->infinity); - secp256k1_fe_cmov(&r->z, &fe_1, a->infinity); - r->infinity = infinity; -} - -static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { - /* Operations: 4 mul, 1 sqr */ - secp256k1_fe zz; - VERIFY_CHECK(!secp256k1_fe_is_zero(s)); - secp256k1_fe_sqr(&zz, s); - secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ - secp256k1_fe_mul(&r->y, &r->y, &zz); - secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ - secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ -} - -static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { - secp256k1_fe x, y; - VERIFY_CHECK(!a->infinity); - x = a->x; - secp256k1_fe_normalize(&x); - y = a->y; - secp256k1_fe_normalize(&y); - secp256k1_fe_to_storage(&r->x, &x); - secp256k1_fe_to_storage(&r->y, &y); -} - -static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) { - secp256k1_fe_from_storage(&r->x, &a->x); - secp256k1_fe_from_storage(&r->y, &a->y); - r->infinity = 0; -} - -static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { - secp256k1_fe_storage_cmov(&r->x, &a->x, flag); - secp256k1_fe_storage_cmov(&r->y, &a->y, flag); -} - -#ifdef USE_ENDOMORPHISM -static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { - static const secp256k1_fe beta = SECP256K1_FE_CONST( - 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, - 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul - ); - *r = *a; - secp256k1_fe_mul(&r->x, &r->x, &beta); -} -#endif - -#endif diff --git a/depend/secp256k1/src/hash.h b/depend/secp256k1/src/hash.h deleted file mode 100644 index 0ff01e63f..000000000 --- a/depend/secp256k1/src/hash.h +++ /dev/null @@ -1,41 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_HASH_ -#define _SECP256K1_HASH_ - -#include -#include - -typedef struct { - uint32_t s[32]; - uint32_t buf[16]; /* In big endian */ - size_t bytes; -} secp256k1_sha256_t; - -static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); -static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); -static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); - -typedef struct { - secp256k1_sha256_t inner, outer; -} secp256k1_hmac_sha256_t; - -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); - -typedef struct { - unsigned char v[32]; - unsigned char k[32]; - int retry; -} secp256k1_rfc6979_hmac_sha256_t; - -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen); -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); - -#endif diff --git a/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java deleted file mode 100644 index 90a498eaa..000000000 --- a/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.bitcoin; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import com.google.common.base.Preconditions; - - -/** - * 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/sipa/secp256k1 - */ -public class NativeSecp256k1 { - public static final boolean enabled; - static { - boolean isEnabled = true; - try { - System.loadLibrary("javasecp256k1"); - } catch (UnsatisfiedLinkError e) { - isEnabled = false; - } - enabled = isEnabled; - } - - private static ThreadLocal nativeECDSABuffer = 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) { - Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); - - ByteBuffer byteBuff = nativeECDSABuffer.get(); - if (byteBuff == null) { - byteBuff = ByteBuffer.allocateDirect(32 + 8 + 520 + 520); - byteBuff.order(ByteOrder.nativeOrder()); - nativeECDSABuffer.set(byteBuff); - } - byteBuff.rewind(); - byteBuff.put(data); - byteBuff.putInt(signature.length); - byteBuff.putInt(pub.length); - byteBuff.put(signature); - byteBuff.put(pub); - return secp256k1_ecdsa_verify(byteBuff) == 1; - } - - /** - * @param byteBuff signature format is byte[32] data, - * native-endian int signatureLength, native-endian int pubkeyLength, - * byte[signatureLength] signature, byte[pubkeyLength] pub - * @returns 1 for valid signature, anything else for invalid - */ - private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff); -} diff --git a/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c deleted file mode 100644 index bb4cd7072..000000000 --- a/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "org_bitcoin_NativeSecp256k1.h" -#include "include/secp256k1.h" - -JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv* env, jclass classObject, jobject byteBufferObject) -{ - unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); - int sigLen = *((int*)(data + 32)); - int pubLen = *((int*)(data + 32 + 4)); - - return secp256k1_ecdsa_verify(data, 32, data+32+8, sigLen, data+32+8+sigLen, pubLen); -} - -static void __javasecp256k1_attach(void) __attribute__((constructor)); -static void __javasecp256k1_detach(void) __attribute__((destructor)); - -static void __javasecp256k1_attach(void) { - secp256k1_start(SECP256K1_START_VERIFY); -} - -static void __javasecp256k1_detach(void) { - secp256k1_stop(); -} diff --git a/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h deleted file mode 100644 index d7fb004fa..000000000 --- a/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h +++ /dev/null @@ -1,21 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class org_bitcoin_NativeSecp256k1 */ - -#ifndef _Included_org_bitcoin_NativeSecp256k1 -#define _Included_org_bitcoin_NativeSecp256k1 -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdsa_verify - * Signature: (Ljava/nio/ByteBuffer;)I - */ -JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv *, jclass, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/depend/secp256k1/src/modules/ecdh/main_impl.h b/depend/secp256k1/src/modules/ecdh/main_impl.h deleted file mode 100644 index c23e4f82f..000000000 --- a/depend/secp256k1/src/modules/ecdh/main_impl.h +++ /dev/null @@ -1,54 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_ECDH_MAIN_ -#define _SECP256K1_MODULE_ECDH_MAIN_ - -#include "include/secp256k1_ecdh.h" -#include "ecmult_const_impl.h" - -int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const secp256k1_pubkey *point, const unsigned char *scalar) { - int ret = 0; - int overflow = 0; - secp256k1_gej res; - secp256k1_ge pt; - secp256k1_scalar s; - ARG_CHECK(result != NULL); - ARG_CHECK(point != NULL); - ARG_CHECK(scalar != NULL); - (void)ctx; - - secp256k1_pubkey_load(ctx, &pt, point); - secp256k1_scalar_set_b32(&s, scalar, &overflow); - if (overflow || secp256k1_scalar_is_zero(&s)) { - ret = 0; - } else { - unsigned char x[32]; - unsigned char y[1]; - secp256k1_sha256_t sha; - - secp256k1_ecmult_const(&res, &pt, &s); - secp256k1_ge_set_gej(&pt, &res); - /* Compute a hash of the point in compressed form - * Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not - * expect its output to be secret and has a timing sidechannel. */ - secp256k1_fe_normalize(&pt.x); - secp256k1_fe_normalize(&pt.y); - secp256k1_fe_get_b32(x, &pt.x); - y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y); - - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, y, sizeof(y)); - secp256k1_sha256_write(&sha, x, sizeof(x)); - secp256k1_sha256_finalize(&sha, result); - ret = 1; - } - - secp256k1_scalar_clear(&s); - return ret; -} - -#endif diff --git a/depend/secp256k1/src/modules/ecdh/tests_impl.h b/depend/secp256k1/src/modules/ecdh/tests_impl.h deleted file mode 100644 index 7badc9033..000000000 --- a/depend/secp256k1/src/modules/ecdh/tests_impl.h +++ /dev/null @@ -1,75 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_ECDH_TESTS_ -#define _SECP256K1_MODULE_ECDH_TESTS_ - -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_t sha; - unsigned char s_b32[32]; - unsigned char output_ecdh[32]; - unsigned char output_ser[32]; - unsigned char point_ser[33]; - size_t point_ser_len = sizeof(point_ser); - secp256k1_scalar s; - - random_scalar_order(&s); - secp256k1_scalar_get_b32(s_b32, &s); - - /* compute using ECDH function */ - CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1); - CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1); - /* compute "explicitly" */ - CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); - CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); - CHECK(point_ser_len == sizeof(point_ser)); - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, point_ser, point_ser_len); - secp256k1_sha256_finalize(&sha, output_ser); - /* compare */ - CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 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) == 0); - CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 0); - /* ...and a good one */ - s_overflow[31] -= 1; - CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 1); -} - -void run_ecdh_tests(void) { - test_ecdh_generator_basepoint(); - test_bad_scalar(); -} - -#endif diff --git a/depend/secp256k1/src/modules/recovery/main_impl.h b/depend/secp256k1/src/modules/recovery/main_impl.h deleted file mode 100644 index ec42f4bb6..000000000 --- a/depend/secp256k1/src/modules/recovery/main_impl.h +++ /dev/null @@ -1,193 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ -#define _SECP256K1_MODULE_RECOVERY_MAIN_ - -#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 *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar r, s; - secp256k1_scalar sec, non, msg; - int recid; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(seckey != NULL); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - /* Fail if the secret key is invalid. */ - if (!overflow && !secp256k1_scalar_is_zero(&sec)) { - unsigned int count = 0; - secp256k1_scalar_set_b32(&msg, msg32, NULL); - while (1) { - unsigned char nonce32[32]; - ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&non, nonce32, &overflow); - memset(nonce32, 0, 32); - if (!secp256k1_scalar_is_zero(&non) && !overflow) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { - break; - } - } - count++; - } - secp256k1_scalar_clear(&msg); - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - } - if (ret) { - secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); - } else { - memset(signature, 0, sizeof(*signature)); - } - return ret; -} - -int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32) { - 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(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); - ARG_CHECK(recid >= 0 && recid < 4); - secp256k1_scalar_set_b32(&m, msg32, 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 diff --git a/depend/secp256k1/src/modules/recovery/tests_impl.h b/depend/secp256k1/src/modules/recovery/tests_impl.h deleted file mode 100644 index 8932d5f0a..000000000 --- a/depend/secp256k1/src/modules/recovery/tests_impl.h +++ /dev/null @@ -1,250 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ -#define _SECP256K1_MODULE_RECOVERY_TESTS_ - -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(memcmp(&signature[4], &signature[0], 64) == 0); - 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(memcmp(&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_rand_bits(6)] += 1 + secp256k1_rand_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 || - memcmp(&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 0. */ - 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 < 64*count; i++) { - test_ecdsa_recovery_end_to_end(); - } - test_ecdsa_recovery_edge_cases(); -} - -#endif diff --git a/depend/secp256k1/src/modules/schnorr/Makefile.am.include b/depend/secp256k1/src/modules/schnorr/Makefile.am.include deleted file mode 100644 index b3bfa7d5c..000000000 --- a/depend/secp256k1/src/modules/schnorr/Makefile.am.include +++ /dev/null @@ -1,10 +0,0 @@ -include_HEADERS += include/secp256k1_schnorr.h -noinst_HEADERS += src/modules/schnorr/main_impl.h -noinst_HEADERS += src/modules/schnorr/schnorr.h -noinst_HEADERS += src/modules/schnorr/schnorr_impl.h -noinst_HEADERS += src/modules/schnorr/tests_impl.h -if USE_BENCHMARK -noinst_PROGRAMS += bench_schnorr_verify -bench_schnorr_verify_SOURCES = src/bench_schnorr_verify.c -bench_schnorr_verify_LDADD = libsecp256k1.la $(SECP_LIBS) -endif diff --git a/depend/secp256k1/src/modules/schnorr/main_impl.h b/depend/secp256k1/src/modules/schnorr/main_impl.h deleted file mode 100644 index fa176a176..000000000 --- a/depend/secp256k1/src/modules/schnorr/main_impl.h +++ /dev/null @@ -1,164 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#ifndef SECP256K1_MODULE_SCHNORR_MAIN -#define SECP256K1_MODULE_SCHNORR_MAIN - -#include "include/secp256k1_schnorr.h" -#include "modules/schnorr/schnorr_impl.h" - -static void secp256k1_schnorr_msghash_sha256(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32) { - secp256k1_sha256_t sha; - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, r32, 32); - secp256k1_sha256_write(&sha, msg32, 32); - secp256k1_sha256_finalize(&sha, h32); -} - -static const unsigned char secp256k1_schnorr_algo16[17] = "Schnorr+SHA256 "; - -int secp256k1_schnorr_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar sec, non; - int ret = 0; - int overflow = 0; - unsigned int count = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(seckey != NULL); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - secp256k1_scalar_set_b32(&sec, seckey, NULL); - while (1) { - unsigned char nonce32[32]; - ret = noncefp(nonce32, msg32, seckey, secp256k1_schnorr_algo16, (void*)noncedata, count); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&non, nonce32, &overflow); - memset(nonce32, 0, 32); - if (!secp256k1_scalar_is_zero(&non) && !overflow) { - if (secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, NULL, secp256k1_schnorr_msghash_sha256, msg32)) { - break; - } - } - count++; - } - if (!ret) { - memset(sig64, 0, 64); - } - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_schnorr_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { - secp256k1_ge q; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_pubkey_load(ctx, &q, pubkey); - return secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &q, secp256k1_schnorr_msghash_sha256, msg32); -} - -int secp256k1_schnorr_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *sig64, const unsigned char *msg32) { - secp256k1_ge q; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(pubkey != NULL); - - if (secp256k1_schnorr_sig_recover(&ctx->ecmult_ctx, sig64, &q, secp256k1_schnorr_msghash_sha256, msg32)) { - secp256k1_pubkey_save(pubkey, &q); - return 1; - } else { - memset(pubkey, 0, sizeof(*pubkey)); - return 0; - } -} - -int secp256k1_schnorr_generate_nonce_pair(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, unsigned char *privnonce32, const unsigned char *sec32, const unsigned char *msg32, secp256k1_nonce_function noncefp, const void* noncedata) { - int count = 0; - int ret = 1; - secp256k1_gej Qj; - secp256k1_ge Q; - secp256k1_scalar sec; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(sec32 != NULL); - ARG_CHECK(pubnonce != NULL); - ARG_CHECK(privnonce32 != NULL); - - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - do { - int overflow; - ret = noncefp(privnonce32, sec32, msg32, secp256k1_schnorr_algo16, (void*)noncedata, count++); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&sec, privnonce32, &overflow); - if (overflow || secp256k1_scalar_is_zero(&sec)) { - continue; - } - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sec); - secp256k1_ge_set_gej(&Q, &Qj); - - secp256k1_pubkey_save(pubnonce, &Q); - break; - } while(1); - - secp256k1_scalar_clear(&sec); - if (!ret) { - memset(pubnonce, 0, sizeof(*pubnonce)); - } - return ret; -} - -int secp256k1_schnorr_partial_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const unsigned char *sec32, const secp256k1_pubkey *pubnonce_others, const unsigned char *secnonce32) { - int overflow = 0; - secp256k1_scalar sec, non; - secp256k1_ge pubnon; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(sec32 != NULL); - ARG_CHECK(secnonce32 != NULL); - ARG_CHECK(pubnonce_others != NULL); - - secp256k1_scalar_set_b32(&sec, sec32, &overflow); - if (overflow || secp256k1_scalar_is_zero(&sec)) { - return -1; - } - secp256k1_scalar_set_b32(&non, secnonce32, &overflow); - if (overflow || secp256k1_scalar_is_zero(&non)) { - return -1; - } - secp256k1_pubkey_load(ctx, &pubnon, pubnonce_others); - return secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64, &sec, &non, &pubnon, secp256k1_schnorr_msghash_sha256, msg32); -} - -int secp256k1_schnorr_partial_combine(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char * const *sig64sin, size_t n) { - ARG_CHECK(sig64 != NULL); - ARG_CHECK(n >= 1); - ARG_CHECK(sig64sin != NULL); - return secp256k1_schnorr_sig_combine(sig64, n, sig64sin); -} - -#endif diff --git a/depend/secp256k1/src/modules/schnorr/schnorr.h b/depend/secp256k1/src/modules/schnorr/schnorr.h deleted file mode 100644 index de18147bd..000000000 --- a/depend/secp256k1/src/modules/schnorr/schnorr.h +++ /dev/null @@ -1,20 +0,0 @@ -/*********************************************************************** - * 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. * - ***********************************************************************/ - -#ifndef _SECP256K1_MODULE_SCHNORR_H_ -#define _SECP256K1_MODULE_SCHNORR_H_ - -#include "scalar.h" -#include "group.h" - -typedef void (*secp256k1_schnorr_msghash)(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32); - -static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, unsigned char *sig64, const secp256k1_scalar *key, const secp256k1_scalar *nonce, const secp256k1_ge *pubnonce, secp256k1_schnorr_msghash hash, const unsigned char *msg32); -static int secp256k1_schnorr_sig_verify(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, const secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32); -static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32); -static int secp256k1_schnorr_sig_combine(unsigned char *sig64, size_t n, const unsigned char * const *sig64ins); - -#endif diff --git a/depend/secp256k1/src/modules/schnorr/schnorr_impl.h b/depend/secp256k1/src/modules/schnorr/schnorr_impl.h deleted file mode 100644 index e13ab6db7..000000000 --- a/depend/secp256k1/src/modules/schnorr/schnorr_impl.h +++ /dev/null @@ -1,207 +0,0 @@ -/*********************************************************************** - * 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. * - ***********************************************************************/ - -#ifndef _SECP256K1_SCHNORR_IMPL_H_ -#define _SECP256K1_SCHNORR_IMPL_H_ - -#include - -#include "schnorr.h" -#include "num.h" -#include "field.h" -#include "group.h" -#include "ecmult.h" -#include "ecmult_gen.h" - -/** - * Custom Schnorr-based signature scheme. They support multiparty signing, public key - * recovery and batch validation. - * - * Rationale for verifying R's y coordinate: - * In order to support batch validation and public key recovery, the full R point must - * be known to verifiers, rather than just its x coordinate. In order to not risk - * being more strict in batch validation than normal validation, validators must be - * required to reject signatures with incorrect y coordinate. This is only possible - * by including a (relatively slow) field inverse, or a field square root. However, - * batch validation offers potentially much higher benefits than this cost. - * - * Rationale for having an implicit y coordinate oddness: - * If we commit to having the full R point known to verifiers, there are two mechanism. - * Either include its oddness in the signature, or give it an implicit fixed value. - * As the R y coordinate can be flipped by a simple negation of the nonce, we choose the - * latter, as it comes with nearly zero impact on signing or validation performance, and - * saves a byte in the signature. - * - * Signing: - * Inputs: 32-byte message m, 32-byte scalar key x (!=0), 32-byte scalar nonce k (!=0) - * - * Compute point R = k * G. Reject nonce if R's y coordinate is odd (or negate nonce). - * Compute 32-byte r, the serialization of R's x coordinate. - * Compute scalar h = Hash(r || m). Reject nonce if h == 0 or h >= order. - * Compute scalar s = k - h * x. - * The signature is (r, s). - * - * - * Verification: - * Inputs: 32-byte message m, public key point Q, signature: (32-byte r, scalar s) - * - * Signature is invalid if s >= order. - * Signature is invalid if r >= p. - * Compute scalar h = Hash(r || m). Signature is invalid if h == 0 or h >= order. - * Option 1 (faster for single verification): - * Compute point R = h * Q + s * G. Signature is invalid if R is infinity or R's y coordinate is odd. - * Signature is valid if the serialization of R's x coordinate equals r. - * Option 2 (allows batch validation and pubkey recovery): - * Decompress x coordinate r into point R, with odd y coordinate. Fail if R is not on the curve. - * Signature is valid if R + h * Q + s * G == 0. - */ - -static int secp256k1_schnorr_sig_sign(const secp256k1_ecmult_gen_context* ctx, unsigned char *sig64, const secp256k1_scalar *key, const secp256k1_scalar *nonce, const secp256k1_ge *pubnonce, secp256k1_schnorr_msghash hash, const unsigned char *msg32) { - secp256k1_gej Rj; - secp256k1_ge Ra; - unsigned char h32[32]; - secp256k1_scalar h, s; - int overflow; - secp256k1_scalar n; - - if (secp256k1_scalar_is_zero(key) || secp256k1_scalar_is_zero(nonce)) { - return 0; - } - n = *nonce; - - secp256k1_ecmult_gen(ctx, &Rj, &n); - if (pubnonce != NULL) { - secp256k1_gej_add_ge(&Rj, &Rj, pubnonce); - } - secp256k1_ge_set_gej(&Ra, &Rj); - secp256k1_fe_normalize(&Ra.y); - if (secp256k1_fe_is_odd(&Ra.y)) { - /* R's y coordinate is odd, which is not allowed (see rationale above). - Force it to be even by negating the nonce. Note that this even works - for multiparty signing, as the R point is known to all participants, - which can all decide to flip the sign in unison, resulting in the - overall R point to be negated too. */ - secp256k1_scalar_negate(&n, &n); - } - secp256k1_fe_normalize(&Ra.x); - secp256k1_fe_get_b32(sig64, &Ra.x); - hash(h32, sig64, msg32); - overflow = 0; - secp256k1_scalar_set_b32(&h, h32, &overflow); - if (overflow || secp256k1_scalar_is_zero(&h)) { - secp256k1_scalar_clear(&n); - return 0; - } - secp256k1_scalar_mul(&s, &h, key); - secp256k1_scalar_negate(&s, &s); - secp256k1_scalar_add(&s, &s, &n); - secp256k1_scalar_clear(&n); - secp256k1_scalar_get_b32(sig64 + 32, &s); - return 1; -} - -static int secp256k1_schnorr_sig_verify(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, const secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32) { - secp256k1_gej Qj, Rj; - secp256k1_ge Ra; - secp256k1_fe Rx; - secp256k1_scalar h, s; - unsigned char hh[32]; - int overflow; - - if (secp256k1_ge_is_infinity(pubkey)) { - return 0; - } - hash(hh, sig64, msg32); - overflow = 0; - secp256k1_scalar_set_b32(&h, hh, &overflow); - if (overflow || secp256k1_scalar_is_zero(&h)) { - return 0; - } - overflow = 0; - secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow); - if (overflow) { - return 0; - } - if (!secp256k1_fe_set_b32(&Rx, sig64)) { - return 0; - } - secp256k1_gej_set_ge(&Qj, pubkey); - secp256k1_ecmult(ctx, &Rj, &Qj, &h, &s); - if (secp256k1_gej_is_infinity(&Rj)) { - return 0; - } - secp256k1_ge_set_gej_var(&Ra, &Rj); - secp256k1_fe_normalize_var(&Ra.y); - if (secp256k1_fe_is_odd(&Ra.y)) { - return 0; - } - return secp256k1_fe_equal_var(&Rx, &Ra.x); -} - -static int secp256k1_schnorr_sig_recover(const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, secp256k1_schnorr_msghash hash, const unsigned char *msg32) { - secp256k1_gej Qj, Rj; - secp256k1_ge Ra; - secp256k1_fe Rx; - secp256k1_scalar h, s; - unsigned char hh[32]; - int overflow; - - hash(hh, sig64, msg32); - overflow = 0; - secp256k1_scalar_set_b32(&h, hh, &overflow); - if (overflow || secp256k1_scalar_is_zero(&h)) { - return 0; - } - overflow = 0; - secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow); - if (overflow) { - return 0; - } - if (!secp256k1_fe_set_b32(&Rx, sig64)) { - return 0; - } - if (!secp256k1_ge_set_xo_var(&Ra, &Rx, 0)) { - return 0; - } - secp256k1_gej_set_ge(&Rj, &Ra); - secp256k1_scalar_inverse_var(&h, &h); - secp256k1_scalar_negate(&s, &s); - secp256k1_scalar_mul(&s, &s, &h); - secp256k1_ecmult(ctx, &Qj, &Rj, &h, &s); - if (secp256k1_gej_is_infinity(&Qj)) { - return 0; - } - secp256k1_ge_set_gej(pubkey, &Qj); - return 1; -} - -static int secp256k1_schnorr_sig_combine(unsigned char *sig64, size_t n, const unsigned char * const *sig64ins) { - secp256k1_scalar s = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); - size_t i; - for (i = 0; i < n; i++) { - secp256k1_scalar si; - int overflow; - secp256k1_scalar_set_b32(&si, sig64ins[i] + 32, &overflow); - if (overflow) { - return -1; - } - if (i) { - if (memcmp(sig64ins[i - 1], sig64ins[i], 32) != 0) { - return -1; - } - } - secp256k1_scalar_add(&s, &s, &si); - } - if (secp256k1_scalar_is_zero(&s)) { - return 0; - } - memcpy(sig64, sig64ins[0], 32); - secp256k1_scalar_get_b32(sig64 + 32, &s); - secp256k1_scalar_clear(&s); - return 1; -} - -#endif diff --git a/depend/secp256k1/src/modules/schnorr/tests_impl.h b/depend/secp256k1/src/modules/schnorr/tests_impl.h deleted file mode 100644 index 5bd14a03e..000000000 --- a/depend/secp256k1/src/modules/schnorr/tests_impl.h +++ /dev/null @@ -1,175 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#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, recpubkey; - - /* Generate a random key and message. */ - { - secp256k1_scalar key; - random_scalar_order_test(&key); - secp256k1_scalar_get_b32(privkey, &key); - secp256k1_rand256_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); - CHECK(secp256k1_schnorr_recover(ctx, &recpubkey, schnorr_signature, message) == 1); - CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); - /* Destroy signature and verify again. */ - schnorr_signature[secp256k1_rand_bits(6)] += 1 + secp256k1_rand_int(255); - CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 0); - CHECK(secp256k1_schnorr_recover(ctx, &recpubkey, schnorr_signature, message) != 1 || - memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); -} - -/** Horribly broken hash function. Do not use for anything but tests. */ -void test_schnorr_hash(unsigned char *h32, const unsigned char *r32, const unsigned char *msg32) { - int i; - for (i = 0; i < 32; i++) { - h32[i] = r32[i] ^ msg32[i]; - } -} - -void test_schnorr_sign_verify(void) { - unsigned char msg32[32]; - unsigned char sig64[3][64]; - secp256k1_gej pubkeyj[3]; - secp256k1_ge pubkey[3]; - secp256k1_scalar nonce[3], key[3]; - int i = 0; - int k; - - secp256k1_rand256_test(msg32); - - for (k = 0; k < 3; k++) { - random_scalar_order_test(&key[k]); - - do { - random_scalar_order_test(&nonce[k]); - if (secp256k1_schnorr_sig_sign(&ctx->ecmult_gen_ctx, sig64[k], &key[k], &nonce[k], NULL, &test_schnorr_hash, msg32)) { - break; - } - } while(1); - - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj[k], &key[k]); - secp256k1_ge_set_gej_var(&pubkey[k], &pubkeyj[k]); - CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[k], &pubkey[k], &test_schnorr_hash, msg32)); - - for (i = 0; i < 4; i++) { - int pos = secp256k1_rand_bits(6); - int mod = 1 + secp256k1_rand_int(255); - sig64[k][pos] ^= mod; - CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[k], &pubkey[k], &test_schnorr_hash, msg32) == 0); - sig64[k][pos] ^= mod; - } - } -} - -void test_schnorr_threshold(void) { - unsigned char msg[32]; - unsigned char sec[5][32]; - secp256k1_pubkey pub[5]; - unsigned char nonce[5][32]; - secp256k1_pubkey pubnonce[5]; - unsigned char sig[5][64]; - const unsigned char* sigs[5]; - unsigned char allsig[64]; - const secp256k1_pubkey* pubs[5]; - secp256k1_pubkey allpub; - int n, i; - int damage; - int ret = 0; - - damage = secp256k1_rand_bits(1) ? (1 + secp256k1_rand_int(4)) : 0; - secp256k1_rand256_test(msg); - n = 2 + secp256k1_rand_int(4); - for (i = 0; i < n; i++) { - do { - secp256k1_rand256_test(sec[i]); - } while (!secp256k1_ec_seckey_verify(ctx, sec[i])); - CHECK(secp256k1_ec_pubkey_create(ctx, &pub[i], sec[i])); - CHECK(secp256k1_schnorr_generate_nonce_pair(ctx, &pubnonce[i], nonce[i], msg, sec[i], NULL, NULL)); - pubs[i] = &pub[i]; - } - if (damage == 1) { - nonce[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255); - } else if (damage == 2) { - sec[secp256k1_rand_int(n)][secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255); - } - for (i = 0; i < n; i++) { - secp256k1_pubkey allpubnonce; - const secp256k1_pubkey *pubnonces[4]; - int j; - for (j = 0; j < i; j++) { - pubnonces[j] = &pubnonce[j]; - } - for (j = i + 1; j < n; j++) { - pubnonces[j - 1] = &pubnonce[j]; - } - CHECK(secp256k1_ec_pubkey_combine(ctx, &allpubnonce, pubnonces, n - 1)); - ret |= (secp256k1_schnorr_partial_sign(ctx, sig[i], msg, sec[i], &allpubnonce, nonce[i]) != 1) * 1; - sigs[i] = sig[i]; - } - if (damage == 3) { - sig[secp256k1_rand_int(n)][secp256k1_rand_bits(6)] ^= 1 + secp256k1_rand_int(255); - } - ret |= (secp256k1_ec_pubkey_combine(ctx, &allpub, pubs, n) != 1) * 2; - if ((ret & 1) == 0) { - ret |= (secp256k1_schnorr_partial_combine(ctx, allsig, sigs, n) != 1) * 4; - } - if (damage == 4) { - allsig[secp256k1_rand_int(32)] ^= 1 + secp256k1_rand_int(255); - } - if ((ret & 7) == 0) { - ret |= (secp256k1_schnorr_verify(ctx, allsig, msg, &allpub) != 1) * 8; - } - CHECK((ret == 0) == (damage == 0)); -} - -void test_schnorr_recovery(void) { - unsigned char msg32[32]; - unsigned char sig64[64]; - secp256k1_ge Q; - - secp256k1_rand256_test(msg32); - secp256k1_rand256_test(sig64); - secp256k1_rand256_test(sig64 + 32); - if (secp256k1_schnorr_sig_recover(&ctx->ecmult_ctx, sig64, &Q, &test_schnorr_hash, msg32) == 1) { - CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &Q, &test_schnorr_hash, msg32) == 1); - } -} - -void run_schnorr_tests(void) { - int i; - for (i = 0; i < 32*count; i++) { - test_schnorr_end_to_end(); - } - for (i = 0; i < 32 * count; i++) { - test_schnorr_sign_verify(); - } - for (i = 0; i < 16 * count; i++) { - test_schnorr_recovery(); - } - for (i = 0; i < 10 * count; i++) { - test_schnorr_threshold(); - } -} - -#endif diff --git a/depend/secp256k1/src/num.h b/depend/secp256k1/src/num.h deleted file mode 100644 index ebfa71eb4..000000000 --- a/depend/secp256k1/src/num.h +++ /dev/null @@ -1,68 +0,0 @@ -/********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_NUM_ -#define _SECP256K1_NUM_ - -#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); - -/** 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 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 diff --git a/depend/secp256k1/src/scalar.h b/depend/secp256k1/src/scalar.h deleted file mode 100644 index b590ccd6d..000000000 --- a/depend/secp256k1/src/scalar.h +++ /dev/null @@ -1,104 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_ -#define _SECP256K1_SCALAR_ - -#include "num.h" - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(USE_SCALAR_4X64) -#include "scalar_4x64.h" -#elif defined(USE_SCALAR_8X32) -#include "scalar_8x32.h" -#else -#error "Please select scalar 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. */ -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); - -/** 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); - -#ifdef USE_ENDOMORPHISM -/** Find r1 and r2 such that r1+r2*2^128 = a. */ -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); -/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); -#endif - -/** 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); - -#endif diff --git a/depend/secp256k1/src/scalar_impl.h b/depend/secp256k1/src/scalar_impl.h deleted file mode 100644 index 88ea97de8..000000000 --- a/depend/secp256k1/src/scalar_impl.h +++ /dev/null @@ -1,337 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef _SECP256K1_SCALAR_IMPL_H_ -#define _SECP256K1_SCALAR_IMPL_H_ - -#include - -#include "group.h" -#include "scalar.h" - -#if defined HAVE_CONFIG_H -#include "libsecp256k1-config.h" -#endif - -#if defined(USE_SCALAR_4X64) -#include "scalar_4x64_impl.h" -#elif defined(USE_SCALAR_8X32) -#include "scalar_8x32_impl.h" -#else -#error "Please select scalar implementation" -#endif - -#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) { - 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 - }; - secp256k1_num_set_bin(r, order, 32); -} -#endif - -static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { - secp256k1_scalar *t; - int i; - /* First compute x ^ (2^N - 1) for some values of N. */ - secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; - - secp256k1_scalar_sqr(&x2, x); - secp256k1_scalar_mul(&x2, &x2, x); - - secp256k1_scalar_sqr(&x3, &x2); - secp256k1_scalar_mul(&x3, &x3, x); - - secp256k1_scalar_sqr(&x4, &x3); - secp256k1_scalar_mul(&x4, &x4, x); - - secp256k1_scalar_sqr(&x6, &x4); - secp256k1_scalar_sqr(&x6, &x6); - secp256k1_scalar_mul(&x6, &x6, &x2); - - secp256k1_scalar_sqr(&x7, &x6); - secp256k1_scalar_mul(&x7, &x7, x); - - secp256k1_scalar_sqr(&x8, &x7); - secp256k1_scalar_mul(&x8, &x8, x); - - secp256k1_scalar_sqr(&x15, &x8); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x15, &x15); - } - secp256k1_scalar_mul(&x15, &x15, &x7); - - secp256k1_scalar_sqr(&x30, &x15); - for (i = 0; i < 14; i++) { - secp256k1_scalar_sqr(&x30, &x30); - } - secp256k1_scalar_mul(&x30, &x30, &x15); - - secp256k1_scalar_sqr(&x60, &x30); - for (i = 0; i < 29; i++) { - secp256k1_scalar_sqr(&x60, &x60); - } - secp256k1_scalar_mul(&x60, &x60, &x30); - - secp256k1_scalar_sqr(&x120, &x60); - for (i = 0; i < 59; i++) { - secp256k1_scalar_sqr(&x120, &x120); - } - secp256k1_scalar_mul(&x120, &x120, &x60); - - secp256k1_scalar_sqr(&x127, &x120); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x127, &x127); - } - secp256k1_scalar_mul(&x127, &x127, &x7); - - /* Then accumulate the final result (t starts at x127). */ - t = &x127; - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 3; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - 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 < 4; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 10; i++) { /* 0000000 */ - 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 < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 4; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 8; i++) { /* 000000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 6; i++) { /* 00000 */ - 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) { - /* d[0] is present and is the lowest word for all representations */ - return !(a->d[0] & 1); -} - -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 -} - -#ifdef USE_ENDOMORPHISM -/** - * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where - * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, - * 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72} - * - * "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 have a small size. - * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are: - * - * - 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} - * - * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives - * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and - * compute k1 as k - k2 * lambda, avoiding the need for 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^272)*b2/d) - * g2 = round((2^272)*b1/d) - * - * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found - * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda'). - * - * The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order). - */ - -static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { - secp256k1_scalar c1, c2; - static const secp256k1_scalar minus_lambda = SECP256K1_SCALAR_CONST( - 0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL, - 0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL - ); - 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( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL, - 0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL - ); - static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST( - 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL, - 0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL - ); - VERIFY_CHECK(r1 != a); - VERIFY_CHECK(r2 != a); - /* these _var calls are constant time since the shift amount is constant */ - secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272); - secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272); - 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, &minus_lambda); - secp256k1_scalar_add(r1, r1, a); -} -#endif - -#endif diff --git a/depend/secp256k1/src/secp256k1.c b/depend/secp256k1/src/secp256k1.c deleted file mode 100644 index 62d192bae..000000000 --- a/depend/secp256k1/src/secp256k1.c +++ /dev/null @@ -1,568 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#define SECP256K1_BUILD (1) - -#include "include/secp256k1.h" - -#include "util.h" -#include "num_impl.h" -#include "field_impl.h" -#include "scalar_impl.h" -#include "group_impl.h" -#include "ecmult_impl.h" -#include "ecmult_const_impl.h" -#include "ecmult_gen_impl.h" -#include "ecdsa_impl.h" -#include "eckey_impl.h" -#include "hash_impl.h" - -#define ARG_CHECK(cond) do { \ - if (EXPECT(!(cond), 0)) { \ - secp256k1_callback_call(&ctx->illegal_callback, #cond); \ - return 0; \ - } \ -} while(0) - -static void default_illegal_callback_fn(const char* str, void* data) { - (void)data; - fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); - abort(); -} - -static const secp256k1_callback default_illegal_callback = { - default_illegal_callback_fn, - NULL -}; - -static void default_error_callback_fn(const char* str, void* data) { - (void)data; - fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); - abort(); -} - -static const secp256k1_callback default_error_callback = { - default_error_callback_fn, - NULL -}; - - -struct secp256k1_context_struct { - secp256k1_ecmult_context ecmult_ctx; - secp256k1_ecmult_gen_context ecmult_gen_ctx; - secp256k1_callback illegal_callback; - secp256k1_callback error_callback; -}; - -secp256k1_context* secp256k1_context_create(unsigned int flags) { - secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context)); - ret->illegal_callback = default_illegal_callback; - ret->error_callback = default_error_callback; - - if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { - secp256k1_callback_call(&ret->illegal_callback, - "Invalid flags"); - free(ret); - return NULL; - } - - secp256k1_ecmult_context_init(&ret->ecmult_ctx); - secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); - - if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { - secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); - } - if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { - secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); - } - - return ret; -} - -secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { - secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context)); - ret->illegal_callback = ctx->illegal_callback; - ret->error_callback = ctx->error_callback; - secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); - secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); - return ret; -} - -void secp256k1_context_destroy(secp256k1_context* ctx) { - if (ctx != NULL) { - secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); - secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); - - free(ctx); - } -} - -void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - if (fun == NULL) { - fun = default_illegal_callback_fn; - } - ctx->illegal_callback.fn = fun; - ctx->illegal_callback.data = data; -} - -void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - if (fun == NULL) { - fun = default_error_callback_fn; - } - ctx->error_callback.fn = fun; - ctx->error_callback.data = data; -} - -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], 64); - 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, 64); - } 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; - - (void)ctx; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(input != NULL); - if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { - return 0; - } - secp256k1_pubkey_save(pubkey, &Q); - secp256k1_ge_clear(&Q); - return 1; -} - -int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { - secp256k1_ge Q; - size_t len; - int ret = 0; - - (void)ctx; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(outputlen != NULL); - ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); - len = *outputlen; - *outputlen = 0; - ARG_CHECK(output != NULL); - memset(output, 0, len); - ARG_CHECK(pubkey != NULL); - ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); - if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { - ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); - if (ret) { - *outputlen = len; - } - } - return ret; -} - -static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { - (void)ctx; - if (sizeof(secp256k1_scalar) == 32) { - /* When the secp256k1_scalar type is exactly 32 byte, use its - * representation inside secp256k1_ecdsa_signature, as conversion is very fast. - * Note that secp256k1_ecdsa_signature_save must use the same representation. */ - memcpy(r, &sig->data[0], 32); - memcpy(s, &sig->data[32], 32); - } else { - secp256k1_scalar_set_b32(r, &sig->data[0], NULL); - secp256k1_scalar_set_b32(s, &sig->data[32], NULL); - } -} - -static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { - if (sizeof(secp256k1_scalar) == 32) { - memcpy(&sig->data[0], r, 32); - memcpy(&sig->data[32], s, 32); - } else { - secp256k1_scalar_get_b32(&sig->data[0], r); - secp256k1_scalar_get_b32(&sig->data[32], s); - } -} - -int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { - secp256k1_scalar r, s; - - (void)ctx; - 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; - - (void)ctx; - 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; - - (void)ctx; - 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; - - (void)ctx; - ARG_CHECK(output64 != NULL); - ARG_CHECK(sig != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - secp256k1_scalar_get_b32(&output64[0], &r); - secp256k1_scalar_get_b32(&output64[32], &s); - return 1; -} - -int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) { - secp256k1_scalar r, s; - int ret = 0; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sigin != NULL); - - secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin); - ret = secp256k1_scalar_is_high(&s); - if (sigout != NULL) { - if (ret) { - secp256k1_scalar_negate(&s, &s); - } - secp256k1_ecdsa_signature_save(sigout, &r, &s); - } - - return ret; -} - -int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { - secp256k1_ge q; - secp256k1_scalar r, s; - secp256k1_scalar m; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(pubkey != NULL); - - secp256k1_scalar_set_b32(&m, msg32, NULL); - secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); - return (!secp256k1_scalar_is_high(&s) && - secp256k1_pubkey_load(ctx, &q, pubkey) && - secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); -} - -static 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]; - int keylen = 64; - secp256k1_rfc6979_hmac_sha256_t 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. - */ - memcpy(keydata, key32, 32); - memcpy(keydata + 32, msg32, 32); - if (data != NULL) { - memcpy(keydata + 64, data, 32); - keylen = 96; - } - if (algo16 != NULL) { - memcpy(keydata + keylen, algo16, 16); - keylen += 16; - } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); - memset(keydata, 0, sizeof(keydata)); - for (i = 0; i <= counter; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); - return 1; -} - -const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; -const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; - -int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { - secp256k1_scalar r, s; - secp256k1_scalar sec, non, msg; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(signature != NULL); - ARG_CHECK(seckey != NULL); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - /* Fail if the secret key is invalid. */ - if (!overflow && !secp256k1_scalar_is_zero(&sec)) { - unsigned int count = 0; - secp256k1_scalar_set_b32(&msg, msg32, NULL); - while (1) { - unsigned char nonce32[32]; - ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&non, nonce32, &overflow); - memset(nonce32, 0, 32); - if (!overflow && !secp256k1_scalar_is_zero(&non)) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { - break; - } - } - count++; - } - secp256k1_scalar_clear(&msg); - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - } - if (ret) { - secp256k1_ecdsa_signature_save(signature, &r, &s); - } else { - memset(signature, 0, sizeof(*signature)); - } - return ret; -} - -int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { - secp256k1_scalar sec; - int ret; - int overflow; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - (void)ctx; - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - ret = !overflow && !secp256k1_scalar_is_zero(&sec); - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { - secp256k1_gej pj; - secp256k1_ge p; - secp256k1_scalar sec; - int overflow; - int ret = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkey != NULL); - memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - ARG_CHECK(seckey != NULL); - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); - if (ret) { - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); - secp256k1_ge_set_gej(&p, &pj); - secp256k1_pubkey_save(pubkey, &p); - } - secp256k1_scalar_clear(&sec); - return ret; -} - -int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { - secp256k1_scalar term; - secp256k1_scalar sec; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - ARG_CHECK(tweak != NULL); - (void)ctx; - - secp256k1_scalar_set_b32(&term, tweak, &overflow); - secp256k1_scalar_set_b32(&sec, seckey, NULL); - - ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term); - memset(seckey, 0, 32); - if (ret) { - secp256k1_scalar_get_b32(seckey, &sec); - } - - secp256k1_scalar_clear(&sec); - secp256k1_scalar_clear(&term); - return ret; -} - -int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { - secp256k1_ge p; - secp256k1_scalar term; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&term, tweak, &overflow); - ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { - secp256k1_pubkey_save(pubkey, &p); - } else { - ret = 0; - } - } - - return ret; -} - -int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { - secp256k1_scalar factor; - secp256k1_scalar sec; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(seckey != NULL); - ARG_CHECK(tweak != NULL); - (void)ctx; - - secp256k1_scalar_set_b32(&factor, tweak, &overflow); - secp256k1_scalar_set_b32(&sec, seckey, NULL); - ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor); - memset(seckey, 0, 32); - if (ret) { - secp256k1_scalar_get_b32(seckey, &sec); - } - - secp256k1_scalar_clear(&sec); - secp256k1_scalar_clear(&factor); - return ret; -} - -int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { - secp256k1_ge p; - secp256k1_scalar factor; - int ret = 0; - int overflow = 0; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(tweak != NULL); - - secp256k1_scalar_set_b32(&factor, tweak, &overflow); - ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); - memset(pubkey, 0, sizeof(*pubkey)); - if (ret) { - if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { - secp256k1_pubkey_save(pubkey, &p); - } else { - ret = 0; - } - } - - return ret; -} - -int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); - return 1; -} - -int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { - size_t i; - secp256k1_gej Qj; - secp256k1_ge Q; - - ARG_CHECK(pubnonce != NULL); - memset(pubnonce, 0, sizeof(*pubnonce)); - ARG_CHECK(n >= 1); - ARG_CHECK(pubnonces != NULL); - - secp256k1_gej_set_infinity(&Qj); - - for (i = 0; i < n; i++) { - secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); - secp256k1_gej_add_ge(&Qj, &Qj, &Q); - } - if (secp256k1_gej_is_infinity(&Qj)) { - return 0; - } - secp256k1_ge_set_gej(&Q, &Qj); - secp256k1_pubkey_save(pubnonce, &Q); - return 1; -} - -#ifdef ENABLE_MODULE_ECDH -# include "modules/ecdh/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/main_impl.h" -#endif - -#ifdef ENABLE_MODULE_RECOVERY -# include "modules/recovery/main_impl.h" -#endif diff --git a/depend/secp256k1/src/testrand_impl.h b/depend/secp256k1/src/testrand_impl.h deleted file mode 100644 index 15c7b9f12..000000000 --- a/depend/secp256k1/src/testrand_impl.h +++ /dev/null @@ -1,110 +0,0 @@ -/********************************************************************** - * 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.* - **********************************************************************/ - -#ifndef _SECP256K1_TESTRAND_IMPL_H_ -#define _SECP256K1_TESTRAND_IMPL_H_ - -#include -#include - -#include "testrand.h" -#include "hash.h" - -static secp256k1_rfc6979_hmac_sha256_t 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_rand_seed(const unsigned char *seed16) { - secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16); -} - -SECP256K1_INLINE static uint32_t secp256k1_rand32(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_rand_bits(int bits) { - uint32_t ret; - if (secp256k1_test_rng_integer_bits_left < bits) { - secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << 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_rand_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_rand_bits(bits); - if (x < trange) { - return (mult == 1) ? x : (x % range); - } - } -} - -static void secp256k1_rand256(unsigned char *b32) { - secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32); -} - -static void secp256k1_rand_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_rand_bits(6) * secp256k1_rand_bits(5) + 16) / 31; - val = secp256k1_rand_bits(1); - while (now > 0 && bits < len * 8) { - bytes[bits / 8] |= val << (bits % 8); - now--; - bits++; - } - } -} - -static void secp256k1_rand256_test(unsigned char *b32) { - secp256k1_rand_bytes_test(b32, 32); -} - -#endif diff --git a/examples/generate_keys.rs b/examples/generate_keys.rs new file mode 100644 index 000000000..ae1ec2b84 --- /dev/null +++ b/examples/generate_keys.rs @@ -0,0 +1,17 @@ +extern crate secp256k1; + +use secp256k1::rand::rngs::OsRng; +use secp256k1::{PublicKey, Secp256k1, SecretKey}; + +fn main() { + let secp = Secp256k1::new(); + let mut rng = OsRng::new().unwrap(); + // First option: + let (seckey, pubkey) = secp.generate_keypair(&mut rng); + + assert_eq!(pubkey, PublicKey::from_secret_key(&secp, &seckey)); + + // Second option: + let seckey = SecretKey::new(&mut rng); + let _pubkey = PublicKey::from_secret_key(&secp, &seckey); +} diff --git a/examples/sign_verify.rs b/examples/sign_verify.rs new file mode 100644 index 000000000..ca474a8d2 --- /dev/null +++ b/examples/sign_verify.rs @@ -0,0 +1,35 @@ +extern crate bitcoin_hashes; +extern crate secp256k1; + +use bitcoin_hashes::{sha256, Hash}; +use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, Signature, Signing, Verification}; + +fn verify(secp: &Secp256k1, msg: &[u8], sig: [u8; 64], pubkey: [u8; 33]) -> Result { + let msg = sha256::Hash::hash(msg); + let msg = Message::from_slice(&msg)?; + let sig = Signature::from_compact(&sig)?; + let pubkey = PublicKey::from_slice(&pubkey)?; + + Ok(secp.verify(&msg, &sig, &pubkey).is_ok()) +} + +fn sign(secp: &Secp256k1, msg: &[u8], seckey: [u8; 32]) -> Result { + let msg = sha256::Hash::hash(msg); + let msg = Message::from_slice(&msg)?; + let seckey = SecretKey::from_slice(&seckey)?; + Ok(secp.sign(&msg, &seckey)) +} + +fn main() { + let secp = Secp256k1::new(); + + let seckey = [59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28]; + let pubkey = [2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91, 141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54]; + let msg = b"This is some message"; + + let signature = sign(&secp, msg, seckey).unwrap(); + + let serialize_sig = signature.serialize_compact(); + + assert!(verify(&secp, msg, serialize_sig, pubkey).unwrap()); +} diff --git a/examples/sign_verify_recovery.rs b/examples/sign_verify_recovery.rs new file mode 100644 index 000000000..1644be4a0 --- /dev/null +++ b/examples/sign_verify_recovery.rs @@ -0,0 +1,47 @@ + +extern crate bitcoin_hashes; +extern crate secp256k1; + +use bitcoin_hashes::{sha256, Hash}; +use secp256k1::recovery::{RecoverableSignature, RecoveryId}; +use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification}; + +fn recover(secp: &Secp256k1,msg: &[u8],sig: [u8; 64],recovery_id: u8) -> Result { + let msg = sha256::Hash::hash(msg); + let msg = Message::from_slice(&msg)?; + let id = RecoveryId::from_i32(recovery_id as i32)?; + let sig = RecoverableSignature::from_compact(&sig, id)?; + + secp.recover(&msg, &sig) +} + +fn sign_recovery(secp: &Secp256k1, msg: &[u8], seckey: [u8; 32]) -> Result { + let msg = sha256::Hash::hash(msg); + let msg = Message::from_slice(&msg)?; + let seckey = SecretKey::from_slice(&seckey)?; + Ok(secp.sign_recoverable(&msg, &seckey)) +} + +fn main() { + let secp = Secp256k1::new(); + + let seckey = [ + 59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, + 94, 203, 174, 253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28, + ]; + let pubkey = PublicKey::from_slice(&[ + 2, + 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, + 245, 41, 91, 141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54, + ]).unwrap(); + let msg = b"This is some message"; + + let signature = sign_recovery(&secp, msg, seckey).unwrap(); + + let (recovery_id, serialize_sig) = signature.serialize_compact(); + + assert_eq!( + recover(&secp, msg, serialize_sig, recovery_id.to_i32() as u8), + Ok(pubkey) + ); +} diff --git a/no_std_test/Cargo.toml b/no_std_test/Cargo.toml new file mode 100644 index 000000000..f68a47ca6 --- /dev/null +++ b/no_std_test/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "no_std_test" +version = "0.1.0" +authors = ["Elichai Turkel "] + +[dependencies] +secp256k1 = { path = "../", default-features = false, features = ["serde", "rand"] } +libc = { version = "0.2", default-features = false } +serde_cbor = { version = "0.10", default-features = false } # A random serializer that supports no-std. + + +[profile.release] +panic = "abort" + +[profile.dev] +panic = "abort" diff --git a/no_std_test/src/main.rs b/no_std_test/src/main.rs new file mode 100644 index 000000000..d40d8e397 --- /dev/null +++ b/no_std_test/src/main.rs @@ -0,0 +1,178 @@ +// Bitcoin secp256k1 bindings +// Written in 2019 by +// Elichai Turkel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +//! # secp256k1 no-std test. +//! This binary is a short smallest rust code to produce a working binary *without libstd*. +//! This gives us 2 things: +//! 1. Test that the parts of the code that should work in a no-std enviroment actually work. +//! 2. Test that we don't accidentally import libstd into `secp256k1`. +//! +//! The first is tested using the following command `cargo run --release | grep -q "Verified Successfully"`. +//! (Making sure that it successfully printed that. i.e. it didn't abort before that). +//! +//! The second is tested by the fact that it compiles. if we accidentally link against libstd we should see the following error: +//! `error[E0152]: duplicate lang item found`. +//! Example: +//! ``` +//! error[E0152]: duplicate lang item found: `eh_personality`. +//! --> src/main.rs:37:1 +//! | +//! 37 | pub extern "C" fn rust_eh_personality() {} +//! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//! | +//! = note: first defined in crate `panic_unwind` (which `std` depends on). +//! ``` +//! +//! Notes: +//! * Requires `panic=abort` and `--release` to not depend on libunwind(which is provided usually by libstd) https://github.com/rust-lang/rust/issues/47493 +//! * Requires linking with `libc` for calling `printf`. +//! + +#![feature(lang_items)] +#![feature(start)] +#![feature(core_intrinsics)] +#![feature(panic_info_message)] +#![no_std] +extern crate libc; +extern crate secp256k1; +extern crate serde_cbor; + +use core::fmt::{self, write, Write}; +use core::intrinsics; +use core::panic::PanicInfo; + +use secp256k1::rand::{self, RngCore}; +use secp256k1::serde::Serialize; +use secp256k1::*; +use secp256k1::ecdh::SharedSecret; + +use serde_cbor::de; +use serde_cbor::ser::SliceWrite; +use serde_cbor::Serializer; + +struct FakeRng; +impl RngCore for FakeRng { + fn next_u32(&mut self) -> u32 { + 57 + } + fn next_u64(&mut self) -> u64 { + 57 + } + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { + for i in dest { + *i = 57; + } + Ok(()) + } + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.try_fill_bytes(dest).unwrap(); + } +} + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + let mut buf = [0u8; 600_000]; + let size = Secp256k1::preallocate_size(); + unsafe { libc::printf("needed size: %d\n\0".as_ptr() as _, size) }; + + let mut secp = Secp256k1::preallocated_new(&mut buf).unwrap(); + secp.randomize(&mut FakeRng); + let secret_key = SecretKey::new(&mut FakeRng); + let public_key = PublicKey::from_secret_key(&secp, &secret_key); + let message = Message::from_slice(&[0xab; 32]).expect("32 bytes"); + + let sig = secp.sign(&message, &secret_key); + assert!(secp.verify(&message, &sig, &public_key).is_ok()); + + let mut cbor_ser = [0u8; 100]; + let writer = SliceWrite::new(&mut cbor_ser[..]); + let mut ser = Serializer::new(writer); + sig.serialize(&mut ser).unwrap(); + let size = ser.into_inner().bytes_written(); + let new_sig: Signature = de::from_mut_slice(&mut cbor_ser[..size]).unwrap(); + assert_eq!(sig, new_sig); + + let _ = SharedSecret::new(&public_key, &secret_key); + let mut x_arr = [0u8; 32]; + let y_arr = unsafe { SharedSecret::new_with_hash_no_panic(&public_key, &secret_key, |x,y| { + x_arr = x; + y.into() + })}.unwrap(); + assert_ne!(x_arr, [0u8; 32]); + assert_ne!(&y_arr[..], &[0u8; 32][..]); + + + unsafe { libc::printf("Verified Successfully!\n\0".as_ptr() as _) }; + 0 +} + +// These functions are used by the compiler, but not +// for a bare-bones hello world. These are normally +// provided by libstd. +#[lang = "eh_personality"] +#[no_mangle] +pub extern "C" fn rust_eh_personality() {} + +// This function may be needed based on the compilation target. +#[lang = "eh_unwind_resume"] +#[no_mangle] +pub extern "C" fn rust_eh_unwind_resume() {} + +const MAX_PRINT: usize = 511; +struct Print { + loc: usize, + buf: [u8; 512], +} + +impl Print { + pub fn new() -> Self { + Self { + loc: 0, + buf: [0u8; 512], + } + } + + pub fn print(&self) { + unsafe { + let newline = "\n"; + libc::printf(self.buf.as_ptr() as _); + libc::printf(newline.as_ptr() as _); + } + } +} + +impl Write for Print { + fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> { + let curr = self.loc; + if curr + s.len() > MAX_PRINT { + unsafe { + libc::printf("overflow\n\0".as_ptr() as _); + intrinsics::abort(); + } + } + self.loc += s.len(); + self.buf[curr..self.loc].copy_from_slice(s.as_bytes()); + Ok(()) + } +} + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + unsafe { libc::printf("shi1\n\0".as_ptr() as _) }; + let msg = info.message().unwrap(); + let mut buf = Print::new(); + write(&mut buf, *msg).unwrap(); + buf.print(); + unsafe { intrinsics::abort() } +} diff --git a/secp256k1-sys/Cargo.toml b/secp256k1-sys/Cargo.toml new file mode 100644 index 000000000..bfea3b1fe --- /dev/null +++ b/secp256k1-sys/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "secp256k1-sys" +version = "0.1.1" +authors = [ "Dawid Ciężarkiewicz ", + "Andrew Poelstra ", + "Steven Roose " ] +license = "CC0-1.0" +homepage = "https://github.com/rust-bitcoin/rust-secp256k1/" +repository = "https://github.com/rust-bitcoin/rust-secp256k1/" +documentation = "https://docs.rs/secp256k1-sys/" +description = "FFI for Pieter Wuille's `libsecp256k1` library." +keywords = [ "secp256k1", "libsecp256k1", "ffi" ] +readme = "README.md" +build = "build.rs" +links = "rustsecp256k1_v0_1_1" + +# Should make docs.rs show all functions, even those behind non-default features +[package.metadata.docs.rs] +features = [ "recovery", "endomorphism", "lowmemory" ] + +[build-dependencies] +# todo[dvdplm] figure out why the requirment here is so stringent; had compilation issies in `eth` where v.46 was picked. +cc = ">= 1.0.28, <= 1.0.46" + +[lib] +name = "secp256k1_sys" +path = "src/lib.rs" + +[features] +default = ["std"] +recovery = [] +endomorphism = [] +lowmemory = [] +std = [] + +# Use this feature to not compile the bundled libsecp256k1 C symbols, +# but use external ones. Use this only if you know what you are doing! +external-symbols = [] + +# Do not use this feature! HAZMAT. (meant for Fuzzing only. this is *BROKEN CRYPTOGRAPHY*) +fuzztarget = [] diff --git a/secp256k1-sys/LICENSE b/secp256k1-sys/LICENSE new file mode 100644 index 000000000..6ca207ef0 --- /dev/null +++ b/secp256k1-sys/LICENSE @@ -0,0 +1,122 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + diff --git a/secp256k1-sys/README.md b/secp256k1-sys/README.md new file mode 100644 index 000000000..835f8aaaf --- /dev/null +++ b/secp256k1-sys/README.md @@ -0,0 +1,34 @@ +secp256k1-sys +============= + + +This crate provides Rust definitions for the FFI structures and methods. + + +## Vendoring + +The default build process is to build using the vendored libsecp256k1 sources in +the depend folder. These sources are prefixed with a special +rust-secp256k1-sys-specific prefix `rustsecp256k1_v1_2_3_`. + +This prefix ensures that no symbol collision can happen: +- when a Rust project has two different versions of rust-secp256k1 in its + depepdency tree, or +- when rust-secp256k1 is used for building a static library in a context where + existing libsecp256k1 symbols are already linked. + +To update the vendored sources, use the `vendor-libsecp.sh` script: + +``` +$ ./vendor-libsecp.sh depend +``` + +- Where `` is the secp256k1-sys version number underscored: `0_1_2`. +- Where `` is the git revision of libsecp256k1 to checkout. + + +## Linking to external symbols + +For the more exotic use cases, this crate can be used with existing libsecp256k1 +symbols by using the `external-symbols` feature. How to setup rustc to link +against those existing symbols is left as an exercise to the reader. diff --git a/secp256k1-sys/build.rs b/secp256k1-sys/build.rs new file mode 100644 index 000000000..bbc325ee5 --- /dev/null +++ b/secp256k1-sys/build.rs @@ -0,0 +1,94 @@ +// Bitcoin secp256k1 bindings +// Written in 2015 by +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +//! # Build script + +// Coding conventions +#![deny(non_upper_case_globals)] +#![deny(non_camel_case_types)] +#![deny(non_snake_case)] +#![deny(unused_mut)] +#![warn(missing_docs)] + +extern crate cc; + +use std::env; + +fn main() { + if cfg!(feature = "external-symbols") { + println!("cargo:rustc-link-lib=static=secp256k1"); + return; + } + + // Check whether we can use 64-bit compilation + let use_64bit_compilation = if env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap() == "64" { + let check = cc::Build::new().file("depend/check_uint128_t.c") + .cargo_metadata(false) + .try_compile("check_uint128_t") + .is_ok(); + if !check { + println!("cargo:warning=Compiling in 32-bit mode on a 64-bit architecture due to lack of uint128_t support."); + } + check + } else { + false + }; + + // Actual build + let mut base_config = cc::Build::new(); + base_config.include("depend/secp256k1/") + .include("depend/secp256k1/include") + .include("depend/secp256k1/src") + .flag_if_supported("-Wno-unused-function") // some ecmult stuff is defined but not used upstream + .define("SECP256K1_BUILD", Some("1")) + // TODO these three should be changed to use libgmp, at least until secp PR 290 is merged + .define("USE_NUM_NONE", Some("1")) + .define("USE_FIELD_INV_BUILTIN", Some("1")) + .define("USE_SCALAR_INV_BUILTIN", Some("1")) + .define("ENABLE_MODULE_ECDH", Some("1")); + + if cfg!(feature = "lowmemory") { + base_config.define("ECMULT_WINDOW_SIZE", Some("4")); // A low-enough value to consume neglible memory + } else { + base_config.define("ECMULT_WINDOW_SIZE", Some("15")); // This is the default in the configure file (`auto`) + } + #[cfg(not(feature = "dont_replace_c_symbols"))] + base_config.define("USE_EXTERNAL_DEFAULT_CALLBACKS", Some("1")); + #[cfg(feature = "endomorphism")] + base_config.define("USE_ENDOMORPHISM", Some("1")); + #[cfg(feature = "recovery")] + base_config.define("ENABLE_MODULE_RECOVERY", Some("1")); + + if let Ok(target_endian) = env::var("CARGO_CFG_TARGET_ENDIAN") { + if target_endian == "big" { + base_config.define("WORDS_BIGENDIAN", Some("1")); + } + } + + if use_64bit_compilation { + base_config.define("USE_FIELD_5X52", Some("1")) + .define("USE_SCALAR_4X64", Some("1")) + .define("HAVE___INT128", Some("1")); + } else { + base_config.define("USE_FIELD_10X26", Some("1")) + .define("USE_SCALAR_8X32", Some("1")); + } + + // secp256k1 + base_config.file("depend/secp256k1/contrib/lax_der_parsing.c") + .file("depend/secp256k1/src/secp256k1.c") + .file("depend/ext.c") + .compile("libsecp256k1.a"); +} + diff --git a/secp256k1-sys/depend/check_uint128_t.c b/secp256k1-sys/depend/check_uint128_t.c new file mode 100644 index 000000000..4d9095526 --- /dev/null +++ b/secp256k1-sys/depend/check_uint128_t.c @@ -0,0 +1,16 @@ + +#include + +int main(void) { + __uint128_t var_128; + uint64_t var_64; + + /* Try to shut up "unused variable" warnings */ + var_64 = 100; + var_128 = 100; + if (var_64 == var_128) { + var_64 = 20; + } + return 0; +} + diff --git a/secp256k1-sys/depend/ext.c b/secp256k1-sys/depend/ext.c new file mode 100644 index 000000000..0e7a0841c --- /dev/null +++ b/secp256k1-sys/depend/ext.c @@ -0,0 +1,31 @@ +/** @file ext.c + * Ethereum extensions to libecp256k1 + * @authors: + * Arkadiy Paronyan + * @date 2015 + */ + +#include "src/secp256k1.c" +/// Returns inverse (1 / n) of secret key `seckey` +int rustsecp256k1_v0_1_1_ec_privkey_inverse(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *inverse, const unsigned char* seckey) { + rustsecp256k1_v0_1_1_scalar inv; + rustsecp256k1_v0_1_1_scalar sec; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(inverse != NULL); + ARG_CHECK(seckey != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&sec, seckey, NULL); + + ret = !overflow; + if (ret) { + memset(inverse, 0, 32); + rustsecp256k1_v0_1_1_scalar_inverse(&inv, &sec); + rustsecp256k1_v0_1_1_scalar_get_b32(inverse, &inv); + } + + rustsecp256k1_v0_1_1_scalar_clear(&inv); + rustsecp256k1_v0_1_1_scalar_clear(&sec); + return ret; +} diff --git a/secp256k1-sys/depend/scratch_impl.h.patch b/secp256k1-sys/depend/scratch_impl.h.patch new file mode 100644 index 000000000..6e72191c8 --- /dev/null +++ b/secp256k1-sys/depend/scratch_impl.h.patch @@ -0,0 +1,26 @@ +13,37d12 +< static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) { +< const size_t base_alloc = ((sizeof(secp256k1_scratch) + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; +< 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 (memcmp(scratch->magic, "scratch", 8) != 0) { +< secp256k1_callback_call(error_callback, "invalid scratch space"); +< return; +< } +< memset(scratch->magic, 0, sizeof(scratch->magic)); +< free(scratch); +< } +< } +< diff --git a/secp256k1-sys/depend/secp256k1-HEAD-revision.txt b/secp256k1-sys/depend/secp256k1-HEAD-revision.txt new file mode 100644 index 000000000..94db77fa7 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1-HEAD-revision.txt @@ -0,0 +1,2 @@ +# This file was automatically created by ./vendor-libsecp.sh +143dc6e9ee31852a60321b23eea407d2006171da diff --git a/secp256k1-sys/depend/secp256k1.c.patch b/secp256k1-sys/depend/secp256k1.c.patch new file mode 100644 index 000000000..c39705a00 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1.c.patch @@ -0,0 +1,43 @@ +139,149d138 +< 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; +< } +< +164,174d152 +< 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; +< } +< +183,189d160 +< void secp256k1_context_destroy(secp256k1_context* ctx) { +< if (ctx != NULL) { +< secp256k1_context_preallocated_destroy(ctx); +< free(ctx); +< } +< } +< +206,215d176 +< } +< +< 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); diff --git a/secp256k1-sys/depend/secp256k1.h.patch b/secp256k1-sys/depend/secp256k1.h.patch new file mode 100644 index 000000000..bfd10ac3e --- /dev/null +++ b/secp256k1-sys/depend/secp256k1.h.patch @@ -0,0 +1,22 @@ +202,204d201 +< SECP256K1_API secp256k1_context* secp256k1_context_create( +< unsigned int flags +< ) SECP256K1_WARN_UNUSED_RESULT; +215,217d211 +< SECP256K1_API secp256k1_context* secp256k1_context_clone( +< const secp256k1_context* ctx +< ) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; +232,234d225 +< SECP256K1_API void secp256k1_context_destroy( +< secp256k1_context* ctx +< ); +311,314d301 +< SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space* secp256k1_scratch_space_create( +< const secp256k1_context* ctx, +< size_t size +< ) SECP256K1_ARG_NONNULL(1); +322,325d308 +< SECP256K1_API void secp256k1_scratch_space_destroy( +< const secp256k1_context* ctx, +< secp256k1_scratch_space* scratch +< ) SECP256K1_ARG_NONNULL(1); diff --git a/depend/secp256k1/.gitignore b/secp256k1-sys/depend/secp256k1/.gitignore similarity index 55% rename from depend/secp256k1/.gitignore rename to secp256k1-sys/depend/secp256k1/.gitignore index e0b7b7a48..55d325aee 100644 --- a/depend/secp256k1/.gitignore +++ b/secp256k1-sys/depend/secp256k1/.gitignore @@ -1,11 +1,13 @@ bench_inv bench_ecdh +bench_ecmult bench_sign bench_verify bench_schnorr_verify bench_recover bench_internal tests +exhaustive_tests gen_context *.exe *.so @@ -25,17 +27,24 @@ config.status libtool .deps/ .dirstamp -build-aux/ *.lo *.o *~ src/libsecp256k1-config.h src/libsecp256k1-config.h.in src/ecmult_static_context.h -m4/libtool.m4 -m4/ltoptions.m4 -m4/ltsugar.m4 -m4/ltversion.m4 -m4/lt~obsolete.m4 +build-aux/config.guess +build-aux/config.sub +build-aux/depcomp +build-aux/install-sh +build-aux/ltmain.sh +build-aux/m4/libtool.m4 +build-aux/m4/lt~obsolete.m4 +build-aux/m4/ltoptions.m4 +build-aux/m4/ltsugar.m4 +build-aux/m4/ltversion.m4 +build-aux/missing +build-aux/compile +build-aux/test-driver src/stamp-h1 libsecp256k1.pc diff --git a/depend/secp256k1/.travis.yml b/secp256k1-sys/depend/secp256k1/.travis.yml similarity index 74% rename from depend/secp256k1/.travis.yml rename to secp256k1-sys/depend/secp256k1/.travis.yml index 3540d17d0..74f658f4d 100644 --- a/depend/secp256k1/.travis.yml +++ b/secp256k1-sys/depend/secp256k1/.travis.yml @@ -1,14 +1,18 @@ language: c -sudo: false +os: linux 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 ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no schnorr=no RECOVERY=no EXPERIMENTAL=no + - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no JNI=no + - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar matrix: - SCALAR=32bit RECOVERY=yes - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes @@ -18,14 +22,14 @@ env: - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes - FIELD=64bit ASM=x86_64 - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 - - FIELD=32bit SCHNORR=yes EXPERIMENTAL=yes - FIELD=32bit ENDOMORPHISM=yes - BIGNUM=no - - BIGNUM=no ENDOMORPHISM=yes SCHNORR=yes RECOVERY=yes EXPERIMENTAL=yes + - 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 matrix: fast_finish: true include: @@ -55,9 +59,10 @@ matrix: packages: - gcc-multilib - libgmp-dev:i386 +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 --enable-module-ecdh=$ECDH --enable-module-schnorr=$SCHNORR --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD -os: linux + - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 $BUILD diff --git a/depend/secp256k1/COPYING b/secp256k1-sys/depend/secp256k1/COPYING similarity index 100% rename from depend/secp256k1/COPYING rename to secp256k1-sys/depend/secp256k1/COPYING diff --git a/secp256k1-sys/depend/secp256k1/Makefile.am b/secp256k1-sys/depend/secp256k1/Makefile.am new file mode 100644 index 000000000..2bde765c3 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/Makefile.am @@ -0,0 +1,183 @@ +ACLOCAL_AMFLAGS = -I build-aux/m4 + +lib_LTLIBRARIES = libsecp256k1.la +if USE_JNI +JNI_LIB = librustsecp256k1_v0_1_1_jni.la +noinst_LTLIBRARIES = $(JNI_LIB) +else +JNI_LIB = +endif +include_HEADERS = include/secp256k1.h +include_HEADERS += include/rustsecp256k1_v0_1_1_preallocated.h +noinst_HEADERS = +noinst_HEADERS += src/scalar.h +noinst_HEADERS += src/scalar_4x64.h +noinst_HEADERS += src/scalar_8x32.h +noinst_HEADERS += src/scalar_low.h +noinst_HEADERS += src/scalar_impl.h +noinst_HEADERS += src/scalar_4x64_impl.h +noinst_HEADERS += src/scalar_8x32_impl.h +noinst_HEADERS += src/scalar_low_impl.h +noinst_HEADERS += src/group.h +noinst_HEADERS += src/group_impl.h +noinst_HEADERS += src/num_gmp.h +noinst_HEADERS += src/num_gmp_impl.h +noinst_HEADERS += src/ecdsa.h +noinst_HEADERS += src/ecdsa_impl.h +noinst_HEADERS += src/eckey.h +noinst_HEADERS += src/eckey_impl.h +noinst_HEADERS += src/ecmult.h +noinst_HEADERS += src/ecmult_impl.h +noinst_HEADERS += src/ecmult_const.h +noinst_HEADERS += src/ecmult_const_impl.h +noinst_HEADERS += src/ecmult_gen.h +noinst_HEADERS += src/ecmult_gen_impl.h +noinst_HEADERS += src/num.h +noinst_HEADERS += src/num_impl.h +noinst_HEADERS += src/field_10x26.h +noinst_HEADERS += src/field_10x26_impl.h +noinst_HEADERS += src/field_5x52.h +noinst_HEADERS += src/field_5x52_impl.h +noinst_HEADERS += src/field_5x52_int128_impl.h +noinst_HEADERS += src/field_5x52_asm_impl.h +noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h +noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h +noinst_HEADERS += src/util.h +noinst_HEADERS += src/scratch.h +noinst_HEADERS += src/scratch_impl.h +noinst_HEADERS += src/testrand.h +noinst_HEADERS += src/testrand_impl.h +noinst_HEADERS += src/hash.h +noinst_HEADERS += src/hash_impl.h +noinst_HEADERS += src/field.h +noinst_HEADERS += src/field_impl.h +noinst_HEADERS += src/bench.h +noinst_HEADERS += contrib/lax_der_parsing.h +noinst_HEADERS += contrib/lax_der_parsing.c +noinst_HEADERS += contrib/lax_der_privatekey_parsing.h +noinst_HEADERS += contrib/lax_der_privatekey_parsing.c + +if USE_EXTERNAL_ASM +COMMON_LIB = librustsecp256k1_v0_1_1_common.la +noinst_LTLIBRARIES = $(COMMON_LIB) +else +COMMON_LIB = +endif + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libsecp256k1.pc + +if USE_EXTERNAL_ASM +if USE_ASM_ARM +librustsecp256k1_v0_1_1_common_la_SOURCES = src/asm/field_10x26_arm.s +endif +endif + +librustsecp256k1_v0_1_1_la_SOURCES = src/secp256k1.c +librustsecp256k1_v0_1_1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) +librustsecp256k1_v0_1_1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) + +librustsecp256k1_v0_1_1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c +librustsecp256k1_v0_1_1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) + +noinst_PROGRAMS = +if USE_BENCHMARK +noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_ecmult +bench_verify_SOURCES = src/bench_verify.c +bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +bench_sign_SOURCES = src/bench_sign.c +bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +bench_internal_SOURCES = src/bench_internal.c +bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) +bench_ecmult_SOURCES = src/bench_ecmult.c +bench_ecmult_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_ecmult_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) +endif + +TESTS = +if USE_TESTS +noinst_PROGRAMS += tests +tests_SOURCES = src/tests.c +tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) +if !ENABLE_COVERAGE +tests_CPPFLAGS += -DVERIFY +endif +tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +tests_LDFLAGS = -static +TESTS += tests +endif + +if USE_EXHAUSTIVE_TESTS +noinst_PROGRAMS += exhaustive_tests +exhaustive_tests_SOURCES = src/tests_exhaustive.c +exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) +if !ENABLE_COVERAGE +exhaustive_tests_CPPFLAGS += -DVERIFY +endif +exhaustive_tests_LDADD = $(SECP_LIBS) $(COMMON_LIB) +exhaustive_tests_LDFLAGS = -static +TESTS += exhaustive_tests +endif + +JAVAROOT=src/java +JAVAORG=org/bitcoin +JAVA_GUAVA=$(srcdir)/$(JAVAROOT)/guava/guava-18.0.jar +CLASSPATH_ENV=CLASSPATH=$(JAVA_GUAVA) +JAVA_FILES= \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1.java \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Test.java \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Util.java \ + $(JAVAROOT)/$(JAVAORG)/Secp256k1Context.java + +if USE_JNI + +$(JAVA_GUAVA): + @echo Guava is missing. Fetch it via: \ + wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O $(@) + @false + +.stamp-java: $(JAVA_FILES) + @echo Compiling $^ + $(AM_V_at)$(CLASSPATH_ENV) javac $^ + @touch $@ + +if USE_TESTS + +check-java: libsecp256k1.la $(JAVA_GUAVA) .stamp-java + $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVA_GUAVA):$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test + +endif +endif + +if USE_ECMULT_STATIC_PRECOMPUTATION +CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) + +gen_context_OBJECTS = gen_context.o +gen_context_BIN = gen_context$(BUILD_EXEEXT) +gen_%.o: src/gen_%.c + $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ + +$(gen_context_BIN): $(gen_context_OBJECTS) + $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) $^ -o $@ + +$(librustsecp256k1_v0_1_1_la_OBJECTS): src/ecmult_static_context.h +$(tests_OBJECTS): src/ecmult_static_context.h +$(bench_internal_OBJECTS): src/ecmult_static_context.h +$(bench_ecmult_OBJECTS): src/ecmult_static_context.h + +src/ecmult_static_context.h: $(gen_context_BIN) + ./$(gen_context_BIN) + +CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java +endif + +EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) + +if ENABLE_MODULE_ECDH +include src/modules/ecdh/Makefile.am.include +endif + +if ENABLE_MODULE_RECOVERY +include src/modules/recovery/Makefile.am.include +endif diff --git a/depend/secp256k1/README.md b/secp256k1-sys/depend/secp256k1/README.md similarity index 95% rename from depend/secp256k1/README.md rename to secp256k1-sys/depend/secp256k1/README.md index 6095db422..8cd344ea8 100644 --- a/depend/secp256k1/README.md +++ b/secp256k1-sys/depend/secp256k1/README.md @@ -1,7 +1,7 @@ libsecp256k1 ============ -[![Build Status](https://travis-ci.org/bitcoin/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin/secp256k1) +[![Build Status](https://travis-ci.org/bitcoin-core/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin-core/secp256k1) Optimized C library for EC operations on curve secp256k1. diff --git a/depend/secp256k1/TODO b/secp256k1-sys/depend/secp256k1/TODO similarity index 100% rename from depend/secp256k1/TODO rename to secp256k1-sys/depend/secp256k1/TODO diff --git a/depend/secp256k1/autogen.sh b/secp256k1-sys/depend/secp256k1/autogen.sh similarity index 100% rename from depend/secp256k1/autogen.sh rename to secp256k1-sys/depend/secp256k1/autogen.sh diff --git a/secp256k1-sys/depend/secp256k1/build-aux/m4/ax_jni_include_dir.m4 b/secp256k1-sys/depend/secp256k1/build-aux/m4/ax_jni_include_dir.m4 new file mode 100644 index 000000000..cdc78d87d --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/build-aux/m4/ax_jni_include_dir.m4 @@ -0,0 +1,145 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_JNI_INCLUDE_DIR +# +# DESCRIPTION +# +# AX_JNI_INCLUDE_DIR finds include directories needed for compiling +# programs using the JNI interface. +# +# JNI include directories are usually in the Java distribution. This is +# deduced from the value of $JAVA_HOME, $JAVAC, or the path to "javac", in +# that order. When this macro completes, a list of directories is left in +# the variable JNI_INCLUDE_DIRS. +# +# Example usage follows: +# +# AX_JNI_INCLUDE_DIR +# +# for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS +# do +# CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" +# done +# +# If you want to force a specific compiler: +# +# - at the configure.in level, set JAVAC=yourcompiler before calling +# AX_JNI_INCLUDE_DIR +# +# - at the configure level, setenv JAVAC +# +# Note: This macro can work with the autoconf M4 macros for Java programs. +# This particular macro is not part of the original set of macros. +# +# LICENSE +# +# Copyright (c) 2008 Don Anderson +# +# 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 14 + +AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) +AC_DEFUN([AX_JNI_INCLUDE_DIR],[ + +JNI_INCLUDE_DIRS="" + +if test "x$JAVA_HOME" != x; then + _JTOPDIR="$JAVA_HOME" +else + if test "x$JAVAC" = x; then + JAVAC=javac + fi + AC_PATH_PROG([_ACJNI_JAVAC], [$JAVAC], [no]) + if test "x$_ACJNI_JAVAC" = xno; then + AC_MSG_WARN([cannot find JDK; try setting \$JAVAC or \$JAVA_HOME]) + fi + _ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC") + _JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'` +fi + +case "$host_os" in + darwin*) # Apple Java headers are inside the Xcode bundle. + macos_version=$(sw_vers -productVersion | sed -n -e 's/^@<:@0-9@:>@*.\(@<:@0-9@:>@*\).@<:@0-9@:>@*/\1/p') + if @<:@ "$macos_version" -gt "7" @:>@; then + _JTOPDIR="$(xcrun --show-sdk-path)/System/Library/Frameworks/JavaVM.framework" + _JINC="$_JTOPDIR/Headers" + else + _JTOPDIR="/System/Library/Frameworks/JavaVM.framework" + _JINC="$_JTOPDIR/Headers" + fi + ;; + *) _JINC="$_JTOPDIR/include";; +esac +_AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) +_AS_ECHO_LOG([_JINC=$_JINC]) + +# On Mac OS X 10.6.4, jni.h is a symlink: +# /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h +# -> ../../CurrentJDK/Headers/jni.h. +AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, +[ + if test -f "$_JINC/jni.h"; then + ac_cv_jni_header_path="$_JINC" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" + else + _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + if test -f "$_JTOPDIR/include/jni.h"; then + ac_cv_jni_header_path="$_JTOPDIR/include" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" + else + ac_cv_jni_header_path=none + fi + fi +]) + +# get the likely subdirectories for system specific java includes +case "$host_os" in +bsdi*) _JNI_INC_SUBDIRS="bsdos";; +freebsd*) _JNI_INC_SUBDIRS="freebsd";; +darwin*) _JNI_INC_SUBDIRS="darwin";; +linux*) _JNI_INC_SUBDIRS="linux genunix";; +osf*) _JNI_INC_SUBDIRS="alpha";; +solaris*) _JNI_INC_SUBDIRS="solaris";; +mingw*) _JNI_INC_SUBDIRS="win32";; +cygwin*) _JNI_INC_SUBDIRS="win32";; +*) _JNI_INC_SUBDIRS="genunix";; +esac + +if test "x$ac_cv_jni_header_path" != "xnone"; then + # add any subdirectories that are present + for JINCSUBDIR in $_JNI_INC_SUBDIRS + do + if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" + fi + done +fi +]) + +# _ACJNI_FOLLOW_SYMLINKS +# Follows symbolic links on , +# finally setting variable _ACJNI_FOLLOWED +# ---------------------------------------- +AC_DEFUN([_ACJNI_FOLLOW_SYMLINKS],[ +# find the include directory relative to the javac executable +_cur="$1" +while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do + AC_MSG_CHECKING([symlink for $_cur]) + _slink=`ls -ld "$_cur" | sed 's/.* -> //'` + case "$_slink" in + /*) _cur="$_slink";; + # 'X' avoids triggering unwanted echo options. + *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; + esac + AC_MSG_RESULT([$_cur]) +done +_ACJNI_FOLLOWED="$_cur" +])# _ACJNI diff --git a/depend/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 b/secp256k1-sys/depend/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 similarity index 100% rename from depend/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 rename to secp256k1-sys/depend/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 diff --git a/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 b/secp256k1-sys/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 similarity index 87% rename from depend/secp256k1/build-aux/m4/bitcoin_secp.m4 rename to secp256k1-sys/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 index d41bbb648..3b3975cbd 100644 --- a/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 +++ b/secp256k1-sys/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 @@ -3,13 +3,13 @@ AC_DEFUN([SECP_INT128_CHECK],[ has_int128=$ac_cv_type___int128 ]) -dnl +dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. AC_DEFUN([SECP_64BIT_ASM_CHECK],[ AC_MSG_CHECKING(for x86_64 assembly availability) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]],[[ uint64_t a = 11, tmp; - __asm__ __volatile__("movq $0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); + __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); ]])],[has_64bit_asm=yes],[has_64bit_asm=no]) AC_MSG_RESULT([$has_64bit_asm]) ]) @@ -46,6 +46,9 @@ if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then ECDSA_sign(0, NULL, 0, NULL, NULL, eckey); ECDSA_verify(0, NULL, 0, NULL, 0, eckey); EC_KEY_free(eckey); + ECDSA_SIG *sig_openssl; + sig_openssl = ECDSA_SIG_new(); + ECDSA_SIG_free(sig_openssl); ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) AC_MSG_RESULT([$has_openssl_ec]) fi diff --git a/depend/secp256k1/configure.ac b/secp256k1-sys/depend/secp256k1/configure.ac similarity index 53% rename from depend/secp256k1/configure.ac rename to secp256k1-sys/depend/secp256k1/configure.ac index e4218669f..dc6d50f70 100644 --- a/depend/secp256k1/configure.ac +++ b/secp256k1-sys/depend/secp256k1/configure.ac @@ -20,7 +20,7 @@ AC_PATH_TOOL(STRIP, strip) AX_PROG_CC_FOR_BUILD if test "x$CFLAGS" = "x"; then - CFLAGS="-O3 -g" + CFLAGS="-g" fi AM_PROG_CC_C_O @@ -29,6 +29,7 @@ AC_PROG_CC_C89 if test x"$ac_cv_prog_cc_c89" = x"no"; then AC_MSG_ERROR([c89 compiler support required]) fi +AM_PROG_AS case $host_os in *darwin*) @@ -84,64 +85,150 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], ]) AC_ARG_ENABLE(benchmark, - AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]), + AS_HELP_STRING([--enable-benchmark],[compile benchmark [default=yes]]), [use_benchmark=$enableval], - [use_benchmark=no]) + [use_benchmark=yes]) + +AC_ARG_ENABLE(coverage, + AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis [default=no]]), + [enable_coverage=$enableval], + [enable_coverage=no]) AC_ARG_ENABLE(tests, - AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), + AS_HELP_STRING([--enable-tests],[compile tests [default=yes]]), [use_tests=$enableval], [use_tests=yes]) +AC_ARG_ENABLE(openssl_tests, + AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests [default=auto]]), + [enable_openssl_tests=$enableval], + [enable_openssl_tests=auto]) + AC_ARG_ENABLE(experimental, - AS_HELP_STRING([--enable-experimental],[allow experimental configure options (default is no)]), + AS_HELP_STRING([--enable-experimental],[allow experimental configure options [default=no]]), [use_experimental=$enableval], [use_experimental=no]) +AC_ARG_ENABLE(exhaustive_tests, + AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests [default=yes]]), + [use_exhaustive_tests=$enableval], + [use_exhaustive_tests=yes]) + AC_ARG_ENABLE(endomorphism, - AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), + AS_HELP_STRING([--enable-endomorphism],[enable endomorphism [default=no]]), [use_endomorphism=$enableval], [use_endomorphism=no]) AC_ARG_ENABLE(ecmult_static_precomputation, - AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is yes)]), + AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing [default=auto]]), [use_ecmult_static_precomputation=$enableval], - [use_ecmult_static_precomputation=yes]) + [use_ecmult_static_precomputation=auto]) AC_ARG_ENABLE(module_ecdh, AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (experimental)]), [enable_module_ecdh=$enableval], [enable_module_ecdh=no]) -AC_ARG_ENABLE(module_schnorr, - AS_HELP_STRING([--enable-module-schnorr],[enable Schnorr signature module (experimental)]), - [enable_module_schnorr=$enableval], - [enable_module_schnorr=no]) - AC_ARG_ENABLE(module_recovery, - AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]), + AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module [default=no]]), [enable_module_recovery=$enableval], [enable_module_recovery=no]) +AC_ARG_ENABLE(external_default_callbacks, + AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions (default is no)]), + [use_external_default_callbacks=$enableval], + [use_external_default_callbacks=no]) + +AC_ARG_ENABLE(jni, + AS_HELP_STRING([--enable-jni],[enable librustsecp256k1_v0_1_1_jni [default=no]]), + [use_jni=$enableval], + [use_jni=no]) + AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], -[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) +[finite field implementation to use [default=auto]])],[req_field=$withval], [req_field=auto]) AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto], -[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto]) +[bignum implementation to use [default=auto]])],[req_bignum=$withval], [req_bignum=auto]) AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto], -[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto]) +[scalar implementation to use [default=auto]])],[req_scalar=$withval], [req_scalar=auto]) -AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|no|auto] -[Specify assembly optimizations to use. Default is auto])],[req_asm=$withval], [req_asm=auto]) +AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto], +[assembly optimizations to use (experimental: arm) [default=auto]])],[req_asm=$withval], [req_asm=auto]) + +AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto], +[window size for ecmult precomputation for verification, specified as integer in range [2..24].] +[Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.] +[The table will store 2^(SIZE-2) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.] +[If the endomorphism optimization is enabled, two tables of this size are used instead of only one.] +["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]] +)], +[req_ecmult_window=$withval], [req_ecmult_window=auto]) AC_CHECK_TYPES([__int128]) -AC_MSG_CHECKING([for __builtin_expect]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], - [ AC_MSG_RESULT([yes]);AC_DEFINE(HAVE_BUILTIN_EXPECT,1,[Define this symbol if __builtin_expect is available]) ], - [ AC_MSG_RESULT([no]) - ]) +if test x"$enable_coverage" = x"yes"; then + AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) + CFLAGS="$CFLAGS -O0 --coverage" + LDFLAGS="$LDFLAGS --coverage" +else + CFLAGS="$CFLAGS -O3" +fi + +if test x"$use_ecmult_static_precomputation" != x"no"; then + # Temporarily switch to an environment for the native compiler + save_cross_compiling=$cross_compiling + cross_compiling=no + SAVE_CC="$CC" + CC="$CC_FOR_BUILD" + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS_FOR_BUILD" + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS_FOR_BUILD" + SAVE_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS_FOR_BUILD" + + warn_CFLAGS_FOR_BUILD="-Wall -Wextra -Wno-unused-function" + saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $warn_CFLAGS_FOR_BUILD" + AC_MSG_CHECKING([if native ${CC_FOR_BUILD} supports ${warn_CFLAGS_FOR_BUILD}]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], + [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" + ]) + + AC_MSG_CHECKING([for working native compiler: ${CC_FOR_BUILD}]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([], [])], + [working_native_cc=yes], + [working_native_cc=no],[dnl]) + + CFLAGS_FOR_BUILD="$CFLAGS" + + # Restore the environment + cross_compiling=$save_cross_compiling + CC="$SAVE_CC" + CFLAGS="$SAVE_CFLAGS" + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" + + if test x"$working_native_cc" = x"no"; then + AC_MSG_RESULT([no]) + set_precomp=no + m4_define([please_set_for_build], [Please set CC_FOR_BUILD, CFLAGS_FOR_BUILD, CPPFLAGS_FOR_BUILD, and/or LDFLAGS_FOR_BUILD.]) + if test x"$use_ecmult_static_precomputation" = x"yes"; then + AC_MSG_ERROR([native compiler ${CC_FOR_BUILD} does not produce working binaries. please_set_for_build]) + else + AC_MSG_WARN([Disabling statically generated ecmult table because the native compiler ${CC_FOR_BUILD} does not produce working binaries. please_set_for_build]) + fi + else + AC_MSG_RESULT([yes]) + set_precomp=yes + fi +else + set_precomp=no +fi if test x"$req_asm" = x"auto"; then SECP_64BIT_ASM_CHECK @@ -160,6 +247,8 @@ else AC_MSG_ERROR([x86_64 assembly optimization requested but not available]) fi ;; + arm) + ;; no) ;; *) @@ -252,10 +341,15 @@ else fi # select assembly optimization +use_external_asm=no + case $set_asm in x86_64) AC_DEFINE(USE_ASM_X86_64, 1, [Define this symbol to enable x86_64 assembly optimizations]) ;; +arm) + use_external_asm=yes + ;; no) ;; *) @@ -307,19 +401,73 @@ case $set_scalar in ;; esac +#set ecmult window size +if test x"$req_ecmult_window" = x"auto"; then + set_ecmult_window=15 +else + set_ecmult_window=$req_ecmult_window +fi + +error_window_size=['window size for ecmult precomputation not an integer in range [2..24] or "auto"'] +case $set_ecmult_window in +''|*[[!0-9]]*) + # no valid integer + AC_MSG_ERROR($error_window_size) + ;; +*) + if test "$set_ecmult_window" -lt 2 -o "$set_ecmult_window" -gt 24 ; then + # not in range + AC_MSG_ERROR($error_window_size) + fi + AC_DEFINE_UNQUOTED(ECMULT_WINDOW_SIZE, $set_ecmult_window, [Set window size for ecmult precomputation]) + ;; +esac + if test x"$use_tests" = x"yes"; then SECP_OPENSSL_CHECK if test x"$has_openssl_ec" = x"yes"; then - AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) - SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" - SECP_TEST_LIBS="$CRYPTO_LIBS" - - case $host in - *mingw*) - SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" - ;; - esac + if test x"$enable_openssl_tests" != x"no"; then + AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) + SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" + SECP_TEST_LIBS="$CRYPTO_LIBS" + + case $host in + *mingw*) + SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" + ;; + esac + fi + else + if test x"$enable_openssl_tests" = x"yes"; then + AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available]) + fi + fi +else + if test x"$enable_openssl_tests" = x"yes"; then + AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled]) + fi +fi +if test x"$use_jni" != x"no"; then + AX_JNI_INCLUDE_DIR + have_jni_dependencies=yes + if test x"$enable_module_ecdh" = x"no"; then + have_jni_dependencies=no + fi + if test "x$JNI_INCLUDE_DIRS" = "x"; then + have_jni_dependencies=no + fi + if test "x$have_jni_dependencies" = "xno"; then + if test x"$use_jni" = x"yes"; then + AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.]) + fi + AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) + use_jni=no + else + use_jni=yes + for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do + JNI_INCLUDES="$JNI_INCLUDES -I$JNI_INCLUDE_DIR" + done fi fi @@ -332,7 +480,7 @@ if test x"$use_endomorphism" = x"yes"; then AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization]) fi -if test x"$use_ecmult_static_precomputation" = x"yes"; then +if test x"$set_precomp" = x"yes"; then AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) fi @@ -340,51 +488,52 @@ 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_schnorr" = x"yes"; then - AC_DEFINE(ENABLE_MODULE_SCHNORR, 1, [Define this symbol to enable the Schnorr signature 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 AC_C_BIGENDIAN() -AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) -AC_MSG_NOTICE([Using field implementation: $set_field]) -AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) -AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) -AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) -AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) +if test x"$use_external_asm" = x"yes"; then + AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used]) +fi + +if test x"$use_external_default_callbacks" = x"yes"; then + AC_DEFINE(USE_EXTERNAL_DEFAULT_CALLBACKS, 1, [Define this symbol if an external implementation of the default callbacks is used]) +fi if test x"$enable_experimental" = x"yes"; then AC_MSG_NOTICE([******]) 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 Schnorr signatures module: $enable_module_schnorr]) AC_MSG_NOTICE([******]) else - if test x"$enable_module_schnorr" = x"yes"; then - AC_MSG_ERROR([Schnorr signature module is experimental. Use --enable-experimental to allow.]) - fi 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"$set_asm" = x"arm"; then + AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.]) + fi fi AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) AC_CONFIG_FILES([Makefile libsecp256k1.pc]) +AC_SUBST(JNI_INCLUDES) AC_SUBST(SECP_INCLUDES) AC_SUBST(SECP_LIBS) AC_SUBST(SECP_TEST_LIBS) AC_SUBST(SECP_TEST_INCLUDES) +AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) +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"$use_ecmult_static_precomputation" = 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_SCHNORR], [test x"$enable_module_schnorr" = 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"]) +AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"]) dnl make sure nothing new is exported so that we don't break the cache PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" @@ -392,3 +541,26 @@ unset PKG_CONFIG_PATH PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP" AC_OUTPUT + +echo +echo "Build Options:" +echo " with endomorphism = $use_endomorphism" +echo " with ecmult precomp = $set_precomp" +echo " with external callbacks = $use_external_default_callbacks" +echo " with jni = $use_jni" +echo " with benchmarks = $use_benchmark" +echo " with coverage = $enable_coverage" +echo " module ecdh = $enable_module_ecdh" +echo " module recovery = $enable_module_recovery" +echo +echo " asm = $set_asm" +echo " bignum = $set_bignum" +echo " field = $set_field" +echo " scalar = $set_scalar" +echo " ecmult window size = $set_ecmult_window" +echo +echo " CC = $CC" +echo " CFLAGS = $CFLAGS" +echo " CPPFLAGS = $CPPFLAGS" +echo " LDFLAGS = $LDFLAGS" +echo diff --git a/depend/secp256k1/contrib/lax_der_parsing.c b/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.c similarity index 88% rename from depend/secp256k1/contrib/lax_der_parsing.c rename to secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.c index 5b141a994..7cc772281 100644 --- a/depend/secp256k1/contrib/lax_der_parsing.c +++ b/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.c @@ -9,7 +9,7 @@ #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) { +int rustsecp256k1_v0_1_1_ecdsa_signature_parse_der_lax(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { size_t rpos, rlen, spos, slen; size_t pos = 0; size_t lenbyte; @@ -17,7 +17,7 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_ int overflow = 0; /* Hack to initialize sig with a correctly-parsed but invalid signature. */ - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); /* Sequence tag byte */ if (pos == inputlen || input[pos] != 0x30) { @@ -139,11 +139,11 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_ } if (!overflow) { - overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + overflow = !rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); } if (overflow) { memset(tmpsig, 0, 64); - secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); } return 1; } diff --git a/depend/secp256k1/contrib/lax_der_parsing.h b/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.h similarity index 88% rename from depend/secp256k1/contrib/lax_der_parsing.h rename to secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.h index 6d27871a7..01babd91d 100644 --- a/depend/secp256k1/contrib/lax_der_parsing.h +++ b/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.h @@ -26,8 +26,8 @@ * 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). + * instead if you have the choice (see rustsecp256k1_v0_1_1_ecdsa_signature_parse_der and + * rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact). * * The supported violations are: * - All numbers are parsed as nonnegative integers, even though X.609-0207 @@ -48,14 +48,14 @@ * 8.3.1. */ -#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ -#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ +#ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H +#define SECP256K1_CONTRIB_LAX_DER_PARSING_H #include -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** Parse a signature in "lax DER" format * @@ -77,9 +77,9 @@ extern "C" { * 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, +int rustsecp256k1_v0_1_1_ecdsa_signature_parse_der_lax( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -88,4 +88,4 @@ int ecdsa_signature_parse_der_lax( } #endif -#endif +#endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */ diff --git a/depend/secp256k1/contrib/lax_der_privatekey_parsing.c b/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.c similarity index 86% rename from depend/secp256k1/contrib/lax_der_privatekey_parsing.c rename to secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.c index c2e63b4b8..ab0d5cf46 100644 --- a/depend/secp256k1/contrib/lax_der_privatekey_parsing.c +++ b/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.c @@ -9,7 +9,7 @@ #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) { +int ec_privkey_import_der(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { const unsigned char *end = privkey + privkeylen; int lenb = 0; int len = 0; @@ -46,17 +46,17 @@ int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, co return 0; } memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); - if (!secp256k1_ec_seckey_verify(ctx, out32)) { + if (!rustsecp256k1_v0_1_1_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; +int ec_privkey_export_der(const rustsecp256k1_v0_1_1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { + rustsecp256k1_v0_1_1_pubkey pubkey; size_t pubkeylen = 0; - if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { + if (!rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, key32)) { *privkeylen = 0; return 0; } @@ -80,7 +80,7 @@ int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, 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); + rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; } else { @@ -105,7 +105,7 @@ int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, 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); + rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; } diff --git a/depend/secp256k1/contrib/lax_der_privatekey_parsing.h b/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.h similarity index 91% rename from depend/secp256k1/contrib/lax_der_privatekey_parsing.h rename to secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.h index 2fd088f8a..6a4a30d97 100644 --- a/depend/secp256k1/contrib/lax_der_privatekey_parsing.h +++ b/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.h @@ -25,14 +25,14 @@ * library are sufficient. */ -#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ -#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ +#ifndef SECP256K1_CONTRIB_BER_PRIVATEKEY_H +#define SECP256K1_CONTRIB_BER_PRIVATEKEY_H #include -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** Export a private key in DER format. * @@ -52,10 +52,10 @@ extern "C" { * 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 + * guaranteed to be parsable by rustsecp256k1_v0_1_1_ec_privkey_import_der */ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( - const secp256k1_context* ctx, + const rustsecp256k1_v0_1_1_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, @@ -77,7 +77,7 @@ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( * key. */ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( - const secp256k1_context* ctx, + const rustsecp256k1_v0_1_1_context* ctx, unsigned char *seckey, const unsigned char *privkey, size_t privkeylen @@ -87,4 +87,4 @@ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( } #endif -#endif +#endif /* SECP256K1_CONTRIB_BER_PRIVATEKEY_H */ diff --git a/depend/secp256k1/include/secp256k1.h b/secp256k1-sys/depend/secp256k1/include/secp256k1.h similarity index 63% rename from depend/secp256k1/include/secp256k1.h rename to secp256k1-sys/depend/secp256k1/include/secp256k1.h index 7145dbcc5..df7f7fa2e 100644 --- a/depend/secp256k1/include/secp256k1.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1.h @@ -1,9 +1,9 @@ -#ifndef _SECP256K1_ -# define _SECP256K1_ +#ifndef SECP256K1_H +#define SECP256K1_H -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif #include @@ -33,45 +33,53 @@ extern "C" { * verification). * * A constructed context can safely be used from multiple threads - * simultaneously, but API call that take a non-const pointer to a context + * simultaneously, but API calls that take a non-const pointer to a context * need exclusive access to it. In particular this is the case for - * secp256k1_context_destroy and secp256k1_context_randomize. + * rustsecp256k1_v0_1_1_context_destroy, rustsecp256k1_v0_1_1_context_preallocated_destroy, + * and rustsecp256k1_v0_1_1_context_randomize. * * Regarding randomization, either do it once at creation time (in which case * you do not need any locking for the other calls), or use a read-write lock. */ -typedef struct secp256k1_context_struct secp256k1_context; +typedef struct rustsecp256k1_v0_1_1_context_struct rustsecp256k1_v0_1_1_context; + +/** Opaque data structure that holds rewriteable "scratch space" + * + * The purpose of this structure is to replace dynamic memory allocations, + * because we target architectures where this may not be available. It is + * essentially a resizable (within specified parameters) block of bytes, + * which is initially created either by memory allocation or TODO as a pointer + * into some fixed rewritable space. + * + * Unlike the context object, this cannot safely be shared between threads + * without additional synchronization logic. + */ +typedef struct rustsecp256k1_v0_1_1_scratch_space_struct rustsecp256k1_v0_1_1_scratch_space; /** Opaque data structure that holds a parsed and valid public key. * * The exact representation of data inside is implementation defined and not * guaranteed to be portable between different platforms or versions. It is * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage or transmission, use - * secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. - * - * Furthermore, it is guaranteed that identical public keys (ignoring - * compression) will have identical representation, so they can be memcmp'ed. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use rustsecp256k1_v0_1_1_ec_pubkey_serialize and rustsecp256k1_v0_1_1_ec_pubkey_parse. */ typedef struct { unsigned char data[64]; -} secp256k1_pubkey; +} rustsecp256k1_v0_1_1_pubkey; /** Opaque data structured that holds a parsed ECDSA signature. * * The exact representation of data inside is implementation defined and not * guaranteed to be portable between different platforms or versions. It is * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage or transmission, use - * the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_serialize_* functions. - * - * Furthermore, it is guaranteed to identical signatures will have identical - * representation, so they can be memcmp'ed. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use the rustsecp256k1_v0_1_1_ecdsa_signature_serialize_* and + * rustsecp256k1_v0_1_1_ecdsa_signature_parse_* functions. */ typedef struct { unsigned char data[64]; -} secp256k1_ecdsa_signature; +} rustsecp256k1_v0_1_1_ecdsa_signature; /** A pointer to a function to deterministically generate a nonce. * @@ -89,7 +97,7 @@ typedef struct { * Except for test cases, this function should compute some cryptographic hash of * the message, the algorithm, the key and the attempt. */ -typedef int (*secp256k1_nonce_function)( +typedef int (*rustsecp256k1_v0_1_1_nonce_function)( unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, @@ -156,41 +164,65 @@ typedef int (*secp256k1_nonce_function)( #define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) #define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) -/** Flags to pass to secp256k1_context_create. */ +/** Flags to pass to rustsecp256k1_v0_1_1_context_create, rustsecp256k1_v0_1_1_context_preallocated_size, and + * rustsecp256k1_v0_1_1_context_preallocated_create. */ #define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) #define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) #define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) -/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ +/** Flag to pass to rustsecp256k1_v0_1_1_ec_pubkey_serialize and rustsecp256k1_v0_1_1_ec_privkey_export. */ #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) #define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) -/** Create a secp256k1 context object. +/** Prefix byte used to tag various encoded curvepoints for specific purposes */ +#define SECP256K1_TAG_PUBKEY_EVEN 0x02 +#define SECP256K1_TAG_PUBKEY_ODD 0x03 +#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04 +#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 +#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 + +/** A simple secp256k1 context object with no precomputed tables. These are useful for + * type serialization/parsing functions which require a context object to maintain + * API consistency, but currently do not require expensive precomputations or dynamic + * allocations. + */ +SECP256K1_API extern const rustsecp256k1_v0_1_1_context *rustsecp256k1_v0_1_1_context_no_precomp; + +/** Create a secp256k1 context object (in dynamically allocated memory). + * + * This function uses malloc to allocate memory. It is guaranteed that malloc is + * called at most once for every call of this function. If you need to avoid dynamic + * memory allocation entirely, see the functions in rustsecp256k1_v0_1_1_preallocated.h. * * Returns: a newly created context object. * In: flags: which parts of the context to initialize. + * + * See also rustsecp256k1_v0_1_1_context_randomize. */ -SECP256K1_API secp256k1_context* secp256k1_context_create( - unsigned int flags -) SECP256K1_WARN_UNUSED_RESULT; -/** Copies a secp256k1 context object. +/** Copy a secp256k1 context object (into dynamically allocated memory). + * + * This function uses malloc to allocate memory. It is guaranteed that malloc is + * called at most once for every call of this function. If you need to avoid dynamic + * memory allocation entirely, see the functions in rustsecp256k1_v0_1_1_preallocated.h. * * Returns: a newly created context object. * Args: ctx: an existing context to copy (cannot be NULL) */ -SECP256K1_API secp256k1_context* secp256k1_context_clone( - const secp256k1_context* ctx -) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; -/** Destroy a secp256k1 context object. +/** Destroy a secp256k1 context object (created in dynamically allocated memory). * * The context pointer may not be used afterwards. - * Args: ctx: an existing context to destroy (cannot be NULL) + * + * The context to destroy must have been created using rustsecp256k1_v0_1_1_context_create + * or rustsecp256k1_v0_1_1_context_clone. If the context has instead been created using + * rustsecp256k1_v0_1_1_context_preallocated_create or rustsecp256k1_v0_1_1_context_preallocated_clone, the + * behaviour is undefined. In that case, rustsecp256k1_v0_1_1_context_preallocated_destroy must + * be used instead. + * + * Args: ctx: an existing context to destroy, constructed using + * rustsecp256k1_v0_1_1_context_create or rustsecp256k1_v0_1_1_context_clone */ -SECP256K1_API void secp256k1_context_destroy( - secp256k1_context* ctx -); /** Set a callback function to be called when an illegal argument is passed to * an API call. It will only trigger for violations that are mentioned @@ -206,14 +238,31 @@ SECP256K1_API void secp256k1_context_destroy( * to cause a crash, though its return value and output arguments are * undefined. * + * When this function has not been called (or called with fn==NULL), then the + * default handler will be used. The library provides a default handler which + * writes the message to stderr and calls abort. This default handler can be + * replaced at link time if the preprocessor macro + * USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build + * has been configured with --enable-external-default-callbacks. Then the + * following two symbols must be provided to link against: + * - void rustsecp256k1_v0_1_1_default_illegal_callback_fn(const char* message, void* data); + * - void rustsecp256k1_v0_1_1_default_error_callback_fn(const char* message, void* data); + * The library can call these default handlers even before a proper callback data + * pointer could have been set using rustsecp256k1_v0_1_1_context_set_illegal_callback or + * rustsecp256k1_v0_1_1_context_set_illegal_callback, e.g., when the creation of a context + * fails. In this case, the corresponding default handler will be called with + * the data pointer argument set to NULL. + * * Args: ctx: an existing context object (cannot be NULL) * In: fun: a pointer to a function to call when an illegal argument is - * passed to the API, taking a message and an opaque pointer - * (NULL restores a default handler that calls abort). + * passed to the API, taking a message and an opaque pointer. + * (NULL restores the default handler.) * data: the opaque pointer to pass to fun above. + * + * See also rustsecp256k1_v0_1_1_context_set_error_callback. */ -SECP256K1_API void secp256k1_context_set_illegal_callback( - secp256k1_context* ctx, +SECP256K1_API void rustsecp256k1_v0_1_1_context_set_illegal_callback( + rustsecp256k1_v0_1_1_context* ctx, void (*fun)(const char* message, void* data), const void* data ) SECP256K1_ARG_NONNULL(1); @@ -224,22 +273,40 @@ SECP256K1_API void secp256k1_context_set_illegal_callback( * This can only trigger in case of a hardware failure, miscompilation, * memory corruption, serious bug in the library, or other error would can * otherwise result in undefined behaviour. It will not trigger due to mere - * incorrect usage of the API (see secp256k1_context_set_illegal_callback + * incorrect usage of the API (see rustsecp256k1_v0_1_1_context_set_illegal_callback * for that). After this callback returns, anything may happen, including * crashing. * * Args: ctx: an existing context object (cannot be NULL) * In: fun: a pointer to a function to call when an internal error occurs, - * taking a message and an opaque pointer (NULL restores a default - * handler that calls abort). + * taking a message and an opaque pointer (NULL restores the + * default handler, see rustsecp256k1_v0_1_1_context_set_illegal_callback + * for details). * data: the opaque pointer to pass to fun above. + * + * See also rustsecp256k1_v0_1_1_context_set_illegal_callback. */ -SECP256K1_API void secp256k1_context_set_error_callback( - secp256k1_context* ctx, +SECP256K1_API void rustsecp256k1_v0_1_1_context_set_error_callback( + rustsecp256k1_v0_1_1_context* ctx, void (*fun)(const char* message, void* data), const void* data ) SECP256K1_ARG_NONNULL(1); +/** Create a secp256k1 scratch space object. + * + * Returns: a newly created scratch space. + * Args: ctx: an existing context object (cannot be NULL) + * In: size: amount of memory to be available as scratch space. Some extra + * (<100 bytes) will be allocated for extra accounting. + */ + +/** Destroy a secp256k1 scratch space. + * + * The pointer may not be used afterwards. + * Args: ctx: a secp256k1 context object. + * scratch: space to destroy + */ + /** Parse a variable-length public key into the pubkey object. * * Returns: 1 if the public key was fully valid. @@ -254,9 +321,9 @@ SECP256K1_API void secp256k1_context_set_error_callback( * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header * byte 0x06 or 0x07) format public keys. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( - const secp256k1_context* ctx, - secp256k1_pubkey* pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_pubkey_parse( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_pubkey* pubkey, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -271,16 +338,16 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( * In/Out: outputlen: a pointer to an integer which is initially set to the * size of output, and is overwritten with the written * size. - * In: pubkey: a pointer to a secp256k1_pubkey containing an + * In: pubkey: a pointer to a rustsecp256k1_v0_1_1_pubkey containing an * initialized public key. * flags: SECP256K1_EC_COMPRESSED if serialization should be in * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. */ -SECP256K1_API int secp256k1_ec_pubkey_serialize( - const secp256k1_context* ctx, +SECP256K1_API int rustsecp256k1_v0_1_1_ec_pubkey_serialize( + const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output, size_t *outputlen, - const secp256k1_pubkey* pubkey, + const rustsecp256k1_v0_1_1_pubkey* pubkey, unsigned int flags ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); @@ -299,9 +366,9 @@ SECP256K1_API int secp256k1_ec_pubkey_serialize( * S are zero, the resulting sig value is guaranteed to fail validation for any * message and public key. */ -SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_ecdsa_signature* sig, const unsigned char *input64 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -320,9 +387,9 @@ SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( * encoded numbers are out of range, signature validation with it is * guaranteed to fail for every message and public key. */ -SECP256K1_API int secp256k1_ecdsa_signature_parse_der( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_signature_parse_der( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -338,11 +405,11 @@ SECP256K1_API int secp256k1_ecdsa_signature_parse_der( * if 0 was returned). * In: sig: a pointer to an initialized signature object */ -SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( - const secp256k1_context* ctx, +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der( + const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output, size_t *outputlen, - const secp256k1_ecdsa_signature* sig + const rustsecp256k1_v0_1_1_ecdsa_signature* sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Serialize an ECDSA signature in compact (64 byte) format. @@ -352,12 +419,12 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( * Out: output64: a pointer to a 64-byte array to store the compact serialization * In: sig: a pointer to an initialized signature object * - * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. + * See rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact for details about the encoding. */ -SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( - const secp256k1_context* ctx, +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact( + const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output64, - const secp256k1_ecdsa_signature* sig + const rustsecp256k1_v0_1_1_ecdsa_signature* sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Verify an ECDSA signature. @@ -373,16 +440,16 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( * form are accepted. * * If you need to accept ECDSA signatures from sources that do not obey this - * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to + * rule, apply rustsecp256k1_v0_1_1_ecdsa_signature_normalize to the signature prior to * validation, but be aware that doing so results in malleable signatures. * * For details, see the comments for that function. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( - const secp256k1_context* ctx, - const secp256k1_ecdsa_signature *sig, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ecdsa_verify( + const rustsecp256k1_v0_1_1_context* ctx, + const rustsecp256k1_v0_1_1_ecdsa_signature *sig, const unsigned char *msg32, - const secp256k1_pubkey *pubkey + const rustsecp256k1_v0_1_1_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Convert a signature to a normalized lower-S form. @@ -422,25 +489,25 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( * accept various non-unique encodings, so care should be taken when this * property is required for an application. * - * The secp256k1_ecdsa_sign function will by default create signatures in the - * lower-S form, and secp256k1_ecdsa_verify will not accept others. In case + * The rustsecp256k1_v0_1_1_ecdsa_sign function will by default create signatures in the + * lower-S form, and rustsecp256k1_v0_1_1_ecdsa_verify will not accept others. In case * signatures come from a system that cannot enforce this property, - * secp256k1_ecdsa_signature_normalize must be called before verification. + * rustsecp256k1_v0_1_1_ecdsa_signature_normalize must be called before verification. */ -SECP256K1_API int secp256k1_ecdsa_signature_normalize( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature *sigout, - const secp256k1_ecdsa_signature *sigin +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_signature_normalize( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_ecdsa_signature *sigout, + const rustsecp256k1_v0_1_1_ecdsa_signature *sigin ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); /** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of * extra entropy. */ -SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; +SECP256K1_API extern const rustsecp256k1_v0_1_1_nonce_function rustsecp256k1_v0_1_1_nonce_function_rfc6979; -/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ -SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; +/** A default safe nonce generation function (currently equal to rustsecp256k1_v0_1_1_nonce_function_rfc6979). */ +SECP256K1_API extern const rustsecp256k1_v0_1_1_nonce_function rustsecp256k1_v0_1_1_nonce_function_default; /** Create an ECDSA signature. * @@ -450,18 +517,18 @@ SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_def * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) * In: msg32: the 32-byte message hash being signed (cannot be NULL) * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used + * noncefp:pointer to a nonce generation function. If NULL, rustsecp256k1_v0_1_1_nonce_function_default is used * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) * * The created signature is always in lower-S form. See - * secp256k1_ecdsa_signature_normalize for more details. + * rustsecp256k1_v0_1_1_ecdsa_signature_normalize for more details. */ -SECP256K1_API int secp256k1_ecdsa_sign( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature *sig, +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_sign( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_ecdsa_signature *sig, const unsigned char *msg32, const unsigned char *seckey, - secp256k1_nonce_function noncefp, + rustsecp256k1_v0_1_1_nonce_function noncefp, const void *ndata ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); @@ -472,8 +539,8 @@ SECP256K1_API int secp256k1_ecdsa_sign( * Args: ctx: pointer to a context object (cannot be NULL) * In: seckey: pointer to a 32-byte secret key (cannot be NULL) */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( - const secp256k1_context* ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_seckey_verify( + const rustsecp256k1_v0_1_1_context* ctx, const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); @@ -485,12 +552,34 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( * Out: pubkey: pointer to the created public key (cannot be NULL) * In: seckey: pointer to a 32-byte private key (cannot be NULL) */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_pubkey_create( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_pubkey *pubkey, const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +/** Negates a private key in place. + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * In/Out: seckey: pointer to the 32-byte private key to be negated (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_privkey_negate( + const rustsecp256k1_v0_1_1_context* ctx, + unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Negates a public key in place. + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_pubkey_negate( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + /** Tweak a private key by adding tweak to it. * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * uniformly random 32-byte arrays, or if the resulting private key @@ -500,8 +589,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( * In/Out: seckey: pointer to a 32-byte private key. * In: tweak: pointer to a 32-byte tweak. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( - const secp256k1_context* ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_privkey_tweak_add( + const rustsecp256k1_v0_1_1_context* ctx, unsigned char *seckey, const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -516,9 +605,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( * In/Out: pubkey: pointer to a public key object. * In: tweak: pointer to a 32-byte tweak. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_pubkey_tweak_add( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_pubkey *pubkey, const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -529,8 +618,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( * In/Out: seckey: pointer to a 32-byte private key. * In: tweak: pointer to a 32-byte tweak. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( - const secp256k1_context* ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_privkey_tweak_mul( + const rustsecp256k1_v0_1_1_context* ctx, unsigned char *seckey, const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -543,20 +632,39 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( * In/Out: pubkey: pointer to a public key obkect. * In: tweak: pointer to a 32-byte tweak. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_pubkey *pubkey, const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Updates the context randomization. - * Returns: 1: randomization successfully updated +/** Updates the context randomization to protect against side-channel leakage. + * Returns: 1: randomization successfully updated or nothing to randomize * 0: error * Args: ctx: pointer to a context object (cannot be NULL) * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) + * + * While secp256k1 code is written to be constant-time no matter what secret + * values are, it's possible that a future compiler may output code which isn't, + * and also that the CPU may not emit the same radio frequencies or draw the same + * amount power for all values. + * + * This function provides a seed which is combined into the blinding value: that + * blinding value is added before each multiplication (and removed afterwards) so + * that it does not affect function results, but shields against attacks which + * rely on any input-dependent behaviour. + * + * This function has currently an effect only on contexts initialized for signing + * because randomization is currently used only for signing. However, this is not + * guaranteed and may change in the future. It is safe to call this function on + * contexts not initialized for signing; then it will have no effect and return 1. + * + * You should call this after rustsecp256k1_v0_1_1_context_create or + * rustsecp256k1_v0_1_1_context_clone (and rustsecp256k1_v0_1_1_context_preallocated_create or + * rustsecp256k1_v0_1_1_context_clone, resp.), and you may call this repeatedly afterwards. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( - secp256k1_context* ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_context_randomize( + rustsecp256k1_v0_1_1_context* ctx, const unsigned char *seed32 ) SECP256K1_ARG_NONNULL(1); @@ -569,15 +677,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( * In: ins: pointer to array of pointers to public keys (cannot be NULL) * n: the number of public keys to add together (must be at least 1) */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( - const secp256k1_context* ctx, - secp256k1_pubkey *out, - const secp256k1_pubkey * const * ins, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ec_pubkey_combine( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_pubkey *out, + const rustsecp256k1_v0_1_1_pubkey * const * ins, size_t n ) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -# ifdef __cplusplus +#ifdef __cplusplus } -# endif - #endif + +#endif /* SECP256K1_H */ diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h new file mode 100644 index 000000000..6eaca50a3 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h @@ -0,0 +1,55 @@ +#ifndef SECP256K1_ECDH_H +#define SECP256K1_ECDH_H + +#include "secp256k1.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** A pointer to a function that applies hash function to a point + * + * Returns: 1 if a point was successfully hashed. 0 will cause ecdh to fail + * Out: output: pointer to an array to be filled by the function + * In: x: pointer to a 32-byte x coordinate + * y: pointer to a 32-byte y coordinate + * data: Arbitrary data pointer that is passed through + */ +typedef int (*rustsecp256k1_v0_1_1_ecdh_hash_function)( + unsigned char *output, + const unsigned char *x, + const unsigned char *y, + void *data +); + +/** An implementation of SHA256 hash function that applies to compressed public key. */ +SECP256K1_API extern const rustsecp256k1_v0_1_1_ecdh_hash_function rustsecp256k1_v0_1_1_ecdh_hash_function_sha256; + +/** A default ecdh hash function (currently equal to rustsecp256k1_v0_1_1_ecdh_hash_function_sha256). */ +SECP256K1_API extern const rustsecp256k1_v0_1_1_ecdh_hash_function rustsecp256k1_v0_1_1_ecdh_hash_function_default; + +/** Compute an EC Diffie-Hellman secret in constant time + * Returns: 1: exponentiation was successful + * 0: scalar was invalid (zero or overflow) + * Args: ctx: pointer to a context object (cannot be NULL) + * Out: output: pointer to an array to be filled by the function + * In: pubkey: a pointer to a rustsecp256k1_v0_1_1_pubkey containing an + * initialized public key + * privkey: a 32-byte scalar with which to multiply the point + * hashfp: pointer to a hash function. If NULL, rustsecp256k1_v0_1_1_ecdh_hash_function_sha256 is used + * data: Arbitrary data pointer that is passed through + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ecdh( + const rustsecp256k1_v0_1_1_context* ctx, + unsigned char *output, + const rustsecp256k1_v0_1_1_pubkey *pubkey, + const unsigned char *privkey, + rustsecp256k1_v0_1_1_ecdh_hash_function hashfp, + void *data +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_ECDH_H */ diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_preallocated.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_preallocated.h new file mode 100644 index 000000000..fd071537f --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_preallocated.h @@ -0,0 +1,128 @@ +#ifndef SECP256K1_PREALLOCATED_H +#define SECP256K1_PREALLOCATED_H + +#include "secp256k1.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* The module provided by this header file is intended for settings in which it + * is not possible or desirable to rely on dynamic memory allocation. It provides + * functions for creating, cloning, and destroying secp256k1 context objects in a + * contiguous fixed-size block of memory provided by the caller. + * + * Context objects created by functions in this module can be used like contexts + * objects created by functions in secp256k1.h, i.e., they can be passed to any + * API function that excepts a context object (see secp256k1.h for details). The + * only exception is that context objects created by functions in this module + * must be destroyed using rustsecp256k1_v0_1_1_context_preallocated_destroy (in this + * module) instead of rustsecp256k1_v0_1_1_context_destroy (in secp256k1.h). + * + * It is guaranteed that functions in by this module will not call malloc or its + * friends realloc, calloc, and free. + */ + +/** Determine the memory size of a secp256k1 context object to be created in + * caller-provided memory. + * + * The purpose of this function is to determine how much memory must be provided + * to rustsecp256k1_v0_1_1_context_preallocated_create. + * + * Returns: the required size of the caller-provided memory block + * In: flags: which parts of the context to initialize. + */ +SECP256K1_API size_t rustsecp256k1_v0_1_1_context_preallocated_size( + unsigned int flags +) SECP256K1_WARN_UNUSED_RESULT; + +/** Create a secp256k1 context object in caller-provided memory. + * + * The caller must provide a pointer to a rewritable contiguous block of memory + * of size at least rustsecp256k1_v0_1_1_context_preallocated_size(flags) bytes, suitably + * aligned to hold an object of any type. + * + * The block of memory is exclusively owned by the created context object during + * the lifetime of this context object, which begins with the call to this + * function and ends when a call to rustsecp256k1_v0_1_1_context_preallocated_destroy + * (which destroys the context object again) returns. During the lifetime of the + * context object, the caller is obligated not to access this block of memory, + * i.e., the caller may not read or write the memory, e.g., by copying the memory + * contents to a different location or trying to create a second context object + * in the memory. In simpler words, the prealloc pointer (or any pointer derived + * from it) should not be used during the lifetime of the context object. + * + * Returns: a newly created context object. + * In: prealloc: a pointer to a rewritable contiguous block of memory of + * size at least rustsecp256k1_v0_1_1_context_preallocated_size(flags) + * bytes, as detailed above (cannot be NULL) + * flags: which parts of the context to initialize. + * + * See also rustsecp256k1_v0_1_1_context_randomize (in secp256k1.h) + * and rustsecp256k1_v0_1_1_context_preallocated_destroy. + */ +SECP256K1_API rustsecp256k1_v0_1_1_context* rustsecp256k1_v0_1_1_context_preallocated_create( + void* prealloc, + unsigned int flags +) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; + +/** Determine the memory size of a secp256k1 context object to be copied into + * caller-provided memory. + * + * Returns: the required size of the caller-provided memory block. + * In: ctx: an existing context to copy (cannot be NULL) + */ +SECP256K1_API size_t rustsecp256k1_v0_1_1_context_preallocated_clone_size( + const rustsecp256k1_v0_1_1_context* ctx +) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; + +/** Copy a secp256k1 context object into caller-provided memory. + * + * The caller must provide a pointer to a rewritable contiguous block of memory + * of size at least rustsecp256k1_v0_1_1_context_preallocated_size(flags) bytes, suitably + * aligned to hold an object of any type. + * + * The block of memory is exclusively owned by the created context object during + * the lifetime of this context object, see the description of + * rustsecp256k1_v0_1_1_context_preallocated_create for details. + * + * Returns: a newly created context object. + * Args: ctx: an existing context to copy (cannot be NULL) + * In: prealloc: a pointer to a rewritable contiguous block of memory of + * size at least rustsecp256k1_v0_1_1_context_preallocated_size(flags) + * bytes, as detailed above (cannot be NULL) + */ +SECP256K1_API rustsecp256k1_v0_1_1_context* rustsecp256k1_v0_1_1_context_preallocated_clone( + const rustsecp256k1_v0_1_1_context* ctx, + void* prealloc +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_WARN_UNUSED_RESULT; + +/** Destroy a secp256k1 context object that has been created in + * caller-provided memory. + * + * The context pointer may not be used afterwards. + * + * The context to destroy must have been created using + * rustsecp256k1_v0_1_1_context_preallocated_create or rustsecp256k1_v0_1_1_context_preallocated_clone. + * If the context has instead been created using rustsecp256k1_v0_1_1_context_create or + * rustsecp256k1_v0_1_1_context_clone, the behaviour is undefined. In that case, + * rustsecp256k1_v0_1_1_context_destroy must be used instead. + * + * If required, it is the responsibility of the caller to deallocate the block + * of memory properly after this function returns, e.g., by calling free on the + * preallocated pointer given to rustsecp256k1_v0_1_1_context_preallocated_create or + * rustsecp256k1_v0_1_1_context_preallocated_clone. + * + * Args: ctx: an existing context to destroy, constructed using + * rustsecp256k1_v0_1_1_context_preallocated_create or + * rustsecp256k1_v0_1_1_context_preallocated_clone (cannot be NULL) + */ +SECP256K1_API void rustsecp256k1_v0_1_1_context_preallocated_destroy( + rustsecp256k1_v0_1_1_context* ctx +); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_PREALLOCATED_H */ diff --git a/depend/secp256k1/include/secp256k1_recovery.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_recovery.h similarity index 70% rename from depend/secp256k1/include/secp256k1_recovery.h rename to secp256k1-sys/depend/secp256k1/include/secp256k1_recovery.h index 055379725..b3a3d747b 100644 --- a/depend/secp256k1/include/secp256k1_recovery.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_recovery.h @@ -1,11 +1,11 @@ -#ifndef _SECP256K1_RECOVERY_ -# define _SECP256K1_RECOVERY_ +#ifndef SECP256K1_RECOVERY_H +#define SECP256K1_RECOVERY_H -# include "secp256k1.h" +#include "secp256k1.h" -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** Opaque data structured that holds a parsed ECDSA signature, * supporting pubkey recovery. @@ -14,8 +14,8 @@ extern "C" { * guaranteed to be portable between different platforms or versions. It is * however guaranteed to be 65 bytes in size, and can be safely copied/moved. * If you need to convert to a format suitable for storage or transmission, use - * the secp256k1_ecdsa_signature_serialize_* and - * secp256k1_ecdsa_signature_parse_* functions. + * the rustsecp256k1_v0_1_1_ecdsa_signature_serialize_* and + * rustsecp256k1_v0_1_1_ecdsa_signature_parse_* functions. * * Furthermore, it is guaranteed that identical signatures (including their * recoverability) will have identical representation, so they can be @@ -23,7 +23,7 @@ extern "C" { */ typedef struct { unsigned char data[65]; -} secp256k1_ecdsa_recoverable_signature; +} rustsecp256k1_v0_1_1_ecdsa_recoverable_signature; /** Parse a compact ECDSA signature (64 bytes + recovery id). * @@ -33,9 +33,9 @@ typedef struct { * In: input64: a pointer to a 64-byte compact signature * recid: the recovery id (0, 1, 2 or 3) */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature* sig, +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -46,10 +46,10 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( * Out: sig: a pointer to a normal signature (cannot be NULL). * In: sigin: a pointer to a recoverable signature (cannot be NULL). */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const secp256k1_ecdsa_recoverable_signature* sigin +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_ecdsa_signature* sig, + const rustsecp256k1_v0_1_1_ecdsa_recoverable_signature* sigin ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Serialize an ECDSA signature in compact format (64 bytes + recovery id). @@ -60,11 +60,11 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( * recid: a pointer to an integer to hold the recovery id (can be NULL). * In: sig: a pointer to an initialized signature object (cannot be NULL) */ -SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( - const secp256k1_context* ctx, +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact( + const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output64, int *recid, - const secp256k1_ecdsa_recoverable_signature* sig + const rustsecp256k1_v0_1_1_ecdsa_recoverable_signature* sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Create a recoverable ECDSA signature. @@ -75,15 +75,15 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) * In: msg32: the 32-byte message hash being signed (cannot be NULL) * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used + * noncefp:pointer to a nonce generation function. If NULL, rustsecp256k1_v0_1_1_nonce_function_default is used * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) */ -SECP256K1_API int secp256k1_ecdsa_sign_recoverable( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature *sig, +SECP256K1_API int rustsecp256k1_v0_1_1_ecdsa_sign_recoverable( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature *sig, const unsigned char *msg32, const unsigned char *seckey, - secp256k1_nonce_function noncefp, + rustsecp256k1_v0_1_1_nonce_function noncefp, const void *ndata ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); @@ -96,15 +96,15 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable( * In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) * msg32: the 32-byte message hash assumed to be signed (cannot be NULL) */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( - const secp256k1_context* ctx, - secp256k1_pubkey *pubkey, - const secp256k1_ecdsa_recoverable_signature *sig, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_1_1_ecdsa_recover( + const rustsecp256k1_v0_1_1_context* ctx, + rustsecp256k1_v0_1_1_pubkey *pubkey, + const rustsecp256k1_v0_1_1_ecdsa_recoverable_signature *sig, const unsigned char *msg32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -# ifdef __cplusplus +#ifdef __cplusplus } -# endif - #endif + +#endif /* SECP256K1_RECOVERY_H */ diff --git a/depend/secp256k1/libsecp256k1.pc.in b/secp256k1-sys/depend/secp256k1/libsecp256k1.pc.in similarity index 85% rename from depend/secp256k1/libsecp256k1.pc.in rename to secp256k1-sys/depend/secp256k1/libsecp256k1.pc.in index 1c72dd000..694e98eef 100644 --- a/depend/secp256k1/libsecp256k1.pc.in +++ b/secp256k1-sys/depend/secp256k1/libsecp256k1.pc.in @@ -5,9 +5,9 @@ includedir=@includedir@ Name: libsecp256k1 Description: Optimized C library for EC operations on curve secp256k1 -URL: https://github.com/bitcoin/secp256k1 +URL: https://github.com/bitcoin-core/secp256k1 Version: @PACKAGE_VERSION@ Cflags: -I${includedir} -Libs.private: @SECP_LIBS@ Libs: -L${libdir} -lsecp256k1 +Libs.private: @SECP_LIBS@ diff --git a/depend/secp256k1/obj/.gitignore b/secp256k1-sys/depend/secp256k1/obj/.gitignore similarity index 100% rename from depend/secp256k1/obj/.gitignore rename to secp256k1-sys/depend/secp256k1/obj/.gitignore diff --git a/depend/secp256k1/sage/group_prover.sage b/secp256k1-sys/depend/secp256k1/sage/group_prover.sage similarity index 99% rename from depend/secp256k1/sage/group_prover.sage rename to secp256k1-sys/depend/secp256k1/sage/group_prover.sage index ab580c5b2..8521f0799 100644 --- a/depend/secp256k1/sage/group_prover.sage +++ b/secp256k1-sys/depend/secp256k1/sage/group_prover.sage @@ -3,7 +3,7 @@ # to independently set assumptions on input or intermediary variables. # # The general approach is: -# * A constraint is a tuple of two sets of of symbolic expressions: +# * A constraint is a tuple of two sets of symbolic expressions: # the first of which are required to evaluate to zero, the second of which # are required to evaluate to nonzero. # - A constraint is said to be conflicting if any of its nonzero expressions @@ -17,7 +17,7 @@ # - A constraint describing the requirements of the law, called "require" # * Implementations are transliterated into functions that operate as well on # algebraic input points, and are called once per combination of branches -# exectured. Each execution returns: +# executed. Each execution returns: # - A constraint describing the assumptions this implementation requires # (such as Z1=1), called "assumeFormula" # - A constraint describing the assumptions this specific branch requires, diff --git a/depend/secp256k1/sage/secp256k1.sage b/secp256k1-sys/depend/secp256k1/sage/secp256k1.sage similarity index 74% rename from depend/secp256k1/sage/secp256k1.sage rename to secp256k1-sys/depend/secp256k1/sage/secp256k1.sage index a97e732f7..8e79c02b1 100644 --- a/depend/secp256k1/sage/secp256k1.sage +++ b/secp256k1-sys/depend/secp256k1/sage/secp256k1.sage @@ -5,8 +5,8 @@ import sys load("group_prover.sage") load("weierstrass_prover.sage") -def formula_secp256k1_gej_double_var(a): - """libsecp256k1's secp256k1_gej_double_var, used by various addition functions""" +def formula_rustsecp256k1_v0_1_1_gej_double_var(a): + """libsecp256k1's rustsecp256k1_v0_1_1_gej_double_var, used by various addition functions""" rz = a.Z * a.Y rz = rz * 2 t1 = a.X^2 @@ -29,8 +29,8 @@ def formula_secp256k1_gej_double_var(a): ry = ry + t2 return jacobianpoint(rx, ry, rz) -def formula_secp256k1_gej_add_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_var""" +def formula_rustsecp256k1_v0_1_1_gej_add_var(branch, a, b): + """libsecp256k1's rustsecp256k1_v0_1_1_gej_add_var""" if branch == 0: return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b) if branch == 1: @@ -48,7 +48,7 @@ def formula_secp256k1_gej_add_var(branch, a, b): i = -s1 i = i + s2 if branch == 2: - r = formula_secp256k1_gej_double_var(a) + r = formula_rustsecp256k1_v0_1_1_gej_double_var(a) return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r) if branch == 3: return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity()) @@ -71,8 +71,8 @@ def formula_secp256k1_gej_add_var(branch, a, b): ry = ry + h3 return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) -def formula_secp256k1_gej_add_ge_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_ge_var, which assume bz==1""" +def formula_rustsecp256k1_v0_1_1_gej_add_ge_var(branch, a, b): + """libsecp256k1's rustsecp256k1_v0_1_1_gej_add_ge_var, which assume bz==1""" if branch == 0: return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b) if branch == 1: @@ -88,7 +88,7 @@ def formula_secp256k1_gej_add_ge_var(branch, a, b): i = -s1 i = i + s2 if (branch == 2): - r = formula_secp256k1_gej_double_var(a) + r = formula_rustsecp256k1_v0_1_1_gej_double_var(a) return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) if (branch == 3): return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) @@ -110,8 +110,8 @@ def formula_secp256k1_gej_add_ge_var(branch, a, b): ry = ry + h3 return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) -def formula_secp256k1_gej_add_zinv_var(branch, a, b): - """libsecp256k1's secp256k1_gej_add_zinv_var""" +def formula_rustsecp256k1_v0_1_1_gej_add_zinv_var(branch, a, b): + """libsecp256k1's rustsecp256k1_v0_1_1_gej_add_zinv_var""" bzinv = b.Z^(-1) if branch == 0: return (constraints(), constraints(nonzero={b.Infinity : 'b_infinite'}), a) @@ -134,7 +134,7 @@ def formula_secp256k1_gej_add_zinv_var(branch, a, b): i = -s1 i = i + s2 if branch == 2: - r = formula_secp256k1_gej_double_var(a) + r = formula_rustsecp256k1_v0_1_1_gej_double_var(a) return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) if branch == 3: return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) @@ -157,8 +157,8 @@ def formula_secp256k1_gej_add_zinv_var(branch, a, b): ry = ry + h3 return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) -def formula_secp256k1_gej_add_ge(branch, a, b): - """libsecp256k1's secp256k1_gej_add_ge""" +def formula_rustsecp256k1_v0_1_1_gej_add_ge(branch, a, b): + """libsecp256k1's rustsecp256k1_v0_1_1_gej_add_ge""" zeroes = {} nonzeroes = {} a_infinity = False @@ -229,8 +229,8 @@ def formula_secp256k1_gej_add_ge(branch, a, b): return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity()) return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) -def formula_secp256k1_gej_add_ge_old(branch, a, b): - """libsecp256k1's old secp256k1_gej_add_ge, which fails when ay+by=0 but ax!=bx""" +def formula_rustsecp256k1_v0_1_1_gej_add_ge_old(branch, a, b): + """libsecp256k1's old rustsecp256k1_v0_1_1_gej_add_ge, which fails when ay+by=0 but ax!=bx""" a_infinity = (branch & 1) != 0 zero = {} nonzero = {} @@ -292,15 +292,15 @@ def formula_secp256k1_gej_add_ge_old(branch, a, b): return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz)) if __name__ == "__main__": - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) - check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old) + check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_var", 0, 7, 5, formula_rustsecp256k1_v0_1_1_gej_add_var) + check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_ge_var", 0, 7, 5, formula_rustsecp256k1_v0_1_1_gej_add_ge_var) + check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_zinv_var", 0, 7, 5, formula_rustsecp256k1_v0_1_1_gej_add_zinv_var) + check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_ge", 0, 7, 16, formula_rustsecp256k1_v0_1_1_gej_add_ge) + check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_ge_old [should fail]", 0, 7, 4, formula_rustsecp256k1_v0_1_1_gej_add_ge_old) if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) - check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43) + check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_var", 0, 7, 5, formula_rustsecp256k1_v0_1_1_gej_add_var, 43) + check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_ge_var", 0, 7, 5, formula_rustsecp256k1_v0_1_1_gej_add_ge_var, 43) + check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_zinv_var", 0, 7, 5, formula_rustsecp256k1_v0_1_1_gej_add_zinv_var, 43) + check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_ge", 0, 7, 16, formula_rustsecp256k1_v0_1_1_gej_add_ge, 43) + check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_1_1_gej_add_ge_old [should fail]", 0, 7, 4, formula_rustsecp256k1_v0_1_1_gej_add_ge_old, 43) diff --git a/depend/secp256k1/sage/weierstrass_prover.sage b/secp256k1-sys/depend/secp256k1/sage/weierstrass_prover.sage similarity index 100% rename from depend/secp256k1/sage/weierstrass_prover.sage rename to secp256k1-sys/depend/secp256k1/sage/weierstrass_prover.sage diff --git a/secp256k1-sys/depend/secp256k1/src/asm/field_10x26_arm.s b/secp256k1-sys/depend/secp256k1/src/asm/field_10x26_arm.s new file mode 100644 index 000000000..1d5139228 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/asm/field_10x26_arm.s @@ -0,0 +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.* + **********************************************************************/ +/* +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 rustsecp256k1_v0_1_1_fe_mul_inner + .type rustsecp256k1_v0_1_1_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 +rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_fe_mul_inner, .-rustsecp256k1_v0_1_1_fe_mul_inner + + .align 2 + .global rustsecp256k1_v0_1_1_fe_sqr_inner + .type rustsecp256k1_v0_1_1_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 +rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_fe_sqr_inner, .-rustsecp256k1_v0_1_1_fe_sqr_inner + diff --git a/depend/secp256k1/src/basic-config.h b/secp256k1-sys/depend/secp256k1/src/basic-config.h similarity index 75% rename from depend/secp256k1/src/basic-config.h rename to secp256k1-sys/depend/secp256k1/src/basic-config.h index c4c16eb7c..3a3969d30 100644 --- a/depend/secp256k1/src/basic-config.h +++ b/secp256k1-sys/depend/secp256k1/src/basic-config.h @@ -4,13 +4,16 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_BASIC_CONFIG_ -#define _SECP256K1_BASIC_CONFIG_ +#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_ENDOMORPHISM +#undef USE_EXTERNAL_ASM +#undef USE_EXTERNAL_DEFAULT_CALLBACKS #undef USE_FIELD_10X26 #undef USE_FIELD_5X52 #undef USE_FIELD_INV_BUILTIN @@ -27,6 +30,8 @@ #define USE_SCALAR_INV_BUILTIN 1 #define USE_FIELD_10X26 1 #define USE_SCALAR_8X32 1 +#define ECMULT_WINDOW_SIZE 15 -#endif // USE_BASIC_CONFIG -#endif // _SECP256K1_BASIC_CONFIG_ +#endif /* USE_BASIC_CONFIG */ + +#endif /* SECP256K1_BASIC_CONFIG_H */ diff --git a/depend/secp256k1/src/bench.h b/secp256k1-sys/depend/secp256k1/src/bench.h similarity index 79% rename from depend/secp256k1/src/bench.h rename to secp256k1-sys/depend/secp256k1/src/bench.h index 3a71b4aaf..5b59783f6 100644 --- a/depend/secp256k1/src/bench.h +++ b/secp256k1-sys/depend/secp256k1/src/bench.h @@ -4,10 +4,11 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_BENCH_H_ -#define _SECP256K1_BENCH_H_ +#ifndef SECP256K1_BENCH_H +#define SECP256K1_BENCH_H #include +#include #include #include "sys/time.h" @@ -23,7 +24,7 @@ void print_number(double x) { if (y < 0.0) { y = -y; } - while (y < 100.0) { + while (y > 0 && y < 100.0) { y *= 10.0; c++; } @@ -63,4 +64,19 @@ void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), v printf("us\n"); } -#endif +int have_flag(int argc, char** argv, char *flag) { + char** argm = argv + argc; + argv++; + if (argv == argm) { + return 1; + } + while (argv != NULL && argv != argm) { + if (strcmp(*argv, flag) == 0) { + return 1; + } + argv++; + } + return 0; +} + +#endif /* SECP256K1_BENCH_H */ diff --git a/depend/secp256k1/src/bench_ecdh.c b/secp256k1-sys/depend/secp256k1/src/bench_ecdh.c similarity index 67% rename from depend/secp256k1/src/bench_ecdh.c rename to secp256k1-sys/depend/secp256k1/src/bench_ecdh.c index 5a7c6376e..ff3d7cd93 100644 --- a/depend/secp256k1/src/bench_ecdh.c +++ b/secp256k1-sys/depend/secp256k1/src/bench_ecdh.c @@ -12,14 +12,14 @@ #include "bench.h" typedef struct { - secp256k1_context *ctx; - secp256k1_pubkey point; + rustsecp256k1_v0_1_1_context *ctx; + rustsecp256k1_v0_1_1_pubkey point; unsigned char scalar[32]; -} bench_ecdh_t; +} bench_ecdh_data; static void bench_ecdh_setup(void* arg) { int i; - bench_ecdh_t *data = (bench_ecdh_t*)arg; + bench_ecdh_data *data = (bench_ecdh_data*)arg; const unsigned char point[] = { 0x03, 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, @@ -28,25 +28,26 @@ static void bench_ecdh_setup(void* arg) { 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f }; - data->ctx = secp256k1_context_create(0); + /* create a context with no capabilities */ + data->ctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); for (i = 0; i < 32; i++) { data->scalar[i] = i + 1; } - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); } static void bench_ecdh(void* arg) { int i; unsigned char res[32]; - bench_ecdh_t *data = (bench_ecdh_t*)arg; + bench_ecdh_data *data = (bench_ecdh_data*)arg; for (i = 0; i < 20000; i++) { - CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdh(data->ctx, res, &data->point, data->scalar, NULL, NULL) == 1); } } int main(void) { - bench_ecdh_t data; + bench_ecdh_data data; run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); return 0; diff --git a/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c b/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c new file mode 100644 index 000000000..c96974ac5 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c @@ -0,0 +1,207 @@ +/********************************************************************** + * Copyright (c) 2017 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +#include + +#include "include/secp256k1.h" + +#include "util.h" +#include "hash_impl.h" +#include "num_impl.h" +#include "field_impl.h" +#include "group_impl.h" +#include "scalar_impl.h" +#include "ecmult_impl.h" +#include "bench.h" +#include "secp256k1.c" + +#define POINTS 32768 +#define ITERS 10000 + +typedef struct { + /* Setup once in advance */ + rustsecp256k1_v0_1_1_context* ctx; + rustsecp256k1_v0_1_1_scratch_space* scratch; + rustsecp256k1_v0_1_1_scalar* scalars; + rustsecp256k1_v0_1_1_ge* pubkeys; + rustsecp256k1_v0_1_1_scalar* seckeys; + rustsecp256k1_v0_1_1_gej* expected_output; + rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_gej* output; +} bench_data; + +static int bench_callback(rustsecp256k1_v0_1_1_scalar* sc, rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_ge_const_g; + } else { + *sc = data->scalars[(data->offset1 + idx) % POINTS]; + *ge = data->pubkeys[(data->offset2 + idx - 1) % POINTS]; + } + return 1; +} + +static void bench_ecmult(void* arg) { + bench_data* data = (bench_data*)arg; + + size_t count = data->count; + int includes_g = data->includes_g; + size_t iters = 1 + ITERS / count; + size_t iter; + + for (iter = 0; iter < iters; ++iter) { + data->ecmult_multi(&data->ctx->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) { + bench_data* data = (bench_data*)arg; + size_t iters = 1 + ITERS / data->count; + size_t iter; + /* Verify the results in teardown, to avoid doing comparisons while benchmarking. */ + for (iter = 0; iter < iters; ++iter) { + rustsecp256k1_v0_1_1_gej tmp; + rustsecp256k1_v0_1_1_gej_add_var(&tmp, &data->output[iter], &data->expected_output[iter], NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&tmp)); + } +} + +static void generate_scalar(uint32_t num, rustsecp256k1_v0_1_1_scalar* scalar) { + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_sha256_initialize(&sha256); + rustsecp256k1_v0_1_1_sha256_write(&sha256, c, sizeof(c)); + rustsecp256k1_v0_1_1_sha256_finalize(&sha256, buf); + rustsecp256k1_v0_1_1_scalar_set_b32(scalar, buf, &overflow); + CHECK(!overflow); +} + +static void run_test(bench_data* data, size_t count, int includes_g) { + char str[32]; + static const rustsecp256k1_v0_1_1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + size_t iters = 1 + ITERS / count; + size_t iter; + + data->count = count; + data->includes_g = includes_g; + + /* Compute (the negation of) the expected results directly. */ + data->offset1 = (data->count * 0x537b7f6f + 0x8f66a481) % POINTS; + data->offset2 = (data->count * 0x7f6f537b + 0x6a1a8f49) % POINTS; + for (iter = 0; iter < iters; ++iter) { + rustsecp256k1_v0_1_1_scalar tmp; + rustsecp256k1_v0_1_1_scalar total = data->scalars[(data->offset1++) % POINTS]; + size_t i = 0; + for (i = 0; i + 1 < count; ++i) { + rustsecp256k1_v0_1_1_scalar_mul(&tmp, &data->seckeys[(data->offset2++) % POINTS], &data->scalars[(data->offset1++) % POINTS]); + rustsecp256k1_v0_1_1_scalar_add(&total, &total, &tmp); + } + rustsecp256k1_v0_1_1_scalar_negate(&total, &total); + rustsecp256k1_v0_1_1_ecmult(&data->ctx->ecmult_ctx, &data->expected_output[iter], NULL, &zero, &total); + } + + /* Run the benchmark. */ + sprintf(str, includes_g ? "ecmult_%ig" : "ecmult_%i", (int)count); + run_benchmark(str, bench_ecmult, bench_ecmult_setup, bench_ecmult_teardown, data, 10, count * (1 + ITERS / count)); +} + +int main(int argc, char **argv) { + bench_data data; + int i, p; + rustsecp256k1_v0_1_1_gej* pubkeys_gej; + size_t scratch_size; + + data.ctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + scratch_size = rustsecp256k1_v0_1_1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; + data.scratch = rustsecp256k1_v0_1_1_scratch_space_create(data.ctx, scratch_size); + data.ecmult_multi = rustsecp256k1_v0_1_1_ecmult_multi_var; + + if (argc > 1) { + if(have_flag(argc, argv, "pippenger_wnaf")) { + printf("Using pippenger_wnaf:\n"); + data.ecmult_multi = rustsecp256k1_v0_1_1_ecmult_pippenger_batch_single; + } else if(have_flag(argc, argv, "strauss_wnaf")) { + printf("Using strauss_wnaf:\n"); + data.ecmult_multi = rustsecp256k1_v0_1_1_ecmult_strauss_batch_single; + } else if(have_flag(argc, argv, "simple")) { + printf("Using simple algorithm:\n"); + data.ecmult_multi = rustsecp256k1_v0_1_1_ecmult_multi_var; + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_scalar) * POINTS); + data.seckeys = malloc(sizeof(rustsecp256k1_v0_1_1_scalar) * POINTS); + data.pubkeys = malloc(sizeof(rustsecp256k1_v0_1_1_ge) * POINTS); + data.expected_output = malloc(sizeof(rustsecp256k1_v0_1_1_gej) * (ITERS + 1)); + data.output = malloc(sizeof(rustsecp256k1_v0_1_1_gej) * (ITERS + 1)); + + /* Generate a set of scalars, and private/public keypairs. */ + pubkeys_gej = malloc(sizeof(rustsecp256k1_v0_1_1_gej) * POINTS); + rustsecp256k1_v0_1_1_gej_set_ge(&pubkeys_gej[0], &rustsecp256k1_v0_1_1_ge_const_g); + rustsecp256k1_v0_1_1_scalar_set_int(&data.seckeys[0], 1); + for (i = 0; i < POINTS; ++i) { + generate_scalar(i, &data.scalars[i]); + if (i) { + rustsecp256k1_v0_1_1_gej_double_var(&pubkeys_gej[i], &pubkeys_gej[i - 1], NULL); + rustsecp256k1_v0_1_1_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]); + } + } + rustsecp256k1_v0_1_1_ge_set_all_gej_var(data.pubkeys, pubkeys_gej, POINTS); + free(pubkeys_gej); + + for (i = 1; i <= 8; ++i) { + run_test(&data, i, 1); + } + + for (p = 0; p <= 11; ++p) { + for (i = 9; i <= 16; ++i) { + run_test(&data, i << p, 1); + } + } + if (data.scratch != NULL) { + rustsecp256k1_v0_1_1_scratch_space_destroy(data.ctx, data.scratch); + } + rustsecp256k1_v0_1_1_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/depend/secp256k1/src/bench_internal.c b/secp256k1-sys/depend/secp256k1/src/bench_internal.c similarity index 56% rename from depend/secp256k1/src/bench_internal.c rename to secp256k1-sys/depend/secp256k1/src/bench_internal.c index 7809f5f8c..ff2f35ca5 100644 --- a/depend/secp256k1/src/bench_internal.c +++ b/secp256k1-sys/depend/secp256k1/src/bench_internal.c @@ -19,16 +19,16 @@ #include "secp256k1.c" typedef struct { - secp256k1_scalar scalar_x, scalar_y; - secp256k1_fe fe_x, fe_y; - secp256k1_ge ge_x, ge_y; - secp256k1_gej gej_x, gej_y; + rustsecp256k1_v0_1_1_scalar scalar_x, scalar_y; + rustsecp256k1_v0_1_1_fe fe_x, fe_y; + rustsecp256k1_v0_1_1_ge ge_x, ge_y; + rustsecp256k1_v0_1_1_gej gej_x, gej_y; unsigned char data[64]; int wnaf[256]; -} bench_inv_t; +} bench_inv; void bench_setup(void* arg) { - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; static const unsigned char init_x[32] = { 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, @@ -44,242 +44,253 @@ void bench_setup(void* arg) { 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3 }; - secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL); - secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL); - secp256k1_fe_set_b32(&data->fe_x, init_x); - secp256k1_fe_set_b32(&data->fe_y, init_y); - CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0)); - CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1)); - secp256k1_gej_set_ge(&data->gej_x, &data->ge_x); - secp256k1_gej_set_ge(&data->gej_y, &data->ge_y); + rustsecp256k1_v0_1_1_scalar_set_b32(&data->scalar_x, init_x, NULL); + rustsecp256k1_v0_1_1_scalar_set_b32(&data->scalar_y, init_y, NULL); + rustsecp256k1_v0_1_1_fe_set_b32(&data->fe_x, init_x); + rustsecp256k1_v0_1_1_fe_set_b32(&data->fe_y, init_y); + CHECK(rustsecp256k1_v0_1_1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0)); + CHECK(rustsecp256k1_v0_1_1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1)); + rustsecp256k1_v0_1_1_gej_set_ge(&data->gej_x, &data->ge_x); + rustsecp256k1_v0_1_1_gej_set_ge(&data->gej_y, &data->ge_y); memcpy(data->data, init_x, 32); memcpy(data->data + 32, init_y, 32); } void bench_scalar_add(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + rustsecp256k1_v0_1_1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_scalar_negate(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { - secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); + rustsecp256k1_v0_1_1_scalar_negate(&data->scalar_x, &data->scalar_x); } } void bench_scalar_sqr(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { - secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); + rustsecp256k1_v0_1_1_scalar_sqr(&data->scalar_x, &data->scalar_x); } } void bench_scalar_mul(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { - secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); + rustsecp256k1_v0_1_1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } #ifdef USE_ENDOMORPHISM void bench_scalar_split(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { - secp256k1_scalar l, r; - secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + rustsecp256k1_v0_1_1_scalar l, r; + rustsecp256k1_v0_1_1_scalar_split_lambda(&l, &r, &data->scalar_x); + rustsecp256k1_v0_1_1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } #endif void bench_scalar_inverse(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000; i++) { - secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + rustsecp256k1_v0_1_1_scalar_inverse(&data->scalar_x, &data->scalar_x); + rustsecp256k1_v0_1_1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_scalar_inverse_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000; i++) { - secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + rustsecp256k1_v0_1_1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); + rustsecp256k1_v0_1_1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_field_normalize(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { - secp256k1_fe_normalize(&data->fe_x); + rustsecp256k1_v0_1_1_fe_normalize(&data->fe_x); } } void bench_field_normalize_weak(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 2000000; i++) { - secp256k1_fe_normalize_weak(&data->fe_x); + rustsecp256k1_v0_1_1_fe_normalize_weak(&data->fe_x); } } void bench_field_mul(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { - secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); + rustsecp256k1_v0_1_1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); } } void bench_field_sqr(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { - secp256k1_fe_sqr(&data->fe_x, &data->fe_x); + rustsecp256k1_v0_1_1_fe_sqr(&data->fe_x, &data->fe_x); } } void bench_field_inverse(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { - secp256k1_fe_inv(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); + rustsecp256k1_v0_1_1_fe_inv(&data->fe_x, &data->fe_x); + rustsecp256k1_v0_1_1_fe_add(&data->fe_x, &data->fe_y); } } void bench_field_inverse_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { - secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); + rustsecp256k1_v0_1_1_fe_inv_var(&data->fe_x, &data->fe_x); + rustsecp256k1_v0_1_1_fe_add(&data->fe_x, &data->fe_y); } } -void bench_field_sqrt_var(void* arg) { +void bench_field_sqrt(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; + rustsecp256k1_v0_1_1_fe t; for (i = 0; i < 20000; i++) { - secp256k1_fe_sqrt_var(&data->fe_x, &data->fe_x); - secp256k1_fe_add(&data->fe_x, &data->fe_y); + t = data->fe_x; + rustsecp256k1_v0_1_1_fe_sqrt(&data->fe_x, &t); + rustsecp256k1_v0_1_1_fe_add(&data->fe_x, &data->fe_y); } } void bench_group_double_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { - secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); + rustsecp256k1_v0_1_1_gej_double_var(&data->gej_x, &data->gej_x, NULL); } } void bench_group_add_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { - secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); + rustsecp256k1_v0_1_1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); } } void bench_group_add_affine(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { - secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); + rustsecp256k1_v0_1_1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); } } void bench_group_add_affine_var(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 200000; i++) { - secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); + rustsecp256k1_v0_1_1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); + } +} + +void bench_group_jacobi_var(void* arg) { + int i; + bench_inv *data = (bench_inv*)arg; + + for (i = 0; i < 20000; i++) { + rustsecp256k1_v0_1_1_gej_has_quad_y_var(&data->gej_x); } } void bench_ecmult_wnaf(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { - secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + rustsecp256k1_v0_1_1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); + rustsecp256k1_v0_1_1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_wnaf_const(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; + bench_inv *data = (bench_inv*)arg; for (i = 0; i < 20000; i++) { - secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); - secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + rustsecp256k1_v0_1_1_wnaf_const(data->wnaf, &data->scalar_x, WINDOW_A, 256); + rustsecp256k1_v0_1_1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); } } void bench_sha256(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_sha256_t sha; + bench_inv *data = (bench_inv*)arg; + rustsecp256k1_v0_1_1_sha256 sha; for (i = 0; i < 20000; i++) { - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, data->data, 32); - secp256k1_sha256_finalize(&sha, data->data); + rustsecp256k1_v0_1_1_sha256_initialize(&sha); + rustsecp256k1_v0_1_1_sha256_write(&sha, data->data, 32); + rustsecp256k1_v0_1_1_sha256_finalize(&sha, data->data); } } void bench_hmac_sha256(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_hmac_sha256_t hmac; + bench_inv *data = (bench_inv*)arg; + rustsecp256k1_v0_1_1_hmac_sha256 hmac; for (i = 0; i < 20000; i++) { - secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); - secp256k1_hmac_sha256_write(&hmac, data->data, 32); - secp256k1_hmac_sha256_finalize(&hmac, data->data); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hmac, data->data, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, data->data, 32); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hmac, data->data); } } void bench_rfc6979_hmac_sha256(void* arg) { int i; - bench_inv_t *data = (bench_inv_t*)arg; - secp256k1_rfc6979_hmac_sha256_t rng; + bench_inv *data = (bench_inv*)arg; + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 rng; for (i = 0; i < 20000; i++) { - secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); - secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); } } @@ -287,7 +298,7 @@ void bench_context_verify(void* arg) { int i; (void)arg; for (i = 0; i < 20; i++) { - secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY)); + rustsecp256k1_v0_1_1_context_destroy(rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_VERIFY)); } } @@ -295,28 +306,28 @@ void bench_context_sign(void* arg) { int i; (void)arg; for (i = 0; i < 200; i++) { - secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN)); + rustsecp256k1_v0_1_1_context_destroy(rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN)); } } +#ifndef USE_NUM_NONE +void bench_num_jacobi(void* arg) { + int i; + bench_inv *data = (bench_inv*)arg; + rustsecp256k1_v0_1_1_num nx, norder; -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++; + rustsecp256k1_v0_1_1_scalar_get_num(&nx, &data->scalar_x); + rustsecp256k1_v0_1_1_scalar_order_get_num(&norder); + rustsecp256k1_v0_1_1_scalar_get_num(&norder, &data->scalar_y); + + for (i = 0; i < 200000; i++) { + rustsecp256k1_v0_1_1_num_jacobi(&nx, &norder); } - return 0; } +#endif int main(int argc, char **argv) { - bench_inv_t data; + bench_inv data; if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000); @@ -333,12 +344,13 @@ int main(int argc, char **argv) { if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000); - if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt_var", bench_field_sqrt_var, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000); if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000); if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000); @@ -350,5 +362,8 @@ int main(int argc, char **argv) { if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 20); if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 200); +#ifndef USE_NUM_NONE + if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, 200000); +#endif return 0; } diff --git a/depend/secp256k1/src/bench_recover.c b/secp256k1-sys/depend/secp256k1/src/bench_recover.c similarity index 64% rename from depend/secp256k1/src/bench_recover.c rename to secp256k1-sys/depend/secp256k1/src/bench_recover.c index 6489378cc..e71ae32af 100644 --- a/depend/secp256k1/src/bench_recover.c +++ b/secp256k1-sys/depend/secp256k1/src/bench_recover.c @@ -10,24 +10,24 @@ #include "bench.h" typedef struct { - secp256k1_context *ctx; + rustsecp256k1_v0_1_1_context *ctx; unsigned char msg[32]; unsigned char sig[64]; -} bench_recover_t; +} bench_recover_data; void bench_recover(void* arg) { int i; - bench_recover_t *data = (bench_recover_t*)arg; - secp256k1_pubkey pubkey; + bench_recover_data *data = (bench_recover_data*)arg; + rustsecp256k1_v0_1_1_pubkey pubkey; unsigned char pubkeyc[33]; for (i = 0; i < 20000; 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)); + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature sig; + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); + CHECK(rustsecp256k1_v0_1_1_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. */ @@ -38,7 +38,7 @@ void bench_recover(void* arg) { void bench_recover_setup(void* arg) { int i; - bench_recover_t *data = (bench_recover_t*)arg; + bench_recover_data *data = (bench_recover_data*)arg; for (i = 0; i < 32; i++) { data->msg[i] = 1 + i; @@ -49,12 +49,12 @@ void bench_recover_setup(void* arg) { } int main(void) { - bench_recover_t data; + bench_recover_data data; - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + data.ctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_VERIFY); run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000); - secp256k1_context_destroy(data.ctx); + rustsecp256k1_v0_1_1_context_destroy(data.ctx); return 0; } diff --git a/depend/secp256k1/src/bench_sign.c b/secp256k1-sys/depend/secp256k1/src/bench_sign.c similarity index 58% rename from depend/secp256k1/src/bench_sign.c rename to secp256k1-sys/depend/secp256k1/src/bench_sign.c index ed7224d75..a7e5f9d5f 100644 --- a/depend/secp256k1/src/bench_sign.c +++ b/secp256k1-sys/depend/secp256k1/src/bench_sign.c @@ -9,14 +9,14 @@ #include "bench.h" typedef struct { - secp256k1_context* ctx; + rustsecp256k1_v0_1_1_context* ctx; unsigned char msg[32]; unsigned char key[32]; -} bench_sign_t; +} bench_sign; static void bench_sign_setup(void* arg) { int i; - bench_sign_t *data = (bench_sign_t*)arg; + bench_sign *data = (bench_sign*)arg; for (i = 0; i < 32; i++) { data->msg[i] = i + 1; @@ -26,17 +26,17 @@ static void bench_sign_setup(void* arg) { } } -static void bench_sign(void* arg) { +static void bench_sign_run(void* arg) { int i; - bench_sign_t *data = (bench_sign_t*)arg; + bench_sign *data = (bench_sign*)arg; unsigned char sig[74]; for (i = 0; i < 20000; 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)); + rustsecp256k1_v0_1_1_ecdsa_signature signature; + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); + CHECK(rustsecp256k1_v0_1_1_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]; @@ -45,12 +45,12 @@ static void bench_sign(void* arg) { } int main(void) { - bench_sign_t data; + bench_sign data; - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + data.ctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN); - run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000); + run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, 20000); - secp256k1_context_destroy(data.ctx); + rustsecp256k1_v0_1_1_context_destroy(data.ctx); return 0; } diff --git a/depend/secp256k1/src/bench_verify.c b/secp256k1-sys/depend/secp256k1/src/bench_verify.c similarity index 73% rename from depend/secp256k1/src/bench_verify.c rename to secp256k1-sys/depend/secp256k1/src/bench_verify.c index 418defa0a..696da767e 100644 --- a/depend/secp256k1/src/bench_verify.c +++ b/secp256k1-sys/depend/secp256k1/src/bench_verify.c @@ -18,7 +18,7 @@ #endif typedef struct { - secp256k1_context *ctx; + rustsecp256k1_v0_1_1_context *ctx; unsigned char msg[32]; unsigned char key[32]; unsigned char sig[72]; @@ -35,14 +35,14 @@ static void benchmark_verify(void* arg) { benchmark_verify_t* data = (benchmark_verify_t*)arg; for (i = 0; i < 20000; i++) { - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; + rustsecp256k1_v0_1_1_pubkey pubkey; + rustsecp256k1_v0_1_1_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)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); + CHECK(rustsecp256k1_v0_1_1_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); @@ -81,11 +81,11 @@ static void benchmark_verify_openssl(void* arg) { int main(void) { int i; - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; + rustsecp256k1_v0_1_1_pubkey pubkey; + rustsecp256k1_v0_1_1_ecdsa_signature sig; benchmark_verify_t data; - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + data.ctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); for (i = 0; i < 32; i++) { data.msg[i] = 1 + i; @@ -94,11 +94,11 @@ int main(void) { 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)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); #ifdef ENABLE_OPENSSL_TESTS @@ -107,6 +107,6 @@ int main(void) { EC_GROUP_free(data.ec_group); #endif - secp256k1_context_destroy(data.ctx); + rustsecp256k1_v0_1_1_context_destroy(data.ctx); return 0; } diff --git a/secp256k1-sys/depend/secp256k1/src/ecdsa.h b/secp256k1-sys/depend/secp256k1/src/ecdsa.h new file mode 100644 index 000000000..3d3bbdfd0 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/ecdsa.h @@ -0,0 +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.* + **********************************************************************/ + +#ifndef SECP256K1_ECDSA_H +#define SECP256K1_ECDSA_H + +#include + +#include "scalar.h" +#include "group.h" +#include "ecmult.h" + +static int rustsecp256k1_v0_1_1_ecdsa_sig_parse(rustsecp256k1_v0_1_1_scalar *r, rustsecp256k1_v0_1_1_scalar *s, const unsigned char *sig, size_t size); +static int rustsecp256k1_v0_1_1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *s); +static int rustsecp256k1_v0_1_1_ecdsa_sig_verify(const rustsecp256k1_v0_1_1_ecmult_context *ctx, const rustsecp256k1_v0_1_1_scalar* r, const rustsecp256k1_v0_1_1_scalar* s, const rustsecp256k1_v0_1_1_ge *pubkey, const rustsecp256k1_v0_1_1_scalar *message); +static int rustsecp256k1_v0_1_1_ecdsa_sig_sign(const rustsecp256k1_v0_1_1_ecmult_gen_context *ctx, rustsecp256k1_v0_1_1_scalar* r, rustsecp256k1_v0_1_1_scalar* s, const rustsecp256k1_v0_1_1_scalar *seckey, const rustsecp256k1_v0_1_1_scalar *message, const rustsecp256k1_v0_1_1_scalar *nonce, int *recid); + +#endif /* SECP256K1_ECDSA_H */ diff --git a/depend/secp256k1/src/ecdsa_impl.h b/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h similarity index 59% rename from depend/secp256k1/src/ecdsa_impl.h rename to secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h index d110b4bb1..5d239fe04 100644 --- a/depend/secp256k1/src/ecdsa_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h @@ -5,8 +5,8 @@ **********************************************************************/ -#ifndef _SECP256K1_ECDSA_IMPL_H_ -#define _SECP256K1_ECDSA_IMPL_H_ +#ifndef SECP256K1_ECDSA_IMPL_H +#define SECP256K1_ECDSA_IMPL_H #include "scalar.h" #include "field.h" @@ -28,7 +28,7 @@ * sage: '%x' % (EllipticCurve ([F (a), F (b)]).order()) * 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141' */ -static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( +static const rustsecp256k1_v0_1_1_fe rustsecp256k1_v0_1_1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL ); @@ -42,11 +42,11 @@ static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST * sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order()) * '14551231950b75fc4402da1722fc9baee' */ -static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( +static const rustsecp256k1_v0_1_1_fe rustsecp256k1_v0_1_1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL ); -static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) { +static int rustsecp256k1_v0_1_1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) { int lenleft, b1; size_t ret = 0; if (*sigp >= sigend) { @@ -81,8 +81,6 @@ static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned cha return -1; } while (lenleft > 0) { - if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) { - } ret = (ret << 8) | **sigp; if (ret + lenleft > (size_t)(sigend - *sigp)) { /* Result exceeds the length of the passed array. */ @@ -98,7 +96,7 @@ static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned cha return ret; } -static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) { +static int rustsecp256k1_v0_1_1_der_parse_integer(rustsecp256k1_v0_1_1_scalar *r, const unsigned char **sig, const unsigned char *sigend) { int overflow = 0; unsigned char ra[32] = {0}; int rlen; @@ -108,7 +106,7 @@ static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char return 0; } (*sig)++; - rlen = secp256k1_der_read_len(sig, sigend); + rlen = rustsecp256k1_v0_1_1_der_read_len(sig, sigend); if (rlen <= 0 || (*sig) + rlen > sigend) { /* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */ return 0; @@ -135,23 +133,23 @@ static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char } if (!overflow) { memcpy(ra + 32 - rlen, *sig, rlen); - secp256k1_scalar_set_b32(r, ra, &overflow); + rustsecp256k1_v0_1_1_scalar_set_b32(r, ra, &overflow); } if (overflow) { - secp256k1_scalar_set_int(r, 0); + rustsecp256k1_v0_1_1_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) { +static int rustsecp256k1_v0_1_1_ecdsa_sig_parse(rustsecp256k1_v0_1_1_scalar *rr, rustsecp256k1_v0_1_1_scalar *rs, const unsigned char *sig, size_t size) { const unsigned char *sigend = sig + size; int rlen; if (sig == sigend || *(sig++) != 0x30) { /* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */ return 0; } - rlen = secp256k1_der_read_len(&sig, sigend); + rlen = rustsecp256k1_v0_1_1_der_read_len(&sig, sigend); if (rlen < 0 || sig + rlen > sigend) { /* Tuple exceeds bounds */ return 0; @@ -161,10 +159,10 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, return 0; } - if (!secp256k1_der_parse_integer(rr, &sig, sigend)) { + if (!rustsecp256k1_v0_1_1_der_parse_integer(rr, &sig, sigend)) { return 0; } - if (!secp256k1_der_parse_integer(rs, &sig, sigend)) { + if (!rustsecp256k1_v0_1_1_der_parse_integer(rs, &sig, sigend)) { return 0; } @@ -176,12 +174,12 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, return 1; } -static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) { +static int rustsecp256k1_v0_1_1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const rustsecp256k1_v0_1_1_scalar* ar, const rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_get_b32(&r[1], ar); + rustsecp256k1_v0_1_1_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) { @@ -200,27 +198,42 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const 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) { +static int rustsecp256k1_v0_1_1_ecdsa_sig_verify(const rustsecp256k1_v0_1_1_ecmult_context *ctx, const rustsecp256k1_v0_1_1_scalar *sigr, const rustsecp256k1_v0_1_1_scalar *sigs, const rustsecp256k1_v0_1_1_ge *pubkey, const rustsecp256k1_v0_1_1_scalar *message) { unsigned char c[32]; - secp256k1_scalar sn, u1, u2; - secp256k1_fe xr; - secp256k1_gej pubkeyj; - secp256k1_gej pr; + rustsecp256k1_v0_1_1_scalar sn, u1, u2; +#if !defined(EXHAUSTIVE_TEST_ORDER) + rustsecp256k1_v0_1_1_fe xr; +#endif + rustsecp256k1_v0_1_1_gej pubkeyj; + rustsecp256k1_v0_1_1_gej pr; - if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { + if (rustsecp256k1_v0_1_1_scalar_is_zero(sigr) || rustsecp256k1_v0_1_1_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)) { + rustsecp256k1_v0_1_1_scalar_inverse_var(&sn, sigs); + rustsecp256k1_v0_1_1_scalar_mul(&u1, &sn, message); + rustsecp256k1_v0_1_1_scalar_mul(&u2, &sn, sigr); + rustsecp256k1_v0_1_1_gej_set_ge(&pubkeyj, pubkey); + rustsecp256k1_v0_1_1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1); + if (rustsecp256k1_v0_1_1_gej_is_infinity(&pr)) { return 0; } - secp256k1_scalar_get_b32(c, sigr); - secp256k1_fe_set_b32(&xr, c); + +#if defined(EXHAUSTIVE_TEST_ORDER) +{ + rustsecp256k1_v0_1_1_scalar computed_r; + rustsecp256k1_v0_1_1_ge pr_ge; + rustsecp256k1_v0_1_1_ge_set_gej(&pr_ge, &pr); + rustsecp256k1_v0_1_1_fe_normalize(&pr_ge.x); + + rustsecp256k1_v0_1_1_fe_get_b32(c, &pr_ge.x); + rustsecp256k1_v0_1_1_scalar_set_b32(&computed_r, c, NULL); + return rustsecp256k1_v0_1_1_scalar_eq(sigr, &computed_r); +} +#else + rustsecp256k1_v0_1_1_scalar_get_b32(c, sigr); + rustsecp256k1_v0_1_1_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), @@ -236,63 +249,60 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const * <=> (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. + * rustsecp256k1_v0_1_1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. */ - if (secp256k1_gej_eq_x_var(&xr, &pr)) { + if (rustsecp256k1_v0_1_1_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) { + if (rustsecp256k1_v0_1_1_fe_cmp_var(&xr, &rustsecp256k1_v0_1_1_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)) { + rustsecp256k1_v0_1_1_fe_add(&xr, &rustsecp256k1_v0_1_1_ecdsa_const_order_as_fe); + if (rustsecp256k1_v0_1_1_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) { +static int rustsecp256k1_v0_1_1_ecdsa_sig_sign(const rustsecp256k1_v0_1_1_ecmult_gen_context *ctx, rustsecp256k1_v0_1_1_scalar *sigr, rustsecp256k1_v0_1_1_scalar *sigs, const rustsecp256k1_v0_1_1_scalar *seckey, const rustsecp256k1_v0_1_1_scalar *message, const rustsecp256k1_v0_1_1_scalar *nonce, int *recid) { unsigned char b[32]; - secp256k1_gej rp; - secp256k1_ge r; - secp256k1_scalar n; + rustsecp256k1_v0_1_1_gej rp; + rustsecp256k1_v0_1_1_ge r; + rustsecp256k1_v0_1_1_scalar n; int overflow = 0; - 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 (secp256k1_scalar_is_zero(sigr)) { - /* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. - * This branch is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. - */ - secp256k1_gej_clear(&rp); - secp256k1_ge_clear(&r); - return 0; - } + rustsecp256k1_v0_1_1_ecmult_gen(ctx, &rp, nonce); + rustsecp256k1_v0_1_1_ge_set_gej(&r, &rp); + rustsecp256k1_v0_1_1_fe_normalize(&r.x); + rustsecp256k1_v0_1_1_fe_normalize(&r.y); + rustsecp256k1_v0_1_1_fe_get_b32(b, &r.x); + rustsecp256k1_v0_1_1_scalar_set_b32(sigr, b, &overflow); + /* These two conditions should be checked before calling */ + VERIFY_CHECK(!rustsecp256k1_v0_1_1_scalar_is_zero(sigr)); + VERIFY_CHECK(overflow == 0); + 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 ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); - } - 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); - if (secp256k1_scalar_is_zero(sigs)) { + *recid = (overflow ? 2 : 0) | (rustsecp256k1_v0_1_1_fe_is_odd(&r.y) ? 1 : 0); + } + rustsecp256k1_v0_1_1_scalar_mul(&n, sigr, seckey); + rustsecp256k1_v0_1_1_scalar_add(&n, &n, message); + rustsecp256k1_v0_1_1_scalar_inverse(sigs, nonce); + rustsecp256k1_v0_1_1_scalar_mul(sigs, sigs, &n); + rustsecp256k1_v0_1_1_scalar_clear(&n); + rustsecp256k1_v0_1_1_gej_clear(&rp); + rustsecp256k1_v0_1_1_ge_clear(&r); + if (rustsecp256k1_v0_1_1_scalar_is_zero(sigs)) { return 0; } - if (secp256k1_scalar_is_high(sigs)) { - secp256k1_scalar_negate(sigs, sigs); + if (rustsecp256k1_v0_1_1_scalar_is_high(sigs)) { + rustsecp256k1_v0_1_1_scalar_negate(sigs, sigs); if (recid) { *recid ^= 1; } @@ -300,4 +310,4 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec return 1; } -#endif +#endif /* SECP256K1_ECDSA_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/eckey.h b/secp256k1-sys/depend/secp256k1/src/eckey.h new file mode 100644 index 000000000..008aea4b5 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/eckey.h @@ -0,0 +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.* + **********************************************************************/ + +#ifndef SECP256K1_ECKEY_H +#define SECP256K1_ECKEY_H + +#include + +#include "group.h" +#include "scalar.h" +#include "ecmult.h" +#include "ecmult_gen.h" + +static int rustsecp256k1_v0_1_1_eckey_pubkey_parse(rustsecp256k1_v0_1_1_ge *elem, const unsigned char *pub, size_t size); +static int rustsecp256k1_v0_1_1_eckey_pubkey_serialize(rustsecp256k1_v0_1_1_ge *elem, unsigned char *pub, size_t *size, int compressed); + +static int rustsecp256k1_v0_1_1_eckey_privkey_tweak_add(rustsecp256k1_v0_1_1_scalar *key, const rustsecp256k1_v0_1_1_scalar *tweak); +static int rustsecp256k1_v0_1_1_eckey_pubkey_tweak_add(const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_ge *key, const rustsecp256k1_v0_1_1_scalar *tweak); +static int rustsecp256k1_v0_1_1_eckey_privkey_tweak_mul(rustsecp256k1_v0_1_1_scalar *key, const rustsecp256k1_v0_1_1_scalar *tweak); +static int rustsecp256k1_v0_1_1_eckey_pubkey_tweak_mul(const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_ge *key, const rustsecp256k1_v0_1_1_scalar *tweak); + +#endif /* SECP256K1_ECKEY_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/eckey_impl.h b/secp256k1-sys/depend/secp256k1/src/eckey_impl.h new file mode 100644 index 000000000..eb2d65d84 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/eckey_impl.h @@ -0,0 +1,100 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_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 rustsecp256k1_v0_1_1_eckey_pubkey_parse(rustsecp256k1_v0_1_1_ge *elem, const unsigned char *pub, size_t size) { + if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { + rustsecp256k1_v0_1_1_fe x; + return rustsecp256k1_v0_1_1_fe_set_b32(&x, pub+1) && rustsecp256k1_v0_1_1_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)) { + rustsecp256k1_v0_1_1_fe x, y; + if (!rustsecp256k1_v0_1_1_fe_set_b32(&x, pub+1) || !rustsecp256k1_v0_1_1_fe_set_b32(&y, pub+33)) { + return 0; + } + rustsecp256k1_v0_1_1_ge_set_xy(elem, &x, &y); + if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && + rustsecp256k1_v0_1_1_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { + return 0; + } + return rustsecp256k1_v0_1_1_ge_is_valid_var(elem); + } else { + return 0; + } +} + +static int rustsecp256k1_v0_1_1_eckey_pubkey_serialize(rustsecp256k1_v0_1_1_ge *elem, unsigned char *pub, size_t *size, int compressed) { + if (rustsecp256k1_v0_1_1_ge_is_infinity(elem)) { + return 0; + } + rustsecp256k1_v0_1_1_fe_normalize_var(&elem->x); + rustsecp256k1_v0_1_1_fe_normalize_var(&elem->y); + rustsecp256k1_v0_1_1_fe_get_b32(&pub[1], &elem->x); + if (compressed) { + *size = 33; + pub[0] = rustsecp256k1_v0_1_1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; + } else { + *size = 65; + pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; + rustsecp256k1_v0_1_1_fe_get_b32(&pub[33], &elem->y); + } + return 1; +} + +static int rustsecp256k1_v0_1_1_eckey_privkey_tweak_add(rustsecp256k1_v0_1_1_scalar *key, const rustsecp256k1_v0_1_1_scalar *tweak) { + rustsecp256k1_v0_1_1_scalar_add(key, key, tweak); + if (rustsecp256k1_v0_1_1_scalar_is_zero(key)) { + return 0; + } + return 1; +} + +static int rustsecp256k1_v0_1_1_eckey_pubkey_tweak_add(const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_ge *key, const rustsecp256k1_v0_1_1_scalar *tweak) { + rustsecp256k1_v0_1_1_gej pt; + rustsecp256k1_v0_1_1_scalar one; + rustsecp256k1_v0_1_1_gej_set_ge(&pt, key); + rustsecp256k1_v0_1_1_scalar_set_int(&one, 1); + rustsecp256k1_v0_1_1_ecmult(ctx, &pt, &pt, &one, tweak); + + if (rustsecp256k1_v0_1_1_gej_is_infinity(&pt)) { + return 0; + } + rustsecp256k1_v0_1_1_ge_set_gej(key, &pt); + return 1; +} + +static int rustsecp256k1_v0_1_1_eckey_privkey_tweak_mul(rustsecp256k1_v0_1_1_scalar *key, const rustsecp256k1_v0_1_1_scalar *tweak) { + if (rustsecp256k1_v0_1_1_scalar_is_zero(tweak)) { + return 0; + } + + rustsecp256k1_v0_1_1_scalar_mul(key, key, tweak); + return 1; +} + +static int rustsecp256k1_v0_1_1_eckey_pubkey_tweak_mul(const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_ge *key, const rustsecp256k1_v0_1_1_scalar *tweak) { + rustsecp256k1_v0_1_1_scalar zero; + rustsecp256k1_v0_1_1_gej pt; + if (rustsecp256k1_v0_1_1_scalar_is_zero(tweak)) { + return 0; + } + + rustsecp256k1_v0_1_1_scalar_set_int(&zero, 0); + rustsecp256k1_v0_1_1_gej_set_ge(&pt, key); + rustsecp256k1_v0_1_1_ecmult(ctx, &pt, &pt, tweak, &zero); + rustsecp256k1_v0_1_1_ge_set_gej(key, &pt); + return 1; +} + +#endif /* SECP256K1_ECKEY_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult.h b/secp256k1-sys/depend/secp256k1/src/ecmult.h new file mode 100644 index 000000000..ffe5b329b --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/ecmult.h @@ -0,0 +1,48 @@ +/********************************************************************** + * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_ECMULT_H +#define SECP256K1_ECMULT_H + +#include "num.h" +#include "group.h" +#include "scalar.h" +#include "scratch.h" + +typedef struct { + /* For accelerating the computation of a*P + b*G: */ + rustsecp256k1_v0_1_1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ +#ifdef USE_ENDOMORPHISM + rustsecp256k1_v0_1_1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ +#endif +} rustsecp256k1_v0_1_1_ecmult_context; + +static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE; +static void rustsecp256k1_v0_1_1_ecmult_context_init(rustsecp256k1_v0_1_1_ecmult_context *ctx); +static void rustsecp256k1_v0_1_1_ecmult_context_build(rustsecp256k1_v0_1_1_ecmult_context *ctx, void **prealloc); +static void rustsecp256k1_v0_1_1_ecmult_context_finalize_memcpy(rustsecp256k1_v0_1_1_ecmult_context *dst, const rustsecp256k1_v0_1_1_ecmult_context *src); +static void rustsecp256k1_v0_1_1_ecmult_context_clear(rustsecp256k1_v0_1_1_ecmult_context *ctx); +static int rustsecp256k1_v0_1_1_ecmult_context_is_built(const rustsecp256k1_v0_1_1_ecmult_context *ctx); + +/** Double multiply: R = na*A + ng*G */ +static void rustsecp256k1_v0_1_1_ecmult(const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_scalar *na, const rustsecp256k1_v0_1_1_scalar *ng); + +typedef int (rustsecp256k1_v0_1_1_ecmult_multi_callback)(rustsecp256k1_v0_1_1_scalar *sc, rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_ecmult_multi_var(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_scratch *scratch, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *inp_g_sc, rustsecp256k1_v0_1_1_ecmult_multi_callback cb, void *cbdata, size_t n); + +#endif /* SECP256K1_ECMULT_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_const.h b/secp256k1-sys/depend/secp256k1/src/ecmult_const.h new file mode 100644 index 000000000..b4c3089bb --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_const.h @@ -0,0 +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.* + **********************************************************************/ + +#ifndef SECP256K1_ECMULT_CONST_H +#define SECP256K1_ECMULT_CONST_H + +#include "scalar.h" +#include "group.h" + +/* 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 rustsecp256k1_v0_1_1_ecmult_const(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_ge *a, const rustsecp256k1_v0_1_1_scalar *q, int bits); + +#endif /* SECP256K1_ECMULT_CONST_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h new file mode 100644 index 000000000..0fe6f6e6c --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h @@ -0,0 +1,261 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_ECMULT_CONST_IMPL_H +#define SECP256K1_ECMULT_CONST_IMPL_H + +#include "scalar.h" +#include "group.h" +#include "ecmult_const.h" +#include "ecmult_impl.h" + +/* This is like `ECMULT_TABLE_GET_GE` but is constant time */ +#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ + int m; \ + int abs_n = (n) * (((n) > 0) * 2 - 1); \ + int idx_n = abs_n / 2; \ + rustsecp256k1_v0_1_1_fe neg_y; \ + VERIFY_CHECK(((n) & 1) == 1); \ + VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ + VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ + VERIFY_SETUP(rustsecp256k1_v0_1_1_fe_clear(&(r)->x)); \ + VERIFY_SETUP(rustsecp256k1_v0_1_1_fe_clear(&(r)->y)); \ + for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \ + /* This loop is used to avoid secret data in array indices. See + * the comment in ecmult_gen_impl.h for rationale. */ \ + rustsecp256k1_v0_1_1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \ + rustsecp256k1_v0_1_1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \ + } \ + (r)->infinity = 0; \ + rustsecp256k1_v0_1_1_fe_negate(&neg_y, &(r)->y, 1); \ + rustsecp256k1_v0_1_1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \ +} while(0) + + +/** Convert a number to WNAF notation. + * The number becomes represented by sum(2^{wi} * wnaf[i], i=0..WNAF_SIZE(w)+1) - return_val. + * It has the following guarantees: + * - each wnaf[i] an odd integer between -(1 << w) and (1 << w) + * - each wnaf[i] is nonzero + * - the number of words set is always WNAF_SIZE(w) + 1 + * + * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar + * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) + * CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003 + * + * Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 + */ +static int rustsecp256k1_v0_1_1_wnaf_const(int *wnaf, const rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_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 `rustsecp256k1_v0_1_1_scalar_cadd_bit` and + * we need to special-case it in this logic. */ + flip = rustsecp256k1_v0_1_1_scalar_is_high(scalar); + /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ + bit = flip ^ !rustsecp256k1_v0_1_1_scalar_is_even(scalar); + /* We check for negative one, since adding 2 to it will cause an overflow */ + rustsecp256k1_v0_1_1_scalar_negate(&s, scalar); + not_neg_one = !rustsecp256k1_v0_1_1_scalar_is_one(&s); + s = *scalar; + rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_scalar_cond_negate(&s, flip); + global_sign *= not_neg_one * 2 - 1; + skew = 1 << bit; + + /* 4 */ + u_last = rustsecp256k1_v0_1_1_scalar_shr_int(&s, w); + do { + int sign; + int even; + + /* 4.1 4.4 */ + u = rustsecp256k1_v0_1_1_scalar_shr_int(&s, w); + /* 4.2 */ + even = ((u & 1) == 0); + sign = 2 * (u_last > 0) - 1; + u += sign * even; + u_last -= sign * even * (1 << w); + + /* 4.3, adapted for global sign change */ + wnaf[word++] = u_last * global_sign; + + u_last = u; + } while (word * w < size); + wnaf[word] = u * global_sign; + + VERIFY_CHECK(rustsecp256k1_v0_1_1_scalar_is_zero(&s)); + VERIFY_CHECK(word == WNAF_SIZE_BITS(size, w)); + return skew; +} + +static void rustsecp256k1_v0_1_1_ecmult_const(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_ge *a, const rustsecp256k1_v0_1_1_scalar *scalar, int size) { + rustsecp256k1_v0_1_1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + rustsecp256k1_v0_1_1_ge tmpa; + rustsecp256k1_v0_1_1_fe Z; + + int skew_1; +#ifdef USE_ENDOMORPHISM + rustsecp256k1_v0_1_1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; + int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; + int skew_lam; + rustsecp256k1_v0_1_1_scalar q_1, q_lam; +#endif + int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; + + int i; + + /* build wnaf representation for q. */ + int rsize = size; +#ifdef USE_ENDOMORPHISM + if (size > 128) { + rsize = 128; + /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ + rustsecp256k1_v0_1_1_scalar_split_lambda(&q_1, &q_lam, scalar); + skew_1 = rustsecp256k1_v0_1_1_wnaf_const(wnaf_1, &q_1, WINDOW_A - 1, 128); + skew_lam = rustsecp256k1_v0_1_1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128); + } else +#endif + { + skew_1 = rustsecp256k1_v0_1_1_wnaf_const(wnaf_1, scalar, WINDOW_A - 1, size); +#ifdef USE_ENDOMORPHISM + skew_lam = 0; +#endif + } + + /* Calculate odd multiples of a. + * All multiples are brought to the same Z 'denominator', which is stored + * in Z. Due to secp256k1' isomorphism we can do all operations pretending + * that the Z coordinate was 1, use affine addition formulae, and correct + * the Z coordinate of the result once at the end. + */ + rustsecp256k1_v0_1_1_gej_set_ge(r, a); + rustsecp256k1_v0_1_1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r); + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + rustsecp256k1_v0_1_1_fe_normalize_weak(&pre_a[i].y); + } +#ifdef USE_ENDOMORPHISM + if (size > 128) { + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + rustsecp256k1_v0_1_1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + } + } +#endif + + /* first loop iteration (separated out so we can directly set r, rather + * than having it start at infinity, get doubled several times, then have + * its new value added to it) */ + i = wnaf_1[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)]; + VERIFY_CHECK(i != 0); + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); + rustsecp256k1_v0_1_1_gej_set_ge(r, &tmpa); +#ifdef USE_ENDOMORPHISM + 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); + rustsecp256k1_v0_1_1_gej_add_ge(r, r, &tmpa); + } +#endif + /* 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) { + rustsecp256k1_v0_1_1_gej_double_nonzero(r, r, NULL); + } + + n = wnaf_1[i]; + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + VERIFY_CHECK(n != 0); + rustsecp256k1_v0_1_1_gej_add_ge(r, r, &tmpa); +#ifdef USE_ENDOMORPHISM + if (size > 128) { + n = wnaf_lam[i]; + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); + VERIFY_CHECK(n != 0); + rustsecp256k1_v0_1_1_gej_add_ge(r, r, &tmpa); + } +#endif + } + + rustsecp256k1_v0_1_1_fe_mul(&r->z, &r->z, &Z); + + { + /* Correct for wNAF skew */ + rustsecp256k1_v0_1_1_ge correction = *a; + rustsecp256k1_v0_1_1_ge_storage correction_1_stor; +#ifdef USE_ENDOMORPHISM + rustsecp256k1_v0_1_1_ge_storage correction_lam_stor; +#endif + rustsecp256k1_v0_1_1_ge_storage a2_stor; + rustsecp256k1_v0_1_1_gej tmpj; + rustsecp256k1_v0_1_1_gej_set_ge(&tmpj, &correction); + rustsecp256k1_v0_1_1_gej_double_var(&tmpj, &tmpj, NULL); + rustsecp256k1_v0_1_1_ge_set_gej(&correction, &tmpj); + rustsecp256k1_v0_1_1_ge_to_storage(&correction_1_stor, a); +#ifdef USE_ENDOMORPHISM + if (size > 128) { + rustsecp256k1_v0_1_1_ge_to_storage(&correction_lam_stor, a); + } +#endif + rustsecp256k1_v0_1_1_ge_to_storage(&a2_stor, &correction); + + /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ + rustsecp256k1_v0_1_1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); +#ifdef USE_ENDOMORPHISM + if (size > 128) { + rustsecp256k1_v0_1_1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); + } +#endif + + /* Apply the correction */ + rustsecp256k1_v0_1_1_ge_from_storage(&correction, &correction_1_stor); + rustsecp256k1_v0_1_1_ge_neg(&correction, &correction); + rustsecp256k1_v0_1_1_gej_add_ge(r, r, &correction); + +#ifdef USE_ENDOMORPHISM + if (size > 128) { + rustsecp256k1_v0_1_1_ge_from_storage(&correction, &correction_lam_stor); + rustsecp256k1_v0_1_1_ge_neg(&correction, &correction); + rustsecp256k1_v0_1_1_ge_mul_lambda(&correction, &correction); + rustsecp256k1_v0_1_1_gej_add_ge(r, r, &correction); + } +#endif + } +} + +#endif /* SECP256K1_ECMULT_CONST_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_gen.h b/secp256k1-sys/depend/secp256k1/src/ecmult_gen.h new file mode 100644 index 000000000..58a9bac7a --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_gen.h @@ -0,0 +1,43 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_ECMULT_GEN_H +#define SECP256K1_ECMULT_GEN_H + +#include "scalar.h" +#include "group.h" + +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 4 bits, called n_0, n_1, n_2, ..., n_63. + * * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: + * * U_i = U * 2^i (for i=0..62) + * * U_i = U * (1-2^63) (for i=63) + * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. + * For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is + * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). + * None of the resulting prec group elements have a known scalar, and neither do any of + * the intermediate sums while computing a*G. + */ + rustsecp256k1_v0_1_1_ge_storage (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */ + rustsecp256k1_v0_1_1_scalar blind; + rustsecp256k1_v0_1_1_gej initial; +} rustsecp256k1_v0_1_1_ecmult_gen_context; + +static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; +static void rustsecp256k1_v0_1_1_ecmult_gen_context_init(rustsecp256k1_v0_1_1_ecmult_gen_context* ctx); +static void rustsecp256k1_v0_1_1_ecmult_gen_context_build(rustsecp256k1_v0_1_1_ecmult_gen_context* ctx, void **prealloc); +static void rustsecp256k1_v0_1_1_ecmult_gen_context_finalize_memcpy(rustsecp256k1_v0_1_1_ecmult_gen_context *dst, const rustsecp256k1_v0_1_1_ecmult_gen_context* src); +static void rustsecp256k1_v0_1_1_ecmult_gen_context_clear(rustsecp256k1_v0_1_1_ecmult_gen_context* ctx); +static int rustsecp256k1_v0_1_1_ecmult_gen_context_is_built(const rustsecp256k1_v0_1_1_ecmult_gen_context* ctx); + +/** Multiply with the generator: R = a*G */ +static void rustsecp256k1_v0_1_1_ecmult_gen(const rustsecp256k1_v0_1_1_ecmult_gen_context* ctx, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *a); + +static void rustsecp256k1_v0_1_1_ecmult_gen_blind(rustsecp256k1_v0_1_1_ecmult_gen_context *ctx, const unsigned char *seed32); + +#endif /* SECP256K1_ECMULT_GEN_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h new file mode 100644 index 000000000..3be3f1d4e --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h @@ -0,0 +1,211 @@ +/********************************************************************** + * 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.* + **********************************************************************/ + +#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(*((rustsecp256k1_v0_1_1_ecmult_gen_context*) NULL)->prec)); +#else + static const size_t SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE = 0; +#endif + +static void rustsecp256k1_v0_1_1_ecmult_gen_context_init(rustsecp256k1_v0_1_1_ecmult_gen_context *ctx) { + ctx->prec = NULL; +} + +static void rustsecp256k1_v0_1_1_ecmult_gen_context_build(rustsecp256k1_v0_1_1_ecmult_gen_context *ctx, void **prealloc) { +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + rustsecp256k1_v0_1_1_ge prec[1024]; + rustsecp256k1_v0_1_1_gej gj; + rustsecp256k1_v0_1_1_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 = (rustsecp256k1_v0_1_1_ge_storage (*)[64][16])manual_alloc(prealloc, prealloc_size, base, prealloc_size); + + /* get the generator */ + rustsecp256k1_v0_1_1_gej_set_ge(&gj, &rustsecp256k1_v0_1_1_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"; + rustsecp256k1_v0_1_1_fe nums_x; + rustsecp256k1_v0_1_1_ge nums_ge; + int r; + r = rustsecp256k1_v0_1_1_fe_set_b32(&nums_x, nums_b32); + (void)r; + VERIFY_CHECK(r); + r = rustsecp256k1_v0_1_1_ge_set_xo_var(&nums_ge, &nums_x, 0); + (void)r; + VERIFY_CHECK(r); + rustsecp256k1_v0_1_1_gej_set_ge(&nums_gej, &nums_ge); + /* Add G to make the bits in x uniformly distributed. */ + rustsecp256k1_v0_1_1_gej_add_ge_var(&nums_gej, &nums_gej, &rustsecp256k1_v0_1_1_ge_const_g, NULL); + } + + /* compute prec. */ + { + rustsecp256k1_v0_1_1_gej precj[1024]; /* Jacobian versions of prec. */ + rustsecp256k1_v0_1_1_gej gbase; + rustsecp256k1_v0_1_1_gej numsbase; + gbase = gj; /* 16^j * G */ + numsbase = nums_gej; /* 2^j * nums. */ + for (j = 0; j < 64; j++) { + /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ + precj[j*16] = numsbase; + for (i = 1; i < 16; i++) { + rustsecp256k1_v0_1_1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL); + } + /* Multiply gbase by 16. */ + for (i = 0; i < 4; i++) { + rustsecp256k1_v0_1_1_gej_double_var(&gbase, &gbase, NULL); + } + /* Multiply numbase by 2. */ + rustsecp256k1_v0_1_1_gej_double_var(&numsbase, &numsbase, NULL); + if (j == 62) { + /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ + rustsecp256k1_v0_1_1_gej_neg(&numsbase, &numsbase); + rustsecp256k1_v0_1_1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); + } + } + rustsecp256k1_v0_1_1_ge_set_all_gej_var(prec, precj, 1024); + } + for (j = 0; j < 64; j++) { + for (i = 0; i < 16; i++) { + rustsecp256k1_v0_1_1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); + } + } +#else + (void)prealloc; + ctx->prec = (rustsecp256k1_v0_1_1_ge_storage (*)[64][16])rustsecp256k1_v0_1_1_ecmult_static_context; +#endif + rustsecp256k1_v0_1_1_ecmult_gen_blind(ctx, NULL); +} + +static int rustsecp256k1_v0_1_1_ecmult_gen_context_is_built(const rustsecp256k1_v0_1_1_ecmult_gen_context* ctx) { + return ctx->prec != NULL; +} + +static void rustsecp256k1_v0_1_1_ecmult_gen_context_finalize_memcpy(rustsecp256k1_v0_1_1_ecmult_gen_context *dst, const rustsecp256k1_v0_1_1_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 = (rustsecp256k1_v0_1_1_ge_storage (*)[64][16])(void*)((unsigned char*)dst + ((unsigned char*)src->prec - (unsigned char*)src)); + } +#else + (void)dst, (void)src; +#endif +} + +static void rustsecp256k1_v0_1_1_ecmult_gen_context_clear(rustsecp256k1_v0_1_1_ecmult_gen_context *ctx) { + rustsecp256k1_v0_1_1_scalar_clear(&ctx->blind); + rustsecp256k1_v0_1_1_gej_clear(&ctx->initial); + ctx->prec = NULL; +} + +static void rustsecp256k1_v0_1_1_ecmult_gen(const rustsecp256k1_v0_1_1_ecmult_gen_context *ctx, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *gn) { + rustsecp256k1_v0_1_1_ge add; + rustsecp256k1_v0_1_1_ge_storage adds; + rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_scalar_add(&gnb, gn, &ctx->blind); + add.infinity = 0; + for (j = 0; j < 64; j++) { + bits = rustsecp256k1_v0_1_1_scalar_get_bits(&gnb, j * 4, 4); + for (i = 0; i < 16; 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) + */ + rustsecp256k1_v0_1_1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits); + } + rustsecp256k1_v0_1_1_ge_from_storage(&add, &adds); + rustsecp256k1_v0_1_1_gej_add_ge(r, r, &add); + } + bits = 0; + rustsecp256k1_v0_1_1_ge_clear(&add); + rustsecp256k1_v0_1_1_scalar_clear(&gnb); +} + +/* Setup blinding values for rustsecp256k1_v0_1_1_ecmult_gen. */ +static void rustsecp256k1_v0_1_1_ecmult_gen_blind(rustsecp256k1_v0_1_1_ecmult_gen_context *ctx, const unsigned char *seed32) { + rustsecp256k1_v0_1_1_scalar b; + rustsecp256k1_v0_1_1_gej gb; + rustsecp256k1_v0_1_1_fe s; + unsigned char nonce32[32]; + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 rng; + int retry; + unsigned char keydata[64] = {0}; + if (seed32 == NULL) { + /* When seed is NULL, reset the initial point and blinding value. */ + rustsecp256k1_v0_1_1_gej_set_ge(&ctx->initial, &rustsecp256k1_v0_1_1_ge_const_g); + rustsecp256k1_v0_1_1_gej_neg(&ctx->initial, &ctx->initial); + rustsecp256k1_v0_1_1_scalar_set_int(&ctx->blind, 1); + } + /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ + rustsecp256k1_v0_1_1_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); + } + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32); + memset(keydata, 0, sizeof(keydata)); + /* Retry for out of range results to achieve uniformity. */ + do { + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + retry = !rustsecp256k1_v0_1_1_fe_set_b32(&s, nonce32); + retry |= rustsecp256k1_v0_1_1_fe_is_zero(&s); + } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */ + /* Randomize the projection to defend against multiplier sidechannels. */ + rustsecp256k1_v0_1_1_gej_rescale(&ctx->initial, &s); + rustsecp256k1_v0_1_1_fe_clear(&s); + do { + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + rustsecp256k1_v0_1_1_scalar_set_b32(&b, nonce32, &retry); + /* A blinding value of 0 works, but would undermine the projection hardening. */ + retry |= rustsecp256k1_v0_1_1_scalar_is_zero(&b); + } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */ + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_finalize(&rng); + memset(nonce32, 0, 32); + rustsecp256k1_v0_1_1_ecmult_gen(ctx, &gb, &b); + rustsecp256k1_v0_1_1_scalar_negate(&b, &b); + ctx->blind = b; + ctx->initial = gb; + rustsecp256k1_v0_1_1_scalar_clear(&b); + rustsecp256k1_v0_1_1_gej_clear(&gb); +} + +#endif /* SECP256K1_ECMULT_GEN_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h new file mode 100644 index 000000000..36f0dd75e --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h @@ -0,0 +1,1215 @@ +/***************************************************************************** + * Copyright (c) 2013, 2014, 2017 Pieter Wuille, Andrew Poelstra, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php. * + *****************************************************************************/ + +#ifndef SECP256K1_ECMULT_IMPL_H +#define SECP256K1_ECMULT_IMPL_H + +#include +#include + +#include "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(rustsecp256k1_v0_1_1_ge_storage) bytes, + * where sizeof(rustsecp256k1_v0_1_1_ge_storage) is typically 64 bytes but can + * be larger due to platform-specific padding and alignment. + * If the endomorphism optimization is enabled (USE_ENDOMORMPHSIM) + * two tables of this size are used instead of only one. + */ +# 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 + * 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 + +#ifdef USE_ENDOMORPHISM + #define WNAF_BITS 128 +#else + #define WNAF_BITS 256 +#endif +#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w)) +#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w) + +/** The number of entries a table with precomputed multiples needs to have. */ +#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) + +/* The number of objects allocated on the scratch space for ecmult_multi algorithms */ +#define PIPPENGER_SCRATCH_OBJECTS 6 +#define STRAUSS_SCRATCH_OBJECTS 6 + +#define PIPPENGER_MAX_BUCKET_WINDOW 12 + +/* Minimum number of points for which pippenger_wnaf is faster than strauss wnaf */ +#ifdef USE_ENDOMORPHISM + #define ECMULT_PIPPENGER_THRESHOLD 88 +#else + #define ECMULT_PIPPENGER_THRESHOLD 160 +#endif + +#ifdef USE_ENDOMORPHISM + #define ECMULT_MAX_POINTS_PER_BATCH 5000000 +#else + #define ECMULT_MAX_POINTS_PER_BATCH 10000000 +#endif + +/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain + * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will + * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. + * Prej's Z values are undefined, except for the last value. + */ +static void rustsecp256k1_v0_1_1_ecmult_odd_multiples_table(int n, rustsecp256k1_v0_1_1_gej *prej, rustsecp256k1_v0_1_1_fe *zr, const rustsecp256k1_v0_1_1_gej *a) { + rustsecp256k1_v0_1_1_gej d; + rustsecp256k1_v0_1_1_ge a_ge, d_ge; + int i; + + VERIFY_CHECK(!a->infinity); + + rustsecp256k1_v0_1_1_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; + + rustsecp256k1_v0_1_1_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++) { + rustsecp256k1_v0_1_1_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. + */ + rustsecp256k1_v0_1_1_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: + * - rustsecp256k1_v0_1_1_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. + * - rustsecp256k1_v0_1_1_ecmult_odd_multiples_table_storage_var, which converts its + * resulting point set to actually affine points, and stores those in pre. + * It operates on tables of any size, but uses heap-allocated temporaries. + * + * To compute a*P + b*G, we compute a table for P using the first function, + * and for G using the second (which requires an inverse, but it only needs to + * happen once). + */ +static void rustsecp256k1_v0_1_1_ecmult_odd_multiples_table_globalz_windowa(rustsecp256k1_v0_1_1_ge *pre, rustsecp256k1_v0_1_1_fe *globalz, const rustsecp256k1_v0_1_1_gej *a) { + rustsecp256k1_v0_1_1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; + rustsecp256k1_v0_1_1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; + + /* Compute the odd multiples in Jacobian form. */ + rustsecp256k1_v0_1_1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); + /* Bring them to the same Z denominator. */ + rustsecp256k1_v0_1_1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); +} + +static void rustsecp256k1_v0_1_1_ecmult_odd_multiples_table_storage_var(const int n, rustsecp256k1_v0_1_1_ge_storage *pre, const rustsecp256k1_v0_1_1_gej *a) { + rustsecp256k1_v0_1_1_gej d; + rustsecp256k1_v0_1_1_ge d_ge, p_ge; + rustsecp256k1_v0_1_1_gej pj; + rustsecp256k1_v0_1_1_fe zi; + rustsecp256k1_v0_1_1_fe zr; + rustsecp256k1_v0_1_1_fe dx_over_dz_squared; + int i; + + VERIFY_CHECK(!a->infinity); + + rustsecp256k1_v0_1_1_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 + * `rustsecp256k1_v0_1_1_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; + + rustsecp256k1_v0_1_1_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++) { + rustsecp256k1_v0_1_1_fe_normalize_var(&pj.y); + rustsecp256k1_v0_1_1_fe_to_storage(&pre[i].y, &pj.y); + rustsecp256k1_v0_1_1_gej_add_ge_var(&pj, &pj, &d_ge, &zr); + rustsecp256k1_v0_1_1_fe_normalize_var(&zr); + rustsecp256k1_v0_1_1_fe_to_storage(&pre[i].x, &zr); + } + + /* Invert d.z in the same batch, preserving pj.z so we can extract 1/d.z */ + rustsecp256k1_v0_1_1_fe_mul(&zi, &pj.z, &d.z); + rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_ge_set_gej_zinv(&p_ge, &pj, &zi); + rustsecp256k1_v0_1_1_ge_to_storage(&pre[n - 1], &p_ge); + + /* Compute the actual x-coordinate of D, which will be needed below. */ + rustsecp256k1_v0_1_1_fe_mul(&d.z, &zi, &pj.z); /* d.z = 1/d.z */ + rustsecp256k1_v0_1_1_fe_sqr(&dx_over_dz_squared, &d.z); + rustsecp256k1_v0_1_1_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) { + rustsecp256k1_v0_1_1_fe zi2, zi3; + const rustsecp256k1_v0_1_1_fe *rzr; + i--; + + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_fe_mul(&zi, &zi, rzr); + rustsecp256k1_v0_1_1_fe_sqr(&zi2, &zi); + rustsecp256k1_v0_1_1_fe_mul(&zi3, &zi2, &zi); + /* To compute the actual x-coordinate, we use the stored z ratio and + * y-coordinate, which we obtained from `rustsecp256k1_v0_1_1_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 + */ + rustsecp256k1_v0_1_1_fe_mul(&p_ge.x, rzr, &zi2); + rustsecp256k1_v0_1_1_fe_negate(&p_ge.x, &p_ge.x, 1); + rustsecp256k1_v0_1_1_fe_add(&p_ge.x, &dx_over_dz_squared); + /* y is stored_y/z^3, as we expect */ + rustsecp256k1_v0_1_1_fe_mul(&p_ge.y, &p_ge.y, &zi3); + /* Store */ + rustsecp256k1_v0_1_1_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]; \ + rustsecp256k1_v0_1_1_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) { \ + rustsecp256k1_v0_1_1_ge_from_storage((r), &(pre)[((n)-1)/2]); \ + } else { \ + rustsecp256k1_v0_1_1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \ + rustsecp256k1_v0_1_1_fe_negate(&((r)->y), &((r)->y), 1); \ + } \ +} while(0) + +static const size_t SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE = + ROUND_TO_ALIGN(sizeof((*((rustsecp256k1_v0_1_1_ecmult_context*) NULL)->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)) +#ifdef USE_ENDOMORPHISM + + ROUND_TO_ALIGN(sizeof((*((rustsecp256k1_v0_1_1_ecmult_context*) NULL)->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)) +#endif + ; + +static void rustsecp256k1_v0_1_1_ecmult_context_init(rustsecp256k1_v0_1_1_ecmult_context *ctx) { + ctx->pre_g = NULL; +#ifdef USE_ENDOMORPHISM + ctx->pre_g_128 = NULL; +#endif +} + +static void rustsecp256k1_v0_1_1_ecmult_context_build(rustsecp256k1_v0_1_1_ecmult_context *ctx, void **prealloc) { + rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_gej_set_ge(&gj, &rustsecp256k1_v0_1_1_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 = (rustsecp256k1_v0_1_1_ge_storage (*)[])manual_alloc(prealloc, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G), base, prealloc_size); + } + + /* precompute the tables with odd multiples */ + rustsecp256k1_v0_1_1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj); + +#ifdef USE_ENDOMORPHISM + { + rustsecp256k1_v0_1_1_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 = (rustsecp256k1_v0_1_1_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++) { + rustsecp256k1_v0_1_1_gej_double_var(&g_128j, &g_128j, NULL); + } + rustsecp256k1_v0_1_1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j); + } +#endif +} + +static void rustsecp256k1_v0_1_1_ecmult_context_finalize_memcpy(rustsecp256k1_v0_1_1_ecmult_context *dst, const rustsecp256k1_v0_1_1_ecmult_context *src) { + if (src->pre_g != NULL) { + /* We cast to void* first to suppress a -Wcast-align warning. */ + dst->pre_g = (rustsecp256k1_v0_1_1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g) - (unsigned char*)src)); + } +#ifdef USE_ENDOMORPHISM + if (src->pre_g_128 != NULL) { + dst->pre_g_128 = (rustsecp256k1_v0_1_1_ge_storage (*)[])(void*)((unsigned char*)dst + ((unsigned char*)(src->pre_g_128) - (unsigned char*)src)); + } +#endif +} + +static int rustsecp256k1_v0_1_1_ecmult_context_is_built(const rustsecp256k1_v0_1_1_ecmult_context *ctx) { + return ctx->pre_g != NULL; +} + +static void rustsecp256k1_v0_1_1_ecmult_context_clear(rustsecp256k1_v0_1_1_ecmult_context *ctx) { + rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_ecmult_wnaf(int *wnaf, int len, const rustsecp256k1_v0_1_1_scalar *a, int w) { + rustsecp256k1_v0_1_1_scalar s = *a; + int last_set_bit = -1; + int bit = 0; + int sign = 1; + int carry = 0; + + VERIFY_CHECK(wnaf != NULL); + VERIFY_CHECK(0 <= len && len <= 256); + VERIFY_CHECK(a != NULL); + VERIFY_CHECK(2 <= w && w <= 31); + + memset(wnaf, 0, len * sizeof(wnaf[0])); + + if (rustsecp256k1_v0_1_1_scalar_get_bits(&s, 255, 1)) { + rustsecp256k1_v0_1_1_scalar_negate(&s, &s); + sign = -1; + } + + while (bit < len) { + int now; + int word; + if (rustsecp256k1_v0_1_1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { + bit++; + continue; + } + + now = w; + if (now > len - bit) { + now = len - bit; + } + + word = rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_scalar_get_bits(&s, bit++, 1) == 0); + } +#endif + return last_set_bit + 1; +} + +struct rustsecp256k1_v0_1_1_strauss_point_state { +#ifdef USE_ENDOMORPHISM + rustsecp256k1_v0_1_1_scalar na_1, na_lam; + int wnaf_na_1[130]; + int wnaf_na_lam[130]; + int bits_na_1; + int bits_na_lam; +#else + int wnaf_na[256]; + int bits_na; +#endif + size_t input_pos; +}; + +struct rustsecp256k1_v0_1_1_strauss_state { + rustsecp256k1_v0_1_1_gej* prej; + rustsecp256k1_v0_1_1_fe* zr; + rustsecp256k1_v0_1_1_ge* pre_a; +#ifdef USE_ENDOMORPHISM + rustsecp256k1_v0_1_1_ge* pre_a_lam; +#endif + struct rustsecp256k1_v0_1_1_strauss_point_state* ps; +}; + +static void rustsecp256k1_v0_1_1_ecmult_strauss_wnaf(const rustsecp256k1_v0_1_1_ecmult_context *ctx, const struct rustsecp256k1_v0_1_1_strauss_state *state, rustsecp256k1_v0_1_1_gej *r, int num, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_scalar *na, const rustsecp256k1_v0_1_1_scalar *ng) { + rustsecp256k1_v0_1_1_ge tmpa; + rustsecp256k1_v0_1_1_fe Z; +#ifdef USE_ENDOMORPHISM + /* Splitted G factors. */ + rustsecp256k1_v0_1_1_scalar ng_1, ng_128; + int wnaf_ng_1[129]; + int bits_ng_1 = 0; + int wnaf_ng_128[129]; + int bits_ng_128 = 0; +#else + int wnaf_ng[256]; + int bits_ng = 0; +#endif + int i; + int bits = 0; + int np; + int no = 0; + + for (np = 0; np < num; ++np) { + if (rustsecp256k1_v0_1_1_scalar_is_zero(&na[np]) || rustsecp256k1_v0_1_1_gej_is_infinity(&a[np])) { + continue; + } + state->ps[no].input_pos = np; +#ifdef USE_ENDOMORPHISM + /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ + rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_ecmult_wnaf(state->ps[no].wnaf_na_1, 130, &state->ps[no].na_1, WINDOW_A); + state->ps[no].bits_na_lam = rustsecp256k1_v0_1_1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 130, &state->ps[no].na_lam, WINDOW_A); + VERIFY_CHECK(state->ps[no].bits_na_1 <= 130); + VERIFY_CHECK(state->ps[no].bits_na_lam <= 130); + if (state->ps[no].bits_na_1 > bits) { + bits = state->ps[no].bits_na_1; + } + if (state->ps[no].bits_na_lam > bits) { + bits = state->ps[no].bits_na_lam; + } +#else + /* build wnaf representation for na. */ + state->ps[no].bits_na = rustsecp256k1_v0_1_1_ecmult_wnaf(state->ps[no].wnaf_na, 256, &na[np], WINDOW_A); + if (state->ps[no].bits_na > bits) { + bits = state->ps[no].bits_na; + } +#endif + ++no; + } + + /* Calculate odd multiples of a. + * All multiples are brought to the same Z 'denominator', which is stored + * in Z. Due to secp256k1' isomorphism we can do all operations pretending + * that the Z coordinate was 1, use affine addition formulae, and correct + * the Z coordinate of the result once at the end. + * The exception is the precomputed G table points, which are actually + * affine. Compared to the base used for other points, they have a Z ratio + * of 1/Z, so we can use rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_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) { + rustsecp256k1_v0_1_1_gej tmp = a[state->ps[np].input_pos]; +#ifdef VERIFY + rustsecp256k1_v0_1_1_fe_normalize_var(&(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z)); +#endif + rustsecp256k1_v0_1_1_gej_rescale(&tmp, &(state->prej[(np - 1) * ECMULT_TABLE_SIZE(WINDOW_A) + ECMULT_TABLE_SIZE(WINDOW_A) - 1].z)); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, &Z, state->prej, state->zr); + } else { + rustsecp256k1_v0_1_1_fe_set_int(&Z, 1); + } + +#ifdef USE_ENDOMORPHISM + for (np = 0; np < no; ++np) { + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + rustsecp256k1_v0_1_1_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) */ + rustsecp256k1_v0_1_1_scalar_split_128(&ng_1, &ng_128, ng); + + /* Build wnaf representation for ng_1 and ng_128 */ + bits_ng_1 = rustsecp256k1_v0_1_1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); + bits_ng_128 = rustsecp256k1_v0_1_1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); + if (bits_ng_1 > bits) { + bits = bits_ng_1; + } + if (bits_ng_128 > bits) { + bits = bits_ng_128; + } + } +#else + if (ng) { + bits_ng = rustsecp256k1_v0_1_1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); + if (bits_ng > bits) { + bits = bits_ng; + } + } +#endif + + rustsecp256k1_v0_1_1_gej_set_infinity(r); + + for (i = bits - 1; i >= 0; i--) { + int n; + rustsecp256k1_v0_1_1_gej_double_var(r, r, NULL); +#ifdef USE_ENDOMORPHISM + 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); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_gej_add_zinv_var(r, r, &tmpa, &Z); + } +#else + for (np = 0; np < no; ++np) { + if (i < state->ps[np].bits_na && (n = state->ps[np].wnaf_na[i])) { + ECMULT_TABLE_GET_GE(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); + rustsecp256k1_v0_1_1_gej_add_ge_var(r, r, &tmpa, NULL); + } + } + if (i < bits_ng && (n = wnaf_ng[i])) { + ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); + rustsecp256k1_v0_1_1_gej_add_zinv_var(r, r, &tmpa, &Z); + } +#endif + } + + if (!r->infinity) { + rustsecp256k1_v0_1_1_fe_mul(&r->z, &r->z, &Z); + } +} + +static void rustsecp256k1_v0_1_1_ecmult(const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_scalar *na, const rustsecp256k1_v0_1_1_scalar *ng) { + rustsecp256k1_v0_1_1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; + rustsecp256k1_v0_1_1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; + rustsecp256k1_v0_1_1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + struct rustsecp256k1_v0_1_1_strauss_point_state ps[1]; +#ifdef USE_ENDOMORPHISM + rustsecp256k1_v0_1_1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; +#endif + struct rustsecp256k1_v0_1_1_strauss_state state; + + state.prej = prej; + state.zr = zr; + state.pre_a = pre_a; +#ifdef USE_ENDOMORPHISM + state.pre_a_lam = pre_a_lam; +#endif + state.ps = ps; + rustsecp256k1_v0_1_1_ecmult_strauss_wnaf(ctx, &state, r, 1, a, na, ng); +} + +static size_t rustsecp256k1_v0_1_1_strauss_scratch_size(size_t n_points) { +#ifdef USE_ENDOMORPHISM + static const size_t point_size = (2 * sizeof(rustsecp256k1_v0_1_1_ge) + sizeof(rustsecp256k1_v0_1_1_gej) + sizeof(rustsecp256k1_v0_1_1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct rustsecp256k1_v0_1_1_strauss_point_state) + sizeof(rustsecp256k1_v0_1_1_gej) + sizeof(rustsecp256k1_v0_1_1_scalar); +#else + static const size_t point_size = (sizeof(rustsecp256k1_v0_1_1_ge) + sizeof(rustsecp256k1_v0_1_1_gej) + sizeof(rustsecp256k1_v0_1_1_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct rustsecp256k1_v0_1_1_strauss_point_state) + sizeof(rustsecp256k1_v0_1_1_gej) + sizeof(rustsecp256k1_v0_1_1_scalar); +#endif + return n_points*point_size; +} + +static int rustsecp256k1_v0_1_1_ecmult_strauss_batch(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_scratch *scratch, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *inp_g_sc, rustsecp256k1_v0_1_1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { + rustsecp256k1_v0_1_1_gej* points; + rustsecp256k1_v0_1_1_scalar* scalars; + struct rustsecp256k1_v0_1_1_strauss_state state; + size_t i; + const size_t scratch_checkpoint = rustsecp256k1_v0_1_1_scratch_checkpoint(error_callback, scratch); + + rustsecp256k1_v0_1_1_gej_set_infinity(r); + if (inp_g_sc == NULL && n_points == 0) { + return 1; + } + + points = (rustsecp256k1_v0_1_1_gej*)rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, n_points * sizeof(rustsecp256k1_v0_1_1_gej)); + scalars = (rustsecp256k1_v0_1_1_scalar*)rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, n_points * sizeof(rustsecp256k1_v0_1_1_scalar)); + state.prej = (rustsecp256k1_v0_1_1_gej*)rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(rustsecp256k1_v0_1_1_gej)); + state.zr = (rustsecp256k1_v0_1_1_fe*)rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(rustsecp256k1_v0_1_1_fe)); +#ifdef USE_ENDOMORPHISM + state.pre_a = (rustsecp256k1_v0_1_1_ge*)rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, n_points * 2 * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(rustsecp256k1_v0_1_1_ge)); + state.pre_a_lam = state.pre_a + n_points * ECMULT_TABLE_SIZE(WINDOW_A); +#else + state.pre_a = (rustsecp256k1_v0_1_1_ge*)rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(rustsecp256k1_v0_1_1_ge)); +#endif + state.ps = (struct rustsecp256k1_v0_1_1_strauss_point_state*)rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, n_points * sizeof(struct rustsecp256k1_v0_1_1_strauss_point_state)); + + if (points == NULL || scalars == NULL || state.prej == NULL || state.zr == NULL || state.pre_a == NULL) { + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + return 0; + } + + for (i = 0; i < n_points; i++) { + rustsecp256k1_v0_1_1_ge point; + if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) { + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + return 0; + } + rustsecp256k1_v0_1_1_gej_set_ge(&points[i], &point); + } + rustsecp256k1_v0_1_1_ecmult_strauss_wnaf(ctx, &state, r, n_points, points, scalars, inp_g_sc); + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + return 1; +} + +/* Wrapper for rustsecp256k1_v0_1_1_ecmult_multi_func interface */ +static int rustsecp256k1_v0_1_1_ecmult_strauss_batch_single(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_ecmult_context *actx, rustsecp256k1_v0_1_1_scratch *scratch, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *inp_g_sc, rustsecp256k1_v0_1_1_ecmult_multi_callback cb, void *cbdata, size_t n) { + return rustsecp256k1_v0_1_1_ecmult_strauss_batch(error_callback, actx, scratch, r, inp_g_sc, cb, cbdata, n, 0); +} + +static size_t rustsecp256k1_v0_1_1_strauss_max_points(const rustsecp256k1_v0_1_1_callback* error_callback, rustsecp256k1_v0_1_1_scratch *scratch) { + return rustsecp256k1_v0_1_1_scratch_max_allocation(error_callback, scratch, STRAUSS_SCRATCH_OBJECTS) / rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_wnaf_fixed(int *wnaf, const rustsecp256k1_v0_1_1_scalar *s, int w) { + int skew = 0; + int pos; + int max_pos; + int last_w; + const rustsecp256k1_v0_1_1_scalar *work = s; + + if (rustsecp256k1_v0_1_1_scalar_is_zero(s)) { + for (pos = 0; pos < WNAF_SIZE(w); pos++) { + wnaf[pos] = 0; + } + return 0; + } + + if (rustsecp256k1_v0_1_1_scalar_is_even(s)) { + skew = 1; + } + + wnaf[0] = rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_pippenger_point_state { + int skew_na; + size_t input_pos; +}; + +struct rustsecp256k1_v0_1_1_pippenger_state { + int *wnaf_na; + struct rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_ecmult_pippenger_wnaf(rustsecp256k1_v0_1_1_gej *buckets, int bucket_window, struct rustsecp256k1_v0_1_1_pippenger_state *state, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *sc, const rustsecp256k1_v0_1_1_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 (rustsecp256k1_v0_1_1_scalar_is_zero(&sc[np]) || rustsecp256k1_v0_1_1_ge_is_infinity(&pt[np])) { + continue; + } + state->ps[no].input_pos = np; + state->ps[no].skew_na = rustsecp256k1_v0_1_1_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1); + no++; + } + rustsecp256k1_v0_1_1_gej_set_infinity(r); + + if (no == 0) { + return 1; + } + + for (i = n_wnaf - 1; i >= 0; i--) { + rustsecp256k1_v0_1_1_gej running_sum; + + for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) { + rustsecp256k1_v0_1_1_gej_set_infinity(&buckets[j]); + } + + for (np = 0; np < no; ++np) { + int n = state->wnaf_na[np*n_wnaf + i]; + struct rustsecp256k1_v0_1_1_pippenger_point_state point_state = state->ps[np]; + rustsecp256k1_v0_1_1_ge tmp; + int idx; + + if (i == 0) { + /* correct for wnaf skew */ + int skew = point_state.skew_na; + if (skew) { + rustsecp256k1_v0_1_1_ge_neg(&tmp, &pt[point_state.input_pos]); + rustsecp256k1_v0_1_1_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL); + } + } + if (n > 0) { + idx = (n - 1)/2; + rustsecp256k1_v0_1_1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); + } else if (n < 0) { + idx = -(n + 1)/2; + rustsecp256k1_v0_1_1_ge_neg(&tmp, &pt[point_state.input_pos]); + rustsecp256k1_v0_1_1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); + } + } + + for(j = 0; j < bucket_window; j++) { + rustsecp256k1_v0_1_1_gej_double_var(r, r, NULL); + } + + rustsecp256k1_v0_1_1_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--) { + rustsecp256k1_v0_1_1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); + rustsecp256k1_v0_1_1_gej_add_var(r, r, &running_sum, NULL); + } + + rustsecp256k1_v0_1_1_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL); + rustsecp256k1_v0_1_1_gej_double_var(r, r, NULL); + rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_pippenger_bucket_window(size_t n) { +#ifdef USE_ENDOMORPHISM + if (n <= 1) { + return 1; + } else if (n <= 4) { + return 2; + } else if (n <= 20) { + return 3; + } else if (n <= 57) { + return 4; + } else if (n <= 136) { + return 5; + } else if (n <= 235) { + return 6; + } else if (n <= 1260) { + return 7; + } else if (n <= 4420) { + return 9; + } else if (n <= 7880) { + return 10; + } else if (n <= 16050) { + return 11; + } else { + return PIPPENGER_MAX_BUCKET_WINDOW; + } +#else + if (n <= 1) { + return 1; + } else if (n <= 11) { + return 2; + } else if (n <= 45) { + return 3; + } else if (n <= 100) { + return 4; + } else if (n <= 275) { + return 5; + } else if (n <= 625) { + return 6; + } else if (n <= 1850) { + return 7; + } else if (n <= 3400) { + return 8; + } else if (n <= 9630) { + return 9; + } else if (n <= 17900) { + return 10; + } else if (n <= 32800) { + return 11; + } else { + return PIPPENGER_MAX_BUCKET_WINDOW; + } +#endif +} + +/** + * Returns the maximum optimal number of points for a bucket_window. + */ +static size_t rustsecp256k1_v0_1_1_pippenger_bucket_window_inv(int bucket_window) { + switch(bucket_window) { +#ifdef USE_ENDOMORPHISM + case 1: return 1; + case 2: return 4; + case 3: return 20; + case 4: return 57; + case 5: return 136; + case 6: return 235; + case 7: return 1260; + case 8: return 1260; + case 9: return 4420; + case 10: return 7880; + case 11: return 16050; + case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX; +#else + case 1: return 1; + case 2: return 11; + case 3: return 45; + case 4: return 100; + case 5: return 275; + case 6: return 625; + case 7: return 1850; + case 8: return 3400; + case 9: return 9630; + case 10: return 17900; + case 11: return 32800; + case PIPPENGER_MAX_BUCKET_WINDOW: return SIZE_MAX; +#endif + } + return 0; +} + + +#ifdef USE_ENDOMORPHISM +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_ecmult_endo_split(rustsecp256k1_v0_1_1_scalar *s1, rustsecp256k1_v0_1_1_scalar *s2, rustsecp256k1_v0_1_1_ge *p1, rustsecp256k1_v0_1_1_ge *p2) { + rustsecp256k1_v0_1_1_scalar tmp = *s1; + rustsecp256k1_v0_1_1_scalar_split_lambda(s1, s2, &tmp); + rustsecp256k1_v0_1_1_ge_mul_lambda(p2, p1); + + if (rustsecp256k1_v0_1_1_scalar_is_high(s1)) { + rustsecp256k1_v0_1_1_scalar_negate(s1, s1); + rustsecp256k1_v0_1_1_ge_neg(p1, p1); + } + if (rustsecp256k1_v0_1_1_scalar_is_high(s2)) { + rustsecp256k1_v0_1_1_scalar_negate(s2, s2); + rustsecp256k1_v0_1_1_ge_neg(p2, p2); + } +} +#endif + +/** + * Returns the scratch size required for a given number of points (excluding + * base point G) without considering alignment. + */ +static size_t rustsecp256k1_v0_1_1_pippenger_scratch_size(size_t n_points, int bucket_window) { +#ifdef USE_ENDOMORPHISM + size_t entries = 2*n_points + 2; +#else + size_t entries = n_points + 1; +#endif + size_t entry_size = sizeof(rustsecp256k1_v0_1_1_ge) + sizeof(rustsecp256k1_v0_1_1_scalar) + sizeof(struct rustsecp256k1_v0_1_1_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); + return (sizeof(rustsecp256k1_v0_1_1_gej) << bucket_window) + sizeof(struct rustsecp256k1_v0_1_1_pippenger_state) + entries * entry_size; +} + +static int rustsecp256k1_v0_1_1_ecmult_pippenger_batch(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_scratch *scratch, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *inp_g_sc, rustsecp256k1_v0_1_1_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { + const size_t scratch_checkpoint = rustsecp256k1_v0_1_1_scratch_checkpoint(error_callback, scratch); + /* Use 2(n+1) with the endomorphism, n+1 without, when calculating batch + * sizes. The reason for +1 is that we add the G scalar to the list of + * other scalars. */ +#ifdef USE_ENDOMORPHISM + size_t entries = 2*n_points + 2; +#else + size_t entries = n_points + 1; +#endif + rustsecp256k1_v0_1_1_ge *points; + rustsecp256k1_v0_1_1_scalar *scalars; + rustsecp256k1_v0_1_1_gej *buckets; + struct rustsecp256k1_v0_1_1_pippenger_state *state_space; + size_t idx = 0; + size_t point_idx = 0; + int i, j; + int bucket_window; + + (void)ctx; + rustsecp256k1_v0_1_1_gej_set_infinity(r); + if (inp_g_sc == NULL && n_points == 0) { + return 1; + } + + bucket_window = rustsecp256k1_v0_1_1_pippenger_bucket_window(n_points); + points = (rustsecp256k1_v0_1_1_ge *) rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, entries * sizeof(*points)); + scalars = (rustsecp256k1_v0_1_1_scalar *) rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, entries * sizeof(*scalars)); + state_space = (struct rustsecp256k1_v0_1_1_pippenger_state *) rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, sizeof(*state_space)); + if (points == NULL || scalars == NULL || state_space == NULL) { + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + return 0; + } + + state_space->ps = (struct rustsecp256k1_v0_1_1_pippenger_point_state *) rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps)); + state_space->wnaf_na = (int *) rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int)); + buckets = (rustsecp256k1_v0_1_1_gej *) rustsecp256k1_v0_1_1_scratch_alloc(error_callback, scratch, (1<ps == NULL || state_space->wnaf_na == NULL || buckets == NULL) { + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + return 0; + } + + if (inp_g_sc != NULL) { + scalars[0] = *inp_g_sc; + points[0] = rustsecp256k1_v0_1_1_ge_const_g; + idx++; +#ifdef USE_ENDOMORPHISM + rustsecp256k1_v0_1_1_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]); + idx++; +#endif + } + + while (point_idx < n_points) { + if (!cb(&scalars[idx], &points[idx], point_idx + cb_offset, cbdata)) { + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + return 0; + } + idx++; +#ifdef USE_ENDOMORPHISM + rustsecp256k1_v0_1_1_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]); + idx++; +#endif + point_idx++; + } + + rustsecp256k1_v0_1_1_ecmult_pippenger_wnaf(buckets, bucket_window, state_space, r, scalars, points, idx); + + /* Clear data */ + for(i = 0; (size_t)i < idx; i++) { + rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_ecmult_multi_simple_var(const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *inp_g_sc, rustsecp256k1_v0_1_1_ecmult_multi_callback cb, void *cbdata, size_t n_points) { + size_t point_idx; + rustsecp256k1_v0_1_1_scalar szero; + rustsecp256k1_v0_1_1_gej tmpj; + + rustsecp256k1_v0_1_1_scalar_set_int(&szero, 0); + rustsecp256k1_v0_1_1_gej_set_infinity(r); + rustsecp256k1_v0_1_1_gej_set_infinity(&tmpj); + /* r = inp_g_sc*G */ + rustsecp256k1_v0_1_1_ecmult(ctx, r, &tmpj, &szero, inp_g_sc); + for (point_idx = 0; point_idx < n_points; point_idx++) { + rustsecp256k1_v0_1_1_ge point; + rustsecp256k1_v0_1_1_gej pointj; + rustsecp256k1_v0_1_1_scalar scalar; + if (!cb(&scalar, &point, point_idx, cbdata)) { + return 0; + } + /* r += scalar*point */ + rustsecp256k1_v0_1_1_gej_set_ge(&pointj, &point); + rustsecp256k1_v0_1_1_ecmult(ctx, &tmpj, &pointj, &scalar, NULL); + rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_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 (*rustsecp256k1_v0_1_1_ecmult_multi_func)(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_ecmult_context*, rustsecp256k1_v0_1_1_scratch*, rustsecp256k1_v0_1_1_gej*, const rustsecp256k1_v0_1_1_scalar*, rustsecp256k1_v0_1_1_ecmult_multi_callback cb, void*, size_t); +static int rustsecp256k1_v0_1_1_ecmult_multi_var(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_ecmult_context *ctx, rustsecp256k1_v0_1_1_scratch *scratch, rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_scalar *inp_g_sc, rustsecp256k1_v0_1_1_ecmult_multi_callback cb, void *cbdata, size_t n) { + size_t i; + + int (*f)(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_ecmult_context*, rustsecp256k1_v0_1_1_scratch*, rustsecp256k1_v0_1_1_gej*, const rustsecp256k1_v0_1_1_scalar*, rustsecp256k1_v0_1_1_ecmult_multi_callback cb, void*, size_t, size_t); + size_t n_batches; + size_t n_batch_points; + + rustsecp256k1_v0_1_1_gej_set_infinity(r); + if (inp_g_sc == NULL && n == 0) { + return 1; + } else if (n == 0) { + rustsecp256k1_v0_1_1_scalar szero; + rustsecp256k1_v0_1_1_scalar_set_int(&szero, 0); + rustsecp256k1_v0_1_1_ecmult(ctx, r, r, &szero, inp_g_sc); + return 1; + } + if (scratch == NULL) { + return rustsecp256k1_v0_1_1_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 (!rustsecp256k1_v0_1_1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, rustsecp256k1_v0_1_1_pippenger_max_points(error_callback, scratch), n)) { + return rustsecp256k1_v0_1_1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n); + } + if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) { + f = rustsecp256k1_v0_1_1_ecmult_pippenger_batch; + } else { + if (!rustsecp256k1_v0_1_1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, rustsecp256k1_v0_1_1_strauss_max_points(error_callback, scratch), n)) { + return rustsecp256k1_v0_1_1_ecmult_multi_simple_var(ctx, r, inp_g_sc, cb, cbdata, n); + } + f = rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_gej tmp; + if (!f(error_callback, ctx, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) { + return 0; + } + rustsecp256k1_v0_1_1_gej_add_var(r, r, &tmp, NULL); + n -= nbp; + } + return 1; +} + +#endif /* SECP256K1_ECMULT_IMPL_H */ diff --git a/depend/secp256k1/src/field.h b/secp256k1-sys/depend/secp256k1/src/field.h similarity index 55% rename from depend/secp256k1/src/field.h rename to secp256k1-sys/depend/secp256k1/src/field.h index 2d52af5e3..96513fc37 100644 --- a/depend/secp256k1/src/field.h +++ b/secp256k1-sys/depend/secp256k1/src/field.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_ -#define _SECP256K1_FIELD_ +#ifndef SECP256K1_FIELD_H +#define SECP256K1_FIELD_H /** Field element module. * @@ -30,92 +30,103 @@ #error "Please select field implementation" #endif +#include "util.h" + /** Normalize a field element. */ -static void secp256k1_fe_normalize(secp256k1_fe *r); +static void rustsecp256k1_v0_1_1_fe_normalize(rustsecp256k1_v0_1_1_fe *r); /** Weakly normalize a field element: reduce it magnitude to 1, but don't fully normalize. */ -static void secp256k1_fe_normalize_weak(secp256k1_fe *r); +static void rustsecp256k1_v0_1_1_fe_normalize_weak(rustsecp256k1_v0_1_1_fe *r); /** Normalize a field element, without constant-time guarantee. */ -static void secp256k1_fe_normalize_var(secp256k1_fe *r); +static void rustsecp256k1_v0_1_1_fe_normalize_var(rustsecp256k1_v0_1_1_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); +static int rustsecp256k1_v0_1_1_fe_normalizes_to_zero(rustsecp256k1_v0_1_1_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); +static int rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_set_int(rustsecp256k1_v0_1_1_fe *r, int a); + +/** Sets a field element equal to zero, initializing all fields. */ +static void rustsecp256k1_v0_1_1_fe_clear(rustsecp256k1_v0_1_1_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); +static int rustsecp256k1_v0_1_1_fe_is_zero(const rustsecp256k1_v0_1_1_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); +static int rustsecp256k1_v0_1_1_fe_is_odd(const rustsecp256k1_v0_1_1_fe *a); /** Compare two field elements. Requires magnitude-1 inputs. */ -static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b); +static int rustsecp256k1_v0_1_1_fe_equal(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *b); + +/** Same as rustsecp256k1_v0_1_1_fe_equal, but may be variable time. */ +static int rustsecp256k1_v0_1_1_fe_equal_var(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_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); +static int rustsecp256k1_v0_1_1_fe_cmp_var(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_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); +static int rustsecp256k1_v0_1_1_fe_set_b32(rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_get_b32(unsigned char *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_negate(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_mul_int(rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_add(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_mul(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_sqr(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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_var(secp256k1_fe *r, const secp256k1_fe *a); +static int rustsecp256k1_v0_1_1_fe_sqrt(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a); + +/** Checks whether a field element is a quadratic residue. */ +static int rustsecp256k1_v0_1_1_fe_is_quad_var(const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_inv(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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); +/** Potentially faster version of rustsecp256k1_v0_1_1_fe_inv, without constant-time guarantee. */ +static void rustsecp256k1_v0_1_1_fe_inv_var(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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(size_t len, secp256k1_fe *r, const secp256k1_fe *a); +static void rustsecp256k1_v0_1_1_fe_inv_all_var(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_to_storage(rustsecp256k1_v0_1_1_fe_storage *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_fe_from_storage(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe_storage *a); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag); +static void rustsecp256k1_v0_1_1_fe_storage_cmov(rustsecp256k1_v0_1_1_fe_storage *r, const rustsecp256k1_v0_1_1_fe_storage *a, int flag); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); +static void rustsecp256k1_v0_1_1_fe_cmov(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, int flag); -#endif +#endif /* SECP256K1_FIELD_H */ diff --git a/depend/secp256k1/src/field_10x26.h b/secp256k1-sys/depend/secp256k1/src/field_10x26.h similarity index 87% rename from depend/secp256k1/src/field_10x26.h rename to secp256k1-sys/depend/secp256k1/src/field_10x26.h index 61ee1e096..bdb05166b 100644 --- a/depend/secp256k1/src/field_10x26.h +++ b/secp256k1-sys/depend/secp256k1/src/field_10x26.h @@ -4,19 +4,21 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_REPR_ -#define _SECP256K1_FIELD_REPR_ +#ifndef SECP256K1_FIELD_REPR_H +#define SECP256K1_FIELD_REPR_H #include typedef struct { - /* X = sum(i=0..9, elem[i]*2^26) mod n */ + /* 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; +} rustsecp256k1_v0_1_1_fe; /* Unpacks a constant into a overlapping multi-limbed FE element. */ #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ @@ -40,8 +42,9 @@ typedef struct { typedef struct { uint32_t n[8]; -} secp256k1_fe_storage; +} rustsecp256k1_v0_1_1_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 + +#endif /* SECP256K1_FIELD_REPR_H */ diff --git a/depend/secp256k1/src/field_10x26_impl.h b/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h similarity index 86% rename from depend/secp256k1/src/field_10x26_impl.h rename to secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h index 212cc5396..91839d9c9 100644 --- a/depend/secp256k1/src/field_10x26_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h @@ -4,17 +4,14 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ -#define _SECP256K1_FIELD_REPR_IMPL_H_ +#ifndef SECP256K1_FIELD_REPR_IMPL_H +#define SECP256K1_FIELD_REPR_IMPL_H -#include -#include #include "util.h" -#include "num.h" #include "field.h" #ifdef VERIFY -static void secp256k1_fe_verify(const secp256k1_fe *a) { +static void rustsecp256k1_v0_1_1_fe_verify(const rustsecp256k1_v0_1_1_fe *a) { const uint32_t *d = a->n; int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; r &= (d[0] <= 0x3FFFFFFUL * m); @@ -40,13 +37,9 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } VERIFY_CHECK(r == 1); } -#else -static void secp256k1_fe_verify(const secp256k1_fe *a) { - (void)a; -} #endif -static void secp256k1_fe_normalize(secp256k1_fe *r) { +static void rustsecp256k1_v0_1_1_fe_normalize(rustsecp256k1_v0_1_1_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]; @@ -97,11 +90,11 @@ static void secp256k1_fe_normalize(secp256k1_fe *r) { #ifdef VERIFY r->magnitude = 1; r->normalized = 1; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { +static void rustsecp256k1_v0_1_1_fe_normalize_weak(rustsecp256k1_v0_1_1_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]; @@ -128,11 +121,11 @@ static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { #ifdef VERIFY r->magnitude = 1; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static void secp256k1_fe_normalize_var(secp256k1_fe *r) { +static void rustsecp256k1_v0_1_1_fe_normalize_var(rustsecp256k1_v0_1_1_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]; @@ -184,11 +177,11 @@ static void secp256k1_fe_normalize_var(secp256k1_fe *r) { #ifdef VERIFY r->magnitude = 1; r->normalized = 1; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { +static int rustsecp256k1_v0_1_1_fe_normalizes_to_zero(rustsecp256k1_v0_1_1_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]; @@ -217,7 +210,7 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { return (z0 == 0) | (z1 == 0x3FFFFFFUL); } -static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { +static int rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(rustsecp256k1_v0_1_1_fe *r) { uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; uint32_t z0, z1; uint32_t x; @@ -269,34 +262,34 @@ static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { return (z0 == 0) | (z1 == 0x3FFFFFFUL); } -SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_set_int(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_fe_is_zero(const rustsecp256k1_v0_1_1_fe *a) { const uint32_t *t = a->n; #ifdef VERIFY VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_fe_is_odd(const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif return a->n[0] & 1; } -SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_clear(rustsecp256k1_v0_1_1_fe *a) { int i; #ifdef VERIFY a->magnitude = 0; @@ -307,13 +300,13 @@ SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { } } -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { +static int rustsecp256k1_v0_1_1_fe_cmp_var(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *b) { int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); VERIFY_CHECK(b->normalized); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); + rustsecp256k1_v0_1_1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(b); #endif for (i = 9; i >= 0; i--) { if (a->n[i] > b->n[i]) { @@ -326,52 +319,73 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { return 0; } -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; - } - } +static int rustsecp256k1_v0_1_1_fe_set_b32(rustsecp256k1_v0_1_1_fe *r, const unsigned char *a) { + 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); + if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { return 0; } #ifdef VERIFY r->magnitude = 1; r->normalized = 1; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif return 1; } /** 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) { - int i; +static void rustsecp256k1_v0_1_1_fe_get_b32(unsigned char *r, const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); - } - r[31-i] = c; - } + 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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_negate(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, int m) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= m); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0]; r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1]; @@ -386,11 +400,11 @@ SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k #ifdef VERIFY r->magnitude = m + 1; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_mul_int(rustsecp256k1_v0_1_1_fe *r, int a) { r->n[0] *= a; r->n[1] *= a; r->n[2] *= a; @@ -404,13 +418,13 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { #ifdef VERIFY r->magnitude *= a; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_add(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif r->n[0] += a->n[0]; r->n[1] += a->n[1]; @@ -425,17 +439,25 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f #ifdef VERIFY r->magnitude += a->magnitude; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } +#if defined(USE_EXTERNAL_ASM) + +/* External assembler implementation */ +void rustsecp256k1_v0_1_1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); +void rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_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; @@ -463,7 +485,8 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t VERIFY_BITS(b[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]*b[x-i], i=0..x). + * 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]. */ @@ -764,7 +787,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t /* [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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_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; @@ -1037,38 +1060,39 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t 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) { +static void rustsecp256k1_v0_1_1_fe_mul(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe * SECP256K1_RESTRICT b) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= 8); VERIFY_CHECK(b->magnitude <= 8); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); + rustsecp256k1_v0_1_1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(b); VERIFY_CHECK(r != b); + VERIFY_CHECK(a != b); #endif - secp256k1_fe_mul_inner(r->n, a->n, b->n); + rustsecp256k1_v0_1_1_fe_mul_inner(r->n, a->n, b->n); #ifdef VERIFY r->magnitude = 1; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { +static void rustsecp256k1_v0_1_1_fe_sqr(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= 8); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif - secp256k1_fe_sqr_inner(r->n, a->n); + rustsecp256k1_v0_1_1_fe_sqr_inner(r->n, a->n); #ifdef VERIFY r->magnitude = 1; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_fe_cmov(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, int flag) { uint32_t mask0, mask1; mask0 = flag + ~((uint32_t)0); mask1 = ~mask0; @@ -1090,7 +1114,7 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_ #endif } -static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_fe_storage_cmov(rustsecp256k1_v0_1_1_fe_storage *r, const rustsecp256k1_v0_1_1_fe_storage *a, int flag) { uint32_t mask0, mask1; mask0 = flag + ~((uint32_t)0); mask1 = ~mask0; @@ -1104,7 +1128,7 @@ static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, 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) { +static void rustsecp256k1_v0_1_1_fe_to_storage(rustsecp256k1_v0_1_1_fe_storage *r, const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); #endif @@ -1118,7 +1142,7 @@ static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe 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) { +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_fe_from_storage(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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); @@ -1135,4 +1159,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se #endif } -#endif +#endif /* SECP256K1_FIELD_REPR_IMPL_H */ diff --git a/depend/secp256k1/src/field_5x52.h b/secp256k1-sys/depend/secp256k1/src/field_5x52.h similarity index 86% rename from depend/secp256k1/src/field_5x52.h rename to secp256k1-sys/depend/secp256k1/src/field_5x52.h index 8e69a560d..72438d063 100644 --- a/depend/secp256k1/src/field_5x52.h +++ b/secp256k1-sys/depend/secp256k1/src/field_5x52.h @@ -4,19 +4,21 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_REPR_ -#define _SECP256K1_FIELD_REPR_ +#ifndef SECP256K1_FIELD_REPR_H +#define SECP256K1_FIELD_REPR_H #include typedef struct { - /* X = sum(i=0..4, elem[i]*2^52) mod n */ + /* 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; +} rustsecp256k1_v0_1_1_fe; /* Unpacks a constant into a overlapping multi-limbed FE element. */ #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ @@ -35,7 +37,7 @@ typedef struct { typedef struct { uint64_t n[4]; -} secp256k1_fe_storage; +} rustsecp256k1_v0_1_1_fe_storage; #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ (d0) | (((uint64_t)(d1)) << 32), \ @@ -44,4 +46,4 @@ typedef struct { (d6) | (((uint64_t)(d7)) << 32) \ }} -#endif +#endif /* SECP256K1_FIELD_REPR_H */ diff --git a/depend/secp256k1/src/field_5x52_asm_impl.h b/secp256k1-sys/depend/secp256k1/src/field_5x52_asm_impl.h similarity index 97% rename from depend/secp256k1/src/field_5x52_asm_impl.h rename to secp256k1-sys/depend/secp256k1/src/field_5x52_asm_impl.h index 98cc004bf..e51f0e040 100644 --- a/depend/secp256k1/src/field_5x52_asm_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_5x52_asm_impl.h @@ -11,10 +11,10 @@ * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly */ -#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ -#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { /** * Registers: rdx:rax = multiplication accumulator * r9:r8 = c @@ -284,7 +284,7 @@ __asm__ __volatile__( ); } -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { /** * Registers: rdx:rax = multiplication accumulator * r9:r8 = c @@ -499,4 +499,4 @@ __asm__ __volatile__( ); } -#endif +#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ diff --git a/depend/secp256k1/src/field_5x52_impl.h b/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h similarity index 66% rename from depend/secp256k1/src/field_5x52_impl.h rename to secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h index b31e24ab8..aa55b9b45 100644 --- a/depend/secp256k1/src/field_5x52_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h @@ -4,16 +4,14 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ -#define _SECP256K1_FIELD_REPR_IMPL_H_ +#ifndef SECP256K1_FIELD_REPR_IMPL_H +#define SECP256K1_FIELD_REPR_IMPL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" #endif -#include #include "util.h" -#include "num.h" #include "field.h" #if defined(USE_ASM_X86_64) @@ -31,7 +29,7 @@ */ #ifdef VERIFY -static void secp256k1_fe_verify(const secp256k1_fe *a) { +static void rustsecp256k1_v0_1_1_fe_verify(const rustsecp256k1_v0_1_1_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. */ @@ -50,13 +48,9 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } VERIFY_CHECK(r == 1); } -#else -static void secp256k1_fe_verify(const secp256k1_fe *a) { - (void)a; -} #endif -static void secp256k1_fe_normalize(secp256k1_fe *r) { +static void rustsecp256k1_v0_1_1_fe_normalize(rustsecp256k1_v0_1_1_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 */ @@ -95,11 +89,11 @@ static void secp256k1_fe_normalize(secp256k1_fe *r) { #ifdef VERIFY r->magnitude = 1; r->normalized = 1; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { +static void rustsecp256k1_v0_1_1_fe_normalize_weak(rustsecp256k1_v0_1_1_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 */ @@ -119,11 +113,11 @@ static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { #ifdef VERIFY r->magnitude = 1; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static void secp256k1_fe_normalize_var(secp256k1_fe *r) { +static void rustsecp256k1_v0_1_1_fe_normalize_var(rustsecp256k1_v0_1_1_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 */ @@ -163,11 +157,11 @@ static void secp256k1_fe_normalize_var(secp256k1_fe *r) { #ifdef VERIFY r->magnitude = 1; r->normalized = 1; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { +static int rustsecp256k1_v0_1_1_fe_normalizes_to_zero(rustsecp256k1_v0_1_1_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 */ @@ -190,7 +184,7 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); } -static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { +static int rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(rustsecp256k1_v0_1_1_fe *r) { uint64_t t0, t1, t2, t3, t4; uint64_t z0, z1; uint64_t x; @@ -231,34 +225,34 @@ static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); } -SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_set_int(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_fe_is_zero(const rustsecp256k1_v0_1_1_fe *a) { const uint64_t *t = a->n; #ifdef VERIFY VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_fe_is_odd(const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif return a->n[0] & 1; } -SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_clear(rustsecp256k1_v0_1_1_fe *a) { int i; #ifdef VERIFY a->magnitude = 0; @@ -269,13 +263,13 @@ SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { } } -static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { +static int rustsecp256k1_v0_1_1_fe_cmp_var(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *b) { int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); VERIFY_CHECK(b->normalized); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); + rustsecp256k1_v0_1_1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(b); #endif for (i = 4; i >= 0; i--) { if (a->n[i] > b->n[i]) { @@ -288,51 +282,96 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { return 0; } -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; - } - } +static int rustsecp256k1_v0_1_1_fe_set_b32(rustsecp256k1_v0_1_1_fe *r, const unsigned char *a) { + 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); if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { return 0; } #ifdef VERIFY r->magnitude = 1; r->normalized = 1; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif return 1; } /** 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) { - int i; +static void rustsecp256k1_v0_1_1_fe_get_b32(unsigned char *r, const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); - } - r[31-i] = c; - } + 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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_negate(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, int m) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= m); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; @@ -342,11 +381,11 @@ SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k #ifdef VERIFY r->magnitude = m + 1; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_mul_int(rustsecp256k1_v0_1_1_fe *r, int a) { r->n[0] *= a; r->n[1] *= a; r->n[2] *= a; @@ -355,13 +394,13 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { #ifdef VERIFY r->magnitude *= a; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_fe_add(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif r->n[0] += a->n[0]; r->n[1] += a->n[1]; @@ -371,40 +410,41 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f #ifdef VERIFY r->magnitude += a->magnitude; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { +static void rustsecp256k1_v0_1_1_fe_mul(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe * SECP256K1_RESTRICT b) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= 8); VERIFY_CHECK(b->magnitude <= 8); - secp256k1_fe_verify(a); - secp256k1_fe_verify(b); + rustsecp256k1_v0_1_1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(b); VERIFY_CHECK(r != b); + VERIFY_CHECK(a != b); #endif - secp256k1_fe_mul_inner(r->n, a->n, b->n); + rustsecp256k1_v0_1_1_fe_mul_inner(r->n, a->n, b->n); #ifdef VERIFY r->magnitude = 1; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { +static void rustsecp256k1_v0_1_1_fe_sqr(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->magnitude <= 8); - secp256k1_fe_verify(a); + rustsecp256k1_v0_1_1_fe_verify(a); #endif - secp256k1_fe_sqr_inner(r->n, a->n); + rustsecp256k1_v0_1_1_fe_sqr_inner(r->n, a->n); #ifdef VERIFY r->magnitude = 1; r->normalized = 0; - secp256k1_fe_verify(r); + rustsecp256k1_v0_1_1_fe_verify(r); #endif } -static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_fe_cmov(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, int flag) { uint64_t mask0, mask1; mask0 = flag + ~((uint64_t)0); mask1 = ~mask0; @@ -421,7 +461,7 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_ #endif } -static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_fe_storage_cmov(rustsecp256k1_v0_1_1_fe_storage *r, const rustsecp256k1_v0_1_1_fe_storage *a, int flag) { uint64_t mask0, mask1; mask0 = flag + ~((uint64_t)0); mask1 = ~mask0; @@ -431,7 +471,7 @@ static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, 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) { +static void rustsecp256k1_v0_1_1_fe_to_storage(rustsecp256k1_v0_1_1_fe_storage *r, const rustsecp256k1_v0_1_1_fe *a) { #ifdef VERIFY VERIFY_CHECK(a->normalized); #endif @@ -441,7 +481,7 @@ static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe 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) { +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_fe_from_storage(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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); @@ -453,4 +493,4 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se #endif } -#endif +#endif /* SECP256K1_FIELD_REPR_IMPL_H */ diff --git a/depend/secp256k1/src/field_5x52_int128_impl.h b/secp256k1-sys/depend/secp256k1/src/field_5x52_int128_impl.h similarity index 93% rename from depend/secp256k1/src/field_5x52_int128_impl.h rename to secp256k1-sys/depend/secp256k1/src/field_5x52_int128_impl.h index 9280bb5ea..400357cca 100644 --- a/depend/secp256k1/src/field_5x52_int128_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_5x52_int128_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ -#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H +#define SECP256K1_FIELD_INNER5X52_IMPL_H #include @@ -15,7 +15,7 @@ #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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_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]; @@ -32,9 +32,11 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t 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. - * px is a shorthand for sum(a[i]*b[x-i], i=0..x). + * 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]. */ @@ -137,7 +139,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t 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;; + 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; @@ -152,7 +154,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t /* [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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_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; @@ -259,7 +261,7 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t 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;; + 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; @@ -274,4 +276,4 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } -#endif +#endif /* SECP256K1_FIELD_INNER5X52_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/field_impl.h b/secp256k1-sys/depend/secp256k1/src/field_impl.h new file mode 100644 index 000000000..e9e8f845f --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/field_impl.h @@ -0,0 +1,318 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_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(USE_FIELD_10X26) +#include "field_10x26_impl.h" +#elif defined(USE_FIELD_5X52) +#include "field_5x52_impl.h" +#else +#error "Please select field implementation" +#endif + +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_fe_equal(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *b) { + rustsecp256k1_v0_1_1_fe na; + rustsecp256k1_v0_1_1_fe_negate(&na, a, 1); + rustsecp256k1_v0_1_1_fe_add(&na, b); + return rustsecp256k1_v0_1_1_fe_normalizes_to_zero(&na); +} + +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_fe_equal_var(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *b) { + rustsecp256k1_v0_1_1_fe na; + rustsecp256k1_v0_1_1_fe_negate(&na, a, 1); + rustsecp256k1_v0_1_1_fe_add(&na, b); + return rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(&na); +} + +static int rustsecp256k1_v0_1_1_fe_sqrt(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_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)). + */ + rustsecp256k1_v0_1_1_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] + */ + + rustsecp256k1_v0_1_1_fe_sqr(&x2, a); + rustsecp256k1_v0_1_1_fe_mul(&x2, &x2, a); + + rustsecp256k1_v0_1_1_fe_sqr(&x3, &x2); + rustsecp256k1_v0_1_1_fe_mul(&x3, &x3, a); + + x6 = x3; + for (j=0; j<3; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x6, &x6); + } + rustsecp256k1_v0_1_1_fe_mul(&x6, &x6, &x3); + + x9 = x6; + for (j=0; j<3; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x9, &x9); + } + rustsecp256k1_v0_1_1_fe_mul(&x9, &x9, &x3); + + x11 = x9; + for (j=0; j<2; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x11, &x11); + } + rustsecp256k1_v0_1_1_fe_mul(&x11, &x11, &x2); + + x22 = x11; + for (j=0; j<11; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x22, &x22); + } + rustsecp256k1_v0_1_1_fe_mul(&x22, &x22, &x11); + + x44 = x22; + for (j=0; j<22; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x44, &x44); + } + rustsecp256k1_v0_1_1_fe_mul(&x44, &x44, &x22); + + x88 = x44; + for (j=0; j<44; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x88, &x88); + } + rustsecp256k1_v0_1_1_fe_mul(&x88, &x88, &x44); + + x176 = x88; + for (j=0; j<88; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x176, &x176); + } + rustsecp256k1_v0_1_1_fe_mul(&x176, &x176, &x88); + + x220 = x176; + for (j=0; j<44; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x220, &x220); + } + rustsecp256k1_v0_1_1_fe_mul(&x220, &x220, &x44); + + x223 = x220; + for (j=0; j<3; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x223, &x223); + } + rustsecp256k1_v0_1_1_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++) { + rustsecp256k1_v0_1_1_fe_sqr(&t1, &t1); + } + rustsecp256k1_v0_1_1_fe_mul(&t1, &t1, &x22); + for (j=0; j<6; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&t1, &t1); + } + rustsecp256k1_v0_1_1_fe_mul(&t1, &t1, &x2); + rustsecp256k1_v0_1_1_fe_sqr(&t1, &t1); + rustsecp256k1_v0_1_1_fe_sqr(r, &t1); + + /* Check that a square root was actually calculated */ + + rustsecp256k1_v0_1_1_fe_sqr(&t1, r); + return rustsecp256k1_v0_1_1_fe_equal(&t1, a); +} + +static void rustsecp256k1_v0_1_1_fe_inv(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a) { + rustsecp256k1_v0_1_1_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] + */ + + rustsecp256k1_v0_1_1_fe_sqr(&x2, a); + rustsecp256k1_v0_1_1_fe_mul(&x2, &x2, a); + + rustsecp256k1_v0_1_1_fe_sqr(&x3, &x2); + rustsecp256k1_v0_1_1_fe_mul(&x3, &x3, a); + + x6 = x3; + for (j=0; j<3; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x6, &x6); + } + rustsecp256k1_v0_1_1_fe_mul(&x6, &x6, &x3); + + x9 = x6; + for (j=0; j<3; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x9, &x9); + } + rustsecp256k1_v0_1_1_fe_mul(&x9, &x9, &x3); + + x11 = x9; + for (j=0; j<2; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x11, &x11); + } + rustsecp256k1_v0_1_1_fe_mul(&x11, &x11, &x2); + + x22 = x11; + for (j=0; j<11; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x22, &x22); + } + rustsecp256k1_v0_1_1_fe_mul(&x22, &x22, &x11); + + x44 = x22; + for (j=0; j<22; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x44, &x44); + } + rustsecp256k1_v0_1_1_fe_mul(&x44, &x44, &x22); + + x88 = x44; + for (j=0; j<44; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x88, &x88); + } + rustsecp256k1_v0_1_1_fe_mul(&x88, &x88, &x44); + + x176 = x88; + for (j=0; j<88; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x176, &x176); + } + rustsecp256k1_v0_1_1_fe_mul(&x176, &x176, &x88); + + x220 = x176; + for (j=0; j<44; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x220, &x220); + } + rustsecp256k1_v0_1_1_fe_mul(&x220, &x220, &x44); + + x223 = x220; + for (j=0; j<3; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&x223, &x223); + } + rustsecp256k1_v0_1_1_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++) { + rustsecp256k1_v0_1_1_fe_sqr(&t1, &t1); + } + rustsecp256k1_v0_1_1_fe_mul(&t1, &t1, &x22); + for (j=0; j<5; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&t1, &t1); + } + rustsecp256k1_v0_1_1_fe_mul(&t1, &t1, a); + for (j=0; j<3; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&t1, &t1); + } + rustsecp256k1_v0_1_1_fe_mul(&t1, &t1, &x2); + for (j=0; j<2; j++) { + rustsecp256k1_v0_1_1_fe_sqr(&t1, &t1); + } + rustsecp256k1_v0_1_1_fe_mul(r, a, &t1); +} + +static void rustsecp256k1_v0_1_1_fe_inv_var(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a) { +#if defined(USE_FIELD_INV_BUILTIN) + rustsecp256k1_v0_1_1_fe_inv(r, a); +#elif defined(USE_FIELD_INV_NUM) + rustsecp256k1_v0_1_1_num n, m; + static const rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_fe c = *a; + rustsecp256k1_v0_1_1_fe_normalize_var(&c); + rustsecp256k1_v0_1_1_fe_get_b32(b, &c); + rustsecp256k1_v0_1_1_num_set_bin(&n, b, 32); + rustsecp256k1_v0_1_1_num_set_bin(&m, prime, 32); + rustsecp256k1_v0_1_1_num_mod_inverse(&n, &n, &m); + rustsecp256k1_v0_1_1_num_get_bin(b, 32, &n); + res = rustsecp256k1_v0_1_1_fe_set_b32(r, b); + (void)res; + VERIFY_CHECK(res); + /* Verify the result is the (unique) valid inverse using non-GMP code. */ + rustsecp256k1_v0_1_1_fe_mul(&c, &c, r); + rustsecp256k1_v0_1_1_fe_add(&c, &negone); + CHECK(rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(&c)); +#else +#error "Please select field inverse implementation" +#endif +} + +static void rustsecp256k1_v0_1_1_fe_inv_all_var(rustsecp256k1_v0_1_1_fe *r, const rustsecp256k1_v0_1_1_fe *a, size_t len) { + rustsecp256k1_v0_1_1_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) { + rustsecp256k1_v0_1_1_fe_mul(&r[i], &r[i - 1], &a[i]); + } + + rustsecp256k1_v0_1_1_fe_inv_var(&u, &r[--i]); + + while (i > 0) { + size_t j = i--; + rustsecp256k1_v0_1_1_fe_mul(&r[j], &r[i], &u); + rustsecp256k1_v0_1_1_fe_mul(&u, &u, &a[j]); + } + + r[0] = u; +} + +static int rustsecp256k1_v0_1_1_fe_is_quad_var(const rustsecp256k1_v0_1_1_fe *a) { +#ifndef USE_NUM_NONE + unsigned char b[32]; + rustsecp256k1_v0_1_1_num n; + rustsecp256k1_v0_1_1_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 + }; + + rustsecp256k1_v0_1_1_fe c = *a; + rustsecp256k1_v0_1_1_fe_normalize_var(&c); + rustsecp256k1_v0_1_1_fe_get_b32(b, &c); + rustsecp256k1_v0_1_1_num_set_bin(&n, b, 32); + rustsecp256k1_v0_1_1_num_set_bin(&m, prime, 32); + return rustsecp256k1_v0_1_1_num_jacobi(&n, &m) >= 0; +#else + rustsecp256k1_v0_1_1_fe r; + return rustsecp256k1_v0_1_1_fe_sqrt(&r, a); +#endif +} + +#endif /* SECP256K1_FIELD_IMPL_H */ diff --git a/depend/secp256k1/src/gen_context.c b/secp256k1-sys/depend/secp256k1/src/gen_context.c similarity index 74% rename from depend/secp256k1/src/gen_context.c rename to secp256k1-sys/depend/secp256k1/src/gen_context.c index 1835fd491..8e4f10286 100644 --- a/depend/secp256k1/src/gen_context.c +++ b/secp256k1-sys/depend/secp256k1/src/gen_context.c @@ -8,6 +8,7 @@ #include "basic-config.h" #include "include/secp256k1.h" +#include "util.h" #include "field_impl.h" #include "scalar_impl.h" #include "group_impl.h" @@ -19,13 +20,14 @@ static void default_error_callback_fn(const char* str, void* data) { abort(); } -static const secp256k1_callback default_error_callback = { +static const rustsecp256k1_v0_1_1_callback default_error_callback = { default_error_callback_fn, NULL }; int main(int argc, char **argv) { - secp256k1_ecmult_gen_context ctx; + rustsecp256k1_v0_1_1_ecmult_gen_context ctx; + void *prealloc, *base; int inner; int outer; FILE* fp; @@ -38,15 +40,17 @@ int main(int argc, char **argv) { 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 \"group.h\"\n"); + fprintf(fp, "#include \"src/group.h\"\n"); fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); - fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n"); + fprintf(fp, "static const rustsecp256k1_v0_1_1_ge_storage rustsecp256k1_v0_1_1_ecmult_static_context[64][16] = {\n"); - secp256k1_ecmult_gen_context_init(&ctx); - secp256k1_ecmult_gen_context_build(&ctx, &default_error_callback); + base = checked_malloc(&default_error_callback, SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE); + prealloc = base; + rustsecp256k1_v0_1_1_ecmult_gen_context_init(&ctx); + rustsecp256k1_v0_1_1_ecmult_gen_context_build(&ctx, &prealloc); for(outer = 0; outer != 64; outer++) { fprintf(fp,"{\n"); for(inner = 0; inner != 16; inner++) { @@ -64,11 +68,12 @@ int main(int argc, char **argv) { } } fprintf(fp,"};\n"); - secp256k1_ecmult_gen_context_clear(&ctx); - + rustsecp256k1_v0_1_1_ecmult_gen_context_clear(&ctx); + free(base); + fprintf(fp, "#undef SC\n"); fprintf(fp, "#endif\n"); fclose(fp); - + return 0; } diff --git a/depend/secp256k1/src/group.h b/secp256k1-sys/depend/secp256k1/src/group.h similarity index 50% rename from depend/secp256k1/src/group.h rename to secp256k1-sys/depend/secp256k1/src/group.h index ebfe1ca70..b61484b07 100644 --- a/depend/secp256k1/src/group.h +++ b/secp256k1-sys/depend/secp256k1/src/group.h @@ -4,138 +4,139 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_GROUP_ -#define _SECP256K1_GROUP_ +#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; + rustsecp256k1_v0_1_1_fe x; + rustsecp256k1_v0_1_1_fe y; int infinity; /* whether this represents the point at infinity */ -} secp256k1_ge; +} rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_fe x; /* actual X: x/z^2 */ + rustsecp256k1_v0_1_1_fe y; /* actual Y: y/z^3 */ + rustsecp256k1_v0_1_1_fe z; int infinity; /* whether this represents the point at infinity */ -} secp256k1_gej; +} rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_fe_storage x; + rustsecp256k1_v0_1_1_fe_storage y; +} rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_ge_set_xy(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_fe *x, const rustsecp256k1_v0_1_1_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_var(secp256k1_ge *r, const secp256k1_fe *x); +static int rustsecp256k1_v0_1_1_ge_set_xquad(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_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); +static int rustsecp256k1_v0_1_1_ge_set_xo_var(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_fe *x, int odd); /** Check whether a group element is the point at infinity. */ -static int secp256k1_ge_is_infinity(const secp256k1_ge *a); +static int rustsecp256k1_v0_1_1_ge_is_infinity(const rustsecp256k1_v0_1_1_ge *a); /** Check whether a group element is valid (i.e., on the curve). */ -static int secp256k1_ge_is_valid_var(const secp256k1_ge *a); +static int rustsecp256k1_v0_1_1_ge_is_valid_var(const rustsecp256k1_v0_1_1_ge *a); -static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); +static void rustsecp256k1_v0_1_1_ge_neg(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_ge_set_gej(rustsecp256k1_v0_1_1_ge *r, rustsecp256k1_v0_1_1_gej *a); /** Set a batch of group elements equal to the inputs given in jacobian coordinates */ -static void secp256k1_ge_set_all_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_callback *cb); - -/** Set a batch of group elements equal to the inputs given in jacobian - * coordinates (with known z-ratios). zr must contain the known z-ratios such - * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */ -static void secp256k1_ge_set_table_gej_var(size_t len, secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr); +static void rustsecp256k1_v0_1_1_ge_set_all_gej_var(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_ge_globalz_set_table_gej(size_t len, rustsecp256k1_v0_1_1_ge *r, rustsecp256k1_v0_1_1_fe *globalz, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_fe *zr); + +/** Set a group element (affine) equal to the point at infinity. */ +static void rustsecp256k1_v0_1_1_ge_set_infinity(rustsecp256k1_v0_1_1_ge *r); /** Set a group element (jacobian) equal to the point at infinity. */ -static void secp256k1_gej_set_infinity(secp256k1_gej *r); +static void rustsecp256k1_v0_1_1_gej_set_infinity(rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_gej_set_ge(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_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); +static int rustsecp256k1_v0_1_1_gej_eq_x_var(const rustsecp256k1_v0_1_1_fe *x, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_gej_neg(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a); /** Check whether a group element is the point at infinity. */ -static int secp256k1_gej_is_infinity(const secp256k1_gej *a); +static int rustsecp256k1_v0_1_1_gej_is_infinity(const rustsecp256k1_v0_1_1_gej *a); + +/** Check whether a group element's y coordinate is a quadratic residue. */ +static int rustsecp256k1_v0_1_1_gej_has_quad_y_var(const rustsecp256k1_v0_1_1_gej *a); /** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). * a may not be zero. Constant time. */ -static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); +static void rustsecp256k1_v0_1_1_gej_double_nonzero(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, rustsecp256k1_v0_1_1_fe *rzr); /** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */ -static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); +static void rustsecp256k1_v0_1_1_gej_double_var(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, rustsecp256k1_v0_1_1_fe *rzr); /** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ -static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr); +static void rustsecp256k1_v0_1_1_gej_add_var(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_gej *b, rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_gej_add_ge(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_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 + than rustsecp256k1_v0_1_1_gej_add_var. It is identical to rustsecp256k1_v0_1_1_gej_add_ge but without constant-time guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ -static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr); +static void rustsecp256k1_v0_1_1_gej_add_ge_var(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_ge *b, rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_gej_add_zinv_var(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_ge *b, const rustsecp256k1_v0_1_1_fe *bzinv); #ifdef USE_ENDOMORPHISM /** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ -static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); +static void rustsecp256k1_v0_1_1_ge_mul_lambda(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_ge *a); #endif -/** Clear a secp256k1_gej to prevent leaking sensitive information. */ -static void secp256k1_gej_clear(secp256k1_gej *r); +/** Clear a rustsecp256k1_v0_1_1_gej to prevent leaking sensitive information. */ +static void rustsecp256k1_v0_1_1_gej_clear(rustsecp256k1_v0_1_1_gej *r); -/** Clear a secp256k1_ge to prevent leaking sensitive information. */ -static void secp256k1_ge_clear(secp256k1_ge *r); +/** Clear a rustsecp256k1_v0_1_1_ge to prevent leaking sensitive information. */ +static void rustsecp256k1_v0_1_1_ge_clear(rustsecp256k1_v0_1_1_ge *r); /** Convert a group element to the storage type. */ -static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a); +static void rustsecp256k1_v0_1_1_ge_to_storage(rustsecp256k1_v0_1_1_ge_storage *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_ge_from_storage(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_ge_storage *a); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ -static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); +static void rustsecp256k1_v0_1_1_ge_storage_cmov(rustsecp256k1_v0_1_1_ge_storage *r, const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_gej_rescale(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_fe *b); -#endif +#endif /* SECP256K1_GROUP_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/group_impl.h b/secp256k1-sys/depend/secp256k1/src/group_impl.h new file mode 100644 index 000000000..9a1148570 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/group_impl.h @@ -0,0 +1,705 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_GROUP_IMPL_H +#define SECP256K1_GROUP_IMPL_H + +#include "num.h" +#include "field.h" +#include "group.h" + +/* These points can be generated in sage as follows: + * + * 0. Setup a worksheet with the following parameters. + * b = 4 # whatever CURVE_B will be set to + * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) + * C = EllipticCurve ([F (0), F (b)]) + * + * 1. Determine all the small orders available to you. (If there are + * no satisfactory ones, go back and change b.) + * print C.order().factor(limit=1000) + * + * 2. Choose an order as one of the prime factors listed in the above step. + * (You can also multiply some to get a composite order, though the + * tests will crash trying to invert scalars during signing.) We take a + * random point and scale it to drop its order to the desired value. + * There is some probability this won't work; just try again. + * order = 199 + * P = C.random_point() + * P = (int(P.order()) / int(order)) * P + * assert(P.order() == order) + * + * 3. Print the values. You'll need to use a vim macro or something to + * split the hex output into 4-byte chunks. + * print "%x %x" % P.xy() + */ +#if defined(EXHAUSTIVE_TEST_ORDER) +# if EXHAUSTIVE_TEST_ORDER == 199 +static const rustsecp256k1_v0_1_1_ge rustsecp256k1_v0_1_1_ge_const_g = SECP256K1_GE_CONST( + 0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069, + 0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18, + 0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868, + 0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED +); + +static const int CURVE_B = 4; +# elif EXHAUSTIVE_TEST_ORDER == 13 +static const rustsecp256k1_v0_1_1_ge rustsecp256k1_v0_1_1_ge_const_g = SECP256K1_GE_CONST( + 0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0, + 0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15, + 0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e, + 0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac +); +static const int CURVE_B = 2; +# else +# error No known generator for the specified exhaustive test group order. +# endif +#else +/** Generator for secp256k1, value 'g' defined in + * "Standards for Efficient Cryptography" (SEC2) 2.7.1. + */ +static const rustsecp256k1_v0_1_1_ge rustsecp256k1_v0_1_1_ge_const_g = SECP256K1_GE_CONST( + 0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL, + 0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL, + 0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL, + 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL +); + +static const int CURVE_B = 7; +#endif + +static void rustsecp256k1_v0_1_1_ge_set_gej_zinv(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_fe *zi) { + rustsecp256k1_v0_1_1_fe zi2; + rustsecp256k1_v0_1_1_fe zi3; + rustsecp256k1_v0_1_1_fe_sqr(&zi2, zi); + rustsecp256k1_v0_1_1_fe_mul(&zi3, &zi2, zi); + rustsecp256k1_v0_1_1_fe_mul(&r->x, &a->x, &zi2); + rustsecp256k1_v0_1_1_fe_mul(&r->y, &a->y, &zi3); + r->infinity = a->infinity; +} + +static void rustsecp256k1_v0_1_1_ge_set_xy(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_fe *x, const rustsecp256k1_v0_1_1_fe *y) { + r->infinity = 0; + r->x = *x; + r->y = *y; +} + +static int rustsecp256k1_v0_1_1_ge_is_infinity(const rustsecp256k1_v0_1_1_ge *a) { + return a->infinity; +} + +static void rustsecp256k1_v0_1_1_ge_neg(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_ge *a) { + *r = *a; + rustsecp256k1_v0_1_1_fe_normalize_weak(&r->y); + rustsecp256k1_v0_1_1_fe_negate(&r->y, &r->y, 1); +} + +static void rustsecp256k1_v0_1_1_ge_set_gej(rustsecp256k1_v0_1_1_ge *r, rustsecp256k1_v0_1_1_gej *a) { + rustsecp256k1_v0_1_1_fe z2, z3; + r->infinity = a->infinity; + rustsecp256k1_v0_1_1_fe_inv(&a->z, &a->z); + rustsecp256k1_v0_1_1_fe_sqr(&z2, &a->z); + rustsecp256k1_v0_1_1_fe_mul(&z3, &a->z, &z2); + rustsecp256k1_v0_1_1_fe_mul(&a->x, &a->x, &z2); + rustsecp256k1_v0_1_1_fe_mul(&a->y, &a->y, &z3); + rustsecp256k1_v0_1_1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +static void rustsecp256k1_v0_1_1_ge_set_gej_var(rustsecp256k1_v0_1_1_ge *r, rustsecp256k1_v0_1_1_gej *a) { + rustsecp256k1_v0_1_1_fe z2, z3; + r->infinity = a->infinity; + if (a->infinity) { + return; + } + rustsecp256k1_v0_1_1_fe_inv_var(&a->z, &a->z); + rustsecp256k1_v0_1_1_fe_sqr(&z2, &a->z); + rustsecp256k1_v0_1_1_fe_mul(&z3, &a->z, &z2); + rustsecp256k1_v0_1_1_fe_mul(&a->x, &a->x, &z2); + rustsecp256k1_v0_1_1_fe_mul(&a->y, &a->y, &z3); + rustsecp256k1_v0_1_1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +static void rustsecp256k1_v0_1_1_ge_set_all_gej_var(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_gej *a, size_t len) { + rustsecp256k1_v0_1_1_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 { + rustsecp256k1_v0_1_1_fe_mul(&r[i].x, &r[last_i].x, &a[i].z); + } + last_i = i; + } + } + if (last_i == SIZE_MAX) { + return; + } + rustsecp256k1_v0_1_1_fe_inv_var(&u, &r[last_i].x); + + i = last_i; + while (i > 0) { + i--; + if (!a[i].infinity) { + rustsecp256k1_v0_1_1_fe_mul(&r[last_i].x, &r[i].x, &u); + rustsecp256k1_v0_1_1_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) { + rustsecp256k1_v0_1_1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); + } + } +} + +static void rustsecp256k1_v0_1_1_ge_globalz_set_table_gej(size_t len, rustsecp256k1_v0_1_1_ge *r, rustsecp256k1_v0_1_1_fe *globalz, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_fe *zr) { + size_t i = len - 1; + rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_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) { + rustsecp256k1_v0_1_1_fe_mul(&zs, &zs, &zr[i]); + } + i--; + rustsecp256k1_v0_1_1_ge_set_gej_zinv(&r[i], &a[i], &zs); + } + } +} + +static void rustsecp256k1_v0_1_1_gej_set_infinity(rustsecp256k1_v0_1_1_gej *r) { + r->infinity = 1; + rustsecp256k1_v0_1_1_fe_clear(&r->x); + rustsecp256k1_v0_1_1_fe_clear(&r->y); + rustsecp256k1_v0_1_1_fe_clear(&r->z); +} + +static void rustsecp256k1_v0_1_1_ge_set_infinity(rustsecp256k1_v0_1_1_ge *r) { + r->infinity = 1; + rustsecp256k1_v0_1_1_fe_clear(&r->x); + rustsecp256k1_v0_1_1_fe_clear(&r->y); +} + +static void rustsecp256k1_v0_1_1_gej_clear(rustsecp256k1_v0_1_1_gej *r) { + r->infinity = 0; + rustsecp256k1_v0_1_1_fe_clear(&r->x); + rustsecp256k1_v0_1_1_fe_clear(&r->y); + rustsecp256k1_v0_1_1_fe_clear(&r->z); +} + +static void rustsecp256k1_v0_1_1_ge_clear(rustsecp256k1_v0_1_1_ge *r) { + r->infinity = 0; + rustsecp256k1_v0_1_1_fe_clear(&r->x); + rustsecp256k1_v0_1_1_fe_clear(&r->y); +} + +static int rustsecp256k1_v0_1_1_ge_set_xquad(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_fe *x) { + rustsecp256k1_v0_1_1_fe x2, x3, c; + r->x = *x; + rustsecp256k1_v0_1_1_fe_sqr(&x2, x); + rustsecp256k1_v0_1_1_fe_mul(&x3, x, &x2); + r->infinity = 0; + rustsecp256k1_v0_1_1_fe_set_int(&c, CURVE_B); + rustsecp256k1_v0_1_1_fe_add(&c, &x3); + return rustsecp256k1_v0_1_1_fe_sqrt(&r->y, &c); +} + +static int rustsecp256k1_v0_1_1_ge_set_xo_var(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_fe *x, int odd) { + if (!rustsecp256k1_v0_1_1_ge_set_xquad(r, x)) { + return 0; + } + rustsecp256k1_v0_1_1_fe_normalize_var(&r->y); + if (rustsecp256k1_v0_1_1_fe_is_odd(&r->y) != odd) { + rustsecp256k1_v0_1_1_fe_negate(&r->y, &r->y, 1); + } + return 1; + +} + +static void rustsecp256k1_v0_1_1_gej_set_ge(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_ge *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + rustsecp256k1_v0_1_1_fe_set_int(&r->z, 1); +} + +static int rustsecp256k1_v0_1_1_gej_eq_x_var(const rustsecp256k1_v0_1_1_fe *x, const rustsecp256k1_v0_1_1_gej *a) { + rustsecp256k1_v0_1_1_fe r, r2; + VERIFY_CHECK(!a->infinity); + rustsecp256k1_v0_1_1_fe_sqr(&r, &a->z); rustsecp256k1_v0_1_1_fe_mul(&r, &r, x); + r2 = a->x; rustsecp256k1_v0_1_1_fe_normalize_weak(&r2); + return rustsecp256k1_v0_1_1_fe_equal_var(&r, &r2); +} + +static void rustsecp256k1_v0_1_1_gej_neg(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + r->z = a->z; + rustsecp256k1_v0_1_1_fe_normalize_weak(&r->y); + rustsecp256k1_v0_1_1_fe_negate(&r->y, &r->y, 1); +} + +static int rustsecp256k1_v0_1_1_gej_is_infinity(const rustsecp256k1_v0_1_1_gej *a) { + return a->infinity; +} + +static int rustsecp256k1_v0_1_1_gej_is_valid_var(const rustsecp256k1_v0_1_1_gej *a) { + rustsecp256k1_v0_1_1_fe y2, x3, z2, z6; + if (a->infinity) { + return 0; + } + /** y^2 = x^3 + 7 + * (Y/Z^3)^2 = (X/Z^2)^3 + 7 + * Y^2 / Z^6 = X^3 / Z^6 + 7 + * Y^2 = X^3 + 7*Z^6 + */ + rustsecp256k1_v0_1_1_fe_sqr(&y2, &a->y); + rustsecp256k1_v0_1_1_fe_sqr(&x3, &a->x); rustsecp256k1_v0_1_1_fe_mul(&x3, &x3, &a->x); + rustsecp256k1_v0_1_1_fe_sqr(&z2, &a->z); + rustsecp256k1_v0_1_1_fe_sqr(&z6, &z2); rustsecp256k1_v0_1_1_fe_mul(&z6, &z6, &z2); + rustsecp256k1_v0_1_1_fe_mul_int(&z6, CURVE_B); + rustsecp256k1_v0_1_1_fe_add(&x3, &z6); + rustsecp256k1_v0_1_1_fe_normalize_weak(&x3); + return rustsecp256k1_v0_1_1_fe_equal_var(&y2, &x3); +} + +static int rustsecp256k1_v0_1_1_ge_is_valid_var(const rustsecp256k1_v0_1_1_ge *a) { + rustsecp256k1_v0_1_1_fe y2, x3, c; + if (a->infinity) { + return 0; + } + /* y^2 = x^3 + 7 */ + rustsecp256k1_v0_1_1_fe_sqr(&y2, &a->y); + rustsecp256k1_v0_1_1_fe_sqr(&x3, &a->x); rustsecp256k1_v0_1_1_fe_mul(&x3, &x3, &a->x); + rustsecp256k1_v0_1_1_fe_set_int(&c, CURVE_B); + rustsecp256k1_v0_1_1_fe_add(&x3, &c); + rustsecp256k1_v0_1_1_fe_normalize_weak(&x3); + return rustsecp256k1_v0_1_1_fe_equal_var(&y2, &x3); +} + +static void rustsecp256k1_v0_1_1_gej_double_var(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, rustsecp256k1_v0_1_1_fe *rzr) { + /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate. + * + * Note that there is an implementation described at + * https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + * which trades a multiply for a square, but in practice this is actually slower, + * mainly because it requires more normalizations. + */ + rustsecp256k1_v0_1_1_fe t1,t2,t3,t4; + /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, + * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have + * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. + * + * Having said this, if this function receives a point on a sextic twist, e.g. by + * a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6, + * since -6 does have a cube root mod p. For this point, this function will not set + * the infinity flag even though the point doubles to infinity, and the result + * point will be gibberish (z = 0 but infinity = 0). + */ + r->infinity = a->infinity; + if (r->infinity) { + if (rzr != NULL) { + rustsecp256k1_v0_1_1_fe_set_int(rzr, 1); + } + return; + } + + if (rzr != NULL) { + *rzr = a->y; + rustsecp256k1_v0_1_1_fe_normalize_weak(rzr); + rustsecp256k1_v0_1_1_fe_mul_int(rzr, 2); + } + + rustsecp256k1_v0_1_1_fe_mul(&r->z, &a->z, &a->y); + rustsecp256k1_v0_1_1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ + rustsecp256k1_v0_1_1_fe_sqr(&t1, &a->x); + rustsecp256k1_v0_1_1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ + rustsecp256k1_v0_1_1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ + rustsecp256k1_v0_1_1_fe_sqr(&t3, &a->y); + rustsecp256k1_v0_1_1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ + rustsecp256k1_v0_1_1_fe_sqr(&t4, &t3); + rustsecp256k1_v0_1_1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ + rustsecp256k1_v0_1_1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ + r->x = t3; + rustsecp256k1_v0_1_1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ + rustsecp256k1_v0_1_1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ + rustsecp256k1_v0_1_1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ + rustsecp256k1_v0_1_1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ + rustsecp256k1_v0_1_1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ + rustsecp256k1_v0_1_1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ + rustsecp256k1_v0_1_1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ + rustsecp256k1_v0_1_1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ + rustsecp256k1_v0_1_1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ +} + +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_gej_double_nonzero(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, rustsecp256k1_v0_1_1_fe *rzr) { + VERIFY_CHECK(!rustsecp256k1_v0_1_1_gej_is_infinity(a)); + rustsecp256k1_v0_1_1_gej_double_var(r, a, rzr); +} + +static void rustsecp256k1_v0_1_1_gej_add_var(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_gej *b, rustsecp256k1_v0_1_1_fe *rzr) { + /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ + rustsecp256k1_v0_1_1_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) { + rustsecp256k1_v0_1_1_fe_set_int(rzr, 1); + } + *r = *a; + return; + } + + r->infinity = 0; + rustsecp256k1_v0_1_1_fe_sqr(&z22, &b->z); + rustsecp256k1_v0_1_1_fe_sqr(&z12, &a->z); + rustsecp256k1_v0_1_1_fe_mul(&u1, &a->x, &z22); + rustsecp256k1_v0_1_1_fe_mul(&u2, &b->x, &z12); + rustsecp256k1_v0_1_1_fe_mul(&s1, &a->y, &z22); rustsecp256k1_v0_1_1_fe_mul(&s1, &s1, &b->z); + rustsecp256k1_v0_1_1_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_1_1_fe_mul(&s2, &s2, &a->z); + rustsecp256k1_v0_1_1_fe_negate(&h, &u1, 1); rustsecp256k1_v0_1_1_fe_add(&h, &u2); + rustsecp256k1_v0_1_1_fe_negate(&i, &s1, 1); rustsecp256k1_v0_1_1_fe_add(&i, &s2); + if (rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(&h)) { + if (rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(&i)) { + rustsecp256k1_v0_1_1_gej_double_var(r, a, rzr); + } else { + if (rzr != NULL) { + rustsecp256k1_v0_1_1_fe_set_int(rzr, 0); + } + r->infinity = 1; + } + return; + } + rustsecp256k1_v0_1_1_fe_sqr(&i2, &i); + rustsecp256k1_v0_1_1_fe_sqr(&h2, &h); + rustsecp256k1_v0_1_1_fe_mul(&h3, &h, &h2); + rustsecp256k1_v0_1_1_fe_mul(&h, &h, &b->z); + if (rzr != NULL) { + *rzr = h; + } + rustsecp256k1_v0_1_1_fe_mul(&r->z, &a->z, &h); + rustsecp256k1_v0_1_1_fe_mul(&t, &u1, &h2); + r->x = t; rustsecp256k1_v0_1_1_fe_mul_int(&r->x, 2); rustsecp256k1_v0_1_1_fe_add(&r->x, &h3); rustsecp256k1_v0_1_1_fe_negate(&r->x, &r->x, 3); rustsecp256k1_v0_1_1_fe_add(&r->x, &i2); + rustsecp256k1_v0_1_1_fe_negate(&r->y, &r->x, 5); rustsecp256k1_v0_1_1_fe_add(&r->y, &t); rustsecp256k1_v0_1_1_fe_mul(&r->y, &r->y, &i); + rustsecp256k1_v0_1_1_fe_mul(&h3, &h3, &s1); rustsecp256k1_v0_1_1_fe_negate(&h3, &h3, 1); + rustsecp256k1_v0_1_1_fe_add(&r->y, &h3); +} + +static void rustsecp256k1_v0_1_1_gej_add_ge_var(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_ge *b, rustsecp256k1_v0_1_1_fe *rzr) { + /* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ + rustsecp256k1_v0_1_1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + if (a->infinity) { + VERIFY_CHECK(rzr == NULL); + rustsecp256k1_v0_1_1_gej_set_ge(r, b); + return; + } + if (b->infinity) { + if (rzr != NULL) { + rustsecp256k1_v0_1_1_fe_set_int(rzr, 1); + } + *r = *a; + return; + } + r->infinity = 0; + + rustsecp256k1_v0_1_1_fe_sqr(&z12, &a->z); + u1 = a->x; rustsecp256k1_v0_1_1_fe_normalize_weak(&u1); + rustsecp256k1_v0_1_1_fe_mul(&u2, &b->x, &z12); + s1 = a->y; rustsecp256k1_v0_1_1_fe_normalize_weak(&s1); + rustsecp256k1_v0_1_1_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_1_1_fe_mul(&s2, &s2, &a->z); + rustsecp256k1_v0_1_1_fe_negate(&h, &u1, 1); rustsecp256k1_v0_1_1_fe_add(&h, &u2); + rustsecp256k1_v0_1_1_fe_negate(&i, &s1, 1); rustsecp256k1_v0_1_1_fe_add(&i, &s2); + if (rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(&h)) { + if (rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(&i)) { + rustsecp256k1_v0_1_1_gej_double_var(r, a, rzr); + } else { + if (rzr != NULL) { + rustsecp256k1_v0_1_1_fe_set_int(rzr, 0); + } + r->infinity = 1; + } + return; + } + rustsecp256k1_v0_1_1_fe_sqr(&i2, &i); + rustsecp256k1_v0_1_1_fe_sqr(&h2, &h); + rustsecp256k1_v0_1_1_fe_mul(&h3, &h, &h2); + if (rzr != NULL) { + *rzr = h; + } + rustsecp256k1_v0_1_1_fe_mul(&r->z, &a->z, &h); + rustsecp256k1_v0_1_1_fe_mul(&t, &u1, &h2); + r->x = t; rustsecp256k1_v0_1_1_fe_mul_int(&r->x, 2); rustsecp256k1_v0_1_1_fe_add(&r->x, &h3); rustsecp256k1_v0_1_1_fe_negate(&r->x, &r->x, 3); rustsecp256k1_v0_1_1_fe_add(&r->x, &i2); + rustsecp256k1_v0_1_1_fe_negate(&r->y, &r->x, 5); rustsecp256k1_v0_1_1_fe_add(&r->y, &t); rustsecp256k1_v0_1_1_fe_mul(&r->y, &r->y, &i); + rustsecp256k1_v0_1_1_fe_mul(&h3, &h3, &s1); rustsecp256k1_v0_1_1_fe_negate(&h3, &h3, 1); + rustsecp256k1_v0_1_1_fe_add(&r->y, &h3); +} + +static void rustsecp256k1_v0_1_1_gej_add_zinv_var(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_ge *b, const rustsecp256k1_v0_1_1_fe *bzinv) { + /* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ + rustsecp256k1_v0_1_1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + + if (b->infinity) { + *r = *a; + return; + } + if (a->infinity) { + rustsecp256k1_v0_1_1_fe bzinv2, bzinv3; + r->infinity = b->infinity; + rustsecp256k1_v0_1_1_fe_sqr(&bzinv2, bzinv); + rustsecp256k1_v0_1_1_fe_mul(&bzinv3, &bzinv2, bzinv); + rustsecp256k1_v0_1_1_fe_mul(&r->x, &b->x, &bzinv2); + rustsecp256k1_v0_1_1_fe_mul(&r->y, &b->y, &bzinv3); + rustsecp256k1_v0_1_1_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. + */ + rustsecp256k1_v0_1_1_fe_mul(&az, &a->z, bzinv); + + rustsecp256k1_v0_1_1_fe_sqr(&z12, &az); + u1 = a->x; rustsecp256k1_v0_1_1_fe_normalize_weak(&u1); + rustsecp256k1_v0_1_1_fe_mul(&u2, &b->x, &z12); + s1 = a->y; rustsecp256k1_v0_1_1_fe_normalize_weak(&s1); + rustsecp256k1_v0_1_1_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_1_1_fe_mul(&s2, &s2, &az); + rustsecp256k1_v0_1_1_fe_negate(&h, &u1, 1); rustsecp256k1_v0_1_1_fe_add(&h, &u2); + rustsecp256k1_v0_1_1_fe_negate(&i, &s1, 1); rustsecp256k1_v0_1_1_fe_add(&i, &s2); + if (rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(&h)) { + if (rustsecp256k1_v0_1_1_fe_normalizes_to_zero_var(&i)) { + rustsecp256k1_v0_1_1_gej_double_var(r, a, NULL); + } else { + r->infinity = 1; + } + return; + } + rustsecp256k1_v0_1_1_fe_sqr(&i2, &i); + rustsecp256k1_v0_1_1_fe_sqr(&h2, &h); + rustsecp256k1_v0_1_1_fe_mul(&h3, &h, &h2); + r->z = a->z; rustsecp256k1_v0_1_1_fe_mul(&r->z, &r->z, &h); + rustsecp256k1_v0_1_1_fe_mul(&t, &u1, &h2); + r->x = t; rustsecp256k1_v0_1_1_fe_mul_int(&r->x, 2); rustsecp256k1_v0_1_1_fe_add(&r->x, &h3); rustsecp256k1_v0_1_1_fe_negate(&r->x, &r->x, 3); rustsecp256k1_v0_1_1_fe_add(&r->x, &i2); + rustsecp256k1_v0_1_1_fe_negate(&r->y, &r->x, 5); rustsecp256k1_v0_1_1_fe_add(&r->y, &t); rustsecp256k1_v0_1_1_fe_mul(&r->y, &r->y, &i); + rustsecp256k1_v0_1_1_fe_mul(&h3, &h3, &s1); rustsecp256k1_v0_1_1_fe_negate(&h3, &h3, 1); + rustsecp256k1_v0_1_1_fe_add(&r->y, &h3); +} + + +static void rustsecp256k1_v0_1_1_gej_add_ge(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_ge *b) { + /* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */ + static const rustsecp256k1_v0_1_1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); + rustsecp256k1_v0_1_1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; + rustsecp256k1_v0_1_1_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. + */ + + rustsecp256k1_v0_1_1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ + u1 = a->x; rustsecp256k1_v0_1_1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ + rustsecp256k1_v0_1_1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ + s1 = a->y; rustsecp256k1_v0_1_1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ + rustsecp256k1_v0_1_1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ + rustsecp256k1_v0_1_1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ + t = u1; rustsecp256k1_v0_1_1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ + m = s1; rustsecp256k1_v0_1_1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ + rustsecp256k1_v0_1_1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ + rustsecp256k1_v0_1_1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ + rustsecp256k1_v0_1_1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ + rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_fe_normalizes_to_zero(&m) & + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ + rustsecp256k1_v0_1_1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ + + rustsecp256k1_v0_1_1_fe_cmov(&rr_alt, &rr, !degenerate); + rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ + rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_fe_sqr(&n, &n); + rustsecp256k1_v0_1_1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ + rustsecp256k1_v0_1_1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ + rustsecp256k1_v0_1_1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */ + infinity = rustsecp256k1_v0_1_1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); + rustsecp256k1_v0_1_1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */ + rustsecp256k1_v0_1_1_fe_negate(&q, &q, 1); /* q = -Q (2) */ + rustsecp256k1_v0_1_1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */ + rustsecp256k1_v0_1_1_fe_normalize_weak(&t); + r->x = t; /* r->x = Ralt^2-Q (1) */ + rustsecp256k1_v0_1_1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */ + rustsecp256k1_v0_1_1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */ + rustsecp256k1_v0_1_1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */ + rustsecp256k1_v0_1_1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */ + rustsecp256k1_v0_1_1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */ + rustsecp256k1_v0_1_1_fe_normalize_weak(&r->y); + rustsecp256k1_v0_1_1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */ + rustsecp256k1_v0_1_1_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). */ + rustsecp256k1_v0_1_1_fe_cmov(&r->x, &b->x, a->infinity); + rustsecp256k1_v0_1_1_fe_cmov(&r->y, &b->y, a->infinity); + rustsecp256k1_v0_1_1_fe_cmov(&r->z, &fe_1, a->infinity); + r->infinity = infinity; +} + +static void rustsecp256k1_v0_1_1_gej_rescale(rustsecp256k1_v0_1_1_gej *r, const rustsecp256k1_v0_1_1_fe *s) { + /* Operations: 4 mul, 1 sqr */ + rustsecp256k1_v0_1_1_fe zz; + VERIFY_CHECK(!rustsecp256k1_v0_1_1_fe_is_zero(s)); + rustsecp256k1_v0_1_1_fe_sqr(&zz, s); + rustsecp256k1_v0_1_1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ + rustsecp256k1_v0_1_1_fe_mul(&r->y, &r->y, &zz); + rustsecp256k1_v0_1_1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ + rustsecp256k1_v0_1_1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ +} + +static void rustsecp256k1_v0_1_1_ge_to_storage(rustsecp256k1_v0_1_1_ge_storage *r, const rustsecp256k1_v0_1_1_ge *a) { + rustsecp256k1_v0_1_1_fe x, y; + VERIFY_CHECK(!a->infinity); + x = a->x; + rustsecp256k1_v0_1_1_fe_normalize(&x); + y = a->y; + rustsecp256k1_v0_1_1_fe_normalize(&y); + rustsecp256k1_v0_1_1_fe_to_storage(&r->x, &x); + rustsecp256k1_v0_1_1_fe_to_storage(&r->y, &y); +} + +static void rustsecp256k1_v0_1_1_ge_from_storage(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_ge_storage *a) { + rustsecp256k1_v0_1_1_fe_from_storage(&r->x, &a->x); + rustsecp256k1_v0_1_1_fe_from_storage(&r->y, &a->y); + r->infinity = 0; +} + +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_ge_storage_cmov(rustsecp256k1_v0_1_1_ge_storage *r, const rustsecp256k1_v0_1_1_ge_storage *a, int flag) { + rustsecp256k1_v0_1_1_fe_storage_cmov(&r->x, &a->x, flag); + rustsecp256k1_v0_1_1_fe_storage_cmov(&r->y, &a->y, flag); +} + +#ifdef USE_ENDOMORPHISM +static void rustsecp256k1_v0_1_1_ge_mul_lambda(rustsecp256k1_v0_1_1_ge *r, const rustsecp256k1_v0_1_1_ge *a) { + static const rustsecp256k1_v0_1_1_fe beta = SECP256K1_FE_CONST( + 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, + 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul + ); + *r = *a; + rustsecp256k1_v0_1_1_fe_mul(&r->x, &r->x, &beta); +} +#endif + +static int rustsecp256k1_v0_1_1_gej_has_quad_y_var(const rustsecp256k1_v0_1_1_gej *a) { + rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_fe_mul(&yz, &a->y, &a->z); + return rustsecp256k1_v0_1_1_fe_is_quad_var(&yz); +} + +#endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/hash.h b/secp256k1-sys/depend/secp256k1/src/hash.h new file mode 100644 index 000000000..33bf5744c --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/hash.h @@ -0,0 +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.* + **********************************************************************/ + +#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; +} rustsecp256k1_v0_1_1_sha256; + +static void rustsecp256k1_v0_1_1_sha256_initialize(rustsecp256k1_v0_1_1_sha256 *hash); +static void rustsecp256k1_v0_1_1_sha256_write(rustsecp256k1_v0_1_1_sha256 *hash, const unsigned char *data, size_t size); +static void rustsecp256k1_v0_1_1_sha256_finalize(rustsecp256k1_v0_1_1_sha256 *hash, unsigned char *out32); + +typedef struct { + rustsecp256k1_v0_1_1_sha256 inner, outer; +} rustsecp256k1_v0_1_1_hmac_sha256; + +static void rustsecp256k1_v0_1_1_hmac_sha256_initialize(rustsecp256k1_v0_1_1_hmac_sha256 *hash, const unsigned char *key, size_t size); +static void rustsecp256k1_v0_1_1_hmac_sha256_write(rustsecp256k1_v0_1_1_hmac_sha256 *hash, const unsigned char *data, size_t size); +static void rustsecp256k1_v0_1_1_hmac_sha256_finalize(rustsecp256k1_v0_1_1_hmac_sha256 *hash, unsigned char *out32); + +typedef struct { + unsigned char v[32]; + unsigned char k[32]; + int retry; +} rustsecp256k1_v0_1_1_rfc6979_hmac_sha256; + +static void rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); +static void rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); +static void rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_finalize(rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 *rng); + +#endif /* SECP256K1_HASH_H */ diff --git a/depend/secp256k1/src/hash_impl.h b/secp256k1-sys/depend/secp256k1/src/hash_impl.h similarity index 66% rename from depend/secp256k1/src/hash_impl.h rename to secp256k1-sys/depend/secp256k1/src/hash_impl.h index ae55df6d8..71ed8093d 100644 --- a/depend/secp256k1/src/hash_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/hash_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_HASH_IMPL_H_ -#define _SECP256K1_HASH_IMPL_H_ +#ifndef SECP256K1_HASH_IMPL_H +#define SECP256K1_HASH_IMPL_H #include "hash.h" @@ -33,7 +33,7 @@ #define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) #endif -static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { +static void rustsecp256k1_v0_1_1_sha256_initialize(rustsecp256k1_v0_1_1_sha256 *hash) { hash->s[0] = 0x6a09e667ul; hash->s[1] = 0xbb67ae85ul; hash->s[2] = 0x3c6ef372ul; @@ -46,7 +46,7 @@ static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { } /** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ -static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { +static void rustsecp256k1_v0_1_1_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; @@ -128,15 +128,16 @@ static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { s[7] += h; } -static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { +static void rustsecp256k1_v0_1_1_sha256_write(rustsecp256k1_v0_1_1_sha256 *hash, const unsigned char *data, size_t len) { size_t bufsize = hash->bytes & 0x3F; hash->bytes += len; while (bufsize + len >= 64) { /* Fill the buffer, and process it. */ - memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize); - data += 64 - bufsize; - len -= 64 - bufsize; - secp256k1_sha256_transform(hash->s, hash->buf); + size_t chunk_len = 64 - bufsize; + memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len); + data += chunk_len; + len -= chunk_len; + rustsecp256k1_v0_1_1_sha256_transform(hash->s, hash->buf); bufsize = 0; } if (len) { @@ -145,15 +146,15 @@ static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char } } -static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { +static void rustsecp256k1_v0_1_1_sha256_finalize(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); + rustsecp256k1_v0_1_1_sha256_write(hash, (const unsigned char*)sizedesc, 8); for (i = 0; i < 8; i++) { out[i] = BE32(hash->s[i]); hash->s[i] = 0; @@ -161,49 +162,49 @@ static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *o memcpy(out32, (const unsigned char*)out, 32); } -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { - int n; +static void rustsecp256k1_v0_1_1_hmac_sha256_initialize(rustsecp256k1_v0_1_1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { + size_t n; unsigned char rkey[64]; - if (keylen <= 64) { + if (keylen <= sizeof(rkey)) { memcpy(rkey, key, keylen); - memset(rkey + keylen, 0, 64 - keylen); + memset(rkey + keylen, 0, sizeof(rkey) - keylen); } else { - secp256k1_sha256_t sha256; - secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, key, keylen); - secp256k1_sha256_finalize(&sha256, rkey); + rustsecp256k1_v0_1_1_sha256 sha256; + rustsecp256k1_v0_1_1_sha256_initialize(&sha256); + rustsecp256k1_v0_1_1_sha256_write(&sha256, key, keylen); + rustsecp256k1_v0_1_1_sha256_finalize(&sha256, rkey); memset(rkey + 32, 0, 32); } - secp256k1_sha256_initialize(&hash->outer); - for (n = 0; n < 64; n++) { + rustsecp256k1_v0_1_1_sha256_initialize(&hash->outer); + for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c; } - secp256k1_sha256_write(&hash->outer, rkey, 64); + rustsecp256k1_v0_1_1_sha256_write(&hash->outer, rkey, sizeof(rkey)); - secp256k1_sha256_initialize(&hash->inner); - for (n = 0; n < 64; n++) { + rustsecp256k1_v0_1_1_sha256_initialize(&hash->inner); + for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c ^ 0x36; } - secp256k1_sha256_write(&hash->inner, rkey, 64); - memset(rkey, 0, 64); + rustsecp256k1_v0_1_1_sha256_write(&hash->inner, rkey, sizeof(rkey)); + memset(rkey, 0, sizeof(rkey)); } -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { - secp256k1_sha256_write(&hash->inner, data, size); +static void rustsecp256k1_v0_1_1_hmac_sha256_write(rustsecp256k1_v0_1_1_hmac_sha256 *hash, const unsigned char *data, size_t size) { + rustsecp256k1_v0_1_1_sha256_write(&hash->inner, data, size); } -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { +static void rustsecp256k1_v0_1_1_hmac_sha256_finalize(rustsecp256k1_v0_1_1_hmac_sha256 *hash, unsigned char *out32) { unsigned char temp[32]; - secp256k1_sha256_finalize(&hash->inner, temp); - secp256k1_sha256_write(&hash->outer, temp, 32); + rustsecp256k1_v0_1_1_sha256_finalize(&hash->inner, temp); + rustsecp256k1_v0_1_1_sha256_write(&hash->outer, temp, 32); memset(temp, 0, 32); - secp256k1_sha256_finalize(&hash->outer, out32); + rustsecp256k1_v0_1_1_sha256_finalize(&hash->outer, out32); } -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) { - secp256k1_hmac_sha256_t hmac; +static void rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { + rustsecp256k1_v0_1_1_hmac_sha256 hmac; static const unsigned char zero[1] = {0x00}; static const unsigned char one[1] = {0x01}; @@ -211,47 +212,47 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2 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); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, zero, 1); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, key, keylen); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hmac, rng->k); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, one, 1); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, key, keylen); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hmac, rng->k); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hmac, rng->v); rng->retry = 0; } -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { +static void rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(rustsecp256k1_v0_1_1_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_t 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); + rustsecp256k1_v0_1_1_hmac_sha256 hmac; + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, zero, 1); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hmac, rng->k); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hmac, rng->v); } while (outlen > 0) { - secp256k1_hmac_sha256_t hmac; + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hmac, rng->v); if (now > 32) { now = 32; } @@ -263,21 +264,19 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 rng->retry = 1; } -static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { +static void rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_finalize(rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 *rng) { memset(rng->k, 0, 32); memset(rng->v, 0, 32); rng->retry = 0; } - +#undef BE32 #undef Round -#undef sigma0 #undef sigma1 -#undef Sigma0 +#undef sigma0 #undef Sigma1 -#undef Ch +#undef Sigma0 #undef Maj -#undef ReadBE32 -#undef WriteBE32 +#undef Ch -#endif +#endif /* SECP256K1_HASH_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java new file mode 100644 index 000000000..706080772 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -0,0 +1,446 @@ +/* + * 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 + * + * 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 com.google.common.base.Preconditions; +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 nativeECDSABuffer = 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) throws AssertFailException{ + Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 520) { + byteBuff = ByteBuffer.allocateDirect(520); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(signature); + byteBuff.put(pub); + + byte[][] retByteArray; + + r.lock(); + try { + return rustsecp256k1_v0_1_1_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{ + Preconditions.checkArgument(data.length == 32 && sec.length <= 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 32 + 32) { + byteBuff = ByteBuffer.allocateDirect(32 + 32); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(sec); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = rustsecp256k1_v0_1_1_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) { + Preconditions.checkArgument(seckey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seckey.length) { + byteBuff = ByteBuffer.allocateDirect(seckey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + + r.lock(); + try { + return rustsecp256k1_v0_1_1_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{ + Preconditions.checkArgument(seckey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seckey.length) { + byteBuff = ByteBuffer.allocateDirect(seckey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = rustsecp256k1_v0_1_1_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 { + rustsecp256k1_v0_1_1_destroy_context(Secp256k1Context.getContext()); + } finally { + w.unlock(); + } + } + + public static long cloneContext() { + r.lock(); + try { + return rustsecp256k1_v0_1_1_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{ + Preconditions.checkArgument(privkey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(privkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = rustsecp256k1_v0_1_1_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{ + Preconditions.checkArgument(privkey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(privkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = rustsecp256k1_v0_1_1_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{ + Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(pubkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = rustsecp256k1_v0_1_1_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{ + Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(pubkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = rustsecp256k1_v0_1_1_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{ + Preconditions.checkArgument(seckey.length <= 32 && pubkey.length <= 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) { + byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + byteBuff.put(pubkey); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = rustsecp256k1_v0_1_1_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{ + Preconditions.checkArgument(seed.length == 32 || seed == null); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seed.length) { + byteBuff = ByteBuffer.allocateDirect(seed.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seed); + + w.lock(); + try { + return rustsecp256k1_v0_1_1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; + } finally { + w.unlock(); + } + } + + private static native long rustsecp256k1_v0_1_1_ctx_clone(long context); + + private static native int rustsecp256k1_v0_1_1_context_randomize(ByteBuffer byteBuff, long context); + + private static native byte[][] rustsecp256k1_v0_1_1_privkey_tweak_add(ByteBuffer byteBuff, long context); + + private static native byte[][] rustsecp256k1_v0_1_1_privkey_tweak_mul(ByteBuffer byteBuff, long context); + + private static native byte[][] rustsecp256k1_v0_1_1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen); + + private static native byte[][] rustsecp256k1_v0_1_1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen); + + private static native void rustsecp256k1_v0_1_1_destroy_context(long context); + + private static native int rustsecp256k1_v0_1_1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen); + + private static native byte[][] rustsecp256k1_v0_1_1_ecdsa_sign(ByteBuffer byteBuff, long context); + + private static native int rustsecp256k1_v0_1_1_ec_seckey_verify(ByteBuffer byteBuff, long context); + + private static native byte[][] rustsecp256k1_v0_1_1_ec_pubkey_create(ByteBuffer byteBuff, long context); + + private static native byte[][] rustsecp256k1_v0_1_1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); + + private static native byte[][] rustsecp256k1_v0_1_1_ecdh(ByteBuffer byteBuff, long context, int inputLen); + +} diff --git a/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java new file mode 100644 index 000000000..d766a1029 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java @@ -0,0 +1,226 @@ +package org.bitcoin; + +import com.google.common.io.BaseEncoding; +import java.util.Arrays; +import java.math.BigInteger; +import javax.xml.bind.DatatypeConverter; +import static org.bitcoin.NativeSecp256k1Util.*; + +/** + * This class holds test cases defined for testing this library. + */ +public class NativeSecp256k1Test { + + //TODO improve comments/add more tests + /** + * This tests verify() for a valid signature + */ + public static void testVerifyPos() throws AssertFailException{ + boolean result = false; + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + result = NativeSecp256k1.verify( data, sig, pub); + assertEquals( result, true , "testVerifyPos"); + } + + /** + * This tests verify() for a non-valid signature + */ + public static void testVerifyNeg() throws AssertFailException{ + boolean result = false; + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" + byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + result = NativeSecp256k1.verify( data, sig, pub); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, false , "testVerifyNeg"); + } + + /** + * This tests secret key verify() for a valid secretkey + */ + public static void testSecKeyVerifyPos() throws AssertFailException{ + boolean result = false; + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + result = NativeSecp256k1.secKeyVerify( sec ); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, true , "testSecKeyVerifyPos"); + } + + /** + * This tests secret key verify() for an invalid secretkey + */ + public static void testSecKeyVerifyNeg() throws AssertFailException{ + boolean result = false; + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + result = NativeSecp256k1.secKeyVerify( sec ); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, false , "testSecKeyVerifyNeg"); + } + + /** + * This tests public key create() for a valid secretkey + */ + public static void testPubKeyCreatePos() throws AssertFailException{ + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( pubkeyString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "testPubKeyCreatePos"); + } + + /** + * This tests public key create() for a invalid secretkey + */ + public static void testPubKeyCreateNeg() throws AssertFailException{ + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( pubkeyString, "" , "testPubKeyCreateNeg"); + } + + /** + * This tests sign() for a valid secretkey + */ + public static void testSignPos() throws AssertFailException{ + + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.sign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos"); + } + + /** + * This tests sign() for a invalid secretkey + */ + public static void testSignNeg() throws AssertFailException{ + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.sign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "" , "testSignNeg"); + } + + /** + * This tests private key tweak-add + */ + public static void testPrivKeyTweakAdd_1() throws AssertFailException { + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "A168571E189E6F9A7E2D657A4B53AE99B909F7E712D1C23CED28093CD57C88F3" , "testPrivKeyAdd_1"); + } + + /** + * This tests private key tweak-mul + */ + public static void testPrivKeyTweakMul_1() throws AssertFailException { + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "97F8184235F101550F3C71C927507651BD3F1CDB4A5A33B8986ACF0DEE20FFFC" , "testPrivKeyMul_1"); + } + + /** + * This tests private key tweak-add uncompressed + */ + public static void testPrivKeyTweakAdd_2() throws AssertFailException { + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "0411C6790F4B663CCE607BAAE08C43557EDC1A4D11D88DFCB3D841D0C6A941AF525A268E2A863C148555C48FB5FBA368E88718A46E205FABC3DBA2CCFFAB0796EF" , "testPrivKeyAdd_2"); + } + + /** + * This tests private key tweak-mul uncompressed + */ + public static void testPrivKeyTweakMul_2() throws AssertFailException { + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "04E0FE6FE55EBCA626B98A807F6CAF654139E14E5E3698F01A9A658E21DC1D2791EC060D4F412A794D5370F672BC94B722640B5F76914151CFCA6E712CA48CC589" , "testPrivKeyMul_2"); + } + + /** + * This tests seed randomization + */ + public static void testRandomize() throws AssertFailException { + byte[] seed = BaseEncoding.base16().lowerCase().decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()); //sha256hash of "random" + boolean result = NativeSecp256k1.randomize(seed); + assertEquals( result, true, "testRandomize"); + } + + public static void testCreateECDHSecret() throws AssertFailException{ + + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); + String ecdhString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret"); + } + + public static void main(String[] args) throws AssertFailException{ + + + System.out.println("\n libsecp256k1 enabled: " + Secp256k1Context.isEnabled() + "\n"); + + assertEquals( Secp256k1Context.isEnabled(), true, "isEnabled" ); + + //Test verify() success/fail + testVerifyPos(); + testVerifyNeg(); + + //Test secKeyVerify() success/fail + testSecKeyVerifyPos(); + testSecKeyVerifyNeg(); + + //Test computePubkey() success/fail + testPubKeyCreatePos(); + testPubKeyCreateNeg(); + + //Test sign() success/fail + testSignPos(); + testSignNeg(); + + //Test privKeyTweakAdd() 1 + testPrivKeyTweakAdd_1(); + + //Test privKeyTweakMul() 2 + testPrivKeyTweakMul_1(); + + //Test privKeyTweakAdd() 3 + testPrivKeyTweakAdd_2(); + + //Test privKeyTweakMul() 4 + testPrivKeyTweakMul_2(); + + //Test randomize() + testRandomize(); + + //Test ECDH + testCreateECDHSecret(); + + NativeSecp256k1.cleanup(); + + System.out.println(" All tests passed." ); + + } +} diff --git a/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java b/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java new file mode 100644 index 000000000..04732ba04 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java @@ -0,0 +1,45 @@ +/* + * 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 + * + * 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 class AssertFailException extends Exception { + public AssertFailException(String message) { + super( message ); + } + } +} diff --git a/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/Secp256k1Context.java b/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/Secp256k1Context.java new file mode 100644 index 000000000..875950915 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/java/org/bitcoin/Secp256k1Context.java @@ -0,0 +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 + * + * 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"); + contextRef = rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_init_context(); +} diff --git a/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c new file mode 100644 index 000000000..bcfbd8d9c --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c @@ -0,0 +1,379 @@ +#include +#include +#include +#include "org_bitcoin_NativeSecp256k1.h" +#include "include/secp256k1.h" +#include "include/secp256k1_ecdh.h" +#include "include/secp256k1_recovery.h" + + +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ctx_1clone + (JNIEnv* env, jclass classObject, jlong ctx_l) +{ + const rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + + jlong ctx_clone_l = (uintptr_t) rustsecp256k1_v0_1_1_context_clone(ctx); + + (void)classObject;(void)env; + + return ctx_clone_l; + +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1context_1randomize + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + + const unsigned char* seed = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + (void)classObject; + + return rustsecp256k1_v0_1_1_context_randomize(ctx, seed); + +} + +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1destroy_1context + (JNIEnv* env, jclass classObject, jlong ctx_l) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + + rustsecp256k1_v0_1_1_context_destroy(ctx); + + (void)classObject;(void)env; +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ecdsa_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* sigdata = { (unsigned char*) (data + 32) }; + const unsigned char* pubdata = { (unsigned char*) (data + siglen + 32) }; + + rustsecp256k1_v0_1_1_ecdsa_signature sig; + rustsecp256k1_v0_1_1_pubkey pubkey; + + int ret = rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen); + + if( ret ) { + ret = rustsecp256k1_v0_1_1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); + + if( ret ) { + ret = rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, data, &pubkey); + } + } + + (void)classObject; + + return ret; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ecdsa_1sign + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + unsigned char* secKey = (unsigned char*) (data + 32); + + jobjectArray retArray; + jbyteArray sigArray, intsByteArray; + unsigned char intsarray[2]; + + rustsecp256k1_v0_1_1_ecdsa_signature sig[72]; + + int ret = rustsecp256k1_v0_1_1_ecdsa_sign(ctx, sig, data, secKey, NULL, NULL); + + unsigned char outputSer[72]; + size_t outputLen = 72; + + if( ret ) { + int ret2 = rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx,outputSer, &outputLen, sig ); (void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + sigArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ec_1seckey_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + (void)classObject; + + return rustsecp256k1_v0_1_1_ec_seckey_verify(ctx, secKey); +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ec_1pubkey_1create + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + rustsecp256k1_v0_1_1_pubkey pubkey; + + jobjectArray retArray; + jbyteArray pubkeyArray, intsByteArray; + unsigned char intsarray[2]; + + int ret = rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, secKey); + + unsigned char outputSer[65]; + size_t outputLen = 65; + + if( ret ) { + int ret2 = rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubkeyArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; + +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1privkey_1tweak_1add + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (privkey + 32); + + jobjectArray retArray; + jbyteArray privArray, intsByteArray; + unsigned char intsarray[2]; + + int privkeylen = 32; + + int ret = rustsecp256k1_v0_1_1_ec_privkey_tweak_add(ctx, privkey, tweak); + + intsarray[0] = privkeylen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + privArray = (*env)->NewByteArray(env, privkeylen); + (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); + (*env)->SetObjectArrayElement(env, retArray, 0, privArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1privkey_1tweak_1mul + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (privkey + 32); + + jobjectArray retArray; + jbyteArray privArray, intsByteArray; + unsigned char intsarray[2]; + + int privkeylen = 32; + + int ret = rustsecp256k1_v0_1_1_ec_privkey_tweak_mul(ctx, privkey, tweak); + + intsarray[0] = privkeylen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + privArray = (*env)->NewByteArray(env, privkeylen); + (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); + (*env)->SetObjectArrayElement(env, retArray, 0, privArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1pubkey_1tweak_1add + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; +/* rustsecp256k1_v0_1_1_pubkey* pubkey = (rustsecp256k1_v0_1_1_pubkey*) (*env)->GetDirectBufferAddress(env, byteBufferObject);*/ + unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (pkey + publen); + + jobjectArray retArray; + jbyteArray pubArray, intsByteArray; + unsigned char intsarray[2]; + unsigned char outputSer[65]; + size_t outputLen = 65; + + rustsecp256k1_v0_1_1_pubkey pubkey; + int ret = rustsecp256k1_v0_1_1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); + + if( ret ) { + ret = rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, &pubkey, tweak); + } + + if( ret ) { + int ret2 = rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1pubkey_1tweak_1mul + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (pkey + publen); + + jobjectArray retArray; + jbyteArray pubArray, intsByteArray; + unsigned char intsarray[2]; + unsigned char outputSer[65]; + size_t outputLen = 65; + + rustsecp256k1_v0_1_1_pubkey pubkey; + int ret = rustsecp256k1_v0_1_1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); + + if ( ret ) { + ret = rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak); + } + + if( ret ) { + int ret2 = rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ecdsa_1pubkey_1combine + (JNIEnv * env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint numkeys) +{ + (void)classObject;(void)env;(void)byteBufferObject;(void)ctx_l;(void)numkeys; + + return 0; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ecdh + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + rustsecp256k1_v0_1_1_context *ctx = (rustsecp256k1_v0_1_1_context*)(uintptr_t)ctx_l; + const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* pubdata = (const unsigned char*) (secdata + 32); + + jobjectArray retArray; + jbyteArray outArray, intsByteArray; + unsigned char intsarray[1]; + rustsecp256k1_v0_1_1_pubkey pubkey; + unsigned char nonce_res[32]; + size_t outputLen = 32; + + int ret = rustsecp256k1_v0_1_1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); + + if (ret) { + ret = rustsecp256k1_v0_1_1_ecdh( + ctx, + nonce_res, + &pubkey, + secdata, + NULL, + NULL + ); + } + + intsarray[0] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + outArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res); + (*env)->SetObjectArrayElement(env, retArray, 0, outArray); + + intsByteArray = (*env)->NewByteArray(env, 1); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} diff --git a/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h new file mode 100644 index 000000000..9e55b61b4 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h @@ -0,0 +1,119 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#include "include/secp256k1.h" +/* Header for class org_bitcoin_NativeSecp256k1 */ + +#ifndef _Included_org_bitcoin_NativeSecp256k1 +#define _Included_org_bitcoin_NativeSecp256k1 +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_ctx_clone + * Signature: (J)J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ctx_1clone + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_context_randomize + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1context_1randomize + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_privkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1privkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_privkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1privkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_pubkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1pubkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_pubkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1pubkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_destroy_context + * Signature: (J)V + */ +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1destroy_1context + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_ecdsa_verify + * Signature: (Ljava/nio/ByteBuffer;JII)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ecdsa_1verify + (JNIEnv *, jclass, jobject, jlong, jint, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_ecdsa_sign + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ecdsa_1sign + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_ec_seckey_verify + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ec_1seckey_1verify + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_ec_pubkey_create + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ec_1pubkey_1create + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_ec_pubkey_parse + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ec_1pubkey_1parse + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: rustsecp256k1_v0_1_1_ecdh + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_rustsecp256k1_v0_1_1_1ecdh + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_Secp256k1Context.c b/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_Secp256k1Context.c new file mode 100644 index 000000000..94b3e5907 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_Secp256k1Context.c @@ -0,0 +1,15 @@ +#include +#include +#include "org_bitcoin_Secp256k1Context.h" +#include "include/secp256k1.h" + +SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_rustsecp256k1_v0_1_1_1init_1context + (JNIEnv* env, jclass classObject) +{ + rustsecp256k1_v0_1_1_context *ctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + (void)classObject;(void)env; + + return (uintptr_t)ctx; +} + diff --git a/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_Secp256k1Context.h b/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_Secp256k1Context.h new file mode 100644 index 000000000..1c3f4f426 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/java/org_bitcoin_Secp256k1Context.h @@ -0,0 +1,22 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#include "include/secp256k1.h" +/* Header for class org_bitcoin_Secp256k1Context */ + +#ifndef _Included_org_bitcoin_Secp256k1Context +#define _Included_org_bitcoin_Secp256k1Context +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_Secp256k1Context + * Method: rustsecp256k1_v0_1_1_init_context + * Signature: ()J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_rustsecp256k1_v0_1_1_1init_1context + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/depend/secp256k1/src/modules/ecdh/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/Makefile.am.include similarity index 61% rename from depend/secp256k1/src/modules/ecdh/Makefile.am.include rename to secp256k1-sys/depend/secp256k1/src/modules/ecdh/Makefile.am.include index 670b9c115..c08852796 100644 --- a/depend/secp256k1/src/modules/ecdh/Makefile.am.include +++ b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/Makefile.am.include @@ -1,8 +1,8 @@ -include_HEADERS += include/secp256k1_ecdh.h +include_HEADERS += include/rustsecp256k1_v0_1_1_ecdh.h noinst_HEADERS += src/modules/ecdh/main_impl.h noinst_HEADERS += src/modules/ecdh/tests_impl.h if USE_BENCHMARK noinst_PROGRAMS += bench_ecdh bench_ecdh_SOURCES = src/bench_ecdh.c -bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/main_impl.h new file mode 100644 index 000000000..01cf62277 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/main_impl.h @@ -0,0 +1,67 @@ +/********************************************************************** + * 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.* + **********************************************************************/ + +#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 *x, const unsigned char *y, void *data) { + unsigned char version = (y[31] & 0x01) | 0x02; + rustsecp256k1_v0_1_1_sha256 sha; + (void)data; + + rustsecp256k1_v0_1_1_sha256_initialize(&sha); + rustsecp256k1_v0_1_1_sha256_write(&sha, &version, 1); + rustsecp256k1_v0_1_1_sha256_write(&sha, x, 32); + rustsecp256k1_v0_1_1_sha256_finalize(&sha, output); + + return 1; +} + +const rustsecp256k1_v0_1_1_ecdh_hash_function rustsecp256k1_v0_1_1_ecdh_hash_function_sha256 = ecdh_hash_function_sha256; +const rustsecp256k1_v0_1_1_ecdh_hash_function rustsecp256k1_v0_1_1_ecdh_hash_function_default = ecdh_hash_function_sha256; + +int rustsecp256k1_v0_1_1_ecdh(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output, const rustsecp256k1_v0_1_1_pubkey *point, const unsigned char *scalar, rustsecp256k1_v0_1_1_ecdh_hash_function hashfp, void *data) { + int ret = 0; + int overflow = 0; + rustsecp256k1_v0_1_1_gej res; + rustsecp256k1_v0_1_1_ge pt; + rustsecp256k1_v0_1_1_scalar s; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output != NULL); + ARG_CHECK(point != NULL); + ARG_CHECK(scalar != NULL); + if (hashfp == NULL) { + hashfp = rustsecp256k1_v0_1_1_ecdh_hash_function_default; + } + + rustsecp256k1_v0_1_1_pubkey_load(ctx, &pt, point); + rustsecp256k1_v0_1_1_scalar_set_b32(&s, scalar, &overflow); + if (overflow || rustsecp256k1_v0_1_1_scalar_is_zero(&s)) { + ret = 0; + } else { + unsigned char x[32]; + unsigned char y[32]; + + rustsecp256k1_v0_1_1_ecmult_const(&res, &pt, &s, 256); + rustsecp256k1_v0_1_1_ge_set_gej(&pt, &res); + + /* Compute a hash of the point */ + rustsecp256k1_v0_1_1_fe_normalize(&pt.x); + rustsecp256k1_v0_1_1_fe_normalize(&pt.y); + rustsecp256k1_v0_1_1_fe_get_b32(x, &pt.x); + rustsecp256k1_v0_1_1_fe_get_b32(y, &pt.y); + + ret = hashfp(output, x, y, data); + } + + rustsecp256k1_v0_1_1_scalar_clear(&s); + return ret; +} + +#endif /* SECP256K1_MODULE_ECDH_MAIN_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/tests_impl.h new file mode 100644 index 000000000..fe8d59930 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/tests_impl.h @@ -0,0 +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.* + **********************************************************************/ + +#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 */ + rustsecp256k1_v0_1_1_context *tctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN); + rustsecp256k1_v0_1_1_pubkey point; + unsigned char res[32]; + unsigned char s_one[32] = { 0 }; + int32_t ecount = 0; + s_one[31] = 1; + + rustsecp256k1_v0_1_1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(tctx, &point, s_one) == 1); + + /* Check all NULLs are detected */ + CHECK(rustsecp256k1_v0_1_1_ecdh(tctx, res, &point, s_one, NULL, NULL) == 1); + CHECK(ecount == 0); + CHECK(rustsecp256k1_v0_1_1_ecdh(tctx, NULL, &point, s_one, NULL, NULL) == 0); + CHECK(ecount == 1); + CHECK(rustsecp256k1_v0_1_1_ecdh(tctx, res, NULL, s_one, NULL, NULL) == 0); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ecdh(tctx, res, &point, NULL, NULL, NULL) == 0); + CHECK(ecount == 3); + CHECK(rustsecp256k1_v0_1_1_ecdh(tctx, res, &point, s_one, NULL, NULL) == 1); + CHECK(ecount == 3); + + /* Cleanup */ + rustsecp256k1_v0_1_1_context_destroy(tctx); +} + +void test_ecdh_generator_basepoint(void) { + unsigned char s_one[32] = { 0 }; + rustsecp256k1_v0_1_1_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) { + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar s; + + random_scalar_order(&s); + rustsecp256k1_v0_1_1_scalar_get_b32(s_b32, &s); + + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &point[0], s_one) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); + + /* compute using ECDH function with custom hash function */ + CHECK(rustsecp256k1_v0_1_1_ecdh(ctx, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1); + /* compute "explicitly" */ + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1); + /* compare */ + CHECK(memcmp(output_ecdh, point_ser, 65) == 0); + + /* compute using ECDH function with default hash function */ + CHECK(rustsecp256k1_v0_1_1_ecdh(ctx, output_ecdh, &point[0], s_b32, NULL, NULL) == 1); + /* compute "explicitly" */ + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); + rustsecp256k1_v0_1_1_sha256_initialize(&sha); + rustsecp256k1_v0_1_1_sha256_write(&sha, point_ser, point_ser_len); + rustsecp256k1_v0_1_1_sha256_finalize(&sha, output_ser); + /* compare */ + CHECK(memcmp(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]; + rustsecp256k1_v0_1_1_scalar rand; + rustsecp256k1_v0_1_1_pubkey point; + + /* Create random point */ + random_scalar_order(&rand); + rustsecp256k1_v0_1_1_scalar_get_b32(s_rand, &rand); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &point, s_rand) == 1); + + /* Try to multiply it by bad values */ + CHECK(rustsecp256k1_v0_1_1_ecdh(ctx, output, &point, s_zero, NULL, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdh(ctx, output, &point, s_overflow, NULL, NULL) == 0); + /* ...and a good one */ + s_overflow[31] -= 1; + CHECK(rustsecp256k1_v0_1_1_ecdh(ctx, output, &point, s_overflow, NULL, NULL) == 1); + + /* Hash function failure results in ecdh failure */ + CHECK(rustsecp256k1_v0_1_1_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/depend/secp256k1/src/modules/recovery/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/recovery/Makefile.am.include similarity index 62% rename from depend/secp256k1/src/modules/recovery/Makefile.am.include rename to secp256k1-sys/depend/secp256k1/src/modules/recovery/Makefile.am.include index 5de3ea33e..0aefe7476 100644 --- a/depend/secp256k1/src/modules/recovery/Makefile.am.include +++ b/secp256k1-sys/depend/secp256k1/src/modules/recovery/Makefile.am.include @@ -1,8 +1,8 @@ -include_HEADERS += include/secp256k1_recovery.h +include_HEADERS += include/rustsecp256k1_v0_1_1_recovery.h noinst_HEADERS += src/modules/recovery/main_impl.h noinst_HEADERS += src/modules/recovery/tests_impl.h if USE_BENCHMARK noinst_PROGRAMS += bench_recover bench_recover_SOURCES = src/bench_recover.c -bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) +bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/recovery/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/recovery/main_impl.h new file mode 100755 index 000000000..45e1531ec --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/recovery/main_impl.h @@ -0,0 +1,193 @@ +/********************************************************************** + * 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.* + **********************************************************************/ + +#ifndef SECP256K1_MODULE_RECOVERY_MAIN_H +#define SECP256K1_MODULE_RECOVERY_MAIN_H + +#include "include/secp256k1_recovery.h" + +static void rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_load(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_scalar* r, rustsecp256k1_v0_1_1_scalar* s, int* recid, const rustsecp256k1_v0_1_1_ecdsa_recoverable_signature* sig) { + (void)ctx; + if (sizeof(rustsecp256k1_v0_1_1_scalar) == 32) { + /* When the rustsecp256k1_v0_1_1_scalar type is exactly 32 byte, use its + * representation inside rustsecp256k1_v0_1_1_ecdsa_signature, as conversion is very fast. + * Note that rustsecp256k1_v0_1_1_ecdsa_signature_save must use the same representation. */ + memcpy(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); + } else { + rustsecp256k1_v0_1_1_scalar_set_b32(r, &sig->data[0], NULL); + rustsecp256k1_v0_1_1_scalar_set_b32(s, &sig->data[32], NULL); + } + *recid = sig->data[64]; +} + +static void rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_save(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature* sig, const rustsecp256k1_v0_1_1_scalar* r, const rustsecp256k1_v0_1_1_scalar* s, int recid) { + if (sizeof(rustsecp256k1_v0_1_1_scalar) == 32) { + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); + } else { + rustsecp256k1_v0_1_1_scalar_get_b32(&sig->data[0], r); + rustsecp256k1_v0_1_1_scalar_get_b32(&sig->data[32], s); + } + sig->data[64] = recid; +} + +int rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { + rustsecp256k1_v0_1_1_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); + + rustsecp256k1_v0_1_1_scalar_set_b32(&r, &input64[0], &overflow); + ret &= !overflow; + rustsecp256k1_v0_1_1_scalar_set_b32(&s, &input64[32], &overflow); + ret &= !overflow; + if (ret) { + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); + } else { + memset(sig, 0, sizeof(*sig)); + } + return ret; +} + +int rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output64, int *recid, const rustsecp256k1_v0_1_1_ecdsa_recoverable_signature* sig) { + rustsecp256k1_v0_1_1_scalar r, s; + + (void)ctx; + ARG_CHECK(output64 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(recid != NULL); + + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); + rustsecp256k1_v0_1_1_scalar_get_b32(&output64[0], &r); + rustsecp256k1_v0_1_1_scalar_get_b32(&output64[32], &s); + return 1; +} + +int rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ecdsa_signature* sig, const rustsecp256k1_v0_1_1_ecdsa_recoverable_signature* sigin) { + rustsecp256k1_v0_1_1_scalar r, s; + int recid; + + (void)ctx; + ARG_CHECK(sig != NULL); + ARG_CHECK(sigin != NULL); + + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); + rustsecp256k1_v0_1_1_ecdsa_signature_save(sig, &r, &s); + return 1; +} + +static int rustsecp256k1_v0_1_1_ecdsa_sig_recover(const rustsecp256k1_v0_1_1_ecmult_context *ctx, const rustsecp256k1_v0_1_1_scalar *sigr, const rustsecp256k1_v0_1_1_scalar* sigs, rustsecp256k1_v0_1_1_ge *pubkey, const rustsecp256k1_v0_1_1_scalar *message, int recid) { + unsigned char brx[32]; + rustsecp256k1_v0_1_1_fe fx; + rustsecp256k1_v0_1_1_ge x; + rustsecp256k1_v0_1_1_gej xj; + rustsecp256k1_v0_1_1_scalar rn, u1, u2; + rustsecp256k1_v0_1_1_gej qj; + int r; + + if (rustsecp256k1_v0_1_1_scalar_is_zero(sigr) || rustsecp256k1_v0_1_1_scalar_is_zero(sigs)) { + return 0; + } + + rustsecp256k1_v0_1_1_scalar_get_b32(brx, sigr); + r = rustsecp256k1_v0_1_1_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 (rustsecp256k1_v0_1_1_fe_cmp_var(&fx, &rustsecp256k1_v0_1_1_ecdsa_const_p_minus_order) >= 0) { + return 0; + } + rustsecp256k1_v0_1_1_fe_add(&fx, &rustsecp256k1_v0_1_1_ecdsa_const_order_as_fe); + } + if (!rustsecp256k1_v0_1_1_ge_set_xo_var(&x, &fx, recid & 1)) { + return 0; + } + rustsecp256k1_v0_1_1_gej_set_ge(&xj, &x); + rustsecp256k1_v0_1_1_scalar_inverse_var(&rn, sigr); + rustsecp256k1_v0_1_1_scalar_mul(&u1, &rn, message); + rustsecp256k1_v0_1_1_scalar_negate(&u1, &u1); + rustsecp256k1_v0_1_1_scalar_mul(&u2, &rn, sigs); + rustsecp256k1_v0_1_1_ecmult(ctx, &qj, &xj, &u2, &u1); + rustsecp256k1_v0_1_1_ge_set_gej_var(pubkey, &qj); + return !rustsecp256k1_v0_1_1_gej_is_infinity(&qj); +} + +int rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, rustsecp256k1_v0_1_1_nonce_function noncefp, const void* noncedata) { + rustsecp256k1_v0_1_1_scalar r, s; + rustsecp256k1_v0_1_1_scalar sec, non, msg; + int recid; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_1_1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(seckey != NULL); + if (noncefp == NULL) { + noncefp = rustsecp256k1_v0_1_1_nonce_function_default; + } + + rustsecp256k1_v0_1_1_scalar_set_b32(&sec, seckey, &overflow); + /* Fail if the secret key is invalid. */ + if (!overflow && !rustsecp256k1_v0_1_1_scalar_is_zero(&sec)) { + unsigned char nonce32[32]; + unsigned int count = 0; + rustsecp256k1_v0_1_1_scalar_set_b32(&msg, msg32, NULL); + while (1) { + ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + if (!ret) { + break; + } + rustsecp256k1_v0_1_1_scalar_set_b32(&non, nonce32, &overflow); + if (!rustsecp256k1_v0_1_1_scalar_is_zero(&non) && !overflow) { + if (rustsecp256k1_v0_1_1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { + break; + } + } + count++; + } + memset(nonce32, 0, 32); + rustsecp256k1_v0_1_1_scalar_clear(&msg); + rustsecp256k1_v0_1_1_scalar_clear(&non); + rustsecp256k1_v0_1_1_scalar_clear(&sec); + } + if (ret) { + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); + } else { + memset(signature, 0, sizeof(*signature)); + } + return ret; +} + +int rustsecp256k1_v0_1_1_ecdsa_recover(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_pubkey *pubkey, const rustsecp256k1_v0_1_1_ecdsa_recoverable_signature *signature, const unsigned char *msg32) { + rustsecp256k1_v0_1_1_ge q; + rustsecp256k1_v0_1_1_scalar r, s; + rustsecp256k1_v0_1_1_scalar m; + int recid; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_1_1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(pubkey != NULL); + + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); + VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ + rustsecp256k1_v0_1_1_scalar_set_b32(&m, msg32, NULL); + if (rustsecp256k1_v0_1_1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { + rustsecp256k1_v0_1_1_pubkey_save(pubkey, &q); + return 1; + } else { + memset(pubkey, 0, sizeof(*pubkey)); + return 0; + } +} + +#endif /* SECP256K1_MODULE_RECOVERY_MAIN_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_impl.h new file mode 100644 index 000000000..c531517eb --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_impl.h @@ -0,0 +1,393 @@ +/********************************************************************** + * 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.* + **********************************************************************/ + +#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 rustsecp256k1_v0_1_1_rand_bits(1); +} + +void test_ecdsa_recovery_api(void) { + /* Setup contexts that just count errors */ + rustsecp256k1_v0_1_1_context *none = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_NONE); + rustsecp256k1_v0_1_1_context *sign = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN); + rustsecp256k1_v0_1_1_context *vrfy = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_VERIFY); + rustsecp256k1_v0_1_1_context *both = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + rustsecp256k1_v0_1_1_pubkey pubkey; + rustsecp256k1_v0_1_1_pubkey recpubkey; + rustsecp256k1_v0_1_1_ecdsa_signature normal_sig; + rustsecp256k1_v0_1_1_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 }; + + rustsecp256k1_v0_1_1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); + + /* Construct and verify corresponding public key. */ + CHECK(rustsecp256k1_v0_1_1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Check bad contexts and NULLs for signing */ + ecount = 0; + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 3); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); + CHECK(ecount == 4); + CHECK(rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); + /* This one will succeed. */ + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(both, NULL, &recsig, message) == 0); + CHECK(ecount == 3); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); + CHECK(ecount == 4); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); + CHECK(ecount == 5); + + /* Check NULLs for conversion */ + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); + CHECK(ecount == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); + + /* Check NULLs for de/serialization */ + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); + CHECK(ecount == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); + CHECK(ecount == 3); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); + + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); + CHECK(ecount == 4); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); + CHECK(ecount == 5); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); + CHECK(ecount == 6); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); + CHECK(ecount == 7); + + /* cleanup */ + rustsecp256k1_v0_1_1_context_destroy(none); + rustsecp256k1_v0_1_1_context_destroy(sign); + rustsecp256k1_v0_1_1_context_destroy(vrfy); + rustsecp256k1_v0_1_1_context_destroy(both); +} + +void test_ecdsa_recovery_end_to_end(void) { + unsigned char extra[32] = {0x00}; + unsigned char privkey[32]; + unsigned char message[32]; + rustsecp256k1_v0_1_1_ecdsa_signature signature[5]; + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature rsignature[5]; + unsigned char sig[74]; + rustsecp256k1_v0_1_1_pubkey pubkey; + rustsecp256k1_v0_1_1_pubkey recpubkey; + int recid = 0; + + /* Generate a random key and message. */ + { + rustsecp256k1_v0_1_1_scalar msg, key; + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + rustsecp256k1_v0_1_1_scalar_get_b32(privkey, &key); + rustsecp256k1_v0_1_1_scalar_get_b32(message, &msg); + } + + /* Construct and verify corresponding public key. */ + CHECK(rustsecp256k1_v0_1_1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Serialize/parse compact and verify/recover. */ + extra[0] = 0; + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(ctx, &rsignature[0], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(ctx, &rsignature[4], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(ctx, &rsignature[1], message, privkey, NULL, extra) == 1); + extra[31] = 1; + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(ctx, &rsignature[2], message, privkey, NULL, extra) == 1); + extra[31] = 0; + extra[0] = 1; + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(memcmp(&signature[4], &signature[0], 64) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); + memset(&rsignature[4], 0, sizeof(rsignature[4])); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); + /* Parse compact (with recovery id) and recover. */ + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1); + CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); + /* Serialize/destroy/parse signature and verify again. */ + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); + sig[rustsecp256k1_v0_1_1_rand_bits(6)] += 1 + rustsecp256k1_v0_1_1_rand_int(255); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0); + /* Recover again */ + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 || + memcmp(&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 0. */ + 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 + }; + rustsecp256k1_v0_1_1_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, + }; + rustsecp256k1_v0_1_1_pubkey pubkeyb; + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature rsig; + rustsecp256k1_v0_1_1_ecdsa_signature sig; + int recid; + + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 0)); + CHECK(!rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 1)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 2)); + CHECK(!rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 3)); + CHECK(!rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); + for (recid2 = 0; recid2 < 4; recid2++) { + rustsecp256k1_v0_1_1_pubkey pubkey2b; + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &pubkey2b, &rsig, msg32) == 1); + /* Verifying with (order + r,4) should always fail. */ + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + } + /* DER parsing tests. */ + /* Zero length r/s. */ + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); + /* Leading zeros. */ + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); + sigbderalt3[4] = 1; + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + sigbderalt4[7] = 1; + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + /* Damage signature. */ + sigbder[7]++; + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + sigbder[7]--; + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbder, 6) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || rustsecp256k1_v0_1_1_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, + }; + rustsecp256k1_v0_1_1_pubkey pubkeyc; + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &pubkeyc, &rsig, msg32) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 1); + sigcder[4] = 0; + sigc64[31] = 0; + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); + sigcder[4] = 1; + sigcder[7] = 0; + sigc64[31] = 1; + sigc64[63] = 0; + CHECK(rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(rustsecp256k1_v0_1_1_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/secp256k1-sys/depend/secp256k1/src/num.h b/secp256k1-sys/depend/secp256k1/src/num.h new file mode 100644 index 000000000..0d7f3a171 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/num.h @@ -0,0 +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.* + **********************************************************************/ + +#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 rustsecp256k1_v0_1_1_num_copy(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a); + +/** Convert a number's absolute value to a binary big-endian string. + * There must be enough place. */ +static void rustsecp256k1_v0_1_1_num_get_bin(unsigned char *r, unsigned int rlen, const rustsecp256k1_v0_1_1_num *a); + +/** Set a number to the value of a binary big-endian string. */ +static void rustsecp256k1_v0_1_1_num_set_bin(rustsecp256k1_v0_1_1_num *r, const unsigned char *a, unsigned int alen); + +/** Compute a modular inverse. The input must be less than the modulus. */ +static void rustsecp256k1_v0_1_1_num_mod_inverse(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *m); + +/** Compute the jacobi symbol (a|b). b must be positive and odd. */ +static int rustsecp256k1_v0_1_1_num_jacobi(const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b); + +/** Compare the absolute value of two numbers. */ +static int rustsecp256k1_v0_1_1_num_cmp(const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b); + +/** Test whether two number are equal (including sign). */ +static int rustsecp256k1_v0_1_1_num_eq(const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b); + +/** Add two (signed) numbers. */ +static void rustsecp256k1_v0_1_1_num_add(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b); + +/** Subtract two (signed) numbers. */ +static void rustsecp256k1_v0_1_1_num_sub(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b); + +/** Multiply two (signed) numbers. */ +static void rustsecp256k1_v0_1_1_num_mul(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_num_mod(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *m); + +/** Right-shift the passed number by bits bits. */ +static void rustsecp256k1_v0_1_1_num_shift(rustsecp256k1_v0_1_1_num *r, int bits); + +/** Check whether a number is zero. */ +static int rustsecp256k1_v0_1_1_num_is_zero(const rustsecp256k1_v0_1_1_num *a); + +/** Check whether a number is one. */ +static int rustsecp256k1_v0_1_1_num_is_one(const rustsecp256k1_v0_1_1_num *a); + +/** Check whether a number is strictly negative. */ +static int rustsecp256k1_v0_1_1_num_is_neg(const rustsecp256k1_v0_1_1_num *a); + +/** Change a number's sign. */ +static void rustsecp256k1_v0_1_1_num_negate(rustsecp256k1_v0_1_1_num *r); + +#endif + +#endif /* SECP256K1_NUM_H */ diff --git a/depend/secp256k1/src/num_gmp.h b/secp256k1-sys/depend/secp256k1/src/num_gmp.h similarity index 81% rename from depend/secp256k1/src/num_gmp.h rename to secp256k1-sys/depend/secp256k1/src/num_gmp.h index 7dd813088..ab26525cd 100644 --- a/depend/secp256k1/src/num_gmp.h +++ b/secp256k1-sys/depend/secp256k1/src/num_gmp.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_NUM_REPR_ -#define _SECP256K1_NUM_REPR_ +#ifndef SECP256K1_NUM_REPR_H +#define SECP256K1_NUM_REPR_H #include @@ -15,6 +15,6 @@ typedef struct { mp_limb_t data[2*NUM_LIMBS]; int neg; int limbs; -} secp256k1_num; +} rustsecp256k1_v0_1_1_num; -#endif +#endif /* SECP256K1_NUM_REPR_H */ diff --git a/depend/secp256k1/src/num_gmp_impl.h b/secp256k1-sys/depend/secp256k1/src/num_gmp_impl.h similarity index 57% rename from depend/secp256k1/src/num_gmp_impl.h rename to secp256k1-sys/depend/secp256k1/src/num_gmp_impl.h index 7b6a89719..21d35962f 100644 --- a/depend/secp256k1/src/num_gmp_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/num_gmp_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_NUM_REPR_IMPL_H_ -#define _SECP256K1_NUM_REPR_IMPL_H_ +#ifndef SECP256K1_NUM_REPR_IMPL_H +#define SECP256K1_NUM_REPR_IMPL_H #include #include @@ -15,18 +15,18 @@ #include "num.h" #ifdef VERIFY -static void secp256k1_num_sanity(const secp256k1_num *a) { +static void rustsecp256k1_v0_1_1_num_sanity(const rustsecp256k1_v0_1_1_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) +#define rustsecp256k1_v0_1_1_num_sanity(a) do { } while(0) #endif -static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a) { +static void rustsecp256k1_v0_1_1_num_copy(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a) { *r = *a; } -static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a) { +static void rustsecp256k1_v0_1_1_num_get_bin(unsigned char *r, unsigned int rlen, const rustsecp256k1_v0_1_1_num *a) { unsigned char tmp[65]; int len = 0; int shift = 0; @@ -42,7 +42,7 @@ static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const sec memset(tmp, 0, sizeof(tmp)); } -static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) { +static void rustsecp256k1_v0_1_1_num_set_bin(rustsecp256k1_v0_1_1_num *r, const unsigned char *a, unsigned int alen) { int len; VERIFY_CHECK(alen > 0); VERIFY_CHECK(alen <= 64); @@ -59,7 +59,7 @@ static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsi } } -static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { +static void rustsecp256k1_v0_1_1_num_add_abs(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_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) { @@ -68,7 +68,7 @@ static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, cons } } -static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { +static void rustsecp256k1_v0_1_1_num_sub_abs(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b) { mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); (void)c; VERIFY_CHECK(c == 0); @@ -78,9 +78,9 @@ static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, cons } } -static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) { - secp256k1_num_sanity(r); - secp256k1_num_sanity(m); +static void rustsecp256k1_v0_1_1_num_mod(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *m) { + rustsecp256k1_v0_1_1_num_sanity(r); + rustsecp256k1_v0_1_1_num_sanity(m); if (r->limbs >= m->limbs) { mp_limb_t t[2*NUM_LIMBS]; @@ -93,20 +93,20 @@ static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) { } if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { - secp256k1_num_sub_abs(r, m, r); + rustsecp256k1_v0_1_1_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) { +static void rustsecp256k1_v0_1_1_num_mod_inverse(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_num_sanity(a); + rustsecp256k1_v0_1_1_num_sanity(m); /** mpn_gcdext computes: (G,S) = gcdext(U,V), where * * G = gcd(U,V) @@ -144,15 +144,41 @@ static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, memset(v, 0, sizeof(v)); } -static int secp256k1_num_is_zero(const secp256k1_num *a) { +static int rustsecp256k1_v0_1_1_num_jacobi(const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b) { + int ret; + mpz_t ga, gb; + rustsecp256k1_v0_1_1_num_sanity(a); + rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_num_is_one(const rustsecp256k1_v0_1_1_num *a) { + return (a->limbs == 1 && a->data[0] == 1); +} + +static int rustsecp256k1_v0_1_1_num_is_zero(const rustsecp256k1_v0_1_1_num *a) { return (a->limbs == 1 && a->data[0] == 0); } -static int secp256k1_num_is_neg(const secp256k1_num *a) { +static int rustsecp256k1_v0_1_1_num_is_neg(const rustsecp256k1_v0_1_1_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) { +static int rustsecp256k1_v0_1_1_num_cmp(const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b) { if (a->limbs > b->limbs) { return 1; } @@ -162,54 +188,54 @@ static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b) { return mpn_cmp(a->data, b->data, a->limbs); } -static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b) { +static int rustsecp256k1_v0_1_1_num_eq(const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_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))) { + if ((a->neg && !rustsecp256k1_v0_1_1_num_is_zero(a)) != (b->neg && !rustsecp256k1_v0_1_1_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) { +static void rustsecp256k1_v0_1_1_num_subadd(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_num_add_abs(r, a, b); } else { - secp256k1_num_add_abs(r, b, a); + rustsecp256k1_v0_1_1_num_add_abs(r, b, a); } } else { - if (secp256k1_num_cmp(a, b) > 0) { + if (rustsecp256k1_v0_1_1_num_cmp(a, b) > 0) { r->neg = a->neg; - secp256k1_num_sub_abs(r, a, b); + rustsecp256k1_v0_1_1_num_sub_abs(r, a, b); } else { r->neg = b->neg ^ bneg; - secp256k1_num_sub_abs(r, b, a); + rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_num_add(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b) { + rustsecp256k1_v0_1_1_num_sanity(a); + rustsecp256k1_v0_1_1_num_sanity(b); + rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_num_sub(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b) { + rustsecp256k1_v0_1_1_num_sanity(a); + rustsecp256k1_v0_1_1_num_sanity(b); + rustsecp256k1_v0_1_1_num_subadd(r, a, b, 1); } -static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { +static void rustsecp256k1_v0_1_1_num_mul(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_num *a, const rustsecp256k1_v0_1_1_num *b) { mp_limb_t tmp[2*NUM_LIMBS+1]; - secp256k1_num_sanity(a); - secp256k1_num_sanity(b); + rustsecp256k1_v0_1_1_num_sanity(a); + rustsecp256k1_v0_1_1_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)) { @@ -233,7 +259,7 @@ static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const se memset(tmp, 0, sizeof(tmp)); } -static void secp256k1_num_shift(secp256k1_num *r, int bits) { +static void rustsecp256k1_v0_1_1_num_shift(rustsecp256k1_v0_1_1_num *r, int bits) { if (bits % GMP_NUMB_BITS) { /* Shift within limbs. */ mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS); @@ -255,8 +281,8 @@ static void secp256k1_num_shift(secp256k1_num *r, int bits) { } } -static void secp256k1_num_negate(secp256k1_num *r) { +static void rustsecp256k1_v0_1_1_num_negate(rustsecp256k1_v0_1_1_num *r) { r->neg ^= 1; } -#endif +#endif /* SECP256K1_NUM_REPR_IMPL_H */ diff --git a/depend/secp256k1/src/num_impl.h b/secp256k1-sys/depend/secp256k1/src/num_impl.h similarity index 86% rename from depend/secp256k1/src/num_impl.h rename to secp256k1-sys/depend/secp256k1/src/num_impl.h index 0b0e3a072..c45193b03 100644 --- a/depend/secp256k1/src/num_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/num_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_NUM_IMPL_H_ -#define _SECP256K1_NUM_IMPL_H_ +#ifndef SECP256K1_NUM_IMPL_H +#define SECP256K1_NUM_IMPL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -21,4 +21,4 @@ #error "Please select num implementation" #endif -#endif +#endif /* SECP256K1_NUM_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/scalar.h b/secp256k1-sys/depend/secp256k1/src/scalar.h new file mode 100644 index 000000000..3292b1a10 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/scalar.h @@ -0,0 +1,106 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_SCALAR_H +#define SECP256K1_SCALAR_H + +#include "num.h" + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(EXHAUSTIVE_TEST_ORDER) +#include "scalar_low.h" +#elif defined(USE_SCALAR_4X64) +#include "scalar_4x64.h" +#elif defined(USE_SCALAR_8X32) +#include "scalar_8x32.h" +#else +#error "Please select scalar implementation" +#endif + +/** Clear a scalar to prevent the leak of sensitive data. */ +static void rustsecp256k1_v0_1_1_scalar_clear(rustsecp256k1_v0_1_1_scalar *r); + +/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ +static unsigned int rustsecp256k1_v0_1_1_scalar_get_bits(const rustsecp256k1_v0_1_1_scalar *a, unsigned int offset, unsigned int count); + +/** Access bits from a scalar. Not constant time. */ +static unsigned int rustsecp256k1_v0_1_1_scalar_get_bits_var(const rustsecp256k1_v0_1_1_scalar *a, unsigned int offset, unsigned int count); + +/** Set a scalar from a big endian byte array. */ +static void rustsecp256k1_v0_1_1_scalar_set_b32(rustsecp256k1_v0_1_1_scalar *r, const unsigned char *bin, int *overflow); + +/** Set a scalar to an unsigned integer. */ +static void rustsecp256k1_v0_1_1_scalar_set_int(rustsecp256k1_v0_1_1_scalar *r, unsigned int v); + +/** Convert a scalar to a byte array. */ +static void rustsecp256k1_v0_1_1_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_1_1_scalar* a); + +/** Add two scalars together (modulo the group order). Returns whether it overflowed. */ +static int rustsecp256k1_v0_1_1_scalar_add(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b); + +/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ +static void rustsecp256k1_v0_1_1_scalar_cadd_bit(rustsecp256k1_v0_1_1_scalar *r, unsigned int bit, int flag); + +/** Multiply two scalars (modulo the group order). */ +static void rustsecp256k1_v0_1_1_scalar_mul(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b); + +/** Shift a scalar right by some amount strictly between 0 and 16, returning + * the low bits that were shifted off */ +static int rustsecp256k1_v0_1_1_scalar_shr_int(rustsecp256k1_v0_1_1_scalar *r, int n); + +/** Compute the square of a scalar (modulo the group order). */ +static void rustsecp256k1_v0_1_1_scalar_sqr(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a); + +/** Compute the inverse of a scalar (modulo the group order). */ +static void rustsecp256k1_v0_1_1_scalar_inverse(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a); + +/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ +static void rustsecp256k1_v0_1_1_scalar_inverse_var(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a); + +/** Compute the complement of a scalar (modulo the group order). */ +static void rustsecp256k1_v0_1_1_scalar_negate(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a); + +/** Check whether a scalar equals zero. */ +static int rustsecp256k1_v0_1_1_scalar_is_zero(const rustsecp256k1_v0_1_1_scalar *a); + +/** Check whether a scalar equals one. */ +static int rustsecp256k1_v0_1_1_scalar_is_one(const rustsecp256k1_v0_1_1_scalar *a); + +/** Check whether a scalar, considered as an nonnegative integer, is even. */ +static int rustsecp256k1_v0_1_1_scalar_is_even(const rustsecp256k1_v0_1_1_scalar *a); + +/** Check whether a scalar is higher than the group order divided by 2. */ +static int rustsecp256k1_v0_1_1_scalar_is_high(const rustsecp256k1_v0_1_1_scalar *a); + +/** Conditionally negate a number, in constant time. + * Returns -1 if the number was negated, 1 otherwise */ +static int rustsecp256k1_v0_1_1_scalar_cond_negate(rustsecp256k1_v0_1_1_scalar *a, int flag); + +#ifndef USE_NUM_NONE +/** Convert a scalar to a number. */ +static void rustsecp256k1_v0_1_1_scalar_get_num(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_scalar *a); + +/** Get the order of the group as a number. */ +static void rustsecp256k1_v0_1_1_scalar_order_get_num(rustsecp256k1_v0_1_1_num *r); +#endif + +/** Compare two scalars. */ +static int rustsecp256k1_v0_1_1_scalar_eq(const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b); + +#ifdef USE_ENDOMORPHISM +/** Find r1 and r2 such that r1+r2*2^128 = a. */ +static void rustsecp256k1_v0_1_1_scalar_split_128(rustsecp256k1_v0_1_1_scalar *r1, rustsecp256k1_v0_1_1_scalar *r2, const rustsecp256k1_v0_1_1_scalar *a); +/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see rustsecp256k1_v0_1_1_gej_mul_lambda). */ +static void rustsecp256k1_v0_1_1_scalar_split_lambda(rustsecp256k1_v0_1_1_scalar *r1, rustsecp256k1_v0_1_1_scalar *r2, const rustsecp256k1_v0_1_1_scalar *a); +#endif + +/** 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 rustsecp256k1_v0_1_1_scalar_mul_shift_var(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b, unsigned int shift); + +#endif /* SECP256K1_SCALAR_H */ diff --git a/depend/secp256k1/src/scalar_4x64.h b/secp256k1-sys/depend/secp256k1/src/scalar_4x64.h similarity index 83% rename from depend/secp256k1/src/scalar_4x64.h rename to secp256k1-sys/depend/secp256k1/src/scalar_4x64.h index cff406038..2e092eab0 100644 --- a/depend/secp256k1/src/scalar_4x64.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_4x64.h @@ -4,16 +4,16 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ +#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; +} rustsecp256k1_v0_1_1_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 +#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/depend/secp256k1/src/scalar_4x64_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h similarity index 85% rename from depend/secp256k1/src/scalar_4x64_impl.h rename to secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h index aa2703dd2..f2602eb0b 100644 --- a/depend/secp256k1/src/scalar_4x64_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ +#ifndef SECP256K1_SCALAR_REPR_IMPL_H +#define SECP256K1_SCALAR_REPR_IMPL_H /* Limbs of the secp256k1 order. */ #define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) @@ -24,37 +24,37 @@ #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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_scalar_clear(rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_scalar_set_int(rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static unsigned int rustsecp256k1_v0_1_1_scalar_get_bits(const rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static unsigned int rustsecp256k1_v0_1_1_scalar_get_bits_var(const rustsecp256k1_v0_1_1_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); + return rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_check_overflow(const rustsecp256k1_v0_1_1_scalar *a) { int yes = 0; int no = 0; no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ @@ -66,7 +66,7 @@ SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scal return yes; } -SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_reduce(rustsecp256k1_v0_1_1_scalar *r, unsigned int overflow) { uint128_t t; VERIFY_CHECK(overflow <= 1); t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0; @@ -80,7 +80,7 @@ SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigne return overflow; } -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { +static int rustsecp256k1_v0_1_1_scalar_add(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { int overflow; uint128_t t = (uint128_t)a->d[0] + b->d[0]; r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; @@ -90,13 +90,13 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, 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); + overflow = t + rustsecp256k1_v0_1_1_scalar_check_overflow(r); VERIFY_CHECK(overflow == 0 || overflow == 1); - secp256k1_scalar_reduce(r, overflow); + rustsecp256k1_v0_1_1_scalar_reduce(r, overflow); return overflow; } -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { +static void rustsecp256k1_v0_1_1_scalar_cadd_bit(rustsecp256k1_v0_1_1_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 */ @@ -110,35 +110,35 @@ static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; #ifdef VERIFY VERIFY_CHECK((t >> 64) == 0); - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); + VERIFY_CHECK(rustsecp256k1_v0_1_1_scalar_check_overflow(r) == 0); #endif } -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { +static void rustsecp256k1_v0_1_1_scalar_set_b32(rustsecp256k1_v0_1_1_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)); + over = rustsecp256k1_v0_1_1_scalar_reduce(r, rustsecp256k1_v0_1_1_scalar_check_overflow(r)); if (overflow) { *overflow = over; } } -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { +static void rustsecp256k1_v0_1_1_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_is_zero(const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_scalar_negate(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a) { + uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (rustsecp256k1_v0_1_1_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; @@ -149,11 +149,11 @@ static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar r->d[3] = t & nonzero; } -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_is_one(const rustsecp256k1_v0_1_1_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) { +static int rustsecp256k1_v0_1_1_scalar_is_high(const rustsecp256k1_v0_1_1_scalar *a) { int yes = 0; int no = 0; no |= (a->d[3] < SECP256K1_N_H_3); @@ -165,11 +165,11 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { return yes; } -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { +static int rustsecp256k1_v0_1_1_scalar_cond_negate(rustsecp256k1_v0_1_1_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 */ + * if we are flag = 1, mask = 11...11 and this is identical to rustsecp256k1_v0_1_1_scalar_negate */ uint64_t mask = !flag - 1; - uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1; + uint64_t nonzero = (rustsecp256k1_v0_1_1_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); @@ -267,7 +267,7 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { VERIFY_CHECK(c2 == 0); \ } -static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) { +static void rustsecp256k1_v0_1_1_scalar_reduce_512(rustsecp256k1_v0_1_1_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; @@ -282,8 +282,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "movq 56(%%rsi), %%r14\n" /* Initialize r8,r9,r10 */ "movq 0(%%rsi), %%r8\n" - "movq $0, %%r9\n" - "movq $0, %%r10\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" /* (r8,r9) += n0 * c0 */ "movq %8, %%rax\n" "mulq %%r11\n" @@ -291,7 +291,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "adcq %%rdx, %%r9\n" /* extract m0 */ "movq %%r8, %q0\n" - "movq $0, %%r8\n" + "xorq %%r8, %%r8\n" /* (r9,r10) += l1 */ "addq 8(%%rsi), %%r9\n" "adcq $0, %%r10\n" @@ -309,7 +309,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "adcq $0, %%r8\n" /* extract m1 */ "movq %%r9, %q1\n" - "movq $0, %%r9\n" + "xorq %%r9, %%r9\n" /* (r10,r8,r9) += l2 */ "addq 16(%%rsi), %%r10\n" "adcq $0, %%r8\n" @@ -332,7 +332,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "adcq $0, %%r9\n" /* extract m2 */ "movq %%r10, %q2\n" - "movq $0, %%r10\n" + "xorq %%r10, %%r10\n" /* (r8,r9,r10) += l3 */ "addq 24(%%rsi), %%r8\n" "adcq $0, %%r9\n" @@ -355,7 +355,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "adcq $0, %%r10\n" /* extract m3 */ "movq %%r8, %q3\n" - "movq $0, %%r8\n" + "xorq %%r8, %%r8\n" /* (r9,r10,r8) += n3 * c1 */ "movq %9, %%rax\n" "mulq %%r14\n" @@ -376,7 +376,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) /* extract m6 */ "movq %%r8, %q6\n" : "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6) - : "S"(l), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "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. */ @@ -387,8 +387,8 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "movq %q11, %%r13\n" /* Initialize (r8,r9,r10) */ "movq %q5, %%r8\n" - "movq $0, %%r9\n" - "movq $0, %%r10\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" /* (r8,r9) += m4 * c0 */ "movq %12, %%rax\n" "mulq %%r11\n" @@ -396,7 +396,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "adcq %%rdx, %%r9\n" /* extract p0 */ "movq %%r8, %q0\n" - "movq $0, %%r8\n" + "xorq %%r8, %%r8\n" /* (r9,r10) += m1 */ "addq %q6, %%r9\n" "adcq $0, %%r10\n" @@ -414,7 +414,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "adcq $0, %%r8\n" /* extract p1 */ "movq %%r9, %q1\n" - "movq $0, %%r9\n" + "xorq %%r9, %%r9\n" /* (r10,r8,r9) += m2 */ "addq %q7, %%r10\n" "adcq $0, %%r8\n" @@ -455,7 +455,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) /* 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), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "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. */ @@ -472,7 +472,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "movq %%rax, 0(%q6)\n" /* Move to (r8,r9) */ "movq %%rdx, %%r8\n" - "movq $0, %%r9\n" + "xorq %%r9, %%r9\n" /* (r8,r9) += p1 */ "addq %q2, %%r8\n" "adcq $0, %%r9\n" @@ -483,7 +483,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "adcq %%rdx, %%r9\n" /* Extract r1 */ "movq %%r8, 8(%q6)\n" - "movq $0, %%r8\n" + "xorq %%r8, %%r8\n" /* (r9,r8) += p4 */ "addq %%r10, %%r9\n" "adcq $0, %%r8\n" @@ -492,7 +492,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) "adcq $0, %%r8\n" /* Extract r2 */ "movq %%r9, 16(%q6)\n" - "movq $0, %%r9\n" + "xorq %%r9, %%r9\n" /* (r8,r9) += p3 */ "addq %q4, %%r8\n" "adcq $0, %%r9\n" @@ -501,7 +501,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) /* Extract c */ "movq %%r9, %q0\n" : "=g"(c) - : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "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; @@ -573,10 +573,10 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) #endif /* Final reduction of r. */ - secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); + rustsecp256k1_v0_1_1_scalar_reduce(r, c + rustsecp256k1_v0_1_1_scalar_check_overflow(r)); } -static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, const secp256k1_scalar *b) { +static void rustsecp256k1_v0_1_1_scalar_mul_512(uint64_t l[8], const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { #ifdef USE_ASM_X86_64 const uint64_t *pb = b->d; __asm__ __volatile__( @@ -743,7 +743,7 @@ static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, c #endif } -static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { +static void rustsecp256k1_v0_1_1_scalar_sqr_512(uint64_t l[8], const rustsecp256k1_v0_1_1_scalar *a) { #ifdef USE_ASM_X86_64 __asm__ __volatile__( /* Preload */ @@ -888,13 +888,13 @@ static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { #undef extract #undef extract_fast -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { +static void rustsecp256k1_v0_1_1_scalar_mul(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { uint64_t l[8]; - secp256k1_scalar_mul_512(l, a, b); - secp256k1_scalar_reduce_512(r, l); + rustsecp256k1_v0_1_1_scalar_mul_512(l, a, b); + rustsecp256k1_v0_1_1_scalar_reduce_512(r, l); } -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { +static int rustsecp256k1_v0_1_1_scalar_shr_int(rustsecp256k1_v0_1_1_scalar *r, int n) { int ret; VERIFY_CHECK(n > 0); VERIFY_CHECK(n < 16); @@ -906,14 +906,14 @@ static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { return ret; } -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { +static void rustsecp256k1_v0_1_1_scalar_sqr(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a) { uint64_t l[8]; - secp256k1_scalar_sqr_512(l, a); - secp256k1_scalar_reduce_512(r, l); + rustsecp256k1_v0_1_1_scalar_sqr_512(l, a); + rustsecp256k1_v0_1_1_scalar_reduce_512(r, l); } #ifdef USE_ENDOMORPHISM -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { +static void rustsecp256k1_v0_1_1_scalar_split_128(rustsecp256k1_v0_1_1_scalar *r1, rustsecp256k1_v0_1_1_scalar *r2, const rustsecp256k1_v0_1_1_scalar *a) { r1->d[0] = a->d[0]; r1->d[1] = a->d[1]; r1->d[2] = 0; @@ -925,17 +925,17 @@ static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r } #endif -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_eq(const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_scalar_mul_shift_var(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_mul_512(l, a, b); shiftlimbs = shift >> 6; shiftlow = shift & 0x3F; shifthigh = 64 - shiftlow; @@ -943,7 +943,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, 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); + rustsecp256k1_v0_1_1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); } -#endif +#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/depend/secp256k1/src/scalar_8x32.h b/secp256k1-sys/depend/secp256k1/src/scalar_8x32.h similarity index 81% rename from depend/secp256k1/src/scalar_8x32.h rename to secp256k1-sys/depend/secp256k1/src/scalar_8x32.h index 1319664f6..cd6b97c80 100644 --- a/depend/secp256k1/src/scalar_8x32.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_8x32.h @@ -4,16 +4,16 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_REPR_ -#define _SECP256K1_SCALAR_REPR_ +#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; +} rustsecp256k1_v0_1_1_scalar; #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} -#endif +#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/depend/secp256k1/src/scalar_8x32_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h similarity index 85% rename from depend/secp256k1/src/scalar_8x32_impl.h rename to secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h index aae4f35c0..0e1fef686 100644 --- a/depend/secp256k1/src/scalar_8x32_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ -#define _SECP256K1_SCALAR_REPR_IMPL_H_ +#ifndef SECP256K1_SCALAR_REPR_IMPL_H +#define SECP256K1_SCALAR_REPR_IMPL_H /* Limbs of the secp256k1 order. */ #define SECP256K1_N_0 ((uint32_t)0xD0364141UL) @@ -34,7 +34,7 @@ #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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_scalar_clear(rustsecp256k1_v0_1_1_scalar *r) { r->d[0] = 0; r->d[1] = 0; r->d[2] = 0; @@ -45,7 +45,7 @@ SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { r->d[7] = 0; } -SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_scalar_set_int(rustsecp256k1_v0_1_1_scalar *r, unsigned int v) { r->d[0] = v; r->d[1] = 0; r->d[2] = 0; @@ -56,23 +56,23 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig r->d[7] = 0; } -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static unsigned int rustsecp256k1_v0_1_1_scalar_get_bits(const rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static unsigned int rustsecp256k1_v0_1_1_scalar_get_bits_var(const rustsecp256k1_v0_1_1_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); + return rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_check_overflow(const rustsecp256k1_v0_1_1_scalar *a) { int yes = 0; int no = 0; no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ @@ -90,7 +90,7 @@ SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scal return yes; } -SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_t overflow) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_reduce(rustsecp256k1_v0_1_1_scalar *r, uint32_t overflow) { uint64_t t; VERIFY_CHECK(overflow <= 1); t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; @@ -112,7 +112,7 @@ SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_ return overflow; } -static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { +static int rustsecp256k1_v0_1_1_scalar_add(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { int overflow; uint64_t t = (uint64_t)a->d[0] + b->d[0]; r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; @@ -130,13 +130,13 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, 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); + overflow = t + rustsecp256k1_v0_1_1_scalar_check_overflow(r); VERIFY_CHECK(overflow == 0 || overflow == 1); - secp256k1_scalar_reduce(r, overflow); + rustsecp256k1_v0_1_1_scalar_reduce(r, overflow); return overflow; } -static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { +static void rustsecp256k1_v0_1_1_scalar_cadd_bit(rustsecp256k1_v0_1_1_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 */ @@ -158,11 +158,11 @@ static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int r->d[7] = t & 0xFFFFFFFFULL; #ifdef VERIFY VERIFY_CHECK((t >> 32) == 0); - VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); + VERIFY_CHECK(rustsecp256k1_v0_1_1_scalar_check_overflow(r) == 0); #endif } -static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { +static void rustsecp256k1_v0_1_1_scalar_set_b32(rustsecp256k1_v0_1_1_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; @@ -172,13 +172,13 @@ static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b 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)); + over = rustsecp256k1_v0_1_1_scalar_reduce(r, rustsecp256k1_v0_1_1_scalar_check_overflow(r)); if (overflow) { *overflow = over; } } -static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { +static void rustsecp256k1_v0_1_1_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_1_1_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]; @@ -189,12 +189,12 @@ static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* 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) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_is_zero(const rustsecp256k1_v0_1_1_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); +static void rustsecp256k1_v0_1_1_scalar_negate(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a) { + uint32_t nonzero = 0xFFFFFFFFUL * (rustsecp256k1_v0_1_1_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; @@ -213,11 +213,11 @@ static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar r->d[7] = t & nonzero; } -SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_is_one(const rustsecp256k1_v0_1_1_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) { +static int rustsecp256k1_v0_1_1_scalar_is_high(const rustsecp256k1_v0_1_1_scalar *a) { int yes = 0; int no = 0; no |= (a->d[7] < SECP256K1_N_H_7); @@ -235,11 +235,11 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { return yes; } -static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { +static int rustsecp256k1_v0_1_1_scalar_cond_negate(rustsecp256k1_v0_1_1_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 */ + * if we are flag = 1, mask = 11...11 and this is identical to rustsecp256k1_v0_1_1_scalar_negate */ uint32_t mask = !flag - 1; - uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0); + uint32_t nonzero = 0xFFFFFFFFUL * (rustsecp256k1_v0_1_1_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); @@ -346,7 +346,7 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { VERIFY_CHECK(c2 == 0); \ } -static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) { +static void rustsecp256k1_v0_1_1_scalar_reduce_512(rustsecp256k1_v0_1_1_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; @@ -485,10 +485,10 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; /* Final reduction of r. */ - secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); + rustsecp256k1_v0_1_1_scalar_reduce(r, c + rustsecp256k1_v0_1_1_scalar_check_overflow(r)); } -static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, const secp256k1_scalar *b) { +static void rustsecp256k1_v0_1_1_scalar_mul_512(uint32_t *l, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { /* 96 bit accumulator. */ uint32_t c0 = 0, c1 = 0, c2 = 0; @@ -576,7 +576,7 @@ static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, con l[15] = c0; } -static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar *a) { +static void rustsecp256k1_v0_1_1_scalar_sqr_512(uint32_t *l, const rustsecp256k1_v0_1_1_scalar *a) { /* 96 bit accumulator. */ uint32_t c0 = 0, c1 = 0, c2 = 0; @@ -644,13 +644,13 @@ static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar *a) { #undef extract #undef extract_fast -static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { +static void rustsecp256k1_v0_1_1_scalar_mul(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { uint32_t l[16]; - secp256k1_scalar_mul_512(l, a, b); - secp256k1_scalar_reduce_512(r, l); + rustsecp256k1_v0_1_1_scalar_mul_512(l, a, b); + rustsecp256k1_v0_1_1_scalar_reduce_512(r, l); } -static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { +static int rustsecp256k1_v0_1_1_scalar_shr_int(rustsecp256k1_v0_1_1_scalar *r, int n) { int ret; VERIFY_CHECK(n > 0); VERIFY_CHECK(n < 16); @@ -666,14 +666,14 @@ static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { return ret; } -static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { +static void rustsecp256k1_v0_1_1_scalar_sqr(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a) { uint32_t l[16]; - secp256k1_scalar_sqr_512(l, a); - secp256k1_scalar_reduce_512(r, l); + rustsecp256k1_v0_1_1_scalar_sqr_512(l, a); + rustsecp256k1_v0_1_1_scalar_reduce_512(r, l); } #ifdef USE_ENDOMORPHISM -static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { +static void rustsecp256k1_v0_1_1_scalar_split_128(rustsecp256k1_v0_1_1_scalar *r1, rustsecp256k1_v0_1_1_scalar *r2, const rustsecp256k1_v0_1_1_scalar *a) { r1->d[0] = a->d[0]; r1->d[1] = a->d[1]; r1->d[2] = a->d[2]; @@ -693,17 +693,17 @@ static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r } #endif -SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_eq(const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_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) { +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_scalar_mul_shift_var(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_mul_512(l, a, b); shiftlimbs = shift >> 5; shiftlow = shift & 0x1F; shifthigh = 32 - shiftlow; @@ -715,7 +715,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, 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); + rustsecp256k1_v0_1_1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); } -#endif +#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_impl.h new file mode 100644 index 000000000..f403d430f --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/scalar_impl.h @@ -0,0 +1,333 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_SCALAR_IMPL_H +#define SECP256K1_SCALAR_IMPL_H + +#include "group.h" +#include "scalar.h" + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(EXHAUSTIVE_TEST_ORDER) +#include "scalar_low_impl.h" +#elif defined(USE_SCALAR_4X64) +#include "scalar_4x64_impl.h" +#elif defined(USE_SCALAR_8X32) +#include "scalar_8x32_impl.h" +#else +#error "Please select scalar implementation" +#endif + +#ifndef USE_NUM_NONE +static void rustsecp256k1_v0_1_1_scalar_get_num(rustsecp256k1_v0_1_1_num *r, const rustsecp256k1_v0_1_1_scalar *a) { + unsigned char c[32]; + rustsecp256k1_v0_1_1_scalar_get_b32(c, a); + rustsecp256k1_v0_1_1_num_set_bin(r, c, 32); +} + +/** secp256k1 curve order, see rustsecp256k1_v0_1_1_ecdsa_const_order_as_fe in ecdsa_impl.h */ +static void rustsecp256k1_v0_1_1_scalar_order_get_num(rustsecp256k1_v0_1_1_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 + rustsecp256k1_v0_1_1_num_set_bin(r, order, 32); +} +#endif + +static void rustsecp256k1_v0_1_1_scalar_inverse(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_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 + rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_scalar x2, x3, x6, x8, x14, x28, x56, x112, x126; + rustsecp256k1_v0_1_1_scalar u2, u5, u9, u11, u13; + + rustsecp256k1_v0_1_1_scalar_sqr(&u2, x); + rustsecp256k1_v0_1_1_scalar_mul(&x2, &u2, x); + rustsecp256k1_v0_1_1_scalar_mul(&u5, &u2, &x2); + rustsecp256k1_v0_1_1_scalar_mul(&x3, &u5, &u2); + rustsecp256k1_v0_1_1_scalar_mul(&u9, &x3, &u2); + rustsecp256k1_v0_1_1_scalar_mul(&u11, &u9, &u2); + rustsecp256k1_v0_1_1_scalar_mul(&u13, &u11, &u2); + + rustsecp256k1_v0_1_1_scalar_sqr(&x6, &u13); + rustsecp256k1_v0_1_1_scalar_sqr(&x6, &x6); + rustsecp256k1_v0_1_1_scalar_mul(&x6, &x6, &u11); + + rustsecp256k1_v0_1_1_scalar_sqr(&x8, &x6); + rustsecp256k1_v0_1_1_scalar_sqr(&x8, &x8); + rustsecp256k1_v0_1_1_scalar_mul(&x8, &x8, &x2); + + rustsecp256k1_v0_1_1_scalar_sqr(&x14, &x8); + for (i = 0; i < 5; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(&x14, &x14); + } + rustsecp256k1_v0_1_1_scalar_mul(&x14, &x14, &x6); + + rustsecp256k1_v0_1_1_scalar_sqr(&x28, &x14); + for (i = 0; i < 13; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(&x28, &x28); + } + rustsecp256k1_v0_1_1_scalar_mul(&x28, &x28, &x14); + + rustsecp256k1_v0_1_1_scalar_sqr(&x56, &x28); + for (i = 0; i < 27; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(&x56, &x56); + } + rustsecp256k1_v0_1_1_scalar_mul(&x56, &x56, &x28); + + rustsecp256k1_v0_1_1_scalar_sqr(&x112, &x56); + for (i = 0; i < 55; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(&x112, &x112); + } + rustsecp256k1_v0_1_1_scalar_mul(&x112, &x112, &x56); + + rustsecp256k1_v0_1_1_scalar_sqr(&x126, &x112); + for (i = 0; i < 13; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(&x126, &x126); + } + rustsecp256k1_v0_1_1_scalar_mul(&x126, &x126, &x14); + + /* Then accumulate the final result (t starts at x126). */ + t = &x126; + for (i = 0; i < 3; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u5); /* 101 */ + for (i = 0; i < 4; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 4; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u5); /* 101 */ + for (i = 0; i < 5; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u11); /* 1011 */ + for (i = 0; i < 4; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u11); /* 1011 */ + for (i = 0; i < 4; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 5; i++) { /* 00 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 6; i++) { /* 00 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 4; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u5); /* 101 */ + for (i = 0; i < 3; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 5; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u9); /* 1001 */ + for (i = 0; i < 6; i++) { /* 000 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u5); /* 101 */ + for (i = 0; i < 10; i++) { /* 0000000 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 4; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 9; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &x8); /* 11111111 */ + for (i = 0; i < 5; i++) { /* 0 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u9); /* 1001 */ + for (i = 0; i < 6; i++) { /* 00 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u11); /* 1011 */ + for (i = 0; i < 4; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 5; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 6; i++) { /* 00 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 10; i++) { /* 000000 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 4; i++) { + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, &u9); /* 1001 */ + for (i = 0; i < 6; i++) { /* 00000 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 8; i++) { /* 00 */ + rustsecp256k1_v0_1_1_scalar_sqr(t, t); + } + rustsecp256k1_v0_1_1_scalar_mul(r, t, &x6); /* 111111 */ +} + +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_is_even(const rustsecp256k1_v0_1_1_scalar *a) { + return !(a->d[0] & 1); +} +#endif + +static void rustsecp256k1_v0_1_1_scalar_inverse_var(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *x) { +#if defined(USE_SCALAR_INV_BUILTIN) + rustsecp256k1_v0_1_1_scalar_inverse(r, x); +#elif defined(USE_SCALAR_INV_NUM) + unsigned char b[32]; + rustsecp256k1_v0_1_1_num n, m; + rustsecp256k1_v0_1_1_scalar t = *x; + rustsecp256k1_v0_1_1_scalar_get_b32(b, &t); + rustsecp256k1_v0_1_1_num_set_bin(&n, b, 32); + rustsecp256k1_v0_1_1_scalar_order_get_num(&m); + rustsecp256k1_v0_1_1_num_mod_inverse(&n, &n, &m); + rustsecp256k1_v0_1_1_num_get_bin(b, 32, &n); + rustsecp256k1_v0_1_1_scalar_set_b32(r, b, NULL); + /* Verify that the inverse was computed correctly, without GMP code. */ + rustsecp256k1_v0_1_1_scalar_mul(&t, &t, r); + CHECK(rustsecp256k1_v0_1_1_scalar_is_one(&t)); +#else +#error "Please select scalar inverse implementation" +#endif +} + +#ifdef USE_ENDOMORPHISM +#if defined(EXHAUSTIVE_TEST_ORDER) +/** + * Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the + * full case we don't bother making k1 and k2 be small, we just want them to be + * nontrivial to get full test coverage for the exhaustive tests. We therefore + * (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda. + */ +static void rustsecp256k1_v0_1_1_scalar_split_lambda(rustsecp256k1_v0_1_1_scalar *r1, rustsecp256k1_v0_1_1_scalar *r2, const rustsecp256k1_v0_1_1_scalar *a) { + *r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER; + *r1 = (*a + (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 {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, + * 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72} + * + * "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 have a small size. + * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are: + * + * - 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} + * + * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives + * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and + * compute k1 as k - k2 * lambda, avoiding the need for 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^272)*b2/d) + * g2 = round((2^272)*b1/d) + * + * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found + * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda'). + * + * The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order). + */ + +static void rustsecp256k1_v0_1_1_scalar_split_lambda(rustsecp256k1_v0_1_1_scalar *r1, rustsecp256k1_v0_1_1_scalar *r2, const rustsecp256k1_v0_1_1_scalar *a) { + rustsecp256k1_v0_1_1_scalar c1, c2; + static const rustsecp256k1_v0_1_1_scalar minus_lambda = SECP256K1_SCALAR_CONST( + 0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL, + 0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL + ); + static const rustsecp256k1_v0_1_1_scalar minus_b1 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, + 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL + ); + static const rustsecp256k1_v0_1_1_scalar minus_b2 = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL + ); + static const rustsecp256k1_v0_1_1_scalar g1 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL, + 0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL + ); + static const rustsecp256k1_v0_1_1_scalar g2 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL, + 0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL + ); + VERIFY_CHECK(r1 != a); + VERIFY_CHECK(r2 != a); + /* these _var calls are constant time since the shift amount is constant */ + rustsecp256k1_v0_1_1_scalar_mul_shift_var(&c1, a, &g1, 272); + rustsecp256k1_v0_1_1_scalar_mul_shift_var(&c2, a, &g2, 272); + rustsecp256k1_v0_1_1_scalar_mul(&c1, &c1, &minus_b1); + rustsecp256k1_v0_1_1_scalar_mul(&c2, &c2, &minus_b2); + rustsecp256k1_v0_1_1_scalar_add(r2, &c1, &c2); + rustsecp256k1_v0_1_1_scalar_mul(r1, r2, &minus_lambda); + rustsecp256k1_v0_1_1_scalar_add(r1, r1, a); +} +#endif +#endif + +#endif /* SECP256K1_SCALAR_IMPL_H */ diff --git a/depend/secp256k1/src/ecmult_const.h b/secp256k1-sys/depend/secp256k1/src/scalar_low.h similarity index 61% rename from depend/secp256k1/src/ecmult_const.h rename to secp256k1-sys/depend/secp256k1/src/scalar_low.h index 2b0097655..fef7696d1 100644 --- a/depend/secp256k1/src/ecmult_const.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_low.h @@ -4,12 +4,12 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_ECMULT_CONST_ -#define _SECP256K1_ECMULT_CONST_ +#ifndef SECP256K1_SCALAR_REPR_H +#define SECP256K1_SCALAR_REPR_H -#include "scalar.h" -#include "group.h" +#include -static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef uint32_t rustsecp256k1_v0_1_1_scalar; -#endif +#endif /* SECP256K1_SCALAR_REPR_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h new file mode 100644 index 000000000..de0fe194c --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h @@ -0,0 +1,114 @@ +/********************************************************************** + * 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.* + **********************************************************************/ + +#ifndef SECP256K1_SCALAR_REPR_IMPL_H +#define SECP256K1_SCALAR_REPR_IMPL_H + +#include "scalar.h" + +#include + +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_is_even(const rustsecp256k1_v0_1_1_scalar *a) { + return !(*a & 1); +} + +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_scalar_clear(rustsecp256k1_v0_1_1_scalar *r) { *r = 0; } +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_scalar_set_int(rustsecp256k1_v0_1_1_scalar *r, unsigned int v) { *r = v; } + +SECP256K1_INLINE static unsigned int rustsecp256k1_v0_1_1_scalar_get_bits(const rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_scalar_get_bits_var(const rustsecp256k1_v0_1_1_scalar *a, unsigned int offset, unsigned int count) { + return rustsecp256k1_v0_1_1_scalar_get_bits(a, offset, count); +} + +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_check_overflow(const rustsecp256k1_v0_1_1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } + +static int rustsecp256k1_v0_1_1_scalar_add(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { + *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; + return *r < *b; +} + +static void rustsecp256k1_v0_1_1_scalar_cadd_bit(rustsecp256k1_v0_1_1_scalar *r, unsigned int bit, int flag) { + if (flag && bit < 32) + *r += (1 << bit); +#ifdef VERIFY + VERIFY_CHECK(rustsecp256k1_v0_1_1_scalar_check_overflow(r) == 0); +#endif +} + +static void rustsecp256k1_v0_1_1_scalar_set_b32(rustsecp256k1_v0_1_1_scalar *r, const unsigned char *b32, int *overflow) { + const int base = 0x100 % EXHAUSTIVE_TEST_ORDER; + int i; + *r = 0; + for (i = 0; i < 32; i++) { + *r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER; + } + /* just deny overflow, it basically always happens */ + if (overflow) *overflow = 0; +} + +static void rustsecp256k1_v0_1_1_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_scalar_is_zero(const rustsecp256k1_v0_1_1_scalar *a) { + return *a == 0; +} + +static void rustsecp256k1_v0_1_1_scalar_negate(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a) { + if (*a == 0) { + *r = 0; + } else { + *r = EXHAUSTIVE_TEST_ORDER - *a; + } +} + +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_is_one(const rustsecp256k1_v0_1_1_scalar *a) { + return *a == 1; +} + +static int rustsecp256k1_v0_1_1_scalar_is_high(const rustsecp256k1_v0_1_1_scalar *a) { + return *a > EXHAUSTIVE_TEST_ORDER / 2; +} + +static int rustsecp256k1_v0_1_1_scalar_cond_negate(rustsecp256k1_v0_1_1_scalar *r, int flag) { + if (flag) rustsecp256k1_v0_1_1_scalar_negate(r, r); + return flag ? -1 : 1; +} + +static void rustsecp256k1_v0_1_1_scalar_mul(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { + *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; +} + +static int rustsecp256k1_v0_1_1_scalar_shr_int(rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_scalar_sqr(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_scalar *a) { + *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER; +} + +static void rustsecp256k1_v0_1_1_scalar_split_128(rustsecp256k1_v0_1_1_scalar *r1, rustsecp256k1_v0_1_1_scalar *r2, const rustsecp256k1_v0_1_1_scalar *a) { + *r1 = *a; + *r2 = 0; +} + +SECP256K1_INLINE static int rustsecp256k1_v0_1_1_scalar_eq(const rustsecp256k1_v0_1_1_scalar *a, const rustsecp256k1_v0_1_1_scalar *b) { + return *a == *b; +} + +#endif /* SECP256K1_SCALAR_REPR_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/scratch.h b/secp256k1-sys/depend/secp256k1/src/scratch.h new file mode 100644 index 000000000..2daa50918 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/scratch.h @@ -0,0 +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.* + **********************************************************************/ + +#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 rustsecp256k1_v0_1_1_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; +} rustsecp256k1_v0_1_1_scratch; + +static rustsecp256k1_v0_1_1_scratch* rustsecp256k1_v0_1_1_scratch_create(const rustsecp256k1_v0_1_1_callback* error_callback, size_t max_size); + +static void rustsecp256k1_v0_1_1_scratch_destroy(const rustsecp256k1_v0_1_1_callback* error_callback, rustsecp256k1_v0_1_1_scratch* scratch); + +/** Returns an opaque object used to "checkpoint" a scratch space. Used + * with `rustsecp256k1_v0_1_1_scratch_apply_checkpoint` to undo allocations. */ +static size_t rustsecp256k1_v0_1_1_scratch_checkpoint(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_scratch* scratch); + +/** Applies a check point received from `rustsecp256k1_v0_1_1_scratch_checkpoint`, + * undoing all allocations since that point. */ +static void rustsecp256k1_v0_1_1_scratch_apply_checkpoint(const rustsecp256k1_v0_1_1_callback* error_callback, rustsecp256k1_v0_1_1_scratch* scratch, size_t checkpoint); + +/** Returns the maximum allocation the scratch space will allow */ +static size_t rustsecp256k1_v0_1_1_scratch_max_allocation(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_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 *rustsecp256k1_v0_1_1_scratch_alloc(const rustsecp256k1_v0_1_1_callback* error_callback, rustsecp256k1_v0_1_1_scratch* scratch, size_t n); + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/scratch_impl.h b/secp256k1-sys/depend/secp256k1/src/scratch_impl.h new file mode 100644 index 000000000..d193804c0 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/scratch_impl.h @@ -0,0 +1,63 @@ +/********************************************************************** + * Copyright (c) 2017 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCRATCH_IMPL_H_ +#define _SECP256K1_SCRATCH_IMPL_H_ + +#include "util.h" +#include "scratch.h" + +static size_t rustsecp256k1_v0_1_1_scratch_checkpoint(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_scratch* scratch) { + if (memcmp(scratch->magic, "scratch", 8) != 0) { + rustsecp256k1_v0_1_1_callback_call(error_callback, "invalid scratch space"); + return 0; + } + return scratch->alloc_size; +} + +static void rustsecp256k1_v0_1_1_scratch_apply_checkpoint(const rustsecp256k1_v0_1_1_callback* error_callback, rustsecp256k1_v0_1_1_scratch* scratch, size_t checkpoint) { + if (memcmp(scratch->magic, "scratch", 8) != 0) { + rustsecp256k1_v0_1_1_callback_call(error_callback, "invalid scratch space"); + return; + } + if (checkpoint > scratch->alloc_size) { + rustsecp256k1_v0_1_1_callback_call(error_callback, "invalid checkpoint"); + return; + } + scratch->alloc_size = checkpoint; +} + +static size_t rustsecp256k1_v0_1_1_scratch_max_allocation(const rustsecp256k1_v0_1_1_callback* error_callback, const rustsecp256k1_v0_1_1_scratch* scratch, size_t objects) { + if (memcmp(scratch->magic, "scratch", 8) != 0) { + rustsecp256k1_v0_1_1_callback_call(error_callback, "invalid scratch space"); + 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 *rustsecp256k1_v0_1_1_scratch_alloc(const rustsecp256k1_v0_1_1_callback* error_callback, rustsecp256k1_v0_1_1_scratch* scratch, size_t size) { + void *ret; + size = ROUND_TO_ALIGN(size); + + if (memcmp(scratch->magic, "scratch", 8) != 0) { + rustsecp256k1_v0_1_1_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/secp256k1-sys/depend/secp256k1/src/secp256k1.c b/secp256k1-sys/depend/secp256k1/src/secp256k1.c new file mode 100644 index 000000000..ab76e0561 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/secp256k1.c @@ -0,0 +1,651 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include "include/secp256k1.h" +#include "include/secp256k1_preallocated.h" + +#include "util.h" +#include "num_impl.h" +#include "field_impl.h" +#include "scalar_impl.h" +#include "group_impl.h" +#include "ecmult_impl.h" +#include "ecmult_const_impl.h" +#include "ecmult_gen_impl.h" +#include "ecdsa_impl.h" +#include "eckey_impl.h" +#include "hash_impl.h" +#include "scratch_impl.h" + +#define ARG_CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + rustsecp256k1_v0_1_1_callback_call(&ctx->illegal_callback, #cond); \ + return 0; \ + } \ +} while(0) + +#define ARG_CHECK_NO_RETURN(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + rustsecp256k1_v0_1_1_callback_call(&ctx->illegal_callback, #cond); \ + } \ +} while(0) + +#ifndef USE_EXTERNAL_DEFAULT_CALLBACKS +#include +#include +static void rustsecp256k1_v0_1_1_default_illegal_callback_fn(const char* str, void* data) { + (void)data; + fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); + abort(); +} +static void rustsecp256k1_v0_1_1_default_error_callback_fn(const char* str, void* data) { + (void)data; + fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); + abort(); +} +#else +void rustsecp256k1_v0_1_1_default_illegal_callback_fn(const char* str, void* data); +void rustsecp256k1_v0_1_1_default_error_callback_fn(const char* str, void* data); +#endif + +static const rustsecp256k1_v0_1_1_callback default_illegal_callback = { + rustsecp256k1_v0_1_1_default_illegal_callback_fn, + NULL +}; + +static const rustsecp256k1_v0_1_1_callback default_error_callback = { + rustsecp256k1_v0_1_1_default_error_callback_fn, + NULL +}; + +struct rustsecp256k1_v0_1_1_context_struct { + rustsecp256k1_v0_1_1_ecmult_context ecmult_ctx; + rustsecp256k1_v0_1_1_ecmult_gen_context ecmult_gen_ctx; + rustsecp256k1_v0_1_1_callback illegal_callback; + rustsecp256k1_v0_1_1_callback error_callback; +}; + +static const rustsecp256k1_v0_1_1_context rustsecp256k1_v0_1_1_context_no_precomp_ = { + { 0 }, + { 0 }, + { rustsecp256k1_v0_1_1_default_illegal_callback_fn, 0 }, + { rustsecp256k1_v0_1_1_default_error_callback_fn, 0 } +}; +const rustsecp256k1_v0_1_1_context *rustsecp256k1_v0_1_1_context_no_precomp = &rustsecp256k1_v0_1_1_context_no_precomp_; + +size_t rustsecp256k1_v0_1_1_context_preallocated_size(unsigned int flags) { + size_t ret = ROUND_TO_ALIGN(sizeof(rustsecp256k1_v0_1_1_context)); + + if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { + rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_context_preallocated_clone_size(const rustsecp256k1_v0_1_1_context* ctx) { + size_t ret = ROUND_TO_ALIGN(sizeof(rustsecp256k1_v0_1_1_context)); + VERIFY_CHECK(ctx != NULL); + if (rustsecp256k1_v0_1_1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { + ret += SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE; + } + if (rustsecp256k1_v0_1_1_ecmult_context_is_built(&ctx->ecmult_ctx)) { + ret += SECP256K1_ECMULT_CONTEXT_PREALLOCATED_SIZE; + } + return ret; +} + +rustsecp256k1_v0_1_1_context* rustsecp256k1_v0_1_1_context_preallocated_create(void* prealloc, unsigned int flags) { + void* const base = prealloc; + size_t prealloc_size; + rustsecp256k1_v0_1_1_context* ret; + + VERIFY_CHECK(prealloc != NULL); + prealloc_size = rustsecp256k1_v0_1_1_context_preallocated_size(flags); + ret = (rustsecp256k1_v0_1_1_context*)manual_alloc(&prealloc, sizeof(rustsecp256k1_v0_1_1_context), base, prealloc_size); + ret->illegal_callback = default_illegal_callback; + ret->error_callback = default_error_callback; + + if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { + rustsecp256k1_v0_1_1_callback_call(&ret->illegal_callback, + "Invalid flags"); + return NULL; + } + + rustsecp256k1_v0_1_1_ecmult_context_init(&ret->ecmult_ctx); + rustsecp256k1_v0_1_1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); + + if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { + rustsecp256k1_v0_1_1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &prealloc); + } + if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { + rustsecp256k1_v0_1_1_ecmult_context_build(&ret->ecmult_ctx, &prealloc); + } + + return (rustsecp256k1_v0_1_1_context*) ret; +} + +rustsecp256k1_v0_1_1_context* rustsecp256k1_v0_1_1_context_preallocated_clone(const rustsecp256k1_v0_1_1_context* ctx, void* prealloc) { + size_t prealloc_size; + rustsecp256k1_v0_1_1_context* ret; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(prealloc != NULL); + + prealloc_size = rustsecp256k1_v0_1_1_context_preallocated_clone_size(ctx); + ret = (rustsecp256k1_v0_1_1_context*)prealloc; + memcpy(ret, ctx, prealloc_size); + rustsecp256k1_v0_1_1_ecmult_gen_context_finalize_memcpy(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx); + rustsecp256k1_v0_1_1_ecmult_context_finalize_memcpy(&ret->ecmult_ctx, &ctx->ecmult_ctx); + return ret; +} + +void rustsecp256k1_v0_1_1_context_preallocated_destroy(rustsecp256k1_v0_1_1_context* ctx) { + ARG_CHECK_NO_RETURN(ctx != rustsecp256k1_v0_1_1_context_no_precomp); + if (ctx != NULL) { + rustsecp256k1_v0_1_1_ecmult_context_clear(&ctx->ecmult_ctx); + rustsecp256k1_v0_1_1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); + } +} + +void rustsecp256k1_v0_1_1_context_set_illegal_callback(rustsecp256k1_v0_1_1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + ARG_CHECK_NO_RETURN(ctx != rustsecp256k1_v0_1_1_context_no_precomp); + if (fun == NULL) { + fun = rustsecp256k1_v0_1_1_default_illegal_callback_fn; + } + ctx->illegal_callback.fn = fun; + ctx->illegal_callback.data = data; +} + +void rustsecp256k1_v0_1_1_context_set_error_callback(rustsecp256k1_v0_1_1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + ARG_CHECK_NO_RETURN(ctx != rustsecp256k1_v0_1_1_context_no_precomp); + if (fun == NULL) { + fun = rustsecp256k1_v0_1_1_default_error_callback_fn; + } + ctx->error_callback.fn = fun; + ctx->error_callback.data = data; +} + +static int rustsecp256k1_v0_1_1_pubkey_load(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ge* ge, const rustsecp256k1_v0_1_1_pubkey* pubkey) { + if (sizeof(rustsecp256k1_v0_1_1_ge_storage) == 64) { + /* When the rustsecp256k1_v0_1_1_ge_storage type is exactly 64 byte, use its + * representation inside rustsecp256k1_v0_1_1_pubkey, as conversion is very fast. + * Note that rustsecp256k1_v0_1_1_pubkey_save must use the same representation. */ + rustsecp256k1_v0_1_1_ge_storage s; + memcpy(&s, &pubkey->data[0], sizeof(s)); + rustsecp256k1_v0_1_1_ge_from_storage(ge, &s); + } else { + /* Otherwise, fall back to 32-byte big endian for X and Y. */ + rustsecp256k1_v0_1_1_fe x, y; + rustsecp256k1_v0_1_1_fe_set_b32(&x, pubkey->data); + rustsecp256k1_v0_1_1_fe_set_b32(&y, pubkey->data + 32); + rustsecp256k1_v0_1_1_ge_set_xy(ge, &x, &y); + } + ARG_CHECK(!rustsecp256k1_v0_1_1_fe_is_zero(&ge->x)); + return 1; +} + +static void rustsecp256k1_v0_1_1_pubkey_save(rustsecp256k1_v0_1_1_pubkey* pubkey, rustsecp256k1_v0_1_1_ge* ge) { + if (sizeof(rustsecp256k1_v0_1_1_ge_storage) == 64) { + rustsecp256k1_v0_1_1_ge_storage s; + rustsecp256k1_v0_1_1_ge_to_storage(&s, ge); + memcpy(&pubkey->data[0], &s, sizeof(s)); + } else { + VERIFY_CHECK(!rustsecp256k1_v0_1_1_ge_is_infinity(ge)); + rustsecp256k1_v0_1_1_fe_normalize_var(&ge->x); + rustsecp256k1_v0_1_1_fe_normalize_var(&ge->y); + rustsecp256k1_v0_1_1_fe_get_b32(pubkey->data, &ge->x); + rustsecp256k1_v0_1_1_fe_get_b32(pubkey->data + 32, &ge->y); + } +} + +int rustsecp256k1_v0_1_1_ec_pubkey_parse(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { + rustsecp256k1_v0_1_1_ge Q; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + memset(pubkey, 0, sizeof(*pubkey)); + ARG_CHECK(input != NULL); + if (!rustsecp256k1_v0_1_1_eckey_pubkey_parse(&Q, input, inputlen)) { + return 0; + } + rustsecp256k1_v0_1_1_pubkey_save(pubkey, &Q); + rustsecp256k1_v0_1_1_ge_clear(&Q); + return 1; +} + +int rustsecp256k1_v0_1_1_ec_pubkey_serialize(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output, size_t *outputlen, const rustsecp256k1_v0_1_1_pubkey* pubkey, unsigned int flags) { + rustsecp256k1_v0_1_1_ge Q; + size_t len; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(outputlen != NULL); + ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); + len = *outputlen; + *outputlen = 0; + ARG_CHECK(output != NULL); + memset(output, 0, len); + ARG_CHECK(pubkey != NULL); + ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); + if (rustsecp256k1_v0_1_1_pubkey_load(ctx, &Q, pubkey)) { + ret = rustsecp256k1_v0_1_1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); + if (ret) { + *outputlen = len; + } + } + return ret; +} + +static void rustsecp256k1_v0_1_1_ecdsa_signature_load(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_scalar* r, rustsecp256k1_v0_1_1_scalar* s, const rustsecp256k1_v0_1_1_ecdsa_signature* sig) { + (void)ctx; + if (sizeof(rustsecp256k1_v0_1_1_scalar) == 32) { + /* When the rustsecp256k1_v0_1_1_scalar type is exactly 32 byte, use its + * representation inside rustsecp256k1_v0_1_1_ecdsa_signature, as conversion is very fast. + * Note that rustsecp256k1_v0_1_1_ecdsa_signature_save must use the same representation. */ + memcpy(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); + } else { + rustsecp256k1_v0_1_1_scalar_set_b32(r, &sig->data[0], NULL); + rustsecp256k1_v0_1_1_scalar_set_b32(s, &sig->data[32], NULL); + } +} + +static void rustsecp256k1_v0_1_1_ecdsa_signature_save(rustsecp256k1_v0_1_1_ecdsa_signature* sig, const rustsecp256k1_v0_1_1_scalar* r, const rustsecp256k1_v0_1_1_scalar* s) { + if (sizeof(rustsecp256k1_v0_1_1_scalar) == 32) { + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); + } else { + rustsecp256k1_v0_1_1_scalar_get_b32(&sig->data[0], r); + rustsecp256k1_v0_1_1_scalar_get_b32(&sig->data[32], s); + } +} + +int rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { + rustsecp256k1_v0_1_1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(input != NULL); + + if (rustsecp256k1_v0_1_1_ecdsa_sig_parse(&r, &s, input, inputlen)) { + rustsecp256k1_v0_1_1_ecdsa_signature_save(sig, &r, &s); + return 1; + } else { + memset(sig, 0, sizeof(*sig)); + return 0; + } +} + +int rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ecdsa_signature* sig, const unsigned char *input64) { + rustsecp256k1_v0_1_1_scalar r, s; + int ret = 1; + int overflow = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(input64 != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&r, &input64[0], &overflow); + ret &= !overflow; + rustsecp256k1_v0_1_1_scalar_set_b32(&s, &input64[32], &overflow); + ret &= !overflow; + if (ret) { + rustsecp256k1_v0_1_1_ecdsa_signature_save(sig, &r, &s); + } else { + memset(sig, 0, sizeof(*sig)); + } + return ret; +} + +int rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output, size_t *outputlen, const rustsecp256k1_v0_1_1_ecdsa_signature* sig) { + rustsecp256k1_v0_1_1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output != NULL); + ARG_CHECK(outputlen != NULL); + ARG_CHECK(sig != NULL); + + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &r, &s, sig); + return rustsecp256k1_v0_1_1_ecdsa_sig_serialize(output, outputlen, &r, &s); +} + +int rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *output64, const rustsecp256k1_v0_1_1_ecdsa_signature* sig) { + rustsecp256k1_v0_1_1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output64 != NULL); + ARG_CHECK(sig != NULL); + + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &r, &s, sig); + rustsecp256k1_v0_1_1_scalar_get_b32(&output64[0], &r); + rustsecp256k1_v0_1_1_scalar_get_b32(&output64[32], &s); + return 1; +} + +int rustsecp256k1_v0_1_1_ecdsa_signature_normalize(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ecdsa_signature *sigout, const rustsecp256k1_v0_1_1_ecdsa_signature *sigin) { + rustsecp256k1_v0_1_1_scalar r, s; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sigin != NULL); + + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &r, &s, sigin); + ret = rustsecp256k1_v0_1_1_scalar_is_high(&s); + if (sigout != NULL) { + if (ret) { + rustsecp256k1_v0_1_1_scalar_negate(&s, &s); + } + rustsecp256k1_v0_1_1_ecdsa_signature_save(sigout, &r, &s); + } + + return ret; +} + +int rustsecp256k1_v0_1_1_ecdsa_verify(const rustsecp256k1_v0_1_1_context* ctx, const rustsecp256k1_v0_1_1_ecdsa_signature *sig, const unsigned char *msg32, const rustsecp256k1_v0_1_1_pubkey *pubkey) { + rustsecp256k1_v0_1_1_ge q; + rustsecp256k1_v0_1_1_scalar r, s; + rustsecp256k1_v0_1_1_scalar m; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_1_1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(pubkey != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&m, msg32, NULL); + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &r, &s, sig); + return (!rustsecp256k1_v0_1_1_scalar_is_high(&s) && + rustsecp256k1_v0_1_1_pubkey_load(ctx, &q, pubkey) && + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_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); + } + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); + memset(keydata, 0, sizeof(keydata)); + for (i = 0; i <= counter; i++) { + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + } + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_finalize(&rng); + return 1; +} + +const rustsecp256k1_v0_1_1_nonce_function rustsecp256k1_v0_1_1_nonce_function_rfc6979 = nonce_function_rfc6979; +const rustsecp256k1_v0_1_1_nonce_function rustsecp256k1_v0_1_1_nonce_function_default = nonce_function_rfc6979; + +int rustsecp256k1_v0_1_1_ecdsa_sign(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, rustsecp256k1_v0_1_1_nonce_function noncefp, const void* noncedata) { + rustsecp256k1_v0_1_1_scalar r, s; + rustsecp256k1_v0_1_1_scalar sec, non, msg; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_1_1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(seckey != NULL); + if (noncefp == NULL) { + noncefp = rustsecp256k1_v0_1_1_nonce_function_default; + } + + rustsecp256k1_v0_1_1_scalar_set_b32(&sec, seckey, &overflow); + /* Fail if the secret key is invalid. */ + if (!overflow && !rustsecp256k1_v0_1_1_scalar_is_zero(&sec)) { + unsigned char nonce32[32]; + unsigned int count = 0; + rustsecp256k1_v0_1_1_scalar_set_b32(&msg, msg32, NULL); + while (1) { + ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + if (!ret) { + break; + } + rustsecp256k1_v0_1_1_scalar_set_b32(&non, nonce32, &overflow); + if (!overflow && !rustsecp256k1_v0_1_1_scalar_is_zero(&non)) { + if (rustsecp256k1_v0_1_1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { + break; + } + } + count++; + } + memset(nonce32, 0, 32); + rustsecp256k1_v0_1_1_scalar_clear(&msg); + rustsecp256k1_v0_1_1_scalar_clear(&non); + rustsecp256k1_v0_1_1_scalar_clear(&sec); + } + if (ret) { + rustsecp256k1_v0_1_1_ecdsa_signature_save(signature, &r, &s); + } else { + memset(signature, 0, sizeof(*signature)); + } + return ret; +} + +int rustsecp256k1_v0_1_1_ec_seckey_verify(const rustsecp256k1_v0_1_1_context* ctx, const unsigned char *seckey) { + rustsecp256k1_v0_1_1_scalar sec; + int ret; + int overflow; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&sec, seckey, &overflow); + ret = !overflow && !rustsecp256k1_v0_1_1_scalar_is_zero(&sec); + rustsecp256k1_v0_1_1_scalar_clear(&sec); + return ret; +} + +int rustsecp256k1_v0_1_1_ec_pubkey_create(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_pubkey *pubkey, const unsigned char *seckey) { + rustsecp256k1_v0_1_1_gej pj; + rustsecp256k1_v0_1_1_ge p; + rustsecp256k1_v0_1_1_scalar sec; + int overflow; + int ret = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + memset(pubkey, 0, sizeof(*pubkey)); + ARG_CHECK(rustsecp256k1_v0_1_1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(seckey != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&sec, seckey, &overflow); + ret = (!overflow) & (!rustsecp256k1_v0_1_1_scalar_is_zero(&sec)); + if (ret) { + rustsecp256k1_v0_1_1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); + rustsecp256k1_v0_1_1_ge_set_gej(&p, &pj); + rustsecp256k1_v0_1_1_pubkey_save(pubkey, &p); + } + rustsecp256k1_v0_1_1_scalar_clear(&sec); + return ret; +} + +int rustsecp256k1_v0_1_1_ec_privkey_negate(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *seckey) { + rustsecp256k1_v0_1_1_scalar sec; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&sec, seckey, NULL); + rustsecp256k1_v0_1_1_scalar_negate(&sec, &sec); + rustsecp256k1_v0_1_1_scalar_get_b32(seckey, &sec); + + rustsecp256k1_v0_1_1_scalar_clear(&sec); + return 1; +} + +int rustsecp256k1_v0_1_1_ec_pubkey_negate(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_pubkey *pubkey) { + int ret = 0; + rustsecp256k1_v0_1_1_ge p; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + + ret = rustsecp256k1_v0_1_1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + rustsecp256k1_v0_1_1_ge_neg(&p, &p); + rustsecp256k1_v0_1_1_pubkey_save(pubkey, &p); + } + return ret; +} + +int rustsecp256k1_v0_1_1_ec_privkey_tweak_add(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { + rustsecp256k1_v0_1_1_scalar term; + rustsecp256k1_v0_1_1_scalar sec; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + ARG_CHECK(tweak != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&term, tweak, &overflow); + rustsecp256k1_v0_1_1_scalar_set_b32(&sec, seckey, NULL); + + ret = !overflow && rustsecp256k1_v0_1_1_eckey_privkey_tweak_add(&sec, &term); + memset(seckey, 0, 32); + if (ret) { + rustsecp256k1_v0_1_1_scalar_get_b32(seckey, &sec); + } + + rustsecp256k1_v0_1_1_scalar_clear(&sec); + rustsecp256k1_v0_1_1_scalar_clear(&term); + return ret; +} + +int rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_pubkey *pubkey, const unsigned char *tweak) { + rustsecp256k1_v0_1_1_ge p; + rustsecp256k1_v0_1_1_scalar term; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_1_1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(tweak != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&term, tweak, &overflow); + ret = !overflow && rustsecp256k1_v0_1_1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + if (rustsecp256k1_v0_1_1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { + rustsecp256k1_v0_1_1_pubkey_save(pubkey, &p); + } else { + ret = 0; + } + } + + return ret; +} + +int rustsecp256k1_v0_1_1_ec_privkey_tweak_mul(const rustsecp256k1_v0_1_1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { + rustsecp256k1_v0_1_1_scalar factor; + rustsecp256k1_v0_1_1_scalar sec; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + ARG_CHECK(tweak != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&factor, tweak, &overflow); + rustsecp256k1_v0_1_1_scalar_set_b32(&sec, seckey, NULL); + ret = !overflow && rustsecp256k1_v0_1_1_eckey_privkey_tweak_mul(&sec, &factor); + memset(seckey, 0, 32); + if (ret) { + rustsecp256k1_v0_1_1_scalar_get_b32(seckey, &sec); + } + + rustsecp256k1_v0_1_1_scalar_clear(&sec); + rustsecp256k1_v0_1_1_scalar_clear(&factor); + return ret; +} + +int rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_pubkey *pubkey, const unsigned char *tweak) { + rustsecp256k1_v0_1_1_ge p; + rustsecp256k1_v0_1_1_scalar factor; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_1_1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(tweak != NULL); + + rustsecp256k1_v0_1_1_scalar_set_b32(&factor, tweak, &overflow); + ret = !overflow && rustsecp256k1_v0_1_1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + if (rustsecp256k1_v0_1_1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { + rustsecp256k1_v0_1_1_pubkey_save(pubkey, &p); + } else { + ret = 0; + } + } + + return ret; +} + +int rustsecp256k1_v0_1_1_context_randomize(rustsecp256k1_v0_1_1_context* ctx, const unsigned char *seed32) { + VERIFY_CHECK(ctx != NULL); + if (rustsecp256k1_v0_1_1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { + rustsecp256k1_v0_1_1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + } + return 1; +} + +int rustsecp256k1_v0_1_1_ec_pubkey_combine(const rustsecp256k1_v0_1_1_context* ctx, rustsecp256k1_v0_1_1_pubkey *pubnonce, const rustsecp256k1_v0_1_1_pubkey * const *pubnonces, size_t n) { + size_t i; + rustsecp256k1_v0_1_1_gej Qj; + rustsecp256k1_v0_1_1_ge Q; + + ARG_CHECK(pubnonce != NULL); + memset(pubnonce, 0, sizeof(*pubnonce)); + ARG_CHECK(n >= 1); + ARG_CHECK(pubnonces != NULL); + + rustsecp256k1_v0_1_1_gej_set_infinity(&Qj); + + for (i = 0; i < n; i++) { + rustsecp256k1_v0_1_1_pubkey_load(ctx, &Q, pubnonces[i]); + rustsecp256k1_v0_1_1_gej_add_ge(&Qj, &Qj, &Q); + } + if (rustsecp256k1_v0_1_1_gej_is_infinity(&Qj)) { + return 0; + } + rustsecp256k1_v0_1_1_ge_set_gej(&Q, &Qj); + rustsecp256k1_v0_1_1_pubkey_save(pubnonce, &Q); + return 1; +} + +#ifdef ENABLE_MODULE_ECDH +# include "modules/ecdh/main_impl.h" +#endif + +#ifdef ENABLE_MODULE_RECOVERY +# include "modules/recovery/main_impl.h" +#endif diff --git a/depend/secp256k1/src/testrand.h b/secp256k1-sys/depend/secp256k1/src/testrand.h similarity index 63% rename from depend/secp256k1/src/testrand.h rename to secp256k1-sys/depend/secp256k1/src/testrand.h index f8efa93c7..6f11d898a 100644 --- a/depend/secp256k1/src/testrand.h +++ b/secp256k1-sys/depend/secp256k1/src/testrand.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_TESTRAND_H_ -#define _SECP256K1_TESTRAND_H_ +#ifndef SECP256K1_TESTRAND_H +#define SECP256K1_TESTRAND_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -14,25 +14,25 @@ /* A non-cryptographic RNG used only for test infrastructure. */ /** Seed the pseudorandom number generator for testing. */ -SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16); +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_rand_seed(const unsigned char *seed16); /** Generate a pseudorandom number in the range [0..2**32-1]. */ -static uint32_t secp256k1_rand32(void); +static uint32_t rustsecp256k1_v0_1_1_rand32(void); /** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or * more. */ -static uint32_t secp256k1_rand_bits(int bits); +static uint32_t rustsecp256k1_v0_1_1_rand_bits(int bits); /** Generate a pseudorandom number in the range [0..range-1]. */ -static uint32_t secp256k1_rand_int(uint32_t range); +static uint32_t rustsecp256k1_v0_1_1_rand_int(uint32_t range); /** Generate a pseudorandom 32-byte array. */ -static void secp256k1_rand256(unsigned char *b32); +static void rustsecp256k1_v0_1_1_rand256(unsigned char *b32); /** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ -static void secp256k1_rand256_test(unsigned char *b32); +static void rustsecp256k1_v0_1_1_rand256_test(unsigned char *b32); /** Generate pseudorandom bytes with long sequences of zero and one bits. */ -static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len); +static void rustsecp256k1_v0_1_1_rand_bytes_test(unsigned char *bytes, size_t len); -#endif +#endif /* SECP256K1_TESTRAND_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/testrand_impl.h b/secp256k1-sys/depend/secp256k1/src/testrand_impl.h new file mode 100644 index 000000000..9ef7a9c8e --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/testrand_impl.h @@ -0,0 +1,110 @@ +/********************************************************************** + * 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.* + **********************************************************************/ + +#ifndef SECP256K1_TESTRAND_IMPL_H +#define SECP256K1_TESTRAND_IMPL_H + +#include +#include + +#include "testrand.h" +#include "hash.h" + +static rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 rustsecp256k1_v0_1_1_test_rng; +static uint32_t rustsecp256k1_v0_1_1_test_rng_precomputed[8]; +static int rustsecp256k1_v0_1_1_test_rng_precomputed_used = 8; +static uint64_t rustsecp256k1_v0_1_1_test_rng_integer; +static int rustsecp256k1_v0_1_1_test_rng_integer_bits_left = 0; + +SECP256K1_INLINE static void rustsecp256k1_v0_1_1_rand_seed(const unsigned char *seed16) { + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(&rustsecp256k1_v0_1_1_test_rng, seed16, 16); +} + +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_1_1_rand32(void) { + if (rustsecp256k1_v0_1_1_test_rng_precomputed_used == 8) { + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rustsecp256k1_v0_1_1_test_rng, (unsigned char*)(&rustsecp256k1_v0_1_1_test_rng_precomputed[0]), sizeof(rustsecp256k1_v0_1_1_test_rng_precomputed)); + rustsecp256k1_v0_1_1_test_rng_precomputed_used = 0; + } + return rustsecp256k1_v0_1_1_test_rng_precomputed[rustsecp256k1_v0_1_1_test_rng_precomputed_used++]; +} + +static uint32_t rustsecp256k1_v0_1_1_rand_bits(int bits) { + uint32_t ret; + if (rustsecp256k1_v0_1_1_test_rng_integer_bits_left < bits) { + rustsecp256k1_v0_1_1_test_rng_integer |= (((uint64_t)rustsecp256k1_v0_1_1_rand32()) << rustsecp256k1_v0_1_1_test_rng_integer_bits_left); + rustsecp256k1_v0_1_1_test_rng_integer_bits_left += 32; + } + ret = rustsecp256k1_v0_1_1_test_rng_integer; + rustsecp256k1_v0_1_1_test_rng_integer >>= bits; + rustsecp256k1_v0_1_1_test_rng_integer_bits_left -= bits; + ret &= ((~((uint32_t)0)) >> (32 - bits)); + return ret; +} + +static uint32_t rustsecp256k1_v0_1_1_rand_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 = rustsecp256k1_v0_1_1_rand_bits(bits); + if (x < trange) { + return (mult == 1) ? x : (x % range); + } + } +} + +static void rustsecp256k1_v0_1_1_rand256(unsigned char *b32) { + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rustsecp256k1_v0_1_1_test_rng, b32, 32); +} + +static void rustsecp256k1_v0_1_1_rand_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 + (rustsecp256k1_v0_1_1_rand_bits(6) * rustsecp256k1_v0_1_1_rand_bits(5) + 16) / 31; + val = rustsecp256k1_v0_1_1_rand_bits(1); + while (now > 0 && bits < len * 8) { + bytes[bits / 8] |= val << (bits % 8); + now--; + bits++; + } + } +} + +static void rustsecp256k1_v0_1_1_rand256_test(unsigned char *b32) { + rustsecp256k1_v0_1_1_rand_bytes_test(b32, 32); +} + +#endif /* SECP256K1_TESTRAND_IMPL_H */ diff --git a/depend/secp256k1/src/tests.c b/secp256k1-sys/depend/secp256k1/src/tests.c similarity index 51% rename from depend/secp256k1/src/tests.c rename to secp256k1-sys/depend/secp256k1/src/tests.c index 3abfe1254..28c2de6a4 100644 --- a/depend/secp256k1/src/tests.c +++ b/secp256k1-sys/depend/secp256k1/src/tests.c @@ -10,11 +10,13 @@ #include #include +#include #include #include "secp256k1.c" #include "include/secp256k1.h" +#include "include/secp256k1_preallocated.h" #include "testrand_impl.h" #ifdef ENABLE_OPENSSL_TESTS @@ -22,6 +24,9 @@ #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" @@ -39,7 +44,7 @@ #endif static int count = 64; -static secp256k1_context *ctx = NULL; +static rustsecp256k1_v0_1_1_context *ctx = NULL; static void counting_illegal_callback_fn(const char* str, void* data) { /* Dummy callback function that just counts. */ @@ -57,183 +62,345 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) { (*p)--; } -void random_field_element_test(secp256k1_fe *fe) { +void random_field_element_test(rustsecp256k1_v0_1_1_fe *fe) { do { unsigned char b32[32]; - secp256k1_rand256_test(b32); - if (secp256k1_fe_set_b32(fe, b32)) { + rustsecp256k1_v0_1_1_rand256_test(b32); + if (rustsecp256k1_v0_1_1_fe_set_b32(fe, b32)) { break; } } while(1); } -void random_field_element_magnitude(secp256k1_fe *fe) { - secp256k1_fe zero; - int n = secp256k1_rand_int(9); - secp256k1_fe_normalize(fe); +void random_field_element_magnitude(rustsecp256k1_v0_1_1_fe *fe) { + rustsecp256k1_v0_1_1_fe zero; + int n = rustsecp256k1_v0_1_1_rand_int(9); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_clear(&zero); + rustsecp256k1_v0_1_1_fe_negate(&zero, &zero, 0); + rustsecp256k1_v0_1_1_fe_mul_int(&zero, n - 1); + rustsecp256k1_v0_1_1_fe_add(fe, &zero); VERIFY_CHECK(fe->magnitude == n); } -void random_group_element_test(secp256k1_ge *ge) { - secp256k1_fe fe; +void random_group_element_test(rustsecp256k1_v0_1_1_ge *ge) { + rustsecp256k1_v0_1_1_fe fe; do { random_field_element_test(&fe); - if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_rand_bits(1))) { - secp256k1_fe_normalize(&ge->y); + if (rustsecp256k1_v0_1_1_ge_set_xo_var(ge, &fe, rustsecp256k1_v0_1_1_rand_bits(1))) { + rustsecp256k1_v0_1_1_fe_normalize(&ge->y); break; } } while(1); } -void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { - secp256k1_fe z2, z3; +void random_group_element_jacobian_test(rustsecp256k1_v0_1_1_gej *gej, const rustsecp256k1_v0_1_1_ge *ge) { + rustsecp256k1_v0_1_1_fe z2, z3; do { random_field_element_test(&gej->z); - if (!secp256k1_fe_is_zero(&gej->z)) { + if (!rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_sqr(&z2, &gej->z); + rustsecp256k1_v0_1_1_fe_mul(&z3, &z2, &gej->z); + rustsecp256k1_v0_1_1_fe_mul(&gej->x, &ge->x, &z2); + rustsecp256k1_v0_1_1_fe_mul(&gej->y, &ge->y, &z3); gej->infinity = ge->infinity; } -void random_scalar_order_test(secp256k1_scalar *num) { +void random_scalar_order_test(rustsecp256k1_v0_1_1_scalar *num) { do { unsigned char b32[32]; int overflow = 0; - secp256k1_rand256_test(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { + rustsecp256k1_v0_1_1_rand256_test(b32); + rustsecp256k1_v0_1_1_scalar_set_b32(num, b32, &overflow); + if (overflow || rustsecp256k1_v0_1_1_scalar_is_zero(num)) { continue; } break; } while(1); } -void random_scalar_order(secp256k1_scalar *num) { +void random_scalar_order(rustsecp256k1_v0_1_1_scalar *num) { do { unsigned char b32[32]; int overflow = 0; - secp256k1_rand256(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { + rustsecp256k1_v0_1_1_rand256(b32); + rustsecp256k1_v0_1_1_scalar_set_b32(num, b32, &overflow); + if (overflow || rustsecp256k1_v0_1_1_scalar_is_zero(num)) { continue; } break; } while(1); } -void run_context_tests(void) { - secp256k1_pubkey pubkey; - secp256k1_ecdsa_signature sig; +void run_context_tests(int use_prealloc) { + rustsecp256k1_v0_1_1_pubkey pubkey; + rustsecp256k1_v0_1_1_pubkey zero_pubkey; + rustsecp256k1_v0_1_1_ecdsa_signature sig; unsigned char ctmp[32]; int32_t ecount; int32_t ecount2; - secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); - secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); - secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + rustsecp256k1_v0_1_1_context *none; + rustsecp256k1_v0_1_1_context *sign; + rustsecp256k1_v0_1_1_context *vrfy; + rustsecp256k1_v0_1_1_context *both; + void *none_prealloc = NULL; + void *sign_prealloc = NULL; + void *vrfy_prealloc = NULL; + void *both_prealloc = NULL; + + rustsecp256k1_v0_1_1_gej pubj; + rustsecp256k1_v0_1_1_ge pub; + rustsecp256k1_v0_1_1_scalar msg, key, nonce; + rustsecp256k1_v0_1_1_scalar sigr, sigs; + + if (use_prealloc) { + none_prealloc = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); + sign_prealloc = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); + vrfy_prealloc = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); + both_prealloc = malloc(rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_context_preallocated_create(none_prealloc, SECP256K1_CONTEXT_NONE); + sign = rustsecp256k1_v0_1_1_context_preallocated_create(sign_prealloc, SECP256K1_CONTEXT_SIGN); + vrfy = rustsecp256k1_v0_1_1_context_preallocated_create(vrfy_prealloc, SECP256K1_CONTEXT_VERIFY); + both = rustsecp256k1_v0_1_1_context_preallocated_create(both_prealloc, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + } else { + none = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_NONE); + sign = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN); + vrfy = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_VERIFY); + both = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + } - secp256k1_gej pubj; - secp256k1_ge pub; - secp256k1_scalar msg, key, nonce; - secp256k1_scalar sigr, sigs; + memset(&zero_pubkey, 0, sizeof(zero_pubkey)); ecount = 0; ecount2 = 10; - secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); - secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2); - secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL); + rustsecp256k1_v0_1_1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2); + rustsecp256k1_v0_1_1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL); CHECK(vrfy->error_callback.fn != sign->error_callback.fn); + /* check if sizes for cloning are consistent */ + CHECK(rustsecp256k1_v0_1_1_context_preallocated_clone_size(none) == rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); + CHECK(rustsecp256k1_v0_1_1_context_preallocated_clone_size(sign) == rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); + CHECK(rustsecp256k1_v0_1_1_context_preallocated_clone_size(vrfy) == rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); + CHECK(rustsecp256k1_v0_1_1_context_preallocated_clone_size(both) == rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_context *ctx_tmp; + + if (use_prealloc) { + /* clone into a non-preallocated context and then again into a new preallocated one. */ + ctx_tmp = none; none = rustsecp256k1_v0_1_1_context_clone(none); rustsecp256k1_v0_1_1_context_preallocated_destroy(ctx_tmp); + free(none_prealloc); none_prealloc = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(none_prealloc != NULL); + ctx_tmp = none; none = rustsecp256k1_v0_1_1_context_preallocated_clone(none, none_prealloc); rustsecp256k1_v0_1_1_context_destroy(ctx_tmp); + + ctx_tmp = sign; sign = rustsecp256k1_v0_1_1_context_clone(sign); rustsecp256k1_v0_1_1_context_preallocated_destroy(ctx_tmp); + free(sign_prealloc); sign_prealloc = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(sign_prealloc != NULL); + ctx_tmp = sign; sign = rustsecp256k1_v0_1_1_context_preallocated_clone(sign, sign_prealloc); rustsecp256k1_v0_1_1_context_destroy(ctx_tmp); - ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp); - ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp); + ctx_tmp = vrfy; vrfy = rustsecp256k1_v0_1_1_context_clone(vrfy); rustsecp256k1_v0_1_1_context_preallocated_destroy(ctx_tmp); + free(vrfy_prealloc); vrfy_prealloc = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(vrfy_prealloc != NULL); + ctx_tmp = vrfy; vrfy = rustsecp256k1_v0_1_1_context_preallocated_clone(vrfy, vrfy_prealloc); rustsecp256k1_v0_1_1_context_destroy(ctx_tmp); + + ctx_tmp = both; both = rustsecp256k1_v0_1_1_context_clone(both); rustsecp256k1_v0_1_1_context_preallocated_destroy(ctx_tmp); + free(both_prealloc); both_prealloc = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(both_prealloc != NULL); + ctx_tmp = both; both = rustsecp256k1_v0_1_1_context_preallocated_clone(both, both_prealloc); rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(prealloc_tmp != NULL); + ctx_tmp = none; none = rustsecp256k1_v0_1_1_context_preallocated_clone(none, prealloc_tmp); rustsecp256k1_v0_1_1_context_destroy(ctx_tmp); + ctx_tmp = none; none = rustsecp256k1_v0_1_1_context_clone(none); rustsecp256k1_v0_1_1_context_preallocated_destroy(ctx_tmp); + free(prealloc_tmp); + + prealloc_tmp = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_SIGN)); CHECK(prealloc_tmp != NULL); + ctx_tmp = sign; sign = rustsecp256k1_v0_1_1_context_preallocated_clone(sign, prealloc_tmp); rustsecp256k1_v0_1_1_context_destroy(ctx_tmp); + ctx_tmp = sign; sign = rustsecp256k1_v0_1_1_context_clone(sign); rustsecp256k1_v0_1_1_context_preallocated_destroy(ctx_tmp); + free(prealloc_tmp); + + prealloc_tmp = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL); + ctx_tmp = vrfy; vrfy = rustsecp256k1_v0_1_1_context_preallocated_clone(vrfy, prealloc_tmp); rustsecp256k1_v0_1_1_context_destroy(ctx_tmp); + ctx_tmp = vrfy; vrfy = rustsecp256k1_v0_1_1_context_clone(vrfy); rustsecp256k1_v0_1_1_context_preallocated_destroy(ctx_tmp); + free(prealloc_tmp); + + prealloc_tmp = malloc(rustsecp256k1_v0_1_1_context_preallocated_size(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)); CHECK(prealloc_tmp != NULL); + ctx_tmp = both; both = rustsecp256k1_v0_1_1_context_preallocated_clone(both, prealloc_tmp); rustsecp256k1_v0_1_1_context_destroy(ctx_tmp); + ctx_tmp = both; both = rustsecp256k1_v0_1_1_context_clone(both); rustsecp256k1_v0_1_1_context_preallocated_destroy(ctx_tmp); + free(prealloc_tmp); + } } /* Verify that the error callback makes it across the clone. */ CHECK(vrfy->error_callback.fn != sign->error_callback.fn); /* And that it resets back to default. */ - secp256k1_context_set_error_callback(sign, NULL, NULL); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key); + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0); CHECK(ecount == 1); VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(sign, &pubkey, ctmp) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0); CHECK(ecount2 == 11); - CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1); CHECK(ecount == 2); - CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0); CHECK(ecount2 == 12); - CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1); CHECK(ecount == 2); - CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); CHECK(ecount2 == 13); - CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_negate(vrfy, &pubkey) == 1); CHECK(ecount == 2); - CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_negate(sign, &pubkey) == 1); + CHECK(ecount == 2); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_negate(sign, NULL) == 0); + CHECK(ecount2 == 14); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0); CHECK(ecount == 3); - CHECK(secp256k1_context_randomize(sign, NULL) == 1); - CHECK(ecount2 == 13); - secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); - secp256k1_context_set_illegal_callback(sign, NULL, NULL); - - /* This shouldn't leak memory, due to already-set tests. */ - secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL); - secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); + CHECK(ecount == 3); + CHECK(rustsecp256k1_v0_1_1_context_randomize(vrfy, ctmp) == 1); + CHECK(ecount == 3); + CHECK(rustsecp256k1_v0_1_1_context_randomize(vrfy, NULL) == 1); + CHECK(ecount == 3); + CHECK(rustsecp256k1_v0_1_1_context_randomize(sign, ctmp) == 1); + CHECK(ecount2 == 14); + CHECK(rustsecp256k1_v0_1_1_context_randomize(sign, NULL) == 1); + CHECK(ecount2 == 14); + rustsecp256k1_v0_1_1_context_set_illegal_callback(vrfy, NULL, NULL); + rustsecp256k1_v0_1_1_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)); + } while(!rustsecp256k1_v0_1_1_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)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + CHECK(rustsecp256k1_v0_1_1_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)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg)); /* cleanup */ - secp256k1_context_destroy(none); - secp256k1_context_destroy(sign); - secp256k1_context_destroy(vrfy); - secp256k1_context_destroy(both); + if (use_prealloc) { + rustsecp256k1_v0_1_1_context_preallocated_destroy(none); + rustsecp256k1_v0_1_1_context_preallocated_destroy(sign); + rustsecp256k1_v0_1_1_context_preallocated_destroy(vrfy); + rustsecp256k1_v0_1_1_context_preallocated_destroy(both); + free(none_prealloc); + free(sign_prealloc); + free(vrfy_prealloc); + free(both_prealloc); + } else { + rustsecp256k1_v0_1_1_context_destroy(none); + rustsecp256k1_v0_1_1_context_destroy(sign); + rustsecp256k1_v0_1_1_context_destroy(vrfy); + rustsecp256k1_v0_1_1_context_destroy(both); + } /* Defined as no-op. */ - secp256k1_context_destroy(NULL); + rustsecp256k1_v0_1_1_context_destroy(NULL); + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_context *none = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_NONE); + rustsecp256k1_v0_1_1_scratch_space *scratch; + rustsecp256k1_v0_1_1_scratch_space local_scratch; + + /* Test public API */ + rustsecp256k1_v0_1_1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); + + scratch = rustsecp256k1_v0_1_1_scratch_space_create(none, 1000); + CHECK(scratch != NULL); + CHECK(ecount == 0); + + /* Test internal API */ + CHECK(rustsecp256k1_v0_1_1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000); + CHECK(rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_scratch_checkpoint(&none->error_callback, scratch); + CHECK(rustsecp256k1_v0_1_1_scratch_alloc(&none->error_callback, scratch, 500) != NULL); + CHECK(rustsecp256k1_v0_1_1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc); + CHECK(rustsecp256k1_v0_1_1_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 500 bytes fails */ + CHECK(rustsecp256k1_v0_1_1_scratch_alloc(&none->error_callback, scratch, 500) == NULL); + CHECK(rustsecp256k1_v0_1_1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000 - adj_alloc); + CHECK(rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint); + CHECK(scratch->alloc_size == 0); + CHECK(rustsecp256k1_v0_1_1_scratch_max_allocation(&none->error_callback, scratch, 0) == 1000); + CHECK(rustsecp256k1_v0_1_1_scratch_alloc(&none->error_callback, scratch, 500) != NULL); + CHECK(scratch->alloc_size != 0); + + /* try to apply a bad checkpoint */ + checkpoint_2 = rustsecp256k1_v0_1_1_scratch_checkpoint(&none->error_callback, scratch); + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint); + CHECK(ecount == 0); + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(&none->error_callback, scratch, checkpoint_2); /* checkpoint_2 is after checkpoint */ + CHECK(ecount == 1); + rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_scratch_space_destroy(none, scratch); + memset(&local_scratch, 0, sizeof(local_scratch)); + scratch = &local_scratch; + CHECK(!rustsecp256k1_v0_1_1_scratch_max_allocation(&none->error_callback, scratch, 0)); + CHECK(ecount == 3); + CHECK(rustsecp256k1_v0_1_1_scratch_alloc(&none->error_callback, scratch, 500) == NULL); + CHECK(ecount == 4); + rustsecp256k1_v0_1_1_scratch_space_destroy(none, scratch); + CHECK(ecount == 5); + + /* cleanup */ + rustsecp256k1_v0_1_1_scratch_space_destroy(none, NULL); /* no-op */ + rustsecp256k1_v0_1_1_context_destroy(none); } /***** HASH TESTS *****/ @@ -258,17 +425,17 @@ void run_sha256_tests(void) { int i; for (i = 0; i < 8; i++) { unsigned char out[32]; - secp256k1_sha256_t hasher; - secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - secp256k1_sha256_finalize(&hasher, out); + rustsecp256k1_v0_1_1_sha256 hasher; + rustsecp256k1_v0_1_1_sha256_initialize(&hasher); + rustsecp256k1_v0_1_1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + rustsecp256k1_v0_1_1_sha256_finalize(&hasher, out); CHECK(memcmp(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { - int split = secp256k1_rand_int(strlen(inputs[i])); - secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - secp256k1_sha256_finalize(&hasher, out); + int split = rustsecp256k1_v0_1_1_rand_int(strlen(inputs[i])); + rustsecp256k1_v0_1_1_sha256_initialize(&hasher); + rustsecp256k1_v0_1_1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + rustsecp256k1_v0_1_1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + rustsecp256k1_v0_1_1_sha256_finalize(&hasher, out); CHECK(memcmp(out, outputs[i], 32) == 0); } } @@ -301,18 +468,18 @@ void run_hmac_sha256_tests(void) { }; int i; for (i = 0; i < 6; i++) { - secp256k1_hmac_sha256_t hasher; + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hasher, out); CHECK(memcmp(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { - int split = secp256k1_rand_int(strlen(inputs[i])); - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - secp256k1_hmac_sha256_finalize(&hasher, out); + int split = rustsecp256k1_v0_1_1_rand_int(strlen(inputs[i])); + rustsecp256k1_v0_1_1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + rustsecp256k1_v0_1_1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + rustsecp256k1_v0_1_1_hmac_sha256_finalize(&hasher, out); CHECK(memcmp(out, outputs[i], 32) == 0); } } @@ -333,30 +500,30 @@ void run_rfc6979_hmac_sha256_tests(void) { {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} }; - secp256k1_rfc6979_hmac_sha256_t rng; + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256 rng; unsigned char out[32]; int i; - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rng, out, 32); CHECK(memcmp(out, out1[i], 32) == 0); } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rng, out, 32); CHECK(memcmp(out, out1[i], 32) != 0); } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_generate(&rng, out, 32); CHECK(memcmp(out, out2[i], 32) == 0); } - secp256k1_rfc6979_hmac_sha256_finalize(&rng); + rustsecp256k1_v0_1_1_rfc6979_hmac_sha256_finalize(&rng); } /***** RANDOM TESTS *****/ @@ -378,7 +545,7 @@ void test_rand_bits(int rand32, int bits) { /* Multiply the output of all rand calls with the odd number m, which should not change the uniformity of its distribution. */ for (i = 0; i < rounds[usebits]; i++) { - uint32_t r = (rand32 ? secp256k1_rand32() : secp256k1_rand_bits(bits)); + uint32_t r = (rand32 ? rustsecp256k1_v0_1_1_rand32() : rustsecp256k1_v0_1_1_rand_bits(bits)); CHECK((((uint64_t)r) >> bits) == 0); for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { uint32_t rm = r * mults[m]; @@ -403,7 +570,7 @@ void test_rand_int(uint32_t range, uint32_t subrange) { uint64_t x = 0; CHECK((range % subrange) == 0); for (i = 0; i < rounds; i++) { - uint32_t r = secp256k1_rand_int(range); + uint32_t r = rustsecp256k1_v0_1_1_rand_int(range); CHECK(r < range); r = r % subrange; x |= (((uint64_t)1) << r); @@ -434,70 +601,176 @@ void run_rand_int(void) { /***** NUM TESTS *****/ #ifndef USE_NUM_NONE -void random_num_negate(secp256k1_num *num) { - if (secp256k1_rand_bits(1)) { - secp256k1_num_negate(num); +void random_num_negate(rustsecp256k1_v0_1_1_num *num) { + if (rustsecp256k1_v0_1_1_rand_bits(1)) { + rustsecp256k1_v0_1_1_num_negate(num); } } -void random_num_order_test(secp256k1_num *num) { - secp256k1_scalar sc; +void random_num_order_test(rustsecp256k1_v0_1_1_num *num) { + rustsecp256k1_v0_1_1_scalar sc; random_scalar_order_test(&sc); - secp256k1_scalar_get_num(num, &sc); + rustsecp256k1_v0_1_1_scalar_get_num(num, &sc); } -void random_num_order(secp256k1_num *num) { - secp256k1_scalar sc; +void random_num_order(rustsecp256k1_v0_1_1_num *num) { + rustsecp256k1_v0_1_1_scalar sc; random_scalar_order(&sc); - secp256k1_scalar_get_num(num, &sc); + rustsecp256k1_v0_1_1_scalar_get_num(num, &sc); } void test_num_negate(void) { - secp256k1_num n1; - secp256k1_num n2; + rustsecp256k1_v0_1_1_num n1; + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_num_copy(&n2, &n1); /* n2 = R */ + rustsecp256k1_v0_1_1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */ + CHECK(rustsecp256k1_v0_1_1_num_is_zero(&n1)); + rustsecp256k1_v0_1_1_num_copy(&n1, &n2); /* n1 = R */ + rustsecp256k1_v0_1_1_num_negate(&n1); /* n1 = -R */ + CHECK(!rustsecp256k1_v0_1_1_num_is_zero(&n1)); + rustsecp256k1_v0_1_1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */ + CHECK(rustsecp256k1_v0_1_1_num_is_zero(&n1)); + rustsecp256k1_v0_1_1_num_copy(&n1, &n2); /* n1 = R */ + rustsecp256k1_v0_1_1_num_negate(&n1); /* n1 = -R */ + CHECK(rustsecp256k1_v0_1_1_num_is_neg(&n1) != rustsecp256k1_v0_1_1_num_is_neg(&n2)); + rustsecp256k1_v0_1_1_num_negate(&n1); /* n1 = R */ + CHECK(rustsecp256k1_v0_1_1_num_eq(&n1, &n2)); } void test_num_add_sub(void) { - secp256k1_num n1; - secp256k1_num n2; - secp256k1_num n1p2, n2p1, n1m2, n2m1; + int i; + rustsecp256k1_v0_1_1_scalar s; + rustsecp256k1_v0_1_1_num n1; + rustsecp256k1_v0_1_1_num n2; + rustsecp256k1_v0_1_1_num n1p2, n2p1, n1m2, n2m1; random_num_order_test(&n1); /* n1 = R1 */ - if (secp256k1_rand_bits(1)) { + if (rustsecp256k1_v0_1_1_rand_bits(1)) { random_num_negate(&n1); } random_num_order_test(&n2); /* n2 = R2 */ - if (secp256k1_rand_bits(1)) { + if (rustsecp256k1_v0_1_1_rand_bits(1)) { random_num_negate(&n2); } - secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ - secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ - secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ - secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ - CHECK(secp256k1_num_eq(&n1p2, &n2p1)); - CHECK(!secp256k1_num_eq(&n1p2, &n1m2)); - secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ - CHECK(secp256k1_num_eq(&n2m1, &n1m2)); - CHECK(!secp256k1_num_eq(&n2m1, &n1)); - secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ - CHECK(secp256k1_num_eq(&n2m1, &n1)); - CHECK(!secp256k1_num_eq(&n2p1, &n1)); - secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ - CHECK(secp256k1_num_eq(&n2p1, &n1)); + rustsecp256k1_v0_1_1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ + rustsecp256k1_v0_1_1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ + rustsecp256k1_v0_1_1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ + rustsecp256k1_v0_1_1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ + CHECK(rustsecp256k1_v0_1_1_num_eq(&n1p2, &n2p1)); + CHECK(!rustsecp256k1_v0_1_1_num_eq(&n1p2, &n1m2)); + rustsecp256k1_v0_1_1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ + CHECK(rustsecp256k1_v0_1_1_num_eq(&n2m1, &n1m2)); + CHECK(!rustsecp256k1_v0_1_1_num_eq(&n2m1, &n1)); + rustsecp256k1_v0_1_1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ + CHECK(rustsecp256k1_v0_1_1_num_eq(&n2m1, &n1)); + CHECK(!rustsecp256k1_v0_1_1_num_eq(&n2p1, &n1)); + rustsecp256k1_v0_1_1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ + CHECK(rustsecp256k1_v0_1_1_num_eq(&n2p1, &n1)); + + /* check is_one */ + rustsecp256k1_v0_1_1_scalar_set_int(&s, 1); + rustsecp256k1_v0_1_1_scalar_get_num(&n1, &s); + CHECK(rustsecp256k1_v0_1_1_num_is_one(&n1)); + /* check that 2^n + 1 is never 1 */ + rustsecp256k1_v0_1_1_scalar_get_num(&n2, &s); + for (i = 0; i < 250; ++i) { + rustsecp256k1_v0_1_1_num_add(&n1, &n1, &n1); /* n1 *= 2 */ + rustsecp256k1_v0_1_1_num_add(&n1p2, &n1, &n2); /* n1p2 = n1 + 1 */ + CHECK(!rustsecp256k1_v0_1_1_num_is_one(&n1p2)); + } +} + +void test_num_mod(void) { + int i; + rustsecp256k1_v0_1_1_scalar s; + rustsecp256k1_v0_1_1_num order, n; + + /* check that 0 mod anything is 0 */ + random_scalar_order_test(&s); + rustsecp256k1_v0_1_1_scalar_get_num(&order, &s); + rustsecp256k1_v0_1_1_scalar_set_int(&s, 0); + rustsecp256k1_v0_1_1_scalar_get_num(&n, &s); + rustsecp256k1_v0_1_1_num_mod(&n, &order); + CHECK(rustsecp256k1_v0_1_1_num_is_zero(&n)); + + /* check that anything mod 1 is 0 */ + rustsecp256k1_v0_1_1_scalar_set_int(&s, 1); + rustsecp256k1_v0_1_1_scalar_get_num(&order, &s); + rustsecp256k1_v0_1_1_scalar_get_num(&n, &s); + rustsecp256k1_v0_1_1_num_mod(&n, &order); + CHECK(rustsecp256k1_v0_1_1_num_is_zero(&n)); + + /* check that increasing the number past 2^256 does not break this */ + random_scalar_order_test(&s); + rustsecp256k1_v0_1_1_scalar_get_num(&n, &s); + /* multiply by 2^8, which'll test this case with high probability */ + for (i = 0; i < 8; ++i) { + rustsecp256k1_v0_1_1_num_add(&n, &n, &n); + } + rustsecp256k1_v0_1_1_num_mod(&n, &order); + CHECK(rustsecp256k1_v0_1_1_num_is_zero(&n)); +} + +void test_num_jacobi(void) { + rustsecp256k1_v0_1_1_scalar sqr; + rustsecp256k1_v0_1_1_scalar small; + rustsecp256k1_v0_1_1_scalar five; /* five is not a quadratic residue */ + rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_scalar_set_int(&five, 5); + rustsecp256k1_v0_1_1_scalar_get_num(&order, &five); + for (i = 0; i < 10; ++i) { + rustsecp256k1_v0_1_1_scalar_set_int(&small, i); + rustsecp256k1_v0_1_1_scalar_get_num(&n, &small); + CHECK(rustsecp256k1_v0_1_1_num_jacobi(&n, &order) == jacobi5[i]); + } + + /** test large values with 5 as group order */ + rustsecp256k1_v0_1_1_scalar_get_num(&order, &five); + /* we first need a scalar which is not a multiple of 5 */ + do { + rustsecp256k1_v0_1_1_num fiven; + random_scalar_order_test(&sqr); + rustsecp256k1_v0_1_1_scalar_get_num(&fiven, &five); + rustsecp256k1_v0_1_1_scalar_get_num(&n, &sqr); + rustsecp256k1_v0_1_1_num_mod(&n, &fiven); + } while (rustsecp256k1_v0_1_1_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 (rustsecp256k1_v0_1_1_num_jacobi(&n, &order) == -1) { + rustsecp256k1_v0_1_1_num_add(&n, &n, &n); + } + + /* test residue */ + CHECK(rustsecp256k1_v0_1_1_num_jacobi(&n, &order) == 1); + /* test nonresidue */ + rustsecp256k1_v0_1_1_num_add(&n, &n, &n); + CHECK(rustsecp256k1_v0_1_1_num_jacobi(&n, &order) == -1); + + /** test with secp group order as order */ + rustsecp256k1_v0_1_1_scalar_order_get_num(&order); + random_scalar_order_test(&sqr); + rustsecp256k1_v0_1_1_scalar_sqr(&sqr, &sqr); + /* test residue */ + rustsecp256k1_v0_1_1_scalar_get_num(&n, &sqr); + CHECK(rustsecp256k1_v0_1_1_num_jacobi(&n, &order) == 1); + /* test nonresidue */ + rustsecp256k1_v0_1_1_scalar_mul(&sqr, &sqr, &five); + rustsecp256k1_v0_1_1_scalar_get_num(&n, &sqr); + CHECK(rustsecp256k1_v0_1_1_num_jacobi(&n, &order) == -1); + /* test multiple of the order*/ + CHECK(rustsecp256k1_v0_1_1_num_jacobi(&order, &order) == 0); + + /* check one less than the order */ + rustsecp256k1_v0_1_1_scalar_set_int(&small, 1); + rustsecp256k1_v0_1_1_scalar_get_num(&n, &small); + rustsecp256k1_v0_1_1_num_sub(&n, &order, &n); + CHECK(rustsecp256k1_v0_1_1_num_jacobi(&n, &order) == 1); /* sage confirms this is 1 */ } void run_num_smalltests(void) { @@ -505,6 +778,8 @@ void run_num_smalltests(void) { for (i = 0; i < 100*count; i++) { test_num_negate(); test_num_add_sub(); + test_num_mod(); + test_num_jacobi(); } } #endif @@ -512,12 +787,12 @@ void run_num_smalltests(void) { /***** SCALAR TESTS *****/ void scalar_test(void) { - secp256k1_scalar s; - secp256k1_scalar s1; - secp256k1_scalar s2; + rustsecp256k1_v0_1_1_scalar s; + rustsecp256k1_v0_1_1_scalar s1; + rustsecp256k1_v0_1_1_scalar s2; #ifndef USE_NUM_NONE - secp256k1_num snum, s1num, s2num; - secp256k1_num order, half_order; + rustsecp256k1_v0_1_1_num snum, s1num, s2num; + rustsecp256k1_v0_1_1_num order, half_order; #endif unsigned char c[32]; @@ -529,141 +804,141 @@ void scalar_test(void) { /* 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); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_get_num(&snum, &s); + rustsecp256k1_v0_1_1_scalar_get_num(&s1num, &s1); + rustsecp256k1_v0_1_1_scalar_get_num(&s2num, &s2); - secp256k1_scalar_order_get_num(&order); + rustsecp256k1_v0_1_1_scalar_order_get_num(&order); half_order = order; - secp256k1_num_shift(&half_order, 1); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar n; + rustsecp256k1_v0_1_1_scalar_set_int(&n, 0); for (i = 0; i < 256; i += 4) { - secp256k1_scalar t; + rustsecp256k1_v0_1_1_scalar t; int j; - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); + rustsecp256k1_v0_1_1_scalar_set_int(&t, rustsecp256k1_v0_1_1_scalar_get_bits(&s, 256 - 4 - i, 4)); for (j = 0; j < 4; j++) { - secp256k1_scalar_add(&n, &n, &n); + rustsecp256k1_v0_1_1_scalar_add(&n, &n, &n); } - secp256k1_scalar_add(&n, &n, &t); + rustsecp256k1_v0_1_1_scalar_add(&n, &n, &t); } - CHECK(secp256k1_scalar_eq(&n, &s)); + CHECK(rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_scalar n; int i = 0; - secp256k1_scalar_set_int(&n, 0); + rustsecp256k1_v0_1_1_scalar_set_int(&n, 0); while (i < 256) { - secp256k1_scalar t; + rustsecp256k1_v0_1_1_scalar t; int j; - int now = secp256k1_rand_int(15) + 1; + int now = rustsecp256k1_v0_1_1_rand_int(15) + 1; if (now + i > 256) { now = 256 - i; } - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); + rustsecp256k1_v0_1_1_scalar_set_int(&t, rustsecp256k1_v0_1_1_scalar_get_bits_var(&s, 256 - now - i, now)); for (j = 0; j < now; j++) { - secp256k1_scalar_add(&n, &n, &n); + rustsecp256k1_v0_1_1_scalar_add(&n, &n, &n); } - secp256k1_scalar_add(&n, &n, &t); + rustsecp256k1_v0_1_1_scalar_add(&n, &n, &t); i += now; } - CHECK(secp256k1_scalar_eq(&n, &s)); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_num rnum; + rustsecp256k1_v0_1_1_num r2num; + rustsecp256k1_v0_1_1_scalar r; + rustsecp256k1_v0_1_1_num_add(&rnum, &snum, &s2num); + rustsecp256k1_v0_1_1_num_mod(&rnum, &order); + rustsecp256k1_v0_1_1_scalar_add(&r, &s, &s2); + rustsecp256k1_v0_1_1_scalar_get_num(&r2num, &r); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r; + rustsecp256k1_v0_1_1_num r2num; + rustsecp256k1_v0_1_1_num rnum; + rustsecp256k1_v0_1_1_num_mul(&rnum, &snum, &s2num); + rustsecp256k1_v0_1_1_num_mod(&rnum, &order); + rustsecp256k1_v0_1_1_scalar_mul(&r, &s, &s2); + rustsecp256k1_v0_1_1_scalar_get_num(&r2num, &r); + CHECK(rustsecp256k1_v0_1_1_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))); + CHECK(rustsecp256k1_v0_1_1_scalar_is_zero(&r) == (rustsecp256k1_v0_1_1_scalar_is_zero(&s) || rustsecp256k1_v0_1_1_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))); + CHECK(rustsecp256k1_v0_1_1_num_eq(&rnum, &snum) == (rustsecp256k1_v0_1_1_scalar_is_zero(&s) || rustsecp256k1_v0_1_1_scalar_is_one(&s2))); + CHECK(rustsecp256k1_v0_1_1_num_eq(&rnum, &s2num) == (rustsecp256k1_v0_1_1_scalar_is_zero(&s2) || rustsecp256k1_v0_1_1_scalar_is_one(&s))); } { - secp256k1_scalar neg; - secp256k1_num negnum; - secp256k1_num negnum2; + rustsecp256k1_v0_1_1_scalar neg; + rustsecp256k1_v0_1_1_num negnum; + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_num_is_zero(&snum) == rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_scalar_is_high(&s) == (rustsecp256k1_v0_1_1_num_cmp(&snum, &half_order) > 0)); + rustsecp256k1_v0_1_1_scalar_negate(&neg, &s); + rustsecp256k1_v0_1_1_num_sub(&negnum, &order, &snum); + rustsecp256k1_v0_1_1_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)); + CHECK(rustsecp256k1_v0_1_1_scalar_is_high(&neg) == (rustsecp256k1_v0_1_1_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); + CHECK((rustsecp256k1_v0_1_1_scalar_is_high(&s) == rustsecp256k1_v0_1_1_scalar_is_high(&neg)) == rustsecp256k1_v0_1_1_scalar_is_zero(&s)); + rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_num_eq(&negnum, &negnum2)); + rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_scalar_is_zero(&neg)); + rustsecp256k1_v0_1_1_scalar_negate(&neg, &neg); /* Negating zero should still result in zero. */ - CHECK(secp256k1_scalar_is_zero(&neg)); + CHECK(rustsecp256k1_v0_1_1_scalar_is_zero(&neg)); } { - /* Test secp256k1_scalar_mul_shift_var. */ - secp256k1_scalar r; - secp256k1_num one; - secp256k1_num rnum; - secp256k1_num rnum2; + /* Test rustsecp256k1_v0_1_1_scalar_mul_shift_var. */ + rustsecp256k1_v0_1_1_scalar r; + rustsecp256k1_v0_1_1_num one; + rustsecp256k1_v0_1_1_num rnum; + rustsecp256k1_v0_1_1_num rnum2; unsigned char cone[1] = {0x01}; - unsigned int shift = 256 + secp256k1_rand_int(257); - secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift); - secp256k1_num_mul(&rnum, &s1num, &s2num); - secp256k1_num_shift(&rnum, shift - 1); - secp256k1_num_set_bin(&one, cone, 1); - secp256k1_num_add(&rnum, &rnum, &one); - secp256k1_num_shift(&rnum, 1); - secp256k1_scalar_get_num(&rnum2, &r); - CHECK(secp256k1_num_eq(&rnum, &rnum2)); + unsigned int shift = 256 + rustsecp256k1_v0_1_1_rand_int(257); + rustsecp256k1_v0_1_1_scalar_mul_shift_var(&r, &s1, &s2, shift); + rustsecp256k1_v0_1_1_num_mul(&rnum, &s1num, &s2num); + rustsecp256k1_v0_1_1_num_shift(&rnum, shift - 1); + rustsecp256k1_v0_1_1_num_set_bin(&one, cone, 1); + rustsecp256k1_v0_1_1_num_add(&rnum, &rnum, &one); + rustsecp256k1_v0_1_1_num_shift(&rnum, 1); + rustsecp256k1_v0_1_1_scalar_get_num(&rnum2, &r); + CHECK(rustsecp256k1_v0_1_1_num_eq(&rnum, &rnum2)); } { - /* test secp256k1_scalar_shr_int */ - secp256k1_scalar r; + /* test rustsecp256k1_v0_1_1_scalar_shr_int */ + rustsecp256k1_v0_1_1_scalar r; int i; random_scalar_order_test(&r); for (i = 0; i < 100; ++i) { int low; - int shift = 1 + secp256k1_rand_int(15); + int shift = 1 + rustsecp256k1_v0_1_1_rand_int(15); int expected = r.d[0] % (1 << shift); - low = secp256k1_scalar_shr_int(&r, shift); + low = rustsecp256k1_v0_1_1_scalar_shr_int(&r, shift); CHECK(expected == low); } } @@ -671,127 +946,131 @@ void scalar_test(void) { { /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ - if (!secp256k1_scalar_is_zero(&s)) { - secp256k1_scalar inv; + if (!rustsecp256k1_v0_1_1_scalar_is_zero(&s)) { + rustsecp256k1_v0_1_1_scalar inv; #ifndef USE_NUM_NONE - secp256k1_num invnum; - secp256k1_num invnum2; + rustsecp256k1_v0_1_1_num invnum; + rustsecp256k1_v0_1_1_num invnum2; #endif - secp256k1_scalar_inverse(&inv, &s); + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_num_mod_inverse(&invnum, &snum, &order); + rustsecp256k1_v0_1_1_scalar_get_num(&invnum2, &inv); + CHECK(rustsecp256k1_v0_1_1_num_eq(&invnum, &invnum2)); #endif - secp256k1_scalar_mul(&inv, &inv, &s); + rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_scalar_is_one(&inv)); + rustsecp256k1_v0_1_1_scalar_inverse(&inv, &inv); /* Inverting one must result in one. */ - CHECK(secp256k1_scalar_is_one(&inv)); + CHECK(rustsecp256k1_v0_1_1_scalar_is_one(&inv)); +#ifndef USE_NUM_NONE + rustsecp256k1_v0_1_1_scalar_get_num(&invnum, &inv); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, r2; + rustsecp256k1_v0_1_1_scalar_add(&r1, &s1, &s2); + rustsecp256k1_v0_1_1_scalar_add(&r2, &s2, &s1); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&r1, &r2)); } { - secp256k1_scalar r1, r2; - secp256k1_scalar b; + rustsecp256k1_v0_1_1_scalar r1, r2; + rustsecp256k1_v0_1_1_scalar b; int i; /* Test add_bit. */ - int bit = secp256k1_rand_bits(8); - secp256k1_scalar_set_int(&b, 1); - CHECK(secp256k1_scalar_is_one(&b)); + int bit = rustsecp256k1_v0_1_1_rand_bits(8); + rustsecp256k1_v0_1_1_scalar_set_int(&b, 1); + CHECK(rustsecp256k1_v0_1_1_scalar_is_one(&b)); for (i = 0; i < bit; i++) { - secp256k1_scalar_add(&b, &b, &b); + rustsecp256k1_v0_1_1_scalar_add(&b, &b, &b); } r1 = s1; r2 = s1; - if (!secp256k1_scalar_add(&r1, &r1, &b)) { + if (!rustsecp256k1_v0_1_1_scalar_add(&r1, &r1, &b)) { /* No overflow happened. */ - secp256k1_scalar_cadd_bit(&r2, bit, 1); - CHECK(secp256k1_scalar_eq(&r1, &r2)); + rustsecp256k1_v0_1_1_scalar_cadd_bit(&r2, bit, 1); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar_cadd_bit(&r2, bit, 0); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, r2; + rustsecp256k1_v0_1_1_scalar_mul(&r1, &s1, &s2); + rustsecp256k1_v0_1_1_scalar_mul(&r2, &s2, &s1); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, r2; + rustsecp256k1_v0_1_1_scalar_add(&r1, &s1, &s2); + rustsecp256k1_v0_1_1_scalar_add(&r1, &r1, &s); + rustsecp256k1_v0_1_1_scalar_add(&r2, &s2, &s); + rustsecp256k1_v0_1_1_scalar_add(&r2, &s1, &r2); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, r2; + rustsecp256k1_v0_1_1_scalar_mul(&r1, &s1, &s2); + rustsecp256k1_v0_1_1_scalar_mul(&r1, &r1, &s); + rustsecp256k1_v0_1_1_scalar_mul(&r2, &s2, &s); + rustsecp256k1_v0_1_1_scalar_mul(&r2, &s1, &r2); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, r2, t; + rustsecp256k1_v0_1_1_scalar_add(&r1, &s1, &s2); + rustsecp256k1_v0_1_1_scalar_mul(&r1, &r1, &s); + rustsecp256k1_v0_1_1_scalar_mul(&r2, &s1, &s); + rustsecp256k1_v0_1_1_scalar_mul(&t, &s2, &s); + rustsecp256k1_v0_1_1_scalar_add(&r2, &r2, &t); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, r2; + rustsecp256k1_v0_1_1_scalar_sqr(&r1, &s1); + rustsecp256k1_v0_1_1_scalar_mul(&r2, &s1, &s1); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, v1; + rustsecp256k1_v0_1_1_scalar_set_int(&v1,1); + rustsecp256k1_v0_1_1_scalar_mul(&r1, &s1, &v1); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, v0; + rustsecp256k1_v0_1_1_scalar_set_int(&v0,0); + rustsecp256k1_v0_1_1_scalar_add(&r1, &s1, &v0); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar r1, v0; + rustsecp256k1_v0_1_1_scalar_set_int(&v0,0); + rustsecp256k1_v0_1_1_scalar_mul(&r1, &s1, &v0); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&r1, &v0)); } } @@ -804,38 +1083,38 @@ void run_scalar_tests(void) { { /* (-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)); + rustsecp256k1_v0_1_1_scalar s, o; + rustsecp256k1_v0_1_1_scalar_set_int(&s, 1); + CHECK(rustsecp256k1_v0_1_1_scalar_is_one(&s)); + rustsecp256k1_v0_1_1_scalar_negate(&o, &s); + rustsecp256k1_v0_1_1_scalar_add(&o, &o, &s); + CHECK(rustsecp256k1_v0_1_1_scalar_is_zero(&o)); + rustsecp256k1_v0_1_1_scalar_negate(&o, &o); + CHECK(rustsecp256k1_v0_1_1_scalar_is_zero(&o)); } #ifndef USE_NUM_NONE { /* A scalar with value of the curve order should be 0. */ - secp256k1_num order; - secp256k1_scalar zero; + rustsecp256k1_v0_1_1_num order; + rustsecp256k1_v0_1_1_scalar zero; unsigned char bin[32]; int overflow = 0; - secp256k1_scalar_order_get_num(&order); - secp256k1_num_get_bin(bin, 32, &order); - secp256k1_scalar_set_b32(&zero, bin, &overflow); + rustsecp256k1_v0_1_1_scalar_order_get_num(&order); + rustsecp256k1_v0_1_1_num_get_bin(bin, 32, &order); + rustsecp256k1_v0_1_1_scalar_set_b32(&zero, bin, &overflow); CHECK(overflow == 1); - CHECK(secp256k1_scalar_is_zero(&zero)); + CHECK(rustsecp256k1_v0_1_1_scalar_is_zero(&zero)); } #endif { /* Does check_overflow check catch all ones? */ - static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( + static const rustsecp256k1_v0_1_1_scalar overflowed = SECP256K1_SCALAR_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); - CHECK(secp256k1_scalar_check_overflow(&overflowed)); + CHECK(rustsecp256k1_v0_1_1_scalar_check_overflow(&overflowed)); } { @@ -844,18 +1123,18 @@ void run_scalar_tests(void) { * 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; + rustsecp256k1_v0_1_1_scalar x; + rustsecp256k1_v0_1_1_scalar y; + rustsecp256k1_v0_1_1_scalar z; + rustsecp256k1_v0_1_1_scalar zz; + rustsecp256k1_v0_1_1_scalar one; + rustsecp256k1_v0_1_1_scalar r1; + rustsecp256k1_v0_1_1_scalar r2; #if defined(USE_SCALAR_INV_NUM) - secp256k1_scalar zzv; + rustsecp256k1_v0_1_1_scalar zzv; #endif int overflow; - unsigned char chal[32][2][32] = { + 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, @@ -1111,9 +1390,17 @@ void run_scalar_tests(void) { {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}} + 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[32][2][32] = { + 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, @@ -1369,73 +1656,81 @@ void run_scalar_tests(void) { {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}} + 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 < 32; i++) { - secp256k1_scalar_set_b32(&x, chal[i][0], &overflow); + rustsecp256k1_v0_1_1_scalar_set_int(&one, 1); + for (i = 0; i < 33; i++) { + rustsecp256k1_v0_1_1_scalar_set_b32(&x, chal[i][0], &overflow); CHECK(!overflow); - secp256k1_scalar_set_b32(&y, chal[i][1], &overflow); + rustsecp256k1_v0_1_1_scalar_set_b32(&y, chal[i][1], &overflow); CHECK(!overflow); - secp256k1_scalar_set_b32(&r1, res[i][0], &overflow); + rustsecp256k1_v0_1_1_scalar_set_b32(&r1, res[i][0], &overflow); CHECK(!overflow); - secp256k1_scalar_set_b32(&r2, res[i][1], &overflow); + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar_mul(&z, &x, &y); + CHECK(!rustsecp256k1_v0_1_1_scalar_check_overflow(&z)); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&r1, &z)); + if (!rustsecp256k1_v0_1_1_scalar_is_zero(&y)) { + rustsecp256k1_v0_1_1_scalar_inverse(&zz, &y); + CHECK(!rustsecp256k1_v0_1_1_scalar_check_overflow(&zz)); #if defined(USE_SCALAR_INV_NUM) - secp256k1_scalar_inverse_var(&zzv, &y); - CHECK(secp256k1_scalar_eq(&zzv, &zz)); + rustsecp256k1_v0_1_1_scalar_inverse_var(&zzv, &y); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar_mul(&z, &z, &zz); + CHECK(!rustsecp256k1_v0_1_1_scalar_check_overflow(&z)); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&x, &z)); + rustsecp256k1_v0_1_1_scalar_mul(&zz, &zz, &y); + CHECK(!rustsecp256k1_v0_1_1_scalar_check_overflow(&zz)); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_scalar_mul(&z, &x, &x); + CHECK(!rustsecp256k1_v0_1_1_scalar_check_overflow(&z)); + rustsecp256k1_v0_1_1_scalar_sqr(&zz, &x); + CHECK(!rustsecp256k1_v0_1_1_scalar_check_overflow(&zz)); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&zz, &z)); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&r2, &zz)); } } } /***** FIELD TESTS *****/ -void random_fe(secp256k1_fe *x) { +void random_fe(rustsecp256k1_v0_1_1_fe *x) { unsigned char bin[32]; do { - secp256k1_rand256(bin); - if (secp256k1_fe_set_b32(x, bin)) { + rustsecp256k1_v0_1_1_rand256(bin); + if (rustsecp256k1_v0_1_1_fe_set_b32(x, bin)) { return; } } while(1); } -void random_fe_test(secp256k1_fe *x) { +void random_fe_test(rustsecp256k1_v0_1_1_fe *x) { unsigned char bin[32]; do { - secp256k1_rand256_test(bin); - if (secp256k1_fe_set_b32(x, bin)) { + rustsecp256k1_v0_1_1_rand256_test(bin); + if (rustsecp256k1_v0_1_1_fe_set_b32(x, bin)) { return; } } while(1); } -void random_fe_non_zero(secp256k1_fe *nz) { +void random_fe_non_zero(rustsecp256k1_v0_1_1_fe *nz) { int tries = 10; while (--tries >= 0) { random_fe(nz); - secp256k1_fe_normalize(nz); - if (!secp256k1_fe_is_zero(nz)) { + rustsecp256k1_v0_1_1_fe_normalize(nz); + if (!rustsecp256k1_v0_1_1_fe_is_zero(nz)) { break; } } @@ -1443,26 +1738,26 @@ void random_fe_non_zero(secp256k1_fe *nz) { CHECK(tries >= 0); } -void random_fe_non_square(secp256k1_fe *ns) { - secp256k1_fe r; +void random_fe_non_square(rustsecp256k1_v0_1_1_fe *ns) { + rustsecp256k1_v0_1_1_fe r; random_fe_non_zero(ns); - if (secp256k1_fe_sqrt_var(&r, ns)) { - secp256k1_fe_negate(ns, ns, 1); + if (rustsecp256k1_v0_1_1_fe_sqrt(&r, ns)) { + rustsecp256k1_v0_1_1_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_equal(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *b) { + rustsecp256k1_v0_1_1_fe an = *a; + rustsecp256k1_v0_1_1_fe bn = *b; + rustsecp256k1_v0_1_1_fe_normalize_weak(&an); + rustsecp256k1_v0_1_1_fe_normalize_var(&bn); + return rustsecp256k1_v0_1_1_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); +int check_fe_inverse(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *ai) { + rustsecp256k1_v0_1_1_fe x; + rustsecp256k1_v0_1_1_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); + rustsecp256k1_v0_1_1_fe_mul(&x, a, ai); return check_fe_equal(&x, &one); } @@ -1473,150 +1768,150 @@ void run_field_convert(void) { 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( + static const rustsecp256k1_v0_1_1_fe_storage fes = SECP256K1_FE_STORAGE_CONST( 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL ); - static const secp256k1_fe fe = SECP256K1_FE_CONST( + static const rustsecp256k1_v0_1_1_fe fe = SECP256K1_FE_CONST( 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL ); - secp256k1_fe fe2; + rustsecp256k1_v0_1_1_fe fe2; unsigned char b322[32]; - secp256k1_fe_storage fes2; + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_fe_set_b32(&fe2, b32)); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&fe, &fe2)); + rustsecp256k1_v0_1_1_fe_from_storage(&fe2, &fes); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&fe, &fe2)); /* Check conversion from fe. */ - secp256k1_fe_get_b32(b322, &fe); + rustsecp256k1_v0_1_1_fe_get_b32(b322, &fe); CHECK(memcmp(b322, b32, 32) == 0); - secp256k1_fe_to_storage(&fes2, &fe); + rustsecp256k1_v0_1_1_fe_to_storage(&fes2, &fe); CHECK(memcmp(&fes2, &fes, sizeof(fes)) == 0); } -int fe_memcmp(const secp256k1_fe *a, const secp256k1_fe *b) { - secp256k1_fe t = *b; +int fe_memcmp(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *b) { + rustsecp256k1_v0_1_1_fe t = *b; #ifdef VERIFY t.magnitude = a->magnitude; t.normalized = a->normalized; #endif - return memcmp(a, &t, sizeof(secp256k1_fe)); + return memcmp(a, &t, sizeof(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe x; + rustsecp256k1_v0_1_1_fe y; + rustsecp256k1_v0_1_1_fe z; + rustsecp256k1_v0_1_1_fe q; + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_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)); + CHECK(rustsecp256k1_v0_1_1_fe_cmp_var(&x, &x) == 0); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&x, &x)); z = x; - secp256k1_fe_add(&z,&y); + rustsecp256k1_v0_1_1_fe_add(&z,&y); /* Test fe conditional move; z is not normalized here. */ q = x; - secp256k1_fe_cmov(&x, &z, 0); + rustsecp256k1_v0_1_1_fe_cmov(&x, &z, 0); VERIFY_CHECK(!x.normalized && x.magnitude == z.magnitude); - secp256k1_fe_cmov(&x, &x, 1); + rustsecp256k1_v0_1_1_fe_cmov(&x, &x, 1); CHECK(fe_memcmp(&x, &z) != 0); CHECK(fe_memcmp(&x, &q) == 0); - secp256k1_fe_cmov(&q, &z, 1); + rustsecp256k1_v0_1_1_fe_cmov(&q, &z, 1); VERIFY_CHECK(!q.normalized && q.magnitude == z.magnitude); CHECK(fe_memcmp(&q, &z) == 0); - secp256k1_fe_normalize_var(&x); - secp256k1_fe_normalize_var(&z); - CHECK(!secp256k1_fe_equal_var(&x, &z)); - secp256k1_fe_normalize_var(&q); - secp256k1_fe_cmov(&q, &z, (i&1)); + rustsecp256k1_v0_1_1_fe_normalize_var(&x); + rustsecp256k1_v0_1_1_fe_normalize_var(&z); + CHECK(!rustsecp256k1_v0_1_1_fe_equal_var(&x, &z)); + rustsecp256k1_v0_1_1_fe_normalize_var(&q); + rustsecp256k1_v0_1_1_fe_cmov(&q, &z, (i&1)); VERIFY_CHECK(q.normalized && q.magnitude == 1); for (j = 0; j < 6; j++) { - secp256k1_fe_negate(&z, &z, j+1); - secp256k1_fe_normalize_var(&q); - secp256k1_fe_cmov(&q, &z, (j&1)); + rustsecp256k1_v0_1_1_fe_negate(&z, &z, j+1); + rustsecp256k1_v0_1_1_fe_normalize_var(&q); + rustsecp256k1_v0_1_1_fe_cmov(&q, &z, (j&1)); VERIFY_CHECK(!q.normalized && q.magnitude == (j+2)); } - secp256k1_fe_normalize_var(&z); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_to_storage(&xs, &x); + rustsecp256k1_v0_1_1_fe_to_storage(&ys, &y); + rustsecp256k1_v0_1_1_fe_to_storage(&zs, &z); + rustsecp256k1_v0_1_1_fe_storage_cmov(&zs, &xs, 0); + rustsecp256k1_v0_1_1_fe_storage_cmov(&zs, &zs, 1); CHECK(memcmp(&xs, &zs, sizeof(xs)) != 0); - secp256k1_fe_storage_cmov(&ys, &xs, 1); + rustsecp256k1_v0_1_1_fe_storage_cmov(&ys, &xs, 1); CHECK(memcmp(&xs, &ys, sizeof(xs)) == 0); - secp256k1_fe_from_storage(&x, &xs); - secp256k1_fe_from_storage(&y, &ys); - secp256k1_fe_from_storage(&z, &zs); + rustsecp256k1_v0_1_1_fe_from_storage(&x, &xs); + rustsecp256k1_v0_1_1_fe_from_storage(&y, &ys); + rustsecp256k1_v0_1_1_fe_from_storage(&z, &zs); /* Test that mul_int, mul, and add agree. */ - secp256k1_fe_add(&y, &x); - secp256k1_fe_add(&y, &x); + rustsecp256k1_v0_1_1_fe_add(&y, &x); + rustsecp256k1_v0_1_1_fe_add(&y, &x); z = x; - secp256k1_fe_mul_int(&z, 3); + rustsecp256k1_v0_1_1_fe_mul_int(&z, 3); CHECK(check_fe_equal(&y, &z)); - secp256k1_fe_add(&y, &x); - secp256k1_fe_add(&z, &x); + rustsecp256k1_v0_1_1_fe_add(&y, &x); + rustsecp256k1_v0_1_1_fe_add(&z, &x); CHECK(check_fe_equal(&z, &y)); z = x; - secp256k1_fe_mul_int(&z, 5); - secp256k1_fe_mul(&q, &x, &fe5); + rustsecp256k1_v0_1_1_fe_mul_int(&z, 5); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_negate(&x, &x, 1); + rustsecp256k1_v0_1_1_fe_add(&z, &x); + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_fe x, xi, xii; int i; for (i = 0; i < 10*count; i++) { random_fe_non_zero(&x); - secp256k1_fe_inv(&xi, &x); + rustsecp256k1_v0_1_1_fe_inv(&xi, &x); CHECK(check_fe_inverse(&x, &xi)); - secp256k1_fe_inv(&xii, &xi); + rustsecp256k1_v0_1_1_fe_inv(&xii, &xi); CHECK(check_fe_equal(&x, &xii)); } } void run_field_inv_var(void) { - secp256k1_fe x, xi, xii; + rustsecp256k1_v0_1_1_fe x, xi, xii; int i; for (i = 0; i < 10*count; i++) { random_fe_non_zero(&x); - secp256k1_fe_inv_var(&xi, &x); + rustsecp256k1_v0_1_1_fe_inv_var(&xi, &x); CHECK(check_fe_inverse(&x, &xi)); - secp256k1_fe_inv_var(&xii, &xi); + rustsecp256k1_v0_1_1_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]; + rustsecp256k1_v0_1_1_fe x[16], xi[16], xii[16]; int i; /* Check it's safe to call for 0 elements */ - secp256k1_fe_inv_all_var(0, xi, x); + rustsecp256k1_v0_1_1_fe_inv_all_var(xi, x, 0); for (i = 0; i < count; i++) { size_t j; - size_t len = secp256k1_rand_int(15) + 1; + size_t len = rustsecp256k1_v0_1_1_rand_int(15) + 1; for (j = 0; j < len; j++) { random_fe_non_zero(&x[j]); } - secp256k1_fe_inv_all_var(len, xi, x); + rustsecp256k1_v0_1_1_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(len, xii, xi); + rustsecp256k1_v0_1_1_fe_inv_all_var(xii, xi, len); for (j = 0; j < len; j++) { CHECK(check_fe_equal(&x[j], &xii[j])); } @@ -1624,50 +1919,50 @@ void run_field_inv_all_var(void) { } void run_sqr(void) { - secp256k1_fe x, s; + rustsecp256k1_v0_1_1_fe x, s; { int i; - secp256k1_fe_set_int(&x, 1); - secp256k1_fe_negate(&x, &x, 1); + rustsecp256k1_v0_1_1_fe_set_int(&x, 1); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_mul_int(&x, 2); + rustsecp256k1_v0_1_1_fe_normalize(&x); + rustsecp256k1_v0_1_1_fe_sqr(&s, &x); } } } -void test_sqrt(const secp256k1_fe *a, const secp256k1_fe *k) { - secp256k1_fe r1, r2; - int v = secp256k1_fe_sqrt_var(&r1, a); +void test_sqrt(const rustsecp256k1_v0_1_1_fe *a, const rustsecp256k1_v0_1_1_fe *k) { + rustsecp256k1_v0_1_1_fe r1, r2; + int v = rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_fe_negate(&r2, &r1, 1); + rustsecp256k1_v0_1_1_fe_add(&r1, k); rustsecp256k1_v0_1_1_fe_add(&r2, k); + rustsecp256k1_v0_1_1_fe_normalize(&r1); rustsecp256k1_v0_1_1_fe_normalize(&r2); + CHECK(rustsecp256k1_v0_1_1_fe_is_zero(&r1) || rustsecp256k1_v0_1_1_fe_is_zero(&r2)); } } void run_sqrt(void) { - secp256k1_fe ns, x, s, t; + rustsecp256k1_v0_1_1_fe ns, x, s, t; int i; /* Check sqrt(0) is 0 */ - secp256k1_fe_set_int(&x, 0); - secp256k1_fe_sqr(&s, &x); + rustsecp256k1_v0_1_1_fe_set_int(&x, 0); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_set_int(&x, i); + rustsecp256k1_v0_1_1_fe_sqr(&s, &x); test_sqrt(&s, &x); - secp256k1_fe_negate(&t, &s, 1); + rustsecp256k1_v0_1_1_fe_negate(&t, &s, 1); test_sqrt(&t, NULL); } @@ -1677,11 +1972,11 @@ void run_sqrt(void) { random_fe_non_square(&ns); for (j = 0; j < count; j++) { random_fe(&x); - secp256k1_fe_sqr(&s, &x); + rustsecp256k1_v0_1_1_fe_sqr(&s, &x); test_sqrt(&s, &x); - secp256k1_fe_negate(&t, &s, 1); + rustsecp256k1_v0_1_1_fe_negate(&t, &s, 1); test_sqrt(&t, NULL); - secp256k1_fe_mul(&t, &s, &ns); + rustsecp256k1_v0_1_1_fe_mul(&t, &s, &ns); test_sqrt(&t, NULL); } } @@ -1689,52 +1984,52 @@ void run_sqrt(void) { /***** GROUP TESTS *****/ -void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { +void ge_equals_ge(const rustsecp256k1_v0_1_1_ge *a, const rustsecp256k1_v0_1_1_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)); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&a->x, &b->x)); + CHECK(rustsecp256k1_v0_1_1_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 gej_xyz_equals_gej(const rustsecp256k1_v0_1_1_gej *a, const rustsecp256k1_v0_1_1_gej *b) { + rustsecp256k1_v0_1_1_gej a2; + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_fe_normalize(&a2.x); + rustsecp256k1_v0_1_1_fe_normalize(&a2.y); + rustsecp256k1_v0_1_1_fe_normalize(&a2.z); + rustsecp256k1_v0_1_1_fe_normalize(&b2.x); + rustsecp256k1_v0_1_1_fe_normalize(&b2.y); + rustsecp256k1_v0_1_1_fe_normalize(&b2.z); + ret &= rustsecp256k1_v0_1_1_fe_cmp_var(&a2.x, &b2.x) == 0; + ret &= rustsecp256k1_v0_1_1_fe_cmp_var(&a2.y, &b2.y) == 0; + ret &= rustsecp256k1_v0_1_1_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; +void ge_equals_gej(const rustsecp256k1_v0_1_1_ge *a, const rustsecp256k1_v0_1_1_gej *b) { + rustsecp256k1_v0_1_1_fe z2s; + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_fe_sqr(&z2s, &b->z); + rustsecp256k1_v0_1_1_fe_mul(&u1, &a->x, &z2s); + u2 = b->x; rustsecp256k1_v0_1_1_fe_normalize_weak(&u2); + rustsecp256k1_v0_1_1_fe_mul(&s1, &a->y, &z2s); rustsecp256k1_v0_1_1_fe_mul(&s1, &s1, &b->z); + s2 = b->y; rustsecp256k1_v0_1_1_fe_normalize_weak(&s2); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&u1, &u2)); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&s1, &s2)); } void test_ge(void) { @@ -1751,34 +2046,34 @@ void test_ge(void) { * * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. */ - secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); - secp256k1_fe *zinv = (secp256k1_fe *)malloc(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]); + rustsecp256k1_v0_1_1_ge *ge = (rustsecp256k1_v0_1_1_ge *)checked_malloc(&ctx->error_callback, sizeof(rustsecp256k1_v0_1_1_ge) * (1 + 4 * runs)); + rustsecp256k1_v0_1_1_gej *gej = (rustsecp256k1_v0_1_1_gej *)checked_malloc(&ctx->error_callback, sizeof(rustsecp256k1_v0_1_1_gej) * (1 + 4 * runs)); + rustsecp256k1_v0_1_1_fe *zinv = (rustsecp256k1_v0_1_1_fe *)checked_malloc(&ctx->error_callback, sizeof(rustsecp256k1_v0_1_1_fe) * (1 + 4 * runs)); + rustsecp256k1_v0_1_1_fe zf; + rustsecp256k1_v0_1_1_fe zfi2, zfi3; + + rustsecp256k1_v0_1_1_gej_set_infinity(&gej[0]); + rustsecp256k1_v0_1_1_ge_clear(&ge[0]); + rustsecp256k1_v0_1_1_ge_set_gej_var(&ge[0], &gej[0]); for (i = 0; i < runs; i++) { int j; - secp256k1_ge g; + rustsecp256k1_v0_1_1_ge g; random_group_element_test(&g); #ifdef USE_ENDOMORPHISM if (i >= runs - 2) { - secp256k1_ge_mul_lambda(&g, &ge[1]); + rustsecp256k1_v0_1_1_ge_mul_lambda(&g, &ge[1]); } if (i >= runs - 1) { - secp256k1_ge_mul_lambda(&g, &g); + rustsecp256k1_v0_1_1_ge_mul_lambda(&g, &g); } #endif ge[1 + 4 * i] = g; ge[2 + 4 * i] = g; - secp256k1_ge_neg(&ge[3 + 4 * i], &g); - secp256k1_ge_neg(&ge[4 + 4 * i], &g); - secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); + rustsecp256k1_v0_1_1_ge_neg(&ge[3 + 4 * i], &g); + rustsecp256k1_v0_1_1_ge_neg(&ge[4 + 4 * i], &g); + rustsecp256k1_v0_1_1_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]); + rustsecp256k1_v0_1_1_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); @@ -1791,99 +2086,99 @@ void test_ge(void) { /* Compute z inverses. */ { - secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + rustsecp256k1_v0_1_1_fe *zs = checked_malloc(&ctx->error_callback, sizeof(rustsecp256k1_v0_1_1_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])); + } while(rustsecp256k1_v0_1_1_fe_is_zero(&zs[i])); } else { zs[i] = gej[i].z; } } - secp256k1_fe_inv_all_var(4 * runs + 1, zinv, zs); + rustsecp256k1_v0_1_1_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)); + } while(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_inv_var(&zfi3, &zf); + rustsecp256k1_v0_1_1_fe_sqr(&zfi2, &zfi3); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_gej refj, resj; + rustsecp256k1_v0_1_1_ge ref; + rustsecp256k1_v0_1_1_fe zr; + rustsecp256k1_v0_1_1_gej_add_var(&refj, &gej[i1], &gej[i2], rustsecp256k1_v0_1_1_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)); + if (!rustsecp256k1_v0_1_1_gej_is_infinity(&gej[i1]) && !rustsecp256k1_v0_1_1_gej_is_infinity(&refj)) { + rustsecp256k1_v0_1_1_fe zrz; rustsecp256k1_v0_1_1_fe_mul(&zrz, &zr, &gej[i1].z); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&zrz, &refj.z)); } - secp256k1_ge_set_gej_var(&ref, &refj); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_gej_add_ge_var(&resj, &gej[i1], &ge[i2], rustsecp256k1_v0_1_1_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)); + if (!rustsecp256k1_v0_1_1_gej_is_infinity(&gej[i1]) && !rustsecp256k1_v0_1_1_gej_is_infinity(&resj)) { + rustsecp256k1_v0_1_1_fe zrz; rustsecp256k1_v0_1_1_fe_mul(&zrz, &zr, &gej[i1].z); + CHECK(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ + rustsecp256k1_v0_1_1_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_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]); + /* rustsecp256k1_v0_1_1_gej_add_ge does not support its second argument being infinity. */ + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_fe zr2; /* Normal doubling with Z ratio result. */ - secp256k1_gej_double_var(&resj, &gej[i1], &zr2); + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_fe_mul(&zr2, &zr2, &gej[i1].z); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&zr2, &resj.z)); /* Normal doubling. */ - secp256k1_gej_double_var(&resj, &gej[i2], NULL); + rustsecp256k1_v0_1_1_gej_double_var(&resj, &gej[i2], NULL); ge_equals_gej(&ref, &resj); } /* Test adding opposites. */ if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) { - CHECK(secp256k1_ge_is_infinity(&ref)); + CHECK(rustsecp256k1_v0_1_1_ge_is_infinity(&ref)); } /* Test adding infinity. */ if (i1 == 0) { - CHECK(secp256k1_ge_is_infinity(&ge[i1])); - CHECK(secp256k1_gej_is_infinity(&gej[i1])); + CHECK(rustsecp256k1_v0_1_1_ge_is_infinity(&ge[i1])); + CHECK(rustsecp256k1_v0_1_1_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])); + CHECK(rustsecp256k1_v0_1_1_ge_is_infinity(&ge[i2])); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&gej[i2])); ge_equals_gej(&ref, &gej[i1]); } } @@ -1891,51 +2186,63 @@ void test_ge(void) { /* Test adding all points together in random order equals infinity. */ { - secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); + rustsecp256k1_v0_1_1_gej sum = SECP256K1_GEJ_CONST_INFINITY; + rustsecp256k1_v0_1_1_gej *gej_shuffled = (rustsecp256k1_v0_1_1_gej *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(rustsecp256k1_v0_1_1_gej)); for (i = 0; i < 4 * runs + 1; i++) { gej_shuffled[i] = gej[i]; } for (i = 0; i < 4 * runs + 1; i++) { - int swap = i + secp256k1_rand_int(4 * runs + 1 - i); + int swap = i + rustsecp256k1_v0_1_1_rand_int(4 * runs + 1 - i); if (swap != i) { - secp256k1_gej t = gej_shuffled[i]; + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); } - CHECK(secp256k1_gej_is_infinity(&sum)); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&sum)); free(gej_shuffled); } /* Test batch gej -> ge conversion with and without known z ratios. */ { - secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); - secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); + rustsecp256k1_v0_1_1_fe *zr = (rustsecp256k1_v0_1_1_fe *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(rustsecp256k1_v0_1_1_fe)); + rustsecp256k1_v0_1_1_ge *ge_set_all = (rustsecp256k1_v0_1_1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_mul(&zr[i + 1], &zinv[i], &gej[i + 1].z); } } - secp256k1_ge_set_table_gej_var(4 * runs + 1, ge_set_table, gej, zr); - secp256k1_ge_set_all_gej_var(4 * runs + 1, ge_set_all, gej, &ctx->error_callback); + rustsecp256k1_v0_1_1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1); for (i = 0; i < 4 * runs + 1; i++) { - secp256k1_fe s; + rustsecp256k1_v0_1_1_fe s; random_fe_non_zero(&s); - secp256k1_gej_rescale(&gej[i], &s); - ge_equals_gej(&ge_set_table[i], &gej[i]); + rustsecp256k1_v0_1_1_gej_rescale(&gej[i], &s); ge_equals_gej(&ge_set_all[i], &gej[i]); } - free(ge_set_table); 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 infinitiy */ + if(rustsecp256k1_v0_1_1_fe_is_odd(&ge[i].x)) { + rustsecp256k1_v0_1_1_ge_set_infinity(&ge[i]); + } + rustsecp256k1_v0_1_1_gej_set_ge(&gej[i], &ge[i]); + } + /* batch invert */ + rustsecp256k1_v0_1_1_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); @@ -1951,8 +2258,8 @@ void test_add_neg_y_diff_x(void) { * 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/secp256k1/issues/257 which - * this test is a regression test for. + * 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 @@ -1972,39 +2279,39 @@ void test_add_neg_y_diff_x(void) { * print " Q: %x %x" % Q.xy() * print "P + Q: %x %x" % (P + Q).xy() */ - secp256k1_gej aj = SECP256K1_GEJ_CONST( + rustsecp256k1_v0_1_1_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( + rustsecp256k1_v0_1_1_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( + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_ge b; + rustsecp256k1_v0_1_1_gej resj; + rustsecp256k1_v0_1_1_ge res; + rustsecp256k1_v0_1_1_ge_set_gej(&b, &bj); - secp256k1_gej_add_var(&resj, &aj, &bj, NULL); - secp256k1_ge_set_gej(&res, &resj); + rustsecp256k1_v0_1_1_gej_add_var(&resj, &aj, &bj, NULL); + rustsecp256k1_v0_1_1_ge_set_gej(&res, &resj); ge_equals_gej(&res, &sumj); - secp256k1_gej_add_ge(&resj, &aj, &b); - secp256k1_ge_set_gej(&res, &resj); + rustsecp256k1_v0_1_1_gej_add_ge(&resj, &aj, &b); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_gej_add_ge_var(&resj, &aj, &b, NULL); + rustsecp256k1_v0_1_1_ge_set_gej(&res, &resj); ge_equals_gej(&res, &sumj); } @@ -2017,26 +2324,26 @@ void run_ge(void) { } 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; + rustsecp256k1_v0_1_1_scalar sum = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + rustsecp256k1_v0_1_1_pubkey data[6]; + const rustsecp256k1_v0_1_1_pubkey* d[6]; + rustsecp256k1_v0_1_1_pubkey sd; + rustsecp256k1_v0_1_1_pubkey sd2; + rustsecp256k1_v0_1_1_gej Qj; + rustsecp256k1_v0_1_1_ge Q; int i; for (i = 1; i <= 6; i++) { - secp256k1_scalar s; + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_add(&sum, &sum, &s); + rustsecp256k1_v0_1_1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &s); + rustsecp256k1_v0_1_1_ge_set_gej(&Q, &Qj); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sum); + rustsecp256k1_v0_1_1_ge_set_gej(&Q, &Qj); + rustsecp256k1_v0_1_1_pubkey_save(&sd, &Q); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_combine(ctx, &sd2, d, i) == 1); CHECK(memcmp(&sd, &sd2, sizeof(sd)) == 0); } } @@ -2048,31 +2355,32 @@ void run_ec_combine(void) { } } -void test_group_decompress(const secp256k1_fe* x) { +void test_group_decompress(const rustsecp256k1_v0_1_1_fe* x) { /* The input itself, normalized. */ - secp256k1_fe fex = *x; - secp256k1_fe tmp; + rustsecp256k1_v0_1_1_fe fex = *x; + rustsecp256k1_v0_1_1_fe fez; /* Results of set_xquad_var, set_xo_var(..., 0), set_xo_var(..., 1). */ - secp256k1_ge ge_quad, ge_even, ge_odd; + rustsecp256k1_v0_1_1_ge ge_quad, ge_even, ge_odd; + rustsecp256k1_v0_1_1_gej gej_quad; /* Return values of the above calls. */ int res_quad, res_even, res_odd; - secp256k1_fe_normalize_var(&fex); + rustsecp256k1_v0_1_1_fe_normalize_var(&fex); - res_quad = secp256k1_ge_set_xquad_var(&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); + res_quad = rustsecp256k1_v0_1_1_ge_set_xquad(&ge_quad, &fex); + res_even = rustsecp256k1_v0_1_1_ge_set_xo_var(&ge_even, &fex, 0); + res_odd = rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_fe_normalize_var(&ge_quad.x); + rustsecp256k1_v0_1_1_fe_normalize_var(&ge_odd.x); + rustsecp256k1_v0_1_1_fe_normalize_var(&ge_even.x); + rustsecp256k1_v0_1_1_fe_normalize_var(&ge_quad.y); + rustsecp256k1_v0_1_1_fe_normalize_var(&ge_odd.y); + rustsecp256k1_v0_1_1_fe_normalize_var(&ge_even.y); /* No infinity allowed. */ CHECK(!ge_quad.infinity); @@ -2080,25 +2388,41 @@ void test_group_decompress(const secp256k1_fe* x) { 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(rustsecp256k1_v0_1_1_fe_equal_var(&ge_quad.x, x)); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&ge_even.x, x)); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&ge_odd.x, x)); /* Check that the Y coordinate result in ge_quad is a square. */ - CHECK(secp256k1_fe_sqrt_var(&tmp, &ge_quad.y)); - secp256k1_fe_sqr(&tmp, &tmp); - CHECK(secp256k1_fe_equal_var(&tmp, &ge_quad.y)); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_fe_is_odd(&ge_odd.y)); + CHECK(!rustsecp256k1_v0_1_1_fe_is_odd(&ge_even.y)); + + /* Check rustsecp256k1_v0_1_1_gej_has_quad_y_var. */ + rustsecp256k1_v0_1_1_gej_set_ge(&gej_quad, &ge_quad); + CHECK(rustsecp256k1_v0_1_1_gej_has_quad_y_var(&gej_quad)); + do { + random_fe_test(&fez); + } while (rustsecp256k1_v0_1_1_fe_is_zero(&fez)); + rustsecp256k1_v0_1_1_gej_rescale(&gej_quad, &fez); + CHECK(rustsecp256k1_v0_1_1_gej_has_quad_y_var(&gej_quad)); + rustsecp256k1_v0_1_1_gej_neg(&gej_quad, &gej_quad); + CHECK(!rustsecp256k1_v0_1_1_gej_has_quad_y_var(&gej_quad)); + do { + random_fe_test(&fez); + } while (rustsecp256k1_v0_1_1_fe_is_zero(&fez)); + rustsecp256k1_v0_1_1_gej_rescale(&gej_quad, &fez); + CHECK(!rustsecp256k1_v0_1_1_gej_has_quad_y_var(&gej_quad)); + rustsecp256k1_v0_1_1_gej_neg(&gej_quad, &gej_quad); + CHECK(rustsecp256k1_v0_1_1_gej_has_quad_y_var(&gej_quad)); } } void run_group_decompress(void) { int i; for (i = 0; i < count * 4; i++) { - secp256k1_fe fe; + rustsecp256k1_v0_1_1_fe fe; random_fe_test(&fe); test_group_decompress(&fe); } @@ -2108,218 +2432,218 @@ void run_group_decompress(void) { void run_ecmult_chain(void) { /* random starting point A (on the curve) */ - secp256k1_gej a = SECP256K1_GEJ_CONST( + rustsecp256k1_v0_1_1_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( + rustsecp256k1_v0_1_1_scalar xn = SECP256K1_SCALAR_CONST( 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c, 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407 ); - secp256k1_scalar gn = SECP256K1_SCALAR_CONST( + rustsecp256k1_v0_1_1_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); + static const rustsecp256k1_v0_1_1_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); + static const rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar ae = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + rustsecp256k1_v0_1_1_scalar ge = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); /* actual points */ - secp256k1_gej x; - secp256k1_gej x2; + rustsecp256k1_v0_1_1_gej x; + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_mul(&ae, &ae, &xn); + rustsecp256k1_v0_1_1_scalar_mul(&ge, &ge, &xn); + rustsecp256k1_v0_1_1_scalar_add(&ge, &ge, &gn); /* modify xn and gn */ - secp256k1_scalar_mul(&xn, &xn, &xf); - secp256k1_scalar_mul(&gn, &gn, &gf); + rustsecp256k1_v0_1_1_scalar_mul(&xn, &xn, &xf); + rustsecp256k1_v0_1_1_scalar_mul(&gn, &gn, &gf); /* verify */ if (i == 19999) { /* expected result after 19999 iterations */ - secp256k1_gej rp = SECP256K1_GEJ_CONST( + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_gej_neg(&rp, &rp); + rustsecp256k1_v0_1_1_gej_add_var(&rp, &rp, &x, NULL); + CHECK(rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge); + rustsecp256k1_v0_1_1_gej_neg(&x2, &x2); + rustsecp256k1_v0_1_1_gej_add_var(&x2, &x2, &x, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&x2)); } -void test_point_times_order(const secp256k1_gej *point) { +void test_point_times_order(const rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_scalar x; + rustsecp256k1_v0_1_1_scalar nx; + rustsecp256k1_v0_1_1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + rustsecp256k1_v0_1_1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + rustsecp256k1_v0_1_1_gej res1, res2; + rustsecp256k1_v0_1_1_ge res3; unsigned char pub[65]; size_t psize = 65; random_scalar_order_test(&x); - secp256k1_scalar_negate(&nx, &x); - secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */ - secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ - secp256k1_gej_add_var(&res1, &res1, &res2, NULL); - CHECK(secp256k1_gej_is_infinity(&res1)); - CHECK(secp256k1_gej_is_valid_var(&res1) == 0); - secp256k1_ge_set_gej(&res3, &res1); - CHECK(secp256k1_ge_is_infinity(&res3)); - CHECK(secp256k1_ge_is_valid_var(&res3) == 0); - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); + rustsecp256k1_v0_1_1_scalar_negate(&nx, &x); + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */ + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ + rustsecp256k1_v0_1_1_gej_add_var(&res1, &res1, &res2, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&res1)); + CHECK(rustsecp256k1_v0_1_1_gej_is_valid_var(&res1) == 0); + rustsecp256k1_v0_1_1_ge_set_gej(&res3, &res1); + CHECK(rustsecp256k1_v0_1_1_ge_is_infinity(&res3)); + CHECK(rustsecp256k1_v0_1_1_ge_is_valid_var(&res3) == 0); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); psize = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); + CHECK(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero); + rustsecp256k1_v0_1_1_ge_set_gej(&res3, &res1); + CHECK(rustsecp256k1_v0_1_1_ge_is_infinity(&res3)); + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one); + rustsecp256k1_v0_1_1_ge_set_gej(&res3, &res1); + ge_equals_ge(&res3, &rustsecp256k1_v0_1_1_ge_const_g); } void run_point_times_order(void) { int i; - secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); - static const secp256k1_fe xr = SECP256K1_FE_CONST( + rustsecp256k1_v0_1_1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); + static const rustsecp256k1_v0_1_1_fe xr = SECP256K1_FE_CONST( 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C, 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45 ); for (i = 0; i < 500; i++) { - secp256k1_ge p; - if (secp256k1_ge_set_xo_var(&p, &x, 1)) { - secp256k1_gej j; - CHECK(secp256k1_ge_is_valid_var(&p)); - secp256k1_gej_set_ge(&j, &p); - CHECK(secp256k1_gej_is_valid_var(&j)); + rustsecp256k1_v0_1_1_ge p; + if (rustsecp256k1_v0_1_1_ge_set_xo_var(&p, &x, 1)) { + rustsecp256k1_v0_1_1_gej j; + CHECK(rustsecp256k1_v0_1_1_ge_is_valid_var(&p)); + rustsecp256k1_v0_1_1_gej_set_ge(&j, &p); + CHECK(rustsecp256k1_v0_1_1_gej_is_valid_var(&j)); test_point_times_order(&j); } - secp256k1_fe_sqr(&x, &x); + rustsecp256k1_v0_1_1_fe_sqr(&x, &x); } - secp256k1_fe_normalize_var(&x); - CHECK(secp256k1_fe_equal_var(&x, &xr)); + rustsecp256k1_v0_1_1_fe_normalize_var(&x); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&x, &xr)); } void ecmult_const_random_mult(void) { /* random starting point A (on the curve) */ - secp256k1_ge a = SECP256K1_GE_CONST( + rustsecp256k1_v0_1_1_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( + rustsecp256k1_v0_1_1_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( + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_gej b; + rustsecp256k1_v0_1_1_ecmult_const(&b, &a, &xn, 256); - CHECK(secp256k1_ge_is_valid_var(&a)); + CHECK(rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_scalar a; + rustsecp256k1_v0_1_1_scalar b; + rustsecp256k1_v0_1_1_gej res1; + rustsecp256k1_v0_1_1_gej res2; + rustsecp256k1_v0_1_1_ge mid1; + rustsecp256k1_v0_1_1_ge mid2; random_scalar_order_test(&a); random_scalar_order_test(&b); - secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); - secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); - secp256k1_ge_set_gej(&mid1, &res1); - secp256k1_ge_set_gej(&mid2, &res2); - secp256k1_ecmult_const(&res1, &mid1, &b); - secp256k1_ecmult_const(&res2, &mid2, &a); - secp256k1_ge_set_gej(&mid1, &res1); - secp256k1_ge_set_gej(&mid2, &res2); + rustsecp256k1_v0_1_1_ecmult_const(&res1, &rustsecp256k1_v0_1_1_ge_const_g, &a, 256); + rustsecp256k1_v0_1_1_ecmult_const(&res2, &rustsecp256k1_v0_1_1_ge_const_g, &b, 256); + rustsecp256k1_v0_1_1_ge_set_gej(&mid1, &res1); + rustsecp256k1_v0_1_1_ge_set_gej(&mid2, &res2); + rustsecp256k1_v0_1_1_ecmult_const(&res1, &mid1, &b, 256); + rustsecp256k1_v0_1_1_ecmult_const(&res2, &mid2, &a, 256); + rustsecp256k1_v0_1_1_ge_set_gej(&mid1, &res1); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + rustsecp256k1_v0_1_1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + rustsecp256k1_v0_1_1_scalar negone; + rustsecp256k1_v0_1_1_gej res1; + rustsecp256k1_v0_1_1_ge res2; + rustsecp256k1_v0_1_1_ge point; + rustsecp256k1_v0_1_1_scalar_negate(&negone, &one); random_group_element_test(&point); - secp256k1_ecmult_const(&res1, &point, &zero); - secp256k1_ge_set_gej(&res2, &res1); - CHECK(secp256k1_ge_is_infinity(&res2)); - secp256k1_ecmult_const(&res1, &point, &one); - secp256k1_ge_set_gej(&res2, &res1); + rustsecp256k1_v0_1_1_ecmult_const(&res1, &point, &zero, 3); + rustsecp256k1_v0_1_1_ge_set_gej(&res2, &res1); + CHECK(rustsecp256k1_v0_1_1_ge_is_infinity(&res2)); + rustsecp256k1_v0_1_1_ecmult_const(&res1, &point, &one, 2); + rustsecp256k1_v0_1_1_ge_set_gej(&res2, &res1); ge_equals_ge(&res2, &point); - secp256k1_ecmult_const(&res1, &point, &negone); - secp256k1_gej_neg(&res1, &res1); - secp256k1_ge_set_gej(&res2, &res1); + rustsecp256k1_v0_1_1_ecmult_const(&res1, &point, &negone, 256); + rustsecp256k1_v0_1_1_gej_neg(&res1, &res1); + rustsecp256k1_v0_1_1_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( + const rustsecp256k1_v0_1_1_scalar scalar = SECP256K1_SCALAR_CONST( 0x4968d524, 0x2abf9b7a, 0x466abbcf, 0x34b11b6d, 0xcd83d307, 0x827bed62, 0x05fad0ce, 0x18fae63b ); - const secp256k1_gej expected_point = SECP256K1_GEJ_CONST( + const rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_gej point; + rustsecp256k1_v0_1_1_ge res; int i; - secp256k1_gej_set_ge(&point, &secp256k1_ge_const_g); + rustsecp256k1_v0_1_1_gej_set_ge(&point, &rustsecp256k1_v0_1_1_ge_const_g); for (i = 0; i < 100; ++i) { - secp256k1_ge tmp; - secp256k1_ge_set_gej(&tmp, &point); - secp256k1_ecmult_const(&point, &tmp, &scalar); + rustsecp256k1_v0_1_1_ge tmp; + rustsecp256k1_v0_1_1_ge_set_gej(&tmp, &point); + rustsecp256k1_v0_1_1_ecmult_const(&point, &tmp, &scalar, 256); } - secp256k1_ge_set_gej(&res, &point); + rustsecp256k1_v0_1_1_ge_set_gej(&res, &point); ge_equals_gej(&res, &expected_point); } @@ -2330,19 +2654,489 @@ void run_ecmult_const_tests(void) { ecmult_const_chain_multiply(); } -void test_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, two, t; +typedef struct { + rustsecp256k1_v0_1_1_scalar *sc; + rustsecp256k1_v0_1_1_ge *pt; +} ecmult_multi_data; + +static int ecmult_multi_callback(rustsecp256k1_v0_1_1_scalar *sc, rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_scalar *sc, rustsecp256k1_v0_1_1_ge *pt, size_t idx, void *cbdata) { + (void)sc; + (void)pt; + (void)idx; + (void)cbdata; + return 0; +} + +void test_ecmult_multi(rustsecp256k1_v0_1_1_scratch *scratch, rustsecp256k1_v0_1_1_ecmult_multi_func ecmult_multi) { + int ncount; + rustsecp256k1_v0_1_1_scalar szero; + rustsecp256k1_v0_1_1_scalar sc[32]; + rustsecp256k1_v0_1_1_ge pt[32]; + rustsecp256k1_v0_1_1_gej r; + rustsecp256k1_v0_1_1_gej r2; + ecmult_multi_data data; + + data.sc = sc; + data.pt = pt; + rustsecp256k1_v0_1_1_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++) { + rustsecp256k1_v0_1_1_ge ptg; + rustsecp256k1_v0_1_1_gej ptgj; + random_scalar_order(&sc[0]); + random_scalar_order(&sc[1]); + + random_group_element_test(&ptg); + rustsecp256k1_v0_1_1_gej_set_ge(&ptgj, &ptg); + pt[0] = ptg; + pt[1] = rustsecp256k1_v0_1_1_ge_const_g; + + /* only G scalar */ + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_gej_neg(&r2, &r2); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + + /* 1-point */ + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_gej_neg(&r2, &r2); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_gej_neg(&r2, &r2); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + + /* 2-point with G scalar */ + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_gej_neg(&r2, &r2); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + } + + /* Check infinite outputs of various forms */ + for (ncount = 0; ncount < count; ncount++) { + rustsecp256k1_v0_1_1_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]); + rustsecp256k1_v0_1_1_ge_set_infinity(&pt[i]); + } + CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, sizes[j])); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + } + + for (j = 0; j < 3; j++) { + for (i = 0; i < 32; i++) { + random_group_element_test(&ptg); + pt[i] = ptg; + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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]); + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + } + + random_group_element_test(&ptg); + rustsecp256k1_v0_1_1_scalar_set_int(&sc[0], 0); + pt[0] = ptg; + for (i = 1; i < 32; i++) { + pt[i] = ptg; + + random_scalar_order(&sc[i]); + rustsecp256k1_v0_1_1_scalar_add(&sc[0], &sc[0], &sc[i]); + rustsecp256k1_v0_1_1_scalar_negate(&sc[i], &sc[i]); + } + + CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 32)); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + } + + /* Check random points, constant scalar */ + for (ncount = 0; ncount < count; ncount++) { + size_t i; + rustsecp256k1_v0_1_1_gej_set_infinity(&r); + + random_scalar_order(&sc[0]); + for (i = 0; i < 20; i++) { + rustsecp256k1_v0_1_1_ge ptg; + sc[i] = sc[0]; + random_group_element_test(&ptg); + pt[i] = ptg; + rustsecp256k1_v0_1_1_gej_add_ge_var(&r, &r, &pt[i], NULL); + } + + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_gej_neg(&r2, &r2); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + } + + /* Check random scalars, constant point */ + for (ncount = 0; ncount < count; ncount++) { + size_t i; + rustsecp256k1_v0_1_1_ge ptg; + rustsecp256k1_v0_1_1_gej p0j; + rustsecp256k1_v0_1_1_scalar rs; + rustsecp256k1_v0_1_1_scalar_set_int(&rs, 0); + + random_group_element_test(&ptg); + for (i = 0; i < 20; i++) { + random_scalar_order(&sc[i]); + pt[i] = ptg; + rustsecp256k1_v0_1_1_scalar_add(&rs, &rs, &sc[i]); + } + + rustsecp256k1_v0_1_1_gej_set_ge(&p0j, &pt[0]); + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_gej_neg(&r2, &r2); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_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]); + } + + rustsecp256k1_v0_1_1_scalar_clear(&sc[0]); + CHECK(ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &szero, ecmult_multi_callback, &data, 20)); + rustsecp256k1_v0_1_1_scalar_clear(&sc[1]); + rustsecp256k1_v0_1_1_scalar_clear(&sc[2]); + rustsecp256k1_v0_1_1_scalar_clear(&sc[3]); + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_ge ptg; + rustsecp256k1_v0_1_1_gej ptgj; + + random_group_element_test(&ptg); + rustsecp256k1_v0_1_1_gej_set_ge(&ptgj, &ptg); + + for(t0i = 0; t0i < TOP; t0i++) { + for(t1i = 0; t1i < TOP; t1i++) { + rustsecp256k1_v0_1_1_gej t0p, t1p; + rustsecp256k1_v0_1_1_scalar t0, t1; + + rustsecp256k1_v0_1_1_scalar_set_int(&t0, (t0i + 1) / 2); + rustsecp256k1_v0_1_1_scalar_cond_negate(&t0, t0i & 1); + rustsecp256k1_v0_1_1_scalar_set_int(&t1, (t1i + 1) / 2); + rustsecp256k1_v0_1_1_scalar_cond_negate(&t1, t1i & 1); + + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &t0p, &ptgj, &t0, &szero); + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &t1p, &ptgj, &t1, &szero); + + for(s0i = 0; s0i < TOP; s0i++) { + for(s1i = 0; s1i < TOP; s1i++) { + rustsecp256k1_v0_1_1_scalar tmp1, tmp2; + rustsecp256k1_v0_1_1_gej expected, actual; + + rustsecp256k1_v0_1_1_ge_set_gej(&pt[0], &t0p); + rustsecp256k1_v0_1_1_ge_set_gej(&pt[1], &t1p); + + rustsecp256k1_v0_1_1_scalar_set_int(&sc[0], (s0i + 1) / 2); + rustsecp256k1_v0_1_1_scalar_cond_negate(&sc[0], s0i & 1); + rustsecp256k1_v0_1_1_scalar_set_int(&sc[1], (s1i + 1) / 2); + rustsecp256k1_v0_1_1_scalar_cond_negate(&sc[1], s1i & 1); + + rustsecp256k1_v0_1_1_scalar_mul(&tmp1, &t0, &sc[0]); + rustsecp256k1_v0_1_1_scalar_mul(&tmp2, &t1, &sc[1]); + rustsecp256k1_v0_1_1_scalar_add(&tmp1, &tmp1, &tmp2); + + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_gej_neg(&expected, &expected); + rustsecp256k1_v0_1_1_gej_add_var(&actual, &actual, &expected, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&actual)); + } + } + } + } + } +} + +void test_ecmult_multi_batch_single(rustsecp256k1_v0_1_1_ecmult_multi_func ecmult_multi) { + rustsecp256k1_v0_1_1_scalar szero; + rustsecp256k1_v0_1_1_scalar sc[32]; + rustsecp256k1_v0_1_1_ge pt[32]; + rustsecp256k1_v0_1_1_gej r; + ecmult_multi_data data; + rustsecp256k1_v0_1_1_scratch *scratch_empty; + + data.sc = sc; + data.pt = pt; + rustsecp256k1_v0_1_1_scalar_set_int(&szero, 0); + + /* Try to multiply 1 point, but scratch space is empty.*/ + scratch_empty = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, 0); + CHECK(!ecmult_multi(&ctx->error_callback, &ctx->ecmult_ctx, scratch_empty, &r, &szero, ecmult_multi_callback, &data, 1)); + rustsecp256k1_v0_1_1_scratch_destroy(&ctx->error_callback, scratch_empty); +} + +void test_rustsecp256k1_v0_1_1_pippenger_bucket_window_inv(void) { + int i; + + CHECK(rustsecp256k1_v0_1_1_pippenger_bucket_window_inv(0) == 0); + for(i = 1; i <= PIPPENGER_MAX_BUCKET_WINDOW; i++) { +#ifdef USE_ENDOMORPHISM + /* Bucket_window of 8 is not used with endo */ + if (i == 8) { + continue; + } +#endif + CHECK(rustsecp256k1_v0_1_1_pippenger_bucket_window(rustsecp256k1_v0_1_1_pippenger_bucket_window_inv(i)) == i); + if (i != PIPPENGER_MAX_BUCKET_WINDOW) { + CHECK(rustsecp256k1_v0_1_1_pippenger_bucket_window(rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_rand_int(256); + size_t max_size = rustsecp256k1_v0_1_1_pippenger_scratch_size(rustsecp256k1_v0_1_1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12); + rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, scratch_size); + CHECK(scratch != NULL); + checkpoint = rustsecp256k1_v0_1_1_scratch_checkpoint(&ctx->error_callback, scratch); + n_points_supported = rustsecp256k1_v0_1_1_pippenger_max_points(&ctx->error_callback, scratch); + if (n_points_supported == 0) { + rustsecp256k1_v0_1_1_scratch_destroy(&ctx->error_callback, scratch); + continue; + } + bucket_window = rustsecp256k1_v0_1_1_pippenger_bucket_window(n_points_supported); + /* allocate `total_alloc` bytes over `PIPPENGER_SCRATCH_OBJECTS` many allocations */ + total_alloc = rustsecp256k1_v0_1_1_pippenger_scratch_size(n_points_supported, bucket_window); + for (i = 0; i < PIPPENGER_SCRATCH_OBJECTS - 1; i++) { + CHECK(rustsecp256k1_v0_1_1_scratch_alloc(&ctx->error_callback, scratch, 1)); + total_alloc--; + } + CHECK(rustsecp256k1_v0_1_1_scratch_alloc(&ctx->error_callback, scratch, total_alloc)); + rustsecp256k1_v0_1_1_scratch_apply_checkpoint(&ctx->error_callback, scratch, checkpoint); + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 0); + + max_n_batch_points = 1; + n = 0; + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_scalar scG; + rustsecp256k1_v0_1_1_scalar szero; + rustsecp256k1_v0_1_1_scalar *sc = (rustsecp256k1_v0_1_1_scalar *)checked_malloc(&ctx->error_callback, sizeof(rustsecp256k1_v0_1_1_scalar) * n_points); + rustsecp256k1_v0_1_1_ge *pt = (rustsecp256k1_v0_1_1_ge *)checked_malloc(&ctx->error_callback, sizeof(rustsecp256k1_v0_1_1_ge) * n_points); + rustsecp256k1_v0_1_1_gej r; + rustsecp256k1_v0_1_1_gej r2; + ecmult_multi_data data; + int i; + rustsecp256k1_v0_1_1_scratch *scratch; + + rustsecp256k1_v0_1_1_gej_set_infinity(&r2); + rustsecp256k1_v0_1_1_scalar_set_int(&szero, 0); + + /* Get random scalars and group elements and compute result */ + random_scalar_order(&scG); + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &r2, &r2, &szero, &scG); + for(i = 0; i < n_points; i++) { + rustsecp256k1_v0_1_1_ge ptg; + rustsecp256k1_v0_1_1_gej ptgj; + random_group_element_test(&ptg); + rustsecp256k1_v0_1_1_gej_set_ge(&ptgj, &ptg); + pt[i] = ptg; + random_scalar_order(&sc[i]); + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &ptgj, &ptgj, &sc[i], NULL); + rustsecp256k1_v0_1_1_gej_add_var(&r2, &r2, &ptgj, NULL); + } + data.sc = sc; + data.pt = pt; + rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, 0); + CHECK(rustsecp256k1_v0_1_1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + rustsecp256k1_v0_1_1_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 = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, rustsecp256k1_v0_1_1_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); + CHECK(rustsecp256k1_v0_1_1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + rustsecp256k1_v0_1_1_scratch_destroy(&ctx->error_callback, scratch); + + for(i = 1; i <= n_points; i++) { + if (i > ECMULT_PIPPENGER_THRESHOLD) { + int bucket_window = rustsecp256k1_v0_1_1_pippenger_bucket_window(i); + size_t scratch_size = rustsecp256k1_v0_1_1_pippenger_scratch_size(i, bucket_window); + scratch = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); + } else { + size_t scratch_size = rustsecp256k1_v0_1_1_strauss_scratch_size(i); + scratch = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); + } + CHECK(rustsecp256k1_v0_1_1_ecmult_multi_var(&ctx->error_callback, &ctx->ecmult_ctx, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); + rustsecp256k1_v0_1_1_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); + rustsecp256k1_v0_1_1_scratch_destroy(&ctx->error_callback, scratch); + } + free(sc); + free(pt); +} + +void run_ecmult_multi_tests(void) { + rustsecp256k1_v0_1_1_scratch *scratch; + + test_rustsecp256k1_v0_1_1_pippenger_bucket_window_inv(); + test_ecmult_multi_pippenger_max_points(); + scratch = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, 819200); + test_ecmult_multi(scratch, rustsecp256k1_v0_1_1_ecmult_multi_var); + test_ecmult_multi(NULL, rustsecp256k1_v0_1_1_ecmult_multi_var); + test_ecmult_multi(scratch, rustsecp256k1_v0_1_1_ecmult_pippenger_batch_single); + test_ecmult_multi_batch_single(rustsecp256k1_v0_1_1_ecmult_pippenger_batch_single); + test_ecmult_multi(scratch, rustsecp256k1_v0_1_1_ecmult_strauss_batch_single); + test_ecmult_multi_batch_single(rustsecp256k1_v0_1_1_ecmult_strauss_batch_single); + rustsecp256k1_v0_1_1_scratch_destroy(&ctx->error_callback, scratch); + + /* Run test_ecmult_multi with space for exactly one point */ + scratch = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, rustsecp256k1_v0_1_1_strauss_scratch_size(1) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); + test_ecmult_multi(scratch, rustsecp256k1_v0_1_1_ecmult_multi_var); + rustsecp256k1_v0_1_1_scratch_destroy(&ctx->error_callback, scratch); + + test_ecmult_multi_batch_size_helper(); + test_ecmult_multi_batching(); +} + +void test_wnaf(const rustsecp256k1_v0_1_1_scalar *number, int w) { + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_set_int(&x, 0); + rustsecp256k1_v0_1_1_scalar_set_int(&two, 2); + bits = rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_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; @@ -2354,79 +3148,179 @@ void test_wnaf(const secp256k1_scalar *number, int w) { zeroes++; } if (v >= 0) { - secp256k1_scalar_set_int(&t, v); + rustsecp256k1_v0_1_1_scalar_set_int(&t, v); } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); + rustsecp256k1_v0_1_1_scalar_set_int(&t, -v); + rustsecp256k1_v0_1_1_scalar_negate(&t, &t); } - secp256k1_scalar_add(&x, &x, &t); + rustsecp256k1_v0_1_1_scalar_add(&x, &x, &t); } - CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */ + CHECK(rustsecp256k1_v0_1_1_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; +void test_constant_wnaf_negate(const rustsecp256k1_v0_1_1_scalar *number) { + rustsecp256k1_v0_1_1_scalar neg1 = *number; + rustsecp256k1_v0_1_1_scalar neg2 = *number; int sign1 = 1; int sign2 = 1; - if (!secp256k1_scalar_get_bits(&neg1, 0, 1)) { - secp256k1_scalar_negate(&neg1, &neg1); + if (!rustsecp256k1_v0_1_1_scalar_get_bits(&neg1, 0, 1)) { + rustsecp256k1_v0_1_1_scalar_negate(&neg1, &neg1); sign1 = -1; } - sign2 = secp256k1_scalar_cond_negate(&neg2, secp256k1_scalar_is_even(&neg2)); + sign2 = rustsecp256k1_v0_1_1_scalar_cond_negate(&neg2, rustsecp256k1_v0_1_1_scalar_is_even(&neg2)); CHECK(sign1 == sign2); - CHECK(secp256k1_scalar_eq(&neg1, &neg2)); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&neg1, &neg2)); } -void test_constant_wnaf(const secp256k1_scalar *number, int w) { - secp256k1_scalar x, shift; +void test_constant_wnaf(const rustsecp256k1_v0_1_1_scalar *number, int w) { + rustsecp256k1_v0_1_1_scalar x, shift; int wnaf[256] = {0}; int i; -#ifdef USE_ENDOMORPHISM int skew; -#endif - secp256k1_scalar num = *number; + int bits = 256; + rustsecp256k1_v0_1_1_scalar num = *number; - secp256k1_scalar_set_int(&x, 0); - secp256k1_scalar_set_int(&shift, 1 << w); + rustsecp256k1_v0_1_1_scalar_set_int(&x, 0); + rustsecp256k1_v0_1_1_scalar_set_int(&shift, 1 << w); /* With USE_ENDOMORPHISM on we only consider 128-bit numbers */ #ifdef USE_ENDOMORPHISM for (i = 0; i < 16; ++i) { - secp256k1_scalar_shr_int(&num, 8); + rustsecp256k1_v0_1_1_scalar_shr_int(&num, 8); } - skew = secp256k1_wnaf_const(wnaf, num, w); -#else - secp256k1_wnaf_const(wnaf, num, w); + bits = 128; #endif + skew = rustsecp256k1_v0_1_1_wnaf_const(wnaf, &num, w, bits); - for (i = WNAF_SIZE(w); i >= 0; --i) { - secp256k1_scalar t; + for (i = WNAF_SIZE_BITS(bits, w); i >= 0; --i) { + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_mul(&x, &x, &shift); if (v >= 0) { - secp256k1_scalar_set_int(&t, v); + rustsecp256k1_v0_1_1_scalar_set_int(&t, v); } else { - secp256k1_scalar_set_int(&t, -v); - secp256k1_scalar_negate(&t, &t); + rustsecp256k1_v0_1_1_scalar_set_int(&t, -v); + rustsecp256k1_v0_1_1_scalar_negate(&t, &t); } - secp256k1_scalar_add(&x, &x, &t); + rustsecp256k1_v0_1_1_scalar_add(&x, &x, &t); } + /* Skew num because when encoding numbers as odd we use an offset */ + rustsecp256k1_v0_1_1_scalar_cadd_bit(&num, skew == 2, 1); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&x, &num)); +} + +void test_fixed_wnaf(const rustsecp256k1_v0_1_1_scalar *number, int w) { + rustsecp256k1_v0_1_1_scalar x, shift; + int wnaf[256] = {0}; + int i; + int skew; + rustsecp256k1_v0_1_1_scalar num = *number; + + rustsecp256k1_v0_1_1_scalar_set_int(&x, 0); + rustsecp256k1_v0_1_1_scalar_set_int(&shift, 1 << w); + /* With USE_ENDOMORPHISM on we only consider 128-bit numbers */ #ifdef USE_ENDOMORPHISM - /* Skew num because when encoding 128-bit numbers as odd we use an offset */ - secp256k1_scalar_cadd_bit(&num, skew == 2, 1); + for (i = 0; i < 16; ++i) { + rustsecp256k1_v0_1_1_scalar_shr_int(&num, 8); + } #endif - CHECK(secp256k1_scalar_eq(&x, &num)); + skew = rustsecp256k1_v0_1_1_wnaf_fixed(wnaf, &num, w); + + for (i = WNAF_SIZE(w)-1; i >= 0; --i) { + rustsecp256k1_v0_1_1_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 */ + + rustsecp256k1_v0_1_1_scalar_mul(&x, &x, &shift); + if (v >= 0) { + rustsecp256k1_v0_1_1_scalar_set_int(&t, v); + } else { + rustsecp256k1_v0_1_1_scalar_set_int(&t, -v); + rustsecp256k1_v0_1_1_scalar_negate(&t, &t); + } + rustsecp256k1_v0_1_1_scalar_add(&x, &x, &t); + } + /* If skew is 1 then add 1 to num */ + rustsecp256k1_v0_1_1_scalar_cadd_bit(&num, 0, skew == 1); + CHECK(rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_scalar num; + + rustsecp256k1_v0_1_1_scalar_set_int(&num, 0); + skew = rustsecp256k1_v0_1_1_wnaf_fixed(wnaf, &num, w); + for (i = WNAF_SIZE(w)-1; i >= 0; --i) { + int v = wnaf[i]; + CHECK(v == 0); + } + CHECK(skew == 0); + + rustsecp256k1_v0_1_1_scalar_set_int(&num, 1); + skew = rustsecp256k1_v0_1_1_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 }; + rustsecp256k1_v0_1_1_scalar_set_int(&num, 0xffffffff); + skew = rustsecp256k1_v0_1_1_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 }; + rustsecp256k1_v0_1_1_scalar_set_int(&num, 0xeeeeeeee); + skew = rustsecp256k1_v0_1_1_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 }; + rustsecp256k1_v0_1_1_scalar_set_int(&num, 0x01010101); + skew = rustsecp256k1_v0_1_1_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 }; + rustsecp256k1_v0_1_1_scalar_set_int(&num, 0x01ef1ef1); + skew = rustsecp256k1_v0_1_1_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}}; + rustsecp256k1_v0_1_1_scalar n = {{0}}; /* Sanity check: 1 and 2 are the smallest odd and even numbers and should * have easier-to-diagnose failure modes */ @@ -2434,50 +3328,53 @@ void run_wnaf(void) { test_constant_wnaf(&n, 4); n.d[0] = 2; test_constant_wnaf(&n, 4); + /* Test 0 */ + 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)); + rustsecp256k1_v0_1_1_scalar_set_int(&n, 0); + CHECK(rustsecp256k1_v0_1_1_scalar_cond_negate(&n, 1) == -1); + CHECK(rustsecp256k1_v0_1_1_scalar_is_zero(&n)); + CHECK(rustsecp256k1_v0_1_1_scalar_cond_negate(&n, 0) == 1); + CHECK(rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_scalar x; + rustsecp256k1_v0_1_1_gej r; + rustsecp256k1_v0_1_1_ge ng; int i; int j; - secp256k1_ge_neg(&ng, &secp256k1_ge_const_g); + rustsecp256k1_v0_1_1_ge_neg(&ng, &rustsecp256k1_v0_1_1_ge_const_g); for (i = 0; i < 36; i++ ) { - secp256k1_scalar_set_int(&x, i); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); + rustsecp256k1_v0_1_1_scalar_set_int(&x, i); + rustsecp256k1_v0_1_1_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); + ge_equals_gej(&rustsecp256k1_v0_1_1_ge_const_g, &r); } - secp256k1_gej_add_ge(&r, &r, &ng); + rustsecp256k1_v0_1_1_gej_add_ge(&r, &r, &ng); } - CHECK(secp256k1_gej_is_infinity(&r)); + CHECK(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_set_int(&x, i); + rustsecp256k1_v0_1_1_scalar_negate(&x, &x); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_gej_add_ge(&r, &r, &rustsecp256k1_v0_1_1_ge_const_g); } - CHECK(secp256k1_gej_is_infinity(&r)); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&r)); } } @@ -2487,36 +3384,36 @@ void run_ecmult_constants(void) { 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; + rustsecp256k1_v0_1_1_scalar key; + rustsecp256k1_v0_1_1_scalar b; unsigned char seed32[32]; - secp256k1_gej pgej; - secp256k1_gej pgej2; - secp256k1_gej i; - secp256k1_ge pge; + rustsecp256k1_v0_1_1_gej pgej; + rustsecp256k1_v0_1_1_gej pgej2; + rustsecp256k1_v0_1_1_gej i; + rustsecp256k1_v0_1_1_ge pge; random_scalar_order_test(&key); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej, &key); - secp256k1_rand256(seed32); + rustsecp256k1_v0_1_1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej, &key); + rustsecp256k1_v0_1_1_rand256(seed32); b = ctx->ecmult_gen_ctx.blind; i = ctx->ecmult_gen_ctx.initial; - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); - CHECK(!secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej2, &key); + rustsecp256k1_v0_1_1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + CHECK(!rustsecp256k1_v0_1_1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar b; + rustsecp256k1_v0_1_1_gej initial; + rustsecp256k1_v0_1_1_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)); + rustsecp256k1_v0_1_1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); + CHECK(rustsecp256k1_v0_1_1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); CHECK(gej_xyz_equals_gej(&initial, &ctx->ecmult_gen_ctx.initial)); } @@ -2531,25 +3428,25 @@ void run_ecmult_gen_blind(void) { #ifdef USE_ENDOMORPHISM /***** ENDOMORPHISH TESTS *****/ void test_scalar_split(void) { - secp256k1_scalar full; - secp256k1_scalar s1, slam; + rustsecp256k1_v0_1_1_scalar full; + rustsecp256k1_v0_1_1_scalar s1, slam; const unsigned char zero[32] = {0}; unsigned char tmp[32]; random_scalar_order_test(&full); - secp256k1_scalar_split_lambda(&s1, &slam, &full); + rustsecp256k1_v0_1_1_scalar_split_lambda(&s1, &slam, &full); /* check that both are <= 128 bits in size */ - if (secp256k1_scalar_is_high(&s1)) { - secp256k1_scalar_negate(&s1, &s1); + if (rustsecp256k1_v0_1_1_scalar_is_high(&s1)) { + rustsecp256k1_v0_1_1_scalar_negate(&s1, &s1); } - if (secp256k1_scalar_is_high(&slam)) { - secp256k1_scalar_negate(&slam, &slam); + if (rustsecp256k1_v0_1_1_scalar_is_high(&slam)) { + rustsecp256k1_v0_1_1_scalar_negate(&slam, &slam); } - secp256k1_scalar_get_b32(tmp, &s1); + rustsecp256k1_v0_1_1_scalar_get_b32(tmp, &s1); CHECK(memcmp(zero, tmp, 16) == 0); - secp256k1_scalar_get_b32(tmp, &slam); + rustsecp256k1_v0_1_1_scalar_get_b32(tmp, &slam); CHECK(memcmp(zero, tmp, 16) == 0); } @@ -2560,12 +3457,12 @@ void run_endomorphism_tests(void) { void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { unsigned char pubkeyc[65]; - secp256k1_pubkey pubkey; - secp256k1_ge ge; + rustsecp256k1_v0_1_1_pubkey pubkey; + rustsecp256k1_v0_1_1_ge ge; size_t pubkeyclen; int32_t ecount; ecount = 0; - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_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; @@ -2591,11 +3488,11 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali memset(&pubkey, 0, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); ecount = 0; - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); VG_CHECK(pubkeyo, outl); CHECK(outl == 33); CHECK(memcmp(&pubkeyo[1], &pubkeyc[1], 32) == 0); @@ -2603,14 +3500,14 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali 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); + CHECK(rustsecp256k1_v0_1_1_pubkey_load(ctx, &ge, &pubkey) == 1); memset(&pubkey, 0, sizeof(pubkey)); VG_UNDEF(&pubkey, sizeof(pubkey)); - secp256k1_pubkey_save(&pubkey, &ge); + rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); VG_CHECK(pubkeyo, outl); CHECK(outl == 65); CHECK(pubkeyo[0] == 4); @@ -2622,15 +3519,15 @@ void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvali memset(&pubkey, 0xfe, sizeof(pubkey)); ecount = 0; VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); } } } - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); + rustsecp256k1_v0_1_1_context_set_illegal_callback(ctx, NULL, NULL); } void run_ec_pubkey_parse_test(void) { @@ -2814,8 +3711,8 @@ void run_ec_pubkey_parse_test(void) { }; unsigned char sout[65]; unsigned char shortkey[2]; - secp256k1_ge ge; - secp256k1_pubkey pubkey; + rustsecp256k1_v0_1_1_ge ge; + rustsecp256k1_v0_1_1_pubkey pubkey; size_t len; int32_t i; int32_t ecount; @@ -2823,16 +3720,16 @@ void run_ec_pubkey_parse_test(void) { 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); + rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); /* Length one claimed, fail, zeroize, no illegal arg error. */ for (i = 0; i < 256 ; i++) { @@ -2841,10 +3738,10 @@ void run_ec_pubkey_parse_test(void) { shortkey[0] = i; VG_UNDEF(&shortkey[1], 1); VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 1) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_pubkey_load(ctx, &ge, &pubkey) == 0); CHECK(ecount == 1); } /* Length two claimed, fail, zeroize, no illegal arg error. */ @@ -2854,100 +3751,101 @@ void run_ec_pubkey_parse_test(void) { shortkey[0] = i & 255; shortkey[1] = i >> 8; VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 2) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_parse(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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); + ge_equals_ge(&rustsecp256k1_v0_1_1_ge_const_g, &ge); CHECK(ecount == 0); - /* secp256k1_ec_pubkey_serialize illegal args. */ + /* rustsecp256k1_v0_1_1_ec_pubkey_serialize illegal args. */ ecount = 0; len = 65; - CHECK(secp256k1_ec_pubkey_serialize(ctx, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_context_set_illegal_callback(ctx, uncounting_illegal_callback_fn, &ecount2); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); CHECK(ecount == 1); CHECK(ecount2 == 10); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); + rustsecp256k1_v0_1_1_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); @@ -2967,263 +3865,263 @@ void run_eckey_edge_case_test(void) { 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 }; - const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00}; + const unsigned char zeros[sizeof(rustsecp256k1_v0_1_1_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]; + rustsecp256k1_v0_1_1_pubkey pubkey; + rustsecp256k1_v0_1_1_pubkey pubkey2; + rustsecp256k1_v0_1_1_pubkey pubkey_one; + rustsecp256k1_v0_1_1_pubkey pubkey_negone; + const rustsecp256k1_v0_1_1_pubkey *pubkeys[3]; size_t len; int32_t ecount; /* Group order is too large, reject. */ - CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_seckey_verify(ctx, orderc) == 0); VG_UNDEF(&pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, orderc) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); /* Maximum value is too large, reject. */ memset(ctmp, 255, 32); - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); /* Zero is too small, reject. */ memset(ctmp, 0, 32); - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); /* One must be accepted. */ ctmp[31] = 0x01; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); /* -1 must be accepted. */ ctmp[31] = 0x40; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); VG_CHECK(&pubkey, sizeof(pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) > 0); pubkey_negone = pubkey; - /* Tweak of zero leaves the value changed. */ + /* Tweak of zero leaves the value unchanged. */ memset(ctmp2, 0, 32); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); memcpy(&pubkey2, &pubkey, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Multiply tweak of zero zeroizes the output. */ - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0); CHECK(memcmp(zeros, ctmp, 32) == 0); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* Overflowing key tweak zeroizes. */ memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0); CHECK(memcmp(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0); CHECK(memcmp(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* Private key tweaks results in a key of zero. */ ctmp2[31] = 1; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0); CHECK(memcmp(zeros, ctmp2, 32) == 0); ctmp2[31] = 1; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* Tweak computation wraps and results in a key of 1. */ ctmp2[31] = 2; - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1); CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); ctmp2[31] = 2; - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); ctmp2[31] = 1; - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Tweak mul * 2 = 1+1. */ - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); ctmp2[31] = 2; - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Test argument errors. */ ecount = 0; - secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); CHECK(ecount == 1); CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); memset(&pubkey2, 0, 32); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0); CHECK(ecount == 2); CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0); /* Plain argument errors. */ ecount = 0; - CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_seckey_verify(ctx, ctmp) == 1); CHECK(ecount == 0); - CHECK(secp256k1_ec_seckey_verify(ctx, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0); CHECK(ecount == 2); ecount = 0; memset(ctmp2, 0, 32); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); - CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0); CHECK(ecount == 2); ecount = 0; memset(ctmp2, 0, 32); ctmp2[31] = 1; - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0); CHECK(ecount == 1); - CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0); CHECK(ecount == 2); ecount = 0; - CHECK(secp256k1_ec_pubkey_create(ctx, NULL, ctmp) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); CHECK(ecount == 2); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); - /* secp256k1_ec_pubkey_combine tests. */ + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); + /* rustsecp256k1_v0_1_1_ec_pubkey_combine tests. */ ecount = 0; pubkeys[0] = &pubkey_one; - VG_UNDEF(&pubkeys[0], sizeof(secp256k1_pubkey *)); - VG_UNDEF(&pubkeys[1], sizeof(secp256k1_pubkey *)); - VG_UNDEF(&pubkeys[2], sizeof(secp256k1_pubkey *)); - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + VG_UNDEF(&pubkeys[0], sizeof(rustsecp256k1_v0_1_1_pubkey *)); + VG_UNDEF(&pubkeys[1], sizeof(rustsecp256k1_v0_1_1_pubkey *)); + VG_UNDEF(&pubkeys[2], sizeof(rustsecp256k1_v0_1_1_pubkey *)); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_1_1_pubkey)); + VG_UNDEF(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0); + VG_CHECK(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); CHECK(ecount == 1); - CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); CHECK(ecount == 2); - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_1_1_pubkey)); + VG_UNDEF(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0); + VG_CHECK(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); CHECK(ecount == 3); pubkeys[0] = &pubkey_negone; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_1_1_pubkey)); + VG_UNDEF(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1); + VG_CHECK(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); CHECK(memcmp(ctmp, ctmp2, 33) == 0); /* Result is infinity. */ pubkeys[0] = &pubkey_one; pubkeys[1] = &pubkey_negone; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_1_1_pubkey)); + VG_UNDEF(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0); + VG_CHECK(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) == 0); CHECK(ecount == 3); /* Passes through infinity but comes out one. */ pubkeys[2] = &pubkey_one; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_1_1_pubkey)); + VG_UNDEF(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1); + VG_CHECK(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); CHECK(memcmp(ctmp, ctmp2, 33) == 0); /* Adds to two. */ pubkeys[1] = &pubkey_one; - memset(&pubkey, 255, sizeof(secp256k1_pubkey)); - VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1); - VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); - CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_1_1_pubkey)); + VG_UNDEF(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1); + VG_CHECK(&pubkey, sizeof(rustsecp256k1_v0_1_1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(rustsecp256k1_v0_1_1_pubkey)) > 0); CHECK(ecount == 3); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); + rustsecp256k1_v0_1_1_context_set_illegal_callback(ctx, NULL, NULL); } -void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { - secp256k1_scalar nonce; +void random_sign(rustsecp256k1_v0_1_1_scalar *sigr, rustsecp256k1_v0_1_1_scalar *sigs, const rustsecp256k1_v0_1_1_scalar *key, const rustsecp256k1_v0_1_1_scalar *msg, int *recid) { + rustsecp256k1_v0_1_1_scalar nonce; do { random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); + } while(!rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_gej pubj; + rustsecp256k1_v0_1_1_ge pub; + rustsecp256k1_v0_1_1_scalar one; + rustsecp256k1_v0_1_1_scalar msg, key; + rustsecp256k1_v0_1_1_scalar sigr, sigs; int recid; int getrec; random_scalar_order_test(&msg); random_scalar_order_test(&key); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); - getrec = secp256k1_rand_bits(1); + rustsecp256k1_v0_1_1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key); + rustsecp256k1_v0_1_1_ge_set_gej(&pub, &pubj); + getrec = rustsecp256k1_v0_1_1_rand_bits(1); random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL); if (getrec) { CHECK(recid >= 0 && recid < 4); } - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); - secp256k1_scalar_set_int(&one, 1); - secp256k1_scalar_add(&msg, &msg, &one); - CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + rustsecp256k1_v0_1_1_scalar_set_int(&one, 1); + rustsecp256k1_v0_1_1_scalar_add(&msg, &msg, &one); + CHECK(!rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); } void run_ecdsa_sign_verify(void) { @@ -3280,9 +4178,9 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); } -int is_empty_signature(const secp256k1_ecdsa_signature *sig) { - static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0}; - return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0; +int is_empty_signature(const rustsecp256k1_v0_1_1_ecdsa_signature *sig) { + static const unsigned char res[sizeof(rustsecp256k1_v0_1_1_ecdsa_signature)] = {0}; + return memcmp(sig, res, sizeof(rustsecp256k1_v0_1_1_ecdsa_signature)) == 0; } void test_ecdsa_end_to_end(void) { @@ -3290,82 +4188,90 @@ void test_ecdsa_end_to_end(void) { unsigned char privkey[32]; unsigned char message[32]; unsigned char privkey2[32]; - secp256k1_ecdsa_signature signature[6]; - secp256k1_scalar r, s; + rustsecp256k1_v0_1_1_ecdsa_signature signature[6]; + rustsecp256k1_v0_1_1_scalar r, s; unsigned char sig[74]; size_t siglen = 74; unsigned char pubkeyc[65]; size_t pubkeyclen = 65; - secp256k1_pubkey pubkey; + rustsecp256k1_v0_1_1_pubkey pubkey; + rustsecp256k1_v0_1_1_pubkey pubkey_tmp; unsigned char seckey[300]; size_t seckeylen = 300; /* Generate a random key and message. */ { - secp256k1_scalar msg, key; + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_get_b32(privkey, &key); + rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); /* Verify exporting and importing public key. */ - CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, rustsecp256k1_v0_1_1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); memset(&pubkey, 0, sizeof(pubkey)); - CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + + /* Verify negation changes the key and changes it back */ + memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey)); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); + CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); + CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); /* Verify private key import and export. */ - CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); + CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, rustsecp256k1_v0_1_1_rand_bits(1) == 1)); CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); CHECK(memcmp(privkey, privkey2, 32) == 0); /* Optionally tweak the keys using addition. */ - if (secp256k1_rand_int(3) == 0) { + if (rustsecp256k1_v0_1_1_rand_int(3) == 0) { int ret1; int ret2; unsigned char rnd[32]; - secp256k1_pubkey pubkey2; - secp256k1_rand256_test(rnd); - ret1 = secp256k1_ec_privkey_tweak_add(ctx, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); + rustsecp256k1_v0_1_1_pubkey pubkey2; + rustsecp256k1_v0_1_1_rand256_test(rnd); + ret1 = rustsecp256k1_v0_1_1_ec_privkey_tweak_add(ctx, privkey, rnd); + ret2 = rustsecp256k1_v0_1_1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); CHECK(ret1 == ret2); if (ret1 == 0) { return; } - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Optionally tweak the keys using multiplication. */ - if (secp256k1_rand_int(3) == 0) { + if (rustsecp256k1_v0_1_1_rand_int(3) == 0) { int ret1; int ret2; unsigned char rnd[32]; - secp256k1_pubkey pubkey2; - secp256k1_rand256_test(rnd); - ret1 = secp256k1_ec_privkey_tweak_mul(ctx, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); + rustsecp256k1_v0_1_1_pubkey pubkey2; + rustsecp256k1_v0_1_1_rand256_test(rnd); + ret1 = rustsecp256k1_v0_1_1_ec_privkey_tweak_mul(ctx, privkey, rnd); + ret2 = rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); CHECK(ret1 == ret2); if (ret1 == 0) { return; } - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Sign. */ - CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &signature[4], message, privkey, NULL, NULL) == 1); - CHECK(secp256k1_ecdsa_sign(ctx, &signature[1], message, privkey, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &signature[4], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &signature[3], message, privkey, NULL, extra) == 1); CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0); CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0); CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0); @@ -3374,71 +4280,71 @@ void test_ecdsa_end_to_end(void) { CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0); CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 0); /* Verify. */ - CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[2], message, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, &signature[3], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[2], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_1_1_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(!rustsecp256k1_v0_1_1_ecdsa_signature_normalize(ctx, NULL, &signature[0])); + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &r, &s, &signature[0]); + rustsecp256k1_v0_1_1_scalar_negate(&s, &s); + rustsecp256k1_v0_1_1_ecdsa_signature_save(&signature[5], &r, &s); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); + CHECK(!rustsecp256k1_v0_1_1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(!rustsecp256k1_v0_1_1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); + rustsecp256k1_v0_1_1_scalar_negate(&s, &s); + rustsecp256k1_v0_1_1_ecdsa_signature_save(&signature[5], &r, &s); + CHECK(!rustsecp256k1_v0_1_1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); CHECK(memcmp(&signature[5], &signature[0], 64) == 0); /* Serialize/parse DER and verify again */ - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); + CHECK(rustsecp256k1_v0_1_1_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); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); /* Serialize/destroy/parse DER and verify again. */ siglen = 74; - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); - sig[secp256k1_rand_int(siglen)] += 1 + secp256k1_rand_int(255); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 || - secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); + sig[rustsecp256k1_v0_1_1_rand_int(siglen)] += 1 + rustsecp256k1_v0_1_1_rand_int(255); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 || + rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 0); } void test_random_pubkeys(void) { - secp256k1_ge elem; - secp256k1_ge elem2; + rustsecp256k1_v0_1_1_ge elem; + rustsecp256k1_v0_1_1_ge elem2; unsigned char in[65]; /* Generate some randomly sized pubkeys. */ - size_t len = secp256k1_rand_bits(2) == 0 ? 65 : 33; - if (secp256k1_rand_bits(2) == 0) { - len = secp256k1_rand_bits(6); + size_t len = rustsecp256k1_v0_1_1_rand_bits(2) == 0 ? 65 : 33; + if (rustsecp256k1_v0_1_1_rand_bits(2) == 0) { + len = rustsecp256k1_v0_1_1_rand_bits(6); } if (len == 65) { - in[0] = secp256k1_rand_bits(1) ? 4 : (secp256k1_rand_bits(1) ? 6 : 7); + in[0] = rustsecp256k1_v0_1_1_rand_bits(1) ? 4 : (rustsecp256k1_v0_1_1_rand_bits(1) ? 6 : 7); } else { - in[0] = secp256k1_rand_bits(1) ? 2 : 3; + in[0] = rustsecp256k1_v0_1_1_rand_bits(1) ? 2 : 3; } - if (secp256k1_rand_bits(3) == 0) { - in[0] = secp256k1_rand_bits(8); + if (rustsecp256k1_v0_1_1_rand_bits(3) == 0) { + in[0] = rustsecp256k1_v0_1_1_rand_bits(8); } if (len > 1) { - secp256k1_rand256(&in[1]); + rustsecp256k1_v0_1_1_rand256(&in[1]); } if (len > 33) { - secp256k1_rand256(&in[33]); + rustsecp256k1_v0_1_1_rand256(&in[33]); } - if (secp256k1_eckey_pubkey_parse(&elem, in, len)) { + if (rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); CHECK(size == len); CHECK(memcmp(&in[1], &out[1], len-1) == 0); /* ... except for the type of hybrid inputs. */ @@ -3446,13 +4352,13 @@ void test_random_pubkeys(void) { CHECK(in[0] == out[0]); } size = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_serialize(&elem, in, &size, 0)); CHECK(size == 65); - CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_parse(&elem2, in, size)); ge_equals_ge(&elem,&elem2); /* Check that the X9.62 hybrid type is checked. */ - in[0] = secp256k1_rand_bits(1) ? 6 : 7; - res = secp256k1_eckey_pubkey_parse(&elem2, in, size); + in[0] = rustsecp256k1_v0_1_1_rand_bits(1) ? 6 : 7; + res = rustsecp256k1_v0_1_1_eckey_pubkey_parse(&elem2, in, size); if (firstb == 2 || firstb == 3) { if (in[0] == firstb + 4) { CHECK(res); @@ -3462,7 +4368,7 @@ void test_random_pubkeys(void) { } if (res) { ge_equals_ge(&elem,&elem2); - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_serialize(&elem, out, &size, 0)); CHECK(memcmp(&in[1], &out[1], 64) == 0); } } @@ -3484,22 +4390,24 @@ void run_ecdsa_end_to_end(void) { 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; + rustsecp256k1_v0_1_1_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; + rustsecp256k1_v0_1_1_ecdsa_signature sig_der_lax; unsigned char roundtrip_der_lax[2048]; unsigned char compact_der_lax[64]; size_t len_der_lax = 2048; @@ -3507,29 +4415,30 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_ #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); + parsed_der = rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen); if (parsed_der) { - ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0; + ret |= (!rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0; valid_der = (memcmp(compact_der, zeroes, 32) != 0) && (memcmp(compact_der + 32, zeroes, 32) != 0); } if (valid_der) { - ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1; + ret |= (!rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1; roundtrips_der = (len_der == siglen) && memcmp(roundtrip_der, sig, siglen) == 0; } - parsed_der_lax = ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen); + parsed_der_lax = rustsecp256k1_v0_1_1_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; + ret |= (!rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10; valid_der_lax = (memcmp(compact_der_lax, zeroes, 32) != 0) && (memcmp(compact_der_lax + 32, zeroes, 32) != 0); } if (valid_der_lax) { - ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; + ret |= (!rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; roundtrips_der_lax = (len_der_lax == siglen) && memcmp(roundtrip_der_lax, sig, siglen) == 0; } @@ -3558,15 +4467,16 @@ int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_ sigptr = sig; parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL); if (parsed_openssl) { - valid_openssl = !BN_is_negative(sig_openssl->r) && !BN_is_negative(sig_openssl->s) && BN_num_bits(sig_openssl->r) > 0 && BN_num_bits(sig_openssl->r) <= 256 && BN_num_bits(sig_openssl->s) > 0 && BN_num_bits(sig_openssl->s) <= 256; + ECDSA_SIG_get0(sig_openssl, &r, &s); + valid_openssl = !BN_is_negative(r) && !BN_is_negative(s) && BN_num_bits(r) > 0 && BN_num_bits(r) <= 256 && BN_num_bits(s) > 0 && BN_num_bits(s) <= 256; if (valid_openssl) { unsigned char tmp[32] = {0}; - BN_bn2bin(sig_openssl->r, tmp + 32 - BN_num_bytes(sig_openssl->r)); + BN_bn2bin(r, tmp + 32 - BN_num_bytes(r)); valid_openssl = memcmp(tmp, max_scalar, 32) < 0; } if (valid_openssl) { unsigned char tmp[32] = {0}; - BN_bn2bin(sig_openssl->s, tmp + 32 - BN_num_bytes(sig_openssl->s)); + BN_bn2bin(s, tmp + 32 - BN_num_bytes(s)); valid_openssl = memcmp(tmp, max_scalar, 32) < 0; } } @@ -3606,27 +4516,27 @@ static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { static void damage_array(unsigned char *sig, size_t *len) { int pos; - int action = secp256k1_rand_bits(3); + int action = rustsecp256k1_v0_1_1_rand_bits(3); if (action < 1 && *len > 3) { /* Delete a byte. */ - pos = secp256k1_rand_int(*len); + pos = rustsecp256k1_v0_1_1_rand_int(*len); memmove(sig + pos, sig + pos + 1, *len - pos - 1); (*len)--; return; } else if (action < 2 && *len < 2048) { /* Insert a byte. */ - pos = secp256k1_rand_int(1 + *len); + pos = rustsecp256k1_v0_1_1_rand_int(1 + *len); memmove(sig + pos + 1, sig + pos, *len - pos); - sig[pos] = secp256k1_rand_bits(8); + sig[pos] = rustsecp256k1_v0_1_1_rand_bits(8); (*len)++; return; } else if (action < 4) { /* Modify a byte. */ - sig[secp256k1_rand_int(*len)] += 1 + secp256k1_rand_int(255); + sig[rustsecp256k1_v0_1_1_rand_int(*len)] += 1 + rustsecp256k1_v0_1_1_rand_int(255); return; } else { /* action < 8 */ /* Modify a bit. */ - sig[secp256k1_rand_int(*len)] ^= 1 << secp256k1_rand_bits(3); + sig[rustsecp256k1_v0_1_1_rand_int(*len)] ^= 1 << rustsecp256k1_v0_1_1_rand_bits(3); return; } } @@ -3639,23 +4549,23 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly int n; *len = 0; - der = secp256k1_rand_bits(2) == 0; + der = rustsecp256k1_v0_1_1_rand_bits(2) == 0; *certainly_der = der; *certainly_not_der = 0; - indet = der ? 0 : secp256k1_rand_int(10) == 0; + indet = der ? 0 : rustsecp256k1_v0_1_1_rand_int(10) == 0; for (n = 0; n < 2; n++) { /* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */ - nlow[n] = der ? 1 : (secp256k1_rand_bits(3) != 0); + nlow[n] = der ? 1 : (rustsecp256k1_v0_1_1_rand_bits(3) != 0); /* The length of the number in bytes (the first byte of which will always be nonzero) */ - nlen[n] = nlow[n] ? secp256k1_rand_int(33) : 32 + secp256k1_rand_int(200) * secp256k1_rand_int(8) / 8; + nlen[n] = nlow[n] ? rustsecp256k1_v0_1_1_rand_int(33) : 32 + rustsecp256k1_v0_1_1_rand_int(200) * rustsecp256k1_v0_1_1_rand_int(8) / 8; CHECK(nlen[n] <= 232); /* The top bit of the number. */ - nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_rand_bits(1)); + nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : rustsecp256k1_v0_1_1_rand_bits(1)); /* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */ - nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_rand_bits(7) : 1 + secp256k1_rand_int(127)); + nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + rustsecp256k1_v0_1_1_rand_bits(7) : 1 + rustsecp256k1_v0_1_1_rand_int(127)); /* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */ - nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_rand_int(3) : secp256k1_rand_int(300 - nlen[n]) * secp256k1_rand_int(8) / 8); + nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? rustsecp256k1_v0_1_1_rand_int(3) : rustsecp256k1_v0_1_1_rand_int(300 - nlen[n]) * rustsecp256k1_v0_1_1_rand_int(8) / 8); if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) { *certainly_not_der = 1; } @@ -3664,7 +4574,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2); if (!der) { /* nlenlen[n] max 127 bytes */ - int add = secp256k1_rand_int(127 - nlenlen[n]) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; + int add = rustsecp256k1_v0_1_1_rand_int(127 - nlenlen[n]) * rustsecp256k1_v0_1_1_rand_int(16) * rustsecp256k1_v0_1_1_rand_int(16) / 256; nlenlen[n] += add; if (add != 0) { *certainly_not_der = 1; @@ -3678,7 +4588,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly CHECK(tlen <= 856); /* The length of the garbage inside the tuple. */ - elen = (der || indet) ? 0 : secp256k1_rand_int(980 - tlen) * secp256k1_rand_int(8) / 8; + elen = (der || indet) ? 0 : rustsecp256k1_v0_1_1_rand_int(980 - tlen) * rustsecp256k1_v0_1_1_rand_int(8) / 8; if (elen != 0) { *certainly_not_der = 1; } @@ -3686,7 +4596,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly CHECK(tlen <= 980); /* The length of the garbage after the end of the tuple. */ - glen = der ? 0 : secp256k1_rand_int(990 - tlen) * secp256k1_rand_int(8) / 8; + glen = der ? 0 : rustsecp256k1_v0_1_1_rand_int(990 - tlen) * rustsecp256k1_v0_1_1_rand_int(8) / 8; if (glen != 0) { *certainly_not_der = 1; } @@ -3701,7 +4611,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly } else { int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2); if (!der) { - int add = secp256k1_rand_int(127 - tlenlen) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; + int add = rustsecp256k1_v0_1_1_rand_int(127 - tlenlen) * rustsecp256k1_v0_1_1_rand_int(16) * rustsecp256k1_v0_1_1_rand_int(16) / 256; tlenlen += add; if (add != 0) { *certainly_not_der = 1; @@ -3752,13 +4662,13 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly nlen[n]--; } /* Generate remaining random bytes of number */ - secp256k1_rand_bytes_test(sig + *len, nlen[n]); + rustsecp256k1_v0_1_1_rand_bytes_test(sig + *len, nlen[n]); *len += nlen[n]; nlen[n] = 0; } /* Generate random garbage inside tuple. */ - secp256k1_rand_bytes_test(sig + *len, elen); + rustsecp256k1_v0_1_1_rand_bytes_test(sig + *len, elen); *len += elen; /* Generate end-of-contents bytes. */ @@ -3770,7 +4680,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly CHECK(tlen + glen <= 1121); /* Generate random garbage outside tuple. */ - secp256k1_rand_bytes_test(sig + *len, glen); + rustsecp256k1_v0_1_1_rand_bytes_test(sig + *len, glen); *len += glen; tlen += glen; CHECK(tlen <= 1121); @@ -3811,22 +4721,22 @@ void run_ecdsa_der_parse(void) { /* Tests several edge cases. */ void test_ecdsa_edge_cases(void) { int t; - secp256k1_ecdsa_signature sig; + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_gej keyj; + rustsecp256k1_v0_1_1_ge key; + rustsecp256k1_v0_1_1_scalar msg; + rustsecp256k1_v0_1_1_scalar sr, ss; + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 1); + rustsecp256k1_v0_1_1_scalar_negate(&ss, &ss); + rustsecp256k1_v0_1_1_scalar_inverse(&ss, &ss); + rustsecp256k1_v0_1_1_scalar_set_int(&sr, 1); + rustsecp256k1_v0_1_1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr); + rustsecp256k1_v0_1_1_ge_set_gej(&key, &keyj); msg = ss; - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Verify signature with r of zero fails. */ @@ -3838,14 +4748,14 @@ void test_ecdsa_edge_cases(void) { 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); + rustsecp256k1_v0_1_1_ge key; + rustsecp256k1_v0_1_1_scalar msg; + rustsecp256k1_v0_1_1_scalar sr, ss; + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 1); + rustsecp256k1_v0_1_1_scalar_set_int(&msg, 0); + rustsecp256k1_v0_1_1_scalar_set_int(&sr, 0); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Verify signature with s of zero fails. */ @@ -3857,14 +4767,14 @@ void test_ecdsa_edge_cases(void) { 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); + rustsecp256k1_v0_1_1_ge key; + rustsecp256k1_v0_1_1_scalar msg; + rustsecp256k1_v0_1_1_scalar sr, ss; + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 0); + rustsecp256k1_v0_1_1_scalar_set_int(&msg, 0); + rustsecp256k1_v0_1_1_scalar_set_int(&sr, 1); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Verify signature with message 0 passes. */ @@ -3883,23 +4793,23 @@ void test_ecdsa_edge_cases(void) { 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); + rustsecp256k1_v0_1_1_ge key; + rustsecp256k1_v0_1_1_ge key2; + rustsecp256k1_v0_1_1_scalar msg; + rustsecp256k1_v0_1_1_scalar sr, ss; + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 2); + rustsecp256k1_v0_1_1_scalar_set_int(&msg, 0); + rustsecp256k1_v0_1_1_scalar_set_int(&sr, 2); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_parse(&key2, pubkey2, 33)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + rustsecp256k1_v0_1_1_scalar_negate(&ss, &ss); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); } /* Verify signature with message 1 passes. */ @@ -3924,24 +4834,24 @@ void test_ecdsa_edge_cases(void) { 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); + rustsecp256k1_v0_1_1_ge key; + rustsecp256k1_v0_1_1_ge key2; + rustsecp256k1_v0_1_1_scalar msg; + rustsecp256k1_v0_1_1_scalar sr, ss; + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 1); + rustsecp256k1_v0_1_1_scalar_set_int(&msg, 1); + rustsecp256k1_v0_1_1_scalar_set_b32(&sr, csr, NULL); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_parse(&key2, pubkey2, 33)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + rustsecp256k1_v0_1_1_scalar_negate(&ss, &ss); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 2); + rustsecp256k1_v0_1_1_scalar_inverse_var(&ss, &ss); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); } /* Verify signature with message -1 passes. */ @@ -3959,25 +4869,25 @@ void test_ecdsa_edge_cases(void) { 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); + rustsecp256k1_v0_1_1_ge key; + rustsecp256k1_v0_1_1_scalar msg; + rustsecp256k1_v0_1_1_scalar sr, ss; + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 1); + rustsecp256k1_v0_1_1_scalar_set_int(&msg, 1); + rustsecp256k1_v0_1_1_scalar_negate(&msg, &msg); + rustsecp256k1_v0_1_1_scalar_set_b32(&sr, csr, NULL); + CHECK(rustsecp256k1_v0_1_1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + rustsecp256k1_v0_1_1_scalar_negate(&ss, &ss); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + rustsecp256k1_v0_1_1_scalar_set_int(&ss, 3); + rustsecp256k1_v0_1_1_scalar_inverse_var(&ss, &ss); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Signature where s would be zero. */ { - secp256k1_pubkey pubkey; + rustsecp256k1_v0_1_1_pubkey pubkey; size_t siglen; int32_t ecount; unsigned char signature[72]; @@ -4006,71 +4916,71 @@ void test_ecdsa_edge_cases(void) { 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); + rustsecp256k1_v0_1_1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); + CHECK(rustsecp256k1_v0_1_1_ec_pubkey_create(ctx, &pubkey, key) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, NULL, msg, &pubkey) == 0); CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0); CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg, NULL) == 0); CHECK(ecount == 6); - CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1); CHECK(ecount == 6); - CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 0); CHECK(ecount == 8); siglen = 72; - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0); CHECK(ecount == 9); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0); CHECK(ecount == 10); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0); CHECK(ecount == 11); - CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1); CHECK(ecount == 11); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, NULL, signature, siglen) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, NULL, signature, siglen) == 0); CHECK(ecount == 12); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, NULL, siglen) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_der(ctx, &sig, NULL, siglen) == 0); CHECK(ecount == 13); - CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, signature, siglen) == 1); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0); CHECK(ecount == 13); ecount = 0; - CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_normalize(ctx, NULL, NULL) == 0); CHECK(ecount == 1); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, NULL, &sig) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact(ctx, NULL, &sig) == 0); CHECK(ecount == 2); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact(ctx, signature, NULL) == 0); CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, &sig) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact(ctx, signature, &sig) == 1); CHECK(ecount == 3); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, NULL, signature) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact(ctx, NULL, signature) == 0); CHECK(ecount == 4); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, NULL) == 0); + CHECK(rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact(ctx, &sig, NULL) == 0); CHECK(ecount == 5); - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 1); + CHECK(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 0); CHECK(ecount == 5); - secp256k1_context_set_illegal_callback(ctx, NULL, NULL); + rustsecp256k1_v0_1_1_context_set_illegal_callback(ctx, NULL, NULL); } /* Nonce function corner cases. */ @@ -4079,43 +4989,43 @@ void test_ecdsa_edge_cases(void) { int i; unsigned char key[32]; unsigned char msg[32]; - secp256k1_ecdsa_signature sig2; - secp256k1_scalar sr[512], ss; + rustsecp256k1_v0_1_1_ecdsa_signature sig2; + rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); CHECK(!is_empty_signature(&sig2)); CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); /* The default nonce function is deterministic. */ - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); /* The default nonce function changes output with different messages. */ for(i = 0; i < 256; i++) { int j; msg[0] = i; - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); + CHECK(!rustsecp256k1_v0_1_1_scalar_eq(&sr[i], &sr[j])); } } msg[0] = 0; @@ -4124,11 +5034,11 @@ void test_ecdsa_edge_cases(void) { for(i = 256; i < 512; i++) { int j; key[0] = i - 256; - CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); + CHECK(!rustsecp256k1_v0_1_1_scalar_eq(&sr[i], &sr[j])); } } key[0] = 0; @@ -4187,7 +5097,7 @@ EC_KEY *get_openssl_key(const unsigned char *key32) { unsigned char privkey[300]; size_t privkeylen; const unsigned char* pbegin = privkey; - int compr = secp256k1_rand_bits(1); + int compr = rustsecp256k1_v0_1_1_rand_bits(1); EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); CHECK(ec_privkey_export_der(ctx, privkey, &privkeylen, key32, compr)); CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); @@ -4196,35 +5106,35 @@ EC_KEY *get_openssl_key(const unsigned char *key32) { } 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; + rustsecp256k1_v0_1_1_gej qj; + rustsecp256k1_v0_1_1_ge q; + rustsecp256k1_v0_1_1_scalar sigr, sigs; + rustsecp256k1_v0_1_1_scalar one; + rustsecp256k1_v0_1_1_scalar msg2; + rustsecp256k1_v0_1_1_scalar key, msg; EC_KEY *ec_key; unsigned int sigsize = 80; size_t secp_sigsize = 80; unsigned char message[32]; unsigned char signature[80]; unsigned char key32[32]; - secp256k1_rand256_test(message); - secp256k1_scalar_set_b32(&msg, message, NULL); + rustsecp256k1_v0_1_1_rand256_test(message); + rustsecp256k1_v0_1_1_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); + rustsecp256k1_v0_1_1_scalar_get_b32(key32, &key); + rustsecp256k1_v0_1_1_ecmult_gen(&ctx->ecmult_gen_ctx, &qj, &key); + rustsecp256k1_v0_1_1_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)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize)); + CHECK(rustsecp256k1_v0_1_1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg)); + rustsecp256k1_v0_1_1_scalar_set_int(&one, 1); + rustsecp256k1_v0_1_1_scalar_add(&msg2, &msg, &one); + CHECK(!rustsecp256k1_v0_1_1_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(rustsecp256k1_v0_1_1_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); @@ -4242,10 +5152,6 @@ void run_ecdsa_openssl(void) { # include "modules/ecdh/tests_impl.h" #endif -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/tests_impl.h" -#endif - #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/tests_impl.h" #endif @@ -4274,8 +5180,9 @@ int main(int argc, char **argv) { } } else { FILE *frand = fopen("/dev/urandom", "r"); - if ((frand == NULL) || !fread(&seed16, sizeof(seed16), 1, frand)) { + 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; @@ -4285,19 +5192,23 @@ int main(int argc, char **argv) { seed16[6] ^= t >> 48; seed16[7] ^= t >> 56; } - fclose(frand); + if (frand) { + fclose(frand); + } } - secp256k1_rand_seed(seed16); + rustsecp256k1_v0_1_1_rand_seed(seed16); printf("test count = %i\n", count); printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); /* initialize */ - run_context_tests(); - ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - if (secp256k1_rand_bits(1)) { - secp256k1_rand256(run32); - CHECK(secp256k1_context_randomize(ctx, secp256k1_rand_bits(1) ? run32 : NULL)); + run_context_tests(0); + run_context_tests(1); + run_scratch_tests(); + ctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + if (rustsecp256k1_v0_1_1_rand_bits(1)) { + rustsecp256k1_v0_1_1_rand256(run32); + CHECK(rustsecp256k1_v0_1_1_context_randomize(ctx, rustsecp256k1_v0_1_1_rand_bits(1) ? run32 : NULL)); } run_rand_bits(); @@ -4335,6 +5246,7 @@ int main(int argc, char **argv) { run_ecmult_constants(); run_ecmult_gen_blind(); run_ecmult_const_tests(); + run_ecmult_multi_tests(); run_ec_combine(); /* endomorphism tests */ @@ -4363,21 +5275,16 @@ int main(int argc, char **argv) { run_ecdsa_openssl(); #endif -#ifdef ENABLE_MODULE_SCHNORR - /* Schnorr tests */ - run_schnorr_tests(); -#endif - #ifdef ENABLE_MODULE_RECOVERY /* ECDSA pubkey recovery tests */ run_recovery_tests(); #endif - secp256k1_rand256(run32); + rustsecp256k1_v0_1_1_rand256(run32); printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); /* shutdown */ - secp256k1_context_destroy(ctx); + rustsecp256k1_v0_1_1_context_destroy(ctx); printf("no problems found\n"); return 0; diff --git a/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c b/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c new file mode 100644 index 000000000..3b0e6d256 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c @@ -0,0 +1,511 @@ +/*********************************************************************** + * Copyright (c) 2016 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include +#include + +#include + +#undef USE_ECMULT_STATIC_PRECOMPUTATION + +#ifndef EXHAUSTIVE_TEST_ORDER +/* see group_impl.h for allowable values */ +#define EXHAUSTIVE_TEST_ORDER 13 +#define EXHAUSTIVE_TEST_LAMBDA 9 /* cube root of 1 mod 13 */ +#endif + +#include "include/secp256k1.h" +#include "group.h" +#include "secp256k1.c" +#include "testrand_impl.h" + +#ifdef ENABLE_MODULE_RECOVERY +#include "src/modules/recovery/main_impl.h" +#include "include/secp256k1_recovery.h" +#endif + +/** stolen from tests.c */ +void ge_equals_ge(const rustsecp256k1_v0_1_1_ge *a, const rustsecp256k1_v0_1_1_ge *b) { + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&a->x, &b->x)); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&a->y, &b->y)); +} + +void ge_equals_gej(const rustsecp256k1_v0_1_1_ge *a, const rustsecp256k1_v0_1_1_gej *b) { + rustsecp256k1_v0_1_1_fe z2s; + rustsecp256k1_v0_1_1_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. */ + rustsecp256k1_v0_1_1_fe_sqr(&z2s, &b->z); + rustsecp256k1_v0_1_1_fe_mul(&u1, &a->x, &z2s); + u2 = b->x; rustsecp256k1_v0_1_1_fe_normalize_weak(&u2); + rustsecp256k1_v0_1_1_fe_mul(&s1, &a->y, &z2s); rustsecp256k1_v0_1_1_fe_mul(&s1, &s1, &b->z); + s2 = b->y; rustsecp256k1_v0_1_1_fe_normalize_weak(&s2); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&u1, &u2)); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&s1, &s2)); +} + +void random_fe(rustsecp256k1_v0_1_1_fe *x) { + unsigned char bin[32]; + do { + rustsecp256k1_v0_1_1_rand256(bin); + if (rustsecp256k1_v0_1_1_fe_set_b32(x, bin)) { + return; + } + } while(1); +} +/** END stolen from tests.c */ + +int rustsecp256k1_v0_1_1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, + const unsigned char *key32, const unsigned char *algo16, + void *data, unsigned int attempt) { + rustsecp256k1_v0_1_1_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; + } + rustsecp256k1_v0_1_1_scalar_set_int(&s, *idata); + rustsecp256k1_v0_1_1_scalar_get_b32(nonce32, &s); + return 1; +} + +#ifdef USE_ENDOMORPHISM +void test_exhaustive_endomorphism(const rustsecp256k1_v0_1_1_ge *group, int order) { + int i; + for (i = 0; i < order; i++) { + rustsecp256k1_v0_1_1_ge res; + rustsecp256k1_v0_1_1_ge_mul_lambda(&res, &group[i]); + ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); + } +} +#endif + +void test_exhaustive_addition(const rustsecp256k1_v0_1_1_ge *group, const rustsecp256k1_v0_1_1_gej *groupj, int order) { + int i, j; + + /* Sanity-check (and check infinity functions) */ + CHECK(rustsecp256k1_v0_1_1_ge_is_infinity(&group[0])); + CHECK(rustsecp256k1_v0_1_1_gej_is_infinity(&groupj[0])); + for (i = 1; i < order; i++) { + CHECK(!rustsecp256k1_v0_1_1_ge_is_infinity(&group[i])); + CHECK(!rustsecp256k1_v0_1_1_gej_is_infinity(&groupj[i])); + } + + /* Check all addition formulae */ + for (j = 0; j < order; j++) { + rustsecp256k1_v0_1_1_fe fe_inv; + rustsecp256k1_v0_1_1_fe_inv(&fe_inv, &groupj[j].z); + for (i = 0; i < order; i++) { + rustsecp256k1_v0_1_1_ge zless_gej; + rustsecp256k1_v0_1_1_gej tmp; + /* add_var */ + rustsecp256k1_v0_1_1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); + ge_equals_gej(&group[(i + j) % order], &tmp); + /* add_ge */ + if (j > 0) { + rustsecp256k1_v0_1_1_gej_add_ge(&tmp, &groupj[i], &group[j]); + ge_equals_gej(&group[(i + j) % order], &tmp); + } + /* add_ge_var */ + rustsecp256k1_v0_1_1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); + ge_equals_gej(&group[(i + j) % order], &tmp); + /* add_zinv_var */ + zless_gej.infinity = groupj[j].infinity; + zless_gej.x = groupj[j].x; + zless_gej.y = groupj[j].y; + rustsecp256k1_v0_1_1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); + ge_equals_gej(&group[(i + j) % order], &tmp); + } + } + + /* Check doubling */ + for (i = 0; i < order; i++) { + rustsecp256k1_v0_1_1_gej tmp; + if (i > 0) { + rustsecp256k1_v0_1_1_gej_double_nonzero(&tmp, &groupj[i], NULL); + ge_equals_gej(&group[(2 * i) % order], &tmp); + } + rustsecp256k1_v0_1_1_gej_double_var(&tmp, &groupj[i], NULL); + ge_equals_gej(&group[(2 * i) % order], &tmp); + } + + /* Check negation */ + for (i = 1; i < order; i++) { + rustsecp256k1_v0_1_1_ge tmp; + rustsecp256k1_v0_1_1_gej tmpj; + rustsecp256k1_v0_1_1_ge_neg(&tmp, &group[i]); + ge_equals_ge(&group[order - i], &tmp); + rustsecp256k1_v0_1_1_gej_neg(&tmpj, &groupj[i]); + ge_equals_gej(&group[order - i], &tmpj); + } +} + +void test_exhaustive_ecmult(const rustsecp256k1_v0_1_1_context *ctx, const rustsecp256k1_v0_1_1_ge *group, const rustsecp256k1_v0_1_1_gej *groupj, int order) { + int i, j, r_log; + for (r_log = 1; r_log < order; r_log++) { + for (j = 0; j < order; j++) { + for (i = 0; i < order; i++) { + rustsecp256k1_v0_1_1_gej tmp; + rustsecp256k1_v0_1_1_scalar na, ng; + rustsecp256k1_v0_1_1_scalar_set_int(&na, i); + rustsecp256k1_v0_1_1_scalar_set_int(&ng, j); + + rustsecp256k1_v0_1_1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); + ge_equals_gej(&group[(i * r_log + j) % order], &tmp); + + if (i > 0) { + rustsecp256k1_v0_1_1_ecmult_const(&tmp, &group[i], &ng, 256); + ge_equals_gej(&group[(i * j) % order], &tmp); + } + } + } + } +} + +typedef struct { + rustsecp256k1_v0_1_1_scalar sc[2]; + rustsecp256k1_v0_1_1_ge pt[2]; +} ecmult_multi_data; + +static int ecmult_multi_callback(rustsecp256k1_v0_1_1_scalar *sc, rustsecp256k1_v0_1_1_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 rustsecp256k1_v0_1_1_context *ctx, const rustsecp256k1_v0_1_1_ge *group, int order) { + int i, j, k, x, y; + rustsecp256k1_v0_1_1_scratch *scratch = rustsecp256k1_v0_1_1_scratch_create(&ctx->error_callback, 4096); + for (i = 0; i < order; i++) { + for (j = 0; j < order; j++) { + for (k = 0; k < order; k++) { + for (x = 0; x < order; x++) { + for (y = 0; y < order; y++) { + rustsecp256k1_v0_1_1_gej tmp; + rustsecp256k1_v0_1_1_scalar g_sc; + ecmult_multi_data data; + + rustsecp256k1_v0_1_1_scalar_set_int(&data.sc[0], i); + rustsecp256k1_v0_1_1_scalar_set_int(&data.sc[1], j); + rustsecp256k1_v0_1_1_scalar_set_int(&g_sc, k); + data.pt[0] = group[x]; + data.pt[1] = group[y]; + + rustsecp256k1_v0_1_1_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) % order], &tmp); + } + } + } + } + } + rustsecp256k1_v0_1_1_scratch_destroy(&ctx->error_callback, scratch); +} + +void r_from_k(rustsecp256k1_v0_1_1_scalar *r, const rustsecp256k1_v0_1_1_ge *group, int k) { + rustsecp256k1_v0_1_1_fe x; + unsigned char x_bin[32]; + k %= EXHAUSTIVE_TEST_ORDER; + x = group[k].x; + rustsecp256k1_v0_1_1_fe_normalize(&x); + rustsecp256k1_v0_1_1_fe_get_b32(x_bin, &x); + rustsecp256k1_v0_1_1_scalar_set_b32(r, x_bin, NULL); +} + +void test_exhaustive_verify(const rustsecp256k1_v0_1_1_context *ctx, const rustsecp256k1_v0_1_1_ge *group, int order) { + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + rustsecp256k1_v0_1_1_ge nonconst_ge; + rustsecp256k1_v0_1_1_ecdsa_signature sig; + rustsecp256k1_v0_1_1_pubkey pk; + rustsecp256k1_v0_1_1_scalar sk_s, msg_s, r_s, s_s; + rustsecp256k1_v0_1_1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int k, should_verify; + unsigned char msg32[32]; + + rustsecp256k1_v0_1_1_scalar_set_int(&s_s, s); + rustsecp256k1_v0_1_1_scalar_set_int(&r_s, r); + rustsecp256k1_v0_1_1_scalar_set_int(&msg_s, msg); + rustsecp256k1_v0_1_1_scalar_set_int(&sk_s, key); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + rustsecp256k1_v0_1_1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + rustsecp256k1_v0_1_1_scalar_set_int(&s_times_k_s, k); + rustsecp256k1_v0_1_1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + rustsecp256k1_v0_1_1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + rustsecp256k1_v0_1_1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= rustsecp256k1_v0_1_1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !rustsecp256k1_v0_1_1_scalar_is_high(&s_s); + + /* Verify by calling verify */ + rustsecp256k1_v0_1_1_ecdsa_signature_save(&sig, &r_s, &s_s); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + rustsecp256k1_v0_1_1_pubkey_save(&pk, &nonconst_ge); + rustsecp256k1_v0_1_1_scalar_get_b32(msg32, &msg_s); + CHECK(should_verify == + rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} + +void test_exhaustive_sign(const rustsecp256k1_v0_1_1_context *ctx, const rustsecp256k1_v0_1_1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + rustsecp256k1_v0_1_1_ecdsa_signature sig; + rustsecp256k1_v0_1_1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + rustsecp256k1_v0_1_1_scalar_set_int(&msg, i); + rustsecp256k1_v0_1_1_scalar_set_int(&sk, j); + rustsecp256k1_v0_1_1_scalar_get_b32(sk32, &sk); + rustsecp256k1_v0_1_1_scalar_get_b32(msg32, &msg); + + rustsecp256k1_v0_1_1_ecdsa_sign(ctx, &sig, msg32, sk32, rustsecp256k1_v0_1_1_nonce_function_smallint, &k); + + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } + + /* We would like to verify zero-knowledge here by counting how often every + * possible (s, r) tuple appears, but because the group order is larger + * than the field order, when coercing the x-values to scalar values, some + * appear more often than others, so we are actually not zero-knowledge. + * (This effect also appears in the real code, but the difference is on the + * order of 1/2^128th the field order, so the deviation is not useful to a + * computationally bounded attacker.) + */ +} + +#ifdef ENABLE_MODULE_RECOVERY +void test_exhaustive_recovery_sign(const rustsecp256k1_v0_1_1_context *ctx, const rustsecp256k1_v0_1_1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + rustsecp256k1_v0_1_1_fe r_dot_y_normalized; + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature rsig; + rustsecp256k1_v0_1_1_ecdsa_signature sig; + rustsecp256k1_v0_1_1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + int expected_recid; + int recid; + rustsecp256k1_v0_1_1_scalar_set_int(&msg, i); + rustsecp256k1_v0_1_1_scalar_set_int(&sk, j); + rustsecp256k1_v0_1_1_scalar_get_b32(sk32, &sk); + rustsecp256k1_v0_1_1_scalar_get_b32(msg32, &msg); + + rustsecp256k1_v0_1_1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, rustsecp256k1_v0_1_1_nonce_function_smallint, &k); + + /* Check directly */ + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + /* In computing the recid, there is an overflow condition that is disabled in + * scalar_low_impl.h `rustsecp256k1_v0_1_1_scalar_set_b32` because almost every r.y value + * will exceed the group order, and our signing code always holds out for r + * values that don't overflow, so with a proper overflow check the tests would + * loop indefinitely. */ + r_dot_y_normalized = group[k].y; + rustsecp256k1_v0_1_1_fe_normalize(&r_dot_y_normalized); + /* Also the recovery id is flipped depending if we hit the low-s branch */ + if ((k * s) % order == (i + r * j) % order) { + expected_recid = rustsecp256k1_v0_1_1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; + } else { + expected_recid = rustsecp256k1_v0_1_1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; + } + CHECK(recid == expected_recid); + + /* Convert to a standard sig then check */ + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + rustsecp256k1_v0_1_1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } +} + +void test_exhaustive_recovery_verify(const rustsecp256k1_v0_1_1_context *ctx, const rustsecp256k1_v0_1_1_ge *group, int order) { + /* This is essentially a copy of test_exhaustive_verify, with recovery added */ + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + rustsecp256k1_v0_1_1_ge nonconst_ge; + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature rsig; + rustsecp256k1_v0_1_1_ecdsa_signature sig; + rustsecp256k1_v0_1_1_pubkey pk; + rustsecp256k1_v0_1_1_scalar sk_s, msg_s, r_s, s_s; + rustsecp256k1_v0_1_1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int recid = 0; + int k, should_verify; + unsigned char msg32[32]; + + rustsecp256k1_v0_1_1_scalar_set_int(&s_s, s); + rustsecp256k1_v0_1_1_scalar_set_int(&r_s, r); + rustsecp256k1_v0_1_1_scalar_set_int(&msg_s, msg); + rustsecp256k1_v0_1_1_scalar_set_int(&sk_s, key); + rustsecp256k1_v0_1_1_scalar_get_b32(msg32, &msg_s); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + rustsecp256k1_v0_1_1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + rustsecp256k1_v0_1_1_scalar_set_int(&s_times_k_s, k); + rustsecp256k1_v0_1_1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + rustsecp256k1_v0_1_1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + rustsecp256k1_v0_1_1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= rustsecp256k1_v0_1_1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !rustsecp256k1_v0_1_1_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 */ + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); + rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + rustsecp256k1_v0_1_1_pubkey_save(&pk, &nonconst_ge); + CHECK(should_verify == + rustsecp256k1_v0_1_1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} +#endif + +int main(void) { + int i; + rustsecp256k1_v0_1_1_gej groupj[EXHAUSTIVE_TEST_ORDER]; + rustsecp256k1_v0_1_1_ge group[EXHAUSTIVE_TEST_ORDER]; + + /* Build context */ + rustsecp256k1_v0_1_1_context *ctx = rustsecp256k1_v0_1_1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + /* TODO set z = 1, then do num_tests runs with random z values */ + + /* Generate the entire group */ + rustsecp256k1_v0_1_1_gej_set_infinity(&groupj[0]); + rustsecp256k1_v0_1_1_ge_set_gej(&group[0], &groupj[0]); + for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { + /* Set a different random z-value for each Jacobian point */ + rustsecp256k1_v0_1_1_fe z; + random_fe(&z); + + rustsecp256k1_v0_1_1_gej_add_ge(&groupj[i], &groupj[i - 1], &rustsecp256k1_v0_1_1_ge_const_g); + rustsecp256k1_v0_1_1_ge_set_gej(&group[i], &groupj[i]); + rustsecp256k1_v0_1_1_gej_rescale(&groupj[i], &z); + + /* Verify against ecmult_gen */ + { + rustsecp256k1_v0_1_1_scalar scalar_i; + rustsecp256k1_v0_1_1_gej generatedj; + rustsecp256k1_v0_1_1_ge generated; + + rustsecp256k1_v0_1_1_scalar_set_int(&scalar_i, i); + rustsecp256k1_v0_1_1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); + rustsecp256k1_v0_1_1_ge_set_gej(&generated, &generatedj); + + CHECK(group[i].infinity == 0); + CHECK(generated.infinity == 0); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&generated.x, &group[i].x)); + CHECK(rustsecp256k1_v0_1_1_fe_equal_var(&generated.y, &group[i].y)); + } + } + + /* Run the tests */ +#ifdef USE_ENDOMORPHISM + test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); +#endif + test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_ecmult_multi(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); + +#ifdef ENABLE_MODULE_RECOVERY + test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); +#endif + + rustsecp256k1_v0_1_1_context_destroy(ctx); + return 0; +} + diff --git a/depend/secp256k1/src/util.h b/secp256k1-sys/depend/secp256k1/src/util.h similarity index 50% rename from depend/secp256k1/src/util.h rename to secp256k1-sys/depend/secp256k1/src/util.h index 4eef4ded4..7ea0d15f0 100644 --- a/depend/secp256k1/src/util.h +++ b/secp256k1-sys/depend/secp256k1/src/util.h @@ -4,8 +4,8 @@ * file COPYING or http://www.opensource.org/licenses/mit-license.php.* **********************************************************************/ -#ifndef _SECP256K1_UTIL_H_ -#define _SECP256K1_UTIL_H_ +#ifndef SECP256K1_UTIL_H +#define SECP256K1_UTIL_H #if defined HAVE_CONFIG_H #include "libsecp256k1-config.h" @@ -18,9 +18,9 @@ typedef struct { void (*fn)(const char *text, void* data); const void* data; -} secp256k1_callback; +} rustsecp256k1_v0_1_1_callback; -static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) { +static SECP256K1_INLINE void rustsecp256k1_v0_1_1_callback_call(const rustsecp256k1_v0_1_1_callback * const cb, const char * const text) { cb->fn(text, (void*)cb->data); } @@ -36,7 +36,7 @@ static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * } while(0) #endif -#ifdef HAVE_BUILTIN_EXPECT +#if SECP256K1_GNUC_PREREQ(3, 0) #define EXPECT(x,c) __builtin_expect((x),(c)) #else #define EXPECT(x,c) (x) @@ -57,7 +57,10 @@ static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * #endif /* Like assert(), but when VERIFY is defined, and side-effect safe. */ -#ifdef VERIFY +#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 @@ -65,11 +68,44 @@ static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * #define VERIFY_SETUP(stmt) #endif -static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) { - void *ret = malloc(size); - if (ret == NULL) { - secp256k1_callback_call(cb, "Out of memory"); - } +#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; } @@ -107,4 +143,4 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_ SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; #endif -#endif +#endif /* SECP256K1_UTIL_H */ diff --git a/secp256k1-sys/depend/util.h.patch b/secp256k1-sys/depend/util.h.patch new file mode 100644 index 000000000..92731c741 --- /dev/null +++ b/secp256k1-sys/depend/util.h.patch @@ -0,0 +1,17 @@ +71,86d70 +< 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; +< } +< diff --git a/secp256k1-sys/src/lib.rs b/secp256k1-sys/src/lib.rs new file mode 100644 index 000000000..79342c6b3 --- /dev/null +++ b/secp256k1-sys/src/lib.rs @@ -0,0 +1,822 @@ +// Bitcoin secp256k1 bindings +// Written in 2014 by +// Dawid Ciężarkiewicz +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// +//! # secp256k1-sys FFI bindings +//! Direct bindings to the underlying C library functions. These should +//! not be needed for most users. + +#![crate_type = "lib"] +#![crate_type = "rlib"] +#![crate_type = "dylib"] +#![crate_name = "secp256k1_sys"] + +#![cfg_attr(all(not(test), not(fuzztarget), not(feature = "std")), no_std)] +#![cfg_attr(feature = "dev", allow(unstable_features))] +#![cfg_attr(feature = "dev", feature(plugin))] +#![cfg_attr(feature = "dev", plugin(clippy))] + +#[cfg(any(test, feature = "std"))] +extern crate core; + +#[macro_use] +mod macros; +pub mod types; + +#[cfg(feature = "recovery")] +pub mod recovery; + +use core::{hash, slice, ptr}; +use types::*; + +/// Flag for context to enable no precomputation +pub const SECP256K1_START_NONE: c_uint = 1; +/// Flag for context to enable verification precomputation +pub const SECP256K1_START_VERIFY: c_uint = 1 | (1 << 8); +/// Flag for context to enable signing precomputation +pub const SECP256K1_START_SIGN: c_uint = 1 | (1 << 9); +/// Flag for keys to indicate uncompressed serialization format +pub const SECP256K1_SER_UNCOMPRESSED: c_uint = (1 << 1); +/// Flag for keys to indicate compressed serialization format +pub const SECP256K1_SER_COMPRESSED: c_uint = (1 << 1) | (1 << 8); + +/// A nonce generation function. Ordinary users of the library +/// never need to see this type; only if you need to control +/// nonce generation do you need to use it. I have deliberately +/// made this hard to do: you have to write your own wrapper +/// around the FFI functions to use it. And it's an unsafe type. +/// Nonces are generated deterministically by RFC6979 by +/// default; there should be no need to ever change this. +pub type NonceFn = unsafe extern "C" fn(nonce32: *mut c_uchar, + msg32: *const c_uchar, + key32: *const c_uchar, + algo16: *const c_uchar, + data: *mut c_void, + attempt: c_uint, +); + +/// Hash function to use to post-process an ECDH point to get +/// a shared secret. +pub type EcdhHashFn = unsafe extern "C" fn( + output: *mut c_uchar, + x: *const c_uchar, + y: *const c_uchar, + data: *mut c_void, +) -> c_int; + +/// A Secp256k1 context, containing various precomputed values and such +/// needed to do elliptic curve computations. If you create one of these +/// with `secp256k1_context_create` you MUST destroy it with +/// `secp256k1_context_destroy`, or else you will have a memory leak. +#[derive(Clone, Debug)] +#[repr(C)] pub struct Context(c_int); + +#[cfg(feature = "fuzztarget")] +impl Context { + pub fn flags(&self) -> u32 { + self.0 as u32 + } +} + +/// Library-internal representation of a Secp256k1 public key +#[repr(C)] +pub struct PublicKey([c_uchar; 64]); +impl_array_newtype!(PublicKey, c_uchar, 64); +impl_raw_debug!(PublicKey); + +impl PublicKey { + /// Create a new (zeroed) public key usable for the FFI interface + pub fn new() -> PublicKey { PublicKey([0; 64]) } + /// Create a new (uninitialized) public key usable for the FFI interface + #[deprecated(since = "0.15.3", note = "Please use the new function instead")] + pub unsafe fn blank() -> PublicKey { PublicKey::new() } +} + +impl Default for PublicKey { + fn default() -> Self { + PublicKey::new() + } +} + +impl hash::Hash for PublicKey { + fn hash(&self, state: &mut H) { + state.write(&self.0) + } +} + +/// Library-internal representation of a Secp256k1 signature +#[repr(C)] +pub struct Signature([c_uchar; 64]); +impl_array_newtype!(Signature, c_uchar, 64); +impl_raw_debug!(Signature); + +impl Signature { + /// Create a new (zeroed) signature usable for the FFI interface + pub fn new() -> Signature { Signature([0; 64]) } + /// Create a new (uninitialized) signature usable for the FFI interface + #[deprecated(since = "0.15.3", note = "Please use the new function instead")] + pub unsafe fn blank() -> Signature { Signature::new() } +} + +impl Default for Signature { + fn default() -> Self { + Signature::new() + } +} + + +#[cfg(not(feature = "fuzztarget"))] +extern "C" { + /// Default ECDH hash function + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdh_hash_function_default")] + pub static secp256k1_ecdh_hash_function_default: EcdhHashFn; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_nonce_function_rfc6979")] + pub static secp256k1_nonce_function_rfc6979: NonceFn; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_nonce_function_default")] + pub static secp256k1_nonce_function_default: NonceFn; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_no_precomp")] + pub static secp256k1_context_no_precomp: *const Context; + + // Contexts + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_size")] + pub fn secp256k1_context_preallocated_size(flags: c_uint) -> usize; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_create")] + pub fn secp256k1_context_preallocated_create(prealloc: *mut c_void, flags: c_uint) -> *mut Context; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_destroy")] + pub fn secp256k1_context_preallocated_destroy(cx: *mut Context); + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_clone_size")] + pub fn secp256k1_context_preallocated_clone_size(cx: *const Context) -> usize; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_clone")] + pub fn secp256k1_context_preallocated_clone(cx: *const Context, prealloc: *mut c_void) -> *mut Context; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_randomize")] + pub fn secp256k1_context_randomize(cx: *mut Context, + seed32: *const c_uchar) + -> c_int; + + // Pubkeys + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_parse")] + pub fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey, + input: *const c_uchar, in_len: usize) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_serialize")] + pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar, + out_len: *mut usize, pk: *const PublicKey, + compressed: c_uint) + -> c_int; + + // Signatures + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_parse_der")] + pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context, sig: *mut Signature, + input: *const c_uchar, in_len: usize) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact")] + pub fn secp256k1_ecdsa_signature_parse_compact(cx: *const Context, sig: *mut Signature, + input64: *const c_uchar) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_parse_der_lax")] + pub fn ecdsa_signature_parse_der_lax(cx: *const Context, sig: *mut Signature, + input: *const c_uchar, in_len: usize) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der")] + pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *mut c_uchar, + out_len: *mut usize, sig: *const Signature) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact")] + pub fn secp256k1_ecdsa_signature_serialize_compact(cx: *const Context, output64: *mut c_uchar, + sig: *const Signature) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_normalize")] + pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context, out_sig: *mut Signature, + in_sig: *const Signature) + -> c_int; + + // ECDSA + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_verify")] + pub fn secp256k1_ecdsa_verify(cx: *const Context, + sig: *const Signature, + msg32: *const c_uchar, + pk: *const PublicKey) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_sign")] + pub fn secp256k1_ecdsa_sign(cx: *const Context, + sig: *mut Signature, + msg32: *const c_uchar, + sk: *const c_uchar, + noncefn: NonceFn, + noncedata: *const c_void) + -> c_int; + + // EC + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_seckey_verify")] + pub fn secp256k1_ec_seckey_verify(cx: *const Context, + sk: *const c_uchar) -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_create")] + pub fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey, + sk: *const c_uchar) -> c_int; + +//TODO secp256k1_ec_privkey_export +//TODO secp256k1_ec_privkey_import + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_privkey_tweak_add")] + pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context, + sk: *mut c_uchar, + tweak: *const c_uchar) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_tweak_add")] + pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, + pk: *mut PublicKey, + tweak: *const c_uchar) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_privkey_tweak_mul")] + pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context, + sk: *mut c_uchar, + tweak: *const c_uchar) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_tweak_mul")] + pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, + pk: *mut PublicKey, + tweak: *const c_uchar) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_combine")] + pub fn secp256k1_ec_pubkey_combine(cx: *const Context, + out: *mut PublicKey, + ins: *const *const PublicKey, + n: c_int) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdh")] + pub fn secp256k1_ecdh( + cx: *const Context, + output: *mut c_uchar, + pubkey: *const PublicKey, + privkey: *const c_uchar, + hashfp: EcdhHashFn, + data: *mut c_void, + ) -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_privkey_inverse")] + pub fn secp256k1_ec_privkey_inverse(cx: *const Context, + out: *mut c_uchar, + scalar: *const c_uchar) + -> c_int; +} + + +/// A reimplementation of the C function `secp256k1_context_create` in rust. +/// +/// This function allocates memory, the pointer should be deallocated using `secp256k1_context_destroy` +/// A failure to do so will result in a memory leak. +/// +/// This will create a secp256k1 raw context. +// Returns: a newly created context object. +// In: flags: which parts of the context to initialize. +#[no_mangle] +#[cfg(all(feature = "std", not(feature = "external_symbols")))] +pub unsafe extern "C" fn rustsecp256k1_v0_1_1_context_create(flags: c_uint) -> *mut Context { + use std::mem; + assert!(mem::align_of::() >= mem::align_of::()); + assert_eq!(mem::size_of::(), mem::size_of::<&usize>()); + + let word_size = mem::size_of::(); + let n_words = (secp256k1_context_preallocated_size(flags) + word_size - 1) / word_size; + + let buf = vec![0usize; n_words + 1].into_boxed_slice(); + let ptr = Box::into_raw(buf) as *mut usize; + ::core::ptr::write(ptr, n_words); + let ptr: *mut usize = ptr.offset(1); + + secp256k1_context_preallocated_create(ptr as *mut c_void, flags) +} + +#[cfg(all(feature = "std", not(feature = "external_symbols")))] +pub unsafe fn secp256k1_context_create(flags: c_uint) -> *mut Context { + rustsecp256k1_v0_1_1_context_create(flags) +} + +/// A reimplementation of the C function `secp256k1_context_destroy` in rust. +/// +/// This function destroys and deallcates the context created by `secp256k1_context_create`. +/// +/// The pointer shouldn't be used after passing to this function, consider it as passing it to `free()`. +/// +#[no_mangle] +#[cfg(all(feature = "std", not(feature = "external_symbols")))] +pub unsafe extern "C" fn rustsecp256k1_v0_1_1_context_destroy(ctx: *mut Context) { + secp256k1_context_preallocated_destroy(ctx); + let ctx: *mut usize = ctx as *mut usize; + + let n_words_ptr: *mut usize = ctx.offset(-1); + let n_words: usize = ::core::ptr::read(n_words_ptr); + let slice: &mut [usize] = slice::from_raw_parts_mut(n_words_ptr , n_words+1); + let _ = Box::from_raw(slice as *mut [usize]); +} + +#[cfg(all(feature = "std", not(feature = "external_symbols")))] +pub unsafe fn secp256k1_context_destroy(ctx: *mut Context) { + rustsecp256k1_v0_1_1_context_destroy(ctx) +} + + +/// **This function is an override for the C function, this is the an edited version of the original description:** +/// +/// A callback function to be called when an illegal argument is passed to +/// an API call. It will only trigger for violations that are mentioned +/// explicitly in the header. **This will cause a panic**. +/// +/// The philosophy is that these shouldn't be dealt with through a +/// specific return value, as calling code should not have branches to deal with +/// the case that this code itself is broken. +/// +/// On the other hand, during debug stage, one would want to be informed about +/// such mistakes, and the default (crashing) may be inadvisable. +/// When this callback is triggered, the API function called is guaranteed not +/// to cause a crash, though its return value and output arguments are +/// undefined. +/// +/// See also secp256k1_default_error_callback_fn. +/// +#[no_mangle] +#[cfg(not(feature = "external_symbols"))] +pub unsafe extern "C" fn rustsecp256k1_v0_1_1_default_illegal_callback_fn(message: *const c_char, _data: *mut c_void) { + use core::str; + let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); + let msg = str::from_utf8_unchecked(msg_slice); + panic!("[libsecp256k1] illegal argument. {}", msg); +} + +/// **This function is an override for the C function, this is the an edited version of the original description:** +/// +/// A callback function to be called when an internal consistency check +/// fails. **This will cause a panic**. +/// +/// This can only trigger in case of a hardware failure, miscompilation, +/// memory corruption, serious bug in the library, or other error would can +/// otherwise result in undefined behaviour. It will not trigger due to mere +/// incorrect usage of the API (see secp256k1_default_illegal_callback_fn +/// for that). After this callback returns, anything may happen, including +/// crashing. +/// +/// See also secp256k1_default_illegal_callback_fn. +/// +#[no_mangle] +#[cfg(not(feature = "external_symbols"))] +pub unsafe extern "C" fn rustsecp256k1_v0_1_1_default_error_callback_fn(message: *const c_char, _data: *mut c_void) { + use core::str; + let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); + let msg = str::from_utf8_unchecked(msg_slice); + panic!("[libsecp256k1] internal consistency check failed {}", msg); +} + + +unsafe fn strlen(mut str_ptr: *const c_char) -> usize { + let mut ctr = 0; + while *str_ptr != '\0' as c_char { + ctr += 1; + str_ptr = str_ptr.offset(1); + } + ctr +} + + +/// A trait for producing pointers that will always be valid in C. (assuming NULL pointer is a valid no-op) +/// Rust doesn't promise what pointers does it give to ZST (https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts) +/// In case the type is empty this trait will give a NULL pointer, which should be handled in C. +/// +pub trait CPtr { + type Target; + fn as_c_ptr(&self) -> *const Self::Target; + fn as_mut_c_ptr(&mut self) -> *mut Self::Target; +} + +impl CPtr for [T] { + type Target = T; + fn as_c_ptr(&self) -> *const Self::Target { + if self.is_empty() { + ptr::null() + } else { + self.as_ptr() + } + } + + fn as_mut_c_ptr(&mut self) -> *mut Self::Target { + if self.is_empty() { + ptr::null::() as *mut _ + } else { + self.as_mut_ptr() + } + } +} + + + + +#[cfg(feature = "fuzztarget")] +mod fuzz_dummy { + extern crate std; + use self::std::{ptr, mem}; + use self::std::boxed::Box; + use types::*; + use ::{Signature, Context, NonceFn, EcdhHashFn, PublicKey, + SECP256K1_START_NONE, SECP256K1_START_VERIFY, SECP256K1_START_SIGN, + SECP256K1_SER_COMPRESSED, SECP256K1_SER_UNCOMPRESSED}; + + #[allow(non_upper_case_globals)] + pub static secp256k1_context_no_precomp: &Context = &Context(0); + + extern "C" { + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdh_hash_function_default")] + pub static secp256k1_ecdh_hash_function_default: EcdhHashFn; + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_nonce_function_rfc6979")] + pub static secp256k1_nonce_function_rfc6979: NonceFn; + } + + // Contexts + /// Creates a dummy context, tracking flags to ensure proper calling semantics + pub unsafe fn secp256k1_context_preallocated_create(_ptr: *mut c_void, flags: c_uint) -> *mut Context { + let b = Box::new(Context(flags as i32)); + Box::into_raw(b) + } + + /// Return dummy size of context struct. + pub unsafe fn secp256k1_context_preallocated_size(_flags: c_uint) -> usize { + mem::size_of::() + } + + /// Return dummy size of context struct. + pub unsafe fn secp256k1_context_preallocated_clone_size(_cx: *mut Context) -> usize { + mem::size_of::() + } + + /// Copies a dummy context + pub unsafe fn secp256k1_context_preallocated_clone(cx: *const Context, prealloc: *mut c_void) -> *mut Context { + let ret = prealloc as *mut Context; + *ret = (*cx).clone(); + ret + } + + /// "Destroys" a dummy context + pub unsafe fn secp256k1_context_preallocated_destroy(cx: *mut Context) { + (*cx).0 = 0; + } + + /// Asserts that cx is properly initialized + pub unsafe fn secp256k1_context_randomize(cx: *mut Context, + _seed32: *const c_uchar) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + 1 + } + + // TODO secp256k1_context_set_illegal_callback + // TODO secp256k1_context_set_error_callback + // (Actually, I don't really want these exposed; if either of these + // are ever triggered it indicates a bug in rust-secp256k1, since + // one goal is to use Rust's type system to eliminate all possible + // bad inputs.) + + // Pubkeys + /// Parse 33/65 byte pubkey into PublicKey, losing compressed information + pub unsafe fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey, + input: *const c_uchar, in_len: usize) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + match in_len { + 33 => { + if (*input.offset(1) > 0x7f && *input != 2) || (*input.offset(1) <= 0x7f && *input != 3) { + 0 + } else { + ptr::copy(input.offset(1), (*pk).0[0..32].as_mut_ptr(), 32); + ptr::copy(input.offset(1), (*pk).0[32..64].as_mut_ptr(), 32); + test_pk_validate(cx, pk) + } + }, + 65 => { + if *input != 4 && *input != 6 && *input != 7 { + 0 + } else { + ptr::copy(input.offset(1), (*pk).0.as_mut_ptr(), 64); + test_pk_validate(cx, pk) + } + }, + _ => 0 + } + } + + /// Serialize PublicKey back to 33/65 byte pubkey + pub unsafe fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar, + out_len: *mut usize, pk: *const PublicKey, + compressed: c_uint) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if test_pk_validate(cx, pk) != 1 { return 0; } + if compressed == SECP256K1_SER_COMPRESSED { + assert_eq!(*out_len, 33); + if (*pk).0[0] > 0x7f { + *output = 2; + } else { + *output = 3; + } + ptr::copy((*pk).0.as_ptr(), output.offset(1), 32); + } else if compressed == SECP256K1_SER_UNCOMPRESSED { + assert_eq!(*out_len, 65); + *output = 4; + ptr::copy((*pk).0.as_ptr(), output.offset(1), 64); + } else { + panic!("Bad flags"); + } + 1 + } + + // Signatures + pub unsafe fn secp256k1_ecdsa_signature_parse_der(_cx: *const Context, _sig: *mut Signature, + _input: *const c_uchar, _in_len: usize) + -> c_int { + unimplemented!(); + } + + /// Copies input64 to sig, checking the pubkey part is valid + pub unsafe fn secp256k1_ecdsa_signature_parse_compact(cx: *const Context, sig: *mut Signature, + input64: *const c_uchar) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if secp256k1_ec_seckey_verify(cx, input64.offset(32)) != 1 { return 0; } // sig should be msg32||sk + ptr::copy(input64, (*sig).0[..].as_mut_ptr(), 64); + 1 + } + + pub unsafe fn ecdsa_signature_parse_der_lax(_cx: *const Context, _sig: *mut Signature, + _input: *const c_uchar, _in_len: usize) + -> c_int { + unimplemented!(); + } + + /// Copies up to 72 bytes into output from sig + pub unsafe fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *mut c_uchar, + out_len: *mut usize, sig: *const Signature) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + + let mut len_r = 33; + if *(*sig).0.as_ptr().offset(0) < 0x80 { + len_r -= 1; + } + let mut len_s = 33; + if *(*sig).0.as_ptr().offset(32) < 0x80 { + len_s -= 1; + } + + assert!(*out_len >= (6 + len_s + len_r) as usize); + + *output.offset(0) = 0x30; + *output.offset(1) = 4 + len_r + len_s; + *output.offset(2) = 0x02; + *output.offset(3) = len_r; + if len_r == 33 { + *output.offset(4) = 0; + ptr::copy((*sig).0[..].as_ptr(), output.offset(5), 32); + } else { + ptr::copy((*sig).0[..].as_ptr(), output.offset(4), 32); + } + *output.offset(4 + len_r as isize) = 0x02; + *output.offset(5 + len_r as isize) = len_s; + if len_s == 33 { + *output.offset(6 + len_r as isize) = 0; + ptr::copy((*sig).0[..].as_ptr().offset(32), output.offset(7 + len_r as isize), 32); + } else { + ptr::copy((*sig).0[..].as_ptr().offset(32), output.offset(6 + len_r as isize), 32); + } + 1 + } + + /// Copies sig to output64 + pub unsafe fn secp256k1_ecdsa_signature_serialize_compact(cx: *const Context, output64: *mut c_uchar, + sig: *const Signature) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + ptr::copy((*sig).0[..].as_ptr(), output64, 64); + 1 + } + + pub unsafe fn secp256k1_ecdsa_signature_normalize(_cx: *const Context, _out_sig: *mut Signature, + _in_sig: *const Signature) + -> c_int { + unimplemented!(); + } + + // ECDSA + /// Verifies that sig is msg32||pk[0..32] + pub unsafe fn secp256k1_ecdsa_verify(cx: *const Context, + sig: *const Signature, + msg32: *const c_uchar, + pk: *const PublicKey) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + assert!((*cx).0 as u32 & SECP256K1_START_VERIFY == SECP256K1_START_VERIFY); + if test_pk_validate(cx, pk) != 1 { return 0; } + for i in 0..32 { + if (*sig).0[i] != *msg32.offset(i as isize) { + return 0; + } + } + if (*sig).0[32..64] != (*pk).0[0..32] { + 0 + } else { + 1 + } + } + + /// Sets sig to msg32||sk + pub unsafe fn secp256k1_ecdsa_sign(cx: *const Context, + sig: *mut Signature, + msg32: *const c_uchar, + sk: *const c_uchar, + _noncefn: NonceFn, + _noncedata: *const c_void) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + assert!((*cx).0 as u32 & SECP256K1_START_SIGN == SECP256K1_START_SIGN); + if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } + ptr::copy(msg32, (*sig).0[0..32].as_mut_ptr(), 32); + ptr::copy(sk, (*sig).0[32..64].as_mut_ptr(), 32); + 1 + } + + // EC + /// Checks that pk != 0xffff...ffff and pk[0..32] == pk[32..64] + pub unsafe fn test_pk_validate(cx: *const Context, + pk: *const PublicKey) -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if (*pk).0[0..32] != (*pk).0[32..64] || secp256k1_ec_seckey_verify(cx, (*pk).0[0..32].as_ptr()) == 0 { + 0 + } else { + 1 + } + } + + /// Checks that sk != 0xffff...ffff + pub unsafe fn secp256k1_ec_seckey_verify(cx: *const Context, + sk: *const c_uchar) -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + let mut res = 0; + for i in 0..32 { + if *sk.offset(i as isize) != 0xff { res = 1 }; + } + res + } + + /// Sets pk to sk||sk + pub unsafe fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey, + sk: *const c_uchar) -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } + ptr::copy(sk, (*pk).0[0..32].as_mut_ptr(), 32); + ptr::copy(sk, (*pk).0[32..64].as_mut_ptr(), 32); + 1 + } + +//TODO secp256k1_ec_privkey_export +//TODO secp256k1_ec_privkey_import + + /// Copies the first 16 bytes of tweak into the last 16 bytes of sk + pub unsafe fn secp256k1_ec_privkey_tweak_add(cx: *const Context, + sk: *mut c_uchar, + tweak: *const c_uchar) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } + ptr::copy(tweak.offset(16), sk.offset(16), 16); + *sk.offset(24) = 0x7f; // Ensure sk remains valid no matter what tweak was + 1 + } + + /// The PublicKey equivalent of secp256k1_ec_privkey_tweak_add + pub unsafe fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, + pk: *mut PublicKey, + tweak: *const c_uchar) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if test_pk_validate(cx, pk) != 1 { return 0; } + ptr::copy(tweak.offset(16), (*pk).0[16..32].as_mut_ptr(), 16); + ptr::copy(tweak.offset(16), (*pk).0[16+32..64].as_mut_ptr(), 16); + (*pk).0[24] = 0x7f; // Ensure pk remains valid no matter what tweak was + (*pk).0[24+32] = 0x7f; // Ensure pk remains valid no matter what tweak was + 1 + } + + /// Copies the last 16 bytes of tweak into the last 16 bytes of sk + pub unsafe fn secp256k1_ec_privkey_tweak_mul(cx: *const Context, + sk: *mut c_uchar, + tweak: *const c_uchar) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } + ptr::copy(tweak.offset(16), sk.offset(16), 16); + *sk.offset(24) = 0x00; // Ensure sk remains valid no matter what tweak was + 1 + } + + /// The PublicKey equivalent of secp256k1_ec_privkey_tweak_mul + pub unsafe fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, + pk: *mut PublicKey, + tweak: *const c_uchar) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if test_pk_validate(cx, pk) != 1 { return 0; } + ptr::copy(tweak.offset(16), (*pk).0[16..32].as_mut_ptr(), 16); + ptr::copy(tweak.offset(16), (*pk).0[16+32..64].as_mut_ptr(), 16); + (*pk).0[24] = 0x00; // Ensure pk remains valid no matter what tweak was + (*pk).0[24+32] = 0x00; // Ensure pk remains valid no matter what tweak was + 1 + } + + pub unsafe fn secp256k1_ec_pubkey_combine(cx: *const Context, + out: *mut PublicKey, + ins: *const *const PublicKey, + n: c_int) + -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + assert!(n <= 32 && n >= 0); //TODO: Remove this restriction? + for i in 0..n { + if test_pk_validate(cx, *ins.offset(i as isize)) != 1 { return 0; } + (*out).0[(i*32/n) as usize..((i+1)*32/n) as usize].copy_from_slice(&(**ins.offset(i as isize)).0[(i*32/n) as usize..((i+1)*32/n) as usize]); + } + ptr::copy((*out).0[0..32].as_ptr(), (*out).0[32..64].as_mut_ptr(), 32); + (*out).0[24] = 0x7f; // pk should always be valid + (*out).0[24+32] = 0x7f; // pk should always be valid + test_pk_validate(cx, out) + } + + /// Sets out to point[0..16]||scalar[0..16] + pub unsafe fn secp256k1_ecdh( + cx: *const Context, + out: *mut c_uchar, + point: *const PublicKey, + scalar: *const c_uchar, + _hashfp: EcdhHashFn, + _data: *mut c_void, + ) -> c_int { + assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + if secp256k1_ec_seckey_verify(cx, scalar) != 1 { return 0; } + + let mut scalar_prefix = [0; 16]; + ptr::copy(scalar, scalar_prefix[..].as_mut_ptr(), 16); + + if (*point).0[0..16] > scalar_prefix[0..16] { + ptr::copy((*point).as_ptr(), out, 16); + ptr::copy(scalar, out.offset(16), 16); + } else { + ptr::copy(scalar, out, 16); + ptr::copy((*point).as_ptr(), out.offset(16), 16); + } + (*out.offset(16)) = 0x00; // result should always be a valid secret key + 1 + } +} +#[cfg(feature = "fuzztarget")] +pub use self::fuzz_dummy::*; + + +#[cfg(test)] +mod tests { + use std::ffi::CString; + use super::strlen; + + #[test] + fn test_strlen() { + let orig = "test strlen \t \n"; + let test = CString::new(orig).unwrap(); + + assert_eq!(orig.len(), unsafe {strlen(test.as_ptr())}); + } +} + diff --git a/secp256k1-sys/src/macros.rs b/secp256k1-sys/src/macros.rs new file mode 100644 index 000000000..3263ff161 --- /dev/null +++ b/secp256k1-sys/src/macros.rs @@ -0,0 +1,159 @@ +// Bitcoin secp256k1 bindings +// Written in 2014 by +// Dawid Ciężarkiewicz +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +// This is a macro that routinely comes in handy +#[macro_export] +macro_rules! impl_array_newtype { + ($thing:ident, $ty:ty, $len:expr) => { + impl Copy for $thing {} + + impl $thing { + #[inline] + /// Converts the object to a raw pointer for FFI interfacing + pub fn as_ptr(&self) -> *const $ty { + let &$thing(ref dat) = self; + dat.as_ptr() + } + + #[inline] + /// Converts the object to a mutable raw pointer for FFI interfacing + pub fn as_mut_ptr(&mut self) -> *mut $ty { + let &mut $thing(ref mut dat) = self; + dat.as_mut_ptr() + } + + #[inline] + /// Returns the length of the object as an array + pub fn len(&self) -> usize { $len } + + #[inline] + /// Returns whether the object as an array is empty + pub fn is_empty(&self) -> bool { false } + } + + impl PartialEq for $thing { + #[inline] + fn eq(&self, other: &$thing) -> bool { + &self[..] == &other[..] + } + } + + impl Eq for $thing {} + + impl PartialOrd for $thing { + #[inline] + fn partial_cmp(&self, other: &$thing) -> Option<::core::cmp::Ordering> { + self[..].partial_cmp(&other[..]) + } + } + + impl Ord for $thing { + #[inline] + fn cmp(&self, other: &$thing) -> ::core::cmp::Ordering { + self[..].cmp(&other[..]) + } + } + + impl Clone for $thing { + #[inline] + fn clone(&self) -> $thing { + let &$thing(ref dat) = self; + $thing(dat.clone()) + } + } + + impl ::core::ops::Index for $thing { + type Output = $ty; + + #[inline] + fn index(&self, index: usize) -> &$ty { + let &$thing(ref dat) = self; + &dat[index] + } + } + + impl ::core::ops::Index<::core::ops::Range> for $thing { + type Output = [$ty]; + + #[inline] + fn index(&self, index: ::core::ops::Range) -> &[$ty] { + let &$thing(ref dat) = self; + &dat[index] + } + } + + impl ::core::ops::Index<::core::ops::RangeTo> for $thing { + type Output = [$ty]; + + #[inline] + fn index(&self, index: ::core::ops::RangeTo) -> &[$ty] { + let &$thing(ref dat) = self; + &dat[index] + } + } + + impl ::core::ops::Index<::core::ops::RangeFrom> for $thing { + type Output = [$ty]; + + #[inline] + fn index(&self, index: ::core::ops::RangeFrom) -> &[$ty] { + let &$thing(ref dat) = self; + &dat[index] + } + } + + impl ::core::ops::Index<::core::ops::RangeFull> for $thing { + type Output = [$ty]; + + #[inline] + fn index(&self, _: ::core::ops::RangeFull) -> &[$ty] { + let &$thing(ref dat) = self; + &dat[..] + } + } + impl ::CPtr for $thing { + type Target = $ty; + fn as_c_ptr(&self) -> *const Self::Target { + if self.is_empty() { + ::core::ptr::null() + } else { + self.as_ptr() + } + } + + fn as_mut_c_ptr(&mut self) -> *mut Self::Target { + if self.is_empty() { + ::core::ptr::null::() as *mut _ + } else { + self.as_mut_ptr() + } + } + } + } +} + +#[macro_export] +macro_rules! impl_raw_debug { + ($thing:ident) => { + impl ::core::fmt::Debug for $thing { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + for i in self[..].iter().cloned() { + write!(f, "{:02x}", i)?; + } + Ok(()) + } + } + } +} diff --git a/secp256k1-sys/src/recovery.rs b/secp256k1-sys/src/recovery.rs new file mode 100644 index 000000000..4e5d2b983 --- /dev/null +++ b/secp256k1-sys/src/recovery.rs @@ -0,0 +1,134 @@ +// Bitcoin secp256k1 bindings +// Written in 2014 by +// Dawid Ciężarkiewicz +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +//! # FFI of the recovery module + +use ::types::*; +#[cfg(not(feature = "fuzztarget"))] +use ::{Context, Signature, NonceFn, PublicKey}; + +/// Library-internal representation of a Secp256k1 signature + recovery ID +#[repr(C)] +pub struct RecoverableSignature([c_uchar; 65]); +impl_array_newtype!(RecoverableSignature, c_uchar, 65); +impl_raw_debug!(RecoverableSignature); + +impl RecoverableSignature { + /// Create a new (zeroed) signature usable for the FFI interface + pub fn new() -> RecoverableSignature { RecoverableSignature([0; 65]) } + /// Create a new (uninitialized) signature usable for the FFI interface + #[deprecated(since = "0.15.3", note = "Please use the new function instead")] + pub unsafe fn blank() -> RecoverableSignature { RecoverableSignature::new() } +} + +impl Default for RecoverableSignature { + fn default() -> Self { + RecoverableSignature::new() + } +} + +#[cfg(not(feature = "fuzztarget"))] +extern "C" { + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_parse_compact")] + pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature, + input64: *const c_uchar, recid: c_int) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_serialize_compact")] + pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *mut c_uchar, + recid: *mut c_int, sig: *const RecoverableSignature) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_recoverable_signature_convert")] + pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, sig: *mut Signature, + input: *const RecoverableSignature) + -> c_int; + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_sign_recoverable")] + pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, + sig: *mut RecoverableSignature, + msg32: *const c_uchar, + sk: *const c_uchar, + noncefn: NonceFn, + noncedata: *const c_void) + -> c_int; + + #[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_recover")] + pub fn secp256k1_ecdsa_recover(cx: *const Context, + pk: *mut PublicKey, + sig: *const RecoverableSignature, + msg32: *const c_uchar) + -> c_int; +} + + +#[cfg(feature = "fuzztarget")] +mod fuzz_dummy { + extern crate std; + use self::std::ptr; + use super::RecoverableSignature; + use types::*; + use ::{Signature, Context, PublicKey, NonceFn, secp256k1_ec_seckey_verify, + SECP256K1_START_NONE, SECP256K1_START_VERIFY, SECP256K1_START_SIGN}; + + pub unsafe fn secp256k1_ecdsa_recoverable_signature_parse_compact(_cx: *const Context, _sig: *mut RecoverableSignature, + _input64: *const c_uchar, _recid: c_int) + -> c_int { + unimplemented!(); + } + + pub unsafe fn secp256k1_ecdsa_recoverable_signature_serialize_compact(_cx: *const Context, _output64: *mut c_uchar, + _recid: *mut c_int, _sig: *const RecoverableSignature) + -> c_int { + unimplemented!(); + } + + pub unsafe fn secp256k1_ecdsa_recoverable_signature_convert(_cx: *const Context, _sig: *mut Signature, + _input: *const RecoverableSignature) + -> c_int { + unimplemented!(); + } + + /// Sets sig to (2|3)||msg32||sk + pub unsafe fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, + sig: *mut RecoverableSignature, + msg32: *const c_uchar, + sk: *const c_uchar, + _noncefn: NonceFn, + _noncedata: *const c_void) + -> c_int { + assert!(!cx.is_null() && (*cx).flags() & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0); + assert!((*cx).flags() & SECP256K1_START_SIGN == SECP256K1_START_SIGN); + if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; } + if *sk.offset(0) > 0x7f { + (*sig).0[0] = 2; + } else { + (*sig).0[0] = 3; + } + ptr::copy(msg32, (*sig).0[1..33].as_mut_ptr(), 32); + ptr::copy(sk, (*sig).0[33..65].as_mut_ptr(), 32); + 1 + } + + pub unsafe fn secp256k1_ecdsa_recover(_cx: *const Context, + _pk: *mut PublicKey, + _sig: *const RecoverableSignature, + _msg32: *const c_uchar) + -> c_int { + unimplemented!(); + } +} +#[cfg(feature = "fuzztarget")] +pub use self::fuzz_dummy::*; + diff --git a/secp256k1-sys/src/types.rs b/secp256k1-sys/src/types.rs new file mode 100644 index 000000000..8c9f3625b --- /dev/null +++ b/secp256k1-sys/src/types.rs @@ -0,0 +1,41 @@ +#![allow(non_camel_case_types)] +use core::fmt; + +pub type c_int = i32; +pub type c_uchar = u8; +pub type c_uint = u32; + +/// This might not match C's `c_char` exactly. +/// The way we use it makes it fine either way but this type shouldn't be used outside of the library. +pub type c_char = i8; + +/// This is an exact copy of https://doc.rust-lang.org/core/ffi/enum.c_void.html +/// It should be Equivalent to C's void type when used as a pointer. +/// +/// We can replace this with `core::ffi::c_void` once we update the rustc version to >=1.30.0. +#[repr(u8)] +pub enum c_void { + #[doc(hidden)] __variant1, + #[doc(hidden)] __variant2, +} + +impl fmt::Debug for c_void { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("c_void") + } +} + +#[cfg(test)] +mod tests { + use std::os::raw; + use std::any::TypeId; + use types; + + #[test] + fn verify_types() { + assert_eq!(TypeId::of::(), TypeId::of::()); + assert_eq!(TypeId::of::(), TypeId::of::()); + assert_eq!(TypeId::of::(), TypeId::of::()); + assert_eq!(TypeId::of::(), TypeId::of::()); + } +} diff --git a/secp256k1-sys/vendor-libsecp.sh b/secp256k1-sys/vendor-libsecp.sh new file mode 100755 index 000000000..094b08139 --- /dev/null +++ b/secp256k1-sys/vendor-libsecp.sh @@ -0,0 +1,73 @@ +#!/bin/bash +set -e + + +if [ -z "$1" ] | [ -z "$2" ]; then + echo "\$1 parameter must be the rust-secp256k1-sys depend directory" + echo "\$2 parameter must be the rust-secp256k1-sys version code (M_m_p format)" + echo "\$3 parameter (optional) can be the revision to check out" + exit 1 +fi + +PARENT_DIR=$1 +VERSIONCODE=$2 +REV=$3 +DIR=secp256k1 +ORIGDIR=$(pwd) + +while true; do + read -r -p "$PARENT_DIR/$DIR will be deleted [yn]: " yn + case $yn in + [Yy]* ) break;; + [Nn]* ) exit;; + * ) echo "Please answer yes or no.";; + esac +done + +cd "$PARENT_DIR" || exit 1 +rm -rf "$DIR" +git clone https://github.com/bitcoin-core/secp256k1.git "$DIR" +cd "$DIR" +if [ -n "$REV" ]; then + git checkout "$REV" +fi +HEAD=$(git rev-parse HEAD) +cd .. +echo "# This file was automatically created by $0" > ./secp256k1-HEAD-revision.txt +echo "$HEAD" >> ./secp256k1-HEAD-revision.txt + +# We need to make some source changes to the files. + +# To support compiling for WASM, we need to remove all methods that use malloc. +# To compensate, the secp_context_create and _destroy methods are redefined in Rust. +patch "$DIR/include/secp256k1.h" "./secp256k1.h.patch" +patch "$DIR/src/secp256k1.c" "./secp256k1.c.patch" +patch "$DIR/src/scratch_impl.h" "./scratch_impl.h.patch" +patch "$DIR/src/util.h" "./util.h.patch" + +# Prefix all methods with rustsecp and a version prefix +find "$DIR" -not -path '*/\.*' -type f -print0 | xargs -0 sed -i "/^#include/! s/secp256k1_/rustsecp256k1_v${VERSIONCODE}_/g" + +# special rule for a method that is not prefixed in libsecp +find "$DIR" -not -path '*/\.*' -type f -print0 | xargs -0 sed -i "/^#include/! s/ecdsa_signature_parse_der_lax/rustsecp256k1_v${VERSIONCODE}_ecdsa_signature_parse_der_lax/g" + +# TODO: can be removed once 496c5b43b lands in secp-zkp +find "$DIR" -not -path '*/\.*' -type f -print0 | xargs -0 sed -i 's/^const int CURVE_B/static const int CURVE_B/g' + +while true; do + read -r -p "Update Rust extern references and Cargo.toml as well? [yn]: " yn + case $yn in + [Yy]* ) break;; + [Nn]* ) exit;; + * ) echo "Please answer yes or no.";; + esac +done + +cd "$ORIGDIR" + +# Update the `links = ` in the manifest file. +sed -i -r "s/^links = \".*\"$/links = \"rustsecp256k1_v${VERSIONCODE}\"/" Cargo.toml + +# Update the extern references in the Rust FFI source files. +find "./src/" -name "*.rs" -type f -print0 | xargs -0 sed -i -r "s/rustsecp256k1_v[0-9]+_[0-9]+_[0-9]+_(.*)([\"\(])/rustsecp256k1_v${VERSIONCODE}_\1\2/g" + diff --git a/src/constants.rs b/src/constants.rs index 9a219ee7e..0a4db4903 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -22,22 +22,15 @@ pub const MESSAGE_SIZE: usize = 32; /// The size (in bytes) of a secret key pub const SECRET_KEY_SIZE: usize = 32; -/// The size (in bytes) of a public key array. This only needs to be 65 -/// but must be 72 for compatibility with the `ArrayVec` library. -pub const PUBLIC_KEY_SIZE: usize = 72; +/// The size (in bytes) of a serialized public key. +pub const PUBLIC_KEY_SIZE: usize = 33; -/// The size (in bytes) of an uncompressed public key +/// The size (in bytes) of an serialized uncompressed public key pub const UNCOMPRESSED_PUBLIC_KEY_SIZE: usize = 65; -/// The size (in bytes) of a compressed public key -pub const COMPRESSED_PUBLIC_KEY_SIZE: usize = 33; - /// The maximum size of a signature pub const MAX_SIGNATURE_SIZE: usize = 72; -/// The size of a Schnorr signature -pub const SCHNORR_SIGNATURE_SIZE: usize = 64; - /// The maximum size of a compact signature pub const COMPACT_SIGNATURE_SIZE: usize = 64; diff --git a/src/context.rs b/src/context.rs new file mode 100644 index 000000000..a3d8fe875 --- /dev/null +++ b/src/context.rs @@ -0,0 +1,302 @@ +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use ptr; +use ffi::{self, CPtr}; +use ffi::types::{c_uint, c_void}; +use Error; +use Secp256k1; + +#[cfg(feature = "std")] +pub use self::std_only::*; + +/// A trait for all kinds of Context's that Lets you define the exact flags and a function to deallocate memory. +/// It shouldn't be possible to implement this for types outside this crate. +pub unsafe trait Context : private::Sealed { + /// Flags for the ffi. + const FLAGS: c_uint; + /// A constant description of the context. + const DESCRIPTION: &'static str; + /// A function to deallocate the memory when the context is dropped. + unsafe fn deallocate(ptr: *mut [u8]); +} + +/// Marker trait for indicating that an instance of `Secp256k1` can be used for signing. +pub trait Signing: Context {} + +/// Marker trait for indicating that an instance of `Secp256k1` can be used for verification. +pub trait Verification: Context {} + +/// Represents the set of capabilities needed for signing with a user preallocated memory. +pub struct SignOnlyPreallocated<'buf> { + phantom: PhantomData<&'buf ()>, +} + +/// Represents the set of capabilities needed for verification with a user preallocated memory. +pub struct VerifyOnlyPreallocated<'buf> { + phantom: PhantomData<&'buf ()>, +} + +/// Represents the set of all capabilities with a user preallocated memory. +pub struct AllPreallocated<'buf> { + phantom: PhantomData<&'buf ()>, +} + +mod private { + use super::*; + // A trick to prevent users from implementing a trait. + // on one hand this trait is public, on the other it's in a private module + // so it's not visible to anyone besides it's parent (the context module) + pub trait Sealed {} + + impl<'buf> Sealed for AllPreallocated<'buf> {} + impl<'buf> Sealed for VerifyOnlyPreallocated<'buf> {} + impl<'buf> Sealed for SignOnlyPreallocated<'buf> {} +} + +#[cfg(feature = "std")] +mod std_only { + impl private::Sealed for SignOnly {} + impl private::Sealed for All {} + impl private::Sealed for VerifyOnly {} + + use super::*; + + /// Represents the set of capabilities needed for signing. + pub enum SignOnly {} + + /// Represents the set of capabilities needed for verification. + pub enum VerifyOnly {} + + /// Represents the set of all capabilities. + pub enum All {} + + impl Signing for SignOnly {} + impl Signing for All {} + + impl Verification for VerifyOnly {} + impl Verification for All {} + + unsafe impl Context for SignOnly { + const FLAGS: c_uint = ffi::SECP256K1_START_SIGN; + const DESCRIPTION: &'static str = "signing only"; + + unsafe fn deallocate(ptr: *mut [u8]) { + let _ = Box::from_raw(ptr); + } + } + + unsafe impl Context for VerifyOnly { + const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY; + const DESCRIPTION: &'static str = "verification only"; + + unsafe fn deallocate(ptr: *mut [u8]) { + let _ = Box::from_raw(ptr); + } + } + + unsafe impl Context for All { + const FLAGS: c_uint = VerifyOnly::FLAGS | SignOnly::FLAGS; + const DESCRIPTION: &'static str = "all capabilities"; + + unsafe fn deallocate(ptr: *mut [u8]) { + let _ = Box::from_raw(ptr); + } + } + + impl Secp256k1 { + /// Lets you create a context in a generic manner(sign/verify/all) + pub fn gen_new() -> Secp256k1 { + let buf = vec![0u8; Self::preallocate_size_gen()].into_boxed_slice(); + let ptr = Box::into_raw(buf); + Secp256k1 { + ctx: unsafe { ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS) }, + phantom: PhantomData, + buf: ptr, + } + } + } + + impl Secp256k1 { + /// Creates a new Secp256k1 context with all capabilities + pub fn new() -> Secp256k1 { + Secp256k1::gen_new() + } + } + + impl Secp256k1 { + /// Creates a new Secp256k1 context that can only be used for signing + pub fn signing_only() -> Secp256k1 { + Secp256k1::gen_new() + } + } + + impl Secp256k1 { + /// Creates a new Secp256k1 context that can only be used for verification + pub fn verification_only() -> Secp256k1 { + Secp256k1::gen_new() + } + } + + impl Default for Secp256k1 { + fn default() -> Self { + Self::new() + } + } + + impl Clone for Secp256k1 { + fn clone(&self) -> Secp256k1 { + let clone_size = unsafe {ffi::secp256k1_context_preallocated_clone_size(self.ctx)}; + let ptr_buf = Box::into_raw(vec![0u8; clone_size].into_boxed_slice()); + Secp256k1 { + ctx: unsafe { ffi::secp256k1_context_preallocated_clone(self.ctx, ptr_buf as *mut c_void) }, + phantom: PhantomData, + buf: ptr_buf, + } + } + } +} + +impl<'buf> Signing for SignOnlyPreallocated<'buf> {} +impl<'buf> Signing for AllPreallocated<'buf> {} + +impl<'buf> Verification for VerifyOnlyPreallocated<'buf> {} +impl<'buf> Verification for AllPreallocated<'buf> {} + +unsafe impl<'buf> Context for SignOnlyPreallocated<'buf> { + const FLAGS: c_uint = ffi::SECP256K1_START_SIGN; + const DESCRIPTION: &'static str = "signing only"; + + unsafe fn deallocate(_ptr: *mut [u8]) { + // Allocated by the user + } +} + +unsafe impl<'buf> Context for VerifyOnlyPreallocated<'buf> { + const FLAGS: c_uint = ffi::SECP256K1_START_VERIFY; + const DESCRIPTION: &'static str = "verification only"; + + unsafe fn deallocate(_ptr: *mut [u8]) { + // Allocated by the user + } +} + +unsafe impl<'buf> Context for AllPreallocated<'buf> { + const FLAGS: c_uint = SignOnlyPreallocated::FLAGS | VerifyOnlyPreallocated::FLAGS; + const DESCRIPTION: &'static str = "all capabilities"; + + unsafe fn deallocate(_ptr: *mut [u8]) { + // Allocated by the user + } +} + +impl<'buf, C: Context + 'buf> Secp256k1 { + /// Lets you create a context with preallocated buffer in a generic manner(sign/verify/all) + pub fn preallocated_gen_new(buf: &'buf mut [u8]) -> Result, Error> { + if buf.len() < Self::preallocate_size_gen() { + return Err(Error::NotEnoughMemory); + } + Ok(Secp256k1 { + ctx: unsafe { + ffi::secp256k1_context_preallocated_create( + buf.as_mut_c_ptr() as *mut c_void, + C::FLAGS) + }, + phantom: PhantomData, + buf: buf as *mut [u8], + }) + } +} + +impl<'buf> Secp256k1> { + /// Creates a new Secp256k1 context with all capabilities + pub fn preallocated_new(buf: &'buf mut [u8]) -> Result>, Error> { + Secp256k1::preallocated_gen_new(buf) + } + /// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context + pub fn preallocate_size() -> usize { + Self::preallocate_size_gen() + } + + /// Create a context from a raw context. + /// + /// # Safety + /// This is highly unsafe, due to the number of conditions that aren't checked. + /// * `raw_ctx` needs to be a valid Secp256k1 context pointer. + /// that was generated by *exactly* the same code/version of the libsecp256k1 used here. + /// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1 + /// when generating the context. + /// * The user must handle the freeing of the context(using the correct functions) by himself. + /// * Violating these may lead to Undefined Behavior. + /// + pub unsafe fn from_raw_all(raw_ctx: *mut ffi::Context) -> ManuallyDrop>> { + ManuallyDrop::new(Secp256k1 { + ctx: raw_ctx, + phantom: PhantomData, + buf: ptr::null_mut::<[u8;0]>() as *mut [u8] , + }) + } +} + +impl<'buf> Secp256k1> { + /// Creates a new Secp256k1 context that can only be used for signing + pub fn preallocated_signing_only(buf: &'buf mut [u8]) -> Result>, Error> { + Secp256k1::preallocated_gen_new(buf) + } + + /// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context + #[inline] + pub fn preallocate_signing_size() -> usize { + Self::preallocate_size_gen() + } + + /// Create a context from a raw context. + /// + /// # Safety + /// This is highly unsafe, due to the number of conditions that aren't checked. + /// * `raw_ctx` needs to be a valid Secp256k1 context pointer. + /// that was generated by *exactly* the same code/version of the libsecp256k1 used here. + /// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1 + /// when generating the context. + /// * The user must handle the freeing of the context(using the correct functions) by himself. + /// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior., + /// + pub unsafe fn from_raw_signining_only(raw_ctx: *mut ffi::Context) -> ManuallyDrop>> { + ManuallyDrop::new(Secp256k1 { + ctx: raw_ctx, + phantom: PhantomData, + buf: ptr::null_mut::<[u8;0]>() as *mut [u8] , + }) + } +} + +impl<'buf> Secp256k1> { + /// Creates a new Secp256k1 context that can only be used for verification + pub fn preallocated_verification_only(buf: &'buf mut [u8]) -> Result>, Error> { + Secp256k1::preallocated_gen_new(buf) + } + + /// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context + #[inline] + pub fn preallocate_verification_size() -> usize { + Self::preallocate_size_gen() + } + + /// Create a context from a raw context. + /// + /// # Safety + /// This is highly unsafe, due to the number of conditions that aren't checked. + /// * `raw_ctx` needs to be a valid Secp256k1 context pointer. + /// that was generated by *exactly* the same code/version of the libsecp256k1 used here. + /// * The capabilities (All/SignOnly/VerifyOnly) of the context *must* match the flags passed to libsecp256k1 + /// when generating the context. + /// * The user must handle the freeing of the context(using the correct functions) by himself. + /// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior., + /// + pub unsafe fn from_raw_verification_only(raw_ctx: *mut ffi::Context) -> ManuallyDrop>> { + ManuallyDrop::new(Secp256k1 { + ctx: raw_ctx, + phantom: PhantomData, + buf: ptr::null_mut::<[u8;0]>() as *mut [u8] , + }) + } +} \ No newline at end of file diff --git a/src/ecdh.rs b/src/ecdh.rs index 3b116c90a..166907bdf 100644 --- a/src/ecdh.rs +++ b/src/ecdh.rs @@ -16,77 +16,209 @@ //! Support for shared secret computations //! -use std::ops; +use core::ptr; +use core::ops::{FnMut, Deref}; -use super::Secp256k1; use key::{SecretKey, PublicKey}; -use ffi; +use ffi::{self, CPtr}; +use secp256k1_sys::types::{c_int, c_uchar, c_void}; +use Error; /// A tag used for recovering the public key from a compact signature -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct SharedSecret(ffi::SharedSecret); +#[derive(Copy, Clone)] +pub struct SharedSecret { + data: [u8; 256], + len: usize, +} +impl_raw_debug!(SharedSecret); + + +// This implementes `From` for all `[u8; N]` arrays from 128bits(16 byte) to 2048bits allowing known hash lengths. +// Lower than 128 bits isn't resistant to collisions any more. +impl_from_array_len!(SharedSecret, 256, (16 20 28 32 48 64 96 128 256)); impl SharedSecret { - /// Creates a new shared secret from a pubkey and secret key - #[inline] - pub fn new(secp: &Secp256k1, point: &PublicKey, scalar: &SecretKey) -> SharedSecret { - unsafe { - let mut ss = ffi::SharedSecret::blank(); - let res = ffi::secp256k1_ecdh(secp.ctx, &mut ss, point.as_ptr(), scalar.as_ptr()); - debug_assert_eq!(res, 1); - SharedSecret(ss) + + /// Create an empty SharedSecret + pub(crate) fn empty() -> SharedSecret { + SharedSecret { + data: [0u8; 256], + len: 0, } } - /// Obtains a raw pointer suitable for use with FFI functions - #[inline] - pub fn as_ptr(&self) -> *const ffi::SharedSecret { - &self.0 as *const _ + /// Get a pointer to the underlying data with the specified capacity. + pub(crate) fn get_data_mut_ptr(&mut self) -> *mut u8 { + self.data.as_mut_ptr() } -} -/// Creates a new shared secret from a FFI shared secret -impl From for SharedSecret { - #[inline] - fn from(ss: ffi::SharedSecret) -> SharedSecret { - SharedSecret(ss) + /// Get the capacity of the underlying data buffer. + pub fn capacity(&self) -> usize { + self.data.len() } -} + /// Get the len of the used data. + pub fn len(&self) -> usize { + self.len + } -impl ops::Index for SharedSecret { - type Output = u8; + /// Set the length of the object. + pub(crate) fn set_len(&mut self, len: usize) { + debug_assert!(len <= self.data.len()); + self.len = len; + } +} - #[inline] - fn index(&self, index: usize) -> &u8 { - &self.0[index] +impl PartialEq for SharedSecret { + fn eq(&self, other: &SharedSecret) -> bool { + self.as_ref() == other.as_ref() } } -impl ops::Index> for SharedSecret { - type Output = [u8]; +impl AsRef<[u8]> for SharedSecret { + fn as_ref(&self) -> &[u8] { + &self.data[..self.len] + } +} - #[inline] - fn index(&self, index: ops::Range) -> &[u8] { - &self.0[index] +impl Deref for SharedSecret { + type Target = [u8]; + fn deref(&self) -> &[u8] { + &self.data[..self.len] } } -impl ops::Index> for SharedSecret { - type Output = [u8]; - #[inline] - fn index(&self, index: ops::RangeFrom) -> &[u8] { - &self.0[index.start..] +unsafe fn callback_logic(output: *mut c_uchar, x: *const c_uchar, y: *const c_uchar, data: *mut c_void) -> c_int + where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret { + let callback: &mut F = &mut *(data as *mut F); + + let mut x_arr = [0; 32]; + let mut y_arr = [0; 32]; + ptr::copy_nonoverlapping(x, x_arr.as_mut_ptr(), 32); + ptr::copy_nonoverlapping(y, y_arr.as_mut_ptr(), 32); + + let secret = callback(x_arr, y_arr); + ptr::copy_nonoverlapping(secret.as_ptr(), output as *mut u8, secret.len()); + + secret.len() as c_int +} + +#[cfg(feature = "std")] +unsafe extern "C" fn hash_callback_catch_unwind(output: *mut c_uchar, x: *const c_uchar, y: *const c_uchar, data: *mut c_void) -> c_int + where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret { + + let res = ::std::panic::catch_unwind(||callback_logic::(output, x, y, data)); + if let Ok(len) = res { + len + } else { + -1 } } -impl ops::Index for SharedSecret { - type Output = [u8]; +unsafe extern "C" fn hash_callback_unsafe(output: *mut c_uchar, x: *const c_uchar, y: *const c_uchar, data: *mut c_void) -> c_int + where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret { + callback_logic::(output, x, y, data) +} + +impl SharedSecret { + /// Creates a new shared secret from a pubkey and secret key #[inline] - fn index(&self, _: ops::RangeFull) -> &[u8] { - &self.0[..] + pub fn new(point: &PublicKey, scalar: &SecretKey) -> SharedSecret { + let mut ss = SharedSecret::empty(); + let res = unsafe { + ffi::secp256k1_ecdh( + ffi::secp256k1_context_no_precomp, + ss.get_data_mut_ptr(), + point.as_c_ptr(), + scalar.as_c_ptr(), + ffi::secp256k1_ecdh_hash_function_default, + ptr::null_mut(), + ) + }; + debug_assert_eq!(res, 1); // The default `secp256k1_ecdh_hash_function_default` should always return 1. + ss.set_len(32); // The default hash function is SHA256, which is 32 bytes long. + ss + } + + fn new_with_callback_internal(point: &PublicKey, scalar: &SecretKey, mut closure: F, callback: ffi::EcdhHashFn) -> Result + where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret { + let mut ss = SharedSecret::empty(); + + let res = unsafe { + ffi::secp256k1_ecdh( + ffi::secp256k1_context_no_precomp, + ss.get_data_mut_ptr(), + point.as_ptr(), + scalar.as_ptr(), + callback, + &mut closure as *mut F as *mut c_void, + ) + }; + if res == -1 { + return Err(Error::CallbackPanicked); + } + debug_assert!(res >= 16); // 128 bit is the minimum for a secure hash function and the minimum we let users. + ss.set_len(res as usize); + Ok(ss) + + } + + /// Creates a new shared secret from a pubkey and secret key with applied custom hash function + /// # Examples + /// ``` + /// # use secp256k1::ecdh::SharedSecret; + /// # use secp256k1::{Secp256k1, PublicKey, SecretKey}; + /// # fn sha2(_a: &[u8], _b: &[u8]) -> [u8; 32] {[0u8; 32]} + /// # let secp = Secp256k1::signing_only(); + /// # let secret_key = SecretKey::from_slice(&[3u8; 32]).unwrap(); + /// # let secret_key2 = SecretKey::from_slice(&[7u8; 32]).unwrap(); + /// # let public_key = PublicKey::from_secret_key(&secp, &secret_key2); + /// + /// let secret = SharedSecret::new_with_hash(&public_key, &secret_key, |x,y| { + /// let hash: [u8; 32] = sha2(&x,&y); + /// hash.into() + /// }); + /// + /// ``` + #[cfg(feature = "std")] + pub fn new_with_hash(point: &PublicKey, scalar: &SecretKey, hash_function: F) -> Result + where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret { + Self::new_with_callback_internal(point, scalar, hash_function, hash_callback_catch_unwind::) + } + + /// Creates a new shared secret from a pubkey and secret key with applied custom hash function + /// Note that this function is the same as [`new_with_hash`] + /// + /// # Safety + /// The function doesn't wrap the callback with [`catch_unwind`] + /// so if the callback panics it will panic through an FFI boundray which is [`Undefined Behavior`] + /// If possible you should use [`new_with_hash`] which does wrap the callback with [`catch_unwind`] so is safe to use. + /// + /// [`catch_unwind`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html + /// [`Undefined Behavior`]: https://doc.rust-lang.org/nomicon/ffi.html#ffi-and-panics + /// [`new_with_hash`]: #method.new_with_hash + /// # Examples + /// ``` + /// # use secp256k1::ecdh::SharedSecret; + /// # use secp256k1::{Secp256k1, PublicKey, SecretKey}; + /// # fn sha2(_a: &[u8], _b: &[u8]) -> [u8; 32] {[0u8; 32]} + /// # let secp = Secp256k1::signing_only(); + /// # let secret_key = SecretKey::from_slice(&[3u8; 32]).unwrap(); + /// # let secret_key2 = SecretKey::from_slice(&[7u8; 32]).unwrap(); + /// # let public_key = PublicKey::from_secret_key(&secp, &secret_key2); + // + /// let secret = unsafe { SharedSecret::new_with_hash_no_panic(&public_key, &secret_key, |x,y| { + /// let hash: [u8; 32] = sha2(&x,&y); + /// hash.into() + /// })}; + /// + /// + /// ``` + pub unsafe fn new_with_hash_no_panic(point: &PublicKey, scalar: &SecretKey, hash_function: F) -> Result + where F: FnMut([u8; 32], [u8; 32]) -> SharedSecret { + Self::new_with_callback_internal(point, scalar, hash_function, hash_callback_unsafe::) } } @@ -95,19 +227,68 @@ mod tests { use rand::thread_rng; use super::SharedSecret; use super::super::Secp256k1; + use Error; #[test] fn ecdh() { - let s = Secp256k1::with_caps(::ContextFlag::SignOnly); - let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); - let (sk2, pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); + let s = Secp256k1::signing_only(); + let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); + let (sk2, pk2) = s.generate_keypair(&mut thread_rng()); - let sec1 = SharedSecret::new(&s, &pk1, &sk2); - let sec2 = SharedSecret::new(&s, &pk2, &sk1); - let sec_odd = SharedSecret::new(&s, &pk1, &sk1); + let sec1 = SharedSecret::new(&pk1, &sk2); + let sec2 = SharedSecret::new(&pk2, &sk1); + let sec_odd = SharedSecret::new(&pk1, &sk1); assert_eq!(sec1, sec2); assert!(sec_odd != sec2); } + + #[test] + fn ecdh_with_hash() { + let s = Secp256k1::signing_only(); + let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); + let (sk2, pk2) = s.generate_keypair(&mut thread_rng()); + + let sec1 = SharedSecret::new_with_hash(&pk1, &sk2, |x,_| x.into()).unwrap(); + let sec2 = SharedSecret::new_with_hash(&pk2, &sk1, |x,_| x.into()).unwrap(); + let sec_odd = SharedSecret::new_with_hash(&pk1, &sk1, |x,_| x.into()).unwrap(); + assert_eq!(sec1, sec2); + assert_ne!(sec_odd, sec2); + } + + #[test] + fn ecdh_with_hash_callback() { + let s = Secp256k1::signing_only(); + let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); + let expect_result: [u8; 64] = [123; 64]; + let mut x_out = [0u8; 32]; + let mut y_out = [0u8; 32]; + let result = SharedSecret::new_with_hash(&pk1, &sk1, | x, y | { + x_out = x; + y_out = y; + expect_result.into() + }).unwrap(); + let result_unsafe = unsafe {SharedSecret::new_with_hash_no_panic(&pk1, &sk1, | x, y | { + x_out = x; + y_out = y; + expect_result.into() + }).unwrap()}; + assert_eq!(&expect_result[..], &result[..]); + assert_eq!(result, result_unsafe); + assert_ne!(x_out, [0u8; 32]); + assert_ne!(y_out, [0u8; 32]); + } + + #[test] + fn ecdh_with_hash_callback_panic() { + let s = Secp256k1::signing_only(); + let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); + let mut res = [0u8; 48]; + let result = SharedSecret::new_with_hash(&pk1, &sk1, | x, _ | { + res.copy_from_slice(&x); // res.len() != x.len(). this will panic. + res.into() + }); + assert_eq!(result, Err(Error::CallbackPanicked)); + } } #[cfg(all(test, feature = "unstable"))] @@ -120,12 +301,12 @@ mod benches { #[bench] pub fn bench_ecdh(bh: &mut Bencher) { - let s = Secp256k1::with_caps(::ContextFlag::SignOnly); - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + let s = Secp256k1::signing_only(); + let (sk, pk) = s.generate_keypair(&mut thread_rng()); let s = Secp256k1::new(); bh.iter( || { - let res = SharedSecret::new(&s, &pk, &sk); + let res = SharedSecret::new(&pk, &sk); black_box(res); }); } diff --git a/src/ffi.rs b/src/ffi.rs deleted file mode 100644 index 80bd74127..000000000 --- a/src/ffi.rs +++ /dev/null @@ -1,269 +0,0 @@ -// Bitcoin secp256k1 bindings -// Written in 2014 by -// Dawid Ciężarkiewicz -// Andrew Poelstra -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. -// If not, see . -// - -//! # FFI bindings -//! Direct bindings to the underlying C library functions. These should -//! not be needed for most users. -use std::mem; -use std::hash; - -use libc::{c_int, c_uchar, c_uint, c_void, size_t}; - -/// Flag for context to enable no precomputation -pub const SECP256K1_START_NONE: c_uint = (1 << 0) | 0; -/// Flag for context to enable verification precomputation -pub const SECP256K1_START_VERIFY: c_uint = (1 << 0) | (1 << 8); -/// Flag for context to enable signing precomputation -pub const SECP256K1_START_SIGN: c_uint = (1 << 0) | (1 << 9); -/// Flag for keys to indicate uncompressed serialization format -pub const SECP256K1_SER_UNCOMPRESSED: c_uint = (1 << 1) | 0; -/// Flag for keys to indicate compressed serialization format -pub const SECP256K1_SER_COMPRESSED: c_uint = (1 << 1) | (1 << 8); - -/// A nonce generation function. Ordinary users of the library -/// never need to see this type; only if you need to control -/// nonce generation do you need to use it. I have deliberately -/// made this hard to do: you have to write your own wrapper -/// around the FFI functions to use it. And it's an unsafe type. -/// Nonces are generated deterministically by RFC6979 by -/// default; there should be no need to ever change this. -pub type NonceFn = unsafe extern "C" fn(nonce32: *mut c_uchar, - msg32: *const c_uchar, - key32: *const c_uchar, - algo16: *const c_uchar, - attempt: c_uint, - data: *const c_void); - - -/// A Secp256k1 context, containing various precomputed values and such -/// needed to do elliptic curve computations. If you create one of these -/// with `secp256k1_context_create` you MUST destroy it with -/// `secp256k1_context_destroy`, or else you will have a memory leak. -#[derive(Clone, Debug)] -#[repr(C)] pub struct Context(c_int); - -/// Library-internal representation of a Secp256k1 public key -#[repr(C)] -pub struct PublicKey([c_uchar; 64]); -impl_array_newtype!(PublicKey, c_uchar, 64); -impl_raw_debug!(PublicKey); - -impl PublicKey { - /// Create a new (zeroed) public key usable for the FFI interface - pub fn new() -> PublicKey { PublicKey([0; 64]) } - /// Create a new (uninitialized) public key usable for the FFI interface - pub unsafe fn blank() -> PublicKey { mem::uninitialized() } -} - -impl hash::Hash for PublicKey { - fn hash(&self, state: &mut H) { - state.write(&self.0) - } -} - -/// Library-internal representation of a Secp256k1 signature -#[repr(C)] -pub struct Signature([c_uchar; 64]); -impl_array_newtype!(Signature, c_uchar, 64); -impl_raw_debug!(Signature); - -/// Library-internal representation of a Secp256k1 signature + recovery ID -#[repr(C)] -pub struct RecoverableSignature([c_uchar; 65]); -impl_array_newtype!(RecoverableSignature, c_uchar, 65); -impl_raw_debug!(RecoverableSignature); - -impl Signature { - /// Create a new (zeroed) signature usable for the FFI interface - pub fn new() -> Signature { Signature([0; 64]) } - /// Create a new (uninitialized) signature usable for the FFI interface - pub unsafe fn blank() -> Signature { mem::uninitialized() } -} - -impl RecoverableSignature { - /// Create a new (zeroed) signature usable for the FFI interface - pub fn new() -> RecoverableSignature { RecoverableSignature([0; 65]) } - /// Create a new (uninitialized) signature usable for the FFI interface - pub unsafe fn blank() -> RecoverableSignature { mem::uninitialized() } -} - -/// Library-internal representation of an ECDH shared secret -#[repr(C)] -pub struct SharedSecret([c_uchar; 32]); -impl_array_newtype!(SharedSecret, c_uchar, 32); -impl_raw_debug!(SharedSecret); - -impl SharedSecret { - /// Create a new (zeroed) signature usable for the FFI interface - pub fn new() -> SharedSecret { SharedSecret([0; 32]) } - /// Create a new (uninitialized) signature usable for the FFI interface - pub unsafe fn blank() -> SharedSecret { mem::uninitialized() } -} - -extern "C" { - pub static secp256k1_nonce_function_rfc6979: NonceFn; - - pub static secp256k1_nonce_function_default: NonceFn; - - // Contexts - pub fn secp256k1_context_create(flags: c_uint) -> *mut Context; - - pub fn secp256k1_context_clone(cx: *mut Context) -> *mut Context; - - pub fn secp256k1_context_destroy(cx: *mut Context); - - pub fn secp256k1_context_randomize(cx: *mut Context, - seed32: *const c_uchar) - -> c_int; - - // TODO secp256k1_context_set_illegal_callback - // TODO secp256k1_context_set_error_callback - // (Actually, I don't really want these exposed; if either of these - // are ever triggered it indicates a bug in rust-secp256k1, since - // one goal is to use Rust's type system to eliminate all possible - // bad inputs.) - - // Pubkeys - pub fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey, - input: *const c_uchar, in_len: size_t) - -> c_int; - - pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *const c_uchar, - out_len: *mut size_t, pk: *const PublicKey -, compressed: c_uint) - -> c_int; - - // Signatures - pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context, sig: *mut Signature, - input: *const c_uchar, in_len: size_t) - -> c_int; - - pub fn ecdsa_signature_parse_der_lax(cx: *const Context, sig: *mut Signature, - input: *const c_uchar, in_len: size_t) - -> c_int; - - pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *const c_uchar, - out_len: *mut size_t, sig: *const Signature) - -> c_int; - - pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature, - input64: *const c_uchar, recid: c_int) - -> c_int; - - pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *const c_uchar, - recid: *mut c_int, sig: *const RecoverableSignature) - -> c_int; - - pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, sig: *mut Signature, - input: *const RecoverableSignature) - -> c_int; - - pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context, out_sig: *mut Signature, - in_sig: *const Signature) - -> c_int; - - // ECDSA - pub fn secp256k1_ecdsa_verify(cx: *const Context, - sig: *const Signature, - msg32: *const c_uchar, - pk: *const PublicKey) - -> c_int; - - pub fn secp256k1_ecdsa_sign(cx: *const Context, - sig: *mut Signature, - msg32: *const c_uchar, - sk: *const c_uchar, - noncefn: NonceFn, - noncedata: *const c_void) - -> c_int; - - pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, - sig: *mut RecoverableSignature, - msg32: *const c_uchar, - sk: *const c_uchar, - noncefn: NonceFn, - noncedata: *const c_void) - -> c_int; - - pub fn secp256k1_ecdsa_recover(cx: *const Context, - pk: *mut PublicKey, - sig: *const RecoverableSignature, - msg32: *const c_uchar) - -> c_int; - - // Schnorr - pub fn secp256k1_schnorr_sign(cx: *const Context, - sig64: *mut c_uchar, - msg32: *const c_uchar, - sk: *const c_uchar, - noncefn: NonceFn, - noncedata: *const c_void) - -> c_int; - - pub fn secp256k1_schnorr_verify(cx: *const Context, - sig64: *const c_uchar, - msg32: *const c_uchar, - pk: *const PublicKey) - -> c_int; - - pub fn secp256k1_schnorr_recover(cx: *const Context, - pk: *mut PublicKey, - sig64: *const c_uchar, - msg32: *const c_uchar) - -> c_int; - - // EC - pub fn secp256k1_ec_seckey_verify(cx: *const Context, - sk: *const c_uchar) -> c_int; - - pub fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey, - sk: *const c_uchar) -> c_int; - -//TODO secp256k1_ec_privkey_export -//TODO secp256k1_ec_privkey_import - - pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context, - sk: *mut c_uchar, - tweak: *const c_uchar) - -> c_int; - - pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, - pk: *mut PublicKey, - tweak: *const c_uchar) - -> c_int; - - pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context, - sk: *mut c_uchar, - tweak: *const c_uchar) - -> c_int; - - pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, - pk: *mut PublicKey, - tweak: *const c_uchar) - -> c_int; - - pub fn secp256k1_ec_pubkey_combine(cx: *const Context, - out: *mut PublicKey, - ins: *const *const PublicKey, - n: c_int) - -> c_int; - - pub fn secp256k1_ecdh(cx: *const Context, - out: *mut SharedSecret, - point: *const PublicKey, - scalar: *const c_uchar) - -> c_int; -} - diff --git a/src/key.rs b/src/key.rs index 6b2063454..3effc20b3 100644 --- a/src/key.rs +++ b/src/key.rs @@ -15,47 +15,111 @@ //! # Public and secret keys -use std::intrinsics::copy_nonoverlapping; -use std::marker; -use arrayvec::ArrayVec; -use rand::Rng; -use serialize::{Decoder, Decodable, Encoder, Encodable}; -use serde::{Serialize, Deserialize, Serializer, Deserializer}; - -use super::{Secp256k1, ContextFlag}; -use super::Error::{self, IncapableContext, InvalidPublicKey, InvalidSecretKey}; +#[cfg(any(test, feature = "rand"))] use rand::Rng; + +use core::{fmt, str}; + +use super::{from_hex, Secp256k1}; +use super::Error::{self, InvalidPublicKey, InvalidSecretKey}; +use Signing; +use Verification; use constants; -use ffi; +use ffi::{self, CPtr}; /// Secret 256-bit key used as `x` in an ECDSA signature pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]); impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE); impl_pretty_debug!(SecretKey); +impl fmt::LowerHex for SecretKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for ch in &self.0[..] { + write!(f, "{:02x}", *ch)?; + } + Ok(()) + } +} + +impl fmt::Display for SecretKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::LowerHex::fmt(self, f) + } +} + +impl str::FromStr for SecretKey { + type Err = Error; + fn from_str(s: &str) -> Result { + let mut res = [0; constants::SECRET_KEY_SIZE]; + match from_hex(s, &mut res) { + Ok(constants::SECRET_KEY_SIZE) => Ok(SecretKey(res)), + _ => Err(Error::InvalidSecretKey) + } + } +} + /// The number 1 encoded as a secret key -pub static ONE: SecretKey = SecretKey([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, 1]); +pub const ONE_KEY: SecretKey = SecretKey([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, 1]); /// A Secp256k1 public key, used for verification of signatures -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)] pub struct PublicKey(ffi::PublicKey); +impl fmt::LowerHex for PublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let ser = self.serialize(); + for ch in &ser[..] { + write!(f, "{:02x}", *ch)?; + } + Ok(()) + } +} -fn random_32_bytes(rng: &mut R) -> [u8; 32] { +impl fmt::Display for PublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::LowerHex::fmt(self, f) + } +} + +impl str::FromStr for PublicKey { + type Err = Error; + fn from_str(s: &str) -> Result { + let mut res = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]; + match from_hex(s, &mut res) { + Ok(constants::PUBLIC_KEY_SIZE) => { + PublicKey::from_slice( + &res[0..constants::PUBLIC_KEY_SIZE] + ) + } + Ok(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE) => { + PublicKey::from_slice(&res) + } + _ => Err(Error::InvalidPublicKey) + } + } +} + +#[cfg(any(test, feature = "rand"))] +fn random_32_bytes(rng: &mut R) -> [u8; 32] { let mut ret = [0u8; 32]; rng.fill_bytes(&mut ret); ret } impl SecretKey { - /// Creates a new random secret key + /// Creates a new random secret key. Requires compilation with the "rand" feature. #[inline] - pub fn new(secp: &Secp256k1, rng: &mut R) -> SecretKey { + #[cfg(any(test, feature = "rand"))] + pub fn new(rng: &mut R) -> SecretKey { let mut data = random_32_bytes(rng); unsafe { - while ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 { + while ffi::secp256k1_ec_seckey_verify( + ffi::secp256k1_context_no_precomp, + data.as_c_ptr(), + ) == 0 + { data = random_32_bytes(rng); } } @@ -64,19 +128,20 @@ impl SecretKey { /// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key #[inline] - pub fn from_slice(secp: &Secp256k1, data: &[u8]) - -> Result { + pub fn from_slice(data: &[u8])-> Result { match data.len() { constants::SECRET_KEY_SIZE => { let mut ret = [0; constants::SECRET_KEY_SIZE]; unsafe { - if ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 { + if ffi::secp256k1_ec_seckey_verify( + ffi::secp256k1_context_no_precomp, + data.as_c_ptr(), + ) == 0 + { return Err(InvalidSecretKey); } - copy_nonoverlapping(data.as_ptr(), - ret.as_mut_ptr(), - data.len()); } + ret[..].copy_from_slice(data); Ok(SecretKey(ret)) } _ => Err(InvalidSecretKey) @@ -84,67 +149,118 @@ impl SecretKey { } #[inline] - /// Adds one secret key to another, modulo the curve order - pub fn add_assign(&mut self, secp: &Secp256k1, other: &SecretKey) - -> Result<(), Error> { + /// Adds one secret key to another, modulo the curve order. WIll + /// return an error if the resulting key would be invalid or if + /// the tweak was not a 32-byte length slice. + pub fn add_assign( + &mut self, + other: &[u8], + ) -> Result<(), Error> { + if other.len() != 32 { + return Err(Error::InvalidTweak); + } unsafe { - if ffi::secp256k1_ec_privkey_tweak_add(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 { - Err(InvalidSecretKey) + if ffi::secp256k1_ec_privkey_tweak_add( + ffi::secp256k1_context_no_precomp, + self.as_mut_c_ptr(), + other.as_c_ptr(), + ) != 1 + { + Err(Error::InvalidTweak) } else { Ok(()) } } } -} -impl PublicKey { - /// Creates a new zeroed out public key #[inline] - pub fn new() -> PublicKey { - PublicKey(ffi::PublicKey::new()) + /// Multiplies one secret key by another, modulo the curve order. Will + /// return an error if the resulting key would be invalid or if + /// the tweak was not a 32-byte length slice. + pub fn mul_assign( + &mut self, + other: &[u8], + ) -> Result<(), Error> { + if other.len() != 32 { + return Err(Error::InvalidTweak); + } + unsafe { + if ffi::secp256k1_ec_privkey_tweak_mul( + ffi::secp256k1_context_no_precomp, + self.as_mut_c_ptr(), + other.as_c_ptr(), + ) != 1 + { + Err(Error::InvalidTweak) + } else { + Ok(()) + } + } } - /// Determines whether a pubkey is valid #[inline] - pub fn is_valid(&self) -> bool { - // The only invalid pubkey the API should be able to create is - // the zero one. - self.0[..].iter().any(|&x| x != 0) + /// Inverts (1 / self) this secret key. + pub fn inv_assign(&mut self) -> Result<(), Error> { + let original = self.clone(); + unsafe { + if ffi::secp256k1_ec_privkey_inverse( + ffi::secp256k1_context_no_precomp, + self.as_mut_c_ptr(), + original.as_c_ptr() + ) != 1 + { + Err(InvalidSecretKey) + } else { + Ok(()) + } + } } +} - /// Obtains a raw pointer suitable for use with FFI functions +serde_impl!(SecretKey, constants::SECRET_KEY_SIZE); + +impl PublicKey { + /// Obtains a raw const pointer suitable for use with FFI functions #[inline] pub fn as_ptr(&self) -> *const ffi::PublicKey { &self.0 as *const _ } + /// Obtains a raw mutable pointer suitable for use with FFI functions + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut ffi::PublicKey { + &mut self.0 as *mut _ + } + /// Creates a new public key from a secret key. #[inline] - pub fn from_secret_key(secp: &Secp256k1, + pub fn from_secret_key(secp: &Secp256k1, sk: &SecretKey) - -> Result { - if secp.caps == ContextFlag::VerifyOnly || secp.caps == ContextFlag::None { - return Err(IncapableContext); - } - let mut pk = unsafe { ffi::PublicKey::blank() }; + -> PublicKey { + let mut pk = ffi::PublicKey::new(); unsafe { // We can assume the return value because it's not possible to construct // an invalid `SecretKey` without transmute trickery or something - let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_ptr()); + let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_c_ptr()); debug_assert_eq!(res, 1); } - Ok(PublicKey(pk)) + PublicKey(pk) } /// Creates a public key directly from a slice #[inline] - pub fn from_slice(secp: &Secp256k1, data: &[u8]) - -> Result { + pub fn from_slice(data: &[u8]) -> Result { + if data.is_empty() {return Err(Error::InvalidPublicKey);} - let mut pk = unsafe { ffi::PublicKey::blank() }; + let mut pk = ffi::PublicKey::new(); unsafe { - if ffi::secp256k1_ec_pubkey_parse(secp.ctx, &mut pk, data.as_ptr(), - data.len() as ::libc::size_t) == 1 { + if ffi::secp256k1_ec_pubkey_parse( + ffi::secp256k1_context_no_precomp, + &mut pk, + data.as_c_ptr(), + data.len() as usize, + ) == 1 + { Ok(PublicKey(pk)) } else { Err(InvalidPublicKey) @@ -156,68 +272,121 @@ impl PublicKey { /// Serialize the key as a byte-encoded pair of values. In compressed form /// the y-coordinate is represented by only a single bit, as x determines /// it up to one bit. - pub fn serialize_vec(&self, secp: &Secp256k1, compressed: bool) -> ArrayVec<[u8; constants::PUBLIC_KEY_SIZE]> { - let mut ret = ArrayVec::new(); + pub fn serialize(&self) -> [u8; constants::PUBLIC_KEY_SIZE] { + let mut ret = [0; constants::PUBLIC_KEY_SIZE]; unsafe { - let mut ret_len = constants::PUBLIC_KEY_SIZE as ::libc::size_t; - let compressed = if compressed { ffi::SECP256K1_SER_COMPRESSED } else { ffi::SECP256K1_SER_UNCOMPRESSED }; - let err = ffi::secp256k1_ec_pubkey_serialize(secp.ctx, ret.as_ptr(), - &mut ret_len, self.as_ptr(), - compressed); + let mut ret_len = constants::PUBLIC_KEY_SIZE as usize; + let err = ffi::secp256k1_ec_pubkey_serialize( + ffi::secp256k1_context_no_precomp, + ret.as_mut_c_ptr(), + &mut ret_len, + self.as_c_ptr(), + ffi::SECP256K1_SER_COMPRESSED, + ); debug_assert_eq!(err, 1); - ret.set_len(ret_len as usize); + debug_assert_eq!(ret_len, ret.len()); + } + ret + } + + /// Serialize the key as a byte-encoded pair of values, in uncompressed form + pub fn serialize_uncompressed(&self) -> [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] { + let mut ret = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]; + + unsafe { + let mut ret_len = constants::UNCOMPRESSED_PUBLIC_KEY_SIZE as usize; + let err = ffi::secp256k1_ec_pubkey_serialize( + ffi::secp256k1_context_no_precomp, + ret.as_mut_c_ptr(), + &mut ret_len, + self.as_c_ptr(), + ffi::SECP256K1_SER_UNCOMPRESSED, + ); + debug_assert_eq!(err, 1); + debug_assert_eq!(ret_len, ret.len()); } ret } #[inline] /// Adds the pk corresponding to `other` to the pk `self` in place - pub fn add_exp_assign(&mut self, secp: &Secp256k1, other: &SecretKey) - -> Result<(), Error> { - if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None { - return Err(IncapableContext); + /// Will return an error if the resulting key would be invalid or + /// if the tweak was not a 32-byte length slice. + pub fn add_exp_assign( + &mut self, + secp: &Secp256k1, + other: &[u8] + ) -> Result<(), Error> { + if other.len() != 32 { + return Err(Error::InvalidTweak); } unsafe { if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0 as *mut _, - other.as_ptr()) == 1 { + other.as_c_ptr()) == 1 { Ok(()) } else { - Err(InvalidSecretKey) + Err(Error::InvalidTweak) } } } -} -impl Decodable for PublicKey { - fn decode(d: &mut D) -> Result { - d.read_seq(|d, len| { - let s = Secp256k1::with_caps(::ContextFlag::None); - if len == constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { - unsafe { - use std::mem; - let mut ret: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized(); - for i in 0..len { - ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); - } - PublicKey::from_slice(&s, &ret).map_err(|_| d.error("invalid public key")) - } - } else if len == constants::COMPRESSED_PUBLIC_KEY_SIZE { - unsafe { - use std::mem; - let mut ret: [u8; constants::COMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized(); - for i in 0..len { - ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); - } - PublicKey::from_slice(&s, &ret).map_err(|_| d.error("invalid public key")) - } + #[inline] + /// Muliplies the pk `self` in place by the scalar `other` + /// Will return an error if the resulting key would be invalid or + /// if the tweak was not a 32-byte length slice. + pub fn mul_assign( + &mut self, + secp: &Secp256k1, + other: &[u8], + ) -> Result<(), Error> { + if other.len() != 32 { + return Err(Error::InvalidTweak); + } + unsafe { + if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0 as *mut _, + other.as_c_ptr()) == 1 { + Ok(()) + } else { + Err(Error::InvalidTweak) + } + } + } + + /// Adds a second key to this one, returning the sum. Returns an error if + /// the result would be the point at infinity, i.e. we are adding this point + /// to its own negation + pub fn combine(&self, other: &PublicKey) -> Result { + unsafe { + let mut ret = ffi::PublicKey::new(); + let ptrs = [self.as_c_ptr(), other.as_c_ptr()]; + if ffi::secp256k1_ec_pubkey_combine( + ffi::secp256k1_context_no_precomp, + &mut ret, + ptrs.as_c_ptr(), + 2 + ) == 1 + { + Ok(PublicKey(ret)) } else { - Err(d.error("Invalid length")) + Err(InvalidPublicKey) } - }) + } } } +impl CPtr for PublicKey { + type Target = ffi::PublicKey; + fn as_c_ptr(&self) -> *const Self::Target { + self.as_ptr() + } + + fn as_mut_c_ptr(&mut self) -> *mut Self::Target { + self.as_mut_ptr() + } +} + + /// Creates a new public key from a FFI public key impl From for PublicKey { #[inline] @@ -226,95 +395,111 @@ impl From for PublicKey { } } - -impl Encodable for PublicKey { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - let secp = Secp256k1::with_caps(::ContextFlag::None); - self.serialize_vec(&secp, true).encode(s) +#[cfg(feature = "serde")] +impl ::serde::Serialize for PublicKey { + fn serialize(&self, s: S) -> Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + s.serialize_bytes(&self.serialize()) + } } } -impl Deserialize for PublicKey { - fn deserialize(d: &mut D) -> Result - where D: Deserializer - { - use serde::de; - struct Visitor { - marker: marker::PhantomData, - } - impl de::Visitor for Visitor { - type Value = PublicKey; +#[cfg(feature = "serde")] +impl<'de> ::serde::Deserialize<'de> for PublicKey { + fn deserialize>(d: D) -> Result { + if d.is_human_readable() { + struct HexVisitor; - #[inline] - fn visit_seq(&mut self, mut v: V) -> Result - where V: de::SeqVisitor - { - debug_assert!(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE >= constants::COMPRESSED_PUBLIC_KEY_SIZE); + impl<'de> ::serde::de::Visitor<'de> for HexVisitor { + type Value = PublicKey; - let s = Secp256k1::with_caps(::ContextFlag::None); - unsafe { - use std::mem; - let mut ret: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized(); - - let mut read_len = 0; - while read_len < constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { - let read_ch = match try!(v.visit()) { - Some(c) => c, - None => break - }; - ret[read_len] = read_ch; - read_len += 1; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an ASCII hex string") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: ::serde::de::Error, + { + if let Ok(hex) = str::from_utf8(v) { + str::FromStr::from_str(hex).map_err(E::custom) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) } - try!(v.end()); + } - PublicKey::from_slice(&s, &ret[..read_len]).map_err(|e| de::Error::syntax(&e.to_string())) + fn visit_str(self, v: &str) -> Result + where + E: ::serde::de::Error, + { + str::FromStr::from_str(v).map_err(E::custom) } } - } + d.deserialize_str(HexVisitor) + } else { + struct BytesVisitor; - // Begin actual function - d.visit(Visitor { marker: ::std::marker::PhantomData }) - } -} + impl<'de> ::serde::de::Visitor<'de> for BytesVisitor { + type Value = PublicKey; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a bytestring") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: ::serde::de::Error, + { + PublicKey::from_slice(v).map_err(E::custom) + } + } -impl Serialize for PublicKey { - fn serialize(&self, s: &mut S) -> Result<(), S::Error> - where S: Serializer - { - let secp = Secp256k1::with_caps(::ContextFlag::None); - (&self.serialize_vec(&secp, true)[..]).serialize(s) + d.deserialize_bytes(BytesVisitor) + } } } #[cfg(test)] mod test { - use super::super::{Secp256k1, ContextFlag}; - use super::super::Error::{InvalidPublicKey, InvalidSecretKey, IncapableContext}; + use Secp256k1; + use from_hex; + use super::super::Error::{InvalidPublicKey, InvalidSecretKey}; use super::{PublicKey, SecretKey}; use super::super::constants; - use rand::{Rng, thread_rng}; + use rand::{Error, ErrorKind, RngCore, thread_rng}; + use rand_core::impls; + use std::iter; + use std::str::FromStr; + + macro_rules! hex { + ($hex:expr) => ({ + let mut result = vec![0; $hex.len() / 2]; + from_hex($hex, &mut result).expect("valid hex string"); + result + }); + } #[test] fn skey_from_slice() { - let s = Secp256k1::new(); - let sk = SecretKey::from_slice(&s, &[1; 31]); + let sk = SecretKey::from_slice(&[1; 31]); assert_eq!(sk, Err(InvalidSecretKey)); - let sk = SecretKey::from_slice(&s, &[1; 32]); + let sk = SecretKey::from_slice(&[1; 32]); assert!(sk.is_ok()); } #[test] fn pubkey_from_slice() { - let s = Secp256k1::new(); - assert_eq!(PublicKey::from_slice(&s, &[]), Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[1, 2, 3]), Err(InvalidPublicKey)); + assert_eq!(PublicKey::from_slice(&[]), Err(InvalidPublicKey)); + assert_eq!(PublicKey::from_slice(&[1, 2, 3]), Err(InvalidPublicKey)); - let uncompressed = PublicKey::from_slice(&s, &[4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188]); + let uncompressed = PublicKey::from_slice(&[4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188]); assert!(uncompressed.is_ok()); - let compressed = PublicKey::from_slice(&s, &[3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, 78]); + let compressed = PublicKey::from_slice(&[3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, 78]); assert!(compressed.is_ok()); } @@ -322,196 +507,41 @@ mod test { fn keypair_slice_round_trip() { let s = Secp256k1::new(); - let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); - assert_eq!(SecretKey::from_slice(&s, &sk1[..]), Ok(sk1)); - assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_vec(&s, true)[..]), Ok(pk1)); - assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_vec(&s, false)[..]), Ok(pk1)); + let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); + assert_eq!(SecretKey::from_slice(&sk1[..]), Ok(sk1)); + assert_eq!(PublicKey::from_slice(&pk1.serialize()[..]), Ok(pk1)); + assert_eq!(PublicKey::from_slice(&pk1.serialize_uncompressed()[..]), Ok(pk1)); } #[test] fn invalid_secret_key() { - let s = Secp256k1::new(); // Zero - assert_eq!(SecretKey::from_slice(&s, &[0; 32]), Err(InvalidSecretKey)); + assert_eq!(SecretKey::from_slice(&[0; 32]), Err(InvalidSecretKey)); // -1 - assert_eq!(SecretKey::from_slice(&s, &[0xff; 32]), Err(InvalidSecretKey)); + assert_eq!(SecretKey::from_slice(&[0xff; 32]), Err(InvalidSecretKey)); // Top of range - assert!(SecretKey::from_slice(&s, - &[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]).is_ok()); + assert!(SecretKey::from_slice(&[ + 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, + ]).is_ok()); // One past top of range - assert!(SecretKey::from_slice(&s, - &[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]).is_err()); - } - - #[test] - fn test_pubkey_from_slice_bad_context() { - let s = Secp256k1::without_caps(); - let sk = SecretKey::new(&s, &mut thread_rng()); - assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext)); - - let s = Secp256k1::with_caps(ContextFlag::VerifyOnly); - assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext)); - - let s = Secp256k1::with_caps(ContextFlag::SignOnly); - assert!(PublicKey::from_secret_key(&s, &sk).is_ok()); - - let s = Secp256k1::with_caps(ContextFlag::Full); - assert!(PublicKey::from_secret_key(&s, &sk).is_ok()); - } - - #[test] - fn test_add_exp_bad_context() { - let s = Secp256k1::with_caps(ContextFlag::Full); - let (sk, mut pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - - assert!(pk.add_exp_assign(&s, &sk).is_ok()); - - let s = Secp256k1::with_caps(ContextFlag::VerifyOnly); - assert!(pk.add_exp_assign(&s, &sk).is_ok()); - - let s = Secp256k1::with_caps(ContextFlag::SignOnly); - assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext)); - - let s = Secp256k1::with_caps(ContextFlag::None); - assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext)); - } - - #[test] - fn test_bad_deserialize() { - use std::io::Cursor; - use serialize::{json, Decodable}; - - let zero31 = "[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]".as_bytes(); - let json31 = json::Json::from_reader(&mut Cursor::new(zero31)).unwrap(); - let zero32 = "[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]".as_bytes(); - let json32 = json::Json::from_reader(&mut Cursor::new(zero32)).unwrap(); - let zero65 = "[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,0,0]".as_bytes(); - let json65 = json::Json::from_reader(&mut Cursor::new(zero65)).unwrap(); - let string = "\"my key\"".as_bytes(); - let json = json::Json::from_reader(&mut Cursor::new(string)).unwrap(); - - // Invalid length - let mut decoder = json::Decoder::new(json31.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json31.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json32.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json32.clone()); - assert!(::decode(&mut decoder).is_ok()); - let mut decoder = json::Decoder::new(json65.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json65.clone()); - assert!(::decode(&mut decoder).is_err()); - - // Syntax error - let mut decoder = json::Decoder::new(json.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json.clone()); - assert!(::decode(&mut decoder).is_err()); - } - - #[test] - fn test_serialize() { - use std::io::Cursor; - use serialize::{json, Decodable, Encodable}; - - macro_rules! round_trip ( - ($var:ident) => ({ - let start = $var; - let mut encoded = String::new(); - { - let mut encoder = json::Encoder::new(&mut encoded); - start.encode(&mut encoder).unwrap(); - } - let json = json::Json::from_reader(&mut Cursor::new(encoded.as_bytes())).unwrap(); - let mut decoder = json::Decoder::new(json); - let decoded = Decodable::decode(&mut decoder); - assert_eq!(Ok(Some(start)), decoded); - }) - ); - - let s = Secp256k1::new(); - for _ in 0..500 { - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - round_trip!(sk); - round_trip!(pk); - } - } - - #[test] - fn test_bad_serde_deserialize() { - use serde::Deserialize; - use json; - - // Invalid length - let zero31 = "[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]".as_bytes(); - let mut json = json::de::Deserializer::new(zero31.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - let mut json = json::de::Deserializer::new(zero31.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - - let zero32 = "[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]".as_bytes(); - let mut json = json::de::Deserializer::new(zero32.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - let mut json = json::de::Deserializer::new(zero32.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_ok()); - - // All zeroes pk is invalid - let zero65 = "[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,0,0]".as_bytes(); - let mut json = json::de::Deserializer::new(zero65.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - let mut json = json::de::Deserializer::new(zero65.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - - // Syntax error - let string = "\"my key\"".as_bytes(); - let mut json = json::de::Deserializer::new(string.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - let mut json = json::de::Deserializer::new(string.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - } - - - #[test] - fn test_serialize_serde() { - use serde::{Serialize, Deserialize}; - use json; - - macro_rules! round_trip ( - ($var:ident) => ({ - let start = $var; - let mut encoded = Vec::new(); - { - let mut serializer = json::ser::Serializer::new(&mut encoded); - start.serialize(&mut serializer).unwrap(); - } - let mut deserializer = json::de::Deserializer::new(encoded.iter().map(|c| Ok(*c))); - let decoded = Deserialize::deserialize(&mut deserializer); - assert_eq!(Some(start), decoded.ok()); - }) - ); - - let s = Secp256k1::new(); - for _ in 0..500 { - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - round_trip!(sk); - round_trip!(pk); - } + assert!(SecretKey::from_slice(&[ + 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, + ]).is_err()); } #[test] fn test_out_of_range() { struct BadRng(u8); - impl Rng for BadRng { + impl RngCore for BadRng { fn next_u32(&mut self) -> u32 { unimplemented!() } + fn next_u64(&mut self) -> u64 { unimplemented!() } // This will set a secret key to a little over the // group order, then decrement with repeated calls // until it returns a valid key @@ -522,101 +552,232 @@ mod test { 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41]; assert_eq!(data.len(), 32); - unsafe { - use std::intrinsics::copy_nonoverlapping; - copy_nonoverlapping(group_order.as_ptr(), - data.as_mut_ptr(), - 32); - } + data.copy_from_slice(&group_order[..]); data[31] = self.0; self.0 -= 1; } + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + Ok(self.fill_bytes(dest)) + } } let s = Secp256k1::new(); - s.generate_keypair(&mut BadRng(0xff)).unwrap(); + s.generate_keypair(&mut BadRng(0xff)); } #[test] fn test_pubkey_from_bad_slice() { - let s = Secp256k1::new(); // Bad sizes - assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE - 1]), - Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE + 1]), - Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]), - Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 1]), - Err(InvalidPublicKey)); + assert_eq!( + PublicKey::from_slice(&[0; constants::PUBLIC_KEY_SIZE - 1]), + Err(InvalidPublicKey) + ); + assert_eq!( + PublicKey::from_slice(&[0; constants::PUBLIC_KEY_SIZE + 1]), + Err(InvalidPublicKey) + ); + assert_eq!( + PublicKey::from_slice(&[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]), + Err(InvalidPublicKey) + ); + assert_eq!( + PublicKey::from_slice(&[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 1]), + Err(InvalidPublicKey) + ); // Bad parse - assert_eq!(PublicKey::from_slice(&s, &[0xff; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]), - Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0x55; constants::COMPRESSED_PUBLIC_KEY_SIZE]), - Err(InvalidPublicKey)); + assert_eq!( + PublicKey::from_slice(&[0xff; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]), + Err(InvalidPublicKey) + ); + assert_eq!( + PublicKey::from_slice(&[0x55; constants::PUBLIC_KEY_SIZE]), + Err(InvalidPublicKey) + ); + assert_eq!( + PublicKey::from_slice(&[]), + Err(InvalidPublicKey) + ); + } + + #[test] + fn test_seckey_from_bad_slice() { + // Bad sizes + assert_eq!( + SecretKey::from_slice(&[0; constants::SECRET_KEY_SIZE - 1]), + Err(InvalidSecretKey) + ); + assert_eq!( + SecretKey::from_slice(&[0; constants::SECRET_KEY_SIZE + 1]), + Err(InvalidSecretKey) + ); + // Bad parse + assert_eq!( + SecretKey::from_slice(&[0xff; constants::SECRET_KEY_SIZE]), + Err(InvalidSecretKey) + ); + assert_eq!( + SecretKey::from_slice(&[0x00; constants::SECRET_KEY_SIZE]), + Err(InvalidSecretKey) + ); + assert_eq!( + SecretKey::from_slice(&[]), + Err(InvalidSecretKey) + ); } #[test] fn test_debug_output() { struct DumbRng(u32); - impl Rng for DumbRng { + impl RngCore for DumbRng { fn next_u32(&mut self) -> u32 { self.0 = self.0.wrapping_add(1); self.0 } + fn next_u64(&mut self) -> u64 { + self.next_u32() as u64 + } + fn fill_bytes(&mut self, dest: &mut [u8]) { + impls::fill_bytes_via_next(self, dest); + } + + fn try_fill_bytes(&mut self, _dest: &mut [u8]) -> Result<(), Error> { + Err(Error::new(ErrorKind::Unavailable, "not implemented")) + } } let s = Secp256k1::new(); - let (sk, _) = s.generate_keypair(&mut DumbRng(0)).unwrap(); + let (sk, _) = s.generate_keypair(&mut DumbRng(0)); assert_eq!(&format!("{:?}", sk), - "SecretKey(0200000001000000040000000300000006000000050000000800000007000000)"); + "SecretKey(0100000000000000020000000000000003000000000000000400000000000000)"); + } + + #[test] + fn test_display_output() { + static SK_BYTES: [u8; 32] = [ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + ]; + + let s = Secp256k1::signing_only(); + let sk = SecretKey::from_slice(&SK_BYTES).expect("sk"); + let pk = PublicKey::from_secret_key(&s, &sk); + + assert_eq!( + sk.to_string(), + "01010101010101010001020304050607ffff0000ffff00006363636363636363" + ); + assert_eq!( + SecretKey::from_str("01010101010101010001020304050607ffff0000ffff00006363636363636363").unwrap(), + sk + ); + assert_eq!( + pk.to_string(), + "0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166" + ); + assert_eq!( + PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166").unwrap(), + pk + ); + assert_eq!( + PublicKey::from_str("04\ + 18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166\ + 84B84DB303A340CD7D6823EE88174747D12A67D2F8F2F9BA40846EE5EE7A44F6" + ).unwrap(), + pk + ); + + assert!(SecretKey::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").is_err()); + assert!(SecretKey::from_str("01010101010101010001020304050607ffff0000ffff0000636363636363636363").is_err()); + assert!(SecretKey::from_str("01010101010101010001020304050607ffff0000ffff0000636363636363636").is_err()); + assert!(SecretKey::from_str("01010101010101010001020304050607ffff0000ffff000063636363636363").is_err()); + assert!(SecretKey::from_str("01010101010101010001020304050607ffff0000ffff000063636363636363xx").is_err()); + assert!(PublicKey::from_str("0300000000000000000000000000000000000000000000000000000000000000000").is_err()); + assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd16601").is_err()); + assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd16").is_err()); + assert!(PublicKey::from_str("0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").is_err()); + assert!(PublicKey::from_str("xx0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1").is_err()); + + let long_str: String = iter::repeat('a').take(1024 * 1024).collect(); + assert!(SecretKey::from_str(&long_str).is_err()); + assert!(PublicKey::from_str(&long_str).is_err()); } #[test] fn test_pubkey_serialize() { struct DumbRng(u32); - impl Rng for DumbRng { + impl RngCore for DumbRng { fn next_u32(&mut self) -> u32 { self.0 = self.0.wrapping_add(1); self.0 } + fn next_u64(&mut self) -> u64 { + self.next_u32() as u64 + } + fn try_fill_bytes(&mut self, _dest: &mut [u8]) -> Result<(), Error> { + Err(Error::new(ErrorKind::Unavailable, "not implemented")) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + impls::fill_bytes_via_next(self, dest); + } } let s = Secp256k1::new(); - let (_, pk1) = s.generate_keypair(&mut DumbRng(0)).unwrap(); - assert_eq!(&pk1.serialize_vec(&s, false)[..], - &[4, 149, 16, 196, 140, 38, 92, 239, 179, 65, 59, 224, 230, 183, 91, 238, 240, 46, 186, 252, 175, 102, 52, 249, 98, 178, 123, 72, 50, 171, 196, 254, 236, 1, 189, 143, 242, 227, 16, 87, 247, 183, 162, 68, 237, 140, 92, 205, 151, 129, 166, 58, 111, 96, 123, 64, 180, 147, 51, 12, 209, 89, 236, 213, 206][..]); - assert_eq!(&pk1.serialize_vec(&s, true)[..], - &[2, 149, 16, 196, 140, 38, 92, 239, 179, 65, 59, 224, 230, 183, 91, 238, 240, 46, 186, 252, 175, 102, 52, 249, 98, 178, 123, 72, 50, 171, 196, 254, 236][..]); + let (_, pk1) = s.generate_keypair(&mut DumbRng(0)); + assert_eq!(&pk1.serialize_uncompressed()[..], + &[4, 124, 121, 49, 14, 253, 63, 197, 50, 39, 194, 107, 17, 193, 219, 108, 154, 126, 9, 181, 248, 2, 12, 149, 233, 198, 71, 149, 134, 250, 184, 154, 229, 185, 28, 165, 110, 27, 3, 162, 126, 238, 167, 157, 242, 221, 76, 251, 237, 34, 231, 72, 39, 245, 3, 191, 64, 111, 170, 117, 103, 82, 28, 102, 163][..]); + assert_eq!(&pk1.serialize()[..], + &[3, 124, 121, 49, 14, 253, 63, 197, 50, 39, 194, 107, 17, 193, 219, 108, 154, 126, 9, 181, 248, 2, 12, 149, 233, 198, 71, 149, 134, 250, 184, 154, 229][..]); } #[test] fn test_addition() { let s = Secp256k1::new(); - let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); - let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()); + let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()); + + assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1); + assert!(sk1.add_assign(&sk2[..]).is_ok()); + assert!(pk1.add_exp_assign(&s, &sk2[..]).is_ok()); + assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1); + + assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2); + assert!(sk2.add_assign(&sk1[..]).is_ok()); + assert!(pk2.add_exp_assign(&s, &sk1[..]).is_ok()); + assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2); + } + + #[test] + fn test_multiplication() { + let s = Secp256k1::new(); + + let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()); + let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()); - assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); - assert!(sk1.add_assign(&s, &sk2).is_ok()); - assert!(pk1.add_exp_assign(&s, &sk2).is_ok()); - assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); + assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1); + assert!(sk1.mul_assign(&sk2[..]).is_ok()); + assert!(pk1.mul_assign(&s, &sk2[..]).is_ok()); + assert_eq!(PublicKey::from_secret_key(&s, &sk1), pk1); - assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); - assert!(sk2.add_assign(&s, &sk1).is_ok()); - assert!(pk2.add_exp_assign(&s, &sk1).is_ok()); - assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); + assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2); + assert!(sk2.mul_assign(&sk1[..]).is_ok()); + assert!(pk2.mul_assign(&s, &sk1[..]).is_ok()); + assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2); } #[test] fn pubkey_hash() { - use std::hash::{Hash, SipHasher, Hasher}; + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; use std::collections::HashSet; fn hash(t: &T) -> u64 { - let mut s = SipHasher::new(); + let mut s = DefaultHasher::new(); t.hash(&mut s); s.finish() } @@ -625,13 +786,88 @@ mod test { let mut set = HashSet::new(); const COUNT : usize = 1024; let count = (0..COUNT).map(|_| { - let (_, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (_, pk) = s.generate_keypair(&mut thread_rng()); let hash = hash(&pk); assert!(!set.contains(&hash)); set.insert(hash); }).count(); assert_eq!(count, COUNT); } -} + #[test] + fn pubkey_combine() { + let compressed1 = PublicKey::from_slice( + &hex!("0241cc121c419921942add6db6482fb36243faf83317c866d2a28d8c6d7089f7ba"), + ).unwrap(); + let compressed2 = PublicKey::from_slice( + &hex!("02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"), + ).unwrap(); + let exp_sum = PublicKey::from_slice( + &hex!("0384526253c27c7aef56c7b71a5cd25bebb66dddda437826defc5b2568bde81f07"), + ).unwrap(); + + let sum1 = compressed1.combine(&compressed2); + assert!(sum1.is_ok()); + let sum2 = compressed2.combine(&compressed1); + assert!(sum2.is_ok()); + assert_eq!(sum1, sum2); + assert_eq!(sum1.unwrap(), exp_sum); + } + #[test] + fn pubkey_equal() { + let pk1 = PublicKey::from_slice( + &hex!("0241cc121c419921942add6db6482fb36243faf83317c866d2a28d8c6d7089f7ba"), + ).unwrap(); + let pk2 = pk1.clone(); + let pk3 = PublicKey::from_slice( + &hex!("02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443"), + ).unwrap(); + + assert!(pk1 == pk2); + assert!(pk1 <= pk2); + assert!(pk2 <= pk1); + assert!(!(pk2 < pk1)); + assert!(!(pk1 < pk2)); + + assert!(pk3 < pk1); + assert!(pk1 > pk3); + assert!(pk3 <= pk1); + assert!(pk1 >= pk3); + } + + #[cfg(feature = "serde")] + #[test] + fn test_signature_serde() { + use serde_test::{Configure, Token, assert_tokens}; + static SK_BYTES: [u8; 32] = [ + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 2, 3, 4, 5, 6, 7, + 0xff, 0xff, 0, 0, 0xff, 0xff, 0, 0, + 99, 99, 99, 99, 99, 99, 99, 99 + ]; + static SK_STR: &'static str = "\ + 01010101010101010001020304050607ffff0000ffff00006363636363636363\ + "; + static PK_BYTES: [u8; 33] = [ + 0x02, + 0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, + 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d, + 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, + 0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66, + ]; + static PK_STR: &'static str = "\ + 0218845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166\ + "; + + let s = Secp256k1::new(); + + let sk = SecretKey::from_slice(&SK_BYTES).unwrap(); + let pk = PublicKey::from_secret_key(&s, &sk); + + assert_tokens(&sk.compact(), &[Token::BorrowedBytes(&SK_BYTES[..])]); + assert_tokens(&sk.readable(), &[Token::BorrowedStr(SK_STR)]); + assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]); + assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]); + } +} diff --git a/src/lib.rs b/src/lib.rs index 83253d41c..8b613726b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,103 @@ //! curve. Such signatures are used extensively by the Bitcoin network //! and its derivatives. //! +//! To minimize dependencies, some functions are feature-gated. To generate +//! random keys or to re-randomize a context object, compile with the "rand" +//! feature. To de/serialize objects with serde, compile with "serde". +//! +//! Where possible, the bindings use the Rust type system to ensure that +//! API usage errors are impossible. For example, the library uses context +//! objects that contain precomputation tables which are created on object +//! construction. Since this is a slow operation (10+ milliseconds, vs ~50 +//! microseconds for typical crypto operations, on a 2.70 Ghz i7-6820HQ) +//! the tables are optional, giving a performance boost for users who only +//! care about signing, only care about verification, or only care about +//! parsing. In the upstream library, if you attempt to sign a message using +//! a context that does not support this, it will trigger an assertion +//! failure and terminate the program. In `rust-secp256k1`, this is caught +//! at compile-time; in fact, it is impossible to compile code that will +//! trigger any assertion failures in the upstream library. +//! +//! ```rust +//! extern crate secp256k1; +//! # #[cfg(feature="rand")] +//! extern crate rand; +//! +//! # +//! # fn main() { +//! # #[cfg(feature="rand")] { +//! use rand::OsRng; +//! use secp256k1::{Secp256k1, Message}; +//! +//! let secp = Secp256k1::new(); +//! let mut rng = OsRng::new().expect("OsRng"); +//! let (secret_key, public_key) = secp.generate_keypair(&mut rng); +//! let message = Message::from_slice(&[0xab; 32]).expect("32 bytes"); +//! +//! let sig = secp.sign(&message, &secret_key); +//! assert!(secp.verify(&message, &sig, &public_key).is_ok()); +//! # } } +//! ``` +//! +//! The above code requires `rust-secp256k1` to be compiled with the `rand` +//! feature enabled, to get access to [`generate_keypair`](struct.Secp256k1.html#method.generate_keypair) +//! Alternately, keys can be parsed from slices, like +//! +//! ```rust +//! # fn main() { +//! use self::secp256k1::{Secp256k1, Message, SecretKey, PublicKey}; +//! +//! let secp = Secp256k1::new(); +//! let secret_key = SecretKey::from_slice(&[0xcd; 32]).expect("32 bytes, within curve order"); +//! let public_key = PublicKey::from_secret_key(&secp, &secret_key); +//! let message = Message::from_slice(&[0xab; 32]).expect("32 bytes"); +//! +//! let sig = secp.sign(&message, &secret_key); +//! assert!(secp.verify(&message, &sig, &public_key).is_ok()); +//! # } +//! ``` +//! +//! Users who only want to verify signatures can use a cheaper context, like so: +//! +//! ```rust +//! # fn main() { +//! use secp256k1::{Secp256k1, Message, Signature, PublicKey}; +//! +//! let secp = Secp256k1::verification_only(); +//! +//! let public_key = PublicKey::from_slice(&[ +//! 0x02, +//! 0xc6, 0x6e, 0x7d, 0x89, 0x66, 0xb5, 0xc5, 0x55, +//! 0xaf, 0x58, 0x05, 0x98, 0x9d, 0xa9, 0xfb, 0xf8, +//! 0xdb, 0x95, 0xe1, 0x56, 0x31, 0xce, 0x35, 0x8c, +//! 0x3a, 0x17, 0x10, 0xc9, 0x62, 0x67, 0x90, 0x63, +//! ]).expect("public keys must be 33 or 65 bytes, serialized according to SEC 2"); +//! +//! let message = Message::from_slice(&[ +//! 0xaa, 0xdf, 0x7d, 0xe7, 0x82, 0x03, 0x4f, 0xbe, +//! 0x3d, 0x3d, 0xb2, 0xcb, 0x13, 0xc0, 0xcd, 0x91, +//! 0xbf, 0x41, 0xcb, 0x08, 0xfa, 0xc7, 0xbd, 0x61, +//! 0xd5, 0x44, 0x53, 0xcf, 0x6e, 0x82, 0xb4, 0x50, +//! ]).expect("messages must be 32 bytes and are expected to be hashes"); +//! +//! let sig = Signature::from_compact(&[ +//! 0xdc, 0x4d, 0xc2, 0x64, 0xa9, 0xfe, 0xf1, 0x7a, +//! 0x3f, 0x25, 0x34, 0x49, 0xcf, 0x8c, 0x39, 0x7a, +//! 0xb6, 0xf1, 0x6f, 0xb3, 0xd6, 0x3d, 0x86, 0x94, +//! 0x0b, 0x55, 0x86, 0x82, 0x3d, 0xfd, 0x02, 0xae, +//! 0x3b, 0x46, 0x1b, 0xb4, 0x33, 0x6b, 0x5e, 0xcb, +//! 0xae, 0xfd, 0x66, 0x27, 0xaa, 0x92, 0x2e, 0xfc, +//! 0x04, 0x8f, 0xec, 0x0c, 0x88, 0x1c, 0x10, 0xc4, +//! 0xc9, 0x42, 0x8f, 0xca, 0x69, 0xc1, 0x32, 0xa2, +//! ]).expect("compact signatures are 64 bytes; DER signatures are 68-72 bytes"); +//! +//! assert!(secp.verify(&message, &sig, &public_key).is_ok()); +//! # } +//! ``` +//! +//! Observe that the same code using, say [`signing_only`](struct.Secp256k1.html#method.signing_only) +//! to generate a context would simply not compile. +//! #![crate_type = "lib"] #![crate_type = "rlib"] @@ -32,71 +129,170 @@ #![deny(unused_mut)] #![warn(missing_docs)] +// In general, rust is absolutely horrid at supporting users doing things like, +// for example, compiling Rust code for real environments. Disable useless lints +// that don't do anything but annoy us and cant actually ever be resolved. +#![allow(bare_trait_objects)] +#![allow(ellipsis_inclusive_range_patterns)] + #![cfg_attr(feature = "dev", allow(unstable_features))] #![cfg_attr(feature = "dev", feature(plugin))] #![cfg_attr(feature = "dev", plugin(clippy))] + +#![cfg_attr(all(not(test), not(fuzztarget), not(feature = "std")), no_std)] #![cfg_attr(all(test, feature = "unstable"), feature(test))] -#[cfg(all(test, feature = "unstable"))] extern crate test; -extern crate arrayvec; -extern crate rustc_serialize as serialize; -extern crate serde; -extern crate serde_json as json; +#[macro_use] +pub extern crate secp256k1_sys; +pub use secp256k1_sys as ffi; -extern crate libc; -extern crate rand; +#[cfg(all(test, feature = "unstable"))] extern crate test; +#[cfg(any(test, feature = "rand"))] pub extern crate rand; +#[cfg(any(test))] extern crate rand_core; +#[cfg(feature = "serde")] pub extern crate serde; +#[cfg(all(test, feature = "serde"))] extern crate serde_test; +#[cfg(any(test, feature = "rand"))] use rand::Rng; +#[cfg(any(test, feature = "std"))] extern crate core; -use libc::size_t; -use std::{error, fmt, ops, ptr}; -use rand::Rng; +use core::{fmt, ptr, str}; #[macro_use] mod macros; +mod context; pub mod constants; pub mod ecdh; -pub mod ffi; pub mod key; -pub mod schnorr; +#[cfg(feature = "recovery")] +pub mod recovery; -/// A tag used for recovering the public key from a compact signature -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct RecoveryId(i32); +pub use key::SecretKey; +pub use key::PublicKey; +pub use context::*; +use core::marker::PhantomData; +use core::ops::Deref; +use ffi::CPtr; /// An ECDSA signature -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq)] pub struct Signature(ffi::Signature); -/// An ECDSA signature with a recovery ID for pubkey recovery -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct RecoverableSignature(ffi::RecoverableSignature); +/// A DER serialized Signature +#[derive(Copy, Clone)] +pub struct SerializedSignature { + data: [u8; 72], + len: usize, +} -impl RecoveryId { - #[inline] - /// Allows library users to create valid recovery IDs from i32. - pub fn from_i32(id: i32) -> Result { - match id { - 0 | 1 | 2 | 3 => Ok(RecoveryId(id)), - _ => Err(Error::InvalidRecoveryId) - } +impl fmt::Debug for Signature { +fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, f) +} +} + +impl fmt::Display for Signature { +fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let sig = self.serialize_der(); + for v in sig.iter() { + write!(f, "{:02x}", v)?; } + Ok(()) +} +} - #[inline] - /// Allows library users to convert recovery IDs to i32. - pub fn to_i32(&self) -> i32 { - self.0 +impl str::FromStr for Signature { +type Err = Error; +fn from_str(s: &str) -> Result { + let mut res = [0; 72]; + match from_hex(s, &mut res) { + Ok(x) => Signature::from_der(&res[0..x]), + _ => Err(Error::InvalidSignature), } } +} + +/// Trait describing something that promises to be a 32-byte random number; in particular, +/// it has negligible probability of being zero or overflowing the group order. Such objects +/// may be converted to `Message`s without any error paths. +pub trait ThirtyTwoByteHash { + /// Converts the object into a 32-byte array + fn into_32(self) -> [u8; 32]; +} + +impl SerializedSignature { + /// Get a pointer to the underlying data with the specified capacity. + pub(crate) fn get_data_mut_ptr(&mut self) -> *mut u8 { + self.data.as_mut_ptr() + } + + /// Get the capacity of the underlying data buffer. + pub fn capacity(&self) -> usize { + self.data.len() + } + + /// Get the len of the used data. + pub fn len(&self) -> usize { + self.len + } + + /// Set the length of the object. + pub(crate) fn set_len(&mut self, len: usize) { + self.len = len; + } + + /// Convert the serialized signature into the Signature struct. + /// (This DER deserializes it) + pub fn to_signature(&self) -> Result { + Signature::from_der(&self) + } + + /// Create a SerializedSignature from a Signature. + /// (this DER serializes it) + pub fn from_signature(sig: &Signature) -> SerializedSignature { + sig.serialize_der() + } + + /// Check if the space is zero. + pub fn is_empty(&self) -> bool { self.len() == 0 } +} impl Signature { - #[inline] +#[inline] /// Converts a DER-encoded byte slice to a signature - pub fn from_der(secp: &Secp256k1, data: &[u8]) -> Result { - let mut ret = unsafe { ffi::Signature::blank() }; + pub fn from_der(data: &[u8]) -> Result { + if data.is_empty() {return Err(Error::InvalidSignature);} + + let mut ret = ffi::Signature::new(); + + unsafe { + if ffi::secp256k1_ecdsa_signature_parse_der( + ffi::secp256k1_context_no_precomp, + &mut ret, + data.as_c_ptr(), + data.len() as usize, + ) == 1 + { + Ok(Signature(ret)) + } else { + Err(Error::InvalidSignature) + } + } + } + + /// Converts a 64-byte compact-encoded byte slice to a signature + pub fn from_compact(data: &[u8]) -> Result { + let mut ret = ffi::Signature::new(); + if data.len() != 64 { + return Err(Error::InvalidSignature) + } unsafe { - if ffi::secp256k1_ecdsa_signature_parse_der(secp.ctx, &mut ret, - data.as_ptr(), data.len() as libc::size_t) == 1 { + if ffi::secp256k1_ecdsa_signature_parse_compact( + ffi::secp256k1_context_no_precomp, + &mut ret, + data.as_c_ptr(), + ) == 1 + { Ok(Signature(ret)) } else { Err(Error::InvalidSignature) @@ -108,11 +304,18 @@ impl Signature { /// only useful for validating signatures in the Bitcoin blockchain from before /// 2016. It should never be used in new applications. This library does not /// support serializing to this "format" - pub fn from_der_lax(secp: &Secp256k1, data: &[u8]) -> Result { + pub fn from_der_lax(data: &[u8]) -> Result { + if data.is_empty() {return Err(Error::InvalidSignature);} + unsafe { - let mut ret = ffi::Signature::blank(); - if ffi::ecdsa_signature_parse_der_lax(secp.ctx, &mut ret, - data.as_ptr(), data.len() as libc::size_t) == 1 { + let mut ret = ffi::Signature::new(); + if ffi::ecdsa_signature_parse_der_lax( + ffi::secp256k1_context_no_precomp, + &mut ret, + data.as_c_ptr(), + data.len() as usize, + ) == 1 + { Ok(Signature(ret)) } else { Err(Error::InvalidSignature) @@ -128,7 +331,7 @@ impl Signature { /// the signed message still cannot be changed, but for some applications, /// changing even the signature itself can be a problem. Such applications /// require a "strong signature". It is believed that ECDSA is a strong - /// signature except for this ambiguity in the sign of s, so to accomodate + /// signature except for this ambiguity in the sign of s, so to accommodate /// these applications libsecp256k1 will only accept signatures for which /// s is in the lower half of the field range. This eliminates the /// ambiguity. @@ -137,12 +340,15 @@ impl Signature { /// valid. (For example, parsing the historic Bitcoin blockchain requires /// this.) For these applications we provide this normalization function, /// which ensures that the s value lies in the lower half of its range. - pub fn normalize_s(&mut self, secp: &Secp256k1) { + pub fn normalize_s(&mut self) { unsafe { // Ignore return value, which indicates whether the sig // was already normalized. We don't care. - ffi::secp256k1_ecdsa_signature_normalize(secp.ctx, self.as_mut_ptr(), - self.as_ptr()); + ffi::secp256k1_ecdsa_signature_normalize( + ffi::secp256k1_context_no_precomp, + self.as_mut_c_ptr(), + self.as_c_ptr(), + ); } } @@ -160,121 +366,82 @@ impl Signature { #[inline] /// Serializes the signature in DER format - pub fn serialize_der(&self, secp: &Secp256k1) -> Vec { - let mut ret = Vec::with_capacity(72); - let mut len: size_t = ret.capacity() as size_t; + pub fn serialize_der(&self) -> SerializedSignature { + let mut ret = SerializedSignature::default(); + let mut len: usize = ret.capacity(); unsafe { - let err = ffi::secp256k1_ecdsa_signature_serialize_der(secp.ctx, ret.as_mut_ptr(), - &mut len, self.as_ptr()); + let err = ffi::secp256k1_ecdsa_signature_serialize_der( + ffi::secp256k1_context_no_precomp, + ret.get_data_mut_ptr(), + &mut len, + self.as_c_ptr(), + ); debug_assert!(err == 1); - ret.set_len(len as usize); + ret.set_len(len); } ret } -} -/// Creates a new signature from a FFI signature -impl From for Signature { #[inline] - fn from(sig: ffi::Signature) -> Signature { - Signature(sig) - } -} - - -impl RecoverableSignature { - #[inline] - /// Converts a compact-encoded byte slice to a signature. This - /// representation is nonstandard and defined by the libsecp256k1 - /// library. - pub fn from_compact(secp: &Secp256k1, data: &[u8], recid: RecoveryId) -> Result { - let mut ret = unsafe { ffi::RecoverableSignature::blank() }; - + /// Serializes the signature in compact format + pub fn serialize_compact(&self) -> [u8; 64] { + let mut ret = [0; 64]; unsafe { - if data.len() != 64 { - Err(Error::InvalidSignature) - } else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact(secp.ctx, &mut ret, - data.as_ptr(), recid.0) == 1 { - Ok(RecoverableSignature(ret)) - } else { - Err(Error::InvalidSignature) - } - } - } - - /// Obtains a raw pointer suitable for use with FFI functions - #[inline] - pub fn as_ptr(&self) -> *const ffi::RecoverableSignature { - &self.0 as *const _ - } - - #[inline] - /// Serializes the recoverable signature in compact format - pub fn serialize_compact(&self, secp: &Secp256k1) -> (RecoveryId, [u8; 64]) { - let mut ret = [0u8; 64]; - let mut recid = 0i32; - unsafe { - let err = ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact( - secp.ctx, ret.as_mut_ptr(), &mut recid, self.as_ptr()); - assert!(err == 1); - } - (RecoveryId(recid), ret) - } - - /// Converts a recoverable signature to a non-recoverable one (this is needed - /// for verification - #[inline] - pub fn to_standard(&self, secp: &Secp256k1) -> Signature { - let mut ret = unsafe { ffi::Signature::blank() }; - unsafe { - let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(secp.ctx, &mut ret, self.as_ptr()); - assert!(err == 1); + let err = ffi::secp256k1_ecdsa_signature_serialize_compact( + ffi::secp256k1_context_no_precomp, + ret.as_mut_c_ptr(), + self.as_c_ptr(), + ); + debug_assert!(err == 1); } - Signature(ret) + ret } } -/// Creates a new recoverable signature from a FFI one -impl From for RecoverableSignature { - #[inline] - fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature { - RecoverableSignature(sig) +impl CPtr for Signature { + type Target = ffi::Signature; + fn as_c_ptr(&self) -> *const Self::Target { + self.as_ptr() } -} - -impl ops::Index for Signature { - type Output = u8; - #[inline] - fn index(&self, index: usize) -> &u8 { - &self.0[index] + fn as_mut_c_ptr(&mut self) -> *mut Self::Target { + self.as_mut_ptr() } } -impl ops::Index> for Signature { - type Output = [u8]; - +/// Creates a new signature from a FFI signature +impl From for Signature { #[inline] - fn index(&self, index: ops::Range) -> &[u8] { - &self.0[index] + fn from(sig: ffi::Signature) -> Signature { + Signature(sig) } } -impl ops::Index> for Signature { - type Output = [u8]; - #[inline] - fn index(&self, index: ops::RangeFrom) -> &[u8] { - &self.0[index.start..] +#[cfg(feature = "serde")] +impl ::serde::Serialize for Signature { + fn serialize(&self, s: S) -> Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + s.serialize_bytes(&self.serialize_der()) + } + } } -impl ops::Index for Signature { - type Output = [u8]; - - #[inline] - fn index(&self, _: ops::RangeFull) -> &[u8] { - &self.0[..] +#[cfg(feature = "serde")] +impl<'de> ::serde::Deserialize<'de> for Signature { + fn deserialize>(d: D) -> Result { + use ::serde::de::Error; + use str::FromStr; + if d.is_human_readable() { + let sl: &str = ::serde::Deserialize::deserialize(d)?; + Signature::from_str(sl).map_err(D::Error::custom) + } else { + let sl: &[u8] = ::serde::Deserialize::deserialize(d)?; + Signature::from_der(sl).map_err(D::Error::custom) + } } } @@ -287,14 +454,14 @@ impl Message { /// Converts a `MESSAGE_SIZE`-byte slice to a message object #[inline] pub fn from_slice(data: &[u8]) -> Result { + if data == [0; constants::MESSAGE_SIZE] { + return Err(Error::InvalidMessage); + } + match data.len() { constants::MESSAGE_SIZE => { let mut ret = [0; constants::MESSAGE_SIZE]; - unsafe { - ptr::copy_nonoverlapping(data.as_ptr(), - ret.as_mut_ptr(), - data.len()); - } + ret[..].copy_from_slice(data); Ok(Message(ret)) } _ => Err(Error::InvalidMessage) @@ -302,15 +469,20 @@ impl Message { } } +impl From for Message { + /// Converts a 32-byte hash directly to a message without error paths + fn from(t: T) -> Message { + Message(t.into_32()) + } +} + /// An ECDSA error #[derive(Copy, PartialEq, Eq, Clone, Debug)] pub enum Error { - /// A `Secp256k1` was used for an operation, but it was not created to - /// support this (so necessary precomputations have not been done) - IncapableContext, /// Signature failed verification IncorrectSignature, - /// Badly sized message + /// Badly sized message ("messages" are actually fixed-sized digests; see the `MESSAGE_SIZE` + /// constant) InvalidMessage, /// Bad public key InvalidPublicKey, @@ -320,122 +492,135 @@ pub enum Error { InvalidSecretKey, /// Bad recovery id InvalidRecoveryId, + /// Invalid tweak for add_*_assign or mul_*_assign + InvalidTweak, + /// Didn't pass enough memory to context creation with preallocated memory + NotEnoughMemory, + /// The callback has panicked. + CallbackPanicked, } -// Passthrough Debug to Display, since errors should be user-visible -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.write_str(error::Error::description(self)) - } -} - -impl error::Error for Error { - fn cause(&self) -> Option<&error::Error> { None } - - fn description(&self) -> &str { +impl Error { + fn as_str(&self) -> &str { match *self { - Error::IncapableContext => "secp: context does not have sufficient capabilities", Error::IncorrectSignature => "secp: signature failed verification", Error::InvalidMessage => "secp: message was not 32 bytes (do you need to hash?)", Error::InvalidPublicKey => "secp: malformed public key", Error::InvalidSignature => "secp: malformed signature", Error::InvalidSecretKey => "secp: malformed or out-of-range secret key", - Error::InvalidRecoveryId => "secp: bad recovery id" + Error::InvalidRecoveryId => "secp: bad recovery id", + Error::InvalidTweak => "secp: bad tweak", + Error::NotEnoughMemory => "secp: not enough memory allocated", + Error::CallbackPanicked => "secp: a callback passed has panicked", } } } +// Passthrough Debug to Display, since errors should be user-visible +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.write_str(self.as_str()) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn description(&self) -> &str { self.as_str() } +} + + /// The secp256k1 engine, used to execute all signature operations -pub struct Secp256k1 { +pub struct Secp256k1 { ctx: *mut ffi::Context, - caps: ContextFlag + phantom: PhantomData, + buf: *mut [u8], } -unsafe impl Send for Secp256k1 {} -unsafe impl Sync for Secp256k1 {} +// The underlying secp context does not contain any references to memory it does not own +unsafe impl Send for Secp256k1 {} +// The API does not permit any mutation of `Secp256k1` objects except through `&mut` references +unsafe impl Sync for Secp256k1 {} + -/// Flags used to determine the capabilities of a `Secp256k1` object; -/// the more capabilities, the more expensive it is to create. -#[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub enum ContextFlag { - /// Can neither sign nor verify signatures (cheapest to create, useful - /// for cases not involving signatures, such as creating keys from slices) - None, - /// Can sign but not verify signatures - SignOnly, - /// Can verify but not create signatures - VerifyOnly, - /// Can verify and create signatures - Full +impl PartialEq for Secp256k1 { + fn eq(&self, _other: &Secp256k1) -> bool { true } } -// Passthrough Debug to Display, since caps should be user-visible -impl fmt::Display for ContextFlag { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt::Debug::fmt(self, f) +impl Default for SerializedSignature { + fn default() -> SerializedSignature { + SerializedSignature { + data: [0u8; 72], + len: 0, + } } } -impl Clone for Secp256k1 { - fn clone(&self) -> Secp256k1 { - Secp256k1 { - ctx: unsafe { ffi::secp256k1_context_clone(self.ctx) }, - caps: self.caps - } +impl PartialEq for SerializedSignature { + fn eq(&self, other: &SerializedSignature) -> bool { + self.data[..self.len] == other.data[..other.len] } } -impl PartialEq for Secp256k1 { - fn eq(&self, other: &Secp256k1) -> bool { self.caps == other.caps } +impl AsRef<[u8]> for SerializedSignature { + fn as_ref(&self) -> &[u8] { + &self.data[..self.len] + } } -impl Eq for Secp256k1 { } -impl fmt::Debug for Secp256k1 { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "Secp256k1 {{ [private], caps: {:?} }}", self.caps) +impl Deref for SerializedSignature { + type Target = [u8]; + fn deref(&self) -> &[u8] { + &self.data[..self.len] } } -impl Drop for Secp256k1 { +impl Eq for SerializedSignature {} + +impl Eq for Secp256k1 { } + +impl Drop for Secp256k1 { fn drop(&mut self) { - unsafe { ffi::secp256k1_context_destroy(self.ctx); } + unsafe { + ffi::secp256k1_context_preallocated_destroy(self.ctx); + C::deallocate(self.buf); + } } } -impl Secp256k1 { - /// Creates a new Secp256k1 context - #[inline] - pub fn new() -> Secp256k1 { - Secp256k1::with_caps(ContextFlag::Full) +impl fmt::Debug for Secp256k1 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "", self.ctx, C::DESCRIPTION) } +} - /// Creates a new Secp256k1 context with the specified capabilities - pub fn with_caps(caps: ContextFlag) -> Secp256k1 { - let flag = match caps { - ContextFlag::None => ffi::SECP256K1_START_NONE, - ContextFlag::SignOnly => ffi::SECP256K1_START_SIGN, - ContextFlag::VerifyOnly => ffi::SECP256K1_START_VERIFY, - ContextFlag::Full => ffi::SECP256K1_START_SIGN | ffi::SECP256K1_START_VERIFY - }; - Secp256k1 { ctx: unsafe { ffi::secp256k1_context_create(flag) }, caps: caps } +impl Secp256k1 { + + /// Getter for the raw pointer to the underlying secp256k1 context. This + /// shouldn't be needed with normal usage of the library. It enables + /// extending the Secp256k1 with more cryptographic algorithms outside of + /// this crate. + pub fn ctx(&self) -> &*mut ffi::Context { + &self.ctx } - /// Creates a new Secp256k1 context with no capabilities (just de/serialization) - pub fn without_caps() -> Secp256k1 { - Secp256k1::with_caps(ContextFlag::None) + /// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all) + pub fn preallocate_size_gen() -> usize { + unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) } } - /// (Re)randomizes the Secp256k1 context for cheap sidechannel resistence; - /// see comment in libsecp256k1 commit d2275795f by Gregory Maxwell - pub fn randomize(&mut self, rng: &mut R) { + /// (Re)randomizes the Secp256k1 context for cheap sidechannel resistance; + /// see comment in libsecp256k1 commit d2275795f by Gregory Maxwell. Requires + /// compilation with "rand" feature. + #[cfg(any(test, feature = "rand"))] + pub fn randomize(&mut self, rng: &mut R) { let mut seed = [0; 32]; rng.fill_bytes(&mut seed); unsafe { - let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_ptr()); + let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_c_ptr()); // This function cannot fail; it has an error return for future-proofing. // We do not expose this error since it is impossible to hit, and we have // precedent for not exposing impossible errors (for example in - // `PublicKey::from_secret_key` where it is impossble to create an invalid + // `PublicKey::from_secret_key` where it is impossible to create an invalid // secret key through the API.) // However, if this DOES fail, the result is potentially weaker side-channel // resistance, which is deadly and undetectable, so we take out the entire @@ -444,74 +629,42 @@ impl Secp256k1 { } } - /// Generates a random keypair. Convenience function for `key::SecretKey::new` - /// and `key::PublicKey::from_secret_key`; call those functions directly for - /// batch key generation. Requires a signing-capable context. - #[inline] - pub fn generate_keypair(&self, rng: &mut R) - -> Result<(key::SecretKey, key::PublicKey), Error> { - let sk = key::SecretKey::new(self, rng); - let pk = try!(key::PublicKey::from_secret_key(self, &sk)); - Ok((sk, pk)) - } +} + +impl Secp256k1 { /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce /// Requires a signing-capable context. pub fn sign(&self, msg: &Message, sk: &key::SecretKey) - -> Result { - if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } + -> Signature { - let mut ret = unsafe { ffi::Signature::blank() }; + let mut ret = ffi::Signature::new(); unsafe { // We can assume the return value because it's not possible to construct // an invalid signature from a valid `Message` and `SecretKey` - assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_ptr(), - sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979, + assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(), + sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979, ptr::null()), 1); } - Ok(Signature::from(ret)) - } - - /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce - /// Requires a signing-capable context. - pub fn sign_recoverable(&self, msg: &Message, sk: &key::SecretKey) - -> Result { - if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } - let mut ret = unsafe { ffi::RecoverableSignature::blank() }; - unsafe { - // We can assume the return value because it's not possible to construct - // an invalid signature from a valid `Message` and `SecretKey` - assert_eq!(ffi::secp256k1_ecdsa_sign_recoverable(self.ctx, &mut ret, msg.as_ptr(), - sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979, - ptr::null()), 1); - } - Ok(RecoverableSignature::from(ret)) + Signature::from(ret) } - /// Determines the public key for which `sig` is a valid signature for - /// `msg`. Requires a verify-capable context. - pub fn recover(&self, msg: &Message, sig: &RecoverableSignature) - -> Result { - if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } - - let mut pk = unsafe { ffi::PublicKey::blank() }; - - unsafe { - if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, - sig.as_ptr(), msg.as_ptr()) != 1 { - return Err(Error::InvalidSignature); - } - }; - Ok(key::PublicKey::from(pk)) + /// Generates a random keypair. Convenience function for `key::SecretKey::new` + /// and `key::PublicKey::from_secret_key`; call those functions directly for + /// batch key generation. Requires a signing-capable context. Requires compilation + /// with the "rand" feature. + #[inline] + #[cfg(any(test, feature = "rand"))] + pub fn generate_keypair(&self, rng: &mut R) + -> (key::SecretKey, key::PublicKey) { + let sk = key::SecretKey::new(rng); + let pk = key::PublicKey::from_secret_key(self, &sk); + (sk, pk) } +} +impl Secp256k1 { /// Checks that `sig` is a valid ECDSA signature for `msg` using the public /// key `pubkey`. Returns `Ok(true)` on success. Note that this function cannot /// be used for Bitcoin consensus checking since there may exist signatures @@ -519,135 +672,186 @@ impl Secp256k1 { /// verify-capable context. #[inline] pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> { - if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); + unsafe { + if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_c_ptr(), msg.as_c_ptr(), pk.as_c_ptr()) == 0 { + Err(Error::IncorrectSignature) + } else { + Ok(()) + } } + } +} - if !pk.is_valid() { - Err(Error::InvalidPublicKey) - } else if unsafe { ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), - pk.as_ptr()) } == 0 { - Err(Error::IncorrectSignature) - } else { - Ok(()) +/// Utility function used to parse hex into a target u8 buffer. Returns +/// the number of bytes converted or an error if it encounters an invalid +/// character or unexpected end of string. +fn from_hex(hex: &str, target: &mut [u8]) -> Result { + if hex.len() % 2 == 1 || hex.len() > target.len() * 2 { + return Err(()); + } + + let mut b = 0; + let mut idx = 0; + for c in hex.bytes() { + b <<= 4; + match c { + b'A'...b'F' => b |= c - b'A' + 10, + b'a'...b'f' => b |= c - b'a' + 10, + b'0'...b'9' => b |= c - b'0', + _ => return Err(()), + } + if (idx & 1) == 1 { + target[idx / 2] = b; + b = 0; } + idx += 1; } + Ok(idx / 2) } #[cfg(test)] mod tests { - use rand::{Rng, thread_rng}; - use std::ptr; - use serialize::hex::FromHex; + use rand::{RngCore, thread_rng}; + use std::str::FromStr; + use std::marker::PhantomData; use key::{SecretKey, PublicKey}; + use super::from_hex; use super::constants; - use super::{Secp256k1, Signature, RecoverableSignature, Message, RecoveryId, ContextFlag}; - use super::Error::{InvalidMessage, InvalidPublicKey, IncorrectSignature, InvalidSignature, - IncapableContext}; + use super::{Secp256k1, Signature, Message}; + use super::Error::{InvalidMessage, IncorrectSignature, InvalidSignature}; + use ffi; + use context::*; + + macro_rules! hex { + ($hex:expr) => ({ + let mut result = vec![0; $hex.len() / 2]; + from_hex($hex, &mut result).expect("valid hex string"); + result + }); + } - macro_rules! hex (($hex:expr) => ($hex.from_hex().unwrap())); #[test] - fn capabilities() { - let none = Secp256k1::with_caps(ContextFlag::None); - let sign = Secp256k1::with_caps(ContextFlag::SignOnly); - let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly); - let full = Secp256k1::with_caps(ContextFlag::Full); + #[cfg(not(feature = "dont_replace_c_symbols"))] + fn test_manual_create_destroy() { + let ctx_full = unsafe { ffi::secp256k1_context_create(AllPreallocated::FLAGS) }; + let ctx_sign = unsafe { ffi::secp256k1_context_create(SignOnlyPreallocated::FLAGS) }; + let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) }; + + let buf: *mut [u8] = &mut [0u8;0] as _; + let full: Secp256k1 = Secp256k1{ctx: ctx_full, phantom: PhantomData, buf}; + let sign: Secp256k1 = Secp256k1{ctx: ctx_sign, phantom: PhantomData, buf}; + let vrfy: Secp256k1 = Secp256k1{ctx: ctx_vrfy, phantom: PhantomData, buf}; + + let (sk, pk) = full.generate_keypair(&mut thread_rng()); + let msg = Message::from_slice(&[2u8; 32]).unwrap(); + // Try signing + assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk)); + let sig = full.sign(&msg, &sk); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + // Try verifying + assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); + assert!(full.verify(&msg, &sig, &pk).is_ok()); - // Try key generation - assert_eq!(none.generate_keypair(&mut thread_rng()), Err(IncapableContext)); - assert_eq!(vrfy.generate_keypair(&mut thread_rng()), Err(IncapableContext)); - assert!(sign.generate_keypair(&mut thread_rng()).is_ok()); - assert!(full.generate_keypair(&mut thread_rng()).is_ok()); - let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap(); + drop(full);drop(sign);drop(vrfy); + + unsafe { ffi::secp256k1_context_destroy(ctx_vrfy) }; + unsafe { ffi::secp256k1_context_destroy(ctx_sign) }; + unsafe { ffi::secp256k1_context_destroy(ctx_full) }; + } + #[test] + fn test_raw_ctx() { + let ctx_full = Secp256k1::new(); + let ctx_sign = Secp256k1::signing_only(); + let ctx_vrfy = Secp256k1::verification_only(); + + let full = unsafe {Secp256k1::from_raw_all(ctx_full.ctx)}; + let sign = unsafe {Secp256k1::from_raw_signining_only(ctx_sign.ctx)}; + let vrfy = unsafe {Secp256k1::from_raw_verification_only(ctx_vrfy.ctx)}; + + let (sk, pk) = full.generate_keypair(&mut thread_rng()); + let msg = Message::from_slice(&[2u8; 32]).unwrap(); // Try signing - assert_eq!(none.sign(&msg, &sk), Err(IncapableContext)); - assert_eq!(vrfy.sign(&msg, &sk), Err(IncapableContext)); - assert!(sign.sign(&msg, &sk).is_ok()); - assert!(full.sign(&msg, &sk).is_ok()); - assert_eq!(none.sign_recoverable(&msg, &sk), Err(IncapableContext)); - assert_eq!(vrfy.sign_recoverable(&msg, &sk), Err(IncapableContext)); - assert!(sign.sign_recoverable(&msg, &sk).is_ok()); - assert!(full.sign_recoverable(&msg, &sk).is_ok()); assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk)); - assert_eq!(sign.sign_recoverable(&msg, &sk), full.sign_recoverable(&msg, &sk)); - let sig = full.sign(&msg, &sk).unwrap(); - let sigr = full.sign_recoverable(&msg, &sk).unwrap(); + let sig = full.sign(&msg, &sk); // Try verifying - assert_eq!(none.verify(&msg, &sig, &pk), Err(IncapableContext)); - assert_eq!(sign.verify(&msg, &sig, &pk), Err(IncapableContext)); assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); assert!(full.verify(&msg, &sig, &pk).is_ok()); - // Try pk recovery - assert_eq!(none.recover(&msg, &sigr), Err(IncapableContext)); - assert_eq!(sign.recover(&msg, &sigr), Err(IncapableContext)); - assert!(vrfy.recover(&msg, &sigr).is_ok()); - assert!(full.recover(&msg, &sigr).is_ok()); - - assert_eq!(vrfy.recover(&msg, &sigr), - full.recover(&msg, &sigr)); - assert_eq!(full.recover(&msg, &sigr), Ok(pk)); + drop(full);drop(sign);drop(vrfy); + drop(ctx_full);drop(ctx_sign);drop(ctx_vrfy); + } - // Check that we can produce keys from slices with no precomputation - let (pk_slice, sk_slice) = (&pk.serialize_vec(&none, true), &sk[..]); - let new_pk = PublicKey::from_slice(&none, pk_slice).unwrap(); - let new_sk = SecretKey::from_slice(&none, sk_slice).unwrap(); - assert_eq!(sk, new_sk); - assert_eq!(pk, new_pk); + #[test] + #[should_panic] + fn test_panic_raw_ctx() { + let ctx_vrfy = Secp256k1::verification_only(); + let raw_ctx_verify_as_full = unsafe {Secp256k1::from_raw_all(ctx_vrfy.ctx)}; + let (sk, _) = raw_ctx_verify_as_full.generate_keypair(&mut thread_rng()); + let msg = Message::from_slice(&[2u8; 32]).unwrap(); + // Try signing + raw_ctx_verify_as_full.sign(&msg, &sk); } #[test] - fn recid_sanity_check() { - let one = RecoveryId(1); - assert_eq!(one, one.clone()); + fn test_preallocation() { + let mut buf_ful = vec![0u8; Secp256k1::preallocate_size()]; + let mut buf_sign = vec![0u8; Secp256k1::preallocate_signing_size()]; + let mut buf_vfy = vec![0u8; Secp256k1::preallocate_verification_size()]; +// + let full = Secp256k1::preallocated_new(&mut buf_ful).unwrap(); + let sign = Secp256k1::preallocated_signing_only(&mut buf_sign).unwrap(); + let vrfy = Secp256k1::preallocated_verification_only(&mut buf_vfy).unwrap(); + +// drop(buf_vfy); // The buffer can't get dropped before the context. +// println!("{:?}", buf_ful[5]); // Can't even read the data thanks to the borrow checker. + + let (sk, pk) = full.generate_keypair(&mut thread_rng()); + let msg = Message::from_slice(&[2u8; 32]).unwrap(); + // Try signing + assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk)); + let sig = full.sign(&msg, &sk); + + // Try verifying + assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); + assert!(full.verify(&msg, &sig, &pk).is_ok()); } #[test] - fn invalid_pubkey() { - let s = Secp256k1::new(); - let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap(); - let pk = PublicKey::new(); + fn capabilities() { + let sign = Secp256k1::signing_only(); + let vrfy = Secp256k1::verification_only(); + let full = Secp256k1::new(); + let mut msg = [0u8; 32]; thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - assert_eq!(s.verify(&msg, &sig.to_standard(&s), &pk), Err(InvalidPublicKey)); - } + // Try key generation + let (sk, pk) = full.generate_keypair(&mut thread_rng()); - #[test] - fn sign() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); - let one = [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, 1]; + // Try signing + assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk)); + let sig = full.sign(&msg, &sk); - let sk = SecretKey::from_slice(&s, &one).unwrap(); - let msg = Message::from_slice(&one).unwrap(); + // Try verifying + assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); + assert!(full.verify(&msg, &sig, &pk).is_ok()); - let sig = s.sign_recoverable(&msg, &sk).unwrap(); - assert_eq!(Ok(sig), RecoverableSignature::from_compact(&s, &[ - 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, - 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, - 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, - 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, - 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, - 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, - 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, - 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], - RecoveryId(1))) + // Check that we can produce keys from slices with no precomputation + let (pk_slice, sk_slice) = (&pk.serialize(), &sk[..]); + let new_pk = PublicKey::from_slice(pk_slice).unwrap(); + let new_sk = SecretKey::from_slice(sk_slice).unwrap(); + assert_eq!(sk, new_sk); + assert_eq!(pk, new_pk); } #[test] - fn signature_der_roundtrip() { + fn signature_serialize_roundtrip() { let mut s = Secp256k1::new(); s.randomize(&mut thread_rng()); @@ -656,21 +860,70 @@ mod tests { thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig1 = s.sign(&msg, &sk).unwrap(); - let der = sig1.serialize_der(&s); - let sig2 = Signature::from_der(&s, &der[..]).unwrap(); + let (sk, _) = s.generate_keypair(&mut thread_rng()); + let sig1 = s.sign(&msg, &sk); + let der = sig1.serialize_der(); + let sig2 = Signature::from_der(&der[..]).unwrap(); assert_eq!(sig1, sig2); + + let compact = sig1.serialize_compact(); + let sig2 = Signature::from_compact(&compact[..]).unwrap(); + assert_eq!(sig1, sig2); + + assert!(Signature::from_compact(&der[..]).is_err()); + assert!(Signature::from_compact(&compact[0..4]).is_err()); + assert!(Signature::from_der(&compact[..]).is_err()); + assert!(Signature::from_der(&der[0..4]).is_err()); } } + #[test] + fn signature_display() { + let hex_str = "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"; + let byte_str = hex!(hex_str); + + assert_eq!( + Signature::from_der(&byte_str).expect("byte str decode"), + Signature::from_str(&hex_str).expect("byte str decode") + ); + + let sig = Signature::from_str(&hex_str).expect("byte str decode"); + assert_eq!(&sig.to_string(), hex_str); + assert_eq!(&format!("{:?}", sig), hex_str); + + assert!(Signature::from_str( + "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\ + 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab4" + ).is_err()); + assert!(Signature::from_str( + "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\ + 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab" + ).is_err()); + assert!(Signature::from_str( + "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\ + 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eabxx" + ).is_err()); + assert!(Signature::from_str( + "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\ + 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\ + 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\ + 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\ + 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\ + 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45" + ).is_err()); + + // 71 byte signature + let hex_str = "30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce774b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776"; + let sig = Signature::from_str(&hex_str).expect("byte str decode"); + assert_eq!(&format!("{}", sig), hex_str); + } + #[test] fn signature_lax_der() { macro_rules! check_lax_sig( ($hex:expr) => ({ - let secp = Secp256k1::without_caps(); let sig = hex!($hex); - assert!(Signature::from_der_lax(&secp, &sig[..]).is_ok()); + assert!(Signature::from_der_lax(&sig[..]).is_ok()); }) ); @@ -693,8 +946,8 @@ mod tests { thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig = s.sign(&msg, &sk).unwrap(); + let (sk, pk) = s.generate_keypair(&mut thread_rng()); + let sig = s.sign(&msg, &sk); assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); } } @@ -705,31 +958,24 @@ mod tests { s.randomize(&mut thread_rng()); // Wild keys: 1, CURVE_ORDER - 1 - // Wild msgs: 0, 1, CURVE_ORDER - 1, CURVE_ORDER + // Wild msgs: 1, CURVE_ORDER - 1 let mut wild_keys = [[0; 32]; 2]; - let mut wild_msgs = [[0; 32]; 4]; + let mut wild_msgs = [[0; 32]; 2]; wild_keys[0][0] = 1; - wild_msgs[1][0] = 1; - unsafe { - use constants; - ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), - wild_keys[1].as_mut_ptr(), - 32); - ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), - wild_msgs[1].as_mut_ptr(), - 32); - ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), - wild_msgs[2].as_mut_ptr(), - 32); - wild_keys[1][0] -= 1; - wild_msgs[1][0] -= 1; - } + wild_msgs[0][0] = 1; + + use constants; + wild_keys[1][..].copy_from_slice(&constants::CURVE_ORDER[..]); + wild_msgs[1][..].copy_from_slice(&constants::CURVE_ORDER[..]); + + wild_keys[1][0] -= 1; + wild_msgs[1][0] -= 1; - for key in wild_keys.iter().map(|k| SecretKey::from_slice(&s, &k[..]).unwrap()) { + for key in wild_keys.iter().map(|k| SecretKey::from_slice(&k[..]).unwrap()) { for msg in wild_msgs.iter().map(|m| Message::from_slice(&m[..]).unwrap()) { - let sig = s.sign(&msg, &key).unwrap(); - let pk = PublicKey::from_secret_key(&s, &key).unwrap(); + let sig = s.sign(&msg, &key); + let pk = PublicKey::from_secret_key(&s, &key); assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); } } @@ -744,121 +990,32 @@ mod tests { thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (sk, pk) = s.generate_keypair(&mut thread_rng()); - let sigr = s.sign_recoverable(&msg, &sk).unwrap(); - let sig = sigr.to_standard(&s); + let sig = s.sign(&msg, &sk); let mut msg = [0u8; 32]; thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); assert_eq!(s.verify(&msg, &sig, &pk), Err(IncorrectSignature)); - - let recovered_key = s.recover(&msg, &sigr).unwrap(); - assert!(recovered_key != pk); - } - - #[test] - fn sign_with_recovery() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); - - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); - - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - - let sig = s.sign_recoverable(&msg, &sk).unwrap(); - - assert_eq!(s.recover(&msg, &sig), Ok(pk)); - } - - #[test] - fn bad_recovery() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); - - let msg = Message::from_slice(&[0x55; 32]).unwrap(); - - // Zero is not a valid sig - let sig = RecoverableSignature::from_compact(&s, &[0; 64], RecoveryId(0)).unwrap(); - assert_eq!(s.recover(&msg, &sig), Err(InvalidSignature)); - // ...but 111..111 is - let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap(); - assert!(s.recover(&msg, &sig).is_ok()); } #[test] fn test_bad_slice() { - let s = Secp256k1::new(); - assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE + 1]), + assert_eq!(Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]), Err(InvalidSignature)); - assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE]), + assert_eq!(Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE]), Err(InvalidSignature)); assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]), Err(InvalidMessage)); assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]), Err(InvalidMessage)); - assert!(Message::from_slice(&[0; constants::MESSAGE_SIZE]).is_ok()); - } - - #[test] - fn test_debug_output() { - let s = Secp256k1::new(); - let sig = RecoverableSignature::from_compact(&s, &[ - 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, - 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, - 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, - 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, - 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, - 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, - 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, - 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], - RecoveryId(1)).unwrap(); - assert_eq!(&format!("{:?}", sig), "RecoverableSignature(98882e09f4ed6dc3659e43fc771e0cafa60b1f926f2b77041f744721adff7366898cb609d0ee128d06ae9aa3c48020ff9f705e02f80e1280a8ade05216971a4c01)"); - - let msg = Message([1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 255]); - assert_eq!(&format!("{:?}", msg), "Message(0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fff)"); - } - - #[test] - fn test_recov_sig_serialize_compact() { - let s = Secp256k1::new(); - - let recid_in = RecoveryId(1); - let bytes_in = &[ - 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, - 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, - 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, - 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, - 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, - 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, - 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, - 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89]; - let sig = RecoverableSignature::from_compact( - &s, bytes_in, recid_in).unwrap(); - let (recid_out, bytes_out) = sig.serialize_compact(&s); - assert_eq!(recid_in, recid_out); - assert_eq!(&bytes_in[..], &bytes_out[..]); - } - - #[test] - fn test_recov_id_conversion_between_i32() { - assert!(RecoveryId::from_i32(-1).is_err()); - assert!(RecoveryId::from_i32(0).is_ok()); - assert!(RecoveryId::from_i32(1).is_ok()); - assert!(RecoveryId::from_i32(2).is_ok()); - assert!(RecoveryId::from_i32(3).is_ok()); - assert!(RecoveryId::from_i32(4).is_err()); - let id0 = RecoveryId::from_i32(0).unwrap(); - assert_eq!(id0.to_i32(), 0); - let id1 = RecoveryId(1); - assert_eq!(id1.to_i32(), 1); + assert_eq!( + Message::from_slice(&[0; constants::MESSAGE_SIZE]), + Err(InvalidMessage) + ); + assert!(Message::from_slice(&[1; constants::MESSAGE_SIZE]).is_ok()); } #[test] @@ -871,36 +1028,81 @@ mod tests { let msg = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d"); let secp = Secp256k1::new(); - let mut sig = Signature::from_der(&secp, &sig[..]).unwrap(); - let pk = PublicKey::from_slice(&secp, &pk[..]).unwrap(); + let mut sig = Signature::from_der(&sig[..]).unwrap(); + let pk = PublicKey::from_slice(&pk[..]).unwrap(); let msg = Message::from_slice(&msg[..]).unwrap(); // without normalization we expect this will fail assert_eq!(secp.verify(&msg, &sig, &pk), Err(IncorrectSignature)); // after normalization it should pass - sig.normalize_s(&secp); + sig.normalize_s(); assert_eq!(secp.verify(&msg, &sig, &pk), Ok(())); } + + #[cfg(feature = "serde")] + #[test] + fn test_signature_serde() { + use serde_test::{Configure, Token, assert_tokens}; + + let s = Secp256k1::new(); + + let msg = Message::from_slice(&[1; 32]).unwrap(); + let sk = SecretKey::from_slice(&[2; 32]).unwrap(); + let sig = s.sign(&msg, &sk); + static SIG_BYTES: [u8; 71] = [ + 48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237, + 179, 76, 119, 72, 102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148, + 8, 230, 206, 119, 75, 2, 32, 40, 118, 231, 16, 47, 32, 79, 107, 254, + 226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125, 75, 1, 0, 98, 225, + 147, 247, 99, 25, 15, 103, 118 + ]; + static SIG_STR: &'static str = "\ + 30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce77\ + 4b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776\ + "; + + assert_tokens(&sig.compact(), &[Token::BorrowedBytes(&SIG_BYTES[..])]); + assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]); + } } #[cfg(all(test, feature = "unstable"))] mod benches { - use rand::{Rng, thread_rng}; + use rand::{thread_rng, RngCore}; use test::{Bencher, black_box}; use super::{Secp256k1, Message}; #[bench] pub fn generate(bh: &mut Bencher) { - struct CounterRng(u32); - impl Rng for CounterRng { - fn next_u32(&mut self) -> u32 { self.0 += 1; self.0 } + struct CounterRng(u64); + impl RngCore for CounterRng { + fn next_u32(&mut self) -> u32 { + self.next_u64() as u32 + } + + fn next_u64(&mut self) -> u64 { + self.0 += 1; + self.0 + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + for chunk in dest.chunks_mut(64/8) { + let rand: [u8; 64/8] = unsafe {std::mem::transmute(self.next_u64())}; + chunk.copy_from_slice(&rand[..chunk.len()]); + } + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { + Ok(self.fill_bytes(dest)) + } } + let s = Secp256k1::new(); let mut r = CounterRng(0); bh.iter( || { - let (sk, pk) = s.generate_keypair(&mut r).unwrap(); + let (sk, pk) = s.generate_keypair(&mut r); black_box(sk); black_box(pk); }); @@ -912,10 +1114,10 @@ mod benches { let mut msg = [0u8; 32]; thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (sk, _) = s.generate_keypair(&mut thread_rng()); bh.iter(|| { - let sig = s.sign(&msg, &sk).unwrap(); + let sig = s.sign(&msg, &sk); black_box(sig); }); } @@ -926,28 +1128,12 @@ mod benches { let mut msg = [0u8; 32]; thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig = s.sign(&msg, &sk).unwrap(); + let (sk, pk) = s.generate_keypair(&mut thread_rng()); + let sig = s.sign(&msg, &sk); bh.iter(|| { let res = s.verify(&msg, &sig, &pk).unwrap(); black_box(res); }); } - - #[bench] - pub fn bench_recover(bh: &mut Bencher) { - let s = Secp256k1::new(); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); - let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig = s.sign_recoverable(&msg, &sk).unwrap(); - - bh.iter(|| { - let res = s.recover(&msg, &sig).unwrap(); - black_box(res); - }); - } } - diff --git a/src/macros.rs b/src/macros.rs index 235b01a67..9cf9ba6d3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,208 +13,77 @@ // If not, see . // -// This is a macro that routinely comes in handy -macro_rules! impl_array_newtype { - ($thing:ident, $ty:ty, $len:expr) => { - impl Copy for $thing {} - - impl $thing { - #[inline] - /// Converts the object to a raw pointer for FFI interfacing - pub fn as_ptr(&self) -> *const $ty { - let &$thing(ref dat) = self; - dat.as_ptr() - } - - #[inline] - /// Converts the object to a mutable raw pointer for FFI interfacing - pub fn as_mut_ptr(&mut self) -> *mut $ty { - let &mut $thing(ref mut dat) = self; - dat.as_mut_ptr() - } - - #[inline] - /// Returns the length of the object as an array - pub fn len(&self) -> usize { $len } - - #[inline] - /// Returns whether the object as an array is empty - pub fn is_empty(&self) -> bool { false } - } - - impl PartialEq for $thing { - #[inline] - fn eq(&self, other: &$thing) -> bool { - &self[..] == &other[..] - } - } - - impl Eq for $thing {} - - impl Clone for $thing { - #[inline] - fn clone(&self) -> $thing { - unsafe { - use std::intrinsics::copy_nonoverlapping; - use std::mem; - let mut ret: $thing = mem::uninitialized(); - copy_nonoverlapping(self.as_ptr(), - ret.as_mut_ptr(), - mem::size_of::<$thing>()); - ret +macro_rules! impl_pretty_debug { + ($thing:ident) => { + impl ::core::fmt::Debug for $thing { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}(", stringify!($thing))?; + for i in self[..].iter().cloned() { + write!(f, "{:02x}", i)?; } + write!(f, ")") } } + } +} - impl ::std::ops::Index for $thing { - type Output = $ty; - - #[inline] - fn index(&self, index: usize) -> &$ty { - let &$thing(ref dat) = self; - &dat[index] - } - } - - impl ::std::ops::Index<::std::ops::Range> for $thing { - type Output = [$ty]; - - #[inline] - fn index(&self, index: ::std::ops::Range) -> &[$ty] { - let &$thing(ref dat) = self; - &dat[index] - } - } - - impl ::std::ops::Index<::std::ops::RangeTo> for $thing { - type Output = [$ty]; - - #[inline] - fn index(&self, index: ::std::ops::RangeTo) -> &[$ty] { - let &$thing(ref dat) = self; - &dat[index] - } - } - - impl ::std::ops::Index<::std::ops::RangeFrom> for $thing { - type Output = [$ty]; - - #[inline] - fn index(&self, index: ::std::ops::RangeFrom) -> &[$ty] { - let &$thing(ref dat) = self; - &dat[index] - } - } - - impl ::std::ops::Index<::std::ops::RangeFull> for $thing { - type Output = [$ty]; - - #[inline] - fn index(&self, _: ::std::ops::RangeFull) -> &[$ty] { - let &$thing(ref dat) = self; - &dat[..] - } - } - - impl ::serialize::Decodable for $thing { - fn decode(d: &mut D) -> Result<$thing, D::Error> { - use serialize::Decodable; - - d.read_seq(|d, len| { - if len != $len { - Err(d.error("Invalid length")) - } else { - unsafe { - use std::mem; - let mut ret: [$ty; $len] = mem::uninitialized(); - for i in 0..len { - ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); - } - Ok($thing(ret)) - } - } - }) - } - } - - impl ::serialize::Encodable for $thing { - fn encode(&self, s: &mut S) - -> Result<(), S::Error> { - self[..].encode(s) - } - } - - impl ::serde::Deserialize for $thing { - fn deserialize(d: &mut D) -> Result<$thing, D::Error> - where D: ::serde::Deserializer - { - // We have to define the Visitor struct inside the function - // to make it local ... all we really need is that it's - // local to the macro, but this works too :) - struct Visitor { - marker: ::std::marker::PhantomData<$thing>, - } - impl ::serde::de::Visitor for Visitor { - type Value = $thing; - - #[inline] - fn visit_seq(&mut self, mut v: V) -> Result<$thing, V::Error> - where V: ::serde::de::SeqVisitor - { - unsafe { - use std::mem; - let mut ret: [$ty; $len] = mem::uninitialized(); - for i in 0..$len { - ret[i] = match try!(v.visit()) { - Some(c) => c, - None => return Err(::serde::de::Error::end_of_stream()) - }; - } - try!(v.end()); - Ok($thing(ret)) - } +macro_rules! impl_from_array_len { + ($thing:ident, $capacity:tt, ($($N:tt)+)) => { + $( + impl From<[u8; $N]> for $thing { + fn from(arr: [u8; $N]) -> Self { + let mut data = [0u8; $capacity]; + data[..$N].copy_from_slice(&arr); + $thing { + data, + len: $N, } } - - // Begin actual function - d.visit(Visitor { marker: ::std::marker::PhantomData }) } - } - - impl ::serde::Serialize for $thing { - fn serialize(&self, s: &mut S) -> Result<(), S::Error> - where S: ::serde::Serializer - { - (&self.0[..]).serialize(s) - } - } + )+ } } -macro_rules! impl_pretty_debug { - ($thing:ident) => { - impl ::std::fmt::Debug for $thing { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - try!(write!(f, "{}(", stringify!($thing))); - for i in self[..].iter().cloned() { - try!(write!(f, "{:02x}", i)); +#[cfg(feature="serde")] +/// Implements `Serialize` and `Deserialize` for a type `$t` which represents +/// a newtype over a byte-slice over length `$len`. Type `$t` must implement +/// the `FromStr` and `Display` trait. +macro_rules! serde_impl( + ($t:ident, $len:expr) => ( + impl ::serde::Serialize for $t { + fn serialize(&self, s: S) -> Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + s.serialize_bytes(&self[..]) } - write!(f, ")") } } - } -} -macro_rules! impl_raw_debug { - ($thing:ident) => { - impl ::std::fmt::Debug for $thing { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - for i in self[..].iter().cloned() { - try!(write!(f, "{:02x}", i)); + impl<'de> ::serde::Deserialize<'de> for $t { + fn deserialize>(d: D) -> Result<$t, D::Error> { + use ::serde::de::Error; + use core::str::FromStr; + + if d.is_human_readable() { + let sl: &str = ::serde::Deserialize::deserialize(d)?; + SecretKey::from_str(sl).map_err(D::Error::custom) + } else { + let sl: &[u8] = ::serde::Deserialize::deserialize(d)?; + if sl.len() != $len { + Err(D::Error::invalid_length(sl.len(), &stringify!($len))) + } else { + let mut ret = [0; $len]; + ret.copy_from_slice(sl); + Ok($t(ret)) + } } - Ok(()) } } - } -} + ) +); +#[cfg(not(feature="serde"))] +macro_rules! serde_impl( + ($t:ident, $len:expr) => () +); diff --git a/src/recovery.rs b/src/recovery.rs new file mode 100644 index 000000000..d50cca982 --- /dev/null +++ b/src/recovery.rs @@ -0,0 +1,380 @@ +// Bitcoin secp256k1 bindings +// Written in 2014 by +// Dawid Ciężarkiewicz +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +//! # Recovery module +//! Provides a signing function that allows recovering the public key from the +//! signature. + +use core::ptr; +use key; +use super::{Secp256k1, Message, Error, Signature, Verification, Signing}; +use super::ffi as super_ffi; +pub use key::SecretKey; +pub use key::PublicKey; +use self::super_ffi::CPtr; + +use ffi::recovery as ffi; + +/// A tag used for recovering the public key from a compact signature +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct RecoveryId(i32); + +/// An ECDSA signature with a recovery ID for pubkey recovery +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct RecoverableSignature(ffi::RecoverableSignature); + +impl RecoveryId { +#[inline] +/// Allows library users to create valid recovery IDs from i32. +pub fn from_i32(id: i32) -> Result { + match id { + 0 | 1 | 2 | 3 => Ok(RecoveryId(id)), + _ => Err(Error::InvalidRecoveryId) + } +} + +#[inline] +/// Allows library users to convert recovery IDs to i32. +pub fn to_i32(self) -> i32 { + self.0 +} +} + +impl RecoverableSignature { + #[inline] + /// Converts a compact-encoded byte slice to a signature. This + /// representation is nonstandard and defined by the libsecp256k1 + /// library. + pub fn from_compact(data: &[u8], recid: RecoveryId) -> Result { + if data.is_empty() {return Err(Error::InvalidSignature);} + + let mut ret = ffi::RecoverableSignature::new(); + + unsafe { + if data.len() != 64 { + Err(Error::InvalidSignature) + } else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact( + super_ffi::secp256k1_context_no_precomp, + &mut ret, + data.as_c_ptr(), + recid.0, + ) == 1 + { + Ok(RecoverableSignature(ret)) + } else { + Err(Error::InvalidSignature) + } + } + } + + /// Obtains a raw pointer suitable for use with FFI functions + #[inline] + pub fn as_ptr(&self) -> *const ffi::RecoverableSignature { + &self.0 as *const _ + } + + /// Obtains a raw mutable pointer suitable for use with FFI functions + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature { + &mut self.0 as *mut _ + } + + #[inline] + /// Serializes the recoverable signature in compact format + pub fn serialize_compact(&self) -> (RecoveryId, [u8; 64]) { + let mut ret = [0u8; 64]; + let mut recid = 0i32; + unsafe { + let err = ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact( + super_ffi::secp256k1_context_no_precomp, + ret.as_mut_c_ptr(), + &mut recid, + self.as_c_ptr(), + ); + assert!(err == 1); + } + (RecoveryId(recid), ret) + } + + /// Converts a recoverable signature to a non-recoverable one (this is needed + /// for verification + #[inline] + pub fn to_standard(&self) -> Signature { + let mut ret = super_ffi::Signature::new(); + unsafe { + let err = ffi::secp256k1_ecdsa_recoverable_signature_convert( + super_ffi::secp256k1_context_no_precomp, + &mut ret, + self.as_c_ptr(), + ); + assert!(err == 1); + } + Signature(ret) + } +} + + +impl CPtr for RecoverableSignature { + type Target = ffi::RecoverableSignature; + fn as_c_ptr(&self) -> *const Self::Target { + self.as_ptr() + } + + fn as_mut_c_ptr(&mut self) -> *mut Self::Target { + self.as_mut_ptr() + } +} + +/// Creates a new recoverable signature from a FFI one +impl From for RecoverableSignature { + #[inline] + fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature { + RecoverableSignature(sig) + } +} + +impl Secp256k1 { + /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce + /// Requires a signing-capable context. + pub fn sign_recoverable(&self, msg: &Message, sk: &key::SecretKey) + -> RecoverableSignature { + + let mut ret = ffi::RecoverableSignature::new(); + unsafe { + // We can assume the return value because it's not possible to construct + // an invalid signature from a valid `Message` and `SecretKey` + assert_eq!( + ffi::secp256k1_ecdsa_sign_recoverable( + self.ctx, + &mut ret, + msg.as_c_ptr(), + sk.as_c_ptr(), + super_ffi::secp256k1_nonce_function_rfc6979, + ptr::null() + ), + 1 + ); + } + + RecoverableSignature::from(ret) + } +} + +impl Secp256k1 { + /// Determines the public key for which `sig` is a valid signature for + /// `msg`. Requires a verify-capable context. + pub fn recover(&self, msg: &Message, sig: &RecoverableSignature) + -> Result { + + let mut pk = super_ffi::PublicKey::new(); + + unsafe { + if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, + sig.as_c_ptr(), msg.as_c_ptr()) != 1 { + return Err(Error::InvalidSignature); + } + }; + Ok(key::PublicKey::from(pk)) + } +} + + +#[cfg(test)] +mod tests { + use rand::{RngCore, thread_rng}; + + use key::SecretKey; + use super::{RecoveryId, RecoverableSignature}; + use super::super::{Secp256k1, Message}; + use super::super::Error::{IncorrectSignature, InvalidSignature}; + + #[test] + fn capabilities() { + let sign = Secp256k1::signing_only(); + let vrfy = Secp256k1::verification_only(); + let full = Secp256k1::new(); + + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + + // Try key generation + let (sk, pk) = full.generate_keypair(&mut thread_rng()); + + // Try signing + assert_eq!(sign.sign_recoverable(&msg, &sk), full.sign_recoverable(&msg, &sk)); + let sigr = full.sign_recoverable(&msg, &sk); + + // Try pk recovery + assert!(vrfy.recover(&msg, &sigr).is_ok()); + assert!(full.recover(&msg, &sigr).is_ok()); + + assert_eq!(vrfy.recover(&msg, &sigr), + full.recover(&msg, &sigr)); + assert_eq!(full.recover(&msg, &sigr), Ok(pk)); + } + + #[test] + fn recid_sanity_check() { + let one = RecoveryId(1); + assert_eq!(one, one.clone()); + } + + #[test] + fn sign() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); + let one = [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, 1]; + + let sk = SecretKey::from_slice(&one).unwrap(); + let msg = Message::from_slice(&one).unwrap(); + + let sig = s.sign_recoverable(&msg, &sk); + assert_eq!(Ok(sig), RecoverableSignature::from_compact(&[ + 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, + 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, + 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, + 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, + 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, + 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, + 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, + 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], + RecoveryId(1))) + } + + #[test] + fn sign_and_verify_fail() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); + + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + + let (sk, pk) = s.generate_keypair(&mut thread_rng()); + + let sigr = s.sign_recoverable(&msg, &sk); + let sig = sigr.to_standard(); + + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + assert_eq!(s.verify(&msg, &sig, &pk), Err(IncorrectSignature)); + + let recovered_key = s.recover(&msg, &sigr).unwrap(); + assert!(recovered_key != pk); + } + + #[test] + fn sign_with_recovery() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); + + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + + let (sk, pk) = s.generate_keypair(&mut thread_rng()); + + let sig = s.sign_recoverable(&msg, &sk); + + assert_eq!(s.recover(&msg, &sig), Ok(pk)); + } + + #[test] + fn bad_recovery() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); + + let msg = Message::from_slice(&[0x55; 32]).unwrap(); + + // Zero is not a valid sig + let sig = RecoverableSignature::from_compact(&[0; 64], RecoveryId(0)).unwrap(); + assert_eq!(s.recover(&msg, &sig), Err(InvalidSignature)); + // ...but 111..111 is + let sig = RecoverableSignature::from_compact(&[1; 64], RecoveryId(0)).unwrap(); + assert!(s.recover(&msg, &sig).is_ok()); + } + + #[test] + fn test_debug_output() { + let sig = RecoverableSignature::from_compact(&[ + 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, + 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, + 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, + 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, + 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, + 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, + 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, + 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], + RecoveryId(1)).unwrap(); + assert_eq!(&format!("{:?}", sig), "RecoverableSignature(98882e09f4ed6dc3659e43fc771e0cafa60b1f926f2b77041f744721adff7366898cb609d0ee128d06ae9aa3c48020ff9f705e02f80e1280a8ade05216971a4c01)"); + } + + #[test] + fn test_recov_sig_serialize_compact() { + let recid_in = RecoveryId(1); + let bytes_in = &[ + 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, + 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, + 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, + 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, + 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, + 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, + 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, + 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89]; + let sig = RecoverableSignature::from_compact( + bytes_in, + recid_in, + ).unwrap(); + let (recid_out, bytes_out) = sig.serialize_compact(); + assert_eq!(recid_in, recid_out); + assert_eq!(&bytes_in[..], &bytes_out[..]); + } + + #[test] + fn test_recov_id_conversion_between_i32() { + assert!(RecoveryId::from_i32(-1).is_err()); + assert!(RecoveryId::from_i32(0).is_ok()); + assert!(RecoveryId::from_i32(1).is_ok()); + assert!(RecoveryId::from_i32(2).is_ok()); + assert!(RecoveryId::from_i32(3).is_ok()); + assert!(RecoveryId::from_i32(4).is_err()); + let id0 = RecoveryId::from_i32(0).unwrap(); + assert_eq!(id0.to_i32(), 0); + let id1 = RecoveryId(1); + assert_eq!(id1.to_i32(), 1); + } +} + + +#[cfg(all(test, feature = "unstable"))] +mod benches { + #[bench] + pub fn bench_recover(bh: &mut Bencher) { + let s = Secp256k1::new(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + let (sk, _) = s.generate_keypair(&mut thread_rng()); + let sig = s.sign_recoverable(&msg, &sk); + + bh.iter(|| { + let res = s.recover(&msg, &sig).unwrap(); + black_box(res); + }); + } +} diff --git a/src/schnorr.rs b/src/schnorr.rs deleted file mode 100644 index 22fdeb82a..000000000 --- a/src/schnorr.rs +++ /dev/null @@ -1,190 +0,0 @@ -// Bitcoin secp256k1 bindings -// Written in 2014 by -// Dawid Ciężarkiewicz -// Andrew Poelstra -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. -// If not, see . -// - -//! # Schnorr signatures - -use ContextFlag; -use Error; -use Message; -use Secp256k1; - -use constants; -use ffi; -use key::{SecretKey, PublicKey}; - -use std::{mem, ptr}; - -/// A Schnorr signature. -pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]); -impl_array_newtype!(Signature, u8, constants::SCHNORR_SIGNATURE_SIZE); -impl_pretty_debug!(Signature); - -impl Signature { - /// Deserializes a signature from a 64-byte vector - pub fn deserialize(data: &[u8]) -> Signature { - assert_eq!(data.len(), constants::SCHNORR_SIGNATURE_SIZE); - unsafe { - let mut ret: Signature = mem::uninitialized(); - ptr::copy_nonoverlapping(data.as_ptr(), ret.as_mut_ptr(), - constants::SCHNORR_SIGNATURE_SIZE); - ret - } - } - - /// Serializes a signature to a 64-byte vector - pub fn serialize(&self) -> Vec { - let mut ret = Vec::with_capacity(constants::SCHNORR_SIGNATURE_SIZE); - unsafe { - ptr::copy_nonoverlapping(self.as_ptr(), ret.as_mut_ptr(), - constants::SCHNORR_SIGNATURE_SIZE); - ret.set_len(constants::SCHNORR_SIGNATURE_SIZE); - } - ret - } -} - -impl Secp256k1 { - /// Create a Schnorr signature - pub fn sign_schnorr(&self, msg: &Message, sk: &SecretKey) -> Result { - if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } - - let mut ret: Signature = unsafe { mem::uninitialized() }; - unsafe { - // We can assume the return value because it's not possible to construct - // an invalid signature from a valid `Message` and `SecretKey` - let err = ffi::secp256k1_schnorr_sign(self.ctx, ret.as_mut_ptr(), msg.as_ptr(), - sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979, - ptr::null()); - debug_assert_eq!(err, 1); - } - Ok(ret) - } - - /// Verify a Schnorr signature - pub fn verify_schnorr(&self, msg: &Message, sig: &Signature, pk: &PublicKey) -> Result<(), Error> { - if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } - - if !pk.is_valid() { - Err(Error::InvalidPublicKey) - } else if unsafe { ffi::secp256k1_schnorr_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), - pk.as_ptr()) } == 0 { - Err(Error::IncorrectSignature) - } else { - Ok(()) - } - } - - /// Retrieves the public key for which `sig` is a valid signature for `msg`. - /// Requires a verify-capable context. - pub fn recover_schnorr(&self, msg: &Message, sig: &Signature) - -> Result { - if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } - - let mut pk = unsafe { ffi::PublicKey::blank() }; - unsafe { - if ffi::secp256k1_schnorr_recover(self.ctx, &mut pk, - sig.as_ptr(), msg.as_ptr()) != 1 { - return Err(Error::InvalidSignature); - } - }; - Ok(PublicKey::from(pk)) - } -} - -#[cfg(test)] -mod tests { - use rand::{Rng, thread_rng}; - use ContextFlag; - use Message; - use Secp256k1; - use Error::IncapableContext; - use super::Signature; - - #[test] - fn capabilities() { - let none = Secp256k1::with_caps(ContextFlag::None); - let sign = Secp256k1::with_caps(ContextFlag::SignOnly); - let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly); - let full = Secp256k1::with_caps(ContextFlag::Full); - - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); - - let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap(); - - // Try signing - assert_eq!(none.sign_schnorr(&msg, &sk), Err(IncapableContext)); - assert_eq!(vrfy.sign_schnorr(&msg, &sk), Err(IncapableContext)); - assert!(sign.sign_schnorr(&msg, &sk).is_ok()); - assert!(full.sign_schnorr(&msg, &sk).is_ok()); - assert_eq!(sign.sign_schnorr(&msg, &sk), full.sign_schnorr(&msg, &sk)); - let sig = full.sign_schnorr(&msg, &sk).unwrap(); - - // Try verifying - assert_eq!(none.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext)); - assert_eq!(sign.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext)); - assert!(vrfy.verify_schnorr(&msg, &sig, &pk).is_ok()); - assert!(full.verify_schnorr(&msg, &sig, &pk).is_ok()); - - // Try pk recovery - assert_eq!(none.recover_schnorr(&msg, &sig), Err(IncapableContext)); - assert_eq!(sign.recover_schnorr(&msg, &sig), Err(IncapableContext)); - assert!(vrfy.recover_schnorr(&msg, &sig).is_ok()); - assert!(full.recover_schnorr(&msg, &sig).is_ok()); - - assert_eq!(vrfy.recover_schnorr(&msg, &sig), - full.recover_schnorr(&msg, &sig)); - assert_eq!(full.recover_schnorr(&msg, &sig), Ok(pk)); - } - - #[test] - fn sign_verify() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); - - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); - - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - - let sig = s.sign_schnorr(&msg, &sk).unwrap(); - assert!(s.verify_schnorr(&msg, &sig, &pk).is_ok()); - } - - #[test] - fn deserialize() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); - - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); - - let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); - - let sig1 = s.sign_schnorr(&msg, &sk).unwrap(); - let sig2 = Signature::deserialize(&sig1.serialize()); - assert_eq!(sig1, sig2); - } -} -