mirror of
https://github.com/shadowsocks/shadowsocks-rust.git
synced 2026-02-09 01:59:16 +08:00
use openssl crate on crates.io
This commit is contained in:
15
Cargo.toml
15
Cargo.toml
@@ -12,11 +12,6 @@ name = "shadowsocks"
|
||||
|
||||
default = [
|
||||
"cipher-aes-cfb",
|
||||
"cipher-aes-ofb",
|
||||
"cipher-bf-cfb",
|
||||
"cipher-cast5-cfb",
|
||||
"cipher-des-cfb",
|
||||
"cipher-rc2-cfb",
|
||||
"cipher-rc4",
|
||||
|
||||
"cipher-chacha20",
|
||||
@@ -26,16 +21,7 @@ default = [
|
||||
]
|
||||
|
||||
cipher-aes-cfb = []
|
||||
cipher-aes-ofb = []
|
||||
cipher-aes-ctr = []
|
||||
cipher-bf-cfb = []
|
||||
cipher-camellia-cfb = []
|
||||
cipher-cast5-cfb = []
|
||||
cipher-des-cfb = []
|
||||
cipher-idea-cfb = []
|
||||
cipher-rc2-cfb = []
|
||||
cipher-rc4 = []
|
||||
cipher-seed-cfb = []
|
||||
cipher-chacha20 = []
|
||||
cipher-salsa20 = []
|
||||
|
||||
@@ -72,6 +58,7 @@ qrcode = "^0.1.6"
|
||||
env_logger = "^0.3.2"
|
||||
rust-crypto = "^0.2.34"
|
||||
ip = "1.0.0"
|
||||
openssl = "^0.7.1"
|
||||
|
||||
[dependencies.lru-cache]
|
||||
git = "https://github.com/zonyitoo/lru-cache.git"
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
extern crate libc;
|
||||
extern crate test;
|
||||
|
||||
use std::convert::From;
|
||||
|
||||
use openssl::crypto::symm;
|
||||
|
||||
pub mod cipher;
|
||||
pub mod openssl;
|
||||
pub mod digest;
|
||||
@@ -36,3 +40,12 @@ pub enum CryptoMode {
|
||||
Encrypt,
|
||||
Decrypt
|
||||
}
|
||||
|
||||
impl From<CryptoMode> for symm::Mode {
|
||||
fn from(m: CryptoMode) -> symm::Mode {
|
||||
match m {
|
||||
CryptoMode::Encrypt => symm::Mode::Encrypt,
|
||||
CryptoMode::Decrypt => symm::Mode::Decrypt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,8 @@
|
||||
|
||||
//! Cipher defined with Rust binding for libcrypto (OpenSSL)
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern crate libc;
|
||||
use std::convert::From;
|
||||
use std::io::Write;
|
||||
|
||||
use crypto::cipher::{Cipher, CipherType, CipherResult};
|
||||
use crypto::cipher;
|
||||
@@ -32,385 +31,55 @@ use crypto::digest::Digest;
|
||||
use crypto::digest;
|
||||
use crypto::CryptoMode;
|
||||
|
||||
use std::ptr;
|
||||
use std::clone::Clone;
|
||||
|
||||
mod ffi {
|
||||
extern crate libc;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type EVP_CIPHER_CTX = libc::c_void;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type EVP_CIPHER = libc::c_void;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type EVP_MD_CTX = libc::c_void;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type EVP_MD = libc::c_void;
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type ENGINE = libc::c_void;
|
||||
|
||||
pub const CRYPTO_MODE_ENCRYPT: libc::c_int = 1;
|
||||
pub const CRYPTO_MODE_DECRYPT: libc::c_int = 0;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[link(name = "crypto")]
|
||||
extern {
|
||||
pub fn EVP_CIPHER_CTX_new() -> *mut EVP_CIPHER_CTX;
|
||||
pub fn EVP_CIPHER_CTX_cleanup(ctx: *mut EVP_CIPHER_CTX);
|
||||
pub fn EVP_CIPHER_CTX_free(ctx: *mut EVP_CIPHER_CTX);
|
||||
pub fn EVP_CIPHER_CTX_copy(out: *mut EVP_CIPHER_CTX, ctx_in: *const EVP_CIPHER_CTX) -> libc::c_int;
|
||||
|
||||
pub fn EVP_CipherInit_ex(ctx: *mut EVP_CIPHER_CTX, evp: *const EVP_CIPHER, engine: *mut ENGINE,
|
||||
key: *const libc::c_uchar, iv: *const libc::c_uchar, mode: libc::c_int)
|
||||
-> libc::c_int;
|
||||
pub fn EVP_CipherUpdate(ctx: *mut EVP_CIPHER_CTX,
|
||||
outbuf: *mut libc::c_uchar, outlen: *mut libc::c_int,
|
||||
inbuf: *const libc::c_uchar, inlen: libc::c_int) -> libc::c_int;
|
||||
pub fn EVP_CipherFinal(ctx: *mut EVP_CIPHER_CTX, res: *mut libc::c_uchar, len: *mut libc::c_int)
|
||||
-> libc::c_int;
|
||||
|
||||
// Ciphers
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_128_cfb1() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_128_cfb8() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_128_cfb128() -> *const EVP_CIPHER;
|
||||
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_192_cfb1() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_192_cfb8() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_192_cfb128() -> *const EVP_CIPHER;
|
||||
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_256_cfb1() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_256_cfb8() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
pub fn EVP_aes_256_cfb128() -> *const EVP_CIPHER;
|
||||
|
||||
#[cfg(feature = "cipher-aes-ofb")]
|
||||
pub fn EVP_aes_128_ofb() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-ofb")]
|
||||
pub fn EVP_aes_192_ofb() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-ofb")]
|
||||
pub fn EVP_aes_256_ofb() -> *const EVP_CIPHER;
|
||||
|
||||
#[cfg(feature = "cipher-aes-ctr")]
|
||||
pub fn EVP_aes_128_ctr() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-ctr")]
|
||||
pub fn EVP_aes_192_ctr() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-aes-ctr")]
|
||||
pub fn EVP_aes_256_ctr() -> *const EVP_CIPHER;
|
||||
|
||||
#[cfg(feature = "cipher-bf-cfb")]
|
||||
pub fn EVP_bf_cfb64() -> *const EVP_CIPHER;
|
||||
|
||||
#[cfg(feature = "cipher-camellia-cfb")]
|
||||
pub fn EVP_camellia_128_cfb128() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-camellia-cfb")]
|
||||
pub fn EVP_camellia_192_cfb128() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-camellia-cfb")]
|
||||
pub fn EVP_camellia_256_cfb128() -> *const EVP_CIPHER;
|
||||
|
||||
#[cfg(feature = "cipher-cast5-cfb")]
|
||||
pub fn EVP_cast5_cfb64() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-des-cfb")]
|
||||
pub fn EVP_des_cfb64() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-idea-cfb")]
|
||||
pub fn EVP_idea_cfb64() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-rc2-cfb")]
|
||||
pub fn EVP_rc2_cfb64() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-seed-cfb")]
|
||||
pub fn EVP_seed_cfb128() -> *const EVP_CIPHER;
|
||||
#[cfg(feature = "cipher-rc4")]
|
||||
pub fn EVP_rc4() -> *const EVP_CIPHER;
|
||||
|
||||
// MD
|
||||
pub fn EVP_MD_CTX_create() -> *mut EVP_MD_CTX;
|
||||
pub fn EVP_MD_CTX_init(ctx: *mut EVP_MD_CTX);
|
||||
pub fn EVP_MD_CTX_cleanup(ctx: *mut EVP_MD_CTX);
|
||||
pub fn EVP_MD_CTX_destroy(ctx: *mut EVP_MD_CTX);
|
||||
pub fn EVP_MD_CTX_copy_ex(out: *mut EVP_MD_CTX, ctx_in: *const EVP_MD_CTX) -> libc::c_int;
|
||||
pub fn EVP_DigestInit_ex(ctx: *mut EVP_MD_CTX, md_type: *const EVP_MD, engine: *mut ENGINE) -> libc::c_int;
|
||||
pub fn EVP_DigestUpdate(ctx: *const EVP_MD_CTX, d: *const libc::c_void, cnt: libc::size_t) -> libc::c_int;
|
||||
pub fn EVP_DigestFinal_ex(ctx: *const EVP_MD_CTX, md: *mut libc::c_uchar, s: *mut libc::size_t);
|
||||
|
||||
pub fn EVP_md5() -> *const EVP_MD;
|
||||
pub fn EVP_sha() -> *const EVP_MD;
|
||||
pub fn EVP_sha1() -> *const EVP_MD;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OpenSSLDigest {
|
||||
md_ctx: *mut ffi::EVP_MD_CTX,
|
||||
digest_len: usize,
|
||||
}
|
||||
|
||||
impl OpenSSLDigest {
|
||||
pub fn new(t: digest::DigestType) -> OpenSSLDigest {
|
||||
let ctx = unsafe {
|
||||
let md_ctx = ffi::EVP_MD_CTX_create();
|
||||
assert!(!md_ctx.is_null());
|
||||
ffi::EVP_MD_CTX_init(md_ctx);
|
||||
md_ctx
|
||||
};
|
||||
|
||||
let md = OpenSSLDigest::get_md(t);
|
||||
unsafe {
|
||||
ffi::EVP_DigestInit_ex(ctx, md, ptr::null_mut());
|
||||
}
|
||||
|
||||
OpenSSLDigest {
|
||||
md_ctx: ctx,
|
||||
digest_len: t.digest_len(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_md(t: digest::DigestType) -> *const ffi::EVP_MD {
|
||||
unsafe {
|
||||
match t {
|
||||
digest::DigestType::Md5 => ffi::EVP_md5(),
|
||||
digest::DigestType::Sha => ffi::EVP_sha(),
|
||||
digest::DigestType::Sha1 => ffi::EVP_sha1(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for OpenSSLDigest {
|
||||
fn update(&mut self, data: &[u8]) {
|
||||
unsafe {
|
||||
if ffi::EVP_DigestUpdate(self.md_ctx, data.as_ptr() as *const libc::c_void, data.len() as libc::size_t)
|
||||
!= 1 as libc::c_int {
|
||||
panic!("Failed to call EVP_DigestUpdate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn digest(&mut self) -> Vec<u8> {
|
||||
let mut dig = Vec::with_capacity(self.digest_len);
|
||||
unsafe {
|
||||
dig.set_len(self.digest_len);
|
||||
ffi::EVP_DigestFinal_ex(self.md_ctx, dig.as_mut_ptr(), ptr::null_mut());
|
||||
}
|
||||
dig
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for OpenSSLDigest {
|
||||
fn clone(&self) -> OpenSSLDigest {
|
||||
let ctx = unsafe {
|
||||
let md_ctx = ffi::EVP_MD_CTX_create();
|
||||
assert!(!md_ctx.is_null());
|
||||
if ffi::EVP_MD_CTX_copy_ex(md_ctx, self.md_ctx) != 1 as libc::c_int {
|
||||
ffi::EVP_MD_CTX_destroy(md_ctx);
|
||||
panic!("Failed to call EVP_MD_CTX_copy_ex");
|
||||
}
|
||||
md_ctx
|
||||
};
|
||||
OpenSSLDigest {
|
||||
md_ctx: ctx,
|
||||
digest_len: self.digest_len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OpenSSLDigest {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_MD_CTX_cleanup(self.md_ctx);
|
||||
ffi::EVP_MD_CTX_destroy(self.md_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for OpenSSLDigest {}
|
||||
use openssl::crypto::symm;
|
||||
use openssl::crypto::hash;
|
||||
|
||||
pub struct OpenSSLCrypto {
|
||||
evp_ctx: *mut ffi::EVP_CIPHER_CTX,
|
||||
cipher_type: CipherType,
|
||||
inner: symm::Crypter,
|
||||
}
|
||||
|
||||
impl OpenSSLCrypto {
|
||||
pub fn new(cipher_type: cipher::CipherType, key: &[u8], iv: &[u8], mode: CryptoMode) -> OpenSSLCrypto {
|
||||
let ctx = unsafe {
|
||||
let cipher = OpenSSLCrypto::get_cipher(cipher_type);
|
||||
let t = match cipher_type {
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
CipherType::Aes128Cfb => symm::Type::AES_128_CFB128,
|
||||
#[cfg(feature = "cipher-aes-cfb1")]
|
||||
CipherType::Aes128Cfb1 => symm::Type::AES_128_CFB1,
|
||||
#[cfg(feature = "cipher-aes-cfb128")]
|
||||
CipherType::Aes128Cfb128 => symm::Type::AES_128_CFB128,
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
CipherType::Aes256Cfb => symm::Type::AES_256_CFB128,
|
||||
#[cfg(feature = "cipher-aes-cfb1")]
|
||||
CipherType::Aes256Cfb1 => symm::Type::AES_256_CFB1,
|
||||
#[cfg(feature = "cipher-aes-cfb128")]
|
||||
CipherType::Aes256Cfb128 => symm::Type::AES_256_CFB128,
|
||||
|
||||
debug_assert!(iv.len() >= cipher_type.block_size());
|
||||
debug_assert!(key.len() == cipher_type.key_size());
|
||||
let evp_ctx = ffi::EVP_CIPHER_CTX_new();
|
||||
assert!(!evp_ctx.is_null());
|
||||
|
||||
let op = match mode {
|
||||
CryptoMode::Encrypt => ffi::CRYPTO_MODE_ENCRYPT,
|
||||
CryptoMode::Decrypt => ffi::CRYPTO_MODE_DECRYPT,
|
||||
};
|
||||
|
||||
if ffi::EVP_CipherInit_ex(evp_ctx, cipher, ptr::null_mut(), key.as_ptr(),
|
||||
iv.as_ptr(), op) != 1 as libc::c_int {
|
||||
ffi::EVP_CIPHER_CTX_free(evp_ctx);
|
||||
panic!("EVP_CipherInit error");
|
||||
}
|
||||
|
||||
evp_ctx
|
||||
#[cfg(feature = "cipher-rc4")]
|
||||
CipherType::Rc4 => symm::Type::RC4_128,
|
||||
_ => panic!("Cipher type {:?} does not supported by OpenSSLCrypt yet", cipher_type),
|
||||
};
|
||||
|
||||
let cipher = symm::Crypter::new(t);
|
||||
cipher.init(From::from(mode), key, iv);
|
||||
|
||||
OpenSSLCrypto {
|
||||
evp_ctx: ctx,
|
||||
cipher_type: cipher_type,
|
||||
inner: cipher,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cipher(cipher_type: cipher::CipherType) -> *const ffi::EVP_CIPHER {
|
||||
unsafe {
|
||||
match cipher_type {
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes128Cfb => ffi::EVP_aes_128_cfb128(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes128Cfb1 => ffi::EVP_aes_128_cfb1(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes128Cfb8 => ffi::EVP_aes_128_cfb8(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes128Cfb128 => ffi::EVP_aes_128_cfb128(),
|
||||
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes192Cfb => ffi::EVP_aes_192_cfb128(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes192Cfb1 => ffi::EVP_aes_192_cfb1(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes192Cfb8 => ffi::EVP_aes_192_cfb8(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes192Cfb128 => ffi::EVP_aes_192_cfb128(),
|
||||
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes256Cfb => ffi::EVP_aes_256_cfb128(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes256Cfb1 => ffi::EVP_aes_256_cfb1(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes256Cfb8 => ffi::EVP_aes_256_cfb8(),
|
||||
#[cfg(feature = "cipher-aes-cfb")]
|
||||
cipher::CipherType::Aes256Cfb128 => ffi::EVP_aes_256_cfb128(),
|
||||
|
||||
#[cfg(feature = "cipher-aes-ofb")]
|
||||
cipher::CipherType::Aes128Ofb => ffi::EVP_aes_128_ofb(),
|
||||
#[cfg(feature = "cipher-aes-ofb")]
|
||||
cipher::CipherType::Aes192Ofb => ffi::EVP_aes_192_ofb(),
|
||||
#[cfg(feature = "cipher-aes-ofb")]
|
||||
cipher::CipherType::Aes256Ofb => ffi::EVP_aes_256_ofb(),
|
||||
|
||||
#[cfg(feature = "cipher-aes-ctr")]
|
||||
cipher::CipherType::Aes128Ctr => ffi::EVP_aes_128_ctr(),
|
||||
#[cfg(feature = "cipher-aes-ctr")]
|
||||
cipher::CipherType::Aes192Ctr => ffi::EVP_aes_192_ctr(),
|
||||
#[cfg(feature = "cipher-aes-ctr")]
|
||||
cipher::CipherType::Aes256Ctr => ffi::EVP_aes_256_ctr(),
|
||||
|
||||
#[cfg(feature = "cipher-bf-cfb")]
|
||||
cipher::CipherType::BfCfb => ffi::EVP_bf_cfb64(),
|
||||
|
||||
#[cfg(feature = "cipher-camellia-cfb")]
|
||||
cipher::CipherType::Camellia128Cfb => ffi::EVP_camellia_128_cfb128(),
|
||||
#[cfg(feature = "cipher-camellia-cfb")]
|
||||
cipher::CipherType::Camellia192Cfb => ffi::EVP_camellia_192_cfb128(),
|
||||
#[cfg(feature = "cipher-camellia-cfb")]
|
||||
cipher::CipherType::Camellia256Cfb => ffi::EVP_camellia_256_cfb128(),
|
||||
|
||||
#[cfg(feature = "cipher-cast5-cfb")]
|
||||
cipher::CipherType::Cast5Cfb => ffi::EVP_cast5_cfb64(),
|
||||
#[cfg(feature = "cipher-des-cfb")]
|
||||
cipher::CipherType::DesCfb => ffi::EVP_des_cfb64(),
|
||||
#[cfg(feature = "cipher-idea-cfb")]
|
||||
cipher::CipherType::IdeaCfb => ffi::EVP_idea_cfb64(),
|
||||
#[cfg(feature = "cipher-rc2-cfb")]
|
||||
cipher::CipherType::Rc2Cfb => ffi::EVP_rc2_cfb64(),
|
||||
#[cfg(feature = "cipher-seed-cfb")]
|
||||
cipher::CipherType::SeedCfb => ffi::EVP_seed_cfb128(),
|
||||
#[cfg(feature = "cipher-rc4")]
|
||||
cipher::CipherType::Rc4 => ffi::EVP_rc4(),
|
||||
|
||||
_ => { panic!("Unsupported cipher type of OpenSSL") },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&self, data: &[u8], out: &mut Vec<u8>) -> CipherResult<()> {
|
||||
let pdata: *const u8 = data.as_ptr();
|
||||
let datalen: libc::c_int = data.len() as libc::c_int;
|
||||
|
||||
out.reserve(data.len() + self.cipher_type.block_size());
|
||||
|
||||
let mut len: libc::c_int = 0;
|
||||
let orig_len = out.len();
|
||||
let pres: *mut u8 = out[orig_len..].as_mut_ptr();
|
||||
|
||||
unsafe {
|
||||
if ffi::EVP_CipherUpdate(self.evp_ctx,
|
||||
pres, &mut len,
|
||||
pdata, datalen) != 1 {
|
||||
|
||||
return Err(cipher::Error {
|
||||
kind: cipher::ErrorKind::OpenSSLError,
|
||||
desc: "Failed on EVP_CipherUpdate",
|
||||
detail: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { out.set_len(orig_len + len as usize) }
|
||||
pub fn update(&mut self, data: &[u8], out: &mut Vec<u8>) -> CipherResult<()> {
|
||||
let output = self.inner.update(data);
|
||||
out.extend(output.into_iter());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn finalize(&self, out: &mut Vec<u8>) -> CipherResult<()> {
|
||||
let mut len: libc::c_int = 0;
|
||||
let orig_len = out.len();
|
||||
out.reserve(self.cipher_type.block_size());
|
||||
|
||||
unsafe {
|
||||
if ffi::EVP_CipherFinal(self.evp_ctx, out.as_mut_ptr(), &mut len) != 1 {
|
||||
return Err(cipher::Error {
|
||||
kind: cipher::ErrorKind::OpenSSLError,
|
||||
desc: "Failed on EVP_CipherFinal",
|
||||
detail: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
unsafe { out.set_len(orig_len + len as usize) }
|
||||
pub fn finalize(&mut self, out: &mut Vec<u8>) -> CipherResult<()> {
|
||||
let output = self.inner.finalize();
|
||||
out.extend(output.into_iter());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for OpenSSLCrypto {
|
||||
fn clone(&self) -> OpenSSLCrypto {
|
||||
let ctx = unsafe {
|
||||
let ctx = ffi::EVP_CIPHER_CTX_new();
|
||||
if ffi::EVP_CIPHER_CTX_copy(ctx, self.evp_ctx) != 1 {
|
||||
ffi::EVP_CIPHER_CTX_free(ctx);
|
||||
panic!("Failed to call EVP_CIPHER_CTX_copy");
|
||||
}
|
||||
ctx
|
||||
};
|
||||
|
||||
OpenSSLCrypto {
|
||||
evp_ctx: ctx,
|
||||
cipher_type: self.cipher_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Drop for OpenSSLCrypto {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_CIPHER_CTX_cleanup(self.evp_ctx);
|
||||
ffi::EVP_CIPHER_CTX_free(self.evp_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The Cipher binding for OpenSSL's `libcrypto`.
|
||||
///
|
||||
/// It should be noticed that the decipher needs to read the iv (initialization vector)
|
||||
@@ -438,7 +107,6 @@ impl Drop for OpenSSLCrypto {
|
||||
///
|
||||
/// assert!(&decrypted_message[..] == message.as_bytes());
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct OpenSSLCipher {
|
||||
worker: OpenSSLCrypto,
|
||||
}
|
||||
@@ -451,6 +119,8 @@ impl OpenSSLCipher {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for OpenSSLCipher {}
|
||||
|
||||
impl Cipher for OpenSSLCipher {
|
||||
fn update(&mut self, data: &[u8], out: &mut Vec<u8>) -> CipherResult<()> {
|
||||
self.worker.update(data, out)
|
||||
@@ -461,123 +131,32 @@ impl Cipher for OpenSSLCipher {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for OpenSSLCipher {}
|
||||
pub struct OpenSSLDigest {
|
||||
inner: hash::Hasher,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_openssl {
|
||||
extern crate test;
|
||||
use crypto::cipher::{self, Cipher};
|
||||
use crypto::openssl::OpenSSLCipher;
|
||||
use crypto::CryptoMode;
|
||||
impl OpenSSLDigest {
|
||||
pub fn new(t: digest::DigestType) -> OpenSSLDigest {
|
||||
let t = match t {
|
||||
digest::DigestType::Md5 => hash::Type::MD5,
|
||||
digest::DigestType::Sha => hash::Type::SHA512,
|
||||
digest::DigestType::Sha1 => hash::Type::SHA1,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_default_ciphers() {
|
||||
|
||||
let message = "hello world";
|
||||
let key = "passwordhaha";
|
||||
|
||||
println!("ORIGINAL {:?}", message.as_bytes());
|
||||
|
||||
let types = [
|
||||
cipher::CipherType::Aes128Cfb,
|
||||
cipher::CipherType::Aes128Cfb1,
|
||||
cipher::CipherType::Aes128Cfb8,
|
||||
cipher::CipherType::Aes128Cfb128,
|
||||
|
||||
cipher::CipherType::Aes192Cfb,
|
||||
cipher::CipherType::Aes192Cfb1,
|
||||
cipher::CipherType::Aes192Cfb8,
|
||||
cipher::CipherType::Aes192Cfb128,
|
||||
|
||||
cipher::CipherType::Aes256Cfb,
|
||||
cipher::CipherType::Aes256Cfb1,
|
||||
cipher::CipherType::Aes256Cfb8,
|
||||
cipher::CipherType::Aes256Cfb128,
|
||||
|
||||
cipher::CipherType::Aes128Ofb,
|
||||
cipher::CipherType::Aes192Ofb,
|
||||
cipher::CipherType::Aes256Ofb,
|
||||
|
||||
cipher::CipherType::BfCfb,
|
||||
|
||||
cipher::CipherType::Cast5Cfb,
|
||||
cipher::CipherType::DesCfb,
|
||||
cipher::CipherType::Rc2Cfb,
|
||||
];
|
||||
|
||||
for t in types.iter() {
|
||||
let k = t.bytes_to_key(key.as_bytes());
|
||||
let iv = t.gen_init_vec();
|
||||
|
||||
let mut enc = OpenSSLCipher::new(*t, &k[..], &iv[..], CryptoMode::Encrypt);
|
||||
|
||||
let mut encrypted_msg = Vec::new();
|
||||
enc.update(message.as_bytes(), &mut encrypted_msg).unwrap();
|
||||
enc.finalize(&mut encrypted_msg).unwrap();
|
||||
println!("ENC {:?}", encrypted_msg);
|
||||
|
||||
let mut dec = OpenSSLCipher::new(*t, &k[..], &iv[..], CryptoMode::Decrypt);
|
||||
let mut decrypted_msg = Vec::new();
|
||||
dec.update(&encrypted_msg[..], &mut decrypted_msg).unwrap();
|
||||
dec.finalize(&mut decrypted_msg).unwrap();
|
||||
println!("DEC {:?}", &decrypted_msg[..]);
|
||||
|
||||
assert_eq!(message.as_bytes(), &decrypted_msg[..]);
|
||||
OpenSSLDigest {
|
||||
inner: hash::Hasher::new(t),
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_openssl_default_cipher_encrypt(b: &mut test::Bencher) {
|
||||
use rand::random;
|
||||
|
||||
let msg_size: usize = 0xffff;
|
||||
|
||||
let mut test_data = Vec::new();
|
||||
for _ in 0..100 {
|
||||
let msg = (0..msg_size).map(|_| random::<u8>()).collect::<Vec<u8>>();
|
||||
let key = (1..random::<usize>() % 63).map(|_| random::<u8>()).collect::<Vec<u8>>();
|
||||
let k = cipher::CipherType::Aes256Cfb.bytes_to_key(&key[..]);
|
||||
let v = cipher::CipherType::Aes256Cfb.gen_init_vec();
|
||||
|
||||
test_data.push((msg, k, v));
|
||||
}
|
||||
|
||||
b.iter(|| {
|
||||
let (ref msg, ref key, ref iv) = test_data[random::<usize>() % test_data.len()];
|
||||
|
||||
let mut enc = OpenSSLCipher::new(cipher::CipherType::Aes256Cfb,
|
||||
&key[..], &iv[..], CryptoMode::Encrypt);
|
||||
let mut out = Vec::new();
|
||||
enc.update(&msg[..], &mut out).unwrap();
|
||||
});
|
||||
b.bytes = msg_size as u64;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_openssl_default_cipher_decrypt(b: &mut test::Bencher) {
|
||||
use rand::random;
|
||||
|
||||
let msg_size: usize = 0xffff;
|
||||
let mut test_data = Vec::new();
|
||||
for _ in 0..100 {
|
||||
let msg = (0..msg_size).map(|_| random::<u8>()).collect::<Vec<u8>>();
|
||||
let key = (1..random::<usize>() % 63).map(|_| random::<u8>()).collect::<Vec<u8>>();
|
||||
let k = cipher::CipherType::Aes256Cfb.bytes_to_key(&key[..]);
|
||||
let v = cipher::CipherType::Aes256Cfb.gen_init_vec();
|
||||
let mut cipher = OpenSSLCipher::new(cipher::CipherType::Aes256Cfb,
|
||||
&k[..], &v[..], CryptoMode::Encrypt);
|
||||
let mut encrypted_msg = Vec::new();
|
||||
cipher.update(&msg[..], &mut encrypted_msg).unwrap();
|
||||
test_data.push((k, v, encrypted_msg));
|
||||
}
|
||||
|
||||
b.iter(|| {
|
||||
let (ref key, ref iv, ref encrypted_msg) = test_data[random::<usize>() % test_data.len()];
|
||||
let mut cipher = OpenSSLCipher::new(cipher::CipherType::Aes256Cfb,
|
||||
&key[..], &iv[..], CryptoMode::Decrypt);
|
||||
let mut out = Vec::new();
|
||||
cipher.update(&encrypted_msg[..], &mut out).unwrap();
|
||||
});
|
||||
b.bytes = msg_size as u64;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for OpenSSLDigest {}
|
||||
|
||||
impl Digest for OpenSSLDigest {
|
||||
fn update(&mut self, data: &[u8]) {
|
||||
let _ = self.inner.write(data);
|
||||
}
|
||||
|
||||
fn digest(&mut self) -> Vec<u8> {
|
||||
self.inner.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ extern crate coio;
|
||||
|
||||
extern crate crypto as rust_crypto;
|
||||
extern crate ip;
|
||||
extern crate openssl;
|
||||
|
||||
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user