1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Traits for AES-CTR.
16 use super::{AesBlock, AesKey, BLOCK_SIZE};
17 
18 /// The number of bytes used for the nonce, with the remaining bytes in a block used as the counter.
19 ///
20 /// Other lengths may be used, but 12 is a good general purpose choice.
21 pub const AES_CTR_NONCE_LEN: usize = 12;
22 
23 /// The nonce portion of the nonce+counter block used by CTR mode.
24 pub type AesCtrNonce = [u8; AES_CTR_NONCE_LEN];
25 
26 /// An implementation of AES-CTR.
27 ///
28 /// An AesCtr impl must only be used for encryption _or_ decryption, not both. Since CTR mode
29 /// is stateful, mixing encrypts and decrypts may advance the internal state in unexpected ways.
30 /// Create separate encrypt/decrypt instances if both operations are needed.
31 pub trait AesCtr {
32     /// The [AesKey] this cipher uses. See [super::Aes128Key] and [super::Aes256Key] for the common AES-128 and
33     /// AES-256 cases.
34     type Key: AesKey;
35 
36     /// Build a `Self` from key material.
new(key: &Self::Key, nonce_and_counter: NonceAndCounter) -> Self37     fn new(key: &Self::Key, nonce_and_counter: NonceAndCounter) -> Self;
38 
39     /// Applies the key stream to the data in place, advancing the counter state appropriately.
apply_keystream(&mut self, data: &mut [u8])40     fn apply_keystream(&mut self, data: &mut [u8]);
41 }
42 
43 /// The combined nonce and counter that CTR increments and encrypts to form the keystream.
44 pub struct NonceAndCounter {
45     block: AesBlock,
46 }
47 
48 impl NonceAndCounter {
49     /// Appends 4 zero bytes of counter to the nonce
from_nonce(nonce: AesCtrNonce) -> Self50     pub fn from_nonce(nonce: AesCtrNonce) -> Self {
51         let mut block = [0; BLOCK_SIZE];
52         block[..12].copy_from_slice(nonce.as_slice());
53         NonceAndCounter { block }
54     }
55 
56     /// Initialize from an already concatenated nonce and counter
57     // Not recommended for general use, so restricted so only test vectors can use it
58     #[cfg(feature = "test_vectors")]
from_block(block: AesBlock) -> Self59     pub fn from_block(block: AesBlock) -> Self {
60         Self { block }
61     }
62 
63     /// Nonce and counter as an AES block-sized byte array
as_block_array(&self) -> AesBlock64     pub fn as_block_array(&self) -> AesBlock {
65         self.block
66     }
67 }
68