use des::cipher::{BlockDecrypt, BlockEncrypt, KeyInit};
use generic_array::GenericArray;
use trussed_core::{
api::{reply, request},
Error,
};
use crate::key;
use crate::service::MechanismImpl;
use crate::store::Keystore;
const TDES_KEY_SIZE: usize = 24;
impl MechanismImpl for super::Tdes {
#[inline(never)]
fn encrypt(
&self,
keystore: &mut impl Keystore,
request: &request::Encrypt,
) -> Result<reply::Encrypt, Error> {
if request.message.len() != 8 {
return Err(Error::WrongMessageLength);
}
let key_id = request.key;
let key = keystore.load_key(key::Secrecy::Secret, None, &key_id)?;
if !matches!(
key.kind,
key::Kind::Symmetric(TDES_KEY_SIZE) | key::Kind::Shared(TDES_KEY_SIZE)
) {
return Err(Error::WrongKeyKind);
}
let symmetric_key: [u8; TDES_KEY_SIZE] = key
.material
.as_slice()
.try_into()
.map_err(|_| Error::InternalError)?;
let cipher = des::TdesEde3::new(GenericArray::from_slice(&symmetric_key));
let mut message = request.message.clone();
cipher.encrypt_block(GenericArray::from_mut_slice(&mut message));
Ok(reply::Encrypt {
ciphertext: message,
nonce: Default::default(),
tag: Default::default(),
})
}
#[inline(never)]
fn decrypt(
&self,
keystore: &mut impl Keystore,
request: &request::Decrypt,
) -> Result<reply::Decrypt, Error> {
if request.message.len() != 8 {
return Err(Error::WrongMessageLength);
}
let key_id = request.key;
let symmetric_key: [u8; TDES_KEY_SIZE] = keystore
.load_key(key::Secrecy::Secret, None, &key_id)?
.material
.as_slice()
.try_into()
.map_err(|_| Error::InternalError)?;
let cipher = des::TdesEde3::new(GenericArray::from_slice(&symmetric_key));
let mut message = request.message.clone();
cipher.decrypt_block(GenericArray::from_mut_slice(&mut message));
Ok(reply::Decrypt {
plaintext: Some(message),
})
}
fn unsafe_inject_key(
&self,
keystore: &mut impl Keystore,
request: &request::UnsafeInjectKey,
) -> Result<reply::UnsafeInjectKey, Error> {
if request.raw_key.len() != TDES_KEY_SIZE {
return Err(Error::InvalidSerializedKey);
}
let key_id = keystore.store_key(
request.attributes.persistence,
key::Secrecy::Secret,
key::Kind::Symmetric(request.raw_key.len()),
&request.raw_key,
)?;
Ok(reply::UnsafeInjectKey { key: key_id })
}
}