Skip to content

Commit

Permalink
aead: remove stateful AEAD traits (AeadMut*) (#1740)
Browse files Browse the repository at this point in the history
We currently have no implementations which require these traits, or
plans to implement any.

If we do wind up needing these, they can be easily added back.
  • Loading branch information
tarcieri authored Jan 30, 2025
1 parent 1a770af commit 88b3274
Showing 1 changed file with 10 additions and 177 deletions.
187 changes: 10 additions & 177 deletions aead/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,6 @@ pub trait AeadCore {
}

/// Authenticated Encryption with Associated Data (AEAD) algorithm.
///
/// This trait is intended for use with stateless AEAD algorithms. The
/// [`AeadMut`] trait provides a stateful interface.
#[cfg(feature = "alloc")]
pub trait Aead: AeadCore {
/// Encrypt the given plaintext payload, and return the resulting
Expand Down Expand Up @@ -207,53 +204,6 @@ pub trait Aead: AeadCore {
) -> Result<Vec<u8>>;
}

/// Stateful Authenticated Encryption with Associated Data algorithm.
#[cfg(feature = "alloc")]
pub trait AeadMut: AeadCore {
/// Encrypt the given plaintext slice, and return the resulting ciphertext
/// as a vector of bytes.
///
/// See notes on [`Aead::encrypt()`] about allowable message payloads and
/// Associated Additional Data (AAD).
fn encrypt<'msg, 'aad>(
&mut self,
nonce: &Nonce<Self>,
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>>;

/// Decrypt the given ciphertext slice, and return the resulting plaintext
/// as a vector of bytes.
///
/// See notes on [`Aead::encrypt()`] and [`Aead::decrypt()`] about allowable
/// message payloads and Associated Additional Data (AAD).
fn decrypt<'msg, 'aad>(
&mut self,
nonce: &Nonce<Self>,
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>>;
}

/// Implement the `decrypt_in_place` method on [`AeadInPlace`] and
/// [`AeadMutInPlace]`, using a macro to gloss over the `&self` vs `&mut self`.
///
/// Assumes a postfix authentication tag. AEAD ciphers which do not use a
/// postfix authentication tag will need to define their own implementation.
macro_rules! impl_decrypt_in_place {
($aead:expr, $nonce:expr, $aad:expr, $buffer:expr) => {{
let tag_pos = $buffer
.len()
.checked_sub(Self::TagSize::to_usize())
.ok_or(Error)?;

let (msg, tag) = $buffer.as_mut().split_at_mut(tag_pos);
let tag = Tag::<Self>::try_from(&*tag).expect("tag length mismatch");

$aead.decrypt_in_place_detached($nonce, $aad, msg, &tag)?;
$buffer.truncate(tag_pos);
Ok(())
}};
}

/// In-place stateless AEAD trait.
///
/// This trait is both object safe and has no dependencies on `alloc` or `std`.
Expand Down Expand Up @@ -297,72 +247,24 @@ pub trait AeadInPlace: AeadCore {
associated_data: &[u8],
buffer: &mut dyn Buffer,
) -> Result<()> {
impl_decrypt_in_place!(self, nonce, associated_data, buffer)
}
let tag_pos = buffer
.len()
.checked_sub(Self::TagSize::to_usize())
.ok_or(Error)?;

/// Decrypt the message in-place, returning an error in the event the provided
/// authentication tag does not match the given ciphertext (i.e. ciphertext
/// is modified/unauthentic)
fn decrypt_in_place_detached(
&self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
tag: &Tag<Self>,
) -> Result<()>;
}
let (msg, tag) = buffer.as_mut().split_at_mut(tag_pos);
let tag = Tag::<Self>::try_from(&*tag).expect("tag length mismatch");

/// In-place stateful AEAD trait.
///
/// This trait is both object safe and has no dependencies on `alloc` or `std`.
pub trait AeadMutInPlace: AeadCore {
/// Encrypt the given buffer containing a plaintext message in-place.
///
/// The buffer must have sufficient capacity to store the ciphertext
/// message, which will always be larger than the original plaintext.
/// The exact size needed is cipher-dependent, but generally includes
/// the size of an authentication tag.
///
/// Returns an error if the buffer has insufficient capacity to store the
/// resulting ciphertext message.
fn encrypt_in_place(
&mut self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut impl Buffer,
) -> Result<()> {
let tag = self.encrypt_in_place_detached(nonce, associated_data, buffer.as_mut())?;
buffer.extend_from_slice(tag.as_slice())?;
self.decrypt_in_place_detached(nonce, associated_data, msg, &tag)?;
buffer.truncate(tag_pos);
Ok(())
}

/// Encrypt the data in-place, returning the authentication tag
fn encrypt_in_place_detached(
&mut self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<Tag<Self>>;

/// Decrypt the message in-place, returning an error in the event the
/// provided authentication tag does not match the given ciphertext.
///
/// The buffer will be truncated to the length of the original plaintext
/// message upon success.
fn decrypt_in_place(
&mut self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut impl Buffer,
) -> Result<()> {
impl_decrypt_in_place!(self, nonce, associated_data, buffer)
}

/// Decrypt the data in-place, returning an error in the event the provided
/// Decrypt the message in-place, returning an error in the event the provided
/// authentication tag does not match the given ciphertext (i.e. ciphertext
/// is modified/unauthentic)
fn decrypt_in_place_detached(
&mut self,
&self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
Expand Down Expand Up @@ -396,71 +298,6 @@ impl<Alg: AeadInPlace> Aead for Alg {
}
}

#[cfg(feature = "alloc")]
impl<Alg: AeadMutInPlace> AeadMut for Alg {
fn encrypt<'msg, 'aad>(
&mut self,
nonce: &Nonce<Self>,
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>> {
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>(
&mut self,
nonce: &Nonce<Self>,
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> Result<Vec<u8>> {
let payload = ciphertext.into();
let mut buffer = Vec::from(payload.msg);
self.decrypt_in_place(nonce, payload.aad, &mut buffer)?;
Ok(buffer)
}
}

impl<Alg: AeadInPlace> AeadMutInPlace for Alg {
fn encrypt_in_place(
&mut self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut impl Buffer,
) -> Result<()> {
<Self as AeadInPlace>::encrypt_in_place(self, nonce, associated_data, buffer)
}

fn encrypt_in_place_detached(
&mut self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<Tag<Self>> {
<Self as AeadInPlace>::encrypt_in_place_detached(self, nonce, associated_data, buffer)
}

fn decrypt_in_place(
&mut self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut impl Buffer,
) -> Result<()> {
<Self as AeadInPlace>::decrypt_in_place(self, nonce, associated_data, buffer)
}

fn decrypt_in_place_detached(
&mut self,
nonce: &Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
tag: &Tag<Self>,
) -> Result<()> {
<Self as AeadInPlace>::decrypt_in_place_detached(self, nonce, associated_data, buffer, tag)
}
}

/// AEAD payloads (message + AAD).
///
/// Combination of a message (plaintext or ciphertext) and
Expand Down Expand Up @@ -572,8 +409,4 @@ mod tests {
/// Ensure that `AeadInPlace` is object-safe
#[allow(dead_code)]
type DynAeadInPlace<N, T> = dyn AeadInPlace<NonceSize = N, TagSize = T>;

/// Ensure that `AeadMutInPlace` is object-safe
#[allow(dead_code)]
type DynAeadMutInPlace<N, T> = dyn AeadMutInPlace<NonceSize = N, TagSize = T>;
}

0 comments on commit 88b3274

Please sign in to comment.