LCOV - code coverage report
Current view: top level - ballet/ed25519/avx512 - fd_curve25519_secure.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 61 61 100.0 %
Date: 2026-01-24 04:58:51 Functions: 6 8 75.0 %

          Line data    Source code
       1             : #include "../fd_curve25519.h"
       2             : #include "./fd_r43x6_ge.h"
       3             : 
       4             : /* All the functions in this file are considered "secure", specifically:
       5             : 
       6             :    - Constant time in the input, i.e. the input can be a secret
       7             :    - Small and auditable code base, incl. simple types
       8             :    - No local variables = no need to clear them before exit
       9             :    - Clear registers via FD_FN_SENSITIVE
      10             :  */
      11             : 
      12             : /* FD_R43X6_GE_ADD_TABLE_ALT is similar to FD_R43X6_GE_ADD,
      13             :    with 3 minor differences:
      14             :    1. order of arguments: P3, P1 points in extended Edwards coordinates,
      15             :       T2 precomputed table point
      16             :    2. T2 = (Y-X : Y+X : Z==1 : kT), all coords are u44
      17             :    3. temp vars as input, so we can safely clear them in the caller
      18             : */
      19    58789844 : #define FD_R43X6_GE_ADD_TABLE_ALT( P3, P1, T2, _ta, _tb ) do {                                                                  \
      20    58789844 :     FD_R43X6_QUAD_MOV          ( _ta, T2 );                     /* _ta = (Y2-X2,Y2+X2,Z2=1,T2*2d), u44|u44|u44|u44 */ \
      21    58789844 :     FD_R43X6_QUAD_PERMUTE      ( _tb, 1,0,2,3, P1 );            /* _tb = (Y1,   X1,   Z1,  T1   ), s61|s61|s61|s61 */ \
      22    58789844 :     FD_R43X6_QUAD_LANE_SUB_FAST( _tb, _tb, 1,0,0,0, _tb, P1 );  /* _tb = (Y1-X1,X1,   Z1,  T1   ), s62|s61|s61|s61 */ \
      23    58789844 :     FD_R43X6_QUAD_LANE_ADD_FAST( _tb, _tb, 0,1,1,0, _tb, P1 );  /* _tb = (Y1-X1,Y1+X1,Z1*2,T1   ), s62|s62|s62|s61 */ \
      24    58789844 :     FD_R43X6_QUAD_FOLD_SIGNED  ( _tb, _tb );                    /* _tb = (Y1-X1,Y1+X1,Z1*2,T1   ), u44|u44|u44|u44 */ \
      25    58789844 :     FD_R43X6_QUAD_MUL_FAST     ( _ta, _ta, _tb );               /* _ta = (A,    B,    D,   C    ), u62|u62|u62|u62 */ \
      26    58789844 :     FD_R43X6_QUAD_FOLD_UNSIGNED( _ta, _ta );                    /* _ta = (A,    B,    D,   C    ), u44|u44|u44|u44 */ \
      27    58789844 :     FD_R43X6_QUAD_PERMUTE      ( _tb, 1,0,3,2, _ta );           /* _tb = (B,    A,    C,   D    ), u44|u44|u44|u44 */ \
      28    58789844 :     FD_R43X6_QUAD_LANE_SUB_FAST( _tb, _tb, 1,0,0,1, _tb, _ta ); /* _tb = (E,    A,    C,   F    ), s45|u44|u44|s45 */ \
      29    58789844 :     FD_R43X6_QUAD_LANE_ADD_FAST( _tb, _tb, 0,1,1,0, _tb, _ta ); /* _tb = (E,    H,    G,   F    ), s45|u45|u45|s45 */ \
      30    58789844 :     FD_R43X6_QUAD_FOLD_SIGNED  ( _tb, _tb );                    /* _tb = (E,    H,    G,   F    ), u44|u44|u44|u44 */ \
      31    58789844 :     FD_R43X6_QUAD_PERMUTE      ( _ta, 0,2,2,0, _tb );           /* _ta = (E,    G,    G,   E    ), u44|u44|u44|u44 */ \
      32    58789844 :     FD_R43X6_QUAD_PERMUTE      ( _tb, 3,1,3,1, _tb );           /* _tb = (F,    H,    F,   H    ), u44|u44|u44|u44 */ \
      33    58789844 :     FD_R43X6_QUAD_MUL_FAST     ( _ta, _ta, _tb );               /* _ta = (X3,   Y3,   Z3,  T3   ), u62|u62|u62|u62 */ \
      34    58789844 :     FD_R43X6_QUAD_FOLD_UNSIGNED( P3, _ta );                     /* P3  = (X3,   Y3,   Z3,  T3   ), u44|u44|u44|u44 */ \
      35    58789844 :   } while(0)
      36             : 
      37             : /* fd_ed25519_point_add_secure computes r = a + b.
      38             : 
      39             :    It's equivalent to fd_ed25519_point_add_with_opts( r, a, b, 1, 1, 0 ),
      40             :    i.e. it assumes that b is from a precomputation table.
      41             : 
      42             :    This implementation has no temporary variables and clears registers on return.
      43             :    The intent is to avoid that an attacker can retrieve information about b,
      44             :    that was chosen in const time based on a secret value. */
      45             : FD_25519_INLINE void FD_FN_SENSITIVE
      46             : fd_ed25519_point_add_secure( fd_ed25519_point_t *       restrict r,
      47             :                              fd_ed25519_point_t const * restrict a,
      48             :                              fd_ed25519_point_t const * restrict b,
      49             :                              fd_ed25519_point_t *       restrict tmp0,
      50    36467009 :                              fd_ed25519_point_t *       restrict tmp1 ) {
      51             : 
      52    36467009 :   FD_R43X6_GE_ADD_TABLE_ALT( r->P, a->P, b->P, tmp0->P, tmp1->P );
      53             : 
      54    36467009 : }
      55             : 
      56             : /* FD_R43X6_GE_DBL_ALT is similar to FD_R43X6_GE_DBL,
      57             :    with 2 minor differences:
      58             :    1. removed _BB, by reordering instructions
      59             :    2. temp vars as input, so we can safely clear them in the caller
      60             : */
      61     2279140 : #define FD_R43X6_GE_DBL_ALT( P3, P1, _ta, _tb ) do {                                                                              \
      62     2279140 :     FD_R43X6_QUAD_PERMUTE      ( _ta, 1,1,2,0, P1 );            /* _ta = (Y1,       Y1,Z1,  X1), u44/u44/u44/u44 */ \
      63     2279140 :     FD_R43X6_QUAD_LANE_ADD_FAST( _ta, _ta, 1,0,0,0, _ta, P1 );  /* _ta = (X1+Y1,    Y1,Z1,  X1), u45/u44/u44/u44 */ \
      64     2279140 :     FD_R43X6_QUAD_SQR_FAST     ( _ta, _ta );                    /* _ta = ((X1+Y1)^2,B, Z1^2,A ), u61/u61/u61/u61 */ \
      65     2279140 :     FD_R43X6_QUAD_LANE_ADD_FAST( _ta, _ta, 0,0,1,0, _ta, _ta ); /* _ta = ((X1+Y1)^2,B, C,   A ), u61/u61/u62/u61 */ \
      66     2279140 :     FD_R43X6_QUAD_PERMUTE      ( _tb, 3,3,3,3, _ta );           /* _tb = (A,        A, A,   A ), u61/u61/u61/u61 */ \
      67     2279140 :     FD_R43X6_QUAD_LANE_ADD_FAST( _tb, _tb, 0,0,1,0, _tb, _ta ); /* _tb = (A,        A, A+C, A ), u61/u61/u63/u61 */ \
      68     2279140 :     FD_R43X6_QUAD_LANE_SUB_FAST( _tb, _tb, 1,0,0,0, _tb, _ta ); /* _tb = (A-(sum)^2,A, A+C, A ), s61/u61/u63/u61 */ \
      69     2279140 :     FD_R43X6_QUAD_PERMUTE      ( _ta, 1,1,1,1, _ta );           /* _ta = (B,        B, B,   B ), u61/u61/u61/u61 */ \
      70     2279140 :     FD_R43X6_QUAD_LANE_ADD_FAST( _tb, _tb, 1,0,0,1, _tb, _ta ); /* _tb = (E,        A, A+C, H ), s62/u61/u63/u62 */ \
      71     2279140 :     FD_R43X6_QUAD_LANE_SUB_FAST( _tb, _tb, 0,1,1,0, _tb, _ta ); /* _tb = (E,        G, F,   H ), s62/s61/s63/u62 */ \
      72     2279140 :     FD_R43X6_QUAD_FOLD_SIGNED  ( _tb, _tb );                    /* _tb = (E,        G, F,   H ), u44/u44/u44/u44 */ \
      73     2279140 :     FD_R43X6_QUAD_PERMUTE      ( _ta, 0,1,1,0, _tb );           /* _tb = (E,        G, G,   E ), u44/u44/u44/u44 */ \
      74     2279140 :     FD_R43X6_QUAD_PERMUTE      ( _tb, 2,3,2,3, _tb );           /* _tb = (F,        H, F,   H ), u44/u44/u44/u44 */ \
      75     2279140 :     FD_R43X6_QUAD_MUL_FAST     ( _ta, _ta, _tb );               /* _ta = (X3,       Y3,Z3,  T3), u62/u62/u62/u62 */ \
      76     2279140 :     FD_R43X6_QUAD_FOLD_UNSIGNED( P3, _ta );                     /* P3  = (X3,       Y3,Z3,  T3), u44/u44/u44/u44 */ \
      77     2279140 :   } while(0)
      78             : 
      79             : /* fd_ed25519_point_dbln_secure computes r = 2^n a.
      80             : 
      81             :    It's equivalent to fd_ed25519_point_dbln( r, a, n ).
      82             : 
      83             :    This implementation has no temporary variables and clears registers on return.
      84             :    The intent is to avoid that an attacker can retrieve information about a,
      85             :    that's a partial aggregation of secretly chosen points. */
      86             : FD_25519_INLINE void FD_FN_SENSITIVE
      87             : fd_ed25519_point_dbln_secure( fd_ed25519_point_t *       r,
      88             :                               fd_ed25519_point_t const * a,
      89             :                               int                        n,
      90             :                               fd_ed25519_point_t *       restrict tmp0,
      91      569785 :                               fd_ed25519_point_t *       restrict tmp1 ) {
      92      569785 :   FD_R43X6_GE_DBL_ALT( r->P, a->P, tmp0->P, tmp1->P );
      93     2279140 :   for( uchar i=1; i<n; i++ ) {
      94     1709355 :     FD_R43X6_GE_DBL_ALT( r->P, r->P, tmp0->P, tmp1->P );
      95     1709355 :   }
      96      569785 : }
      97             : 
      98             : /* fd_ed25519_point_if sets r = a0 if secret_cond, else r = a1.
      99             :    Equivalent to r = secret_cond ? a0 : a1.
     100             :    Note: this is const time, as the underlying wwl_if is const time. */
     101             : FD_25519_INLINE void FD_FN_SENSITIVE
     102             : fd_ed25519_point_if( fd_ed25519_point_t * restrict r,
     103             :                      uchar const                   secret_cond, /* 0, 1 */
     104             :                      fd_ed25519_point_t const *    a0,
     105   291729920 :                      fd_ed25519_point_t const *    a1 ) {
     106   291729920 :   r->P03 = wwl_if( -secret_cond, a0->P03, a1->P03 );
     107   291729920 :   r->P14 = wwl_if( -secret_cond, a0->P14, a1->P14 );
     108   291729920 :   r->P25 = wwl_if( -secret_cond, a0->P25, a1->P25 );
     109   291729920 : }
     110             : 
     111             : /* fd_ed25519_point_neg_if sets r = -r if secret_cond, else r = r.
     112             :    Equivalent to r = secret_cond ? -r : r.
     113             :    Note: this is const time, as the underlying wwl_if is const time. */
     114             : FD_25519_INLINE void FD_FN_SENSITIVE
     115             : fd_ed25519_point_neg_if( fd_ed25519_point_t * FD_RESTRICT r,
     116             :                          fd_ed25519_point_t * const       a,
     117    36466752 :                          uchar const                      secret_cond /* 0, 1 */ ) {
     118    36466752 :   FD_R43X6_QUAD_DECL( _p );
     119    36466752 :   _p03 = wwl( 8796093022189L, 8796093022189L, 8796093022189L, 8796093022189L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L );
     120    36466752 :   _p14 = wwl( 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L );
     121    36466752 :   _p25 = wwl( 8796093022207L, 8796093022207L, 8796093022207L, 8796093022207L, 1099511627775L, 1099511627775L, 1099511627775L, 1099511627775L );
     122    36466752 :   r->P03 = wwv_sub_if( 136, _p03, a->P03, a->P03 );
     123    36466752 :   r->P14 = wwv_sub_if( 136, _p14, a->P14, a->P14 );
     124    36466752 :   r->P25 = wwv_sub_if( 136, _p25, a->P25, a->P25 );
     125    36466752 :   FD_R43X6_QUAD_PERMUTE( r->P, 1,0,2,3, r->P );
     126    36466752 :   r->P03 = wwl_if( -secret_cond, r->P03, a->P03 );
     127    36466752 :   r->P14 = wwl_if( -secret_cond, r->P14, a->P14 );
     128    36466752 :   r->P25 = wwl_if( -secret_cond, r->P25, a->P25 );
     129    36466752 : }

Generated by: LCOV version 1.14