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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use crypto::cipher::{CipherType, CipherCategory, CipherResult};
use crypto::crypto::CryptoAeadCrypto;
use rust_crypto::hkdf::{hkdf_expand, hkdf_extract};
use rust_crypto::sha1::Sha1;
use rust_crypto::digest::Digest;
use bytes::{BytesMut, Bytes};
pub trait AeadEncryptor {
fn encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8]);
}
pub trait AeadDecryptor {
fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> CipherResult<()>;
}
pub fn new_aead_encryptor(t: CipherType, key: &[u8], nounce: &[u8]) -> Box<AeadEncryptor> {
assert!(t.category() == CipherCategory::Aead);
match t {
CipherType::Aes128Gcm |
CipherType::Aes192Gcm |
CipherType::Aes256Gcm => Box::new(CryptoAeadCrypto::new(t, key, nounce)),
_ => unreachable!(),
}
}
pub fn new_aead_decryptor(t: CipherType, key: &[u8], nounce: &[u8]) -> Box<AeadDecryptor> {
assert!(t.category() == CipherCategory::Aead);
match t {
CipherType::Aes128Gcm |
CipherType::Aes192Gcm |
CipherType::Aes256Gcm => Box::new(CryptoAeadCrypto::new(t, key, nounce)),
_ => unreachable!(),
}
}
const SUBKEY_INFO: &'static [u8] = b"ss-subkey";
pub fn make_skey(t: CipherType, key: &[u8], salt: &[u8]) -> Bytes {
assert!(t.category() == CipherCategory::Aead);
let sha1 = Sha1::new();
let output_bytes = sha1.output_bytes();
let mut prk = BytesMut::with_capacity(output_bytes);
unsafe {
prk.set_len(output_bytes);
}
hkdf_extract(sha1, salt, key, &mut prk);
let mut skey = BytesMut::with_capacity(key.len());
unsafe {
skey.set_len(key.len());
}
hkdf_expand(Sha1::new(), &prk, SUBKEY_INFO, &mut skey);
skey.freeze()
}
pub fn increase_nonce(nonce: &mut [u8]) {
let mut adding = true;
for v in nonce.iter_mut() {
if !adding {
break;
}
let (r, overflow) = v.overflowing_add(1);
*v = r;
adding = overflow;
}
}