LCOV - code coverage report
Current view: top level - ballet/ed25519 - fd_curve25519.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 137 165 83.0 %
Date: 2025-12-05 04:49:52 Functions: 6 10 60.0 %

          Line data    Source code
       1             : #include "fd_curve25519.h"
       2             : #include "../hex/fd_hex.h"
       3             : 
       4             : /*
       5             :  * Secure implementations (const time + clean temp vars)
       6             :  */
       7             : #include "fd_curve25519_secure.c"
       8             : 
       9             : #if FD_HAS_AVX512
      10             : #include "avx512/fd_curve25519.c"
      11             : #else
      12             : #include "ref/fd_curve25519.c"
      13             : #endif
      14             : 
      15     8782425 : #define WNAF_BIT_SZ 4
      16     7806600 : #define WNAF_TBL_SZ (2*WNAF_BIT_SZ)
      17             : 
      18             : /*
      19             :  * Ser/de
      20             :  */
      21             : 
      22             :  void
      23             :  fd_ed25519_debug( char const *               name,
      24           0 :                    fd_ed25519_point_t const * a ) {
      25           0 :   fd_f25519_t x[1], y[1], z[1], t[1];
      26           0 :   fd_ed25519_point_to( x, y, z, t, a );
      27           0 :   FD_LOG_WARNING(( "%s", name ));
      28           0 :   fd_f25519_debug( "x", x );
      29           0 :   fd_f25519_debug( "y", y );
      30           0 :   fd_f25519_debug( "z", z );
      31           0 :   fd_f25519_debug( "t", t );
      32           0 :  }
      33             : 
      34             : fd_ed25519_point_t *
      35             : fd_ed25519_point_frombytes( fd_ed25519_point_t * r,
      36     1131093 :                             uchar const          buf[ 32 ] ) {
      37     1131093 :   fd_f25519_t x[1], y[1], t[1];
      38     1131093 :   fd_f25519_frombytes( y, buf );
      39     1131093 :   uchar expected_x_sign = buf[31] >> 7;
      40             : 
      41     1131093 :   fd_f25519_t u[1];
      42     1131093 :   fd_f25519_t v[1];
      43     1131093 :   fd_f25519_sqr( u, y                );
      44     1131093 :   fd_f25519_mul( v, u, fd_f25519_d   );
      45     1131093 :   fd_f25519_sub( u, u, fd_f25519_one ); /* u = y^2-1 */
      46     1131093 :   fd_f25519_add( v, v, fd_f25519_one ); /* v = dy^2+1 */
      47             : 
      48     1131093 :   int was_square = fd_f25519_sqrt_ratio( x, u, v );
      49     1131093 :   if( FD_UNLIKELY( !was_square ) ) {
      50       89164 :     return NULL;
      51       89164 :   }
      52             : 
      53     1041929 :   if( fd_f25519_sgn(x)!=expected_x_sign ) { /* 50% prob */
      54      631966 :     fd_f25519_neg( x, x );
      55      631966 :   }
      56             : 
      57     1041929 :   fd_f25519_mul( t, x, y );
      58     1041929 :   fd_ed25519_point_from( r, x, y, fd_f25519_one, t );
      59             : 
      60     1041929 :   return r;
      61     1131093 : }
      62             : 
      63             : uchar *
      64             : fd_ed25519_point_tobytes( uchar                      out[ 32 ],
      65     1709400 :                           fd_ed25519_point_t const * a ) {
      66     1709400 :   fd_f25519_t x[1], y[1], z[1], t[1];
      67     1709400 :   fd_ed25519_point_to( x, y, z, t, a );
      68     1709400 :   fd_f25519_inv( t, z );
      69     1709400 :   fd_f25519_mul2( x, x, t,
      70     1709400 :                   y, y, t );
      71     1709400 :   fd_f25519_tobytes( out, y );
      72     1709400 :   out[31] ^= (uchar)(fd_f25519_sgn( x ) << 7);
      73     1709400 :   return out;
      74     1709400 : }
      75             : 
      76             : /*
      77             :  * Scalar multiplication
      78             :  */
      79             : 
      80             : fd_ed25519_point_t *
      81             : fd_ed25519_scalar_mul( fd_ed25519_point_t *       r,
      82             :                        uchar const                n[ 32 ],
      83       30024 :                        fd_ed25519_point_t const * a ) {
      84       30024 :   short nslide[256];
      85       30024 :   fd_curve25519_scalar_wnaf( nslide, n, WNAF_BIT_SZ );
      86             : 
      87       30024 :   fd_ed25519_point_t ai[WNAF_TBL_SZ]; /* A,3A,5A,7A,9A,11A,13A,15A */
      88       30024 :   fd_ed25519_point_t a2[1];           /* 2A (temp) */
      89       30024 :   fd_ed25519_point_t t[1];
      90             : 
      91             :   /* pre-computed table */
      92       30024 :   fd_ed25519_point_set( &ai[0], a );
      93       30024 :   fd_ed25519_point_dbln( a2, a, 1 ); // note: a is affine, we could save 1mul
      94       30024 :   fd_curve25519_into_precomputed( &ai[0] );
      95      240192 :   for( int i=1; i<WNAF_TBL_SZ; i++ ) {
      96      210168 :     fd_ed25519_point_add_with_opts( t, a2, &ai[i-1], i==1, 1, 1 );
      97      210168 :     fd_ed25519_point_add_final_mul( &ai[i], t );
      98             :     /* pre-compute kT, to save 1mul during the loop */
      99      210168 :     fd_curve25519_into_precomputed( &ai[i] );
     100      210168 :   }
     101             : 
     102             :   /* main dbl-and-add loop. note: last iter unrolled */
     103       30024 :   fd_ed25519_point_set_zero( r );
     104       30024 :   int i;
     105      121686 :   for( i=255; i>=0; i-- ) { if( nslide[i] ) break; }
     106     7624506 :   for(      ; i>=0; i-- ) {
     107     7594482 :     fd_ed25519_partial_dbl( t, r );
     108     7594482 :     if(      nslide[i] > 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_add_with_opts( t, r, &ai[  nslide[i]  / 2], nslide[i]==1, 1, 1 ); }
     109     7294194 :     else if( nslide[i] < 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_sub_with_opts( t, r, &ai[(-nslide[i]) / 2], nslide[i]==-1, 1, 1 ); }
     110             : 
     111             :     /* ignore r->T because dbl doesn't need it, except in the last cycle */
     112     7594482 :     if (i == 0) {
     113       30024 :       fd_ed25519_point_add_final_mul( r, t );            // compute r->T
     114     7564458 :     } else {
     115     7564458 :       fd_ed25519_point_add_final_mul_projective( r, t ); // ignore r->T
     116     7564458 :     }
     117     7594482 :   }
     118       30024 :   return r;
     119       30024 : }
     120             : 
     121             : fd_ed25519_point_t *
     122             : fd_ed25519_double_scalar_mul_base( fd_ed25519_point_t *       r,
     123             :                                    uchar const                n1[ 32 ],
     124             :                                    fd_ed25519_point_t const * a,
     125      768744 :                                    uchar const                n2[ 32 ] ) {
     126             : 
     127      768744 :   short n1slide[256]; fd_curve25519_scalar_wnaf( n1slide, n1, WNAF_BIT_SZ );
     128      768744 :   short n2slide[256]; fd_curve25519_scalar_wnaf( n2slide, n2, 8 );
     129             : 
     130      768744 :   fd_ed25519_point_t ai[WNAF_TBL_SZ]; /* A,3A,5A,7A,9A,11A,13A,15A */
     131      768744 :   fd_ed25519_point_t a2[1];           /* 2A (temp) */
     132      768744 :   fd_ed25519_point_t t[1];
     133             : 
     134             :   /* pre-computed table */
     135      768744 :   fd_ed25519_point_set( &ai[0], a );
     136      768744 :   fd_ed25519_point_dbln( a2, a, 1 ); // note: a is affine, we could save 1mul
     137      768744 :   fd_curve25519_into_precomputed( &ai[0] );
     138     6149952 :   for( int i=1; i<WNAF_TBL_SZ; i++ ) {
     139     5381208 :     fd_ed25519_point_add_with_opts( t, a2, &ai[i-1], i==1, 1, 1 );
     140     5381208 :     fd_ed25519_point_add_final_mul( &ai[i], t );
     141             :     /* pre-compute kT, to save 1mul during the loop */
     142     5381208 :     fd_curve25519_into_precomputed( &ai[i] );
     143     5381208 :   }
     144             : 
     145             :   /* main dbl-and-add loop */
     146      768744 :   fd_ed25519_point_set_zero( r );
     147             : 
     148      768744 :   int i;
     149     4779277 :   for( i=255; i>=0; i-- ) { if( n1slide[i] || n2slide[i] ) break; }
     150   193556675 :   for(      ; i>=0; i-- ) {
     151   192787931 :     fd_ed25519_partial_dbl( t, r );
     152   192787931 :     if(      n1slide[i] > 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_add_with_opts( t, r, &ai[  n1slide[i]  / 2], n1slide[i]==1, 1, 1 ); }
     153   176016578 :     else if( n1slide[i] < 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_sub_with_opts( t, r, &ai[(-n1slide[i]) / 2], n1slide[i]==-1, 1, 1 ); }
     154   192787931 :     if(      n2slide[i] > 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_add_with_opts( t, r, &fd_ed25519_base_point_wnaf_table[  n2slide[i]  / 2], 1, 1, 1 ); }
     155   182644623 :     else if( n2slide[i] < 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_sub_with_opts( t, r, &fd_ed25519_base_point_wnaf_table[(-n2slide[i]) / 2], 1, 1, 1 ); }
     156             : 
     157             :     /* ignore r->T because dbl doesn't need it, except in the last cycle */
     158   192787931 :     if (i == 0) {
     159      768744 :       fd_ed25519_point_add_final_mul( r, t );            // compute r->T
     160   192019187 :     } else {
     161   192019187 :       fd_ed25519_point_add_final_mul_projective( r, t ); // ignore r->T
     162   192019187 :     }
     163   192787931 :   }
     164      768744 :   return r;
     165      768744 : }
     166             : 
     167             : 
     168             : FD_25519_INLINE fd_ed25519_point_t *
     169             : fd_ed25519_multi_scalar_mul_with_opts( fd_ed25519_point_t *     r,
     170             :                                        uchar const              n[], /* sz * 32 */
     171             :                                        fd_ed25519_point_t const a[], /* sz */
     172             :                                        ulong const              sz,
     173        5553 :                                        ulong const              base_sz ) {
     174        5553 :   short nslide[FD_BALLET_CURVE25519_MSM_BATCH_SZ][256];
     175        5553 :   fd_ed25519_point_t ai[FD_BALLET_CURVE25519_MSM_BATCH_SZ][WNAF_TBL_SZ]; /* A,3A,5A,7A,9A,11A,13A,15A */
     176        5553 :   fd_ed25519_point_t a2[1];                          /* 2A (temp) */
     177        5553 :   fd_ed25519_point_t t[1];                           /* temp */
     178             : 
     179        5553 :   if( base_sz ) {
     180           0 :     fd_curve25519_scalar_wnaf( nslide[0], &n[32*0], 8 );
     181           0 :   }
     182      182610 :   for( ulong j=base_sz; j<sz; j++ ) {
     183      177057 :     fd_curve25519_scalar_wnaf( nslide[j], &n[32*j], WNAF_BIT_SZ );
     184             : 
     185             :     /* pre-computed table */
     186      177057 :     fd_ed25519_point_set( &ai[j][0], &a[j] );
     187      177057 :     fd_ed25519_point_dbln( a2, &a[j], 1 ); // note: a is affine, we could save 1mul
     188      177057 :     fd_curve25519_into_precomputed( &ai[j][0] );
     189     1416456 :     for( int i=1; i<WNAF_TBL_SZ; i++ ) {
     190     1239399 :       fd_ed25519_point_add_with_opts( t, a2, &ai[j][i-1], i==1, 1, 1 );
     191     1239399 :       fd_ed25519_point_add_final_mul( &ai[j][i], t );
     192             :       /* pre-compute kT, to save 1mul during the loop */
     193     1239399 :       fd_curve25519_into_precomputed( &ai[j][i] );
     194     1239399 :     }
     195      177057 :   }
     196             : 
     197             :   /* main dbl-and-add loop */
     198        5553 :   fd_ed25519_point_set_zero( r );
     199     1427121 :   for( int i=255; i>=0; i-- ) {
     200     1421568 :     fd_ed25519_partial_dbl( t, r );
     201     1421568 :     if( base_sz ) {
     202           0 :       if(      nslide[0][i] > 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_add_with_opts( t, r, &fd_ed25519_base_point_wnaf_table[  nslide[0][i]  / 2], 1, 1, 1 ); }
     203           0 :       else if( nslide[0][i] < 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_sub_with_opts( t, r, &fd_ed25519_base_point_wnaf_table[(-nslide[0][i]) / 2], 1, 1, 1 ); }
     204           0 :     }
     205    46748160 :     for( ulong j=base_sz; j<sz; j++ ) {
     206    45326592 :       short n = nslide[j][i];
     207    45326592 :       if(      n > 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_add_with_opts( t, r, &ai[j][  n  / 2], (n==1), 1, 1 ); }
     208    41533682 :       else if( n < 0 ) { fd_ed25519_point_add_final_mul( r, t ); fd_ed25519_point_sub_with_opts( t, r, &ai[j][(-n) / 2], (n==-1), 1, 1 ); }
     209    45326592 :     }
     210             : 
     211             :     /* ignore r->T because dbl doesn't need it, except in the last cycle */
     212     1421568 :     if (i == 0) {
     213        5553 :       fd_ed25519_point_add_final_mul( r, t );            // compute r->T
     214     1416015 :     } else {
     215     1416015 :       fd_ed25519_point_add_final_mul_projective( r, t ); // ignore r->T
     216     1416015 :     }
     217     1421568 :   }
     218        5553 :   return r;
     219        5553 : }
     220             : 
     221             : fd_ed25519_point_t *
     222             : fd_ed25519_multi_scalar_mul( fd_ed25519_point_t *     r,
     223             :                              uchar const              n[], /* sz * 32 */
     224             :                              fd_ed25519_point_t const a[], /* sz */
     225        1863 :                              ulong const              sz ) {
     226             : 
     227        1863 :   fd_ed25519_point_t h[1];
     228        1863 :   fd_ed25519_point_set_zero( r );
     229             : 
     230        7416 :   for( ulong i=0; i<sz; i+=FD_BALLET_CURVE25519_MSM_BATCH_SZ ) {
     231        5553 :     ulong batch_sz = fd_ulong_min(sz-i, FD_BALLET_CURVE25519_MSM_BATCH_SZ);
     232             : 
     233        5553 :     fd_ed25519_multi_scalar_mul_with_opts( h, &n[ 32*i ], &a[ i ], batch_sz, 0 );
     234        5553 :     fd_ed25519_point_add( r, r, h );
     235        5553 :   }
     236             : 
     237        1863 :   return r;
     238        1863 : }
     239             : 
     240             : fd_ed25519_point_t *
     241             : fd_ed25519_multi_scalar_mul_base( fd_ed25519_point_t *     r,
     242             :                                   uchar const              n[], /* sz * 32 */
     243             :                                   fd_ed25519_point_t const a[], /* sz */
     244           0 :                                   ulong const              sz ) {
     245           0 :   if (sz > FD_BALLET_CURVE25519_MSM_BATCH_SZ) {
     246           0 :     return NULL;
     247           0 :   }
     248           0 :   return fd_ed25519_multi_scalar_mul_with_opts( r, n, a, sz, 1 );
     249           0 : }
     250             : 
     251             : /*
     252             :  * Init
     253             :  */
     254             : 
     255             : fd_ed25519_point_t *
     256             : fd_curve25519_affine_add( fd_ed25519_point_t *       r,
     257             :                           fd_ed25519_point_t const * a,
     258           0 :                           fd_ed25519_point_t const * b ) {
     259           0 :   fd_ed25519_point_add_with_opts( r, a, b, 1, 0, 0 );
     260           0 :   return fd_curve25519_into_affine( r );
     261           0 : }
     262             : 
     263             : fd_ed25519_point_t *
     264             : fd_curve25519_affine_dbln( fd_ed25519_point_t *       r,
     265             :                            fd_ed25519_point_t const * a,
     266           0 :                            int const                  n ) {
     267           0 :   fd_ed25519_point_dbln( r, a, n );
     268           0 :   return fd_curve25519_into_affine( r );
     269           0 : }

Generated by: LCOV version 1.14