LCOV - code coverage report
Current view: top level - ballet/ed25519/ref - fd_curve25519.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 119 133 89.5 %
Date: 2024-11-13 11:58:15 Functions: 6 8 75.0 %

          Line data    Source code
       1             : #include "../fd_curve25519.h"
       2             : 
       3             : /*
       4             :  * Add
       5             :  */
       6             : 
       7             : /* fd_ed25519_point_add_with_opts computes r = a + b, and returns r.
       8             : 
       9             :    https://eprint.iacr.org/2008/522
      10             :    Sec 4.2, 4-Processor Montgomery addition and doubling.
      11             : 
      12             :    This implementation includes several optional optimizations
      13             :    that are used for speeding up scalar multiplication:
      14             : 
      15             :    - b_Z_is_one, if b->Z == 1 (affine, or decompressed), we can skip 1mul
      16             : 
      17             :    - b_is_precomputed, since the scalar mul loop typically accumulates
      18             :      points from a table, we can pre-compute kT into the table points and
      19             :      therefore skip 1mul in during the loop.
      20             : 
      21             :    - skip_last_mul, since dbl can be computed with just (X, Y, Z)
      22             :      and doesn't need T, we can skip the last 4 mul and selectively
      23             :      compute (X, Y, Z) or (X, Y, Z, T) during the scalar mul loop.
      24             :  */
      25             : FD_25519_INLINE fd_ed25519_point_t *
      26             : fd_ed25519_point_add_with_opts( fd_ed25519_point_t *       r,
      27             :                                 fd_ed25519_point_t const * a,
      28             :                                 fd_ed25519_point_t const * b,
      29             :                                 int const b_Z_is_one,
      30             :                                 int const b_is_precomputed,
      31    28190958 :                                 int const skip_last_mul ) {
      32    28190958 :   fd_f25519_t r1[1], r2[1], r3[1], r4[1];
      33    28190958 :   fd_f25519_t r5[1], r6[1], r7[1], r8[1];
      34    28190958 :   fd_f25519_t t[1];
      35    28190958 :   fd_f25519_t const *r2p = r2, *r4p = r4;
      36             : 
      37    28190958 :   fd_f25519_sub_nr( r1, a->Y, a->X );
      38    28190958 :   fd_f25519_add_nr( r3, a->Y, a->X );
      39             : 
      40    28190958 : #if CURVE25519_PRECOMP_XY
      41    28190958 :   if (b_is_precomputed) {
      42    26165948 :     r2p = b->X;
      43    26165948 :     r4p = b->Y;
      44    26165948 :   } else {
      45     2025010 :     fd_f25519_sub_nr( r2, b->Y, b->X );
      46     2025010 :     fd_f25519_add_nr( r4, b->Y, b->X );
      47     2025010 :   }
      48             : #else
      49             :     fd_f25519_sub_nr( r2, b->Y, b->X );
      50             :     fd_f25519_add_nr( r4, b->Y, b->X );
      51             : #endif
      52             : 
      53             :   /* if b->Z == 1, save 1mul */
      54    28190958 :   if( b_Z_is_one ) {
      55     9606065 :     fd_f25519_mul3( r5, r1,   r2p,
      56     9606065 :                     r6, r3,   r4p,
      57     9606065 :                     r7, a->T, b->T );
      58     9606065 :     fd_f25519_add( r8, a->Z, a->Z );
      59    18584893 :   } else {
      60    18584893 :     fd_f25519_add_nr( t, a->Z, a->Z );
      61    18584893 :     fd_f25519_mul4( r5, r1,   r2p,
      62    18584893 :                     r6, r3,   r4p,
      63    18584893 :                     r7, a->T, b->T,
      64    18584893 :                     r8, t, b->Z );
      65    18584893 :   } /* b_Z_is_one */
      66             : 
      67             :   /* if b->T actually contains k*b->T, save 1mul */
      68    28190958 :   if( !b_is_precomputed ) {
      69     2025010 :     fd_f25519_mul( r7, r7, fd_f25519_k );
      70     2025010 :   }
      71             : 
      72             :   /* skip last mul step, and use fd_ed25519_point_add_final_mul
      73             :      or fd_ed25519_point_add_final_mul_projective instead. */
      74    28190958 :   if( skip_last_mul ) {
      75             :     /* store r1, r2, r3, r4 resp. in X, Y, Z, T */
      76    26165948 :     fd_f25519_sub_nr( r->X, r6, r5 );
      77    26165948 :     fd_f25519_sub_nr( r->Y, r8, r7 );
      78    26165948 :     fd_f25519_add_nr( r->Z, r8, r7 );
      79    26165948 :     fd_f25519_add_nr( r->T, r6, r5 );
      80    26165948 :   } else {
      81     2025010 :     fd_f25519_sub_nr( r1, r6, r5 );
      82     2025010 :     fd_f25519_sub_nr( r2, r8, r7 );
      83     2025010 :     fd_f25519_add_nr( r3, r8, r7 );
      84     2025010 :     fd_f25519_add_nr( r4, r6, r5 );
      85             : 
      86     2025010 :     fd_f25519_mul4( r->X, r1, r2,
      87     2025010 :                     r->Y, r3, r4,
      88     2025010 :                     r->Z, r2, r3,
      89     2025010 :                     r->T, r1, r4 );
      90     2025010 :   } /* skip_last_mul */
      91    28190958 :   return r;
      92    28190958 : }
      93             : 
      94             : /* fd_ed25519_point_add computes r = a + b, and returns r. */
      95             : fd_ed25519_point_t *
      96             : fd_ed25519_point_add( fd_ed25519_point_t *       r,
      97             :                       fd_ed25519_point_t const * a,
      98     2025010 :                       fd_ed25519_point_t const * b ) {
      99     2025010 :   return fd_ed25519_point_add_with_opts( r, a, b, 0, 0, 0 );
     100     2025010 : }
     101             : 
     102             : /*
     103             :  * Sub
     104             :  */
     105             : 
     106             : /* fd_ed25519_point_sub_with_opts computes r = a - b, and returns r.
     107             :    This is like fd_ed25519_point_add_with_opts, replacing:
     108             :    - b->X => -b->X
     109             :    - b->T => -b->T
     110             :    See fd_ed25519_point_add_with_opts for details.
     111             :  */
     112             : FD_25519_INLINE fd_ed25519_point_t *
     113             : fd_ed25519_point_sub_with_opts( fd_ed25519_point_t *       r,
     114             :                                 fd_ed25519_point_t const * a,
     115             :                                 fd_ed25519_point_t const * b,
     116             :                                 int const b_Z_is_one,
     117             :                                 int const b_is_precomputed,
     118    22059831 :                                 int const skip_last_mul ) {
     119    22059831 :   fd_f25519_t r1[1], r2[1], r3[1], r4[1];
     120    22059831 :   fd_f25519_t r5[1], r6[1], r7[1], r8[1];
     121    22059831 :   fd_f25519_t t[1];
     122    22059831 :   fd_f25519_t const *r2p = r2, *r4p = r4;
     123             : 
     124    22059831 :   fd_f25519_sub_nr( r1, a->Y, a->X );
     125    22059831 :   fd_f25519_add_nr( r3, a->Y, a->X );
     126             : 
     127    22059831 : #if CURVE25519_PRECOMP_XY
     128    22059831 :   if (b_is_precomputed) {
     129    20059609 :     r2p = b->Y;
     130    20059609 :     r4p = b->X;
     131    20059609 :   } else {
     132     2000222 :     fd_f25519_add_nr( r2, b->Y, b->X ); // _sub => _add (because of -b->X)
     133     2000222 :     fd_f25519_sub_nr( r4, b->Y, b->X ); // _add => _sub (because of -b->X)
     134     2000222 :   }
     135             : #else
     136             :     fd_f25519_add_nr( r2, b->Y, b->X ); // _sub => _add (because of -b->X)
     137             :     fd_f25519_sub_nr( r4, b->Y, b->X ); // _add => _sub (because of -b->X)
     138             : #endif
     139             : 
     140             :   /* if b->Z == 1, save 1mul */
     141    22059831 :   if( b_Z_is_one ) {
     142     7839488 :     fd_f25519_mul3( r5, r1,   r2p,
     143     7839488 :                     r6, r3,   r4p,
     144     7839488 :                     r7, a->T, b->T );
     145     7839488 :     fd_f25519_add( r8, a->Z, a->Z );
     146    14220343 :   } else {
     147    14220343 :     fd_f25519_add_nr( t, a->Z, a->Z );
     148    14220343 :     fd_f25519_mul4( r5, r1,   r2p,
     149    14220343 :                     r6, r3,   r4p,
     150    14220343 :                     r7, a->T, b->T,
     151    14220343 :                     r8, t, b->Z );
     152    14220343 :   } /* b_Z_is_one */
     153             : 
     154             :   /* if b->T actually contains k*b->T, save 1mul */
     155    22059831 :   if( !b_is_precomputed ) {
     156     2000222 :     fd_f25519_mul( r7, r7, fd_f25519_k );
     157     2000222 :   }
     158             : 
     159             :   /* skip last mul step, and use fd_ed25519_point_add_final_mul
     160             :      or fd_ed25519_point_add_final_mul_projective instead. */
     161    22059831 :   if( skip_last_mul ) {
     162             :     /* store r1, r2, r3, r4 resp. in X, Y, Z, T */
     163    20059609 :     fd_f25519_sub_nr( r->X, r6, r5 );
     164    20059609 :     fd_f25519_add_nr( r->Y, r8, r7 ); // _sub => _add (because of -b->T => -r7)
     165    20059609 :     fd_f25519_sub_nr( r->Z, r8, r7 ); // _add => _sub (because of -b->T => -r7)
     166    20059609 :     fd_f25519_add_nr( r->T, r6, r5 );
     167    20059609 :   } else {
     168     2000222 :     fd_f25519_sub_nr( r1, r6, r5 );
     169     2000222 :     fd_f25519_add_nr( r2, r8, r7 );   // _sub => _add (because of -b->T => -r7)
     170     2000222 :     fd_f25519_sub_nr( r3, r8, r7 );   // _add => _sub (because of -b->T => -r7)
     171     2000222 :     fd_f25519_add_nr( r4, r6, r5 );
     172             : 
     173     2000222 :     fd_f25519_mul4( r->X, r1, r2,
     174     2000222 :                     r->Y, r3, r4,
     175     2000222 :                     r->Z, r2, r3,
     176     2000222 :                     r->T, r1, r4 );
     177     2000222 :   } /* skip_last_mul */
     178    22059831 :   return r;
     179    22059831 : }
     180             : 
     181             : /* fd_ed25519_point_sub computes r = a - b, and returns r. */
     182             : fd_ed25519_point_t *
     183             : fd_ed25519_point_sub( fd_ed25519_point_t *       r,
     184             :                       fd_ed25519_point_t const * a,
     185     2000222 :                       fd_ed25519_point_t const * b ) {
     186     2000222 :   return fd_ed25519_point_sub_with_opts( r, a, b, 0, 0, 0 );
     187     2000222 : }
     188             : 
     189             : /*
     190             :  * Dbl
     191             :  */
     192             : 
     193             : fd_ed25519_point_t *
     194             : fd_ed25519_point_dbl( fd_ed25519_point_t *       r,
     195           0 :                       fd_ed25519_point_t const * a ) {
     196           0 :   fd_ed25519_point_t t[1];
     197             :   /* Dedicated dbl
     198             :      https://eprint.iacr.org/2008/522
     199             :      Sec 4.4.
     200             :      This uses sqr instead of mul. */
     201           0 :   fd_ed25519_partial_dbl( t, a );
     202           0 :   return fd_ed25519_point_add_final_mul( r, t );
     203           0 : }
     204             : 
     205             : /*
     206             :  * Ser/de
     207             :  */
     208             : 
     209             : int
     210             : fd_ed25519_point_frombytes_2x( fd_ed25519_point_t * r1,
     211             :                                uchar const          buf1[ 32 ],
     212             :                                fd_ed25519_point_t * r2,
     213      608568 :                                uchar const          buf2[ 32 ] ) {
     214      608568 :   fd_ed25519_point_t * res = NULL;
     215      608568 :   res = fd_ed25519_point_frombytes( r1, buf1 );
     216      608568 :   if( res == NULL ) {
     217       80268 :     return 1;
     218       80268 :   }
     219      528300 :   res = fd_ed25519_point_frombytes( r2, buf2 );
     220      528300 :   if( res == NULL ) {
     221        8818 :     return 2;
     222        8818 :   }
     223      519482 :   return 0;
     224      528300 : }
     225             : 
     226             : /*
     227             :   Affine (only for init(), can be slow)
     228             : */
     229             : fd_ed25519_point_t *
     230             : fd_curve25519_affine_frombytes( fd_ed25519_point_t * r,
     231             :                                 uchar const          x[ 32 ],
     232           2 :                                 uchar const          y[ 32 ] ) {
     233           2 :   fd_f25519_frombytes( r->X, x );
     234           2 :   fd_f25519_frombytes( r->Y, y );
     235           2 :   fd_f25519_set( r->Z, fd_f25519_one );
     236           2 :   fd_f25519_mul( r->T, r->X, r->Y );
     237           2 :   return r;
     238           2 : }
     239             : 
     240             : fd_ed25519_point_t *
     241           0 : fd_curve25519_into_affine( fd_ed25519_point_t * r ) {
     242           0 :   fd_f25519_t invz[1];
     243           0 :   fd_f25519_inv( invz, r->Z );
     244           0 :   fd_f25519_mul( r->X, r->X, invz );
     245           0 :   fd_f25519_mul( r->Y, r->Y, invz );
     246           0 :   fd_f25519_set( r->Z, fd_f25519_one );
     247           0 :   fd_f25519_mul( r->T, r->X, r->Y );
     248           0 :   return r;
     249           0 : }

Generated by: LCOV version 1.14