Skip to content

Commit 9eb91e9

Browse files
committed
Harden constant-time equality on arrays and slices
1 parent 74360d7 commit 9eb91e9

File tree

2 files changed

+9
-22
lines changed

2 files changed

+9
-22
lines changed

src/lib.rs

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,6 @@ pub trait ConstantTimeEq {
286286
impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
287287
/// Check whether two slices of `ConstantTimeEq` types are equal.
288288
///
289-
/// # Note
290-
///
291-
/// This function short-circuits if the lengths of the input slices
292-
/// are different. Otherwise, it should execute in time independent
293-
/// of the slice contents.
294-
///
295289
/// Since arrays coerce to slices, this function works with fixed-size arrays:
296290
///
297291
/// ```
@@ -308,23 +302,17 @@ impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
308302
/// ```
309303
#[inline]
310304
fn ct_eq(&self, _rhs: &[T]) -> Choice {
311-
let len = self.len();
312-
313-
// Short-circuit on the *lengths* of the slices, not their
314-
// contents.
315-
if len != _rhs.len() {
316-
return Choice::from(0);
317-
}
305+
// Determine if the lengths are equal in constant time
306+
let len_ct_eq = self.len().ct_eq(&_rhs.len());
318307

319-
// This loop shouldn't be shortcircuitable, since the compiler
320-
// shouldn't be able to reason about the value of the `u8`
321-
// unwrapped from the `ct_eq` result.
322-
let mut x = 1u8;
308+
// Check each byte for equality in constant time
309+
let mut contents_ct_eq = Choice::from(1u8);
323310
for (ai, bi) in self.iter().zip(_rhs.iter()) {
324-
x &= ai.ct_eq(bi).unwrap_u8();
311+
contents_ct_eq &= ai.ct_eq(bi);
325312
}
326313

327-
x.into()
314+
// Now check that the length and bytes are both equal in constant time
315+
len_ct_eq & contents_ct_eq
328316
}
329317
}
330318

tests/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ use rand::RngCore;
66
use subtle::*;
77

88
#[test]
9-
#[should_panic]
10-
fn slices_equal_different_lengths() {
9+
fn slices_different_lengths() {
1110
let a: [u8; 3] = [0, 0, 0];
1211
let b: [u8; 4] = [0, 0, 0, 0];
1312

14-
assert_eq!((&a).ct_eq(&b).unwrap_u8(), 1);
13+
assert_eq!((&a).ct_eq(&b).unwrap_u8(), 0);
1514
}
1615

1716
#[test]

0 commit comments

Comments
 (0)