diff --git a/Cargo.lock b/Cargo.lock index a85c2b26..9f55077c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,7 +114,6 @@ version = "0.9.0-pre.2" dependencies = [ "cipher", "hex-literal", - "subtle", ] [[package]] diff --git a/des/Cargo.toml b/des/Cargo.toml index 12f396bc..550d5441 100644 --- a/des/Cargo.toml +++ b/des/Cargo.toml @@ -14,7 +14,6 @@ categories = ["cryptography", "no-std"] [dependencies] cipher = "=0.5.0-pre.7" -subtle = { version = "2.6", default-features = false } [dev-dependencies] cipher = { version = "=0.5.0-pre.7", features = ["dev"] } diff --git a/des/src/consts.rs b/des/src/consts.rs index 5bac66e1..90f67f68 100644 --- a/des/src/consts.rs +++ b/des/src/consts.rs @@ -57,3 +57,76 @@ pub const SBOXES: [[u8; 64]; 8] = [ 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11, ], ]; + +macro_rules! as_ne_u64 { + [$($key:expr,)*] => { + [$(u64::from_ne_bytes($key),)*] + }; +} + +pub(crate) static WEAK_KEYS: &[u64; 64] = &as_ne_u64![ + [0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01], + [0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], + [0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1], + [0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E], + [0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E], + [0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01], + [0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1], + [0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01], + [0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE], + [0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01], + [0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1], + [0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E], + [0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE], + [0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E], + [0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE], + [0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1], + [0x01, 0x01, 0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E], + [0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E, 0x01, 0x01], + [0xE0, 0xE0, 0x1F, 0x1F, 0xF1, 0xF1, 0x0E, 0x0E], + [0x01, 0x01, 0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1], + [0x1F, 0x1F, 0xE0, 0xE0, 0x0E, 0x0E, 0xF1, 0xF1], + [0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1, 0xFE, 0xFE], + [0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE], + [0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E, 0xFE, 0xFE], + [0xE0, 0xFE, 0x01, 0x1F, 0xF1, 0xFE, 0x01, 0x0E], + [0x01, 0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E, 0x01], + [0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1, 0x01, 0xFE], + [0xE0, 0xFE, 0x1F, 0x01, 0xF1, 0xFE, 0x0E, 0x01], + [0x01, 0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1, 0xFE], + [0x1F, 0xE0, 0xE0, 0x1F, 0x0E, 0xF1, 0xF1, 0x0E], + [0xE0, 0xFE, 0xFE, 0xE0, 0xF1, 0xFE, 0xFE, 0xF1], + [0x01, 0x1F, 0xFE, 0xE0, 0x01, 0x0E, 0xFE, 0xF1], + [0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1, 0xFE, 0x01], + [0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE], + [0x01, 0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E, 0xFE], + [0x1F, 0xFE, 0x01, 0xE0, 0x0E, 0xFE, 0x01, 0xF1], + [0xFE, 0x01, 0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1], + [0xFE, 0x01, 0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E], + [0x1F, 0xFE, 0xE0, 0x01, 0x0E, 0xFE, 0xF1, 0x01], + [0xFE, 0x1F, 0x01, 0xE0, 0xFE, 0x0E, 0x01, 0xF1], + [0x01, 0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1, 0x01], + [0x1F, 0xFE, 0xFE, 0x1F, 0x0E, 0xFE, 0xFE, 0x0E], + [0xFE, 0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1, 0x01], + [0x01, 0xE0, 0xFE, 0x1F, 0x01, 0xF1, 0xFE, 0x0E], + [0xE0, 0x01, 0x01, 0xE0, 0xF1, 0x01, 0x01, 0xF1], + [0xFE, 0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E, 0xFE], + [0x01, 0xFE, 0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1], + [0xE0, 0x01, 0x1F, 0xFE, 0xF1, 0x01, 0x0E, 0xFE], + [0xFE, 0xE0, 0x01, 0x1F, 0xFE, 0xF1, 0x01, 0x0E], + [0x01, 0xFE, 0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E], + [0xE0, 0x01, 0xFE, 0x1F, 0xF1, 0x01, 0xFE, 0x0E], + [0xFE, 0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E, 0x01], + [0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01], + [0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E, 0x01, 0xFE], + [0xFE, 0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1, 0xFE], + [0x1F, 0x01, 0x01, 0x1F, 0x0E, 0x01, 0x01, 0x0E], + [0xE0, 0x1F, 0x1F, 0xE0, 0xF1, 0x0E, 0x0E, 0xF1], + [0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01], + [0x1F, 0x01, 0xE0, 0xFE, 0x0E, 0x01, 0xF1, 0xFE], + [0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E, 0xFE, 0x01], + [0xFE, 0xFE, 0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E], + [0x1F, 0x01, 0xFE, 0xE0, 0x0E, 0x01, 0xFE, 0xF1], + [0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1, 0x01, 0x01], + [0xFE, 0xFE, 0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1], +]; diff --git a/des/src/des.rs b/des/src/des.rs index 2e520e41..917871f6 100644 --- a/des/src/des.rs +++ b/des/src/des.rs @@ -10,7 +10,6 @@ use cipher::{ KeyInit, KeySizeUser, ParBlocksSizeUser, }; use core::fmt; -use subtle::{Choice, ConstantTimeEq}; #[cfg(feature = "zeroize")] use cipher::zeroize::{Zeroize, ZeroizeOnDrop}; @@ -45,73 +44,6 @@ impl KeySizeUser for Des { type KeySize = U8; } -static WEAK_KEYS: [[u8; 8]; 64] = [ - [0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01], - [0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE], - [0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1], - [0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E], - [0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E], - [0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01], - [0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1], - [0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01], - [0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE], - [0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01], - [0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1], - [0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E], - [0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE], - [0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E], - [0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE], - [0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1], - [0x01, 0x01, 0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E], - [0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E, 0x01, 0x01], - [0xE0, 0xE0, 0x1F, 0x1F, 0xF1, 0xF1, 0x0E, 0x0E], - [0x01, 0x01, 0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1], - [0x1F, 0x1F, 0xE0, 0xE0, 0x0E, 0x0E, 0xF1, 0xF1], - [0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1, 0xFE, 0xFE], - [0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE], - [0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E, 0xFE, 0xFE], - [0xE0, 0xFE, 0x01, 0x1F, 0xF1, 0xFE, 0x01, 0x0E], - [0x01, 0x1F, 0x1F, 0x01, 0x01, 0x0E, 0x0E, 0x01], - [0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1, 0x01, 0xFE], - [0xE0, 0xFE, 0x1F, 0x01, 0xF1, 0xFE, 0x0E, 0x01], - [0x01, 0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1, 0xFE], - [0x1F, 0xE0, 0xE0, 0x1F, 0x0E, 0xF1, 0xF1, 0x0E], - [0xE0, 0xFE, 0xFE, 0xE0, 0xF1, 0xFE, 0xFE, 0xF1], - [0x01, 0x1F, 0xFE, 0xE0, 0x01, 0x0E, 0xFE, 0xF1], - [0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1, 0xFE, 0x01], - [0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE], - [0x01, 0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E, 0xFE], - [0x1F, 0xFE, 0x01, 0xE0, 0x0E, 0xFE, 0x01, 0xF1], - [0xFE, 0x01, 0x1F, 0xE0, 0xFE, 0x01, 0x0E, 0xF1], - [0xFE, 0x01, 0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E], - [0x1F, 0xFE, 0xE0, 0x01, 0x0E, 0xFE, 0xF1, 0x01], - [0xFE, 0x1F, 0x01, 0xE0, 0xFE, 0x0E, 0x01, 0xF1], - [0x01, 0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1, 0x01], - [0x1F, 0xFE, 0xFE, 0x1F, 0x0E, 0xFE, 0xFE, 0x0E], - [0xFE, 0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1, 0x01], - [0x01, 0xE0, 0xFE, 0x1F, 0x01, 0xF1, 0xFE, 0x0E], - [0xE0, 0x01, 0x01, 0xE0, 0xF1, 0x01, 0x01, 0xF1], - [0xFE, 0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E, 0xFE], - [0x01, 0xFE, 0x1F, 0xE0, 0x01, 0xFE, 0x0E, 0xF1], - [0xE0, 0x01, 0x1F, 0xFE, 0xF1, 0x01, 0x0E, 0xFE], - [0xFE, 0xE0, 0x01, 0x1F, 0xFE, 0xF1, 0x01, 0x0E], - [0x01, 0xFE, 0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E], - [0xE0, 0x01, 0xFE, 0x1F, 0xF1, 0x01, 0xFE, 0x0E], - [0xFE, 0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E, 0x01], - [0x01, 0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01], - [0xE0, 0x1F, 0x01, 0xFE, 0xF1, 0x0E, 0x01, 0xFE], - [0xFE, 0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1, 0xFE], - [0x1F, 0x01, 0x01, 0x1F, 0x0E, 0x01, 0x01, 0x0E], - [0xE0, 0x1F, 0x1F, 0xE0, 0xF1, 0x0E, 0x0E, 0xF1], - [0xFE, 0xFE, 0x01, 0x01, 0xFE, 0xFE, 0x01, 0x01], - [0x1F, 0x01, 0xE0, 0xFE, 0x0E, 0x01, 0xF1, 0xFE], - [0xE0, 0x1F, 0xFE, 0x01, 0xF1, 0x0E, 0xFE, 0x01], - [0xFE, 0xFE, 0x1F, 0x1F, 0xFE, 0xFE, 0x0E, 0x0E], - [0x1F, 0x01, 0xFE, 0xE0, 0x0E, 0x01, 0xFE, 0xF1], - [0xE0, 0xE0, 0x01, 0x01, 0xF1, 0xF1, 0x01, 0x01], - [0xFE, 0xFE, 0xE0, 0xE0, 0xFE, 0xFE, 0xF1, 0xF1], -]; - impl KeyInit for Des { #[inline] fn new(key: &Key) -> Self { @@ -121,16 +53,9 @@ impl KeyInit for Des { #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - let mut weak = Choice::from(0); - - for weak_key in &WEAK_KEYS { - weak |= key.ct_eq(weak_key); - } - - if weak.unwrap_u8() == 0 { - Ok(()) - } else { - Err(WeakKeyError) + match super::weak_key_test(&key.0) { + 0 => Ok(()), + _ => Err(WeakKeyError), } } } diff --git a/des/src/lib.rs b/des/src/lib.rs index 7dc04377..7bd0f9c3 100644 --- a/des/src/lib.rs +++ b/des/src/lib.rs @@ -30,3 +30,15 @@ mod utils; pub use crate::des::Des; pub use crate::tdes::{TdesEde2, TdesEde3, TdesEee2, TdesEee3}; + +/// Checks whether the key is weak. +/// +/// Returns 1 if the key is weak; otherwise, returns 0. +fn weak_key_test(key: &[u8; 8]) -> u8 { + let key = u64::from_ne_bytes(*key); + let mut is_weak = 0u8; + for &weak_key in crate::consts::WEAK_KEYS { + is_weak |= u8::from(key == weak_key); + } + is_weak +} diff --git a/des/src/tdes.rs b/des/src/tdes.rs index 024f7990..16b242ed 100644 --- a/des/src/tdes.rs +++ b/des/src/tdes.rs @@ -12,36 +12,23 @@ use cipher::{ use core::fmt; #[cfg(feature = "zeroize")] -use cipher::zeroize::{ZeroizeOnDrop, Zeroizing}; +use cipher::zeroize::ZeroizeOnDrop; #[inline] -fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - #[cfg(feature = "zeroize")] - let mut tmp = Zeroizing::new(Key::::default()); - #[cfg(not(feature = "zeroize"))] - let mut tmp = Key::::default(); +fn weak_key_test(key: &[u8]) -> Result<(), WeakKeyError> { + let sub_key_size = ::KeySize::USIZE; + assert_eq!(key.len() % sub_key_size, 0); - for i in 0..::KeySize::USIZE { - // count number of set bits in byte, excluding the low-order bit - SWAR method - let mut c = key[i] & 0xFE; - - c = (c & 0x55) + ((c >> 1) & 0x55); - c = (c & 0x33) + ((c >> 2) & 0x33); - c = (c & 0x0F) + ((c >> 4) & 0x0F); - - // if count is even, set low key bit to 1, otherwise 0 - tmp[i] = (key[i] & 0xFE) | u8::from(c & 0x01 != 0x01); + let mut is_weak = 0u8; + for des_key in key.chunks_exact(sub_key_size) { + let des_key = des_key.try_into().unwrap(); + is_weak |= super::weak_key_test(des_key); } - let mut des_key = Key::::default(); - for i in 0..SIZE { - des_key.copy_from_slice( - &tmp.as_slice()[i * ::KeySize::USIZE - ..(i + 1) * ::KeySize::USIZE], - ); - Des::weak_key_test(&des_key)?; + match is_weak { + 0 => Ok(()), + _ => Err(WeakKeyError), } - Ok(()) } /// Triple DES (3DES) block cipher. @@ -70,7 +57,7 @@ impl KeyInit for TdesEde3 { #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test::<3, Self>(key) + weak_key_test(key) } } @@ -159,7 +146,7 @@ impl KeyInit for TdesEee3 { #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test::<3, Self>(key) + weak_key_test(key) } } @@ -245,7 +232,7 @@ impl KeyInit for TdesEde2 { #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test::<2, Self>(key) + weak_key_test(key) } } @@ -331,7 +318,7 @@ impl KeyInit for TdesEee2 { #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test::<2, Self>(key) + weak_key_test(key) } }