aboutsummaryrefslogtreecommitdiff
path: root/src/modules/recovery/tests_impl.h
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2017-05-05 11:12:58 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2017-05-05 11:12:58 -0700
commite7c1b4490f2c559b050b8255df2d347dd0e4945f (patch)
tree0cedbba829a5b38b750b2952af49b45880c32117 /src/modules/recovery/tests_impl.h
parent7b49f22bdbdecca600c4744d020b3553fe427e61 (diff)
downloadbitcoin-e7c1b4490f2c559b050b8255df2d347dd0e4945f.tar.xz
Squashed 'src/secp256k1/' changes from 8225239..84973d3
84973d3 Merge #454: Remove residual parts from the schnorr expirement. 5e95bf2 Remove residual parts from the schnorr expirement. cbc20b8 Merge #452: Minor optimizations to _scalar_inverse to save 4M 4cc8f52 Merge #437: Unroll secp256k1_fe_(get|set)_b32 to make them much faster. 465159c Further shorten the addition chain for scalar inversion. a2b6b19 Fix benchmark print_number infinite loop. 8b7680a Unroll secp256k1_fe_(get|set)_b32 for 10x26. aa84990 Unroll secp256k1_fe_(get|set)_b32 for 5x52. cf12fa1 Minor optimizations to _scalar_inverse to save 4M 1199492 Merge #408: Add `secp256k1_ec_pubkey_negate` and `secp256k1_ec_privkey_negate` 6af0871 Merge #441: secp256k1_context_randomize: document. ab31a52 Merge #444: test: Use checked_alloc eda5c1a Merge #449: Remove executable bit from secp256k1.c 51b77ae Remove executable bit from secp256k1.c 5eb030c test: Use checked_alloc 72d952c FIXUP: Missing "is" 70ff29b secp256k1_context_randomize: document. 9d560f9 Merge #428: Exhaustive recovery 8e48aa6 Add `secp256k1_ec_pubkey_negate` and `secp256k1_ec_privkey_negate` 2cee5fd exhaustive tests: add recovery module 678b0e5 exhaustive tests: remove erroneous comment from ecdsa_sig_sign 03ff8c2 group_impl.h: remove unused `secp256k1_ge_set_infinity` function a724d72 configure: add --enable-coverage to set options for coverage analysis b595163 recovery: add tests to cover API misusage 6f8ae2f ecdh: test NULL-checking of arguments 25e3cfb ecdsa_impl: replace scalar if-checks with VERIFY_CHECKs in ecdsa_sig_sign git-subtree-dir: src/secp256k1 git-subtree-split: 84973d393ac240a90b2e1a6538c5368202bc2224
Diffstat (limited to 'src/modules/recovery/tests_impl.h')
-rw-r--r--src/modules/recovery/tests_impl.h143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/modules/recovery/tests_impl.h b/src/modules/recovery/tests_impl.h
index 8932d5f0af..765c7dd81e 100644
--- a/src/modules/recovery/tests_impl.h
+++ b/src/modules/recovery/tests_impl.h
@@ -7,6 +7,146 @@
#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_
#define _SECP256K1_MODULE_RECOVERY_TESTS_
+static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) {
+ (void) msg32;
+ (void) key32;
+ (void) algo16;
+ (void) data;
+
+ /* On the first run, return 0 to force a second run */
+ if (counter == 0) {
+ memset(nonce32, 0, 32);
+ return 1;
+ }
+ /* On the second run, return an overflow to force a third run */
+ if (counter == 1) {
+ memset(nonce32, 0xff, 32);
+ return 1;
+ }
+ /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */
+ memset(nonce32, 1, 32);
+ return secp256k1_rand_bits(1);
+}
+
+void test_ecdsa_recovery_api(void) {
+ /* Setup contexts that just count errors */
+ secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
+ secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
+ secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
+ secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
+ secp256k1_pubkey pubkey;
+ secp256k1_pubkey recpubkey;
+ secp256k1_ecdsa_signature normal_sig;
+ secp256k1_ecdsa_recoverable_signature recsig;
+ unsigned char privkey[32] = { 1 };
+ unsigned char message[32] = { 2 };
+ int32_t ecount = 0;
+ int recid = 0;
+ unsigned char sig[74];
+ unsigned char zero_privkey[32] = { 0 };
+ unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
+ secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount);
+
+ /* Construct and verify corresponding public key. */
+ CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1);
+ CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1);
+
+ /* Check bad contexts and NULLs for signing */
+ ecount = 0;
+ CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0);
+ CHECK(ecount == 4);
+ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0);
+ CHECK(ecount == 5);
+ /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */
+ secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL);
+ CHECK(ecount == 5);
+ /* These will all fail, but not in ARG_CHECK way */
+ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0);
+ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0);
+ /* This one will succeed. */
+ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
+ CHECK(ecount == 5);
+
+ /* Check signing with a goofy nonce function */
+
+ /* Check bad contexts and NULLs for recovery */
+ ecount = 0;
+ CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0);
+ CHECK(ecount == 4);
+ CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0);
+ CHECK(ecount == 5);
+
+ /* Check NULLs for conversion */
+ CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1);
+ ecount = 0;
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1);
+
+ /* Check NULLs for de/serialization */
+ CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1);
+ ecount = 0;
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0);
+ CHECK(ecount == 1);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0);
+ CHECK(ecount == 2);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0);
+ CHECK(ecount == 3);
+ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1);
+
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0);
+ CHECK(ecount == 4);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0);
+ CHECK(ecount == 5);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0);
+ CHECK(ecount == 6);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0);
+ CHECK(ecount == 7);
+ /* overflow in signature will fail but not affect ecount */
+ memcpy(sig, over_privkey, 32);
+ CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0);
+ CHECK(ecount == 7);
+
+ /* cleanup */
+ secp256k1_context_destroy(none);
+ secp256k1_context_destroy(sign);
+ secp256k1_context_destroy(vrfy);
+ secp256k1_context_destroy(both);
+}
+
void test_ecdsa_recovery_end_to_end(void) {
unsigned char extra[32] = {0x00};
unsigned char privkey[32];
@@ -241,6 +381,9 @@ void test_ecdsa_recovery_edge_cases(void) {
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();
}