1use core::mem::size_of;
5use core::ptr::null_mut;
6
7use crate::cipher::chacha;
8
9use crate::aws_lc::{
10 evp_aead_direction_t, evp_aead_direction_t_evp_aead_open, evp_aead_direction_t_evp_aead_seal,
11 EVP_AEAD_CTX_init, EVP_AEAD_CTX_init_with_direction, EVP_AEAD_CTX_zero, EVP_aead_aes_128_gcm,
12 EVP_aead_aes_128_gcm_randnonce, EVP_aead_aes_128_gcm_siv, EVP_aead_aes_128_gcm_tls12,
13 EVP_aead_aes_128_gcm_tls13, EVP_aead_aes_192_gcm, EVP_aead_aes_256_gcm,
14 EVP_aead_aes_256_gcm_randnonce, EVP_aead_aes_256_gcm_siv, EVP_aead_aes_256_gcm_tls12,
15 EVP_aead_aes_256_gcm_tls13, EVP_aead_chacha20_poly1305, OPENSSL_malloc, EVP_AEAD_CTX,
16};
17use crate::cipher::aes::{AES_128_KEY_LEN, AES_192_KEY_LEN, AES_256_KEY_LEN};
18use crate::error::Unspecified;
19use crate::ptr::LcPtr;
20
21pub(crate) enum AeadDirection {
22 Open,
23 Seal,
24}
25
26impl From<AeadDirection> for evp_aead_direction_t {
27 fn from(value: AeadDirection) -> Self {
28 match value {
29 AeadDirection::Open => evp_aead_direction_t_evp_aead_open,
30 AeadDirection::Seal => evp_aead_direction_t_evp_aead_seal,
31 }
32 }
33}
34
35#[allow(
36 clippy::large_enum_variant,
37 variant_size_differences,
38 non_camel_case_types
39)]
40pub(crate) enum AeadCtx {
41 AES_128_GCM(LcPtr<EVP_AEAD_CTX>),
42 AES_192_GCM(LcPtr<EVP_AEAD_CTX>),
43 AES_256_GCM(LcPtr<EVP_AEAD_CTX>),
44
45 AES_128_GCM_SIV(LcPtr<EVP_AEAD_CTX>),
46 AES_256_GCM_SIV(LcPtr<EVP_AEAD_CTX>),
47
48 AES_128_GCM_RANDNONCE(LcPtr<EVP_AEAD_CTX>),
49 AES_256_GCM_RANDNONCE(LcPtr<EVP_AEAD_CTX>),
50
51 AES_128_GCM_TLS12(LcPtr<EVP_AEAD_CTX>),
52 AES_256_GCM_TLS12(LcPtr<EVP_AEAD_CTX>),
53
54 AES_128_GCM_TLS13(LcPtr<EVP_AEAD_CTX>),
55 AES_256_GCM_TLS13(LcPtr<EVP_AEAD_CTX>),
56
57 CHACHA20_POLY1305(LcPtr<EVP_AEAD_CTX>),
58}
59
60unsafe impl Send for AeadCtx {}
61unsafe impl Sync for AeadCtx {}
62
63impl AeadCtx {
64 pub(crate) fn aes_128_gcm(key_bytes: &[u8], tag_len: usize) -> Result<Self, Unspecified> {
65 Ok(AeadCtx::AES_128_GCM(AeadCtx::aes_128_context(
66 EVP_aead_aes_128_gcm,
67 key_bytes,
68 tag_len,
69 None,
70 )?))
71 }
72
73 pub(crate) fn aes_128_gcm_siv(key_bytes: &[u8], tag_len: usize) -> Result<Self, Unspecified> {
74 Ok(AeadCtx::AES_128_GCM_SIV(AeadCtx::aes_128_context(
75 EVP_aead_aes_128_gcm_siv,
76 key_bytes,
77 tag_len,
78 None,
79 )?))
80 }
81
82 pub(crate) fn aes_192_gcm(key_bytes: &[u8], tag_len: usize) -> Result<Self, Unspecified> {
83 Ok(AeadCtx::AES_192_GCM(AeadCtx::aes_192_context(
84 EVP_aead_aes_192_gcm,
85 key_bytes,
86 tag_len,
87 None,
88 )?))
89 }
90
91 pub(crate) fn aes_256_gcm(key_bytes: &[u8], tag_len: usize) -> Result<Self, Unspecified> {
92 Ok(AeadCtx::AES_256_GCM(AeadCtx::aes_256_context(
93 EVP_aead_aes_256_gcm,
94 key_bytes,
95 tag_len,
96 None,
97 )?))
98 }
99
100 pub(crate) fn aes_256_gcm_siv(key_bytes: &[u8], tag_len: usize) -> Result<Self, Unspecified> {
101 Ok(AeadCtx::AES_256_GCM_SIV(AeadCtx::aes_256_context(
102 EVP_aead_aes_256_gcm_siv,
103 key_bytes,
104 tag_len,
105 None,
106 )?))
107 }
108
109 pub(crate) fn aes_128_gcm_randnonce(
110 key_bytes: &[u8],
111 tag_len: usize,
112 nonce_len: usize,
113 ) -> Result<Self, Unspecified> {
114 Ok(AeadCtx::AES_128_GCM_RANDNONCE(AeadCtx::aes_128_context(
115 EVP_aead_aes_128_gcm_randnonce,
116 key_bytes,
117 tag_len + nonce_len,
118 None,
119 )?))
120 }
121
122 pub(crate) fn aes_256_gcm_randnonce(
123 key_bytes: &[u8],
124 tag_len: usize,
125 nonce_len: usize,
126 ) -> Result<Self, Unspecified> {
127 Ok(AeadCtx::AES_256_GCM_RANDNONCE(AeadCtx::aes_256_context(
128 EVP_aead_aes_256_gcm_randnonce,
129 key_bytes,
130 tag_len + nonce_len,
131 None,
132 )?))
133 }
134
135 pub(crate) fn aes_128_gcm_tls12(
136 key_bytes: &[u8],
137 tag_len: usize,
138 direction: AeadDirection,
139 ) -> Result<Self, Unspecified> {
140 Ok(AeadCtx::AES_128_GCM_TLS12(AeadCtx::aes_128_context(
141 EVP_aead_aes_128_gcm_tls12,
142 key_bytes,
143 tag_len,
144 Some(direction),
145 )?))
146 }
147
148 pub(crate) fn aes_256_gcm_tls12(
149 key_bytes: &[u8],
150 tag_len: usize,
151 direction: AeadDirection,
152 ) -> Result<Self, Unspecified> {
153 Ok(AeadCtx::AES_256_GCM_TLS12(AeadCtx::aes_256_context(
154 EVP_aead_aes_256_gcm_tls12,
155 key_bytes,
156 tag_len,
157 Some(direction),
158 )?))
159 }
160
161 pub(crate) fn aes_128_gcm_tls13(
162 key_bytes: &[u8],
163 tag_len: usize,
164 direction: AeadDirection,
165 ) -> Result<Self, Unspecified> {
166 Ok(AeadCtx::AES_128_GCM_TLS13(AeadCtx::aes_128_context(
167 EVP_aead_aes_128_gcm_tls13,
168 key_bytes,
169 tag_len,
170 Some(direction),
171 )?))
172 }
173
174 pub(crate) fn aes_256_gcm_tls13(
175 key_bytes: &[u8],
176 tag_len: usize,
177 direction: AeadDirection,
178 ) -> Result<Self, Unspecified> {
179 Ok(AeadCtx::AES_256_GCM_TLS13(AeadCtx::aes_256_context(
180 EVP_aead_aes_256_gcm_tls13,
181 key_bytes,
182 tag_len,
183 Some(direction),
184 )?))
185 }
186
187 pub(crate) fn chacha20(key_bytes: &[u8], tag_len: usize) -> Result<Self, Unspecified> {
188 if chacha::KEY_LEN != key_bytes.len() {
189 return Err(Unspecified);
190 }
191 Ok(AeadCtx::CHACHA20_POLY1305(AeadCtx::build_context(
192 EVP_aead_chacha20_poly1305,
193 key_bytes,
194 tag_len,
195 None,
196 )?))
197 }
198
199 fn aes_128_context(
200 aead: unsafe extern "C" fn() -> *const aws_lc::evp_aead_st,
201 key_bytes: &[u8],
202 tag_len: usize,
203 direction: Option<AeadDirection>,
204 ) -> Result<LcPtr<EVP_AEAD_CTX>, Unspecified> {
205 if AES_128_KEY_LEN != key_bytes.len() {
206 return Err(Unspecified);
207 }
208 AeadCtx::build_context(aead, key_bytes, tag_len, direction)
209 }
210
211 fn aes_192_context(
212 aead: unsafe extern "C" fn() -> *const aws_lc::evp_aead_st,
213 key_bytes: &[u8],
214 tag_len: usize,
215 direction: Option<AeadDirection>,
216 ) -> Result<LcPtr<EVP_AEAD_CTX>, Unspecified> {
217 if AES_192_KEY_LEN != key_bytes.len() {
218 return Err(Unspecified);
219 }
220 AeadCtx::build_context(aead, key_bytes, tag_len, direction)
221 }
222
223 fn aes_256_context(
224 aead: unsafe extern "C" fn() -> *const aws_lc::evp_aead_st,
225 key_bytes: &[u8],
226 tag_len: usize,
227 direction: Option<AeadDirection>,
228 ) -> Result<LcPtr<EVP_AEAD_CTX>, Unspecified> {
229 if AES_256_KEY_LEN != key_bytes.len() {
230 return Err(Unspecified);
231 }
232 AeadCtx::build_context(aead, key_bytes, tag_len, direction)
233 }
234
235 fn build_context(
236 aead_fn: unsafe extern "C" fn() -> *const aws_lc::evp_aead_st,
237 key_bytes: &[u8],
238 tag_len: usize,
239 direction: Option<AeadDirection>,
240 ) -> Result<LcPtr<EVP_AEAD_CTX>, Unspecified> {
241 let aead = unsafe { aead_fn() };
242
243 let mut aead_ctx: LcPtr<EVP_AEAD_CTX> =
246 LcPtr::new(unsafe { OPENSSL_malloc(size_of::<EVP_AEAD_CTX>()) }.cast())?;
247
248 unsafe { EVP_AEAD_CTX_zero(*aead_ctx.as_mut()) };
249
250 if 1 != match direction {
251 Some(direction) => unsafe {
252 EVP_AEAD_CTX_init_with_direction(
253 *aead_ctx.as_mut(),
254 aead,
255 key_bytes.as_ptr(),
256 key_bytes.len(),
257 tag_len,
258 direction.into(),
259 )
260 },
261 None => unsafe {
262 EVP_AEAD_CTX_init(
263 *aead_ctx.as_mut(),
264 aead,
265 key_bytes.as_ptr(),
266 key_bytes.len(),
267 tag_len,
268 null_mut(),
269 )
270 },
271 } {
272 return Err(Unspecified);
273 }
274 Ok(aead_ctx)
275 }
276}
277
278impl AsRef<LcPtr<EVP_AEAD_CTX>> for AeadCtx {
279 #[inline]
280 fn as_ref(&self) -> &LcPtr<EVP_AEAD_CTX> {
281 match self {
282 AeadCtx::AES_128_GCM(ctx)
283 | AeadCtx::AES_192_GCM(ctx)
284 | AeadCtx::AES_256_GCM(ctx)
285 | AeadCtx::AES_128_GCM_SIV(ctx)
286 | AeadCtx::AES_256_GCM_SIV(ctx)
287 | AeadCtx::AES_128_GCM_RANDNONCE(ctx)
288 | AeadCtx::AES_256_GCM_RANDNONCE(ctx)
289 | AeadCtx::AES_128_GCM_TLS12(ctx)
290 | AeadCtx::AES_256_GCM_TLS12(ctx)
291 | AeadCtx::AES_128_GCM_TLS13(ctx)
292 | AeadCtx::AES_256_GCM_TLS13(ctx)
293 | AeadCtx::CHACHA20_POLY1305(ctx) => ctx,
294 }
295 }
296}