Skip to content

Commit

Permalink
mgm: rework detection of weak keys using the KeyInit trait
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo committed Feb 12, 2025
1 parent 13bdf9a commit 725040e
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 106 deletions.
16 changes: 6 additions & 10 deletions Cargo.lock

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

17 changes: 16 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ x509-cert = { version = "=0.3.0-pre.0", features = [ "builder", "hazmat" ] }
[dependencies]
bitflags = "2.5.0"
der = "=0.8.0-rc.1"
des = "=0.9.0-pre.2"
des = { version = "=0.9.0-pre.2", features = [ "zeroize" ] }
elliptic-curve = "=0.14.0-rc.1"
hex = { package = "base16ct", version = "0.2", features = ["alloc"] }
log = "0.4"
Expand Down Expand Up @@ -60,3 +60,18 @@ untested = []
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[patch.crates-io]
# https://github.com/RustCrypto/traits/issues/1738
# https://github.com/RustCrypto/traits/pull/1742
# https://github.com/RustCrypto/traits/pull/1747
# Pending release of crypto-common 0.2.0-rc.2
# Pending release of digest 0.11.0-rc.0
# Pending release of cipher 0.5.0-pre.8
cipher = { git = "https://github.com/RustCrypto/traits.git" }
crypto-common = { git = "https://github.com/RustCrypto/traits.git" }
digest = { git = "https://github.com/RustCrypto/traits.git" }

# https://github.com/RustCrypto/block-ciphers/pull/465
# https://github.com/RustCrypto/block-ciphers/pull/467
des = { git = "https://github.com/RustCrypto/block-ciphers.git" }
50 changes: 25 additions & 25 deletions src/mgm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::{Error, Result};
use log::error;
use rand_core::{OsRng, RngCore};
use zeroize::Zeroize;

use des::{
cipher::{BlockCipherDecrypt, BlockCipherEncrypt, KeyInit},
TdesEde3,
cipher::{
typenum::Unsigned, BlockCipherDecrypt, BlockCipherEncrypt, Key, KeyInit, KeySizeUser,
},
Des, TdesEde3,
};
#[cfg(feature = "untested")]
use {
Expand All @@ -56,6 +57,7 @@ use {
Serial, Version,
},
bitflags::bitflags,
log::error,
pbkdf2::pbkdf2_hmac,
sha1::Sha1,
};
Expand All @@ -70,9 +72,11 @@ pub(crate) const APPLET_NAME: &str = "YubiKey MGMT";
#[cfg(feature = "untested")]
pub(crate) const APPLET_ID: &[u8] = &[0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17];

mod tdes;
pub(crate) use tdes::DES_LEN_3DES;
use tdes::DES_LEN_DES;
/// Size of a 3DES key
#[cfg(feature = "untested")]
pub(crate) const DES_LEN_3DES: usize = <TdesEde3 as KeySizeUser>::KeySize::USIZE;
/// Size of a DES key
const DES_LEN_DES: usize = <Des as KeySizeUser>::KeySize::USIZE;

pub(crate) const ADMIN_FLAGS_1_PROTECTED_MGM: u8 = 0x02;

Expand Down Expand Up @@ -150,12 +154,12 @@ impl MgmAlgorithmId {
///
/// The only supported algorithm for MGM keys is 3DES.
#[derive(Clone)]
pub struct MgmKey([u8; DES_LEN_3DES]);
pub struct MgmKey(Key<TdesEde3>);

impl MgmKey {
/// Generate a random MGM key
pub fn generate() -> Self {
let mut key_bytes = [0u8; DES_LEN_3DES];
let mut key_bytes = Key::<TdesEde3>::default();
OsRng.fill_bytes(&mut key_bytes);
Self(key_bytes)
}
Expand All @@ -170,15 +174,8 @@ impl MgmKey {
/// Create an MGM key from the given byte array.
///
/// Returns an error if the key is weak.
pub fn new(key_bytes: [u8; DES_LEN_3DES]) -> Result<Self> {
if tdes::is_weak_key(&key_bytes) {
error!(
"blacklisting key '{:?}' since it's weak (with odd parity)",
&key_bytes
);

return Err(Error::KeyError);
}
pub fn new(key_bytes: Key<TdesEde3>) -> Result<Self> {
TdesEde3::weak_key_test(&key_bytes).map_err(|_| Error::KeyError)?;

Ok(Self(key_bytes))
}
Expand Down Expand Up @@ -208,7 +205,7 @@ impl MgmKey {
return Err(Error::GenericError);
}

let mut mgm = [0u8; DES_LEN_3DES];
let mut mgm = Key::<TdesEde3>::default();
pbkdf2_hmac::<Sha1>(pin, salt, ITER_MGM_PBKDF2, &mut mgm);
MgmKey::from_bytes(mgm)
}
Expand Down Expand Up @@ -383,30 +380,33 @@ impl MgmKey {
/// Encrypt with 3DES key
pub(crate) fn encrypt(&self, input: &[u8; DES_LEN_DES]) -> [u8; DES_LEN_DES] {
let mut output = input.to_owned();
TdesEde3::new(&self.0.into()).encrypt_block((&mut output).into());
TdesEde3::new(&self.0).encrypt_block((&mut output).into());
output
}

/// Decrypt with 3DES key
pub(crate) fn decrypt(&self, input: &[u8; DES_LEN_DES]) -> [u8; DES_LEN_DES] {
let mut output = input.to_owned();
TdesEde3::new(&self.0.into()).decrypt_block((&mut output).into());
TdesEde3::new(&self.0).decrypt_block((&mut output).into());
output
}
}

impl AsRef<[u8; DES_LEN_3DES]> for MgmKey {
fn as_ref(&self) -> &[u8; DES_LEN_3DES] {
impl AsRef<Key<TdesEde3>> for MgmKey {
fn as_ref(&self) -> &Key<TdesEde3> {
&self.0
}
}

/// Default MGM key configured on all YubiKeys
impl Default for MgmKey {
fn default() -> Self {
MgmKey([
1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8,
])
MgmKey(
[
1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8,
]
.into(),
)
}
}

Expand Down
70 changes: 0 additions & 70 deletions src/mgm/tdes.rs

This file was deleted.

0 comments on commit 725040e

Please sign in to comment.