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