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