Skip to content

Commit

Permalink
ctr: impl FromBlockCipher
Browse files Browse the repository at this point in the history
Impls the new `FromBlockCipher` trait introduced in:

RustCrypto/traits#164
  • Loading branch information
tarcieri committed Jun 3, 2020
1 parent 1e50e14 commit d3f34c6
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 67 deletions.
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions ctr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ readme = "README.md"
edition = "2018"

[dependencies]
stream-cipher = { version = "= 0.4.0-pre", git = "https://github.com/RustCrypto/traits" }
block-cipher = "0.7.0-pre"
stream-cipher = { version = "= 0.4.0-pre", features = ["block-cipher"] }

[dev-dependencies]
aes = { version = "= 0.4.0-pre", git = "https://github.com/RustCrypto/block-ciphers" }
stream-cipher = { version = "= 0.4.0-pre", features = ["dev"], git = "https://github.com/RustCrypto/traits" }
aes = "= 0.4.0-pre"
stream-cipher = { version = "= 0.4.0-pre", features = ["dev"] }
blobby = "0.1"
80 changes: 26 additions & 54 deletions ctr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,13 @@

pub use stream_cipher;

use stream_cipher::{
InvalidKeyNonceLength, LoopError, NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek,
use core::{cmp, convert::TryInto, fmt, mem};
use stream_cipher::block_cipher::{BlockCipher, NewBlockCipher};
use stream_cipher::generic_array::{
typenum::{Unsigned, U16},
ArrayLength, GenericArray,
};

use block_cipher::generic_array::typenum::{Unsigned, U16};
use block_cipher::generic_array::{ArrayLength, GenericArray};
use block_cipher::{BlockCipher, NewBlockCipher};
use core::{cmp, fmt, mem, ptr};
use stream_cipher::{FromBlockCipher, LoopError, SyncStreamCipher, SyncStreamCipherSeek};

#[inline(always)]
fn xor(buf: &mut [u8], key: &[u8]) {
Expand All @@ -60,7 +59,7 @@ fn xor(buf: &mut [u8], key: &[u8]) {

type Block<C> = GenericArray<u8, <C as BlockCipher>::BlockSize>;
type Blocks<C> = GenericArray<Block<C>, <C as BlockCipher>::ParBlocks>;
type Nonce<C> = GenericArray<u8, <C as NewStreamCipher>::NonceSize>;
type Nonce = GenericArray<u8, U16>;

/// CTR mode of operation for 128-bit block ciphers
pub struct Ctr128<C>
Expand All @@ -75,65 +74,27 @@ where
pos: Option<u8>,
}

impl<C> Ctr128<C>
impl<C> FromBlockCipher for Ctr128<C>
where
C: BlockCipher<BlockSize = U16>,
C: BlockCipher<BlockSize = U16> + NewBlockCipher,
C::ParBlocks: ArrayLength<GenericArray<u8, U16>>,
{
/// 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);
}
type BlockCipher = C;

fn from_block_cipher(cipher: C, nonce: &Nonce) -> Self {
Self {
cipher,
nonce: conv_be(n),
nonce: [
u64::from_be_bytes(nonce[..8].try_into().unwrap()),
u64::from_be_bytes(nonce[8..].try_into().unwrap()),
],
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();
unsafe { core::slice::from_raw_parts(blocks.as_ptr() as *const u8, blocks_len) }
}

impl<C> NewStreamCipher for Ctr128<C>
where
C: BlockCipher<BlockSize = U16> + NewBlockCipher,
C::ParBlocks: ArrayLength<GenericArray<u8, U16>>,
{
type KeySize = C::KeySize;
type NonceSize = C::BlockSize;

fn new(key: &GenericArray<u8, Self::KeySize>, nonce: &Nonce<Self>) -> Self {
let cipher = C::new(key);
Self::from_cipher(cipher, nonce)
}

fn new_var(key: &[u8], nonce: &[u8]) -> Result<Self, InvalidKeyNonceLength> {
let nonce = if Self::NonceSize::to_usize() != nonce.len() {
Err(InvalidKeyNonceLength)?
} else {
GenericArray::from_slice(nonce)
};
let cipher = C::new_varkey(key).map_err(|_| InvalidKeyNonceLength)?;
Ok(Self::from_cipher(cipher, nonce))
}
}

impl<C> SyncStreamCipher for Ctr128<C>
where
C: BlockCipher<BlockSize = U16>,
Expand Down Expand Up @@ -290,3 +251,14 @@ where
write!(f, "Ctr128 {{ .. }}")
}
}

#[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();
unsafe { core::slice::from_raw_parts(blocks.as_ptr() as *const u8, blocks_len) }
}
5 changes: 2 additions & 3 deletions ctr/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use aes::block_cipher::generic_array::GenericArray;
use aes::block_cipher::NewBlockCipher;
use stream_cipher::SyncStreamCipher;
use stream_cipher::{new_seek_test, new_sync_test};
use stream_cipher::{new_seek_test, new_sync_test, FromBlockCipher, SyncStreamCipher};

type Aes128Ctr = ctr::Ctr128<aes::Aes128>;
type Aes256Ctr = ctr::Ctr128<aes::Aes256>;
Expand All @@ -21,7 +20,7 @@ fn test_from_cipher() {
let ciphertext = row[3];

let block_cipher = aes::Aes128::new_varkey(key).unwrap();
let mut cipher = ctr::Ctr128::from_cipher(block_cipher, iv);
let mut cipher = ctr::Ctr128::from_block_cipher(block_cipher, iv);

let mut buf = plaintext.to_vec();
cipher.apply_keystream(&mut buf);
Expand Down

0 comments on commit d3f34c6

Please sign in to comment.