| // Copyright 2015-2021 Brian Smith. |
| // |
| // Permission to use, copy, modify, and/or distribute this software for any |
| // purpose with or without fee is hereby granted, provided that the above |
| // copyright notice and this permission notice appear in all copies. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES |
| // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY |
| // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
| // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
| // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| //! Authenticated Encryption with Associated Data (AEAD). |
| //! |
| //! See [Authenticated encryption: relations among notions and analysis of the |
| //! generic composition paradigm][AEAD] for an introduction to the concept of |
| //! AEADs. |
| //! |
| //! [AEAD]: http://www-cse.ucsd.edu/~mihir/papers/oem.html |
| //! [`crypto.cipher.AEAD`]: https://golang.org/pkg/crypto/cipher/#AEAD |
| |
| use super::{Aad, Algorithm, BoundKey, LessSafeKey, NonceSequence, Tag, UnboundKey}; |
| use crate::error; |
| |
| /// An AEAD key for encrypting and signing ("sealing"), bound to a nonce |
| /// sequence. |
| /// |
| /// Intentionally not `Clone` or `Copy` since cloning would allow duplication |
| /// of the nonce sequence. |
| pub struct SealingKey<N: NonceSequence> { |
| key: LessSafeKey, |
| nonce_sequence: N, |
| } |
| |
| impl<N: NonceSequence> BoundKey<N> for SealingKey<N> { |
| fn new(key: UnboundKey, nonce_sequence: N) -> Self { |
| Self { |
| key: key.into_inner(), |
| nonce_sequence, |
| } |
| } |
| |
| #[inline] |
| fn algorithm(&self) -> &'static Algorithm { |
| self.key.algorithm() |
| } |
| } |
| |
| impl<N: NonceSequence> core::fmt::Debug for SealingKey<N> { |
| fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { |
| self.key.fmt_debug("SealingKey", f) |
| } |
| } |
| |
| impl<N: NonceSequence> SealingKey<N> { |
| /// Encrypts and signs (“seals”) data in place, appending the tag to the |
| /// resulting ciphertext. |
| /// |
| /// `key.seal_in_place_append_tag(aad, in_out)` is equivalent to: |
| /// |
| /// ```skip |
| /// key.seal_in_place_separate_tag(aad, in_out.as_mut()) |
| /// .map(|tag| in_out.extend(tag.as_ref())) |
| /// ``` |
| #[inline] |
| pub fn seal_in_place_append_tag<A, InOut>( |
| &mut self, |
| aad: Aad<A>, |
| in_out: &mut InOut, |
| ) -> Result<(), error::Unspecified> |
| where |
| A: AsRef<[u8]>, |
| InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>, |
| { |
| self.key |
| .seal_in_place_append_tag(self.nonce_sequence.advance()?, aad, in_out) |
| } |
| |
| /// Encrypts and signs (“seals”) data in place. |
| /// |
| /// `aad` is the additional authenticated data (AAD), if any. This is |
| /// authenticated but not encrypted. The type `A` could be a byte slice |
| /// `&[u8]`, a byte array `[u8; N]` for some constant `N`, `Vec<u8>`, etc. |
| /// If there is no AAD then use `Aad::empty()`. |
| /// |
| /// The plaintext is given as the input value of `in_out`. `seal_in_place()` |
| /// will overwrite the plaintext with the ciphertext and return the tag. |
| /// For most protocols, the caller must append the tag to the ciphertext. |
| /// The tag will be `self.algorithm.tag_len()` bytes long. |
| #[inline] |
| pub fn seal_in_place_separate_tag<A>( |
| &mut self, |
| aad: Aad<A>, |
| in_out: &mut [u8], |
| ) -> Result<Tag, error::Unspecified> |
| where |
| A: AsRef<[u8]>, |
| { |
| self.key |
| .seal_in_place_separate_tag(self.nonce_sequence.advance()?, aad, in_out) |
| } |
| } |