LCOV - code coverage report
Current view: top level - ballet/ed25519 - fd_curve25519_secure.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 60 60 100.0 %
Date: 2024-11-13 11:58:15 Functions: 4 4 100.0 %

          Line data    Source code
       1             : #include "fd_curve25519.h"
       2             : 
       3             : #if FD_HAS_AVX512
       4             : #include "avx512/fd_curve25519_secure.c"
       5             : #else
       6             : #include "ref/fd_curve25519_secure.c"
       7             : #endif
       8             : 
       9             : /* All the functions in this file are considered "secure", specifically:
      10             : 
      11             :    - Constant time in the input, i.e. the input can be a secret
      12             :    - Small and auditable code base, incl. simple types
      13             :    - Either, no local variables = no need to clear them before exit (most functions)
      14             :    - Or, only static allocation + clear local variable before exit (fd_ed25519_scalar_mul_base_const_time)
      15             :    - Clear registers via FD_FN_SENSITIVE
      16             :    - C safety
      17             :  */
      18             : 
      19             : FD_25519_INLINE void FD_FN_SENSITIVE
      20             : fd_ed25519_scalar_radix16( char        secret_e[ 64 ], /* ouput: 64-entry in [-8;8] */
      21             :                            uchar const secret_a[ 32 ], /* input: 32-byte, assumes valid scalar */
      22     1759947 :                            char *      tmp_secret_carry ) {
      23     1759947 :   (*tmp_secret_carry) = 0;
      24             : 
      25    58078251 :   for( int i=0; i<32; i++ ) {
      26    56318304 :     secret_e[2*i+0] = (char)((secret_a[i]     ) & 0xF);
      27    56318304 :     secret_e[2*i+1] = (char)((secret_a[i] >> 4) & 0xF);
      28    56318304 :   }
      29             : 
      30             :   /* At this point, e[0:62] are in [0:15], e[63] is in [0:7] */
      31             : 
      32   112636608 :   for( int i=0; i<63; i++ ) {
      33   110876661 :     secret_e[i] = (char)(secret_e[i] + (*tmp_secret_carry));
      34   110876661 :     (*tmp_secret_carry) = (char)((secret_e[i] + 8) >> 4);
      35   110876661 :     secret_e[i] = (char)(secret_e[i] - ((*tmp_secret_carry) << 4));
      36   110876661 :   }
      37     1759947 :   secret_e[63] = (char)(secret_e[63] + (*tmp_secret_carry));
      38     1759947 : }
      39             : 
      40             : /* const_time_eq returns a==b ? 1 : 0.
      41             :    Note: this is const time. */
      42             : FD_25519_INLINE uchar FD_FN_SENSITIVE
      43   901092864 : const_time_eq( const uchar secret_a, const uchar secret_b ) {
      44   901092864 :   return (uchar)((((uint)(secret_a ^ secret_b))-1U) >> 31);
      45   901092864 : }
      46             : 
      47             : /* fd_ed25519_table_select selects an element in the table of pre-computed
      48             :    points &fd_ed25519_base_point_const_time_table.
      49             : 
      50             :    Given (j, secret), j in 0..31, secret in -8..7:
      51             :    - if secret==0 return 0 (point at infinity)
      52             :    - if secret>0  return table[j][secret-1]
      53             :    - if secret<0  return table[j][-secret-1]
      54             : 
      55             :    Note: this is const time, equivalent to the following code:
      56             :     if ( secret == 0 ) {
      57             :       fd_ed25519_point_set_zero_precomputed( r );
      58             :     } else if ( secret > 0 ) {
      59             :       fd_ed25519_point_set( r, &fd_ed25519_base_point_const_time_table[j][secret-1] );
      60             :     } else {
      61             :       fd_ed25519_point_neg( r, &fd_ed25519_base_point_const_time_table[j][-secret-1] );
      62             :     }
      63             : */
      64             : FD_25519_INLINE void FD_FN_SENSITIVE
      65             : fd_ed25519_table_select( fd_ed25519_point_t * r,
      66             :                          fd_ed25519_point_t * tmp,
      67             :                          int j,
      68             :                          char secret,
      69             :                          uchar * tmp_secret_idx,
      70   112636608 :                          uchar * tmp_secret_sgn ) {
      71             :   // (*tmp_secret_sgn) = secret < 0 ? 1 : 0;
      72   112636608 :   (*tmp_secret_sgn) = ((uchar)(secret)) >> 7;
      73             :   // (*tmp_secret_idx) = (secret < 0) ? (uchar)(-secret-1) : (secret > 0) ? (uchar)secret-1 : 0xff;
      74   112636608 :   (*tmp_secret_idx) = (uchar)(secret - (2*(*tmp_secret_sgn)*secret) - 1); // e = e - (2*e) = -e = |e| if e<0, e - 2*0 = e = |e| o.w.
      75             : 
      76             :   /* select the point from table in const time */
      77   112636608 :   fd_ed25519_point_set_zero_precomputed( tmp );
      78             : 
      79             :   /* for( uchar i=0; i<8; i++ ) unrolled */
      80   112636608 :   fd_ed25519_point_if( r,   const_time_eq( 0, (*tmp_secret_idx) ), &fd_ed25519_base_point_const_time_table[j][0], tmp );
      81   112636608 :   fd_ed25519_point_if( tmp, const_time_eq( 1, (*tmp_secret_idx) ), &fd_ed25519_base_point_const_time_table[j][1], r   );
      82   112636608 :   fd_ed25519_point_if( r,   const_time_eq( 2, (*tmp_secret_idx) ), &fd_ed25519_base_point_const_time_table[j][2], tmp );
      83   112636608 :   fd_ed25519_point_if( tmp, const_time_eq( 3, (*tmp_secret_idx) ), &fd_ed25519_base_point_const_time_table[j][3], r   );
      84   112636608 :   fd_ed25519_point_if( r,   const_time_eq( 4, (*tmp_secret_idx) ), &fd_ed25519_base_point_const_time_table[j][4], tmp );
      85   112636608 :   fd_ed25519_point_if( tmp, const_time_eq( 5, (*tmp_secret_idx) ), &fd_ed25519_base_point_const_time_table[j][5], r   );
      86   112636608 :   fd_ed25519_point_if( r,   const_time_eq( 6, (*tmp_secret_idx) ), &fd_ed25519_base_point_const_time_table[j][6], tmp );
      87   112636608 :   fd_ed25519_point_if( tmp, const_time_eq( 7, (*tmp_secret_idx) ), &fd_ed25519_base_point_const_time_table[j][7], r   );
      88             : 
      89             :   /* negate point if needed, in const time */
      90   112636608 :   fd_ed25519_point_neg_if( r, tmp, (*tmp_secret_sgn) );
      91   112636608 : }
      92             : 
      93             : /* fd_ed25519_scalar_mul_base_const_time computes a scalar mul of the base point
      94             :    in const time wrt secret_scalar, clearing stack and registers before returning.
      95             :    This is the main function used by fd_ed25519_sign.
      96             :    All sub-functions called by fd_ed25519_scalar_mul_base_const_time are expected
      97             :    to be static inline, have no local variable, and clear their registers. */
      98             : 
      99             : fd_ed25519_point_t * FD_FN_SENSITIVE
     100             : fd_ed25519_scalar_mul_base_const_time( fd_ed25519_point_t * r,
     101     1759947 :                                        uchar const          secret_scalar[ 32 ] ) { /* can be a secret */
     102             : 
     103             :   //TODO: add input ptr to secure memory from the caller?
     104             : 
     105             :   /* memory areas that will contain (partial) secrets and will be cleared at the end */
     106     1759947 :   char secret_scalar_naf[64 + 2];
     107     1759947 :   fd_ed25519_point_t secret_tmp_points[5];
     108             : 
     109             :   /* human-readable variables */
     110     1759947 :   char * tmp_secret_carry = &secret_scalar_naf[64];
     111     1759947 :   uchar * tmp_secret_idx = (uchar *)&secret_scalar_naf[64];
     112     1759947 :   uchar * tmp_secret_sgn = (uchar *)&secret_scalar_naf[65];
     113     1759947 :   fd_ed25519_point_t * selected =        &secret_tmp_points[0]; // selected point from precomput table
     114     1759947 :   fd_ed25519_point_t * r2 =              &secret_tmp_points[1]; // temp result, to 2-unroll loop
     115     1759947 :   fd_ed25519_point_t * selected2 =       &secret_tmp_points[2]; // temp selectedc point, to 2-unroll loop
     116     1759947 :   fd_ed25519_point_t * add_secure_tmp0 = &secret_tmp_points[3]; // tmp0 point for fd_ed25519_point_add_secure
     117     1759947 :   fd_ed25519_point_t * add_secure_tmp1 = &secret_tmp_points[4]; // tmp1 point for fd_ed25519_point_add_secure
     118             : 
     119     1759947 :   fd_ed25519_scalar_radix16( secret_scalar_naf, secret_scalar, tmp_secret_carry );
     120             : 
     121     1759947 :   fd_ed25519_point_set_zero( r );
     122    29919099 :   for( int i=1; i<64; i+=4 ) {
     123    28159152 :     fd_ed25519_table_select( selected, selected2, i/2, secret_scalar_naf[i], tmp_secret_idx, tmp_secret_sgn );
     124    28159152 :     fd_ed25519_point_add_secure( r2, r, selected, add_secure_tmp0, add_secure_tmp1 );
     125    28159152 :     fd_ed25519_table_select( selected2, selected, i/2+1, secret_scalar_naf[i+2], tmp_secret_idx, tmp_secret_sgn );
     126    28159152 :     fd_ed25519_point_add_secure( r, r2, selected2, add_secure_tmp0, add_secure_tmp1 );
     127    28159152 :   }
     128             : 
     129     1759947 :   fd_ed25519_point_dbln_secure( r, r, 4, add_secure_tmp0, add_secure_tmp1 );
     130             : 
     131    29919099 :   for( int i=0; i<64; i+=4 ) {
     132    28159152 :     fd_ed25519_table_select( selected, selected2, i/2, secret_scalar_naf[i], tmp_secret_idx, tmp_secret_sgn );
     133    28159152 :     fd_ed25519_point_add_secure( r2, r, selected, add_secure_tmp0, add_secure_tmp1 );
     134    28159152 :     fd_ed25519_table_select( selected2, selected, i/2+1, secret_scalar_naf[i+2], tmp_secret_idx, tmp_secret_sgn );
     135    28159152 :     fd_ed25519_point_add_secure( r, r2, selected2, add_secure_tmp0, add_secure_tmp1 );
     136    28159152 :   }
     137             : 
     138             :   /* Sanitize */
     139             : 
     140     1759947 :   fd_memset_explicit( secret_scalar_naf, 0, sizeof(secret_scalar_naf) );
     141     1759947 :   fd_memset_explicit( secret_tmp_points, 0, sizeof(secret_tmp_points) );
     142             : 
     143     1759947 :   return r;
     144     1759947 : }

Generated by: LCOV version 1.14