Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split up salsa20-family crate into salsa20-core, salsa20 and chacha20 #16

Merged
merged 5 commits into from
Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ members = [
"aes-ctr",
"cfb8",
"cfb-mode",
"chacha20",
"ctr",
"ofb",
"salsa20-family"
"salsa20",
"salsa20-core",
]
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ Crates have not yet received any formal cryptographic and security reviews.
| `aes-ctr` | [![crates.io](https://img.shields.io/crates/v/aes-ctr.svg)](https://crates.io/crates/aes-ctr) | [![Documentation](https://docs.rs/aes-ctr/badge.svg)](https://docs.rs/aes-ctr) |
| `cfb-mode` | [![crates.io](https://img.shields.io/crates/v/cfb-mode.svg)](https://crates.io/crates/cfb-mode) | [![Documentation](https://docs.rs/cfb-mode/badge.svg)](https://docs.rs/cfb-mode) |
| `cfb8` | [![crates.io](https://img.shields.io/crates/v/cfb8.svg)](https://crates.io/crates/cfb8) | [![Documentation](https://docs.rs/cfb8/badge.svg)](https://docs.rs/cfb8) |
| `chacha20` | [![crates.io](https://img.shields.io/crates/v/chacha20.svg)](https://crates.io/crates/chacha20) | [![Documentation](https://docs.rs/chacha20/badge.svg)](https://docs.rs/chacha20) |
| `ctr` | [![crates.io](https://img.shields.io/crates/v/ctr.svg)](https://crates.io/crates/ctr) | [![Documentation](https://docs.rs/ctr/badge.svg)](https://docs.rs/ctr) |
| `ofb` | [![crates.io](https://img.shields.io/crates/v/ofb.svg)](https://crates.io/crates/ofb) | [![Documentation](https://docs.rs/ofb/badge.svg)](https://docs.rs/ofb) |
| `salsa20` | [![crates.io](https://img.shields.io/crates/v/salsa20.svg)](https://crates.io/crates/salsa20) | [![Documentation](https://docs.rs/salsa20/badge.svg)](https://docs.rs/salsa20) |
| `salsa20-core` | [![crates.io](https://img.shields.io/crates/v/salsa20-core.svg)](https://crates.io/crates/salsa20-core) | [![Documentation](https://docs.rs/salsa20-core/badge.svg)](https://docs.rs/salsa20-core) |


### Minimum Rust version
Expand Down
22 changes: 22 additions & 0 deletions chacha20/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "chacha20"
version = "0.1.0"
authors = ["RustCrypto Developers"]
license = "MIT OR Apache-2.0"
description = "Chacha20 Stream Cipher"
repository = "https://github.com/RustCrypto/stream-ciphers"
keywords = ["crypto", "stream-cipher", "trait"]
categories = ["cryptography", "no-std"]

[dependencies]
block-cipher-trait = "0.6"
stream-cipher = "0.3"
salsa20-core = { path = "../salsa20-core" }
sseemayer marked this conversation as resolved.
Show resolved Hide resolved
zeroize = { version = "0.9", optional = true }

[dev-dependencies]
stream-cipher = { version = "0.3", features = ["dev"] }
block-cipher-trait = { version = "0.6", features = ["dev"] }

[badges]
travis-ci = { repository = "RustCrypto/stream-ciphers" }
File renamed without changes.
File renamed without changes.
39 changes: 22 additions & 17 deletions salsa20-family/src/chacha.rs → chacha20/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
#![no_std]
extern crate block_cipher_trait;
extern crate salsa20_core;
extern crate stream_cipher;

#[cfg(cargo_feature = "zeroize")]
extern crate zeroize;

use block_cipher_trait::generic_array::typenum::{U32, U8};
use block_cipher_trait::generic_array::GenericArray;
use block_cipher_trait::generic_array::typenum::U8;
use block_cipher_trait::generic_array::typenum::U32;
use stream_cipher::NewStreamCipher;
use stream_cipher::StreamCipher;
use stream_cipher::SyncStreamCipherSeek;
use stream_cipher::{NewStreamCipher, StreamCipher, SyncStreamCipherSeek};

#[cfg(cargo_feature = "zeroize")]
use zeroize::Zeroize;

use salsa_family_state::SalsaFamilyState;
use salsa_family_state::SalsaFamilyCipher;
use salsa20_core::{SalsaFamilyCipher, SalsaFamilyState};

/// Wrapper for state for ChaCha-type ciphers.
struct ChaChaState {
state: SalsaFamilyState
state: SalsaFamilyState,
}

/// The ChaCha20 cipher.
pub struct ChaCha20 {
state: ChaChaState
state: ChaChaState,
}

#[inline]
fn quarter_round(a: usize, b: usize, c: usize, d: usize,
block: &mut [u32; 16]) {
fn quarter_round(a: usize, b: usize, c: usize, d: usize, block: &mut [u32; 16]) {
block[a] = block[a].wrapping_add(block[b]);
block[d] ^= block[a];
block[d] = block[d].rotate_left(16);
Expand Down Expand Up @@ -136,9 +139,10 @@ impl NewStreamCipher for ChaChaState {
/// Nonce size in bytes
type NonceSize = U8;

fn new(key: &GenericArray<u8, Self::KeySize>,
iv: &GenericArray<u8, Self::NonceSize>) -> Self {
ChaChaState { state: SalsaFamilyState::new(key, iv) }
fn new(key: &GenericArray<u8, Self::KeySize>, iv: &GenericArray<u8, Self::NonceSize>) -> Self {
ChaChaState {
state: SalsaFamilyState::new(key, iv),
}
}
}

Expand Down Expand Up @@ -188,9 +192,10 @@ impl NewStreamCipher for ChaCha20 {
/// Nonce size in bytes
type NonceSize = U8;

fn new(key: &GenericArray<u8, Self::KeySize>,
iv: &GenericArray<u8, Self::NonceSize>) -> Self {
let mut out = ChaCha20 { state: ChaChaState::new(key, iv) };
fn new(key: &GenericArray<u8, Self::KeySize>, iv: &GenericArray<u8, Self::NonceSize>) -> Self {
let mut out = ChaCha20 {
state: ChaChaState::new(key, iv),
};

out.gen_block();

Expand Down
187 changes: 187 additions & 0 deletions chacha20/tests/chacha20.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
extern crate block_cipher_trait;
extern crate chacha20;
extern crate stream_cipher;

use block_cipher_trait::generic_array::GenericArray;
use chacha20::ChaCha20;
use stream_cipher::NewStreamCipher;
use stream_cipher::StreamCipher;
use stream_cipher::SyncStreamCipherSeek;

#[cfg(test)]
const KEY_BYTES: usize = 32;

#[cfg(test)]
const IV_BYTES: usize = 8;

#[cfg(test)]
const IETF_KEY0: [u8; KEY_BYTES] = [0; KEY_BYTES];

#[cfg(test)]
const IETF_KEY1: [u8; KEY_BYTES] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
];

#[cfg(test)]
const KEY_LONG: [u8; KEY_BYTES] = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32,
];

#[cfg(test)]
const IETF_IV0: [u8; IV_BYTES] = [0; IV_BYTES];

#[cfg(test)]
const IETF_IV1: [u8; IV_BYTES] = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];

#[cfg(test)]
const IETF_IVHI: [u8; IV_BYTES] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01];

#[cfg(test)]
const IV_LONG: [u8; IV_BYTES] = [3, 1, 4, 1, 5, 9, 2, 6];

#[cfg(test)]
const EXPECTED_IETF_KEY0_IV0: [u8; 64] = [
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
];

#[cfg(test)]
const EXPECTED_IETF_KEY1_IV0: [u8; 64] = [
0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96, 0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60, 0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2, 0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81, 0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
];

#[cfg(test)]
const EXPECTED_IETF_KEY0_IV1: [u8; 64] = [
0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c, 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d, 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
];

#[cfg(test)]
const EXPECTED_IETF_KEY0_IVHI: [u8; 60] = [
0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5, 0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13, 0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45, 0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e, 0x44, 0x5f, 0x41, 0xe3,
];

#[cfg(test)]
const EXPECTED_LONG: [u8; 256] = [
0xde, 0xeb, 0x6b, 0x9d, 0x06, 0xdf, 0xf3, 0xe0, 0x91, 0xbf, 0x3a, 0xd4, 0xf4, 0xd4, 0x92, 0xb6,
0xdd, 0x98, 0x24, 0x6f, 0x69, 0x69, 0x18, 0x02, 0xe4, 0x66, 0xe0, 0x3b, 0xad, 0x23, 0x57, 0x87,
0x0f, 0x1c, 0x6c, 0x01, 0x0b, 0x6c, 0x2e, 0x65, 0x0c, 0x4b, 0xf5, 0x8d, 0x2d, 0x35, 0xc7, 0x2a,
0xb6, 0x39, 0x43, 0x70, 0x69, 0xa3, 0x84, 0xe0, 0x31, 0x00, 0x07, 0x8c, 0xc1, 0xd7, 0x35, 0xa0,
0xdb, 0x4e, 0x8f, 0x47, 0x4e, 0xe6, 0x29, 0x14, 0x60, 0xfd, 0x91, 0x97, 0xc7, 0x7e, 0xd8, 0x7b,
0x4c, 0x64, 0xe0, 0xd9, 0xac, 0x68, 0x5b, 0xd1, 0xc5, 0x6c, 0xce, 0x02, 0x1f, 0x38, 0x19, 0xcd,
0x13, 0xf4, 0x9c, 0x9a, 0x30, 0x53, 0x60, 0x36, 0x02, 0x58, 0x2a, 0x06, 0x0e, 0x59, 0xc2, 0xfb,
0xee, 0x90, 0xab, 0x0b, 0xf7, 0xbb, 0x10, 0x2d, 0x81, 0x9c, 0xed, 0x03, 0x96, 0x9d, 0x3b, 0xae,
0x71, 0x03, 0x4f, 0xe5, 0x98, 0x24, 0x65, 0x83, 0x33, 0x6a, 0xa7, 0x44, 0xd8, 0x16, 0x8e, 0x5d,
0xff, 0xf5, 0xc6, 0xd1, 0x02, 0x70, 0xf1, 0x25, 0xa4, 0x13, 0x0e, 0x71, 0x97, 0x17, 0xe7, 0x83,
0xc0, 0x85, 0x8b, 0x6f, 0x79, 0x64, 0x43, 0x71, 0x73, 0xea, 0x1d, 0x75, 0x56, 0xc1, 0x58, 0xbc,
0x7a, 0x99, 0xe7, 0x4a, 0x34, 0xd9, 0x3d, 0xa6, 0xbf, 0x72, 0xac, 0x97, 0x36, 0xa2, 0x15, 0xac,
0xae, 0xfd, 0x4e, 0xc0, 0x31, 0xf3, 0xf1, 0x3f, 0x09, 0x9e, 0x3d, 0x81, 0x1d, 0x83, 0xa2, 0xcf,
0x1d, 0x54, 0x4a, 0x68, 0xd2, 0x75, 0x24, 0x09, 0xcc, 0x6b, 0xe8, 0x52, 0xb0, 0x51, 0x1a, 0x2e,
0x32, 0xf6, 0x9a, 0xa0, 0xbe, 0x91, 0xb3, 0x09, 0x81, 0x58, 0x4a, 0x1c, 0x56, 0xce, 0x75, 0x46,
0xcc, 0xa2, 0x4d, 0x8c, 0xfd, 0xfc, 0xa5, 0x25, 0xd6, 0xb1, 0x5e, 0xea, 0x83, 0xb6, 0xb6, 0x86,
];

#[test]
fn chacha20_ietf_key0_iv0() {
let mut cipher = ChaCha20::new(
&GenericArray::from(IETF_KEY0),
&GenericArray::from(IETF_IV0),
);
let mut buf = [0; 64];

cipher.encrypt(&mut buf);

for i in 0..64 {
assert_eq!(buf[i], EXPECTED_IETF_KEY0_IV0[i])
}
}

#[test]
fn chacha20_ietf_key1_iv0() {
let mut cipher = ChaCha20::new(
&GenericArray::from(IETF_KEY1),
&GenericArray::from(IETF_IV0),
);
let mut buf = [0; 64];

cipher.encrypt(&mut buf);

for i in 0..64 {
assert_eq!(buf[i], EXPECTED_IETF_KEY1_IV0[i])
}
}

#[test]
fn chacha20_ietf_key0_iv1() {
let mut cipher = ChaCha20::new(
&GenericArray::from(IETF_KEY0),
&GenericArray::from(IETF_IV1),
);
let mut buf = [0; 64];

cipher.encrypt(&mut buf);

for i in 0..64 {
assert_eq!(buf[i], EXPECTED_IETF_KEY0_IV1[i])
}
}

#[test]
fn chacha20_ietf_key0_ivhi() {
let mut cipher = ChaCha20::new(
&GenericArray::from(IETF_KEY0),
&GenericArray::from(IETF_IVHI),
);
let mut buf = [0; 60];

cipher.encrypt(&mut buf);

for i in 0..60 {
assert_eq!(buf[i], EXPECTED_IETF_KEY0_IVHI[i])
}
}

#[test]
fn chacha20_long() {
let mut cipher = ChaCha20::new(&GenericArray::from(KEY_LONG), &GenericArray::from(IV_LONG));
let mut buf = [0; 256];

cipher.encrypt(&mut buf);

for i in 0..256 {
assert_eq!(buf[i], EXPECTED_LONG[i])
}
}

#[test]
fn chacha20_offsets() {
for idx in 0..256 {
for middle in idx..256 {
for last in middle..256 {
let mut cipher =
ChaCha20::new(&GenericArray::from(KEY_LONG), &GenericArray::from(IV_LONG));
let mut buf = [0; 256];

cipher.seek(idx as u64);
cipher.encrypt(&mut buf[idx..middle]);
cipher.encrypt(&mut buf[middle..last]);

for k in idx..last {
assert_eq!(buf[k], EXPECTED_LONG[k])
}
}
}
}
}
2 changes: 1 addition & 1 deletion salsa20-family/Cargo.toml → salsa20-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "salsa20-family"
name = "salsa20-core"
version = "0.1.0"
authors = ["Eric McCorkle <eric@metricspace.net>"]
license = "MIT OR Apache-2.0"
Expand Down