Skip to content

Commit e83fa48

Browse files
authored
aes,des: implement weak key detection (#465)
See RustCrypto/traits#1738
1 parent 551e791 commit e83fa48

File tree

13 files changed

+287
-2
lines changed

13 files changed

+287
-2
lines changed

Cargo.lock

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ members = [
2525

2626
[profile.dev]
2727
opt-level = 2
28+
29+
[patch.crates-io]
30+
# https://github.com/RustCrypto/traits/pull/1742
31+
crypto-common = { git = "https://github.com/RustCrypto/traits.git" }

aes/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ categories = ["cryptography", "no-std"]
1515
[dependencies]
1616
cfg-if = "1"
1717
cipher = "=0.5.0-pre.7"
18+
subtle = { version = "2.6", default-features = false }
1819
zeroize = { version = "1.5.6", optional = true, default-features = false, features = [
1920
"aarch64",
2021
] }

aes/src/armv8.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod test_expand;
1919

2020
use cipher::{
2121
consts::{self, U16, U24, U32},
22+
crypto_common::WeakKeyError,
2223
AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure,
2324
BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser,
2425
};
@@ -108,6 +109,10 @@ macro_rules! define_aes_impl {
108109
let decrypt = $name_back_dec::from(encrypt.clone());
109110
Self { encrypt, decrypt }
110111
}
112+
113+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
114+
weak_key_test!(key, Self)
115+
}
111116
}
112117

113118
impl From<$name_enc> for $name {
@@ -193,6 +198,10 @@ macro_rules! define_aes_impl {
193198
let backend = $name_back_enc::new(key);
194199
Self { backend }
195200
}
201+
202+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
203+
weak_key_test!(key, Self)
204+
}
196205
}
197206

198207
impl BlockSizeUser for $name_enc {
@@ -255,6 +264,10 @@ macro_rules! define_aes_impl {
255264
let backend = encrypt.clone().into();
256265
Self { backend }
257266
}
267+
268+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
269+
weak_key_test!(key, Self)
270+
}
258271
}
259272

260273
impl From<$name_enc> for $name_dec {

aes/src/autodetect.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use crate::soft;
55
use cipher::{
66
consts::{U16, U24, U32},
7+
crypto_common::WeakKeyError,
78
AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure,
89
BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser,
910
};
@@ -103,6 +104,10 @@ macro_rules! define_aes_impl {
103104

104105
Self { inner, token }
105106
}
107+
108+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
109+
weak_key_test!(key, Self)
110+
}
106111
}
107112

108113
impl Clone for $name {
@@ -220,6 +225,10 @@ macro_rules! define_aes_impl {
220225

221226
Self { inner, token }
222227
}
228+
229+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
230+
weak_key_test!(key, Self)
231+
}
223232
}
224233

225234
impl Clone for $name_enc {
@@ -347,6 +356,10 @@ macro_rules! define_aes_impl {
347356

348357
Self { inner, token }
349358
}
359+
360+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
361+
weak_key_test!(key, Self)
362+
}
350363
}
351364

352365
impl Clone for $name_dec {

aes/src/macros.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,29 @@ macro_rules! impl_backends {
103103
}
104104
};
105105
}
106+
107+
macro_rules! weak_key_test {
108+
($key: expr, $k: ty) => {{
109+
// Check if any bit of the upper half of the key is set
110+
//
111+
// This follows the interpretation laid out in section `11.4.10.4 Reject of weak keys`
112+
// from the TPM specification:
113+
// ```
114+
// In the case of AES, at least one bit in the upper half of the key must be set
115+
// ```
116+
// See: https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=82
117+
let mut weak = subtle::Choice::from(0);
118+
119+
for v in &$key
120+
[..(<<$k as cipher::KeySizeUser>::KeySize as cipher::typenum::Unsigned>::USIZE / 2)]
121+
{
122+
weak |= <_ as subtle::ConstantTimeGreater>::ct_gt(v, &0);
123+
}
124+
125+
if weak.unwrap_u8() == 0 {
126+
Err(cipher::crypto_common::WeakKeyError)
127+
} else {
128+
Ok(())
129+
}
130+
}};
131+
}

aes/src/ni.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use core::arch::x86_64 as arch;
3030

3131
use cipher::{
3232
consts::{self, U16, U24, U32},
33+
crypto_common::WeakKeyError,
3334
AlgorithmName, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncClosure,
3435
BlockCipherEncrypt, BlockSizeUser, Key, KeyInit, KeySizeUser,
3536
};
@@ -118,6 +119,10 @@ macro_rules! define_aes_impl {
118119
let decrypt = $name_dec::from(&encrypt);
119120
Self { encrypt, decrypt }
120121
}
122+
123+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
124+
weak_key_test!(key, Self)
125+
}
121126
}
122127

123128
impl From<$name_enc> for $name {
@@ -193,6 +198,10 @@ macro_rules! define_aes_impl {
193198
backend: $name_back_enc::new(key),
194199
}
195200
}
201+
202+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
203+
weak_key_test!(key, Self)
204+
}
196205
}
197206

198207
impl BlockSizeUser for $name_enc {
@@ -253,6 +262,10 @@ macro_rules! define_aes_impl {
253262
fn new(key: &Key<Self>) -> Self {
254263
$name_enc::new(key).into()
255264
}
265+
266+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
267+
weak_key_test!(key, Self)
268+
}
256269
}
257270

258271
impl From<$name_enc> for $name_dec {

aes/src/soft.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub(crate) mod fixslice;
1515
use crate::Block;
1616
use cipher::{
1717
consts::{U16, U24, U32},
18+
crypto_common::WeakKeyError,
1819
inout::InOut,
1920
AlgorithmName, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt,
2021
BlockCipherEncBackend, BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, Key, KeyInit,
@@ -67,6 +68,10 @@ macro_rules! define_aes_impl {
6768
keys: $fixslice_key_schedule(key.into()),
6869
}
6970
}
71+
72+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
73+
weak_key_test!(key, Self)
74+
}
7075
}
7176

7277
impl BlockSizeUser for $name {
@@ -146,6 +151,10 @@ macro_rules! define_aes_impl {
146151
let inner = $name::new(key);
147152
Self { inner }
148153
}
154+
155+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
156+
weak_key_test!(key, Self)
157+
}
149158
}
150159

151160
impl BlockSizeUser for $name_enc {
@@ -197,6 +206,10 @@ macro_rules! define_aes_impl {
197206
let inner = $name::new(key);
198207
Self { inner }
199208
}
209+
210+
fn weak_key_test(key: &Key<Self>) -> Result<(), WeakKeyError> {
211+
weak_key_test!(key, Self)
212+
}
200213
}
201214

202215
impl From<$name_enc> for $name_dec {

aes/tests/weak.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use aes::Aes128;
2+
use cipher::{Key, KeyInit};
3+
use hex_literal::hex;
4+
5+
#[test]
6+
fn test_weak_key() {
7+
for k in &[
8+
hex!("00000000000000000000000000000000"),
9+
hex!("00000000000000000101010101010101"),
10+
hex!("00000000000000000100000000000000"),
11+
] {
12+
let k = Key::<Aes128>::from(*k);
13+
assert!(Aes128::weak_key_test(&k).is_err());
14+
}
15+
16+
for k in &[
17+
hex!("00000000010000000000000000000000"),
18+
hex!("00000000010000000101010101010101"),
19+
hex!("00000000010000000100000000000000"),
20+
] {
21+
let k = Key::<Aes128>::from(*k);
22+
assert!(Aes128::weak_key_test(&k).is_ok());
23+
}
24+
}

des/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ categories = ["cryptography", "no-std"]
1414

1515
[dependencies]
1616
cipher = "=0.5.0-pre.7"
17+
subtle = { version = "2.6", default-features = false }
1718

1819
[dev-dependencies]
1920
cipher = { version = "=0.5.0-pre.7", features = ["dev"] }
21+
hex-literal = "0.4"
2022

2123
[features]
2224
zeroize = ["cipher/zeroize"]

0 commit comments

Comments
 (0)