Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ script:
cargo test --no-default-features --features std &&
cargo test --no-default-features --features "std i128" &&
cargo test --no-default-features --features "std core_hint_black_box" &&
cargo test --no-default-features --features "std i128 core_hint_black_box"
cargo test --no-default-features --features "std const-generics" &&
cargo test --no-default-features --features "std i128 core_hint_black_box" &&
cargo test --no-default-features --features "std i128 core_hint_black_box const-generics"

notifications:
slack:
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ travis-ci = { repository = "dalek-cryptography/subtle", branch = "master"}
rand = { version = "0.7" }

[features]
const-generics = []
core_hint_black_box = []
default = ["std", "i128"]
std = []
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ Rust versions from 1.66 or higher support a new best-effort optimization
barrier ([`core::hint::black_box`]). To use the new optimization barrier,
enable the `core_hint_black_box` feature.

Rust versions from 1.51 or higher have const generics support. You may enable
`const-generics` feautre to have `subtle` traits implemented for arrays `[T; N]`.

Versions prior to `2.2` recommended use of the `nightly` feature to enable an
optimization barrier; this is not required in versions `2.2` and above.

Expand Down
6 changes: 5 additions & 1 deletion fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ cargo-fuzz = true

[dependencies.subtle]
path = ".."
features = ["nightly"]
features = ["nightly", "const-generics"]
[dependencies.libfuzzer-sys]
git = "https://github.com/rust-fuzz/libfuzzer-sys.git"

Expand All @@ -33,3 +33,7 @@ path = "fuzzers/conditional_assign_i8.rs"
[[bin]]
name = "conditional_assign_i128"
path = "fuzzers/conditional_assign_i128.rs"

[[bin]]
name = "conditional_assign_array"
path = "fuzzers/conditional_assign_array.rs"
29 changes: 29 additions & 0 deletions fuzz/fuzzers/conditional_assign_array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#![no_main]

#[macro_use]
extern crate libfuzzer_sys;
extern crate subtle;
extern crate core;

use core::convert::TryFrom;

use subtle::ConditionallySelectable;

fuzz_target!(|data: &[u8]| {
let chunk_size: usize = 16;

if data.len() % chunk_size != 0 {
return;
}

for bytes in data.chunks(chunk_size) {
let mut x = [0u8; 16];
let y = <[u8; 16]>::try_from(bytes).unwrap();

x.conditional_assign(&y, 0.into());
assert_eq!(x, [0u8; 16]);

x.conditional_assign(&y, 1.into());
assert_eq!(x, y);
}
});
42 changes: 37 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@
//! inner `u8` by passing it through a volatile read. For more information, see
//! the _About_ section below.
//!
//! Rust versions from 1.66 or higher support a new best-effort optimization
//! barrier ([`core::hint::black_box`]). To use the new optimization barrier,
//! enable the `core_hint_black_box` feature.
//!
//! Rust versions from 1.51 or higher have const generics support. You may enable
//! `const-generics` feautre to have `subtle` traits implemented for arrays `[T; N]`.
//!
//! Versions prior to `2.2` recommended use of the `nightly` feature to enable an
//! optimization barrier; this is not required in versions `2.2` and above.
//!
Expand All @@ -63,10 +70,15 @@
//!
//! This library aims to be the Rust equivalent of Go’s `crypto/subtle` module.
//!
//! The optimization barrier in `impl From<u8> for Choice` was based on Tim
//! Maclean's [work on `rust-timing-shield`][rust-timing-shield], which attempts to
//! provide a more comprehensive approach for preventing software side-channels in
//! Rust code.
//! Old versions of the optimization barrier in `impl From<u8> for Choice` were
//! based on Tim Maclean's [work on `rust-timing-shield`][rust-timing-shield],
//! which attempts to provide a more comprehensive approach for preventing
//! software side-channels in Rust code.
//!
//! From version `2.2`, it was based on Diane Hosfelt and Amber Sprenkels' work on
//! "Secret Types in Rust". Version `2.3` adds the `core_hint_black_box` feature,
//! which uses the original method through the [`core::hint::black_box`] function
//! from the Rust standard library.
//!
//! `subtle` is authored by isis agora lovecruft and Henry de Valence.
//!
Expand All @@ -81,6 +93,7 @@
//! **USE AT YOUR OWN RISK**
//!
//! [docs]: https://docs.rs/subtle
//! [`core::hint::black_box`]: https://doc.rust-lang.org/core/hint/fn.black_box.html
//! [rust-timing-shield]: https://www.chosenplaintext.ca/open-source/rust-timing-shield/security

#[cfg(feature = "std")]
Expand Down Expand Up @@ -539,6 +552,25 @@ impl ConditionallySelectable for Choice {
}
}

#[cfg(feature = "const-generics")]
impl<T, const N: usize> ConditionallySelectable for [T; N]
where
T: ConditionallySelectable,
{
#[inline]
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
let mut output = *a;
output.conditional_assign(b, choice);
output
}

fn conditional_assign(&mut self, other: &Self, choice: Choice) {
for (a_i, b_i) in self.iter_mut().zip(other) {
a_i.conditional_assign(b_i, choice)
}
}
}

/// A type which can be conditionally negated in constant time.
///
/// # Note
Expand Down Expand Up @@ -837,7 +869,7 @@ macro_rules! generate_unsigned_integer_greater {
Choice::from((bit & 1) as u8)
}
}
}
};
}

generate_unsigned_integer_greater!(u8, 8);
Expand Down