Skip to content

Commit 1f94514

Browse files
authored
Implement ChaCha20_Poly1305 cipher suite (#675)
* Allow ciphersuite to be chosen on commandline in dial_selfsign example * chacha20 support for webrtc-dtls * support cipher suite for chacha20, but don't prefer it
1 parent 0f2db13 commit 1f94514

File tree

7 files changed

+349
-0
lines changed

7 files changed

+349
-0
lines changed

Cargo.lock

Lines changed: 37 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dtls/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ log = "0.4"
5252
thiserror = "1"
5353
pem = { version = "3", optional = true }
5454
portable-atomic = "1.6"
55+
chacha20poly1305 = "0.10.1"
5556

5657
[dev-dependencies]
5758
tokio-test = "0.4"

dtls/examples/dial/selfsign/dial_selfsign.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ async fn main() -> Result<(), Error> {
4646
.default_value("127.0.0.1:4444")
4747
.long("server")
4848
.help("DTLS Server name."),
49+
)
50+
.arg(
51+
Arg::with_name("ciphersuite")
52+
.takes_value(true)
53+
.long("ciphersuite")
54+
.help("Force a single ciphersuite."),
4955
);
5056

5157
let matches = app.clone().get_matches();
@@ -68,6 +74,11 @@ async fn main() -> Result<(), Error> {
6874
certificates: vec![certificate],
6975
insecure_skip_verify: true,
7076
extended_master_secret: ExtendedMasterSecretType::Require,
77+
cipher_suites: if matches.is_present("ciphersuite") {
78+
vec![matches.value_of("ciphersuite").unwrap().into()]
79+
} else {
80+
vec![]
81+
},
7182
..Default::default()
7283
};
7384
let dtls_conn: Arc<dyn Conn + Send + Sync> =
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
use super::*;
2+
use crate::crypto::crypto_chacha20::*;
3+
use crate::prf::*;
4+
5+
#[derive(Clone)]
6+
pub struct CipherSuiteChaCha20Poly1305Sha256 {
7+
rsa: bool,
8+
cipher: Option<CryptoChaCha20>,
9+
}
10+
11+
impl CipherSuiteChaCha20Poly1305Sha256 {
12+
const PRF_MAC_LEN: usize = 0;
13+
const PRF_KEY_LEN: usize = 32;
14+
const PRF_IV_LEN: usize = 12;
15+
16+
pub fn new(rsa: bool) -> Self {
17+
CipherSuiteChaCha20Poly1305Sha256 {
18+
rsa: rsa,
19+
cipher: None,
20+
}
21+
}
22+
}
23+
24+
impl CipherSuite for CipherSuiteChaCha20Poly1305Sha256 {
25+
fn to_string(&self) -> String {
26+
if self.rsa {
27+
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256".to_owned()
28+
} else {
29+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256".to_owned()
30+
}
31+
}
32+
33+
fn id(&self) -> CipherSuiteId {
34+
if self.rsa {
35+
CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256
36+
} else {
37+
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256
38+
}
39+
}
40+
41+
fn certificate_type(&self) -> ClientCertificateType {
42+
if self.rsa {
43+
ClientCertificateType::RsaSign
44+
} else {
45+
ClientCertificateType::EcdsaSign
46+
}
47+
}
48+
49+
fn hash_func(&self) -> CipherSuiteHash {
50+
CipherSuiteHash::Sha256
51+
}
52+
53+
fn is_psk(&self) -> bool {
54+
false
55+
}
56+
57+
fn is_initialized(&self) -> bool {
58+
self.cipher.is_some()
59+
}
60+
61+
fn init(
62+
&mut self,
63+
master_secret: &[u8],
64+
client_random: &[u8],
65+
server_random: &[u8],
66+
is_client: bool,
67+
) -> Result<()> {
68+
let keys = prf_encryption_keys(
69+
master_secret,
70+
client_random,
71+
server_random,
72+
CipherSuiteChaCha20Poly1305Sha256::PRF_MAC_LEN,
73+
CipherSuiteChaCha20Poly1305Sha256::PRF_KEY_LEN,
74+
CipherSuiteChaCha20Poly1305Sha256::PRF_IV_LEN,
75+
self.hash_func(),
76+
)?;
77+
78+
if is_client {
79+
self.cipher = Some(CryptoChaCha20::new(
80+
&keys.client_write_key,
81+
&keys.client_write_iv,
82+
&keys.server_write_key,
83+
&keys.server_write_iv,
84+
));
85+
} else {
86+
self.cipher = Some(CryptoChaCha20::new(
87+
&keys.server_write_key,
88+
&keys.server_write_iv,
89+
&keys.client_write_key,
90+
&keys.client_write_iv,
91+
));
92+
}
93+
94+
Ok(())
95+
}
96+
97+
fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
98+
if let Some(cg) = &self.cipher {
99+
cg.encrypt(pkt_rlh, raw)
100+
} else {
101+
Err(Error::Other(
102+
"CipherSuite has not been initialized, unable to encrypt".to_owned(),
103+
))
104+
}
105+
}
106+
107+
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>> {
108+
if let Some(cg) = &self.cipher {
109+
cg.decrypt(input)
110+
} else {
111+
Err(Error::Other(
112+
"CipherSuite has not been initialized, unable to decrypt".to_owned(),
113+
))
114+
}
115+
}
116+
}

dtls/src/cipher_suite/mod.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod cipher_suite_aes_128_ccm;
22
pub mod cipher_suite_aes_128_gcm_sha256;
33
pub mod cipher_suite_aes_256_cbc_sha;
4+
pub mod cipher_suite_chacha20_poly1305_sha256;
45
pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm;
56
pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8;
67
pub mod cipher_suite_tls_psk_with_aes_128_ccm;
@@ -12,6 +13,7 @@ use std::marker::{Send, Sync};
1213

1314
use cipher_suite_aes_128_gcm_sha256::*;
1415
use cipher_suite_aes_256_cbc_sha::*;
16+
use cipher_suite_chacha20_poly1305_sha256::*;
1517
use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm::*;
1618
use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8::*;
1719
use cipher_suite_tls_psk_with_aes_128_ccm::*;
@@ -43,6 +45,10 @@ pub enum CipherSuiteId {
4345
Tls_Psk_With_Aes_128_Ccm_8 = 0xc0a8,
4446
Tls_Psk_With_Aes_128_Gcm_Sha256 = 0x00a8,
4547

48+
// CHACHA20_POLY1305_SHA256
49+
Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 = 0xcca8,
50+
Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 = 0xcca9,
51+
4652
Unsupported,
4753
}
4854

@@ -72,6 +78,13 @@ impl fmt::Display for CipherSuiteId {
7278
CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
7379
write!(f, "TLS_PSK_WITH_AES_128_GCM_SHA256")
7480
}
81+
CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 => {
82+
write!(f, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256")
83+
}
84+
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 => {
85+
write!(f, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
86+
}
87+
7588
_ => write!(f, "Unsupported CipherSuiteID"),
7689
}
7790
}
@@ -96,6 +109,43 @@ impl From<u16> for CipherSuiteId {
96109
0xc0a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
97110
0x00a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
98111

112+
// CHACHA20_POLY1305_SHA256
113+
0xcca8 => CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256,
114+
0xcca9 => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256,
115+
116+
_ => CipherSuiteId::Unsupported,
117+
}
118+
}
119+
}
120+
121+
impl From<&str> for CipherSuiteId {
122+
fn from(val: &str) -> Self {
123+
match val {
124+
"TLS_ECDHE_ECDSA_WITH_AES_128_CCM" => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
125+
"TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" => {
126+
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8
127+
}
128+
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => {
129+
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256
130+
}
131+
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" => {
132+
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256
133+
}
134+
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" => {
135+
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha
136+
}
137+
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" => {
138+
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha
139+
}
140+
"TLS_PSK_WITH_AES_128_CCM" => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
141+
"TLS_PSK_WITH_AES_128_CCM_8" => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
142+
"TLS_PSK_WITH_AES_128_GCM_SHA256" => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
143+
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => {
144+
CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256
145+
}
146+
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => {
147+
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256
148+
}
99149
_ => CipherSuiteId::Unsupported,
100150
}
101151
}
@@ -167,6 +217,13 @@ pub fn cipher_suite_for_id(id: CipherSuiteId) -> Result<Box<dyn CipherSuite + Se
167217
CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
168218
Ok(Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default())
169219
}
220+
CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 => {
221+
Ok(Box::new(CipherSuiteChaCha20Poly1305Sha256::new(true)))
222+
}
223+
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 => {
224+
Ok(Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)))
225+
}
226+
170227
_ => Err(Error::ErrInvalidCipherSuite),
171228
}
172229
}
@@ -178,6 +235,7 @@ pub(crate) fn default_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>>
178235
Box::new(CipherSuiteAes256CbcSha::new(false)),
179236
Box::new(CipherSuiteAes128GcmSha256::new(true)),
180237
Box::new(CipherSuiteAes256CbcSha::new(true)),
238+
Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)),
181239
]
182240
}
183241

@@ -192,6 +250,8 @@ fn all_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>> {
192250
Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()),
193251
Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()),
194252
Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default(),
253+
Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)),
254+
Box::new(CipherSuiteChaCha20Poly1305Sha256::new(true)),
195255
]
196256
}
197257

0 commit comments

Comments
 (0)