use bytes::Bytes;
use crate::dtls::Result;
use crate::dtls::crypto::keys::{DtlsKeyingMaterial, extract_srtp_keys};
use crate::dtls::message::extension::SrtpProtectionProfile;
use crate::srtp::{SrtpCryptoSuite, SrtpCryptoKey, SrtpEncryptionAlgorithm, SrtpAuthenticationAlgorithm};
#[derive(Debug, Clone)]
pub struct DtlsSrtpContext {
pub profile: SrtpCryptoSuite,
pub client_write_key: SrtpCryptoKey,
pub server_write_key: SrtpCryptoKey,
}
impl DtlsSrtpContext {
pub fn new(
profile: SrtpCryptoSuite,
client_write_key: SrtpCryptoKey,
server_write_key: SrtpCryptoKey,
) -> Self {
Self {
profile,
client_write_key,
server_write_key,
}
}
pub fn get_key_for_role(&self, is_client: bool) -> &SrtpCryptoKey {
if is_client {
&self.client_write_key
} else {
&self.server_write_key
}
}
}
pub fn extract_srtp_keys_from_dtls(
keying_material: &DtlsKeyingMaterial,
profile: SrtpProtectionProfile,
is_client: bool,
) -> Result<DtlsSrtpContext> {
let crypto_suite = convert_profile_to_suite(profile)?;
let key_length = crypto_suite.key_length;
let salt_length = 14;
let (client_key, client_salt) = extract_srtp_keys(
keying_material,
key_length,
salt_length,
true, )?;
let (server_key, server_salt) = extract_srtp_keys(
keying_material,
key_length,
salt_length,
false, )?;
let client_write_key = SrtpCryptoKey::new(client_key.to_vec(), client_salt.to_vec());
let server_write_key = SrtpCryptoKey::new(server_key.to_vec(), server_salt.to_vec());
Ok(DtlsSrtpContext::new(
crypto_suite,
client_write_key,
server_write_key,
))
}
fn convert_profile_to_suite(profile: SrtpProtectionProfile) -> Result<SrtpCryptoSuite> {
match profile {
SrtpProtectionProfile::Aes128CmSha1_80 => {
Ok(SrtpCryptoSuite {
encryption: SrtpEncryptionAlgorithm::AesCm,
authentication: SrtpAuthenticationAlgorithm::HmacSha1_80,
key_length: 16, tag_length: 10, })
}
SrtpProtectionProfile::Aes128CmSha1_32 => {
Ok(SrtpCryptoSuite {
encryption: SrtpEncryptionAlgorithm::AesCm,
authentication: SrtpAuthenticationAlgorithm::HmacSha1_32,
key_length: 16, tag_length: 4, })
}
SrtpProtectionProfile::AeadAes128Gcm => {
Err(crate::error::Error::UnsupportedFeature("AEAD GCM crypto suite not yet supported".to_string()))
}
SrtpProtectionProfile::AeadAes256Gcm => {
Err(crate::error::Error::UnsupportedFeature("AEAD GCM crypto suite not yet supported".to_string()))
}
SrtpProtectionProfile::Unknown(_) => {
Err(crate::error::Error::UnsupportedFeature("Unknown SRTP protection profile".to_string()))
}
}
}