mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-07 20:50:39 +00:00
Merge branch 'feature/subtle' into develop
This commit is contained in:
commit
b2470cb7b9
3 changed files with 117 additions and 1 deletions
|
|
@ -36,6 +36,10 @@ version = "0.4"
|
||||||
# same version that digest depends on
|
# same version that digest depends on
|
||||||
version = "^0.6"
|
version = "^0.6"
|
||||||
|
|
||||||
|
[dependencies.num-traits]
|
||||||
|
optional = true
|
||||||
|
version = "^0.1"
|
||||||
|
|
||||||
[dev-dependencies.sha2]
|
[dev-dependencies.sha2]
|
||||||
version = "0.4"
|
version = "0.4"
|
||||||
|
|
||||||
|
|
@ -45,7 +49,7 @@ version = "0.6"
|
||||||
[features]
|
[features]
|
||||||
nightly = ["radix_51"]
|
nightly = ["radix_51"]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = ["rand"]
|
std = ["rand", "num-traits"]
|
||||||
yolocrypto = []
|
yolocrypto = []
|
||||||
bench = []
|
bench = []
|
||||||
# Radix-51 arithmetic using u128
|
# Radix-51 arithmetic using u128
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#![cfg_attr(not(feature = "std"), feature(collections))]
|
#![cfg_attr(not(feature = "std"), feature(collections))]
|
||||||
#![cfg_attr(feature = "nightly", feature(i128_type))]
|
#![cfg_attr(feature = "nightly", feature(i128_type))]
|
||||||
#![cfg_attr(feature = "bench", feature(test))]
|
#![cfg_attr(feature = "bench", feature(test))]
|
||||||
|
#![cfg_attr(all(feature = "nightly", feature = "std"), feature(zero_one))]
|
||||||
|
|
||||||
#![allow(unused_features)]
|
#![allow(unused_features)]
|
||||||
#![deny(missing_docs)] // refuse to compile if documentation is missing
|
#![deny(missing_docs)] // refuse to compile if documentation is missing
|
||||||
|
|
@ -58,6 +59,9 @@ extern crate core;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
extern crate num_traits;
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
extern crate collections;
|
extern crate collections;
|
||||||
|
|
||||||
|
|
|
||||||
108
src/subtle.rs
108
src/subtle.rs
|
|
@ -11,8 +11,23 @@
|
||||||
|
|
||||||
//! Constant-time traits and utility functions.
|
//! Constant-time traits and utility functions.
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use core::ops::BitAnd;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use core::ops::BitOr;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use core::ops::Not;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use core::ops::Sub;
|
||||||
|
|
||||||
use core::ops::Neg;
|
use core::ops::Neg;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use num_traits::One;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use num_traits::Signed;
|
||||||
|
|
||||||
|
|
||||||
/// Trait for items which can be conditionally assigned in constant time.
|
/// Trait for items which can be conditionally assigned in constant time.
|
||||||
pub trait CTAssignable {
|
pub trait CTAssignable {
|
||||||
/// If `choice == 1u8`, assign `other` to `self`.
|
/// If `choice == 1u8`, assign `other` to `self`.
|
||||||
|
|
@ -50,11 +65,84 @@ impl<T> CTNegatable for T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Select `a` if `choice == 1` or select `b` if `choice == 0`, in constant time.
|
||||||
|
///
|
||||||
|
/// # Inputs
|
||||||
|
///
|
||||||
|
/// * `a`, `b`, and `choice` must be types for which bitwise-AND, and
|
||||||
|
/// bitwise-OR, bitwise-complement, subtraction, multiplicative identity,
|
||||||
|
/// copying, partial equality, and partial order comparison are defined.
|
||||||
|
/// * `choice`: If `choice` is equal to the multiplicative identity of the type
|
||||||
|
/// (i.e. `1u8` for `u8`, etc.), then `a` is returned. If `choice` is equal
|
||||||
|
/// to the additive identity (i.e. `0u8` for `u8`, etc.) then `b` is returned.
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
///
|
||||||
|
/// The behaviour of this function is undefined if `choice` is something other
|
||||||
|
/// than a multiplicative identity or additive identity (i.e. `1u8` or `0u8`).
|
||||||
|
///
|
||||||
|
/// If you somehow manage to design a type which is not a signed integer, and
|
||||||
|
/// yet implements all the requisite trait bounds for this generic, it's your
|
||||||
|
/// problem if something breaks.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// This function should work for signed integer types:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # extern crate curve25519_dalek;
|
||||||
|
/// # use curve25519_dalek::subtle::conditional_select;
|
||||||
|
/// # fn main() {
|
||||||
|
/// let a: i32 = 5;
|
||||||
|
/// let b: i32 = 13;
|
||||||
|
///
|
||||||
|
/// assert!(conditional_select(a, b, 0) == 13);
|
||||||
|
/// assert!(conditional_select(a, b, 1) == 5);
|
||||||
|
///
|
||||||
|
/// let c: i64 = 2343249123;
|
||||||
|
/// let d: i64 = 8723884895;
|
||||||
|
///
|
||||||
|
/// assert!(conditional_select(c, d, 0) == d);
|
||||||
|
/// assert!(conditional_select(c, d, 1) == c);
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// It does not work with `i128`s, however, because the `num` crate doesn't
|
||||||
|
/// implement `num::traits::Signed` for `i128`.
|
||||||
|
///
|
||||||
|
/// # TODO
|
||||||
|
///
|
||||||
|
/// Once `#[feature(specialization)]` is finished, we should rewrite this. Or
|
||||||
|
/// find some other way to only implement it for types which we know work
|
||||||
|
/// correctly.
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub fn conditional_select<T>(a: T, b: T, choice: T) -> T
|
||||||
|
where T: PartialEq + PartialOrd + Copy +
|
||||||
|
One + Signed + Sub<T, Output = T> + Not<Output = T> +
|
||||||
|
BitAnd<T, Output = T> + BitOr<T, Output = T> {
|
||||||
|
(!(choice - T::one()) & a) | ((choice - T::one()) & b)
|
||||||
|
}
|
||||||
|
|
||||||
/// Check equality of two bytes in constant time.
|
/// Check equality of two bytes in constant time.
|
||||||
///
|
///
|
||||||
/// # Return
|
/// # Return
|
||||||
///
|
///
|
||||||
/// Returns `1u8` if `a == b` and `0u8` otherwise.
|
/// Returns `1u8` if `a == b` and `0u8` otherwise.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # extern crate curve25519_dalek;
|
||||||
|
/// # use curve25519_dalek::subtle::bytes_equal;
|
||||||
|
/// # fn main() {
|
||||||
|
/// let a: u8 = 0xDE;
|
||||||
|
/// let b: u8 = 0xAD;
|
||||||
|
///
|
||||||
|
/// assert_eq!(bytes_equal(a, b), 0);
|
||||||
|
/// assert_eq!(bytes_equal(a, a), 1);
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn bytes_equal(a: u8, b: u8) -> u8 {
|
pub fn bytes_equal(a: u8, b: u8) -> u8 {
|
||||||
let mut x: u8;
|
let mut x: u8;
|
||||||
|
|
@ -163,4 +251,24 @@ mod test {
|
||||||
|
|
||||||
assert!(arrays_equal(&a, &b) == 1);
|
assert!(arrays_equal(&a, &b) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
fn conditional_select_i32() {
|
||||||
|
let a: i32 = 5;
|
||||||
|
let b: i32 = 13;
|
||||||
|
|
||||||
|
assert_eq!(conditional_select(a, b, 0), 13);
|
||||||
|
assert_eq!(conditional_select(a, b, 1), 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
fn conditional_select_i64() {
|
||||||
|
let c: i64 = 2343249123;
|
||||||
|
let d: i64 = 8723884895;
|
||||||
|
|
||||||
|
assert_eq!(conditional_select(c, d, 0), d);
|
||||||
|
assert_eq!(conditional_select(c, d, 1), c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue