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"] }
digest = { version = "0.8", default-features = false }
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 }
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.0.0-pre.0", default-features = false }
serde = { version = "1.0", 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
# feature before the main-stage compilation.
stage2_build = []

View file

@ -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,8 +76,12 @@ impl From<ExtendedPoint> for edwards::EdwardsPoint {
}
}
impl ConditionallyAssignable for ExtendedPoint {
fn conditional_assign(&mut self, other: &ExtendedPoint, choice: Choice) {
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);
}
}
@ -209,8 +213,12 @@ impl Identity for CachedPoint {
}
}
impl ConditionallyAssignable for CachedPoint {
fn conditional_assign(&mut self, other: &CachedPoint, choice: Choice) {
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);
}
}

View file

@ -144,15 +144,37 @@ 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([
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.
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 `FieldElement32` represents an element of the field
/// \\( \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) {
for i in 0..10 {
self.0[i].conditional_assign(&other.0[i], 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);
}
}

View file

@ -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,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) {
for i in 0..5 {
self.0[i].conditional_assign(&other.0[i], 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);
}
}

View file

@ -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,8 +268,17 @@ impl ValidityCheck for ProjectivePoint {
// Constant-time assignment
// ------------------------------------------------------------------------
impl ConditionallyAssignable for ProjectiveNielsPoint {
fn conditional_assign(&mut self, other: &ProjectiveNielsPoint, choice: 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),
}
}
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);
@ -277,9 +286,16 @@ impl ConditionallyAssignable for ProjectiveNielsPoint {
}
}
impl ConditionallyAssignable for AffineNielsPoint {
fn conditional_assign(&mut self, other: &AffineNielsPoint, choice: Choice) {
// PreComputedGroupElementCMove()
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),
}
}
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);
@ -296,7 +312,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 +327,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 +339,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,

View file

@ -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())
}
}
@ -897,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::*;

View file

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

View file

@ -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
@ -51,16 +51,15 @@
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::ConditionallyAssignable;
use subtle::ConditionallySwappable;
use subtle::ConstantTimeEq;
use subtle::Choice;
use subtle::ConditionallySelectable;
use subtle::ConstantTimeEq;
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
/// Curve25519 or its twist.
@ -141,7 +140,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 +160,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 +201,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,
) {
@ -249,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()
}

View file

@ -157,28 +157,28 @@
//! [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::ConditionallyAssignable;
use subtle::Choice;
use subtle::ConditionallySelectable;
use subtle::ConditionallyNegatable;
use subtle::ConstantTimeEq;
use subtle::Choice;
use edwards::EdwardsPoint;
use edwards::EdwardsBasepointTable;
use edwards::EdwardsPoint;
#[allow(unused_imports)]
use prelude::*;
@ -949,11 +949,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
///
@ -961,7 +961,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;
@ -974,17 +974,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))
}
}

View file

@ -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 }
}
}
@ -981,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]);

View file

@ -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<T> ZeroSafe for LookupTable<T> {}
impl<T> LookupTable<T>
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 {