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}