Skip to content

Commit 0dfc572

Browse files
committed
Add core_hint_black_box feature that uses core::hint::black_box
This commit partially reverts the changes from 4978f42, and adds the new optimization barrier implementation under a new feature `core_hint_black_box`.
1 parent df58872 commit 0dfc572

File tree

4 files changed

+55
-8
lines changed

4 files changed

+55
-8
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ matrix:
2525
script:
2626
- cargo test && cargo test --no-default-features &&
2727
cargo test --no-default-features --features std &&
28-
cargo test --no-default-features --features "std i128"
28+
cargo test --no-default-features --features "std i128" &&
29+
cargo test --no-default-features --features "std core_hint_black_box" &&
30+
cargo test --no-default-features --features "std i128 core_hint_black_box"
2931

3032
notifications:
3133
slack:

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ travis-ci = { repository = "dalek-cryptography/subtle", branch = "master"}
2828
rand = { version = "0.7" }
2929

3030
[features]
31+
core_hint_black_box = []
3132
default = ["std", "i128"]
3233
std = []
3334
i128 = []

README.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ prevent this refinement, the crate tries to hide the value of a `Choice`'s
2626
inner `u8` by passing it through a volatile read. For more information, see
2727
the _About_ section below.
2828

29+
Rust versions from 1.66 or higher support a new best-effort optimization
30+
barrier ([`core::hint::black_box`]). To use the new optimization barrier,
31+
enable the `core_hint_black_box` feature.
32+
2933
Versions prior to `2.2` recommended use of the `nightly` feature to enable an
3034
optimization barrier; this is not required in versions `2.2` and above.
3135

@@ -40,18 +44,23 @@ Documentation is available [here][docs].
4044

4145
## Minimum Supported Rust Version
4246

43-
Rust **1.66** or higher.
47+
Rust **1.41** or higher.
4448

4549
Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump.
4650

4751
## About
4852

4953
This library aims to be the Rust equivalent of Go’s `crypto/subtle` module.
5054

51-
The optimization barrier in `impl From<u8> for Choice` was based on Tim
52-
Maclean's [work on `rust-timing-shield`][rust-timing-shield], which attempts to
53-
provide a more comprehensive approach for preventing software side-channels in
54-
Rust code.
55+
Old versions of the optimization barrier in `impl From<u8> for Choice` were
56+
based on Tim Maclean's [work on `rust-timing-shield`][rust-timing-shield],
57+
which attempts to provide a more comprehensive approach for preventing
58+
software side-channels in Rust code.
59+
60+
From version `2.2`, it was based on Diane Hosfelt and Amber Sprenkels' work on
61+
"Secret Types in Rust". Version `2.3` adds the `core_hint_black_box` feature,
62+
which uses the original method through the [`core::hint::black_box`] function
63+
from the Rust standard library.
5564

5665
`subtle` is authored by isis agora lovecruft and Henry de Valence.
5766

@@ -66,4 +75,5 @@ effort is fundamentally limited.
6675
**USE AT YOUR OWN RISK**
6776

6877
[docs]: https://docs.rs/subtle
78+
[`core::hint::black_box`]: https://doc.rust-lang.org/core/hint/fn.black_box.html
6979
[rust-timing-shield]: https://www.chosenplaintext.ca/open-source/rust-timing-shield/security

src/lib.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,47 @@ impl Not for Choice {
200200
}
201201
}
202202

203+
/// This function is a best-effort attempt to prevent the compiler from knowing
204+
/// anything about the value of the returned `u8`, other than its type.
205+
///
206+
/// Because we want to support stable Rust, we don't have access to inline
207+
/// assembly or test::black_box, so we use the fact that volatile values will
208+
/// never be elided to register values.
209+
///
210+
/// Note: Rust's notion of "volatile" is subject to change over time. While this
211+
/// code may break in a non-destructive way in the future, “constant-time” code
212+
/// is a continually moving target, and this is better than doing nothing.
213+
#[cfg(not(feature = "core_hint_black_box"))]
214+
#[inline(never)]
215+
fn black_box(input: u8) -> u8 {
216+
debug_assert!((input == 0u8) | (input == 1u8));
217+
218+
unsafe {
219+
// Optimization barrier
220+
//
221+
// Unsafe is ok, because:
222+
// - &input is not NULL;
223+
// - size of input is not zero;
224+
// - u8 is neither Sync, nor Send;
225+
// - u8 is Copy, so input is always live;
226+
// - u8 type is always properly aligned.
227+
core::ptr::read_volatile(&input as *const u8)
228+
}
229+
}
230+
231+
#[cfg(feature = "core_hint_black_box")]
232+
#[inline]
233+
fn black_box(input: u8) -> u8 {
234+
debug_assert!((input == 0u8) | (input == 1u8));
235+
core::hint::black_box(input)
236+
}
237+
203238
impl From<u8> for Choice {
204239
#[inline]
205240
fn from(input: u8) -> Choice {
206-
debug_assert!((input == 0u8) | (input == 1u8));
207241
// Our goal is to prevent the compiler from inferring that the value held inside the
208242
// resulting `Choice` struct is really an `i1` instead of an `i8`.
209-
Choice(core::hint::black_box(input))
243+
Choice(black_box(input))
210244
}
211245
}
212246

0 commit comments

Comments
 (0)