x509_certificate/
rfc2986.rs1use {
8 crate::{
9 rfc3280::Name,
10 rfc5280::{AlgorithmIdentifier, SubjectPublicKeyInfo},
11 rfc5652::Attribute,
12 rfc5958::Attributes,
13 },
14 bcder::{
15 decode::{Constructed, DecodeError, Source},
16 encode::{self, PrimitiveContent, Values},
17 BitString, Integer, Mode, Tag,
18 },
19 std::io::Write,
20};
21
22#[derive(Clone, Copy, Debug)]
23pub enum Version {
24 V1 = 0,
25}
26
27impl From<Version> for u8 {
28 fn from(v: Version) -> u8 {
29 match v {
30 Version::V1 => 0,
31 }
32 }
33}
34
35impl Version {
36 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
37 match cons.take_primitive_if(Tag::INTEGER, Integer::i8_from_primitive)? {
38 0 => Ok(Self::V1),
39 _ => Err(cons.content_err("unexpected non-integer when parsing Version")),
40 }
41 }
42
43 pub fn encode(self) -> impl Values {
44 u8::from(self).encode()
45 }
46}
47
48#[derive(Clone)]
59pub struct CertificationRequestInfo {
60 pub version: Version,
61 pub subject: Name,
62 pub subject_public_key_info: SubjectPublicKeyInfo,
63 pub attributes: Attributes,
64}
65
66impl CertificationRequestInfo {
67 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
68 cons.take_sequence(|cons| Self::from_sequence(cons))
69 }
70
71 pub fn from_sequence<S: Source>(
72 cons: &mut Constructed<S>,
73 ) -> Result<Self, DecodeError<S::Error>> {
74 let version = Version::take_from(cons)?;
75 let subject = Name::take_from(cons)?;
76 let subject_public_key_info = SubjectPublicKeyInfo::take_from(cons)?;
77 let attributes = cons.take_constructed_if(Tag::CTX_0, |cons| {
78 let mut attributes = Attributes::default();
79
80 while let Some(attribute) = Attribute::take_opt_from(cons)? {
81 attributes.push(attribute);
82 }
83
84 Ok(attributes)
85 })?;
86
87 Ok(Self {
88 version,
89 subject,
90 subject_public_key_info,
91 attributes,
92 })
93 }
94
95 pub fn encode_ref(&self) -> impl Values + '_ {
96 encode::sequence((
97 self.version.encode(),
98 self.subject.encode_ref(),
99 self.subject_public_key_info.encode_ref(),
100 self.attributes.encode_ref_as(Tag::CTX_0),
101 ))
102 }
103}
104
105impl Values for CertificationRequestInfo {
106 fn encoded_len(&self, mode: Mode) -> usize {
107 self.encode_ref().encoded_len(mode)
108 }
109
110 fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
111 self.encode_ref().write_encoded(mode, target)
112 }
113}
114
115#[derive(Clone)]
125pub struct CertificationRequest {
126 pub certificate_request_info: CertificationRequestInfo,
127 pub signature_algorithm: AlgorithmIdentifier,
128 pub signature: BitString,
129}
130
131impl CertificationRequest {
132 pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
133 cons.take_sequence(|cons| Self::from_sequence(cons))
134 }
135
136 pub fn from_sequence<S: Source>(
137 cons: &mut Constructed<S>,
138 ) -> Result<Self, DecodeError<S::Error>> {
139 let certificate_request_info = CertificationRequestInfo::take_from(cons)?;
140 let signature_algorithm = AlgorithmIdentifier::take_from(cons)?;
141 let signature = BitString::take_from(cons)?;
142
143 Ok(Self {
144 certificate_request_info,
145 signature_algorithm,
146 signature,
147 })
148 }
149
150 pub fn encode_ref(&self) -> impl Values + '_ {
151 encode::sequence((
152 self.certificate_request_info.encode_ref(),
153 &self.signature_algorithm,
154 self.signature.encode_ref(),
155 ))
156 }
157
158 pub fn encode_der(&self) -> Result<Vec<u8>, std::io::Error> {
160 let mut buffer = vec![];
161 self.write_encoded(Mode::Der, &mut buffer)?;
162
163 Ok(buffer)
164 }
165
166 pub fn encode_pem(&self) -> Result<String, std::io::Error> {
168 Ok(pem::Pem::new("CERTIFICATE REQUEST", self.encode_der()?).to_string())
169 }
170}
171
172impl Values for CertificationRequest {
173 fn encoded_len(&self, mode: Mode) -> usize {
174 self.encode_ref().encoded_len(mode)
175 }
176
177 fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
178 self.encode_ref().write_encoded(mode, target)
179 }
180}
181
182#[cfg(test)]
183mod test {
184 use super::*;
185
186 #[test]
187 fn rsa_parse() {
188 let der = include_bytes!("testdata/csr-rsa2048.der");
189
190 let csr = Constructed::decode(der.as_ref(), Mode::Der, |cons| {
191 CertificationRequest::take_from(cons)
192 })
193 .unwrap();
194
195 let mut encoded = vec![];
196 csr.write_encoded(Mode::Der, &mut encoded).unwrap();
197
198 assert_eq!(&encoded, der);
199 }
200}