11
11
#![ no_std]
12
12
#![ deny( missing_docs) ]
13
13
#![ doc( html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png" ) ]
14
- #![ doc( html_root_url = "https://docs.rs/subtle/2.5 .0" ) ]
14
+ #![ doc( html_root_url = "https://docs.rs/subtle/2.6 .0" ) ]
15
15
16
16
//! # subtle [](https://crates.io/crates/subtle) [](https://doc.dalek.rs/subtle) [](https://travis-ci.org/dalek-cryptography/subtle)
17
17
//!
22
22
//! type is a wrapper around a `u8` that holds a `0` or `1`.
23
23
//!
24
24
//! ```toml
25
- //! subtle = "2.5 "
25
+ //! subtle = "2.6 "
26
26
//! ```
27
27
//!
28
28
//! This crate represents a “best-effort” attempt, since side-channels
41
41
//! inner `u8` by passing it through a volatile read. For more information, see
42
42
//! the _About_ section below.
43
43
//!
44
- //! Rust versions from 1.66 or higher support a new best-effort optimization
45
- //! barrier ([`core::hint::black_box`]). To use the new optimization barrier,
46
- //! enable the `core_hint_black_box` feature.
47
- //!
48
44
//! Rust versions from 1.51 or higher have const generics support. You may enable
49
45
//! `const-generics` feautre to have `subtle` traits implemented for arrays `[T; N]`.
50
46
//!
74
70
//! based on Tim Maclean's [work on `rust-timing-shield`][rust-timing-shield],
75
71
//! which attempts to provide a more comprehensive approach for preventing
76
72
//! software side-channels in Rust code.
77
- //!
78
73
//! From version `2.2`, it was based on Diane Hosfelt and Amber Sprenkels' work on
79
- //! "Secret Types in Rust". Version `2.5` adds the `core_hint_black_box` feature,
80
- //! which uses the original method through the [`core::hint::black_box`] function
81
- //! from the Rust standard library.
74
+ //! "Secret Types in Rust".
82
75
//!
83
76
//! `subtle` is authored by isis agora lovecruft and Henry de Valence.
84
77
//!
93
86
//! **USE AT YOUR OWN RISK**
94
87
//!
95
88
//! [docs]: https://docs.rs/subtle
96
- //! [`core::hint::black_box`]: https://doc.rust-lang.org/core/hint/fn.black_box.html
97
89
//! [rust-timing-shield]: https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
98
90
99
91
#[ cfg( feature = "std" ) ]
@@ -104,6 +96,9 @@ use core::cmp;
104
96
use core:: ops:: { BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Neg , Not } ;
105
97
use core:: option:: Option ;
106
98
99
+ #[ cfg( feature = "core_hint_black_box" ) ]
100
+ use core:: hint:: black_box;
101
+
107
102
/// The `Choice` struct represents a choice for use in conditional assignment.
108
103
///
109
104
/// It is a wrapper around a `u8`, which should have the value either `1` (true)
@@ -224,36 +219,26 @@ impl Not for Choice {
224
219
/// Note: Rust's notion of "volatile" is subject to change over time. While this
225
220
/// code may break in a non-destructive way in the future, “constant-time” code
226
221
/// is a continually moving target, and this is better than doing nothing.
227
- #[ cfg( not( feature = "core_hint_black_box" ) ) ]
228
222
#[ inline( never) ]
229
- fn black_box ( input : u8 ) -> u8 {
230
- debug_assert ! ( ( input == 0u8 ) | ( input == 1u8 ) ) ;
231
-
223
+ fn black_box < T : Copy > ( input : T ) -> T {
232
224
unsafe {
233
225
// Optimization barrier
234
226
//
235
- // Unsafe is ok, because:
236
- // - &input is not NULL;
237
- // - size of input is not zero;
238
- // - u8 is neither Sync, nor Send;
239
- // - u8 is Copy, so input is always live;
240
- // - u8 type is always properly aligned.
241
- core:: ptr:: read_volatile ( & input as * const u8 )
227
+ // SAFETY:
228
+ // - &input is not NULL because we own input;
229
+ // - input is Copy and always live;
230
+ // - input is always properly aligned.
231
+ core:: ptr:: read_volatile ( & input)
242
232
}
243
233
}
244
234
245
- #[ cfg( feature = "core_hint_black_box" ) ]
246
- #[ inline( never) ]
247
- fn black_box ( input : u8 ) -> u8 {
248
- debug_assert ! ( ( input == 0u8 ) | ( input == 1u8 ) ) ;
249
- core:: hint:: black_box ( input)
250
- }
251
-
252
235
impl From < u8 > for Choice {
253
236
#[ inline]
254
237
fn from ( input : u8 ) -> Choice {
238
+ debug_assert ! ( ( input == 0u8 ) | ( input == 1u8 ) ) ;
239
+
255
240
// Our goal is to prevent the compiler from inferring that the value held inside the
256
- // resulting `Choice` struct is really an `i1 ` instead of an `i8 `.
241
+ // resulting `Choice` struct is really a `bool ` instead of a `u8 `.
257
242
Choice ( black_box ( input) )
258
243
}
259
244
}
@@ -270,6 +255,9 @@ impl From<u8> for Choice {
270
255
/// assert_eq!(x.ct_eq(&y).unwrap_u8(), 0);
271
256
/// assert_eq!(x.ct_eq(&x).unwrap_u8(), 1);
272
257
/// ```
258
+ //
259
+ // #[inline] is specified on these function prototypes to signify that they
260
+ #[ allow( unused_attributes) ] // should be in the actual implementation
273
261
pub trait ConstantTimeEq {
274
262
/// Determine if two items are equal.
275
263
///
@@ -280,6 +268,7 @@ pub trait ConstantTimeEq {
280
268
/// * `Choice(1u8)` if `self == other`;
281
269
/// * `Choice(0u8)` if `self != other`.
282
270
#[ inline]
271
+ #[ allow( unused_attributes) ]
283
272
fn ct_eq ( & self , other : & Self ) -> Choice ;
284
273
285
274
/// Determine if two items are NOT equal.
@@ -397,6 +386,9 @@ impl ConstantTimeEq for cmp::Ordering {
397
386
///
398
387
/// This trait also provides generic implementations of conditional
399
388
/// assignment and conditional swaps.
389
+ //
390
+ // #[inline] is specified on these function prototypes to signify that they
391
+ #[ allow( unused_attributes) ] // should be in the actual implementation
400
392
pub trait ConditionallySelectable : Copy {
401
393
/// Select `a` or `b` according to `choice`.
402
394
///
@@ -423,6 +415,7 @@ pub trait ConditionallySelectable: Copy {
423
415
/// # }
424
416
/// ```
425
417
#[ inline]
418
+ #[ allow( unused_attributes) ]
426
419
fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self ;
427
420
428
421
/// Conditionally assign `other` to `self`, according to `choice`.
@@ -604,12 +597,16 @@ where
604
597
/// A generic implementation of `ConditionallyNegatable` is provided
605
598
/// for types `T` which are `ConditionallySelectable` and have `Neg`
606
599
/// implemented on `&T`.
600
+ //
601
+ // #[inline] is specified on these function prototypes to signify that they
602
+ #[ allow( unused_attributes) ] // should be in the actual implementation
607
603
pub trait ConditionallyNegatable {
608
604
/// Negate `self` if `choice == Choice(1)`; otherwise, leave it
609
605
/// unchanged.
610
606
///
611
607
/// This function should execute in constant time.
612
608
#[ inline]
609
+ #[ allow( unused_attributes) ]
613
610
fn conditional_negate ( & mut self , choice : Choice ) ;
614
611
}
615
612
@@ -801,6 +798,22 @@ impl<T> CtOption<T> {
801
798
802
799
Self :: conditional_select ( & self , & f, is_none)
803
800
}
801
+
802
+ /// Convert the `CtOption<T>` wrapper into an `Option<T>`, depending on whether
803
+ /// the underlying `is_some` `Choice` was a `0` or a `1` once unwrapped.
804
+ ///
805
+ /// # Note
806
+ ///
807
+ /// This function exists to avoid ending up with ugly, verbose and/or bad handled
808
+ /// conversions from the `CtOption<T>` wraps to an `Option<T>` or `Result<T, E>`.
809
+ /// This implementation doesn't intend to be constant-time nor try to protect the
810
+ /// leakage of the `T` since the `Option<T>` will do it anyways.
811
+ ///
812
+ /// It's equivalent to the corresponding `From` impl, however this version is
813
+ /// friendlier for type inference.
814
+ pub fn into_option ( self ) -> Option < T > {
815
+ self . into ( )
816
+ }
804
817
}
805
818
806
819
impl < T : ConditionallySelectable > ConditionallySelectable for CtOption < T > {
@@ -974,3 +987,21 @@ impl ConstantTimeLess for cmp::Ordering {
974
987
( a as u8 ) . ct_lt ( & ( b as u8 ) )
975
988
}
976
989
}
990
+
991
+ /// Wrapper type which implements an optimization barrier for all accesses.
992
+ #[ derive( Clone , Copy , Debug ) ]
993
+ pub struct BlackBox < T : Copy > ( T ) ;
994
+
995
+ impl < T : Copy > BlackBox < T > {
996
+ /// Constructs a new instance of `BlackBox` which will wrap the specified value.
997
+ ///
998
+ /// All access to the inner value will be mediated by a `black_box` optimization barrier.
999
+ pub const fn new ( value : T ) -> Self {
1000
+ Self ( value)
1001
+ }
1002
+
1003
+ /// Read the inner value, applying an optimization barrier on access.
1004
+ pub fn get ( self ) -> T {
1005
+ black_box ( self . 0 )
1006
+ }
1007
+ }
0 commit comments