LCOV - code coverage report
Current view: top level - ballet/ed25519 - fd_curve25519.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 15 22 68.2 %
Date: 2025-01-08 12:08:44 Functions: 7 100 7.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_ballet_ed25519_fd_curve25519_h
       2             : #define HEADER_fd_src_ballet_ed25519_fd_curve25519_h
       3             : 
       4             : /* fd_curve25519.h provides the public Curve25519 API.
       5             : 
       6             :    Most operations in this API should be assumed to take a variable
       7             :    amount of time depending on inputs.  (And thus should not be exposed
       8             :    to secret data).
       9             : 
      10             :    Const time operations are made explicit, see fd_curve25519_secure.c */
      11             : 
      12             : #if FD_HAS_AVX512
      13             : #include "avx512/fd_curve25519.h"
      14             : #else
      15             : #include "ref/fd_curve25519.h"
      16             : #endif
      17             : 
      18             : /* Max batch size for MSM. */
      19       14334 : #define FD_BALLET_CURVE25519_MSM_BATCH_SZ 32
      20             : 
      21             : /* curve constants. these are imported from table/fd_curve25519_table_{arch}.c.
      22             :    they are (re)defined here to avoid breaking compilation when the table needs
      23             :    to be rebuilt. */
      24             : static const fd_ed25519_point_t fd_ed25519_base_point[1];
      25             : static const fd_ed25519_point_t fd_ed25519_base_point_wnaf_table[128];
      26             : static const fd_ed25519_point_t fd_ed25519_base_point_const_time_table[32][8];
      27             : 
      28             : FD_PROTOTYPES_BEGIN
      29             : 
      30             : /* fd_ed25519_point_add computes r = a + b, and returns r.
      31             :    formulas are complete, i.e. it can be a == b.
      32             :    Cost: 9mul */
      33             : fd_ed25519_point_t *
      34             : fd_ed25519_point_add( fd_ed25519_point_t *       r,
      35             :                       fd_ed25519_point_t const * a,
      36             :                       fd_ed25519_point_t const * b );
      37             : 
      38             : /* fd_ed25519_point_dbln computes r = 2^n a, and returns r.
      39             :    More efficient than n fd_ed25519_point_add. */
      40             : fd_ed25519_point_t *
      41             : fd_ed25519_point_dbln( fd_ed25519_point_t *       r,
      42             :                        fd_ed25519_point_t const * a,
      43             :                        int const                  n );
      44             : 
      45             : /* fd_ed25519_point_sub computes r = a - b, and returns r.
      46             :    formulas are complete, i.e. it can be a == b.
      47             :    Cost: 9mul */
      48             : fd_ed25519_point_t *
      49             : fd_ed25519_point_sub( fd_ed25519_point_t *       r,
      50             :                       fd_ed25519_point_t const * a,
      51             :                       fd_ed25519_point_t const * b );
      52             : 
      53             : /* fd_ed25519_point_set sets r = 0 (point at infinity). */
      54             : fd_ed25519_point_t *
      55             : fd_ed25519_point_set_zero( fd_ed25519_point_t * r );
      56             : 
      57             : /* fd_ed25519_point_set_zero_precomputed sets r = 0 (point at infinity). */
      58             : fd_ed25519_point_t *
      59             : fd_ed25519_point_set_zero_precomputed( fd_ed25519_point_t * r );
      60             : 
      61             : /* fd_ed25519_point_set sets r = a. */
      62             : fd_ed25519_point_t *
      63             : fd_ed25519_point_set( fd_ed25519_point_t *       r,
      64             :                       fd_ed25519_point_t const * a );
      65             : 
      66             : /* fd_ed25519_point_from sets r = (x : y : z : t). */
      67             : fd_ed25519_point_t *
      68             : fd_ed25519_point_from( fd_ed25519_point_t * r,
      69             :                        fd_f25519_t const *  x,
      70             :                        fd_f25519_t const *  y,
      71             :                        fd_f25519_t const *  z,
      72             :                        fd_f25519_t const *  t );
      73             : 
      74             : /* fd_ed25519_point_sub sets r = -a. */
      75             : fd_ed25519_point_t *
      76             : fd_ed25519_point_neg( fd_ed25519_point_t *       r,
      77             :                       fd_ed25519_point_t const * a );
      78             : 
      79             : fd_ed25519_point_t *
      80             : fd_ed25519_point_dbl( fd_ed25519_point_t *       r,
      81             :                       fd_ed25519_point_t const * a );
      82             : 
      83             : /* fd_ed25519_point_is_zero returns 1 if a == 0 (point at infinity), 0 otherwise. */
      84             : int
      85             : fd_ed25519_point_is_zero( fd_ed25519_point_t const * a );
      86             : 
      87             : /* fd_ed25519_affine_is_small_order returns 1 if a has small order (order <= 8), 0 otherwise. */
      88             : FD_25519_INLINE int
      89     1549977 : fd_ed25519_affine_is_small_order( fd_ed25519_point_t const * a ) {
      90             :   /* There are 8 points with order <= 8, aka low order:
      91             :      0100000000000000000000000000000000000000000000000000000000000000 ( 0    :  1   )  P0: order 1
      92             :      ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f ( 0    : -1   )  P1: order 2
      93             :      0000000000000000000000000000000000000000000000000000000000000000 ( b0.. :  0   )  P2: order 4
      94             :      0000000000000000000000000000000000000000000000000000000000000080 ( 3d.. :  0   ) -P2: order 4
      95             :      26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05 ( 4a.. : 26.. )  P3: order 8
      96             :      26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85 ( a3.. : 26.. ) -P3: order 8
      97             :      c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a ( 4a.. : c7.. )  P4: order 8
      98             :      c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa ( a3.. : c7.. ) -P4: order 8
      99             : 
     100             :      We could test:
     101             :        fd_ed25519_point_t r[1];
     102             :        fd_ed25519_point_dbln( r, a, 3 );
     103             :        return fd_ed25519_point_is_zero( r );
     104             : 
     105             :      When the point is affine (Z==1), we can simply check:
     106             :      -     X==0
     107             :      - or, Y==0
     108             :      - or, Y==2a..., or Y==c7...
     109             : 
     110             :      And if the point is not affine, we could do 1 single dbl and check for X==0 or Y==0
     111             :      (currently not implemented as not needed).
     112             :   */
     113     1549977 :   fd_f25519_t x[1], y[1], z[1], t[1];
     114     1549977 :   fd_ed25519_point_to( x, y, z, t, a );
     115     1549977 :   return fd_f25519_is_zero( x ) | fd_f25519_is_zero( y )
     116     1549977 :     | fd_f25519_eq( y, fd_ed25519_order8_point_y0 )
     117     1549977 :     | fd_f25519_eq( y, fd_ed25519_order8_point_y1 );
     118     1549977 : }
     119             : 
     120             : /* fd_ed25519_point_eq returns 1 if a == b, 0 otherwise. */
     121             : int
     122             : fd_ed25519_point_eq( fd_ed25519_point_t const * a,
     123             :                      fd_ed25519_point_t const * b );
     124             : 
     125             : /* fd_ed25519_point_eq returns 1 if a == b, 0 otherwise.
     126             :    b is a point with Z==1, e.g. a decompressed point. */
     127             : int
     128             : fd_ed25519_point_eq_z1( fd_ed25519_point_t const * a,
     129             :                         fd_ed25519_point_t const * b ); /* b.Z == 1, e.g. a decompressed point */
     130             : 
     131             : /* fd_ed25519_scalar_validate is an alias of fd_curve25519_scalar_validate
     132             :    It checks whether the given Ed25519 scalar n matches the canonical byte
     133             :    representation.  Not constant time and thus should not be exposed to secrets.
     134             :    Returns s if canonical, NULL otherwise. */
     135             : 
     136             : FD_25519_INLINE uchar const *
     137     3000009 : fd_ed25519_scalar_validate( uchar const n[ 32 ] ) {
     138     3000009 :   return fd_curve25519_scalar_validate( n );
     139     3000009 : }
     140             : 
     141             : /* fd_ed25519_scalar_mul computes r = n * a, and returns r.
     142             :    n is a scalar. */
     143             : fd_ed25519_point_t *
     144             : fd_ed25519_scalar_mul( fd_ed25519_point_t *       r,
     145             :                        uchar const                n[ 32 ],
     146             :                        fd_ed25519_point_t const * a );
     147             : 
     148             : /* fd_ed25519_scalar_mul_base_const_time computes r = n * P, and returns r.
     149             :    n is a scalar. P is the base point.
     150             :    Note: const time implementation, safe to use with n secret. */
     151             : fd_ed25519_point_t * FD_FN_SENSITIVE
     152             : fd_ed25519_scalar_mul_base_const_time( fd_ed25519_point_t * r,
     153             :                                        uchar const          n[ 32 ] ); /* can be a secret */
     154             : 
     155             : /* fd_ed25519_scalar_mul computes r = n1 * a + n2 * P, and returns r.
     156             :    n1, n2 are scalars. P is the base point. */
     157             : fd_ed25519_point_t *
     158             : fd_ed25519_double_scalar_mul_base( fd_ed25519_point_t *       r,
     159             :                                    uchar const                n1[ 32 ],
     160             :                                    fd_ed25519_point_t const * a,
     161             :                                    uchar const                n2[ 32 ] );
     162             : 
     163             : /* fd_ed25519_multi_scalar_mul computes r = n0 * a0 + n1 * a1 + ..., and returns r.
     164             :    n is a vector of sz scalars. a is a vector of sz points. */
     165             : fd_ed25519_point_t *
     166             : fd_ed25519_multi_scalar_mul( fd_ed25519_point_t *     r,
     167             :                              uchar const              n[], /* sz * 32 */
     168             :                              fd_ed25519_point_t const a[],  /* sz */
     169             :                              ulong const              sz );
     170             : 
     171             : /* fd_ed25519_multi_scalar_mul computes r = n0 * B + n1 * a1 + ..., and returns r.
     172             :    n is a vector of sz scalars. a is a vector of sz points.
     173             :    the first point is ignored, and the base point is used instead. */
     174             : fd_ed25519_point_t *
     175             : fd_ed25519_multi_scalar_mul_base( fd_ed25519_point_t *     r,
     176             :                                   uchar const              n[], /* sz * 32 */
     177             :                                   fd_ed25519_point_t const a[],  /* sz */
     178             :                                   ulong const              sz );
     179             : 
     180             : /* fd_ed25519_point_frombytes deserializes a 32-byte buffer buf into a
     181             :    point r, and returns r (on success, NULL on error).
     182             :    buf is in little endian form, according to RFC 8032.
     183             :    Cost: 1sqrt ~= 1inv ~= 250mul */
     184             : fd_ed25519_point_t *
     185             : fd_ed25519_point_frombytes( fd_ed25519_point_t * r,
     186             :                             uchar const          buf[ 32 ] );
     187             : 
     188             : /* fd_ed25519_point_frombytes_2x deserializes 2x 32-byte buffers buf1, buf2
     189             :    resp. into points r1, r2, and returns r.
     190             :    buf1, buf2 are in little endian form, according to RFC 8032.
     191             :    It returns 0 on success, 1 or 2 on failure.
     192             :    Cost: 2sqrt (executed concurrently if possible) */
     193             : int
     194             : fd_ed25519_point_frombytes_2x( fd_ed25519_point_t * r1,
     195             :                                uchar const          buf1[ 32 ],
     196             :                                fd_ed25519_point_t * r2,
     197             :                                uchar const          buf2[ 32 ] );
     198             : 
     199             : /* fd_ed25519_point_validate checks if buf represents a valid compressed point,
     200             :    by attempting to decompress it.
     201             :    Use fd_ed25519_point_frombytes if the decompressed point is needed.
     202             :    It returns 1 if buf represents a valid point, 0 if not. */
     203             : FD_25519_INLINE int
     204        1353 : fd_ed25519_point_validate(uchar const buf[ 32 ] ) {
     205        1353 :   fd_ed25519_point_t t[1];
     206        1353 :   return !!fd_ed25519_point_frombytes( t, buf );
     207        1353 : }
     208             : 
     209             : /* fd_ed25519_point_tobytes serializes a point a into
     210             :    a 32-byte buffer out, and returns out.
     211             :    out is in little endian form, according to RFC 8032. */
     212             : uchar *
     213             : fd_ed25519_point_tobytes( uchar                      out[ 32 ],
     214             :                           fd_ed25519_point_t const * a );
     215             : 
     216             : /* fd_ed25519_affine_tobytes serializes a point a into
     217             :    a 32-byte buffer out, and returns out.
     218             :    out is in little endian form, according to RFC 8032.
     219             :    a is an affine point, i.e. a->Z == 1; compared to
     220             :    fd_ed25519_point_tobytes, this function doesn't require inv. */
     221             : FD_25519_INLINE uchar *
     222             : fd_ed25519_affine_tobytes( uchar                      out[ 32 ],
     223           0 :                            fd_ed25519_point_t const * a ) {
     224           0 :   fd_f25519_t x[1], y[1], z[1], t[1];
     225           0 :   fd_ed25519_point_to( x, y, z, t, a );
     226           0 :   fd_f25519_tobytes( out, y );
     227           0 :   out[31] ^= (uchar)(fd_f25519_sgn( x ) << 7);
     228           0 :   return out;
     229           0 : }
     230             : 
     231             : /* fd_curve25519_into_precomputed transforms a point into
     232             :    precomputed table format, e.g. replaces T -> kT to save
     233             :    1mul in the dbl-and-add loop. */
     234             : void
     235             : fd_curve25519_into_precomputed( fd_ed25519_point_t * r );
     236             : 
     237             : /*
     238             :   Affine (only for offline building precomputation tables, can be slow)
     239             : */
     240             : fd_ed25519_point_t *
     241             : fd_curve25519_affine_frombytes( fd_ed25519_point_t * r,
     242             :                                 uchar const          x[ 32 ],
     243             :                                 uchar const          y[ 32 ] );
     244             : 
     245             : fd_ed25519_point_t *
     246             : fd_curve25519_into_affine( fd_ed25519_point_t * r );
     247             : 
     248             : fd_ed25519_point_t *
     249             : fd_curve25519_affine_add( fd_ed25519_point_t *       r,
     250             :                           fd_ed25519_point_t const * a,
     251             :                           fd_ed25519_point_t const * b );
     252             : 
     253             : fd_ed25519_point_t *
     254             : fd_curve25519_affine_dbln( fd_ed25519_point_t *       r,
     255             :                            fd_ed25519_point_t const * a,
     256             :                            int const                  n );
     257             : 
     258             : FD_PROTOTYPES_END
     259             : 
     260             : #endif /* HEADER_fd_src_ballet_ed25519_fd_curve25519_h */

Generated by: LCOV version 1.14