diff --git a/Cargo.lock b/Cargo.lock index 9f55077c..c3a6d887 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,6 @@ dependencies = [ "cipher", "cpufeatures", "hex-literal", - "subtle", "zeroize", ] @@ -217,12 +216,6 @@ dependencies = [ "hex-literal", ] -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "threefish" version = "0.6.0-pre" diff --git a/aes/Cargo.toml b/aes/Cargo.toml index c4e82b81..cbe2c1ce 100644 --- a/aes/Cargo.toml +++ b/aes/Cargo.toml @@ -15,7 +15,6 @@ categories = ["cryptography", "no-std"] [dependencies] cfg-if = "1" cipher = "=0.5.0-pre.7" -subtle = { version = "2.6", default-features = false } zeroize = { version = "1.5.6", optional = true, default-features = false, features = [ "aarch64", ] } diff --git a/aes/src/armv8.rs b/aes/src/armv8.rs index 114f637f..ab684c5a 100644 --- a/aes/src/armv8.rs +++ b/aes/src/armv8.rs @@ -110,8 +110,9 @@ macro_rules! define_aes_impl { Self { encrypt, decrypt } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } @@ -199,8 +200,9 @@ macro_rules! define_aes_impl { Self { backend } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } @@ -265,8 +267,9 @@ macro_rules! define_aes_impl { Self { backend } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } diff --git a/aes/src/autodetect.rs b/aes/src/autodetect.rs index 8cfd47c4..b1510679 100644 --- a/aes/src/autodetect.rs +++ b/aes/src/autodetect.rs @@ -105,8 +105,9 @@ macro_rules! define_aes_impl { Self { inner, token } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } @@ -226,8 +227,9 @@ macro_rules! define_aes_impl { Self { inner, token } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } @@ -357,8 +359,9 @@ macro_rules! define_aes_impl { Self { inner, token } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } diff --git a/aes/src/lib.rs b/aes/src/lib.rs index b7fc6823..f4c23b88 100644 --- a/aes/src/lib.rs +++ b/aes/src/lib.rs @@ -143,11 +143,41 @@ cfg_if! { } pub use cipher; -use cipher::{array::Array, consts::U16}; +use cipher::{array::Array, consts::U16, crypto_common::WeakKeyError}; /// 128-bit AES block pub type Block = Array; +/// Check if any bit of the upper half of the key is set. +/// +/// This follows the interpretation laid out in section `11.4.10.4 Reject of weak keys` +/// from the [TPM specification][0]: +/// ```text +/// In the case of AES, at least one bit in the upper half of the key must be set +/// ``` +/// +/// [0]: https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=82 +pub(crate) fn weak_key_test(key: &[u8; N]) -> Result<(), WeakKeyError> { + let t = match N { + 16 => u64::from_ne_bytes(key[..8].try_into().unwrap()), + 24 => { + let t1 = u64::from_ne_bytes(key[..8].try_into().unwrap()); + let t2 = u32::from_ne_bytes(key[8..12].try_into().unwrap()); + t1 | u64::from(t2) + } + 32 => { + let t1 = u64::from_ne_bytes(key[..8].try_into().unwrap()); + let t2 = u64::from_ne_bytes(key[8..16].try_into().unwrap()); + t1 | t2 + } + _ => unreachable!(), + }; + match t { + 0 => Err(WeakKeyError), + _ => Ok(()), + } +} + #[cfg(test)] mod tests { #[cfg(feature = "zeroize")] diff --git a/aes/src/macros.rs b/aes/src/macros.rs index 28583e99..e688c00d 100644 --- a/aes/src/macros.rs +++ b/aes/src/macros.rs @@ -103,29 +103,3 @@ macro_rules! impl_backends { } }; } - -macro_rules! weak_key_test { - ($key: expr, $k: ty) => {{ - // Check if any bit of the upper half of the key is set - // - // This follows the interpretation laid out in section `11.4.10.4 Reject of weak keys` - // from the TPM specification: - // ``` - // In the case of AES, at least one bit in the upper half of the key must be set - // ``` - // See: https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=82 - let mut weak = subtle::Choice::from(0); - - for v in &$key - [..(<<$k as cipher::KeySizeUser>::KeySize as cipher::typenum::Unsigned>::USIZE / 2)] - { - weak |= <_ as subtle::ConstantTimeGreater>::ct_gt(v, &0); - } - - if weak.unwrap_u8() == 0 { - Err(cipher::crypto_common::WeakKeyError) - } else { - Ok(()) - } - }}; -} diff --git a/aes/src/ni.rs b/aes/src/ni.rs index 5833b821..14068397 100644 --- a/aes/src/ni.rs +++ b/aes/src/ni.rs @@ -120,8 +120,9 @@ macro_rules! define_aes_impl { Self { encrypt, decrypt } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } @@ -199,8 +200,9 @@ macro_rules! define_aes_impl { } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } @@ -263,8 +265,9 @@ macro_rules! define_aes_impl { $name_enc::new(key).into() } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } diff --git a/aes/src/soft.rs b/aes/src/soft.rs index 19c2576d..762618cb 100644 --- a/aes/src/soft.rs +++ b/aes/src/soft.rs @@ -69,8 +69,9 @@ macro_rules! define_aes_impl { } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } @@ -152,8 +153,9 @@ macro_rules! define_aes_impl { Self { inner } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } @@ -207,8 +209,9 @@ macro_rules! define_aes_impl { Self { inner } } + #[inline] fn weak_key_test(key: &Key) -> Result<(), WeakKeyError> { - weak_key_test!(key, Self) + crate::weak_key_test(&key.0) } } diff --git a/aes/src/weak_key.rs b/aes/src/weak_key.rs new file mode 100644 index 00000000..44bebd89 --- /dev/null +++ b/aes/src/weak_key.rs @@ -0,0 +1,17 @@ +pub(crate) fn test192(key: &[u8; 24]) -> Result<(), WeakKeyError> { + let t1 = u32::from_ne_bytes(key[..4].try_into().unwrap()); + let t2 = u32::from_ne_bytes(key[4..8].try_into().unwrap()); + let t3 = u32::from_ne_bytes(key[8..12].try_into().unwrap()); + match t1 | t2 | t3 { + 0 => Err(WeakKeyError), + _ => Ok(()), + } +} + +pub(crate) fn test256(key: &[u8; 32]) -> Result<(), WeakKeyError> { + let t = u128::from_ne_bytes(key[..16].try_into().unwrap()); + match t { + 0 => Err(WeakKeyError), + _ => Ok(()), + } +}