diff --git a/Cargo.toml b/Cargo.toml index 558a062..4ca1999 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ rand = { version = "0.5", default-features = false } byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] } digest = { version = "0.8", default-features = false } clear_on_drop = "=0.2.3" -subtle = { version = "1", default-features = false } +subtle = { version = "2", default-features = false } serde = { version = "1.0", optional = true } packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true } @@ -54,7 +54,7 @@ rand = { version = "0.5", default-features = false } byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] } digest = { version = "0.8", default-features = false } clear_on_drop = "=0.2.3" -subtle = { version = "1", default-features = false } +subtle = { version = "2", default-features = false } serde = { version = "1.0", optional = true } packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true } @@ -78,3 +78,6 @@ avx2_backend = ["nightly", "u64_backend", "packed_simd"] # into the build script. Then, the build.rs emits the stage2_build # feature before the main-stage compilation. stage2_build = [] + +[patch.crates-io] +subtle = { git = "https://github.com/dalek-cryptography/subtle", branch = "fix-subtle-traits" } diff --git a/src/backend/avx2/edwards.rs b/src/backend/avx2/edwards.rs index cf9e881..18ecfde 100644 --- a/src/backend/avx2/edwards.rs +++ b/src/backend/avx2/edwards.rs @@ -80,6 +80,10 @@ impl ConditionallySelectable for ExtendedPoint { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { ExtendedPoint(FieldElement32x4::conditional_select(&a.0, &b.0, choice)) } + + fn conditional_assign(&mut self, other: &Self, choice: Choice) { + self.0.conditional_assign(&other.0, choice); + } } impl Default for ExtendedPoint { @@ -213,6 +217,10 @@ impl ConditionallySelectable for CachedPoint { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { CachedPoint(FieldElement32x4::conditional_select(&a.0, &b.0, choice)) } + + fn conditional_assign(&mut self, other: &Self, choice: Choice) { + self.0.conditional_assign(&other.0, choice); + } } impl<'a> Neg for &'a CachedPoint { diff --git a/src/backend/avx2/field.rs b/src/backend/avx2/field.rs index a37ed50..27ba558 100644 --- a/src/backend/avx2/field.rs +++ b/src/backend/avx2/field.rs @@ -155,13 +155,27 @@ impl ConditionallySelectable for FieldElement32x4 { let mask = (-(choice.unwrap_u8() as i32)) as u32; let mask_vec = u32x8::splat(mask); FieldElement32x4([ - self.0[0] ^ (mask_vec & (self.0[0] ^ other.0[0])), - self.0[1] ^ (mask_vec & (self.0[1] ^ other.0[1])), - self.0[2] ^ (mask_vec & (self.0[2] ^ other.0[2])), - self.0[3] ^ (mask_vec & (self.0[3] ^ other.0[3])), - self.0[4] ^ (mask_vec & (self.0[4] ^ other.0[4])), + a.0[0] ^ (mask_vec & (a.0[0] ^ b.0[0])), + a.0[1] ^ (mask_vec & (a.0[1] ^ b.0[1])), + a.0[2] ^ (mask_vec & (a.0[2] ^ b.0[2])), + a.0[3] ^ (mask_vec & (a.0[3] ^ b.0[3])), + a.0[4] ^ (mask_vec & (a.0[4] ^ b.0[4])), ]) } + + fn conditional_assign( + &mut self, + other: &FieldElement32x4, + choice: Choice, + ) { + let mask = (-(choice.unwrap_u8() as i32)) as u32; + let mask_vec = u32x8::splat(mask); + self.0[0] ^= mask_vec & (self.0[0] ^ other.0[0]); + self.0[1] ^= mask_vec & (self.0[1] ^ other.0[1]); + self.0[2] ^= mask_vec & (self.0[2] ^ other.0[2]); + self.0[3] ^= mask_vec & (self.0[3] ^ other.0[3]); + self.0[4] ^= mask_vec & (self.0[4] ^ other.0[4]); + } } impl FieldElement32x4 { diff --git a/src/backend/u32/field.rs b/src/backend/u32/field.rs index 2a9f5bb..5f2fe1d 100644 --- a/src/backend/u32/field.rs +++ b/src/backend/u32/field.rs @@ -16,13 +16,13 @@ //! of signed limbs. use core::fmt::Debug; -use core::ops::{Add, AddAssign}; -use core::ops::{Sub, SubAssign}; -use core::ops::{Mul, MulAssign}; use core::ops::Neg; +use core::ops::{Add, AddAssign}; +use core::ops::{Mul, MulAssign}; +use core::ops::{Sub, SubAssign}; -use subtle::ConditionallySelectable; use subtle::Choice; +use subtle::ConditionallySelectable; /// A `FieldElement32` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). @@ -238,6 +238,32 @@ impl ConditionallySelectable for FieldElement32 { u32::conditional_select(&a.0[9], &b.0[9], choice), ]) } + + fn conditional_assign(&mut self, other: &FieldElement32, choice: Choice) { + self.0[0].conditional_assign(&other.0[0], choice); + self.0[1].conditional_assign(&other.0[1], choice); + self.0[2].conditional_assign(&other.0[2], choice); + self.0[3].conditional_assign(&other.0[3], choice); + self.0[4].conditional_assign(&other.0[4], choice); + self.0[5].conditional_assign(&other.0[5], choice); + self.0[6].conditional_assign(&other.0[6], choice); + self.0[7].conditional_assign(&other.0[7], choice); + self.0[8].conditional_assign(&other.0[8], choice); + self.0[9].conditional_assign(&other.0[9], choice); + } + + fn conditional_swap(a: &mut FieldElement32, b: &mut FieldElement32, choice: Choice) { + u32::conditional_swap(&mut a.0[0], &mut b.0[0], choice); + u32::conditional_swap(&mut a.0[1], &mut b.0[1], choice); + u32::conditional_swap(&mut a.0[2], &mut b.0[2], choice); + u32::conditional_swap(&mut a.0[3], &mut b.0[3], choice); + u32::conditional_swap(&mut a.0[4], &mut b.0[4], choice); + u32::conditional_swap(&mut a.0[5], &mut b.0[5], choice); + u32::conditional_swap(&mut a.0[6], &mut b.0[6], choice); + u32::conditional_swap(&mut a.0[7], &mut b.0[7], choice); + u32::conditional_swap(&mut a.0[8], &mut b.0[8], choice); + u32::conditional_swap(&mut a.0[9], &mut b.0[9], choice); + } } impl FieldElement32 { diff --git a/src/backend/u64/field.rs b/src/backend/u64/field.rs index 9276af4..ffe1a48 100644 --- a/src/backend/u64/field.rs +++ b/src/backend/u64/field.rs @@ -223,6 +223,22 @@ impl ConditionallySelectable for FieldElement64 { u64::conditional_select(&a.0[4], &b.0[4], choice), ]) } + + fn conditional_swap(a: &mut FieldElement64, b: &mut FieldElement64, 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, other: &FieldElement64, choice: Choice) { + self.0[0].conditional_assign(&other.0[0], choice); + self.0[1].conditional_assign(&other.0[1], choice); + self.0[2].conditional_assign(&other.0[2], choice); + self.0[3].conditional_assign(&other.0[3], choice); + self.0[4].conditional_assign(&other.0[4], choice); + } } impl FieldElement64 { diff --git a/src/curve_models/mod.rs b/src/curve_models/mod.rs index 7c472c9..8133818 100644 --- a/src/curve_models/mod.rs +++ b/src/curve_models/mod.rs @@ -277,6 +277,13 @@ impl ConditionallySelectable for ProjectiveNielsPoint { T2d: FieldElement::conditional_select(&a.T2d, &b.T2d, choice), } } + + fn conditional_assign(&mut self, other: &Self, choice: Choice) { + self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice); + self.Y_minus_X.conditional_assign(&other.Y_minus_X, choice); + self.Z.conditional_assign(&other.Z, choice); + self.T2d.conditional_assign(&other.T2d, choice); + } } impl ConditionallySelectable for AffineNielsPoint { @@ -287,6 +294,12 @@ impl ConditionallySelectable for AffineNielsPoint { xy2d: FieldElement::conditional_select(&a.xy2d, &b.xy2d, choice), } } + + fn conditional_assign(&mut self, other: &Self, choice: Choice) { + self.y_plus_x.conditional_assign(&other.y_plus_x, choice); + self.y_minus_x.conditional_assign(&other.y_minus_x, choice); + self.xy2d.conditional_assign(&other.xy2d, choice); + } } // ------------------------------------------------------------------------ diff --git a/src/edwards.rs b/src/edwards.rs index ff5318e..78a7bca 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -903,7 +903,7 @@ impl Debug for EdwardsBasepointTable { mod test { use field::FieldElement; use scalar::Scalar; - use subtle::ConditionallyAssignable; + use subtle::ConditionallySelectable; use constants; use super::*; diff --git a/src/field.rs b/src/field.rs index e523df9..ff8d472 100644 --- a/src/field.rs +++ b/src/field.rs @@ -24,7 +24,7 @@ use core::cmp::{Eq, PartialEq}; -use subtle::ConditionallyAssignable; +use subtle::ConditionallySelectable; use subtle::ConditionallyNegatable; use subtle::Choice; use subtle::ConstantTimeEq; diff --git a/src/montgomery.rs b/src/montgomery.rs index 76ef4e2..d07e6af 100644 --- a/src/montgomery.rs +++ b/src/montgomery.rs @@ -51,15 +51,14 @@ use core::ops::{Mul, MulAssign}; use constants::APLUS2_OVER_FOUR; +use edwards::{CompressedEdwardsY, EdwardsPoint}; use field::FieldElement; -use edwards::{EdwardsPoint, CompressedEdwardsY}; use scalar::Scalar; use traits::Identity; use subtle::Choice; use subtle::ConditionallySelectable; -use subtle::ConditionallySwappable; use subtle::ConstantTimeEq; /// Holds the \\(u\\)-coordinate of a point on the Montgomery form of @@ -255,19 +254,22 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint { // Algorithm 8 of Costello-Smith 2017 let affine_u = FieldElement::from_bytes(&self.0); let mut x0 = ProjectivePoint::identity(); - let mut x1 = ProjectivePoint{ U: affine_u, W: FieldElement::one() }; + let mut x1 = ProjectivePoint { + U: affine_u, + W: FieldElement::one(), + }; let bits: [i8; 256] = scalar.bits(); for i in (0..255).rev() { - let choice: u8 = (bits[i+1] ^ bits[i]) as u8; + let choice: u8 = (bits[i + 1] ^ bits[i]) as u8; debug_assert!(choice == 0 || choice == 1); - x0.conditional_swap(&mut x1, choice.into()); + ProjectivePoint::conditional_swap(&mut x0, &mut x1, choice.into()); differential_add_and_double(&mut x0, &mut x1, &affine_u); } - x0.conditional_swap(&mut x1, Choice::from(bits[0] as u8)); + ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(bits[0] as u8)); x0.to_affine() } diff --git a/src/ristretto.rs b/src/ristretto.rs index 7657902..29fcbb4 100644 --- a/src/ristretto.rs +++ b/src/ristretto.rs @@ -173,9 +173,8 @@ use constants; use field::FieldElement; use subtle::Choice; -use subtle::ConditionallyAssignable; -use subtle::ConditionallyNegatable; use subtle::ConditionallySelectable; +use subtle::ConditionallyNegatable; use subtle::ConstantTimeEq; use edwards::EdwardsBasepointTable; diff --git a/src/scalar.rs b/src/scalar.rs index eacd4e3..2e4d256 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -983,7 +983,7 @@ impl Scalar { /// # extern crate curve25519_dalek; /// # extern crate subtle; /// # use curve25519_dalek::scalar::Scalar; - /// # use subtle::ConditionallyAssignable; + /// # use subtle::ConditionallySelectable; /// # fn main() { /// // 2^255 - 1, since `from_bits` clears the high bit /// let _2_255_minus_1 = Scalar::from_bits([0xff;32]); diff --git a/src/scalar_mul/window.rs b/src/scalar_mul/window.rs index c116136..d5ad2d6 100644 --- a/src/scalar_mul/window.rs +++ b/src/scalar_mul/window.rs @@ -15,7 +15,7 @@ use core::fmt::Debug; use subtle::ConditionallyNegatable; -use subtle::ConditionallyAssignable; +use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; use subtle::Choice; @@ -59,7 +59,7 @@ unsafe impl ZeroSafe for LookupTable {} impl LookupTable where - T: Identity + ConditionallyAssignable + ConditionallyNegatable, + T: Identity + ConditionallySelectable + ConditionallyNegatable, { /// Given \\(-8 \leq x \leq 8\\), return \\(xP\\) in constant time. pub fn select(&self, x: i8) -> T {