1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
// -*- mode: rust; -*- // // To the extent possible under law, the authors have waived all copyright and // related or neighboring rights to curve25519-dalek, using the Creative // Commons "CC0" public domain dedication. See // <http://creativecommons.org/publicdomain/zero/.0/> for full details. // // Authors: // - Isis Agora Lovecruft <isis@patternsinthevoid.net> // - Henry de Valence <hdevalence@hdevalence.ca> //! Constant-time traits and utility functions. 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`. /// Otherwise, leave `self` unchanged. /// Executes in constant time. fn conditional_assign(&mut self, other: &Self, choice: u8); } /// Trait for items whose equality to another item may be tested in constant time. pub trait CTEq { /// Determine if two items are equal in constant time. /// /// # Returns /// /// `1u8` if the two items are equal, and `0u8` otherwise. fn ct_eq(&self, other: &Self) -> 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 CTNegatable { /// Conditionally negate an element if `choice == 1u8`. fn conditional_negate(&mut self, choice: u8); } impl<T> CTNegatable for T where T: CTAssignable, for<'a> &'a T: Neg<Output=T> { 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 /// /// Returns `1u8` if `a == b` and `0u8` otherwise. #[inline(always)] pub fn bytes_equal_ct(a: u8, b: u8) -> u8 { let mut x: u8; x = !(a ^ b); x &= x >> 4; x &= x >> 2; x &= x >> 1; x } /// Test if a byte is non-zero in constant time. /// /// ```rust,ignore /// let mut x: u8; /// x = 0; /// assert!(byte_is_nonzero(x)); /// x = 3; /// assert!(byte_is_nonzero(x) == 1); /// ``` /// /// # Return /// /// * If b != 0, returns 1u8. /// * If b == 0, returns 0u8. #[inline(always)] pub fn byte_is_nonzero(b: u8) -> u8 { let mut x = b; x |= x >> 4; x |= x >> 2; x |= x >> 1; (x & 1) } /// Check equality of two 32-byte arrays in constant time. /// /// # Return /// /// Returns `1u8` if `a == b` and `0u8` otherwise. #[inline(always)] pub fn arrays_equal_ct(a: &[u8; 32], b: &[u8; 32]) -> u8 { let mut x: u8 = 0; for i in 0..32 { x |= a[i] ^ b[i]; } bytes_equal_ct(x, 0) }