use crate::{crypto::cipher_suite::CipherSuiteParams, error::Result, frame::FrameBuffer};
use super::AadData;
pub struct EncryptionBufferView<'a> {
pub aad: &'a mut [u8],
pub cipher_text: &'a mut [u8],
pub tag: &'a mut [u8],
}
pub struct EncryptionBuffer<'a> {
io_buffer: &'a mut [u8],
aad_len: usize,
cipher_text_len: usize,
}
impl<'a> EncryptionBuffer<'a> {
pub fn try_allocate(
buffer: &'a mut impl FrameBuffer,
cipher_suite: &CipherSuiteParams,
aad_data: &impl AadData,
unencrypted_data: &[u8],
) -> Result<Self> {
let aad_len = aad_data.len();
let cipher_text_len = unencrypted_data.len();
let buffer_len_needed = cipher_text_len + aad_len + cipher_suite.auth_tag_len;
log::trace!("Trying to allocate encryption buffer of size {buffer_len_needed}");
let io_buffer = buffer.allocate(buffer_len_needed)?.as_mut();
let mut encryption_buffer = Self {
io_buffer,
aad_len,
cipher_text_len,
};
encryption_buffer.try_fill(aad_data, unencrypted_data)?;
Ok(encryption_buffer)
}
fn try_fill(&mut self, aad_data: &impl AadData, unencrypted_data: &[u8]) -> Result<()> {
let buffers = EncryptionBufferView::from(self);
aad_data.serialize(buffers.aad)?;
buffers.cipher_text.copy_from_slice(unencrypted_data);
Ok(())
}
}
impl<'a> From<EncryptionBuffer<'a>> for &'a mut [u8] {
fn from(val: EncryptionBuffer<'a>) -> Self {
val.io_buffer
}
}
impl<'a, 'buf> From<&'a mut EncryptionBuffer<'buf>> for EncryptionBufferView<'a> {
fn from(unencrypted_data: &'a mut EncryptionBuffer<'buf>) -> Self {
let (aad, remain) = unencrypted_data
.io_buffer
.split_at_mut(unencrypted_data.aad_len);
let (cipher_text, tag) = remain.split_at_mut(unencrypted_data.cipher_text_len);
EncryptionBufferView {
aad,
cipher_text,
tag,
}
}
}
#[cfg(test)]
mod test {
use crate::{CipherSuite, crypto::buffer::test::TestAadData};
use super::*;
#[test]
fn allocate_encryption_buffer() {
let mut buffer = Vec::new();
let aad_data = TestAadData { data: [1, 2, 3, 4] };
let unencrypted_data = [5, 6, 7, 8, 9];
let cipher_suite = CipherSuite::AesGcm128Sha256.into();
let mut encryption_buffer = EncryptionBuffer::try_allocate(
&mut buffer,
&cipher_suite,
&aad_data,
&unencrypted_data,
)
.unwrap();
let view = EncryptionBufferView::from(&mut encryption_buffer);
assert_eq!(view.aad, [1, 2, 3, 4]);
assert_eq!(view.cipher_text, [5, 6, 7, 8, 9]);
assert_eq!(view.tag.len(), cipher_suite.auth_tag_len);
}
}