1 use crate::cri_attributes::*;
2 #[cfg(feature = "verify")]
3 use crate::error::X509Error;
4 use crate::error::X509Result;
5 use crate::extensions::*;
6 use crate::x509::{
7     parse_signature_value, AlgorithmIdentifier, SubjectPublicKeyInfo, X509Name, X509Version,
8 };
9 
10 use der_parser::ber::BitStringObject;
11 use der_parser::der::*;
12 use der_parser::oid::Oid;
13 use der_parser::*;
14 use nom::Offset;
15 #[cfg(feature = "verify")]
16 use oid_registry::*;
17 use std::collections::HashMap;
18 
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> {
27     /// Parse a certification signing request (CSR)
28     ///
29     /// <pre>
30     /// CertificationRequest ::= SEQUENCE {
31     ///     certificationRequestInfo CertificationRequestInfo,
32     ///     signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
33     ///     signature          BIT STRING
34     /// }
35     /// </pre>
36     ///
37     /// certificateRequestInfo is the "Certification request information", it is the value being
38     /// signed; signatureAlgorithm identifies the signature algorithm; and signature is the result
39     /// of signing the certification request information with the subject's private key.
from_der(i: &'a [u8]) -> X509Result<Self>40     pub fn from_der(i: &'a [u8]) -> X509Result<Self> {
41         parse_der_sequence_defined_g(|i, _| {
42             let (i, certification_request_info) = X509CertificationRequestInfo::from_der(i)?;
43             let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?;
44             let (i, signature_value) = parse_signature_value(i)?;
45             let cert = X509CertificationRequest {
46                 certification_request_info,
47                 signature_algorithm,
48                 signature_value,
49             };
50             Ok((i, cert))
51         })(i)
52     }
53 
requested_extensions(&self) -> Option<impl Iterator<Item = &ParsedExtension<'a>>>54     pub fn requested_extensions(&self) -> Option<impl Iterator<Item = &ParsedExtension<'a>>> {
55         self.certification_request_info
56             .attributes
57             .values()
58             .find_map(|attr| {
59                 if let ParsedCriAttribute::ExtensionRequest(requested) = &attr.parsed_attribute {
60                     Some(
61                         requested
62                             .extensions
63                             .values()
64                             .map(|ext| &ext.parsed_extension),
65                     )
66                 } else {
67                     None
68                 }
69             })
70     }
71 
72     /// Verify the cryptographic signature of this certification request
73     ///
74     /// Uses the public key contained in the CSR, which must be the one of the entity
75     /// requesting the certification for this verification to succeed.
76     #[cfg(feature = "verify")]
verify_signature(&self) -> Result<(), X509Error>77     pub fn verify_signature(&self) -> Result<(), X509Error> {
78         use ring::signature;
79         let spki = &self.certification_request_info.subject_pki;
80         let signature_alg = &self.signature_algorithm.algorithm;
81         // identify verification algorithm
82         let verification_alg: &dyn signature::VerificationAlgorithm =
83             if *signature_alg == OID_PKCS1_SHA1WITHRSA {
84                 &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY
85             } else if *signature_alg == OID_PKCS1_SHA256WITHRSA {
86                 &signature::RSA_PKCS1_2048_8192_SHA256
87             } else if *signature_alg == OID_PKCS1_SHA384WITHRSA {
88                 &signature::RSA_PKCS1_2048_8192_SHA384
89             } else if *signature_alg == OID_PKCS1_SHA512WITHRSA {
90                 &signature::RSA_PKCS1_2048_8192_SHA512
91             } else if *signature_alg == OID_SIG_ECDSA_WITH_SHA256 {
92                 &signature::ECDSA_P256_SHA256_ASN1
93             } else if *signature_alg == OID_SIG_ECDSA_WITH_SHA384 {
94                 &signature::ECDSA_P384_SHA384_ASN1
95             } else {
96                 return Err(X509Error::SignatureUnsupportedAlgorithm);
97             };
98         // get public key
99         let key = signature::UnparsedPublicKey::new(verification_alg, spki.subject_public_key.data);
100         // verify signature
101         let sig = self.signature_value.data;
102         key.verify(self.certification_request_info.raw, sig)
103             .or(Err(X509Error::SignatureVerificationError))
104     }
105 }
106 
107 #[derive(Debug, PartialEq)]
108 pub struct X509CertificationRequestInfo<'a> {
109     pub version: X509Version,
110     pub subject: X509Name<'a>,
111     pub subject_pki: SubjectPublicKeyInfo<'a>,
112     pub attributes: HashMap<Oid<'a>, X509CriAttribute<'a>>,
113     pub raw: &'a [u8],
114 }
115 
116 impl<'a> X509CertificationRequestInfo<'a> {
117     /// Parse a certification request info structure
118     ///
119     /// Certification request information is defined by the following ASN.1 structure:
120     ///
121     /// <pre>
122     /// CertificationRequestInfo ::= SEQUENCE {
123     ///      version       INTEGER { v1(0) } (v1,...),
124     ///      subject       Name,
125     ///      subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
126     ///      attributes    [0] Attributes{{ CRIAttributes }}
127     /// }
128     /// </pre>
129     ///
130     /// version is the version number; subject is the distinguished name of the certificate
131     /// subject; subject_pki contains information about the public key being certified, and
132     /// attributes is a collection of attributes providing additional information about the
133     /// subject of the certificate.
from_der(i: &'a [u8]) -> X509Result<Self>134     pub fn from_der(i: &'a [u8]) -> X509Result<Self> {
135         let start_i = i;
136         parse_der_sequence_defined_g(move |i, _| {
137             let (i, version) = X509Version::from_der_required(i)?;
138             let (i, subject) = X509Name::from_der(i)?;
139             let (i, subject_pki) = SubjectPublicKeyInfo::from_der(i)?;
140             let (i, attributes) = parse_cri_attributes(i)?;
141             let len = start_i.offset(i);
142             let tbs = X509CertificationRequestInfo {
143                 version,
144                 subject,
145                 subject_pki,
146                 attributes,
147                 raw: &start_i[..len],
148             };
149             Ok((i, tbs))
150         })(i)
151     }
152 }
153