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