curve25519_dalek/field.rs
1// -*- mode: rust; -*-
2//
3// This file is part of curve25519-dalek.
4// Copyright (c) 2016-2021 isis agora lovecruft
5// Copyright (c) 2016-2019 Henry de Valence
6// See LICENSE for licensing information.
7//
8// Authors:
9// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
10// - Henry de Valence <hdevalence@hdevalence.ca>
11
12//! Field arithmetic modulo \\(p = 2\^{255} - 19\\).
13//!
14//! The `curve25519_dalek::field` module provides a type alias
15//! `curve25519_dalek::field::FieldElement` to a field element type
16//! defined in the `backend` module; either `FieldElement51` or
17//! `FieldElement2625`.
18//!
19//! Field operations defined in terms of machine
20//! operations, such as field multiplication or squaring, are defined in
21//! the backend implementation.
22//!
23//! Field operations defined in terms of other field operations, such as
24//! field inversion or square roots, are defined here.
25
26#![allow(unused_qualifications)]
27
28use cfg_if::cfg_if;
29
30use subtle::Choice;
31use subtle::ConditionallyNegatable;
32use subtle::ConditionallySelectable;
33use subtle::ConstantTimeEq;
34
35use crate::backend;
36use crate::constants;
37
38cfg_if! {
39 if #[cfg(curve25519_dalek_backend = "fiat")] {
40 /// A `FieldElement` represents an element of the field
41 /// \\( \mathbb Z / (2\^{255} - 19)\\).
42 ///
43 /// The `FieldElement` type is an alias for one of the platform-specific
44 /// implementations.
45 ///
46 /// Using formally-verified field arithmetic from fiat-crypto.
47 #[cfg(curve25519_dalek_bits = "32")]
48 pub(crate) type FieldElement = backend::serial::fiat_u32::field::FieldElement2625;
49
50 /// A `FieldElement` represents an element of the field
51 /// \\( \mathbb Z / (2\^{255} - 19)\\).
52 ///
53 /// The `FieldElement` type is an alias for one of the platform-specific
54 /// implementations.
55 ///
56 /// Using formally-verified field arithmetic from fiat-crypto.
57 #[cfg(curve25519_dalek_bits = "64")]
58 pub(crate) type FieldElement = backend::serial::fiat_u64::field::FieldElement51;
59 } else if #[cfg(curve25519_dalek_bits = "64")] {
60 /// A `FieldElement` represents an element of the field
61 /// \\( \mathbb Z / (2\^{255} - 19)\\).
62 ///
63 /// The `FieldElement` type is an alias for one of the platform-specific
64 /// implementations.
65 pub(crate) type FieldElement = backend::serial::u64::field::FieldElement51;
66 } else {
67 /// A `FieldElement` represents an element of the field
68 /// \\( \mathbb Z / (2\^{255} - 19)\\).
69 ///
70 /// The `FieldElement` type is an alias for one of the platform-specific
71 /// implementations.
72 pub(crate) type FieldElement = backend::serial::u32::field::FieldElement2625;
73 }
74}
75
76impl Eq for FieldElement {}
77
78impl PartialEq for FieldElement {
79 fn eq(&self, other: &FieldElement) -> bool {
80 self.ct_eq(other).into()
81 }
82}
83
84impl ConstantTimeEq for FieldElement {
85 /// Test equality between two `FieldElement`s. Since the
86 /// internal representation is not canonical, the field elements
87 /// are normalized to wire format before comparison.
88 fn ct_eq(&self, other: &FieldElement) -> Choice {
89 self.as_bytes().ct_eq(&other.as_bytes())
90 }
91}
92
93impl FieldElement {
94 /// Determine if this `FieldElement` is negative, in the sense
95 /// used in the ed25519 paper: `x` is negative if the low bit is
96 /// set.
97 ///
98 /// # Return
99 ///
100 /// If negative, return `Choice(1)`. Otherwise, return `Choice(0)`.
101 pub(crate) fn is_negative(&self) -> Choice {
102 let bytes = self.as_bytes();
103 (bytes[0] & 1).into()
104 }
105
106 /// Determine if this `FieldElement` is zero.
107 ///
108 /// # Return
109 ///
110 /// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`.
111 pub(crate) fn is_zero(&self) -> Choice {
112 let zero = [0u8; 32];
113 let bytes = self.as_bytes();
114
115 bytes.ct_eq(&zero)
116 }
117
118 /// Compute (self^(2^250-1), self^11), used as a helper function
119 /// within invert() and pow22523().
120 #[rustfmt::skip] // keep alignment of explanatory comments
121 fn pow22501(&self) -> (FieldElement, FieldElement) {
122 // Instead of managing which temporary variables are used
123 // for what, we define as many as we need and leave stack
124 // allocation to the compiler
125 //
126 // Each temporary variable t_i is of the form (self)^e_i.
127 // Squaring t_i corresponds to multiplying e_i by 2,
128 // so the pow2k function shifts e_i left by k places.
129 // Multiplying t_i and t_j corresponds to adding e_i + e_j.
130 //
131 // Temporary t_i Nonzero bits of e_i
132 //
133 let t0 = self.square(); // 1 e_0 = 2^1
134 let t1 = t0.square().square(); // 3 e_1 = 2^3
135 let t2 = self * &t1; // 3,0 e_2 = 2^3 + 2^0
136 let t3 = &t0 * &t2; // 3,1,0
137 let t4 = t3.square(); // 4,2,1
138 let t5 = &t2 * &t4; // 4,3,2,1,0
139 let t6 = t5.pow2k(5); // 9,8,7,6,5
140 let t7 = &t6 * &t5; // 9,8,7,6,5,4,3,2,1,0
141 let t8 = t7.pow2k(10); // 19..10
142 let t9 = &t8 * &t7; // 19..0
143 let t10 = t9.pow2k(20); // 39..20
144 let t11 = &t10 * &t9; // 39..0
145 let t12 = t11.pow2k(10); // 49..10
146 let t13 = &t12 * &t7; // 49..0
147 let t14 = t13.pow2k(50); // 99..50
148 let t15 = &t14 * &t13; // 99..0
149 let t16 = t15.pow2k(100); // 199..100
150 let t17 = &t16 * &t15; // 199..0
151 let t18 = t17.pow2k(50); // 249..50
152 let t19 = &t18 * &t13; // 249..0
153
154 (t19, t3)
155 }
156
157 /// Given a slice of pub(crate)lic `FieldElements`, replace each with its inverse.
158 ///
159 /// When an input `FieldElement` is zero, its value is unchanged.
160 #[cfg(feature = "alloc")]
161 pub(crate) fn batch_invert(inputs: &mut [FieldElement]) {
162 // Montgomery’s Trick and Fast Implementation of Masked AES
163 // Genelle, Prouff and Quisquater
164 // Section 3.2
165
166 let n = inputs.len();
167 let mut scratch = vec![FieldElement::ONE; n];
168
169 // Keep an accumulator of all of the previous products
170 let mut acc = FieldElement::ONE;
171
172 // Pass through the input vector, recording the previous
173 // products in the scratch space
174 for (input, scratch) in inputs.iter().zip(scratch.iter_mut()) {
175 *scratch = acc;
176 // acc <- acc * input, but skipping zeros (constant-time)
177 acc.conditional_assign(&(&acc * input), !input.is_zero());
178 }
179
180 // acc is nonzero because we skipped zeros in inputs
181 assert!(bool::from(!acc.is_zero()));
182
183 // Compute the inverse of all products
184 acc = acc.invert();
185
186 // Pass through the vector backwards to compute the inverses
187 // in place
188 for (input, scratch) in inputs.iter_mut().rev().zip(scratch.into_iter().rev()) {
189 let tmp = &acc * input;
190 // input <- acc * scratch, then acc <- tmp
191 // Again, we skip zeros in a constant-time way
192 let nz = !input.is_zero();
193 input.conditional_assign(&(&acc * &scratch), nz);
194 acc.conditional_assign(&tmp, nz);
195 }
196 }
197
198 /// Given a nonzero field element, compute its inverse.
199 ///
200 /// The inverse is computed as self^(p-2), since
201 /// x^(p-2)x = x^(p-1) = 1 (mod p).
202 ///
203 /// This function returns zero on input zero.
204 #[rustfmt::skip] // keep alignment of explanatory comments
205 #[allow(clippy::let_and_return)]
206 pub(crate) fn invert(&self) -> FieldElement {
207 // The bits of p-2 = 2^255 -19 -2 are 11010111111...11.
208 //
209 // nonzero bits of exponent
210 let (t19, t3) = self.pow22501(); // t19: 249..0 ; t3: 3,1,0
211 let t20 = t19.pow2k(5); // 254..5
212 let t21 = &t20 * &t3; // 254..5,3,1,0
213
214 t21
215 }
216
217 /// Raise this field element to the power (p-5)/8 = 2^252 -3.
218 #[rustfmt::skip] // keep alignment of explanatory comments
219 #[allow(clippy::let_and_return)]
220 fn pow_p58(&self) -> FieldElement {
221 // The bits of (p-5)/8 are 101111.....11.
222 //
223 // nonzero bits of exponent
224 let (t19, _) = self.pow22501(); // 249..0
225 let t20 = t19.pow2k(2); // 251..2
226 let t21 = self * &t20; // 251..2,0
227
228 t21
229 }
230
231 /// Given `FieldElements` `u` and `v`, compute either `sqrt(u/v)`
232 /// or `sqrt(i*u/v)` in constant time.
233 ///
234 /// This function always returns the nonnegative square root.
235 ///
236 /// # Return
237 ///
238 /// - `(Choice(1), +sqrt(u/v)) ` if `v` is nonzero and `u/v` is square;
239 /// - `(Choice(1), zero) ` if `u` is zero;
240 /// - `(Choice(0), zero) ` if `v` is zero and `u` is nonzero;
241 /// - `(Choice(0), +sqrt(i*u/v))` if `u/v` is nonsquare (so `i*u/v` is square).
242 ///
243 pub(crate) fn sqrt_ratio_i(u: &FieldElement, v: &FieldElement) -> (Choice, FieldElement) {
244 // Using the same trick as in ed25519 decoding, we merge the
245 // inversion, the square root, and the square test as follows.
246 //
247 // To compute sqrt(α), we can compute β = α^((p+3)/8).
248 // Then β^2 = ±α, so multiplying β by sqrt(-1) if necessary
249 // gives sqrt(α).
250 //
251 // To compute 1/sqrt(α), we observe that
252 // 1/β = α^(p-1 - (p+3)/8) = α^((7p-11)/8)
253 // = α^3 * (α^7)^((p-5)/8).
254 //
255 // We can therefore compute sqrt(u/v) = sqrt(u)/sqrt(v)
256 // by first computing
257 // r = u^((p+3)/8) v^(p-1-(p+3)/8)
258 // = u u^((p-5)/8) v^3 (v^7)^((p-5)/8)
259 // = (uv^3) (uv^7)^((p-5)/8).
260 //
261 // If v is nonzero and u/v is square, then r^2 = ±u/v,
262 // so vr^2 = ±u.
263 // If vr^2 = u, then sqrt(u/v) = r.
264 // If vr^2 = -u, then sqrt(u/v) = r*sqrt(-1).
265 //
266 // If v is zero, r is also zero.
267
268 let v3 = &v.square() * v;
269 let v7 = &v3.square() * v;
270 let mut r = &(u * &v3) * &(u * &v7).pow_p58();
271 let check = v * &r.square();
272
273 let i = &constants::SQRT_M1;
274
275 let correct_sign_sqrt = check.ct_eq(u);
276 let flipped_sign_sqrt = check.ct_eq(&(-u));
277 let flipped_sign_sqrt_i = check.ct_eq(&(&(-u) * i));
278
279 let r_prime = &constants::SQRT_M1 * &r;
280 r.conditional_assign(&r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i);
281
282 // Choose the nonnegative square root.
283 let r_is_negative = r.is_negative();
284 r.conditional_negate(r_is_negative);
285
286 let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt;
287
288 (was_nonzero_square, r)
289 }
290
291 /// Attempt to compute `sqrt(1/self)` in constant time.
292 ///
293 /// Convenience wrapper around `sqrt_ratio_i`.
294 ///
295 /// This function always returns the nonnegative square root.
296 ///
297 /// # Return
298 ///
299 /// - `(Choice(1), +sqrt(1/self)) ` if `self` is a nonzero square;
300 /// - `(Choice(0), zero) ` if `self` is zero;
301 /// - `(Choice(0), +sqrt(i/self)) ` if `self` is a nonzero nonsquare;
302 ///
303 pub(crate) fn invsqrt(&self) -> (Choice, FieldElement) {
304 FieldElement::sqrt_ratio_i(&FieldElement::ONE, self)
305 }
306}
307
308#[cfg(test)]
309mod test {
310 use crate::field::*;
311
312 /// Random element a of GF(2^255-19), from Sage
313 /// a = 1070314506888354081329385823235218444233221\
314 /// 2228051251926706380353716438957572
315 static A_BYTES: [u8; 32] = [
316 0x04, 0xfe, 0xdf, 0x98, 0xa7, 0xfa, 0x0a, 0x68, 0x84, 0x92, 0xbd, 0x59, 0x08, 0x07, 0xa7,
317 0x03, 0x9e, 0xd1, 0xf6, 0xf2, 0xe1, 0xd9, 0xe2, 0xa4, 0xa4, 0x51, 0x47, 0x36, 0xf3, 0xc3,
318 0xa9, 0x17,
319 ];
320
321 /// Byte representation of a**2
322 static ASQ_BYTES: [u8; 32] = [
323 0x75, 0x97, 0x24, 0x9e, 0xe6, 0x06, 0xfe, 0xab, 0x24, 0x04, 0x56, 0x68, 0x07, 0x91, 0x2d,
324 0x5d, 0x0b, 0x0f, 0x3f, 0x1c, 0xb2, 0x6e, 0xf2, 0xe2, 0x63, 0x9c, 0x12, 0xba, 0x73, 0x0b,
325 0xe3, 0x62,
326 ];
327
328 /// Byte representation of 1/a
329 static AINV_BYTES: [u8; 32] = [
330 0x96, 0x1b, 0xcd, 0x8d, 0x4d, 0x5e, 0xa2, 0x3a, 0xe9, 0x36, 0x37, 0x93, 0xdb, 0x7b, 0x4d,
331 0x70, 0xb8, 0x0d, 0xc0, 0x55, 0xd0, 0x4c, 0x1d, 0x7b, 0x90, 0x71, 0xd8, 0xe9, 0xb6, 0x18,
332 0xe6, 0x30,
333 ];
334
335 /// Byte representation of a^((p-5)/8)
336 static AP58_BYTES: [u8; 32] = [
337 0x6a, 0x4f, 0x24, 0x89, 0x1f, 0x57, 0x60, 0x36, 0xd0, 0xbe, 0x12, 0x3c, 0x8f, 0xf5, 0xb1,
338 0x59, 0xe0, 0xf0, 0xb8, 0x1b, 0x20, 0xd2, 0xb5, 0x1f, 0x15, 0x21, 0xf9, 0xe3, 0xe1, 0x61,
339 0x21, 0x55,
340 ];
341
342 #[test]
343 fn a_mul_a_vs_a_squared_constant() {
344 let a = FieldElement::from_bytes(&A_BYTES);
345 let asq = FieldElement::from_bytes(&ASQ_BYTES);
346 assert_eq!(asq, &a * &a);
347 }
348
349 #[test]
350 fn a_square_vs_a_squared_constant() {
351 let a = FieldElement::from_bytes(&A_BYTES);
352 let asq = FieldElement::from_bytes(&ASQ_BYTES);
353 assert_eq!(asq, a.square());
354 }
355
356 #[test]
357 fn a_square2_vs_a_squared_constant() {
358 let a = FieldElement::from_bytes(&A_BYTES);
359 let asq = FieldElement::from_bytes(&ASQ_BYTES);
360 assert_eq!(a.square2(), &asq + &asq);
361 }
362
363 #[test]
364 fn a_invert_vs_inverse_of_a_constant() {
365 let a = FieldElement::from_bytes(&A_BYTES);
366 let ainv = FieldElement::from_bytes(&AINV_BYTES);
367 let should_be_inverse = a.invert();
368 assert_eq!(ainv, should_be_inverse);
369 assert_eq!(FieldElement::ONE, &a * &should_be_inverse);
370 }
371
372 #[test]
373 #[cfg(feature = "alloc")]
374 fn batch_invert_a_matches_nonbatched() {
375 let a = FieldElement::from_bytes(&A_BYTES);
376 let ap58 = FieldElement::from_bytes(&AP58_BYTES);
377 let asq = FieldElement::from_bytes(&ASQ_BYTES);
378 let ainv = FieldElement::from_bytes(&AINV_BYTES);
379 let a0 = &a - &a;
380 let a2 = &a + &a;
381 let a_list = vec![a, ap58, asq, ainv, a0, a2];
382 let mut ainv_list = a_list.clone();
383 FieldElement::batch_invert(&mut ainv_list[..]);
384 for i in 0..6 {
385 assert_eq!(a_list[i].invert(), ainv_list[i]);
386 }
387 }
388
389 #[test]
390 fn sqrt_ratio_behavior() {
391 let zero = FieldElement::ZERO;
392 let one = FieldElement::ONE;
393 let i = constants::SQRT_M1;
394 let two = &one + &one; // 2 is nonsquare mod p.
395 let four = &two + &two; // 4 is square mod p.
396
397 // 0/0 should return (1, 0) since u is 0
398 let (choice, sqrt) = FieldElement::sqrt_ratio_i(&zero, &zero);
399 assert!(bool::from(choice));
400 assert_eq!(sqrt, zero);
401 assert!(bool::from(!sqrt.is_negative()));
402
403 // 1/0 should return (0, 0) since v is 0, u is nonzero
404 let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &zero);
405 assert!(bool::from(!choice));
406 assert_eq!(sqrt, zero);
407 assert!(bool::from(!sqrt.is_negative()));
408
409 // 2/1 is nonsquare, so we expect (0, sqrt(i*2))
410 let (choice, sqrt) = FieldElement::sqrt_ratio_i(&two, &one);
411 assert!(bool::from(!choice));
412 assert_eq!(sqrt.square(), &two * &i);
413 assert!(bool::from(!sqrt.is_negative()));
414
415 // 4/1 is square, so we expect (1, sqrt(4))
416 let (choice, sqrt) = FieldElement::sqrt_ratio_i(&four, &one);
417 assert!(bool::from(choice));
418 assert_eq!(sqrt.square(), four);
419 assert!(bool::from(!sqrt.is_negative()));
420
421 // 1/4 is square, so we expect (1, 1/sqrt(4))
422 let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &four);
423 assert!(bool::from(choice));
424 assert_eq!(&sqrt.square() * &four, one);
425 assert!(bool::from(!sqrt.is_negative()));
426 }
427
428 #[test]
429 fn a_p58_vs_ap58_constant() {
430 let a = FieldElement::from_bytes(&A_BYTES);
431 let ap58 = FieldElement::from_bytes(&AP58_BYTES);
432 assert_eq!(ap58, a.pow_p58());
433 }
434
435 #[test]
436 fn equality() {
437 let a = FieldElement::from_bytes(&A_BYTES);
438 let ainv = FieldElement::from_bytes(&AINV_BYTES);
439 assert!(a == a);
440 assert!(a != ainv);
441 }
442
443 /// Notice that the last element has the high bit set, which
444 /// should be ignored
445 static B_BYTES: [u8; 32] = [
446 113, 191, 169, 143, 91, 234, 121, 15, 241, 131, 217, 36, 230, 101, 92, 234, 8, 208, 170,
447 251, 97, 127, 70, 210, 58, 23, 166, 87, 240, 169, 184, 178,
448 ];
449
450 #[test]
451 fn from_bytes_highbit_is_ignored() {
452 let mut cleared_bytes = B_BYTES;
453 cleared_bytes[31] &= 127u8;
454 let with_highbit_set = FieldElement::from_bytes(&B_BYTES);
455 let without_highbit_set = FieldElement::from_bytes(&cleared_bytes);
456 assert_eq!(without_highbit_set, with_highbit_set);
457 }
458
459 #[test]
460 fn conditional_negate() {
461 let one = FieldElement::ONE;
462 let minus_one = FieldElement::MINUS_ONE;
463 let mut x = one;
464 x.conditional_negate(Choice::from(1));
465 assert_eq!(x, minus_one);
466 x.conditional_negate(Choice::from(0));
467 assert_eq!(x, minus_one);
468 x.conditional_negate(Choice::from(1));
469 assert_eq!(x, one);
470 }
471
472 #[test]
473 fn encoding_is_canonical() {
474 // Encode 1 wrongly as 1 + (2^255 - 19) = 2^255 - 18
475 let one_encoded_wrongly_bytes: [u8; 32] = [
476 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
477 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
478 0xff, 0xff, 0xff, 0x7f,
479 ];
480 // Decode to a field element
481 let one = FieldElement::from_bytes(&one_encoded_wrongly_bytes);
482 // .. then check that the encoding is correct
483 let one_bytes = one.as_bytes();
484 assert_eq!(one_bytes[0], 1);
485 for byte in &one_bytes[1..] {
486 assert_eq!(*byte, 0);
487 }
488 }
489
490 #[test]
491 #[cfg(feature = "alloc")]
492 fn batch_invert_empty() {
493 FieldElement::batch_invert(&mut []);
494 }
495}