/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x509-parser-0.18.1/src/certification_request.rs
Line | Count | Source |
1 | | use crate::cri_attributes::*; |
2 | | use crate::error::{X509Error, X509Result}; |
3 | | use crate::extensions::*; |
4 | | use crate::x509::{ |
5 | | parse_signature_value, AlgorithmIdentifier, SubjectPublicKeyInfo, X509Name, X509Version, |
6 | | }; |
7 | | |
8 | | #[cfg(any(feature = "verify", feature = "verify-aws"))] |
9 | | use crate::verify::verify_signature; |
10 | | use asn1_rs::{BitString, FromDer}; |
11 | | use der_parser::der::*; |
12 | | use der_parser::*; |
13 | | use nom::Offset; |
14 | | use std::collections::HashMap; |
15 | | |
16 | | /// Certification Signing Request (CSR) |
17 | | #[derive(Debug, PartialEq)] |
18 | | pub struct X509CertificationRequest<'a> { |
19 | | pub certification_request_info: X509CertificationRequestInfo<'a>, |
20 | | pub signature_algorithm: AlgorithmIdentifier<'a>, |
21 | | pub signature_value: BitString<'a>, |
22 | | |
23 | | /// Complete raw ASN.1 DER content (request info, signature algorithm and signature). |
24 | | pub(crate) raw: &'a [u8], |
25 | | } |
26 | | |
27 | | impl<'a> X509CertificationRequest<'a> { |
28 | | /// Return the raw ASN.1 DER content of the complete signed certification request that was parsed. |
29 | | /// |
30 | | /// This includes the certification request info, the signature algorithm, and the signature. |
31 | | /// |
32 | | /// We avoid the `AsRef` trait in this instance to ensure the full lifetime of the `X509CertificationRequest` is used. |
33 | 0 | pub fn as_raw(&self) -> &'a [u8] { |
34 | 0 | self.raw |
35 | 0 | } |
36 | | |
37 | 0 | pub fn requested_extensions(&self) -> Option<impl Iterator<Item = &ParsedExtension<'_>>> { |
38 | 0 | self.certification_request_info |
39 | 0 | .iter_attributes() |
40 | 0 | .find_map(|attr| { |
41 | 0 | if let ParsedCriAttribute::ExtensionRequest(requested) = &attr.parsed_attribute { |
42 | 0 | Some(requested.extensions.iter().map(|ext| &ext.parsed_extension)) |
43 | | } else { |
44 | 0 | None |
45 | | } |
46 | 0 | }) |
47 | 0 | } |
48 | | |
49 | | /// Verify the cryptographic signature of this certification request |
50 | | /// |
51 | | /// Uses the public key contained in the CSR, which must be the one of the entity |
52 | | /// requesting the certification for this verification to succeed. |
53 | | #[cfg(any(feature = "verify", feature = "verify-aws"))] |
54 | | #[cfg_attr(docsrs, doc(cfg(any(feature = "verify", feature = "verify-aws"))))] |
55 | | pub fn verify_signature(&self) -> Result<(), X509Error> { |
56 | | let spki = &self.certification_request_info.subject_pki; |
57 | | verify_signature( |
58 | | spki, |
59 | | &self.signature_algorithm, |
60 | | &self.signature_value, |
61 | | self.certification_request_info.raw, |
62 | | ) |
63 | | } |
64 | | } |
65 | | |
66 | | impl<'a> AsRef<[u8]> for X509CertificationRequest<'a> { |
67 | 0 | fn as_ref(&self) -> &[u8] { |
68 | 0 | self.as_raw() |
69 | 0 | } |
70 | | } |
71 | | |
72 | | /// <pre> |
73 | | /// CertificationRequest ::= SEQUENCE { |
74 | | /// certificationRequestInfo CertificationRequestInfo, |
75 | | /// signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, |
76 | | /// signature BIT STRING |
77 | | /// } |
78 | | /// </pre> |
79 | | impl<'a> FromDer<'a, X509Error> for X509CertificationRequest<'a> { |
80 | 0 | fn from_der(i: &'a [u8]) -> X509Result<'a, Self> { |
81 | 0 | let start_i = i; |
82 | 0 | let (rem, mut req) = parse_der_sequence_defined_g(|i, _| { |
83 | 0 | let (i, certification_request_info) = X509CertificationRequestInfo::from_der(i)?; |
84 | 0 | let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?; |
85 | 0 | let (i, signature_value) = parse_signature_value(i)?; |
86 | 0 | let cert = X509CertificationRequest { |
87 | 0 | certification_request_info, |
88 | 0 | signature_algorithm, |
89 | 0 | signature_value, |
90 | 0 | raw: &[], |
91 | 0 | }; |
92 | 0 | Ok((i, cert)) |
93 | 0 | })(i)?; |
94 | 0 | let len = start_i.offset(rem); |
95 | 0 | req.raw = &start_i[..len]; |
96 | 0 | Ok((rem, req)) |
97 | 0 | } |
98 | | } |
99 | | |
100 | | /// Certification Request Info structure |
101 | | /// |
102 | | /// Certification request information is defined by the following ASN.1 structure: |
103 | | /// |
104 | | /// <pre> |
105 | | /// CertificationRequestInfo ::= SEQUENCE { |
106 | | /// version INTEGER { v1(0) } (v1,...), |
107 | | /// subject Name, |
108 | | /// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, |
109 | | /// attributes [0] Attributes{{ CRIAttributes }} |
110 | | /// } |
111 | | /// </pre> |
112 | | /// |
113 | | /// version is the version number; subject is the distinguished name of the certificate |
114 | | /// subject; subject_pki contains information about the public key being certified, and |
115 | | /// attributes is a collection of attributes providing additional information about the |
116 | | /// subject of the certificate. |
117 | | #[derive(Debug, PartialEq)] |
118 | | pub struct X509CertificationRequestInfo<'a> { |
119 | | pub version: X509Version, |
120 | | pub subject: X509Name<'a>, |
121 | | pub subject_pki: SubjectPublicKeyInfo<'a>, |
122 | | attributes: Vec<X509CriAttribute<'a>>, |
123 | | pub raw: &'a [u8], |
124 | | } |
125 | | |
126 | | impl X509CertificationRequestInfo<'_> { |
127 | | /// Get the CRL entry extensions. |
128 | | #[inline] |
129 | 0 | pub fn attributes(&self) -> &[X509CriAttribute<'_>] { |
130 | 0 | &self.attributes |
131 | 0 | } |
132 | | |
133 | | /// Returns an iterator over the CRL entry extensions |
134 | | #[inline] |
135 | 0 | pub fn iter_attributes(&self) -> impl Iterator<Item = &X509CriAttribute<'_>> { |
136 | 0 | self.attributes.iter() |
137 | 0 | } |
138 | | |
139 | | /// Searches for a CRL entry extension with the given `Oid`. |
140 | | /// |
141 | | /// Note: if there are several extensions with the same `Oid`, the first one is returned. |
142 | 0 | pub fn find_attribute(&self, oid: &Oid) -> Option<&X509CriAttribute<'_>> { |
143 | 0 | self.attributes.iter().find(|&ext| ext.oid == *oid) |
144 | 0 | } |
145 | | |
146 | | /// Builds and returns a map of CRL entry extensions. |
147 | | /// |
148 | | /// If an extension is present twice, this will fail and return `DuplicateExtensions`. |
149 | 0 | pub fn attributes_map(&self) -> Result<HashMap<Oid<'_>, &X509CriAttribute<'_>>, X509Error> { |
150 | 0 | self.attributes |
151 | 0 | .iter() |
152 | 0 | .try_fold(HashMap::new(), |mut m, ext| { |
153 | 0 | if m.contains_key(&ext.oid) { |
154 | 0 | return Err(X509Error::DuplicateAttributes); |
155 | 0 | } |
156 | 0 | m.insert(ext.oid.clone(), ext); |
157 | 0 | Ok(m) |
158 | 0 | }) |
159 | 0 | } |
160 | | } |
161 | | |
162 | | /// <pre> |
163 | | /// CertificationRequestInfo ::= SEQUENCE { |
164 | | /// version INTEGER { v1(0) } (v1,...), |
165 | | /// subject Name, |
166 | | /// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, |
167 | | /// attributes [0] Attributes{{ CRIAttributes }} |
168 | | /// } |
169 | | /// </pre> |
170 | | impl<'a> FromDer<'a, X509Error> for X509CertificationRequestInfo<'a> { |
171 | 0 | fn from_der(i: &'a [u8]) -> X509Result<'a, Self> { |
172 | 0 | let start_i = i; |
173 | 0 | parse_der_sequence_defined_g(move |i, _| { |
174 | 0 | let (i, version) = X509Version::from_der(i)?; |
175 | 0 | let (i, subject) = X509Name::from_der(i)?; |
176 | 0 | let (i, subject_pki) = SubjectPublicKeyInfo::from_der(i)?; |
177 | 0 | let (i, attributes) = parse_cri_attributes(i)?; |
178 | 0 | let len = start_i.offset(i); |
179 | 0 | let tbs = X509CertificationRequestInfo { |
180 | 0 | version, |
181 | 0 | subject, |
182 | 0 | subject_pki, |
183 | 0 | attributes, |
184 | 0 | raw: &start_i[..len], |
185 | 0 | }; |
186 | 0 | Ok((i, tbs)) |
187 | 0 | })(i) |
188 | 0 | } |
189 | | } |