1 // Copyright 2015-2021 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 //! Authenticated Encryption with Associated Data (AEAD).
16 //!
17 //! See [Authenticated encryption: relations among notions and analysis of the
18 //! generic composition paradigm][AEAD] for an introduction to the concept of
19 //! AEADs.
20 //!
21 //! [AEAD]: https://eprint.iacr.org/2000/025.pdf
22 //! [`crypto.cipher.AEAD`]: https://golang.org/pkg/crypto/cipher/#AEAD
23 
24 use super::{Aad, Algorithm, BoundKey, LessSafeKey, NonceSequence, Tag, UnboundKey};
25 use crate::error;
26 
27 /// An AEAD key for encrypting and signing ("sealing"), bound to a nonce
28 /// sequence.
29 ///
30 /// Intentionally not `Clone` or `Copy` since cloning would allow duplication
31 /// of the nonce sequence.
32 pub struct SealingKey<N: NonceSequence> {
33     key: LessSafeKey,
34     nonce_sequence: N,
35 }
36 
37 impl<N: NonceSequence> BoundKey<N> for SealingKey<N> {
new(key: UnboundKey, nonce_sequence: N) -> Self38     fn new(key: UnboundKey, nonce_sequence: N) -> Self {
39         Self {
40             key: key.into_inner(),
41             nonce_sequence,
42         }
43     }
44 
45     #[inline]
algorithm(&self) -> &'static Algorithm46     fn algorithm(&self) -> &'static Algorithm {
47         self.key.algorithm()
48     }
49 }
50 
51 impl<N: NonceSequence> core::fmt::Debug for SealingKey<N> {
fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error>52     fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
53         self.key.fmt_debug("SealingKey", f)
54     }
55 }
56 
57 impl<N: NonceSequence> SealingKey<N> {
58     /// Encrypts and signs (“seals”) data in place, appending the tag to the
59     /// resulting ciphertext.
60     ///
61     /// `key.seal_in_place_append_tag(aad, in_out)` is equivalent to:
62     ///
63     /// ```skip
64     /// key.seal_in_place_separate_tag(aad, in_out.as_mut())
65     ///     .map(|tag| in_out.extend(tag.as_ref()))
66     /// ```
67     #[inline]
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>,68     pub fn seal_in_place_append_tag<A, InOut>(
69         &mut self,
70         aad: Aad<A>,
71         in_out: &mut InOut,
72     ) -> Result<(), error::Unspecified>
73     where
74         A: AsRef<[u8]>,
75         InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>,
76     {
77         self.key
78             .seal_in_place_append_tag(self.nonce_sequence.advance()?, aad, in_out)
79     }
80 
81     /// Encrypts and signs (“seals”) data in place.
82     ///
83     /// `aad` is the additional authenticated data (AAD), if any. This is
84     /// authenticated but not encrypted. The type `A` could be a byte slice
85     /// `&[u8]`, a byte array `[u8; N]` for some constant `N`, `Vec<u8>`, etc.
86     /// If there is no AAD then use `Aad::empty()`.
87     ///
88     /// The plaintext is given as the input value of `in_out`. `seal_in_place()`
89     /// will overwrite the plaintext with the ciphertext and return the tag.
90     /// For most protocols, the caller must append the tag to the ciphertext.
91     /// The tag will be `self.algorithm.tag_len()` bytes long.
92     #[inline]
seal_in_place_separate_tag<A>( &mut self, aad: Aad<A>, in_out: &mut [u8], ) -> Result<Tag, error::Unspecified> where A: AsRef<[u8]>,93     pub fn seal_in_place_separate_tag<A>(
94         &mut self,
95         aad: Aad<A>,
96         in_out: &mut [u8],
97     ) -> Result<Tag, error::Unspecified>
98     where
99         A: AsRef<[u8]>,
100     {
101         self.key
102             .seal_in_place_separate_tag(self.nonce_sequence.advance()?, aad, in_out)
103     }
104 }
105