use crate::api::*;
use crate::error::Error;
use crate::service::*;
use crate::types::*;
#[cfg(feature = "chacha8-poly1305")]
impl GenerateKey for super::Chacha8Poly1305 {
#[inline(never)]
fn generate_key(keystore: &mut impl Keystore, request: &request::GenerateKey)
-> Result<reply::GenerateKey, Error>
{
use rand_core::RngCore as _;
let mut serialized = [0u8; 44];
let entropy = &mut serialized[..32];
keystore.rng().fill_bytes(entropy);
let key_id = keystore.store_key(
request.attributes.persistence,
key::Secrecy::Secret,
key::Kind::Symmetric32Nonce(12),
&serialized,
)?;
Ok(reply::GenerateKey { key: key_id })
}
}
#[inline(never)]
fn increment_nonce(nonce: &mut [u8]) -> Result<(), Error> {
let mut carry: u16 = 1;
for digit in nonce.iter_mut() {
let x = (*digit as u16) + carry;
*digit = x as u8;
carry = x >> 8;
}
if carry == 0 {
Ok(())
} else {
Err(Error::NonceOverflow)
}
}
#[cfg(feature = "chacha8-poly1305")]
impl Decrypt for super::Chacha8Poly1305
{
#[inline(never)]
fn decrypt(keystore: &mut impl Keystore, request: &request::Decrypt)
-> Result<reply::Decrypt, Error>
{
use chacha20poly1305::ChaCha8Poly1305;
use chacha20poly1305::aead::{AeadInPlace, NewAead};
let serialized_material = keystore
.load_key(key::Secrecy::Secret, Some(key::Kind::Symmetric32Nonce(12)), &request.key)?
.material;
let serialized = serialized_material.as_slice();
assert!(serialized.len() == 44);
let symmetric_key = &serialized[..32];
let aead = ChaCha8Poly1305::new(&GenericArray::clone_from_slice(&symmetric_key));
let mut plaintext = request.message.clone();
let nonce = GenericArray::from_slice(&request.nonce);
let tag = GenericArray::from_slice(&request.tag);
let outcome = aead.decrypt_in_place_detached(
&nonce, &request.associated_data, &mut plaintext, &tag);
Ok(reply::Decrypt { plaintext: {
if outcome.is_ok() {
Some(plaintext)
} else {
None
}
}})
}
}
#[cfg(feature = "chacha8-poly1305")]
impl Encrypt for super::Chacha8Poly1305
{
#[inline(never)]
fn encrypt(keystore: &mut impl Keystore, request: &request::Encrypt)
-> Result<reply::Encrypt, Error>
{
use chacha20poly1305::ChaCha8Poly1305;
use chacha20poly1305::aead::{AeadInPlace, NewAead};
let secrecy = key::Secrecy::Secret;
let key_kind = key::Kind::Symmetric32Nonce(12);
let key_id = &request.key;
let mut serialized_material = keystore
.load_key(secrecy, Some(key_kind), key_id)?
.material;
let serialized: &mut [u8] = serialized_material.as_mut();
assert!(serialized.len() == 44);
let location = keystore.location(secrecy, key_id).unwrap();
{
let nonce = &mut serialized[32..];
increment_nonce(nonce)?;
}
keystore.overwrite_key(location, secrecy, key_kind, key_id, &serialized)?;
let (symmetric_key, generated_nonce) = serialized.split_at_mut(32);
let nonce = match request.nonce.as_ref() {
Some(nonce) => nonce.as_ref(),
None => generated_nonce,
};
let aead = ChaCha8Poly1305::new(&GenericArray::clone_from_slice(symmetric_key));
let mut ciphertext = request.message.clone();
let tag: [u8; 16] = aead.encrypt_in_place_detached(
&GenericArray::clone_from_slice(nonce),
&request.associated_data,
&mut ciphertext,
).unwrap().as_slice().try_into().unwrap();
let nonce = ShortData::from_slice(nonce).unwrap();
let tag = ShortData::from_slice(&tag).unwrap();
Ok(reply::Encrypt { ciphertext, nonce, tag })
}
}
#[cfg(feature = "chacha8-poly1305")]
impl WrapKey for super::Chacha8Poly1305
{
#[inline(never)]
fn wrap_key(keystore: &mut impl Keystore, request: &request::WrapKey)
-> Result<reply::WrapKey, Error>
{
debug!("trussed: Chacha8Poly1305::WrapKey");
let serialized_key = keystore
.load_key(key::Secrecy::Secret, None, &request.key)?;
let message = Message::from_slice(&serialized_key.serialize()).unwrap();
let encryption_request = request::Encrypt {
mechanism: Mechanism::Chacha8Poly1305,
key: request.wrapping_key,
message,
associated_data: ShortData::new(),
nonce: None,
};
let encryption_reply = <super::Chacha8Poly1305>::encrypt(keystore, &encryption_request)?;
let wrapped_key = crate::postcard_serialize_bytes(&encryption_reply).map_err(|_| Error::CborError)?;
Ok(reply::WrapKey { wrapped_key })
}
}
#[cfg(feature = "chacha8-poly1305")]
impl UnwrapKey for super::Chacha8Poly1305
{
#[inline(never)]
fn unwrap_key(keystore: &mut impl Keystore, request: &request::UnwrapKey)
-> Result<reply::UnwrapKey, Error>
{
let reply::Encrypt { ciphertext, nonce, tag } = crate::postcard_deserialize(
&request.wrapped_key).map_err(|_| Error::CborError)?;
let decryption_request = request::Decrypt {
mechanism: Mechanism::Chacha8Poly1305,
key: request.wrapping_key,
message: ciphertext,
associated_data: request.associated_data.clone(),
nonce,
tag,
};
let serialized_key = if let Some(serialized_key) =
<super::Chacha8Poly1305>::decrypt(keystore, &decryption_request)?.plaintext {
serialized_key
} else {
return Ok(reply::UnwrapKey { key: None } );
};
let key::Key{ flags: _, kind, material } = key::Key::try_deserialize(&serialized_key)?;
let key_id = keystore.store_key(
request.attributes.persistence,
key::Secrecy::Secret,
kind,
&material,
)?;
Ok(reply::UnwrapKey { key: Some(key_id) })
}
}
#[cfg(not(feature = "chacha8-poly1305"))]
impl<P: Platform>
Decrypt<P> for super::Chacha8Poly1305 {}
#[cfg(not(feature = "chacha8-poly1305"))]
impl<P: Platform>
Encrypt<P> for super::Chacha8Poly1305 {}
#[cfg(not(feature = "chacha8-poly1305"))]
impl<P: Platform>
GenerateKey<P> for super::Chacha8Poly1305 {}