@@ -2634,6 +2634,87 @@ void test_point_times_order(const secp256k1_gej *point) {
2634
2634
ge_equals_ge (& res3 , & secp256k1_ge_const_g );
2635
2635
}
2636
2636
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
+
2637
2718
void run_point_times_order (void ) {
2638
2719
int i ;
2639
2720
secp256k1_fe x = SECP256K1_FE_CONST (0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 );
@@ -3555,14 +3636,12 @@ void run_ecmult_gen_blind(void) {
3555
3636
3556
3637
#ifdef USE_ENDOMORPHISM
3557
3638
/***** ENDOMORPHISH TESTS *****/
3558
- void test_scalar_split (void ) {
3559
- secp256k1_scalar full ;
3639
+ void test_scalar_split (const secp256k1_scalar * full ) {
3560
3640
secp256k1_scalar s1 , slam ;
3561
3641
const unsigned char zero [32 ] = {0 };
3562
3642
unsigned char tmp [32 ];
3563
3643
3564
- random_scalar_order_test (& full );
3565
- secp256k1_scalar_split_lambda (& s1 , & slam , & full );
3644
+ secp256k1_scalar_split_lambda (& s1 , & slam , full );
3566
3645
3567
3646
/* check that both are <= 128 bits in size */
3568
3647
if (secp256k1_scalar_is_high (& s1 )) {
@@ -3578,8 +3657,17 @@ void test_scalar_split(void) {
3578
3657
CHECK (memcmp (zero , tmp , 16 ) == 0 );
3579
3658
}
3580
3659
3660
+
3581
3661
void 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
+ }
3583
3671
}
3584
3672
#endif
3585
3673
@@ -5626,6 +5714,7 @@ int main(int argc, char **argv) {
5626
5714
/* ecmult tests */
5627
5715
run_wnaf ();
5628
5716
run_point_times_order ();
5717
+ run_ecmult_near_split_bound ();
5629
5718
run_ecmult_chain ();
5630
5719
run_ecmult_constants ();
5631
5720
run_ecmult_gen_blind ();
0 commit comments