1use 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
37pub trait NonceSequence {
47 fn advance(&mut self) -> Result<Nonce, error::Unspecified>;
55}
56
57pub trait BoundKey<N: NonceSequence>: core::fmt::Debug {
59 fn new(key: UnboundKey, nonce_sequence: N) -> Self;
61
62 fn algorithm(&self) -> &'static Algorithm;
64}
65
66pub struct Aad<A>(A);
72
73impl<A: AsRef<[u8]>> Aad<A> {
74 #[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 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
143pub 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 max_input_len: u64,
162}
163
164const fn max_input_len(block_len: usize, overhead_blocks_per_nonce: usize) -> u64 {
165 ((1u64 << 32) - polyfill::u64_from_usize(overhead_blocks_per_nonce))
168 * polyfill::u64_from_usize(block_len)
169}
170
171impl Algorithm {
172 #[inline(always)]
174 pub fn key_len(&self) -> usize {
175 self.key_len
176 }
177
178 #[inline(always)]
182 pub fn tag_len(&self) -> usize {
183 TAG_LEN
184 }
185
186 #[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#[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
223const TAG_LEN: usize = 16;
225
226pub 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;