diff --git a/frodo-kem/src/hazmat/traits.rs b/frodo-kem/src/hazmat/traits.rs index cc271b1..e755a62 100644 --- a/frodo-kem/src/hazmat/traits.rs +++ b/frodo-kem/src/hazmat/traits.rs @@ -7,7 +7,7 @@ use crate::hazmat::{ use alloc::{string::String, vec::Vec}; use rand_core::CryptoRng; use sha3::digest::{ExtendableOutput, ExtendableOutputReset, Update}; -use subtle::{Choice, ConditionallySelectable}; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; use zeroize::Zeroize; /// Trait for implementing the FrodoKEM sampling algorithm @@ -403,8 +403,7 @@ pub trait Kem: Params + Expanded + Sample { // Needs to avoid branching on secret data as per: // Qian Guo, Thomas Johansson, Alexander Nilsson. A key-recovery timing attack on post-quantum // primitives using the Fujisaki-Okamoto transformation and its application on FrodoKEM. In CRYPTO 2020. - let choice = - self.ct_verify(&matrix_bp, &matrix_bpp) & self.ct_verify(&matrix_c, &matrix_cc); + let choice = matrix_bp.ct_eq(&matrix_bpp) & matrix_c.ct_eq(&matrix_cc); let mut fin_k = vec![0u8; Self::SHARED_SECRET_LENGTH]; // Take k if choice == 0, otherwise take s @@ -769,19 +768,6 @@ pub trait Kem: Params + Expanded + Sample { } } - /// Constant time verify for a u16 array - fn ct_verify(&self, a: &[u16], b: &[u16]) -> Choice { - let mut choice = 0; - - for i in 0..a.len() { - choice |= a[i] ^ b[i]; - } - - let mut choice = choice as i16; - choice = ((choice | choice.wrapping_neg()) >> 15) + 1; - Choice::from(choice as u8) - } - /// Constant time select for a u16 array fn ct_select(&self, choice: Choice, a: &[u8], b: &[u8], out: &mut [u8]) { for i in 0..a.len() { diff --git a/frodo-kem/src/lib.rs b/frodo-kem/src/lib.rs index 6e100c3..d90be93 100644 --- a/frodo-kem/src/lib.rs +++ b/frodo-kem/src/lib.rs @@ -236,7 +236,7 @@ macro_rules! ct_eq_imp { ($name:ident) => { impl ConstantTimeEq for $name { fn ct_eq(&self, other: &Self) -> Choice { - self.algorithm.ct_eq(&other.algorithm) & ct_eq_bytes(&self.value, &other.value) + self.algorithm.ct_eq(&other.algorithm) & self.value.ct_eq(&other.value) } } @@ -1644,20 +1644,6 @@ pub struct AlgorithmParams { pub ciphertext_length: usize, } -fn ct_eq_bytes(lhs: &[u8], rhs: &[u8]) -> Choice { - if lhs.len() != rhs.len() { - return 0u8.into(); - } - - let mut eq = 0u8; - for i in 0..lhs.len() { - eq |= lhs[i] ^ rhs[i]; - } - - let eq = ((eq | eq.wrapping_neg()) >> 7).wrapping_add(1); - Choice::from(eq) -} - #[cfg(test)] #[allow(clippy::unwrap_used)] mod tests {