libs.nfc_rs/src/crypto/cipher_key.rs

95 lines
2.6 KiB
Rust
Raw Normal View History

2021-01-24 05:19:35 +01:00
use crate::crypto::cipher_type::CipherType;
use crate::crypto::cipher_type::CipherType::*;
use crate::crypto::cipher::{aes, tdes, tdes_2k, tdes_3k};
use crate::error::Error;
use crate::error::Result;
use simple_error::simple_error;
#[derive(Debug, Clone)]
struct CipherKey {
/// Key as Array
key: Box<[u8]>,
/// CipherType of Key
cipher: CipherType,
/// KeyVersion of Key
key_version: u8
}
impl CipherKey {
pub fn new(key: &[u8], cipher: CipherType, key_version: u8) -> Result<CipherKey> {
if cipher == AES && key_version < 0x10 {
return Err(Error::Boxed(Box::new(simple_error!("KeyVersion is to low for AES Key (Minimum = 0x10)"))))
}
if !check_key(key, cipher.clone()) {
return Err(Error::Boxed(Box::new(simple_error!("Key is not valid for CipherType"))))
}
let mut key: Box<[u8]> = Box::from(key);
if cipher == TDES || cipher == TDES2K || cipher == TDES3K {
key = set_key_version(key.as_ref(), key_version);
}
Ok(CipherKey {
cipher,
key_version,
key
})
}
pub fn new_from_str(key: &str, cipher: CipherType, key_version: u8) -> Result<CipherKey> {
CipherKey::new(&*hex::decode(key)?, cipher, key_version)
}
pub fn new_empty(cipher: CipherType) -> Result<CipherKey> {
Ok(CipherKey{
key: generate_empty_key(cipher.clone()),
key_version: if cipher == AES { 0x10u8 } else { 0x00u8 },
cipher
})
}
}
/// Generate Empty Key for CipherType
pub fn generate_empty_key(cipher: CipherType) -> Box<[u8]> {
let size = get_key_size(cipher);
vec![0u8; size].into_boxed_slice()
}
/// Get KeySize for CipherType
pub fn get_key_size(cipher: CipherType) -> usize {
match cipher {
TDES => tdes::KEY_LEN,
TDES2K => tdes_2k::KEY_LEN,
TDES3K => tdes_3k::KEY_LEN,
AES => aes::KEY_LEN
}
}
/// Check Key Slice
pub fn check_key(key: &[u8], cipher: CipherType) -> bool {
if key.len() != get_key_size(cipher) { false } else { true }
}
/// Set Key Version for DES/TDES Keys
/// KeyVersion is stored in the LSBits of the first 8 Bytes
/// Parity Bits are not used from DESFire Cars
pub fn set_key_version(key: &[u8], version: u8) -> Box<[u8]> {
let pow2 = [0x01u8, 0x02u8, 0x04u8, 0x08u8, 0x10u8, 0x20u8, 0x40u8, 0x80u8];
let mut new_key = key.to_vec();
for i in 0..8 {
if (version & pow2[i]) > 0 {
new_key[i] = (new_key[5] | 0x01u8) as u8;
} else {
new_key[i] = (new_key[5] & 0x7fu8) as u8;
}
}
new_key.into_boxed_slice()
}