Coverage Report

Created: 2026-03-31 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.4.1/src/lib.rs
Line
Count
Source
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
86
#[cfg(feature = "std")]
87
#[macro_use]
88
extern crate std;
89
90
use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Neg, Not};
91
use 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)]
111
pub struct Choice(u8);
112
113
impl 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
80.0k
    pub fn unwrap_u8(&self) -> u8 {
125
80.0k
        self.0
126
80.0k
    }
127
}
128
129
impl From<Choice> for bool {
130
    /// Convert the `Choice` wrapper into a `bool`, depending on whether
131
    /// the underlying `u8` was a `0` or a `1`.
132
    ///
133
    /// # Note
134
    ///
135
    /// This function exists to avoid having higher-level cryptographic protocol
136
    /// implementations duplicating this pattern.
137
    ///
138
    /// The intended use case for this conversion is at the _end_ of a
139
    /// higher-level primitive implementation: for example, in checking a keyed
140
    /// MAC, where the verification should happen in constant-time (and thus use
141
    /// a `Choice`) but it is safe to return a `bool` at the end of the
142
    /// verification.
143
    #[inline]
144
1.29k
    fn from(source: Choice) -> bool {
145
1.29k
        debug_assert!((source.0 == 0u8) | (source.0 == 1u8));
146
1.29k
        source.0 != 0
147
1.29k
    }
148
}
149
150
impl BitAnd for Choice {
151
    type Output = Choice;
152
    #[inline]
153
0
    fn bitand(self, rhs: Choice) -> Choice {
154
0
        (self.0 & rhs.0).into()
155
0
    }
156
}
157
158
impl BitAndAssign for Choice {
159
    #[inline]
160
0
    fn bitand_assign(&mut self, rhs: Choice) {
161
0
        *self = *self & rhs;
162
0
    }
163
}
164
165
impl BitOr for Choice {
166
    type Output = Choice;
167
    #[inline]
168
0
    fn bitor(self, rhs: Choice) -> Choice {
169
0
        (self.0 | rhs.0).into()
170
0
    }
171
}
172
173
impl BitOrAssign for Choice {
174
    #[inline]
175
0
    fn bitor_assign(&mut self, rhs: Choice) {
176
0
        *self = *self | rhs;
177
0
    }
178
}
179
180
impl BitXor for Choice {
181
    type Output = Choice;
182
    #[inline]
183
0
    fn bitxor(self, rhs: Choice) -> Choice {
184
0
        (self.0 ^ rhs.0).into()
185
0
    }
186
}
187
188
impl BitXorAssign for Choice {
189
    #[inline]
190
0
    fn bitxor_assign(&mut self, rhs: Choice) {
191
0
        *self = *self ^ rhs;
192
0
    }
193
}
194
195
impl Not for Choice {
196
    type Output = Choice;
197
    #[inline]
198
0
    fn not(self) -> Choice {
199
0
        (1u8 & (!self.0)).into()
200
0
    }
201
}
202
203
/// This function is a best-effort attempt to prevent the compiler from knowing
204
/// anything about the value of the returned `u8`, other than its type.
205
///
206
/// Because we want to support stable Rust, we don't have access to inline
207
/// assembly or test::black_box, so we use the fact that volatile values will
208
/// never be elided to register values.
209
///
210
/// Note: Rust's notion of "volatile" is subject to change over time. While this
211
/// code may break in a non-destructive way in the future, “constant-time” code
212
/// is a continually moving target, and this is better than doing nothing.
213
#[inline(never)]
214
81.2k
fn black_box(input: u8) -> u8 {
215
81.2k
    debug_assert!((input == 0u8) | (input == 1u8));
216
217
    unsafe {
218
        // Optimization barrier
219
        //
220
        // Unsafe is ok, because:
221
        //   - &input is not NULL;
222
        //   - size of input is not zero;
223
        //   - u8 is neither Sync, nor Send;
224
        //   - u8 is Copy, so input is always live;
225
        //   - u8 type is always properly aligned.
226
81.2k
        core::ptr::read_volatile(&input as *const u8)
227
    }
228
81.2k
}
229
230
impl From<u8> for Choice {
231
    #[inline]
232
81.2k
    fn from(input: u8) -> Choice {
233
        // Our goal is to prevent the compiler from inferring that the value held inside the
234
        // resulting `Choice` struct is really an `i1` instead of an `i8`.
235
81.2k
        Choice(black_box(input))
236
81.2k
    }
237
}
238
239
/// An `Eq`-like trait that produces a `Choice` instead of a `bool`.
240
///
241
/// # Example
242
///
243
/// ```
244
/// use subtle::ConstantTimeEq;
245
/// let x: u8 = 5;
246
/// let y: u8 = 13;
247
///
248
/// assert_eq!(x.ct_eq(&y).unwrap_u8(), 0);
249
/// assert_eq!(x.ct_eq(&x).unwrap_u8(), 1);
250
/// ```
251
pub trait ConstantTimeEq {
252
    /// Determine if two items are equal.
253
    ///
254
    /// The `ct_eq` function should execute in constant time.
255
    ///
256
    /// # Returns
257
    ///
258
    /// * `Choice(1u8)` if `self == other`;
259
    /// * `Choice(0u8)` if `self != other`.
260
    #[inline]
261
    fn ct_eq(&self, other: &Self) -> Choice;
262
}
263
264
impl<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 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
4.78k
    fn ct_eq(&self, _rhs: &[T]) -> Choice {
289
4.78k
        let len = self.len();
290
291
        // Short-circuit on the *lengths* of the slices, not their
292
        // contents.
293
4.78k
        if len != _rhs.len() {
294
0
            return Choice::from(0);
295
4.78k
        }
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
4.78k
        let mut x = 1u8;
301
76.5k
        for (ai, bi) in self.iter().zip(_rhs.iter()) {
302
76.5k
            x &= ai.ct_eq(bi).unwrap_u8();
303
76.5k
        }
304
305
4.78k
        x.into()
306
4.78k
    }
<[u8] as subtle::ConstantTimeEq>::ct_eq
Line
Count
Source
288
1.29k
    fn ct_eq(&self, _rhs: &[T]) -> Choice {
289
1.29k
        let len = self.len();
290
291
        // Short-circuit on the *lengths* of the slices, not their
292
        // contents.
293
1.29k
        if len != _rhs.len() {
294
0
            return Choice::from(0);
295
1.29k
        }
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
1.29k
        let mut x = 1u8;
301
20.6k
        for (ai, bi) in self.iter().zip(_rhs.iter()) {
302
20.6k
            x &= ai.ct_eq(bi).unwrap_u8();
303
20.6k
        }
304
305
1.29k
        x.into()
306
1.29k
    }
Unexecuted instantiation: <[_] as subtle::ConstantTimeEq>::ct_eq
<[u8] as subtle::ConstantTimeEq>::ct_eq
Line
Count
Source
288
3.49k
    fn ct_eq(&self, _rhs: &[T]) -> Choice {
289
3.49k
        let len = self.len();
290
291
        // Short-circuit on the *lengths* of the slices, not their
292
        // contents.
293
3.49k
        if len != _rhs.len() {
294
0
            return Choice::from(0);
295
3.49k
        }
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
3.49k
        let mut x = 1u8;
301
55.8k
        for (ai, bi) in self.iter().zip(_rhs.iter()) {
302
55.8k
            x &= ai.ct_eq(bi).unwrap_u8();
303
55.8k
        }
304
305
3.49k
        x.into()
306
3.49k
    }
307
}
308
309
impl ConstantTimeEq for Choice {
310
    #[inline]
311
0
    fn ct_eq(&self, rhs: &Choice) -> Choice {
312
0
        !(*self ^ *rhs)
313
0
    }
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.
319
macro_rules! generate_integer_equal {
320
    ($t_u:ty, $t_i:ty, $bit_width:expr) => {
321
        impl ConstantTimeEq for $t_u {
322
            #[inline]
323
76.5k
            fn ct_eq(&self, other: &$t_u) -> Choice {
324
                // x == 0 if and only if self == other
325
76.5k
                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
76.5k
                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
76.5k
                ((y ^ (1 as $t_u)) as u8).into()
333
76.5k
            }
<u8 as subtle::ConstantTimeEq>::ct_eq
Line
Count
Source
323
76.5k
            fn ct_eq(&self, other: &$t_u) -> Choice {
324
                // x == 0 if and only if self == other
325
76.5k
                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
76.5k
                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
76.5k
                ((y ^ (1 as $t_u)) as u8).into()
333
76.5k
            }
Unexecuted instantiation: <u16 as subtle::ConstantTimeEq>::ct_eq
Unexecuted instantiation: <u32 as subtle::ConstantTimeEq>::ct_eq
Unexecuted instantiation: <u64 as subtle::ConstantTimeEq>::ct_eq
Unexecuted instantiation: <usize as subtle::ConstantTimeEq>::ct_eq
334
        }
335
        impl ConstantTimeEq for $t_i {
336
            #[inline]
337
0
            fn ct_eq(&self, other: &$t_i) -> Choice {
338
                // Bitcast to unsigned and call that implementation.
339
0
                (*self as $t_u).ct_eq(&(*other as $t_u))
340
0
            }
Unexecuted instantiation: <i8 as subtle::ConstantTimeEq>::ct_eq
Unexecuted instantiation: <i16 as subtle::ConstantTimeEq>::ct_eq
Unexecuted instantiation: <i32 as subtle::ConstantTimeEq>::ct_eq
Unexecuted instantiation: <i64 as subtle::ConstantTimeEq>::ct_eq
Unexecuted instantiation: <isize as subtle::ConstantTimeEq>::ct_eq
341
        }
342
    };
343
}
344
345
generate_integer_equal!(u8, i8, 8);
346
generate_integer_equal!(u16, i16, 16);
347
generate_integer_equal!(u32, i32, 32);
348
generate_integer_equal!(u64, i64, 64);
349
#[cfg(feature = "i128")]
350
generate_integer_equal!(u128, i128, 128);
351
generate_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.
357
pub 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 subtle;
371
    /// use 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
    #[inline]
384
    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self;
385
386
    /// Conditionally assign `other` to `self`, according to `choice`.
387
    ///
388
    /// This function should execute in constant time.
389
    ///
390
    /// # Example
391
    ///
392
    /// ```
393
    /// # extern crate subtle;
394
    /// use subtle::ConditionallySelectable;
395
    /// #
396
    /// # fn main() {
397
    /// let mut x: u8 = 13;
398
    /// let mut y: u8 = 42;
399
    ///
400
    /// x.conditional_assign(&y, 0.into());
401
    /// assert_eq!(x, 13);
402
    /// x.conditional_assign(&y, 1.into());
403
    /// assert_eq!(x, 42);
404
    /// # }
405
    /// ```
406
    #[inline]
407
0
    fn conditional_assign(&mut self, other: &Self, choice: Choice) {
408
0
        *self = Self::conditional_select(self, other, choice);
409
0
    }
410
411
    /// Conditionally swap `self` and `other` if `choice == 1`; otherwise,
412
    /// reassign both unto themselves.
413
    ///
414
    /// This function should execute in constant time.
415
    ///
416
    /// # Example
417
    ///
418
    /// ```
419
    /// # extern crate subtle;
420
    /// use subtle::ConditionallySelectable;
421
    /// #
422
    /// # fn main() {
423
    /// let mut x: u8 = 13;
424
    /// let mut y: u8 = 42;
425
    ///
426
    /// u8::conditional_swap(&mut x, &mut y, 0.into());
427
    /// assert_eq!(x, 13);
428
    /// assert_eq!(y, 42);
429
    /// u8::conditional_swap(&mut x, &mut y, 1.into());
430
    /// assert_eq!(x, 42);
431
    /// assert_eq!(y, 13);
432
    /// # }
433
    /// ```
434
    #[inline]
435
0
    fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
436
0
        let t: Self = *a;
437
0
        a.conditional_assign(&b, choice);
438
0
        b.conditional_assign(&t, choice);
439
0
    }
440
}
441
442
macro_rules! to_signed_int {
443
    (u8) => {
444
        i8
445
    };
446
    (u16) => {
447
        i16
448
    };
449
    (u32) => {
450
        i32
451
    };
452
    (u64) => {
453
        i64
454
    };
455
    (u128) => {
456
        i128
457
    };
458
    (i8) => {
459
        i8
460
    };
461
    (i16) => {
462
        i16
463
    };
464
    (i32) => {
465
        i32
466
    };
467
    (i64) => {
468
        i64
469
    };
470
    (i128) => {
471
        i128
472
    };
473
}
474
475
macro_rules! generate_integer_conditional_select {
476
    ($($t:tt)*) => ($(
477
        impl ConditionallySelectable for $t {
478
            #[inline]
479
0
            fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
480
                // if choice = 0, mask = (-0) = 0000...0000
481
                // if choice = 1, mask = (-1) = 1111...1111
482
0
                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
483
0
                a ^ (mask & (a ^ b))
484
0
            }
Unexecuted instantiation: <i16 as subtle::ConditionallySelectable>::conditional_select
Unexecuted instantiation: <u32 as subtle::ConditionallySelectable>::conditional_select
Unexecuted instantiation: <i32 as subtle::ConditionallySelectable>::conditional_select
Unexecuted instantiation: <u64 as subtle::ConditionallySelectable>::conditional_select
Unexecuted instantiation: <i64 as subtle::ConditionallySelectable>::conditional_select
Unexecuted instantiation: <u8 as subtle::ConditionallySelectable>::conditional_select
Unexecuted instantiation: <i8 as subtle::ConditionallySelectable>::conditional_select
Unexecuted instantiation: <u16 as subtle::ConditionallySelectable>::conditional_select
485
486
            #[inline]
487
0
            fn conditional_assign(&mut self, other: &Self, choice: Choice) {
488
                // if choice = 0, mask = (-0) = 0000...0000
489
                // if choice = 1, mask = (-1) = 1111...1111
490
0
                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
491
0
                *self ^= mask & (*self ^ *other);
492
0
            }
Unexecuted instantiation: <i16 as subtle::ConditionallySelectable>::conditional_assign
Unexecuted instantiation: <u32 as subtle::ConditionallySelectable>::conditional_assign
Unexecuted instantiation: <i32 as subtle::ConditionallySelectable>::conditional_assign
Unexecuted instantiation: <u64 as subtle::ConditionallySelectable>::conditional_assign
Unexecuted instantiation: <i64 as subtle::ConditionallySelectable>::conditional_assign
Unexecuted instantiation: <u8 as subtle::ConditionallySelectable>::conditional_assign
Unexecuted instantiation: <i8 as subtle::ConditionallySelectable>::conditional_assign
Unexecuted instantiation: <u16 as subtle::ConditionallySelectable>::conditional_assign
493
494
            #[inline]
495
0
            fn conditional_swap(a: &mut Self, b: &mut Self, choice: Choice) {
496
                // if choice = 0, mask = (-0) = 0000...0000
497
                // if choice = 1, mask = (-1) = 1111...1111
498
0
                let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t;
499
0
                let t = mask & (*a ^ *b);
500
0
                *a ^= t;
501
0
                *b ^= t;
502
0
            }
Unexecuted instantiation: <i16 as subtle::ConditionallySelectable>::conditional_swap
Unexecuted instantiation: <u32 as subtle::ConditionallySelectable>::conditional_swap
Unexecuted instantiation: <i32 as subtle::ConditionallySelectable>::conditional_swap
Unexecuted instantiation: <u64 as subtle::ConditionallySelectable>::conditional_swap
Unexecuted instantiation: <i64 as subtle::ConditionallySelectable>::conditional_swap
Unexecuted instantiation: <u8 as subtle::ConditionallySelectable>::conditional_swap
Unexecuted instantiation: <i8 as subtle::ConditionallySelectable>::conditional_swap
Unexecuted instantiation: <u16 as subtle::ConditionallySelectable>::conditional_swap
503
         }
504
    )*)
505
}
506
507
generate_integer_conditional_select!(  u8   i8);
508
generate_integer_conditional_select!( u16  i16);
509
generate_integer_conditional_select!( u32  i32);
510
generate_integer_conditional_select!( u64  i64);
511
#[cfg(feature = "i128")]
512
generate_integer_conditional_select!(u128 i128);
513
514
impl ConditionallySelectable for Choice {
515
    #[inline]
516
0
    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
517
0
        Choice(u8::conditional_select(&a.0, &b.0, choice))
518
0
    }
519
}
520
521
/// A type which can be conditionally negated in constant time.
522
///
523
/// # Note
524
///
525
/// A generic implementation of `ConditionallyNegatable` is provided
526
/// for types `T` which are `ConditionallySelectable` and have `Neg`
527
/// implemented on `&T`.
528
pub trait ConditionallyNegatable {
529
    /// Negate `self` if `choice == Choice(1)`; otherwise, leave it
530
    /// unchanged.
531
    ///
532
    /// This function should execute in constant time.
533
    #[inline]
534
    fn conditional_negate(&mut self, choice: Choice);
535
}
536
537
impl<T> ConditionallyNegatable for T
538
where
539
    T: ConditionallySelectable,
540
    for<'a> &'a T: Neg<Output = T>,
541
{
542
    #[inline]
543
0
    fn conditional_negate(&mut self, choice: Choice) {
544
        // Need to cast to eliminate mutability
545
0
        let self_neg: T = -(self as &T);
546
0
        self.conditional_assign(&self_neg, choice);
547
0
    }
548
}
549
550
/// The `CtOption<T>` type represents an optional value similar to the
551
/// [`Option<T>`](core::option::Option) type but is intended for
552
/// use in constant time APIs.
553
///
554
/// Any given `CtOption<T>` is either `Some` or `None`, but unlike
555
/// `Option<T>` these variants are not exposed. The
556
/// [`is_some()`](CtOption::is_some) method is used to determine if
557
/// the value is `Some`, and [`unwrap_or()`](CtOption::unwrap_or) and
558
/// [`unwrap_or_else()`](CtOption::unwrap_or_else) methods are
559
/// provided to access the underlying value. The value can also be
560
/// obtained with [`unwrap()`](CtOption::unwrap) but this will panic
561
/// if it is `None`.
562
///
563
/// Functions that are intended to be constant time may not produce
564
/// valid results for all inputs, such as square root and inversion
565
/// operations in finite field arithmetic. Returning an `Option<T>`
566
/// from these functions makes it difficult for the caller to reason
567
/// about the result in constant time, and returning an incorrect
568
/// value burdens the caller and increases the chance of bugs.
569
#[derive(Clone, Copy, Debug)]
570
pub struct CtOption<T> {
571
    value: T,
572
    is_some: Choice,
573
}
574
575
impl<T> From<CtOption<T>> for Option<T> {
576
    /// Convert the `CtOption<T>` wrapper into an `Option<T>`, depending on whether
577
    /// the underlying `is_some` `Choice` was a `0` or a `1` once unwrapped.
578
    ///
579
    /// # Note
580
    ///
581
    /// This function exists to avoid ending up with ugly, verbose and/or bad handled
582
    /// conversions from the `CtOption<T>` wraps to an `Option<T>` or `Result<T, E>`.
583
    /// This implementation doesn't intend to be constant-time nor try to protect the
584
    /// leakage of the `T` since the `Option<T>` will do it anyways.
585
0
    fn from(source: CtOption<T>) -> Option<T> {
586
0
        if source.is_some().unwrap_u8() == 1u8 {
587
0
            Option::Some(source.value)
588
        } else {
589
0
            None
590
        }
591
0
    }
592
}
593
594
impl<T> CtOption<T> {
595
    /// This method is used to construct a new `CtOption<T>` and takes
596
    /// a value of type `T`, and a `Choice` that determines whether
597
    /// the optional value should be `Some` or not. If `is_some` is
598
    /// false, the value will still be stored but its value is never
599
    /// exposed.
600
    #[inline]
601
0
    pub fn new(value: T, is_some: Choice) -> CtOption<T> {
602
0
        CtOption {
603
0
            value: value,
604
0
            is_some: is_some,
605
0
        }
606
0
    }
607
608
    /// This returns the underlying value but panics if it
609
    /// is not `Some`.
610
    #[inline]
611
0
    pub fn unwrap(self) -> T {
612
0
        assert_eq!(self.is_some.unwrap_u8(), 1);
613
614
0
        self.value
615
0
    }
616
617
    /// This returns the underlying value if it is `Some`
618
    /// or the provided value otherwise.
619
    #[inline]
620
0
    pub fn unwrap_or(self, def: T) -> T
621
0
    where
622
0
        T: ConditionallySelectable,
623
    {
624
0
        T::conditional_select(&def, &self.value, self.is_some)
625
0
    }
626
627
    /// This returns the underlying value if it is `Some`
628
    /// or the value produced by the provided closure otherwise.
629
    #[inline]
630
0
    pub fn unwrap_or_else<F>(self, f: F) -> T
631
0
    where
632
0
        T: ConditionallySelectable,
633
0
        F: FnOnce() -> T,
634
    {
635
0
        T::conditional_select(&f(), &self.value, self.is_some)
636
0
    }
637
638
    /// Returns a true `Choice` if this value is `Some`.
639
    #[inline]
640
0
    pub fn is_some(&self) -> Choice {
641
0
        self.is_some
642
0
    }
643
644
    /// Returns a true `Choice` if this value is `None`.
645
    #[inline]
646
0
    pub fn is_none(&self) -> Choice {
647
0
        !self.is_some
648
0
    }
649
650
    /// Returns a `None` value if the option is `None`, otherwise
651
    /// returns a `CtOption` enclosing the value of the provided closure.
652
    /// The closure is given the enclosed value or, if the option is
653
    /// `None`, it is provided a dummy value computed using
654
    /// `Default::default()`.
655
    ///
656
    /// This operates in constant time, because the provided closure
657
    /// is always called.
658
    #[inline]
659
0
    pub fn map<U, F>(self, f: F) -> CtOption<U>
660
0
    where
661
0
        T: Default + ConditionallySelectable,
662
0
        F: FnOnce(T) -> U,
663
    {
664
0
        CtOption::new(
665
0
            f(T::conditional_select(
666
0
                &T::default(),
667
0
                &self.value,
668
0
                self.is_some,
669
0
            )),
670
0
            self.is_some,
671
        )
672
0
    }
673
674
    /// Returns a `None` value if the option is `None`, otherwise
675
    /// returns the result of the provided closure. The closure is
676
    /// given the enclosed value or, if the option is `None`, it
677
    /// is provided a dummy value computed using `Default::default()`.
678
    ///
679
    /// This operates in constant time, because the provided closure
680
    /// is always called.
681
    #[inline]
682
0
    pub fn and_then<U, F>(self, f: F) -> CtOption<U>
683
0
    where
684
0
        T: Default + ConditionallySelectable,
685
0
        F: FnOnce(T) -> CtOption<U>,
686
    {
687
0
        let mut tmp = f(T::conditional_select(
688
0
            &T::default(),
689
0
            &self.value,
690
0
            self.is_some,
691
0
        ));
692
0
        tmp.is_some &= self.is_some;
693
694
0
        tmp
695
0
    }
696
697
    /// Returns `self` if it contains a value, and otherwise returns the result of
698
    /// calling `f`. The provided function `f` is always called.
699
    #[inline]
700
0
    pub fn or_else<F>(self, f: F) -> CtOption<T>
701
0
    where
702
0
        T: ConditionallySelectable,
703
0
        F: FnOnce() -> CtOption<T>,
704
    {
705
0
        let is_none = self.is_none();
706
0
        let f = f();
707
708
0
        Self::conditional_select(&self, &f, is_none)
709
0
    }
710
}
711
712
impl<T: ConditionallySelectable> ConditionallySelectable for CtOption<T> {
713
0
    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
714
0
        CtOption::new(
715
0
            T::conditional_select(&a.value, &b.value, choice),
716
0
            Choice::conditional_select(&a.is_some, &b.is_some, choice),
717
        )
718
0
    }
719
}
720
721
impl<T: ConstantTimeEq> ConstantTimeEq for CtOption<T> {
722
    /// Two `CtOption<T>`s are equal if they are both `Some` and
723
    /// their values are equal, or both `None`.
724
    #[inline]
725
0
    fn ct_eq(&self, rhs: &CtOption<T>) -> Choice {
726
0
        let a = self.is_some();
727
0
        let b = rhs.is_some();
728
729
0
        (a & b & self.value.ct_eq(&rhs.value)) | (!a & !b)
730
0
    }
731
}
732
733
/// A type which can be compared in some manner and be determined to be greater
734
/// than another of the same type.
735
pub trait ConstantTimeGreater {
736
    /// Determine whether `self > other`.
737
    ///
738
    /// The bitwise-NOT of the return value of this function should be usable to
739
    /// determine if `self <= other`.
740
    ///
741
    /// This function should execute in constant time.
742
    ///
743
    /// # Returns
744
    ///
745
    /// A `Choice` with a set bit if `self > other`, and with no set bits
746
    /// otherwise.
747
    ///
748
    /// # Example
749
    ///
750
    /// ```
751
    /// # extern crate subtle;
752
    /// use subtle::ConstantTimeGreater;
753
    ///
754
    /// let x: u8 = 13;
755
    /// let y: u8 = 42;
756
    ///
757
    /// let x_gt_y = x.ct_gt(&y);
758
    ///
759
    /// assert_eq!(x_gt_y.unwrap_u8(), 0);
760
    ///
761
    /// let y_gt_x = y.ct_gt(&x);
762
    ///
763
    /// assert_eq!(y_gt_x.unwrap_u8(), 1);
764
    ///
765
    /// let x_gt_x = x.ct_gt(&x);
766
    ///
767
    /// assert_eq!(x_gt_x.unwrap_u8(), 0);
768
    /// ```
769
    fn ct_gt(&self, other: &Self) -> Choice;
770
}
771
772
macro_rules! generate_unsigned_integer_greater {
773
    ($t_u: ty, $bit_width: expr) => {
774
        impl ConstantTimeGreater for $t_u {
775
            /// Returns Choice::from(1) iff x > y, and Choice::from(0) iff x <= y.
776
            ///
777
            /// # Note
778
            ///
779
            /// This algoritm would also work for signed integers if we first
780
            /// flip the top bit, e.g. `let x: u8 = x ^ 0x80`, etc.
781
            #[inline]
782
0
            fn ct_gt(&self, other: &$t_u) -> Choice {
783
0
                let gtb = self & !other; // All the bits in self that are greater than their corresponding bits in other.
784
0
                let mut ltb = !self & other; // All the bits in self that are less than their corresponding bits in other.
785
0
                let mut pow = 1;
786
787
                // Less-than operator is okay here because it's dependent on the bit-width.
788
0
                while pow < $bit_width {
789
0
                    ltb |= ltb >> pow; // Bit-smear the highest set bit to the right.
790
0
                    pow += pow;
791
0
                }
792
0
                let mut bit = gtb & !ltb; // Select the highest set bit.
793
0
                let mut pow = 1;
794
795
0
                while pow < $bit_width {
796
0
                    bit |= bit >> pow; // Shift it to the right until we end up with either 0 or 1.
797
0
                    pow += pow;
798
0
                }
799
                // XXX We should possibly do the above flattening to 0 or 1 in the
800
                //     Choice constructor rather than making it a debug error?
801
0
                Choice::from((bit & 1) as u8)
802
0
            }
Unexecuted instantiation: <u8 as subtle::ConstantTimeGreater>::ct_gt
Unexecuted instantiation: <u16 as subtle::ConstantTimeGreater>::ct_gt
Unexecuted instantiation: <u32 as subtle::ConstantTimeGreater>::ct_gt
Unexecuted instantiation: <u64 as subtle::ConstantTimeGreater>::ct_gt
803
        }
804
    }
805
}
806
807
generate_unsigned_integer_greater!(u8, 8);
808
generate_unsigned_integer_greater!(u16, 16);
809
generate_unsigned_integer_greater!(u32, 32);
810
generate_unsigned_integer_greater!(u64, 64);
811
#[cfg(feature = "i128")]
812
generate_unsigned_integer_greater!(u128, 128);
813
814
/// A type which can be compared in some manner and be determined to be less
815
/// than another of the same type.
816
pub trait ConstantTimeLess: ConstantTimeEq + ConstantTimeGreater {
817
    /// Determine whether `self < other`.
818
    ///
819
    /// The bitwise-NOT of the return value of this function should be usable to
820
    /// determine if `self >= other`.
821
    ///
822
    /// A default implementation is provided and implemented for the unsigned
823
    /// integer types.
824
    ///
825
    /// This function should execute in constant time.
826
    ///
827
    /// # Returns
828
    ///
829
    /// A `Choice` with a set bit if `self < other`, and with no set bits
830
    /// otherwise.
831
    ///
832
    /// # Example
833
    ///
834
    /// ```
835
    /// # extern crate subtle;
836
    /// use subtle::ConstantTimeLess;
837
    ///
838
    /// let x: u8 = 13;
839
    /// let y: u8 = 42;
840
    ///
841
    /// let x_lt_y = x.ct_lt(&y);
842
    ///
843
    /// assert_eq!(x_lt_y.unwrap_u8(), 1);
844
    ///
845
    /// let y_lt_x = y.ct_lt(&x);
846
    ///
847
    /// assert_eq!(y_lt_x.unwrap_u8(), 0);
848
    ///
849
    /// let x_lt_x = x.ct_lt(&x);
850
    ///
851
    /// assert_eq!(x_lt_x.unwrap_u8(), 0);
852
    /// ```
853
    #[inline]
854
0
    fn ct_lt(&self, other: &Self) -> Choice {
855
0
        !self.ct_gt(other) & !self.ct_eq(other)
856
0
    }
857
}
858
859
impl ConstantTimeLess for u8 {}
860
impl ConstantTimeLess for u16 {}
861
impl ConstantTimeLess for u32 {}
862
impl ConstantTimeLess for u64 {}
863
#[cfg(feature = "i128")]
864
impl ConstantTimeLess for u128 {}