diff --git a/Cargo.lock b/Cargo.lock index 972a00a21..33d30686a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,7 @@ dependencies = [ "bytes", "crypto-common 0.2.0-rc.2", "heapless", + "inout", ] [[package]] diff --git a/aead/Cargo.toml b/aead/Cargo.toml index 66a4ae464..10c425dba 100644 --- a/aead/Cargo.toml +++ b/aead/Cargo.toml @@ -23,9 +23,10 @@ arrayvec = { version = "0.7", optional = true, default-features = false } blobby = { version = "0.4.0-pre.0", optional = true } bytes = { version = "1", optional = true, default-features = false } heapless = { version = "0.8", optional = true, default-features = false } +inout = { version = "0.2.0-rc.4", optional = true, default-features = false } [features] -default = ["rand_core"] +default = ["inout", "rand_core"] alloc = [] dev = ["blobby"] os_rng = ["crypto-common/os_rng", "rand_core"] diff --git a/aead/src/lib.rs b/aead/src/lib.rs index edc0760a6..26faef2a3 100644 --- a/aead/src/lib.rs +++ b/aead/src/lib.rs @@ -30,21 +30,26 @@ pub use crypto_common::{ pub use arrayvec; #[cfg(feature = "bytes")] pub use bytes; -#[cfg(feature = "heapless")] -pub use heapless; - #[cfg(feature = "rand_core")] pub use crypto_common::rand_core; +#[cfg(feature = "heapless")] +pub use heapless; +#[cfg(feature = "inout")] +pub use inout; use core::fmt; -use crypto_common::array::{Array, ArraySize, typenum::Unsigned}; +use crypto_common::array::{Array, ArraySize}; #[cfg(feature = "alloc")] use alloc::vec::Vec; #[cfg(feature = "bytes")] use bytes::BytesMut; +#[cfg(any(feature = "alloc", feature = "inout"))] +use crypto_common::array::typenum::Unsigned; #[cfg(feature = "os_rng")] use crypto_common::rand_core::{OsError, OsRng, TryRngCore}; +#[cfg(feature = "inout")] +use inout::InOutBuf; #[cfg(feature = "rand_core")] use rand_core::{CryptoRng, TryCryptoRng}; @@ -240,23 +245,24 @@ pub trait AeadInPlace: AeadCore { } /// In-place AEAD trait which handles the authentication tag as a return value/separate parameter. -pub trait AeadInPlaceDetached: AeadCore { - /// Encrypt the data in-place, returning the authentication tag. - fn encrypt_in_place_detached( +#[cfg(feature = "inout")] +pub trait AeadInOut: AeadCore { + /// Encrypt the data in the provided [`InOutBuf`], returning the authentication tag. + fn encrypt_inout_detached( &self, nonce: &Nonce, associated_data: &[u8], - buffer: &mut [u8], + buffer: InOutBuf<'_, '_, u8>, ) -> Result>; - /// Decrypt the message in-place, returning an error in the event the provided - /// authentication tag does not match the given ciphertext (i.e. ciphertext + /// Decrypt the data in the provided [`InOutBuf`], returning an error in the event the + /// provided authentication tag is invalid for the given ciphertext (i.e. ciphertext /// is modified/unauthentic) - fn decrypt_in_place_detached( + fn decrypt_inout_detached( &self, nonce: &Nonce, associated_data: &[u8], - buffer: &mut [u8], + buffer: InOutBuf<'_, '_, u8>, tag: &Tag, ) -> Result<()>; } @@ -267,14 +273,41 @@ pub trait AeadInPlaceDetached: AeadCore { /// This is the common convention for AEAD algorithms. pub trait PostfixTagged {} -impl AeadInPlace for T { +#[cfg(feature = "alloc")] +impl Aead for Alg { + fn encrypt<'msg, 'aad>( + &self, + nonce: &Nonce, + plaintext: impl Into>, + ) -> Result> { + let payload = plaintext.into(); + let mut buffer = Vec::with_capacity(payload.msg.len() + Self::TagSize::to_usize()); + buffer.extend_from_slice(payload.msg); + self.encrypt_in_place(nonce, payload.aad, &mut buffer)?; + Ok(buffer) + } + + fn decrypt<'msg, 'aad>( + &self, + nonce: &Nonce, + ciphertext: impl Into>, + ) -> Result> { + let payload = ciphertext.into(); + let mut buffer = Vec::from(payload.msg); + self.decrypt_in_place(nonce, payload.aad, &mut buffer)?; + Ok(buffer) + } +} + +#[cfg(feature = "inout")] +impl AeadInPlace for T { fn encrypt_in_place( &self, nonce: &Nonce, associated_data: &[u8], buffer: &mut dyn Buffer, ) -> Result<()> { - let tag = self.encrypt_in_place_detached(nonce, associated_data, buffer.as_mut())?; + let tag = self.encrypt_inout_detached(nonce, associated_data, buffer.as_mut().into())?; buffer.extend_from_slice(tag.as_slice())?; Ok(()) } @@ -293,38 +326,12 @@ impl AeadInPlace for T { let (msg, tag) = buffer.as_mut().split_at_mut(tag_pos); let tag = Tag::::try_from(&*tag).expect("tag length mismatch"); - self.decrypt_in_place_detached(nonce, associated_data, msg, &tag)?; + self.decrypt_inout_detached(nonce, associated_data, msg.into(), &tag)?; buffer.truncate(tag_pos); Ok(()) } } -#[cfg(feature = "alloc")] -impl Aead for Alg { - fn encrypt<'msg, 'aad>( - &self, - nonce: &Nonce, - plaintext: impl Into>, - ) -> Result> { - let payload = plaintext.into(); - let mut buffer = Vec::with_capacity(payload.msg.len() + Self::TagSize::to_usize()); - buffer.extend_from_slice(payload.msg); - self.encrypt_in_place(nonce, payload.aad, &mut buffer)?; - Ok(buffer) - } - - fn decrypt<'msg, 'aad>( - &self, - nonce: &Nonce, - ciphertext: impl Into>, - ) -> Result> { - let payload = ciphertext.into(); - let mut buffer = Vec::from(payload.msg); - self.decrypt_in_place(nonce, payload.aad, &mut buffer)?; - Ok(buffer) - } -} - /// AEAD payloads (message + AAD). /// /// Combination of a message (plaintext or ciphertext) and