Skip to content

Commit

Permalink
ctr fix u64 counter to u128
Browse files Browse the repository at this point in the history
  • Loading branch information
Joonas Koivunen committed Dec 11, 2019
1 parent 1235638 commit 05d19d4
Showing 1 changed file with 19 additions and 27 deletions.
46 changes: 19 additions & 27 deletions ctr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use stream_cipher::{
use block_cipher_trait::generic_array::typenum::{Unsigned, U16};
use block_cipher_trait::generic_array::{ArrayLength, GenericArray};
use block_cipher_trait::BlockCipher;
use core::{cmp, fmt, mem, ptr};
use core::{cmp, convert::TryInto, fmt, mem};

#[inline(always)]
fn xor(buf: &mut [u8], key: &[u8]) {
Expand All @@ -70,8 +70,8 @@ where
C::ParBlocks: ArrayLength<GenericArray<u8, U16>>,
{
cipher: C,
nonce: [u64; 2],
counter: u64,
nonce: u128,
counter: u128,
block: Block<C>,
pos: Option<u8>,
}
Expand All @@ -83,28 +83,18 @@ where
{
/// Create new CTR mode instance using initialized block cipher.
pub fn from_cipher(cipher: C, nonce: &GenericArray<u8, U16>) -> Self {
let mut n = [0u64; 2];

// TODO: replace with `u64::from_be_bytes` in libcore (1.32+)
unsafe {
ptr::copy_nonoverlapping(nonce.as_ptr(), n.as_mut_ptr() as *mut u8, 16);
}
let nonce = u128::from_be_bytes(nonce.as_slice().try_into().unwrap());

Self {
cipher,
nonce: conv_be(n),
nonce,
counter: 0,
block: Default::default(),
pos: None,
}
}
}

#[inline(always)]
fn conv_be(val: [u64; 2]) -> [u64; 2] {
[val[0].to_be(), val[1].to_be()]
}

#[inline(always)]
fn to_slice<C: BlockCipher>(blocks: &Blocks<C>) -> &[u8] {
let blocks_len = C::BlockSize::to_usize() * C::ParBlocks::to_usize();
Expand Down Expand Up @@ -168,7 +158,7 @@ where
let (l, r) = { data }.split_at_mut(pbs);
data = r;
let blocks = self.generate_par_blocks(counter);
counter += Self::par_blocks();
counter += Self::par_blocks() as u128;
xor(l, to_slice::<C>(&blocks));
}
self.counter = counter;
Expand Down Expand Up @@ -203,16 +193,18 @@ where
C::ParBlocks: ArrayLength<GenericArray<u8, U16>>,
{
fn current_pos(&self) -> u64 {
let bs = Self::block_size() as u64;
let bs = Self::block_size() as u128;
match self.pos {
Some(pos) => self.counter.wrapping_sub(1) * bs + u64::from(pos),
Some(pos) => self.counter.wrapping_sub(1) * bs + u128::from(pos),
None => self.counter * bs,
}
.try_into()
.unwrap()
}

fn seek(&mut self, pos: u64) {
let bs = Self::block_size() as u64;
self.counter = pos / bs;
self.counter = (pos / bs) as u128;
let l = (pos % bs) as u16;
if l == 0 {
self.pos = None;
Expand All @@ -230,14 +222,14 @@ where
C::ParBlocks: ArrayLength<GenericArray<u8, U16>>,
{
#[inline(always)]
fn generate_par_blocks(&self, counter: u64) -> Blocks<C> {
fn generate_par_blocks(&self, counter: u128) -> Blocks<C> {
let mut block = self.nonce;
block[1] = block[1].wrapping_add(counter);
block = block.wrapping_add(counter);
let mut blocks: Blocks<C> = unsafe { mem::zeroed() };
for b in blocks.iter_mut() {
let block_be = conv_be(block);
let block_be = block.to_be();
*b = unsafe { mem::transmute_copy(&block_be) };
block[1] = block[1].wrapping_add(1);
block = block.wrapping_add(1);
}

self.cipher.encrypt_blocks(&mut blocks);
Expand All @@ -246,10 +238,10 @@ where
}

#[inline(always)]
fn generate_block(&self, counter: u64) -> Block<C> {
fn generate_block(&self, counter: u128) -> Block<C> {
let mut block = self.nonce;
block[1] = block[1].wrapping_add(counter);
let mut block: Block<C> = unsafe { mem::transmute(conv_be(block)) };
block = block.wrapping_add(counter);
let mut block: Block<C> = unsafe { mem::transmute(block.to_be()) };
self.cipher.encrypt_block(&mut block);
block
}
Expand All @@ -274,7 +266,7 @@ where
None => 0,
};
let data_blocks = dlen / bs + if data.len() % bs != 0 { 1 } else { 0 };
if self.counter.checked_add(data_blocks as u64).is_some() {
if self.counter.checked_add(data_blocks as u128).is_some() {
Ok(())
} else {
Err(LoopError)
Expand Down

0 comments on commit 05d19d4

Please sign in to comment.