1use crate::FieldBytes;
5use elliptic_curve::{
6 subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
7 zeroize::Zeroize,
8};
9
10#[derive(Clone, Copy, Debug)]
16pub struct FieldElement5x52(pub(crate) [u64; 5]);
17
18impl FieldElement5x52 {
19 pub const ZERO: Self = Self([0, 0, 0, 0, 0]);
21
22 pub const ONE: Self = Self([1, 0, 0, 0, 0]);
24
25 pub(crate) const fn from_bytes_unchecked(bytes: &[u8; 32]) -> Self {
28 let w0 = (bytes[31] as u64)
29 | ((bytes[30] as u64) << 8)
30 | ((bytes[29] as u64) << 16)
31 | ((bytes[28] as u64) << 24)
32 | ((bytes[27] as u64) << 32)
33 | ((bytes[26] as u64) << 40)
34 | (((bytes[25] & 0xFu8) as u64) << 48);
35
36 let w1 = ((bytes[25] >> 4) as u64)
37 | ((bytes[24] as u64) << 4)
38 | ((bytes[23] as u64) << 12)
39 | ((bytes[22] as u64) << 20)
40 | ((bytes[21] as u64) << 28)
41 | ((bytes[20] as u64) << 36)
42 | ((bytes[19] as u64) << 44);
43
44 let w2 = (bytes[18] as u64)
45 | ((bytes[17] as u64) << 8)
46 | ((bytes[16] as u64) << 16)
47 | ((bytes[15] as u64) << 24)
48 | ((bytes[14] as u64) << 32)
49 | ((bytes[13] as u64) << 40)
50 | (((bytes[12] & 0xFu8) as u64) << 48);
51
52 let w3 = ((bytes[12] >> 4) as u64)
53 | ((bytes[11] as u64) << 4)
54 | ((bytes[10] as u64) << 12)
55 | ((bytes[9] as u64) << 20)
56 | ((bytes[8] as u64) << 28)
57 | ((bytes[7] as u64) << 36)
58 | ((bytes[6] as u64) << 44);
59
60 let w4 = (bytes[5] as u64)
61 | ((bytes[4] as u64) << 8)
62 | ((bytes[3] as u64) << 16)
63 | ((bytes[2] as u64) << 24)
64 | ((bytes[1] as u64) << 32)
65 | ((bytes[0] as u64) << 40);
66
67 Self([w0, w1, w2, w3, w4])
68 }
69
70 #[inline]
75 pub fn from_bytes(bytes: &FieldBytes) -> CtOption<Self> {
76 let res = Self::from_bytes_unchecked(bytes.as_ref());
77 let overflow = res.get_overflow();
78 CtOption::new(res, !overflow)
79 }
80
81 pub const fn from_u64(val: u64) -> Self {
82 let w0 = val & 0xFFFFFFFFFFFFF;
83 let w1 = val >> 52;
84 Self([w0, w1, 0, 0, 0])
85 }
86
87 pub fn to_bytes(self) -> FieldBytes {
89 let mut ret = FieldBytes::default();
90 ret[0] = (self.0[4] >> 40) as u8;
91 ret[1] = (self.0[4] >> 32) as u8;
92 ret[2] = (self.0[4] >> 24) as u8;
93 ret[3] = (self.0[4] >> 16) as u8;
94 ret[4] = (self.0[4] >> 8) as u8;
95 ret[5] = self.0[4] as u8;
96 ret[6] = (self.0[3] >> 44) as u8;
97 ret[7] = (self.0[3] >> 36) as u8;
98 ret[8] = (self.0[3] >> 28) as u8;
99 ret[9] = (self.0[3] >> 20) as u8;
100 ret[10] = (self.0[3] >> 12) as u8;
101 ret[11] = (self.0[3] >> 4) as u8;
102 ret[12] = ((self.0[2] >> 48) as u8 & 0xFu8) | ((self.0[3] as u8 & 0xFu8) << 4);
103 ret[13] = (self.0[2] >> 40) as u8;
104 ret[14] = (self.0[2] >> 32) as u8;
105 ret[15] = (self.0[2] >> 24) as u8;
106 ret[16] = (self.0[2] >> 16) as u8;
107 ret[17] = (self.0[2] >> 8) as u8;
108 ret[18] = self.0[2] as u8;
109 ret[19] = (self.0[1] >> 44) as u8;
110 ret[20] = (self.0[1] >> 36) as u8;
111 ret[21] = (self.0[1] >> 28) as u8;
112 ret[22] = (self.0[1] >> 20) as u8;
113 ret[23] = (self.0[1] >> 12) as u8;
114 ret[24] = (self.0[1] >> 4) as u8;
115 ret[25] = ((self.0[0] >> 48) as u8 & 0xFu8) | ((self.0[1] as u8 & 0xFu8) << 4);
116 ret[26] = (self.0[0] >> 40) as u8;
117 ret[27] = (self.0[0] >> 32) as u8;
118 ret[28] = (self.0[0] >> 24) as u8;
119 ret[29] = (self.0[0] >> 16) as u8;
120 ret[30] = (self.0[0] >> 8) as u8;
121 ret[31] = self.0[0] as u8;
122 ret
123 }
124
125 fn add_modulus_correction(&self, x: u64) -> Self {
127 let t0 = self.0[0] + x * 0x1000003D1u64;
129
130 let t1 = self.0[1] + (t0 >> 52);
132 let t0 = t0 & 0xFFFFFFFFFFFFFu64;
133
134 let t2 = self.0[2] + (t1 >> 52);
135 let t1 = t1 & 0xFFFFFFFFFFFFFu64;
136
137 let t3 = self.0[3] + (t2 >> 52);
138 let t2 = t2 & 0xFFFFFFFFFFFFFu64;
139
140 let t4 = self.0[4] + (t3 >> 52);
141 let t3 = t3 & 0xFFFFFFFFFFFFFu64;
142
143 Self([t0, t1, t2, t3, t4])
144 }
145
146 fn subtract_modulus_approximation(&self) -> (Self, u64) {
149 let x = self.0[4] >> 48;
150 let t4 = self.0[4] & 0x0FFFFFFFFFFFFu64; (Self([self.0[0], self.0[1], self.0[2], self.0[3], t4]), x)
152 }
153
154 fn get_overflow(&self) -> Choice {
156 let m = self.0[1] & self.0[2] & self.0[3];
157 let x = (self.0[4] >> 48 != 0)
158 | ((self.0[4] == 0x0FFFFFFFFFFFFu64)
159 & (m == 0xFFFFFFFFFFFFFu64)
160 & (self.0[0] >= 0xFFFFEFFFFFC2Fu64));
161 Choice::from(x as u8)
162 }
163
164 pub fn normalize_weak(&self) -> Self {
166 let (t, x) = self.subtract_modulus_approximation();
168
169 let res = t.add_modulus_correction(x);
171
172 debug_assert!(res.0[4] >> 49 == 0);
174
175 res
176 }
177
178 pub fn normalize(&self) -> Self {
182 let res = self.normalize_weak();
183
184 let overflow = res.get_overflow();
187
188 let res_corrected = res.add_modulus_correction(1u64);
190 let (res_corrected, x) = res_corrected.subtract_modulus_approximation();
192
193 debug_assert!(x == (overflow.unwrap_u8() as u64));
196
197 Self::conditional_select(&res, &res_corrected, overflow)
198 }
199
200 pub fn normalizes_to_zero(&self) -> Choice {
202 let res = self.normalize_weak();
203
204 let t0 = res.0[0];
205 let t1 = res.0[1];
206 let t2 = res.0[2];
207 let t3 = res.0[3];
208 let t4 = res.0[4];
209
210 let z0 = t0 | t1 | t2 | t3 | t4;
212 let z1 = (t0 ^ 0x1000003D0u64) & t1 & t2 & t3 & (t4 ^ 0xF000000000000u64);
213
214 Choice::from(((z0 == 0) | (z1 == 0xFFFFFFFFFFFFFu64)) as u8)
215 }
216
217 pub fn is_zero(&self) -> Choice {
223 Choice::from(((self.0[0] | self.0[1] | self.0[2] | self.0[3] | self.0[4]) == 0) as u8)
224 }
225
226 pub fn is_odd(&self) -> Choice {
232 (self.0[0] as u8 & 1).into()
233 }
234
235 #[cfg(debug_assertions)]
237 pub const fn max_magnitude() -> u32 {
238 2047u32
239 }
240
241 pub const fn negate(&self, magnitude: u32) -> Self {
245 let m = (magnitude + 1) as u64;
246 let r0 = 0xFFFFEFFFFFC2Fu64 * 2 * m - self.0[0];
247 let r1 = 0xFFFFFFFFFFFFFu64 * 2 * m - self.0[1];
248 let r2 = 0xFFFFFFFFFFFFFu64 * 2 * m - self.0[2];
249 let r3 = 0xFFFFFFFFFFFFFu64 * 2 * m - self.0[3];
250 let r4 = 0x0FFFFFFFFFFFFu64 * 2 * m - self.0[4];
251 Self([r0, r1, r2, r3, r4])
252 }
253
254 pub const fn add(&self, rhs: &Self) -> Self {
257 Self([
258 self.0[0] + rhs.0[0],
259 self.0[1] + rhs.0[1],
260 self.0[2] + rhs.0[2],
261 self.0[3] + rhs.0[3],
262 self.0[4] + rhs.0[4],
263 ])
264 }
265
266 pub const fn mul_single(&self, rhs: u32) -> Self {
269 let rhs_u64 = rhs as u64;
270 Self([
271 self.0[0] * rhs_u64,
272 self.0[1] * rhs_u64,
273 self.0[2] * rhs_u64,
274 self.0[3] * rhs_u64,
275 self.0[4] * rhs_u64,
276 ])
277 }
278
279 #[inline(always)]
280 fn mul_inner(&self, rhs: &Self) -> Self {
281 let a0 = self.0[0] as u128;
293 let a1 = self.0[1] as u128;
294 let a2 = self.0[2] as u128;
295 let a3 = self.0[3] as u128;
296 let a4 = self.0[4] as u128;
297 let b0 = rhs.0[0] as u128;
298 let b1 = rhs.0[1] as u128;
299 let b2 = rhs.0[2] as u128;
300 let b3 = rhs.0[3] as u128;
301 let b4 = rhs.0[4] as u128;
302 let m = 0xFFFFFFFFFFFFFu128;
303 let r = 0x1000003D10u128;
304
305 debug_assert!(a0 >> 56 == 0);
306 debug_assert!(a1 >> 56 == 0);
307 debug_assert!(a2 >> 56 == 0);
308 debug_assert!(a3 >> 56 == 0);
309 debug_assert!(a4 >> 52 == 0);
310
311 debug_assert!(b0 >> 56 == 0);
312 debug_assert!(b1 >> 56 == 0);
313 debug_assert!(b2 >> 56 == 0);
314 debug_assert!(b3 >> 56 == 0);
315 debug_assert!(b4 >> 52 == 0);
316
317 let mut d = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
323 debug_assert!(d >> 114 == 0);
324 let mut c = a4 * b4;
326 debug_assert!(c >> 112 == 0);
327 d += (c & m) * r;
329 c >>= 52;
330 debug_assert!(d >> 115 == 0);
331 debug_assert!(c >> 60 == 0);
332 let c64 = c as u64;
333 let t3 = (d & m) as u64;
335 d >>= 52;
336 debug_assert!(t3 >> 52 == 0);
337 debug_assert!(d >> 63 == 0);
338 let d64 = d as u64;
339 d = d64 as u128 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
342 debug_assert!(d >> 115 == 0);
343 d += c64 as u128 * r;
345 debug_assert!(d >> 116 == 0);
346 let t4 = (d & m) as u64;
348 d >>= 52;
349 debug_assert!(t4 >> 52 == 0);
350 debug_assert!(d >> 64 == 0);
351 let d64 = d as u64;
352 let tx = t4 >> 48;
354 let t4 = t4 & ((m as u64) >> 4);
355 debug_assert!(tx >> 4 == 0);
356 debug_assert!(t4 >> 48 == 0);
357 c = a0 * b0;
360 debug_assert!(c >> 112 == 0);
361 d = d64 as u128 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1;
363 debug_assert!(d >> 115 == 0);
364 let u0 = (d & m) as u64;
366 d >>= 52;
367 debug_assert!(u0 >> 52 == 0);
368 debug_assert!(d >> 63 == 0);
369 let d64 = d as u64;
370 let u0 = (u0 << 4) | tx;
373 debug_assert!(u0 >> 56 == 0);
374 c += u0 as u128 * ((r as u64) >> 4) as u128;
376 debug_assert!(c >> 115 == 0);
377 let r0 = (c & m) as u64;
379 c >>= 52;
380 debug_assert!(r0 >> 52 == 0);
381 debug_assert!(c >> 61 == 0);
382 let c64 = c as u64;
383 c = c64 as u128 + a0 * b1 + a1 * b0;
386 debug_assert!(c >> 114 == 0);
387 d = d64 as u128 + a2 * b4 + a3 * b3 + a4 * b2;
389 debug_assert!(d >> 114 == 0);
390 c += (d & m) * r;
392 d >>= 52;
393 debug_assert!(c >> 115 == 0);
394 debug_assert!(d >> 62 == 0);
395 let d64 = d as u64;
396 let r1 = (c & m) as u64;
398 c >>= 52;
399 debug_assert!(r1 >> 52 == 0);
400 debug_assert!(c >> 63 == 0);
401 let c64 = c as u64;
402 c = c64 as u128 + a0 * b2 + a1 * b1 + a2 * b0;
405 debug_assert!(c >> 114 == 0);
406 d = d64 as u128 + a3 * b4 + a4 * b3;
408 debug_assert!(d >> 114 == 0);
409 c += (d & m) * r;
411 d >>= 52;
412 debug_assert!(c >> 115 == 0);
413 debug_assert!(d >> 62 == 0);
414 let d64 = d as u64;
415 let r2 = (c & m) as u64;
419 c >>= 52;
420 debug_assert!(r2 >> 52 == 0);
421 debug_assert!(c >> 63 == 0);
422 let c64 = c as u64;
423 c = c64 as u128 + (d64 as u128) * r + t3 as u128;
425 debug_assert!(c >> 100 == 0);
426 let r3 = (c & m) as u64;
428 c >>= 52;
429 debug_assert!(r3 >> 52 == 0);
430 debug_assert!(c >> 48 == 0);
431 let c64 = c as u64;
432 c = c64 as u128 + t4 as u128;
434 debug_assert!(c >> 49 == 0);
435 let r4 = c as u64;
437 debug_assert!(r4 >> 49 == 0);
438 Self([r0, r1, r2, r3, r4])
441 }
442
443 #[inline(always)]
447 pub fn mul(&self, rhs: &Self) -> Self {
448 self.mul_inner(rhs)
449 }
450
451 pub fn square(&self) -> Self {
455 self.mul_inner(self)
456 }
457}
458
459impl Default for FieldElement5x52 {
460 fn default() -> Self {
461 Self::ZERO
462 }
463}
464
465impl ConditionallySelectable for FieldElement5x52 {
466 #[inline(always)]
467 fn conditional_select(
468 a: &FieldElement5x52,
469 b: &FieldElement5x52,
470 choice: Choice,
471 ) -> FieldElement5x52 {
472 FieldElement5x52([
473 u64::conditional_select(&a.0[0], &b.0[0], choice),
474 u64::conditional_select(&a.0[1], &b.0[1], choice),
475 u64::conditional_select(&a.0[2], &b.0[2], choice),
476 u64::conditional_select(&a.0[3], &b.0[3], choice),
477 u64::conditional_select(&a.0[4], &b.0[4], choice),
478 ])
479 }
480}
481
482impl ConstantTimeEq for FieldElement5x52 {
483 fn ct_eq(&self, other: &Self) -> Choice {
484 self.0[0].ct_eq(&other.0[0])
485 & self.0[1].ct_eq(&other.0[1])
486 & self.0[2].ct_eq(&other.0[2])
487 & self.0[3].ct_eq(&other.0[3])
488 & self.0[4].ct_eq(&other.0[4])
489 }
490}
491
492impl Zeroize for FieldElement5x52 {
493 fn zeroize(&mut self) {
494 self.0.zeroize();
495 }
496}
497
498#[cfg(test)]
499mod tests {
500 use super::FieldElement5x52;
501
502 #[test]
503 fn overflow_check_after_weak_normalize() {
504 let z = FieldElement5x52([
519 (1 << 52), (1 << 52) - 1,
522 (1 << 52) - 1,
523 (1 << 52) - 1,
524 (1 << 48) - 1,
526 ]);
527
528 let z_normalized = z.normalize();
530
531 let z_reference = FieldElement5x52([0x1000003d1, 0, 0, 0, 0]);
534
535 assert_eq!(z_normalized.0, z_reference.0);
536 }
537}