1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
7)]
8#![allow(clippy::upper_case_acronyms)]
9
10#[cfg(feature = "alloc")]
11extern crate alloc;
12
13use aead::{
14 AeadCore, AeadInOut, Buffer, Error, Result,
15 array::{
16 Array, ArraySize,
17 typenum::{U4, U5, Unsigned},
18 },
19};
20use core::ops::{AddAssign, Sub};
21
22pub use aead;
23
24pub use aead::{Key, KeyInit};
25
26#[cfg(feature = "alloc")]
27use {aead::Payload, alloc::vec::Vec};
28
29pub type Nonce<A, S> = Array<u8, NonceSize<A, S>>;
31
32pub type NonceSize<A, S> =
35 <<A as AeadCore>::NonceSize as Sub<<S as StreamPrimitive<A>>::NonceOverhead>>::Output;
36
37pub trait NewStream<A>: StreamPrimitive<A>
39where
40 A: AeadInOut,
41 A::NonceSize: Sub<Self::NonceOverhead>,
42 NonceSize<A, Self>: ArraySize,
43{
44 fn new(key: &Key<A>, nonce: &Nonce<A, Self>) -> Self
46 where
47 A: KeyInit,
48 Self: Sized,
49 {
50 Self::from_aead(A::new(key), nonce)
51 }
52
53 fn from_aead(aead: A, nonce: &Nonce<A, Self>) -> Self;
55}
56
57pub trait StreamPrimitive<A>
64where
65 A: AeadInOut,
66 A::NonceSize: Sub<Self::NonceOverhead>,
67 NonceSize<A, Self>: ArraySize,
68{
69 type NonceOverhead: ArraySize;
71
72 type Counter: AddAssign + Copy + Default + Eq;
74
75 const COUNTER_INCR: Self::Counter;
77
78 const COUNTER_MAX: Self::Counter;
80
81 fn encrypt_in_place(
86 &self,
87 position: Self::Counter,
88 last_block: bool,
89 associated_data: &[u8],
90 buffer: &mut dyn Buffer,
91 ) -> Result<()>;
92
93 fn decrypt_in_place(
98 &self,
99 position: Self::Counter,
100 last_block: bool,
101 associated_data: &[u8],
102 buffer: &mut dyn Buffer,
103 ) -> Result<()>;
104
105 #[cfg(feature = "alloc")]
110 fn encrypt<'msg, 'aad>(
111 &self,
112 position: Self::Counter,
113 last_block: bool,
114 plaintext: impl Into<Payload<'msg, 'aad>>,
115 ) -> Result<Vec<u8>> {
116 let payload = plaintext.into();
117 let mut buffer = Vec::with_capacity(payload.msg.len() + A::TagSize::to_usize());
118 buffer.extend_from_slice(payload.msg);
119 self.encrypt_in_place(position, last_block, payload.aad, &mut buffer)?;
120 Ok(buffer)
121 }
122
123 #[cfg(feature = "alloc")]
128 fn decrypt<'msg, 'aad>(
129 &self,
130 position: Self::Counter,
131 last_block: bool,
132 ciphertext: impl Into<Payload<'msg, 'aad>>,
133 ) -> Result<Vec<u8>> {
134 let payload = ciphertext.into();
135 let mut buffer = Vec::from(payload.msg);
136 self.decrypt_in_place(position, last_block, payload.aad, &mut buffer)?;
137 Ok(buffer)
138 }
139
140 fn encryptor(self) -> Encryptor<A, Self>
142 where
143 Self: Sized,
144 {
145 Encryptor::from_stream_primitive(self)
146 }
147
148 fn decryptor(self) -> Decryptor<A, Self>
150 where
151 Self: Sized,
152 {
153 Decryptor::from_stream_primitive(self)
154 }
155}
156
157macro_rules! impl_stream_object {
159 (
160 $name:ident,
161 $next_method:tt,
162 $next_in_place_method:tt,
163 $last_method:tt,
164 $last_in_place_method:tt,
165 $op:tt,
166 $in_place_op:tt,
167 $op_desc:expr,
168 $obj_desc:expr
169 ) => {
170 #[doc = "Stateful STREAM object which can"]
171 #[doc = $op_desc]
172 #[doc = "AEAD messages one-at-a-time."]
173 #[doc = ""]
174 #[doc = "This corresponds to the "]
175 #[doc = $obj_desc]
176 #[doc = "object as defined in the paper"]
177 #[doc = "[Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance][1]."]
178 #[doc = ""]
179 #[doc = "[1]: https://eprint.iacr.org/2015/189.pdf"]
180 #[derive(Debug)]
181 pub struct $name<A, S>
182 where
183 A: AeadInOut,
184 S: StreamPrimitive<A>,
185 A::NonceSize: Sub<<S as StreamPrimitive<A>>::NonceOverhead>,
186 NonceSize<A, S>: ArraySize,
187 {
188 stream: S,
190
191 position: S::Counter,
193 }
194
195 impl<A, S> $name<A, S>
196 where
197 A: AeadInOut,
198 S: StreamPrimitive<A>,
199 A::NonceSize: Sub<<S as StreamPrimitive<A>>::NonceOverhead>,
200 NonceSize<A, S>: ArraySize,
201 {
202 #[doc = "Create a"]
203 #[doc = $obj_desc]
204 #[doc = "object from the given AEAD key and nonce."]
205 pub fn new(key: &Key<A>, nonce: &Nonce<A, S>) -> Self
206 where
207 A: KeyInit,
208 S: NewStream<A>,
209 {
210 Self::from_stream_primitive(S::new(key, nonce))
211 }
212
213 #[doc = "Create a"]
214 #[doc = $obj_desc]
215 #[doc = "object from the given AEAD primitive."]
216 pub fn from_aead(aead: A, nonce: &Nonce<A, S>) -> Self
217 where
218 S: NewStream<A>,
219 {
220 Self::from_stream_primitive(S::from_aead(aead, nonce))
221 }
222
223 #[doc = "Create a"]
224 #[doc = $obj_desc]
225 #[doc = "object from the given STREAM primitive."]
226 pub fn from_stream_primitive(stream: S) -> Self {
227 Self {
228 stream,
229 position: Default::default(),
230 }
231 }
232
233 #[doc = "Use the underlying AEAD to"]
234 #[doc = $op_desc]
235 #[doc = "the next AEAD message in this STREAM, returning the"]
236 #[doc = "result as a [`Vec`]."]
237 #[doc = "\n"]
238 #[doc = "# Errors\n"]
239 #[doc = "Propagates errors from the underlying AEAD"]
240 #[cfg(feature = "alloc")]
241 pub fn $next_method<'msg, 'aad>(
242 &mut self,
243 payload: impl Into<Payload<'msg, 'aad>>,
244 ) -> Result<Vec<u8>> {
245 if self.position == S::COUNTER_MAX {
246 return Err(Error);
250 }
251
252 let result = self.stream.$op(self.position, false, payload)?;
253
254 self.position += S::COUNTER_INCR;
256 Ok(result)
257 }
258
259 #[doc = "Use the underlying AEAD to"]
260 #[doc = $op_desc]
261 #[doc = "the next AEAD message in this STREAM in-place."]
262 #[doc = "\n"]
263 #[doc = "# Errors\n"]
264 #[doc = "Propagates errors from the underlying AEAD"]
265 pub fn $next_in_place_method(
266 &mut self,
267 associated_data: &[u8],
268 buffer: &mut dyn Buffer,
269 ) -> Result<()> {
270 if self.position == S::COUNTER_MAX {
271 return Err(Error);
275 }
276
277 self.stream
278 .$in_place_op(self.position, false, associated_data, buffer)?;
279
280 self.position += S::COUNTER_INCR;
282 Ok(())
283 }
284
285 #[doc = "Use the underlying AEAD to"]
286 #[doc = $op_desc]
287 #[doc = "the last AEAD message in this STREAM,"]
288 #[doc = "consuming the "]
289 #[doc = $obj_desc]
290 #[doc = "object in order to prevent further use."]
291 #[doc = "\n"]
292 #[doc = "# Errors\n"]
293 #[doc = "Propagates errors from the underlying AEAD"]
294 #[cfg(feature = "alloc")]
295 pub fn $last_method<'msg, 'aad>(
296 self,
297 payload: impl Into<Payload<'msg, 'aad>>,
298 ) -> Result<Vec<u8>> {
299 self.stream.$op(self.position, true, payload)
300 }
301
302 #[doc = "Use the underlying AEAD to"]
303 #[doc = $op_desc]
304 #[doc = "the last AEAD message in this STREAM in-place,"]
305 #[doc = "consuming the "]
306 #[doc = $obj_desc]
307 #[doc = "object in order to prevent further use."]
308 #[doc = "\n"]
309 #[doc = "# Errors\n"]
310 #[doc = "Propagates errors from the underlying AEAD"]
311 pub fn $last_in_place_method(
312 self,
313 associated_data: &[u8],
314 buffer: &mut dyn Buffer,
315 ) -> Result<()> {
316 self.stream
317 .$in_place_op(self.position, true, associated_data, buffer)
318 }
319 }
320 };
321}
322
323impl_stream_object!(
324 Encryptor,
325 encrypt_next,
326 encrypt_next_in_place,
327 encrypt_last,
328 encrypt_last_in_place,
329 encrypt,
330 encrypt_in_place,
331 "encrypt",
332 "ℰ STREAM encryptor"
333);
334
335impl_stream_object!(
336 Decryptor,
337 decrypt_next,
338 decrypt_next_in_place,
339 decrypt_last,
340 decrypt_last_in_place,
341 decrypt,
342 decrypt_in_place,
343 "decrypt",
344 "𝒟 STREAM decryptor"
345);
346
347pub type EncryptorBE32<A> = Encryptor<A, StreamBE32<A>>;
350
351pub type DecryptorBE32<A> = Decryptor<A, StreamBE32<A>>;
354
355pub type EncryptorLE31<A> = Encryptor<A, StreamLE31<A>>;
358
359pub type DecryptorLE31<A> = Decryptor<A, StreamLE31<A>>;
362
363#[derive(Debug)]
371pub struct StreamBE32<A>
372where
373 A: AeadInOut,
374 A::NonceSize: Sub<U5>,
375 <<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
376{
377 aead: A,
379
380 nonce: Nonce<A, Self>,
382}
383
384impl<A> NewStream<A> for StreamBE32<A>
385where
386 A: AeadInOut,
387 A::NonceSize: Sub<U5>,
388 <<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
389{
390 fn from_aead(aead: A, nonce: &Nonce<A, Self>) -> Self {
391 Self {
392 aead,
393 nonce: nonce.clone(),
394 }
395 }
396}
397
398impl<A> StreamPrimitive<A> for StreamBE32<A>
399where
400 A: AeadInOut,
401 A::NonceSize: Sub<U5>,
402 <<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
403{
404 type NonceOverhead = U5;
405 type Counter = u32;
406 const COUNTER_INCR: u32 = 1;
407 const COUNTER_MAX: u32 = u32::MAX;
408
409 fn encrypt_in_place(
410 &self,
411 position: u32,
412 last_block: bool,
413 associated_data: &[u8],
414 buffer: &mut dyn Buffer,
415 ) -> Result<()> {
416 let nonce = self.aead_nonce(position, last_block);
417 self.aead.encrypt_in_place(&nonce, associated_data, buffer)
418 }
419
420 fn decrypt_in_place(
421 &self,
422 position: Self::Counter,
423 last_block: bool,
424 associated_data: &[u8],
425 buffer: &mut dyn Buffer,
426 ) -> Result<()> {
427 let nonce = self.aead_nonce(position, last_block);
428 self.aead.decrypt_in_place(&nonce, associated_data, buffer)
429 }
430}
431
432impl<A> StreamBE32<A>
433where
434 A: AeadInOut,
435 A::NonceSize: Sub<U5>,
436 <<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
437{
438 fn aead_nonce(&self, position: u32, last_block: bool) -> aead::Nonce<A> {
441 let mut result = Array::default();
442
443 let (prefix, tail) = result.split_at_mut(NonceSize::<A, Self>::to_usize());
445 prefix.copy_from_slice(&self.nonce);
446
447 let (counter, flag) = tail.split_at_mut(4);
448 counter.copy_from_slice(&position.to_be_bytes());
449 flag[0] = u8::from(last_block);
450
451 result
452 }
453}
454
455#[derive(Debug)]
461pub struct StreamLE31<A>
462where
463 A: AeadInOut,
464 A::NonceSize: Sub<U4>,
465 <<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
466{
467 aead: A,
469
470 nonce: Nonce<A, Self>,
472}
473
474impl<A> NewStream<A> for StreamLE31<A>
475where
476 A: AeadInOut,
477 A::NonceSize: Sub<U4>,
478 <<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
479{
480 fn from_aead(aead: A, nonce: &Nonce<A, Self>) -> Self {
481 Self {
482 aead,
483 nonce: nonce.clone(),
484 }
485 }
486}
487
488impl<A> StreamPrimitive<A> for StreamLE31<A>
489where
490 A: AeadInOut,
491 A::NonceSize: Sub<U4>,
492 <<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
493{
494 type NonceOverhead = U4;
495 type Counter = u32;
496 const COUNTER_INCR: u32 = 1;
497 const COUNTER_MAX: u32 = 0x7fff_ffff;
498
499 fn encrypt_in_place(
500 &self,
501 position: u32,
502 last_block: bool,
503 associated_data: &[u8],
504 buffer: &mut dyn Buffer,
505 ) -> Result<()> {
506 let nonce = self.aead_nonce(position, last_block)?;
507 self.aead.encrypt_in_place(&nonce, associated_data, buffer)
508 }
509
510 fn decrypt_in_place(
511 &self,
512 position: Self::Counter,
513 last_block: bool,
514 associated_data: &[u8],
515 buffer: &mut dyn Buffer,
516 ) -> Result<()> {
517 let nonce = self.aead_nonce(position, last_block)?;
518 self.aead.decrypt_in_place(&nonce, associated_data, buffer)
519 }
520}
521
522impl<A> StreamLE31<A>
523where
524 A: AeadInOut,
525 A::NonceSize: Sub<U4>,
526 <<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
527{
528 fn aead_nonce(&self, position: u32, last_block: bool) -> Result<aead::Nonce<A>> {
531 if position > Self::COUNTER_MAX {
532 return Err(Error);
533 }
534
535 let mut result = Array::default();
536
537 let (prefix, tail) = result.split_at_mut(NonceSize::<A, Self>::to_usize());
539 prefix.copy_from_slice(&self.nonce);
540
541 let position_with_flag = position | (u32::from(last_block) << 31);
542 tail.copy_from_slice(&position_with_flag.to_le_bytes());
543
544 Ok(result)
545 }
546}