Coverage Report

Created: 2025-05-07 06:59

/rust/registry/src/index.crates.io-6f17d22bba15001f/subtle-2.6.1/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
// -*- mode: rust; -*-
2
//
3
// This file is part of subtle, part of the dalek cryptography project.
4
// Copyright (c) 2016-2018 isis lovecruft, Henry de Valence
5
// See LICENSE for licensing information.
6
//
7
// Authors:
8
// - isis agora lovecruft <isis@patternsinthevoid.net>
9
// - Henry de Valence <hdevalence@hdevalence.ca>
10
11
#![no_std]
12
#![deny(missing_docs)]
13
#![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")]
14
#![doc(html_root_url = "https://docs.rs/subtle/2.6.0")]
15
16
//! # subtle [![](https://img.shields.io/crates/v/subtle.svg)](https://crates.io/crates/subtle) [![](https://img.shields.io/badge/dynamic/json.svg?label=docs&uri=https%3A%2F%2Fcrates.io%2Fapi%2Fv1%2Fcrates%2Fsubtle%2Fversions&query=%24.versions%5B0%5D.num&colorB=4F74A6)](https://doc.dalek.rs/subtle) [![](https://travis-ci.org/dalek-cryptography/subtle.svg?branch=master)](https://travis-ci.org/dalek-cryptography/subtle)
17
//!
18
//! **Pure-Rust traits and utilities for constant-time cryptographic implementations.**
19
//!
20
//! It consists of a `Choice` type, and a collection of traits using `Choice`
21
//! instead of `bool` which are intended to execute in constant-time.  The `Choice`
22
//! type is a wrapper around a `u8` that holds a `0` or `1`.
23
//!
24
//! ```toml
25
//! subtle = "2.6"
26
//! ```
27
//!
28
//! This crate represents a “best-effort” attempt, since side-channels
29
//! are ultimately a property of a deployed cryptographic system
30
//! including the hardware it runs on, not just of software.
31
//!
32
//! The traits are implemented using bitwise operations, and should execute in
33
//! constant time provided that a) the bitwise operations are constant-time and
34
//! b) the bitwise operations are not recognized as a conditional assignment and
35
//! optimized back into a branch.
36
//!
37
//! For a compiler to recognize that bitwise operations represent a conditional
38
//! assignment, it needs to know that the value used to generate the bitmasks is
39
//! really a boolean `i1` rather than an `i8` byte value. In an attempt to
40
//! prevent this refinement, the crate tries to hide the value of a `Choice`'s
41
//! inner `u8` by passing it through a volatile read. For more information, see
42
//! the _About_ section below.
43
//!
44
//! Rust versions from 1.51 or higher have const generics support. You may enable
45
//! `const-generics` feautre to have `subtle` traits implemented for arrays `[T; N]`.
46
//!
47
//! Versions prior to `2.2` recommended use of the `nightly` feature to enable an
48
//! optimization barrier; this is not required in versions `2.2` and above.
49
//!
50
//! Note: the `subtle` crate contains `debug_assert`s to check invariants during
51
//! debug builds. These invariant checks involve secret-dependent branches, and
52
//! are not present when compiled in release mode. This crate is intended to be
53
//! used in release mode.
54
//!
55
//! ## Documentation
56
//!
57
//! Documentation is available [here][docs].
58
//!
59
//! ## Minimum Supported Rust Version
60
//!
61
//! Rust **1.41** or higher.
62
//!
63
//! Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump.
64
//!
65
//! ## About
66
//!
67
//! This library aims to be the Rust equivalent of Go’s `crypto/subtle` module.
68
//!
69
//! Old versions of the optimization barrier in `impl From<u8> for Choice` were
70
//! based on Tim Maclean's [work on `rust-timing-shield`][rust-timing-shield],
71
//! which attempts to provide a more comprehensive approach for preventing
72
//! software side-channels in Rust code.
73
//! From version `2.2`, it was based on Diane Hosfelt and Amber Sprenkels' work on
74
//! "Secret Types in Rust".
75
//!
76
//! `subtle` is authored by isis agora lovecruft and Henry de Valence.
77
//!
78
//! ## Warning
79
//!
80
//! This code is a low-level library, intended for specific use-cases implementing
81
//! cryptographic protocols.  It represents a best-effort attempt to protect
82
//! against some software side-channels.  Because side-channel resistance is not a
83
//! property of software alone, but of software together with hardware, any such
84
//! effort is fundamentally limited.
85
//!
86
//! **USE AT YOUR OWN RISK**
87
//!
88
//! [docs]: https://docs.rs/subtle
89
//! [rust-timing-shield]: https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
90
91
#[cfg(feature = "std")]
92
#[macro_use]
93
extern crate std;
94
95
use core::cmp;
96
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Neg, Not};
97
use core::option::Option;
98
99
#[cfg(feature = "core_hint_black_box")]
100
use core::hint::black_box;
101
102
/// The `Choice` struct represents a choice for use in conditional assignment.
103
///
104
/// It is a wrapper around a `u8`, which should have the value either `1` (true)
105
/// or `0` (false).
106
///
107
/// The conversion from `u8` to `Choice` passes the value through an optimization
108
/// barrier, as a best-effort attempt to prevent the compiler from inferring that
109
/// the `Choice` value is a boolean. This strategy is based on Tim Maclean's
110
/// [work on `rust-timing-shield`][rust-timing-shield], which attempts to provide
111
/// a more comprehensive approach for preventing software side-channels in Rust
112
/// code.
113
///
114
/// The `Choice` struct implements operators for AND, OR, XOR, and NOT, to allow
115
/// combining `Choice` values. These operations do not short-circuit.
116
///
117
/// [rust-timing-shield]:
118
/// https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
119
#[derive(Copy, Clone, Debug)]
120
pub struct Choice(u8);
121
122
impl Choice {
123
    /// Unwrap the `Choice` wrapper to reveal the underlying `u8`.
124
    ///
125
    /// # Note
126
    ///
127
    /// This function only exists as an **escape hatch** for the rare case
128
    /// where it's not possible to use one of the `subtle`-provided
129
    /// trait impls.
130
    ///
131
    /// **To convert a `Choice` to a `bool`, use the `From` implementation instead.**
132
    #[inline]
133
0
    pub fn unwrap_u8(&self) -> u8 {
134
0
        self.0
135
0
    }
136
}
137
138
impl From<Choice> for bool {
139
    /// Convert the `Choice` wrapper into a `bool`, depending on whether
140
    /// the underlying `u8` was a `0` or a `1`.
141
    ///
142
    /// # Note
143
    ///
144
    /// This function exists to avoid having higher-level cryptographic protocol
145
    /// implementations duplicating this pattern.
146
    ///
147
    /// The intended use case for this conversion is at the _end_ of a
148
    /// higher-level primitive implementation: for example, in checking a keyed
149
    /// MAC, where the verification should happen in constant-time (and thus use
150
    /// a `Choice`) but it is safe to return a `bool` at the end of the
151
    /// verification.
152
    #[inline]
153
0
    fn from(source: Choice) -> bool {
154
0
        debug_assert!((source.0 == 0u8) | (source.0 == 1u8));
155
0
        source.0 != 0
156
0
    }
157
}
158
159
impl BitAnd for Choice {
160
    type Output = Choice;
161
    #[inline]
162
    fn bitand(self, rhs: Choice) -> Choice {
163
        (self.0 & rhs.0).into()
164
    }
165
}
166
167
impl BitAndAssign for Choice {
168
    #[inline]
169
    fn bitand_assign(&mut self, rhs: Choice) {
170
        *self = *self & rhs;
171
    }
172
}
173
174
impl BitOr for Choice {
175
    type Output = Choice;
176
    #[inline]
177
    fn bitor(self, rhs: Choice) -> Choice {
178
        (self.0 | rhs.0).into()
179
    }
180
}
181
182
impl BitOrAssign for Choice {
183
    #[inline]
184
    fn bitor_assign(&mut self, rhs: Choice) {
185
        *self = *self | rhs;
186
    }
187
}
188
189
impl BitXor for Choice {
190
    type Output = Choice;
191
    #[inline]
192
    fn bitxor(self, rhs: Choice) -> Choice {
193
        (self.0 ^ rhs.0).into()
194
    }
195
}
196
197
impl BitXorAssign for Choice {
198
    #[inline]
199
    fn bitxor_assign(&mut self, rhs: Choice) {
200
        *self = *self ^ rhs;
201
    }
202
}
203
204
impl Not for Choice {
205
    type Output = Choice;
206
    #[inline]
207
0
    fn not(self) -> Choice {
208
0
        (1u8 & (!self.0)).into()
209
0
    }
210
}
211
212
/// This function is a best-effort attempt to prevent the compiler from knowing
213
/// anything about the value of the returned `u8`, other than its type.
214
///
215
/// Because we want to support stable Rust, we don't have access to inline
216
/// assembly or test::black_box, so we use the fact that volatile values will
217
/// never be elided to register values.
218
///
219
/// Note: Rust's notion of "volatile" is subject to change over time. While this
220
/// code may break in a non-destructive way in the future, “constant-time” code
221
/// is a continually moving target, and this is better than doing nothing.
222
#[cfg(not(feature = "core_hint_black_box"))]
223
#[inline(never)]
224
0
fn black_box<T: Copy>(input: T) -> T {
225
0
    unsafe {
226
0
        // Optimization barrier
227
0
        //
228
0
        // SAFETY:
229
0
        //   - &input is not NULL because we own input;
230
0
        //   - input is Copy and always live;
231
0
        //   - input is always properly aligned.
232
0
        core::ptr::read_volatile(&input)
233
0
    }
234
0
}
235
236
impl From<u8> for Choice {
237
    #[inline]
238
0
    fn from(input: u8) -> Choice {
239
0
        debug_assert!((input == 0u8) | (input == 1u8));
240
241
        // Our goal is to prevent the compiler from inferring that the value held inside the
242
        // resulting `Choice` struct is really a `bool` instead of a `u8`.
243
0
        Choice(black_box(input))
244
0
    }
245
}
246
247
/// An `Eq`-like trait that produces a `Choice` instead of a `bool`.
248
///
249
/// # Example
250
///
251
/// ```
252
/// use subtle::ConstantTimeEq;
253
/// let x: u8 = 5;
254
/// let y: u8 = 13;
255
///
256
/// assert_eq!(x.ct_eq(&y).unwrap_u8(), 0);
257
/// assert_eq!(x.ct_eq(&x).unwrap_u8(), 1);
258
/// ```
259
//
260
// #[inline] is specified on these function prototypes to signify that they
261
#[allow(unused_attributes)] // should be in the actual implementation
262
pub trait ConstantTimeEq {
263
    /// Determine if two items are equal.
264
    ///
265
    /// The `ct_eq` function should execute in constant time.
266
    ///
267
    /// # Returns
268
    ///
269
    /// * `Choice(1u8)` if `self == other`;
270
    /// * `Choice(0u8)` if `self != other`.
271
    #[inline]
272
    #[allow(unused_attributes)]
273
    fn ct_eq(&self, other: &Self) -> Choice;
274
275
    /// Determine if two items are NOT equal.
276
    ///
277
    /// The `ct_ne` function should execute in constant time.
278
    ///
279
    /// # Returns
280
    ///
281
    /// * `Choice(0u8)` if `self == other`;
282
    /// * `Choice(1u8)` if `self != other`.
283
    #[inline]
284
0
    fn ct_ne(&self, other: &Self) -> Choice {
285
0
        !self.ct_eq(other)
286
0
    }
287
}
288
289
impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
290
    /// Check whether two slices of `ConstantTimeEq` types are equal.
291
    ///
292
    /// # Note
293
    ///
294
    /// This function short-circuits if the lengths of the input slices
295
    /// are different.  Otherwise, it should execute in time independent
296
    /// of the slice contents.
297
    ///
298
    /// Since arrays coerce to slices, this function works with fixed-size arrays:
299
    ///
300
    /// ```
301
    /// # use subtle::ConstantTimeEq;
302
    /// #
303
    /// let a: [u8; 8] = [0,1,2,3,4,5,6,7];
304
    /// let b: [u8; 8] = [0,1,2,3,0,1,2,3];
305
    ///
306
    /// let a_eq_a = a.ct_eq(&a);
307
    /// let a_eq_b = a.ct_eq(&b);
308
    ///
309
    /// assert_eq!(a_eq_a.unwrap_u8(), 1);
310
    /// assert_eq!(a_eq_b.unwrap_u8(), 0);
311
    /// ```
312
    #[inline]
313
0
    fn ct_eq(&self, _rhs: &[T]) -> Choice {
314
0
        let len = self.len();
315
0
316
0
        // Short-circuit on the *lengths* of the slices, not their
317
0
        // contents.
318
0
        if len != _rhs.len() {
319
0
            return Choice::from(0);
320
0
        }
321
0
322
0
        // This loop shouldn't be shortcircuitable, since the compiler
323
0
        // shouldn't be able to reason about the value of the `u8`
324
0
        // unwrapped from the `ct_eq` result.
325
0
        let mut x = 1u8;
326
0
        for (ai, bi) in self.iter().zip(_rhs.iter()) {
327
0
            x &= ai.ct_eq(bi).unwrap_u8();
328
0
        }
329
330
0
        x.into()
331
0
    }
332
}
333
334
impl ConstantTimeEq for Choice {
335
    #[inline]
336
    fn ct_eq(&self, rhs: &Choice) -> Choice {
337
        !(*self ^ *rhs)
338
    }
339
}
340
341
/// Given the bit-width `$bit_width` and the corresponding primitive
342
/// unsigned and signed types `$t_u` and `$t_i` respectively, generate
343
/// an `ConstantTimeEq` implementation.
344
macro_rules! generate_integer_equal {
345
    ($t_u:ty, $t_i:ty, $bit_width:expr) => {
346
        impl ConstantTimeEq for $t_u {
347
            #[inline]
348
0
            fn ct_eq(&self, other: &$t_u) -> Choice {
349
0
                // x == 0 if and only if self == other
350
0
                let x: $t_u = self ^ other;
351
0
352
0
                // If x == 0, then x and -x are both equal to zero;
353
0
                // otherwise, one or both will have its high bit set.
354
0
                let y: $t_u = (x | x.wrapping_neg()) >> ($bit_width - 1);
355
0
356
0
                // Result is the opposite of the high bit (now shifted to low).
357
0
                ((y ^ (1 as $t_u)) as u8).into()
358
0
            }
359
        }
360
        impl ConstantTimeEq for $t_i {
361
            #[inline]
362
            fn ct_eq(&self, other: &$t_i) -> Choice {
363
                // Bitcast to unsigned and call that implementation.
364
                (*self as $t_u).ct_eq(&(*other as $t_u))
365
            }
366
        }
367
    };
368
}
369
370
generate_integer_equal!(u8, i8, 8);
371
generate_integer_equal!(u16, i16, 16);
372
generate_integer_equal!(u32, i32, 32);
373
generate_integer_equal!(u64, i64, 64);
374
#[cfg(feature = "i128")]
375
generate_integer_equal!(u128, i128, 128);
376
generate_integer_equal!(usize, isize, ::core::mem::size_of::<usize>() * 8);
377
378
/// `Ordering` is `#[repr(i8)]` making it possible to leverage `i8::ct_eq`.
379
impl ConstantTimeEq for cmp::Ordering {
380
    #[inline]
381
    fn ct_eq(&self, other: &Self) -> Choice {
382
        (*self as i8).ct_eq(&(*other as i8))
383
    }
384
}
385
386
/// A type which can be conditionally selected in constant time.
387
///
388
/// This trait also provides generic implementations of conditional
389
/// assignment and conditional swaps.
390
//
391
// #[inline] is specified on these function prototypes to signify that they
392
#[allow(unused_attributes)] // should be in the actual implementation
393
pub trait ConditionallySelectable: Copy {
394
    /// Select `a` or `b` according to `choice`.
395
    ///
396
    /// # Returns
397
    ///
398
    /// * `a` if `choice == Choice(0)`;
399
    /// * `b` if `choice == Choice(1)`.
400
    ///
401
    /// This function should execute in constant time.
402
    ///
403
    /// # Example
404
    ///
405
    /// ```
406
    /// use subtle::ConditionallySelectable;
407
    /// #
408
    /// # fn main() {
409
    /// let x: u8 = 13;
410
    /// let y: u8 = 42;
411
    ///
412
    /// let z = u8::conditional_select(&x, &y, 0.into());
413
    /// assert_eq!(z, x);
414
    /// let z = u8::conditional_select(&x, &y, 1.into());
415
    /// assert_eq!(z, y);
416
    /// # }
417
    /// ```
418
    #[inline]
419
    #[allow(unused_attributes)]
420
    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self;
421
422
    /// Conditionally assign `other` to `self`, according to `choice`.
423
    ///
424
    /// This function should execute in constant time.
425
    ///
426
    /// # Example
427
    ///
428
    /// ```
429
    /// use subtle::ConditionallySelectable;
430
    /// #
431
    /// # fn main() {
432
    /// let mut x: u8 = 13;
433
    /// let mut y: u8 = 42;
434
    ///
435
    /// x.conditional_assign(&y, 0.into());
436
    /// assert_eq!(x, 13);
437
    /// x.conditional_assign(&y, 1.into());
438
    /// assert_eq!(x, 42);
439
    /// # }
440
    /// ```
441
    #[inline]
442
    fn conditional_assign(&mut self, other: &Self, choice: Choice) {
443
        *self = Self::conditional_select(self, other, choice);
444
    }
445
446
    /// Conditionally swap `self` and `other` if `choice == 1`; otherwise,
447
    /// reassign both unto themselves.
448
    ///
449
    /// This function should execute in constant time.
450
    ///
451
    /// # Example
452
    ///
453
    /// ```
454
    /// use subtle::ConditionallySelectable;
455
    /// #
456
    /// # fn main() {
457
    /// let mut x: u8 = 13;
458
    /// let mut y: u8 = 42;
459
    ///
460
    /// u8::conditional_swap(&mut x, &mut y, 0.into());
461
    /// assert_eq!(x, 13);
462
    /// assert_eq!(y, 42);
463
    /// u8::conditional_swap(&mut x, &mut y, 1.into());
464
    /// assert_eq!(x, 42);
465
    /// assert_eq!(y, 13);
466
    /// # }
467
    /// ```
468
    #[inline]
469
    fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
470
        let t: Self = *a;
471
        a.conditional_assign(&b, choice);
472
        b.conditional_assign(&t, choice);
473
    }
474
}
475
476
macro_rules! to_signed_int {
477
    (u8) => {
478
        i8
479
    };
480
    (u16) => {
481
        i16
482
    };
483
    (u32) => {
484
        i32
485
    };
486
    (u64) => {
487
        i64
488
    };
489
    (u128) => {
490
        i128
491
    };
492
    (i8) => {
493
        i8
494
    };
495
    (i16) => {
496
        i16
497
    };
498
    (i32) => {
499
        i32
500
    };
501
    (i64) => {
502
        i64
503
    };
504
    (i128) => {
505
        i128
506
    };
507
}
508
509
macro_rules! generate_integer_conditional_select {
510
    ($($t:tt)*) => ($(
511
        impl ConditionallySelectable for $t {
512
            #[inline]
513
            fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
514
                // if choice = 0, mask = (-0) = 0000...0000
515
                // if choice = 1, mask = (-1) = 1111...1111
516
                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
517
                a ^ (mask & (a ^ b))
518
            }
519
520
            #[inline]
521
            fn conditional_assign(&mut self, other: &Self, choice: Choice) {
522
                // if choice = 0, mask = (-0) = 0000...0000
523
                // if choice = 1, mask = (-1) = 1111...1111
524
                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
525
                *self ^= mask & (*self ^ *other);
526
            }
527
528
            #[inline]
529
            fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
530
                // if choice = 0, mask = (-0) = 0000...0000
531
                // if choice = 1, mask = (-1) = 1111...1111
532
                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
533
                let t = mask & (*a ^ *b);
534
                *a ^= t;
535
                *b ^= t;
536
            }
537
         }
538
    )*)
539
}
540
541
generate_integer_conditional_select!(  u8   i8);
542
generate_integer_conditional_select!( u16  i16);
543
generate_integer_conditional_select!( u32  i32);
544
generate_integer_conditional_select!( u64  i64);
545
#[cfg(feature = "i128")]
546
generate_integer_conditional_select!(u128 i128);
547
548
/// `Ordering` is `#[repr(i8)]` where:
549
///
550
/// - `Less` => -1
551
/// - `Equal` => 0
552
/// - `Greater` => 1
553
///
554
/// Given this, it's possible to operate on orderings as if they're integers,
555
/// which allows leveraging conditional masking for predication.
556
impl ConditionallySelectable for cmp::Ordering {
557
    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
558
        let a = *a as i8;
559
        let b = *b as i8;
560
        let ret = i8::conditional_select(&a, &b, choice);
561
562
        // SAFETY: `Ordering` is `#[repr(i8)]` and `ret` has been assigned to
563
        // a value which was originally a valid `Ordering` then cast to `i8`
564
        unsafe { *((&ret as *const _) as *const cmp::Ordering) }
565
    }
566
}
567
568
impl ConditionallySelectable for Choice {
569
    #[inline]
570
    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
571
        Choice(u8::conditional_select(&a.0, &b.0, choice))
572
    }
573
}
574
575
#[cfg(feature = "const-generics")]
576
impl<T, const N: usize> ConditionallySelectable for [T; N]
577
where
578
    T: ConditionallySelectable,
579
{
580
    #[inline]
581
    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
582
        let mut output = *a;
583
        output.conditional_assign(b, choice);
584
        output
585
    }
586
587
    fn conditional_assign(&mut self, other: &Self, choice: Choice) {
588
        for (a_i, b_i) in self.iter_mut().zip(other) {
589
            a_i.conditional_assign(b_i, choice)
590
        }
591
    }
592
}
593
594
/// A type which can be conditionally negated in constant time.
595
///
596
/// # Note
597
///
598
/// A generic implementation of `ConditionallyNegatable` is provided
599
/// for types `T` which are `ConditionallySelectable` and have `Neg`
600
/// implemented on `&T`.
601
//
602
// #[inline] is specified on these function prototypes to signify that they
603
#[allow(unused_attributes)] // should be in the actual implementation
604
pub trait ConditionallyNegatable {
605
    /// Negate `self` if `choice == Choice(1)`; otherwise, leave it
606
    /// unchanged.
607
    ///
608
    /// This function should execute in constant time.
609
    #[inline]
610
    #[allow(unused_attributes)]
611
    fn conditional_negate(&mut self, choice: Choice);
612
}
613
614
impl<T> ConditionallyNegatable for T
615
where
616
    T: ConditionallySelectable,
617
    for<'a> &'a T: Neg<Output = T>,
618
{
619
    #[inline]
620
    fn conditional_negate(&mut self, choice: Choice) {
621
        // Need to cast to eliminate mutability
622
        let self_neg: T = -(self as &T);
623
        self.conditional_assign(&self_neg, choice);
624
    }
625
}
626
627
/// The `CtOption<T>` type represents an optional value similar to the
628
/// [`Option<T>`](core::option::Option) type but is intended for
629
/// use in constant time APIs.
630
///
631
/// Any given `CtOption<T>` is either `Some` or `None`, but unlike
632
/// `Option<T>` these variants are not exposed. The
633
/// [`is_some()`](CtOption::is_some) method is used to determine if
634
/// the value is `Some`, and [`unwrap_or()`](CtOption::unwrap_or) and
635
/// [`unwrap_or_else()`](CtOption::unwrap_or_else) methods are
636
/// provided to access the underlying value. The value can also be
637
/// obtained with [`unwrap()`](CtOption::unwrap) but this will panic
638
/// if it is `None`.
639
///
640
/// Functions that are intended to be constant time may not produce
641
/// valid results for all inputs, such as square root and inversion
642
/// operations in finite field arithmetic. Returning an `Option<T>`
643
/// from these functions makes it difficult for the caller to reason
644
/// about the result in constant time, and returning an incorrect
645
/// value burdens the caller and increases the chance of bugs.
646
#[derive(Clone, Copy, Debug)]
647
pub struct CtOption<T> {
648
    value: T,
649
    is_some: Choice,
650
}
651
652
impl<T> From<CtOption<T>> for Option<T> {
653
    /// Convert the `CtOption<T>` wrapper into an `Option<T>`, depending on whether
654
    /// the underlying `is_some` `Choice` was a `0` or a `1` once unwrapped.
655
    ///
656
    /// # Note
657
    ///
658
    /// This function exists to avoid ending up with ugly, verbose and/or bad handled
659
    /// conversions from the `CtOption<T>` wraps to an `Option<T>` or `Result<T, E>`.
660
    /// This implementation doesn't intend to be constant-time nor try to protect the
661
    /// leakage of the `T` since the `Option<T>` will do it anyways.
662
    fn from(source: CtOption<T>) -> Option<T> {
663
        if source.is_some().unwrap_u8() == 1u8 {
664
            Option::Some(source.value)
665
        } else {
666
            None
667
        }
668
    }
669
}
670
671
impl<T> CtOption<T> {
672
    /// This method is used to construct a new `CtOption<T>` and takes
673
    /// a value of type `T`, and a `Choice` that determines whether
674
    /// the optional value should be `Some` or not. If `is_some` is
675
    /// false, the value will still be stored but its value is never
676
    /// exposed.
677
    #[inline]
678
    pub fn new(value: T, is_some: Choice) -> CtOption<T> {
679
        CtOption {
680
            value: value,
681
            is_some: is_some,
682
        }
683
    }
684
685
    /// Returns the contained value, consuming the `self` value.
686
    ///
687
    /// # Panics
688
    ///
689
    /// Panics if the value is none with a custom panic message provided by
690
    /// `msg`.
691
    pub fn expect(self, msg: &str) -> T {
692
        assert_eq!(self.is_some.unwrap_u8(), 1, "{}", msg);
693
694
        self.value
695
    }
696
697
    /// This returns the underlying value but panics if it
698
    /// is not `Some`.
699
    #[inline]
700
    pub fn unwrap(self) -> T {
701
        assert_eq!(self.is_some.unwrap_u8(), 1);
702
703
        self.value
704
    }
705
706
    /// This returns the underlying value if it is `Some`
707
    /// or the provided value otherwise.
708
    #[inline]
709
    pub fn unwrap_or(self, def: T) -> T
710
    where
711
        T: ConditionallySelectable,
712
    {
713
        T::conditional_select(&def, &self.value, self.is_some)
714
    }
715
716
    /// This returns the underlying value if it is `Some`
717
    /// or the value produced by the provided closure otherwise.
718
    ///
719
    /// This operates in constant time, because the provided closure
720
    /// is always called.
721
    #[inline]
722
    pub fn unwrap_or_else<F>(self, f: F) -> T
723
    where
724
        T: ConditionallySelectable,
725
        F: FnOnce() -> T,
726
    {
727
        T::conditional_select(&f(), &self.value, self.is_some)
728
    }
729
730
    /// Returns a true `Choice` if this value is `Some`.
731
    #[inline]
732
    pub fn is_some(&self) -> Choice {
733
        self.is_some
734
    }
735
736
    /// Returns a true `Choice` if this value is `None`.
737
    #[inline]
738
    pub fn is_none(&self) -> Choice {
739
        !self.is_some
740
    }
741
742
    /// Returns a `None` value if the option is `None`, otherwise
743
    /// returns a `CtOption` enclosing the value of the provided closure.
744
    /// The closure is given the enclosed value or, if the option is
745
    /// `None`, it is provided a dummy value computed using
746
    /// `Default::default()`.
747
    ///
748
    /// This operates in constant time, because the provided closure
749
    /// is always called.
750
    #[inline]
751
    pub fn map<U, F>(self, f: F) -> CtOption<U>
752
    where
753
        T: Default + ConditionallySelectable,
754
        F: FnOnce(T) -> U,
755
    {
756
        CtOption::new(
757
            f(T::conditional_select(
758
                &T::default(),
759
                &self.value,
760
                self.is_some,
761
            )),
762
            self.is_some,
763
        )
764
    }
765
766
    /// Returns a `None` value if the option is `None`, otherwise
767
    /// returns the result of the provided closure. The closure is
768
    /// given the enclosed value or, if the option is `None`, it
769
    /// is provided a dummy value computed using `Default::default()`.
770
    ///
771
    /// This operates in constant time, because the provided closure
772
    /// is always called.
773
    #[inline]
774
    pub fn and_then<U, F>(self, f: F) -> CtOption<U>
775
    where
776
        T: Default + ConditionallySelectable,
777
        F: FnOnce(T) -> CtOption<U>,
778
    {
779
        let mut tmp = f(T::conditional_select(
780
            &T::default(),
781
            &self.value,
782
            self.is_some,
783
        ));
784
        tmp.is_some &= self.is_some;
785
786
        tmp
787
    }
788
789
    /// Returns `self` if it contains a value, and otherwise returns the result of
790
    /// calling `f`. The provided function `f` is always called.
791
    #[inline]
792
    pub fn or_else<F>(self, f: F) -> CtOption<T>
793
    where
794
        T: ConditionallySelectable,
795
        F: FnOnce() -> CtOption<T>,
796
    {
797
        let is_none = self.is_none();
798
        let f = f();
799
800
        Self::conditional_select(&self, &f, is_none)
801
    }
802
803
    /// Convert the `CtOption<T>` wrapper into an `Option<T>`, depending on whether
804
    /// the underlying `is_some` `Choice` was a `0` or a `1` once unwrapped.
805
    ///
806
    /// # Note
807
    ///
808
    /// This function exists to avoid ending up with ugly, verbose and/or bad handled
809
    /// conversions from the `CtOption<T>` wraps to an `Option<T>` or `Result<T, E>`.
810
    /// This implementation doesn't intend to be constant-time nor try to protect the
811
    /// leakage of the `T` since the `Option<T>` will do it anyways.
812
    ///
813
    /// It's equivalent to the corresponding `From` impl, however this version is
814
    /// friendlier for type inference.
815
    pub fn into_option(self) -> Option<T> {
816
        self.into()
817
    }
818
}
819
820
impl<T: ConditionallySelectable> ConditionallySelectable for CtOption<T> {
821
    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
822
        CtOption::new(
823
            T::conditional_select(&a.value, &b.value, choice),
824
            Choice::conditional_select(&a.is_some, &b.is_some, choice),
825
        )
826
    }
827
}
828
829
impl<T: ConstantTimeEq> ConstantTimeEq for CtOption<T> {
830
    /// Two `CtOption<T>`s are equal if they are both `Some` and
831
    /// their values are equal, or both `None`.
832
    #[inline]
833
    fn ct_eq(&self, rhs: &CtOption<T>) -> Choice {
834
        let a = self.is_some();
835
        let b = rhs.is_some();
836
837
        (a & b & self.value.ct_eq(&rhs.value)) | (!a & !b)
838
    }
839
}
840
841
/// A type which can be compared in some manner and be determined to be greater
842
/// than another of the same type.
843
pub trait ConstantTimeGreater {
844
    /// Determine whether `self > other`.
845
    ///
846
    /// The bitwise-NOT of the return value of this function should be usable to
847
    /// determine if `self <= other`.
848
    ///
849
    /// This function should execute in constant time.
850
    ///
851
    /// # Returns
852
    ///
853
    /// A `Choice` with a set bit if `self > other`, and with no set bits
854
    /// otherwise.
855
    ///
856
    /// # Example
857
    ///
858
    /// ```
859
    /// use subtle::ConstantTimeGreater;
860
    ///
861
    /// let x: u8 = 13;
862
    /// let y: u8 = 42;
863
    ///
864
    /// let x_gt_y = x.ct_gt(&y);
865
    ///
866
    /// assert_eq!(x_gt_y.unwrap_u8(), 0);
867
    ///
868
    /// let y_gt_x = y.ct_gt(&x);
869
    ///
870
    /// assert_eq!(y_gt_x.unwrap_u8(), 1);
871
    ///
872
    /// let x_gt_x = x.ct_gt(&x);
873
    ///
874
    /// assert_eq!(x_gt_x.unwrap_u8(), 0);
875
    /// ```
876
    fn ct_gt(&self, other: &Self) -> Choice;
877
}
878
879
macro_rules! generate_unsigned_integer_greater {
880
    ($t_u: ty, $bit_width: expr) => {
881
        impl ConstantTimeGreater for $t_u {
882
            /// Returns Choice::from(1) iff x > y, and Choice::from(0) iff x <= y.
883
            ///
884
            /// # Note
885
            ///
886
            /// This algoritm would also work for signed integers if we first
887
            /// flip the top bit, e.g. `let x: u8 = x ^ 0x80`, etc.
888
            #[inline]
889
            fn ct_gt(&self, other: &$t_u) -> Choice {
890
                let gtb = self & !other; // All the bits in self that are greater than their corresponding bits in other.
891
                let mut ltb = !self & other; // All the bits in self that are less than their corresponding bits in other.
892
                let mut pow = 1;
893
894
                // Less-than operator is okay here because it's dependent on the bit-width.
895
                while pow < $bit_width {
896
                    ltb |= ltb >> pow; // Bit-smear the highest set bit to the right.
897
                    pow += pow;
898
                }
899
                let mut bit = gtb & !ltb; // Select the highest set bit.
900
                let mut pow = 1;
901
902
                while pow < $bit_width {
903
                    bit |= bit >> pow; // Shift it to the right until we end up with either 0 or 1.
904
                    pow += pow;
905
                }
906
                // XXX We should possibly do the above flattening to 0 or 1 in the
907
                //     Choice constructor rather than making it a debug error?
908
                Choice::from((bit & 1) as u8)
909
            }
910
        }
911
    };
912
}
913
914
generate_unsigned_integer_greater!(u8, 8);
915
generate_unsigned_integer_greater!(u16, 16);
916
generate_unsigned_integer_greater!(u32, 32);
917
generate_unsigned_integer_greater!(u64, 64);
918
#[cfg(feature = "i128")]
919
generate_unsigned_integer_greater!(u128, 128);
920
921
impl ConstantTimeGreater for cmp::Ordering {
922
    #[inline]
923
    fn ct_gt(&self, other: &Self) -> Choice {
924
        // No impl of `ConstantTimeGreater` for `i8`, so use `u8`
925
        let a = (*self as i8) + 1;
926
        let b = (*other as i8) + 1;
927
        (a as u8).ct_gt(&(b as u8))
928
    }
929
}
930
931
/// A type which can be compared in some manner and be determined to be less
932
/// than another of the same type.
933
pub trait ConstantTimeLess: ConstantTimeEq + ConstantTimeGreater {
934
    /// Determine whether `self < other`.
935
    ///
936
    /// The bitwise-NOT of the return value of this function should be usable to
937
    /// determine if `self >= other`.
938
    ///
939
    /// A default implementation is provided and implemented for the unsigned
940
    /// integer types.
941
    ///
942
    /// This function should execute in constant time.
943
    ///
944
    /// # Returns
945
    ///
946
    /// A `Choice` with a set bit if `self < other`, and with no set bits
947
    /// otherwise.
948
    ///
949
    /// # Example
950
    ///
951
    /// ```
952
    /// use subtle::ConstantTimeLess;
953
    ///
954
    /// let x: u8 = 13;
955
    /// let y: u8 = 42;
956
    ///
957
    /// let x_lt_y = x.ct_lt(&y);
958
    ///
959
    /// assert_eq!(x_lt_y.unwrap_u8(), 1);
960
    ///
961
    /// let y_lt_x = y.ct_lt(&x);
962
    ///
963
    /// assert_eq!(y_lt_x.unwrap_u8(), 0);
964
    ///
965
    /// let x_lt_x = x.ct_lt(&x);
966
    ///
967
    /// assert_eq!(x_lt_x.unwrap_u8(), 0);
968
    /// ```
969
    #[inline]
970
    fn ct_lt(&self, other: &Self) -> Choice {
971
        !self.ct_gt(other) & !self.ct_eq(other)
972
    }
973
}
974
975
impl ConstantTimeLess for u8 {}
976
impl ConstantTimeLess for u16 {}
977
impl ConstantTimeLess for u32 {}
978
impl ConstantTimeLess for u64 {}
979
#[cfg(feature = "i128")]
980
impl ConstantTimeLess for u128 {}
981
982
impl ConstantTimeLess for cmp::Ordering {
983
    #[inline]
984
    fn ct_lt(&self, other: &Self) -> Choice {
985
        // No impl of `ConstantTimeLess` for `i8`, so use `u8`
986
        let a = (*self as i8) + 1;
987
        let b = (*other as i8) + 1;
988
        (a as u8).ct_lt(&(b as u8))
989
    }
990
}
991
992
/// Wrapper type which implements an optimization barrier for all accesses.
993
#[derive(Clone, Copy, Debug)]
994
pub struct BlackBox<T: Copy>(T);
995
996
impl<T: Copy> BlackBox<T> {
997
    /// Constructs a new instance of `BlackBox` which will wrap the specified value.
998
    ///
999
    /// All access to the inner value will be mediated by a `black_box` optimization barrier.
1000
    pub fn new(value: T) -> Self {
1001
        Self(value)
1002
    }
1003
1004
    /// Read the inner value, applying an optimization barrier on access.
1005
    pub fn get(self) -> T {
1006
        black_box(self.0)
1007
    }
1008
}