• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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