@@ -287,12 +287,6 @@ pub trait ConstantTimeEq {
287287impl < T : ConstantTimeEq > ConstantTimeEq for [ T ] {
288288 /// Check whether two slices of `ConstantTimeEq` types are equal.
289289 ///
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- ///
296290 /// Since arrays coerce to slices, this function works with fixed-size arrays:
297291 ///
298292 /// ```
@@ -309,23 +303,17 @@ impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
309303 /// ```
310304 #[ inline]
311305 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 ( ) ) ;
319308
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 ) ;
324311 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) ;
326313 }
327314
328- x. into ( )
315+ // Now check that the length and bytes are both equal in constant time
316+ len_ct_eq & contents_ct_eq
329317 }
330318}
331319
0 commit comments