fullcodec_subtle/
lib.rs

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.4.1")]
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.4"
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//! Versions prior to `2.2` recommended use of the `nightly` feature to enable an
45//! optimization barrier; this is not required in versions `2.2` and above.
46//!
47//! Note: the `subtle` crate contains `debug_assert`s to check invariants during
48//! debug builds. These invariant checks involve secret-dependent branches, and
49//! are not present when compiled in release mode. This crate is intended to be
50//! used in release mode.
51//!
52//! ## Documentation
53//!
54//! Documentation is available [here][docs].
55//!
56//! ## Minimum Supported Rust Version
57//!
58//! Rust **1.41** or higher.
59//!
60//! Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump.
61//!
62//! ## About
63//!
64//! This library aims to be the Rust equivalent of Go’s `crypto/subtle` module.
65//!
66//! The optimization barrier in `impl From<u8> for Choice` was based on Tim
67//! Maclean's [work on `rust-timing-shield`][rust-timing-shield], which attempts to
68//! provide a more comprehensive approach for preventing software side-channels in
69//! Rust code.
70//!
71//! `subtle` is authored by isis agora lovecruft and Henry de Valence.
72//!
73//! ## Warning
74//!
75//! This code is a low-level library, intended for specific use-cases implementing
76//! cryptographic protocols.  It represents a best-effort attempt to protect
77//! against some software side-channels.  Because side-channel resistance is not a
78//! property of software alone, but of software together with hardware, any such
79//! effort is fundamentally limited.
80//!
81//! **USE AT YOUR OWN RISK**
82//!
83//! [docs]: https://docs.rs/subtle
84//! [rust-timing-shield]: https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
85
86extern crate parity_scale_codec;
87extern crate serde;
88
89use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Neg, Not};
90use core::option::Option;
91use parity_scale_codec::{Decode, Encode};
92use serde::{Deserialize, Serialize};
93
94/// The `Choice` struct represents a choice for use in conditional assignment.
95///
96/// It is a wrapper around a `u8`, which should have the value either `1` (true)
97/// or `0` (false).
98///
99/// The conversion from `u8` to `Choice` passes the value through an optimization
100/// barrier, as a best-effort attempt to prevent the compiler from inferring that
101/// the `Choice` value is a boolean. This strategy is based on Tim Maclean's
102/// [work on `rust-timing-shield`][rust-timing-shield], which attempts to provide
103/// a more comprehensive approach for preventing software side-channels in Rust
104/// code.
105///
106/// The `Choice` struct implements operators for AND, OR, XOR, and NOT, to allow
107/// combining `Choice` values. These operations do not short-circuit.
108///
109/// [rust-timing-shield]:
110/// https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
111#[derive(Copy, Clone, Debug, Encode, Decode, Serialize, Deserialize, PartialEq)]
112pub struct Choice(u8);
113
114impl Choice {
115    /// Unwrap the `Choice` wrapper to reveal the underlying `u8`.
116    ///
117    /// # Note
118    ///
119    /// This function only exists as an **escape hatch** for the rare case
120    /// where it's not possible to use one of the `subtle`-provided
121    /// trait impls.
122    ///
123    /// **To convert a `Choice` to a `bool`, use the `From` implementation instead.**
124    #[inline]
125    pub fn unwrap_u8(&self) -> u8 {
126        self.0
127    }
128}
129
130impl From<Choice> for bool {
131    /// Convert the `Choice` wrapper into a `bool`, depending on whether
132    /// the underlying `u8` was a `0` or a `1`.
133    ///
134    /// # Note
135    ///
136    /// This function exists to avoid having higher-level cryptographic protocol
137    /// implementations duplicating this pattern.
138    ///
139    /// The intended use case for this conversion is at the _end_ of a
140    /// higher-level primitive implementation: for example, in checking a keyed
141    /// MAC, where the verification should happen in constant-time (and thus use
142    /// a `Choice`) but it is safe to return a `bool` at the end of the
143    /// verification.
144    #[inline]
145    fn from(source: Choice) -> bool {
146        debug_assert!((source.0 == 0u8) | (source.0 == 1u8));
147        source.0 != 0
148    }
149}
150
151impl BitAnd for Choice {
152    type Output = Choice;
153    #[inline]
154    fn bitand(self, rhs: Choice) -> Choice {
155        (self.0 & rhs.0).into()
156    }
157}
158
159impl BitAndAssign for Choice {
160    #[inline]
161    fn bitand_assign(&mut self, rhs: Choice) {
162        *self = *self & rhs;
163    }
164}
165
166impl BitOr for Choice {
167    type Output = Choice;
168    #[inline]
169    fn bitor(self, rhs: Choice) -> Choice {
170        (self.0 | rhs.0).into()
171    }
172}
173
174impl BitOrAssign for Choice {
175    #[inline]
176    fn bitor_assign(&mut self, rhs: Choice) {
177        *self = *self | rhs;
178    }
179}
180
181impl BitXor for Choice {
182    type Output = Choice;
183    #[inline]
184    fn bitxor(self, rhs: Choice) -> Choice {
185        (self.0 ^ rhs.0).into()
186    }
187}
188
189impl BitXorAssign for Choice {
190    #[inline]
191    fn bitxor_assign(&mut self, rhs: Choice) {
192        *self = *self ^ rhs;
193    }
194}
195
196impl Not for Choice {
197    type Output = Choice;
198    #[inline]
199    fn not(self) -> Choice {
200        (1u8 & (!self.0)).into()
201    }
202}
203
204/// This function is a best-effort attempt to prevent the compiler from knowing
205/// anything about the value of the returned `u8`, other than its type.
206///
207/// Because we want to support stable Rust, we don't have access to inline
208/// assembly or test::black_box, so we use the fact that volatile values will
209/// never be elided to register values.
210///
211/// Note: Rust's notion of "volatile" is subject to change over time. While this
212/// code may break in a non-destructive way in the future, “constant-time” code
213/// is a continually moving target, and this is better than doing nothing.
214#[inline(never)]
215fn 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
231impl From<u8> for Choice {
232    #[inline]
233    fn from(input: u8) -> Choice {
234        // Our goal is to prevent the compiler from inferring that the value held inside the
235        // resulting `Choice` struct is really an `i1` instead of an `i8`.
236        Choice(black_box(input))
237    }
238}
239
240/// An `Eq`-like trait that produces a `Choice` instead of a `bool`.
241///
242/// # Example
243///
244/// ```
245/// use parity_subtle::ConstantTimeEq;
246/// let x: u8 = 5;
247/// let y: u8 = 13;
248///
249/// assert_eq!(x.ct_eq(&y).unwrap_u8(), 0);
250/// assert_eq!(x.ct_eq(&x).unwrap_u8(), 1);
251/// ```
252pub trait ConstantTimeEq {
253    /// Determine if two items are equal.
254    ///
255    /// The `ct_eq` function should execute in constant time.
256    ///
257    /// # Returns
258    ///
259    /// * `Choice(1u8)` if `self == other`;
260    /// * `Choice(0u8)` if `self != other`.
261    fn ct_eq(&self, other: &Self) -> Choice;
262}
263
264impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
265    /// Check whether two slices of `ConstantTimeEq` types are equal.
266    ///
267    /// # Note
268    ///
269    /// This function short-circuits if the lengths of the input slices
270    /// are different.  Otherwise, it should execute in time independent
271    /// of the slice contents.
272    ///
273    /// Since arrays coerce to slices, this function works with fixed-size arrays:
274    ///
275    /// ```
276    /// # use parity_subtle::ConstantTimeEq;
277    /// #
278    /// let a: [u8; 8] = [0,1,2,3,4,5,6,7];
279    /// let b: [u8; 8] = [0,1,2,3,0,1,2,3];
280    ///
281    /// let a_eq_a = a.ct_eq(&a);
282    /// let a_eq_b = a.ct_eq(&b);
283    ///
284    /// assert_eq!(a_eq_a.unwrap_u8(), 1);
285    /// assert_eq!(a_eq_b.unwrap_u8(), 0);
286    /// ```
287    #[inline]
288    fn ct_eq(&self, _rhs: &[T]) -> Choice {
289        let len = self.len();
290
291        // Short-circuit on the *lengths* of the slices, not their
292        // contents.
293        if len != _rhs.len() {
294            return Choice::from(0);
295        }
296
297        // This loop shouldn't be shortcircuitable, since the compiler
298        // shouldn't be able to reason about the value of the `u8`
299        // unwrapped from the `ct_eq` result.
300        let mut x = 1u8;
301        for (ai, bi) in self.iter().zip(_rhs.iter()) {
302            x &= ai.ct_eq(bi).unwrap_u8();
303        }
304
305        x.into()
306    }
307}
308
309impl ConstantTimeEq for Choice {
310    #[inline]
311    fn ct_eq(&self, rhs: &Choice) -> Choice {
312        !(*self ^ *rhs)
313    }
314}
315
316/// Given the bit-width `$bit_width` and the corresponding primitive
317/// unsigned and signed types `$t_u` and `$t_i` respectively, generate
318/// an `ConstantTimeEq` implementation.
319macro_rules! generate_integer_equal {
320    ($t_u:ty, $t_i:ty, $bit_width:expr) => {
321        impl ConstantTimeEq for $t_u {
322            #[inline]
323            fn ct_eq(&self, other: &$t_u) -> Choice {
324                // x == 0 if and only if self == other
325                let x: $t_u = self ^ other;
326
327                // If x == 0, then x and -x are both equal to zero;
328                // otherwise, one or both will have its high bit set.
329                let y: $t_u = (x | x.wrapping_neg()) >> ($bit_width - 1);
330
331                // Result is the opposite of the high bit (now shifted to low).
332                ((y ^ (1 as $t_u)) as u8).into()
333            }
334        }
335        impl ConstantTimeEq for $t_i {
336            #[inline]
337            fn ct_eq(&self, other: &$t_i) -> Choice {
338                // Bitcast to unsigned and call that implementation.
339                (*self as $t_u).ct_eq(&(*other as $t_u))
340            }
341        }
342    };
343}
344
345generate_integer_equal!(u8, i8, 8);
346generate_integer_equal!(u16, i16, 16);
347generate_integer_equal!(u32, i32, 32);
348generate_integer_equal!(u64, i64, 64);
349#[cfg(feature = "i128")]
350generate_integer_equal!(u128, i128, 128);
351generate_integer_equal!(usize, isize, ::core::mem::size_of::<usize>() * 8);
352
353/// A type which can be conditionally selected in constant time.
354///
355/// This trait also provides generic implementations of conditional
356/// assignment and conditional swaps.
357pub trait ConditionallySelectable: Copy {
358    /// Select `a` or `b` according to `choice`.
359    ///
360    /// # Returns
361    ///
362    /// * `a` if `choice == Choice(0)`;
363    /// * `b` if `choice == Choice(1)`.
364    ///
365    /// This function should execute in constant time.
366    ///
367    /// # Example
368    ///
369    /// ```
370    /// # extern crate parity_subtle;
371    /// use parity_subtle::ConditionallySelectable;
372    /// #
373    /// # fn main() {
374    /// let x: u8 = 13;
375    /// let y: u8 = 42;
376    ///
377    /// let z = u8::conditional_select(&x, &y, 0.into());
378    /// assert_eq!(z, x);
379    /// let z = u8::conditional_select(&x, &y, 1.into());
380    /// assert_eq!(z, y);
381    /// # }
382    /// ```
383    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self;
384
385    /// Conditionally assign `other` to `self`, according to `choice`.
386    ///
387    /// This function should execute in constant time.
388    ///
389    /// # Example
390    ///
391    /// ```
392    /// # extern crate parity_subtle;
393    /// use parity_subtle::ConditionallySelectable;
394    /// #
395    /// # fn main() {
396    /// let mut x: u8 = 13;
397    /// let mut y: u8 = 42;
398    ///
399    /// x.conditional_assign(&y, 0.into());
400    /// assert_eq!(x, 13);
401    /// x.conditional_assign(&y, 1.into());
402    /// assert_eq!(x, 42);
403    /// # }
404    /// ```
405    #[inline]
406    fn conditional_assign(&mut self, other: &Self, choice: Choice) {
407        *self = Self::conditional_select(self, other, choice);
408    }
409
410    /// Conditionally swap `self` and `other` if `choice == 1`; otherwise,
411    /// reassign both unto themselves.
412    ///
413    /// This function should execute in constant time.
414    ///
415    /// # Example
416    ///
417    /// ```
418    /// # extern crate parity_subtle;
419    /// use parity_subtle::ConditionallySelectable;
420    /// #
421    /// # fn main() {
422    /// let mut x: u8 = 13;
423    /// let mut y: u8 = 42;
424    ///
425    /// u8::conditional_swap(&mut x, &mut y, 0.into());
426    /// assert_eq!(x, 13);
427    /// assert_eq!(y, 42);
428    /// u8::conditional_swap(&mut x, &mut y, 1.into());
429    /// assert_eq!(x, 42);
430    /// assert_eq!(y, 13);
431    /// # }
432    /// ```
433    #[inline]
434    fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
435        let t: Self = *a;
436        a.conditional_assign(&b, choice);
437        b.conditional_assign(&t, choice);
438    }
439}
440
441macro_rules! to_signed_int {
442    (u8) => {
443        i8
444    };
445    (u16) => {
446        i16
447    };
448    (u32) => {
449        i32
450    };
451    (u64) => {
452        i64
453    };
454    (u128) => {
455        i128
456    };
457    (i8) => {
458        i8
459    };
460    (i16) => {
461        i16
462    };
463    (i32) => {
464        i32
465    };
466    (i64) => {
467        i64
468    };
469    (i128) => {
470        i128
471    };
472}
473
474macro_rules! generate_integer_conditional_select {
475    ($($t:tt)*) => ($(
476        impl ConditionallySelectable for $t {
477            #[inline]
478            fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
479                // if choice = 0, mask = (-0) = 0000...0000
480                // if choice = 1, mask = (-1) = 1111...1111
481                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
482                a ^ (mask & (a ^ b))
483            }
484
485            #[inline]
486            fn conditional_assign(&mut self, other: &Self, choice: Choice) {
487                // if choice = 0, mask = (-0) = 0000...0000
488                // if choice = 1, mask = (-1) = 1111...1111
489                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
490                *self ^= mask & (*self ^ *other);
491            }
492
493            #[inline]
494            fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
495                // if choice = 0, mask = (-0) = 0000...0000
496                // if choice = 1, mask = (-1) = 1111...1111
497                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
498                let t = mask & (*a ^ *b);
499                *a ^= t;
500                *b ^= t;
501            }
502         }
503    )*)
504}
505
506generate_integer_conditional_select!(  u8   i8);
507generate_integer_conditional_select!( u16  i16);
508generate_integer_conditional_select!( u32  i32);
509generate_integer_conditional_select!( u64  i64);
510#[cfg(feature = "i128")]
511generate_integer_conditional_select!(u128 i128);
512
513impl ConditionallySelectable for Choice {
514    #[inline]
515    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
516        Choice(u8::conditional_select(&a.0, &b.0, choice))
517    }
518}
519
520/// A type which can be conditionally negated in constant time.
521///
522/// # Note
523///
524/// A generic implementation of `ConditionallyNegatable` is provided
525/// for types `T` which are `ConditionallySelectable` and have `Neg`
526/// implemented on `&T`.
527pub trait ConditionallyNegatable {
528    /// Negate `self` if `choice == Choice(1)`; otherwise, leave it
529    /// unchanged.
530    ///
531    /// This function should execute in constant time.
532    fn conditional_negate(&mut self, choice: Choice);
533}
534
535impl<T> ConditionallyNegatable for T
536where
537    T: ConditionallySelectable,
538    for<'a> &'a T: Neg<Output = T>,
539{
540    #[inline]
541    fn conditional_negate(&mut self, choice: Choice) {
542        // Need to cast to eliminate mutability
543        let self_neg: T = -(self as &T);
544        self.conditional_assign(&self_neg, choice);
545    }
546}
547
548/// The `CtOption<T>` type represents an optional value similar to the
549/// [`Option<T>`](core::option::Option) type but is intended for
550/// use in constant time APIs.
551///
552/// Any given `CtOption<T>` is either `Some` or `None`, but unlike
553/// `Option<T>` these variants are not exposed. The
554/// [`is_some()`](CtOption::is_some) method is used to determine if
555/// the value is `Some`, and [`unwrap_or()`](CtOption::unwrap_or) and
556/// [`unwrap_or_else()`](CtOption::unwrap_or_else) methods are
557/// provided to access the underlying value. The value can also be
558/// obtained with [`unwrap()`](CtOption::unwrap) but this will panic
559/// if it is `None`.
560///
561/// Functions that are intended to be constant time may not produce
562/// valid results for all inputs, such as square root and inversion
563/// operations in finite field arithmetic. Returning an `Option<T>`
564/// from these functions makes it difficult for the caller to reason
565/// about the result in constant time, and returning an incorrect
566/// value burdens the caller and increases the chance of bugs.
567#[derive(Clone, Copy, Debug)]
568pub struct CtOption<T> {
569    value: T,
570    is_some: Choice,
571}
572
573impl<T> From<CtOption<T>> for Option<T> {
574    /// Convert the `CtOption<T>` wrapper into an `Option<T>`, depending on whether
575    /// the underlying `is_some` `Choice` was a `0` or a `1` once unwrapped.
576    ///
577    /// # Note
578    ///
579    /// This function exists to avoid ending up with ugly, verbose and/or bad handled
580    /// conversions from the `CtOption<T>` wraps to an `Option<T>` or `Result<T, E>`.
581    /// This implementation doesn't intend to be constant-time nor try to protect the
582    /// leakage of the `T` since the `Option<T>` will do it anyways.
583    fn from(source: CtOption<T>) -> Option<T> {
584        if source.is_some().unwrap_u8() == 1u8 {
585            Option::Some(source.value)
586        } else {
587            None
588        }
589    }
590}
591
592impl<T> CtOption<T> {
593    /// This method is used to construct a new `CtOption<T>` and takes
594    /// a value of type `T`, and a `Choice` that determines whether
595    /// the optional value should be `Some` or not. If `is_some` is
596    /// false, the value will still be stored but its value is never
597    /// exposed.
598    #[inline]
599    pub fn new(value: T, is_some: Choice) -> CtOption<T> {
600        CtOption {
601            value: value,
602            is_some: is_some,
603        }
604    }
605
606    /// This returns the underlying value but panics if it
607    /// is not `Some`.
608    #[inline]
609    pub fn unwrap(self) -> T {
610        assert_eq!(self.is_some.unwrap_u8(), 1);
611
612        self.value
613    }
614
615    /// This returns the underlying value if it is `Some`
616    /// or the provided value otherwise.
617    #[inline]
618    pub fn unwrap_or(self, def: T) -> T
619    where
620        T: ConditionallySelectable,
621    {
622        T::conditional_select(&def, &self.value, self.is_some)
623    }
624
625    /// This returns the underlying value if it is `Some`
626    /// or the value produced by the provided closure otherwise.
627    #[inline]
628    pub fn unwrap_or_else<F>(self, f: F) -> T
629    where
630        T: ConditionallySelectable,
631        F: FnOnce() -> T,
632    {
633        T::conditional_select(&f(), &self.value, self.is_some)
634    }
635
636    /// Returns a true `Choice` if this value is `Some`.
637    #[inline]
638    pub fn is_some(&self) -> Choice {
639        self.is_some
640    }
641
642    /// Returns a true `Choice` if this value is `None`.
643    #[inline]
644    pub fn is_none(&self) -> Choice {
645        !self.is_some
646    }
647
648    /// Returns a `None` value if the option is `None`, otherwise
649    /// returns a `CtOption` enclosing the value of the provided closure.
650    /// The closure is given the enclosed value or, if the option is
651    /// `None`, it is provided a dummy value computed using
652    /// `Default::default()`.
653    ///
654    /// This operates in constant time, because the provided closure
655    /// is always called.
656    #[inline]
657    pub fn map<U, F>(self, f: F) -> CtOption<U>
658    where
659        T: Default + ConditionallySelectable,
660        F: FnOnce(T) -> U,
661    {
662        CtOption::new(
663            f(T::conditional_select(
664                &T::default(),
665                &self.value,
666                self.is_some,
667            )),
668            self.is_some,
669        )
670    }
671
672    /// Returns a `None` value if the option is `None`, otherwise
673    /// returns the result of the provided closure. The closure is
674    /// given the enclosed value or, if the option is `None`, it
675    /// is provided a dummy value computed using `Default::default()`.
676    ///
677    /// This operates in constant time, because the provided closure
678    /// is always called.
679    #[inline]
680    pub fn and_then<U, F>(self, f: F) -> CtOption<U>
681    where
682        T: Default + ConditionallySelectable,
683        F: FnOnce(T) -> CtOption<U>,
684    {
685        let mut tmp = f(T::conditional_select(
686            &T::default(),
687            &self.value,
688            self.is_some,
689        ));
690        tmp.is_some &= self.is_some;
691
692        tmp
693    }
694
695    /// Returns `self` if it contains a value, and otherwise returns the result of
696    /// calling `f`. The provided function `f` is always called.
697    #[inline]
698    pub fn or_else<F>(self, f: F) -> CtOption<T>
699    where
700        T: ConditionallySelectable,
701        F: FnOnce() -> CtOption<T>,
702    {
703        let is_none = self.is_none();
704        let f = f();
705
706        Self::conditional_select(&self, &f, is_none)
707    }
708}
709
710impl<T: ConditionallySelectable> ConditionallySelectable for CtOption<T> {
711    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
712        CtOption::new(
713            T::conditional_select(&a.value, &b.value, choice),
714            Choice::conditional_select(&a.is_some, &b.is_some, choice),
715        )
716    }
717}
718
719impl<T: ConstantTimeEq> ConstantTimeEq for CtOption<T> {
720    /// Two `CtOption<T>`s are equal if they are both `Some` and
721    /// their values are equal, or both `None`.
722    #[inline]
723    fn ct_eq(&self, rhs: &CtOption<T>) -> Choice {
724        let a = self.is_some();
725        let b = rhs.is_some();
726
727        (a & b & self.value.ct_eq(&rhs.value)) | (!a & !b)
728    }
729}
730
731/// A type which can be compared in some manner and be determined to be greater
732/// than another of the same type.
733pub trait ConstantTimeGreater {
734    /// Determine whether `self > other`.
735    ///
736    /// The bitwise-NOT of the return value of this function should be usable to
737    /// determine if `self <= other`.
738    ///
739    /// This function should execute in constant time.
740    ///
741    /// # Returns
742    ///
743    /// A `Choice` with a set bit if `self > other`, and with no set bits
744    /// otherwise.
745    ///
746    /// # Example
747    ///
748    /// ```
749    /// # extern crate parity_subtle;
750    /// use parity_subtle::ConstantTimeGreater;
751    ///
752    /// let x: u8 = 13;
753    /// let y: u8 = 42;
754    ///
755    /// let x_gt_y = x.ct_gt(&y);
756    ///
757    /// assert_eq!(x_gt_y.unwrap_u8(), 0);
758    ///
759    /// let y_gt_x = y.ct_gt(&x);
760    ///
761    /// assert_eq!(y_gt_x.unwrap_u8(), 1);
762    ///
763    /// let x_gt_x = x.ct_gt(&x);
764    ///
765    /// assert_eq!(x_gt_x.unwrap_u8(), 0);
766    /// ```
767    fn ct_gt(&self, other: &Self) -> Choice;
768}
769
770macro_rules! generate_unsigned_integer_greater {
771    ($t_u: ty, $bit_width: expr) => {
772        impl ConstantTimeGreater for $t_u {
773            /// Returns Choice::from(1) iff x > y, and Choice::from(0) iff x <= y.
774            ///
775            /// # Note
776            ///
777            /// This algoritm would also work for signed integers if we first
778            /// flip the top bit, e.g. `let x: u8 = x ^ 0x80`, etc.
779            #[inline]
780            fn ct_gt(&self, other: &$t_u) -> Choice {
781                let gtb = self & !other; // All the bits in self that are greater than their corresponding bits in other.
782                let mut ltb = !self & other; // All the bits in self that are less than their corresponding bits in other.
783                let mut pow = 1;
784
785                // Less-than operator is okay here because it's dependent on the bit-width.
786                while pow < $bit_width {
787                    ltb |= ltb >> pow; // Bit-smear the highest set bit to the right.
788                    pow += pow;
789                }
790                let mut bit = gtb & !ltb; // Select the highest set bit.
791                let mut pow = 1;
792
793                while pow < $bit_width {
794                    bit |= bit >> pow; // Shift it to the right until we end up with either 0 or 1.
795                    pow += pow;
796                }
797                // XXX We should possibly do the above flattening to 0 or 1 in the
798                //     Choice constructor rather than making it a debug error?
799                Choice::from((bit & 1) as u8)
800            }
801        }
802    };
803}
804
805generate_unsigned_integer_greater!(u8, 8);
806generate_unsigned_integer_greater!(u16, 16);
807generate_unsigned_integer_greater!(u32, 32);
808generate_unsigned_integer_greater!(u64, 64);
809#[cfg(feature = "i128")]
810generate_unsigned_integer_greater!(u128, 128);
811
812/// A type which can be compared in some manner and be determined to be less
813/// than another of the same type.
814pub trait ConstantTimeLess: ConstantTimeEq + ConstantTimeGreater {
815    /// Determine whether `self < other`.
816    ///
817    /// The bitwise-NOT of the return value of this function should be usable to
818    /// determine if `self >= other`.
819    ///
820    /// A default implementation is provided and implemented for the unsigned
821    /// integer types.
822    ///
823    /// This function should execute in constant time.
824    ///
825    /// # Returns
826    ///
827    /// A `Choice` with a set bit if `self < other`, and with no set bits
828    /// otherwise.
829    ///
830    /// # Example
831    ///
832    /// ```
833    /// # extern crate parity_subtle;
834    /// use parity_subtle::ConstantTimeLess;
835    ///
836    /// let x: u8 = 13;
837    /// let y: u8 = 42;
838    ///
839    /// let x_lt_y = x.ct_lt(&y);
840    ///
841    /// assert_eq!(x_lt_y.unwrap_u8(), 1);
842    ///
843    /// let y_lt_x = y.ct_lt(&x);
844    ///
845    /// assert_eq!(y_lt_x.unwrap_u8(), 0);
846    ///
847    /// let x_lt_x = x.ct_lt(&x);
848    ///
849    /// assert_eq!(x_lt_x.unwrap_u8(), 0);
850    /// ```
851    #[inline]
852    fn ct_lt(&self, other: &Self) -> Choice {
853        !self.ct_gt(other) & !self.ct_eq(other)
854    }
855}
856
857impl ConstantTimeLess for u8 {}
858impl ConstantTimeLess for u16 {}
859impl ConstantTimeLess for u32 {}
860impl ConstantTimeLess for u64 {}
861#[cfg(feature = "i128")]
862impl ConstantTimeLess for u128 {}