main
Raw Download raw file
  1package fp25519
  2
  3import (
  4	"encoding/binary"
  5	"math/bits"
  6)
  7
  8func cmovGeneric(x, y *Elt, n uint) {
  9	m := -uint64(n & 0x1)
 10	x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
 11	x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
 12	x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
 13	x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
 14
 15	y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
 16	y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
 17	y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
 18	y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
 19
 20	x0 = (x0 &^ m) | (y0 & m)
 21	x1 = (x1 &^ m) | (y1 & m)
 22	x2 = (x2 &^ m) | (y2 & m)
 23	x3 = (x3 &^ m) | (y3 & m)
 24
 25	binary.LittleEndian.PutUint64(x[0*8:1*8], x0)
 26	binary.LittleEndian.PutUint64(x[1*8:2*8], x1)
 27	binary.LittleEndian.PutUint64(x[2*8:3*8], x2)
 28	binary.LittleEndian.PutUint64(x[3*8:4*8], x3)
 29}
 30
 31func cswapGeneric(x, y *Elt, n uint) {
 32	m := -uint64(n & 0x1)
 33	x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
 34	x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
 35	x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
 36	x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
 37
 38	y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
 39	y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
 40	y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
 41	y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
 42
 43	t0 := m & (x0 ^ y0)
 44	t1 := m & (x1 ^ y1)
 45	t2 := m & (x2 ^ y2)
 46	t3 := m & (x3 ^ y3)
 47	x0 ^= t0
 48	x1 ^= t1
 49	x2 ^= t2
 50	x3 ^= t3
 51	y0 ^= t0
 52	y1 ^= t1
 53	y2 ^= t2
 54	y3 ^= t3
 55
 56	binary.LittleEndian.PutUint64(x[0*8:1*8], x0)
 57	binary.LittleEndian.PutUint64(x[1*8:2*8], x1)
 58	binary.LittleEndian.PutUint64(x[2*8:3*8], x2)
 59	binary.LittleEndian.PutUint64(x[3*8:4*8], x3)
 60
 61	binary.LittleEndian.PutUint64(y[0*8:1*8], y0)
 62	binary.LittleEndian.PutUint64(y[1*8:2*8], y1)
 63	binary.LittleEndian.PutUint64(y[2*8:3*8], y2)
 64	binary.LittleEndian.PutUint64(y[3*8:4*8], y3)
 65}
 66
 67func addGeneric(z, x, y *Elt) {
 68	x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
 69	x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
 70	x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
 71	x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
 72
 73	y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
 74	y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
 75	y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
 76	y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
 77
 78	z0, c0 := bits.Add64(x0, y0, 0)
 79	z1, c1 := bits.Add64(x1, y1, c0)
 80	z2, c2 := bits.Add64(x2, y2, c1)
 81	z3, c3 := bits.Add64(x3, y3, c2)
 82
 83	z0, c0 = bits.Add64(z0, (-c3)&38, 0)
 84	z1, c1 = bits.Add64(z1, 0, c0)
 85	z2, c2 = bits.Add64(z2, 0, c1)
 86	z3, c3 = bits.Add64(z3, 0, c2)
 87	z0, _ = bits.Add64(z0, (-c3)&38, 0)
 88
 89	binary.LittleEndian.PutUint64(z[0*8:1*8], z0)
 90	binary.LittleEndian.PutUint64(z[1*8:2*8], z1)
 91	binary.LittleEndian.PutUint64(z[2*8:3*8], z2)
 92	binary.LittleEndian.PutUint64(z[3*8:4*8], z3)
 93}
 94
 95func subGeneric(z, x, y *Elt) {
 96	x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
 97	x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
 98	x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
 99	x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
100
101	y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
102	y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
103	y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
104	y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
105
106	z0, c0 := bits.Sub64(x0, y0, 0)
107	z1, c1 := bits.Sub64(x1, y1, c0)
108	z2, c2 := bits.Sub64(x2, y2, c1)
109	z3, c3 := bits.Sub64(x3, y3, c2)
110
111	z0, c0 = bits.Sub64(z0, (-c3)&38, 0)
112	z1, c1 = bits.Sub64(z1, 0, c0)
113	z2, c2 = bits.Sub64(z2, 0, c1)
114	z3, c3 = bits.Sub64(z3, 0, c2)
115	z0, _ = bits.Sub64(z0, (-c3)&38, 0)
116
117	binary.LittleEndian.PutUint64(z[0*8:1*8], z0)
118	binary.LittleEndian.PutUint64(z[1*8:2*8], z1)
119	binary.LittleEndian.PutUint64(z[2*8:3*8], z2)
120	binary.LittleEndian.PutUint64(z[3*8:4*8], z3)
121}
122
123func addsubGeneric(x, y *Elt) {
124	z := &Elt{}
125	addGeneric(z, x, y)
126	subGeneric(y, x, y)
127	*x = *z
128}
129
130func mulGeneric(z, x, y *Elt) {
131	x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
132	x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
133	x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
134	x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
135
136	y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
137	y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
138	y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
139	y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
140
141	yi := y0
142	h0, l0 := bits.Mul64(x0, yi)
143	h1, l1 := bits.Mul64(x1, yi)
144	h2, l2 := bits.Mul64(x2, yi)
145	h3, l3 := bits.Mul64(x3, yi)
146
147	z0 := l0
148	a0, c0 := bits.Add64(h0, l1, 0)
149	a1, c1 := bits.Add64(h1, l2, c0)
150	a2, c2 := bits.Add64(h2, l3, c1)
151	a3, _ := bits.Add64(h3, 0, c2)
152
153	yi = y1
154	h0, l0 = bits.Mul64(x0, yi)
155	h1, l1 = bits.Mul64(x1, yi)
156	h2, l2 = bits.Mul64(x2, yi)
157	h3, l3 = bits.Mul64(x3, yi)
158
159	z1, c0 := bits.Add64(a0, l0, 0)
160	h0, c1 = bits.Add64(h0, l1, c0)
161	h1, c2 = bits.Add64(h1, l2, c1)
162	h2, c3 := bits.Add64(h2, l3, c2)
163	h3, _ = bits.Add64(h3, 0, c3)
164
165	a0, c0 = bits.Add64(a1, h0, 0)
166	a1, c1 = bits.Add64(a2, h1, c0)
167	a2, c2 = bits.Add64(a3, h2, c1)
168	a3, _ = bits.Add64(0, h3, c2)
169
170	yi = y2
171	h0, l0 = bits.Mul64(x0, yi)
172	h1, l1 = bits.Mul64(x1, yi)
173	h2, l2 = bits.Mul64(x2, yi)
174	h3, l3 = bits.Mul64(x3, yi)
175
176	z2, c0 := bits.Add64(a0, l0, 0)
177	h0, c1 = bits.Add64(h0, l1, c0)
178	h1, c2 = bits.Add64(h1, l2, c1)
179	h2, c3 = bits.Add64(h2, l3, c2)
180	h3, _ = bits.Add64(h3, 0, c3)
181
182	a0, c0 = bits.Add64(a1, h0, 0)
183	a1, c1 = bits.Add64(a2, h1, c0)
184	a2, c2 = bits.Add64(a3, h2, c1)
185	a3, _ = bits.Add64(0, h3, c2)
186
187	yi = y3
188	h0, l0 = bits.Mul64(x0, yi)
189	h1, l1 = bits.Mul64(x1, yi)
190	h2, l2 = bits.Mul64(x2, yi)
191	h3, l3 = bits.Mul64(x3, yi)
192
193	z3, c0 := bits.Add64(a0, l0, 0)
194	h0, c1 = bits.Add64(h0, l1, c0)
195	h1, c2 = bits.Add64(h1, l2, c1)
196	h2, c3 = bits.Add64(h2, l3, c2)
197	h3, _ = bits.Add64(h3, 0, c3)
198
199	z4, c0 := bits.Add64(a1, h0, 0)
200	z5, c1 := bits.Add64(a2, h1, c0)
201	z6, c2 := bits.Add64(a3, h2, c1)
202	z7, _ := bits.Add64(0, h3, c2)
203
204	red64(z, z0, z1, z2, z3, z4, z5, z6, z7)
205}
206
207func sqrGeneric(z, x *Elt) {
208	x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
209	x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
210	x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
211	x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
212
213	h0, a0 := bits.Mul64(x0, x1)
214	h1, l1 := bits.Mul64(x0, x2)
215	h2, l2 := bits.Mul64(x0, x3)
216	h3, l3 := bits.Mul64(x3, x1)
217	h4, l4 := bits.Mul64(x3, x2)
218	h, l := bits.Mul64(x1, x2)
219
220	a1, c0 := bits.Add64(l1, h0, 0)
221	a2, c1 := bits.Add64(l2, h1, c0)
222	a3, c2 := bits.Add64(l3, h2, c1)
223	a4, c3 := bits.Add64(l4, h3, c2)
224	a5, _ := bits.Add64(h4, 0, c3)
225
226	a2, c0 = bits.Add64(a2, l, 0)
227	a3, c1 = bits.Add64(a3, h, c0)
228	a4, c2 = bits.Add64(a4, 0, c1)
229	a5, c3 = bits.Add64(a5, 0, c2)
230	a6, _ := bits.Add64(0, 0, c3)
231
232	a0, c0 = bits.Add64(a0, a0, 0)
233	a1, c1 = bits.Add64(a1, a1, c0)
234	a2, c2 = bits.Add64(a2, a2, c1)
235	a3, c3 = bits.Add64(a3, a3, c2)
236	a4, c4 := bits.Add64(a4, a4, c3)
237	a5, c5 := bits.Add64(a5, a5, c4)
238	a6, _ = bits.Add64(a6, a6, c5)
239
240	b1, b0 := bits.Mul64(x0, x0)
241	b3, b2 := bits.Mul64(x1, x1)
242	b5, b4 := bits.Mul64(x2, x2)
243	b7, b6 := bits.Mul64(x3, x3)
244
245	b1, c0 = bits.Add64(b1, a0, 0)
246	b2, c1 = bits.Add64(b2, a1, c0)
247	b3, c2 = bits.Add64(b3, a2, c1)
248	b4, c3 = bits.Add64(b4, a3, c2)
249	b5, c4 = bits.Add64(b5, a4, c3)
250	b6, c5 = bits.Add64(b6, a5, c4)
251	b7, _ = bits.Add64(b7, a6, c5)
252
253	red64(z, b0, b1, b2, b3, b4, b5, b6, b7)
254}
255
256func modpGeneric(x *Elt) {
257	x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
258	x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
259	x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
260	x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
261
262	// CX = C[255] ? 38 : 19
263	cx := uint64(19) << (x3 >> 63)
264	// PUT BIT 255 IN CARRY FLAG AND CLEAR
265	x3 &^= 1 << 63
266
267	x0, c0 := bits.Add64(x0, cx, 0)
268	x1, c1 := bits.Add64(x1, 0, c0)
269	x2, c2 := bits.Add64(x2, 0, c1)
270	x3, _ = bits.Add64(x3, 0, c2)
271
272	// TEST FOR BIT 255 AGAIN; ONLY TRIGGERED ON OVERFLOW MODULO 2^255-19
273	// cx = C[255] ? 0 : 19
274	cx = uint64(19) &^ (-(x3 >> 63))
275	// CLEAR BIT 255
276	x3 &^= 1 << 63
277
278	x0, c0 = bits.Sub64(x0, cx, 0)
279	x1, c1 = bits.Sub64(x1, 0, c0)
280	x2, c2 = bits.Sub64(x2, 0, c1)
281	x3, _ = bits.Sub64(x3, 0, c2)
282
283	binary.LittleEndian.PutUint64(x[0*8:1*8], x0)
284	binary.LittleEndian.PutUint64(x[1*8:2*8], x1)
285	binary.LittleEndian.PutUint64(x[2*8:3*8], x2)
286	binary.LittleEndian.PutUint64(x[3*8:4*8], x3)
287}
288
289func red64(z *Elt, x0, x1, x2, x3, x4, x5, x6, x7 uint64) {
290	h0, l0 := bits.Mul64(x4, 38)
291	h1, l1 := bits.Mul64(x5, 38)
292	h2, l2 := bits.Mul64(x6, 38)
293	h3, l3 := bits.Mul64(x7, 38)
294
295	l1, c0 := bits.Add64(h0, l1, 0)
296	l2, c1 := bits.Add64(h1, l2, c0)
297	l3, c2 := bits.Add64(h2, l3, c1)
298	l4, _ := bits.Add64(h3, 0, c2)
299
300	l0, c0 = bits.Add64(l0, x0, 0)
301	l1, c1 = bits.Add64(l1, x1, c0)
302	l2, c2 = bits.Add64(l2, x2, c1)
303	l3, c3 := bits.Add64(l3, x3, c2)
304	l4, _ = bits.Add64(l4, 0, c3)
305
306	_, l4 = bits.Mul64(l4, 38)
307	l0, c0 = bits.Add64(l0, l4, 0)
308	z1, c1 := bits.Add64(l1, 0, c0)
309	z2, c2 := bits.Add64(l2, 0, c1)
310	z3, c3 := bits.Add64(l3, 0, c2)
311	z0, _ := bits.Add64(l0, (-c3)&38, 0)
312
313	binary.LittleEndian.PutUint64(z[0*8:1*8], z0)
314	binary.LittleEndian.PutUint64(z[1*8:2*8], z1)
315	binary.LittleEndian.PutUint64(z[2*8:3*8], z2)
316	binary.LittleEndian.PutUint64(z[3*8:4*8], z3)
317}