14
14
15
15
#![ no_std]
16
16
17
+ #[ cfg( feature = "alloc" ) ]
17
18
extern crate alloc;
18
19
19
20
pub use generic_array;
20
21
22
+ #[ cfg( feature = "alloc" ) ]
21
23
use alloc:: vec:: Vec ;
22
24
use generic_array:: { typenum:: Unsigned , ArrayLength , GenericArray } ;
23
25
26
+ // Define the default implementation for both `Aead::encrypt()` and
27
+ // `AeadMut::encrypt()`. Uses a macro to gloss over `&self` vs `&mut self`.
28
+ #[ cfg( feature = "alloc" ) ]
29
+ macro_rules! encrypt_to_postfix_tagged_vec {
30
+ ( $aead: expr, $nonce: expr, $payload: expr) => { {
31
+ let payload = $payload. into( ) ;
32
+ let mut buffer = Vec :: with_capacity( payload. msg. len( ) + Self :: TagSize :: to_usize( ) ) ;
33
+ buffer. extend_from_slice( payload. msg) ;
34
+
35
+ let tag = $aead. encrypt_in_place_detached( $nonce, payload. aad, & mut buffer) ?;
36
+ buffer. extend_from_slice( tag. as_slice( ) ) ;
37
+ Ok ( buffer)
38
+ } } ;
39
+ }
40
+
41
+ // Define the default implementation for both `Aead::decrypt()` and
42
+ // `AeadMut::decrypt()`. Uses a macro to gloss over `&self` vs `&mut self`.
43
+ #[ cfg( feature = "alloc" ) ]
44
+ macro_rules! decrypt_postfix_tagged_ciphertext_to_vec {
45
+ ( $aead: expr, $nonce: expr, $payload: expr) => { {
46
+ let payload = $payload. into( ) ;
47
+
48
+ if payload. msg. len( ) < Self :: TagSize :: to_usize( ) {
49
+ return Err ( Error ) ;
50
+ }
51
+
52
+ let tag_start = payload. msg. len( ) - Self :: TagSize :: to_usize( ) ;
53
+ let mut buffer = Vec :: from( & payload. msg[ ..tag_start] ) ;
54
+ let tag = GenericArray :: from_slice( & payload. msg[ tag_start..] ) ;
55
+ $aead. decrypt_in_place_detached( $nonce, payload. aad, & mut buffer, tag) ?;
56
+
57
+ Ok ( buffer)
58
+ } } ;
59
+ }
60
+
24
61
#[ derive( Clone , Copy , Debug , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
25
62
pub struct Error ;
26
63
@@ -36,7 +73,7 @@ pub trait NewAead {
36
73
/// Authenticated Encryption with Associated Data (AEAD) algorithm.
37
74
///
38
75
/// This trait is intended for use with stateless AEAD algorithms. The
39
- /// `AeadMut` trait provides a stateful interface.
76
+ /// [ `AeadMut`] trait provides a stateful interface.
40
77
pub trait Aead {
41
78
/// The length of a nonce.
42
79
type NonceSize : ArrayLength < u8 > ;
@@ -64,11 +101,27 @@ pub trait Aead {
64
101
/// let plaintext = b"Top secret message, handle with care";
65
102
/// let ciphertext = cipher.encrypt(nonce, plaintext);
66
103
/// ```
104
+ ///
105
+ /// The default implementation assumes a postfix tag (ala AES-GCM,
106
+ /// AES-GCM-SIV, ChaCha20Poly1305). [`Aead`] implementations which do not
107
+ /// use a postfix tag will need to override this to correctly assemble the
108
+ /// ciphertext message.
109
+ #[ cfg( feature = "alloc" ) ]
67
110
fn encrypt < ' msg , ' aad > (
68
111
& self ,
69
112
nonce : & GenericArray < u8 , Self :: NonceSize > ,
70
113
plaintext : impl Into < Payload < ' msg , ' aad > > ,
71
- ) -> Result < Vec < u8 > , Error > ;
114
+ ) -> Result < Vec < u8 > , Error > {
115
+ encrypt_to_postfix_tagged_vec ! ( self , nonce, plaintext)
116
+ }
117
+
118
+ /// Encrypt the data in-place, returning the authentication tag
119
+ fn encrypt_in_place_detached (
120
+ & self ,
121
+ nonce : & GenericArray < u8 , Self :: NonceSize > ,
122
+ associated_data : & [ u8 ] ,
123
+ buffer : & mut [ u8 ] ,
124
+ ) -> Result < GenericArray < u8 , Self :: TagSize > , Error > ;
72
125
73
126
/// Decrypt the given ciphertext slice, and return the resulting plaintext
74
127
/// as a vector of bytes.
@@ -82,11 +135,30 @@ pub trait Aead {
82
135
/// let ciphertext = b"...";
83
136
/// let plaintext = cipher.decrypt(nonce, ciphertext)?;
84
137
/// ```
138
+ ///
139
+ /// The default implementation assumes a postfix tag (ala AES-GCM,
140
+ /// AES-GCM-SIV, ChaCha20Poly1305). [`Aead`] implementations which do not
141
+ /// use a postfix tag will need to override this to correctly parse the
142
+ /// ciphertext message.
143
+ #[ cfg( feature = "alloc" ) ]
85
144
fn decrypt < ' msg , ' aad > (
86
145
& self ,
87
146
nonce : & GenericArray < u8 , Self :: NonceSize > ,
88
147
ciphertext : impl Into < Payload < ' msg , ' aad > > ,
89
- ) -> Result < Vec < u8 > , Error > ;
148
+ ) -> Result < Vec < u8 > , Error > {
149
+ decrypt_postfix_tagged_ciphertext_to_vec ! ( self , nonce, ciphertext)
150
+ }
151
+
152
+ /// Decrypt the data in-place, returning an error in the event the provided
153
+ /// authentication tag does not match the given ciphertext (i.e. ciphertext
154
+ /// is modified/unauthentic)
155
+ fn decrypt_in_place_detached (
156
+ & self ,
157
+ nonce : & GenericArray < u8 , Self :: NonceSize > ,
158
+ associated_data : & [ u8 ] ,
159
+ buffer : & mut [ u8 ] ,
160
+ tag : & GenericArray < u8 , Self :: TagSize > ,
161
+ ) -> Result < ( ) , Error > ;
90
162
}
91
163
92
164
/// Stateful Authenticated Encryption with Associated Data algorithm.
@@ -104,22 +176,47 @@ pub trait AeadMut {
104
176
///
105
177
/// See notes on [`Aead::encrypt()`] about allowable message payloads and
106
178
/// Associated Additional Data (AAD).
179
+ #[ cfg( feature = "alloc" ) ]
107
180
fn encrypt < ' msg , ' aad > (
108
181
& mut self ,
109
182
nonce : & GenericArray < u8 , Self :: NonceSize > ,
110
183
plaintext : impl Into < Payload < ' msg , ' aad > > ,
111
- ) -> Result < Vec < u8 > , Error > ;
184
+ ) -> Result < Vec < u8 > , Error > {
185
+ encrypt_to_postfix_tagged_vec ! ( self , nonce, plaintext)
186
+ }
187
+
188
+ /// Encrypt the data in-place, returning the authentication tag
189
+ fn encrypt_in_place_detached (
190
+ & mut self ,
191
+ nonce : & GenericArray < u8 , Self :: NonceSize > ,
192
+ associated_data : & [ u8 ] ,
193
+ buffer : & mut [ u8 ] ,
194
+ ) -> Result < GenericArray < u8 , Self :: TagSize > , Error > ;
112
195
113
196
/// Decrypt the given ciphertext slice, and return the resulting plaintext
114
197
/// as a vector of bytes.
115
198
///
116
199
/// See notes on [`Aead::encrypt()`] and [`Aead::decrypt()`] about allowable
117
200
/// message payloads and Associated Additional Data (AAD).
201
+ #[ cfg( feature = "alloc" ) ]
118
202
fn decrypt < ' msg , ' aad > (
119
203
& mut self ,
120
204
nonce : & GenericArray < u8 , Self :: NonceSize > ,
121
205
ciphertext : impl Into < Payload < ' msg , ' aad > > ,
122
- ) -> Result < Vec < u8 > , Error > ;
206
+ ) -> Result < Vec < u8 > , Error > {
207
+ decrypt_postfix_tagged_ciphertext_to_vec ! ( self , nonce, ciphertext)
208
+ }
209
+
210
+ /// Decrypt the data in-place, returning an error in the event the provided
211
+ /// authentication tag does not match the given ciphertext (i.e. ciphertext
212
+ /// is modified/unauthentic)
213
+ fn decrypt_in_place_detached (
214
+ & mut self ,
215
+ nonce : & GenericArray < u8 , Self :: NonceSize > ,
216
+ associated_data : & [ u8 ] ,
217
+ buffer : & mut [ u8 ] ,
218
+ tag : & GenericArray < u8 , Self :: TagSize > ,
219
+ ) -> Result < ( ) , Error > ;
123
220
}
124
221
125
222
/// A blanket implementation of the Stateful AEAD interface for Stateless
@@ -131,6 +228,7 @@ impl<Algo: Aead> AeadMut for Algo {
131
228
132
229
/// Encrypt the given plaintext slice, and return the resulting ciphertext
133
230
/// as a vector of bytes.
231
+ #[ cfg( feature = "alloc" ) ]
134
232
fn encrypt < ' msg , ' aad > (
135
233
& mut self ,
136
234
nonce : & GenericArray < u8 , Self :: NonceSize > ,
@@ -139,15 +237,39 @@ impl<Algo: Aead> AeadMut for Algo {
139
237
<Self as Aead >:: encrypt ( self , nonce, plaintext)
140
238
}
141
239
240
+ /// Encrypt the data in-place, returning the authentication tag
241
+ fn encrypt_in_place_detached (
242
+ & mut self ,
243
+ nonce : & GenericArray < u8 , Self :: NonceSize > ,
244
+ associated_data : & [ u8 ] ,
245
+ buffer : & mut [ u8 ] ,
246
+ ) -> Result < GenericArray < u8 , Self :: TagSize > , Error > {
247
+ <Self as Aead >:: encrypt_in_place_detached ( self , nonce, associated_data, buffer)
248
+ }
249
+
142
250
/// Decrypt the given ciphertext slice, and return the resulting plaintext
143
251
/// as a vector of bytes.
252
+ #[ cfg( feature = "alloc" ) ]
144
253
fn decrypt < ' msg , ' aad > (
145
254
& mut self ,
146
255
nonce : & GenericArray < u8 , Self :: NonceSize > ,
147
256
ciphertext : impl Into < Payload < ' msg , ' aad > > ,
148
257
) -> Result < Vec < u8 > , Error > {
149
258
<Self as Aead >:: decrypt ( self , nonce, ciphertext)
150
259
}
260
+
261
+ /// Decrypt the data in-place, returning an error in the event the provided
262
+ /// authentication tag does not match the given ciphertext (i.e. ciphertext
263
+ /// is modified/unauthentic)
264
+ fn decrypt_in_place_detached (
265
+ & mut self ,
266
+ nonce : & GenericArray < u8 , Self :: NonceSize > ,
267
+ associated_data : & [ u8 ] ,
268
+ buffer : & mut [ u8 ] ,
269
+ tag : & GenericArray < u8 , Self :: TagSize > ,
270
+ ) -> Result < ( ) , Error > {
271
+ <Self as Aead >:: decrypt_in_place_detached ( self , nonce, associated_data, buffer, tag)
272
+ }
151
273
}
152
274
153
275
/// AEAD payloads are a combination of a message (plaintext or ciphertext)
0 commit comments