From eca6cdb123a01bea17a1689cfa7427c0181f1e99 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 29 Oct 2014 00:35:09 -0700 Subject: [PATCH 1/2] Switch scalar to use get/set 32-byte arrays --- src/ecdsa_impl.h | 2 +- src/eckey_impl.h | 9 ++++++--- src/scalar.h | 4 ++-- src/scalar_impl.h | 8 ++++---- src/secp256k1.c | 42 ++++++++++++++++++++++++++---------------- src/tests.c | 4 ++-- 6 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index eef3b7d355..39f35df80b 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -159,7 +159,7 @@ int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_ int overflow = 0; secp256k1_scalar_t sigr; secp256k1_scalar_init(&sigr); - secp256k1_scalar_set_bin(&sigr, b, 32, &overflow); + secp256k1_scalar_set_b32(&sigr, b, &overflow); if (recid) *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); secp256k1_scalar_t n; diff --git a/src/eckey_impl.h b/src/eckey_impl.h index 792b7419c6..eb26398a6e 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -73,7 +73,10 @@ int static secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) return 0; int overflow = 0; - secp256k1_scalar_set_bin(key, privkey+2, privkey[1], &overflow); + unsigned char c[32] = {0}; + memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]); + secp256k1_scalar_set_b32(key, c, &overflow); + memset(c, 0, 32); return !overflow; } @@ -99,7 +102,7 @@ int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privke }; unsigned char *ptr = privkey; memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - secp256k1_scalar_get_bin(ptr, 32, key); ptr += 32; + secp256k1_scalar_get_b32(ptr, key); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); int pubkeylen = 0; secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; @@ -123,7 +126,7 @@ int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privke }; unsigned char *ptr = privkey; memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); - secp256k1_scalar_get_bin(ptr, 32, key); ptr += 32; + secp256k1_scalar_get_b32(ptr, key); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); int pubkeylen = 0; secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; diff --git a/src/scalar.h b/src/scalar.h index 880bbeaf9c..738b3fe88a 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -25,10 +25,10 @@ void static secp256k1_scalar_free(secp256k1_scalar_t *r); int static secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count); /** Set a scalar from a big endian byte array. */ -void static secp256k1_scalar_set_bin(secp256k1_scalar_t *r, const unsigned char *bin, int len, int *overflow); +void static secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *bin, int *overflow); /** Convert a scalar to a byte array. */ -void static secp256k1_scalar_get_bin(unsigned char *bin, int len, const secp256k1_scalar_t* a); +void static secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a); /** Add two scalars together (modulo the group order). */ void static secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b); diff --git a/src/scalar_impl.h b/src/scalar_impl.h index 9cc1657a0c..64c9266442 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -27,16 +27,16 @@ int static secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, in return secp256k1_num_get_bits(&a->n, offset, count); } -void static secp256k1_scalar_set_bin(secp256k1_scalar_t *r, const unsigned char *bin, int len, int *overflow) { - secp256k1_num_set_bin(&r->n, bin, len); +void static secp256k1_scalar_set_b32(secp256k1_scalar_t *r, const unsigned char *bin, int *overflow) { + secp256k1_num_set_bin(&r->n, bin, 32); if (overflow) { *overflow = secp256k1_num_cmp(&r->n, &secp256k1_ge_consts->order) >= 0; } secp256k1_num_mod(&r->n, &secp256k1_ge_consts->order); } -void static secp256k1_scalar_get_bin(unsigned char *bin, int len, const secp256k1_scalar_t* a) { - secp256k1_num_get_bin(bin, len, &a->n); +void static secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar_t* a) { + secp256k1_num_get_bin(bin, 32, &a->n); } void static secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) { diff --git a/src/secp256k1.c b/src/secp256k1.c index a7ba14faf7..6fa3e6e45c 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -80,10 +80,15 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned secp256k1_scalar_init(&sec); secp256k1_scalar_init(&non); secp256k1_scalar_init(&msg); - secp256k1_scalar_set_bin(&sec, seckey, 32, NULL); + secp256k1_scalar_set_b32(&sec, seckey, NULL); int overflow = 0; - secp256k1_scalar_set_bin(&non, nonce, 32, &overflow); - secp256k1_scalar_set_bin(&msg, message, messagelen, NULL); + secp256k1_scalar_set_b32(&non, nonce, &overflow); + { + unsigned char c[32] = {0}; + memcpy(c + 32 - messagelen, message, messagelen); + secp256k1_scalar_set_b32(&msg, c, NULL); + memset(c, 0, 32); + } int ret = !secp256k1_scalar_is_zero(&non) && !overflow; secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_init(&sig); @@ -115,10 +120,15 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u secp256k1_scalar_init(&sec); secp256k1_scalar_init(&non); secp256k1_scalar_init(&msg); - secp256k1_scalar_set_bin(&sec, seckey, 32, NULL); + secp256k1_scalar_set_b32(&sec, seckey, NULL); int overflow = 0; - secp256k1_scalar_set_bin(&non, nonce, 32, &overflow); - secp256k1_scalar_set_bin(&msg, message, messagelen, NULL); + secp256k1_scalar_set_b32(&non, nonce, &overflow); + { + unsigned char c[32] = {0}; + memcpy(c + 32 - messagelen, message, messagelen); + secp256k1_scalar_set_b32(&msg, c, NULL); + memset(c, 0, 32); + } int ret = !secp256k1_scalar_is_zero(&non) && !overflow; secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_init(&sig); @@ -173,7 +183,7 @@ int secp256k1_ec_seckey_verify(const unsigned char *seckey) { secp256k1_scalar_t sec; secp256k1_scalar_init(&sec); int overflow; - secp256k1_scalar_set_bin(&sec, seckey, 32, &overflow); + secp256k1_scalar_set_b32(&sec, seckey, &overflow); int ret = !secp256k1_scalar_is_zero(&sec) && !overflow; secp256k1_scalar_clear(&sec); secp256k1_scalar_free(&sec); @@ -195,7 +205,7 @@ int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsi secp256k1_scalar_t sec; secp256k1_scalar_init(&sec); - secp256k1_scalar_set_bin(&sec, seckey, 32, NULL); + secp256k1_scalar_set_b32(&sec, seckey, NULL); secp256k1_gej_t pj; secp256k1_ecmult_gen(&pj, &sec); secp256k1_scalar_clear(&sec); @@ -224,14 +234,14 @@ int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *t secp256k1_scalar_t term; secp256k1_scalar_init(&term); int overflow = 0; - secp256k1_scalar_set_bin(&term, tweak, 32, &overflow); + secp256k1_scalar_set_b32(&term, tweak, &overflow); secp256k1_scalar_t sec; secp256k1_scalar_init(&sec); - secp256k1_scalar_set_bin(&sec, seckey, 32, NULL); + secp256k1_scalar_set_b32(&sec, seckey, NULL); int ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow; if (ret) { - secp256k1_scalar_get_bin(seckey, 32, &sec); + secp256k1_scalar_get_b32(seckey, &sec); } secp256k1_scalar_clear(&sec); @@ -271,13 +281,13 @@ int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *t secp256k1_scalar_t factor; secp256k1_scalar_init(&factor); int overflow = 0; - secp256k1_scalar_set_bin(&factor, tweak, 32, &overflow); + secp256k1_scalar_set_b32(&factor, tweak, &overflow); secp256k1_scalar_t sec; secp256k1_scalar_init(&sec); - secp256k1_scalar_set_bin(&sec, seckey, 32, NULL); + secp256k1_scalar_set_b32(&sec, seckey, NULL); int ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow; if (ret) { - secp256k1_scalar_get_bin(seckey, 32, &sec); + secp256k1_scalar_get_b32(seckey, &sec); } secp256k1_scalar_clear(&sec); @@ -317,7 +327,7 @@ int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *priv secp256k1_scalar_t key; secp256k1_scalar_init(&key); - secp256k1_scalar_set_bin(&key, seckey, 32, NULL); + secp256k1_scalar_set_b32(&key, seckey, NULL); int ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed); secp256k1_scalar_clear(&key); secp256k1_scalar_free(&key); @@ -332,7 +342,7 @@ int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *priv secp256k1_scalar_init(&key); int ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen); if (ret) - secp256k1_scalar_get_bin(seckey, 32, &key); + secp256k1_scalar_get_b32(seckey, &key); secp256k1_scalar_clear(&key); secp256k1_scalar_free(&key); return ret; diff --git a/src/tests.c b/src/tests.c index 76a20fbd34..684b3314a8 100644 --- a/src/tests.c +++ b/src/tests.c @@ -46,7 +46,7 @@ void random_scalar_order_test(secp256k1_scalar_t *num) { unsigned char b32[32]; secp256k1_rand256_test(b32); int overflow = 0; - secp256k1_scalar_set_bin(num, b32, 32, &overflow); + secp256k1_scalar_set_b32(num, b32, &overflow); if (overflow || secp256k1_scalar_is_zero(num)) continue; break; @@ -677,7 +677,7 @@ void test_ecdsa_openssl() { secp256k1_scalar_init(&msg); unsigned char message[32]; secp256k1_rand256_test(message); - secp256k1_scalar_set_bin(&msg, message, 32, NULL); + secp256k1_scalar_set_b32(&msg, message, NULL); secp256k1_scalar_init(&key); random_scalar_order_test(&key); secp256k1_gej_t qj; From 79359302fbc8d870a484882f2995e3c0dad4a2eb Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 29 Oct 2014 00:35:38 -0700 Subject: [PATCH 2/2] Add unit tests for scalars. Also add a secp256k1_scalar_is_one function. --- src/scalar.h | 3 + src/scalar_impl.h | 5 + src/tests.c | 260 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 268 insertions(+) diff --git a/src/scalar.h b/src/scalar.h index 738b3fe88a..a7dde37bd8 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -45,6 +45,9 @@ void static secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scala /** Check whether a scalar equals zero. */ int static secp256k1_scalar_is_zero(const secp256k1_scalar_t *a); +/** Check whether a scalar equals one. */ +int static secp256k1_scalar_is_one(const secp256k1_scalar_t *a); + /** Check whether a scalar is higher than the group order divided by 2. */ int static secp256k1_scalar_is_high(const secp256k1_scalar_t *a); diff --git a/src/scalar_impl.h b/src/scalar_impl.h index 64c9266442..03b2891230 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -54,12 +54,17 @@ void static secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scal void static secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) { secp256k1_num_sub(&r->n, &secp256k1_ge_consts->order, &a->n); + secp256k1_num_mod(&r->n, &secp256k1_ge_consts->order); } int static secp256k1_scalar_is_zero(const secp256k1_scalar_t *a) { return secp256k1_num_is_zero(&a->n); } +int static secp256k1_scalar_is_one(const secp256k1_scalar_t *a) { + return secp256k1_num_bits(&a->n) == 1; +} + int static secp256k1_scalar_is_high(const secp256k1_scalar_t *a) { return secp256k1_num_cmp(&a->n, &secp256k1_ge_consts->half_order) > 0; } diff --git a/src/tests.c b/src/tests.c index 684b3314a8..57afcf82f2 100644 --- a/src/tests.c +++ b/src/tests.c @@ -221,6 +221,263 @@ void run_num_smalltests() { run_num_int(); } +/***** SCALAR TESTS *****/ + +int secp256k1_scalar_eq(const secp256k1_scalar_t *s1, const secp256k1_scalar_t *s2) { + secp256k1_scalar_t t; + secp256k1_scalar_init(&t); + secp256k1_scalar_negate(&t, s2); + secp256k1_scalar_add(&t, &t, s1); + int ret = secp256k1_scalar_is_zero(&t); + secp256k1_scalar_free(&t); + return ret; +} + +void scalar_test(void) { + unsigned char c[32]; + + // Set 's' to a random scalar, with value 'snum'. + secp256k1_rand256_test(c); + secp256k1_scalar_t s; + secp256k1_scalar_init(&s); + secp256k1_scalar_set_b32(&s, c, NULL); + secp256k1_num_t snum; + secp256k1_num_init(&snum); + secp256k1_num_set_bin(&snum, c, 32); + secp256k1_num_mod(&snum, &secp256k1_ge_consts->order); + + // Set 's1' to a random scalar, with value 's1num'. + secp256k1_rand256_test(c); + secp256k1_scalar_t s1; + secp256k1_scalar_init(&s1); + secp256k1_scalar_set_b32(&s1, c, NULL); + secp256k1_num_t s1num; + secp256k1_num_init(&s1num); + secp256k1_num_set_bin(&s1num, c, 32); + secp256k1_num_mod(&s1num, &secp256k1_ge_consts->order); + + // Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. + secp256k1_rand256_test(c); + secp256k1_scalar_t s2; + secp256k1_scalar_init(&s2); + int overflow = 0; + secp256k1_scalar_set_b32(&s2, c, &overflow); + secp256k1_num_t s2num; + secp256k1_num_init(&s2num); + secp256k1_num_set_bin(&s2num, c, 32); + secp256k1_num_mod(&s2num, &secp256k1_ge_consts->order); + + { + // Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. + secp256k1_num_t n, t, m; + secp256k1_num_init(&n); + secp256k1_num_init(&t); + secp256k1_num_init(&m); + secp256k1_num_set_int(&n, 0); + secp256k1_num_set_int(&m, 16); + for (int i = 0; i < 256; i += 4) { + secp256k1_num_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); + secp256k1_num_mul(&n, &n, &m); + secp256k1_num_add(&n, &n, &t); + } + CHECK(secp256k1_num_eq(&n, &snum)); + secp256k1_num_free(&m); + secp256k1_num_free(&t); + secp256k1_num_free(&n); + } + + { + // Test that get_b32 returns the same as get_bin on the number. + unsigned char r1[32]; + secp256k1_scalar_get_b32(r1, &s2); + unsigned char r2[32]; + secp256k1_num_get_bin(r2, 32, &s2num); + CHECK(memcmp(r1, r2, 32) == 0); + // If no overflow occurred when assigning, it should also be equal to the original byte array. + CHECK((memcmp(r1, c, 32) == 0) == (overflow == 0)); + } + + { + // Test that adding the scalars together is equal to adding their numbers together modulo the order. + secp256k1_num_t rnum; + secp256k1_num_init(&rnum); + secp256k1_num_add(&rnum, &snum, &s2num); + secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order); + secp256k1_scalar_t r; + secp256k1_scalar_init(&r); + secp256k1_scalar_add(&r, &s, &s2); + secp256k1_num_t r2num; + secp256k1_num_init(&r2num); + secp256k1_scalar_get_num(&r2num, &r); + CHECK(secp256k1_num_eq(&rnum, &r2num)); + secp256k1_num_free(&r2num); + secp256k1_num_free(&rnum); + secp256k1_scalar_free(&r); + } + + { + // Test that multipying the scalars is equal to multiplying their numbers modulo the order. + secp256k1_num_t rnum; + secp256k1_num_init(&rnum); + secp256k1_num_mul(&rnum, &snum, &s2num); + secp256k1_num_mod(&rnum, &secp256k1_ge_consts->order); + secp256k1_scalar_t r; + secp256k1_scalar_init(&r); + secp256k1_scalar_mul(&r, &s, &s2); + secp256k1_num_t r2num; + secp256k1_num_init(&r2num); + secp256k1_scalar_get_num(&r2num, &r); + CHECK(secp256k1_num_eq(&rnum, &r2num)); + // The result can only be zero if at least one of the factors was zero. + CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); + // The results can only be equal to one of the factors if that factor was zero, or the other factor was one. + CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); + CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); + secp256k1_num_free(&r2num); + secp256k1_num_free(&rnum); + secp256k1_scalar_free(&r); + } + + { + // Check that comparison with zero matches comparison with zero on the number. + CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); + // Check that comparison with the half order is equal to testing for high scalar. + CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &secp256k1_ge_consts->half_order) > 0)); + secp256k1_scalar_t neg; + secp256k1_scalar_init(&neg); + secp256k1_scalar_negate(&neg, &s); + secp256k1_num_t negnum; + secp256k1_num_init(&negnum); + secp256k1_num_sub(&negnum, &secp256k1_ge_consts->order, &snum); + secp256k1_num_mod(&negnum, &secp256k1_ge_consts->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, &secp256k1_ge_consts->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_num_t negnum2; + secp256k1_num_init(&negnum2); + secp256k1_scalar_get_num(&negnum2, &neg); + // Negating a scalar should be equal to (order - n) mod order on the number. + CHECK(secp256k1_num_eq(&negnum, &negnum2)); + secp256k1_scalar_add(&neg, &neg, &s); + // Adding a number to its negation should result in zero. + CHECK(secp256k1_scalar_is_zero(&neg)); + secp256k1_scalar_negate(&neg, &neg); + // Negating zero should still result in zero. + CHECK(secp256k1_scalar_is_zero(&neg)); + secp256k1_num_free(&negnum); + secp256k1_num_free(&negnum2); + secp256k1_scalar_free(&neg); + } + + { + // Test that scalar inverses are equal to the inverse of their number modulo the order. + if (!secp256k1_scalar_is_zero(&s)) { + secp256k1_scalar_t inv; + secp256k1_scalar_init(&inv); + secp256k1_scalar_inverse(&inv, &s); + secp256k1_num_t invnum; + secp256k1_num_init(&invnum); + secp256k1_num_mod_inverse(&invnum, &snum, &secp256k1_ge_consts->order); + secp256k1_num_t invnum2; + secp256k1_num_init(&invnum2); + secp256k1_scalar_get_num(&invnum2, &inv); + CHECK(secp256k1_num_eq(&invnum, &invnum2)); + secp256k1_scalar_mul(&inv, &inv, &s); + // Multiplying a scalar with its inverse must result in one. + CHECK(secp256k1_scalar_is_one(&inv)); + secp256k1_scalar_inverse(&inv, &inv); + // Inverting one must result in one. + CHECK(secp256k1_scalar_is_one(&inv)); + secp256k1_num_free(&invnum); + secp256k1_num_free(&invnum2); + secp256k1_scalar_free(&inv); + } + } + + { + // Test commutativity of add. + secp256k1_scalar_t r1, r2; + secp256k1_scalar_init(&r1); + secp256k1_scalar_init(&r2); + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_add(&r2, &s2, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + secp256k1_scalar_free(&r1); + secp256k1_scalar_free(&r2); + } + + { + // Test commutativity of mul. + secp256k1_scalar_t r1, r2; + secp256k1_scalar_init(&r1); + secp256k1_scalar_init(&r2); + secp256k1_scalar_mul(&r1, &s1, &s2); + secp256k1_scalar_mul(&r2, &s2, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + secp256k1_scalar_free(&r1); + secp256k1_scalar_free(&r2); + } + + { + // Test associativity of add. + secp256k1_scalar_t r1, r2; + secp256k1_scalar_init(&r1); + secp256k1_scalar_init(&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)); + secp256k1_scalar_free(&r1); + secp256k1_scalar_free(&r2); + } + + { + // Test associativity of mul. + secp256k1_scalar_t r1, r2; + secp256k1_scalar_init(&r1); + secp256k1_scalar_init(&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)); + secp256k1_scalar_free(&r1); + secp256k1_scalar_free(&r2); + } + + { + // Test distributitivity of mul over add. + secp256k1_scalar_t r1, r2, t; + secp256k1_scalar_init(&r1); + secp256k1_scalar_init(&r2); + secp256k1_scalar_init(&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)); + secp256k1_scalar_free(&r1); + secp256k1_scalar_free(&r2); + secp256k1_scalar_free(&t); + } + + secp256k1_num_free(&snum); + secp256k1_scalar_free(&s); + secp256k1_num_free(&s1num); + secp256k1_scalar_free(&s1); + secp256k1_num_free(&s2num); + secp256k1_scalar_free(&s2); +} + +void run_scalar_tests(void) { + for (int i = 0; i < 128 * count; i++) { + scalar_test(); + } +} + /***** FIELD TESTS *****/ void random_fe(secp256k1_fe_t *x) { @@ -746,6 +1003,9 @@ int main(int argc, char **argv) { // num tests run_num_smalltests(); + // scalar tests + run_scalar_tests(); + // field tests run_field_inv(); run_field_inv_var();