diff --git a/.travis.yml b/.travis.yml index af16309..6a3e92b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,8 @@ matrix: env: TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES='' - rust: beta env: TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES='' + - rust: nightly + env: TEST_COMMAND=build EXTRA_FLAGS=--no-default-features FEATURES='alloc' script: - cargo $TEST_COMMAND --features="$FEATURES" $EXTRA_FLAGS diff --git a/Cargo.toml b/Cargo.toml index 500dffb..7a25c98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "curve25519-dalek" -version = "0.9.0" +version = "0.9.1" authors = ["Isis Lovecruft ", "Henry de Valence "] readme = "README.md" @@ -30,14 +30,17 @@ optional = true version = "0.3" [dependencies.digest] -version = "0.4" +version = "0.6" + +[dependencies.subtle] +version = "^0.1" [dependencies.generic-array] # same version that digest depends on -version = "^0.6" +version = "^0.8" [dev-dependencies.sha2] -version = "0.4" +version = "0.6" [dev-dependencies.serde_cbor] version = "0.6" @@ -46,6 +49,7 @@ version = "0.6" nightly = ["radix_51"] default = ["std"] std = ["rand"] +alloc = [] yolocrypto = [] bench = [] # Radix-51 arithmetic using u128 diff --git a/src/curve.rs b/src/curve.rs index cc1cfc8..deac819 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -77,8 +77,8 @@ // affine and projective cakes and eat both of them too. #![allow(non_snake_case)] -#[cfg(not(feature = "std"))] -use collections::Vec; +#[cfg(feature = "alloc")] +use alloc::Vec; use core::fmt::Debug; use core::iter::Iterator; @@ -91,7 +91,7 @@ use constants; use field::FieldElement; use scalar::Scalar; use subtle::arrays_equal; -use subtle::bytes_equal_ct; +use subtle::bytes_equal; use subtle::CTAssignable; use subtle::CTEq; use subtle::CTNegatable; @@ -193,7 +193,7 @@ impl CompressedMontgomeryU { // // XXX any other exceptional points for the birational map? pub fn decompress(&self) -> Option { - let u: FieldElement = FieldElement::from_bytes(&self.0); + let u: FieldElement = FieldElement::from_bytes(&self.0); // If u = -1, then v^2 = u*(u^2+486662*u+1) = 486660. // But 486660 is nonsquare mod p, so this is not a curve point. @@ -317,8 +317,9 @@ impl<'de> Deserialize<'de> for ExtendedPoint { where E: serde::de::Error { if v.len() == 32 { - let arr32 = array_ref!(v,0,32); // &[u8;32] from &[u8] - CompressedEdwardsY(*arr32).decompress() + let arr32 = array_ref!(v, 0, 32); // &[u8;32] from &[u8] + CompressedEdwardsY(*arr32) + .decompress() .ok_or(serde::de::Error::custom("decompression failed")) } else { Err(serde::de::Error::invalid_length(v.len(), &self)) @@ -518,8 +519,8 @@ impl CTAssignable for ExtendedPoint { impl CTEq for ExtendedPoint { fn ct_eq(&self, other: &ExtendedPoint) -> u8 { - arrays_equal( self.compress_edwards().as_bytes(), - other.compress_edwards().as_bytes()) + arrays_equal(self.compress_edwards().as_bytes(), + other.compress_edwards().as_bytes()) } } @@ -551,7 +552,7 @@ impl ProjectivePoint { /// Given (X:Y:Z) in Ɛ, passing to Ɛₑ can be performed in 3M+1S by /// computing (XZ,YZ,XY,Z²). (Note that in that paper, points are /// (X:Y:T:Z) so this really does match the code below). - #[allow(dead_code)] // rustc complains this is unused even when it's used + #[allow(dead_code)] // rustc complains this is unused even when it's used fn to_extended(&self) -> ExtendedPoint { ExtendedPoint{ X: &self.X * &self.Z, @@ -714,7 +715,7 @@ impl ExtendedPoint { // Addition and Subtraction // ------------------------------------------------------------------------ -impl<'a,'b> Add<&'b ProjectiveNielsPoint> for &'a ExtendedPoint { +impl<'a, 'b> Add<&'b ProjectiveNielsPoint> for &'a ExtendedPoint { type Output = CompletedPoint; fn add(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint { @@ -735,7 +736,7 @@ impl<'a,'b> Add<&'b ProjectiveNielsPoint> for &'a ExtendedPoint { } } -impl<'a,'b> Sub<&'b ProjectiveNielsPoint> for &'a ExtendedPoint { +impl<'a, 'b> Sub<&'b ProjectiveNielsPoint> for &'a ExtendedPoint { type Output = CompletedPoint; fn sub(self, other: &'b ProjectiveNielsPoint) -> CompletedPoint { @@ -756,7 +757,7 @@ impl<'a,'b> Sub<&'b ProjectiveNielsPoint> for &'a ExtendedPoint { } } -impl<'a,'b> Add<&'b AffineNielsPoint> for &'a ExtendedPoint { +impl<'a, 'b> Add<&'b AffineNielsPoint> for &'a ExtendedPoint { type Output = CompletedPoint; fn add(self, other: &'b AffineNielsPoint) -> CompletedPoint { @@ -776,7 +777,7 @@ impl<'a,'b> Add<&'b AffineNielsPoint> for &'a ExtendedPoint { } } -impl<'a,'b> Sub<&'b AffineNielsPoint> for &'a ExtendedPoint { +impl<'a, 'b> Sub<&'b AffineNielsPoint> for &'a ExtendedPoint { type Output = CompletedPoint; fn sub(self, other: &'b AffineNielsPoint) -> CompletedPoint { @@ -796,7 +797,7 @@ impl<'a,'b> Sub<&'b AffineNielsPoint> for &'a ExtendedPoint { } } -impl<'a,'b> Add<&'b ExtendedPoint> for &'a ExtendedPoint { +impl<'a, 'b> Add<&'b ExtendedPoint> for &'a ExtendedPoint { type Output = ExtendedPoint; fn add(self, other: &'b ExtendedPoint) -> ExtendedPoint { (self + &other.to_projective_niels()).to_extended() @@ -809,7 +810,7 @@ impl<'b> AddAssign<&'b ExtendedPoint> for ExtendedPoint { } } -impl<'a,'b> Sub<&'b ExtendedPoint> for &'a ExtendedPoint { +impl<'a, 'b> Sub<&'b ExtendedPoint> for &'a ExtendedPoint { type Output = ExtendedPoint; fn sub(self, other: &'b ExtendedPoint) -> ExtendedPoint { (self - &other.to_projective_niels()).to_extended() @@ -1006,7 +1007,7 @@ impl EdwardsBasepointTable { // XXX can we skip the initialization without too much unsafety? // stick 30K on the stack and call it a day. let mut table = EdwardsBasepointTable([[AffineNielsPoint::identity(); 8]; 32]); - let mut P = basepoint.clone(); + let mut P = *basepoint; for i in 0..32 { // P = (16^2)^i * B let mut jP = P.to_affine_niels(); @@ -1081,7 +1082,7 @@ fn select_precomputed_point(x: i8, points: &[T; 8]) -> T for j in 1..9 { // Copy `points[j-1] == j*P` onto `t` in constant time if `|x| == j`. t.conditional_assign(&points[j-1], - bytes_equal_ct(xabs as u8, j as u8)); + bytes_equal(xabs as u8, j as u8)); } // Now t == |x| * P. @@ -1181,22 +1182,22 @@ pub mod vartime { impl Index for OddMultiples { type Output = ProjectiveNielsPoint; - fn index<'a>(&'a self, _index: usize) -> &'a ProjectiveNielsPoint { + fn index(&self, _index: usize) -> &ProjectiveNielsPoint { &(self.0[_index]) } } /// Given a vector of public scalars and a vector of (possibly secret) - /// points, compute - /// - /// c_1 P_1 + ... + c_n P_n. + /// points, compute `c_1 P_1 + ... + c_n P_n`. /// /// # Input /// /// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an /// error to call this function with two vectors of different lengths. - pub fn k_fold_scalar_mult<'a,'b,I,J>(scalars: I, points: J) -> ExtendedPoint - where I: IntoIterator, J: IntoIterator + #[cfg(any(feature = "alloc", feature = "std"))] + pub fn k_fold_scalar_mult<'a, 'b, I, J>(scalars: I, points: J) -> ExtendedPoint + where I: IntoIterator, + J: IntoIterator { //assert_eq!(scalars.len(), points.len()); @@ -1654,7 +1655,7 @@ mod test { // CBOR apparently has two bytes of overhead for a 32-byte string. // Set the low byte of the compressed point to 1 to make it invalid. output[2] = 1; - let parsed: Result = serde_cbor::from_slice(&output); + let parsed: Result = serde_cbor::from_slice(&output); assert!(parsed.is_err()); } } @@ -1669,7 +1670,7 @@ mod bench { use test::Bencher; use constants; use super::*; - use super::test::{A_SCALAR}; + use super::test::A_SCALAR; #[bench] fn edwards_decompress(b: &mut Bencher) { @@ -1736,21 +1737,21 @@ mod bench { fn projective_double_output_completed(b: &mut Bencher) { let p1 = constants::ED25519_BASEPOINT.to_projective(); - b.iter(|| p1.double() ); + b.iter(|| p1.double()); } #[bench] fn extended_double_output_extended(b: &mut Bencher) { let p1 = constants::ED25519_BASEPOINT; - b.iter(|| p1.double() ); + b.iter(|| p1.double()); } #[bench] fn mult_by_cofactor(b: &mut Bencher) { let p1 = constants::ED25519_BASEPOINT; - b.iter(|| p1.mult_by_cofactor() ); + b.iter(|| p1.mult_by_cofactor()); } #[cfg(feature="basepoint_table_creation")] diff --git a/src/decaf.rs b/src/decaf.rs index 6e41868..2b489b0 100644 --- a/src/decaf.rs +++ b/src/decaf.rs @@ -60,7 +60,7 @@ pub struct CompressedDecaf(pub [u8; 32]); /// The result of compressing a `DecafPoint`. impl CompressedDecaf { /// View this `CompressedDecaf` as an array of bytes. - pub fn as_bytes<'a>(&'a self) -> &'a [u8;32] { + pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] { &self.0 } @@ -121,7 +121,7 @@ impl CompressedDecaf { impl Identity for CompressedDecaf { fn identity() -> CompressedDecaf { - CompressedDecaf([0u8;32]) + CompressedDecaf([0u8; 32]) } } @@ -165,8 +165,9 @@ impl<'de> Deserialize<'de> for DecafPoint { where E: serde::de::Error { if v.len() == 32 { - let arr32 = array_ref!(v,0,32); // &[u8;32] from &[u8] - CompressedDecaf(*arr32).decompress() + let arr32 = array_ref!(v, 0, 32); // &[u8;32] from &[u8] + CompressedDecaf(*arr32) + .decompress() .ok_or(serde::de::Error::custom("decompression failed")) } else { Err(serde::de::Error::invalid_length(v.len(), &self)) @@ -193,10 +194,10 @@ impl DecafPoint { pub fn compress(&self) -> CompressedDecaf { // Q: Do we want to encode twisted or untwisted? // - // Notes: + // Notes: // Recall that the twisted Edwards curve E_{a,d} is of the form // - // ax^2 + y^2 = 1 + dx^2y^2. + // ax^2 + y^2 = 1 + dx^2y^2. // // Internally, we operate on the curve with a = -1, d = // -121665/121666, a.k.a., the twist. But maybe we would like @@ -205,11 +206,11 @@ impl DecafPoint { // // Fix i, a square root of -1 (mod p). // - // The map x -> ix is an isomorphism from E_{a,d} to E_{-a,-d}. + // The map x -> ix is an isomorphism from E_{a,d} to E_{-a,-d}. // Its inverse is x -> -ix. // let untwisted_X = &self.X * &constants::MSQRT_M1; // etc. - + // // Step 0: pre-rotation, needed for Decaf with E[8] = Z/8. // // We want to select a point (x,y) in the coset P + E[4] with @@ -247,7 +248,7 @@ impl DecafPoint { // // 0 = (-X^2 + Y^2)*Z^2 - Z^4 - d*X^2*Y^2, // - // so + // so // 0 = (-X^2 + Y^2)*Z^2 - Z^4 - d*T^2*Z^2 since XY=TZ // = (-X^2 + Y^2 - Z^2 - d*T^2)*Z^2 // = ( X^2 - Y^2 + Z^2 + d*T^2)*Z^2 mult by -1 @@ -304,7 +305,7 @@ impl DecafPoint { let (tmp_is_nonzero_square, W) = tmp.invsqrt(); // tmp should always be a square (why? related to being in the // image of the isogeny?) - debug_assert_eq!( tmp_is_nonzero_square | tmp.is_zero(), 1u8 ); + debug_assert_eq!(tmp_is_nonzero_square | tmp.is_zero(), 1u8); let xy = &T.square() * &(&W.square() * &(&TZ * &ZZ_plus_XX)); let rotate = 1u8 & !(Y.is_nonzero() & xy.is_nonnegative_decaf()); @@ -363,7 +364,7 @@ impl DecafPoint { let r_0_squared = r_0.square(); let r = &r_0_squared + &r_0_squared; - // 2. Compute D <--- (dr + (a-d)) * (dr - (d + ar)) + // 2. Compute D <--- (dr + (a-d)) * (dr - (d + ar)) let dr = &constants::d * &r; // D = (dr + (a-d)) * (dr - (d + ar)) // = (dr + (a-d)) * (dr - (d-r)) since a=-1 @@ -398,7 +399,7 @@ impl DecafPoint { s *= &c; // 6. Compute t <--- -c*N*(r-1)* ((a-2d)*e)^2 -1 - let a_minus_2d_e_sq = (&(&minus_one-&constants::d2)*&e).square(); + let a_minus_2d_e_sq = (&(&minus_one - &constants::d2) * &e).square(); let c_N_r_minus_1 = &c * &(&N * &(&r + &minus_one)); let t = &minus_one - &(&c_N_r_minus_1 * &a_minus_2d_e_sq); @@ -467,7 +468,8 @@ impl DecafPoint { /// ``` /// pub fn hash_from_bytes(input: &[u8]) -> DecafPoint - where D: Digest + Default { + where D: Digest + Default + { let mut hash = D::default(); hash.input(input); DecafPoint::from_hash(hash) @@ -479,7 +481,8 @@ impl DecafPoint { /// to stream data into the `Digest` than to pass a single byte /// slice. pub fn from_hash(hash: D) -> DecafPoint - where D: Digest + Default { + where D: Digest + Default + { // XXX this seems clumsy let mut output = [0u8; 32]; output.copy_from_slice(hash.result().as_slice()); @@ -617,10 +620,15 @@ impl CTAssignable for DecafPoint { /// # Example /// /// ``` + /// # extern crate subtle; + /// # extern crate curve25519_dalek; + /// # + /// # use subtle::CTAssignable; + /// # /// # use curve25519_dalek::curve::Identity; /// # use curve25519_dalek::decaf::DecafPoint; - /// # use curve25519_dalek::subtle::CTAssignable; /// # use curve25519_dalek::constants; + /// # fn main() { /// let A = DecafPoint::identity(); /// let B = constants::DECAF_ED25519_BASEPOINT; /// @@ -630,6 +638,7 @@ impl CTAssignable for DecafPoint { /// assert!(P == A); /// P.conditional_assign(&B, 1u8); /// assert!(P == B); + /// # } /// ``` fn conditional_assign(&mut self, other: &DecafPoint, choice: u8) { self.0.X.conditional_assign(&other.0.X, choice); @@ -674,8 +683,9 @@ pub mod vartime { /// /// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an /// error to call this function with two vectors of different lengths. - pub fn k_fold_scalar_mult<'a,'b,I,J>(scalars: I, points: J) -> DecafPoint - where I: IntoIterator, J: IntoIterator + pub fn k_fold_scalar_mult<'a, 'b, I, J>(scalars: I, points: J) -> DecafPoint + where I: IntoIterator, + J: IntoIterator { let extended_points = points.into_iter().map(|P| &P.0); DecafPoint(curve::vartime::k_fold_scalar_mult(scalars, extended_points)) @@ -836,4 +846,3 @@ mod bench { b.iter(|| P.compress()); } } - diff --git a/src/field.rs b/src/field.rs index ef36f28..bcf8d17 100644 --- a/src/field.rs +++ b/src/field.rs @@ -116,7 +116,7 @@ impl Index for FieldElement { impl IndexMut for FieldElement { fn index_mut(&mut self, _index: usize) -> &mut Limb { - &mut(self.0[_index]) + &mut (self.0[_index]) } } @@ -340,25 +340,33 @@ impl CTAssignable for FieldElement { /// If `choice == 0`, replace `self` with `self`: /// /// ``` + /// # extern crate subtle; + /// # extern crate curve25519_dalek; /// # use curve25519_dalek::field::FieldElement; - /// # use curve25519_dalek::subtle::CTAssignable; + /// # use subtle::CTAssignable; + /// # fn main() { /// let f = FieldElement([1,1,1,1,1,1,1,1,1,1]); /// let g = FieldElement([2,2,2,2,2,2,2,2,2,2]); /// let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]); /// h.conditional_assign(&g, 0); /// assert!(h == f); + /// # } /// ``` /// /// If `choice == 1`, replace `self` with `f`: /// /// ``` + /// # extern crate subtle; + /// # extern crate curve25519_dalek; /// # use curve25519_dalek::field::FieldElement; - /// # use curve25519_dalek::subtle::CTAssignable; + /// # use subtle::CTAssignable; + /// # fn main() { /// # let f = FieldElement([1,1,1,1,1,1,1,1,1,1]); /// # let g = FieldElement([2,2,2,2,2,2,2,2,2,2]); /// # let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]); /// h.conditional_assign(&g, 1); /// assert!(h == g); + /// # } /// ``` /// /// # Preconditions @@ -456,7 +464,7 @@ impl FieldElement { #[cfg(not(feature="radix_51"))] fn reduce(mut h: [i64; 10]) -> FieldElement { //FeCombine - let mut c = [0i64;10]; + let mut c = [0i64; 10]; /* |h[0]| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38)) @@ -709,7 +717,7 @@ impl FieldElement { // evidently 2^255 h10-2^255 q = 0. // Goal: Output h[0]+...+2^230 h[9]. - let mut s = [0u8;32]; + let mut s = [0u8; 32]; s[0] = (h[0] >> 0) as u8; s[1] = (h[0] >> 8) as u8; s[2] = (h[0] >> 16) as u8; @@ -826,7 +834,7 @@ impl FieldElement { debug_assert!((s[31] & 0b1000_0000u8) == 0u8); s[31] &= 127u8; - return s + s } /// Determine if this `FieldElement` is negative, in the sense @@ -1179,7 +1187,7 @@ impl FieldElement { let r_prime = &constants::SQRT_M1 * &r; r.conditional_assign(&r_prime, flipped_sign_sqrt); - + let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; (was_nonzero_square, r) @@ -1263,7 +1271,7 @@ mod test { fn a_mul_a_vs_a_squared_constant() { let a = FieldElement::from_bytes(&A_BYTES); let asq = FieldElement::from_bytes(&ASQ_BYTES); - assert_eq!(asq, &a*&a); + assert_eq!(asq, &a * &a); } #[test] @@ -1381,7 +1389,7 @@ mod bench { #[bench] fn fieldelement_a_mul_a(b: &mut Bencher) { let a = FieldElement::from_bytes(&A_BYTES); - b.iter(|| &a*&a); + b.iter(|| &a * &a); } #[bench] diff --git a/src/lib.rs b/src/lib.rs index 408d7ff..fd96048 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,9 +10,10 @@ // - Henry de Valence #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(collections))] +#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "nightly", feature(i128_type))] #![cfg_attr(feature = "bench", feature(test))] +#![cfg_attr(all(feature = "nightly", feature = "std"), feature(zero_one))] #![allow(unused_features)] #![deny(missing_docs)] // refuse to compile if documentation is missing @@ -46,6 +47,7 @@ extern crate arrayref; extern crate generic_array; extern crate digest; +extern crate subtle; #[cfg(feature = "serde")] extern crate serde; @@ -58,8 +60,8 @@ extern crate core; #[cfg(feature = "std")] extern crate rand; -#[cfg(not(feature = "std"))] -extern crate collections; +#[cfg(feature = "alloc")] +extern crate alloc; // Modules for low-level operations directly on field elements and curve points. @@ -71,9 +73,8 @@ pub mod curve; #[cfg(feature = "yolocrypto")] pub mod decaf; -// Constant-time functions and other miscelaneous utilities. +// Other miscelaneous utilities. -pub mod subtle; pub mod utils; // Low-level curve and point constants, as well as pre-computed curve group elements. diff --git a/src/scalar.rs b/src/scalar.rs index 3f4a6cc..e8beab7 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -63,7 +63,7 @@ impl Debug for Scalar { } } -impl Eq for Scalar{} +impl Eq for Scalar {} impl PartialEq for Scalar { /// Test equality between two `Scalar`s. /// @@ -101,7 +101,7 @@ impl Index for Scalar { impl IndexMut for Scalar { fn index_mut(&mut self, _index: usize) -> &mut u8 { - &mut(self.0[_index]) + &mut (self.0[_index]) } } @@ -151,15 +151,18 @@ impl<'a> Neg for &'a Scalar { type Output = Scalar; fn neg(self) -> Scalar { self * &constants::l_minus_1 - } + } } impl CTAssignable for Scalar { /// Conditionally assign another Scalar to this one. /// /// ``` + /// # extern crate curve25519_dalek; + /// # extern crate subtle; /// # use curve25519_dalek::scalar::Scalar; - /// # use curve25519_dalek::subtle::CTAssignable; + /// # use subtle::CTAssignable; + /// # fn main() { /// let a = Scalar([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); /// let b = Scalar([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -169,6 +172,7 @@ impl CTAssignable for Scalar { /// assert!(t[0] == a[0]); /// t.conditional_assign(&b, 1u8); /// assert!(t[0] == b[0]); + /// # } /// ``` /// /// # Preconditions @@ -218,7 +222,7 @@ impl<'de> Deserialize<'de> for Scalar { { if v.len() == 32 { // array_ref turns &[u8] into &[u8;32] - Ok(Scalar(*array_ref!(v,0,32))) + Ok(Scalar(*array_ref!(v, 0, 32))) } else { Err(serde::de::Error::invalid_length(v.len(), &self)) } @@ -270,7 +274,8 @@ impl Scalar { /// ``` /// pub fn hash_from_bytes(input: &[u8]) -> Scalar - where D: Digest + Default { + where D: Digest + Default + { let mut hash = D::default(); hash.input(input); Scalar::from_hash(hash) @@ -282,9 +287,10 @@ impl Scalar { /// to stream data into the `Digest` than to pass a single byte /// slice. pub fn from_hash(hash: D) -> Scalar - where D: Digest + Default { + where D: Digest + Default + { // XXX this seems clumsy - let mut output = [0u8;64]; + let mut output = [0u8; 64]; output.copy_from_slice(hash.result().as_slice()); Scalar::reduce(&output) } @@ -320,7 +326,7 @@ impl Scalar { } /// Get the bits of the scalar. - pub fn bits(&self) -> [i8;256] { + pub fn bits(&self) -> [i8; 256] { let mut bits = [0i8; 256]; for i in 0..256 { // As i runs from 0..256, the bottom 3 bits index the bit, @@ -379,7 +385,7 @@ impl Scalar { // Unpack a scalar into 12 21-bit limbs. fn unpack(&self) -> UnpackedScalar { - let mask_21bits: i64 = (1 << 21) -1; + let mask_21bits: i64 = (1 << 21) - 1; let mut a = UnpackedScalar([0i64; 12]); a[ 0] = mask_21bits & load3(&self.0[ 0..]) ; a[ 1] = mask_21bits & (load4(&self.0[ 2..]) >> 5); @@ -504,7 +510,7 @@ impl Index for UnpackedScalar { impl IndexMut for UnpackedScalar { fn index_mut(&mut self, _index: usize) -> &mut i64 { - &mut(self.0[_index]) + &mut (self.0[_index]) } } @@ -616,7 +622,7 @@ impl UnpackedScalar { /// 2^252 = -27742317777372353535851937790883648493 (mod l). /// /// We can write the right-hand side in 21-bit limbs as - /// + /// /// rhs = 666643 * 2^0 /// + 470296 * 2^21 /// + 654183 * 2^42 @@ -640,7 +646,7 @@ impl UnpackedScalar { fn reduce_limbs(mut limbs: &mut [i64; 24]) -> UnpackedScalar { #[inline] #[allow(dead_code)] - fn do_reduction(limbs: &mut [i64; 24], i:usize) { + fn do_reduction(limbs: &mut [i64; 24], i: usize) { limbs[i - 12] += limbs[i] * 666643; limbs[i - 11] += limbs[i] * 470296; limbs[i - 10] += limbs[i] * 654183; @@ -662,7 +668,7 @@ impl UnpackedScalar { #[allow(dead_code)] /// Carry excess from the `i`-th limb into the `(i+1)`-th limb. /// Postcondition: `-2^20 <= limbs[i] < 2^20`. - fn do_carry_centered(limbs: &mut [i64; 24], i:usize) { + fn do_carry_centered(limbs: &mut [i64; 24], i: usize) { let carry: i64 = (limbs[i] + (1<<20)) >> 21; limbs[i+1] += carry; limbs[i ] -= carry << 21; @@ -717,7 +723,6 @@ impl UnpackedScalar { UnpackedScalar(*array_ref!(limbs, 0, 12)) } - } #[cfg(test)] @@ -901,7 +906,7 @@ mod bench { #[bench] fn scalar_multiply_add(b: &mut Bencher) { - b.iter(|| Scalar::multiply_add(&X, &Y, &Z) ); + b.iter(|| Scalar::multiply_add(&X, &Y, &Z)); } #[bench] @@ -915,6 +920,6 @@ mod bench { let x = X.unpack(); let y = Y.unpack(); let z = Z.unpack(); - b.iter(|| UnpackedScalar::multiply_add(&x, &y, &z) ); + b.iter(|| UnpackedScalar::multiply_add(&x, &y, &z)); } } diff --git a/src/subtle.rs b/src/subtle.rs deleted file mode 100644 index 1dd6ba4..0000000 --- a/src/subtle.rs +++ /dev/null @@ -1,167 +0,0 @@ -// -*- mode: rust; -*- -// -// To the extent possible under law, the authors have waived all copyright and -// related or neighboring rights to curve25519-dalek, using the Creative -// Commons "CC0" public domain dedication. See -// for full details. -// -// Authors: -// - Isis Agora Lovecruft -// - Henry de Valence - -//! Constant-time traits and utility functions. - -use core::ops::Neg; - -/// Trait for items which can be conditionally assigned in constant time. -pub trait CTAssignable { - /// If `choice == 1u8`, assign `other` to `self`. - /// Otherwise, leave `self` unchanged. - /// Executes in constant time. - fn conditional_assign(&mut self, other: &Self, choice: u8); -} - -/// Trait for items whose equality to another item may be tested in constant time. -pub trait CTEq { - /// Determine if two items are equal in constant time. - /// - /// # Returns - /// - /// `1u8` if the two items are equal, and `0u8` otherwise. - fn ct_eq(&self, other: &Self) -> u8; -} - -/// Trait for items which can be conditionally negated in constant time. -/// -/// Note: it is not necessary to implement this trait, as a generic -/// implementation is provided. -pub trait CTNegatable -{ - /// Conditionally negate an element if `choice == 1u8`. - fn conditional_negate(&mut self, choice: u8); -} - -impl CTNegatable for T - where T: CTAssignable, for<'a> &'a T: Neg -{ - fn conditional_negate(&mut self, choice: u8) { - // Need to cast to eliminate mutability - let self_neg: T = -(self as &T); - self.conditional_assign(&self_neg, choice); - } -} - -/// Check equality of two bytes in constant time. -/// -/// # Return -/// -/// Returns `1u8` if `a == b` and `0u8` otherwise. -#[inline(always)] -pub fn bytes_equal_ct(a: u8, b: u8) -> u8 { - let mut x: u8; - - x = !(a ^ b); - x &= x >> 4; - x &= x >> 2; - x &= x >> 1; - x -} - -/// Test if a byte is non-zero in constant time. -/// -/// ``` -/// # extern crate curve25519_dalek; -/// # use curve25519_dalek::subtle::byte_is_nonzero; -/// # fn main() { -/// let mut x: u8; -/// x = 0; -/// assert!(byte_is_nonzero(x) == 0); -/// x = 3; -/// assert!(byte_is_nonzero(x) == 1); -/// # } -/// ``` -/// -/// # Return -/// -/// * If b != 0, returns 1u8. -/// * If b == 0, returns 0u8. -#[inline(always)] -pub fn byte_is_nonzero(b: u8) -> u8 { - let mut x = b; - x |= x >> 4; - x |= x >> 2; - x |= x >> 1; - (x & 1) -} - -/// Check equality of two arrays, `a` and `b`, in constant time. -/// -/// There is a `debug_assert!` that the two arrays are of equal length. For -/// example, the following code will panic: -/// -/// ```rust,ignore -/// let a: [u8; 3] = [0, 0, 0]; -/// let b: [u8; 4] = [0, 0, 0, 0]; -/// -/// assert!(arrays_equal(&a, &b) == 1); -/// ``` -/// -/// However, if the arrays are equal length, but their contents do *not* match, -/// `0u8` will be returned: -/// -/// ``` -/// # extern crate curve25519_dalek; -/// # use curve25519_dalek::subtle::arrays_equal; -/// # fn main() { -/// let a: [u8; 3] = [0, 1, 2]; -/// let b: [u8; 3] = [1, 2, 3]; -/// -/// assert!(arrays_equal(&a, &b) == 0); -/// # } -/// ``` -/// -/// And finally, if the contents *do* match, `1u8` is returned: -/// -/// ``` -/// # extern crate curve25519_dalek; -/// # use curve25519_dalek::subtle::arrays_equal; -/// # fn main() { -/// let a: [u8; 3] = [0, 1, 2]; -/// let b: [u8; 3] = [0, 1, 2]; -/// -/// assert!(arrays_equal(&a, &b) == 1); -/// # } -/// ``` -/// -/// This function is commonly used in various cryptographic applications, such -/// as [signature verification](https://github.com/isislovecruft/ed25519-dalek/blob/0.3.2/src/ed25519.rs#L280), -/// among many other applications. -/// -/// # Return -/// -/// Returns `1u8` if `a == b` and `0u8` otherwise. -#[inline(always)] -pub fn arrays_equal(a: &[u8], b: &[u8]) -> u8 { - debug_assert!(a.len() == b.len()); - - let mut x: u8 = 0; - - for i in 0 .. a.len() { - x |= a[i] ^ b[i]; - } - bytes_equal_ct(x, 0) -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - #[should_panic] - fn arrays_equal_different_lengths() { - let a: [u8; 3] = [0, 0, 0]; - let b: [u8; 4] = [0, 0, 0, 0]; - - assert!(arrays_equal(&a, &b) == 1); - } -}