Line data Source code
1 : #ifndef HEADER_fd_src_ballet_ed25519_fd_f25519_h
2 : #error "Do not include this directly; use fd_f25519.h"
3 : #endif
4 :
5 : #include "../../fd_ballet_base.h"
6 : #include "fd_r43x6.h"
7 :
8 : #define FD_F25519_ALIGN 64
9 :
10 : /* A fd_f25519_t stores a curve25519 field element in 5 ulong, aligned to 64 bytes */
11 : struct fd_f25519 {
12 : fd_r43x6_t el __attribute__((aligned(FD_F25519_ALIGN)));
13 : };
14 : typedef struct fd_f25519 fd_f25519_t;
15 :
16 : #include "../table/fd_f25519_table_avx512.c"
17 :
18 : FD_PROTOTYPES_BEGIN
19 :
20 : /*
21 : * Implementation of inline functions
22 : */
23 :
24 : /* fd_f25519_mul computes r = a * b, and returns r. */
25 : FD_25519_INLINE fd_f25519_t *
26 : fd_f25519_mul( fd_f25519_t * r,
27 : fd_f25519_t const * a,
28 16065715 : fd_f25519_t const * b ) {
29 16065715 : FD_R43X6_MUL1_INL( r->el, a->el, b->el );
30 16065715 : return r;
31 16065715 : }
32 :
33 : /* fd_f25519_sqr computes r = a^2, and returns r. */
34 : FD_25519_INLINE fd_f25519_t *
35 : fd_f25519_sqr( fd_f25519_t * r,
36 249115780 : fd_f25519_t const * a ) {
37 249115780 : FD_R43X6_SQR1_INL( r->el, a->el );
38 249115780 : return r;
39 249115780 : }
40 :
41 : /* fd_f25519_add computes r = a + b, and returns r. */
42 : FD_25519_INLINE fd_f25519_t *
43 : fd_f25519_add( fd_f25519_t * r,
44 : fd_f25519_t const * a,
45 1320680 : fd_f25519_t const * b ) {
46 1320680 : (r->el) = fd_r43x6_add( (a->el), (b->el) );
47 1320680 : return r;
48 1320680 : }
49 :
50 : /* fd_f25519_add computes r = a - b, and returns r. */
51 : FD_25519_INLINE fd_f25519_t *
52 : fd_f25519_sub( fd_f25519_t * r,
53 : fd_f25519_t const * a,
54 3236920 : fd_f25519_t const * b ) {
55 3236920 : (r->el) = fd_r43x6_fold_signed( fd_r43x6_sub_fast( (a->el), (b->el) ) );
56 3236920 : return r;
57 3236920 : }
58 :
59 : /* fd_f25519_add computes r = a + b, and returns r.
60 : Note: this does NOT reduce the result mod p.
61 : It can be used before mul, sqr. */
62 : FD_25519_INLINE fd_f25519_t *
63 : fd_f25519_add_nr( fd_f25519_t * r,
64 : fd_f25519_t const * a,
65 2 : fd_f25519_t const * b ) {
66 2 : (r->el) = fd_r43x6_add_fast( (a->el), (b->el) );
67 2 : return r;
68 2 : }
69 :
70 : /* fd_f25519_sub computes r = a - b, and returns r.
71 : Note: this does NOT reduce the result mod p.
72 : It can be used before mul, sqr. */
73 : FD_25519_INLINE fd_f25519_t *
74 : fd_f25519_sub_nr( fd_f25519_t * r,
75 : fd_f25519_t const * a,
76 0 : fd_f25519_t const * b ) {
77 0 : (r->el) = fd_r43x6_sub_fast( (a->el), (b->el) );
78 0 : return r;
79 0 : }
80 :
81 : /* fd_f25519_add computes r = -a, and returns r. */
82 : FD_25519_INLINE fd_f25519_t *
83 : fd_f25519_neg( fd_f25519_t * r,
84 992526 : fd_f25519_t const * a ) {
85 992526 : (r->el) = fd_r43x6_neg( (a->el) );
86 992526 : return r;
87 992526 : }
88 :
89 : /* fd_f25519_add computes r = a * k, k=121666, and returns r. */
90 : FD_25519_INLINE fd_f25519_t *
91 : fd_f25519_mul_121666( fd_f25519_t * r,
92 0 : FD_FN_UNUSED fd_f25519_t const * a ) {
93 0 : (r->el) = fd_r43x6_fold_unsigned( fd_r43x6_scale_fast( 121666L, (a->el) ) );
94 0 : return r;
95 0 : }
96 :
97 : /* fd_f25519_frombytes deserializes a 32-byte buffer buf into a
98 : fd_f25519_t element r, and returns r.
99 : buf is in little endian form, we accept non-canonical elements
100 : unlike RFC 8032. */
101 : FD_25519_INLINE fd_f25519_t *
102 : fd_f25519_frombytes( fd_f25519_t * r,
103 1196431 : uchar const buf[ 32 ] ) {
104 1196431 : ulong y0 = fd_ulong_load_8_fast( buf ); /* Bits 0- 63 */
105 1196431 : ulong y1 = fd_ulong_load_8_fast( buf+8 ); /* Bits 64-127 */
106 1196431 : ulong y2 = fd_ulong_load_8_fast( buf+16 ); /* Bits 128-191 */
107 1196431 : ulong y3 = fd_ulong_load_8_fast( buf+24 ) & 0x7fffffffffffffff; /* Bits 192-254 */
108 1196431 : r->el = fd_r43x6_unpack( wv( y0, y1, y2, y3 ) );
109 1196431 : return r;
110 1196431 : }
111 :
112 : /* fd_f25519_tobytes serializes a fd_f25519_t element a into
113 : a 32-byte buffer out, and returns out.
114 : out is in little endian form, according to RFC 8032
115 : (we don't output non-canonical elements). */
116 : FD_25519_INLINE uchar *
117 : fd_f25519_tobytes( uchar out[ 32 ],
118 3167844 : fd_f25519_t const * a ) {
119 3167844 : wv_stu( out, fd_r43x6_pack( fd_r43x6_mod( a->el ) ) );
120 3167844 : return out;
121 3167844 : }
122 :
123 : /* fd_f25519_if sets r = a0 if cond, else r = a1, equivalent to:
124 : r = cond ? a0 : a1.
125 : Note: this is constant time. */
126 : FD_25519_INLINE fd_f25519_t *
127 : fd_f25519_if( fd_f25519_t * r,
128 : int const cond, /* 0, 1 */
129 : fd_f25519_t const * a0,
130 1252079 : fd_f25519_t const * a1 ) {
131 1252079 : r->el = fd_r43x6_if( -!!cond, a0->el, a1->el );
132 1252079 : return r;
133 1252079 : }
134 :
135 : /* fd_f25519_swap_if swaps r1, r2 if cond, else leave them as is.
136 : Note: this is constant time. */
137 : FD_25519_INLINE void
138 : fd_f25519_swap_if( fd_f25519_t * restrict r1,
139 : fd_f25519_t * restrict r2,
140 0 : int const cond /* 0, 1 */ ) {
141 0 : wwl_t zero = wwl_zero();
142 0 : wwl_t m = wwl_xor(r1->el, r2->el);
143 0 : m = wwl_if( -!!cond, m, zero );
144 0 : r1->el = wwl_xor( r1->el, m );
145 0 : r2->el = wwl_xor( r2->el, m );
146 0 : }
147 :
148 : /* fd_f25519_set copies r = a, and returns r. */
149 : FD_25519_INLINE fd_f25519_t *
150 : fd_f25519_set( fd_f25519_t * r,
151 1130536 : fd_f25519_t const * a ) {
152 1130536 : r->el = a->el;
153 1130536 : return r;
154 1130536 : }
155 :
156 : /* fd_f25519_is_zero returns 1 if a == 0, 0 otherwise. */
157 : FD_25519_INLINE int
158 2939413 : fd_f25519_is_zero( fd_f25519_t const * a ) {
159 2939413 : return ( ( wwl_eq( a->el, fd_r43x6_zero() ) & 0xFF ) == 0xFF )
160 2939413 : || ( ( wwl_eq( a->el, fd_r43x6_p() ) & 0xFF ) == 0xFF );
161 2939413 : }
162 :
163 : /*
164 : * Vectorized
165 : */
166 :
167 : /* fd_f25519_muln computes r_i = a_i * b_i */
168 : FD_25519_INLINE void
169 : fd_f25519_mul2( fd_f25519_t * r1, fd_f25519_t const * a1, fd_f25519_t const * b1,
170 599802 : fd_f25519_t * r2, fd_f25519_t const * a2, fd_f25519_t const * b2 ) {
171 599802 : FD_R43X6_MUL2_INL( r1->el, a1->el, b1->el,
172 599802 : r2->el, a2->el, b2->el );
173 599802 : }
174 :
175 : FD_25519_INLINE void
176 : fd_f25519_mul3( fd_f25519_t * r1, fd_f25519_t const * a1, fd_f25519_t const * b1,
177 : fd_f25519_t * r2, fd_f25519_t const * a2, fd_f25519_t const * b2,
178 0 : fd_f25519_t * r3, fd_f25519_t const * a3, fd_f25519_t const * b3 ) {
179 0 : FD_R43X6_MUL3_INL( r1->el, a1->el, b1->el,
180 0 : r2->el, a2->el, b2->el,
181 0 : r3->el, a3->el, b3->el );
182 0 : }
183 :
184 : FD_25519_INLINE void
185 : fd_f25519_mul4( fd_f25519_t * r1, fd_f25519_t const * a1, fd_f25519_t const * b1,
186 : fd_f25519_t * r2, fd_f25519_t const * a2, fd_f25519_t const * b2,
187 : fd_f25519_t * r3, fd_f25519_t const * a3, fd_f25519_t const * b3,
188 30002 : fd_f25519_t * r4, fd_f25519_t const * a4, fd_f25519_t const * b4 ) {
189 30002 : FD_R43X6_MUL4_INL( r1->el, a1->el, b1->el,
190 30002 : r2->el, a2->el, b2->el,
191 30002 : r3->el, a3->el, b3->el,
192 30002 : r4->el, a4->el, b4->el );
193 30002 : }
194 :
195 : /* fd_f25519_sqrn computes r_i = a_i^2 */
196 : FD_25519_INLINE void
197 : fd_f25519_sqr2( fd_f25519_t * r1, fd_f25519_t const * a1,
198 0 : fd_f25519_t * r2, fd_f25519_t const * a2 ) {
199 0 : FD_R43X6_SQR2_INL( r1->el, a1->el,
200 0 : r2->el, a2->el );
201 0 : }
202 :
203 : FD_25519_INLINE void
204 : fd_f25519_sqr3( fd_f25519_t * r1, fd_f25519_t const * a1,
205 : fd_f25519_t * r2, fd_f25519_t const * a2,
206 0 : fd_f25519_t * r3, fd_f25519_t const * a3 ) {
207 0 : FD_R43X6_SQR3_INL( r1->el, a1->el,
208 0 : r2->el, a2->el,
209 0 : r3->el, a3->el );
210 0 : }
211 :
212 : FD_25519_INLINE void
213 : fd_f25519_sqr4( fd_f25519_t * r1, fd_f25519_t const * a1,
214 : fd_f25519_t * r2, fd_f25519_t const * a2,
215 : fd_f25519_t * r3, fd_f25519_t const * a3,
216 0 : fd_f25519_t * r4, fd_f25519_t const * a4 ) {
217 : FD_R43X6_SQR4_INL( r1->el, a1->el,
218 0 : r2->el, a2->el,
219 0 : r3->el, a3->el,
220 0 : r4->el, a4->el );
221 0 : }
222 :
223 : FD_PROTOTYPES_END
|