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]: http://www-cse.ucsd.edu/~mihir/papers/oem.html
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 pub struct Aad<A>(A);
72
73 impl<A: AsRef<[u8]>> Aad<A> {
74 /// Construct the `Aad` from the given bytes.
75 #[inline]
from(aad: A) -> Self76 pub fn from(aad: A) -> Self {
77 Self(aad)
78 }
79 }
80
81 impl<A> AsRef<[u8]> for Aad<A>
82 where
83 A: AsRef<[u8]>,
84 {
as_ref(&self) -> &[u8]85 fn as_ref(&self) -> &[u8] {
86 self.0.as_ref()
87 }
88 }
89
90 impl Aad<[u8; 0]> {
91 /// Construct an empty `Aad`.
empty() -> Self92 pub fn empty() -> Self {
93 Self::from([])
94 }
95 }
96
97 impl<A> Clone for Aad<A>
98 where
99 A: Clone,
100 {
101 #[inline]
clone(&self) -> Self102 fn clone(&self) -> Self {
103 Self(self.0.clone())
104 }
105 }
106
107 impl<A> Copy for Aad<A> where A: Copy {}
108
109 impl<A> core::fmt::Debug for Aad<A>
110 where
111 A: core::fmt::Debug,
112 {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result113 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
114 f.debug_tuple("Aad").field(&self.0).finish()
115 }
116 }
117
118 impl<A> PartialEq for Aad<A>
119 where
120 A: PartialEq,
121 {
122 #[inline]
eq(&self, other: &Self) -> bool123 fn eq(&self, other: &Self) -> bool {
124 self.0.eq(&other.0)
125 }
126 }
127
128 impl<A> Eq for Aad<A> where A: Eq {}
129
130 #[allow(clippy::large_enum_variant, variant_size_differences)]
131 enum KeyInner {
132 AesGcm(aes_gcm::Key),
133 ChaCha20Poly1305(chacha20_poly1305::Key),
134 }
135
136 impl hkdf::KeyType for &'static Algorithm {
137 #[inline]
len(&self) -> usize138 fn len(&self) -> usize {
139 self.key_len()
140 }
141 }
142
143 /// An AEAD Algorithm.
144 pub struct Algorithm {
145 init: fn(key: &[u8], cpu_features: cpu::Features) -> Result<KeyInner, error::Unspecified>,
146
147 seal: fn(key: &KeyInner, nonce: Nonce, aad: Aad<&[u8]>, in_out: &mut [u8]) -> Tag,
148 open: fn(
149 key: &KeyInner,
150 nonce: Nonce,
151 aad: Aad<&[u8]>,
152 in_out: &mut [u8],
153 src: RangeFrom<usize>,
154 ) -> Tag,
155
156 key_len: usize,
157 id: AlgorithmID,
158
159 /// Use `max_input_len!()` to initialize this.
160 // TODO: Make this `usize`.
161 max_input_len: u64,
162 }
163
max_input_len(block_len: usize, overhead_blocks_per_nonce: usize) -> u64164 const fn max_input_len(block_len: usize, overhead_blocks_per_nonce: usize) -> u64 {
165 // Each of our AEADs use a 32-bit block counter so the maximum is the
166 // largest input that will not overflow the counter.
167 ((1u64 << 32) - polyfill::u64_from_usize(overhead_blocks_per_nonce))
168 * polyfill::u64_from_usize(block_len)
169 }
170
171 impl Algorithm {
172 /// The length of the key.
173 #[inline(always)]
key_len(&self) -> usize174 pub fn key_len(&self) -> usize {
175 self.key_len
176 }
177
178 /// The length of a tag.
179 ///
180 /// See also `MAX_TAG_LEN`.
181 #[inline(always)]
tag_len(&self) -> usize182 pub fn tag_len(&self) -> usize {
183 TAG_LEN
184 }
185
186 /// The length of the nonces.
187 #[inline(always)]
nonce_len(&self) -> usize188 pub fn nonce_len(&self) -> usize {
189 NONCE_LEN
190 }
191 }
192
193 derive_debug_via_id!(Algorithm);
194
195 #[derive(Debug, Eq, PartialEq)]
196 enum AlgorithmID {
197 AES_128_GCM,
198 AES_256_GCM,
199 CHACHA20_POLY1305,
200 }
201
202 impl PartialEq for Algorithm {
eq(&self, other: &Self) -> bool203 fn eq(&self, other: &Self) -> bool {
204 self.id == other.id
205 }
206 }
207
208 impl Eq for Algorithm {}
209
210 /// An authentication tag.
211 #[must_use]
212 #[repr(C)]
213 pub struct Tag([u8; TAG_LEN]);
214
215 impl AsRef<[u8]> for Tag {
as_ref(&self) -> &[u8]216 fn as_ref(&self) -> &[u8] {
217 self.0.as_ref()
218 }
219 }
220
221 const MAX_KEY_LEN: usize = 32;
222
223 // All the AEADs we support use 128-bit tags.
224 const TAG_LEN: usize = 16;
225
226 /// The maximum length of a tag for the algorithms in this module.
227 pub const MAX_TAG_LEN: usize = TAG_LEN;
228
229 mod aes;
230 mod aes_gcm;
231 mod block;
232 mod chacha;
233 mod chacha20_poly1305;
234 pub mod chacha20_poly1305_openssh;
235 mod gcm;
236 mod less_safe_key;
237 mod nonce;
238 mod opening_key;
239 mod poly1305;
240 pub mod quic;
241 mod sealing_key;
242 mod shift;
243 mod unbound_key;
244