@@ -286,12 +286,6 @@ pub trait ConstantTimeEq {
286286impl < 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
0 commit comments