summaryrefslogtreecommitdiffstats
path: root/rust/vendor/aead/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/vendor/aead/src/lib.rs')
-rw-r--r--rust/vendor/aead/src/lib.rs533
1 files changed, 533 insertions, 0 deletions
diff --git a/rust/vendor/aead/src/lib.rs b/rust/vendor/aead/src/lib.rs
new file mode 100644
index 0000000..fb67f68
--- /dev/null
+++ b/rust/vendor/aead/src/lib.rs
@@ -0,0 +1,533 @@
+//! [Authenticated Encryption with Associated Data] (AEAD) traits
+//!
+//! This crate provides an abstract interface for AEAD ciphers, which guarantee
+//! both confidentiality and integrity, even from a powerful attacker who is
+//! able to execute [chosen-ciphertext attacks]. The resulting security property,
+//! [ciphertext indistinguishability], is considered a basic requirement for
+//! modern cryptographic implementations.
+//!
+//! See [RustCrypto/AEADs] for cipher implementations which use this trait.
+//!
+//! [Authenticated Encryption with Associated Data]: https://en.wikipedia.org/wiki/Authenticated_encryption
+//! [chosen-ciphertext attacks]: https://en.wikipedia.org/wiki/Chosen-ciphertext_attack
+//! [ciphertext indistinguishability]: https://en.wikipedia.org/wiki/Ciphertext_indistinguishability
+//! [RustCrypto/AEADs]: https://github.com/RustCrypto/AEADs
+
+#![no_std]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![forbid(unsafe_code, clippy::unwrap_used)]
+#![doc(
+ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
+ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
+ html_root_url = "https://docs.rs/aead/0.4.3"
+)]
+#![warn(missing_docs, rust_2018_idioms)]
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+#[cfg(feature = "std")]
+extern crate std;
+
+#[cfg(feature = "dev")]
+#[cfg_attr(docsrs, doc(cfg(feature = "dev")))]
+pub mod dev;
+
+#[cfg(feature = "stream")]
+#[cfg_attr(docsrs, doc(cfg(feature = "stream")))]
+pub mod stream;
+
+pub use generic_array::{self, typenum::consts};
+
+#[cfg(feature = "heapless")]
+#[cfg_attr(docsrs, doc(cfg(feature = "heapless")))]
+pub use heapless;
+
+#[cfg(feature = "rand_core")]
+#[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
+pub use rand_core;
+
+use core::fmt;
+use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
+
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+
+#[cfg(feature = "rand_core")]
+use rand_core::{CryptoRng, RngCore};
+
+/// Error type.
+///
+/// This type is deliberately opaque as to avoid potential side-channel
+/// leakage (e.g. padding oracle).
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub struct Error;
+
+/// Result type alias with [`Error`].
+pub type Result<T> = core::result::Result<T, Error>;
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("aead::Error")
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for Error {}
+
+/// Key for a [`NewAead`] algorithm
+// TODO(tarcieri): make this a struct and zeroize on drop?
+pub type Key<A> = GenericArray<u8, <A as NewAead>::KeySize>;
+
+/// Nonce: single-use value for ensuring ciphertexts are unique
+pub type Nonce<A> = GenericArray<u8, <A as AeadCore>::NonceSize>;
+
+/// Tag: authentication code which ensures ciphertexts are authentic
+pub type Tag<A> = GenericArray<u8, <A as AeadCore>::TagSize>;
+
+/// Instantiate either a stateless [`Aead`] or stateful [`AeadMut`] algorithm.
+pub trait NewAead {
+ /// The size of the key array required by this algorithm.
+ type KeySize: ArrayLength<u8>;
+
+ /// Create a new AEAD instance with the given key.
+ fn new(key: &Key<Self>) -> Self;
+
+ /// Create new AEAD instance from key given as a byte slice..
+ ///
+ /// Default implementation will accept only keys with length equal to `KeySize`.
+ fn new_from_slice(key: &[u8]) -> Result<Self>
+ where
+ Self: Sized,
+ {
+ if key.len() != Self::KeySize::to_usize() {
+ Err(Error)
+ } else {
+ Ok(Self::new(GenericArray::from_slice(key)))
+ }
+ }
+
+ /// Generate a random key for this AEAD using the provided [`CryptoRng`].
+ #[cfg(feature = "rand_core")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "rand_core")))]
+ fn generate_key(mut rng: impl CryptoRng + RngCore) -> Key<Self> {
+ let mut key = Key::<Self>::default();
+ rng.fill_bytes(&mut key);
+ key
+ }
+}
+
+/// Authenticated Encryption with Associated Data (AEAD) algorithm core trait.
+///
+/// Defines nonce, tag, and overhead sizes that are consumed by various other
+/// `Aead*` traits.
+pub trait AeadCore {
+ /// The length of a nonce.
+ type NonceSize: ArrayLength<u8>;
+
+ /// The maximum length of the nonce.
+ type TagSize: ArrayLength<u8>;
+
+ /// The upper bound amount of additional space required to support a
+ /// ciphertext vs. a plaintext.
+ type CiphertextOverhead: ArrayLength<u8> + Unsigned;
+}
+
+/// 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")]
+#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+pub trait Aead: AeadCore {
+ /// Encrypt the given plaintext payload, and return the resulting
+ /// ciphertext as a vector of bytes.
+ ///
+ /// The [`Payload`] type can be used to provide Additional Associated Data
+ /// (AAD) along with the message: this is an optional bytestring which is
+ /// not encrypted, but *is* authenticated along with the message. Failure
+ /// to pass the same AAD that was used during encryption will cause
+ /// decryption to fail, which is useful if you would like to "bind" the
+ /// ciphertext to some other identifier, like a digital signature key
+ /// or other identifier.
+ ///
+ /// If you don't care about AAD and just want to encrypt a plaintext
+ /// message, `&[u8]` will automatically be coerced into a `Payload`:
+ ///
+ /// ```nobuild
+ /// let plaintext = b"Top secret message, handle with care";
+ /// let ciphertext = cipher.encrypt(nonce, plaintext);
+ /// ```
+ ///
+ /// The default implementation assumes a postfix tag (ala AES-GCM,
+ /// AES-GCM-SIV, ChaCha20Poly1305). [`Aead`] implementations which do not
+ /// use a postfix tag will need to override this to correctly assemble the
+ /// ciphertext message.
+ fn encrypt<'msg, 'aad>(
+ &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()`] about allowable message payloads and
+ /// Associated Additional Data (AAD).
+ ///
+ /// If you have no AAD, you can call this as follows:
+ ///
+ /// ```nobuild
+ /// let ciphertext = b"...";
+ /// let plaintext = cipher.decrypt(nonce, ciphertext)?;
+ /// ```
+ ///
+ /// The default implementation assumes a postfix tag (ala AES-GCM,
+ /// AES-GCM-SIV, ChaCha20Poly1305). [`Aead`] implementations which do not
+ /// use a postfix tag will need to override this to correctly parse the
+ /// ciphertext message.
+ fn decrypt<'msg, 'aad>(
+ &self,
+ nonce: &Nonce<Self>,
+ ciphertext: impl Into<Payload<'msg, 'aad>>,
+ ) -> Result<Vec<u8>>;
+}
+
+/// Stateful Authenticated Encryption with Associated Data algorithm.
+#[cfg(feature = "alloc")]
+#[cfg_attr(docsrs, doc(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) => {{
+ if $buffer.len() < Self::TagSize::to_usize() {
+ return Err(Error);
+ }
+
+ let tag_pos = $buffer.len() - Self::TagSize::to_usize();
+ let (msg, tag) = $buffer.as_mut().split_at_mut(tag_pos);
+ $aead.decrypt_in_place_detached($nonce, $aad, msg, Tag::<Self>::from_slice(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`.
+pub trait AeadInPlace: 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(
+ &self,
+ nonce: &Nonce<Self>,
+ associated_data: &[u8],
+ buffer: &mut dyn Buffer,
+ ) -> Result<()> {
+ let tag = self.encrypt_in_place_detached(nonce, associated_data, buffer.as_mut())?;
+ buffer.extend_from_slice(tag.as_slice())?;
+ Ok(())
+ }
+
+ /// Encrypt the data in-place, returning the authentication tag
+ fn encrypt_in_place_detached(
+ &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(
+ &self,
+ nonce: &Nonce<Self>,
+ associated_data: &[u8],
+ buffer: &mut dyn Buffer,
+ ) -> Result<()> {
+ impl_decrypt_in_place!(self, nonce, associated_data, buffer)
+ }
+
+ /// 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<()>;
+}
+
+/// 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())?;
+ 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
+ /// authentication tag does not match the given ciphertext (i.e. ciphertext
+ /// is modified/unauthentic)
+ fn decrypt_in_place_detached(
+ &mut self,
+ nonce: &Nonce<Self>,
+ associated_data: &[u8],
+ buffer: &mut [u8],
+ tag: &Tag<Self>,
+ ) -> Result<()>;
+}
+
+#[cfg(feature = "alloc")]
+impl<Alg: AeadInPlace> Aead for Alg {
+ fn encrypt<'msg, 'aad>(
+ &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>(
+ &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)
+ }
+}
+
+#[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 are a combination of a message (plaintext or ciphertext)
+/// and "additional associated data" (AAD) to be authenticated (in cleartext)
+/// along with the message.
+///
+/// If you don't care about AAD, you can pass a `&[u8]` as the payload to
+/// `encrypt`/`decrypt` and it will automatically be coerced to this type.
+#[cfg(feature = "alloc")]
+#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
+pub struct Payload<'msg, 'aad> {
+ /// Message to be encrypted/decrypted
+ pub msg: &'msg [u8],
+
+ /// Optional "additional associated data" to authenticate along with
+ /// this message. If AAD is provided at the time the message is encrypted,
+ /// the same AAD *MUST* be provided at the time the message is decrypted,
+ /// or decryption will fail.
+ pub aad: &'aad [u8],
+}
+
+#[cfg(feature = "alloc")]
+impl<'msg, 'aad> From<&'msg [u8]> for Payload<'msg, 'aad> {
+ fn from(msg: &'msg [u8]) -> Self {
+ Self { msg, aad: b"" }
+ }
+}
+
+/// In-place encryption/decryption byte buffers.
+///
+/// This trait defines the set of methods needed to support in-place operations
+/// on a `Vec`-like data type.
+pub trait Buffer: AsRef<[u8]> + AsMut<[u8]> {
+ /// Get the length of the buffer
+ fn len(&self) -> usize {
+ self.as_ref().len()
+ }
+
+ /// Is the buffer empty?
+ fn is_empty(&self) -> bool {
+ self.as_ref().is_empty()
+ }
+
+ /// Extend this buffer from the given slice
+ fn extend_from_slice(&mut self, other: &[u8]) -> Result<()>;
+
+ /// Truncate this buffer to the given size
+ fn truncate(&mut self, len: usize);
+}
+
+#[cfg(feature = "alloc")]
+impl Buffer for Vec<u8> {
+ fn extend_from_slice(&mut self, other: &[u8]) -> Result<()> {
+ Vec::extend_from_slice(self, other);
+ Ok(())
+ }
+
+ fn truncate(&mut self, len: usize) {
+ Vec::truncate(self, len);
+ }
+}
+
+#[cfg(feature = "heapless")]
+impl<const N: usize> Buffer for heapless::Vec<u8, N> {
+ fn extend_from_slice(&mut self, other: &[u8]) -> Result<()> {
+ heapless::Vec::extend_from_slice(self, other).map_err(|_| Error)
+ }
+
+ fn truncate(&mut self, len: usize) {
+ heapless::Vec::truncate(self, len);
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ /// Ensure that `AeadInPlace` is object-safe
+ #[allow(dead_code)]
+ type DynAeadInPlace<N, T, O> =
+ dyn AeadInPlace<NonceSize = N, TagSize = T, CiphertextOverhead = O>;
+
+ /// Ensure that `AeadMutInPlace` is object-safe
+ #[allow(dead_code)]
+ type DynAeadMutInPlace<N, T, O> =
+ dyn AeadMutInPlace<NonceSize = N, TagSize = T, CiphertextOverhead = O>;
+}