mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-05 20:30:57 +00:00
Merge remote-tracking branch 'hdevalence/feature/move-ct-traits' into develop
This commit is contained in:
commit
39f417f75e
4 changed files with 81 additions and 85 deletions
11
src/curve.rs
11
src/curve.rs
|
|
@ -86,6 +86,7 @@ use constants;
|
||||||
use field::FieldElement;
|
use field::FieldElement;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
use util::bytes_equal_ct;
|
use util::bytes_equal_ct;
|
||||||
|
use util::CTAssignable;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Compressed points
|
// Compressed points
|
||||||
|
|
@ -283,15 +284,6 @@ impl Identity for PreComputedPoint {
|
||||||
// Constant-time assignment
|
// Constant-time assignment
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Trait for items which can be conditionally assigned in constant time.
|
|
||||||
pub trait CTAssignable {
|
|
||||||
/// If `choice == 1u8`, assign `other` to `self`.
|
|
||||||
/// Otherwise, leave `self` unchanged.
|
|
||||||
/// Executes in constant time.
|
|
||||||
// XXX this trait should be extracted?
|
|
||||||
fn conditional_assign(&mut self, other: &Self, choice: u8);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CTAssignable for CachedPoint {
|
impl CTAssignable for CachedPoint {
|
||||||
fn conditional_assign(&mut self, other: &CachedPoint, choice: u8) {
|
fn conditional_assign(&mut self, other: &CachedPoint, choice: u8) {
|
||||||
self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice);
|
self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice);
|
||||||
|
|
@ -815,6 +807,7 @@ mod test {
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
use field::FieldElement;
|
use field::FieldElement;
|
||||||
use scalar::Scalar;
|
use scalar::Scalar;
|
||||||
|
use util::CTAssignable;
|
||||||
use constants;
|
use constants;
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::select_precomputed_point;
|
use super::select_precomputed_point;
|
||||||
|
|
|
||||||
115
src/field.rs
115
src/field.rs
|
|
@ -25,6 +25,7 @@ use std::cmp::{Eq, PartialEq};
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
|
|
||||||
use util::byte_is_nonzero;
|
use util::byte_is_nonzero;
|
||||||
|
use util::CTAssignable;
|
||||||
|
|
||||||
/// FieldElements are represented as an array of ten "Limbs", which are radix
|
/// FieldElements are represented as an array of ten "Limbs", which are radix
|
||||||
/// 25.5, that is, each Limb of a FieldElement alternates between being
|
/// 25.5, that is, each Limb of a FieldElement alternates between being
|
||||||
|
|
@ -142,6 +143,44 @@ impl<'a> Neg for &'a FieldElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CTAssignable for FieldElement {
|
||||||
|
/// Conditionally assign another FieldElement to this one.
|
||||||
|
///
|
||||||
|
/// If `choice == 0`, replace `self` with `self`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use curve25519_dalek::field::FieldElement;
|
||||||
|
/// # use curve25519_dalek::util::CTAssignable;
|
||||||
|
/// let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
||||||
|
/// let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
|
||||||
|
/// let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
||||||
|
/// h.conditional_assign(&g, 0);
|
||||||
|
/// assert!(h == f);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If `choice == 1`, replace `self` with `f`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use curve25519_dalek::field::FieldElement;
|
||||||
|
/// # use curve25519_dalek::util::CTAssignable;
|
||||||
|
/// # let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
||||||
|
/// # let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
|
||||||
|
/// # let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
||||||
|
/// h.conditional_assign(&g, 1);
|
||||||
|
/// assert!(h == g);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Preconditions
|
||||||
|
///
|
||||||
|
/// * `choice` in {0,1}
|
||||||
|
fn conditional_assign(&mut self, f: &FieldElement, choice: u8) {
|
||||||
|
let mask = -(choice as Limb);
|
||||||
|
for i in 0..10 {
|
||||||
|
self[i] ^= mask & (self[i] ^ f[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert an array of (at least) three bytes into an i64.
|
/// Convert an array of (at least) three bytes into an i64.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -179,82 +218,6 @@ impl FieldElement {
|
||||||
FieldElement([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ])
|
FieldElement([ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Overwrite this FieldElement with one of the inputs without branching.
|
|
||||||
/// Like `conditional_assign`, but chooses between two inputs instead of
|
|
||||||
/// one input and the original value.
|
|
||||||
///
|
|
||||||
/// If `choice == 0`, replace `self` with `f`:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use curve25519_dalek::field::FieldElement;
|
|
||||||
/// let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
|
||||||
/// let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
|
|
||||||
/// let mut h = FieldElement([0,0,0,0,0,0,0,0,0,0]);
|
|
||||||
/// h.conditional_choose(&f, &g, 0);
|
|
||||||
/// assert!(h == f);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// If `choice == 1`, replace `self` with `g`:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use curve25519_dalek::field::FieldElement;
|
|
||||||
/// # let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
|
||||||
/// # let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
|
|
||||||
/// # let mut h = FieldElement([0,0,0,0,0,0,0,0,0,0]);
|
|
||||||
/// h.conditional_choose(&f, &g, 1);
|
|
||||||
/// assert!(h == g);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// # Preconditions
|
|
||||||
///
|
|
||||||
/// * `b` in {0,1}
|
|
||||||
pub fn conditional_choose(&mut self,
|
|
||||||
f: &FieldElement,
|
|
||||||
g: &FieldElement,
|
|
||||||
choice: u8)
|
|
||||||
{
|
|
||||||
let mask = -(choice as Limb);
|
|
||||||
for i in 0..10 {
|
|
||||||
self[i] = f[i] ^ (mask & (f[i] ^ g[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Conditionally assign the Limbs of another FieldElement to this
|
|
||||||
/// one. Like `conditional_choose`, but choosing between one
|
|
||||||
/// input and the original value.
|
|
||||||
///
|
|
||||||
/// If `choice == 0`, replace `self` with `self`:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use curve25519_dalek::field::FieldElement;
|
|
||||||
/// let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
|
||||||
/// let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
|
|
||||||
/// let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
|
||||||
/// h.conditional_assign(&g, 0);
|
|
||||||
/// assert!(h == f);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// If `choice == 1`, replace `self` with `f`:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use curve25519_dalek::field::FieldElement;
|
|
||||||
/// # let f = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
|
||||||
/// # let g = FieldElement([2,2,2,2,2,2,2,2,2,2]);
|
|
||||||
/// # let mut h = FieldElement([1,1,1,1,1,1,1,1,1,1]);
|
|
||||||
/// h.conditional_assign(&g, 1);
|
|
||||||
/// assert!(h == g);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// # Preconditions
|
|
||||||
///
|
|
||||||
/// * `choice` in {0,1}
|
|
||||||
pub fn conditional_assign(&mut self, f: &FieldElement, choice: u8) {
|
|
||||||
let mask = -(choice as Limb);
|
|
||||||
for i in 0..10 {
|
|
||||||
self[i] ^= mask & (self[i] ^ f[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn combine_coeffs(input: &[i64;10]) -> FieldElement { //FeCombine
|
fn combine_coeffs(input: &[i64;10]) -> FieldElement { //FeCombine
|
||||||
let mut c = [0i64;10];
|
let mut c = [0i64;10];
|
||||||
let mut h = input.clone();
|
let mut h = input.clone();
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ use rand::Rng;
|
||||||
|
|
||||||
// XXX should these be in a utility module ?
|
// XXX should these be in a utility module ?
|
||||||
use field::{load3, load4};
|
use field::{load3, load4};
|
||||||
|
use util::CTAssignable;
|
||||||
|
|
||||||
/// The `Scalar` struct represents an element in ℤ/lℤ, where
|
/// The `Scalar` struct represents an element in ℤ/lℤ, where
|
||||||
///
|
///
|
||||||
|
|
@ -60,6 +61,37 @@ impl IndexMut<usize> for Scalar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CTAssignable for Scalar {
|
||||||
|
/// Conditionally assign another Scalar to this one.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use curve25519_dalek::scalar::Scalar;
|
||||||
|
/// # use curve25519_dalek::util::CTAssignable;
|
||||||
|
/// let a = Scalar([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
/// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
|
||||||
|
/// let b = Scalar([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
|
/// 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]);
|
||||||
|
/// let mut t = a;
|
||||||
|
/// t.conditional_assign(&b, 0u8);
|
||||||
|
/// assert!(t[0] == a[0]);
|
||||||
|
/// t.conditional_assign(&b, 1u8);
|
||||||
|
/// assert!(t[0] == b[0]);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Preconditions
|
||||||
|
///
|
||||||
|
/// * `choice` in {0,1}
|
||||||
|
// XXX above test checks first byte because Scalar does not impl Eq
|
||||||
|
fn conditional_assign(&mut self, other: &Scalar, choice: u8) {
|
||||||
|
// if choice = 0u8, mask = (-0i8) as u8 = 00000000
|
||||||
|
// if choice = 1u8, mask = (-1i8) as u8 = 11111111
|
||||||
|
let mask = -(choice as i8) as u8;
|
||||||
|
for i in 0..32 {
|
||||||
|
self[i] ^= mask & (self[i] ^ other[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Scalar {
|
impl Scalar {
|
||||||
/// Return a `Scalar` chosen uniformly at random using a CSPRNG.
|
/// Return a `Scalar` chosen uniformly at random using a CSPRNG.
|
||||||
/// Panics if the operating system's CSPRNG is unavailable.
|
/// Panics if the operating system's CSPRNG is unavailable.
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,14 @@
|
||||||
|
|
||||||
//! Utility functions and tools for constant-time comparisons.
|
//! Utility functions and tools for constant-time comparisons.
|
||||||
|
|
||||||
|
/// Trait for items which can be conditionally assigned in constant time.
|
||||||
|
pub trait CTAssignable {
|
||||||
|
/// If `choice == 1u8`, assign `other` to `self`.
|
||||||
|
/// Otherwise, leave `self` unchanged.
|
||||||
|
/// Executes in constant time.
|
||||||
|
fn conditional_assign(&mut self, other: &Self, choice: u8);
|
||||||
|
}
|
||||||
|
|
||||||
/// Check equality of two bytes in constant time.
|
/// Check equality of two bytes in constant time.
|
||||||
///
|
///
|
||||||
/// # Return
|
/// # Return
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue