@@ -34,22 +34,18 @@ pub use bytes;
3434pub use crypto_common:: rand_core;
3535#[ cfg( feature = "heapless" ) ]
3636pub use heapless;
37- #[ cfg( feature = "inout" ) ]
3837pub use inout;
3938
4039use core:: fmt;
41- use crypto_common:: array:: { Array , ArraySize } ;
40+ use crypto_common:: array:: { Array , ArraySize , typenum:: Unsigned } ;
41+ use inout:: InOutBuf ;
4242
4343#[ cfg( feature = "alloc" ) ]
4444use alloc:: vec:: Vec ;
4545#[ cfg( feature = "bytes" ) ]
4646use bytes:: BytesMut ;
47- #[ cfg( any( feature = "alloc" , feature = "inout" ) ) ]
48- use crypto_common:: array:: typenum:: Unsigned ;
4947#[ cfg( feature = "os_rng" ) ]
5048use crypto_common:: rand_core:: { OsError , OsRng , TryRngCore } ;
51- #[ cfg( feature = "inout" ) ]
52- use inout:: InOutBuf ;
5349#[ cfg( feature = "rand_core" ) ]
5450use rand_core:: { CryptoRng , TryCryptoRng } ;
5551
@@ -77,17 +73,26 @@ pub type Nonce<A> = Array<u8, <A as AeadCore>::NonceSize>;
7773/// Tag: authentication code which ensures ciphertexts are authentic
7874pub type Tag < A > = Array < u8 , <A as AeadCore >:: TagSize > ;
7975
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.
8486pub trait AeadCore {
8587 /// The length of a nonce.
8688 type NonceSize : ArraySize ;
8789
8890 /// The maximum length of the tag.
8991 type TagSize : ArraySize ;
9092
93+ /// The AEAD tag position.
94+ const TAG_POSITION : TagPosition ;
95+
9196 /// Generate a random nonce for this AEAD algorithm.
9297 ///
9398 /// AEAD algorithms accept a parameter to encryption/decryption called
@@ -155,6 +160,94 @@ pub trait AeadCore {
155160 }
156161}
157162
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+
158251/// Authenticated Encryption with Associated Data (AEAD) algorithm.
159252#[ cfg( feature = "alloc" ) ]
160253pub trait Aead : AeadCore {
@@ -211,70 +304,8 @@ pub trait Aead: AeadCore {
211304 ) -> Result < Vec < u8 > > ;
212305}
213306
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-
276307#[ cfg( feature = "alloc" ) ]
277- impl < Alg : AeadInPlace > Aead for Alg {
308+ impl < T : AeadInOut > Aead for T {
278309 fn encrypt < ' msg , ' aad > (
279310 & self ,
280311 nonce : & Nonce < Self > ,
@@ -299,39 +330,6 @@ impl<Alg: AeadInPlace> Aead for Alg {
299330 }
300331}
301332
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-
335333/// AEAD payloads (message + AAD).
336334///
337335/// Combination of a message (plaintext or ciphertext) and
@@ -340,7 +338,6 @@ impl<T: AeadInOut + PostfixTagged> AeadInPlace for T {
340338///
341339/// If you don't care about AAD, you can pass a `&[u8]` as the payload to
342340/// `encrypt`/`decrypt` and it will automatically be coerced to this type.
343- #[ cfg( feature = "alloc" ) ]
344341#[ derive( Debug ) ]
345342pub struct Payload < ' msg , ' aad > {
346343 /// Message to be encrypted/decrypted
@@ -353,7 +350,6 @@ pub struct Payload<'msg, 'aad> {
353350 pub aad : & ' aad [ u8 ] ,
354351}
355352
356- #[ cfg( feature = "alloc" ) ]
357353impl < ' msg > From < & ' msg [ u8 ] > for Payload < ' msg , ' _ > {
358354 fn from ( msg : & ' msg [ u8 ] ) -> Self {
359355 Self { msg, aad : b"" }
@@ -436,11 +432,12 @@ impl<const N: usize> Buffer for heapless::Vec<u8, N> {
436432 }
437433}
438434
435+ #[ cfg( feature = "alloc" ) ]
439436#[ cfg( test) ]
440437mod tests {
441438 use super :: * ;
442439
443440 /// Ensure that `AeadInPlace` is object-safe
444441 #[ 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 > ;
446443}
0 commit comments