Skip to content

Commit

Permalink
aes,des: implement weak key detection
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo committed Jan 30, 2025
1 parent 81f1eb4 commit f757587
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 2 deletions.
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ members = [

[profile.dev]
opt-level = 2

[patch.crates-io]
crypto-common = { git = "https://github.com/baloo/traits.git", branch = "baloo/weak-key" }
1 change: 1 addition & 0 deletions aes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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",
] }
Expand Down
13 changes: 13 additions & 0 deletions aes/src/armv8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mod test_expand;

use cipher::{
consts::{self, U16, U24, U32},
crypto_common::WeakKeyError,
AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure,
BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser,
};
Expand Down Expand Up @@ -108,6 +109,10 @@ macro_rules! define_aes_impl {
let decrypt = $name_back_dec::from(encrypt.clone());
Self { encrypt, decrypt }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl From<$name_enc> for $name {
Expand Down Expand Up @@ -193,6 +198,10 @@ macro_rules! define_aes_impl {
let backend = $name_back_enc::new(key);
Self { backend }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl BlockSizeUser for $name_enc {
Expand Down Expand Up @@ -255,6 +264,10 @@ macro_rules! define_aes_impl {
let backend = encrypt.clone().into();
Self { backend }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl From<$name_enc> for $name_dec {
Expand Down
13 changes: 13 additions & 0 deletions aes/src/autodetect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use crate::soft;
use cipher::{
consts::{U16, U24, U32},
crypto_common::WeakKeyError,
AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure,
BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser,
};
Expand Down Expand Up @@ -103,6 +104,10 @@ macro_rules! define_aes_impl {

Self { inner, token }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl Clone for $name {
Expand Down Expand Up @@ -220,6 +225,10 @@ macro_rules! define_aes_impl {

Self { inner, token }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl Clone for $name_enc {
Expand Down Expand Up @@ -347,6 +356,10 @@ macro_rules! define_aes_impl {

Self { inner, token }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl Clone for $name_dec {
Expand Down
26 changes: 26 additions & 0 deletions aes/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,29 @@ 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(())
}
}};
}
13 changes: 13 additions & 0 deletions aes/src/ni.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use core::arch::x86_64 as arch;

use cipher::{
consts::{self, U16, U24, U32},
crypto_common::WeakKeyError,
AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure,
BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser,
};
Expand Down Expand Up @@ -118,6 +119,10 @@ macro_rules! define_aes_impl {
let decrypt = $name_dec::from(&encrypt);
Self { encrypt, decrypt }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl From<$name_enc> for $name {
Expand Down Expand Up @@ -193,6 +198,10 @@ macro_rules! define_aes_impl {
backend: $name_back_enc::new(key),
}
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl BlockSizeUser for $name_enc {
Expand Down Expand Up @@ -253,6 +262,10 @@ macro_rules! define_aes_impl {
fn new(key: &Key<Self>) -> Self {
$name_enc::new(key).into()
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl From<$name_enc> for $name_dec {
Expand Down
13 changes: 13 additions & 0 deletions aes/src/soft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub(crate) mod fixslice;
use crate::Block;
use cipher::{
consts::{U16, U24, U32},
crypto_common::WeakKeyError,
inout::InOut,
AlgorithmName, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt,
BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, Key, KeyInit,
Expand Down Expand Up @@ -67,6 +68,10 @@ macro_rules! define_aes_impl {
keys: $fixslice_key_schedule(key.into()),
}
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl BlockSizeUser for $name {
Expand Down Expand Up @@ -146,6 +151,10 @@ macro_rules! define_aes_impl {
let inner = $name::new(key);
Self { inner }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl BlockSizeUser for $name_enc {
Expand Down Expand Up @@ -197,6 +206,10 @@ macro_rules! define_aes_impl {
let inner = $name::new(key);
Self { inner }
}

fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
weak_key_test!(key, Self)
}
}

impl From<$name_enc> for $name_dec {
Expand Down
24 changes: 24 additions & 0 deletions aes/tests/weak.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use aes::Aes128;
use cipher::{Key, KeyInit};
use hex_literal::hex;

#[test]
fn test_weak_key() {
for k in &[
hex!("00000000000000000000000000000000"),
hex!("00000000000000000101010101010101"),
hex!("00000000000000000100000000000000"),
] {
let k = Key::<Aes128>::from(*k);
assert!(Aes128::weak_key_test(&k).is_err());
}

for k in &[
hex!("00000000010000000000000000000000"),
hex!("00000000010000000101010101010101"),
hex!("00000000010000000100000000000000"),
] {
let k = Key::<Aes128>::from(*k);
assert!(Aes128::weak_key_test(&k).is_ok());
}
}
1 change: 1 addition & 0 deletions des/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ 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"] }
Expand Down
83 changes: 83 additions & 0 deletions des/src/des.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

use cipher::{
consts::{U1, U8},
crypto_common::WeakKeyError,
AlgorithmName, Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt,
BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, Key,
KeyInit, KeySizeUser, ParBlocksSizeUser,
};
use core::fmt;
use subtle::{Choice, ConstantTimeEq};

#[cfg(feature = "zeroize")]
use cipher::zeroize::{Zeroize, ZeroizeOnDrop};
Expand Down Expand Up @@ -43,12 +45,93 @@ 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>) -> Self {
let keys = gen_keys(u64::from_be_bytes(key.0));
Self { keys }
}

fn weak_key_test(key: &Key<Self>) -> 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)
}
}
}

impl BlockSizeUser for Des {
Expand Down

0 comments on commit f757587

Please sign in to comment.