refactor: 将 DTLS 本地依赖迁移到 libs 目录

This commit is contained in:
mofeng-git
2026-10-01 22:46:36 +08:00
parent 2f60e61dd5
commit 4f59e78179
99 changed files with 2 additions and 2 deletions

View File

@@ -0,0 +1,112 @@
use super::*;
use crate::client_certificate_type::ClientCertificateType;
use crate::crypto::crypto_ccm::{CryptoCcm, CryptoCcmTagLen};
use crate::prf::*;
#[derive(Clone)]
pub struct CipherSuiteAes128Ccm {
ccm: Option<CryptoCcm>,
client_certificate_type: ClientCertificateType,
id: CipherSuiteId,
psk: bool,
crypto_ccm_tag_len: CryptoCcmTagLen,
}
impl CipherSuiteAes128Ccm {
const PRF_MAC_LEN: usize = 0;
const PRF_KEY_LEN: usize = 16;
const PRF_IV_LEN: usize = 4;
pub fn new(
client_certificate_type: ClientCertificateType,
id: CipherSuiteId,
psk: bool,
crypto_ccm_tag_len: CryptoCcmTagLen,
) -> Self {
CipherSuiteAes128Ccm {
ccm: None,
client_certificate_type,
id,
psk,
crypto_ccm_tag_len,
}
}
}
impl CipherSuite for CipherSuiteAes128Ccm {
fn to_string(&self) -> String {
format!("{}", self.id)
}
fn id(&self) -> CipherSuiteId {
self.id
}
fn certificate_type(&self) -> ClientCertificateType {
self.client_certificate_type
}
fn hash_func(&self) -> CipherSuiteHash {
CipherSuiteHash::Sha256
}
fn is_psk(&self) -> bool {
self.psk
}
fn is_initialized(&self) -> bool {
self.ccm.is_some()
}
fn init(
&mut self,
master_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
is_client: bool,
) -> Result<()> {
let keys = prf_encryption_keys(
master_secret,
client_random,
server_random,
CipherSuiteAes128Ccm::PRF_MAC_LEN,
CipherSuiteAes128Ccm::PRF_KEY_LEN,
CipherSuiteAes128Ccm::PRF_IV_LEN,
self.hash_func(),
)?;
if is_client {
self.ccm = Some(CryptoCcm::new(
&self.crypto_ccm_tag_len,
&keys.client_write_key,
&keys.client_write_iv,
&keys.server_write_key,
&keys.server_write_iv,
));
} else {
self.ccm = Some(CryptoCcm::new(
&self.crypto_ccm_tag_len,
&keys.server_write_key,
&keys.server_write_iv,
&keys.client_write_key,
&keys.client_write_iv,
));
}
Ok(())
}
fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
let ccm = self.ccm.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to encrypt".to_owned(),
))?;
ccm.encrypt(pkt_rlh, raw)
}
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>> {
let ccm = self.ccm.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to decrypt".to_owned(),
))?;
ccm.decrypt(input)
}
}

View File

@@ -0,0 +1,107 @@
use super::*;
use crate::crypto::crypto_gcm::*;
use crate::prf::*;
#[derive(Clone)]
pub struct CipherSuiteAes128GcmSha256 {
gcm: Option<CryptoGcm>,
rsa: bool,
}
impl CipherSuiteAes128GcmSha256 {
const PRF_MAC_LEN: usize = 0;
const PRF_KEY_LEN: usize = 16;
const PRF_IV_LEN: usize = 4;
pub fn new(rsa: bool) -> Self {
CipherSuiteAes128GcmSha256 { gcm: None, rsa }
}
}
impl CipherSuite for CipherSuiteAes128GcmSha256 {
fn to_string(&self) -> String {
if self.rsa {
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256".to_owned()
} else {
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256".to_owned()
}
}
fn id(&self) -> CipherSuiteId {
if self.rsa {
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256
} else {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256
}
}
fn certificate_type(&self) -> ClientCertificateType {
if self.rsa {
ClientCertificateType::RsaSign
} else {
ClientCertificateType::EcdsaSign
}
}
fn hash_func(&self) -> CipherSuiteHash {
CipherSuiteHash::Sha256
}
fn is_psk(&self) -> bool {
false
}
fn is_initialized(&self) -> bool {
self.gcm.is_some()
}
fn init(
&mut self,
master_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
is_client: bool,
) -> Result<()> {
let keys = prf_encryption_keys(
master_secret,
client_random,
server_random,
CipherSuiteAes128GcmSha256::PRF_MAC_LEN,
CipherSuiteAes128GcmSha256::PRF_KEY_LEN,
CipherSuiteAes128GcmSha256::PRF_IV_LEN,
self.hash_func(),
)?;
if is_client {
self.gcm = Some(CryptoGcm::new(
&keys.client_write_key,
&keys.client_write_iv,
&keys.server_write_key,
&keys.server_write_iv,
));
} else {
self.gcm = Some(CryptoGcm::new(
&keys.server_write_key,
&keys.server_write_iv,
&keys.client_write_key,
&keys.client_write_iv,
));
}
Ok(())
}
fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
let cg = self.gcm.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to encrypt".to_owned(),
))?;
cg.encrypt(pkt_rlh, raw)
}
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>> {
let cg = self.gcm.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to decrypt".to_owned(),
))?;
cg.decrypt(input)
}
}

View File

@@ -0,0 +1,107 @@
use super::*;
use crate::crypto::crypto_cbc::*;
use crate::prf::*;
#[derive(Clone)]
pub struct CipherSuiteAes256CbcSha {
cbc: Option<CryptoCbc>,
rsa: bool,
}
impl CipherSuiteAes256CbcSha {
const PRF_MAC_LEN: usize = 20;
const PRF_KEY_LEN: usize = 32;
const PRF_IV_LEN: usize = 16;
pub fn new(rsa: bool) -> Self {
CipherSuiteAes256CbcSha { cbc: None, rsa }
}
}
impl CipherSuite for CipherSuiteAes256CbcSha {
fn to_string(&self) -> String {
if self.rsa {
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA".to_owned()
} else {
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA".to_owned()
}
}
fn id(&self) -> CipherSuiteId {
if self.rsa {
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha
} else {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha
}
}
fn certificate_type(&self) -> ClientCertificateType {
if self.rsa {
ClientCertificateType::RsaSign
} else {
ClientCertificateType::EcdsaSign
}
}
fn hash_func(&self) -> CipherSuiteHash {
CipherSuiteHash::Sha256
}
fn is_psk(&self) -> bool {
false
}
fn is_initialized(&self) -> bool {
self.cbc.is_some()
}
fn init(
&mut self,
master_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
is_client: bool,
) -> Result<()> {
let keys = prf_encryption_keys(
master_secret,
client_random,
server_random,
CipherSuiteAes256CbcSha::PRF_MAC_LEN,
CipherSuiteAes256CbcSha::PRF_KEY_LEN,
CipherSuiteAes256CbcSha::PRF_IV_LEN,
self.hash_func(),
)?;
if is_client {
self.cbc = Some(CryptoCbc::new(
&keys.client_write_key,
&keys.client_mac_key,
&keys.server_write_key,
&keys.server_mac_key,
)?);
} else {
self.cbc = Some(CryptoCbc::new(
&keys.server_write_key,
&keys.server_mac_key,
&keys.client_write_key,
&keys.client_mac_key,
)?);
}
Ok(())
}
fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
let cg = self.cbc.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to encrypt".to_owned(),
))?;
cg.encrypt(pkt_rlh, raw)
}
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>> {
let cg = self.cbc.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to decrypt".to_owned(),
))?;
cg.decrypt(input)
}
}

View File

@@ -0,0 +1,107 @@
use super::*;
use crate::crypto::crypto_chacha20::*;
use crate::prf::*;
#[derive(Clone)]
pub struct CipherSuiteChaCha20Poly1305Sha256 {
rsa: bool,
cipher: Option<CryptoChaCha20>,
}
impl CipherSuiteChaCha20Poly1305Sha256 {
const PRF_MAC_LEN: usize = 0;
const PRF_KEY_LEN: usize = 32;
const PRF_IV_LEN: usize = 12;
pub fn new(rsa: bool) -> Self {
CipherSuiteChaCha20Poly1305Sha256 { rsa, cipher: None }
}
}
impl CipherSuite for CipherSuiteChaCha20Poly1305Sha256 {
fn to_string(&self) -> String {
if self.rsa {
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256".to_owned()
} else {
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256".to_owned()
}
}
fn id(&self) -> CipherSuiteId {
if self.rsa {
CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256
} else {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256
}
}
fn certificate_type(&self) -> ClientCertificateType {
if self.rsa {
ClientCertificateType::RsaSign
} else {
ClientCertificateType::EcdsaSign
}
}
fn hash_func(&self) -> CipherSuiteHash {
CipherSuiteHash::Sha256
}
fn is_psk(&self) -> bool {
false
}
fn is_initialized(&self) -> bool {
self.cipher.is_some()
}
fn init(
&mut self,
master_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
is_client: bool,
) -> Result<()> {
let keys = prf_encryption_keys(
master_secret,
client_random,
server_random,
CipherSuiteChaCha20Poly1305Sha256::PRF_MAC_LEN,
CipherSuiteChaCha20Poly1305Sha256::PRF_KEY_LEN,
CipherSuiteChaCha20Poly1305Sha256::PRF_IV_LEN,
self.hash_func(),
)?;
if is_client {
self.cipher = Some(CryptoChaCha20::new(
&keys.client_write_key,
&keys.client_write_iv,
&keys.server_write_key,
&keys.server_write_iv,
));
} else {
self.cipher = Some(CryptoChaCha20::new(
&keys.server_write_key,
&keys.server_write_iv,
&keys.client_write_key,
&keys.client_write_iv,
));
}
Ok(())
}
fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
let cg = self.cipher.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to encrypt".to_owned(),
))?;
cg.encrypt(pkt_rlh, raw)
}
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>> {
let cg = self.cipher.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to decrypt".to_owned(),
))?;
cg.decrypt(input)
}
}

View File

@@ -0,0 +1,12 @@
use super::*;
use crate::cipher_suite::cipher_suite_aes_128_ccm::CipherSuiteAes128Ccm;
use crate::crypto::crypto_ccm::CryptoCcmTagLen;
pub fn new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm() -> CipherSuiteAes128Ccm {
CipherSuiteAes128Ccm::new(
ClientCertificateType::EcdsaSign,
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
false,
CryptoCcmTagLen::CryptoCcmTagLength,
)
}

View File

@@ -0,0 +1,12 @@
use super::*;
use crate::cipher_suite::cipher_suite_aes_128_ccm::CipherSuiteAes128Ccm;
use crate::crypto::crypto_ccm::CryptoCcmTagLen;
pub fn new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8() -> CipherSuiteAes128Ccm {
CipherSuiteAes128Ccm::new(
ClientCertificateType::EcdsaSign,
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8,
false,
CryptoCcmTagLen::CryptoCcm8TagLength,
)
}

View File

@@ -0,0 +1,12 @@
use super::*;
use crate::cipher_suite::cipher_suite_aes_128_ccm::CipherSuiteAes128Ccm;
use crate::crypto::crypto_ccm::CryptoCcmTagLen;
pub fn new_cipher_suite_tls_psk_with_aes_128_ccm() -> CipherSuiteAes128Ccm {
CipherSuiteAes128Ccm::new(
ClientCertificateType::Unsupported,
CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
true,
CryptoCcmTagLen::CryptoCcmTagLength,
)
}

View File

@@ -0,0 +1,12 @@
use super::*;
use crate::cipher_suite::cipher_suite_aes_128_ccm::CipherSuiteAes128Ccm;
use crate::crypto::crypto_ccm::CryptoCcmTagLen;
pub fn new_cipher_suite_tls_psk_with_aes_128_ccm8() -> CipherSuiteAes128Ccm {
CipherSuiteAes128Ccm::new(
ClientCertificateType::Unsupported,
CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
true,
CryptoCcmTagLen::CryptoCcm8TagLength,
)
}

View File

@@ -0,0 +1,90 @@
use super::*;
use crate::crypto::crypto_gcm::*;
use crate::prf::*;
#[derive(Clone, Default)]
pub struct CipherSuiteTlsPskWithAes128GcmSha256 {
gcm: Option<CryptoGcm>,
}
impl CipherSuiteTlsPskWithAes128GcmSha256 {
const PRF_MAC_LEN: usize = 0;
const PRF_KEY_LEN: usize = 16;
const PRF_IV_LEN: usize = 4;
}
impl CipherSuite for CipherSuiteTlsPskWithAes128GcmSha256 {
fn to_string(&self) -> String {
"TLS_PSK_WITH_AES_128_GCM_SHA256".to_owned()
}
fn id(&self) -> CipherSuiteId {
CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256
}
fn certificate_type(&self) -> ClientCertificateType {
ClientCertificateType::Unsupported
}
fn hash_func(&self) -> CipherSuiteHash {
CipherSuiteHash::Sha256
}
fn is_psk(&self) -> bool {
true
}
fn is_initialized(&self) -> bool {
self.gcm.is_some()
}
fn init(
&mut self,
master_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
is_client: bool,
) -> Result<()> {
let keys = prf_encryption_keys(
master_secret,
client_random,
server_random,
CipherSuiteTlsPskWithAes128GcmSha256::PRF_MAC_LEN,
CipherSuiteTlsPskWithAes128GcmSha256::PRF_KEY_LEN,
CipherSuiteTlsPskWithAes128GcmSha256::PRF_IV_LEN,
self.hash_func(),
)?;
if is_client {
self.gcm = Some(CryptoGcm::new(
&keys.client_write_key,
&keys.client_write_iv,
&keys.server_write_key,
&keys.server_write_iv,
));
} else {
self.gcm = Some(CryptoGcm::new(
&keys.server_write_key,
&keys.server_write_iv,
&keys.client_write_key,
&keys.client_write_iv,
));
}
Ok(())
}
fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>> {
let cg = self.gcm.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to encrypt".to_owned(),
))?;
cg.encrypt(pkt_rlh, raw)
}
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>> {
let cg = self.gcm.as_ref().ok_or(Error::Other(
"CipherSuite has not been initialized, unable to decrypt".to_owned(),
))?;
cg.decrypt(input)
}
}

View File

@@ -0,0 +1,287 @@
pub mod cipher_suite_aes_128_ccm;
pub mod cipher_suite_aes_128_gcm_sha256;
pub mod cipher_suite_aes_256_cbc_sha;
pub mod cipher_suite_chacha20_poly1305_sha256;
pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm;
pub mod cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8;
pub mod cipher_suite_tls_psk_with_aes_128_ccm;
pub mod cipher_suite_tls_psk_with_aes_128_ccm8;
pub mod cipher_suite_tls_psk_with_aes_128_gcm_sha256;
use std::fmt;
use std::marker::{Send, Sync};
use cipher_suite_aes_128_gcm_sha256::*;
use cipher_suite_aes_256_cbc_sha::*;
use cipher_suite_chacha20_poly1305_sha256::*;
use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm::*;
use cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8::*;
use cipher_suite_tls_psk_with_aes_128_ccm::*;
use cipher_suite_tls_psk_with_aes_128_ccm8::*;
use cipher_suite_tls_psk_with_aes_128_gcm_sha256::*;
use super::client_certificate_type::*;
use super::error::*;
use super::record_layer::record_layer_header::*;
// CipherSuiteID is an ID for our supported CipherSuites
// Supported Cipher Suites
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CipherSuiteId {
// AES-128-CCM
Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm = 0xc0ac,
Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 = 0xc0ae,
// AES-128-GCM-SHA256
Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 = 0xc02b,
Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 = 0xc02f,
// AES-256-CBC-SHA
Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha = 0xc00a,
Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha = 0xc014,
Tls_Psk_With_Aes_128_Ccm = 0xc0a4,
Tls_Psk_With_Aes_128_Ccm_8 = 0xc0a8,
Tls_Psk_With_Aes_128_Gcm_Sha256 = 0x00a8,
// CHACHA20_POLY1305_SHA256
Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 = 0xcca8,
Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 = 0xcca9,
Unsupported,
}
impl fmt::Display for CipherSuiteId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM")
}
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => {
write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8")
}
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
write!(f, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256")
}
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
write!(f, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
}
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
write!(f, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA")
}
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
write!(f, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA")
}
CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => write!(f, "TLS_PSK_WITH_AES_128_CCM"),
CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => write!(f, "TLS_PSK_WITH_AES_128_CCM_8"),
CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
write!(f, "TLS_PSK_WITH_AES_128_GCM_SHA256")
}
CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 => {
write!(f, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256")
}
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 => {
write!(f, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256")
}
_ => write!(f, "Unsupported CipherSuiteID"),
}
}
}
impl From<u16> for CipherSuiteId {
fn from(val: u16) -> Self {
match val {
// AES-128-CCM
0xc0ac => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
0xc0ae => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8,
// AES-128-GCM-SHA256
0xc02b => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256,
0xc02f => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256,
// AES-256-CBC-SHA
0xc00a => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha,
0xc014 => CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha,
0xc0a4 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
0xc0a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
0x00a8 => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
// CHACHA20_POLY1305_SHA256
0xcca8 => CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256,
0xcca9 => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256,
_ => CipherSuiteId::Unsupported,
}
}
}
impl From<&str> for CipherSuiteId {
fn from(val: &str) -> Self {
match val {
"TLS_ECDHE_ECDSA_WITH_AES_128_CCM" => CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm,
"TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" => {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8
}
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256
}
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" => {
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256
}
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" => {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha
}
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" => {
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha
}
"TLS_PSK_WITH_AES_128_CCM" => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm,
"TLS_PSK_WITH_AES_128_CCM_8" => CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8,
"TLS_PSK_WITH_AES_128_GCM_SHA256" => CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256,
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => {
CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256
}
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256
}
_ => CipherSuiteId::Unsupported,
}
}
}
#[derive(Copy, Clone, Debug)]
pub enum CipherSuiteHash {
Sha256,
}
impl CipherSuiteHash {
pub(crate) fn size(&self) -> usize {
match *self {
CipherSuiteHash::Sha256 => 32,
}
}
}
pub trait CipherSuite {
fn to_string(&self) -> String;
fn id(&self) -> CipherSuiteId;
fn certificate_type(&self) -> ClientCertificateType;
fn hash_func(&self) -> CipherSuiteHash;
fn is_psk(&self) -> bool;
fn is_initialized(&self) -> bool;
// Generate the internal encryption state
fn init(
&mut self,
master_secret: &[u8],
client_random: &[u8],
server_random: &[u8],
is_client: bool,
) -> Result<()>;
fn encrypt(&self, pkt_rlh: &RecordLayerHeader, raw: &[u8]) -> Result<Vec<u8>>;
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>>;
}
// Taken from https://www.iana.org/assignments/tls-parameters/tls-parameters.xml
// A cipher_suite is a specific combination of key agreement, cipher and MAC
// function.
pub fn cipher_suite_for_id(id: CipherSuiteId) -> Result<Box<dyn CipherSuite + Send + Sync>> {
match id {
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm => {
Ok(Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()))
}
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8 => Ok(Box::new(
new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8(),
)),
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Gcm_Sha256 => {
Ok(Box::new(CipherSuiteAes128GcmSha256::new(false)))
}
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_128_Gcm_Sha256 => {
Ok(Box::new(CipherSuiteAes128GcmSha256::new(true)))
}
CipherSuiteId::Tls_Ecdhe_Rsa_With_Aes_256_Cbc_Sha => {
Ok(Box::new(CipherSuiteAes256CbcSha::new(true)))
}
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_256_Cbc_Sha => {
Ok(Box::new(CipherSuiteAes256CbcSha::new(false)))
}
CipherSuiteId::Tls_Psk_With_Aes_128_Ccm => {
Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()))
}
CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8 => {
Ok(Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()))
}
CipherSuiteId::Tls_Psk_With_Aes_128_Gcm_Sha256 => {
Ok(Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default())
}
CipherSuiteId::Tls_Ecdhe_Rsa_With_ChaCha20_Poly1305_Sha256 => {
Ok(Box::new(CipherSuiteChaCha20Poly1305Sha256::new(true)))
}
CipherSuiteId::Tls_Ecdhe_Ecdsa_With_ChaCha20_Poly1305_Sha256 => {
Ok(Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)))
}
_ => Err(Error::ErrInvalidCipherSuite),
}
}
// CipherSuites we support in order of preference
pub(crate) fn default_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>> {
vec![
Box::new(CipherSuiteAes128GcmSha256::new(false)),
Box::new(CipherSuiteAes256CbcSha::new(false)),
Box::new(CipherSuiteAes128GcmSha256::new(true)),
Box::new(CipherSuiteAes256CbcSha::new(true)),
Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)),
]
}
fn all_cipher_suites() -> Vec<Box<dyn CipherSuite + Send + Sync>> {
vec![
Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm()),
Box::new(new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8()),
Box::new(CipherSuiteAes128GcmSha256::new(false)),
Box::new(CipherSuiteAes128GcmSha256::new(true)),
Box::new(CipherSuiteAes256CbcSha::new(false)),
Box::new(CipherSuiteAes256CbcSha::new(true)),
Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm()),
Box::new(new_cipher_suite_tls_psk_with_aes_128_ccm8()),
Box::<CipherSuiteTlsPskWithAes128GcmSha256>::default(),
Box::new(CipherSuiteChaCha20Poly1305Sha256::new(false)),
Box::new(CipherSuiteChaCha20Poly1305Sha256::new(true)),
]
}
fn cipher_suites_for_ids(ids: &[CipherSuiteId]) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>> {
let mut cipher_suites = vec![];
for id in ids {
cipher_suites.push(cipher_suite_for_id(*id)?);
}
Ok(cipher_suites)
}
pub(crate) fn parse_cipher_suites(
user_selected_suites: &[CipherSuiteId],
exclude_psk: bool,
exclude_non_psk: bool,
) -> Result<Vec<Box<dyn CipherSuite + Send + Sync>>> {
let cipher_suites = if !user_selected_suites.is_empty() {
cipher_suites_for_ids(user_selected_suites)?
} else {
default_cipher_suites()
};
let filtered_cipher_suites: Vec<Box<dyn CipherSuite + Send + Sync>> = cipher_suites
.into_iter()
.filter(|c| !((exclude_psk && c.is_psk()) || (exclude_non_psk && !c.is_psk())))
.collect();
if filtered_cipher_suites.is_empty() {
Err(Error::ErrNoAvailableCipherSuites)
} else {
Ok(filtered_cipher_suites)
}
}