@@ -2634,6 +2634,87 @@ void test_point_times_order(const secp256k1_gej *point) {
26342634 ge_equals_ge (& res3 , & secp256k1_ge_const_g );
26352635}
26362636
2637+ /* These scalars reach large (in absolute value) outputs when fed to secp256k1_scalar_split_lambda.
2638+ *
2639+ * They are computed as:
2640+ * - For a in [-2, -1, 0, 1, 2]:
2641+ * - For b in [-3, -1, 1, 3]:
2642+ * - Output (a*LAMBDA + (ORDER+b)/2) % ORDER
2643+ */
2644+ static const secp256k1_scalar scalars_near_split_bounds [20 ] = {
2645+ SECP256K1_SCALAR_CONST (0xd938a566 , 0x7f479e3e , 0xb5b3c7fa , 0xefdb3749 , 0x3aa0585c , 0xc5ea2367 , 0xe1b660db , 0x0209e6fc ),
2646+ SECP256K1_SCALAR_CONST (0xd938a566 , 0x7f479e3e , 0xb5b3c7fa , 0xefdb3749 , 0x3aa0585c , 0xc5ea2367 , 0xe1b660db , 0x0209e6fd ),
2647+ SECP256K1_SCALAR_CONST (0xd938a566 , 0x7f479e3e , 0xb5b3c7fa , 0xefdb3749 , 0x3aa0585c , 0xc5ea2367 , 0xe1b660db , 0x0209e6fe ),
2648+ SECP256K1_SCALAR_CONST (0xd938a566 , 0x7f479e3e , 0xb5b3c7fa , 0xefdb3749 , 0x3aa0585c , 0xc5ea2367 , 0xe1b660db , 0x0209e6ff ),
2649+ SECP256K1_SCALAR_CONST (0x2c9c52b3 , 0x3fa3cf1f , 0x5ad9e3fd , 0x77ed9ba5 , 0xb294b893 , 0x3722e9a5 , 0x00e698ca , 0x4cf7632d ),
2650+ SECP256K1_SCALAR_CONST (0x2c9c52b3 , 0x3fa3cf1f , 0x5ad9e3fd , 0x77ed9ba5 , 0xb294b893 , 0x3722e9a5 , 0x00e698ca , 0x4cf7632e ),
2651+ SECP256K1_SCALAR_CONST (0x2c9c52b3 , 0x3fa3cf1f , 0x5ad9e3fd , 0x77ed9ba5 , 0xb294b893 , 0x3722e9a5 , 0x00e698ca , 0x4cf7632f ),
2652+ SECP256K1_SCALAR_CONST (0x2c9c52b3 , 0x3fa3cf1f , 0x5ad9e3fd , 0x77ed9ba5 , 0xb294b893 , 0x3722e9a5 , 0x00e698ca , 0x4cf76330 ),
2653+ SECP256K1_SCALAR_CONST (0x7fffffff , 0xffffffff , 0xffffffff , 0xffffffff , 0xd576e735 , 0x57a4501d , 0xdfe92f46 , 0x681b209f ),
2654+ SECP256K1_SCALAR_CONST (0x7fffffff , 0xffffffff , 0xffffffff , 0xffffffff , 0xd576e735 , 0x57a4501d , 0xdfe92f46 , 0x681b20a0 ),
2655+ SECP256K1_SCALAR_CONST (0x7fffffff , 0xffffffff , 0xffffffff , 0xffffffff , 0xd576e735 , 0x57a4501d , 0xdfe92f46 , 0x681b20a1 ),
2656+ SECP256K1_SCALAR_CONST (0x7fffffff , 0xffffffff , 0xffffffff , 0xffffffff , 0xd576e735 , 0x57a4501d , 0xdfe92f46 , 0x681b20a2 ),
2657+ SECP256K1_SCALAR_CONST (0xd363ad4c , 0xc05c30e0 , 0xa5261c02 , 0x88126459 , 0xf85915d7 , 0x7825b696 , 0xbeebc5c2 , 0x833ede11 ),
2658+ SECP256K1_SCALAR_CONST (0xd363ad4c , 0xc05c30e0 , 0xa5261c02 , 0x88126459 , 0xf85915d7 , 0x7825b696 , 0xbeebc5c2 , 0x833ede12 ),
2659+ SECP256K1_SCALAR_CONST (0xd363ad4c , 0xc05c30e0 , 0xa5261c02 , 0x88126459 , 0xf85915d7 , 0x7825b696 , 0xbeebc5c2 , 0x833ede13 ),
2660+ SECP256K1_SCALAR_CONST (0xd363ad4c , 0xc05c30e0 , 0xa5261c02 , 0x88126459 , 0xf85915d7 , 0x7825b696 , 0xbeebc5c2 , 0x833ede14 ),
2661+ SECP256K1_SCALAR_CONST (0x26c75a99 , 0x80b861c1 , 0x4a4c3805 , 0x1024c8b4 , 0x704d760e , 0xe95e7cd3 , 0xde1bfdb1 , 0xce2c5a42 ),
2662+ SECP256K1_SCALAR_CONST (0x26c75a99 , 0x80b861c1 , 0x4a4c3805 , 0x1024c8b4 , 0x704d760e , 0xe95e7cd3 , 0xde1bfdb1 , 0xce2c5a43 ),
2663+ SECP256K1_SCALAR_CONST (0x26c75a99 , 0x80b861c1 , 0x4a4c3805 , 0x1024c8b4 , 0x704d760e , 0xe95e7cd3 , 0xde1bfdb1 , 0xce2c5a44 ),
2664+ SECP256K1_SCALAR_CONST (0x26c75a99 , 0x80b861c1 , 0x4a4c3805 , 0x1024c8b4 , 0x704d760e , 0xe95e7cd3 , 0xde1bfdb1 , 0xce2c5a45 )
2665+ };
2666+
2667+ void test_ecmult_target (const secp256k1_scalar * target , int mode ) {
2668+ /* Mode: 0=ecmult_gen, 1=ecmult, 2=ecmult_const */
2669+ secp256k1_scalar n1 , n2 ;
2670+ secp256k1_ge p ;
2671+ secp256k1_gej pj , p1j , p2j , ptj ;
2672+ static const secp256k1_scalar zero = SECP256K1_SCALAR_CONST (0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
2673+
2674+ /* Generate random n1,n2 such that n1+n2 = -target. */
2675+ random_scalar_order_test (& n1 );
2676+ secp256k1_scalar_add (& n2 , & n1 , target );
2677+ secp256k1_scalar_negate (& n2 , & n2 );
2678+
2679+ /* Generate a random input point. */
2680+ if (mode != 0 ) {
2681+ random_group_element_test (& p );
2682+ secp256k1_gej_set_ge (& pj , & p );
2683+ }
2684+
2685+ /* EC multiplications */
2686+ if (mode == 0 ) {
2687+ secp256k1_ecmult_gen (& ctx -> ecmult_gen_ctx , & p1j , & n1 );
2688+ secp256k1_ecmult_gen (& ctx -> ecmult_gen_ctx , & p2j , & n2 );
2689+ secp256k1_ecmult_gen (& ctx -> ecmult_gen_ctx , & ptj , target );
2690+ } else if (mode == 1 ) {
2691+ secp256k1_ecmult (& ctx -> ecmult_ctx , & p1j , & pj , & n1 , & zero );
2692+ secp256k1_ecmult (& ctx -> ecmult_ctx , & p2j , & pj , & n2 , & zero );
2693+ secp256k1_ecmult (& ctx -> ecmult_ctx , & ptj , & pj , target , & zero );
2694+ } else {
2695+ secp256k1_ecmult_const (& p1j , & p , & n1 , 256 );
2696+ secp256k1_ecmult_const (& p2j , & p , & n2 , 256 );
2697+ secp256k1_ecmult_const (& ptj , & p , target , 256 );
2698+ }
2699+
2700+ /* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */
2701+ secp256k1_gej_add_var (& ptj , & ptj , & p1j , NULL );
2702+ secp256k1_gej_add_var (& ptj , & ptj , & p2j , NULL );
2703+ CHECK (secp256k1_gej_is_infinity (& ptj ));
2704+ }
2705+
2706+ void run_ecmult_near_split_bound (void ) {
2707+ int i ;
2708+ unsigned j ;
2709+ for (i = 0 ; i < 4 * count ; ++ i ) {
2710+ for (j = 0 ; j < sizeof (scalars_near_split_bounds ) / sizeof (scalars_near_split_bounds [0 ]); ++ j ) {
2711+ test_ecmult_target (& scalars_near_split_bounds [j ], 0 );
2712+ test_ecmult_target (& scalars_near_split_bounds [j ], 1 );
2713+ test_ecmult_target (& scalars_near_split_bounds [j ], 2 );
2714+ }
2715+ }
2716+ }
2717+
26372718void run_point_times_order (void ) {
26382719 int i ;
26392720 secp256k1_fe x = SECP256K1_FE_CONST (0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 );
@@ -3555,14 +3636,12 @@ void run_ecmult_gen_blind(void) {
35553636
35563637#ifdef USE_ENDOMORPHISM
35573638/***** ENDOMORPHISH TESTS *****/
3558- void test_scalar_split (void ) {
3559- secp256k1_scalar full ;
3639+ void test_scalar_split (const secp256k1_scalar * full ) {
35603640 secp256k1_scalar s1 , slam ;
35613641 const unsigned char zero [32 ] = {0 };
35623642 unsigned char tmp [32 ];
35633643
3564- random_scalar_order_test (& full );
3565- secp256k1_scalar_split_lambda (& s1 , & slam , & full );
3644+ secp256k1_scalar_split_lambda (& s1 , & slam , full );
35663645
35673646 /* check that both are <= 128 bits in size */
35683647 if (secp256k1_scalar_is_high (& s1 )) {
@@ -3578,8 +3657,17 @@ void test_scalar_split(void) {
35783657 CHECK (memcmp (zero , tmp , 16 ) == 0 );
35793658}
35803659
3660+
35813661void run_endomorphism_tests (void ) {
3582- test_scalar_split ();
3662+ unsigned i ;
3663+ for (i = 0 ; i < 100U * count ; ++ i ) {
3664+ secp256k1_scalar full ;
3665+ random_scalar_order_test (& full );
3666+ test_scalar_split (& full );
3667+ }
3668+ for (i = 0 ; i < sizeof (scalars_near_split_bounds ) / sizeof (scalars_near_split_bounds [0 ]); ++ i ) {
3669+ test_scalar_split (& scalars_near_split_bounds [i ]);
3670+ }
35833671}
35843672#endif
35853673
@@ -5626,6 +5714,7 @@ int main(int argc, char **argv) {
56265714 /* ecmult tests */
56275715 run_wnaf ();
56285716 run_point_times_order ();
5717+ run_ecmult_near_split_bound ();
56295718 run_ecmult_chain ();
56305719 run_ecmult_constants ();
56315720 run_ecmult_gen_blind ();
0 commit comments