Skip to content

Commit 29c68cd

Browse files
committed
fix: u64 -> u128 counter change
before the counter used to be an u64 which would produce different output whenever nonce plus counter should had affected the upper 64-bits as well. this fixes most of the code to use u128 as both nonce and counter and wrapping operations to match openssl aes-ctr-128.
1 parent c481367 commit 29c68cd

File tree

1 file changed

+16
-23
lines changed

1 file changed

+16
-23
lines changed

ctr/src/ctr128.rs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ where
3030
{
3131
cipher: C,
3232
block: Block<C>,
33-
nonce: [u64; 2],
34-
counter: u64,
33+
nonce: u128,
34+
counter: u128,
3535
pos: u8,
3636
}
3737

@@ -46,10 +46,11 @@ where
4646
fn from_block_cipher(cipher: C, nonce: &Nonce) -> Self {
4747
Self {
4848
cipher,
49-
nonce: [
50-
u64::from_be_bytes(nonce[..8].try_into().unwrap()),
51-
u64::from_be_bytes(nonce[8..].try_into().unwrap()),
52-
],
49+
nonce: u128::from_be_bytes(
50+
nonce[..]
51+
.try_into()
52+
.expect("nonce is 16 bytes, cannot fail"),
53+
),
5354
counter: 0,
5455
block: Default::default(),
5556
pos: 0,
@@ -89,7 +90,7 @@ where
8990
let mut chunks = data.chunks_exact_mut(bs * pb);
9091
for chunk in &mut chunks {
9192
let blocks = self.generate_par_blocks(counter);
92-
counter += pb as u64;
93+
counter += pb as u128;
9394
xor(chunk, to_slice::<C>(&blocks));
9495
}
9596
chunks.into_remainder()
@@ -141,14 +142,12 @@ where
141142
C::ParBlocks: ArrayLength<GenericArray<u8, U16>>,
142143
{
143144
#[inline(always)]
144-
fn generate_par_blocks(&self, counter: u64) -> ParBlocks<C> {
145-
let mut block = self.nonce;
146-
block[1] = block[1].wrapping_add(counter);
145+
fn generate_par_blocks(&self, counter: u128) -> ParBlocks<C> {
146+
let mut block = self.nonce.wrapping_add(counter);
147147
let mut blocks: ParBlocks<C> = unsafe { mem::zeroed() };
148148
for b in blocks.iter_mut() {
149-
let block_be = conv_be(block);
150-
*b = unsafe { mem::transmute_copy(&block_be) };
151-
block[1] = block[1].wrapping_add(1);
149+
*b = unsafe { mem::transmute_copy(&block.to_be()) };
150+
block = block.wrapping_add(1);
152151
}
153152

154153
self.cipher.encrypt_blocks(&mut blocks);
@@ -157,10 +156,9 @@ where
157156
}
158157

159158
#[inline(always)]
160-
fn generate_block(&self, counter: u64) -> Block<C> {
161-
let mut block = self.nonce;
162-
block[1] = block[1].wrapping_add(counter);
163-
let mut block: Block<C> = unsafe { mem::transmute(conv_be(block)) };
159+
fn generate_block(&self, counter: u128) -> Block<C> {
160+
let block = self.nonce.wrapping_add(counter);
161+
let mut block: Block<C> = unsafe { mem::transmute(block.to_be()) };
164162
self.cipher.encrypt_block(&mut block);
165163
block
166164
}
@@ -173,7 +171,7 @@ where
173171
}
174172
let blocks = 1 + (data.len() - leftover_bytes) / bs;
175173
self.counter
176-
.checked_add(blocks as u64)
174+
.checked_add(blocks as u128)
177175
.ok_or(LoopError)
178176
.map(|_| ())
179177
}
@@ -189,11 +187,6 @@ where
189187
}
190188
}
191189

192-
#[inline(always)]
193-
fn conv_be(val: [u64; 2]) -> [u64; 2] {
194-
[val[0].to_be(), val[1].to_be()]
195-
}
196-
197190
#[inline(always)]
198191
fn to_slice<C: BlockCipher>(blocks: &ParBlocks<C>) -> &[u8] {
199192
let blocks_len = C::BlockSize::to_usize() * C::ParBlocks::to_usize();

0 commit comments

Comments
 (0)