@@ -289,12 +289,6 @@ pub trait ConstantTimeEq {
289289impl < T : ConstantTimeEq > ConstantTimeEq for [ T ] {
290290 /// Check whether two slices of `ConstantTimeEq` types are equal.
291291 ///
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- ///
298292 /// Since arrays coerce to slices, this function works with fixed-size arrays:
299293 ///
300294 /// ```
@@ -311,23 +305,17 @@ impl<T: ConstantTimeEq> ConstantTimeEq for [T] {
311305 /// ```
312306 #[ inline]
313307 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 ( ) ) ;
321310
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 ;
326313 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 ( ) ;
328315 }
329316
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 ( )
331319 }
332320}
333321
0 commit comments