LCOV - code coverage report
Current view: top level - ballet/secp256k1 - fd_secp256k1_s2n.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 329 329 100.0 %
Date: 2026-03-31 06:22:16 Functions: 31 31 100.0 %

          Line data    Source code
       1             : #include <stdint.h>
       2             : #include <s2n-bignum.h>
       3             : 
       4             : /* Scalars */
       5             : 
       6             : static inline int
       7      120213 : fd_secp256k1_scalar_is_zero( fd_secp256k1_scalar_t const *r ) {
       8      120213 :   return fd_uint256_eq( r, fd_secp256k1_const_zero );
       9      120213 : }
      10             : 
      11             : /* Returns the scalar in NON Montgomery form. */
      12             : static inline fd_secp256k1_scalar_t *
      13             : fd_secp256k1_scalar_frombytes( fd_secp256k1_scalar_t * r,
      14      120231 :                                uchar const             input[ 32 ] ) {
      15      120231 :   memcpy( r, input, 32 );
      16      120231 :   fd_uint256_bswap( r, r );
      17             : 
      18             :   /*
      19             :     The verifier SHALL check that 0 < r' < q and 0 < s' < q.
      20             :     The r' element is parsed as a scalar, and checked against r' < n.
      21             :     Later it is re-used as fp_t, however n < p, so we do not need to
      22             :     perform any additional checks after this.
      23             :   */
      24      120231 :   if( FD_UNLIKELY( fd_uint256_cmp( r, fd_secp256k1_const_n ) >= 0 ) ) {
      25          18 :     return NULL;
      26          18 :   }
      27      120213 :   if( FD_UNLIKELY( fd_secp256k1_scalar_is_zero( r ) ) ) {
      28          15 :     return NULL;
      29          15 :   }
      30      120198 :   return r;
      31      120213 : }
      32             : 
      33             : /* r = 1 / a
      34             :    Operates on scalars NOT in the montgomery domain.
      35             :    a MUST not be 0. */
      36             : fd_secp256k1_scalar_t *
      37             : fd_secp256k1_scalar_invert( fd_secp256k1_scalar_t *       r,
      38       30060 :                             fd_secp256k1_scalar_t const * a ) {
      39       30060 :   ulong t[ 12 ];
      40       30060 :   bignum_modinv( 4, r->limbs, (ulong *)a->limbs, (ulong *)fd_secp256k1_const_n[ 0 ].limbs, t );
      41       30060 :   return r;
      42       30060 : }
      43             : 
      44             : /* None of the arguments may alias. */
      45             : static inline fd_secp256k1_scalar_t *
      46             : fd_secp256k1_scalar_mul( fd_secp256k1_scalar_t *       restrict r,
      47             :                          fd_secp256k1_scalar_t const * restrict a,
      48       60120 :                          fd_secp256k1_scalar_t const * restrict b ) {
      49       60120 :   bignum_montmul( 4, r->limbs, (ulong *)a->limbs, (ulong *)b->limbs, (ulong *)fd_secp256k1_const_n[0].limbs );
      50       60120 :   return r;
      51       60120 : }
      52             : 
      53             : /* r = -a */
      54             : static inline fd_secp256k1_scalar_t *
      55             : fd_secp256k1_scalar_negate( fd_secp256k1_scalar_t *       r,
      56       30060 :                             fd_secp256k1_scalar_t const * a ) {
      57             :   /* We cannot use bignum_modsub() as it requires a < n /\ b < n.
      58             : 
      59             :      The best way to implement it using the current API is to use
      60             :      bignum_sub(n, a), getting a reuslt bound within [0, n+1). Then
      61             :      we perform a second reduction from [0, n+1) to [0, n) with
      62             :      bignum_mod_n256k1_4(). */
      63             : 
      64             :   /* t \in [0, n + 1). There is not carry-out, as a < n. */
      65       30060 :   ulong t[4];
      66       30060 :   bignum_sub( 4, t, 4, (ulong *)fd_secp256k1_const_n[ 0 ].limbs, 4, (ulong *)a->limbs );
      67       30060 :   bignum_mod_n256k1_4( r->limbs, t );
      68       30060 :   return r;
      69       30060 : }
      70             : 
      71             : static inline fd_secp256k1_scalar_t *
      72             : fd_secp256k1_scalar_tomont( fd_secp256k1_scalar_t *       r,
      73       90180 :                             fd_secp256k1_scalar_t const * a ) {
      74             :   /* bignum_montmul has an undocumented restriction
      75             :      that the input and outputs may not alias. */
      76       90180 :   ulong t[4];
      77       90180 :   memcpy( t, a->limbs, 32 );
      78       90180 :   bignum_montmul( 4, r->limbs, t, (ulong *)fd_secp256k1_const_scalar_rr_mont, (ulong *)fd_secp256k1_const_n[ 0 ].limbs );
      79       90180 :   return r;
      80       90180 : }
      81             : 
      82             : static inline fd_secp256k1_scalar_t *
      83             : fd_secp256k1_scalar_demont( fd_secp256k1_scalar_t *       r,
      84       60120 :                             fd_secp256k1_scalar_t const * a ) {
      85       60120 :   bignum_demont( 4, r->limbs, (ulong *)a->limbs, (ulong *)fd_secp256k1_const_n[ 0 ].limbs );
      86       60120 :   return r;
      87       60120 : }
      88             : 
      89             : /* Field */
      90             : 
      91             : static inline fd_secp256k1_fp_t *
      92             : fd_secp256k1_fp_set( fd_secp256k1_fp_t *       r,
      93     4687968 :                      fd_secp256k1_fp_t const * a ) {
      94     4687968 :   r->limbs[ 0 ] = a->limbs[ 0 ];
      95     4687968 :   r->limbs[ 1 ] = a->limbs[ 1 ];
      96     4687968 :   r->limbs[ 2 ] = a->limbs[ 2 ];
      97     4687968 :   r->limbs[ 3 ] = a->limbs[ 3 ];
      98     4687968 :   return r;
      99     4687968 : }
     100             : 
     101             : /* r = (a == b) */
     102             : static inline int
     103             : fd_secp256k1_fp_eq( fd_secp256k1_fp_t const * a,
     104      180324 :                     fd_secp256k1_fp_t const * b ) {
     105      180324 :   return fd_uint256_eq( a, b );
     106      180324 : }
     107             : 
     108             : /* r = a + b */
     109             : static inline fd_secp256k1_fp_t *
     110             : fd_secp256k1_fp_add( fd_secp256k1_fp_t *       r,
     111             :                      fd_secp256k1_fp_t const * a,
     112    99856464 :                      fd_secp256k1_fp_t const * b ) {
     113    99856464 :   bignum_add_p256k1( r->limbs, (ulong *)a->limbs, (ulong *)b->limbs );
     114    99856464 :   return r;
     115    99856464 : }
     116             : 
     117             : /* r = a - b */
     118             : static inline fd_secp256k1_fp_t *
     119             : fd_secp256k1_fp_sub( fd_secp256k1_fp_t *       r,
     120             :                      fd_secp256k1_fp_t const * a,
     121    26722455 :                      fd_secp256k1_fp_t const * b ) {
     122    26722455 :   bignum_sub_p256k1( r->limbs, (ulong *)a->limbs, (ulong *)b->limbs );
     123    26722455 :   return r;
     124    26722455 : }
     125             : 
     126             : /* r = 2 * a */
     127             : static inline fd_secp256k1_fp_t *
     128             : fd_secp256k1_fp_dbl( fd_secp256k1_fp_t *       r,
     129   101481144 :                      fd_secp256k1_fp_t const * a ) {
     130   101481144 :   bignum_double_p256k1( r->limbs, (ulong *)a->limbs );
     131   101481144 :   return r;
     132   101481144 : }
     133             : 
     134             : /* r = a * b */
     135             : static inline fd_secp256k1_fp_t *
     136             : fd_secp256k1_fp_mul( fd_secp256k1_fp_t *       r,
     137             :                      fd_secp256k1_fp_t const * a,
     138    93604212 :                      fd_secp256k1_fp_t const * b ) {
     139    93604212 :   bignum_montmul_p256k1( r->limbs, (ulong *)a->limbs, (ulong *)b->limbs );
     140    93604212 :   return r;
     141    93604212 : }
     142             : 
     143             : /* r = a^2 */
     144             : static inline fd_secp256k1_fp_t *
     145             : fd_secp256k1_fp_sqr( fd_secp256k1_fp_t *       r,
     146    31193100 :                      fd_secp256k1_fp_t const * a ) {
     147    31193100 :   bignum_montsqr_p256k1( r->limbs, (ulong *)a->limbs );
     148    31193100 :   return r;
     149    31193100 : }
     150             : 
     151             : /* r = -a */
     152             : static inline fd_secp256k1_fp_t *
     153             : fd_secp256k1_fp_negate( fd_secp256k1_fp_t *       r,
     154     2043414 :                         fd_secp256k1_fp_t const * a ) {
     155     2043414 :   bignum_neg_p256k1( r->limbs, (ulong *)a->limbs );
     156     2043414 :   return r;
     157     2043414 : }
     158             : 
     159             : static inline int
     160       30060 : fd_secp256k1_fp_is_odd( fd_secp256k1_fp_t const *r ) {
     161       30060 :   fd_secp256k1_fp_t scratch[1];
     162       30060 :   bignum_demont_p256k1( scratch->limbs, (ulong *)r->limbs );
     163       30060 :   return scratch->limbs[ 0 ] & 1;
     164       30060 : }
     165             : 
     166             : /* r = 1 / a
     167             :    a MUST not be 0. */
     168             : static inline fd_secp256k1_fp_t *
     169             : fd_secp256k1_fp_invert( fd_secp256k1_fp_t *       r,
     170       30060 :                         fd_secp256k1_fp_t const * a ) {
     171       30060 :   fd_secp256k1_fp_t ad[1];
     172       30060 :   bignum_demont_p256k1( ad->limbs, (ulong *)a->limbs );
     173       30060 :   ulong t[ 12 ];
     174       30060 :   bignum_modinv( 4, r->limbs, (ulong *)ad->limbs, (ulong *)fd_secp256k1_const_p[0].limbs, t );
     175       30060 :   bignum_tomont_p256k1( r->limbs, (ulong *)r->limbs );
     176       30060 :   return r;
     177       30060 : }
     178             : 
     179             : static inline uchar *
     180             : fd_secp256k1_fp_tobytes( uchar                    r[ 32 ],
     181       60120 :                          fd_secp256k1_fp_t const *a ) {
     182       60120 :   fd_secp256k1_fp_t swapped[1];
     183       60120 :   bignum_demont_p256k1( swapped->limbs, (ulong *)a->limbs );
     184       60120 :   fd_uint256_bswap( swapped, swapped );
     185       60120 :   memcpy( r, swapped->buf, 32 );
     186       60120 :   return r;
     187       60120 : }
     188             : 
     189             : /*
     190             :   Returns NULL if a is not a square.
     191             :   r may NOT alias a
     192             : 
     193             :   r = a^((p + 1) / 4) mod p
     194             : 
     195             :   We know that a^((p-1)/2) = 1 when a is a quadratic residue.
     196             :   So for a valid square, we can show that re-squaring recovers a with:
     197             :     (a^((p+1)/4))^2 = a^((p+1)/1)
     198             :                     = a * a^((p-1)/2)
     199             :                     = a (if a is a square)
     200             : 
     201             :   We use a more optimal addition-chain which takes advantage that quite
     202             :   a few of the powers consist of all 1s when in binary form. We build up:
     203             :     x2    = a^3
     204             :     x3    = a^7
     205             :     x6    = a^63
     206             :     x9    = a^511
     207             :     x11   = a^2047
     208             :     x22   = a^(2^22 − 1) # All of these are all 1s
     209             :     x44   = a^(2^44 − 1)
     210             :     x88   = a^(2^88 − 1)
     211             :     x176  = a^(2^176 − 1)
     212             :     x220  = a^(2^220 − 1)
     213             :     x223  = a^(2^223 − 1)
     214             : 
     215             :   These "all 1s" exponents are convenient because:
     216             :     (2^k - 1)*(2^m)+(2^m - 1) = 2^(k+m) - 1
     217             :   Allowing us to quickly build them.
     218             : 
     219             :   If a is NOT a square, then
     220             :     a^((p-1)/2) = -1
     221             :   and the result will fail the final verification.
     222             : */
     223             : static inline fd_secp256k1_fp_t *
     224             : fd_secp256k1_fp_sqrt( fd_secp256k1_fp_t *       restrict r,
     225       60084 :                       fd_secp256k1_fp_t const * restrict a ) {
     226       60084 :   fd_secp256k1_fp_t x2;
     227       60084 :   fd_secp256k1_fp_t x3;
     228             : 
     229       60084 :   fd_secp256k1_fp_sqr( &x2, a );
     230       60084 :   fd_secp256k1_fp_mul( &x2, &x2, a );
     231             : 
     232       60084 :   fd_secp256k1_fp_sqr( &x3, &x2 );
     233       60084 :   fd_secp256k1_fp_mul( &x3, &x3, a );
     234             : 
     235       60084 :   fd_secp256k1_fp_t x6 = x3;
     236      240336 :   for( int j=0; j<3; j++ ) fd_secp256k1_fp_sqr( &x6, &x6 );
     237       60084 :   fd_secp256k1_fp_mul( &x6, &x6, &x3 );
     238             : 
     239       60084 :   fd_secp256k1_fp_t x9 = x6;
     240      240336 :   for( int j=0; j<3; j++ ) fd_secp256k1_fp_sqr( &x9, &x9 );
     241       60084 :   fd_secp256k1_fp_mul( &x9, &x9, &x3 );
     242             : 
     243       60084 :   fd_secp256k1_fp_t x11 = x9;
     244      180252 :   for( int j=0; j<2; j++ ) fd_secp256k1_fp_sqr( &x11, &x11 );
     245       60084 :   fd_secp256k1_fp_mul( &x11, &x11, &x2 );
     246             : 
     247       60084 :   fd_secp256k1_fp_t x22 = x11;
     248      721008 :   for( int j=0; j<11; j++ ) fd_secp256k1_fp_sqr( &x22, &x22 );
     249       60084 :   fd_secp256k1_fp_mul( &x22, &x22, &x11 );
     250             : 
     251       60084 :   fd_secp256k1_fp_t x44 = x22;
     252     1381932 :   for( int j=0; j<22; j++ ) fd_secp256k1_fp_sqr( &x44, &x44 );
     253       60084 :   fd_secp256k1_fp_mul( &x44, &x44, &x22 );
     254             : 
     255       60084 :   fd_secp256k1_fp_t x88 = x44;
     256     2703780 :   for( int j=0; j<44; j++ ) fd_secp256k1_fp_sqr( &x88, &x88 );
     257       60084 :   fd_secp256k1_fp_mul( &x88, &x88, &x44 );
     258             : 
     259       60084 :   fd_secp256k1_fp_t x176 = x88;
     260     5347476 :   for( int j=0; j<88; j++ ) fd_secp256k1_fp_sqr( &x176, &x176 );
     261       60084 :   fd_secp256k1_fp_mul( &x176, &x176, &x88 );
     262             : 
     263       60084 :   fd_secp256k1_fp_t x220 = x176;
     264     2703780 :   for( int j=0; j<44; j++ ) fd_secp256k1_fp_sqr( &x220, &x220 );
     265       60084 :   fd_secp256k1_fp_mul( &x220, &x220, &x44 );
     266             : 
     267       60084 :   fd_secp256k1_fp_t x223 = x220;
     268      240336 :   for( int j=0; j<3; j++ ) fd_secp256k1_fp_sqr( &x223, &x223 );
     269       60084 :   fd_secp256k1_fp_mul( &x223, &x223, &x3 );
     270             : 
     271       60084 :   fd_secp256k1_fp_t t1 = x223;
     272     1442016 :   for( int j=0; j<23; j++ ) fd_secp256k1_fp_sqr( &t1, &t1 );
     273       60084 :   fd_secp256k1_fp_mul( &t1, &t1, &x22 );
     274             : 
     275      420588 :   for( int j=0; j<6; j++ ) fd_secp256k1_fp_sqr( &t1, &t1 );
     276       60084 :   fd_secp256k1_fp_mul( &t1, &t1, &x2 );
     277       60084 :   fd_secp256k1_fp_sqr( &t1, &t1 );
     278       60084 :   fd_secp256k1_fp_sqr( r, &t1 );
     279             : 
     280       60084 :   fd_secp256k1_fp_sqr( &t1, r );
     281       60084 :   if( FD_UNLIKELY( !fd_secp256k1_fp_eq( &t1, a ) ) ) {
     282       30024 :     return NULL;
     283       30024 :   }
     284             : 
     285       30060 :   return r;
     286       60084 : }
     287             : 
     288             : /* Point */
     289             : 
     290             : /* Sets a group element to the identity element in Jacobian coordinates */
     291             : static inline void
     292       90180 : fd_secp256k1_point_set_identity( fd_secp256k1_point_t *r ) {
     293       90180 :   fd_secp256k1_fp_set( r->x, fd_secp256k1_const_zero );
     294       90180 :   fd_secp256k1_fp_set( r->y, fd_secp256k1_const_one_mont );
     295       90180 :   fd_secp256k1_fp_set( r->z, fd_secp256k1_const_zero );
     296       90180 : }
     297             : 
     298             : /* Sets a group element to the base element in Jacobian coordinates */
     299             : static inline void
     300       30060 : fd_secp256k1_point_set_base( fd_secp256k1_point_t *r ) {
     301       30060 :   fd_secp256k1_fp_set( r->x, fd_secp256k1_const_base_x_mont );
     302       30060 :   fd_secp256k1_fp_set( r->y, fd_secp256k1_const_base_y_mont );
     303       30060 :   fd_secp256k1_fp_set( r->z, fd_secp256k1_const_one_mont );
     304       30060 : }
     305             : 
     306             : /* r = a */
     307             : static inline void
     308             : fd_secp256k1_point_set( fd_secp256k1_point_t *       r,
     309       60120 :                         fd_secp256k1_point_t const * a ) {
     310       60120 :   fd_secp256k1_fp_set( r->x, a->x );
     311       60120 :   fd_secp256k1_fp_set( r->y, a->y );
     312       60120 :   fd_secp256k1_fp_set( r->z, a->z );
     313       60120 : }
     314             : 
     315             : /* https://eprint.iacr.org/2015/1060.pdf, Algorithm 7 */
     316             : static inline fd_secp256k1_point_t *
     317             : fd_secp256k1_point_add( fd_secp256k1_point_t *       r,
     318             :                         fd_secp256k1_point_t const * a,
     319     3757323 :                         fd_secp256k1_point_t const * b ) {
     320     3757323 :   fd_secp256k1_fp_t t0[ 1 ];
     321     3757323 :   fd_secp256k1_fp_t t1[ 1 ];
     322     3757323 :   fd_secp256k1_fp_t t2[ 1 ];
     323     3757323 :   fd_secp256k1_fp_t t3[ 1 ];
     324     3757323 :   fd_secp256k1_fp_t t4[ 1 ];
     325             : 
     326     3757323 :   fd_secp256k1_fp_t X3[ 1 ];
     327     3757323 :   fd_secp256k1_fp_t Y3[ 1 ];
     328     3757323 :   fd_secp256k1_fp_t Z3[ 1 ];
     329             : 
     330             :   /* t0 = X1 * X2 */
     331     3757323 :   fd_secp256k1_fp_mul( t0, a->x, b->x );
     332             :   /* t1 = Y1 * Y2 */
     333     3757323 :   fd_secp256k1_fp_mul( t1, a->y, b->y );
     334             :   /* t2 = Z1 * Z2 */
     335     3757323 :   fd_secp256k1_fp_mul( t2, a->z, b->z );
     336             : 
     337             :   /* t3 = (a.x + a.y) * (b.x + b.y) - (t0 + t1) */
     338     3757323 :   fd_secp256k1_fp_add( t3, a->x, a->y );
     339     3757323 :   fd_secp256k1_fp_add( t4, b->x, b->y );
     340     3757323 :   fd_secp256k1_fp_mul( t3, t3, t4 );
     341     3757323 :   fd_secp256k1_fp_add( t4, t0, t1 );
     342     3757323 :   fd_secp256k1_fp_sub( t3, t3, t4 );
     343             : 
     344             :   /* t4 = (a.y + a.z) * (b.y + b.z) - (t1 + t2) */
     345     3757323 :   fd_secp256k1_fp_add( t4, a->y, a->z );
     346     3757323 :   fd_secp256k1_fp_add( X3, b->y, b->z );
     347     3757323 :   fd_secp256k1_fp_mul( t4, t4, X3 );
     348     3757323 :   fd_secp256k1_fp_add( X3, t1, t2 );
     349     3757323 :   fd_secp256k1_fp_sub( t4, t4, X3 );
     350             : 
     351             :   /* Y3 = (a.x + a.z) * (b.x + b.z) - (t0 + t2) */
     352     3757323 :   fd_secp256k1_fp_add( X3, a->x, a->z );
     353     3757323 :   fd_secp256k1_fp_add( Y3, b->x, b->z );
     354     3757323 :   fd_secp256k1_fp_mul( X3, X3, Y3 );
     355     3757323 :   fd_secp256k1_fp_add( Y3, t0, t2 );
     356     3757323 :   fd_secp256k1_fp_sub( Y3, X3, Y3 );
     357             : 
     358             :   /* t0 = 3 * t0 */
     359     3757323 :   bignum_triple_p256k1( t0->limbs, (ulong *)t0->limbs );
     360             : 
     361             :   /* b3 = (2^2)^2 + 2^2 + 1 = 21 */
     362     3757323 :   fd_secp256k1_fp_t t2_4[ 1 ];
     363     3757323 :   fd_secp256k1_fp_t t5[ 1 ];
     364     3757323 :   fd_secp256k1_fp_dbl( t2_4, t2 );
     365     3757323 :   fd_secp256k1_fp_dbl( t2_4, t2_4 );
     366     3757323 :   fd_secp256k1_fp_dbl( t5, t2_4 );
     367     3757323 :   fd_secp256k1_fp_dbl( t5, t5 );
     368     3757323 :   fd_secp256k1_fp_add( t5, t5, t2_4 );
     369     3757323 :   fd_secp256k1_fp_add( t2, t5, t2 );
     370             : 
     371             :   /* Z3 = t1 * t2
     372             :      t1 = t1 - t2 */
     373     3757323 :   fd_secp256k1_fp_add( Z3, t1, t2 );
     374     3757323 :   fd_secp256k1_fp_sub( t1, t1, t2 );
     375             : 
     376     3757323 :   fd_secp256k1_fp_t Y3_4[ 1 ];
     377     3757323 :   fd_secp256k1_fp_dbl( Y3_4, Y3 );
     378     3757323 :   fd_secp256k1_fp_dbl( Y3_4, Y3_4 );
     379     3757323 :   fd_secp256k1_fp_dbl( t5, Y3_4 );
     380     3757323 :   fd_secp256k1_fp_dbl( t5, t5 );
     381     3757323 :   fd_secp256k1_fp_add( t5, t5, Y3_4 );
     382     3757323 :   fd_secp256k1_fp_add( Y3, t5, Y3 );
     383             : 
     384     3757323 :   fd_secp256k1_fp_mul( X3, t4, Y3 );
     385     3757323 :   fd_secp256k1_fp_mul( t2, t3, t1 );
     386     3757323 :   fd_secp256k1_fp_sub( r->x, t2, X3 );
     387     3757323 :   fd_secp256k1_fp_mul( Y3, Y3, t0 );
     388     3757323 :   fd_secp256k1_fp_mul( t1, t1, Z3 );
     389     3757323 :   fd_secp256k1_fp_add( r->y, t1, Y3 );
     390     3757323 :   fd_secp256k1_fp_mul( t0, t0, t3 );
     391     3757323 :   fd_secp256k1_fp_mul( Z3, Z3, t4 );
     392     3757323 :   fd_secp256k1_fp_add( r->z, Z3, t0 );
     393             : 
     394     3757323 :   return r;
     395     3757323 : }
     396             : 
     397             : /* https://eprint.iacr.org/2015/1060.pdf, Algorithm 9 */
     398             : static inline fd_secp256k1_point_t *
     399             : fd_secp256k1_point_dbl( fd_secp256k1_point_t *       r,
     400     7935840 :                         fd_secp256k1_point_t const * a ) {
     401     7935840 :   fd_secp256k1_fp_t t0[ 1 ];
     402     7935840 :   fd_secp256k1_fp_t t1[ 1 ];
     403     7935840 :   fd_secp256k1_fp_t t2[ 1 ];
     404             : 
     405     7935840 :   fd_secp256k1_fp_t X3[ 1 ];
     406     7935840 :   fd_secp256k1_fp_t Y3[ 1 ];
     407     7935840 :   fd_secp256k1_fp_t Z3[ 1 ];
     408             : 
     409             :   /* t0 = Y * Y*/
     410     7935840 :   fd_secp256k1_fp_sqr( t0, a->y );
     411             :   /* Z3 = 8 * t0 */
     412     7935840 :   fd_secp256k1_fp_dbl( Z3, t0 );
     413     7935840 :   fd_secp256k1_fp_dbl( Z3, Z3 );
     414     7935840 :   fd_secp256k1_fp_dbl( Z3, Z3 );
     415             : 
     416             :   /* t1 = Y * Z */
     417     7935840 :   fd_secp256k1_fp_mul( t1, a->y, a->z );
     418             :   /* t2 = Z * Z */
     419     7935840 :   fd_secp256k1_fp_sqr( t2, a->z );
     420             : 
     421             :   /* b3 = (2^2)^2 + 2^2 + 1
     422             :      t2 = b3 * t2 */
     423     7935840 :   fd_secp256k1_fp_t t2_4[1], t5[1];
     424     7935840 :   fd_secp256k1_fp_dbl( t2_4, t2 );
     425     7935840 :   fd_secp256k1_fp_dbl( t2_4, t2_4 );
     426     7935840 :   fd_secp256k1_fp_dbl( t5, t2_4 );
     427     7935840 :   fd_secp256k1_fp_dbl( t5, t5 );
     428     7935840 :   fd_secp256k1_fp_add( t5, t5, t2_4 );
     429     7935840 :   fd_secp256k1_fp_add( t2, t5, t2 );
     430             : 
     431             :   /* X3 = t2 * Z3 */
     432     7935840 :   fd_secp256k1_fp_mul( X3, t2, Z3 );
     433             :   /* Y3 = t0 + t2 */
     434     7935840 :   fd_secp256k1_fp_add( Y3, t0, t2 );
     435             : 
     436     7935840 :   fd_secp256k1_fp_mul( r->z, t1, Z3 );
     437             : 
     438     7935840 :   fd_secp256k1_fp_dbl( t1, t2 );
     439     7935840 :   fd_secp256k1_fp_add( t2, t1, t2 );
     440     7935840 :   fd_secp256k1_fp_sub( t0, t0, t2 );
     441     7935840 :   fd_secp256k1_fp_mul( Y3, t0, Y3 );
     442             :   /* compute t1 first, as the next add may overwrite a->y */
     443     7935840 :   fd_secp256k1_fp_mul( t1, a->x, a->y );
     444     7935840 :   fd_secp256k1_fp_add( r->y, X3, Y3 );
     445             : 
     446     7935840 :   fd_secp256k1_fp_mul( X3, t0, t1 );
     447     7935840 :   fd_secp256k1_fp_dbl( r->x, X3 );
     448             : 
     449     7935840 :   return r;
     450     7935840 : }
     451             : 
     452             : /* r = -a */
     453             : static inline fd_secp256k1_point_t *
     454             : fd_secp256k1_point_neg( fd_secp256k1_point_t *       r,
     455     2043384 :                         fd_secp256k1_point_t const * a ) {
     456     2043384 :   fd_secp256k1_fp_set( r->x, a->x );
     457     2043384 :   fd_secp256k1_fp_set( r->z, a->z );
     458     2043384 :   fd_secp256k1_fp_negate( r->y, a->y );
     459     2043384 :   return r;
     460     2043384 : }
     461             : 
     462             : /* r = a - b */
     463             : static inline fd_secp256k1_point_t *
     464             : fd_secp256k1_point_sub( fd_secp256k1_point_t *       r,
     465             :                         fd_secp256k1_point_t const * a,
     466     2043384 :                         fd_secp256k1_point_t const * b ) {
     467     2043384 :   fd_secp256k1_point_t tmp[ 1 ];
     468     2043384 :   fd_secp256k1_point_neg( tmp, b );
     469     2043384 :   return fd_secp256k1_point_add( r, a, tmp );
     470     2043384 : }
     471             : 
     472             : /* Double base multiplication */
     473             : 
     474             : static inline schar *
     475             : fd_secp256k1_slide( schar       r[ 2 * 32 + 1 ],
     476       60120 :                     uchar const s[ 32 ] ) {
     477     1983960 :   for(int i = 0; i<32; i++) {
     478     1923840 :     uchar x = s[i];
     479     1923840 :     r[i * 2 + 0] = x & 0xF;
     480     1923840 :     r[i * 2 + 1] = (x >> 4) & 0xF;
     481     1923840 :   }
     482             :   /* Now, r[0..63] is between 0 and 15, r[63] is between 0 and 7 */
     483       60120 :   schar carry = 0;
     484     3907800 :   for(int i = 0; i<64; i++) {
     485     3847680 :     r[i] += carry;
     486     3847680 :     carry = (schar)(r[i] + 8) >> 4;
     487     3847680 :     r[i] -= (schar)(carry * 16);
     488             :     /* r[i] MUST be between [-8, 8] */
     489     3847680 :   }
     490       60120 :   r[64] = carry;
     491             :   /* carry MUST be between [-8, 8] */
     492       60120 :   return r;
     493       60120 : }
     494             : 
     495             : static inline fd_secp256k1_point_t *
     496             : fd_secp256k1_precompute( fd_secp256k1_point_t         r[ 9 ],
     497       60120 :                          fd_secp256k1_point_t const * a ) {
     498       60120 :   fd_secp256k1_point_set_identity( &r[0] );
     499       60120 :   fd_secp256k1_point_set( &r[1], a );
     500      480960 :   for(int i = 2; i <= 8; i++) {
     501      420840 :     if(i % 2) {
     502      180360 :       fd_secp256k1_point_add( &r[i], &r[i - 1], a );
     503      240480 :     } else {
     504      240480 :       fd_secp256k1_point_dbl( &r[i], &r[i / 2]    );
     505      240480 :     }
     506      420840 :   }
     507       60120 :   return r;
     508       60120 : }
     509             : 
     510             : /* Computes s1*G + s2*P2, where G is the base point */
     511             : static inline fd_secp256k1_point_t *
     512             : fd_secp256k1_double_base_mul( fd_secp256k1_point_t *        r,
     513             :                               fd_secp256k1_scalar_t const * s1,
     514             :                               fd_secp256k1_point_t  const * p2,
     515       30060 :                               fd_secp256k1_scalar_t const * s2 ) {
     516       30060 :   fd_secp256k1_point_t base[ 1 ];
     517       30060 :   fd_secp256k1_point_set_base( base );
     518             : 
     519       30060 :   fd_secp256k1_point_t pc1[ 9 ];
     520       30060 :   fd_secp256k1_point_t pc2[ 9 ];
     521             :   /* TODO: Precompute the basepoint table in a generated table */
     522       30060 :   fd_secp256k1_precompute( pc1, base );
     523       30060 :   fd_secp256k1_precompute( pc2, p2 );
     524             : 
     525       30060 :   schar e1[ 2 * 32 + 1 ];
     526       30060 :   schar e2[ 2 * 32 + 1 ];
     527       30060 :   fd_secp256k1_slide( e1, s1->buf );
     528       30060 :   fd_secp256k1_slide( e2, s2->buf );
     529             : 
     530       30060 :   fd_secp256k1_point_set_identity( r );
     531     1953900 :   for( int pos = 2 * 32; ; pos -= 1 ) {
     532     1953900 :     schar slot1 = e1[pos];
     533     1953900 :     if( slot1 > 0 ) {
     534      781878 :       fd_secp256k1_point_add( r, r, &pc1[(ulong)slot1] );
     535     1172022 :     } else if( slot1 < 0 ) {
     536      961515 :       fd_secp256k1_point_sub( r, r, &pc1[(ulong)(-slot1)] );
     537      961515 :     }
     538             : 
     539     1953900 :     schar slot2 = e2[pos];
     540     1953900 :     if( slot2 > 0 ) {
     541      751701 :       fd_secp256k1_point_add( r, r, &pc2[(ulong)slot2] );
     542     1202199 :     } else if( slot2 < 0 ) {
     543     1081869 :       fd_secp256k1_point_sub( r, r, &pc2[(ulong)(-slot2)] );
     544     1081869 :     }
     545             : 
     546     1953900 :     if( pos == 0 ) break;
     547     1923840 :     fd_secp256k1_point_dbl( r, r );
     548     1923840 :     fd_secp256k1_point_dbl( r, r );
     549     1923840 :     fd_secp256k1_point_dbl( r, r );
     550     1923840 :     fd_secp256k1_point_dbl( r, r );
     551     1923840 :   }
     552             : 
     553       30060 :   return r;
     554       30060 : }
     555             : 
     556             : static inline fd_secp256k1_point_t *
     557             : fd_secp256k1_point_to_affine( fd_secp256k1_point_t *       r,
     558       30060 :                               fd_secp256k1_point_t const * a ) {
     559       30060 :   fd_secp256k1_fp_t z[1];
     560       30060 :   fd_secp256k1_fp_invert( z, a->z );
     561       30060 :   fd_secp256k1_fp_mul( r->x, a->x, z );
     562       30060 :   fd_secp256k1_fp_mul( r->y, a->y, z );
     563       30060 :   return r;
     564       30060 : }
     565             : 
     566             : static inline int
     567       30060 : fd_secp256k1_point_is_identity( fd_secp256k1_point_t const *a ) {
     568       30060 :   int affine =
     569       30060 :      fd_secp256k1_fp_eq( a->x, fd_secp256k1_const_zero ) &
     570       30060 :      ( fd_secp256k1_fp_eq( a->y, fd_secp256k1_const_zero     ) |
     571       30060 :        fd_secp256k1_fp_eq( a->y, fd_secp256k1_const_one_mont ) );
     572       30060 :   return fd_secp256k1_fp_eq( a->z, fd_secp256k1_const_zero ) | affine;
     573       30060 : }

Generated by: LCOV version 1.14