@@ -258,6 +258,11 @@ impl From<u8> for Choice {
258
258
}
259
259
}
260
260
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
+
261
266
/// An `Eq`-like trait that produces a `Choice` instead of a `bool`.
262
267
///
263
268
/// # Example
@@ -397,6 +402,89 @@ impl ConstantTimeEq for cmp::Ordering {
397
402
///
398
403
/// This trait also provides generic implementations of conditional
399
404
/// 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" ) ]
400
488
pub trait ConditionallySelectable : Copy {
401
489
/// Select `a` or `b` according to `choice`.
402
490
///
@@ -422,7 +510,6 @@ pub trait ConditionallySelectable: Copy {
422
510
/// assert_eq!(z, y);
423
511
/// # }
424
512
/// ```
425
- #[ inline]
426
513
fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self ;
427
514
428
515
/// Conditionally assign `other` to `self`, according to `choice`.
@@ -479,6 +566,24 @@ pub trait ConditionallySelectable: Copy {
479
566
}
480
567
}
481
568
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
+
482
587
macro_rules! to_signed_int {
483
588
( u8 ) => {
484
589
i8
@@ -514,6 +619,7 @@ macro_rules! to_signed_int {
514
619
515
620
macro_rules! generate_integer_conditional_select {
516
621
( $( $t: tt) * ) => ( $(
622
+ #[ allow( deprecated) ]
517
623
impl ConditionallySelectable for $t {
518
624
#[ inline]
519
625
fn conditional_select( a: & Self , b: & Self , choice: Choice ) -> Self {
@@ -559,6 +665,7 @@ generate_integer_conditional_select!(u128 i128);
559
665
///
560
666
/// Given this, it's possible to operate on orderings as if they're integers,
561
667
/// which allows leveraging conditional masking for predication.
668
+ #[ allow( deprecated) ]
562
669
impl ConditionallySelectable for cmp:: Ordering {
563
670
fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
564
671
let a = * a as i8 ;
@@ -571,6 +678,7 @@ impl ConditionallySelectable for cmp::Ordering {
571
678
}
572
679
}
573
680
681
+ #[ allow( deprecated) ]
574
682
impl ConditionallySelectable for Choice {
575
683
#[ inline]
576
684
fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
@@ -579,6 +687,7 @@ impl ConditionallySelectable for Choice {
579
687
}
580
688
581
689
#[ cfg( feature = "const-generics" ) ]
690
+ #[ allow( deprecated) ]
582
691
impl < T , const N : usize > ConditionallySelectable for [ T ; N ]
583
692
where
584
693
T : ConditionallySelectable ,
@@ -613,6 +722,7 @@ pub trait ConditionallyNegatable {
613
722
fn conditional_negate ( & mut self , choice : Choice ) ;
614
723
}
615
724
725
+ #[ allow( deprecated) ]
616
726
impl < T > ConditionallyNegatable for T
617
727
where
618
728
T : ConditionallySelectable ,
@@ -710,9 +820,9 @@ impl<T> CtOption<T> {
710
820
#[ inline]
711
821
pub fn unwrap_or ( self , def : T ) -> T
712
822
where
713
- T : ConditionallySelectable ,
823
+ T : ConstantTimeSelect ,
714
824
{
715
- T :: conditional_select ( & def, & self . value , self . is_some )
825
+ T :: ct_select ( & def, & self . value , self . is_some )
716
826
}
717
827
718
828
/// This returns the underlying value if it is `Some`
@@ -723,10 +833,10 @@ impl<T> CtOption<T> {
723
833
#[ inline]
724
834
pub fn unwrap_or_else < F > ( self , f : F ) -> T
725
835
where
726
- T : ConditionallySelectable ,
836
+ T : ConstantTimeSelect ,
727
837
F : FnOnce ( ) -> T ,
728
838
{
729
- T :: conditional_select ( & f ( ) , & self . value , self . is_some )
839
+ T :: ct_select ( & f ( ) , & self . value , self . is_some )
730
840
}
731
841
732
842
/// Returns a true `Choice` if this value is `Some`.
@@ -752,17 +862,9 @@ impl<T> CtOption<T> {
752
862
#[ inline]
753
863
pub fn map < U , F > ( self , f : F ) -> CtOption < U >
754
864
where
755
- T : Default + ConditionallySelectable ,
756
865
F : FnOnce ( T ) -> U ,
757
866
{
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 )
766
868
}
767
869
768
870
/// Returns a `None` value if the option is `None`, otherwise
@@ -775,34 +877,31 @@ impl<T> CtOption<T> {
775
877
#[ inline]
776
878
pub fn and_then < U , F > ( self , f : F ) -> CtOption < U >
777
879
where
778
- T : Default + ConditionallySelectable ,
779
880
F : FnOnce ( T ) -> CtOption < U > ,
780
881
{
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
789
885
}
790
886
791
887
/// Returns `self` if it contains a value, and otherwise returns the result of
792
888
/// calling `f`. The provided function `f` is always called.
793
889
#[ inline]
794
890
pub fn or_else < F > ( self , f : F ) -> CtOption < T >
795
891
where
796
- T : ConditionallySelectable ,
892
+ T : ConstantTimeSelect ,
797
893
F : FnOnce ( ) -> CtOption < T > ,
798
894
{
799
- let is_none = self . is_none ( ) ;
895
+ let mut is_some = self . is_some ( ) ;
800
896
let f = f ( ) ;
801
897
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)
803
901
}
804
902
}
805
903
904
+ #[ allow( deprecated) ]
806
905
impl < T : ConditionallySelectable > ConditionallySelectable for CtOption < T > {
807
906
fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
808
907
CtOption :: new (
0 commit comments