ring/aead.rs
1// Copyright 2015-2024 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 AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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,
26 polyfill::{u64_from_usize, usize_from_u64_saturated},
27};
28
29pub use self::{
30 algorithm::{Algorithm, AES_128_GCM, AES_256_GCM, CHACHA20_POLY1305},
31 less_safe_key::LessSafeKey,
32 nonce::{Nonce, NONCE_LEN},
33 opening_key::OpeningKey,
34 sealing_key::SealingKey,
35 unbound_key::UnboundKey,
36};
37
38/// A sequences of unique nonces.
39///
40/// A given `NonceSequence` must never return the same `Nonce` twice from
41/// `advance()`.
42///
43/// A simple counter is a reasonable (but probably not ideal) `NonceSequence`.
44///
45/// Intentionally not `Clone` or `Copy` since cloning would allow duplication
46/// of the sequence.
47pub trait NonceSequence {
48 /// Returns the next nonce in the sequence.
49 ///
50 /// This may fail if "too many" nonces have been requested, where how many
51 /// is too many is up to the implementation of `NonceSequence`. An
52 /// implementation may that enforce a maximum number of records are
53 /// sent/received under a key this way. Once `advance()` fails, it must
54 /// fail for all subsequent calls.
55 fn advance(&mut self) -> Result<Nonce, error::Unspecified>;
56}
57
58/// An AEAD key bound to a nonce sequence.
59pub trait BoundKey<N: NonceSequence>: core::fmt::Debug {
60 /// Constructs a new key from the given `UnboundKey` and `NonceSequence`.
61 fn new(key: UnboundKey, nonce_sequence: N) -> Self;
62
63 /// The key's AEAD algorithm.
64 fn algorithm(&self) -> &'static Algorithm;
65}
66
67/// The additionally authenticated data (AAD) for an opening or sealing
68/// operation. This data is authenticated but is **not** encrypted.
69///
70/// The type `A` could be a byte slice `&[u8]`, a byte array `[u8; N]`
71/// for some constant `N`, `Vec<u8>`, etc.
72#[derive(Clone, Copy)]
73pub struct Aad<A>(A);
74
75impl<A: AsRef<[u8]>> Aad<A> {
76 /// Construct the `Aad` from the given bytes.
77 #[inline]
78 pub fn from(aad: A) -> Self {
79 Self(aad)
80 }
81}
82
83impl<A> AsRef<[u8]> for Aad<A>
84where
85 A: AsRef<[u8]>,
86{
87 fn as_ref(&self) -> &[u8] {
88 self.0.as_ref()
89 }
90}
91
92impl Aad<[u8; 0]> {
93 /// Construct an empty `Aad`.
94 pub fn empty() -> Self {
95 Self::from([])
96 }
97}
98
99impl<A> core::fmt::Debug for Aad<A>
100where
101 A: core::fmt::Debug,
102{
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 f.debug_tuple("Aad").field(&self.0).finish()
105 }
106}
107
108impl<A> PartialEq for Aad<A>
109where
110 A: PartialEq,
111{
112 #[inline]
113 fn eq(&self, other: &Self) -> bool {
114 self.0.eq(&other.0)
115 }
116}
117
118impl<A> Eq for Aad<A> where A: Eq {}
119
120#[allow(clippy::large_enum_variant, variant_size_differences)]
121#[derive(Clone)]
122enum KeyInner {
123 AesGcm(aes_gcm::Key),
124 ChaCha20Poly1305(chacha20_poly1305::Key),
125}
126
127const fn max_input_len(block_len: usize, overhead_blocks_per_nonce: usize) -> usize {
128 // Each of our AEADs use a 32-bit block counter so the maximum is the
129 // largest input that will not overflow the counter.
130 usize_from_u64_saturated(
131 ((1u64 << 32) - u64_from_usize(overhead_blocks_per_nonce)) * u64_from_usize(block_len),
132 )
133}
134
135/// A possibly valid authentication tag.
136#[must_use]
137#[repr(C)]
138#[derive(Clone, Copy)]
139pub struct Tag([u8; TAG_LEN]);
140
141impl AsRef<[u8]> for Tag {
142 fn as_ref(&self) -> &[u8] {
143 self.0.as_ref()
144 }
145}
146
147impl TryFrom<&[u8]> for Tag {
148 type Error = error::Unspecified;
149
150 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
151 let raw_tag: [u8; TAG_LEN] = value.try_into().map_err(|_| error::Unspecified)?;
152 Ok(Self::from(raw_tag))
153 }
154}
155
156impl From<[u8; TAG_LEN]> for Tag {
157 #[inline]
158 fn from(value: [u8; TAG_LEN]) -> Self {
159 Self(value)
160 }
161}
162
163const MAX_KEY_LEN: usize = 32;
164
165// All the AEADs we support use 128-bit tags.
166const TAG_LEN: usize = 16;
167
168/// The maximum length of a tag for the algorithms in this module.
169pub const MAX_TAG_LEN: usize = TAG_LEN;
170
171mod aes;
172mod aes_gcm;
173mod algorithm;
174mod chacha;
175mod chacha20_poly1305;
176pub mod chacha20_poly1305_openssh;
177mod gcm;
178mod less_safe_key;
179mod nonce;
180mod opening_key;
181mod overlapping;
182mod poly1305;
183pub mod quic;
184mod sealing_key;
185mod shift;
186mod unbound_key;