x509_parser/
certification_request.rs

1use crate::cri_attributes::*;
2use crate::error::{X509Error, X509Result};
3use crate::extensions::*;
4use crate::x509::{
5    parse_signature_value, AlgorithmIdentifier, SubjectPublicKeyInfo, X509Name, X509Version,
6};
7
8#[cfg(feature = "verify")]
9use crate::verify::verify_signature;
10use asn1_rs::{BitString, FromDer};
11use der_parser::der::*;
12use der_parser::*;
13use nom::Offset;
14use std::collections::HashMap;
15
16/// Certification Signing Request (CSR)
17#[derive(Debug, PartialEq)]
18pub 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
27impl<'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    pub fn as_raw(&self) -> &'a [u8] {
34        self.raw
35    }
36
37    pub fn requested_extensions(&self) -> Option<impl Iterator<Item = &ParsedExtension<'_>>> {
38        self.certification_request_info
39            .iter_attributes()
40            .find_map(|attr| {
41                if let ParsedCriAttribute::ExtensionRequest(requested) = &attr.parsed_attribute {
42                    Some(requested.extensions.iter().map(|ext| &ext.parsed_extension))
43                } else {
44                    None
45                }
46            })
47    }
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(feature = "verify")]
54    pub fn verify_signature(&self) -> Result<(), X509Error> {
55        let spki = &self.certification_request_info.subject_pki;
56        verify_signature(
57            spki,
58            &self.signature_algorithm,
59            &self.signature_value,
60            self.certification_request_info.raw,
61        )
62    }
63}
64
65impl<'a> AsRef<[u8]> for X509CertificationRequest<'a> {
66    fn as_ref(&self) -> &[u8] {
67        self.as_raw()
68    }
69}
70
71/// <pre>
72/// CertificationRequest ::= SEQUENCE {
73///     certificationRequestInfo CertificationRequestInfo,
74///     signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
75///     signature          BIT STRING
76/// }
77/// </pre>
78impl<'a> FromDer<'a, X509Error> for X509CertificationRequest<'a> {
79    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
80        let start_i = i;
81        let (rem, mut req) = parse_der_sequence_defined_g(|i, _| {
82            let (i, certification_request_info) = X509CertificationRequestInfo::from_der(i)?;
83            let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?;
84            let (i, signature_value) = parse_signature_value(i)?;
85            let cert = X509CertificationRequest {
86                certification_request_info,
87                signature_algorithm,
88                signature_value,
89                raw: &[],
90            };
91            Ok((i, cert))
92        })(i)?;
93        let len = start_i.offset(rem);
94        req.raw = &start_i[..len];
95        Ok((rem, req))
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)]
117pub 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
125impl X509CertificationRequestInfo<'_> {
126    /// Get the CRL entry extensions.
127    #[inline]
128    pub fn attributes(&self) -> &[X509CriAttribute<'_>] {
129        &self.attributes
130    }
131
132    /// Returns an iterator over the CRL entry extensions
133    #[inline]
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.
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`.
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>
169impl<'a> FromDer<'a, X509Error> for X509CertificationRequestInfo<'a> {
170    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
171        let start_i = i;
172        parse_der_sequence_defined_g(move |i, _| {
173            let (i, version) = X509Version::from_der(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}