@@ -34,22 +34,18 @@ pub use bytes;
34
34
pub use crypto_common:: rand_core;
35
35
#[ cfg( feature = "heapless" ) ]
36
36
pub use heapless;
37
- #[ cfg( feature = "inout" ) ]
38
37
pub use inout;
39
38
40
39
use core:: fmt;
41
- use crypto_common:: array:: { Array , ArraySize } ;
40
+ use crypto_common:: array:: { Array , ArraySize , typenum:: Unsigned } ;
41
+ use inout:: InOutBuf ;
42
42
43
43
#[ cfg( feature = "alloc" ) ]
44
44
use alloc:: vec:: Vec ;
45
45
#[ cfg( feature = "bytes" ) ]
46
46
use bytes:: BytesMut ;
47
- #[ cfg( any( feature = "alloc" , feature = "inout" ) ) ]
48
- use crypto_common:: array:: typenum:: Unsigned ;
49
47
#[ cfg( feature = "os_rng" ) ]
50
48
use crypto_common:: rand_core:: { OsError , OsRng , TryRngCore } ;
51
- #[ cfg( feature = "inout" ) ]
52
- use inout:: InOutBuf ;
53
49
#[ cfg( feature = "rand_core" ) ]
54
50
use rand_core:: { CryptoRng , TryCryptoRng } ;
55
51
@@ -77,17 +73,26 @@ pub type Nonce<A> = Array<u8, <A as AeadCore>::NonceSize>;
77
73
/// Tag: authentication code which ensures ciphertexts are authentic
78
74
pub type Tag < A > = Array < u8 , <A as AeadCore >:: TagSize > ;
79
75
80
- /// Authenticated Encryption with Associated Data (AEAD) algorithm core trait.
81
- ///
82
- /// Defines nonce, tag, and overhead sizes that are consumed by various other
83
- /// `Aead*` traits.
76
+ /// Enum which specifies tag position used by an AEAD algorithm.
77
+ #[ derive( Debug , Clone , Copy , Eq , PartialEq ) ]
78
+ pub enum TagPosition {
79
+ /// Postfix tag
80
+ Postfix ,
81
+ /// Prefix tag
82
+ Prefix ,
83
+ }
84
+
85
+ /// Authenticated Encryption with Associated Data (AEAD) algorithm.
84
86
pub trait AeadCore {
85
87
/// The length of a nonce.
86
88
type NonceSize : ArraySize ;
87
89
88
90
/// The maximum length of the tag.
89
91
type TagSize : ArraySize ;
90
92
93
+ /// The AEAD tag position.
94
+ const TAG_POSITION : TagPosition ;
95
+
91
96
/// Generate a random nonce for this AEAD algorithm.
92
97
///
93
98
/// AEAD algorithms accept a parameter to encryption/decryption called
@@ -155,6 +160,94 @@ pub trait AeadCore {
155
160
}
156
161
}
157
162
163
+ /// In-place and inout AEAD trait which handles the authentication tag as a return value/separate parameter.
164
+ pub trait AeadInOut : AeadCore {
165
+ /// Encrypt the data in the provided [`InOutBuf`], returning the authentication tag.
166
+ fn encrypt_inout_detached (
167
+ & self ,
168
+ nonce : & Nonce < Self > ,
169
+ associated_data : & [ u8 ] ,
170
+ buffer : InOutBuf < ' _ , ' _ , u8 > ,
171
+ ) -> Result < Tag < Self > > ;
172
+
173
+ /// Decrypt the data in the provided [`InOutBuf`], returning an error in the event the
174
+ /// provided authentication tag is invalid for the given ciphertext (i.e. ciphertext
175
+ /// is modified/unauthentic)
176
+ fn decrypt_inout_detached (
177
+ & self ,
178
+ nonce : & Nonce < Self > ,
179
+ associated_data : & [ u8 ] ,
180
+ buffer : InOutBuf < ' _ , ' _ , u8 > ,
181
+ tag : & Tag < Self > ,
182
+ ) -> Result < ( ) > ;
183
+
184
+ /// Encrypt the given buffer containing a plaintext message in-place.
185
+ ///
186
+ /// The buffer must have sufficient capacity to store the ciphertext
187
+ /// message, which will always be larger than the original plaintext.
188
+ /// The exact size needed is cipher-dependent, but generally includes
189
+ /// the size of an authentication tag.
190
+ ///
191
+ /// Returns an error if the buffer has insufficient capacity to store the
192
+ /// resulting ciphertext message.
193
+ fn encrypt_in_place (
194
+ & self ,
195
+ nonce : & Nonce < Self > ,
196
+ associated_data : & [ u8 ] ,
197
+ buffer : & mut dyn Buffer ,
198
+ ) -> Result < ( ) > {
199
+ match Self :: TAG_POSITION {
200
+ TagPosition :: Prefix => {
201
+ let msg_len = buffer. len ( ) ;
202
+ buffer. extend_from_slice ( & Tag :: < Self > :: default ( ) ) ?;
203
+ let buffer = buffer. as_mut ( ) ;
204
+ let tag_size = Self :: TagSize :: USIZE ;
205
+ buffer. copy_within ( ..msg_len, tag_size) ;
206
+ let ( tag_dst, msg) = buffer. split_at_mut ( tag_size) ;
207
+ let tag = self . encrypt_inout_detached ( nonce, associated_data, msg. into ( ) ) ?;
208
+ tag_dst. copy_from_slice ( & tag) ;
209
+ }
210
+ TagPosition :: Postfix => {
211
+ let tag =
212
+ self . encrypt_inout_detached ( nonce, associated_data, buffer. as_mut ( ) . into ( ) ) ?;
213
+ buffer. extend_from_slice ( tag. as_slice ( ) ) ?;
214
+ }
215
+ }
216
+ Ok ( ( ) )
217
+ }
218
+
219
+ /// Decrypt the message in-place, returning an error in the event the
220
+ /// provided authentication tag does not match the given ciphertext.
221
+ ///
222
+ /// The buffer will be truncated to the length of the original plaintext
223
+ /// message upon success.
224
+ fn decrypt_in_place (
225
+ & self ,
226
+ nonce : & Nonce < Self > ,
227
+ associated_data : & [ u8 ] ,
228
+ buffer : & mut dyn Buffer ,
229
+ ) -> Result < ( ) > {
230
+ let tag_size = Self :: TagSize :: USIZE ;
231
+ let tagless_len = buffer. len ( ) . checked_sub ( tag_size) . ok_or ( Error ) ?;
232
+
233
+ match Self :: TAG_POSITION {
234
+ TagPosition :: Prefix => {
235
+ let ( tag, msg) = buffer. as_mut ( ) . split_at_mut ( tag_size) ;
236
+ let tag = Tag :: < Self > :: try_from ( & * tag) . expect ( "tag length mismatch" ) ;
237
+ self . decrypt_inout_detached ( nonce, associated_data, msg. into ( ) , & tag) ?;
238
+ buffer. as_mut ( ) . copy_within ( tag_size.., 0 ) ;
239
+ }
240
+ TagPosition :: Postfix => {
241
+ let ( msg, tag) = buffer. as_mut ( ) . split_at_mut ( tagless_len) ;
242
+ let tag = Tag :: < Self > :: try_from ( & * tag) . expect ( "tag length mismatch" ) ;
243
+ self . decrypt_inout_detached ( nonce, associated_data, msg. into ( ) , & tag) ?;
244
+ }
245
+ }
246
+ buffer. truncate ( tagless_len) ;
247
+ Ok ( ( ) )
248
+ }
249
+ }
250
+
158
251
/// Authenticated Encryption with Associated Data (AEAD) algorithm.
159
252
#[ cfg( feature = "alloc" ) ]
160
253
pub trait Aead : AeadCore {
@@ -211,70 +304,8 @@ pub trait Aead: AeadCore {
211
304
) -> Result < Vec < u8 > > ;
212
305
}
213
306
214
- /// In-place AEAD trait.
215
- ///
216
- /// This trait is both object safe and has no dependencies on `alloc` or `std`.
217
- pub trait AeadInPlace : AeadCore {
218
- /// Encrypt the given buffer containing a plaintext message in-place.
219
- ///
220
- /// The buffer must have sufficient capacity to store the ciphertext
221
- /// message, which will always be larger than the original plaintext.
222
- /// The exact size needed is cipher-dependent, but generally includes
223
- /// the size of an authentication tag.
224
- ///
225
- /// Returns an error if the buffer has insufficient capacity to store the
226
- /// resulting ciphertext message.
227
- fn encrypt_in_place (
228
- & self ,
229
- nonce : & Nonce < Self > ,
230
- associated_data : & [ u8 ] ,
231
- buffer : & mut dyn Buffer ,
232
- ) -> Result < ( ) > ;
233
-
234
- /// Decrypt the message in-place, returning an error in the event the
235
- /// provided authentication tag does not match the given ciphertext.
236
- ///
237
- /// The buffer will be truncated to the length of the original plaintext
238
- /// message upon success.
239
- fn decrypt_in_place (
240
- & self ,
241
- nonce : & Nonce < Self > ,
242
- associated_data : & [ u8 ] ,
243
- buffer : & mut dyn Buffer ,
244
- ) -> Result < ( ) > ;
245
- }
246
-
247
- /// In-place AEAD trait which handles the authentication tag as a return value/separate parameter.
248
- #[ cfg( feature = "inout" ) ]
249
- pub trait AeadInOut : AeadCore {
250
- /// Encrypt the data in the provided [`InOutBuf`], returning the authentication tag.
251
- fn encrypt_inout_detached (
252
- & self ,
253
- nonce : & Nonce < Self > ,
254
- associated_data : & [ u8 ] ,
255
- buffer : InOutBuf < ' _ , ' _ , u8 > ,
256
- ) -> Result < Tag < Self > > ;
257
-
258
- /// Decrypt the data in the provided [`InOutBuf`], returning an error in the event the
259
- /// provided authentication tag is invalid for the given ciphertext (i.e. ciphertext
260
- /// is modified/unauthentic)
261
- fn decrypt_inout_detached (
262
- & self ,
263
- nonce : & Nonce < Self > ,
264
- associated_data : & [ u8 ] ,
265
- buffer : InOutBuf < ' _ , ' _ , u8 > ,
266
- tag : & Tag < Self > ,
267
- ) -> Result < ( ) > ;
268
- }
269
-
270
- /// Marker trait for AEAD algorithms which append the authentication tag to the end of the
271
- /// ciphertext message.
272
- ///
273
- /// This is the common convention for AEAD algorithms.
274
- pub trait PostfixTagged { }
275
-
276
307
#[ cfg( feature = "alloc" ) ]
277
- impl < Alg : AeadInPlace > Aead for Alg {
308
+ impl < T : AeadInOut > Aead for T {
278
309
fn encrypt < ' msg , ' aad > (
279
310
& self ,
280
311
nonce : & Nonce < Self > ,
@@ -299,39 +330,6 @@ impl<Alg: AeadInPlace> Aead for Alg {
299
330
}
300
331
}
301
332
302
- #[ cfg( feature = "inout" ) ]
303
- impl < T : AeadInOut + PostfixTagged > AeadInPlace for T {
304
- fn encrypt_in_place (
305
- & self ,
306
- nonce : & Nonce < Self > ,
307
- associated_data : & [ u8 ] ,
308
- buffer : & mut dyn Buffer ,
309
- ) -> Result < ( ) > {
310
- let tag = self . encrypt_inout_detached ( nonce, associated_data, buffer. as_mut ( ) . into ( ) ) ?;
311
- buffer. extend_from_slice ( tag. as_slice ( ) ) ?;
312
- Ok ( ( ) )
313
- }
314
-
315
- fn decrypt_in_place (
316
- & self ,
317
- nonce : & Nonce < Self > ,
318
- associated_data : & [ u8 ] ,
319
- buffer : & mut dyn Buffer ,
320
- ) -> Result < ( ) > {
321
- let tag_pos = buffer
322
- . len ( )
323
- . checked_sub ( Self :: TagSize :: to_usize ( ) )
324
- . ok_or ( Error ) ?;
325
-
326
- let ( msg, tag) = buffer. as_mut ( ) . split_at_mut ( tag_pos) ;
327
- let tag = Tag :: < Self > :: try_from ( & * tag) . expect ( "tag length mismatch" ) ;
328
-
329
- self . decrypt_inout_detached ( nonce, associated_data, msg. into ( ) , & tag) ?;
330
- buffer. truncate ( tag_pos) ;
331
- Ok ( ( ) )
332
- }
333
- }
334
-
335
333
/// AEAD payloads (message + AAD).
336
334
///
337
335
/// Combination of a message (plaintext or ciphertext) and
@@ -340,7 +338,6 @@ impl<T: AeadInOut + PostfixTagged> AeadInPlace for T {
340
338
///
341
339
/// If you don't care about AAD, you can pass a `&[u8]` as the payload to
342
340
/// `encrypt`/`decrypt` and it will automatically be coerced to this type.
343
- #[ cfg( feature = "alloc" ) ]
344
341
#[ derive( Debug ) ]
345
342
pub struct Payload < ' msg , ' aad > {
346
343
/// Message to be encrypted/decrypted
@@ -353,7 +350,6 @@ pub struct Payload<'msg, 'aad> {
353
350
pub aad : & ' aad [ u8 ] ,
354
351
}
355
352
356
- #[ cfg( feature = "alloc" ) ]
357
353
impl < ' msg > From < & ' msg [ u8 ] > for Payload < ' msg , ' _ > {
358
354
fn from ( msg : & ' msg [ u8 ] ) -> Self {
359
355
Self { msg, aad : b"" }
@@ -436,11 +432,12 @@ impl<const N: usize> Buffer for heapless::Vec<u8, N> {
436
432
}
437
433
}
438
434
435
+ #[ cfg( feature = "alloc" ) ]
439
436
#[ cfg( test) ]
440
437
mod tests {
441
438
use super :: * ;
442
439
443
440
/// Ensure that `AeadInPlace` is object-safe
444
441
#[ allow( dead_code) ]
445
- type DynAeadInPlace < N , T > = dyn AeadInPlace < NonceSize = N , TagSize = T > ;
442
+ type DynAeadInPlace < N , T > = dyn Aead < NonceSize = N , TagSize = T > ;
446
443
}
0 commit comments