Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 90 additions & 6 deletions aead/src/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ use generic_array::{
ArrayLength, GenericArray,
};

#[cfg(feature = "alloc")]
use {crate::Payload, alloc::vec::Vec};

/// Nonce as used by a given AEAD construction and STREAM primitive.
pub type Nonce<A, S> = GenericArray<u8, NonceSize<A, S>>;

Expand Down Expand Up @@ -110,6 +113,39 @@ where
buffer: &mut dyn Buffer,
) -> Result<(), Error>;

/// Encrypt the given plaintext payload, and return the resulting
/// ciphertext as a vector of bytes.
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
fn encrypt<'msg, 'aad>(
&self,
position: Self::Counter,
last_block: bool,
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error> {
let payload = plaintext.into();
let mut buffer = Vec::with_capacity(payload.msg.len() + A::TagSize::to_usize());
buffer.extend_from_slice(payload.msg);
self.encrypt_in_place(position, last_block, payload.aad, &mut buffer)?;
Ok(buffer)
}

/// Decrypt the given ciphertext slice, and return the resulting plaintext
/// as a vector of bytes.
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
fn decrypt<'msg, 'aad>(
&self,
position: Self::Counter,
last_block: bool,
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error> {
let payload = ciphertext.into();
let mut buffer = Vec::from(payload.msg);
self.decrypt_in_place(position, last_block, payload.aad, &mut buffer)?;
Ok(buffer)
}

/// Obtain [`Encryptor`] for this [`StreamPrimitive`].
fn encryptor(self) -> Encryptor<A, Self>
where
Expand All @@ -132,8 +168,11 @@ macro_rules! impl_stream_object {
(
$name:ident,
$next_method:tt,
$next_in_place_method:tt,
$last_method:tt,
$op_method:tt,
$last_in_place_method:tt,
$op:tt,
$in_place_op:tt,
$op_desc:expr,
$obj_desc:expr
) => {
Expand Down Expand Up @@ -200,58 +239,103 @@ macro_rules! impl_stream_object {
}
}

#[doc = "Use the underlying AEAD to"]
#[doc = $op_desc]
#[doc = "the next AEAD message in this STREAM, returning the"]
#[doc = "result as a [`Vec`]."]
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn $next_method<'msg, 'aad>(
&mut self,
payload: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error> {
if self.position == S::COUNTER_MAX {
// Counter overflow. Note that the maximum counter value is
// deliberately disallowed, as it would preclude being able
// to encrypt a last block (i.e. with `$last_in_place_method`)
return Err(Error);
}

let result = self.stream.$op(self.position, false, payload)?;

// Note: overflow checked above
self.position += S::COUNTER_INCR;
Ok(result)
}

#[doc = "Use the underlying AEAD to"]
#[doc = $op_desc]
#[doc = "the next AEAD message in this STREAM in-place."]
pub fn $next_method(
pub fn $next_in_place_method(
&mut self,
associated_data: &[u8],
buffer: &mut dyn Buffer,
) -> Result<(), Error> {
if self.position == S::COUNTER_MAX {
// Counter overflow. Note that the maximum counter value is
// deliberately disallowed, as it would preclude being able
// to encrypt a last block (i.e. with `$last_method`)
// to encrypt a last block (i.e. with `$last_in_place_method`)
return Err(Error);
}

self.stream.$op_method(self.position, false, associated_data, buffer)?;
self.stream.$in_place_op(self.position, false, associated_data, buffer)?;

// Note: overflow checked above
self.position += S::COUNTER_INCR;
Ok(())
}

#[doc = "Use the underlying AEAD to"]
#[doc = $op_desc]
#[doc = "the last AEAD message in this STREAM,"]
#[doc = "consuming the "]
#[doc = $obj_desc]
#[doc = "object in order to prevent further use."]
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn $last_method<'msg, 'aad>(
self,
payload: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>, Error> {
self.stream.$op(self.position, true, payload)
}

#[doc = "Use the underlying AEAD to"]
#[doc = $op_desc]
#[doc = "the last AEAD message in this STREAM in-place,"]
#[doc = "consuming the "]
#[doc = $obj_desc]
#[doc = "object in order to prevent further use."]
pub fn $last_method(
pub fn $last_in_place_method(
self,
associated_data: &[u8],
buffer: &mut dyn Buffer
) -> Result<(), Error> {
self.stream.$op_method(self.position, true, associated_data, buffer)
self.stream.$in_place_op(self.position, true, associated_data, buffer)
}
}
}
}

impl_stream_object!(
Encryptor,
encrypt_next,
encrypt_next_in_place,
encrypt_last,
encrypt_last_in_place,
encrypt,
encrypt_in_place,
"encrypt",
"ℰ STREAM encryptor"
);

impl_stream_object!(
Decryptor,
decrypt_next,
decrypt_next_in_place,
decrypt_last,
decrypt_last_in_place,
decrypt,
decrypt_in_place,
"decrypt",
"𝒟 STREAM decryptor"
Expand Down