@@ -2633,6 +2633,87 @@ void test_point_times_order(const secp256k1_gej *point) {
2633
2633
ge_equals_ge (& res3 , & secp256k1_ge_const_g );
2634
2634
}
2635
2635
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
+
2636
2717
void run_point_times_order (void ) {
2637
2718
int i ;
2638
2719
secp256k1_fe x = SECP256K1_FE_CONST (0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 );
@@ -3552,14 +3633,12 @@ void run_ecmult_gen_blind(void) {
3552
3633
3553
3634
#ifdef USE_ENDOMORPHISM
3554
3635
/***** ENDOMORPHISH TESTS *****/
3555
- void test_scalar_split (void ) {
3556
- secp256k1_scalar full ;
3636
+ void test_scalar_split (const secp256k1_scalar * full ) {
3557
3637
secp256k1_scalar s1 , slam ;
3558
3638
const unsigned char zero [32 ] = {0 };
3559
3639
unsigned char tmp [32 ];
3560
3640
3561
- random_scalar_order_test (& full );
3562
- secp256k1_scalar_split_lambda (& s1 , & slam , & full );
3641
+ secp256k1_scalar_split_lambda (& s1 , & slam , full );
3563
3642
3564
3643
/* check that both are <= 128 bits in size */
3565
3644
if (secp256k1_scalar_is_high (& s1 )) {
@@ -3575,8 +3654,17 @@ void test_scalar_split(void) {
3575
3654
CHECK (secp256k1_memcmp_var (zero , tmp , 16 ) == 0 );
3576
3655
}
3577
3656
3657
+
3578
3658
void run_endomorphism_tests (void ) {
3579
- test_scalar_split ();
3659
+ unsigned i ;
3660
+ for (i = 0 ; i < 100U * count ; ++ i ) {
3661
+ secp256k1_scalar full ;
3662
+ random_scalar_order_test (& full );
3663
+ test_scalar_split (& full );
3664
+ }
3665
+ for (i = 0 ; i < sizeof (scalars_near_split_bounds ) / sizeof (scalars_near_split_bounds [0 ]); ++ i ) {
3666
+ test_scalar_split (& scalars_near_split_bounds [i ]);
3667
+ }
3580
3668
}
3581
3669
#endif
3582
3670
@@ -5596,6 +5684,7 @@ int main(int argc, char **argv) {
5596
5684
/* ecmult tests */
5597
5685
run_wnaf ();
5598
5686
run_point_times_order ();
5687
+ run_ecmult_near_split_bound ();
5599
5688
run_ecmult_chain ();
5600
5689
run_ecmult_constants ();
5601
5690
run_ecmult_gen_blind ();
0 commit comments