// Copyright (c) Facebook, Inc. and its affiliates. // // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. #![allow(clippy::let_and_return)] //! Field arithmetic modulo \\(p = 2\^{255} - 19\\), using \\(64\\)-bit //! limbs with \\(128\\)-bit products. use core::fmt::Debug; use core::ops::Neg; use core::ops::{Add, AddAssign}; use core::ops::{Mul, MulAssign}; use subtle::Choice; use subtle::ConditionallyNegatable; use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; use zeroize::Zeroize; use fiat_crypto::curve25519_64::*; /// A `FieldElement51` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). /// /// In the 64-bit implementation, a `FieldElement` is represented in /// radix \\(2\^{51}\\) as five `u64`s; the coefficients are allowed to /// grow up to \\(2\^{54}\\) between reductions modulo \\(p\\). /// /// # Note /// /// The `curve25519_dalek::field` module provides a type alias /// `curve25519_dalek::field::FieldElement` to either `FieldElement51` /// or `FieldElement2625`. /// /// The backend-specific type `FieldElement51` should not be used /// outside of the `curve25519_dalek::field` module. #[derive(Copy, Clone)] pub struct FieldElement51(pub(crate) [u64; 5]); impl Debug for FieldElement51 { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "FieldElement51({:?})", &self.0[..]) } } impl Zeroize for FieldElement51 { fn zeroize(&mut self) { self.0.zeroize(); } } impl ConstantTimeEq for FieldElement51 { /// Test equality between two `FieldElement`s. Since the /// internal representation is not canonical, the field elements /// are normalized to wire format before comparison. fn ct_eq(&self, other: &FieldElement51) -> Choice { self.to_bytes().ct_eq(&other.to_bytes()) } } impl<'b> AddAssign<&'b FieldElement51> for FieldElement51 { fn add_assign(&mut self, _rhs: &'b FieldElement51) { let input = self.0; fiat_25519_add(&mut self.0, &input, &_rhs.0); let input = self.0; fiat_25519_carry(&mut self.0, &input); } } impl<'a, 'b> Add<&'b FieldElement51> for &'a FieldElement51 { type Output = FieldElement51; fn add(self, _rhs: &'b FieldElement51) -> FieldElement51 { let mut output = *self; fiat_25519_add(&mut output.0, &self.0, &_rhs.0); let input = output.0; fiat_25519_carry(&mut output.0, &input); output } } impl<'b> MulAssign<&'b FieldElement51> for FieldElement51 { fn mul_assign(&mut self, _rhs: &'b FieldElement51) { let input = self.0; fiat_25519_carry_mul(&mut self.0, &input, &_rhs.0); } } impl<'a, 'b> Mul<&'b FieldElement51> for &'a FieldElement51 { type Output = FieldElement51; fn mul(self, _rhs: &'b FieldElement51) -> FieldElement51 { let mut output = *self; fiat_25519_carry_mul(&mut output.0, &self.0, &_rhs.0); output } } impl<'a> Neg for &'a FieldElement51 { type Output = FieldElement51; fn neg(self) -> FieldElement51 { let mut output = *self; fiat_25519_opp(&mut output.0, &self.0); let input = output.0; fiat_25519_carry(&mut output.0, &input); output } } impl ConditionallySelectable for FieldElement51 { fn conditional_select( a: &FieldElement51, b: &FieldElement51, choice: Choice, ) -> FieldElement51 { let mut output = [0u64; 5]; fiat_25519_selectznz(&mut output, choice.unwrap_u8() as fiat_25519_u1, &a.0, &b.0); FieldElement51(output) } fn conditional_swap(a: &mut FieldElement51, b: &mut FieldElement51, choice: Choice) { u64::conditional_swap(&mut a.0[0], &mut b.0[0], choice); u64::conditional_swap(&mut a.0[1], &mut b.0[1], choice); u64::conditional_swap(&mut a.0[2], &mut b.0[2], choice); u64::conditional_swap(&mut a.0[3], &mut b.0[3], choice); u64::conditional_swap(&mut a.0[4], &mut b.0[4], choice); } fn conditional_assign(&mut self, _rhs: &FieldElement51, choice: Choice) { let mut output = [0u64; 5]; let choicebit = choice.unwrap_u8() as fiat_25519_u1; fiat_25519_cmovznz_u64(&mut output[0], choicebit, self.0[0], _rhs.0[0]); fiat_25519_cmovznz_u64(&mut output[1], choicebit, self.0[1], _rhs.0[1]); fiat_25519_cmovznz_u64(&mut output[2], choicebit, self.0[2], _rhs.0[2]); fiat_25519_cmovznz_u64(&mut output[3], choicebit, self.0[3], _rhs.0[3]); fiat_25519_cmovznz_u64(&mut output[4], choicebit, self.0[4], _rhs.0[4]); *self = FieldElement51(output); } } impl FieldElement51 { /// Construct zero. pub fn zero() -> FieldElement51 { FieldElement51([0, 0, 0, 0, 0]) } /// Construct one. pub fn one() -> FieldElement51 { FieldElement51([1, 0, 0, 0, 0]) } pub fn is_negative(&self) -> Choice { let bytes = self.to_bytes(); (bytes[0] & 1).into() } /// Raise this field element to the power (p-5)/8 = 2^252 -3. fn pow_p58(&self) -> FieldElement51 { // The bits of (p-5)/8 are 101111.....11. // // nonzero bits of exponent let (t19, _) = self.pow22501(); // 249..0 let t20 = t19.pow2k(2); // 251..2 let t21 = self * &t20; // 251..2,0 t21 } /// Given a nonzero field element, compute its inverse. /// /// The inverse is computed as self^(p-2), since /// x^(p-2)x = x^(p-1) = 1 (mod p). /// /// This function returns zero on input zero. pub fn invert(&self) -> FieldElement51 { // The bits of p-2 = 2^255 -19 -2 are 11010111111...11. // // nonzero bits of exponent let (t19, t3) = self.pow22501(); // t19: 249..0 ; t3: 3,1,0 let t20 = t19.pow2k(5); // 254..5 let t21 = &t20 * &t3; // 254..5,3,1,0 t21 } /// Compute (self^(2^250-1), self^11), used as a helper function /// within invert() and pow22523(). fn pow22501(&self) -> (FieldElement51, FieldElement51) { // Instead of managing which temporary variables are used // for what, we define as many as we need and leave stack // allocation to the compiler // // Each temporary variable t_i is of the form (self)^e_i. // Squaring t_i corresponds to multiplying e_i by 2, // so the pow2k function shifts e_i left by k places. // Multiplying t_i and t_j corresponds to adding e_i + e_j. // // Temporary t_i Nonzero bits of e_i // let t0 = self.square(); // 1 e_0 = 2^1 let t1 = t0.square().square(); // 3 e_1 = 2^3 let t2 = self * &t1; // 3,0 e_2 = 2^3 + 2^0 let t3 = &t0 * &t2; // 3,1,0 let t4 = t3.square(); // 4,2,1 let t5 = &t2 * &t4; // 4,3,2,1,0 let t6 = t5.pow2k(5); // 9,8,7,6,5 let t7 = &t6 * &t5; // 9,8,7,6,5,4,3,2,1,0 let t8 = t7.pow2k(10); // 19..10 let t9 = &t8 * &t7; // 19..0 let t10 = t9.pow2k(20); // 39..20 let t11 = &t10 * &t9; // 39..0 let t12 = t11.pow2k(10); // 49..10 let t13 = &t12 * &t7; // 49..0 let t14 = t13.pow2k(50); // 99..50 let t15 = &t14 * &t13; // 99..0 let t16 = t15.pow2k(100); // 199..100 let t17 = &t16 * &t15; // 199..0 let t18 = t17.pow2k(50); // 249..50 let t19 = &t18 * &t13; // 249..0 (t19, t3) } /// Load a `FieldElement51` from the low 255 bits of a 256-bit /// input. /// /// # Warning /// /// This function does not check that the input used the canonical /// representative. It masks the high bit, but it will happily /// decode 2^255 - 18 to 1. Applications that require a canonical /// encoding of every field element should decode, re-encode to /// the canonical encoding, and check that the input was /// canonical. /// pub fn from_bytes(bytes: &[u8; 32]) -> FieldElement51 { let mut temp = [0u8; 32]; temp.copy_from_slice(bytes); temp[31] &= 127u8; let mut output = [0u64; 5]; fiat_25519_from_bytes(&mut output, &temp); FieldElement51(output) } /// Serialize this `FieldElement51` to a 32-byte array. The /// encoding is canonical. pub fn to_bytes(&self) -> [u8; 32] { let mut bytes = [0u8; 32]; fiat_25519_to_bytes(&mut bytes, &self.0); bytes } /// Given `k > 0`, return `self^(2^k)`. pub fn pow2k(&self, mut k: u32) -> FieldElement51 { let mut output = *self; loop { let input = output.0; fiat_25519_carry_square(&mut output.0, &input); k -= 1; if k == 0 { return output; } } } /// Given `FieldElements` `u` and `v`, compute either `sqrt(u/v)` /// or `sqrt(i*u/v)` in constant time. /// /// This function always returns the nonnegative square root. /// /// # Return /// /// - `(Choice(1), +sqrt(u/v)) ` if `v` is nonzero and `u/v` is square; /// - `(Choice(1), zero) ` if `u` is zero; /// - `(Choice(0), zero) ` if `v` is zero and `u` is nonzero; /// - `(Choice(0), +sqrt(i*u/v))` if `u/v` is nonsquare (so `i*u/v` is square). /// pub fn sqrt_ratio_i(u: &FieldElement51, v: &FieldElement51) -> (Choice, FieldElement51) { // Using the same trick as in ed25519 decoding, we merge the // inversion, the square root, and the square test as follows. // // To compute sqrt(α), we can compute β = α^((p+3)/8). // Then β^2 = ±α, so multiplying β by sqrt(-1) if necessary // gives sqrt(α). // // To compute 1/sqrt(α), we observe that // 1/β = α^(p-1 - (p+3)/8) = α^((7p-11)/8) // = α^3 * (α^7)^((p-5)/8). // // We can therefore compute sqrt(u/v) = sqrt(u)/sqrt(v) // by first computing // r = u^((p+3)/8) v^(p-1-(p+3)/8) // = u u^((p-5)/8) v^3 (v^7)^((p-5)/8) // = (uv^3) (uv^7)^((p-5)/8). // // If v is nonzero and u/v is square, then r^2 = ±u/v, // so vr^2 = ±u. // If vr^2 = u, then sqrt(u/v) = r. // If vr^2 = -u, then sqrt(u/v) = r*sqrt(-1). // // If v is zero, r is also zero. let v3 = &v.square() * v; let v7 = &v3.square() * v; let mut r = &(u * &v3) * &(u * &v7).pow_p58(); let check = v * &r.square(); let i = &SQRT_M1; let correct_sign_sqrt = check.ct_eq(u); let flipped_sign_sqrt = check.ct_eq(&(-u)); let flipped_sign_sqrt_i = check.ct_eq(&(&(-u) * i)); let r_prime = &SQRT_M1 * &r; r.conditional_assign(&r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i); // Choose the nonnegative square root. let r_is_negative = r.is_negative(); r.conditional_negate(r_is_negative); let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; (was_nonzero_square, r) } /// Returns the square of this field element. pub fn square(&self) -> FieldElement51 { let mut output = *self; fiat_25519_carry_square(&mut output.0, &self.0); output } /// Returns 2 times the square of this field element. pub fn square2(&self) -> FieldElement51 { let mut output = *self; let mut temp = *self; // Void vs return type, measure cost of copying self fiat_25519_carry_square(&mut temp.0, &self.0); fiat_25519_add(&mut output.0, &temp.0, &temp.0); let input = output.0; fiat_25519_carry(&mut output.0, &input); output } } /// Precomputed value of one of the square roots of -1 (mod p) pub(crate) const SQRT_M1: FieldElement51 = FieldElement51([ 1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, 765476049583133, ]);