diff --git a/src/curve.rs b/src/curve.rs index b36cc0b..b659980 100644 --- a/src/curve.rs +++ b/src/curve.rs @@ -87,6 +87,7 @@ use field::FieldElement; use scalar::Scalar; use util::bytes_equal_ct; use util::CTAssignable; +use util::CTNegateable; // ------------------------------------------------------------------------ // Compressed points @@ -734,9 +735,8 @@ fn select_precomputed_point(x: i8, points: &[T; 8]) -> T } // Now t == |x| * P. - let minus_t = -(&t); let neg_mask = (xmask & 1) as u8; - t.conditional_assign(&minus_t, neg_mask); + t.conditional_negate(neg_mask); // Now t == x * P. t diff --git a/src/field.rs b/src/field.rs index dc21ea3..e0e4767 100644 --- a/src/field.rs +++ b/src/field.rs @@ -803,6 +803,7 @@ impl FieldElement { mod test { use field::*; use test::Bencher; + use util::CTNegateable; #[bench] fn bench_fieldelement_a_mul_a(b: &mut Bencher) { @@ -932,4 +933,17 @@ mod test { // high bit is set to zero in to_bytes assert!(test_bytes[31] == (B_BYTES[31] & 127u8)); } + + #[test] + fn test_conditional_negate() { + let one = FieldElement([ 1,0,0,0,0,0,0,0,0,0]); + let minus_one = FieldElement([-1,0,0,0,0,0,0,0,0,0]); + let mut x = one; + x.conditional_negate(1u8); + assert_eq!(x, minus_one); + x.conditional_negate(0u8); + assert_eq!(x, minus_one); + x.conditional_negate(1u8); + assert_eq!(x, one); + } } diff --git a/src/util.rs b/src/util.rs index 1391ef8..2d08f79 100644 --- a/src/util.rs +++ b/src/util.rs @@ -11,6 +11,8 @@ //! Utility functions and tools for constant-time comparisons. +use core::ops::Neg; + /// Trait for items which can be conditionally assigned in constant time. pub trait CTAssignable { /// If `choice == 1u8`, assign `other` to `self`. @@ -19,6 +21,26 @@ pub trait CTAssignable { fn conditional_assign(&mut self, other: &Self, choice: u8); } +/// Trait for items which can be conditionally negated in constant time. +/// +/// Note: it is not necessary to implement this trait, as a generic +/// implementation is provided. +pub trait CTNegateable +{ + /// Conditionally negate an element if `choice == 1u8`. + fn conditional_negate(&mut self, choice: u8); +} + +impl CTNegateable for T + where T: CTAssignable, for<'a> &'a T: Neg +{ + fn conditional_negate(&mut self, choice: u8) { + // Need to cast to eliminate mutability + let self_neg: T = -(self as &T); + self.conditional_assign(&self_neg, choice); + } +} + /// Check equality of two bytes in constant time. /// /// # Return