tls_parser/
tls_ec.rs

1use alloc::vec::Vec;
2use nom::error::{make_error, ErrorKind};
3use nom::multi::length_data;
4use nom::number::streaming::be_u8;
5use nom::{Err, IResult};
6use nom_derive::*;
7use rusticata_macros::newtype_enum;
8
9/// Named elliptic curves
10///
11/// Named curves, as defined in [RFC4492](https://tools.ietf.org/html/rfc4492), [RFC7027](https://tools.ietf.org/html/rfc7027), [RFC7919](https://tools.ietf.org/html/rfc7919) and
12/// [IANA Supported Groups
13/// Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8)
14#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
15pub struct NamedGroup(pub u16);
16
17newtype_enum! {
18impl debug NamedGroup {
19    Sect163k1 = 1,
20    Sect163r1 = 2,
21    Sect163r2 = 3,
22    Sect193r1 = 4,
23    Sect193r2 = 5,
24    Sect233k1 = 6,
25    Sect233r1 = 7,
26    Sect239k1 = 8,
27    Sect283k1 = 9,
28    Sect283r1 = 10,
29    Sect409k1 = 11,
30    Sect409r1 = 12,
31    Sect571k1 = 13,
32    Sect571r1 = 14,
33    Secp160k1 = 15,
34    Secp160r1 = 16,
35    Secp160r2 = 17,
36    Secp192k1 = 18,
37    Secp192r1 = 19,
38    Secp224k1 = 20,
39    Secp224r1 = 21,
40    Secp256k1 = 22,
41    Secp256r1 = 23,
42    Secp384r1 = 24,
43    Secp521r1 = 25,
44    BrainpoolP256r1 = 26,
45    BrainpoolP384r1 = 27,
46    BrainpoolP512r1 = 28,
47    EcdhX25519 = 29,
48    EcdhX448 = 30,
49    BrainpoolP256r1tls13 = 31,
50    BrainpoolP384r1tls13 = 32,
51    BrainpoolP512r1tls13 = 33,
52    Sm2 = 41,
53    Ffdhe2048 = 0x100,
54    Ffdhe3072 = 0x101,
55    Ffdhe4096 = 0x102,
56    Ffdhe6144 = 0x103,
57    Ffdhe8192 = 0x104,
58    ArbitraryExplicitPrimeCurves = 0xFF01,
59    ArbitraryExplicitChar2Curves = 0xFF02,
60}
61}
62
63impl NamedGroup {
64    /// Return key size of curve in bits, or None if unknown
65    pub fn key_bits(self: NamedGroup) -> Option<u16> {
66        match self {
67            NamedGroup::Sect163k1 => Some(163),
68            NamedGroup::Sect163r1 => Some(163),
69            NamedGroup::Sect163r2 => Some(163),
70            NamedGroup::Sect193r1 => Some(193),
71            NamedGroup::Sect193r2 => Some(193),
72            NamedGroup::Sect233k1 => Some(233),
73            NamedGroup::Sect233r1 => Some(233),
74            NamedGroup::Sect239k1 => Some(239),
75            NamedGroup::Sect283k1 => Some(283),
76            NamedGroup::Sect283r1 => Some(283),
77            NamedGroup::Sect409k1 => Some(409),
78            NamedGroup::Sect409r1 => Some(409),
79            NamedGroup::Sect571k1 => Some(571),
80            NamedGroup::Sect571r1 => Some(571),
81            NamedGroup::Secp160k1 => Some(160),
82            NamedGroup::Secp160r1 => Some(160),
83            NamedGroup::Secp160r2 => Some(160),
84            NamedGroup::Secp192k1 => Some(192),
85            NamedGroup::Secp192r1 => Some(192),
86            NamedGroup::Secp224k1 => Some(224),
87            NamedGroup::Secp224r1 => Some(224),
88            NamedGroup::Secp256k1 => Some(256),
89            NamedGroup::Secp256r1 => Some(256),
90            NamedGroup::Secp384r1 => Some(384),
91            NamedGroup::Secp521r1 => Some(521),
92            NamedGroup::BrainpoolP256r1 => Some(256),
93            NamedGroup::BrainpoolP384r1 => Some(384),
94            NamedGroup::BrainpoolP512r1 => Some(521),
95            NamedGroup::EcdhX25519 => Some(253),
96            _ => None,
97        }
98    }
99}
100
101/// Elliptic curve
102///
103/// a and b specify the coefficients of the curve
104#[derive(Debug, PartialEq, NomBE)]
105pub struct ECCurve<'a> {
106    #[nom(Parse = "length_data(be_u8)")]
107    pub a: &'a [u8],
108    #[nom(Parse = "length_data(be_u8)")]
109    pub b: &'a [u8],
110}
111
112/// Elliptic curve types, as defined in the
113/// [IANA EC Curve Type Registry
114/// Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-10)
115#[derive(Clone, Copy, PartialEq, Eq, NomBE)]
116pub struct ECCurveType(pub u8);
117
118newtype_enum! {
119impl display ECCurveType {
120    ExplicitPrime = 1,
121    ExplicitChar2 = 2,
122    NamedGroup = 3,
123}
124}
125
126/// EC Point
127#[derive(Clone, Debug, PartialEq, NomBE)]
128pub struct ECPoint<'a> {
129    #[nom(Parse = "length_data(be_u8)")]
130    pub point: &'a [u8],
131}
132
133/// Elliptic curve parameters, conveyed verbosely as a prime field, as
134/// defined in [RFC4492](https://tools.ietf.org/html/rfc4492) section 5.4
135#[derive(Debug, PartialEq, NomBE)]
136pub struct ExplicitPrimeContent<'a> {
137    #[nom(Parse = "length_data(be_u8)")]
138    pub prime_p: &'a [u8],
139    pub curve: ECCurve<'a>,
140    pub base: ECPoint<'a>,
141    #[nom(Parse = "length_data(be_u8)")]
142    pub order: &'a [u8],
143    #[nom(Parse = "length_data(be_u8)")]
144    pub cofactor: &'a [u8],
145}
146
147/// Elliptic curve parameters content (depending on EC type)
148#[derive(PartialEq, Nom)]
149#[nom(Selector = "ECCurveType")]
150pub enum ECParametersContent<'a> {
151    #[nom(Selector = "ECCurveType::ExplicitPrime")]
152    ExplicitPrime(ExplicitPrimeContent<'a>),
153    // TODO ExplicitChar2 is defined in [RFC4492] section 5.4
154    // #[nom(Selector="ECCurveType::ExplicitChar2")]
155    // ExplicitChar2(&'a [u8]),
156    #[nom(Selector = "ECCurveType::NamedGroup")]
157    NamedGroup(NamedGroup),
158}
159
160/// Elliptic curve parameters,
161/// defined in [RFC4492](https://tools.ietf.org/html/rfc4492) section 5.4
162#[derive(PartialEq, NomBE)]
163pub struct ECParameters<'a> {
164    /// Should match a [ECCurveType](enum.ECCurveType.html) value
165    pub curve_type: ECCurveType,
166    #[nom(Parse = "{|i| ECParametersContent::parse(i, curve_type)}")]
167    pub params_content: ECParametersContent<'a>,
168}
169
170/// ECDH parameters
171/// defined in [RFC4492](https://tools.ietf.org/html/rfc4492) section 5.4
172#[derive(Debug, PartialEq, NomBE)]
173pub struct ServerECDHParams<'a> {
174    pub curve_params: ECParameters<'a>,
175    pub public: ECPoint<'a>,
176}
177
178/// Parse the entire input as a list of named groups (curves)
179pub fn parse_named_groups(i: &[u8]) -> IResult<&[u8], Vec<NamedGroup>> {
180    let len = i.len();
181    if len == 0 {
182        return Ok((i, Vec::new()));
183    }
184    if len % 2 == 1 || len > i.len() {
185        return Err(Err::Error(make_error(i, ErrorKind::LengthValue)));
186    }
187    let v = (i[..len])
188        .chunks(2)
189        .map(|chunk| NamedGroup((chunk[0] as u16) << 8 | chunk[1] as u16))
190        .collect();
191    Ok((&i[len..], v))
192}
193
194#[inline]
195pub fn parse_ec_parameters(i: &[u8]) -> IResult<&[u8], ECParameters> {
196    ECParameters::parse(i)
197}
198
199#[inline]
200pub fn parse_ecdh_params(i: &[u8]) -> IResult<&[u8], ServerECDHParams> {
201    ServerECDHParams::parse(i)
202}