1use libcrux_secrets::U8;
6
7pub trait Aead {
13 fn keygen(key: &mut [U8], rand: &[U8]) -> Result<(), KeyGenError>;
16
17 fn encrypt(
20 ciphertext: &mut [u8],
21 tag: &mut [U8],
22 key: &[U8],
23 nonce: &[U8],
24 aad: &[u8],
25 plaintext: &[U8],
26 ) -> Result<(), EncryptError>;
27
28 fn decrypt(
31 plaintext: &mut [U8],
32 key: &[U8],
33 nonce: &[U8],
34 aad: &[u8],
35 ciphertext: &[u8],
36 tag: &[U8],
37 ) -> Result<(), DecryptError>;
38}
39
40pub enum KeyGenError {
42 WrongKeyLength,
44
45 InsufficientRandomness,
47
48 UnsuitableRandomness,
51}
52
53#[derive(Debug, PartialEq, Eq)]
55pub enum EncryptError {
56 WrongCiphertextLength,
58
59 PlaintextTooLong,
61
62 AadTooLong,
64
65 WrongKeyLength,
67
68 WrongTagLength,
70
71 WrongNonceLength,
73
74 Unknown,
76}
77
78#[derive(Debug, PartialEq, Eq)]
80pub enum DecryptError {
81 InvalidTag,
84
85 WrongPlaintextLength,
87
88 PlaintextTooLong,
90
91 AadTooLong,
93
94 WrongKeyLength,
96
97 WrongTagLength,
99
100 WrongNonceLength,
102
103 Unknown,
105}
106
107impl From<super::arrayref::EncryptError> for EncryptError {
108 fn from(value: super::arrayref::EncryptError) -> Self {
109 match value {
110 super::arrayref::EncryptError::WrongCiphertextLength => {
111 EncryptError::WrongCiphertextLength
112 }
113 super::arrayref::EncryptError::PlaintextTooLong => EncryptError::PlaintextTooLong,
114 super::arrayref::EncryptError::AadTooLong => EncryptError::AadTooLong,
115 super::arrayref::EncryptError::Unknown => EncryptError::Unknown,
116 }
117 }
118}
119
120impl From<super::arrayref::DecryptError> for DecryptError {
121 fn from(value: super::arrayref::DecryptError) -> Self {
122 match value {
123 super::arrayref::DecryptError::InvalidTag => DecryptError::InvalidTag,
124 super::arrayref::DecryptError::WrongPlaintextLength => {
125 DecryptError::WrongPlaintextLength
126 }
127 super::arrayref::DecryptError::PlaintextTooLong => DecryptError::PlaintextTooLong,
128 super::arrayref::DecryptError::AadTooLong => DecryptError::AadTooLong,
129 super::arrayref::DecryptError::Unknown => DecryptError::Unknown,
130 }
131 }
132}
133
134impl core::fmt::Display for EncryptError {
135 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
136 let text = match self {
137 EncryptError::WrongCiphertextLength => "ciphertext buffer has wrong length",
138 EncryptError::PlaintextTooLong => {
139 "plaintext is too long for algorithm or implementation"
140 }
141 EncryptError::AadTooLong => "aad is too long for algorithm or implementation",
142 EncryptError::Unknown => "an unknown error occurred",
143 EncryptError::WrongKeyLength => "key has wrong length",
144 EncryptError::WrongTagLength => "tag has wrong length",
145 EncryptError::WrongNonceLength => "nonce has wrong length",
146 };
147
148 f.write_str(text)
149 }
150}
151
152impl core::fmt::Display for DecryptError {
153 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
154 let text = match self {
155 DecryptError::InvalidTag => "invalid authentication tag",
156 DecryptError::WrongPlaintextLength => "plaintext buffer has wrong length",
157 DecryptError::PlaintextTooLong => {
158 "plaintext is too long for algorithm or implementation"
159 }
160 DecryptError::AadTooLong => "aad is too long for algorithm or implementation",
161 DecryptError::Unknown => "an unknown error occurred",
162 DecryptError::WrongKeyLength => "key has wrong length",
163 DecryptError::WrongTagLength => "tag has wrong length",
164 DecryptError::WrongNonceLength => "nonce has wrong length",
165 };
166
167 f.write_str(text)
168 }
169}
170
171#[cfg(feature = "error-in-core")]
172mod error_in_core {
175 impl core::error::Error for super::EncryptError {}
176 impl core::error::Error for super::DecryptError {}
177}
178
179#[macro_export]
184macro_rules! impl_aead_slice_trait {
185 ($type:ty => $key:expr, $tag:expr, $nonce:expr) => {
186 impl $crate::aead::slice::Aead for $type {
187 fn keygen(
188 key: &mut [$crate::libcrux_secrets::U8],
189 rand: &[$crate::libcrux_secrets::U8],
190 ) -> Result<(), $crate::aead::slice::KeyGenError> {
191 let key: &mut [$crate::libcrux_secrets::U8; $key] = key
192 .try_into()
193 .map_err(|_| $crate::aead::slice::KeyGenError::WrongKeyLength)?;
194 if rand.len() < $key {
195 return Err($crate::aead::slice::KeyGenError::InsufficientRandomness);
196 }
197
198 Ok(key.copy_from_slice(rand))
199 }
200
201 fn encrypt(
202 ciphertext: &mut [u8],
203 tag: &mut [$crate::libcrux_secrets::U8],
204 key: &[$crate::libcrux_secrets::U8],
205 nonce: &[$crate::libcrux_secrets::U8],
206 aad: &[u8],
207 plaintext: &[$crate::libcrux_secrets::U8],
208 ) -> Result<(), $crate::aead::slice::EncryptError> {
209 let key: &[$crate::libcrux_secrets::U8; $key] = key
210 .try_into()
211 .map_err(|_| $crate::aead::slice::EncryptError::WrongKeyLength)?;
212 let tag: &mut [$crate::libcrux_secrets::U8; $tag] = tag
213 .try_into()
214 .map_err(|_| $crate::aead::slice::EncryptError::WrongTagLength)?;
215 let nonce: &[$crate::libcrux_secrets::U8; $nonce] = nonce
216 .try_into()
217 .map_err(|_| $crate::aead::slice::EncryptError::WrongNonceLength)?;
218
219 <Self as $crate::aead::arrayref::Aead<$key, $tag, $nonce>>::encrypt(
220 ciphertext, tag, key, nonce, aad, plaintext,
221 )
222 .map_err($crate::aead::slice::EncryptError::from)
223 }
224
225 fn decrypt(
226 plaintext: &mut [$crate::libcrux_secrets::U8],
227 key: &[$crate::libcrux_secrets::U8],
228 nonce: &[$crate::libcrux_secrets::U8],
229 aad: &[u8],
230 ciphertext: &[u8],
231 tag: &[$crate::libcrux_secrets::U8],
232 ) -> Result<(), $crate::aead::slice::DecryptError> {
233 let key: &[$crate::libcrux_secrets::U8; $key] = key
234 .try_into()
235 .map_err(|_| $crate::aead::slice::DecryptError::WrongKeyLength)?;
236 let tag: &[$crate::libcrux_secrets::U8; $tag] = tag
237 .try_into()
238 .map_err(|_| $crate::aead::slice::DecryptError::WrongTagLength)?;
239 let nonce: &[$crate::libcrux_secrets::U8; $nonce] = nonce
240 .try_into()
241 .map_err(|_| $crate::aead::slice::DecryptError::WrongNonceLength)?;
242
243 <Self as $crate::aead::arrayref::Aead<$key, $tag, $nonce>>::decrypt(
244 plaintext, key, nonce, aad, ciphertext, tag,
245 )
246 .map_err($crate::aead::slice::DecryptError::from)
247 }
248 }
249
250 #[cfg(test)]
251 #[test]
252 fn simple_aead_test() {
253 $crate::aead::tests::simple::<$key, $tag, $nonce, $type>();
254 }
255 };
256}
257
258pub use impl_aead_slice_trait;