LCOV - code coverage report
Current view: top level - ballet/ed25519/avx512 - fd_curve25519.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 82 86 95.3 %
Date: 2026-10-22 04:28:21 Functions: 15 16 93.8 %

          Line data    Source code
       1             : #include "../fd_curve25519.h"
       2             : #include "./fd_r43x6_ge.h"
       3             : 
       4             : /*
       5             :  * Add
       6             :  */
       7             : 
       8             : /* fd_ed25519_point_add_with_opts computes r = a + b, and returns r.
       9             : 
      10             :    https://eprint.iacr.org/2008/522
      11             :    Sec 4.2, 4-Processor Montgomery addition and doubling.
      12             : 
      13             :    This implementation includes several optional optimizations
      14             :    that are used for speeding up scalar multiplication:
      15             : 
      16             :    - b_Z_is_one, if b->Z == 1 (affine, or decompressed), we can skip 1mul
      17             : 
      18             :    - b_is_precomputed, since the scalar mul loop typically accumulates
      19             :      points from a table, we can pre-compute kT into the table points and
      20             :      therefore skip 1mul in during the loop.
      21             : 
      22             :    - skip_last_mul, since dbl can be computed with just (X, Y, Z)
      23             :      and doesn't need T, we can skip the last 4 mul and selectively
      24             :      compute (X, Y, Z) or (X, Y, Z, T) during the scalar mul loop.
      25             :  */
      26             : FD_25519_INLINE fd_ed25519_point_t *
      27             : fd_ed25519_point_add_with_opts( fd_ed25519_point_t *       r,
      28             :                                 fd_ed25519_point_t const * a,
      29             :                                 fd_ed25519_point_t const * b,
      30             :                                 FD_PARAM_UNUSED int const b_Z_is_one,
      31             :                                 int const b_is_precomputed,
      32    15354188 :                                 FD_PARAM_UNUSED int const skip_last_mul ) {
      33             : 
      34    15354188 :   if( b_is_precomputed ) {
      35    13151913 :     fd_ed25519_point_t tmp[2];
      36    13151913 :     FD_R43X6_GE_ADD_TABLE_ALT( r->P, a->P, b->P, tmp[0].P, tmp[1].P );
      37    13151913 :   } else {
      38     2202275 :     FD_R43X6_GE_ADD( r->P, a->P, b->P );
      39     2202275 :   }
      40    15354188 :   return r;
      41    15354188 : }
      42             : 
      43             : /* fd_ed25519_point_add computes r = a + b, and returns r. */
      44             : fd_ed25519_point_t *
      45             : fd_ed25519_point_add( fd_ed25519_point_t *       r,
      46             :                       fd_ed25519_point_t const * a,
      47     1202163 :                       fd_ed25519_point_t const * b ) {
      48     1202163 :   return fd_ed25519_point_add_with_opts( r, a, b, 0, 0, 0 );
      49     1202163 : }
      50             : 
      51             : /* fd_ed25519_point_add_final_mul computes just the final mul step in point add.
      52             :    See fd_ed25519_point_add_with_opts. */
      53             : FD_25519_INLINE fd_ed25519_point_t *
      54             : fd_ed25519_point_add_final_mul( fd_ed25519_point_t * restrict r,
      55    13296075 :                                 fd_ed25519_point_t const *    a ) {
      56    13296075 :   fd_ed25519_point_set( r, a );
      57    13296075 :   return r;
      58    13296075 : }
      59             : 
      60             : /* fd_ed25519_point_add_final_mul_projective computes just the final mul step
      61             :    in point add, assuming the result is projective (X, Y, Z), i.e. ignoring T.
      62             :    This is useful because dbl only needs (X, Y, Z) in input, so we can save 1mul.
      63             :    See fd_ed25519_point_add_with_opts. */
      64             : FD_25519_INLINE fd_ed25519_point_t *
      65             : fd_ed25519_point_add_final_mul_projective( fd_ed25519_point_t * restrict r,
      66    22369944 :                                            fd_ed25519_point_t const *    a ) {
      67    22369944 :   fd_ed25519_point_set( r, a );
      68    22369944 :   return r;
      69    22369944 : }
      70             : 
      71             : /*
      72             :  * Sub
      73             :  */
      74             : 
      75             : /* fd_ed25519_point_sub sets r = -a. */
      76             : FD_25519_INLINE fd_ed25519_point_t *
      77             : fd_ed25519_point_neg_precomputed( fd_ed25519_point_t *       r,
      78     5945286 :                       fd_ed25519_point_t const * a ) {
      79             :   /* use p instead of zero to avoid mod reduction */
      80     5945286 :   FD_R43X6_QUAD_DECL( _p );
      81     5945286 :   _p03 = wwl( 8796093022189L, 8796093022189L, 8796093022189L, 8796093022189L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L );
      82     5945286 :   _p14 = wwl( 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L );
      83     5945286 :   _p25 = wwl( 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 1099511627775L, 1099511627775L, 1099511627775L, 1099511627775L );
      84     5945286 :   FD_R43X6_QUAD_LANE_SUB_FAST( r->P, a->P, 0,0,0,1, _p, a->P );
      85     5945286 :   FD_R43X6_QUAD_PERMUTE      ( r->P, 1,0,2,3, r->P );
      86     5945286 :   return r;
      87     5945286 : }
      88             : 
      89             : /* fd_ed25519_point_sub_with_opts computes r = a - b, and returns r.
      90             :    This is like fd_ed25519_point_add_with_opts, replacing:
      91             :    - b->X => -b->X
      92             :    - b->T => -b->T
      93             :    See fd_ed25519_point_add_with_opts for details.
      94             :  */
      95             : FD_25519_INLINE fd_ed25519_point_t *
      96             : fd_ed25519_point_sub_with_opts( fd_ed25519_point_t *       r,
      97             :                                 fd_ed25519_point_t const * a,
      98             :                                 fd_ed25519_point_t const * b,
      99             :                                 int const b_Z_is_one,
     100             :                                 int const b_is_precomputed,
     101     6945398 :                                 int const skip_last_mul ) {
     102             : 
     103     6945398 :   fd_ed25519_point_t neg[1];
     104     6945398 :   if (b_is_precomputed) {
     105     5945286 :     fd_ed25519_point_neg_precomputed( neg, b );
     106     5945286 :   } else {
     107     1000112 :     fd_ed25519_point_neg( neg, b );
     108     1000112 :   }
     109     6945398 :   return fd_ed25519_point_add_with_opts( r, a, neg, b_Z_is_one, b_is_precomputed, skip_last_mul );
     110     6945398 : }
     111             : 
     112             : /* fd_ed25519_point_sub computes r = a - b, and returns r. */
     113             : fd_ed25519_point_t *
     114             : fd_ed25519_point_sub( fd_ed25519_point_t *       r,
     115             :                       fd_ed25519_point_t const * a,
     116     1000112 :                       fd_ed25519_point_t const * b ) {
     117     1000112 :   return fd_ed25519_point_sub_with_opts( r, a, b, 0, 0, 0 );
     118     1000112 : }
     119             : 
     120             : /*
     121             :  * Dbl
     122             :  */
     123             : 
     124             : /* Dedicated dbl
     125             :    https://eprint.iacr.org/2008/522
     126             :    Sec 4.4.
     127             :    This uses sqr instead of mul.
     128             : 
     129             :    TODO: use the same iface with_opts?
     130             :   */
     131             : 
     132             : FD_25519_INLINE fd_ed25519_point_t *
     133             : fd_ed25519_partial_dbl( fd_ed25519_point_t *       r,
     134    22514106 :                         fd_ed25519_point_t const * a ) {
     135    22514106 :   FD_R43X6_GE_DBL( r->P, a->P );
     136    22514106 :   return r;
     137    22514106 : }
     138             : 
     139             : fd_ed25519_point_t *
     140             : fd_ed25519_point_dbl( fd_ed25519_point_t *       r,
     141           0 :                       fd_ed25519_point_t const * a ) {
     142           0 :   FD_R43X6_GE_DBL( r->P, a->P );
     143           0 :   return r;
     144           0 : }
     145             : 
     146             : /*
     147             :  * Ser/de
     148             :  */
     149             : 
     150             : int
     151             : fd_ed25519_point_frombytes_2x( fd_ed25519_point_t * r1,
     152             :                                uchar const          buf1[ 32 ],
     153             :                                fd_ed25519_point_t * r2,
     154      143881 :                                uchar const          buf2[ 32 ] ) {
     155             :   //TODO: consider unifying code with ref
     156      143881 :   return FD_R43X6_GE_DECODE2( r1->P, buf1, r2->P, buf2 );
     157      143881 : }
     158             : 
     159             : int
     160             : fd_ed25519_point_frombytes_1x( fd_ed25519_point_t * r,
     161      177747 :                                uchar const          buf[ 32 ] ) {
     162             :   /* fd_r43x6_ge_decode does the same sequence of operations as each
     163             :      lane of fd_r43x6_ge_decode2 */
     164      177747 :   return FD_R43X6_GE_DECODE( r->P, buf );
     165      177747 : }
     166             : 
     167             : void
     168             : fd_ed25519_point_decode_init( fd_ed25519_point_decode_t * st,
     169      110142 :                               uchar const                 buf[ 32 ] ) {
     170      110142 :   fd_r43x6_ge_decode_init( st, buf );
     171      110142 : }
     172             : 
     173             : void
     174             : fd_ed25519_point_decode_step( fd_ed25519_point_decode_t * st,
     175     7861492 :                               ulong                       n ) {
     176     7861492 :   fd_r43x6_ge_decode_step( st, n );
     177     7861492 : }
     178             : 
     179             : int
     180             : fd_ed25519_point_decode_fini( fd_ed25519_point_t *        r,
     181      110142 :                               fd_ed25519_point_decode_t * st ) {
     182      110142 :   FD_R43X6_QUAD_DECL( _P );
     183      110142 :   int err = fd_r43x6_ge_decode_fini( &_P03, &_P14, &_P25, st );
     184      110142 :   FD_R43X6_QUAD_MOV( r->P, _P );
     185      110142 :   return err;
     186      110142 : }
     187             : 
     188             : /*
     189             :   Affine (only for init(), can be slow)
     190             : */
     191             : fd_ed25519_point_t *
     192             : fd_curve25519_affine_frombytes( fd_ed25519_point_t * r,
     193             :                                 uchar const          _x[ 32 ],
     194           1 :                                 uchar const          _y[ 32 ] ) {
     195           1 :   fd_f25519_t x[1], y[1], z[1], t[1];
     196           1 :   fd_f25519_frombytes( x, _x );
     197           1 :   fd_f25519_frombytes( y, _y );
     198           1 :   fd_f25519_set( z, fd_f25519_one );
     199           1 :   fd_f25519_mul( t, x, y );
     200           1 :   FD_R43X6_QUAD_PACK( r->P, x->el, y->el, z->el, t->el );
     201           1 :   return r;
     202           1 : }
     203             : 
     204             : fd_ed25519_point_t *
     205        2500 : fd_curve25519_into_affine( fd_ed25519_point_t * r ) {
     206        2500 :   fd_f25519_t x[1], y[1], z[1], t[1];
     207        2500 :   FD_R43X6_QUAD_UNPACK( x->el, y->el, z->el, t->el, r->P );
     208        2500 :   fd_f25519_inv( z, z );
     209        2500 :   fd_f25519_mul( x, x, z );
     210        2500 :   fd_f25519_mul( y, y, z );
     211        2500 :   fd_f25519_set( z, fd_f25519_one );
     212        2500 :   fd_f25519_mul( t, x, y );
     213             :   FD_R43X6_QUAD_PACK( r->P, x->el, y->el, z->el, t->el );
     214        2500 :   return r;
     215        2500 : }

Generated by: LCOV version 1.14