1 use crate::error::Result; 2 use crate::{option::*, protection_profile::*}; 3 use util::KeyingMaterialExporter; 4 5 const LABEL_EXTRACTOR_DTLS_SRTP: &str = "EXTRACTOR-dtls_srtp"; 6 7 /// SessionKeys bundles the keys required to setup an SRTP session 8 #[derive(Default, Debug, Clone)] 9 pub struct SessionKeys { 10 pub local_master_key: Vec<u8>, 11 pub local_master_salt: Vec<u8>, 12 pub remote_master_key: Vec<u8>, 13 pub remote_master_salt: Vec<u8>, 14 } 15 16 /// Config is used to configure a session. 17 /// You can provide either a KeyingMaterialExporter to export keys 18 /// or directly pass the keys themselves. 19 /// After a Config is passed to a session it must not be modified. 20 #[derive(Default)] 21 pub struct Config { 22 pub keys: SessionKeys, 23 pub profile: ProtectionProfile, 24 //LoggerFactory: logging.LoggerFactory 25 /// List of local/remote context options. 26 /// ReplayProtection is enabled on remote context by default. 27 /// Default replay protection window size is 64. 28 pub local_rtp_options: Option<ContextOption>, 29 pub remote_rtp_options: Option<ContextOption>, 30 31 pub local_rtcp_options: Option<ContextOption>, 32 pub remote_rtcp_options: Option<ContextOption>, 33 } 34 35 impl Config { 36 /// ExtractSessionKeysFromDTLS allows setting the Config SessionKeys by 37 /// extracting them from DTLS. This behavior is defined in RFC5764: 38 /// https://tools.ietf.org/html/rfc5764 extract_session_keys_from_dtls( &mut self, exporter: impl KeyingMaterialExporter, is_client: bool, ) -> Result<()>39 pub async fn extract_session_keys_from_dtls( 40 &mut self, 41 exporter: impl KeyingMaterialExporter, 42 is_client: bool, 43 ) -> Result<()> { 44 let key_len = self.profile.key_len(); 45 let salt_len = self.profile.salt_len(); 46 47 let keying_material = exporter 48 .export_keying_material( 49 LABEL_EXTRACTOR_DTLS_SRTP, 50 &[], 51 (key_len * 2) + (salt_len * 2), 52 ) 53 .await?; 54 55 let mut offset = 0; 56 let client_write_key = keying_material[offset..offset + key_len].to_vec(); 57 offset += key_len; 58 59 let server_write_key = keying_material[offset..offset + key_len].to_vec(); 60 offset += key_len; 61 62 let client_write_salt = keying_material[offset..offset + salt_len].to_vec(); 63 offset += salt_len; 64 65 let server_write_salt = keying_material[offset..offset + salt_len].to_vec(); 66 67 if is_client { 68 self.keys.local_master_key = client_write_key; 69 self.keys.local_master_salt = client_write_salt; 70 self.keys.remote_master_key = server_write_key; 71 self.keys.remote_master_salt = server_write_salt; 72 } else { 73 self.keys.local_master_key = server_write_key; 74 self.keys.local_master_salt = server_write_salt; 75 self.keys.remote_master_key = client_write_key; 76 self.keys.remote_master_salt = client_write_salt; 77 } 78 79 Ok(()) 80 } 81 } 82