@@ -287,12 +287,6 @@ pub trait ConstantTimeEq {
287
287
impl < T : ConstantTimeEq > ConstantTimeEq for [ T ] {
288
288
/// Check whether two slices of `ConstantTimeEq` types are equal.
289
289
///
290
- /// # Note
291
- ///
292
- /// This function short-circuits if the lengths of the input slices
293
- /// are different. Otherwise, it should execute in time independent
294
- /// of the slice contents.
295
- ///
296
290
/// Since arrays coerce to slices, this function works with fixed-size arrays:
297
291
///
298
292
/// ```
@@ -309,23 +303,17 @@ impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
309
303
/// ```
310
304
#[ inline]
311
305
fn ct_eq ( & self , _rhs : & [ T ] ) -> Choice {
312
- let len = self . len ( ) ;
313
-
314
- // Short-circuit on the *lengths* of the slices, not their
315
- // contents.
316
- if len != _rhs. len ( ) {
317
- return Choice :: from ( 0 ) ;
318
- }
306
+ // Determine if the lengths are equal in constant time
307
+ let len_ct_eq = self . len ( ) . ct_eq ( & _rhs. len ( ) ) ;
319
308
320
- // This loop shouldn't be shortcircuitable, since the compiler
321
- // shouldn't be able to reason about the value of the `u8`
322
- // unwrapped from the `ct_eq` result.
323
- let mut x = 1u8 ;
309
+ // Check each byte for equality in constant time
310
+ let mut contents_ct_eq = Choice :: from ( 1u8 ) ;
324
311
for ( ai, bi) in self . iter ( ) . zip ( _rhs. iter ( ) ) {
325
- x &= ai. ct_eq ( bi) . unwrap_u8 ( ) ;
312
+ contents_ct_eq &= ai. ct_eq ( bi) ;
326
313
}
327
314
328
- x. into ( )
315
+ // Now check that the length and bytes are both equal in constant time
316
+ len_ct_eq & contents_ct_eq
329
317
}
330
318
}
331
319
0 commit comments