Skip to content

Commit

Permalink
Upgrade to stream-cipher v0.7 (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov committed Aug 25, 2020
1 parent 4d9a1ad commit dec7d26
Show file tree
Hide file tree
Showing 30 changed files with 273 additions and 302 deletions.
18 changes: 14 additions & 4 deletions Cargo.lock

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

5 changes: 3 additions & 2 deletions aes-ctr/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.5.0 (2020-08-14)
## 0.5.0 (2020-08-25)
### Changed
- Bump `stream-cipher` dependency to v0.6, implement the `FromBlockCipher` trait ([#161])
- Bump `stream-cipher` dependency to v0.7, implement the `FromBlockCipher` trait ([#161], [#164])

[#161]: https://github.com/RustCrypto/stream-ciphers/pull/161
[#164]: https://github.com/RustCrypto/stream-ciphers/pull/164

## 0.4.0 (2020-06-08)
### Changed
Expand Down
6 changes: 3 additions & 3 deletions aes-ctr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ readme = "README.md"
edition = "2018"

[dependencies]
stream-cipher = "0.6"
stream-cipher = "0.7"

[target.'cfg(not(all(target_feature = "aes", target_feature = "sse2", target_feature = "ssse3", any(target_arch = "x86_64", target_arch = "x86"))))'.dependencies]
ctr = { version = "0.5", path = "../ctr" }
aes-soft = "0.5"

[target.'cfg(all(target_feature = "aes", target_feature = "sse2", target_feature = "ssse3", any(target_arch = "x86_64", target_arch = "x86")))'.dependencies]
aesni = "0.8"
aesni = "0.9"

[dev-dependencies]
stream-cipher = { version = "0.6", features = ["dev"] }
stream-cipher = { version = "0.7", features = ["dev"] }
4 changes: 2 additions & 2 deletions aes-ctr/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ use aes_ctr::{Aes128Ctr, Aes256Ctr};
use stream_cipher::{new_seek_test, new_sync_test};

new_sync_test!(aes128_ctr_core, Aes128Ctr, "aes128-ctr");
new_seek_test!(aes128_ctr_seek, Aes128Ctr, "aes128-ctr");
new_sync_test!(aes256_ctr_core, Aes256Ctr, "aes256-ctr");
new_seek_test!(aes256_ctr_seek, Aes256Ctr, "aes256-ctr");
new_seek_test!(aes128_ctr_seek, Aes128Ctr);
new_seek_test!(aes256_ctr_seek, Aes256Ctr);
5 changes: 3 additions & 2 deletions cfb-mode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.5.0 (2020-08-14)
## 0.5.0 (2020-08-25)
### Changed
- Bump `stream-cipher` dependency to v0.6, implement the `FromBlockCipher` trait ([#161])
- Bump `stream-cipher` dependency to v0.7, implement the `FromBlockCipher` trait ([#161], [#164])

[#161]: https://github.com/RustCrypto/stream-ciphers/pull/161
[#164]: https://github.com/RustCrypto/stream-ciphers/pull/164

## 0.4.0 (2020-06-08)
### Changed
Expand Down
4 changes: 2 additions & 2 deletions cfb-mode/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ readme = "README.md"
edition = "2018"

[dependencies]
stream-cipher = { version = "0.6", features = ["block-cipher"] }
stream-cipher = { version = "0.7", features = ["block-cipher"] }

[dev-dependencies]
aes = "0.5"
stream-cipher = { version = "0.6", features = ["dev"] }
stream-cipher = { version = "0.7", features = ["dev"] }
hex-literal = "0.2"
5 changes: 3 additions & 2 deletions cfb8/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.5.0 (2020-08-14)
## 0.5.0 (2020-08-25)
### Changed
- Bump `stream-cipher` dependency to v0.6, implement the `FromBlockCipher` trait ([#161])
- Bump `stream-cipher` dependency to v0.7, implement the `FromBlockCipher` trait ([#161], [#164])

[#161]: https://github.com/RustCrypto/stream-ciphers/pull/161
[#164]: https://github.com/RustCrypto/stream-ciphers/pull/164

## 0.4.0 (2020-06-08)
### Changed
Expand Down
4 changes: 2 additions & 2 deletions cfb8/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ readme = "README.md"
edition = "2018"

[dependencies]
stream-cipher = { version = "0.6", features = ["block-cipher"] }
stream-cipher = { version = "0.7", features = ["block-cipher"] }

[dev-dependencies]
aes = "0.5"
stream-cipher = { version = "0.6", features = ["dev"] }
stream-cipher = { version = "0.7", features = ["dev"] }
hex-literal = "0.2"
5 changes: 3 additions & 2 deletions chacha20/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.5.0 (2020-08-14)
## 0.5.0 (2020-08-25)
### Changed
- Bump `stream-cipher` dependency to v0.6 ([#161])
- Bump `stream-cipher` dependency to v0.7 ([#161], [#164])

[#161]: https://github.com/RustCrypto/stream-ciphers/pull/161
[#164]: https://github.com/RustCrypto/stream-ciphers/pull/164

## 0.4.3 (2020-06-11)
### Changed
Expand Down
4 changes: 2 additions & 2 deletions chacha20/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ edition = "2018"

[dependencies]
rand_core = { version = "0.5", optional = true, default-features = false }
stream-cipher = { version = "0.6", optional = true }
stream-cipher = { version = "0.7", optional = true }
zeroize = { version = "1", optional = true, default-features = false }

[dev-dependencies]
stream-cipher = { version = "0.6", features = ["dev"] }
stream-cipher = { version = "0.7", features = ["dev"] }
hex-literal = "0.2"

[features]
Expand Down
118 changes: 52 additions & 66 deletions chacha20/src/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ use crate::{
BLOCK_SIZE, MAX_BLOCKS,
};
use core::{
cmp,
convert::TryInto,
fmt::{self, Debug},
};
use stream_cipher::consts::{U12, U32};
use stream_cipher::{LoopError, NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek};
use stream_cipher::{
consts::{U12, U32},
LoopError, NewStreamCipher, OverflowError, SeekNum, SyncStreamCipher, SyncStreamCipherSeek,
};

/// ChaCha8 stream cipher (reduced-round variant of ChaCha20 with 8 rounds)
pub type ChaCha8 = Cipher<R8>;
Expand Down Expand Up @@ -61,7 +62,7 @@ pub struct Cipher<R: Rounds> {
buffer: Buffer,

/// Position within buffer, or `None` if the buffer is not in use
buffer_pos: Option<u8>,
buffer_pos: u8,

/// Current counter value relative to the start of the keystream
counter: u64,
Expand Down Expand Up @@ -93,7 +94,7 @@ impl<R: Rounds> NewStreamCipher for Cipher<R> {
Self {
block,
buffer: [0u8; BUFFER_SIZE],
buffer_pos: None,
buffer_pos: 0,
counter: 0,
counter_offset,
}
Expand All @@ -103,98 +104,83 @@ impl<R: Rounds> NewStreamCipher for Cipher<R> {
impl<R: Rounds> SyncStreamCipher for Cipher<R> {
fn try_apply_keystream(&mut self, mut data: &mut [u8]) -> Result<(), LoopError> {
self.check_data_len(data)?;
let pos = self.buffer_pos as usize;

let mut counter = self.counter;
// xor with leftover bytes from the last call if any
if let Some(pos) = self.buffer_pos {
let pos = pos as usize;

if data.len() >= BUFFER_SIZE - pos {
let buf = &self.buffer[pos..];
let (r, l) = data.split_at_mut(buf.len());
data = l;
xor(r, buf);
self.buffer_pos = None;
} else {
let buf = &self.buffer[pos..pos.checked_add(data.len()).unwrap()];
xor(data, buf);
self.buffer_pos = Some(pos.checked_add(data.len()).unwrap() as u8);
if pos != 0 {
if data.len() < BUFFER_SIZE - pos {
let n = pos + data.len();
xor(data, &self.buffer[pos..n]);
self.buffer_pos = n as u8;
return Ok(());
} else {
let (l, r) = data.split_at_mut(BUFFER_SIZE - pos);
data = r;
xor(l, &self.buffer[pos..]);
counter = counter.checked_add(COUNTER_INCR).unwrap();
}
}

let mut counter = self.counter;

while data.len() >= BUFFER_SIZE {
let (l, r) = { data }.split_at_mut(BUFFER_SIZE);
data = r;

let mut chunks = data.chunks_exact_mut(BUFFER_SIZE);
for chunk in &mut chunks {
// TODO(tarcieri): double check this should be checked and not wrapping
let counter_with_offset = self.counter_offset.checked_add(counter).unwrap();
self.block.apply_keystream(counter_with_offset, l);

self.block.apply_keystream(counter_with_offset, chunk);
counter = counter.checked_add(COUNTER_INCR).unwrap();
}

if !data.is_empty() {
let rem = chunks.into_remainder();
self.buffer_pos = rem.len() as u8;
self.counter = counter;
if !rem.is_empty() {
self.generate_block(counter);
counter = counter.checked_add(COUNTER_INCR).unwrap();
let n = data.len();
xor(data, &self.buffer[..n]);
self.buffer_pos = Some(n as u8);
xor(rem, &self.buffer[..rem.len()]);
}

self.counter = counter;

Ok(())
}
}

impl<R: Rounds> SyncStreamCipherSeek for Cipher<R> {
fn current_pos(&self) -> u64 {
let bs = BLOCK_SIZE as u64;

if let Some(pos) = self.buffer_pos {
(self.counter.wrapping_sub(1) * bs)
.checked_add(u64::from(pos))
.unwrap()
fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError> {
// quick and dirty fix, until ctr-like parallel block processing will be added
let (counter, pos) = if self.buffer_pos < BLOCK_SIZE as u8 {
(self.counter, self.buffer_pos)
} else {
self.counter * bs
}
(
self.counter.checked_add(1).ok_or(OverflowError)?,
self.buffer_pos - BLOCK_SIZE as u8,
)
};
T::from_block_byte(counter, pos, BLOCK_SIZE as u8)
}

fn seek(&mut self, pos: u64) {
let bs = BLOCK_SIZE as u64;
self.counter = pos / bs;
let rem = pos % bs;

if rem == 0 {
self.buffer_pos = None;
} else {
fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError> {
let res = pos.to_block_byte(BLOCK_SIZE as u8)?;
self.counter = res.0;
self.buffer_pos = res.1;
if self.buffer_pos != 0 {
self.generate_block(self.counter);
self.counter = self.counter.checked_add(COUNTER_INCR).unwrap();
self.buffer_pos = Some(rem as u8);
}
Ok(())
}
}

impl<R: Rounds> Cipher<R> {
/// Check data length
fn check_data_len(&self, data: &[u8]) -> Result<(), LoopError> {
let dlen = data.len()
- self
.buffer_pos
.map(|pos| cmp::min(BUFFER_SIZE - pos as usize, data.len()))
.unwrap_or_default();

let data_blocks = dlen / BLOCK_SIZE + if data.len() % BLOCK_SIZE != 0 { 1 } else { 0 };

if let Some(new_counter) = self.counter.checked_add(data_blocks as u64) {
if new_counter <= MAX_BLOCKS as u64 {
return Ok(());
}
let leftover_bytes = BUFFER_SIZE - self.buffer_pos as usize;
if data.len() < leftover_bytes {
return Ok(());
}
let blocks = 1 + (data.len() - leftover_bytes) / BLOCK_SIZE;
let res = self.counter.checked_add(blocks as u64).ok_or(LoopError)?;
if res <= MAX_BLOCKS as u64 {
Ok(())
} else {
Err(LoopError)
}

Err(LoopError)
}

/// Generate a block, storing it in the internal buffer
Expand Down
14 changes: 8 additions & 6 deletions chacha20/src/legacy.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Legacy version of ChaCha20 with a 64-bit nonce

use crate::cipher::{ChaCha20, Key};
use stream_cipher::consts::{U32, U8};
use stream_cipher::{LoopError, NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek};
use stream_cipher::{
consts::{U32, U8},
LoopError, NewStreamCipher, OverflowError, SeekNum, SyncStreamCipher, SyncStreamCipherSeek,
};

/// Size of the nonce for the legacy ChaCha20 stream cipher
#[cfg_attr(docsrs, doc(cfg(feature = "legacy")))]
Expand Down Expand Up @@ -35,11 +37,11 @@ impl SyncStreamCipher for ChaCha20Legacy {
}

impl SyncStreamCipherSeek for ChaCha20Legacy {
fn current_pos(&self) -> u64 {
self.0.current_pos()
fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError> {
self.0.try_current_pos()
}

fn seek(&mut self, pos: u64) {
self.0.seek(pos);
fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError> {
self.0.try_seek(pos)
}
}
Loading

0 comments on commit dec7d26

Please sign in to comment.