9
9
// - Henry de Valence <hdevalence@hdevalence.ca>
10
10
11
11
#![ no_std]
12
- #![ cfg_attr( feature = "nightly" , feature( asm) ) ]
13
12
#![ cfg_attr( feature = "nightly" , feature( external_doc) ) ]
14
13
#![ cfg_attr( feature = "nightly" , doc( include = "../README.md" ) ) ]
15
14
#![ cfg_attr( feature = "nightly" , deny( missing_docs) ) ]
16
15
#![ doc( html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png" ) ]
16
+ #![ doc( html_root_url = "https://docs.rs/subtle/2.2.3" ) ]
17
17
18
18
//! Note that docs will only build on nightly Rust until
19
19
//! [RFC 1990 stabilizes](https://github.com/rust-lang/rust/issues/44732).
@@ -24,25 +24,23 @@ extern crate std;
24
24
25
25
use core:: ops:: { BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Neg , Not } ;
26
26
27
- /// The `Choice` struct represents a choice for use in conditional
28
- /// assignment.
29
- ///
30
- /// It is a wrapper around a `u8`, which should have the value either
31
- /// `1` (true) or `0` (false).
32
- ///
33
- /// With the `nightly` feature enabled, the conversion from `u8` to
34
- /// `Choice` passes the value through an optimization barrier, as a
35
- /// best-effort attempt to prevent the compiler from inferring that the
36
- /// `Choice` value is a boolean. This strategy is based on Tim
37
- /// Maclean's [work on `rust-timing-shield`][rust-timing-shield],
38
- /// which attempts to provide a more comprehensive approach for
39
- /// preventing software side-channels in Rust code.
40
- ///
41
- /// The `Choice` struct implements operators for AND, OR, XOR, and
42
- /// NOT, to allow combining `Choice` values.
43
- /// These operations do not short-circuit.
44
- ///
45
- /// [rust-timing-shield]: https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
27
+ /// The `Choice` struct represents a choice for use in conditional assignment.
28
+ ///
29
+ /// It is a wrapper around a `u8`, which should have the value either `1` (true)
30
+ /// or `0` (false).
31
+ ///
32
+ /// The conversion from `u8` to `Choice` passes the value through an optimization
33
+ /// barrier, as a best-effort attempt to prevent the compiler from inferring that
34
+ /// the `Choice` value is a boolean. This strategy is based on Tim Maclean's
35
+ /// [work on `rust-timing-shield`][rust-timing-shield], which attempts to provide
36
+ /// a more comprehensive approach for preventing software side-channels in Rust
37
+ /// code.
38
+ ///
39
+ /// The `Choice` struct implements operators for AND, OR, XOR, and NOT, to allow
40
+ /// combining `Choice` values. These operations do not short-circuit.
41
+ ///
42
+ /// [rust-timing-shield]:
43
+ /// https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
46
44
#[ derive( Copy , Clone , Debug ) ]
47
45
pub struct Choice ( u8 ) ;
48
46
@@ -51,11 +49,11 @@ impl Choice {
51
49
///
52
50
/// # Note
53
51
///
54
- /// This function only exists as an escape hatch for the rare case
52
+ /// This function only exists as an ** escape hatch** for the rare case
55
53
/// where it's not possible to use one of the `subtle`-provided
56
54
/// trait impls.
57
55
///
58
- /// To convert a `Choice` to a `bool`, use the `From` implementation instead.
56
+ /// ** To convert a `Choice` to a `bool`, use the `From` implementation instead.**
59
57
#[ inline]
60
58
pub fn unwrap_u8 ( & self ) -> u8 {
61
59
self . 0
@@ -136,30 +134,19 @@ impl Not for Choice {
136
134
}
137
135
}
138
136
139
- /// This function is a best-effort attempt to prevent the compiler
140
- /// from knowing anything about the value of the returned `u8`, other
141
- /// than its type.
142
- ///
143
- /// Uses inline asm when available, otherwise it's a no-op.
144
- #[ cfg( all( feature = "nightly" , not( any( target_arch = "asmjs" , target_arch = "wasm32" ) ) ) ) ]
145
- #[ inline( always) ]
146
- fn black_box ( mut input : u8 ) -> u8 {
147
- debug_assert ! ( ( input == 0u8 ) | ( input == 1u8 ) ) ;
148
-
149
- // Move value through assembler, which is opaque to the compiler, even though we don't do anything.
150
- unsafe { asm ! ( "" : "=r" ( input) : "0" ( input) ) }
151
-
152
- input
153
- }
154
- #[ cfg( any( target_arch = "asmjs" , target_arch = "wasm32" , not( feature = "nightly" ) ) ) ]
137
+ /// This function is a best-effort attempt to prevent the compiler from knowing
138
+ /// anything about the value of the returned `u8`, other than its type.
139
+ ///
140
+ /// Because we want to support stable Rust, we don't have access to inline
141
+ /// assembly or test::black_box, so we use the fact that volatile values will
142
+ /// never be elided to register values.
143
+ ///
144
+ /// Note: Rust's notion of "volatile" is subject to change over time. While this
145
+ /// code may break in a non-destructive way in the future, “constant-time” code
146
+ /// is a continually moving target, and this is better than doing nothing.
155
147
#[ inline( never) ]
156
148
fn black_box ( input : u8 ) -> u8 {
157
149
debug_assert ! ( ( input == 0u8 ) | ( input == 1u8 ) ) ;
158
- // We don't have access to inline assembly or test::black_box, so we use the fact that
159
- // volatile values will never be elided to register values.
160
- //
161
- // Note: Rust's notion of "volatile" is subject to change over time. While this code may break
162
- // in a non-destructive way in the future, it is better than doing nothing.
163
150
164
151
unsafe {
165
152
// Optimization barrier
0 commit comments