Skip to main content

rtc_dtls/extension/
mod.rs

1/// Server Name Indication (SNI).
2pub mod extension_server_name;
3/// The curves a client will accept for ECDHE.
4pub mod extension_supported_elliptic_curves;
5/// The EC point formats a client will accept; WebRTC uses uncompressed.
6pub mod extension_supported_point_formats;
7/// The signature and hash algorithm pairs a client will accept.
8pub mod extension_supported_signature_algorithms;
9/// The extended master secret extension ([RFC 7627]), which binds the master secret to the
10/// whole handshake.
11pub mod extension_use_extended_master_secret;
12/// The `use_srtp` extension, which negotiates SRTP protection profiles during the DTLS
13/// handshake ([RFC 5764]).
14pub mod extension_use_srtp;
15/// The renegotiation info extension, sent empty to signal renegotiation is not supported.
16pub mod renegotiation_info;
17
18use extension_server_name::*;
19use extension_supported_elliptic_curves::*;
20use extension_supported_point_formats::*;
21use extension_supported_signature_algorithms::*;
22use extension_use_extended_master_secret::*;
23use extension_use_srtp::*;
24
25use shared::error::*;
26
27use crate::extension::renegotiation_info::ExtensionRenegotiationInfo;
28use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
29use std::io::{Read, Write};
30
31// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
32#[derive(Clone, Debug, PartialEq, Eq)]
33/// The extension type code points this crate understands.
34pub enum ExtensionValue {
35    /// `SERVER_NAME` (`0`).
36    ServerName = 0,
37    /// `SUPPORTED_ELLIPTIC_CURVES` (`10`).
38    SupportedEllipticCurves = 10,
39    /// `SUPPORTED_POINT_FORMATS` (`11`).
40    SupportedPointFormats = 11,
41    /// `SUPPORTED_SIGNATURE_ALGORITHMS` (`13`).
42    SupportedSignatureAlgorithms = 13,
43    /// `USE_SRTP` (`14`).
44    UseSrtp = 14,
45    /// `USE_EXTENDED_MASTER_SECRET` (`23`).
46    UseExtendedMasterSecret = 23,
47    /// `RENEGOTIATION_INFO` (`65281`).
48    RenegotiationInfo = 65281,
49    /// An extension this crate does not implement, which is ignored.
50    Unsupported,
51}
52
53impl From<u16> for ExtensionValue {
54    fn from(val: u16) -> Self {
55        match val {
56            0 => ExtensionValue::ServerName,
57            10 => ExtensionValue::SupportedEllipticCurves,
58            11 => ExtensionValue::SupportedPointFormats,
59            13 => ExtensionValue::SupportedSignatureAlgorithms,
60            14 => ExtensionValue::UseSrtp,
61            23 => ExtensionValue::UseExtendedMasterSecret,
62            65281 => ExtensionValue::RenegotiationInfo,
63            _ => ExtensionValue::Unsupported,
64        }
65    }
66}
67
68#[derive(PartialEq, Eq, Debug, Clone)]
69/// A parsed hello extension.
70pub enum Extension {
71    /// Server Name Indication.
72    ServerName(ExtensionServerName),
73    /// The curves the sender accepts for ECDHE.
74    SupportedEllipticCurves(ExtensionSupportedEllipticCurves),
75    /// The EC point formats the sender accepts.
76    SupportedPointFormats(ExtensionSupportedPointFormats),
77    /// The signature and hash pairs the sender accepts.
78    SupportedSignatureAlgorithms(ExtensionSupportedSignatureAlgorithms),
79    /// The SRTP protection profiles offered or selected.
80    UseSrtp(ExtensionUseSrtp),
81    /// The extended master secret extension.
82    UseExtendedMasterSecret(ExtensionUseExtendedMasterSecret),
83    /// The renegotiation info extension.
84    RenegotiationInfo(ExtensionRenegotiationInfo),
85}
86
87impl Extension {
88    /// The extension type this value is carried under.
89    pub fn extension_value(&self) -> ExtensionValue {
90        match self {
91            Extension::ServerName(ext) => ext.extension_value(),
92            Extension::SupportedEllipticCurves(ext) => ext.extension_value(),
93            Extension::SupportedPointFormats(ext) => ext.extension_value(),
94            Extension::SupportedSignatureAlgorithms(ext) => ext.extension_value(),
95            Extension::UseSrtp(ext) => ext.extension_value(),
96            Extension::UseExtendedMasterSecret(ext) => ext.extension_value(),
97            Extension::RenegotiationInfo(ext) => ext.extension_value(),
98        }
99    }
100
101    /// The encoded size of this message in bytes.
102    pub fn size(&self) -> usize {
103        let mut len = 2;
104
105        len += match self {
106            Extension::ServerName(ext) => ext.size(),
107            Extension::SupportedEllipticCurves(ext) => ext.size(),
108            Extension::SupportedPointFormats(ext) => ext.size(),
109            Extension::SupportedSignatureAlgorithms(ext) => ext.size(),
110            Extension::UseSrtp(ext) => ext.size(),
111            Extension::UseExtendedMasterSecret(ext) => ext.size(),
112            Extension::RenegotiationInfo(ext) => ext.size(),
113        };
114
115        len
116    }
117
118    /// Encodes this message to `writer`.
119    ///
120    /// # Errors
121    ///
122    /// Fails on a write error, or if a field exceeds the length its wire format allows.
123    pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
124        writer.write_u16::<BigEndian>(self.extension_value() as u16)?;
125        match self {
126            Extension::ServerName(ext) => ext.marshal(writer),
127            Extension::SupportedEllipticCurves(ext) => ext.marshal(writer),
128            Extension::SupportedPointFormats(ext) => ext.marshal(writer),
129            Extension::SupportedSignatureAlgorithms(ext) => ext.marshal(writer),
130            Extension::UseSrtp(ext) => ext.marshal(writer),
131            Extension::UseExtendedMasterSecret(ext) => ext.marshal(writer),
132            Extension::RenegotiationInfo(ext) => ext.marshal(writer),
133        }
134    }
135
136    /// Decodes one of these messages from `reader`.
137    ///
138    /// # Errors
139    ///
140    /// Fails if `reader` is truncated or its contents are not a valid encoding.
141    pub fn unmarshal<R: Read>(reader: &mut R) -> Result<Self> {
142        let extension_value: ExtensionValue = reader.read_u16::<BigEndian>()?.into();
143        match extension_value {
144            ExtensionValue::ServerName => Ok(Extension::ServerName(
145                ExtensionServerName::unmarshal(reader)?,
146            )),
147            ExtensionValue::SupportedEllipticCurves => Ok(Extension::SupportedEllipticCurves(
148                ExtensionSupportedEllipticCurves::unmarshal(reader)?,
149            )),
150            ExtensionValue::SupportedPointFormats => Ok(Extension::SupportedPointFormats(
151                ExtensionSupportedPointFormats::unmarshal(reader)?,
152            )),
153            ExtensionValue::SupportedSignatureAlgorithms => {
154                Ok(Extension::SupportedSignatureAlgorithms(
155                    ExtensionSupportedSignatureAlgorithms::unmarshal(reader)?,
156                ))
157            }
158            ExtensionValue::UseSrtp => Ok(Extension::UseSrtp(ExtensionUseSrtp::unmarshal(reader)?)),
159            ExtensionValue::UseExtendedMasterSecret => Ok(Extension::UseExtendedMasterSecret(
160                ExtensionUseExtendedMasterSecret::unmarshal(reader)?,
161            )),
162            ExtensionValue::RenegotiationInfo => Ok(Extension::RenegotiationInfo(
163                ExtensionRenegotiationInfo::unmarshal(reader)?,
164            )),
165            _ => Err(Error::ErrInvalidExtensionType),
166        }
167    }
168}