tls_parser/
tls_sign_hash.rs

1use nom::combinator::map;
2use nom::multi::length_data;
3use nom::number::streaming::be_u16;
4use nom::sequence::pair;
5use nom::IResult;
6use nom_derive::*;
7use rusticata_macros::newtype_enum;
8
9/// Hash algorithms, as defined in \[RFC5246\]
10#[derive(Clone, Debug, PartialEq, Eq, Nom)]
11pub struct HashAlgorithm(pub u8);
12
13newtype_enum! {
14impl display HashAlgorithm {
15    None = 0,
16    Md5 = 1,
17    Sha1 = 2,
18    Sha224 = 3,
19    Sha256 = 4,
20    Sha384 = 5,
21    Sha512 = 6,
22    Intrinsic = 8, // [RFC8422]
23}
24}
25
26/// Signature algorithms, as defined in \[RFC5246\]
27#[derive(Clone, Debug, PartialEq, Eq, Nom)]
28pub struct SignAlgorithm(pub u8);
29
30newtype_enum! {
31impl display SignAlgorithm {
32    Anonymous = 0,
33    Rsa = 1,
34    Dsa = 2,
35    Ecdsa = 3,
36    Ed25519 = 7, // [RFC8422]
37    Ed448 = 8, // [RFC8422]
38}
39}
40
41#[derive(Clone, PartialEq, Nom)]
42pub struct SignatureAndHashAlgorithm {
43    pub hash: HashAlgorithm,
44    pub sign: SignAlgorithm,
45}
46
47/// Signature algorithms, as defined in \[RFC8446\] 4.2.3
48#[derive(Debug, PartialEq, Eq, Nom)]
49pub struct SignatureScheme(pub u16);
50
51newtype_enum! {
52impl display SignatureScheme {
53    /* RSASSA-PKCS1-v1_5 algorithms */
54    rsa_pkcs1_sha256 = 0x0401,
55    rsa_pkcs1_sha384 = 0x0501,
56    rsa_pkcs1_sha512 = 0x0601,
57
58    /* ECDSA algorithms */
59    ecdsa_secp256r1_sha256 = 0x0403,
60    ecdsa_secp384r1_sha384 = 0x0503,
61    ecdsa_secp521r1_sha512 = 0x0603,
62
63    /* ShangMi (SM) Cipher Suites */
64    sm2sig_sm3 = 0x0708,
65
66    /* RSASSA-PSS algorithms with public key OID rsaEncryption */
67    rsa_pss_rsae_sha256 = 0x0804,
68    rsa_pss_rsae_sha384 = 0x0805,
69    rsa_pss_rsae_sha512 = 0x0806,
70
71    /* EdDSA algorithms */
72    ed25519 = 0x0807,
73    ed448 = 0x0808,
74
75    /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
76    rsa_pss_pss_sha256 = 0x0809,
77    rsa_pss_pss_sha384 = 0x080a,
78    rsa_pss_pss_sha512 = 0x080b,
79
80    /* Brainpool SignatureScheme Types for TLS 1.3 (RFC8734) */
81    ecdsa_brainpoolP256r1tls13_sha256 = 0x081a,
82    ecdsa_brainpoolP384r1tls13_sha384 = 0x081b,
83    ecdsa_brainpoolP512r1tls13_sha512 = 0x081c,
84
85    /* Legacy algorithms */
86    rsa_pkcs1_sha1 = 0x0201,
87    ecdsa_sha1 = 0x0203,
88}
89}
90
91impl SignatureScheme {
92    pub fn is_reserved(&self) -> bool {
93        self.0 >= 0xfe00 && self.0 < 0xff00
94    }
95
96    /// Get Hash algorithm (for tls <= 1.2) for legacy extension format
97    pub fn hash_alg(&self) -> u8 {
98        ((self.0 >> 8) & 0xff) as u8
99    }
100
101    /// Get Signature algorithm (for tls <= 1.2) for legacy extension format
102    pub fn sign_alg(&self) -> u8 {
103        (self.0 & 0xff) as u8
104    }
105}
106
107/// DigitallySigned structure from \[RFC2246\] section 4.7
108/// has no algorithm definition.
109/// This should be deprecated in favor of
110/// DigitallySigned structure from \[RFC5246\] section 4.7
111#[derive(Clone, PartialEq)]
112pub struct DigitallySigned<'a> {
113    pub alg: Option<SignatureAndHashAlgorithm>,
114    // pub alg: Option<u16>, // SignatureScheme
115    pub data: &'a [u8],
116}
117
118pub fn parse_digitally_signed_old(i: &[u8]) -> IResult<&[u8], DigitallySigned> {
119    map(length_data(be_u16), |data| DigitallySigned {
120        alg: None,
121        data,
122    })(i)
123}
124
125pub fn parse_digitally_signed(i: &[u8]) -> IResult<&[u8], DigitallySigned> {
126    let (i, hash) = HashAlgorithm::parse(i)?;
127    let (i, sign) = SignAlgorithm::parse(i)?;
128    let (i, data) = length_data(be_u16)(i)?;
129    let signed = DigitallySigned {
130        alg: Some(SignatureAndHashAlgorithm { hash, sign }),
131        data,
132    };
133    Ok((i, signed))
134}
135
136/// Parse DigitallySigned object, depending on the `ext` parameter which should
137/// be true if the TLS client has sent the `signature_algorithms` extension
138pub fn parse_content_and_signature<'a, F, T>(
139    i: &'a [u8],
140    fun: F,
141    ext: bool,
142) -> IResult<&'a [u8], (T, DigitallySigned<'a>)>
143where
144    F: Fn(&'a [u8]) -> IResult<&'a [u8], T>,
145{
146    if ext {
147        pair(fun, parse_digitally_signed)(i)
148    } else {
149        pair(fun, parse_digitally_signed_old)(i)
150    }
151}