13
13
#![ cfg_attr( feature = "nightly" , doc( include = "../README.md" ) ) ]
14
14
#![ cfg_attr( feature = "nightly" , deny( missing_docs) ) ]
15
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 " ) ]
16
+ #![ doc( html_root_url = "https://docs.rs/subtle/2.3.0 " ) ]
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).
23
23
extern crate std;
24
24
25
25
use core:: ops:: { BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Neg , Not } ;
26
+ use core:: option:: Option ;
26
27
27
28
/// The `Choice` struct represents a choice for use in conditional assignment.
28
- ///
29
+ ///
29
30
/// It is a wrapper around a `u8`, which should have the value either `1` (true)
30
31
/// or `0` (false).
31
- ///
32
+ ///
32
33
/// The conversion from `u8` to `Choice` passes the value through an optimization
33
34
/// barrier, as a best-effort attempt to prevent the compiler from inferring that
34
35
/// the `Choice` value is a boolean. This strategy is based on Tim Maclean's
35
36
/// [work on `rust-timing-shield`][rust-timing-shield], which attempts to provide
36
37
/// a more comprehensive approach for preventing software side-channels in Rust
37
38
/// code.
38
- ///
39
+ ///
39
40
/// The `Choice` struct implements operators for AND, OR, XOR, and NOT, to allow
40
41
/// combining `Choice` values. These operations do not short-circuit.
41
- ///
42
+ ///
42
43
/// [rust-timing-shield]:
43
44
/// https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
44
45
#[ derive( Copy , Clone , Debug ) ]
@@ -136,11 +137,11 @@ impl Not for Choice {
136
137
137
138
/// This function is a best-effort attempt to prevent the compiler from knowing
138
139
/// anything about the value of the returned `u8`, other than its type.
139
- ///
140
+ ///
140
141
/// Because we want to support stable Rust, we don't have access to inline
141
142
/// assembly or test::black_box, so we use the fact that volatile values will
142
143
/// never be elided to register values.
143
- ///
144
+ ///
144
145
/// Note: Rust's notion of "volatile" is subject to change over time. While this
145
146
/// code may break in a non-destructive way in the future, “constant-time” code
146
147
/// is a continually moving target, and this is better than doing nothing.
@@ -240,6 +241,13 @@ impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
240
241
}
241
242
}
242
243
244
+ impl ConstantTimeEq for Choice {
245
+ #[ inline]
246
+ fn ct_eq ( & self , rhs : & Choice ) -> Choice {
247
+ !( * self ^ * rhs)
248
+ }
249
+ }
250
+
243
251
/// Given the bit-width `$bit_width` and the corresponding primitive
244
252
/// unsigned and signed types `$t_u` and `$t_i` respectively, generate
245
253
/// an `ConstantTimeEq` implementation.
@@ -499,6 +507,25 @@ pub struct CtOption<T> {
499
507
is_some : Choice ,
500
508
}
501
509
510
+ impl < T > From < CtOption < T > > for Option < T > {
511
+ /// Convert the `CtOption<T>` wrapper into an `Option<T>`, depending on whether
512
+ /// the underlying `is_some` `Choice` was a `0` or a `1` once unwrapped.
513
+ ///
514
+ /// # Note
515
+ ///
516
+ /// This function exists to avoid ending up with ugly, verbose and/or bad handled
517
+ /// conversions from the `CtOption<T>` wraps to an `Option<T>` or `Result<T, E>`.
518
+ /// This implementation doesn't intend to be constant-time nor try to protect the
519
+ /// leakage of the `T` since the `Option<T>` will do it anyways.
520
+ fn from ( source : CtOption < T > ) -> Option < T > {
521
+ if source. is_some ( ) . unwrap_u8 ( ) == 1u8 {
522
+ Option :: Some ( source. value )
523
+ } else {
524
+ None
525
+ }
526
+ }
527
+ }
528
+
502
529
impl < T > CtOption < T > {
503
530
/// This method is used to construct a new `CtOption<T>` and takes
504
531
/// a value of type `T`, and a `Choice` that determines whether
@@ -507,7 +534,10 @@ impl<T> CtOption<T> {
507
534
/// exposed.
508
535
#[ inline]
509
536
pub fn new ( value : T , is_some : Choice ) -> CtOption < T > {
510
- CtOption { value : value, is_some : is_some }
537
+ CtOption {
538
+ value : value,
539
+ is_some : is_some,
540
+ }
511
541
}
512
542
513
543
/// This returns the underlying value but panics if it
0 commit comments