x509_parser/
certification_request.rs1use 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(any(feature = "verify", feature = "verify-aws"))]
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#[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 pub(crate) raw: &'a [u8],
25}
26
27impl<'a> X509CertificationRequest<'a> {
28 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 #[cfg(any(feature = "verify", feature = "verify-aws"))]
54 #[cfg_attr(docsrs, doc(cfg(any(feature = "verify", feature = "verify-aws"))))]
55 pub fn verify_signature(&self) -> Result<(), X509Error> {
56 let spki = &self.certification_request_info.subject_pki;
57 verify_signature(
58 spki,
59 &self.signature_algorithm,
60 &self.signature_value,
61 self.certification_request_info.raw,
62 )
63 }
64}
65
66impl<'a> AsRef<[u8]> for X509CertificationRequest<'a> {
67 fn as_ref(&self) -> &[u8] {
68 self.as_raw()
69 }
70}
71
72impl<'a> FromDer<'a, X509Error> for X509CertificationRequest<'a> {
80 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
81 let start_i = i;
82 let (rem, mut req) = parse_der_sequence_defined_g(|i, _| {
83 let (i, certification_request_info) = X509CertificationRequestInfo::from_der(i)?;
84 let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?;
85 let (i, signature_value) = parse_signature_value(i)?;
86 let cert = X509CertificationRequest {
87 certification_request_info,
88 signature_algorithm,
89 signature_value,
90 raw: &[],
91 };
92 Ok((i, cert))
93 })(i)?;
94 let len = start_i.offset(rem);
95 req.raw = &start_i[..len];
96 Ok((rem, req))
97 }
98}
99
100#[derive(Debug, PartialEq)]
118pub struct X509CertificationRequestInfo<'a> {
119 pub version: X509Version,
120 pub subject: X509Name<'a>,
121 pub subject_pki: SubjectPublicKeyInfo<'a>,
122 attributes: Vec<X509CriAttribute<'a>>,
123 pub raw: &'a [u8],
124}
125
126impl X509CertificationRequestInfo<'_> {
127 #[inline]
129 pub fn attributes(&self) -> &[X509CriAttribute<'_>] {
130 &self.attributes
131 }
132
133 #[inline]
135 pub fn iter_attributes(&self) -> impl Iterator<Item = &X509CriAttribute<'_>> {
136 self.attributes.iter()
137 }
138
139 pub fn find_attribute(&self, oid: &Oid) -> Option<&X509CriAttribute<'_>> {
143 self.attributes.iter().find(|&ext| ext.oid == *oid)
144 }
145
146 pub fn attributes_map(&self) -> Result<HashMap<Oid<'_>, &X509CriAttribute<'_>>, X509Error> {
150 self.attributes
151 .iter()
152 .try_fold(HashMap::new(), |mut m, ext| {
153 if m.contains_key(&ext.oid) {
154 return Err(X509Error::DuplicateAttributes);
155 }
156 m.insert(ext.oid.clone(), ext);
157 Ok(m)
158 })
159 }
160}
161
162impl<'a> FromDer<'a, X509Error> for X509CertificationRequestInfo<'a> {
171 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
172 let start_i = i;
173 parse_der_sequence_defined_g(move |i, _| {
174 let (i, version) = X509Version::from_der(i)?;
175 let (i, subject) = X509Name::from_der(i)?;
176 let (i, subject_pki) = SubjectPublicKeyInfo::from_der(i)?;
177 let (i, attributes) = parse_cri_attributes(i)?;
178 let len = start_i.offset(i);
179 let tbs = X509CertificationRequestInfo {
180 version,
181 subject,
182 subject_pki,
183 attributes,
184 raw: &start_i[..len],
185 };
186 Ok((i, tbs))
187 })(i)
188 }
189}