/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://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] |
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 {} |