Coverage Report

Created: 2024-12-17 06:15

/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
}