1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//! `stream.rs`: The STREAM online authenticated encryption construction.
//! See <https://eprint.iacr.org/2015/189.pdf> for definition.

use crate::{Aead, Aes128PmacSivAead, Aes128SivAead, Aes256PmacSivAead, Aes256SivAead, Error};

#[cfg(feature = "alloc")]
use alloc::vec::Vec;

/// Size of a nonce required by STREAM in bytes
pub const NONCE_SIZE: usize = 8;

/// Byte flag indicating this is the last block in the STREAM (otherwise 0)
const LAST_BLOCK_FLAG: u8 = 1;

/// A STREAM encryptor with a 32-bit counter, generalized for any AEAD algorithm
///
/// This corresponds to the ℰ stream encryptor object as defined in the paper
/// Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance
pub struct Encryptor<A: Aead> {
    alg: A,
    nonce: NonceEncoder32,
}

/// AES-CMAC-SIV STREAM encryptor with 256-bit key size (128-bit security)
/// and a 64-bit (8-byte) nonce.
pub type Aes128SivEncryptor = Encryptor<Aes128SivAead>;

/// AES-CMAC-SIV STREAM encryptor with 512-bit key size (256-bit security)
/// and a 64-bit (8-byte) nonce.
pub type Aes256SivEncryptor = Encryptor<Aes256SivAead>;

/// AES-PMAC-SIV STREAM encryptor with 256-bit key size (128-bit security)
/// and a 64-bit (8-byte) nonce.
pub type Aes128PmacSivEncryptor = Encryptor<Aes128PmacSivAead>;

/// AES-PMAC-SIV STREAM encryptor with 512-bit key size (256-bit security)
/// and a 64-bit (8-byte) nonce.
pub type Aes256PmacSivEncryptor = Encryptor<Aes256PmacSivAead>;

impl<A: Aead> Encryptor<A> {
    /// Create a new STREAM encryptor, initialized with a given key and nonce.
    ///
    /// Panics if the key or nonce is the wrong size.
    pub fn new(key: &[u8], nonce: &[u8]) -> Self {
        Self {
            alg: A::new(key),
            nonce: NonceEncoder32::new(nonce),
        }
    }

    /// Encrypt the next message in the stream in-place
    pub fn encrypt_next_in_place(&mut self, ad: &[u8], buffer: &mut [u8]) {
        self.alg.encrypt_in_place(self.nonce.as_slice(), ad, buffer);
        self.nonce.increment();
    }

    /// Encrypt the final message in-place, consuming the stream encryptor
    pub fn encrypt_last_in_place(mut self, ad: &[u8], buffer: &mut [u8]) {
        self.alg.encrypt_in_place(&self.nonce.finish(), ad, buffer);
    }

    /// Encrypt the next message in the stream, allocating and returning a
    /// `Vec<u8>` for the ciphertext
    #[cfg(feature = "alloc")]
    pub fn encrypt_next(&mut self, ad: &[u8], plaintext: &[u8]) -> Vec<u8> {
        let ciphertext = self.alg.encrypt(self.nonce.as_slice(), ad, plaintext);
        self.nonce.increment();
        ciphertext
    }

    /// Encrypt the final message in the stream, allocating and returning a
    /// `Vec<u8>` for the ciphertext
    #[cfg(feature = "alloc")]
    pub fn encrypt_last(mut self, ad: &[u8], plaintext: &[u8]) -> Vec<u8> {
        self.alg.encrypt(&self.nonce.finish(), ad, plaintext)
    }
}

/// A STREAM decryptor with a 32-bit counter, generalized for any AEAD algorithm
///
/// This corresponds to the 𝒟 stream decryptor object as defined in the paper
/// Online Authenticated-Encryption and its Nonce-Reuse Misuse-Resistance
pub struct Decryptor<A: Aead> {
    alg: A,
    nonce: NonceEncoder32,
}

/// AES-CMAC-SIV STREAM decryptor with 256-bit key size (128-bit security)
/// and a 64-bit (8-byte) nonce.
pub type Aes128SivDecryptor = Decryptor<Aes128SivAead>;

/// AES-CMAC-SIV STREAM decryptor with 512-bit key size (256-bit security)
/// and a 64-bit (8-byte) nonce.
pub type Aes256SivDecryptor = Decryptor<Aes256SivAead>;

/// AES-PMAC-SIV STREAM decryptor with 256-bit key size (128-bit security)
/// and a 64-bit (8-byte) nonce.
pub type Aes128PmacSivDecryptor = Decryptor<Aes128PmacSivAead>;

/// AES-PMAC-SIV STREAM decryptor with 512-bit key size (256-bit security)
/// and a 64-bit (8-byte) nonce.
pub type Aes256PmacSivDecryptor = Decryptor<Aes256PmacSivAead>;

impl<A: Aead> Decryptor<A> {
    /// Create a new STREAM decryptor, initialized with a given key and nonce.
    ///
    /// Panics if the key or nonce is the wrong size.
    pub fn new(key: &[u8], nonce: &[u8]) -> Self {
        Self {
            alg: A::new(key),
            nonce: NonceEncoder32::new(nonce),
        }
    }

    /// Decrypt the next message in the stream in-place
    pub fn decrypt_next_in_place<'a>(
        &mut self,
        ad: &[u8],
        buffer: &'a mut [u8],
    ) -> Result<&'a [u8], Error> {
        let result = self
            .alg
            .decrypt_in_place(self.nonce.as_slice(), ad, buffer)?;
        self.nonce.increment();
        Ok(result)
    }

    /// Decrypt the final message in-place, consuming the stream decryptor
    pub fn decrypt_last_in_place<'a>(
        mut self,
        ad: &[u8],
        buffer: &'a mut [u8],
    ) -> Result<&'a [u8], Error> {
        self.alg.decrypt_in_place(&self.nonce.finish(), ad, buffer)
    }

    /// Decrypt the next message in the stream, allocating and returning a
    /// `Vec<u8>` for the plaintext
    #[cfg(feature = "alloc")]
    pub fn decrypt_next(&mut self, ad: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
        let plaintext = self.alg.decrypt(self.nonce.as_slice(), ad, ciphertext)?;
        self.nonce.increment();
        Ok(plaintext)
    }

    /// Decrypt the next message in the stream, allocating and returning a
    /// `Vec<u8>` for the plaintext
    #[cfg(feature = "alloc")]
    pub fn decrypt_last(mut self, ad: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
        self.alg.decrypt(&self.nonce.finish(), ad, ciphertext)
    }
}

/// STREAM nonce including space for 32-bit counter and 1-byte last block flag
type StreamNonce = [u8; NONCE_SIZE + 4 + 1];

/// Computes STREAM nonces based on the current position in the STREAM.
///
/// Accepts a 64-bit nonce and uses a 32-bit counter internally.
///
/// Panics if the nonce size is incorrect, 32-bit counter overflows
struct NonceEncoder32 {
    value: StreamNonce,
    counter: u32,
}

impl NonceEncoder32 {
    /// Create a new nonce encoder object
    fn new(prefix: &[u8]) -> Self {
        if prefix.len() != NONCE_SIZE {
            panic!(
                "incorrect nonce size (expected {}, got {})",
                NONCE_SIZE,
                prefix.len()
            );
        }

        let mut result = Self {
            value: Default::default(),
            counter: 0,
        };

        result.value[..NONCE_SIZE].copy_from_slice(prefix);
        result
    }

    /// Increment the nonce value in-place
    pub fn increment(&mut self) {
        self.counter = self
            .counter
            .checked_add(1)
            .expect("STREAM nonce counter overflowed");

        self.value[NONCE_SIZE..(NONCE_SIZE + 4)].copy_from_slice(&self.counter.to_be_bytes());
    }

    /// Borrow the current value as a slice
    pub fn as_slice(&self) -> &[u8] {
        &self.value
    }

    /// Compute the final nonce value, consuming self and returning the final
    /// nonce value.
    pub fn finish(mut self) -> StreamNonce {
        *self.value.iter_mut().last().unwrap() = LAST_BLOCK_FLAG;
        self.value
    }
}