Skip to content

Commit ad69263

Browse files
authored
aead-stream: move the remaining items from aead (#647)
This PR follows removal of the items from `aead` in RustCrypto/traits#1713 In a future PR I plan to refactor `aead-stream` further, so it's convenient to have all code in one place.
1 parent 8403768 commit ad69263

File tree

2 files changed

+301
-10
lines changed

2 files changed

+301
-10
lines changed

aead-stream/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ categories = ["cryptography", "no-std"]
1313
rust-version = "1.81"
1414

1515
[dependencies]
16-
aead = { version = "=0.6.0-rc.0", default-features = false, features = ["stream"] }
16+
aead = { version = "=0.6.0-rc.0", default-features = false }
1717

1818
[features]
1919
alloc = ["aead/alloc"]

aead-stream/src/lib.rs

Lines changed: 300 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@
55
#[cfg(feature = "alloc")]
66
extern 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

1517
pub 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.
2325
pub type Nonce<A, S> = Array<u8, NonceSize<A, S>>;
@@ -27,6 +29,295 @@ pub type Nonce<A, S> = Array<u8, NonceSize<A, S>>;
2729
pub 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.
32323
pub type EncryptorBE32<A> = Encryptor<A, StreamBE32<A>>;

0 commit comments

Comments
 (0)