@@ -258,6 +258,11 @@ impl From<u8> for Choice {
258258 }
259259}
260260
261+ /// Marker trait for types whose [`Clone`] impl operates in constant-time.
262+ pub trait ConstantTimeClone : Clone { }
263+
264+ impl < T : Copy > ConstantTimeClone for T { }
265+
261266/// An `Eq`-like trait that produces a `Choice` instead of a `bool`.
262267///
263268/// # Example
@@ -397,6 +402,89 @@ impl ConstantTimeEq for cmp::Ordering {
397402///
398403/// This trait also provides generic implementations of conditional
399404/// assignment and conditional swaps.
405+ pub trait ConstantTimeSelect : ConstantTimeClone {
406+ /// Select `a` or `b` according to `choice`.
407+ ///
408+ /// # Returns
409+ ///
410+ /// * `a` if `choice == Choice(0)`;
411+ /// * `b` if `choice == Choice(1)`.
412+ ///
413+ /// This function should execute in constant time.
414+ ///
415+ /// # Example
416+ ///
417+ /// ```
418+ /// use subtle::ConstantTimeSelect;
419+ /// #
420+ /// # fn main() {
421+ /// let x: u8 = 13;
422+ /// let y: u8 = 42;
423+ ///
424+ /// let z = u8::ct_select(&x, &y, 0.into());
425+ /// assert_eq!(z, x);
426+ /// let z = u8::ct_select(&x, &y, 1.into());
427+ /// assert_eq!(z, y);
428+ /// # }
429+ /// ```
430+ fn ct_select ( a : & Self , b : & Self , choice : Choice ) -> Self ;
431+
432+ /// Conditionally assign `other` to `self`, according to `choice`.
433+ ///
434+ /// This function should execute in constant time.
435+ ///
436+ /// # Example
437+ ///
438+ /// ```
439+ /// use subtle::ConstantTimeSelect;
440+ /// #
441+ /// # fn main() {
442+ /// let mut x: u8 = 13;
443+ /// let mut y: u8 = 42;
444+ ///
445+ /// x.ct_assign(&y, 0.into());
446+ /// assert_eq!(x, 13);
447+ /// x.ct_assign(&y, 1.into());
448+ /// assert_eq!(x, 42);
449+ /// # }
450+ /// ```
451+ #[ inline]
452+ fn ct_assign ( & mut self , other : & Self , choice : Choice ) {
453+ * self = Self :: ct_select ( self , other, choice) ;
454+ }
455+
456+ /// Conditionally swap `self` and `other` if `choice == 1`; otherwise,
457+ /// reassign both unto themselves.
458+ ///
459+ /// This function should execute in constant time.
460+ ///
461+ /// # Example
462+ ///
463+ /// ```
464+ /// use subtle::ConstantTimeSelect;
465+ /// #
466+ /// # fn main() {
467+ /// let mut x: u8 = 13;
468+ /// let mut y: u8 = 42;
469+ ///
470+ /// u8::ct_swap(&mut x, &mut y, 0.into());
471+ /// assert_eq!(x, 13);
472+ /// assert_eq!(y, 42);
473+ /// u8::ct_swap(&mut x, &mut y, 1.into());
474+ /// assert_eq!(x, 42);
475+ /// assert_eq!(y, 13);
476+ /// # }
477+ /// ```
478+ #[ inline]
479+ fn ct_swap ( a : & mut Self , b : & mut Self , choice : Choice ) {
480+ let t: Self = a. clone ( ) ;
481+ a. ct_assign ( & b, choice) ;
482+ b. ct_assign ( & t, choice) ;
483+ }
484+ }
485+
486+ /// Deprecated legacy equivalent of [`ConstantTimeSelect`]: please migrate to the new trait.
487+ #[ deprecated( since = "2.6.0" , note = "use ConstantTimeSelect instead" ) ]
400488pub trait ConditionallySelectable : Copy {
401489 /// Select `a` or `b` according to `choice`.
402490 ///
@@ -422,7 +510,6 @@ pub trait ConditionallySelectable: Copy {
422510 /// assert_eq!(z, y);
423511 /// # }
424512 /// ```
425- #[ inline]
426513 fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self ;
427514
428515 /// Conditionally assign `other` to `self`, according to `choice`.
@@ -479,6 +566,24 @@ pub trait ConditionallySelectable: Copy {
479566 }
480567}
481568
569+ #[ allow( deprecated) ]
570+ impl < T : ConditionallySelectable > ConstantTimeSelect for T {
571+ #[ inline]
572+ fn ct_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
573+ Self :: conditional_select ( a, b, choice)
574+ }
575+
576+ #[ inline]
577+ fn ct_assign ( & mut self , other : & Self , choice : Choice ) {
578+ Self :: conditional_assign ( self , other, choice)
579+ }
580+
581+ #[ inline]
582+ fn ct_swap ( a : & mut Self , b : & mut Self , choice : Choice ) {
583+ Self :: conditional_swap ( a, b, choice)
584+ }
585+ }
586+
482587macro_rules! to_signed_int {
483588 ( u8 ) => {
484589 i8
@@ -514,6 +619,7 @@ macro_rules! to_signed_int {
514619
515620macro_rules! generate_integer_conditional_select {
516621 ( $( $t: tt) * ) => ( $(
622+ #[ allow( deprecated) ]
517623 impl ConditionallySelectable for $t {
518624 #[ inline]
519625 fn conditional_select( a: & Self , b: & Self , choice: Choice ) -> Self {
@@ -559,6 +665,7 @@ generate_integer_conditional_select!(u128 i128);
559665///
560666/// Given this, it's possible to operate on orderings as if they're integers,
561667/// which allows leveraging conditional masking for predication.
668+ #[ allow( deprecated) ]
562669impl ConditionallySelectable for cmp:: Ordering {
563670 fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
564671 let a = * a as i8 ;
@@ -571,6 +678,7 @@ impl ConditionallySelectable for cmp::Ordering {
571678 }
572679}
573680
681+ #[ allow( deprecated) ]
574682impl ConditionallySelectable for Choice {
575683 #[ inline]
576684 fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
@@ -579,6 +687,7 @@ impl ConditionallySelectable for Choice {
579687}
580688
581689#[ cfg( feature = "const-generics" ) ]
690+ #[ allow( deprecated) ]
582691impl < T , const N : usize > ConditionallySelectable for [ T ; N ]
583692where
584693 T : ConditionallySelectable ,
@@ -613,6 +722,7 @@ pub trait ConditionallyNegatable {
613722 fn conditional_negate ( & mut self , choice : Choice ) ;
614723}
615724
725+ #[ allow( deprecated) ]
616726impl < T > ConditionallyNegatable for T
617727where
618728 T : ConditionallySelectable ,
@@ -710,9 +820,9 @@ impl<T> CtOption<T> {
710820 #[ inline]
711821 pub fn unwrap_or ( self , def : T ) -> T
712822 where
713- T : ConditionallySelectable ,
823+ T : ConstantTimeSelect ,
714824 {
715- T :: conditional_select ( & def, & self . value , self . is_some )
825+ T :: ct_select ( & def, & self . value , self . is_some )
716826 }
717827
718828 /// This returns the underlying value if it is `Some`
@@ -723,10 +833,10 @@ impl<T> CtOption<T> {
723833 #[ inline]
724834 pub fn unwrap_or_else < F > ( self , f : F ) -> T
725835 where
726- T : ConditionallySelectable ,
836+ T : ConstantTimeSelect ,
727837 F : FnOnce ( ) -> T ,
728838 {
729- T :: conditional_select ( & f ( ) , & self . value , self . is_some )
839+ T :: ct_select ( & f ( ) , & self . value , self . is_some )
730840 }
731841
732842 /// Returns a true `Choice` if this value is `Some`.
@@ -752,17 +862,9 @@ impl<T> CtOption<T> {
752862 #[ inline]
753863 pub fn map < U , F > ( self , f : F ) -> CtOption < U >
754864 where
755- T : Default + ConditionallySelectable ,
756865 F : FnOnce ( T ) -> U ,
757866 {
758- CtOption :: new (
759- f ( T :: conditional_select (
760- & T :: default ( ) ,
761- & self . value ,
762- self . is_some ,
763- ) ) ,
764- self . is_some ,
765- )
867+ CtOption :: new ( f ( self . value ) , self . is_some )
766868 }
767869
768870 /// Returns a `None` value if the option is `None`, otherwise
@@ -775,34 +877,31 @@ impl<T> CtOption<T> {
775877 #[ inline]
776878 pub fn and_then < U , F > ( self , f : F ) -> CtOption < U >
777879 where
778- T : Default + ConditionallySelectable ,
779880 F : FnOnce ( T ) -> CtOption < U > ,
780881 {
781- let mut tmp = f ( T :: conditional_select (
782- & T :: default ( ) ,
783- & self . value ,
784- self . is_some ,
785- ) ) ;
786- tmp. is_some &= self . is_some ;
787-
788- tmp
882+ let mut ret = f ( self . value ) ;
883+ ret. is_some &= self . is_some ;
884+ ret
789885 }
790886
791887 /// Returns `self` if it contains a value, and otherwise returns the result of
792888 /// calling `f`. The provided function `f` is always called.
793889 #[ inline]
794890 pub fn or_else < F > ( self , f : F ) -> CtOption < T >
795891 where
796- T : ConditionallySelectable ,
892+ T : ConstantTimeSelect ,
797893 F : FnOnce ( ) -> CtOption < T > ,
798894 {
799- let is_none = self . is_none ( ) ;
895+ let mut is_some = self . is_some ( ) ;
800896 let f = f ( ) ;
801897
802- Self :: conditional_select ( & self , & f, is_none)
898+ let value = T :: ct_select ( & f. value , & self . value , is_some) ;
899+ is_some |= f. is_some ( ) ;
900+ CtOption :: new ( value, is_some)
803901 }
804902}
805903
904+ #[ allow( deprecated) ]
806905impl < T : ConditionallySelectable > ConditionallySelectable for CtOption < T > {
807906 fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
808907 CtOption :: new (
0 commit comments