From b0a190bd63eaedfd8384dbb21830c290abe6b797 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Fri, 2 Nov 2018 14:16:51 -0700 Subject: [PATCH 1/4] Change externally-exposed API to implement ConditionallySelectable --- src/edwards.rs | 40 +++++++++++++++++++++++----------------- src/ristretto.rs | 38 ++++++++++++++++++++------------------ src/scalar.rs | 24 +++++++++++++----------- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/edwards.rs b/src/edwards.rs index a09ce45..ff5318e 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -70,7 +70,7 @@ //! The Edwards arithmetic is implemented using the “extended twisted //! coordinates” of Hisil, Wong, Carter, and Dawson, and the //! corresponding complete formulas. For more details, -//! see the [`curve_models` submodule][curve_models] +//! see the [`curve_models` submodule][curve_models] //! of the internal documentation. //! //! ## Validity Checking @@ -92,17 +92,17 @@ // affine and projective cakes and eat both of them too. #![allow(non_snake_case)] +use core::borrow::Borrow; use core::fmt::Debug; use core::iter::Iterator; -use core::ops::{Add, Sub, Neg}; +use core::iter::Sum; +use core::ops::{Add, Neg, Sub}; use core::ops::{AddAssign, SubAssign}; use core::ops::{Mul, MulAssign}; -use core::iter::Sum; -use core::borrow::Borrow; -use subtle::ConditionallyAssignable; -use subtle::ConditionallyNegatable; use subtle::Choice; +use subtle::ConditionallyNegatable; +use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; use constants; @@ -328,10 +328,12 @@ impl CompressedEdwardsY { impl Identity for EdwardsPoint { fn identity() -> EdwardsPoint { - EdwardsPoint{ X: FieldElement::zero(), - Y: FieldElement::one(), - Z: FieldElement::one(), - T: FieldElement::zero() } + EdwardsPoint { + X: FieldElement::zero(), + Y: FieldElement::one(), + Z: FieldElement::one(), + T: FieldElement::zero(), + } } } @@ -358,12 +360,14 @@ impl ValidityCheck for EdwardsPoint { // Constant-time assignment // ------------------------------------------------------------------------ -impl ConditionallyAssignable for EdwardsPoint { - fn conditional_assign(&mut self, other: &EdwardsPoint, choice: Choice) { - self.X.conditional_assign(&other.X, choice); - self.Y.conditional_assign(&other.Y, choice); - self.Z.conditional_assign(&other.Z, choice); - self.T.conditional_assign(&other.T, choice); +impl ConditionallySelectable for EdwardsPoint { + fn conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint { + EdwardsPoint { + X: FieldElement::conditional_select(&a.X, &b.X, choice), + Y: FieldElement::conditional_select(&a.Y, &b.Y, choice), + Z: FieldElement::conditional_select(&a.Z, &b.Z, choice), + T: FieldElement::conditional_select(&a.T, &b.T, choice), + } } } @@ -373,7 +377,9 @@ impl ConditionallyAssignable for EdwardsPoint { impl ConstantTimeEq for EdwardsPoint { fn ct_eq(&self, other: &EdwardsPoint) -> Choice { - self.compress().as_bytes().ct_eq(other.compress().as_bytes()) + self.compress() + .as_bytes() + .ct_eq(other.compress().as_bytes()) } } diff --git a/src/ristretto.rs b/src/ristretto.rs index b34dbe8..7657902 100644 --- a/src/ristretto.rs +++ b/src/ristretto.rs @@ -157,28 +157,29 @@ //! [ristretto_main]: //! https://ristretto.group/ +use core::borrow::Borrow; use core::fmt::Debug; -use core::ops::{Add, Sub, Neg}; +use core::iter::Sum; +use core::ops::{Add, Neg, Sub}; use core::ops::{AddAssign, SubAssign}; use core::ops::{Mul, MulAssign}; -use core::iter::Sum; -use core::borrow::Borrow; -use rand::{Rng, CryptoRng}; +use rand::{CryptoRng, Rng}; -use digest::Digest; use digest::generic_array::typenum::U64; +use digest::Digest; use constants; use field::FieldElement; +use subtle::Choice; use subtle::ConditionallyAssignable; use subtle::ConditionallyNegatable; +use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; -use subtle::Choice; -use edwards::EdwardsPoint; use edwards::EdwardsBasepointTable; +use edwards::EdwardsPoint; #[allow(unused_imports)] use prelude::*; @@ -961,11 +962,11 @@ impl RistrettoBasepointTable { } // ------------------------------------------------------------------------ -// Constant-time conditional assignment +// Constant-time conditional selection // ------------------------------------------------------------------------ -impl ConditionallyAssignable for RistrettoPoint { - /// Conditionally assign `other` to `self`, if `choice == Choice(1)`. +impl ConditionallySelectable for RistrettoPoint { + /// Conditionally select between `self` and `other`. /// /// # Example /// @@ -973,7 +974,7 @@ impl ConditionallyAssignable for RistrettoPoint { /// # extern crate subtle; /// # extern crate curve25519_dalek; /// # - /// use subtle::ConditionallyAssignable; + /// use subtle::ConditionallySelectable; /// use subtle::Choice; /// # /// # use curve25519_dalek::traits::Identity; @@ -986,17 +987,18 @@ impl ConditionallyAssignable for RistrettoPoint { /// /// let mut P = A; /// - /// P.conditional_assign(&B, Choice::from(0)); + /// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(0)); /// assert_eq!(P, A); - /// P.conditional_assign(&B, Choice::from(1)); + /// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(1)); /// assert_eq!(P, B); /// # } /// ``` - fn conditional_assign(&mut self, other: &RistrettoPoint, choice: Choice) { - self.0.X.conditional_assign(&other.0.X, choice); - self.0.Y.conditional_assign(&other.0.Y, choice); - self.0.Z.conditional_assign(&other.0.Z, choice); - self.0.T.conditional_assign(&other.0.T, choice); + fn conditional_select( + a: &RistrettoPoint, + b: &RistrettoPoint, + choice: Choice, + ) -> RistrettoPoint { + RistrettoPoint(EdwardsPoint::conditional_select(&a.0, &b.0, choice)) } } diff --git a/src/scalar.rs b/src/scalar.rs index 06c2f3c..eacd4e3 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -138,26 +138,26 @@ //! The resulting `Scalar` has exactly the specified bit pattern, //! **except for the highest bit, which will be set to 0**. +use core::borrow::Borrow; +use core::cmp::{Eq, PartialEq}; use core::fmt::Debug; +use core::iter::{Product, Sum}; +use core::ops::Index; use core::ops::Neg; use core::ops::{Add, AddAssign}; -use core::ops::{Sub, SubAssign}; use core::ops::{Mul, MulAssign}; -use core::ops::{Index}; -use core::cmp::{Eq, PartialEq}; -use core::iter::{Product, Sum}; -use core::borrow::Borrow; +use core::ops::{Sub, SubAssign}; #[allow(unused_imports)] use prelude::*; -use rand::{Rng, CryptoRng}; +use rand::{CryptoRng, Rng}; -use digest::Digest; use digest::generic_array::typenum::U64; +use digest::Digest; use subtle::Choice; -use subtle::ConditionallyAssignable; +use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; use backend; @@ -343,11 +343,13 @@ impl<'a> Neg for Scalar { } } -impl ConditionallyAssignable for Scalar { - fn conditional_assign(&mut self, other: &Scalar, choice: Choice) { +impl ConditionallySelectable for Scalar { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + let mut bytes = [0u8; 32]; for i in 0..32 { - self.bytes[i].conditional_assign(&other.bytes[i], choice); + bytes[i] = u8::conditional_select(&a.bytes[i], &b.bytes[i], choice); } + Scalar { bytes } } } From 53fcd1060d79e7ebcb0eae0eddaed9ff0cb44a36 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Fri, 2 Nov 2018 14:17:43 -0700 Subject: [PATCH 2/4] Change internal API to use ConditionallySelectable --- src/backend/avx2/edwards.rs | 14 ++++++------- src/backend/avx2/field.rs | 20 ++++++++++++------ src/backend/u32/field.rs | 25 ++++++++++++++++------ src/backend/u64/field.rs | 26 +++++++++++++++-------- src/curve_models/mod.rs | 41 ++++++++++++++++++++----------------- src/montgomery.rs | 24 ++++++++++++++-------- 6 files changed, 94 insertions(+), 56 deletions(-) diff --git a/src/backend/avx2/edwards.rs b/src/backend/avx2/edwards.rs index 1510bda..cf9e881 100644 --- a/src/backend/avx2/edwards.rs +++ b/src/backend/avx2/edwards.rs @@ -38,7 +38,7 @@ use core::convert::From; use core::ops::{Add, Neg, Sub}; use subtle::Choice; -use subtle::ConditionallyAssignable; +use subtle::ConditionallySelectable; use edwards; use scalar_mul::window::{LookupTable, NafLookupTable5, NafLookupTable8}; @@ -76,9 +76,9 @@ impl From for edwards::EdwardsPoint { } } -impl ConditionallyAssignable for ExtendedPoint { - fn conditional_assign(&mut self, other: &ExtendedPoint, choice: Choice) { - self.0.conditional_assign(&other.0, choice); +impl ConditionallySelectable for ExtendedPoint { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + ExtendedPoint(FieldElement32x4::conditional_select(&a.0, &b.0, choice)) } } @@ -209,9 +209,9 @@ impl Identity for CachedPoint { } } -impl ConditionallyAssignable for CachedPoint { - fn conditional_assign(&mut self, other: &CachedPoint, choice: Choice) { - self.0.conditional_assign(&other.0, choice); +impl ConditionallySelectable for CachedPoint { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + CachedPoint(FieldElement32x4::conditional_select(&a.0, &b.0, choice)) } } diff --git a/src/backend/avx2/field.rs b/src/backend/avx2/field.rs index 6f4e1fd..a37ed50 100644 --- a/src/backend/avx2/field.rs +++ b/src/backend/avx2/field.rs @@ -144,15 +144,23 @@ pub enum Shuffle { pub struct FieldElement32x4(pub(crate) [u32x8; 5]); use subtle::Choice; -use subtle::ConditionallyAssignable; +use subtle::ConditionallySelectable; -impl ConditionallyAssignable for FieldElement32x4 { - fn conditional_assign(&mut self, other: &FieldElement32x4, choice: Choice) { +impl ConditionallySelectable for FieldElement32x4 { + fn conditional_select( + a: &FieldElement32x4, + b: &FieldElement32x4, + choice: Choice, + ) -> FieldElement32x4 { let mask = (-(choice.unwrap_u8() as i32)) as u32; let mask_vec = u32x8::splat(mask); - for i in 0..5 { - self.0[i] = self.0[i] ^ (mask_vec & (self.0[i] ^ other.0[i])); - } + 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])), + ]) } } diff --git a/src/backend/u32/field.rs b/src/backend/u32/field.rs index 9de460a..2a9f5bb 100644 --- a/src/backend/u32/field.rs +++ b/src/backend/u32/field.rs @@ -21,7 +21,7 @@ use core::ops::{Sub, SubAssign}; use core::ops::{Mul, MulAssign}; use core::ops::Neg; -use subtle::ConditionallyAssignable; +use subtle::ConditionallySelectable; use subtle::Choice; /// A `FieldElement32` represents an element of the field @@ -219,11 +219,24 @@ impl<'a> Neg for &'a FieldElement32 { } } -impl ConditionallyAssignable for FieldElement32 { - fn conditional_assign(&mut self, other: &FieldElement32, choice: Choice) { - for i in 0..10 { - self.0[i].conditional_assign(&other.0[i], choice); - } +impl ConditionallySelectable for FieldElement32 { + fn conditional_select( + a: &FieldElement32, + b: &FieldElement32, + choice: Choice, + ) -> FieldElement32 { + FieldElement32([ + u32::conditional_select(&a.0[0], &b.0[0], choice), + u32::conditional_select(&a.0[1], &b.0[1], choice), + u32::conditional_select(&a.0[2], &b.0[2], choice), + u32::conditional_select(&a.0[3], &b.0[3], choice), + u32::conditional_select(&a.0[4], &b.0[4], choice), + u32::conditional_select(&a.0[5], &b.0[5], choice), + u32::conditional_select(&a.0[6], &b.0[6], choice), + u32::conditional_select(&a.0[7], &b.0[7], choice), + u32::conditional_select(&a.0[8], &b.0[8], choice), + u32::conditional_select(&a.0[9], &b.0[9], choice), + ]) } } diff --git a/src/backend/u64/field.rs b/src/backend/u64/field.rs index 25a013e..9276af4 100644 --- a/src/backend/u64/field.rs +++ b/src/backend/u64/field.rs @@ -12,13 +12,13 @@ //! limbs with \\(128\\)-bit products. 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::ConditionallyAssignable; use subtle::Choice; +use subtle::ConditionallySelectable; /// A `FieldElement64` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). @@ -209,11 +209,19 @@ impl<'a> Neg for &'a FieldElement64 { } } -impl ConditionallyAssignable for FieldElement64 { - fn conditional_assign(&mut self, other: &FieldElement64, choice: Choice) { - for i in 0..5 { - self.0[i].conditional_assign(&other.0[i], choice); - } +impl ConditionallySelectable for FieldElement64 { + fn conditional_select( + a: &FieldElement64, + b: &FieldElement64, + choice: Choice, + ) -> FieldElement64 { + FieldElement64([ + u64::conditional_select(&a.0[0], &b.0[0], choice), + u64::conditional_select(&a.0[1], &b.0[1], choice), + u64::conditional_select(&a.0[2], &b.0[2], choice), + u64::conditional_select(&a.0[3], &b.0[3], choice), + u64::conditional_select(&a.0[4], &b.0[4], choice), + ]) } } diff --git a/src/curve_models/mod.rs b/src/curve_models/mod.rs index 3f68132..7c472c9 100644 --- a/src/curve_models/mod.rs +++ b/src/curve_models/mod.rs @@ -124,15 +124,15 @@ #![allow(non_snake_case)] use core::fmt::Debug; -use core::ops::{Add, Sub, Neg}; +use core::ops::{Add, Neg, Sub}; -use subtle::ConditionallyAssignable; use subtle::Choice; +use subtle::ConditionallySelectable; use constants; -use field::FieldElement; use edwards::EdwardsPoint; +use field::FieldElement; use traits::ValidityCheck; // ------------------------------------------------------------------------ @@ -204,7 +204,7 @@ use traits::Identity; impl Identity for ProjectivePoint { fn identity() -> ProjectivePoint { - ProjectivePoint{ + ProjectivePoint { X: FieldElement::zero(), Y: FieldElement::one(), Z: FieldElement::one(), @@ -268,21 +268,24 @@ impl ValidityCheck for ProjectivePoint { // Constant-time assignment // ------------------------------------------------------------------------ -impl ConditionallyAssignable for ProjectiveNielsPoint { - fn conditional_assign(&mut self, other: &ProjectiveNielsPoint, 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 ProjectiveNielsPoint { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + ProjectiveNielsPoint { + Y_plus_X: FieldElement::conditional_select(&a.Y_plus_X, &b.Y_plus_X, choice), + Y_minus_X: FieldElement::conditional_select(&a.Y_minus_X, &b.Y_minus_X, choice), + Z: FieldElement::conditional_select(&a.Z, &b.Z, choice), + T2d: FieldElement::conditional_select(&a.T2d, &b.T2d, choice), + } } } -impl ConditionallyAssignable for AffineNielsPoint { - fn conditional_assign(&mut self, other: &AffineNielsPoint, choice: Choice) { - // PreComputedGroupElementCMove() - 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); +impl ConditionallySelectable for AffineNielsPoint { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + AffineNielsPoint { + y_plus_x: FieldElement::conditional_select(&a.y_plus_x, &b.y_plus_x, choice), + y_minus_x: FieldElement::conditional_select(&a.y_minus_x, &b.y_minus_x, choice), + xy2d: FieldElement::conditional_select(&a.xy2d, &b.xy2d, choice), + } } } @@ -296,7 +299,7 @@ impl ProjectivePoint { /// /// This costs \\(3 \mathrm M + 1 \mathrm S\\). pub fn to_extended(&self) -> EdwardsPoint { - EdwardsPoint{ + EdwardsPoint { X: &self.X * &self.Z, Y: &self.Y * &self.Z, Z: self.Z.square(), @@ -311,7 +314,7 @@ impl CompletedPoint { /// /// This costs \\(3 \mathrm M \\). pub fn to_projective(&self) -> ProjectivePoint { - ProjectivePoint{ + ProjectivePoint { X: &self.X * &self.T, Y: &self.Y * &self.Z, Z: &self.Z * &self.T, @@ -323,7 +326,7 @@ impl CompletedPoint { /// /// This costs \\(4 \mathrm M \\). pub fn to_extended(&self) -> EdwardsPoint { - EdwardsPoint{ + EdwardsPoint { X: &self.X * &self.T, Y: &self.Y * &self.Z, Z: &self.Z * &self.T, diff --git a/src/montgomery.rs b/src/montgomery.rs index fe7423b..76ef4e2 100644 --- a/src/montgomery.rs +++ b/src/montgomery.rs @@ -29,7 +29,7 @@ //! //! Scalar multiplication on `MontgomeryPoint`s is provided by the `*` //! operator, which implements the Montgomery ladder. -//! +//! //! # Edwards Conversion //! //! The \\(2\\)-to-\\(1\\) map from the Edwards model to the Montgomery @@ -57,10 +57,10 @@ use scalar::Scalar; use traits::Identity; -use subtle::ConditionallyAssignable; +use subtle::Choice; +use subtle::ConditionallySelectable; use subtle::ConditionallySwappable; use subtle::ConstantTimeEq; -use subtle::Choice; /// Holds the \\(u\\)-coordinate of a point on the Montgomery form of /// Curve25519 or its twist. @@ -141,7 +141,7 @@ impl MontgomeryPoint { /// \\( \mathbb P(\mathbb F\_p) \\), which we identify with the Kummer /// line of the Montgomery curve. #[derive(Copy, Clone, Debug)] -struct ProjectivePoint{ +struct ProjectivePoint { pub U: FieldElement, pub W: FieldElement, } @@ -161,10 +161,16 @@ impl Default for ProjectivePoint { } } -impl ConditionallyAssignable for ProjectivePoint { - fn conditional_assign(&mut self, that: &ProjectivePoint, choice: Choice) { - self.U.conditional_assign(&that.U, choice); - self.W.conditional_assign(&that.W, choice); +impl ConditionallySelectable for ProjectivePoint { + fn conditional_select( + a: &ProjectivePoint, + b: &ProjectivePoint, + choice: Choice, + ) -> ProjectivePoint { + ProjectivePoint { + U: FieldElement::conditional_select(&a.U, &b.U, choice), + W: FieldElement::conditional_select(&a.W, &b.W, choice), + } } } @@ -196,7 +202,7 @@ impl ProjectivePoint { /// (U\_Q : W\_Q) \gets u(P + Q). /// $$ fn differential_add_and_double( - P: &mut ProjectivePoint, + P: &mut ProjectivePoint, Q: &mut ProjectivePoint, affine_PmQ: &FieldElement, ) { From a116fd967912b3aac23b97c6dce72292a29dae73 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 5 Nov 2018 11:16:24 -0800 Subject: [PATCH 3/4] test subtle 2.0 --- Cargo.toml | 7 +++++-- src/backend/avx2/edwards.rs | 8 ++++++++ src/backend/avx2/field.rs | 24 +++++++++++++++++++----- src/backend/u32/field.rs | 34 ++++++++++++++++++++++++++++++---- src/backend/u64/field.rs | 16 ++++++++++++++++ src/curve_models/mod.rs | 13 +++++++++++++ src/edwards.rs | 2 +- src/field.rs | 2 +- src/montgomery.rs | 14 ++++++++------ src/ristretto.rs | 3 +-- src/scalar.rs | 2 +- src/scalar_mul/window.rs | 4 ++-- 12 files changed, 105 insertions(+), 24 deletions(-) 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 { From 92a3b9db49e0da8e16763620572f0d5417675a3f Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Mon, 5 Nov 2018 15:09:50 -0800 Subject: [PATCH 4/4] Change to subtle 2.0.0-pre.0 --- Cargo.toml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4ca1999..f3a1069 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 = "2", default-features = false } +subtle = { version = "2.0.0-pre.0", 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 = "2", default-features = false } +subtle = { version = "2.0.0-pre.0", default-features = false } serde = { version = "1.0", optional = true } packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true } @@ -79,5 +79,3 @@ avx2_backend = ["nightly", "u64_backend", "packed_simd"] # feature before the main-stage compilation. stage2_build = [] -[patch.crates-io] -subtle = { git = "https://github.com/dalek-cryptography/subtle", branch = "fix-subtle-traits" }