/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x509-parser-0.16.0/src/extensions/sct.rs
Line | Count | Source |
1 | | //! Certificate transparency [RFC6962](https://datatracker.ietf.org/doc/html/rfc6962) |
2 | | //! |
3 | | //! Code borrowed from tls-parser crate (file <https://github.com/rusticata/tls-parser/blob/tls-parser-0.11.0/src/certificate_transparency.rs>) |
4 | | |
5 | | use std::convert::TryInto; |
6 | | |
7 | | use asn1_rs::FromDer; |
8 | | use der_parser::error::BerError; |
9 | | use nom::bytes::streaming::take; |
10 | | use nom::combinator::{complete, map_parser}; |
11 | | use nom::multi::{length_data, many1}; |
12 | | use nom::number::streaming::{be_u16, be_u64, be_u8}; |
13 | | use nom::IResult; |
14 | | |
15 | | #[derive(Clone, Debug, PartialEq, Eq)] |
16 | | pub struct SignedCertificateTimestamp<'a> { |
17 | | pub version: CtVersion, |
18 | | pub id: CtLogID<'a>, |
19 | | pub timestamp: u64, |
20 | | pub extensions: CtExtensions<'a>, |
21 | | pub signature: DigitallySigned<'a>, |
22 | | } |
23 | | |
24 | | /// Certificate Transparency Version as defined in |
25 | | /// [RFC6962 Section 3.2](https://datatracker.ietf.org/doc/html/rfc6962#section-3.2) |
26 | | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
27 | | pub struct CtVersion(pub u8); |
28 | | |
29 | | impl CtVersion { |
30 | | pub const V1: CtVersion = CtVersion(0); |
31 | | } |
32 | | |
33 | | /// LogID as defined in |
34 | | /// [RFC6962 Section 3.2](https://datatracker.ietf.org/doc/html/rfc6962#section-3.2) |
35 | | #[derive(Clone, Debug, PartialEq, Eq)] |
36 | | pub struct CtLogID<'a> { |
37 | | pub key_id: &'a [u8; 32], |
38 | | } |
39 | | |
40 | | /// CtExtensions as defined in |
41 | | /// [RFC6962 Section 3.2](https://datatracker.ietf.org/doc/html/rfc6962#section-3.2) |
42 | | #[derive(Clone, Debug, PartialEq, Eq)] |
43 | | pub struct CtExtensions<'a>(pub &'a [u8]); |
44 | | |
45 | | #[derive(Clone, Debug, PartialEq, Eq)] |
46 | | pub struct DigitallySigned<'a> { |
47 | | pub hash_alg_id: u8, |
48 | | pub sign_alg_id: u8, |
49 | | pub data: &'a [u8], |
50 | | } |
51 | | |
52 | | /// Parses a list of Signed Certificate Timestamp entries |
53 | 989 | pub fn parse_ct_signed_certificate_timestamp_list( |
54 | 989 | i: &[u8], |
55 | 989 | ) -> IResult<&[u8], Vec<SignedCertificateTimestamp>, BerError> { |
56 | | // use nom::HexDisplay; |
57 | | // eprintln!("{}", i.to_hex(16)); |
58 | 989 | let (rem, b) = <&[u8]>::from_der(i)?; |
59 | 986 | let (b, sct_len) = be_u16(b)?; |
60 | 986 | let (_, sct_list) = map_parser( |
61 | 986 | take(sct_len as usize), |
62 | 986 | many1(complete(parse_ct_signed_certificate_timestamp)), |
63 | 986 | )(b)?; |
64 | 984 | Ok((rem, sct_list)) |
65 | 989 | } x509_parser::extensions::sct::parse_ct_signed_certificate_timestamp_list Line | Count | Source | 53 | 15 | pub fn parse_ct_signed_certificate_timestamp_list( | 54 | 15 | i: &[u8], | 55 | 15 | ) -> IResult<&[u8], Vec<SignedCertificateTimestamp>, BerError> { | 56 | | // use nom::HexDisplay; | 57 | | // eprintln!("{}", i.to_hex(16)); | 58 | 15 | let (rem, b) = <&[u8]>::from_der(i)?; | 59 | 15 | let (b, sct_len) = be_u16(b)?; | 60 | 15 | let (_, sct_list) = map_parser( | 61 | 15 | take(sct_len as usize), | 62 | 15 | many1(complete(parse_ct_signed_certificate_timestamp)), | 63 | 15 | )(b)?; | 64 | 15 | Ok((rem, sct_list)) | 65 | 15 | } |
x509_parser::extensions::sct::parse_ct_signed_certificate_timestamp_list Line | Count | Source | 53 | 974 | pub fn parse_ct_signed_certificate_timestamp_list( | 54 | 974 | i: &[u8], | 55 | 974 | ) -> IResult<&[u8], Vec<SignedCertificateTimestamp>, BerError> { | 56 | | // use nom::HexDisplay; | 57 | | // eprintln!("{}", i.to_hex(16)); | 58 | 974 | let (rem, b) = <&[u8]>::from_der(i)?; | 59 | 971 | let (b, sct_len) = be_u16(b)?; | 60 | 971 | let (_, sct_list) = map_parser( | 61 | 971 | take(sct_len as usize), | 62 | 971 | many1(complete(parse_ct_signed_certificate_timestamp)), | 63 | 971 | )(b)?; | 64 | 969 | Ok((rem, sct_list)) | 65 | 974 | } |
|
66 | | |
67 | | /// Parses as single Signed Certificate Timestamp entry |
68 | 3.90k | pub fn parse_ct_signed_certificate_timestamp( |
69 | 3.90k | i: &[u8], |
70 | 3.90k | ) -> IResult<&[u8], SignedCertificateTimestamp, BerError> { |
71 | 3.90k | map_parser( |
72 | 3.90k | length_data(be_u16), |
73 | 3.90k | parse_ct_signed_certificate_timestamp_content, |
74 | 3.90k | )(i) |
75 | 3.90k | } x509_parser::extensions::sct::parse_ct_signed_certificate_timestamp Line | Count | Source | 68 | 60 | pub fn parse_ct_signed_certificate_timestamp( | 69 | 60 | i: &[u8], | 70 | 60 | ) -> IResult<&[u8], SignedCertificateTimestamp, BerError> { | 71 | 60 | map_parser( | 72 | 60 | length_data(be_u16), | 73 | 60 | parse_ct_signed_certificate_timestamp_content, | 74 | 60 | )(i) | 75 | 60 | } |
x509_parser::extensions::sct::parse_ct_signed_certificate_timestamp Line | Count | Source | 68 | 3.84k | pub fn parse_ct_signed_certificate_timestamp( | 69 | 3.84k | i: &[u8], | 70 | 3.84k | ) -> IResult<&[u8], SignedCertificateTimestamp, BerError> { | 71 | 3.84k | map_parser( | 72 | 3.84k | length_data(be_u16), | 73 | 3.84k | parse_ct_signed_certificate_timestamp_content, | 74 | 3.84k | )(i) | 75 | 3.84k | } |
|
76 | | |
77 | 2.92k | pub(crate) fn parse_ct_signed_certificate_timestamp_content( |
78 | 2.92k | i: &[u8], |
79 | 2.92k | ) -> IResult<&[u8], SignedCertificateTimestamp, BerError> { |
80 | 2.92k | let (i, version) = be_u8(i)?; |
81 | 2.92k | let (i, id) = parse_log_id(i)?; |
82 | 2.92k | let (i, timestamp) = be_u64(i)?; |
83 | 2.92k | let (i, extensions) = parse_ct_extensions(i)?; |
84 | 2.91k | let (i, signature) = parse_digitally_signed(i)?; |
85 | 2.91k | let sct = SignedCertificateTimestamp { |
86 | 2.91k | version: CtVersion(version), |
87 | 2.91k | id, |
88 | 2.91k | timestamp, |
89 | 2.91k | extensions, |
90 | 2.91k | signature, |
91 | 2.91k | }; |
92 | 2.91k | Ok((i, sct)) |
93 | 2.92k | } x509_parser::extensions::sct::parse_ct_signed_certificate_timestamp_content Line | Count | Source | 77 | 45 | pub(crate) fn parse_ct_signed_certificate_timestamp_content( | 78 | 45 | i: &[u8], | 79 | 45 | ) -> IResult<&[u8], SignedCertificateTimestamp, BerError> { | 80 | 45 | let (i, version) = be_u8(i)?; | 81 | 45 | let (i, id) = parse_log_id(i)?; | 82 | 45 | let (i, timestamp) = be_u64(i)?; | 83 | 45 | let (i, extensions) = parse_ct_extensions(i)?; | 84 | 45 | let (i, signature) = parse_digitally_signed(i)?; | 85 | 45 | let sct = SignedCertificateTimestamp { | 86 | 45 | version: CtVersion(version), | 87 | 45 | id, | 88 | 45 | timestamp, | 89 | 45 | extensions, | 90 | 45 | signature, | 91 | 45 | }; | 92 | 45 | Ok((i, sct)) | 93 | 45 | } |
x509_parser::extensions::sct::parse_ct_signed_certificate_timestamp_content Line | Count | Source | 77 | 2.87k | pub(crate) fn parse_ct_signed_certificate_timestamp_content( | 78 | 2.87k | i: &[u8], | 79 | 2.87k | ) -> IResult<&[u8], SignedCertificateTimestamp, BerError> { | 80 | 2.87k | let (i, version) = be_u8(i)?; | 81 | 2.87k | let (i, id) = parse_log_id(i)?; | 82 | 2.87k | let (i, timestamp) = be_u64(i)?; | 83 | 2.87k | let (i, extensions) = parse_ct_extensions(i)?; | 84 | 2.87k | let (i, signature) = parse_digitally_signed(i)?; | 85 | 2.87k | let sct = SignedCertificateTimestamp { | 86 | 2.87k | version: CtVersion(version), | 87 | 2.87k | id, | 88 | 2.87k | timestamp, | 89 | 2.87k | extensions, | 90 | 2.87k | signature, | 91 | 2.87k | }; | 92 | 2.87k | Ok((i, sct)) | 93 | 2.87k | } |
|
94 | | |
95 | | // Safety: cannot fail, take() returns exactly 32 bytes |
96 | 2.92k | fn parse_log_id(i: &[u8]) -> IResult<&[u8], CtLogID, BerError> { |
97 | 2.92k | let (i, key_id) = take(32usize)(i)?; |
98 | 2.92k | Ok(( |
99 | 2.92k | i, |
100 | 2.92k | CtLogID { |
101 | 2.92k | key_id: key_id |
102 | 2.92k | .try_into() |
103 | 2.92k | .expect("take(32) is in sync with key_id size"), |
104 | 2.92k | }, |
105 | 2.92k | )) |
106 | 2.92k | } x509_parser::extensions::sct::parse_log_id Line | Count | Source | 96 | 45 | fn parse_log_id(i: &[u8]) -> IResult<&[u8], CtLogID, BerError> { | 97 | 45 | let (i, key_id) = take(32usize)(i)?; | 98 | 45 | Ok(( | 99 | 45 | i, | 100 | 45 | CtLogID { | 101 | 45 | key_id: key_id | 102 | 45 | .try_into() | 103 | 45 | .expect("take(32) is in sync with key_id size"), | 104 | 45 | }, | 105 | 45 | )) | 106 | 45 | } |
x509_parser::extensions::sct::parse_log_id Line | Count | Source | 96 | 2.87k | fn parse_log_id(i: &[u8]) -> IResult<&[u8], CtLogID, BerError> { | 97 | 2.87k | let (i, key_id) = take(32usize)(i)?; | 98 | 2.87k | Ok(( | 99 | 2.87k | i, | 100 | 2.87k | CtLogID { | 101 | 2.87k | key_id: key_id | 102 | 2.87k | .try_into() | 103 | 2.87k | .expect("take(32) is in sync with key_id size"), | 104 | 2.87k | }, | 105 | 2.87k | )) | 106 | 2.87k | } |
|
107 | | |
108 | 2.92k | fn parse_ct_extensions(i: &[u8]) -> IResult<&[u8], CtExtensions, BerError> { |
109 | 2.92k | let (i, ext_len) = be_u16(i)?; |
110 | 2.92k | let (i, ext_data) = take(ext_len as usize)(i)?; |
111 | 2.91k | Ok((i, CtExtensions(ext_data))) |
112 | 2.92k | } x509_parser::extensions::sct::parse_ct_extensions Line | Count | Source | 108 | 45 | fn parse_ct_extensions(i: &[u8]) -> IResult<&[u8], CtExtensions, BerError> { | 109 | 45 | let (i, ext_len) = be_u16(i)?; | 110 | 45 | let (i, ext_data) = take(ext_len as usize)(i)?; | 111 | 45 | Ok((i, CtExtensions(ext_data))) | 112 | 45 | } |
x509_parser::extensions::sct::parse_ct_extensions Line | Count | Source | 108 | 2.87k | fn parse_ct_extensions(i: &[u8]) -> IResult<&[u8], CtExtensions, BerError> { | 109 | 2.87k | let (i, ext_len) = be_u16(i)?; | 110 | 2.87k | let (i, ext_data) = take(ext_len as usize)(i)?; | 111 | 2.87k | Ok((i, CtExtensions(ext_data))) | 112 | 2.87k | } |
|
113 | | |
114 | 2.91k | fn parse_digitally_signed(i: &[u8]) -> IResult<&[u8], DigitallySigned, BerError> { |
115 | 2.91k | let (i, hash_alg_id) = be_u8(i)?; |
116 | 2.91k | let (i, sign_alg_id) = be_u8(i)?; |
117 | 2.91k | let (i, data) = length_data(be_u16)(i)?; |
118 | 2.91k | let signed = DigitallySigned { |
119 | 2.91k | hash_alg_id, |
120 | 2.91k | sign_alg_id, |
121 | 2.91k | data, |
122 | 2.91k | }; |
123 | 2.91k | Ok((i, signed)) |
124 | 2.91k | } x509_parser::extensions::sct::parse_digitally_signed Line | Count | Source | 114 | 45 | fn parse_digitally_signed(i: &[u8]) -> IResult<&[u8], DigitallySigned, BerError> { | 115 | 45 | let (i, hash_alg_id) = be_u8(i)?; | 116 | 45 | let (i, sign_alg_id) = be_u8(i)?; | 117 | 45 | let (i, data) = length_data(be_u16)(i)?; | 118 | 45 | let signed = DigitallySigned { | 119 | 45 | hash_alg_id, | 120 | 45 | sign_alg_id, | 121 | 45 | data, | 122 | 45 | }; | 123 | 45 | Ok((i, signed)) | 124 | 45 | } |
x509_parser::extensions::sct::parse_digitally_signed Line | Count | Source | 114 | 2.87k | fn parse_digitally_signed(i: &[u8]) -> IResult<&[u8], DigitallySigned, BerError> { | 115 | 2.87k | let (i, hash_alg_id) = be_u8(i)?; | 116 | 2.87k | let (i, sign_alg_id) = be_u8(i)?; | 117 | 2.87k | let (i, data) = length_data(be_u16)(i)?; | 118 | 2.87k | let signed = DigitallySigned { | 119 | 2.87k | hash_alg_id, | 120 | 2.87k | sign_alg_id, | 121 | 2.87k | data, | 122 | 2.87k | }; | 123 | 2.87k | Ok((i, signed)) | 124 | 2.87k | } |
|