Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/proto/src/crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
mod provider;
pub use provider::{AeadAes128Gcm, AeadAes128GcmCipher, AeadAes256Gcm, AeadAes256GcmCipher};
pub use provider::{Aes128CmSha1_80, Aes128CmSha1_80Cipher, CryptoProvider, CryptoSafe};
pub use provider::{DtlsVersion, Sha1HmacProvider, Sha256Provider};
pub use provider::{Dtls12CipherSuite, Dtls13CipherSuite, DtlsConfig, DtlsVersion};
pub use provider::{Sha1HmacProvider, Sha256Provider};
pub use provider::{SrtpProvider, SupportedAeadAes128Gcm};
pub use provider::{SupportedAeadAes256Gcm, SupportedAes128CmSha1_80};

Expand Down
86 changes: 84 additions & 2 deletions crates/proto/src/crypto/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,88 @@ impl fmt::Display for DtlsVersion {
}
}

// ============================================================================
// DTLS Cipher Suites
// ============================================================================

/// DTLS 1.2 cipher suites.
///
/// These are the TLS 1.2 cipher suites used in DTLS, which specify the
/// full combination of key exchange, authentication, encryption, and hash.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
#[allow(non_camel_case_types)]
pub enum Dtls12CipherSuite {
/// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xC02B).
ECDHE_ECDSA_AES128_GCM_SHA256,
/// TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xC02C).
ECDHE_ECDSA_AES256_GCM_SHA384,
/// TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xCCA9).
ECDHE_ECDSA_CHACHA20_POLY1305_SHA256,
}

#[cfg(feature = "dtls")]
impl Dtls12CipherSuite {
/// Convert to the corresponding dimpl cipher suite.
pub fn into_dimpl(self) -> dimpl::crypto::Dtls12CipherSuite {
use dimpl::crypto::Dtls12CipherSuite as D;
match self {
Self::ECDHE_ECDSA_AES128_GCM_SHA256 => D::ECDHE_ECDSA_AES128_GCM_SHA256,
Self::ECDHE_ECDSA_AES256_GCM_SHA384 => D::ECDHE_ECDSA_AES256_GCM_SHA384,
Self::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256 => D::ECDHE_ECDSA_CHACHA20_POLY1305_SHA256,
}
}
}

/// DTLS 1.3 cipher suites.
///
/// Unlike DTLS 1.2, TLS 1.3 cipher suites only specify the AEAD algorithm
/// and hash function. Key exchange is negotiated separately.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
#[allow(non_camel_case_types)]
pub enum Dtls13CipherSuite {
/// TLS_AES_128_GCM_SHA256 (0x1301).
AES_128_GCM_SHA256,
/// TLS_AES_256_GCM_SHA384 (0x1302).
AES_256_GCM_SHA384,
/// TLS_CHACHA20_POLY1305_SHA256 (0x1303).
CHACHA20_POLY1305_SHA256,
}

#[cfg(feature = "dtls")]
impl Dtls13CipherSuite {
/// Convert to the corresponding dimpl cipher suite.
pub fn into_dimpl(self) -> dimpl::crypto::Dtls13CipherSuite {
use dimpl::crypto::Dtls13CipherSuite as D;
match self {
Self::AES_128_GCM_SHA256 => D::AES_128_GCM_SHA256,
Self::AES_256_GCM_SHA384 => D::AES_256_GCM_SHA384,
Self::CHACHA20_POLY1305_SHA256 => D::CHACHA20_POLY1305_SHA256,
}
}
}

// ============================================================================
// DTLS Config
// ============================================================================

/// Configuration for the DTLS handshake.
///
/// Bundles the DTLS version with optional cipher suite preferences.
/// When cipher suite lists are `None`, all provider-supported suites are used.
/// When set to `Some`, only the listed suites are offered/accepted (allow-list).
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct DtlsConfig {
/// Which DTLS version to use.
pub version: DtlsVersion,
/// Allowed DTLS 1.2 cipher suites. `None` means all provider-supported suites.
pub dtls12_cipher_suites: Option<Vec<Dtls12CipherSuite>>,
/// Allowed DTLS 1.3 cipher suites. `None` means all provider-supported suites.
pub dtls13_cipher_suites: Option<Vec<Dtls13CipherSuite>>,
}

/// Factory for DTLS instances and certificates.
pub trait DtlsProvider: CryptoSafe {
/// Generate a new self-signed DTLS certificate.
Expand All @@ -146,12 +228,12 @@ pub trait DtlsProvider: CryptoSafe {
/// In that case, the user must supply a certificate via `RtcConfig::set_dtls_cert`.
fn generate_certificate(&self) -> Option<DtlsCert>;

/// Create a new DTLS instance with the given certificate.
/// Create a new DTLS instance with the given certificate and configuration.
fn new_dtls(
&self,
cert: &DtlsCert,
now: Instant,
dtls_version: DtlsVersion,
dtls_config: &DtlsConfig,
) -> Result<Box<dyn DtlsInstance>, CryptoError>;

/// Whether the provider is used in a test context.
Expand Down
18 changes: 14 additions & 4 deletions crypto/apple-crypto/src/dtls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use security_framework::key::{GenerateKeyOptions, KeyType, SecKey};
use std::sync::Arc;
use std::time::Instant;
use str0m_proto::crypto::CryptoError;
use str0m_proto::crypto::DtlsVersion;
use str0m_proto::crypto::dtls::{DtlsCert, DtlsImplError, DtlsInstance, DtlsOutput, DtlsProvider};
use str0m_proto::crypto::{DtlsConfig, DtlsVersion};

// Certificate Generation

Expand Down Expand Up @@ -88,7 +88,7 @@ impl DtlsProvider for AppleCryptoDtlsProvider {
&self,
cert: &DtlsCert,
now: Instant,
dtls_version: DtlsVersion,
dtls_config: &DtlsConfig,
) -> Result<Box<dyn DtlsInstance>, CryptoError> {
let dimpl_cert = DtlsCertificate {
certificate: cert.certificate.clone(),
Expand All @@ -103,19 +103,29 @@ impl DtlsProvider for AppleCryptoDtlsProvider {
builder = builder.dangerously_set_rng_seed(42);
}

if let Some(suites) = &dtls_config.dtls12_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls12_cipher_suites(&mapped);
}
if let Some(suites) = &dtls_config.dtls13_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls13_cipher_suites(&mapped);
}

let config = builder
.with_crypto_provider(crate::dimpl_provider::default_provider())
.build()
.map_err(|e| CryptoError::Other(format!("dimpl config creation failed: {e}")))?;

let config = Arc::new(config);
let dtls = match dtls_version {
let dtls = match dtls_config.version {
DtlsVersion::Dtls12 => Dtls::new_12(config, dimpl_cert, now),
DtlsVersion::Dtls13 => Dtls::new_13(config, dimpl_cert, now),
DtlsVersion::Auto => Dtls::new_auto(config, dimpl_cert, now),
_ => {
return Err(CryptoError::Other(format!(
"Unsupported DTLS version: {dtls_version}"
"Unsupported DTLS version: {}",
dtls_config.version
)));
}
};
Expand Down
18 changes: 14 additions & 4 deletions crypto/aws-lc-rs/src/dtls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::sync::Arc;
use std::time::Instant;

use str0m_proto::crypto::CryptoError;
use str0m_proto::crypto::DtlsVersion;
use str0m_proto::crypto::dtls::{DtlsCert, DtlsImplError, DtlsInstance, DtlsOutput, DtlsProvider};
use str0m_proto::crypto::{DtlsConfig, DtlsVersion};

// ============================================================================
// DTLS Provider Implementation
Expand All @@ -29,7 +29,7 @@ impl DtlsProvider for AwsLcRsDtlsProvider {
&self,
cert: &DtlsCert,
now: Instant,
dtls_version: DtlsVersion,
dtls_config: &DtlsConfig,
) -> Result<Box<dyn DtlsInstance>, CryptoError> {
let dimpl_cert = dimpl::DtlsCertificate {
certificate: cert.certificate.clone(),
Expand All @@ -44,18 +44,28 @@ impl DtlsProvider for AwsLcRsDtlsProvider {
builder = builder.dangerously_set_rng_seed(42);
}

if let Some(suites) = &dtls_config.dtls12_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls12_cipher_suites(&mapped);
}
if let Some(suites) = &dtls_config.dtls13_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls13_cipher_suites(&mapped);
}

let config = builder
.build()
.map_err(|e| CryptoError::Other(format!("dimpl config creation failed: {}", e)))?;

let config = Arc::new(config);
let dtls = match dtls_version {
let dtls = match dtls_config.version {
DtlsVersion::Dtls12 => dimpl::Dtls::new_12(config, dimpl_cert, now),
DtlsVersion::Dtls13 => dimpl::Dtls::new_13(config, dimpl_cert, now),
DtlsVersion::Auto => dimpl::Dtls::new_auto(config, dimpl_cert, now),
_ => {
return Err(CryptoError::Other(format!(
"Unsupported DTLS version: {dtls_version}"
"Unsupported DTLS version: {}",
dtls_config.version
)));
}
};
Expand Down
18 changes: 14 additions & 4 deletions crypto/openssl/src/dtls_dimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::time::Instant;

use str0m_proto::crypto::dtls::DtlsImplError;
use str0m_proto::crypto::dtls::{DtlsCert, DtlsInstance, DtlsOutput, DtlsProvider};
use str0m_proto::crypto::{CryptoError, DtlsVersion};
use str0m_proto::crypto::{CryptoError, DtlsConfig, DtlsVersion};

// ============================================================================
// DTLS Provider Implementation
Expand All @@ -28,7 +28,7 @@ impl DtlsProvider for OsslDtlsProvider {
&self,
cert: &DtlsCert,
now: Instant,
dtls_version: DtlsVersion,
dtls_config: &DtlsConfig,
) -> Result<Box<dyn DtlsInstance>, CryptoError> {
let dimpl_cert = dimpl::DtlsCertificate {
certificate: cert.certificate.clone(),
Expand All @@ -42,19 +42,29 @@ impl DtlsProvider for OsslDtlsProvider {
builder = builder.dangerously_set_rng_seed(42);
}

if let Some(suites) = &dtls_config.dtls12_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls12_cipher_suites(&mapped);
}
if let Some(suites) = &dtls_config.dtls13_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls13_cipher_suites(&mapped);
}

let config = builder
.with_crypto_provider(crate::dimpl_provider::default_provider())
.build()
.map_err(|e| CryptoError::Other(format!("dimpl config creation failed: {e}")))?;

let config = Arc::new(config);
let dtls = match dtls_version {
let dtls = match dtls_config.version {
DtlsVersion::Dtls12 => dimpl::Dtls::new_12(config, dimpl_cert, now),
DtlsVersion::Dtls13 => dimpl::Dtls::new_13(config, dimpl_cert, now),
DtlsVersion::Auto => dimpl::Dtls::new_auto(config, dimpl_cert, now),
_ => {
return Err(CryptoError::Other(format!(
"Unknown DTLS version: {dtls_version}"
"Unknown DTLS version: {}",
dtls_config.version
)));
}
};
Expand Down
6 changes: 3 additions & 3 deletions crypto/openssl/src/dtls_ossl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use openssl::x509::X509;

use str0m_proto::crypto::dtls::{DtlsCert, KeyingMaterial, SrtpProfile};
use str0m_proto::crypto::dtls::{DtlsImplError, DtlsInstance, DtlsOutput, DtlsProvider};
use str0m_proto::crypto::{CryptoError, DtlsVersion};
use str0m_proto::crypto::{CryptoError, DtlsConfig, DtlsVersion};
use str0m_proto::{DATAGRAM_MTU, DATAGRAM_MTU_WARN};

// ============================================================================
Expand Down Expand Up @@ -637,9 +637,9 @@ impl DtlsProvider for OsslDtlsProvider {
&self,
cert: &DtlsCert,
_now: Instant,
dtls_version: DtlsVersion,
dtls_config: &DtlsConfig,
) -> Result<Box<dyn DtlsInstance>, CryptoError> {
match dtls_version {
match dtls_config.version {
DtlsVersion::Dtls12 => Ok(Box::new(OsslDtlsInstance::new(cert)?)),
_ => Err(CryptoError::Other(
"OpenSSL DTLS provider only supports DTLS 1.2 without dimpl. \
Expand Down
18 changes: 14 additions & 4 deletions crypto/rust-crypto/src/dtls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::sync::Arc;
use std::time::Instant;

use str0m_proto::crypto::CryptoError;
use str0m_proto::crypto::DtlsVersion;
use str0m_proto::crypto::dtls::{DtlsCert, DtlsImplError, DtlsInstance, DtlsOutput, DtlsProvider};
use str0m_proto::crypto::{DtlsConfig, DtlsVersion};

// ============================================================================
// DTLS Provider Implementation
Expand All @@ -29,7 +29,7 @@ impl DtlsProvider for RustCryptoDtlsProvider {
&self,
cert: &DtlsCert,
now: Instant,
dtls_version: DtlsVersion,
dtls_config: &DtlsConfig,
) -> Result<Box<dyn DtlsInstance>, CryptoError> {
let dimpl_cert = dimpl::DtlsCertificate {
certificate: cert.certificate.clone(),
Expand All @@ -44,18 +44,28 @@ impl DtlsProvider for RustCryptoDtlsProvider {
builder = builder.dangerously_set_rng_seed(42);
}

if let Some(suites) = &dtls_config.dtls12_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls12_cipher_suites(&mapped);
}
if let Some(suites) = &dtls_config.dtls13_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls13_cipher_suites(&mapped);
}

let config = builder
.build()
.map_err(|e| CryptoError::Other(format!("dimpl config creation failed: {}", e)))?;

let config = Arc::new(config);
let dtls = match dtls_version {
let dtls = match dtls_config.version {
DtlsVersion::Dtls12 => dimpl::Dtls::new_12(config, dimpl_cert, now),
DtlsVersion::Dtls13 => dimpl::Dtls::new_13(config, dimpl_cert, now),
DtlsVersion::Auto => dimpl::Dtls::new_auto(config, dimpl_cert, now),
_ => {
return Err(CryptoError::Other(format!(
"Unsupported DTLS version: {dtls_version}"
"Unsupported DTLS version: {}",
dtls_config.version
)));
}
};
Expand Down
18 changes: 14 additions & 4 deletions crypto/wincrypto/src/dtls_dimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::sync::Arc;
use std::time::Instant;

use str0m_proto::crypto::CryptoError;
use str0m_proto::crypto::DtlsVersion;
use str0m_proto::crypto::dtls::{DtlsCert, DtlsImplError, DtlsInstance, DtlsOutput, DtlsProvider};
use str0m_proto::crypto::{DtlsConfig, DtlsVersion};

use dimpl::{Config, Dtls, DtlsCertificate};

Expand All @@ -25,7 +25,7 @@ impl DtlsProvider for WinCryptoDtlsProvider {
&self,
cert: &DtlsCert,
now: Instant,
dtls_version: DtlsVersion,
dtls_config: &DtlsConfig,
) -> Result<Box<dyn DtlsInstance>, CryptoError> {
let dimpl_cert = DtlsCertificate {
certificate: cert.certificate.clone(),
Expand All @@ -38,19 +38,29 @@ impl DtlsProvider for WinCryptoDtlsProvider {
builder = builder.dangerously_set_rng_seed(42);
}

if let Some(suites) = &dtls_config.dtls12_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls12_cipher_suites(&mapped);
}
if let Some(suites) = &dtls_config.dtls13_cipher_suites {
let mapped: Vec<_> = suites.iter().map(|s| s.into_dimpl()).collect();
builder = builder.dtls13_cipher_suites(&mapped);
}

let config = builder
.with_crypto_provider(crate::dimpl_provider::default_provider())
.build()
.map_err(|e| CryptoError::Other(format!("dimpl config creation failed: {e}")))?;

let config = Arc::new(config);
let dtls = match dtls_version {
let dtls = match dtls_config.version {
DtlsVersion::Dtls12 => Dtls::new_12(config, dimpl_cert, now),
DtlsVersion::Dtls13 => Dtls::new_13(config, dimpl_cert, now),
DtlsVersion::Auto => Dtls::new_auto(config, dimpl_cert, now),
_ => {
return Err(CryptoError::Other(format!(
"Unsupported DTLS version: {dtls_version}"
"Unsupported DTLS version: {}",
dtls_config.version
)));
}
};
Expand Down
Loading
Loading