Jonas Nick
2023-07-27 18:57:30 +00:00
36 changed files with 333 additions and 337 deletions

View File

@@ -89,16 +89,6 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) {
(*p)--;
}
static void random_field_element_test(secp256k1_fe *fe) {
do {
unsigned char b32[32];
secp256k1_testrand256_test(b32);
if (secp256k1_fe_set_b32_limit(fe, b32)) {
break;
}
} while(1);
}
static void random_field_element_magnitude(secp256k1_fe *fe) {
secp256k1_fe zero;
int n = secp256k1_testrand_int(9);
@@ -108,17 +98,33 @@ static void random_field_element_magnitude(secp256k1_fe *fe) {
}
secp256k1_fe_clear(&zero);
secp256k1_fe_negate(&zero, &zero, 0);
secp256k1_fe_mul_int(&zero, n - 1);
secp256k1_fe_mul_int_unchecked(&zero, n - 1);
secp256k1_fe_add(fe, &zero);
#ifdef VERIFY
CHECK(fe->magnitude == n);
#endif
}
static void random_fe_test(secp256k1_fe *x) {
unsigned char bin[32];
do {
secp256k1_testrand256_test(bin);
if (secp256k1_fe_set_b32_limit(x, bin)) {
return;
}
} while(1);
}
static void random_fe_non_zero_test(secp256k1_fe *fe) {
do {
random_fe_test(fe);
} while(secp256k1_fe_is_zero(fe));
}
static void random_group_element_test(secp256k1_ge *ge) {
secp256k1_fe fe;
do {
random_field_element_test(&fe);
random_fe_test(&fe);
if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_testrand_bits(1))) {
secp256k1_fe_normalize(&ge->y);
break;
@@ -129,12 +135,7 @@ static void random_group_element_test(secp256k1_ge *ge) {
static void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) {
secp256k1_fe z2, z3;
do {
random_field_element_test(&gej->z);
if (!secp256k1_fe_is_zero(&gej->z)) {
break;
}
} while(1);
random_fe_non_zero_test(&gej->z);
secp256k1_fe_sqr(&z2, &gej->z);
secp256k1_fe_mul(&z3, &z2, &gej->z);
secp256k1_fe_mul(&gej->x, &ge->x, &z2);
@@ -226,6 +227,35 @@ static void run_util_tests(void) {
}
}
static void run_xoshiro256pp_tests(void) {
{
size_t i;
/* Sanity check that we run before the actual seeding. */
for (i = 0; i < sizeof(secp256k1_test_state)/sizeof(secp256k1_test_state[0]); i++) {
CHECK(secp256k1_test_state[i] == 0);
}
}
{
int i;
unsigned char buf32[32];
unsigned char seed16[16] = {
'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
'C', 'H', 'I', 'C', 'K', 'E', 'N', '!',
};
unsigned char buf32_expected[32] = {
0xAF, 0xCC, 0xA9, 0x16, 0xB5, 0x6C, 0xE3, 0xF0,
0x44, 0x3F, 0x45, 0xE0, 0x47, 0xA5, 0x08, 0x36,
0x4C, 0xCC, 0xC1, 0x18, 0xB2, 0xD8, 0x8F, 0xEF,
0x43, 0x26, 0x15, 0x57, 0x37, 0x00, 0xEF, 0x30,
};
secp256k1_testrand_seed(seed16);
for (i = 0; i < 17; i++) {
secp256k1_testrand256(buf32);
}
CHECK(secp256k1_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0);
}
}
static void run_selftest_tests(void) {
/* Test public API */
secp256k1_selftest();
@@ -869,78 +899,6 @@ static void run_tagged_sha256_tests(void) {
CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0);
}
/***** RANDOM TESTS *****/
static void test_rand_bits(int rand32, int bits) {
/* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to
* get a false negative chance below once in a billion */
static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316};
/* We try multiplying the results with various odd numbers, which shouldn't
* influence the uniform distribution modulo a power of 2. */
static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011};
/* We only select up to 6 bits from the output to analyse */
unsigned int usebits = bits > 6 ? 6 : bits;
unsigned int maxshift = bits - usebits;
/* For each of the maxshift+1 usebits-bit sequences inside a bits-bit
number, track all observed outcomes, one per bit in a uint64_t. */
uint64_t x[6][27] = {{0}};
unsigned int i, shift, m;
/* 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_testrand32() : secp256k1_testrand_bits(bits));
CHECK((((uint64_t)r) >> bits) == 0);
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
uint32_t rm = r * mults[m];
for (shift = 0; shift <= maxshift; shift++) {
x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1)));
}
}
}
for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) {
for (shift = 0; shift <= maxshift; shift++) {
/* Test that the lower usebits bits of x[shift] are 1 */
CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0);
}
}
}
/* Subrange must be a whole divisor of range, and at most 64 */
static void test_rand_int(uint32_t range, uint32_t subrange) {
/* (1-1/subrange)^rounds < 1/10^9 */
int rounds = (subrange * 2073) / 100;
int i;
uint64_t x = 0;
CHECK((range % subrange) == 0);
for (i = 0; i < rounds; i++) {
uint32_t r = secp256k1_testrand_int(range);
CHECK(r < range);
r = r % subrange;
x |= (((uint64_t)1) << r);
}
/* Test that the lower subrange bits of x are 1. */
CHECK(((~x) << (64 - subrange)) == 0);
}
static void run_rand_bits(void) {
size_t b;
test_rand_bits(1, 32);
for (b = 1; b <= 32; b++) {
test_rand_bits(0, b);
}
}
static void run_rand_int(void) {
static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432};
static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64};
unsigned int m, s;
for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) {
for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) {
test_rand_int(ms[m] * ss[s], ss[s]);
}
}
}
/***** MODINV TESTS *****/
/* Compute the modular inverse of (odd) x mod 2^64. */
@@ -3154,16 +3112,6 @@ static void random_fe(secp256k1_fe *x) {
} while(1);
}
static void random_fe_test(secp256k1_fe *x) {
unsigned char bin[32];
do {
secp256k1_testrand256_test(bin);
if (secp256k1_fe_set_b32_limit(x, bin)) {
return;
}
} while(1);
}
static void random_fe_non_zero(secp256k1_fe *nz) {
int tries = 10;
while (--tries >= 0) {
@@ -3404,7 +3352,7 @@ static void run_field_misc(void) {
CHECK(q.normalized && q.magnitude == 1);
#endif
for (j = 0; j < 6; j++) {
secp256k1_fe_negate(&z, &z, j+1);
secp256k1_fe_negate_unchecked(&z, &z, j+1);
secp256k1_fe_normalize_var(&q);
secp256k1_fe_cmov(&q, &z, (j&1));
#ifdef VERIFY
@@ -3990,18 +3938,14 @@ static void test_ge(void) {
}
/* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */
do {
random_field_element_test(&zf);
} while(secp256k1_fe_is_zero(&zf));
random_fe_non_zero_test(&zf);
random_field_element_magnitude(&zf);
secp256k1_fe_inv_var(&zfi3, &zf);
secp256k1_fe_sqr(&zfi2, &zfi3);
secp256k1_fe_mul(&zfi3, &zfi3, &zfi2);
/* Generate random r */
do {
random_field_element_test(&r);
} while(secp256k1_fe_is_zero(&r));
random_fe_non_zero_test(&r);
for (i1 = 0; i1 < 1 + 4 * runs; i1++) {
int i2;
@@ -4218,22 +4162,15 @@ static void test_add_neg_y_diff_x(void) {
* which this test is a regression test for.
*
* These points were generated in sage as
* # secp256k1 params
* F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F)
* C = EllipticCurve ([F (0), F (7)])
* G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798)
* N = FiniteField(G.order())
*
* # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F)
* x = polygen(N)
* lam = (1 - x^3).roots()[1][0]
* load("secp256k1_params.sage")
*
* # random "bad pair"
* P = C.random_element()
* Q = -int(lam) * P
* print " P: %x %x" % P.xy()
* print " Q: %x %x" % Q.xy()
* print "P + Q: %x %x" % (P + Q).xy()
* Q = -int(LAMBDA) * P
* print(" P: %x %x" % P.xy())
* print(" Q: %x %x" % Q.xy())
* print("P + Q: %x %x" % (P + Q).xy())
*/
secp256k1_gej aj = SECP256K1_GEJ_CONST(
0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30,
@@ -4318,10 +4255,7 @@ static void run_gej(void) {
CHECK(!secp256k1_gej_eq_var(&a, &b));
b = a;
random_field_element_test(&fe);
if (secp256k1_fe_is_zero(&fe)) {
continue;
}
random_fe_non_zero_test(&fe);
secp256k1_gej_rescale(&a, &fe);
CHECK(secp256k1_gej_eq_var(&a, &b));
}
@@ -4866,9 +4800,7 @@ static void ecmult_const_mult_xonly(void) {
random_scalar_order_test(&q);
/* If i is odd, n=d*base.x for random non-zero d */
if (i & 1) {
do {
random_field_element_test(&d);
} while (secp256k1_fe_normalizes_to_zero_var(&d));
random_fe_non_zero_test(&d);
secp256k1_fe_mul(&n, &base.x, &d);
} else {
n = base.x;
@@ -4887,22 +4819,17 @@ static void ecmult_const_mult_xonly(void) {
/* Test that secp256k1_ecmult_const_xonly correctly rejects X coordinates not on curve. */
for (i = 0; i < 2*COUNT; ++i) {
secp256k1_fe x, n, d, c, r;
secp256k1_fe x, n, d, r;
int res;
secp256k1_scalar q;
random_scalar_order_test(&q);
/* Generate random X coordinate not on the curve. */
do {
random_field_element_test(&x);
secp256k1_fe_sqr(&c, &x);
secp256k1_fe_mul(&c, &c, &x);
secp256k1_fe_add_int(&c, SECP256K1_B);
} while (secp256k1_fe_is_square_var(&c));
random_fe_test(&x);
} while (secp256k1_ge_x_on_curve_var(&x));
/* If i is odd, n=d*x for random non-zero d. */
if (i & 1) {
do {
random_field_element_test(&d);
} while (secp256k1_fe_normalizes_to_zero_var(&d));
random_fe_non_zero_test(&d);
secp256k1_fe_mul(&n, &x, &d);
} else {
n = x;
@@ -8073,6 +8000,9 @@ int main(int argc, char **argv) {
}
printf("test count = %i\n", COUNT);
/* run test RNG tests (must run before we really initialize the test RNG) */
run_xoshiro256pp_tests();
/* find random seed */
secp256k1_testrand_init(argc > 2 ? argv[2] : NULL);
@@ -8110,9 +8040,7 @@ int main(int argc, char **argv) {
/* scratch tests */
run_scratch_tests();
/* randomness tests */
run_rand_bits();
run_rand_int();
/* util tests */
run_util_tests();
/* integer arithmetic tests */