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 58789890 : #define FD_R43X6_GE_ADD_TABLE_ALT( P3, P1, T2, _ta, _tb ) do { \
20 58789890 : FD_R43X6_QUAD_MOV ( _ta, T2 ); /* _ta = (Y2-X2,Y2+X2,Z2=1,T2*2d), u44|u44|u44|u44 */ \
21 58789890 : FD_R43X6_QUAD_PERMUTE ( _tb, 1,0,2,3, P1 ); /* _tb = (Y1, X1, Z1, T1 ), s61|s61|s61|s61 */ \
22 58789890 : 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 58789890 : 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 58789890 : FD_R43X6_QUAD_FOLD_SIGNED ( _tb, _tb ); /* _tb = (Y1-X1,Y1+X1,Z1*2,T1 ), u44|u44|u44|u44 */ \
25 58789890 : FD_R43X6_QUAD_MUL_FAST ( _ta, _ta, _tb ); /* _ta = (A, B, D, C ), u62|u62|u62|u62 */ \
26 58789890 : FD_R43X6_QUAD_FOLD_UNSIGNED( _ta, _ta ); /* _ta = (A, B, D, C ), u44|u44|u44|u44 */ \
27 58789890 : FD_R43X6_QUAD_PERMUTE ( _tb, 1,0,3,2, _ta ); /* _tb = (B, A, C, D ), u44|u44|u44|u44 */ \
28 58789890 : FD_R43X6_QUAD_LANE_SUB_FAST( _tb, _tb, 1,0,0,1, _tb, _ta ); /* _tb = (E, A, C, F ), s45|u44|u44|s45 */ \
29 58789890 : FD_R43X6_QUAD_LANE_ADD_FAST( _tb, _tb, 0,1,1,0, _tb, _ta ); /* _tb = (E, H, G, F ), s45|u45|u45|s45 */ \
30 58789890 : FD_R43X6_QUAD_FOLD_SIGNED ( _tb, _tb ); /* _tb = (E, H, G, F ), u44|u44|u44|u44 */ \
31 58789890 : FD_R43X6_QUAD_PERMUTE ( _ta, 0,2,2,0, _tb ); /* _ta = (E, G, G, E ), u44|u44|u44|u44 */ \
32 58789890 : FD_R43X6_QUAD_PERMUTE ( _tb, 3,1,3,1, _tb ); /* _tb = (F, H, F, H ), u44|u44|u44|u44 */ \
33 58789890 : FD_R43X6_QUAD_MUL_FAST ( _ta, _ta, _tb ); /* _ta = (X3, Y3, Z3, T3 ), u62|u62|u62|u62 */ \
34 58789890 : FD_R43X6_QUAD_FOLD_UNSIGNED( P3, _ta ); /* P3 = (X3, Y3, Z3, T3 ), u44|u44|u44|u44 */ \
35 58789890 : } 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 : }
|