Skip to content

Commit cb54882

Browse files
committed
Removes non-standard AEAD ciphers that have variable NONCE_LEN
- These ciphers support variable NONCE_LEN. A fixed NONCE_LEN have to be chosen by a SIP process - Bump version to v0.2.4 BREAKING CHANGES: These ciphers have been removed - aes-128-ocb-taglen128, aes-192-ocb-taglen128, aes-256-ocb-taglen128 - aes-siv-cmac-256, aes-siv-cmac-384, aes-siv-cmac-512
1 parent b5ffd28 commit cb54882

File tree

6 files changed

+73
-230
lines changed

6 files changed

+73
-230
lines changed

Diff for: Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "shadowsocks-crypto"
3-
version = "0.2.3"
3+
version = "0.2.4"
44
authors = ["luozijun <[email protected]>"]
55
edition = "2018"
66
license = "MIT"

Diff for: README.md

+17-17
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ shadowsocks' flavored cryptographic algorithm in pure Rust.
88

99
Stream Ciphers:
1010

11-
* SS_TABLE
12-
* SS_RC4_MD5
13-
* AES_128_CTR, AES_192_CTR, AES_256_CTR
14-
* AES_128_CFB1, AES_128_CFB8, AES_128_CFB128, AES_192_CFB1, AES_192_CFB8, AES_192_CFB128, AES_256_CFB1, AES_256_CFB8, AES_256_CFB128
15-
* AES_128_OFB, AES_192_OFB, AES_256_OFB
16-
* CAMELLIA_128_CTR, CAMELLIA_192_CTR, CAMELLIA_256_CTR
17-
* CAMELLIA_128_CFB1, CAMELLIA_128_CFB8, CAMELLIA_128_CFB128, CAMELLIA_192_CFB1, CAMELLIA_192_CFB8, CAMELLIA_192_CFB128, CAMELLIA_256_CFB1, CAMELLIA_256_CFB8, CAMELLIA_256_CFB128
18-
* CAMELLIA_128_OFB, CAMELLIA_192_OFB, CAMELLIA_256_OFB
19-
* RC4
20-
* CHACHA20 (IETF Version)
11+
* [x] SS_TABLE
12+
* [x] SS_RC4_MD5
13+
* [x] AES_128_CTR, AES_192_CTR, AES_256_CTR
14+
* [x] AES_128_CFB1, AES_128_CFB8, AES_128_CFB128, AES_192_CFB1, AES_192_CFB8, AES_192_CFB128, AES_256_CFB1, AES_256_CFB8, AES_256_CFB128
15+
* [x] AES_128_OFB, AES_192_OFB, AES_256_OFB
16+
* [x] CAMELLIA_128_CTR, CAMELLIA_192_CTR, CAMELLIA_256_CTR
17+
* [x] CAMELLIA_128_CFB1, CAMELLIA_128_CFB8, CAMELLIA_128_CFB128, CAMELLIA_192_CFB1, CAMELLIA_192_CFB8, CAMELLIA_192_CFB128, CAMELLIA_256_CFB1, CAMELLIA_256_CFB8, CAMELLIA_256_CFB128
18+
* [x] CAMELLIA_128_OFB, CAMELLIA_192_OFB, CAMELLIA_256_OFB
19+
* [x] RC4
20+
* [x] CHACHA20 (IETF Version)
2121

2222
AEAD Ciphers:
2323

24-
* AES_128_CCM, AES_256_CCM
25-
* AES_128_OCB_TAGLEN128, AES_192_OCB_TAGLEN128, AES_256_OCB_TAGLEN128
26-
* AES_128_GCM, AES_256_GCM
27-
* AES_SIV_CMAC_256, AES_SIV_CMAC_384, AES_SIV_CMAC_512
28-
* AES_128_GCM_SIV, AES_256_GCM_SIV
29-
* CHACHA20_POLY1305 (IETF Version)
30-
* XCHACHA20_POLY1305 (IETF Version)
24+
* [x] AES_128_CCM, AES_256_CCM
25+
* [x] AES_128_GCM, AES_256_GCM
26+
* [x] AES_128_GCM_SIV, AES_256_GCM_SIV
27+
* [x] CHACHA20_POLY1305 (IETF Version)
28+
* [x] XCHACHA20_POLY1305 (IETF Version)
29+
* [ ] AES_128_OCB_TAGLEN128, AES_192_OCB_TAGLEN128, AES_256_OCB_TAGLEN128
30+
* [ ] AES_SIV_CMAC_256, AES_SIV_CMAC_384, AES_SIV_CMAC_512

Diff for: src/v1/aeadcipher/mod.rs

+24-71
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
pub use crypto2::aeadcipher::{
2-
Aes128Ccm, Aes128GcmSiv, Aes128OcbTag128, Aes192OcbTag128, Aes256Ccm, Aes256GcmSiv,
3-
Aes256OcbTag128, AesSivCmac256, AesSivCmac384, AesSivCmac512, Sm4Ccm, Sm4Gcm,
4-
};
1+
pub use crypto2::aeadcipher::{Aes128Ccm, Aes128GcmSiv, Aes256Ccm, Aes256GcmSiv, Sm4Ccm, Sm4Gcm};
52
#[cfg(not(all(
63
any(
74
target_arch = "x86",
@@ -37,13 +34,14 @@ trait AeadCipherExt {
3734
fn ac_n_min(&self) -> usize;
3835
fn ac_n_max(&self) -> usize;
3936
fn ac_tag_len(&self) -> usize;
37+
fn ac_n_len(&self) -> usize;
4038

4139
fn ac_encrypt_slice(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]);
4240
fn ac_decrypt_slice(&self, nonce: &[u8], ciphertext_in_plaintext_out: &mut [u8]) -> bool;
4341
}
4442

4543
macro_rules! impl_aead_cipher {
46-
($name:tt, $kind:tt) => {
44+
($name:tt, $kind:tt $(, $nlen:expr)?) => {
4745
impl AeadCipherExt for $name {
4846
fn ac_kind(&self) -> CipherKind {
4947
CipherKind::$kind
@@ -63,6 +61,7 @@ macro_rules! impl_aead_cipher {
6361
fn ac_tag_len(&self) -> usize {
6462
$name::TAG_LEN
6563
}
64+
impl_aead_cipher!(ac_n_len $(, $nlen)?);
6665

6766
fn ac_encrypt_slice(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
6867
self.encrypt_slice(nonce, &[], plaintext_in_ciphertext_out);
@@ -77,50 +76,17 @@ macro_rules! impl_aead_cipher {
7776
}
7877
}
7978
};
80-
}
81-
82-
#[cfg(feature = "v1-aead-extra")]
83-
macro_rules! impl_siv_cmac_cipher {
84-
($name:tt, $kind:tt) => {
85-
impl AeadCipherExt for $name {
86-
fn ac_kind(&self) -> CipherKind {
87-
CipherKind::$kind
88-
}
89-
fn ac_key_len(&self) -> usize {
90-
$name::KEY_LEN
91-
}
92-
fn ac_block_len(&self) -> usize {
93-
$name::BLOCK_LEN
94-
}
95-
fn ac_n_min(&self) -> usize {
96-
$name::N_MIN
97-
}
98-
fn ac_n_max(&self) -> usize {
99-
$name::N_MAX
100-
}
101-
fn ac_tag_len(&self) -> usize {
102-
$name::TAG_LEN
103-
}
104-
105-
// NOTE: SIV-CMAC 模式,Nonce 在 AAD 数据的最后面。
106-
// TAG 默认也在 PKT 的前面,为此我们这里需要手动把 TAG 数据放置在 密文的后面。
107-
fn ac_encrypt_slice(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
108-
let len = plaintext_in_ciphertext_out.len();
109-
let plen = len - Self::TAG_LEN;
110-
let (plaintext, tag_out) = plaintext_in_ciphertext_out.split_at_mut(plen);
111-
self.encrypt_slice_detached(&[nonce], plaintext, tag_out);
112-
}
11379

114-
fn ac_decrypt_slice(
115-
&self,
116-
nonce: &[u8],
117-
ciphertext_in_plaintext_out: &mut [u8],
118-
) -> bool {
119-
let len = ciphertext_in_plaintext_out.len();
120-
let clen = len - Self::TAG_LEN;
121-
let (ciphertext, tag_in) = ciphertext_in_plaintext_out.split_at_mut(clen);
122-
self.decrypt_slice_detached(&[nonce], ciphertext, &tag_in)
123-
}
80+
(ac_n_len) => {
81+
fn ac_n_len(&self) -> usize {
82+
debug_assert_eq!(self.ac_n_min(), self.ac_n_max());
83+
self.ac_n_max()
84+
}
85+
};
86+
(ac_n_len, $nlen:expr) => {
87+
fn ac_n_len(&self) -> usize {
88+
debug_assert!($nlen >= self.ac_n_min() && $nlen <= self.ac_n_max());
89+
$nlen
12490
}
12591
};
12692
}
@@ -138,22 +104,8 @@ impl_aead_cipher!(Aes128GcmSiv, AES_128_GCM_SIV);
138104
#[cfg(feature = "v1-aead-extra")]
139105
impl_aead_cipher!(Aes256GcmSiv, AES_256_GCM_SIV);
140106

141-
#[cfg(feature = "v1-aead-extra")]
142-
impl_aead_cipher!(Aes128OcbTag128, AES_128_OCB_TAGLEN128);
143-
#[cfg(feature = "v1-aead-extra")]
144-
impl_aead_cipher!(Aes192OcbTag128, AES_192_OCB_TAGLEN128);
145-
#[cfg(feature = "v1-aead-extra")]
146-
impl_aead_cipher!(Aes256OcbTag128, AES_256_OCB_TAGLEN128);
147-
148107
impl_aead_cipher!(Chacha20Poly1305, CHACHA20_POLY1305);
149108

150-
#[cfg(feature = "v1-aead-extra")]
151-
impl_siv_cmac_cipher!(AesSivCmac256, AES_SIV_CMAC_256);
152-
#[cfg(feature = "v1-aead-extra")]
153-
impl_siv_cmac_cipher!(AesSivCmac384, AES_SIV_CMAC_384);
154-
#[cfg(feature = "v1-aead-extra")]
155-
impl_siv_cmac_cipher!(AesSivCmac512, AES_SIV_CMAC_512);
156-
157109
#[cfg(feature = "v1-aead-extra")]
158110
impl_aead_cipher!(XChacha20Poly1305, XCHACHA20_POLY1305);
159111

@@ -235,6 +187,14 @@ macro_rules! aead_cipher_variant {
235187
)+
236188
}
237189
}
190+
fn ac_n_len(&self) -> usize {
191+
match *self {
192+
$(
193+
$(#[cfg($i_meta)])?
194+
AeadCipherInner::$name(ref c) => c.ac_n_len(),
195+
)+
196+
}
197+
}
238198

239199
fn ac_encrypt_slice(&self, nonce: &[u8], plaintext_in_ciphertext_out: &mut [u8]) {
240200
match *self {
@@ -261,17 +221,9 @@ aead_cipher_variant! {
261221
#[cfg(feature = "v1-aead-extra")] Aes128Ccm @ AES_128_CCM,
262222
#[cfg(feature = "v1-aead-extra")] Aes256Ccm @ AES_256_CCM,
263223

264-
#[cfg(feature = "v1-aead-extra")] Aes128OcbTag128 @ AES_128_OCB_TAGLEN128,
265-
#[cfg(feature = "v1-aead-extra")] Aes192OcbTag128 @ AES_192_OCB_TAGLEN128,
266-
#[cfg(feature = "v1-aead-extra")] Aes256OcbTag128 @ AES_256_OCB_TAGLEN128,
267-
268224
Aes128Gcm @ AES_128_GCM,
269225
Aes256Gcm @ AES_256_GCM,
270226

271-
#[cfg(feature = "v1-aead-extra")] AesSivCmac256 @ AES_SIV_CMAC_256,
272-
#[cfg(feature = "v1-aead-extra")] AesSivCmac384 @ AES_SIV_CMAC_384,
273-
#[cfg(feature = "v1-aead-extra")] AesSivCmac512 @ AES_SIV_CMAC_512,
274-
275227
#[cfg(feature = "v1-aead-extra")] Aes128GcmSiv @ AES_128_GCM_SIV,
276228
#[cfg(feature = "v1-aead-extra")] Aes256GcmSiv @ AES_256_GCM_SIV,
277229

@@ -294,7 +246,8 @@ impl AeadCipher {
294246

295247
pub fn new(kind: CipherKind, key: &[u8]) -> Self {
296248
let cipher = AeadCipherInner::new(kind, key);
297-
let nlen = std::cmp::min(cipher.ac_n_max(), Self::N_MAX);
249+
let nlen = cipher.ac_n_len();
250+
debug_assert!(nlen <= Self::N_MAX);
298251
let nonce = [0u8; Self::N_MAX];
299252

300253
Self {

Diff for: src/v1/aeadcipher/xchacha20_poly1305/xchacha20.rs

+28-30
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ impl XChacha20 {
4444
pub const BLOCK_LEN: usize = 64;
4545
pub const NONCE_LEN: usize = 24;
4646

47+
#[allow(dead_code)]
4748
const CHACHA20_NONCE_LEN: usize = 12;
4849
const STATE_LEN: usize = 16; // len in doubleword (32-bits)
4950

@@ -90,11 +91,11 @@ impl XChacha20 {
9091
let mut initial_state = self.initial_state;
9192

9293
// Nonce (128-bits, little-endian)
93-
initial_state[12] = u32::from_le_bytes([nonce[ 0], nonce[ 1], nonce[ 2], nonce[ 3]]);
94-
initial_state[13] = u32::from_le_bytes([nonce[ 4], nonce[ 5], nonce[ 6], nonce[ 7]]);
95-
initial_state[14] = u32::from_le_bytes([nonce[ 8], nonce[ 9], nonce[10], nonce[11]]);
94+
initial_state[12] = u32::from_le_bytes([nonce[0], nonce[1], nonce[2], nonce[3]]);
95+
initial_state[13] = u32::from_le_bytes([nonce[4], nonce[5], nonce[6], nonce[7]]);
96+
initial_state[14] = u32::from_le_bytes([nonce[8], nonce[9], nonce[10], nonce[11]]);
9697
initial_state[15] = u32::from_le_bytes([nonce[12], nonce[13], nonce[14], nonce[15]]);
97-
98+
9899
// 20 rounds (diagonal rounds)
99100
diagonal_rounds(&mut initial_state);
100101

@@ -115,25 +116,25 @@ impl XChacha20 {
115116
#[inline]
116117
fn in_place(&self, init_block_counter: u32, nonce: &[u8], plaintext_or_ciphertext: &mut [u8]) {
117118
debug_assert_eq!(nonce.len(), Self::NONCE_LEN);
118-
119+
119120
let mut initial_state = self.initial_state;
120121
let subkey = self.hchacha20(&nonce[..16]);
121-
122+
122123
// NOTE: 使用 HChaCha20 生成的 256-bits Key.
123-
initial_state[ 4] = subkey[0];
124-
initial_state[ 5] = subkey[1];
125-
initial_state[ 6] = subkey[2];
126-
initial_state[ 7] = subkey[3];
127-
initial_state[ 8] = subkey[4];
128-
initial_state[ 9] = subkey[5];
124+
initial_state[4] = subkey[0];
125+
initial_state[5] = subkey[1];
126+
initial_state[6] = subkey[2];
127+
initial_state[7] = subkey[3];
128+
initial_state[8] = subkey[4];
129+
initial_state[9] = subkey[5];
129130
initial_state[10] = subkey[6];
130131
initial_state[11] = subkey[7];
131-
132+
132133
// ChaCha20 Counter (32-bits, little-endian)
133134
initial_state[12] = init_block_counter;
134135

135136
// ChaCha20 Nonce (96-bits, little-endian)
136-
//
137+
//
137138
// NOTE: 重新组装 12 Bytes 的 Chacha20 Nonce
138139
// [0, 0, 0, 0] + nonce[16..24]
139140
// ------------ -------------
@@ -142,15 +143,12 @@ impl XChacha20 {
142143
if cfg!(target_endian = "little") {
143144
let tmp = &nonce[16..24]; // 8 Bytes
144145
unsafe {
145-
let data: &[u32] = std::slice::from_raw_parts(
146-
tmp.as_ptr() as *const u32,
147-
2,
148-
);
146+
let data: &[u32] = std::slice::from_raw_parts(tmp.as_ptr() as *const u32, 2);
149147
initial_state[14..16].copy_from_slice(data);
150148
}
151149
} else {
152-
initial_state[14] = u32::from_le_bytes([nonce[ 4], nonce[ 5], nonce[ 6], nonce[ 7]]);
153-
initial_state[15] = u32::from_le_bytes([nonce[ 8], nonce[ 9], nonce[10], nonce[11]]);
150+
initial_state[14] = u32::from_le_bytes([nonce[4], nonce[5], nonce[6], nonce[7]]);
151+
initial_state[15] = u32::from_le_bytes([nonce[8], nonce[9], nonce[10], nonce[11]]);
154152
}
155153

156154
let mut chunks = plaintext_or_ciphertext.chunks_exact_mut(Self::BLOCK_LEN);
@@ -284,16 +282,16 @@ fn state_to_keystream(
284282
state: &[u32; XChacha20::STATE_LEN],
285283
keystream: &mut [u8; XChacha20::BLOCK_LEN],
286284
) {
287-
keystream[ 0.. 4].copy_from_slice(&state[ 0].to_le_bytes());
288-
keystream[ 4.. 8].copy_from_slice(&state[ 1].to_le_bytes());
289-
keystream[ 8..12].copy_from_slice(&state[ 2].to_le_bytes());
290-
keystream[12..16].copy_from_slice(&state[ 3].to_le_bytes());
291-
keystream[16..20].copy_from_slice(&state[ 4].to_le_bytes());
292-
keystream[20..24].copy_from_slice(&state[ 5].to_le_bytes());
293-
keystream[24..28].copy_from_slice(&state[ 6].to_le_bytes());
294-
keystream[28..32].copy_from_slice(&state[ 7].to_le_bytes());
295-
keystream[32..36].copy_from_slice(&state[ 8].to_le_bytes());
296-
keystream[36..40].copy_from_slice(&state[ 9].to_le_bytes());
285+
keystream[0..4].copy_from_slice(&state[0].to_le_bytes());
286+
keystream[4..8].copy_from_slice(&state[1].to_le_bytes());
287+
keystream[8..12].copy_from_slice(&state[2].to_le_bytes());
288+
keystream[12..16].copy_from_slice(&state[3].to_le_bytes());
289+
keystream[16..20].copy_from_slice(&state[4].to_le_bytes());
290+
keystream[20..24].copy_from_slice(&state[5].to_le_bytes());
291+
keystream[24..28].copy_from_slice(&state[6].to_le_bytes());
292+
keystream[28..32].copy_from_slice(&state[7].to_le_bytes());
293+
keystream[32..36].copy_from_slice(&state[8].to_le_bytes());
294+
keystream[36..40].copy_from_slice(&state[9].to_le_bytes());
297295
keystream[40..44].copy_from_slice(&state[10].to_le_bytes());
298296
keystream[44..48].copy_from_slice(&state[11].to_le_bytes());
299297
keystream[48..52].copy_from_slice(&state[12].to_le_bytes());

Diff for: src/v1/cipher.rs

-12
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,6 @@ pub const fn available_ciphers() -> &'static [&'static str] {
112112
#[cfg(feature = "v1-aead-extra")]
113113
"aes-256-gcm-siv",
114114
#[cfg(feature = "v1-aead-extra")]
115-
"aes-128-ocb-taglen128",
116-
#[cfg(feature = "v1-aead-extra")]
117-
"aes-192-ocb-taglen128",
118-
#[cfg(feature = "v1-aead-extra")]
119-
"aes-256-ocb-taglen128",
120-
#[cfg(feature = "v1-aead-extra")]
121-
"aes-siv-cmac-256",
122-
#[cfg(feature = "v1-aead-extra")]
123-
"aes-siv-cmac-384",
124-
#[cfg(feature = "v1-aead-extra")]
125-
"aes-siv-cmac-512",
126-
#[cfg(feature = "v1-aead-extra")]
127115
"xchacha20-ietf-poly1305",
128116
#[cfg(feature = "v1-aead-extra")]
129117
"sm4-gcm",

0 commit comments

Comments
 (0)