webrtc_srtp/
config.rs

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