diff --git a/aead/src/stream.rs b/aead/src/stream.rs index 3e220b6fb..554284b35 100644 --- a/aead/src/stream.rs +++ b/aead/src/stream.rs @@ -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 = GenericArray>; @@ -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>, + ) -> Result, 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>, + ) -> Result, 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 where @@ -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 ) => { @@ -200,10 +239,34 @@ 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>, + ) -> 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_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, @@ -211,29 +274,44 @@ macro_rules! impl_stream_object { 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>, + ) -> Result, 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) } } } @@ -241,8 +319,11 @@ macro_rules! impl_stream_object { impl_stream_object!( Encryptor, + encrypt_next, encrypt_next_in_place, + encrypt_last, encrypt_last_in_place, + encrypt, encrypt_in_place, "encrypt", "ℰ STREAM encryptor" @@ -250,8 +331,11 @@ impl_stream_object!( impl_stream_object!( Decryptor, + decrypt_next, decrypt_next_in_place, + decrypt_last, decrypt_last_in_place, + decrypt, decrypt_in_place, "decrypt", "𝒟 STREAM decryptor"