libs.nfc_rs/src/crypto/cipher_key.rs
Kai Jan Kriegel 7d8c8bb3fe ran cargo fix
2022-05-05 13:48:31 +02:00

104 lines
2.7 KiB
Rust

use crate::crypto::cipher::{aes, tdes, tdes_2k, tdes_3k, Cipher};
use crate::crypto::cipher_type::CipherType;
use crate::crypto::cipher_type::CipherType::*;
use crate::error::Result;
use simple_error::simple_error;
#[derive(Debug, Clone)]
pub struct CipherKey {
/// Key as Array
pub key: Box<[u8]>, //TODO: Decide if this should be pub
/// CipherType of Key
#[allow(dead_code)]
pub cipher: CipherType,
/// KeyVersion of Key
#[allow(dead_code)]
pub 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(simple_error!("KeyVersion is to low for AES Key (Minimum = 0x10)").into());
}
if !check_key(key, cipher.clone()) {
return Err(simple_error!("Key is not valid for CipherType").into());
}
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::Tdes::KEY_SIZE,
TDES2K => tdes_2k::Tdes2k::KEY_SIZE,
TDES3K => tdes_3k::Tdes3k::KEY_SIZE,
AES => aes::AES::KEY_SIZE,
}
}
/// 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()
}