Merge pull request #205 from dalek-cryptography/fix-subtle-traits

Change to subtle::ConditionallySelectable
This commit is contained in:
isis agora lovecruft 2018-11-05 23:50:35 +00:00 committed by GitHub
commit 5d0bdf2f21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 235 additions and 108 deletions

View file

@ -45,7 +45,7 @@ rand = { version = "0.5", default-features = false }
byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] } byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
digest = { version = "0.8", default-features = false } digest = { version = "0.8", default-features = false }
clear_on_drop = "=0.2.3" clear_on_drop = "=0.2.3"
subtle = { version = "1", default-features = false } subtle = { version = "2.0.0-pre.0", default-features = false }
serde = { version = "1.0", optional = true } serde = { version = "1.0", optional = true }
packed_simd = { version = "0.3.0", features = ["into_bits"], 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"] } byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
digest = { version = "0.8", default-features = false } digest = { version = "0.8", default-features = false }
clear_on_drop = "=0.2.3" clear_on_drop = "=0.2.3"
subtle = { version = "1", default-features = false } subtle = { version = "2.0.0-pre.0", default-features = false }
serde = { version = "1.0", optional = true } serde = { version = "1.0", optional = true }
packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true } packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true }
@ -78,3 +78,4 @@ avx2_backend = ["nightly", "u64_backend", "packed_simd"]
# into the build script. Then, the build.rs emits the stage2_build # into the build script. Then, the build.rs emits the stage2_build
# feature before the main-stage compilation. # feature before the main-stage compilation.
stage2_build = [] stage2_build = []

View file

@ -38,7 +38,7 @@ use core::convert::From;
use core::ops::{Add, Neg, Sub}; use core::ops::{Add, Neg, Sub};
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallyAssignable; use subtle::ConditionallySelectable;
use edwards; use edwards;
use scalar_mul::window::{LookupTable, NafLookupTable5, NafLookupTable8}; use scalar_mul::window::{LookupTable, NafLookupTable5, NafLookupTable8};
@ -76,8 +76,12 @@ impl From<ExtendedPoint> for edwards::EdwardsPoint {
} }
} }
impl ConditionallyAssignable for ExtendedPoint { impl ConditionallySelectable for ExtendedPoint {
fn conditional_assign(&mut self, other: &ExtendedPoint, choice: Choice) { 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); self.0.conditional_assign(&other.0, choice);
} }
} }
@ -209,8 +213,12 @@ impl Identity for CachedPoint {
} }
} }
impl ConditionallyAssignable for CachedPoint { impl ConditionallySelectable for CachedPoint {
fn conditional_assign(&mut self, other: &CachedPoint, choice: Choice) { 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); self.0.conditional_assign(&other.0, choice);
} }
} }

View file

@ -144,15 +144,37 @@ pub enum Shuffle {
pub struct FieldElement32x4(pub(crate) [u32x8; 5]); pub struct FieldElement32x4(pub(crate) [u32x8; 5]);
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallyAssignable; use subtle::ConditionallySelectable;
impl ConditionallyAssignable for FieldElement32x4 { impl ConditionallySelectable for FieldElement32x4 {
fn conditional_assign(&mut self, other: &FieldElement32x4, choice: Choice) { fn conditional_select(
a: &FieldElement32x4,
b: &FieldElement32x4,
choice: Choice,
) -> FieldElement32x4 {
let mask = (-(choice.unwrap_u8() as i32)) as u32; let mask = (-(choice.unwrap_u8() as i32)) as u32;
let mask_vec = u32x8::splat(mask); let mask_vec = u32x8::splat(mask);
for i in 0..5 { FieldElement32x4([
self.0[i] = self.0[i] ^ (mask_vec & (self.0[i] ^ other.0[i])); 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]);
} }
} }

View file

@ -16,13 +16,13 @@
//! of signed limbs. //! of signed limbs.
use core::fmt::Debug; 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::Neg;
use core::ops::{Add, AddAssign};
use core::ops::{Mul, MulAssign};
use core::ops::{Sub, SubAssign};
use subtle::ConditionallyAssignable;
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallySelectable;
/// A `FieldElement32` represents an element of the field /// A `FieldElement32` represents an element of the field
/// \\( \mathbb Z / (2\^{255} - 19)\\). /// \\( \mathbb Z / (2\^{255} - 19)\\).
@ -219,11 +219,50 @@ impl<'a> Neg for &'a FieldElement32 {
} }
} }
impl ConditionallyAssignable for FieldElement32 { 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),
])
}
fn conditional_assign(&mut self, other: &FieldElement32, choice: Choice) { fn conditional_assign(&mut self, other: &FieldElement32, choice: Choice) {
for i in 0..10 { self.0[0].conditional_assign(&other.0[0], choice);
self.0[i].conditional_assign(&other.0[i], 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);
} }
} }

View file

@ -12,13 +12,13 @@
//! limbs with \\(128\\)-bit products. //! limbs with \\(128\\)-bit products.
use core::fmt::Debug; 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::Neg;
use core::ops::{Add, AddAssign};
use core::ops::{Mul, MulAssign};
use core::ops::{Sub, SubAssign};
use subtle::ConditionallyAssignable;
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallySelectable;
/// A `FieldElement64` represents an element of the field /// A `FieldElement64` represents an element of the field
/// \\( \mathbb Z / (2\^{255} - 19)\\). /// \\( \mathbb Z / (2\^{255} - 19)\\).
@ -209,11 +209,35 @@ impl<'a> Neg for &'a FieldElement64 {
} }
} }
impl ConditionallyAssignable for FieldElement64 { 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),
])
}
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) { fn conditional_assign(&mut self, other: &FieldElement64, choice: Choice) {
for i in 0..5 { self.0[0].conditional_assign(&other.0[0], choice);
self.0[i].conditional_assign(&other.0[i], 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);
} }
} }

View file

@ -124,15 +124,15 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
use core::fmt::Debug; use core::fmt::Debug;
use core::ops::{Add, Sub, Neg}; use core::ops::{Add, Neg, Sub};
use subtle::ConditionallyAssignable;
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallySelectable;
use constants; use constants;
use field::FieldElement;
use edwards::EdwardsPoint; use edwards::EdwardsPoint;
use field::FieldElement;
use traits::ValidityCheck; use traits::ValidityCheck;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -204,7 +204,7 @@ use traits::Identity;
impl Identity for ProjectivePoint { impl Identity for ProjectivePoint {
fn identity() -> ProjectivePoint { fn identity() -> ProjectivePoint {
ProjectivePoint{ ProjectivePoint {
X: FieldElement::zero(), X: FieldElement::zero(),
Y: FieldElement::one(), Y: FieldElement::one(),
Z: FieldElement::one(), Z: FieldElement::one(),
@ -268,8 +268,17 @@ impl ValidityCheck for ProjectivePoint {
// Constant-time assignment // Constant-time assignment
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
impl ConditionallyAssignable for ProjectiveNielsPoint { impl ConditionallySelectable for ProjectiveNielsPoint {
fn conditional_assign(&mut self, other: &ProjectiveNielsPoint, choice: Choice) { 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),
}
}
fn conditional_assign(&mut self, other: &Self, choice: Choice) {
self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice); self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice);
self.Y_minus_X.conditional_assign(&other.Y_minus_X, choice); self.Y_minus_X.conditional_assign(&other.Y_minus_X, choice);
self.Z.conditional_assign(&other.Z, choice); self.Z.conditional_assign(&other.Z, choice);
@ -277,9 +286,16 @@ impl ConditionallyAssignable for ProjectiveNielsPoint {
} }
} }
impl ConditionallyAssignable for AffineNielsPoint { impl ConditionallySelectable for AffineNielsPoint {
fn conditional_assign(&mut self, other: &AffineNielsPoint, choice: Choice) { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
// PreComputedGroupElementCMove() 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),
}
}
fn conditional_assign(&mut self, other: &Self, choice: Choice) {
self.y_plus_x.conditional_assign(&other.y_plus_x, choice); self.y_plus_x.conditional_assign(&other.y_plus_x, choice);
self.y_minus_x.conditional_assign(&other.y_minus_x, choice); self.y_minus_x.conditional_assign(&other.y_minus_x, choice);
self.xy2d.conditional_assign(&other.xy2d, choice); self.xy2d.conditional_assign(&other.xy2d, choice);
@ -296,7 +312,7 @@ impl ProjectivePoint {
/// ///
/// This costs \\(3 \mathrm M + 1 \mathrm S\\). /// This costs \\(3 \mathrm M + 1 \mathrm S\\).
pub fn to_extended(&self) -> EdwardsPoint { pub fn to_extended(&self) -> EdwardsPoint {
EdwardsPoint{ EdwardsPoint {
X: &self.X * &self.Z, X: &self.X * &self.Z,
Y: &self.Y * &self.Z, Y: &self.Y * &self.Z,
Z: self.Z.square(), Z: self.Z.square(),
@ -311,7 +327,7 @@ impl CompletedPoint {
/// ///
/// This costs \\(3 \mathrm M \\). /// This costs \\(3 \mathrm M \\).
pub fn to_projective(&self) -> ProjectivePoint { pub fn to_projective(&self) -> ProjectivePoint {
ProjectivePoint{ ProjectivePoint {
X: &self.X * &self.T, X: &self.X * &self.T,
Y: &self.Y * &self.Z, Y: &self.Y * &self.Z,
Z: &self.Z * &self.T, Z: &self.Z * &self.T,
@ -323,7 +339,7 @@ impl CompletedPoint {
/// ///
/// This costs \\(4 \mathrm M \\). /// This costs \\(4 \mathrm M \\).
pub fn to_extended(&self) -> EdwardsPoint { pub fn to_extended(&self) -> EdwardsPoint {
EdwardsPoint{ EdwardsPoint {
X: &self.X * &self.T, X: &self.X * &self.T,
Y: &self.Y * &self.Z, Y: &self.Y * &self.Z,
Z: &self.Z * &self.T, Z: &self.Z * &self.T,

View file

@ -92,17 +92,17 @@
// affine and projective cakes and eat both of them too. // affine and projective cakes and eat both of them too.
#![allow(non_snake_case)] #![allow(non_snake_case)]
use core::borrow::Borrow;
use core::fmt::Debug; use core::fmt::Debug;
use core::iter::Iterator; 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::{AddAssign, SubAssign};
use core::ops::{Mul, MulAssign}; use core::ops::{Mul, MulAssign};
use core::iter::Sum;
use core::borrow::Borrow;
use subtle::ConditionallyAssignable;
use subtle::ConditionallyNegatable;
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallyNegatable;
use subtle::ConditionallySelectable;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
use constants; use constants;
@ -328,10 +328,12 @@ impl CompressedEdwardsY {
impl Identity for EdwardsPoint { impl Identity for EdwardsPoint {
fn identity() -> EdwardsPoint { fn identity() -> EdwardsPoint {
EdwardsPoint{ X: FieldElement::zero(), EdwardsPoint {
Y: FieldElement::one(), X: FieldElement::zero(),
Z: FieldElement::one(), Y: FieldElement::one(),
T: FieldElement::zero() } Z: FieldElement::one(),
T: FieldElement::zero(),
}
} }
} }
@ -358,12 +360,14 @@ impl ValidityCheck for EdwardsPoint {
// Constant-time assignment // Constant-time assignment
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
impl ConditionallyAssignable for EdwardsPoint { impl ConditionallySelectable for EdwardsPoint {
fn conditional_assign(&mut self, other: &EdwardsPoint, choice: Choice) { fn conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint {
self.X.conditional_assign(&other.X, choice); EdwardsPoint {
self.Y.conditional_assign(&other.Y, choice); X: FieldElement::conditional_select(&a.X, &b.X, choice),
self.Z.conditional_assign(&other.Z, choice); Y: FieldElement::conditional_select(&a.Y, &b.Y, choice),
self.T.conditional_assign(&other.T, 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 { impl ConstantTimeEq for EdwardsPoint {
fn ct_eq(&self, other: &EdwardsPoint) -> Choice { 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())
} }
} }
@ -897,7 +903,7 @@ impl Debug for EdwardsBasepointTable {
mod test { mod test {
use field::FieldElement; use field::FieldElement;
use scalar::Scalar; use scalar::Scalar;
use subtle::ConditionallyAssignable; use subtle::ConditionallySelectable;
use constants; use constants;
use super::*; use super::*;

View file

@ -24,7 +24,7 @@
use core::cmp::{Eq, PartialEq}; use core::cmp::{Eq, PartialEq};
use subtle::ConditionallyAssignable; use subtle::ConditionallySelectable;
use subtle::ConditionallyNegatable; use subtle::ConditionallyNegatable;
use subtle::Choice; use subtle::Choice;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;

View file

@ -51,16 +51,15 @@
use core::ops::{Mul, MulAssign}; use core::ops::{Mul, MulAssign};
use constants::APLUS2_OVER_FOUR; use constants::APLUS2_OVER_FOUR;
use edwards::{CompressedEdwardsY, EdwardsPoint};
use field::FieldElement; use field::FieldElement;
use edwards::{EdwardsPoint, CompressedEdwardsY};
use scalar::Scalar; use scalar::Scalar;
use traits::Identity; use traits::Identity;
use subtle::ConditionallyAssignable;
use subtle::ConditionallySwappable;
use subtle::ConstantTimeEq;
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallySelectable;
use subtle::ConstantTimeEq;
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of /// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
/// Curve25519 or its twist. /// Curve25519 or its twist.
@ -141,7 +140,7 @@ impl MontgomeryPoint {
/// \\( \mathbb P(\mathbb F\_p) \\), which we identify with the Kummer /// \\( \mathbb P(\mathbb F\_p) \\), which we identify with the Kummer
/// line of the Montgomery curve. /// line of the Montgomery curve.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct ProjectivePoint{ struct ProjectivePoint {
pub U: FieldElement, pub U: FieldElement,
pub W: FieldElement, pub W: FieldElement,
} }
@ -161,10 +160,16 @@ impl Default for ProjectivePoint {
} }
} }
impl ConditionallyAssignable for ProjectivePoint { impl ConditionallySelectable for ProjectivePoint {
fn conditional_assign(&mut self, that: &ProjectivePoint, choice: Choice) { fn conditional_select(
self.U.conditional_assign(&that.U, choice); a: &ProjectivePoint,
self.W.conditional_assign(&that.W, choice); b: &ProjectivePoint,
choice: Choice,
) -> ProjectivePoint {
ProjectivePoint {
U: FieldElement::conditional_select(&a.U, &b.U, choice),
W: FieldElement::conditional_select(&a.W, &b.W, choice),
}
} }
} }
@ -249,19 +254,22 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint {
// Algorithm 8 of Costello-Smith 2017 // Algorithm 8 of Costello-Smith 2017
let affine_u = FieldElement::from_bytes(&self.0); let affine_u = FieldElement::from_bytes(&self.0);
let mut x0 = ProjectivePoint::identity(); 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(); let bits: [i8; 256] = scalar.bits();
for i in (0..255).rev() { 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); 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); 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() x0.to_affine()
} }

View file

@ -157,28 +157,28 @@
//! [ristretto_main]: //! [ristretto_main]:
//! https://ristretto.group/ //! https://ristretto.group/
use core::borrow::Borrow;
use core::fmt::Debug; 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::{AddAssign, SubAssign};
use core::ops::{Mul, MulAssign}; 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::generic_array::typenum::U64;
use digest::Digest;
use constants; use constants;
use field::FieldElement; use field::FieldElement;
use subtle::ConditionallyAssignable; use subtle::Choice;
use subtle::ConditionallySelectable;
use subtle::ConditionallyNegatable; use subtle::ConditionallyNegatable;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
use subtle::Choice;
use edwards::EdwardsPoint;
use edwards::EdwardsBasepointTable; use edwards::EdwardsBasepointTable;
use edwards::EdwardsPoint;
#[allow(unused_imports)] #[allow(unused_imports)]
use prelude::*; use prelude::*;
@ -949,11 +949,11 @@ impl RistrettoBasepointTable {
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Constant-time conditional assignment // Constant-time conditional selection
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
impl ConditionallyAssignable for RistrettoPoint { impl ConditionallySelectable for RistrettoPoint {
/// Conditionally assign `other` to `self`, if `choice == Choice(1)`. /// Conditionally select between `self` and `other`.
/// ///
/// # Example /// # Example
/// ///
@ -961,7 +961,7 @@ impl ConditionallyAssignable for RistrettoPoint {
/// # extern crate subtle; /// # extern crate subtle;
/// # extern crate curve25519_dalek; /// # extern crate curve25519_dalek;
/// # /// #
/// use subtle::ConditionallyAssignable; /// use subtle::ConditionallySelectable;
/// use subtle::Choice; /// use subtle::Choice;
/// # /// #
/// # use curve25519_dalek::traits::Identity; /// # use curve25519_dalek::traits::Identity;
@ -974,17 +974,18 @@ impl ConditionallyAssignable for RistrettoPoint {
/// ///
/// let mut P = A; /// let mut P = A;
/// ///
/// P.conditional_assign(&B, Choice::from(0)); /// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(0));
/// assert_eq!(P, A); /// assert_eq!(P, A);
/// P.conditional_assign(&B, Choice::from(1)); /// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(1));
/// assert_eq!(P, B); /// assert_eq!(P, B);
/// # } /// # }
/// ``` /// ```
fn conditional_assign(&mut self, other: &RistrettoPoint, choice: Choice) { fn conditional_select(
self.0.X.conditional_assign(&other.0.X, choice); a: &RistrettoPoint,
self.0.Y.conditional_assign(&other.0.Y, choice); b: &RistrettoPoint,
self.0.Z.conditional_assign(&other.0.Z, choice); choice: Choice,
self.0.T.conditional_assign(&other.0.T, choice); ) -> RistrettoPoint {
RistrettoPoint(EdwardsPoint::conditional_select(&a.0, &b.0, choice))
} }
} }

View file

@ -138,26 +138,26 @@
//! The resulting `Scalar` has exactly the specified bit pattern, //! The resulting `Scalar` has exactly the specified bit pattern,
//! **except for the highest bit, which will be set to 0**. //! **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::fmt::Debug;
use core::iter::{Product, Sum};
use core::ops::Index;
use core::ops::Neg; use core::ops::Neg;
use core::ops::{Add, AddAssign}; use core::ops::{Add, AddAssign};
use core::ops::{Sub, SubAssign};
use core::ops::{Mul, MulAssign}; use core::ops::{Mul, MulAssign};
use core::ops::{Index}; use core::ops::{Sub, SubAssign};
use core::cmp::{Eq, PartialEq};
use core::iter::{Product, Sum};
use core::borrow::Borrow;
#[allow(unused_imports)] #[allow(unused_imports)]
use prelude::*; use prelude::*;
use rand::{Rng, CryptoRng}; use rand::{CryptoRng, Rng};
use digest::Digest;
use digest::generic_array::typenum::U64; use digest::generic_array::typenum::U64;
use digest::Digest;
use subtle::Choice; use subtle::Choice;
use subtle::ConditionallyAssignable; use subtle::ConditionallySelectable;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
use backend; use backend;
@ -343,11 +343,13 @@ impl<'a> Neg for Scalar {
} }
} }
impl ConditionallyAssignable for Scalar { impl ConditionallySelectable for Scalar {
fn conditional_assign(&mut self, other: &Scalar, choice: Choice) { fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
let mut bytes = [0u8; 32];
for i in 0..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 }
} }
} }
@ -981,7 +983,7 @@ impl Scalar {
/// # extern crate curve25519_dalek; /// # extern crate curve25519_dalek;
/// # extern crate subtle; /// # extern crate subtle;
/// # use curve25519_dalek::scalar::Scalar; /// # use curve25519_dalek::scalar::Scalar;
/// # use subtle::ConditionallyAssignable; /// # use subtle::ConditionallySelectable;
/// # fn main() { /// # fn main() {
/// // 2^255 - 1, since `from_bits` clears the high bit /// // 2^255 - 1, since `from_bits` clears the high bit
/// let _2_255_minus_1 = Scalar::from_bits([0xff;32]); /// let _2_255_minus_1 = Scalar::from_bits([0xff;32]);

View file

@ -15,7 +15,7 @@
use core::fmt::Debug; use core::fmt::Debug;
use subtle::ConditionallyNegatable; use subtle::ConditionallyNegatable;
use subtle::ConditionallyAssignable; use subtle::ConditionallySelectable;
use subtle::ConstantTimeEq; use subtle::ConstantTimeEq;
use subtle::Choice; use subtle::Choice;
@ -59,7 +59,7 @@ unsafe impl<T> ZeroSafe for LookupTable<T> {}
impl<T> LookupTable<T> impl<T> LookupTable<T>
where where
T: Identity + ConditionallyAssignable + ConditionallyNegatable, T: Identity + ConditionallySelectable + ConditionallyNegatable,
{ {
/// Given \\(-8 \leq x \leq 8\\), return \\(xP\\) in constant time. /// Given \\(-8 \leq x \leq 8\\), return \\(xP\\) in constant time.
pub fn select(&self, x: i8) -> T { pub fn select(&self, x: i8) -> T {