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