Add experimental SIV support (#81)

* add optional miscreant support

* add miscreant test

* fix miscreant version

* update README

+ add `aes-128-pmac-siv`, `aes-256-pmac-siv`
+ remove `aes-192-gcm`
This commit is contained in:
quininer
2017-11-01 16:23:36 +08:00
committed by Y. T. CHUNG
parent 47551d832a
commit dc8f7e2832
9 changed files with 311 additions and 80 deletions
Generated
+68 -33
View File
@@ -1,36 +1,7 @@
[root]
name = "shadowsocks-rust"
version = "1.6.8"
dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byte_string 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"libsodium-ffi 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"md-5 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)",
"qrcode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"subprocess 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aesni"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "aho-corasick"
@@ -137,6 +108,14 @@ dependencies = [
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clear_on_drop"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "coco"
version = "0.1.1"
@@ -351,6 +330,18 @@ dependencies = [
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miscreant"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aesni 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clear_on_drop 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"subtle 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "net2"
version = "0.2.31"
@@ -533,6 +524,41 @@ dependencies = [
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shadowsocks-rust"
version = "1.6.8"
dependencies = [
"base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byte_string 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"libsodium-ffi 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"md-5 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"miscreant 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)",
"qrcode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"subprocess 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "slab"
version = "0.3.0"
@@ -559,6 +585,11 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "subtle"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "termion"
version = "1.5.1"
@@ -722,6 +753,7 @@ dependencies = [
]
[metadata]
"checksum aesni 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ef0ab1be561c7753c0c416e1b73466c5a07a134c222f4115a4c76ea6526eb56a"
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f"
@@ -737,6 +769,7 @@ dependencies = [
"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180"
"checksum clear_on_drop 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27fc408dd80e7fe9d5b1c8cee6c2add84bea237d8dee70880a76ae7957f6d3a6"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a"
@@ -765,6 +798,7 @@ dependencies = [
"checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb"
"checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum miscreant 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7dc55762103c586148e451ce13e0fbc0ec9f92b90ae70042a2ffc0d77ddb1c"
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
@@ -792,6 +826,7 @@ dependencies = [
"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum subprocess 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "78a77399f1ffa6f2ee3595ab8e329381bbeaf640d59073821519e6a0aa957f9d"
"checksum subtle 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32dbfc4beea0a08bfe33114d0f5e5092f35f6fa387a955b4a2c68888cdd7b0f2"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
+1
View File
@@ -58,6 +58,7 @@ url = "1.5"
byte_string = "1.0"
libsodium-ffi = { version = "0.1", optional = true }
futures-cpupool = "0.1"
miscreant = { version = "0.2", optional = true }
[target.'cfg(unix)'.dependencies]
tokio-signal = "0.1"
+4 -3
View File
@@ -56,7 +56,7 @@ make install
```
Then `sslocal`, `ssserver` and `ssurl` will be installed in `/usr/local/bin` (variable PREFIX).
### **Build standalone binaries**
Requirements:
@@ -170,12 +170,13 @@ $ ssserver -s "[::]:8388" -m "aes-256-gcm" -k "hello-kitty" --plugin "obfs-local
* `dummy` (No encryption, just for debugging)
### AEAD Ciphers
* `aes-128-gcm`, `aes-192-gcm`, `aes-256-gcm`
* `aes-128-gcm`, `aes-256-gcm`
* `chacha20-ietf-poly1305`
* `aes-128-pmac-siv`, `aes-256-pmac-siv` (experimental)
## Useful Tools
1. `ssurl` is for encoding and decoding ShadowSocks URLs (SIP002). Example:
1. `ssurl` is for encoding and decoding ShadowSocks URLs (SIP002). Example:
```plain
ss://YWVzLTI1Ni1jZmI6cGFzc3dvcmQ@127.0.0.1:8388/?plugin=obfs-local%3Bobfs%3Dhttp%3Bobfs-host%3Dwww.baidu.com
+10
View File
@@ -3,6 +3,8 @@
use crypto::cipher::{CipherCategory, CipherResult, CipherType};
use crypto::ring::RingAeadCipher;
#[cfg(feature = "miscreant")]
use crypto::siv::MiscreantCipher;
use ring::digest::SHA1;
use ring::hkdf;
@@ -37,6 +39,10 @@ pub fn new_aead_encryptor(t: CipherType, key: &[u8], nonce: &[u8]) -> BoxAeadEnc
CipherType::Aes256Gcm |
CipherType::ChaCha20Poly1305 => Box::new(RingAeadCipher::new(t, key, nonce, true)),
#[cfg(feature = "miscreant")]
CipherType::Aes128PmacSiv |
CipherType::Aes256PmacSiv => Box::new(MiscreantCipher::new(t, key, nonce)),
_ => unreachable!(),
}
}
@@ -50,6 +56,10 @@ pub fn new_aead_decryptor(t: CipherType, key: &[u8], nonce: &[u8]) -> BoxAeadDec
CipherType::Aes256Gcm |
CipherType::ChaCha20Poly1305 => Box::new(RingAeadCipher::new(t, key, nonce, false)),
#[cfg(feature = "miscreant")]
CipherType::Aes128PmacSiv |
CipherType::Aes256PmacSiv => Box::new(MiscreantCipher::new(t, key, nonce)),
_ => unreachable!(),
}
}
+58 -19
View File
@@ -67,35 +67,40 @@ impl From<::openssl::error::ErrorStack> for Error {
}
}
const CIPHER_AES_128_CFB: &'static str = "aes-128-cfb";
const CIPHER_AES_128_CFB_1: &'static str = "aes-128-cfb1";
const CIPHER_AES_128_CFB_8: &'static str = "aes-128-cfb8";
const CIPHER_AES_128_CFB_128: &'static str = "aes-128-cfb128";
const CIPHER_AES_128_CFB: &str = "aes-128-cfb";
const CIPHER_AES_128_CFB_1: &str = "aes-128-cfb1";
const CIPHER_AES_128_CFB_8: &str = "aes-128-cfb8";
const CIPHER_AES_128_CFB_128: &str = "aes-128-cfb128";
const CIPHER_AES_256_CFB: &'static str = "aes-256-cfb";
const CIPHER_AES_256_CFB_1: &'static str = "aes-256-cfb1";
const CIPHER_AES_256_CFB_8: &'static str = "aes-256-cfb8";
const CIPHER_AES_256_CFB_128: &'static str = "aes-256-cfb128";
const CIPHER_AES_256_CFB: &str = "aes-256-cfb";
const CIPHER_AES_256_CFB_1: &str = "aes-256-cfb1";
const CIPHER_AES_256_CFB_8: &str = "aes-256-cfb8";
const CIPHER_AES_256_CFB_128: &str = "aes-256-cfb128";
const CIPHER_RC4: &'static str = "rc4";
const CIPHER_RC4_MD5: &'static str = "rc4-md5";
const CIPHER_RC4: &str = "rc4";
const CIPHER_RC4_MD5: &str = "rc4-md5";
const CIPHER_TABLE: &'static str = "table";
const CIPHER_TABLE: &str = "table";
#[cfg(feature = "sodium")]
const CIPHER_CHACHA20: &'static str = "chacha20";
const CIPHER_CHACHA20: &str = "chacha20";
#[cfg(feature = "sodium")]
const CIPHER_SALSA20: &'static str = "salsa20";
const CIPHER_SALSA20: &str = "salsa20";
#[cfg(feature = "sodium")]
const CIPHER_XSALSA20: &'static str = "xsalsa20";
const CIPHER_XSALSA20: &str = "xsalsa20";
#[cfg(feature = "sodium")]
const CIPHER_CHACHA20_IETF: &'static str = "chacha20-ietf";
const CIPHER_CHACHA20_IETF: &str = "chacha20-ietf";
const CIPHER_DUMMY: &'static str = "dummy";
#[cfg(feature = "miscreant")]
const CIPHER_AES_128_PMAC_SIV: &str = "aes-128-pmac-siv";
#[cfg(feature = "miscreant")]
const CIPHER_AES_256_PMAC_SIV: &str = "aes-256-pmac-siv";
const CIPHER_AES_128_GCM: &'static str = "aes-128-gcm";
const CIPHER_AES_256_GCM: &'static str = "aes-256-gcm";
const CIPHER_CHACHA20_POLY1305: &'static str = "chacha20-ietf-poly1305";
const CIPHER_DUMMY: &str = "dummy";
const CIPHER_AES_128_GCM: &str = "aes-128-gcm";
const CIPHER_AES_256_GCM: &str = "aes-256-gcm";
const CIPHER_CHACHA20_POLY1305: &str = "chacha20-ietf-poly1305";
/// ShadowSocks cipher type
#[derive(Clone, Debug, Copy)]
@@ -129,6 +134,11 @@ pub enum CipherType {
Aes256Gcm,
ChaCha20Poly1305,
#[cfg(feature = "miscreant")]
Aes128PmacSiv,
#[cfg(feature = "miscreant")]
Aes256PmacSiv,
}
/// Category of ciphers
@@ -168,6 +178,11 @@ impl CipherType {
CipherType::Aes256Gcm => AES_256_GCM.key_len(),
CipherType::ChaCha20Poly1305 => CHACHA20_POLY1305.key_len(),
#[cfg(feature = "miscreant")]
CipherType::Aes128PmacSiv => 32,
#[cfg(feature = "miscreant")]
CipherType::Aes256PmacSiv => 64,
}
}
@@ -263,6 +278,11 @@ impl CipherType {
CipherType::Aes128Gcm => AES_128_GCM.nonce_len(),
CipherType::Aes256Gcm => AES_256_GCM.nonce_len(),
CipherType::ChaCha20Poly1305 => CHACHA20_POLY1305.nonce_len(),
#[cfg(feature = "miscreant")]
CipherType::Aes128PmacSiv => 8,
#[cfg(feature = "miscreant")]
CipherType::Aes256PmacSiv => 8,
}
}
@@ -294,6 +314,11 @@ impl CipherType {
CipherType::Aes128Gcm |
CipherType::Aes256Gcm |
CipherType::ChaCha20Poly1305 => CipherCategory::Aead,
#[cfg(feature = "miscreant")]
CipherType::Aes128PmacSiv |
CipherType::Aes256PmacSiv => CipherCategory::Aead,
_ => CipherCategory::Stream,
}
}
@@ -307,6 +332,10 @@ impl CipherType {
CipherType::Aes256Gcm => AES_256_GCM.tag_len(),
CipherType::ChaCha20Poly1305 => CHACHA20_POLY1305.tag_len(),
#[cfg(feature = "miscreant")]
CipherType::Aes128PmacSiv |
CipherType::Aes256PmacSiv => 16,
_ => panic!("Only support AEAD ciphers, found {:?}", self),
}
}
@@ -356,6 +385,11 @@ impl FromStr for CipherType {
CIPHER_CHACHA20_POLY1305 => Ok(CipherType::ChaCha20Poly1305),
#[cfg(feature = "miscreant")]
CIPHER_AES_128_PMAC_SIV => Ok(CipherType::Aes128PmacSiv),
#[cfg(feature = "miscreant")]
CIPHER_AES_256_PMAC_SIV => Ok(CipherType::Aes256PmacSiv),
_ => Err(Error::UnknownCipherType),
}
}
@@ -391,6 +425,11 @@ impl Display for CipherType {
CipherType::Aes128Gcm => write!(f, "{}", CIPHER_AES_128_GCM),
CipherType::Aes256Gcm => write!(f, "{}", CIPHER_AES_256_GCM),
CipherType::ChaCha20Poly1305 => write!(f, "{}", CIPHER_CHACHA20_POLY1305),
#[cfg(feature = "miscreant")]
CipherType::Aes128PmacSiv => write!(f, "{}", CIPHER_AES_128_PMAC_SIV),
#[cfg(feature = "miscreant")]
CipherType::Aes256PmacSiv => write!(f, "{}", CIPHER_AES_256_PMAC_SIV),
}
}
}
+2
View File
@@ -18,6 +18,8 @@ pub mod ring;
pub mod dummy;
pub mod aead;
pub mod stream;
#[cfg(feature = "miscreant")]
pub mod siv;
#[cfg(feature = "sodium")]
pub mod sodium;
+10 -25
View File
@@ -57,32 +57,17 @@ impl RingAeadCipher {
macro_rules! seal_or_open {
( $item:ident, $key:ident, $crypt:ident ) => {
RingAeadCryptoVariant::$item($key::new(&$crypt, key).unwrap(), Bytes::from(nonce))
};
( $crypt:ident ) => {
if is_seal { seal_or_open!(Seal, SealingKey, $crypt) }
else { seal_or_open!(Open, OpeningKey, $crypt) }
}
}
match t {
CipherType::Aes128Gcm => {
if is_seal {
seal_or_open!(Seal, SealingKey, AES_128_GCM)
} else {
seal_or_open!(Open, OpeningKey, AES_128_GCM)
}
}
CipherType::Aes256Gcm => {
if is_seal {
seal_or_open!(Seal, SealingKey, AES_256_GCM)
} else {
seal_or_open!(Open, OpeningKey, AES_256_GCM)
}
}
CipherType::ChaCha20Poly1305 => {
if is_seal {
seal_or_open!(Seal, SealingKey, CHACHA20_POLY1305)
} else {
seal_or_open!(Open, OpeningKey, CHACHA20_POLY1305)
}
}
CipherType::Aes128Gcm => seal_or_open!(AES_128_GCM),
CipherType::Aes256Gcm => seal_or_open!(AES_256_GCM),
CipherType::ChaCha20Poly1305 => seal_or_open!(CHACHA20_POLY1305),
_ => panic!("unsupported cipher in ring {:?}", t),
}
}
@@ -115,8 +100,8 @@ impl AeadEncryptor for RingAeadCipher {
if let RingAeadCryptoVariant::Seal(ref key, ref nonce) = self.cipher {
seal_in_place(key, nonce, &[], &mut buf, tag_len).unwrap();
output.clone_from_slice(&buf[..input.len()]);
tag.clone_from_slice(&buf[input.len()..]);
output.copy_from_slice(&buf[..input.len()]);
tag.copy_from_slice(&buf[input.len()..]);
} else {
unreachable!("encrypt is called on a non-seal cipher");
}
@@ -134,7 +119,7 @@ impl AeadDecryptor for RingAeadCipher {
let r = if let RingAeadCryptoVariant::Open(ref key, ref nonce) = self.cipher {
match open_in_place(key, nonce, &[], 0, &mut buf) {
Ok(buf) => {
output.clone_from_slice(&buf[..input.len()]);
output.copy_from_slice(&buf[..input.len()]);
Ok(())
}
Err(err) => {
+156
View File
@@ -0,0 +1,156 @@
//! Cipher defined with Miscreant
use std::{iter, ptr};
use miscreant::{Aes128PmacSiv, Aes256PmacSiv};
use crypto::{AeadDecryptor, AeadEncryptor};
use crypto::{CipherResult, CipherType};
use crypto::aead::{increase_nonce, make_skey};
use crypto::cipher::Error;
use bytes::{BufMut, BytesMut};
use byte_string::ByteStr;
/// AEAD ciphers provided by Miscreant
pub enum MiscreantCryptoVariant {
Aes128(Aes128PmacSiv),
Aes256(Aes256PmacSiv)
}
/// AEAD Cipher context
///
/// According to SIP004, the `nonce` has to incr 1 after each encrypt/decrypt.
pub struct MiscreantCipher {
cipher: MiscreantCryptoVariant,
nonce: BytesMut
}
impl MiscreantCipher {
/// Initialize context
pub fn new(t: CipherType, key: &[u8], salt: &[u8]) -> Self {
// NOTE: Don't need check salt is duplicated. :)
let nonce_size = t.iv_size();
let mut nonce = BytesMut::with_capacity(nonce_size);
unsafe {
nonce.set_len(nonce_size);
ptr::write_bytes(nonce.as_mut_ptr(), 0, nonce_size);
}
let skey = make_skey(t, key, salt);
let cipher = Self::new_variant(t, &skey);
MiscreantCipher { cipher: cipher, nonce: nonce }
}
fn new_variant(t: CipherType, key: &[u8]) -> MiscreantCryptoVariant {
match t {
CipherType::Aes128PmacSiv => {
let mut skey = [0; 32];
skey.copy_from_slice(key);
MiscreantCryptoVariant::Aes128(Aes128PmacSiv::new(&skey))
},
CipherType::Aes256PmacSiv => {
let mut skey = [0; 64];
skey.copy_from_slice(key);
MiscreantCryptoVariant::Aes256(Aes256PmacSiv::new(&skey))
},
_ => panic!("unsupported cipher in miscreant {:?}", t),
}
}
}
impl AeadEncryptor for MiscreantCipher {
fn encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8]) {
let tag_len = tag.len();
let buf_len = input.len() + tag_len;
let mut buf = BytesMut::with_capacity(buf_len);
unsafe {
buf.set_len(buf_len);
}
buf[tag_len..].copy_from_slice(input);
match self.cipher {
MiscreantCryptoVariant::Aes128(ref mut cipher) => {
cipher.seal_in_place(iter::once(&self.nonce), &mut buf);
tag.copy_from_slice(&buf[..tag_len]);
output.copy_from_slice(&buf[tag_len..]);
},
MiscreantCryptoVariant::Aes256(ref mut cipher) => {
cipher.seal_in_place(iter::once(&self.nonce), &mut buf);
tag.copy_from_slice(&buf[..tag_len]);
output.copy_from_slice(&buf[tag_len..]);
}
}
increase_nonce(&mut self.nonce);
}
}
impl AeadDecryptor for MiscreantCipher {
fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> CipherResult<()> {
let mut buf = BytesMut::with_capacity(input.len() + tag.len());
buf.put_slice(tag);
buf.put_slice(input);
let result = match self.cipher {
MiscreantCryptoVariant::Aes128(ref mut cipher) =>
cipher.open_in_place(iter::once(&self.nonce), &mut buf),
MiscreantCryptoVariant::Aes256(ref mut cipher) =>
cipher.open_in_place(iter::once(&self.nonce), &mut buf)
};
result
.map(|buf| {
output.copy_from_slice(buf);
increase_nonce(&mut self.nonce);
})
.map_err(|_| {
error!("AEAD decrypt failed, nonce={:?}, input={:?}, tag={:?}, err: decrypt failure",
ByteStr::new(&self.nonce),
ByteStr::new(input),
ByteStr::new(tag));
Error::AeadDecryptFailed
})
}
}
#[cfg(test)]
mod test {
use super::*;
use crypto::{CipherType, AeadEncryptor, AeadDecryptor};
fn test_miscreant(ct: CipherType) {
let key = ct.bytes_to_key(b"PassWORD");
let message = b"message";
let iv = ct.gen_init_vec();
let mut enc = MiscreantCipher::new(ct, &key[..], &iv[..]);
let mut encrypted_msg = vec![0; message.len()];
let mut tag = [0; 16];
enc.encrypt(message, &mut encrypted_msg, &mut tag);
assert_ne!(message, &encrypted_msg[..]);
let mut dec = MiscreantCipher::new(ct, &key[..], &iv[..]);
let mut decrypted_msg = vec![0; encrypted_msg.len()];
dec.decrypt(&encrypted_msg[..], &mut decrypted_msg, &tag).unwrap();
assert_eq!(&decrypted_msg[..], message);
}
#[test]
fn test_rust_crypto_cipher_chacha20() {
test_miscreant(CipherType::Aes128PmacSiv);
}
#[test]
fn test_rust_crypto_cipher_salsa20() {
test_miscreant(CipherType::Aes256PmacSiv);
}
}
+2
View File
@@ -79,6 +79,8 @@ extern crate byteorder;
extern crate rand;
extern crate typenum;
extern crate digest;
#[cfg(feature = "miscreant")]
extern crate miscreant;
#[cfg(feature = "sodium")]
extern crate libsodium_ffi;
extern crate md_5 as md5;