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 crate::{cpu, error, hkdf, polyfill};
25 use core::ops::RangeFrom;
26 
27 pub use self::{
28     aes_gcm::{AES_128_GCM, AES_256_GCM},
29     chacha20_poly1305::CHACHA20_POLY1305,
30     less_safe_key::LessSafeKey,
31     nonce::{Nonce, NONCE_LEN},
32     opening_key::OpeningKey,
33     sealing_key::SealingKey,
34     unbound_key::UnboundKey,
35 };
36 
37 /// A sequences of unique nonces.
38 ///
39 /// A given `NonceSequence` must never return the same `Nonce` twice from
40 /// `advance()`.
41 ///
42 /// A simple counter is a reasonable (but probably not ideal) `NonceSequence`.
43 ///
44 /// Intentionally not `Clone` or `Copy` since cloning would allow duplication
45 /// of the sequence.
46 pub trait NonceSequence {
47     /// Returns the next nonce in the sequence.
48     ///
49     /// This may fail if "too many" nonces have been requested, where how many
50     /// is too many is up to the implementation of `NonceSequence`. An
51     /// implementation may that enforce a maximum number of records are
52     /// sent/received under a key this way. Once `advance()` fails, it must
53     /// fail for all subsequent calls.
advance(&mut self) -> Result<Nonce, error::Unspecified>54     fn advance(&mut self) -> Result<Nonce, error::Unspecified>;
55 }
56 
57 /// An AEAD key bound to a nonce sequence.
58 pub trait BoundKey<N: NonceSequence>: core::fmt::Debug {
59     /// Constructs a new key from the given `UnboundKey` and `NonceSequence`.
new(key: UnboundKey, nonce_sequence: N) -> Self60     fn new(key: UnboundKey, nonce_sequence: N) -> Self;
61 
62     /// The key's AEAD algorithm.
algorithm(&self) -> &'static Algorithm63     fn algorithm(&self) -> &'static Algorithm;
64 }
65 
66 /// The additionally authenticated data (AAD) for an opening or sealing
67 /// operation. This data is authenticated but is **not** encrypted.
68 ///
69 /// The type `A` could be a byte slice `&[u8]`, a byte array `[u8; N]`
70 /// for some constant `N`, `Vec<u8>`, etc.
71 #[derive(Clone, Copy)]
72 pub struct Aad<A>(A);
73 
74 impl<A: AsRef<[u8]>> Aad<A> {
75     /// Construct the `Aad` from the given bytes.
76     #[inline]
from(aad: A) -> Self77     pub fn from(aad: A) -> Self {
78         Self(aad)
79     }
80 }
81 
82 impl<A> AsRef<[u8]> for Aad<A>
83 where
84     A: AsRef<[u8]>,
85 {
as_ref(&self) -> &[u8]86     fn as_ref(&self) -> &[u8] {
87         self.0.as_ref()
88     }
89 }
90 
91 impl Aad<[u8; 0]> {
92     /// Construct an empty `Aad`.
empty() -> Self93     pub fn empty() -> Self {
94         Self::from([])
95     }
96 }
97 
98 impl<A> core::fmt::Debug for Aad<A>
99 where
100     A: core::fmt::Debug,
101 {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result102     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103         f.debug_tuple("Aad").field(&self.0).finish()
104     }
105 }
106 
107 impl<A> PartialEq for Aad<A>
108 where
109     A: PartialEq,
110 {
111     #[inline]
eq(&self, other: &Self) -> bool112     fn eq(&self, other: &Self) -> bool {
113         self.0.eq(&other.0)
114     }
115 }
116 
117 impl<A> Eq for Aad<A> where A: Eq {}
118 
119 #[allow(clippy::large_enum_variant, variant_size_differences)]
120 #[derive(Clone)]
121 enum KeyInner {
122     AesGcm(aes_gcm::Key),
123     ChaCha20Poly1305(chacha20_poly1305::Key),
124 }
125 
126 impl hkdf::KeyType for &'static Algorithm {
127     #[inline]
len(&self) -> usize128     fn len(&self) -> usize {
129         self.key_len()
130     }
131 }
132 
133 /// An AEAD Algorithm.
134 pub struct Algorithm {
135     init: fn(key: &[u8], cpu_features: cpu::Features) -> Result<KeyInner, error::Unspecified>,
136 
137     seal: fn(key: &KeyInner, nonce: Nonce, aad: Aad<&[u8]>, in_out: &mut [u8]) -> Tag,
138     open: fn(
139         key: &KeyInner,
140         nonce: Nonce,
141         aad: Aad<&[u8]>,
142         in_out: &mut [u8],
143         src: RangeFrom<usize>,
144     ) -> Tag,
145 
146     key_len: usize,
147     id: AlgorithmID,
148 
149     /// Use `max_input_len!()` to initialize this.
150     // TODO: Make this `usize`.
151     max_input_len: u64,
152 }
153 
max_input_len(block_len: usize, overhead_blocks_per_nonce: usize) -> u64154 const fn max_input_len(block_len: usize, overhead_blocks_per_nonce: usize) -> u64 {
155     // Each of our AEADs use a 32-bit block counter so the maximum is the
156     // largest input that will not overflow the counter.
157     ((1u64 << 32) - polyfill::u64_from_usize(overhead_blocks_per_nonce))
158         * polyfill::u64_from_usize(block_len)
159 }
160 
161 impl Algorithm {
162     /// The length of the key.
163     #[inline(always)]
key_len(&self) -> usize164     pub fn key_len(&self) -> usize {
165         self.key_len
166     }
167 
168     /// The length of a tag.
169     ///
170     /// See also `MAX_TAG_LEN`.
171     #[inline(always)]
tag_len(&self) -> usize172     pub fn tag_len(&self) -> usize {
173         TAG_LEN
174     }
175 
176     /// The length of the nonces.
177     #[inline(always)]
nonce_len(&self) -> usize178     pub fn nonce_len(&self) -> usize {
179         NONCE_LEN
180     }
181 }
182 
183 derive_debug_via_id!(Algorithm);
184 
185 #[derive(Debug, Eq, PartialEq)]
186 enum AlgorithmID {
187     AES_128_GCM,
188     AES_256_GCM,
189     CHACHA20_POLY1305,
190 }
191 
192 impl PartialEq for Algorithm {
eq(&self, other: &Self) -> bool193     fn eq(&self, other: &Self) -> bool {
194         self.id == other.id
195     }
196 }
197 
198 impl Eq for Algorithm {}
199 
200 /// A possibly valid authentication tag.
201 #[must_use]
202 #[repr(C)]
203 #[derive(Clone, Copy)]
204 pub struct Tag([u8; TAG_LEN]);
205 
206 impl AsRef<[u8]> for Tag {
as_ref(&self) -> &[u8]207     fn as_ref(&self) -> &[u8] {
208         self.0.as_ref()
209     }
210 }
211 
212 impl TryFrom<&[u8]> for Tag {
213     type Error = error::Unspecified;
214 
try_from(value: &[u8]) -> Result<Self, Self::Error>215     fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
216         let raw_tag: [u8; TAG_LEN] = value.try_into().map_err(|_| error::Unspecified)?;
217         Ok(Self::from(raw_tag))
218     }
219 }
220 
221 impl From<[u8; TAG_LEN]> for Tag {
222     #[inline]
from(value: [u8; TAG_LEN]) -> Self223     fn from(value: [u8; TAG_LEN]) -> Self {
224         Self(value)
225     }
226 }
227 
228 const MAX_KEY_LEN: usize = 32;
229 
230 // All the AEADs we support use 128-bit tags.
231 const TAG_LEN: usize = 16;
232 
233 /// The maximum length of a tag for the algorithms in this module.
234 pub const MAX_TAG_LEN: usize = TAG_LEN;
235 
236 mod aes;
237 mod aes_gcm;
238 mod block;
239 mod chacha;
240 mod chacha20_poly1305;
241 pub mod chacha20_poly1305_openssh;
242 mod gcm;
243 mod less_safe_key;
244 mod nonce;
245 mod opening_key;
246 mod poly1305;
247 pub mod quic;
248 mod sealing_key;
249 mod shift;
250 mod unbound_key;
251