Add tests for modinv modules

This adds tests for the modinv{32,64}_impl.h directly (before the functions are used
inside the field/scalar code). It uses a naive implementation of modular multiplication
and gcds in order to verify the modular inverses themselves.
This commit is contained in:
Pieter Wuille 2020-12-22 18:24:36 -08:00
parent d8a92fcc4c
commit 151aac00d3
1 changed files with 444 additions and 0 deletions

View File

@ -18,6 +18,7 @@
#include "include/secp256k1.h" #include "include/secp256k1.h"
#include "include/secp256k1_preallocated.h" #include "include/secp256k1_preallocated.h"
#include "testrand_impl.h" #include "testrand_impl.h"
#include "util.h"
#ifdef ENABLE_OPENSSL_TESTS #ifdef ENABLE_OPENSSL_TESTS
#include "openssl/bn.h" #include "openssl/bn.h"
@ -32,6 +33,11 @@ void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
#include "contrib/lax_der_parsing.c" #include "contrib/lax_der_parsing.c"
#include "contrib/lax_der_privatekey_parsing.c" #include "contrib/lax_der_privatekey_parsing.c"
#include "modinv32_impl.h"
#ifdef SECP256K1_WIDEMUL_INT128
#include "modinv64_impl.h"
#endif
static int count = 64; static int count = 64;
static secp256k1_context *ctx = NULL; static secp256k1_context *ctx = NULL;
@ -816,8 +822,444 @@ void run_num_smalltests(void) {
} }
#endif #endif
/***** MODINV TESTS *****/
/* Compute the modular inverse of (odd) x mod 2^64. */
uint64_t modinv2p64(uint64_t x) {
/* If w = 1/x mod 2^(2^L), then w*(2 - w*x) = 1/x mod 2^(2^(L+1)). See
* Hacker's Delight second edition, Henry S. Warren, Jr., pages 245-247 for
* why. Start with L=0, for which it is true for every odd x that
* 1/x=1 mod 2. Iterating 6 times gives us 1/x mod 2^64. */
int l;
uint64_t w = 1;
CHECK(x & 1);
for (l = 0; l < 6; ++l) w *= (2 - w*x);
return w;
}
/* compute out = (a*b) mod m; if b=NULL, treat b=1.
*
* Out is a 512-bit number (represented as 32 uint16_t's in LE order). The other
* arguments are 256-bit numbers (represented as 16 uint16_t's in LE order). */
void mulmod256(uint16_t* out, const uint16_t* a, const uint16_t* b, const uint16_t* m) {
uint16_t mul[32];
uint64_t c = 0;
int i, j;
int m_bitlen = 0;
int mul_bitlen = 0;
if (b != NULL) {
/* Compute the product of a and b, and put it in mul. */
for (i = 0; i < 32; ++i) {
for (j = i <= 15 ? 0 : i - 15; j <= i && j <= 15; j++) {
c += (uint64_t)a[j] * b[i - j];
}
mul[i] = c & 0xFFFF;
c >>= 16;
}
CHECK(c == 0);
/* compute the highest set bit in mul */
for (i = 511; i >= 0; --i) {
if ((mul[i >> 4] >> (i & 15)) & 1) {
mul_bitlen = i;
break;
}
}
} else {
/* if b==NULL, set mul=a. */
memcpy(mul, a, 32);
memset(mul + 16, 0, 32);
/* compute the highest set bit in mul */
for (i = 255; i >= 0; --i) {
if ((mul[i >> 4] >> (i & 15)) & 1) {
mul_bitlen = i;
break;
}
}
}
/* Compute the highest set bit in m. */
for (i = 255; i >= 0; --i) {
if ((m[i >> 4] >> (i & 15)) & 1) {
m_bitlen = i;
break;
}
}
/* Try do mul -= m<<i, for i going down to 0, whenever the result is not negative */
for (i = mul_bitlen - m_bitlen; i >= 0; --i) {
uint16_t mul2[32];
int64_t cs;
/* Compute mul2 = mul - m<<i. */
cs = 0; /* accumulator */
for (j = 0; j < 32; ++j) { /* j loops over the output limbs in mul2. */
/* Compute sub: the 16 bits in m that will be subtracted from mul2[j]. */
uint16_t sub = 0;
int p;
for (p = 0; p < 16; ++p) { /* p loops over the bit positions in mul2[j]. */
int bitpos = j * 16 - i + p; /* bitpos is the correspond bit position in m. */
if (bitpos >= 0 && bitpos < 256) {
sub |= ((m[bitpos >> 4] >> (bitpos & 15)) & 1) << p;
}
}
/* Add mul[j]-sub to accumulator, and shift bottom 16 bits out to mul2[j]. */
cs += mul[j];
cs -= sub;
mul2[j] = (cs & 0xFFFF);
cs >>= 16;
}
/* If remainder of subtraction is 0, set mul = mul2. */
if (cs == 0) {
memcpy(mul, mul2, sizeof(mul));
}
}
/* Sanity check: test that all limbs higher than m's highest are zero */
for (i = (m_bitlen >> 4) + 1; i < 32; ++i) {
CHECK(mul[i] == 0);
}
memcpy(out, mul, 32);
}
/* Convert a 256-bit number represented as 16 uint16_t's to signed30 notation. */
void uint16_to_signed30(secp256k1_modinv32_signed30* out, const uint16_t* in) {
int i;
memset(out->v, 0, sizeof(out->v));
for (i = 0; i < 256; ++i) {
out->v[i / 30] |= (int32_t)(((in[i >> 4]) >> (i & 15)) & 1) << (i % 30);
}
}
/* Convert a 256-bit number in signed30 notation to a representation as 16 uint16_t's. */
void signed30_to_uint16(uint16_t* out, const secp256k1_modinv32_signed30* in) {
int i;
memset(out, 0, 32);
for (i = 0; i < 256; ++i) {
out[i >> 4] |= (((in->v[i / 30]) >> (i % 30)) & 1) << (i & 15);
}
}
/* Randomly mutate the sign of limbs in signed30 representation, without changing the value. */
void mutate_sign_signed30(secp256k1_modinv32_signed30* x) {
int i;
for (i = 0; i < 16; ++i) {
int pos = secp256k1_testrand_int(8);
if (x->v[pos] > 0 && x->v[pos + 1] <= 0x3fffffff) {
x->v[pos] -= 0x40000000;
x->v[pos + 1] += 1;
} else if (x->v[pos] < 0 && x->v[pos + 1] >= 0x3fffffff) {
x->v[pos] += 0x40000000;
x->v[pos + 1] -= 1;
}
}
}
/* Test secp256k1_modinv32{_var}, using inputs in 16-bit limb format, and returning inverse. */
void test_modinv32_uint16(uint16_t* out, const uint16_t* in, const uint16_t* mod) {
uint16_t tmp[16];
secp256k1_modinv32_signed30 x;
secp256k1_modinv32_modinfo m;
int i, vartime, nonzero;
uint16_to_signed30(&x, in);
nonzero = (x.v[0] | x.v[1] | x.v[2] | x.v[3] | x.v[4] | x.v[5] | x.v[6] | x.v[7] | x.v[8]) != 0;
uint16_to_signed30(&m.modulus, mod);
mutate_sign_signed30(&m.modulus);
/* compute 1/modulus mod 2^30 */
m.modulus_inv30 = modinv2p64(m.modulus.v[0]) & 0x3fffffff;
CHECK(((m.modulus_inv30 * m.modulus.v[0]) & 0x3fffffff) == 1);
for (vartime = 0; vartime < 2; ++vartime) {
/* compute inverse */
(vartime ? secp256k1_modinv32_var : secp256k1_modinv32)(&x, &m);
/* produce output */
signed30_to_uint16(out, &x);
/* check if the inverse times the input is 1 (mod m), unless x is 0. */
mulmod256(tmp, out, in, mod);
CHECK(tmp[0] == nonzero);
for (i = 1; i < 16; ++i) CHECK(tmp[i] == 0);
/* invert again */
(vartime ? secp256k1_modinv32_var : secp256k1_modinv32)(&x, &m);
/* check if the result is equal to the input */
signed30_to_uint16(tmp, &x);
for (i = 0; i < 16; ++i) CHECK(tmp[i] == in[i]);
}
}
#ifdef SECP256K1_WIDEMUL_INT128
/* Convert a 256-bit number represented as 16 uint16_t's to signed62 notation. */
void uint16_to_signed62(secp256k1_modinv64_signed62* out, const uint16_t* in) {
int i;
memset(out->v, 0, sizeof(out->v));
for (i = 0; i < 256; ++i) {
out->v[i / 62] |= (int64_t)(((in[i >> 4]) >> (i & 15)) & 1) << (i % 62);
}
}
/* Convert a 256-bit number in signed62 notation to a representation as 16 uint16_t's. */
void signed62_to_uint16(uint16_t* out, const secp256k1_modinv64_signed62* in) {
int i;
memset(out, 0, 32);
for (i = 0; i < 256; ++i) {
out[i >> 4] |= (((in->v[i / 62]) >> (i % 62)) & 1) << (i & 15);
}
}
/* Randomly mutate the sign of limbs in signed62 representation, without changing the value. */
void mutate_sign_signed62(secp256k1_modinv64_signed62* x) {
static const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
int i;
for (i = 0; i < 8; ++i) {
int pos = secp256k1_testrand_int(4);
if (x->v[pos] > 0 && x->v[pos + 1] <= M62) {
x->v[pos] -= (M62 + 1);
x->v[pos + 1] += 1;
} else if (x->v[pos] < 0 && x->v[pos + 1] >= -M62) {
x->v[pos] += (M62 + 1);
x->v[pos + 1] -= 1;
}
}
}
/* Test secp256k1_modinv64{_var}, using inputs in 16-bit limb format, and returning inverse. */
void test_modinv64_uint16(uint16_t* out, const uint16_t* in, const uint16_t* mod) {
static const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
uint16_t tmp[16];
secp256k1_modinv64_signed62 x;
secp256k1_modinv64_modinfo m;
int i, vartime, nonzero;
uint16_to_signed62(&x, in);
nonzero = (x.v[0] | x.v[1] | x.v[2] | x.v[3] | x.v[4]) != 0;
uint16_to_signed62(&m.modulus, mod);
mutate_sign_signed62(&m.modulus);
/* compute 1/modulus mod 2^62 */
m.modulus_inv62 = modinv2p64(m.modulus.v[0]) & M62;
CHECK(((m.modulus_inv62 * m.modulus.v[0]) & M62) == 1);
for (vartime = 0; vartime < 2; ++vartime) {
/* compute inverse */
(vartime ? secp256k1_modinv64_var : secp256k1_modinv64)(&x, &m);
/* produce output */
signed62_to_uint16(out, &x);
/* check if the inverse times the input is 1 (mod m), unless x is 0. */
mulmod256(tmp, out, in, mod);
CHECK(tmp[0] == nonzero);
for (i = 1; i < 16; ++i) CHECK(tmp[i] == 0);
/* invert again */
(vartime ? secp256k1_modinv64_var : secp256k1_modinv64)(&x, &m);
/* check if the result is equal to the input */
signed62_to_uint16(tmp, &x);
for (i = 0; i < 16; ++i) CHECK(tmp[i] == in[i]);
}
}
#endif
/* test if a and b are coprime */
int coprime(const uint16_t* a, const uint16_t* b) {
uint16_t x[16], y[16], t[16];
int i;
int iszero;
memcpy(x, a, 32);
memcpy(y, b, 32);
/* simple gcd loop: while x!=0, (x,y)=(y%x,x) */
while (1) {
iszero = 1;
for (i = 0; i < 16; ++i) {
if (x[i] != 0) {
iszero = 0;
break;
}
}
if (iszero) break;
mulmod256(t, y, NULL, x);
memcpy(y, x, 32);
memcpy(x, t, 32);
}
/* return whether y=1 */
if (y[0] != 1) return 0;
for (i = 1; i < 16; ++i) {
if (y[i] != 0) return 0;
}
return 1;
}
void run_modinv_tests(void) {
/* Fixed test cases. Each tuple is (input, modulus, output), each as 16x16 bits in LE order. */
static const uint16_t CASES[][3][16] = {
/* Test case known to need 713 divsteps */
{{0x1513, 0x5389, 0x54e9, 0x2798, 0x1957, 0x66a0, 0x8057, 0x3477,
0x7784, 0x1052, 0x326a, 0x9331, 0x6506, 0xa95c, 0x91f3, 0xfb5e},
{0x2bdd, 0x8df4, 0xcc61, 0x481f, 0xdae5, 0x5ca7, 0xf43b, 0x7d54,
0x13d6, 0x469b, 0x2294, 0x20f4, 0xb2a4, 0xa2d1, 0x3ff1, 0xfd4b},
{0xffd8, 0xd9a0, 0x456e, 0x81bb, 0xbabd, 0x6cea, 0x6dbd, 0x73ab,
0xbb94, 0x3d3c, 0xdf08, 0x31c4, 0x3e32, 0xc179, 0x2486, 0xb86b}},
/* Test case known to need 589 divsteps, reaching delta=-140 and
delta=141. */
{{0x3fb1, 0x903b, 0x4eb7, 0x4813, 0xd863, 0x26bf, 0xd89f, 0xa8a9,
0x02fe, 0x57c6, 0x554a, 0x4eab, 0x165e, 0x3d61, 0xee1e, 0x456c},
{0x9295, 0x823b, 0x5c1f, 0x5386, 0x48e0, 0x02ff, 0x4c2a, 0xa2da,
0xe58f, 0x967c, 0xc97e, 0x3f5a, 0x69fb, 0x52d9, 0x0a86, 0xb4a3},
{0x3d30, 0xb893, 0xa809, 0xa7a8, 0x26f5, 0x5b42, 0x55be, 0xf4d0,
0x12c2, 0x7e6a, 0xe41a, 0x90c7, 0xebfa, 0xf920, 0x304e, 0x1419}},
/* Test case known to need 650 divsteps, and doing 65 consecutive (f,g/2) steps. */
{{0x8583, 0x5058, 0xbeae, 0xeb69, 0x48bc, 0x52bb, 0x6a9d, 0xcc94,
0x2a21, 0x87d5, 0x5b0d, 0x42f6, 0x5b8a, 0x2214, 0xe9d6, 0xa040},
{0x7531, 0x27cb, 0x7e53, 0xb739, 0x6a5f, 0x83f5, 0xa45c, 0xcb1d,
0x8a87, 0x1c9c, 0x51d7, 0x851c, 0xb9d8, 0x1fbe, 0xc241, 0xd4a3},
{0xcdb4, 0x275c, 0x7d22, 0xa906, 0x0173, 0xc054, 0x7fdf, 0x5005,
0x7fb8, 0x9059, 0xdf51, 0x99df, 0x2654, 0x8f6e, 0x070f, 0xb347}},
/* Test case with the group order as modulus, needing 635 divsteps. */
{{0x95ed, 0x6c01, 0xd113, 0x5ff1, 0xd7d0, 0x29cc, 0x5817, 0x6120,
0xca8e, 0xaad1, 0x25ae, 0x8e84, 0x9af6, 0x30bf, 0xf0ed, 0x1686},
{0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae,
0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x1631, 0xbf4a, 0x286a, 0x2716, 0x469f, 0x2ac8, 0x1312, 0xe9bc,
0x04f4, 0x304b, 0x9931, 0x113b, 0xd932, 0xc8f4, 0x0d0d, 0x01a1}},
/* Test case with the field size as modulus, needing 637 divsteps. */
{{0x9ec3, 0x1919, 0xca84, 0x7c11, 0xf996, 0x06f3, 0x5408, 0x6688,
0x1320, 0xdb8a, 0x632a, 0x0dcb, 0x8a84, 0x6bee, 0x9c95, 0xe34e},
{0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x18e5, 0x19b6, 0xdf92, 0x1aaa, 0x09fb, 0x8a3f, 0x52b0, 0x8701,
0xac0c, 0x2582, 0xda44, 0x9bcc, 0x6828, 0x1c53, 0xbd8f, 0xbd2c}},
/* Test case with the field size as modulus, needing 935 divsteps with
broken eta handling. */
{{0x1b37, 0xbdc3, 0x8bcd, 0x25e3, 0x1eae, 0x567d, 0x30b6, 0xf0d8,
0x9277, 0x0cf8, 0x9c2e, 0xecd7, 0x631d, 0xe38f, 0xd4f8, 0x5c93},
{0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x1622, 0xe05b, 0xe880, 0x7de9, 0x3e45, 0xb682, 0xee6c, 0x67ed,
0xa179, 0x15db, 0x6b0d, 0xa656, 0x7ccb, 0x8ef7, 0xa2ff, 0xe279}},
/* Test case with the group size as modulus, needing 981 divsteps with
broken eta handling. */
{{0xfeb9, 0xb877, 0xee41, 0x7fa3, 0x87da, 0x94c4, 0x9d04, 0xc5ae,
0x5708, 0x0994, 0xfc79, 0x0916, 0xbf32, 0x3ad8, 0xe11c, 0x5ca2},
{0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae,
0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x0f12, 0x075e, 0xce1c, 0x6f92, 0xc80f, 0xca92, 0x9a04, 0x6126,
0x4b6c, 0x57d6, 0xca31, 0x97f3, 0x1f99, 0xf4fd, 0xda4d, 0x42ce}},
/* Test case with the field size as modulus, input = 0. */
{{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}},
/* Test case with the field size as modulus, input = 1. */
{{0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}},
/* Test case with the field size as modulus, input = 2. */
{{0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0xfe18, 0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff}},
/* Test case with the field size as modulus, input = field - 1. */
{{0xfc2e, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0xfc2f, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0xfc2e, 0xffff, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}},
/* Test case with the group size as modulus, input = 0. */
{{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae,
0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}},
/* Test case with the group size as modulus, input = 1. */
{{0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae,
0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}},
/* Test case with the group size as modulus, input = 2. */
{{0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
{0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae,
0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x20a1, 0x681b, 0x2f46, 0xdfe9, 0x501d, 0x57a4, 0x6e73, 0x5d57,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff}},
/* Test case with the group size as modulus, input = group - 1. */
{{0x4140, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae,
0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x4141, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae,
0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{0x4140, 0xd036, 0x5e8c, 0xbfd2, 0xa03b, 0xaf48, 0xdce6, 0xbaae,
0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}}
};
int i, j, ok;
/* Test known inputs/outputs */
for (i = 0; (size_t)i < sizeof(CASES) / sizeof(CASES[0]); ++i) {
uint16_t out[16];
test_modinv32_uint16(out, CASES[i][0], CASES[i][1]);
for (j = 0; j < 16; ++j) CHECK(out[j] == CASES[i][2][j]);
#ifdef SECP256K1_WIDEMUL_INT128
test_modinv64_uint16(out, CASES[i][0], CASES[i][1]);
for (j = 0; j < 16; ++j) CHECK(out[j] == CASES[i][2][j]);
#endif
}
for (i = 0; i < 100 * count; ++i) {
/* 256-bit numbers in 16-uint16_t's notation */
static const uint16_t ZERO[16] = {0};
uint16_t xd[16]; /* the number (in range [0,2^256)) to be inverted */
uint16_t md[16]; /* the modulus (odd, in range [3,2^256)) */
uint16_t id[16]; /* the inverse of xd mod md */
/* generate random xd and md, so that md is odd, md>1, xd<md, and gcd(xd,md)=1 */
do {
/* generate random xd and md (with many subsequent 0s and 1s) */
secp256k1_testrand256_test((unsigned char*)xd);
secp256k1_testrand256_test((unsigned char*)md);
md[0] |= 1; /* modulus must be odd */
/* If modulus is 1, find another one. */
ok = md[0] != 1;
for (j = 1; j < 16; ++j) ok |= md[j] != 0;
mulmod256(xd, xd, NULL, md); /* Make xd = xd mod md */
} while (!(ok && coprime(xd, md)));
test_modinv32_uint16(id, xd, md);
#ifdef SECP256K1_WIDEMUL_INT128
test_modinv64_uint16(id, xd, md);
#endif
/* In a few cases, also test with input=0 */
if (i < count) {
test_modinv32_uint16(id, ZERO, md);
#ifdef SECP256K1_WIDEMUL_INT128
test_modinv64_uint16(id, ZERO, md);
#endif
}
}
}
/***** SCALAR TESTS *****/ /***** SCALAR TESTS *****/
void scalar_test(void) { void scalar_test(void) {
secp256k1_scalar s; secp256k1_scalar s;
secp256k1_scalar s1; secp256k1_scalar s1;
@ -5627,6 +6069,8 @@ int main(int argc, char **argv) {
run_ctz_tests(); run_ctz_tests();
run_modinv_tests();
run_sha256_tests(); run_sha256_tests();
run_hmac_sha256_tests(); run_hmac_sha256_tests();
run_rfc6979_hmac_sha256_tests(); run_rfc6979_hmac_sha256_tests();