diff --git a/src/crypto/aead.rs b/src/crypto/aead.rs index f0a2c431..0d627aae 100644 --- a/src/crypto/aead.rs +++ b/src/crypto/aead.rs @@ -48,7 +48,8 @@ pub fn new_aead_encryptor(t: CipherType, key: &[u8], nounce: &[u8]) -> Box Box::new(CryptoAeadCrypto::new(t, key, nounce)), + CipherType::Aes256Gcm | + CipherType::ChaCha20IetfPoly1305 => Box::new(CryptoAeadCrypto::new(t, key, nounce)), _ => unreachable!(), } @@ -61,7 +62,8 @@ pub fn new_aead_decryptor(t: CipherType, key: &[u8], nounce: &[u8]) -> Box Box::new(CryptoAeadCrypto::new(t, key, nounce)), + CipherType::Aes256Gcm | + CipherType::ChaCha20IetfPoly1305 => Box::new(CryptoAeadCrypto::new(t, key, nounce)), _ => unreachable!(), } diff --git a/src/crypto/cipher.rs b/src/crypto/cipher.rs index d6cbd32f..95a64a4a 100644 --- a/src/crypto/cipher.rs +++ b/src/crypto/cipher.rs @@ -108,6 +108,8 @@ const CIPHER_AES_128_GCM: &'static str = "aes-128-gcm"; const CIPHER_AES_192_GCM: &'static str = "aes-192-gcm"; const CIPHER_AES_256_GCM: &'static str = "aes-256-gcm"; +const CIPHER_CHACHA20_IETF_POLY1305: &'static str = "chacha20-ietf-poly1305"; + /// ShadowSocks cipher type #[derive(Clone, Debug, Copy)] pub enum CipherType { @@ -133,6 +135,8 @@ pub enum CipherType { Aes128Gcm, Aes192Gcm, Aes256Gcm, + + ChaCha20IetfPoly1305, } /// Category of ciphers @@ -163,11 +167,13 @@ impl CipherType { CipherType::Rc4Md5 => symm::Cipher::rc4().key_len(), CipherType::ChaCha20 | - CipherType::Salsa20 => 32, + CipherType::Salsa20 | + CipherType::ChaCha20IetfPoly1305 => 32, CipherType::Aes128Gcm => 16, CipherType::Aes192Gcm => 24, CipherType::Aes256Gcm => 32, + } } @@ -276,7 +282,8 @@ impl CipherType { CipherType::Aes128Gcm | CipherType::Aes192Gcm | - CipherType::Aes256Gcm => 12, + CipherType::Aes256Gcm | + CipherType::ChaCha20IetfPoly1305 => 12, } } @@ -301,7 +308,8 @@ impl CipherType { match *self { CipherType::Aes128Gcm | CipherType::Aes192Gcm | - CipherType::Aes256Gcm => CipherCategory::Aead, + CipherType::Aes256Gcm | + CipherType::ChaCha20IetfPoly1305 => CipherCategory::Aead, _ => CipherCategory::Stream, } } @@ -313,7 +321,8 @@ impl CipherType { match *self { CipherType::Aes128Gcm | CipherType::Aes192Gcm | - CipherType::Aes256Gcm => 16, + CipherType::Aes256Gcm | + CipherType::ChaCha20IetfPoly1305 => 16, _ => panic!("Only support AEAD ciphers, found {:?}", self), } @@ -357,6 +366,8 @@ impl FromStr for CipherType { CIPHER_AES_192_GCM => Ok(CipherType::Aes192Gcm), CIPHER_AES_256_GCM => Ok(CipherType::Aes256Gcm), + CIPHER_CHACHA20_IETF_POLY1305 => Ok(CipherType::ChaCha20IetfPoly1305), + _ => Err(Error::UnknownCipherType), } } @@ -386,6 +397,8 @@ impl Display for CipherType { CipherType::Aes128Gcm => write!(f, "{}", CIPHER_AES_128_GCM), CipherType::Aes192Gcm => write!(f, "{}", CIPHER_AES_192_GCM), CipherType::Aes256Gcm => write!(f, "{}", CIPHER_AES_256_GCM), + + CipherType::ChaCha20IetfPoly1305 => write!(f, "{}", CIPHER_CHACHA20_IETF_POLY1305), } } } diff --git a/src/crypto/crypto.rs b/src/crypto/crypto.rs index c46a5852..2942cce1 100644 --- a/src/crypto/crypto.rs +++ b/src/crypto/crypto.rs @@ -28,6 +28,7 @@ use rust_crypto::chacha20::ChaCha20; use rust_crypto::salsa20::Salsa20; use rust_crypto::aes_gcm::AesGcm; use rust_crypto::aes::KeySize; +use rust_crypto::chacha20poly1305::ChaCha20Poly1305; use crypto::{StreamCipher, CipherType, CipherResult}; use crypto::{AeadDecryptor, AeadEncryptor}; @@ -76,6 +77,7 @@ impl StreamCipher for CryptoCipher { /// AEAD ciphers provided by Rust-Crypto pub enum CryptoAeadCryptoVariant { AesGcm(AesGcm<'static>), + ChaCha20Poly1305(ChaCha20Poly1305), } /// AEAD Cipher context @@ -111,6 +113,10 @@ impl CryptoAeadCrypto { CipherType::Aes192Gcm => CryptoAeadCryptoVariant::AesGcm(AesGcm::new(KeySize::KeySize192, key, nonce, &[])), CipherType::Aes256Gcm => CryptoAeadCryptoVariant::AesGcm(AesGcm::new(KeySize::KeySize256, key, nonce, &[])), + CipherType::ChaCha20IetfPoly1305 => { + CryptoAeadCryptoVariant::ChaCha20Poly1305(ChaCha20Poly1305::new(key, nonce, &[])) + } + _ => panic!("Unsupported {:?}", t), } } @@ -136,6 +142,9 @@ impl AeadEncryptor for CryptoAeadCrypto { CryptoAeadCryptoVariant::AesGcm(ref mut gcm) => { gcm.encrypt(input, output, tag); } + CryptoAeadCryptoVariant::ChaCha20Poly1305(ref mut cha) => { + cha.encrypt(input, output, tag); + } } } @@ -157,6 +166,13 @@ impl AeadDecryptor for CryptoAeadCrypto { Ok(()) } } + CryptoAeadCryptoVariant::ChaCha20Poly1305(ref mut cha) => { + if !cha.decrypt(input, output, tag) { + Err(Error::AeadDecryptFailed) + } else { + Ok(()) + } + } } };