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