Skip to content

Commit 181230a

Browse files
authored
aead: extract STREAM implementation into aead-stream (#1673)
Sibling PR: RustCrypto/AEADs#627 Closes #1665
1 parent 7dfeb99 commit 181230a

File tree

5 files changed

+5
-238
lines changed

5 files changed

+5
-238
lines changed

.github/workflows/aead.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ jobs:
4040
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features bytes
4141
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features heapless
4242
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features rand_core
43-
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features stream
4443

4544
# TODO(tarcieri): re-enable after next `crypto-common` release
4645
# minimal-versions:

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aead/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ std = ["alloc", "crypto-common/std"]
3131
dev = ["blobby"]
3232
getrandom = ["crypto-common/getrandom"]
3333
rand_core = ["crypto-common/rand_core"]
34-
stream = []
3534

3635
[package.metadata.docs.rs]
3736
all-features = true

aead/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ extern crate std;
2222
#[cfg(feature = "dev")]
2323
pub mod dev;
2424

25-
#[cfg(feature = "stream")]
2625
pub mod stream;
2726

2827
pub use crypto_common::{

aead/src/stream.rs

Lines changed: 4 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,17 @@
11
//! Streaming AEAD support.
22
//!
3-
//! Implementation of the STREAM online authenticated encryption construction
4-
//! as described in the paper
5-
//! [Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance][1].
3+
//! See the [`aead-stream`] crate for a generic implementation of the STREAM construction.
64
//!
7-
//! ## About
8-
//!
9-
//! The STREAM construction supports encrypting/decrypting sequences of AEAD
10-
//! message segments, which is useful in cases where the overall message is too
11-
//! large to fit in a single buffer and needs to be processed incrementally.
12-
//!
13-
//! STREAM defends against reordering and truncation attacks which are common
14-
//! in naive schemes which attempt to provide these properties, and is proven
15-
//! to meet the security definition of "nonce-based online authenticated
16-
//! encryption" (nOAE) as given in the aforementioned paper.
17-
//!
18-
//! ## Diagram
19-
//!
20-
//! ![STREAM Diagram](https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/img/AEADs/rogaway-stream.svg)
21-
//!
22-
//! Legend:
23-
//!
24-
//! - 𝐄k: AEAD encryption under key `k`
25-
//! - 𝐌: message
26-
//! - 𝐍: nonce
27-
//! - 𝐀: additional associated data
28-
//! - 𝐂: ciphertext
29-
//! - 𝜏: MAC tag
30-
//!
31-
//! [1]: https://eprint.iacr.org/2015/189.pdf
5+
//! [`aead-stream`]: https://docs.rs/aead-stream
326
337
#![allow(clippy::upper_case_acronyms)]
348

359
use crate::{AeadCore, AeadInPlace, Buffer, Error, Key, KeyInit, Result};
3610
use core::ops::{AddAssign, Sub};
37-
use crypto_common::array::{
38-
typenum::{Unsigned, U4, U5},
39-
Array, ArraySize,
40-
};
11+
use crypto_common::array::{Array, ArraySize};
4112

4213
#[cfg(feature = "alloc")]
43-
use {crate::Payload, alloc::vec::Vec};
14+
use {crate::Payload, alloc::vec::Vec, crypto_common::array::typenum::Unsigned};
4415

4516
/// Nonce as used by a given AEAD construction and STREAM primitive.
4617
pub type Nonce<A, S> = Array<u8, NonceSize<A, S>>;
@@ -50,22 +21,6 @@ pub type Nonce<A, S> = Array<u8, NonceSize<A, S>>;
5021
pub type NonceSize<A, S> =
5122
<<A as AeadCore>::NonceSize as Sub<<S as StreamPrimitive<A>>::NonceOverhead>>::Output;
5223

53-
/// STREAM encryptor instantiated with [`StreamBE32`] as the underlying
54-
/// STREAM primitive.
55-
pub type EncryptorBE32<A> = Encryptor<A, StreamBE32<A>>;
56-
57-
/// STREAM decryptor instantiated with [`StreamBE32`] as the underlying
58-
/// STREAM primitive.
59-
pub type DecryptorBE32<A> = Decryptor<A, StreamBE32<A>>;
60-
61-
/// STREAM encryptor instantiated with [`StreamLE31`] as the underlying
62-
/// STREAM primitive.
63-
pub type EncryptorLE31<A> = Encryptor<A, StreamLE31<A>>;
64-
65-
/// STREAM decryptor instantiated with [`StreamLE31`] as the underlying
66-
/// STREAM primitive.
67-
pub type DecryptorLE31<A> = Decryptor<A, StreamLE31<A>>;
68-
6924
/// Create a new STREAM from the provided AEAD.
7025
pub trait NewStream<A>: StreamPrimitive<A>
7126
where
@@ -354,188 +309,3 @@ impl_stream_object!(
354309
"decrypt",
355310
"𝒟 STREAM decryptor"
356311
);
357-
358-
/// The original "Rogaway-flavored" STREAM as described in the paper
359-
/// [Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance][1].
360-
///
361-
/// Uses a 32-bit big endian counter and 1-byte "last block" flag stored as
362-
/// the last 5-bytes of the AEAD nonce.
363-
///
364-
/// [1]: https://eprint.iacr.org/2015/189.pdf
365-
#[derive(Debug)]
366-
pub struct StreamBE32<A>
367-
where
368-
A: AeadInPlace,
369-
A::NonceSize: Sub<U5>,
370-
<<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
371-
{
372-
/// Underlying AEAD cipher
373-
aead: A,
374-
375-
/// Nonce (sans STREAM overhead)
376-
nonce: Nonce<A, Self>,
377-
}
378-
379-
impl<A> NewStream<A> for StreamBE32<A>
380-
where
381-
A: AeadInPlace,
382-
A::NonceSize: Sub<U5>,
383-
<<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
384-
{
385-
fn from_aead(aead: A, nonce: &Nonce<A, Self>) -> Self {
386-
Self {
387-
aead,
388-
nonce: nonce.clone(),
389-
}
390-
}
391-
}
392-
393-
impl<A> StreamPrimitive<A> for StreamBE32<A>
394-
where
395-
A: AeadInPlace,
396-
A::NonceSize: Sub<U5>,
397-
<<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
398-
{
399-
type NonceOverhead = U5;
400-
type Counter = u32;
401-
const COUNTER_INCR: u32 = 1;
402-
const COUNTER_MAX: u32 = u32::MAX;
403-
404-
fn encrypt_in_place(
405-
&self,
406-
position: u32,
407-
last_block: bool,
408-
associated_data: &[u8],
409-
buffer: &mut dyn Buffer,
410-
) -> Result<()> {
411-
let nonce = self.aead_nonce(position, last_block);
412-
self.aead.encrypt_in_place(&nonce, associated_data, buffer)
413-
}
414-
415-
fn decrypt_in_place(
416-
&self,
417-
position: Self::Counter,
418-
last_block: bool,
419-
associated_data: &[u8],
420-
buffer: &mut dyn Buffer,
421-
) -> Result<()> {
422-
let nonce = self.aead_nonce(position, last_block);
423-
self.aead.decrypt_in_place(&nonce, associated_data, buffer)
424-
}
425-
}
426-
427-
impl<A> StreamBE32<A>
428-
where
429-
A: AeadInPlace,
430-
A::NonceSize: Sub<U5>,
431-
<<A as AeadCore>::NonceSize as Sub<U5>>::Output: ArraySize,
432-
{
433-
/// Compute the full AEAD nonce including the STREAM counter and last
434-
/// block flag.
435-
fn aead_nonce(&self, position: u32, last_block: bool) -> crate::Nonce<A> {
436-
let mut result = Array::default();
437-
438-
// TODO(tarcieri): use `generic_array::sequence::Concat` (or const generics)
439-
let (prefix, tail) = result.split_at_mut(NonceSize::<A, Self>::to_usize());
440-
prefix.copy_from_slice(&self.nonce);
441-
442-
let (counter, flag) = tail.split_at_mut(4);
443-
counter.copy_from_slice(&position.to_be_bytes());
444-
flag[0] = last_block as u8;
445-
446-
result
447-
}
448-
}
449-
450-
/// STREAM as instantiated with a 31-bit little endian counter and 1-bit
451-
/// "last block" flag stored as the most significant bit of the counter
452-
/// when interpreted as a 32-bit integer.
453-
///
454-
/// The 31-bit + 1-bit value is stored as the last 4 bytes of the AEAD nonce.
455-
#[derive(Debug)]
456-
pub struct StreamLE31<A>
457-
where
458-
A: AeadInPlace,
459-
A::NonceSize: Sub<U4>,
460-
<<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
461-
{
462-
/// Underlying AEAD cipher
463-
aead: A,
464-
465-
/// Nonce (sans STREAM overhead)
466-
nonce: Nonce<A, Self>,
467-
}
468-
469-
impl<A> NewStream<A> for StreamLE31<A>
470-
where
471-
A: AeadInPlace,
472-
A::NonceSize: Sub<U4>,
473-
<<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
474-
{
475-
fn from_aead(aead: A, nonce: &Nonce<A, Self>) -> Self {
476-
Self {
477-
aead,
478-
nonce: nonce.clone(),
479-
}
480-
}
481-
}
482-
483-
impl<A> StreamPrimitive<A> for StreamLE31<A>
484-
where
485-
A: AeadInPlace,
486-
A::NonceSize: Sub<U4>,
487-
<<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
488-
{
489-
type NonceOverhead = U4;
490-
type Counter = u32;
491-
const COUNTER_INCR: u32 = 1;
492-
const COUNTER_MAX: u32 = 0xfff_ffff;
493-
494-
fn encrypt_in_place(
495-
&self,
496-
position: u32,
497-
last_block: bool,
498-
associated_data: &[u8],
499-
buffer: &mut dyn Buffer,
500-
) -> Result<()> {
501-
let nonce = self.aead_nonce(position, last_block)?;
502-
self.aead.encrypt_in_place(&nonce, associated_data, buffer)
503-
}
504-
505-
fn decrypt_in_place(
506-
&self,
507-
position: Self::Counter,
508-
last_block: bool,
509-
associated_data: &[u8],
510-
buffer: &mut dyn Buffer,
511-
) -> Result<()> {
512-
let nonce = self.aead_nonce(position, last_block)?;
513-
self.aead.decrypt_in_place(&nonce, associated_data, buffer)
514-
}
515-
}
516-
517-
impl<A> StreamLE31<A>
518-
where
519-
A: AeadInPlace,
520-
A::NonceSize: Sub<U4>,
521-
<<A as AeadCore>::NonceSize as Sub<U4>>::Output: ArraySize,
522-
{
523-
/// Compute the full AEAD nonce including the STREAM counter and last
524-
/// block flag.
525-
fn aead_nonce(&self, position: u32, last_block: bool) -> Result<crate::Nonce<A>> {
526-
if position > Self::COUNTER_MAX {
527-
return Err(Error);
528-
}
529-
530-
let mut result = Array::default();
531-
532-
// TODO(tarcieri): use `generic_array::sequence::Concat` (or const generics)
533-
let (prefix, tail) = result.split_at_mut(NonceSize::<A, Self>::to_usize());
534-
prefix.copy_from_slice(&self.nonce);
535-
536-
let position_with_flag = position | ((last_block as u32) << 31);
537-
tail.copy_from_slice(&position_with_flag.to_le_bytes());
538-
539-
Ok(result)
540-
}
541-
}

0 commit comments

Comments
 (0)