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