55#[ cfg( feature = "alloc" ) ]
66extern crate alloc;
77
8- use aead:: array:: {
9- typenum:: { Unsigned , U4 , U5 } ,
10- Array , ArraySize ,
8+ use aead:: {
9+ array:: {
10+ typenum:: { Unsigned , U4 , U5 } ,
11+ Array , ArraySize ,
12+ } ,
13+ AeadCore , AeadInPlace , Buffer , Error , Result ,
1114} ;
12- use aead:: { AeadCore , AeadInPlace , Buffer , Error , Result } ;
13- use core:: ops:: Sub ;
15+ use core:: ops:: { AddAssign , Sub } ;
1416
1517pub use aead;
1618
17- pub use aead:: {
18- stream :: { Decryptor , Encryptor , NewStream , StreamPrimitive } ,
19- Key , KeyInit ,
20- } ;
19+ pub use aead:: { Key , KeyInit } ;
20+
21+ # [ cfg ( feature = "alloc" ) ]
22+ use { aead :: Payload , alloc :: vec :: Vec } ;
2123
2224/// Nonce as used by a given AEAD construction and STREAM primitive.
2325pub type Nonce < A , S > = Array < u8 , NonceSize < A , S > > ;
@@ -27,6 +29,295 @@ pub type Nonce<A, S> = Array<u8, NonceSize<A, S>>;
2729pub type NonceSize < A , S > =
2830 <<A as AeadCore >:: NonceSize as Sub < <S as StreamPrimitive < A > >:: NonceOverhead > >:: Output ;
2931
32+ /// Create a new STREAM from the provided AEAD.
33+ pub trait NewStream < A > : StreamPrimitive < A >
34+ where
35+ A : AeadInPlace ,
36+ A :: NonceSize : Sub < Self :: NonceOverhead > ,
37+ NonceSize < A , Self > : ArraySize ,
38+ {
39+ /// Create a new STREAM with the given key and nonce.
40+ fn new ( key : & Key < A > , nonce : & Nonce < A , Self > ) -> Self
41+ where
42+ A : KeyInit ,
43+ Self : Sized ,
44+ {
45+ Self :: from_aead ( A :: new ( key) , nonce)
46+ }
47+
48+ /// Create a new STREAM from the given AEAD cipher.
49+ fn from_aead ( aead : A , nonce : & Nonce < A , Self > ) -> Self ;
50+ }
51+
52+ /// Low-level STREAM implementation.
53+ ///
54+ /// This trait provides a particular "flavor" of STREAM, as there are
55+ /// different ways the specifics of the construction can be implemented.
56+ ///
57+ /// Deliberately immutable and stateless to permit parallel operation.
58+ pub trait StreamPrimitive < A >
59+ where
60+ A : AeadInPlace ,
61+ A :: NonceSize : Sub < Self :: NonceOverhead > ,
62+ NonceSize < A , Self > : ArraySize ,
63+ {
64+ /// Number of bytes this STREAM primitive requires from the nonce.
65+ type NonceOverhead : ArraySize ;
66+
67+ /// Type used as the STREAM counter.
68+ type Counter : AddAssign + Copy + Default + Eq ;
69+
70+ /// Value to use when incrementing the STREAM counter (i.e. one)
71+ const COUNTER_INCR : Self :: Counter ;
72+
73+ /// Maximum value of the STREAM counter.
74+ const COUNTER_MAX : Self :: Counter ;
75+
76+ /// Encrypt an AEAD message in-place at the given position in the STREAM.
77+ fn encrypt_in_place (
78+ & self ,
79+ position : Self :: Counter ,
80+ last_block : bool ,
81+ associated_data : & [ u8 ] ,
82+ buffer : & mut dyn Buffer ,
83+ ) -> Result < ( ) > ;
84+
85+ /// Decrypt an AEAD message in-place at the given position in the STREAM.
86+ fn decrypt_in_place (
87+ & self ,
88+ position : Self :: Counter ,
89+ last_block : bool ,
90+ associated_data : & [ u8 ] ,
91+ buffer : & mut dyn Buffer ,
92+ ) -> Result < ( ) > ;
93+
94+ /// Encrypt the given plaintext payload, and return the resulting
95+ /// ciphertext as a vector of bytes.
96+ #[ cfg( feature = "alloc" ) ]
97+ fn encrypt < ' msg , ' aad > (
98+ & self ,
99+ position : Self :: Counter ,
100+ last_block : bool ,
101+ plaintext : impl Into < Payload < ' msg , ' aad > > ,
102+ ) -> Result < Vec < u8 > > {
103+ let payload = plaintext. into ( ) ;
104+ let mut buffer = Vec :: with_capacity ( payload. msg . len ( ) + A :: TagSize :: to_usize ( ) ) ;
105+ buffer. extend_from_slice ( payload. msg ) ;
106+ self . encrypt_in_place ( position, last_block, payload. aad , & mut buffer) ?;
107+ Ok ( buffer)
108+ }
109+
110+ /// Decrypt the given ciphertext slice, and return the resulting plaintext
111+ /// as a vector of bytes.
112+ #[ cfg( feature = "alloc" ) ]
113+ fn decrypt < ' msg , ' aad > (
114+ & self ,
115+ position : Self :: Counter ,
116+ last_block : bool ,
117+ ciphertext : impl Into < Payload < ' msg , ' aad > > ,
118+ ) -> Result < Vec < u8 > > {
119+ let payload = ciphertext. into ( ) ;
120+ let mut buffer = Vec :: from ( payload. msg ) ;
121+ self . decrypt_in_place ( position, last_block, payload. aad , & mut buffer) ?;
122+ Ok ( buffer)
123+ }
124+
125+ /// Obtain [`Encryptor`] for this [`StreamPrimitive`].
126+ fn encryptor ( self ) -> Encryptor < A , Self >
127+ where
128+ Self : Sized ,
129+ {
130+ Encryptor :: from_stream_primitive ( self )
131+ }
132+
133+ /// Obtain [`Decryptor`] for this [`StreamPrimitive`].
134+ fn decryptor ( self ) -> Decryptor < A , Self >
135+ where
136+ Self : Sized ,
137+ {
138+ Decryptor :: from_stream_primitive ( self )
139+ }
140+ }
141+
142+ /// Implement a stateful STREAM object (i.e. encryptor or decryptor)
143+ macro_rules! impl_stream_object {
144+ (
145+ $name: ident,
146+ $next_method: tt,
147+ $next_in_place_method: tt,
148+ $last_method: tt,
149+ $last_in_place_method: tt,
150+ $op: tt,
151+ $in_place_op: tt,
152+ $op_desc: expr,
153+ $obj_desc: expr
154+ ) => {
155+ #[ doc = "Stateful STREAM object which can" ]
156+ #[ doc = $op_desc]
157+ #[ doc = "AEAD messages one-at-a-time." ]
158+ #[ doc = "" ]
159+ #[ doc = "This corresponds to the " ]
160+ #[ doc = $obj_desc]
161+ #[ doc = "object as defined in the paper" ]
162+ #[ doc = "[Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance][1]." ]
163+ #[ doc = "" ]
164+ #[ doc = "[1]: https://eprint.iacr.org/2015/189.pdf" ]
165+ #[ derive( Debug ) ]
166+ pub struct $name<A , S >
167+ where
168+ A : AeadInPlace ,
169+ S : StreamPrimitive <A >,
170+ A :: NonceSize : Sub <<S as StreamPrimitive <A >>:: NonceOverhead >,
171+ NonceSize <A , S >: ArraySize ,
172+ {
173+ /// Underlying STREAM primitive.
174+ stream: S ,
175+
176+ /// Current position in the STREAM.
177+ position: S :: Counter ,
178+ }
179+
180+ impl <A , S > $name<A , S >
181+ where
182+ A : AeadInPlace ,
183+ S : StreamPrimitive <A >,
184+ A :: NonceSize : Sub <<S as StreamPrimitive <A >>:: NonceOverhead >,
185+ NonceSize <A , S >: ArraySize ,
186+ {
187+ #[ doc = "Create a" ]
188+ #[ doc = $obj_desc]
189+ #[ doc = "object from the given AEAD key and nonce." ]
190+ pub fn new( key: & Key <A >, nonce: & Nonce <A , S >) -> Self
191+ where
192+ A : KeyInit ,
193+ S : NewStream <A >,
194+ {
195+ Self :: from_stream_primitive( S :: new( key, nonce) )
196+ }
197+
198+ #[ doc = "Create a" ]
199+ #[ doc = $obj_desc]
200+ #[ doc = "object from the given AEAD primitive." ]
201+ pub fn from_aead( aead: A , nonce: & Nonce <A , S >) -> Self
202+ where
203+ A : KeyInit ,
204+ S : NewStream <A >,
205+ {
206+ Self :: from_stream_primitive( S :: from_aead( aead, nonce) )
207+ }
208+
209+ #[ doc = "Create a" ]
210+ #[ doc = $obj_desc]
211+ #[ doc = "object from the given STREAM primitive." ]
212+ pub fn from_stream_primitive( stream: S ) -> Self {
213+ Self {
214+ stream,
215+ position: Default :: default ( ) ,
216+ }
217+ }
218+
219+ #[ doc = "Use the underlying AEAD to" ]
220+ #[ doc = $op_desc]
221+ #[ doc = "the next AEAD message in this STREAM, returning the" ]
222+ #[ doc = "result as a [`Vec`]." ]
223+ #[ cfg( feature = "alloc" ) ]
224+ pub fn $next_method<' msg, ' aad>(
225+ & mut self ,
226+ payload: impl Into <Payload <' msg, ' aad>>,
227+ ) -> Result <Vec <u8 >> {
228+ if self . position == S :: COUNTER_MAX {
229+ // Counter overflow. Note that the maximum counter value is
230+ // deliberately disallowed, as it would preclude being able
231+ // to encrypt a last block (i.e. with `$last_in_place_method`)
232+ return Err ( Error ) ;
233+ }
234+
235+ let result = self . stream. $op( self . position, false , payload) ?;
236+
237+ // Note: overflow checked above
238+ self . position += S :: COUNTER_INCR ;
239+ Ok ( result)
240+ }
241+
242+ #[ doc = "Use the underlying AEAD to" ]
243+ #[ doc = $op_desc]
244+ #[ doc = "the next AEAD message in this STREAM in-place." ]
245+ pub fn $next_in_place_method(
246+ & mut self ,
247+ associated_data: & [ u8 ] ,
248+ buffer: & mut dyn Buffer ,
249+ ) -> Result <( ) > {
250+ if self . position == S :: COUNTER_MAX {
251+ // Counter overflow. Note that the maximum counter value is
252+ // deliberately disallowed, as it would preclude being able
253+ // to encrypt a last block (i.e. with `$last_in_place_method`)
254+ return Err ( Error ) ;
255+ }
256+
257+ self . stream
258+ . $in_place_op( self . position, false , associated_data, buffer) ?;
259+
260+ // Note: overflow checked above
261+ self . position += S :: COUNTER_INCR ;
262+ Ok ( ( ) )
263+ }
264+
265+ #[ doc = "Use the underlying AEAD to" ]
266+ #[ doc = $op_desc]
267+ #[ doc = "the last AEAD message in this STREAM," ]
268+ #[ doc = "consuming the " ]
269+ #[ doc = $obj_desc]
270+ #[ doc = "object in order to prevent further use." ]
271+ #[ cfg( feature = "alloc" ) ]
272+ pub fn $last_method<' msg, ' aad>(
273+ self ,
274+ payload: impl Into <Payload <' msg, ' aad>>,
275+ ) -> Result <Vec <u8 >> {
276+ self . stream. $op( self . position, true , payload)
277+ }
278+
279+ #[ doc = "Use the underlying AEAD to" ]
280+ #[ doc = $op_desc]
281+ #[ doc = "the last AEAD message in this STREAM in-place," ]
282+ #[ doc = "consuming the " ]
283+ #[ doc = $obj_desc]
284+ #[ doc = "object in order to prevent further use." ]
285+ pub fn $last_in_place_method(
286+ self ,
287+ associated_data: & [ u8 ] ,
288+ buffer: & mut dyn Buffer ,
289+ ) -> Result <( ) > {
290+ self . stream
291+ . $in_place_op( self . position, true , associated_data, buffer)
292+ }
293+ }
294+ } ;
295+ }
296+
297+ impl_stream_object ! (
298+ Encryptor ,
299+ encrypt_next,
300+ encrypt_next_in_place,
301+ encrypt_last,
302+ encrypt_last_in_place,
303+ encrypt,
304+ encrypt_in_place,
305+ "encrypt" ,
306+ "ℰ STREAM encryptor"
307+ ) ;
308+
309+ impl_stream_object ! (
310+ Decryptor ,
311+ decrypt_next,
312+ decrypt_next_in_place,
313+ decrypt_last,
314+ decrypt_last_in_place,
315+ decrypt,
316+ decrypt_in_place,
317+ "decrypt" ,
318+ "𝒟 STREAM decryptor"
319+ ) ;
320+
30321/// STREAM encryptor instantiated with [`StreamBE32`] as the underlying
31322/// STREAM primitive.
32323pub type EncryptorBE32 < A > = Encryptor < A , StreamBE32 < A > > ;
0 commit comments