Skip to main content

rtc_dtls/
state.rs

1use super::cipher_suite::*;
2use super::conn::*;
3use super::curve::named_curve::*;
4use super::extension::extension_use_srtp::SrtpProtectionProfile;
5use super::handshake::handshake_random::*;
6use super::prf::*;
7use rkyv::{Archive, Deserialize, Serialize};
8use shared::crypto::KeyingMaterialExporter;
9use shared::error::*;
10use std::io::{BufWriter, Cursor};
11
12// State holds the dtls connection state and implements both encoding.BinaryMarshaler and encoding.BinaryUnmarshaler
13/// The negotiated connection state: keys, sequence numbers, peer identity and the active
14/// cipher suite.
15pub struct State {
16    pub(crate) local_epoch: u16,
17    pub(crate) remote_epoch: u16,
18    pub(crate) local_sequence_number: Vec<u64>, // uint48
19    pub(crate) local_random: HandshakeRandom,
20    pub(crate) remote_random: HandshakeRandom,
21    pub(crate) master_secret: Vec<u8>,
22    pub(crate) cipher_suite: Option<Box<dyn CipherSuite>>, // nil if a cipher_suite hasn't been chosen
23
24    pub(crate) srtp_protection_profile: SrtpProtectionProfile, // Negotiated srtp_protection_profile
25    /// The peer's certificate chain, DER-encoded.
26    ///
27    /// WebRTC checks its fingerprint against the one signalled in SDP.
28    pub peer_certificates: Vec<Vec<u8>>,
29    /// The PSK identity hint, for pre-shared-key handshakes.
30    pub identity_hint: Vec<u8>,
31
32    pub(crate) is_client: bool,
33
34    pub(crate) pre_master_secret: Vec<u8>,
35    pub(crate) extended_master_secret: bool,
36
37    pub(crate) named_curve: NamedCurve,
38    pub(crate) local_keypair: Option<NamedCurveKeypair>,
39    pub(crate) cookie: Vec<u8>,
40    pub(crate) handshake_send_sequence: isize,
41    pub(crate) handshake_recv_sequence: isize,
42    pub(crate) server_name: String,
43    pub(crate) remote_requested_certificate: bool, // Did we get a CertificateRequest
44    pub(crate) local_certificates_verify: Vec<u8>, // cache CertificateVerify
45    pub(crate) local_verify_data: Vec<u8>,         // cached VerifyData
46    pub(crate) local_key_signature: Vec<u8>,       // cached keySignature
47    pub(crate) peer_certificates_verified: bool,
48    //pub(crate) replay_detector: Vec<Box<dyn ReplayDetector>>,
49}
50
51#[derive(Archive, Serialize, Deserialize, PartialEq, Debug)]
52struct SerializedState {
53    local_epoch: u16,
54    remote_epoch: u16,
55    local_random: [u8; HANDSHAKE_RANDOM_LENGTH],
56    remote_random: [u8; HANDSHAKE_RANDOM_LENGTH],
57    cipher_suite_id: u16,
58    master_secret: Vec<u8>,
59    sequence_number: u64,
60    srtp_protection_profile: u16,
61    peer_certificates: Vec<Vec<u8>>,
62    identity_hint: Vec<u8>,
63    is_client: bool,
64}
65
66impl Default for State {
67    fn default() -> Self {
68        State {
69            local_epoch: 0,
70            remote_epoch: 0,
71            local_sequence_number: vec![],
72            local_random: HandshakeRandom::default(),
73            remote_random: HandshakeRandom::default(),
74            master_secret: vec![],
75            cipher_suite: None, // nil if a cipher_suite hasn't been chosen
76
77            srtp_protection_profile: SrtpProtectionProfile::Unsupported, // Negotiated srtp_protection_profile
78            peer_certificates: vec![],
79            identity_hint: vec![],
80
81            is_client: false,
82
83            pre_master_secret: vec![],
84            extended_master_secret: false,
85
86            named_curve: NamedCurve::Unsupported,
87            local_keypair: None,
88            cookie: vec![],
89            handshake_send_sequence: 0,
90            handshake_recv_sequence: 0,
91            server_name: "".to_string(),
92            remote_requested_certificate: false, // Did we get a CertificateRequest
93            local_certificates_verify: vec![],   // cache CertificateVerify
94            local_verify_data: vec![],           // cached VerifyData
95            local_key_signature: vec![],         // cached keySignature
96            peer_certificates_verified: false,
97            //replay_detector: vec![],
98        }
99    }
100}
101
102impl State {
103    fn serialize(&self) -> Result<SerializedState> {
104        let mut local_rand = vec![];
105        {
106            let mut writer = BufWriter::<&mut Vec<u8>>::new(local_rand.as_mut());
107            self.local_random.marshal(&mut writer)?;
108        }
109        let mut remote_rand = vec![];
110        {
111            let mut writer = BufWriter::<&mut Vec<u8>>::new(remote_rand.as_mut());
112            self.remote_random.marshal(&mut writer)?;
113        }
114
115        let mut local_random = [0u8; HANDSHAKE_RANDOM_LENGTH];
116        let mut remote_random = [0u8; HANDSHAKE_RANDOM_LENGTH];
117
118        local_random.copy_from_slice(&local_rand);
119        remote_random.copy_from_slice(&remote_rand);
120
121        let local_epoch = self.local_epoch;
122        let remote_epoch = self.remote_epoch;
123        let sequence_number = self.local_sequence_number[local_epoch as usize];
124        let cipher_suite_id = {
125            match &self.cipher_suite {
126                Some(cipher_suite) => cipher_suite.id() as u16,
127                None => return Err(Error::ErrCipherSuiteUnset),
128            }
129        };
130
131        Ok(SerializedState {
132            local_epoch,
133            remote_epoch,
134            local_random,
135            remote_random,
136            cipher_suite_id,
137            master_secret: self.master_secret.clone(),
138            sequence_number,
139            srtp_protection_profile: self.srtp_protection_profile as u16,
140            peer_certificates: self.peer_certificates.clone(),
141            identity_hint: self.identity_hint.clone(),
142            is_client: self.is_client,
143        })
144    }
145
146    fn deserialize(&mut self, serialized: &SerializedState) -> Result<()> {
147        // Set epoch values
148        self.local_epoch = serialized.local_epoch;
149        self.remote_epoch = serialized.remote_epoch;
150        {
151            while self.local_sequence_number.len() <= serialized.local_epoch as usize {
152                self.local_sequence_number.push(0);
153            }
154            self.local_sequence_number[serialized.local_epoch as usize] =
155                serialized.sequence_number;
156        }
157
158        // Set random values
159        let mut reader = Cursor::new(&serialized.local_random);
160        self.local_random = HandshakeRandom::unmarshal(&mut reader)?;
161
162        let mut reader = Cursor::new(&serialized.remote_random);
163        self.remote_random = HandshakeRandom::unmarshal(&mut reader)?;
164
165        self.is_client = serialized.is_client;
166
167        // Set master secret
168        self.master_secret.clone_from(&serialized.master_secret);
169
170        // Set cipher suite
171        self.cipher_suite = Some(cipher_suite_for_id(serialized.cipher_suite_id.into())?);
172
173        self.srtp_protection_profile = serialized.srtp_protection_profile.into();
174
175        // Set remote certificate
176        self.peer_certificates
177            .clone_from(&serialized.peer_certificates);
178        self.identity_hint.clone_from(&serialized.identity_hint);
179
180        Ok(())
181    }
182
183    /// Installs the negotiated keys into the cipher suite.
184    ///
185    /// # Errors
186    ///
187    /// Fails if the master secret or randoms are not yet available.
188    pub fn init_cipher_suite(&mut self) -> Result<()> {
189        if let Some(cipher_suite) = &mut self.cipher_suite {
190            if cipher_suite.is_initialized() {
191                return Ok(());
192            }
193
194            let mut local_random = vec![];
195            {
196                let mut writer = BufWriter::<&mut Vec<u8>>::new(local_random.as_mut());
197                self.local_random.marshal(&mut writer)?;
198            }
199            let mut remote_random = vec![];
200            {
201                let mut writer = BufWriter::<&mut Vec<u8>>::new(remote_random.as_mut());
202                self.remote_random.marshal(&mut writer)?;
203            }
204
205            if self.is_client {
206                cipher_suite.init(&self.master_secret, &local_random, &remote_random, true)
207            } else {
208                cipher_suite.init(&self.master_secret, &remote_random, &local_random, false)
209            }
210        } else {
211            Err(Error::ErrCipherSuiteUnset)
212        }
213    }
214
215    // marshal_binary is a binary.BinaryMarshaler.marshal_binary implementation
216    /// Serializes the state, so a connection can be resumed or migrated.
217    ///
218    /// # Errors
219    ///
220    /// Fails if the state is incomplete.
221    pub fn marshal_binary(&self) -> Result<Vec<u8>> {
222        let serialized = self.serialize()?;
223
224        match rkyv::to_bytes::<rkyv::rancor::Error>(&serialized).map(Vec::from) {
225            Ok(enc) => Ok(enc),
226            Err(err) => Err(Error::Other(err.to_string())),
227        }
228    }
229
230    // unmarshal_binary is a binary.BinaryUnmarshaler.unmarshal_binary implementation
231    /// Restores state previously produced by [`Self::marshal_binary`].
232    ///
233    /// # Errors
234    ///
235    /// Fails if `data` is truncated or malformed.
236    pub fn unmarshal_binary(&mut self, data: &[u8]) -> Result<()> {
237        let serialized: SerializedState =
238            match rkyv::access::<ArchivedSerializedState, rkyv::rancor::Error>(data)
239                .and_then(rkyv::deserialize)
240            {
241                Ok(dec) => dec,
242                Err(err) => return Err(Error::Other(err.to_string())),
243            };
244        self.deserialize(&serialized)?;
245        self.init_cipher_suite()?;
246
247        Ok(())
248    }
249
250    /// The SRTP protection profile negotiated through `use_srtp`.
251    pub fn srtp_protection_profile(&self) -> SrtpProtectionProfile {
252        self.srtp_protection_profile
253    }
254
255    /// Whether this endpoint took the client role.
256    pub fn is_client(&self) -> bool {
257        self.is_client
258    }
259
260    /// The active cipher suite, once one has been negotiated.
261    pub fn cipher_suite(&self) -> Option<&dyn CipherSuite> {
262        self.cipher_suite.as_deref()
263    }
264}
265
266impl KeyingMaterialExporter for State {
267    /// export_keying_material returns length bytes of exported key material in a new
268    /// slice as defined in RFC 5705.
269    /// This allows protocols to use DTLS for key establishment, but
270    /// then use some of the keying material for their own purposes
271    fn export_keying_material(
272        &self,
273        label: &str,
274        context: &[u8],
275        length: usize,
276    ) -> shared::error::Result<Vec<u8>> {
277        if self.local_epoch == 0 {
278            return Err(Error::HandshakeInProgress);
279        } else if !context.is_empty() {
280            return Err(Error::ContextUnsupported);
281        } else if INVALID_KEYING_LABELS.contains(&label) {
282            return Err(Error::ReservedExportKeyingMaterial);
283        }
284
285        let mut local_random = vec![];
286        {
287            let mut writer = BufWriter::<&mut Vec<u8>>::new(local_random.as_mut());
288            self.local_random.marshal(&mut writer)?;
289        }
290        let mut remote_random = vec![];
291        {
292            let mut writer = BufWriter::<&mut Vec<u8>>::new(remote_random.as_mut());
293            self.remote_random.marshal(&mut writer)?;
294        }
295
296        let mut seed = label.as_bytes().to_vec();
297        if self.is_client {
298            seed.extend_from_slice(&local_random);
299            seed.extend_from_slice(&remote_random);
300        } else {
301            seed.extend_from_slice(&remote_random);
302            seed.extend_from_slice(&local_random);
303        }
304
305        if let Some(cipher_suite) = &self.cipher_suite {
306            match prf_p_hash(&self.master_secret, &seed, length, cipher_suite.hash_func()) {
307                Ok(v) => Ok(v),
308                Err(err) => Err(Error::Hash(err.to_string())),
309            }
310        } else {
311            Err(Error::CipherSuiteUnset)
312        }
313    }
314}