Skip to main content

rtc_dtls/handshake/
mod.rs

1//! DTLS handshake messages.
2//!
3//! Each message type has its own module; [`HandshakeMessage`](crate::handshake::HandshakeMessage) is the parsed union of them and
4//! [`Handshake`](crate::handshake::Handshake) pairs one with its [`HandshakeHeader`](crate::handshake::handshake_header::HandshakeHeader).
5//!
6//! Two things distinguish this from a TLS handshake. Messages carry a sequence number and
7//! fragment offsets, because a handshake message may be larger than a datagram and must be
8//! reassembled. And the server may answer a ClientHello with a
9//! [`HelloVerifyRequest`](crate::handshake::handshake_message_hello_verify_request) carrying a cookie, which the
10//! client echoes — a cheap defence against using the handshake for amplification.
11//!
12//! [`handshake_cache`](crate::handshake::handshake_cache) retains the messages so the hash in `Finished` can be computed over
13//! exactly what both sides saw.
14/// Buffers handshake messages so their hash can be computed for `Finished` verification.
15pub mod handshake_cache;
16/// The header prefixing every handshake message, including fragment offsets.
17pub mod handshake_header;
18/// Certificate: the sender's certificate chain.
19pub mod handshake_message_certificate;
20/// CertificateRequest: the server asks the client to authenticate.
21pub mod handshake_message_certificate_request;
22/// CertificateVerify: proves possession of the certificate's private key.
23pub mod handshake_message_certificate_verify;
24/// ClientHello: opens the handshake with the client's offers.
25pub mod handshake_message_client_hello;
26/// ClientKeyExchange: the client's half of the key agreement.
27pub mod handshake_message_client_key_exchange;
28/// Finished: a hash over the handshake, proving both sides saw the same messages.
29pub mod handshake_message_finished;
30/// HelloVerifyRequest: DTLS's cookie exchange, which resists amplification attacks.
31pub mod handshake_message_hello_verify_request;
32/// ServerHello: the server's chosen parameters.
33pub mod handshake_message_server_hello;
34/// ServerHelloDone: the server has finished its first flight.
35pub mod handshake_message_server_hello_done;
36/// ServerKeyExchange: the server's half of the key agreement.
37pub mod handshake_message_server_key_exchange;
38/// The 32-byte random each side contributes to key derivation.
39pub mod handshake_random;
40
41#[cfg(test)]
42mod handshake_test;
43
44use std::fmt;
45use std::io::{Read, Write};
46
47use super::content::*;
48use shared::error::*;
49
50use handshake_header::*;
51use handshake_message_certificate::*;
52use handshake_message_certificate_request::*;
53use handshake_message_certificate_verify::*;
54use handshake_message_client_hello::*;
55use handshake_message_client_key_exchange::*;
56use handshake_message_finished::*;
57use handshake_message_hello_verify_request::*;
58use handshake_message_server_hello::*;
59use handshake_message_server_hello_done::*;
60use handshake_message_server_key_exchange::*;
61
62/// ## Specifications
63///
64/// * [RFC 5246 §7.4]
65///
66/// [RFC 5246 §7.4]: https://tools.ietf.org/html/rfc5246#section-7.4
67#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash)]
68pub enum HandshakeType {
69    /// `HELLO_REQUEST` (`0`).
70    HelloRequest = 0,
71    /// `CLIENT_HELLO` (`1`).
72    ClientHello = 1,
73    /// `SERVER_HELLO` (`2`).
74    ServerHello = 2,
75    /// `HELLO_VERIFY_REQUEST` (`3`).
76    HelloVerifyRequest = 3,
77    /// `CERTIFICATE` (`11`).
78    Certificate = 11,
79    /// `SERVER_KEY_EXCHANGE` (`12`).
80    ServerKeyExchange = 12,
81    /// `CERTIFICATE_REQUEST` (`13`).
82    CertificateRequest = 13,
83    /// `SERVER_HELLO_DONE` (`14`).
84    ServerHelloDone = 14,
85    /// `CERTIFICATE_VERIFY` (`15`).
86    CertificateVerify = 15,
87    /// `CLIENT_KEY_EXCHANGE` (`16`).
88    ClientKeyExchange = 16,
89    /// `FINISHED` (`20`).
90    Finished = 20,
91    #[default]
92    /// A handshake type this crate does not recognise.
93    Invalid,
94}
95
96impl fmt::Display for HandshakeType {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        match *self {
99            HandshakeType::HelloRequest => write!(f, "HelloRequest"),
100            HandshakeType::ClientHello => write!(f, "ClientHello"),
101            HandshakeType::ServerHello => write!(f, "ServerHello"),
102            HandshakeType::HelloVerifyRequest => write!(f, "HelloVerifyRequest"),
103            HandshakeType::Certificate => write!(f, "Certificate"),
104            HandshakeType::ServerKeyExchange => write!(f, "ServerKeyExchange"),
105            HandshakeType::CertificateRequest => write!(f, "CertificateRequest"),
106            HandshakeType::ServerHelloDone => write!(f, "ServerHelloDone"),
107            HandshakeType::CertificateVerify => write!(f, "CertificateVerify"),
108            HandshakeType::ClientKeyExchange => write!(f, "ClientKeyExchange"),
109            HandshakeType::Finished => write!(f, "Finished"),
110            HandshakeType::Invalid => write!(f, "Invalid"),
111        }
112    }
113}
114
115impl From<u8> for HandshakeType {
116    fn from(val: u8) -> Self {
117        match val {
118            0 => HandshakeType::HelloRequest,
119            1 => HandshakeType::ClientHello,
120            2 => HandshakeType::ServerHello,
121            3 => HandshakeType::HelloVerifyRequest,
122            11 => HandshakeType::Certificate,
123            12 => HandshakeType::ServerKeyExchange,
124            13 => HandshakeType::CertificateRequest,
125            14 => HandshakeType::ServerHelloDone,
126            15 => HandshakeType::CertificateVerify,
127            16 => HandshakeType::ClientKeyExchange,
128            20 => HandshakeType::Finished,
129            _ => HandshakeType::Invalid,
130        }
131    }
132}
133
134#[derive(PartialEq, Debug, Clone)]
135/// A parsed handshake message.
136pub enum HandshakeMessage {
137    //HelloRequest(errNotImplemented),
138    /// ClientHello, which opens the handshake.
139    ClientHello(HandshakeMessageClientHello),
140    /// ServerHello, carrying the server's chosen parameters.
141    ServerHello(HandshakeMessageServerHello),
142    /// HelloVerifyRequest, DTLS's cookie challenge.
143    HelloVerifyRequest(HandshakeMessageHelloVerifyRequest),
144    /// Certificate, carrying a certificate chain.
145    Certificate(HandshakeMessageCertificate),
146    /// ServerKeyExchange, the server's key-agreement share.
147    ServerKeyExchange(HandshakeMessageServerKeyExchange),
148    /// CertificateRequest, asking the client to authenticate.
149    CertificateRequest(HandshakeMessageCertificateRequest),
150    /// ServerHelloDone, ending the server's first flight.
151    ServerHelloDone(HandshakeMessageServerHelloDone),
152    /// CertificateVerify, proving possession of the certificate key.
153    CertificateVerify(HandshakeMessageCertificateVerify),
154    /// ClientKeyExchange, the client's key-agreement share.
155    ClientKeyExchange(HandshakeMessageClientKeyExchange),
156    /// Finished, a hash over the handshake that both sides verify.
157    Finished(HandshakeMessageFinished),
158}
159
160impl HandshakeMessage {
161    /// The handshake type that identifies this message on the wire.
162    pub fn handshake_type(&self) -> HandshakeType {
163        match self {
164            HandshakeMessage::ClientHello(msg) => msg.handshake_type(),
165            HandshakeMessage::ServerHello(msg) => msg.handshake_type(),
166            HandshakeMessage::HelloVerifyRequest(msg) => msg.handshake_type(),
167            HandshakeMessage::Certificate(msg) => msg.handshake_type(),
168            HandshakeMessage::ServerKeyExchange(msg) => msg.handshake_type(),
169            HandshakeMessage::CertificateRequest(msg) => msg.handshake_type(),
170            HandshakeMessage::ServerHelloDone(msg) => msg.handshake_type(),
171            HandshakeMessage::CertificateVerify(msg) => msg.handshake_type(),
172            HandshakeMessage::ClientKeyExchange(msg) => msg.handshake_type(),
173            HandshakeMessage::Finished(msg) => msg.handshake_type(),
174        }
175    }
176
177    /// The encoded size of this message in bytes.
178    pub fn size(&self) -> usize {
179        match self {
180            HandshakeMessage::ClientHello(msg) => msg.size(),
181            HandshakeMessage::ServerHello(msg) => msg.size(),
182            HandshakeMessage::HelloVerifyRequest(msg) => msg.size(),
183            HandshakeMessage::Certificate(msg) => msg.size(),
184            HandshakeMessage::ServerKeyExchange(msg) => msg.size(),
185            HandshakeMessage::CertificateRequest(msg) => msg.size(),
186            HandshakeMessage::ServerHelloDone(msg) => msg.size(),
187            HandshakeMessage::CertificateVerify(msg) => msg.size(),
188            HandshakeMessage::ClientKeyExchange(msg) => msg.size(),
189            HandshakeMessage::Finished(msg) => msg.size(),
190        }
191    }
192
193    /// Encodes this message to `writer`.
194    ///
195    /// # Errors
196    ///
197    /// Fails on a write error, or if a field exceeds the length its wire format allows.
198    pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
199        match self {
200            HandshakeMessage::ClientHello(msg) => msg.marshal(writer)?,
201            HandshakeMessage::ServerHello(msg) => msg.marshal(writer)?,
202            HandshakeMessage::HelloVerifyRequest(msg) => msg.marshal(writer)?,
203            HandshakeMessage::Certificate(msg) => msg.marshal(writer)?,
204            HandshakeMessage::ServerKeyExchange(msg) => msg.marshal(writer)?,
205            HandshakeMessage::CertificateRequest(msg) => msg.marshal(writer)?,
206            HandshakeMessage::ServerHelloDone(msg) => msg.marshal(writer)?,
207            HandshakeMessage::CertificateVerify(msg) => msg.marshal(writer)?,
208            HandshakeMessage::ClientKeyExchange(msg) => msg.marshal(writer)?,
209            HandshakeMessage::Finished(msg) => msg.marshal(writer)?,
210        }
211
212        Ok(())
213    }
214}
215
216// The handshake protocol is responsible for selecting a cipher spec and
217// generating a master secret, which together comprise the primary
218// cryptographic parameters associated with a secure session.  The
219// handshake protocol can also optionally authenticate parties who have
220// certificates signed by a trusted certificate authority.
221// https://tools.ietf.org/html/rfc5246#section-7.3
222#[derive(PartialEq, Debug, Clone)]
223/// A handshake record: its header plus the message it carries.
224pub struct Handshake {
225    pub(crate) handshake_header: HandshakeHeader,
226    pub(crate) handshake_message: HandshakeMessage,
227}
228
229impl Handshake {
230    /// Wraps a message in a handshake record, filling in its header.
231    pub fn new(handshake_message: HandshakeMessage) -> Self {
232        Handshake {
233            handshake_header: HandshakeHeader {
234                handshake_type: handshake_message.handshake_type(),
235                length: handshake_message.size() as u32,
236                message_sequence: 0,
237                fragment_offset: 0,
238                fragment_length: handshake_message.size() as u32,
239            },
240            handshake_message,
241        }
242    }
243
244    /// The record content type this message is carried in.
245    pub fn content_type(&self) -> ContentType {
246        ContentType::Handshake
247    }
248
249    /// The encoded size of this message in bytes.
250    pub fn size(&self) -> usize {
251        self.handshake_header.size() + self.handshake_message.size()
252    }
253
254    /// Encodes this message to `writer`.
255    ///
256    /// # Errors
257    ///
258    /// Fails on a write error, or if a field exceeds the length its wire format allows.
259    pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
260        self.handshake_header.marshal(writer)?;
261        self.handshake_message.marshal(writer)?;
262        Ok(())
263    }
264
265    /// Decodes one of these messages from `reader`.
266    ///
267    /// # Errors
268    ///
269    /// Fails if `reader` is truncated or its contents are not a valid encoding.
270    pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
271        let handshake_header = HandshakeHeader::unmarshal(reader)?;
272
273        let handshake_message = match handshake_header.handshake_type {
274            HandshakeType::ClientHello => {
275                HandshakeMessage::ClientHello(HandshakeMessageClientHello::unmarshal(reader)?)
276            }
277            HandshakeType::ServerHello => {
278                HandshakeMessage::ServerHello(HandshakeMessageServerHello::unmarshal(reader)?)
279            }
280            HandshakeType::HelloVerifyRequest => HandshakeMessage::HelloVerifyRequest(
281                HandshakeMessageHelloVerifyRequest::unmarshal(reader)?,
282            ),
283            HandshakeType::Certificate => {
284                HandshakeMessage::Certificate(HandshakeMessageCertificate::unmarshal(reader)?)
285            }
286            HandshakeType::ServerKeyExchange => HandshakeMessage::ServerKeyExchange(
287                HandshakeMessageServerKeyExchange::unmarshal(reader)?,
288            ),
289            HandshakeType::CertificateRequest => HandshakeMessage::CertificateRequest(
290                HandshakeMessageCertificateRequest::unmarshal(reader)?,
291            ),
292            HandshakeType::ServerHelloDone => HandshakeMessage::ServerHelloDone(
293                HandshakeMessageServerHelloDone::unmarshal(reader)?,
294            ),
295            HandshakeType::CertificateVerify => HandshakeMessage::CertificateVerify(
296                HandshakeMessageCertificateVerify::unmarshal(reader)?,
297            ),
298            HandshakeType::ClientKeyExchange => HandshakeMessage::ClientKeyExchange(
299                HandshakeMessageClientKeyExchange::unmarshal(reader)?,
300            ),
301            HandshakeType::Finished => {
302                HandshakeMessage::Finished(HandshakeMessageFinished::unmarshal(reader)?)
303            }
304            _ => return Err(Error::ErrNotImplemented),
305        };
306
307        Ok(Handshake {
308            handshake_header,
309            handshake_message,
310        })
311    }
312}