des 0.9.0

DES and Triple DES (3DES, TDES) block ciphers implementation
Documentation
use core::fmt;

/// Checks whether `key` contains one of the known [weak DES keys][TCG].
///
/// [TCG]: https://trustedcomputinggroup.org/wp-content/uploads/TPM-2.0-1.83-Part-1-Architecture.pdf#page=82
///
/// # Panics
/// If `key` length is not equal to 8, 16, or 24.
#[inline]
pub fn weak_key_test(key: &[u8]) -> Result<(), WeakKeyError> {
    assert!(
        matches!(key.len(), 8 | 16 | 24),
        "key size is not equal to 8, 16, or 24 bytes"
    );

    let mut is_weak = 0u8;

    for subkey in key.chunks_exact(8) {
        let key = u64::from_ne_bytes(subkey.try_into().expect("`subkey` length is equal to 8"));
        for &weak_key in WEAK_KEYS {
            is_weak |= u8::from(key == weak_key);
        }
    }

    match key.len() {
        16 => {
            is_weak |= u8::from(key[..8] == key[8..]);
        }
        24 => {
            let k1 = &key[..8];
            let k2 = &key[8..16];
            let k3 = &key[16..];
            is_weak |= u8::from(k1 == k2);
            is_weak |= u8::from(k1 == k3);
            is_weak |= u8::from(k2 == k3);
        }
        _ => {}
    }

    match is_weak {
        0 => Ok(()),
        _ => Err(WeakKeyError),
    }
}

/// The error type returned when a key is found to be weak.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct WeakKeyError;

impl fmt::Display for WeakKeyError {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        f.write_str("WeakKey")
    }
}

impl core::error::Error for WeakKeyError {}

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],
];