subtle_ml/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://crates.io/crates/subtle) [](https://doc.dalek.rs/subtle) [](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
86#[cfg(feature = "std")]
87#[macro_use]
88extern crate std;
89
90use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Neg, Not};
91use core::option::Option;
92
93/// The `Choice` struct represents a choice for use in conditional assignment.
94///
95/// It is a wrapper around a `u8`, which should have the value either `1` (true)
96/// or `0` (false).
97///
98/// The conversion from `u8` to `Choice` passes the value through an optimization
99/// barrier, as a best-effort attempt to prevent the compiler from inferring that
100/// the `Choice` value is a boolean. This strategy is based on Tim Maclean's
101/// [work on `rust-timing-shield`][rust-timing-shield], which attempts to provide
102/// a more comprehensive approach for preventing software side-channels in Rust
103/// code.
104///
105/// The `Choice` struct implements operators for AND, OR, XOR, and NOT, to allow
106/// combining `Choice` values. These operations do not short-circuit.
107///
108/// [rust-timing-shield]:
109/// https://www.chosenplaintext.ca/open-source/rust-timing-shield/security
110#[derive(Copy, Clone, Debug)]
111pub struct Choice(u8);
112
113impl Choice {
114 /// Unwrap the `Choice` wrapper to reveal the underlying `u8`.
115 ///
116 /// # Note
117 ///
118 /// This function only exists as an **escape hatch** for the rare case
119 /// where it's not possible to use one of the `subtle`-provided
120 /// trait impls.
121 ///
122 /// **To convert a `Choice` to a `bool`, use the `From` implementation instead.**
123 #[inline]
124 pub fn unwrap_u8(&self) -> u8 {
125 self.0
126 }
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
240impl Choice {
241 /// Intended to use in const init situations
242 pub const fn from_u8_unchecked(input: u8) -> Choice {
243 Choice(input)
244 }
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/// ```
259pub trait ConstantTimeEq {
260 /// Determine if two items are equal.
261 ///
262 /// The `ct_eq` function should execute in constant time.
263 ///
264 /// # Returns
265 ///
266 /// * `Choice(1u8)` if `self == other`;
267 /// * `Choice(0u8)` if `self != other`.
268 fn ct_eq(&self, other: &Self) -> Choice;
269}
270
271impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
272 /// Check whether two slices of `ConstantTimeEq` types are equal.
273 ///
274 /// # Note
275 ///
276 /// This function short-circuits if the lengths of the input slices
277 /// are different. Otherwise, it should execute in time independent
278 /// of the slice contents.
279 ///
280 /// Since arrays coerce to slices, this function works with fixed-size arrays:
281 ///
282 /// ```
283 /// # use subtle::ConstantTimeEq;
284 /// #
285 /// let a: [u8; 8] = [0,1,2,3,4,5,6,7];
286 /// let b: [u8; 8] = [0,1,2,3,0,1,2,3];
287 ///
288 /// let a_eq_a = a.ct_eq(&a);
289 /// let a_eq_b = a.ct_eq(&b);
290 ///
291 /// assert_eq!(a_eq_a.unwrap_u8(), 1);
292 /// assert_eq!(a_eq_b.unwrap_u8(), 0);
293 /// ```
294 #[inline]
295 fn ct_eq(&self, _rhs: &[T]) -> Choice {
296 let len = self.len();
297
298 // Short-circuit on the *lengths* of the slices, not their
299 // contents.
300 if len != _rhs.len() {
301 return Choice::from(0);
302 }
303
304 // This loop shouldn't be shortcircuitable, since the compiler
305 // shouldn't be able to reason about the value of the `u8`
306 // unwrapped from the `ct_eq` result.
307 let mut x = 1u8;
308 for (ai, bi) in self.iter().zip(_rhs.iter()) {
309 x &= ai.ct_eq(bi).unwrap_u8();
310 }
311
312 x.into()
313 }
314}
315
316impl ConstantTimeEq for Choice {
317 #[inline]
318 fn ct_eq(&self, rhs: &Choice) -> Choice {
319 !(*self ^ *rhs)
320 }
321}
322
323/// Given the bit-width `$bit_width` and the corresponding primitive
324/// unsigned and signed types `$t_u` and `$t_i` respectively, generate
325/// an `ConstantTimeEq` implementation.
326macro_rules! generate_integer_equal {
327 ($t_u:ty, $t_i:ty, $bit_width:expr) => {
328 impl ConstantTimeEq for $t_u {
329 #[inline]
330 fn ct_eq(&self, other: &$t_u) -> Choice {
331 // x == 0 if and only if self == other
332 let x: $t_u = self ^ other;
333
334 // If x == 0, then x and -x are both equal to zero;
335 // otherwise, one or both will have its high bit set.
336 let y: $t_u = (x | x.wrapping_neg()) >> ($bit_width - 1);
337
338 // Result is the opposite of the high bit (now shifted to low).
339 ((y ^ (1 as $t_u)) as u8).into()
340 }
341 }
342 impl ConstantTimeEq for $t_i {
343 #[inline]
344 fn ct_eq(&self, other: &$t_i) -> Choice {
345 // Bitcast to unsigned and call that implementation.
346 (*self as $t_u).ct_eq(&(*other as $t_u))
347 }
348 }
349 };
350}
351
352generate_integer_equal!(u8, i8, 8);
353generate_integer_equal!(u16, i16, 16);
354generate_integer_equal!(u32, i32, 32);
355generate_integer_equal!(u64, i64, 64);
356#[cfg(feature = "i128")]
357generate_integer_equal!(u128, i128, 128);
358generate_integer_equal!(usize, isize, ::core::mem::size_of::<usize>() * 8);
359
360/// A type which can be conditionally selected in constant time.
361///
362/// This trait also provides generic implementations of conditional
363/// assignment and conditional swaps.
364pub trait ConditionallySelectable: Copy {
365 /// Select `a` or `b` according to `choice`.
366 ///
367 /// # Returns
368 ///
369 /// * `a` if `choice == Choice(0)`;
370 /// * `b` if `choice == Choice(1)`.
371 ///
372 /// This function should execute in constant time.
373 ///
374 /// # Example
375 ///
376 /// ```
377 /// # extern crate subtle;
378 /// use subtle::ConditionallySelectable;
379 /// #
380 /// # fn main() {
381 /// let x: u8 = 13;
382 /// let y: u8 = 42;
383 ///
384 /// let z = u8::conditional_select(&x, &y, 0.into());
385 /// assert_eq!(z, x);
386 /// let z = u8::conditional_select(&x, &y, 1.into());
387 /// assert_eq!(z, y);
388 /// # }
389 /// ```
390 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self;
391
392 /// Conditionally assign `other` to `self`, according to `choice`.
393 ///
394 /// This function should execute in constant time.
395 ///
396 /// # Example
397 ///
398 /// ```
399 /// # extern crate subtle;
400 /// use subtle::ConditionallySelectable;
401 /// #
402 /// # fn main() {
403 /// let mut x: u8 = 13;
404 /// let mut y: u8 = 42;
405 ///
406 /// x.conditional_assign(&y, 0.into());
407 /// assert_eq!(x, 13);
408 /// x.conditional_assign(&y, 1.into());
409 /// assert_eq!(x, 42);
410 /// # }
411 /// ```
412 #[inline]
413 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
414 *self = Self::conditional_select(self, other, choice);
415 }
416
417 /// Conditionally swap `self` and `other` if `choice == 1`; otherwise,
418 /// reassign both unto themselves.
419 ///
420 /// This function should execute in constant time.
421 ///
422 /// # Example
423 ///
424 /// ```
425 /// # extern crate subtle;
426 /// use subtle::ConditionallySelectable;
427 /// #
428 /// # fn main() {
429 /// let mut x: u8 = 13;
430 /// let mut y: u8 = 42;
431 ///
432 /// u8::conditional_swap(&mut x, &mut y, 0.into());
433 /// assert_eq!(x, 13);
434 /// assert_eq!(y, 42);
435 /// u8::conditional_swap(&mut x, &mut y, 1.into());
436 /// assert_eq!(x, 42);
437 /// assert_eq!(y, 13);
438 /// # }
439 /// ```
440 #[inline]
441 fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
442 let t: Self = *a;
443 a.conditional_assign(&b, choice);
444 b.conditional_assign(&t, choice);
445 }
446}
447
448macro_rules! to_signed_int {
449 (u8) => {
450 i8
451 };
452 (u16) => {
453 i16
454 };
455 (u32) => {
456 i32
457 };
458 (u64) => {
459 i64
460 };
461 (u128) => {
462 i128
463 };
464 (i8) => {
465 i8
466 };
467 (i16) => {
468 i16
469 };
470 (i32) => {
471 i32
472 };
473 (i64) => {
474 i64
475 };
476 (i128) => {
477 i128
478 };
479}
480
481macro_rules! generate_integer_conditional_select {
482 ($($t:tt)*) => ($(
483 impl ConditionallySelectable for $t {
484 #[inline]
485 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
486 // if choice = 0, mask = (-0) = 0000...0000
487 // if choice = 1, mask = (-1) = 1111...1111
488 let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
489 a ^ (mask & (a ^ b))
490 }
491
492 #[inline]
493 fn conditional_assign(&mut self, other: &Self, choice: Choice) {
494 // if choice = 0, mask = (-0) = 0000...0000
495 // if choice = 1, mask = (-1) = 1111...1111
496 let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
497 *self ^= mask & (*self ^ *other);
498 }
499
500 #[inline]
501 fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
502 // if choice = 0, mask = (-0) = 0000...0000
503 // if choice = 1, mask = (-1) = 1111...1111
504 let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
505 let t = mask & (*a ^ *b);
506 *a ^= t;
507 *b ^= t;
508 }
509 }
510 )*)
511}
512
513generate_integer_conditional_select!( u8 i8);
514generate_integer_conditional_select!( u16 i16);
515generate_integer_conditional_select!( u32 i32);
516generate_integer_conditional_select!( u64 i64);
517#[cfg(feature = "i128")]
518generate_integer_conditional_select!(u128 i128);
519
520impl ConditionallySelectable for Choice {
521 #[inline]
522 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
523 Choice(u8::conditional_select(&a.0, &b.0, choice))
524 }
525}
526
527/// A type which can be conditionally negated in constant time.
528///
529/// # Note
530///
531/// A generic implementation of `ConditionallyNegatable` is provided
532/// for types `T` which are `ConditionallySelectable` and have `Neg`
533/// implemented on `&T`.
534pub trait ConditionallyNegatable {
535 /// Negate `self` if `choice == Choice(1)`; otherwise, leave it
536 /// unchanged.
537 ///
538 /// This function should execute in constant time.
539 fn conditional_negate(&mut self, choice: Choice);
540}
541
542impl<T> ConditionallyNegatable for T
543where
544 T: ConditionallySelectable,
545 for<'a> &'a T: Neg<Output = T>,
546{
547 #[inline]
548 fn conditional_negate(&mut self, choice: Choice) {
549 // Need to cast to eliminate mutability
550 let self_neg: T = -(self as &T);
551 self.conditional_assign(&self_neg, choice);
552 }
553}
554
555/// The `CtOption<T>` type represents an optional value similar to the
556/// [`Option<T>`](core::option::Option) type but is intended for
557/// use in constant time APIs.
558///
559/// Any given `CtOption<T>` is either `Some` or `None`, but unlike
560/// `Option<T>` these variants are not exposed. The
561/// [`is_some()`](CtOption::is_some) method is used to determine if
562/// the value is `Some`, and [`unwrap_or()`](CtOption::unwrap_or) and
563/// [`unwrap_or_else()`](CtOption::unwrap_or_else) methods are
564/// provided to access the underlying value. The value can also be
565/// obtained with [`unwrap()`](CtOption::unwrap) but this will panic
566/// if it is `None`.
567///
568/// Functions that are intended to be constant time may not produce
569/// valid results for all inputs, such as square root and inversion
570/// operations in finite field arithmetic. Returning an `Option<T>`
571/// from these functions makes it difficult for the caller to reason
572/// about the result in constant time, and returning an incorrect
573/// value burdens the caller and increases the chance of bugs.
574#[derive(Clone, Copy, Debug)]
575pub struct CtOption<T> {
576 value: T,
577 is_some: Choice,
578}
579
580impl<T> From<CtOption<T>> for Option<T> {
581 /// Convert the `CtOption<T>` wrapper into an `Option<T>`, depending on whether
582 /// the underlying `is_some` `Choice` was a `0` or a `1` once unwrapped.
583 ///
584 /// # Note
585 ///
586 /// This function exists to avoid ending up with ugly, verbose and/or bad handled
587 /// conversions from the `CtOption<T>` wraps to an `Option<T>` or `Result<T, E>`.
588 /// This implementation doesn't intend to be constant-time nor try to protect the
589 /// leakage of the `T` since the `Option<T>` will do it anyways.
590 fn from(source: CtOption<T>) -> Option<T> {
591 if source.is_some().unwrap_u8() == 1u8 {
592 Some(source.value)
593 } else {
594 None
595 }
596 }
597}
598
599impl<T> CtOption<T> {
600 /// This method is used to construct a new `CtOption<T>` and takes
601 /// a value of type `T`, and a `Choice` that determines whether
602 /// the optional value should be `Some` or not. If `is_some` is
603 /// false, the value will still be stored but its value is never
604 /// exposed.
605 #[inline]
606 pub fn new(value: T, is_some: Choice) -> CtOption<T> {
607 CtOption {
608 value,
609 is_some,
610 }
611 }
612
613 /// This method is used to construct a new `CtOption<T>` and takes
614 /// a value of type `T`, and a `Choice` that determines whether
615 /// the optional value should be `Some` or not. If `is_some` is
616 /// false, the value will still be stored but its value is never
617 /// exposed. Intended for const fn situations where value is known
618 #[inline]
619 pub const fn new_unchecked(value: T, is_some: Choice) -> CtOption<T> {
620 Self {
621 value,
622 is_some
623 }
624 }
625
626 /// This returns the underlying value but panics if it
627 /// is not `Some`.
628 #[inline]
629 pub fn unwrap(self) -> T {
630 assert_eq!(self.is_some.unwrap_u8(), 1);
631
632 self.value
633 }
634
635 /// This returns the underlying value if it is `Some`
636 /// or the provided value otherwise.
637 #[inline]
638 pub fn unwrap_or(self, def: T) -> T
639 where
640 T: ConditionallySelectable,
641 {
642 T::conditional_select(&def, &self.value, self.is_some)
643 }
644
645 /// This returns the underlying value if it is `Some`
646 /// or the value produced by the provided closure otherwise.
647 #[inline]
648 pub fn unwrap_or_else<F>(self, f: F) -> T
649 where
650 T: ConditionallySelectable,
651 F: FnOnce() -> T,
652 {
653 T::conditional_select(&f(), &self.value, self.is_some)
654 }
655
656 /// Returns a true `Choice` if this value is `Some`.
657 #[inline]
658 pub fn is_some(&self) -> Choice {
659 self.is_some
660 }
661
662 /// Returns a true `Choice` if this value is `None`.
663 #[inline]
664 pub fn is_none(&self) -> Choice {
665 !self.is_some
666 }
667
668 /// Returns a `None` value if the option is `None`, otherwise
669 /// returns a `CtOption` enclosing the value of the provided closure.
670 /// The closure is given the enclosed value or, if the option is
671 /// `None`, it is provided a dummy value computed using
672 /// `Default::default()`.
673 ///
674 /// This operates in constant time, because the provided closure
675 /// is always called.
676 #[inline]
677 pub fn map<U, F>(self, f: F) -> CtOption<U>
678 where
679 T: Default + ConditionallySelectable,
680 F: FnOnce(T) -> U,
681 {
682 CtOption::new(
683 f(T::conditional_select(
684 &T::default(),
685 &self.value,
686 self.is_some,
687 )),
688 self.is_some,
689 )
690 }
691
692 /// Returns a `None` value if the option is `None`, otherwise
693 /// returns the result of the provided closure. The closure is
694 /// given the enclosed value or, if the option is `None`, it
695 /// is provided a dummy value computed using `Default::default()`.
696 ///
697 /// This operates in constant time, because the provided closure
698 /// is always called.
699 #[inline]
700 pub fn and_then<U, F>(self, f: F) -> CtOption<U>
701 where
702 T: Default + ConditionallySelectable,
703 F: FnOnce(T) -> CtOption<U>,
704 {
705 let mut tmp = f(T::conditional_select(
706 &T::default(),
707 &self.value,
708 self.is_some,
709 ));
710 tmp.is_some &= self.is_some;
711
712 tmp
713 }
714
715 /// Returns `self` if it contains a value, and otherwise returns the result of
716 /// calling `f`. The provided function `f` is always called.
717 #[inline]
718 pub fn or_else<F>(self, f: F) -> CtOption<T>
719 where
720 T: ConditionallySelectable,
721 F: FnOnce() -> CtOption<T>,
722 {
723 let is_none = self.is_none();
724 let f = f();
725
726 Self::conditional_select(&self, &f, is_none)
727 }
728}
729
730impl<T: ConditionallySelectable> ConditionallySelectable for CtOption<T> {
731 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
732 CtOption::new(
733 T::conditional_select(&a.value, &b.value, choice),
734 Choice::conditional_select(&a.is_some, &b.is_some, choice),
735 )
736 }
737}
738
739impl<T: ConstantTimeEq> ConstantTimeEq for CtOption<T> {
740 /// Two `CtOption<T>`s are equal if they are both `Some` and
741 /// their values are equal, or both `None`.
742 #[inline]
743 fn ct_eq(&self, rhs: &CtOption<T>) -> Choice {
744 let a = self.is_some();
745 let b = rhs.is_some();
746
747 (a & b & self.value.ct_eq(&rhs.value)) | (!a & !b)
748 }
749}
750
751/// A type which can be compared in some manner and be determined to be greater
752/// than another of the same type.
753pub trait ConstantTimeGreater {
754 /// Determine whether `self > other`.
755 ///
756 /// The bitwise-NOT of the return value of this function should be usable to
757 /// determine if `self <= other`.
758 ///
759 /// This function should execute in constant time.
760 ///
761 /// # Returns
762 ///
763 /// A `Choice` with a set bit if `self > other`, and with no set bits
764 /// otherwise.
765 ///
766 /// # Example
767 ///
768 /// ```
769 /// # extern crate subtle;
770 /// use subtle::ConstantTimeGreater;
771 ///
772 /// let x: u8 = 13;
773 /// let y: u8 = 42;
774 ///
775 /// let x_gt_y = x.ct_gt(&y);
776 ///
777 /// assert_eq!(x_gt_y.unwrap_u8(), 0);
778 ///
779 /// let y_gt_x = y.ct_gt(&x);
780 ///
781 /// assert_eq!(y_gt_x.unwrap_u8(), 1);
782 ///
783 /// let x_gt_x = x.ct_gt(&x);
784 ///
785 /// assert_eq!(x_gt_x.unwrap_u8(), 0);
786 /// ```
787 fn ct_gt(&self, other: &Self) -> Choice;
788}
789
790macro_rules! generate_unsigned_integer_greater {
791 ($t_u: ty, $bit_width: expr) => {
792 impl ConstantTimeGreater for $t_u {
793 /// Returns Choice::from(1) iff x > y, and Choice::from(0) iff x <= y.
794 ///
795 /// # Note
796 ///
797 /// This algoritm would also work for signed integers if we first
798 /// flip the top bit, e.g. `let x: u8 = x ^ 0x80`, etc.
799 #[inline]
800 fn ct_gt(&self, other: &$t_u) -> Choice {
801 let gtb = self & !other; // All the bits in self that are greater than their corresponding bits in other.
802 let mut ltb = !self & other; // All the bits in self that are less than their corresponding bits in other.
803 let mut pow = 1;
804
805 // Less-than operator is okay here because it's dependent on the bit-width.
806 while pow < $bit_width {
807 ltb |= ltb >> pow; // Bit-smear the highest set bit to the right.
808 pow += pow;
809 }
810 let mut bit = gtb & !ltb; // Select the highest set bit.
811 let mut pow = 1;
812
813 while pow < $bit_width {
814 bit |= bit >> pow; // Shift it to the right until we end up with either 0 or 1.
815 pow += pow;
816 }
817 // XXX We should possibly do the above flattening to 0 or 1 in the
818 // Choice constructor rather than making it a debug error?
819 Choice::from((bit & 1) as u8)
820 }
821 }
822 }
823}
824
825generate_unsigned_integer_greater!(u8, 8);
826generate_unsigned_integer_greater!(u16, 16);
827generate_unsigned_integer_greater!(u32, 32);
828generate_unsigned_integer_greater!(u64, 64);
829#[cfg(feature = "i128")]
830generate_unsigned_integer_greater!(u128, 128);
831
832/// A type which can be compared in some manner and be determined to be less
833/// than another of the same type.
834pub trait ConstantTimeLess: ConstantTimeEq + ConstantTimeGreater {
835 /// Determine whether `self < other`.
836 ///
837 /// The bitwise-NOT of the return value of this function should be usable to
838 /// determine if `self >= other`.
839 ///
840 /// A default implementation is provided and implemented for the unsigned
841 /// integer types.
842 ///
843 /// This function should execute in constant time.
844 ///
845 /// # Returns
846 ///
847 /// A `Choice` with a set bit if `self < other`, and with no set bits
848 /// otherwise.
849 ///
850 /// # Example
851 ///
852 /// ```
853 /// # extern crate subtle;
854 /// use subtle::ConstantTimeLess;
855 ///
856 /// let x: u8 = 13;
857 /// let y: u8 = 42;
858 ///
859 /// let x_lt_y = x.ct_lt(&y);
860 ///
861 /// assert_eq!(x_lt_y.unwrap_u8(), 1);
862 ///
863 /// let y_lt_x = y.ct_lt(&x);
864 ///
865 /// assert_eq!(y_lt_x.unwrap_u8(), 0);
866 ///
867 /// let x_lt_x = x.ct_lt(&x);
868 ///
869 /// assert_eq!(x_lt_x.unwrap_u8(), 0);
870 /// ```
871 #[inline]
872 fn ct_lt(&self, other: &Self) -> Choice {
873 !self.ct_gt(other) & !self.ct_eq(other)
874 }
875}
876
877impl ConstantTimeLess for u8 {}
878impl ConstantTimeLess for u16 {}
879impl ConstantTimeLess for u32 {}
880impl ConstantTimeLess for u64 {}
881#[cfg(feature = "i128")]
882impl ConstantTimeLess for u128 {}