1#![no_std]
2#![doc = include_str!("../README.md")]
3#![allow(clippy::upper_case_acronyms)]
4
5#[cfg(feature = "alloc")]
6extern crate alloc;
7
8use aead::{
9 AeadCore, AeadInOut, Buffer, Error, Result,
10 array::{
11 Array, ArraySize,
12 typenum::{U4, U5, Unsigned},
13 },
14};
15use core::ops::{AddAssign, Sub};
16
17pub use aead;
18
19pub use aead::{Key, KeyInit};
20
21#[cfg(feature = "alloc")]
22use {aead::Payload, alloc::vec::Vec};
23
24pub type Nonce<A, S> = Array<u8, NonceSize<A, S>>;
26
27pub type NonceSize<A, S> =
30 <<A as AeadCore>::NonceSize as Sub<<S as StreamPrimitive<A>>::NonceOverhead>>::Output;
31
32pub trait NewStream<A>: StreamPrimitive<A>
34where
35 A: AeadInOut,
36 A::NonceSize: Sub<Self::NonceOverhead>,
37 NonceSize<A, Self>: ArraySize,
38{
39 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 fn from_aead(aead: A, nonce: &Nonce<A, Self>) -> Self;
50}
51
52pub trait StreamPrimitive<A>
59where
60 A: AeadInOut,
61 A::NonceSize: Sub<Self::NonceOverhead>,
62 NonceSize<A, Self>: ArraySize,
63{
64 type NonceOverhead: ArraySize;
66
67 type Counter: AddAssign + Copy + Default + Eq;
69
70 const COUNTER_INCR: Self::Counter;
72
73 const COUNTER_MAX: Self::Counter;
75
76 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 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 #[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 #[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 fn encryptor(self) -> Encryptor<A, Self>
127 where
128 Self: Sized,
129 {
130 Encryptor::from_stream_primitive(self)
131 }
132
133 fn decryptor(self) -> Decryptor<A, Self>
135 where
136 Self: Sized,
137 {
138 Decryptor::from_stream_primitive(self)
139 }
140}
141
142macro_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: AeadInOut,
169 S: StreamPrimitive<A>,
170 A::NonceSize: Sub<<S as StreamPrimitive<A>>::NonceOverhead>,
171 NonceSize<A, S>: ArraySize,
172 {
173 stream: S,
175
176 position: S::Counter,
178 }
179
180 impl<A, S> $name<A, S>
181 where
182 A: AeadInOut,
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 S: NewStream<A>,
204 {
205 Self::from_stream_primitive(S::from_aead(aead, nonce))
206 }
207
208 #[doc = "Create a"]
209 #[doc = $obj_desc]
210 #[doc = "object from the given STREAM primitive."]
211 pub fn from_stream_primitive(stream: S) -> Self {
212 Self {
213 stream,
214 position: Default::default(),
215 }
216 }
217
218 #[doc = "Use the underlying AEAD to"]
219 #[doc = $op_desc]
220 #[doc = "the next AEAD message in this STREAM, returning the"]
221 #[doc = "result as a [`Vec`]."]
222 #[cfg(feature = "alloc")]
223 pub fn $next_method<'msg, 'aad>(
224 &mut self,
225 payload: impl Into<Payload<'msg, 'aad>>,
226 ) -> Result<Vec<u8>> {
227 if self.position == S::COUNTER_MAX {
228 return Err(Error);
232 }
233
234 let result = self.stream.$op(self.position, false, payload)?;
235
236 self.position += S::COUNTER_INCR;
238 Ok(result)
239 }
240
241 #[doc = "Use the underlying AEAD to"]
242 #[doc = $op_desc]
243 #[doc = "the next AEAD message in this STREAM in-place."]
244 pub fn $next_in_place_method(
245 &mut self,
246 associated_data: &[u8],
247 buffer: &mut dyn Buffer,
248 ) -> Result<()> {
249 if self.position == S::COUNTER_MAX {
250 return Err(Error);
254 }
255
256 self.stream
257 .$in_place_op(self.position, false, associated_data, buffer)?;
258
259 self.position += S::COUNTER_INCR;
261 Ok(())
262 }
263
264 #[doc = "Use the underlying AEAD to"]
265 #[doc = $op_desc]
266 #[doc = "the last AEAD message in this STREAM,"]
267 #[doc = "consuming the "]
268 #[doc = $obj_desc]
269 #[doc = "object in order to prevent further use."]
270 #[cfg(feature = "alloc")]
271 pub fn $last_method<'msg, 'aad>(
272 self,
273 payload: impl Into<Payload<'msg, 'aad>>,
274 ) -> Result<Vec<u8>> {
275 self.stream.$op(self.position, true, payload)
276 }
277
278 #[doc = "Use the underlying AEAD to"]
279 #[doc = $op_desc]
280 #[doc = "the last AEAD message in this STREAM in-place,"]
281 #[doc = "consuming the "]
282 #[doc = $obj_desc]
283 #[doc = "object in order to prevent further use."]
284 pub fn $last_in_place_method(
285 self,
286 associated_data: &[u8],
287 buffer: &mut dyn Buffer,
288 ) -> Result<()> {
289 self.stream
290 .$in_place_op(self.position, true, associated_data, buffer)
291 }
292 }
293 };
294}
295
296impl_stream_object!(
297 Encryptor,
298 encrypt_next,
299 encrypt_next_in_place,
300 encrypt_last,
301 encrypt_last_in_place,
302 encrypt,
303 encrypt_in_place,
304 "encrypt",
305 "ℰ STREAM encryptor"
306);
307
308impl_stream_object!(
309 Decryptor,
310 decrypt_next,
311 decrypt_next_in_place,
312 decrypt_last,
313 decrypt_last_in_place,
314 decrypt,
315 decrypt_in_place,
316 "decrypt",
317 "𝒟 STREAM decryptor"
318);
319
320pub type EncryptorBE32<A> = Encryptor<A, StreamBE32<A>>;
323
324pub type DecryptorBE32<A> = Decryptor<A, StreamBE32<A>>;
327
328pub type EncryptorLE31<A> = Encryptor<A, StreamLE31<A>>;
331
332pub type DecryptorLE31<A> = Decryptor<A, StreamLE31<A>>;
335
336#[derive(Debug)]
344pub struct StreamBE32<A>
345where
346 A: AeadInOut,
347 A::NonceSize: Sub<U5>,
348 <<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
349{
350 aead: A,
352
353 nonce: Nonce<A, Self>,
355}
356
357impl<A> NewStream<A> for StreamBE32<A>
358where
359 A: AeadInOut,
360 A::NonceSize: Sub<U5>,
361 <<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
362{
363 fn from_aead(aead: A, nonce: &Nonce<A, Self>) -> Self {
364 Self {
365 aead,
366 nonce: nonce.clone(),
367 }
368 }
369}
370
371impl<A> StreamPrimitive<A> for StreamBE32<A>
372where
373 A: AeadInOut,
374 A::NonceSize: Sub<U5>,
375 <<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
376{
377 type NonceOverhead = U5;
378 type Counter = u32;
379 const COUNTER_INCR: u32 = 1;
380 const COUNTER_MAX: u32 = u32::MAX;
381
382 fn encrypt_in_place(
383 &self,
384 position: u32,
385 last_block: bool,
386 associated_data: &[u8],
387 buffer: &mut dyn Buffer,
388 ) -> Result<()> {
389 let nonce = self.aead_nonce(position, last_block);
390 self.aead.encrypt_in_place(&nonce, associated_data, buffer)
391 }
392
393 fn decrypt_in_place(
394 &self,
395 position: Self::Counter,
396 last_block: bool,
397 associated_data: &[u8],
398 buffer: &mut dyn Buffer,
399 ) -> Result<()> {
400 let nonce = self.aead_nonce(position, last_block);
401 self.aead.decrypt_in_place(&nonce, associated_data, buffer)
402 }
403}
404
405impl<A> StreamBE32<A>
406where
407 A: AeadInOut,
408 A::NonceSize: Sub<U5>,
409 <<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
410{
411 fn aead_nonce(&self, position: u32, last_block: bool) -> aead::Nonce<A> {
414 let mut result = Array::default();
415
416 let (prefix, tail) = result.split_at_mut(NonceSize::<A, Self>::to_usize());
418 prefix.copy_from_slice(&self.nonce);
419
420 let (counter, flag) = tail.split_at_mut(4);
421 counter.copy_from_slice(&position.to_be_bytes());
422 flag[0] = last_block as u8;
423
424 result
425 }
426}
427
428#[derive(Debug)]
434pub struct StreamLE31<A>
435where
436 A: AeadInOut,
437 A::NonceSize: Sub<U4>,
438 <<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
439{
440 aead: A,
442
443 nonce: Nonce<A, Self>,
445}
446
447impl<A> NewStream<A> for StreamLE31<A>
448where
449 A: AeadInOut,
450 A::NonceSize: Sub<U4>,
451 <<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
452{
453 fn from_aead(aead: A, nonce: &Nonce<A, Self>) -> Self {
454 Self {
455 aead,
456 nonce: nonce.clone(),
457 }
458 }
459}
460
461impl<A> StreamPrimitive<A> for StreamLE31<A>
462where
463 A: AeadInOut,
464 A::NonceSize: Sub<U4>,
465 <<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
466{
467 type NonceOverhead = U4;
468 type Counter = u32;
469 const COUNTER_INCR: u32 = 1;
470 const COUNTER_MAX: u32 = 0x7fff_ffff;
471
472 fn encrypt_in_place(
473 &self,
474 position: u32,
475 last_block: bool,
476 associated_data: &[u8],
477 buffer: &mut dyn Buffer,
478 ) -> Result<()> {
479 let nonce = self.aead_nonce(position, last_block)?;
480 self.aead.encrypt_in_place(&nonce, associated_data, buffer)
481 }
482
483 fn decrypt_in_place(
484 &self,
485 position: Self::Counter,
486 last_block: bool,
487 associated_data: &[u8],
488 buffer: &mut dyn Buffer,
489 ) -> Result<()> {
490 let nonce = self.aead_nonce(position, last_block)?;
491 self.aead.decrypt_in_place(&nonce, associated_data, buffer)
492 }
493}
494
495impl<A> StreamLE31<A>
496where
497 A: AeadInOut,
498 A::NonceSize: Sub<U4>,
499 <<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
500{
501 fn aead_nonce(&self, position: u32, last_block: bool) -> Result<aead::Nonce<A>> {
504 if position > Self::COUNTER_MAX {
505 return Err(Error);
506 }
507
508 let mut result = Array::default();
509
510 let (prefix, tail) = result.split_at_mut(NonceSize::<A, Self>::to_usize());
512 prefix.copy_from_slice(&self.nonce);
513
514 let position_with_flag = position | ((last_block as u32) << 31);
515 tail.copy_from_slice(&position_with_flag.to_le_bytes());
516
517 Ok(result)
518 }
519}