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