use std::convert::From;
use crypto::{StreamCipher, CipherType, CipherResult};
use crypto::cipher;
use crypto::CryptoMode;
use openssl::symm;
use bytes::{BufMut, BytesMut};
pub struct OpenSSLCrypto {
cipher: symm::Cipher,
inner: symm::Crypter,
}
impl OpenSSLCrypto {
pub fn new(cipher_type: cipher::CipherType, key: &[u8], iv: &[u8], mode: CryptoMode) -> OpenSSLCrypto {
let t = match cipher_type {
CipherType::Aes128Cfb => symm::Cipher::aes_128_cfb128(),
CipherType::Aes128Cfb1 => symm::Cipher::aes_128_cfb1(),
CipherType::Aes128Cfb128 => symm::Cipher::aes_128_cfb128(),
CipherType::Aes256Cfb => symm::Cipher::aes_256_cfb128(),
CipherType::Aes256Cfb1 => symm::Cipher::aes_256_cfb1(),
CipherType::Aes256Cfb128 => symm::Cipher::aes_256_cfb128(),
CipherType::Rc4 => symm::Cipher::rc4(),
_ => {
panic!("Cipher type {:?} does not supported by OpenSSLCrypt yet",
cipher_type)
}
};
let cipher = symm::Crypter::new(t, From::from(mode), key, Some(iv)).unwrap();
OpenSSLCrypto {
cipher: t,
inner: cipher,
}
}
pub fn update<B: BufMut>(&mut self, data: &[u8], out: &mut B) -> CipherResult<()> {
let least_reserved = data.len() + self.cipher.block_size();
let mut buf = BytesMut::with_capacity(least_reserved); unsafe {
buf.set_len(least_reserved);
}
let length = self.inner.update(data, &mut *buf)?;
buf.truncate(length);
out.put(buf);
Ok(())
}
pub fn finalize<B: BufMut>(&mut self, out: &mut B) -> CipherResult<()> {
let least_reserved = self.cipher.block_size();
let mut buf = BytesMut::with_capacity(least_reserved); unsafe {
buf.set_len(least_reserved);
}
let length = self.inner.finalize(&mut *buf)?;
buf.truncate(length);
out.put(buf);
Ok(())
}
pub fn buffer_size(&self, data: &[u8]) -> usize {
self.cipher.block_size() + data.len()
}
}
pub struct OpenSSLCipher {
worker: OpenSSLCrypto,
}
impl OpenSSLCipher {
pub fn new(cipher_type: cipher::CipherType, key: &[u8], iv: &[u8], mode: CryptoMode) -> OpenSSLCipher {
OpenSSLCipher { worker: OpenSSLCrypto::new(cipher_type, &key[..], &iv[..], mode) }
}
}
unsafe impl Send for OpenSSLCipher {}
impl StreamCipher for OpenSSLCipher {
fn update<B: BufMut>(&mut self, data: &[u8], out: &mut B) -> CipherResult<()> {
self.worker.update(data, out)
}
fn finalize<B: BufMut>(&mut self, out: &mut B) -> CipherResult<()> {
self.worker.finalize(out)
}
fn buffer_size(&self, data: &[u8]) -> usize {
self.worker.buffer_size(data)
}
}