ring/
aead.rs

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
24use crate::{cpu, error, hkdf, polyfill};
25use core::ops::RangeFrom;
26
27pub 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.
46pub 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.
54    fn advance(&mut self) -> Result<Nonce, error::Unspecified>;
55}
56
57/// An AEAD key bound to a nonce sequence.
58pub trait BoundKey<N: NonceSequence>: core::fmt::Debug {
59    /// Constructs a new key from the given `UnboundKey` and `NonceSequence`.
60    fn new(key: UnboundKey, nonce_sequence: N) -> Self;
61
62    /// The key's AEAD algorithm.
63    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.
71pub struct Aad<A>(A);
72
73impl<A: AsRef<[u8]>> Aad<A> {
74    /// Construct the `Aad` from the given bytes.
75    #[inline]
76    pub fn from(aad: A) -> Self {
77        Self(aad)
78    }
79}
80
81impl<A> AsRef<[u8]> for Aad<A>
82where
83    A: AsRef<[u8]>,
84{
85    fn as_ref(&self) -> &[u8] {
86        self.0.as_ref()
87    }
88}
89
90impl Aad<[u8; 0]> {
91    /// Construct an empty `Aad`.
92    pub fn empty() -> Self {
93        Self::from([])
94    }
95}
96
97impl<A> Clone for Aad<A>
98where
99    A: Clone,
100{
101    #[inline]
102    fn clone(&self) -> Self {
103        Self(self.0.clone())
104    }
105}
106
107impl<A> Copy for Aad<A> where A: Copy {}
108
109impl<A> core::fmt::Debug for Aad<A>
110where
111    A: core::fmt::Debug,
112{
113    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
114        f.debug_tuple("Aad").field(&self.0).finish()
115    }
116}
117
118impl<A> PartialEq for Aad<A>
119where
120    A: PartialEq,
121{
122    #[inline]
123    fn eq(&self, other: &Self) -> bool {
124        self.0.eq(&other.0)
125    }
126}
127
128impl<A> Eq for Aad<A> where A: Eq {}
129
130#[allow(clippy::large_enum_variant, variant_size_differences)]
131enum KeyInner {
132    AesGcm(aes_gcm::Key),
133    ChaCha20Poly1305(chacha20_poly1305::Key),
134}
135
136impl hkdf::KeyType for &'static Algorithm {
137    #[inline]
138    fn len(&self) -> usize {
139        self.key_len()
140    }
141}
142
143/// An AEAD Algorithm.
144pub 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
164const 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
171impl Algorithm {
172    /// The length of the key.
173    #[inline(always)]
174    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)]
182    pub fn tag_len(&self) -> usize {
183        TAG_LEN
184    }
185
186    /// The length of the nonces.
187    #[inline(always)]
188    pub fn nonce_len(&self) -> usize {
189        NONCE_LEN
190    }
191}
192
193derive_debug_via_id!(Algorithm);
194
195#[derive(Debug, Eq, PartialEq)]
196enum AlgorithmID {
197    AES_128_GCM,
198    AES_256_GCM,
199    CHACHA20_POLY1305,
200}
201
202impl PartialEq for Algorithm {
203    fn eq(&self, other: &Self) -> bool {
204        self.id == other.id
205    }
206}
207
208impl Eq for Algorithm {}
209
210/// An authentication tag.
211#[must_use]
212#[repr(C)]
213pub struct Tag([u8; TAG_LEN]);
214
215impl AsRef<[u8]> for Tag {
216    fn as_ref(&self) -> &[u8] {
217        self.0.as_ref()
218    }
219}
220
221const MAX_KEY_LEN: usize = 32;
222
223// All the AEADs we support use 128-bit tags.
224const TAG_LEN: usize = 16;
225
226/// The maximum length of a tag for the algorithms in this module.
227pub const MAX_TAG_LEN: usize = TAG_LEN;
228
229mod aes;
230mod aes_gcm;
231mod block;
232mod chacha;
233mod chacha20_poly1305;
234pub mod chacha20_poly1305_openssh;
235mod gcm;
236mod less_safe_key;
237mod nonce;
238mod opening_key;
239mod poly1305;
240pub mod quic;
241mod sealing_key;
242mod shift;
243mod unbound_key;