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