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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crypto::cipher::{CipherType, CipherCategory, CipherResult};
use crypto::openssl;
use crypto::table;
use crypto::CryptoMode;
use crypto::rc4_md5;
use crypto::dummy;
use crypto::crypto::CryptoCipher;
use bytes::BufMut;
pub trait StreamCipher {
fn update<B: BufMut>(&mut self, data: &[u8], out: &mut B) -> CipherResult<()>;
fn finalize<B: BufMut>(&mut self, out: &mut B) -> CipherResult<()>;
fn buffer_size(&self, data: &[u8]) -> usize;
}
macro_rules! define_stream_ciphers {
($($name:ident => $cipher:ty,)+) => {
pub enum StreamCipherVariant {
$(
$name($cipher),
)+
}
impl StreamCipherVariant {
pub fn new<C>(cipher: C) -> StreamCipherVariant
where StreamCipherVariant: From<C>
{
From::from(cipher)
}
}
impl StreamCipher for StreamCipherVariant {
fn update<B: BufMut>(&mut self, data: &[u8], out: &mut B) -> CipherResult<()> {
match *self {
$(
StreamCipherVariant::$name(ref mut cipher) => cipher.update(data, out),
)+
}
}
fn finalize<B: BufMut>(&mut self, out: &mut B) -> CipherResult<()> {
match *self {
$(
StreamCipherVariant::$name(ref mut cipher) => cipher.finalize(out),
)+
}
}
fn buffer_size(&self, data: &[u8]) -> usize {
match *self {
$(
StreamCipherVariant::$name(ref cipher) => cipher.buffer_size(data),
)+
}
}
}
$(
impl From<$cipher> for StreamCipherVariant {
fn from(cipher: $cipher) -> StreamCipherVariant {
StreamCipherVariant::$name(cipher)
}
}
)+
}
}
define_stream_ciphers! {
TableCipher => table::TableCipher,
DummyCipher => dummy::DummyCipher,
Rc4Md5Cipher => rc4_md5::Rc4Md5Cipher,
OpenSSLCipher => openssl::OpenSSLCipher,
CryptoCipher => CryptoCipher,
}
pub fn new_stream(t: CipherType, key: &[u8], iv: &[u8], mode: CryptoMode) -> StreamCipherVariant {
assert!(t.category() == CipherCategory::Stream,
"only allow initializing with stream cipher");
match t {
CipherType::Table => StreamCipherVariant::new(table::TableCipher::new(key, mode)),
CipherType::Dummy => StreamCipherVariant::new(dummy::DummyCipher),
CipherType::ChaCha20 |
CipherType::Salsa20 => StreamCipherVariant::new(CryptoCipher::new(t, key, iv)),
CipherType::Rc4Md5 => StreamCipherVariant::new(rc4_md5::Rc4Md5Cipher::new(key, iv, mode)),
_ => StreamCipherVariant::new(openssl::OpenSSLCipher::new(t, key, iv, mode)),
}
}