1use std::hash::Hash;
2
3#[cfg(feature = "pem")]
4use pem::Pem;
5use pki_types::CertificateSigningRequestDer;
6
7#[cfg(feature = "pem")]
8use crate::ENCODE_CONFIG;
9use crate::{
10 key_pair::serialize_public_key_der, Certificate, CertificateParams, Error, Issuer, KeyPair,
11 PublicKeyData, SignatureAlgorithm,
12};
13#[cfg(feature = "x509-parser")]
14use crate::{DistinguishedName, SanType};
15
16#[derive(Debug, PartialEq, Eq, Hash)]
18pub struct PublicKey {
19 raw: Vec<u8>,
20 alg: &'static SignatureAlgorithm,
21}
22
23impl PublicKey {
24 pub fn algorithm(&self) -> &SignatureAlgorithm {
26 self.alg
27 }
28}
29
30impl PublicKeyData for PublicKey {
31 fn der_bytes(&self) -> &[u8] {
32 &self.raw
33 }
34
35 fn algorithm(&self) -> &SignatureAlgorithm {
36 self.alg
37 }
38}
39
40pub struct CertificateSigningRequest {
42 pub(crate) der: CertificateSigningRequestDer<'static>,
43}
44
45impl CertificateSigningRequest {
46 #[cfg(feature = "pem")]
48 pub fn pem(&self) -> Result<String, Error> {
49 let p = Pem::new("CERTIFICATE REQUEST", &*self.der);
50 Ok(pem::encode_config(&p, ENCODE_CONFIG))
51 }
52
53 pub fn der(&self) -> &CertificateSigningRequestDer<'static> {
58 &self.der
59 }
60}
61
62impl From<CertificateSigningRequest> for CertificateSigningRequestDer<'static> {
63 fn from(csr: CertificateSigningRequest) -> Self {
64 csr.der
65 }
66}
67
68pub struct CertificateSigningRequestParams {
70 pub params: CertificateParams,
72 pub public_key: PublicKey,
74}
75
76impl CertificateSigningRequestParams {
77 #[cfg(all(feature = "pem", feature = "x509-parser"))]
81 pub fn from_pem(pem_str: &str) -> Result<Self, Error> {
82 let csr = pem::parse(pem_str).or(Err(Error::CouldNotParseCertificationRequest))?;
83 Self::from_der(&csr.contents().into())
84 }
85
86 #[cfg(feature = "x509-parser")]
97 pub fn from_der(csr: &CertificateSigningRequestDer<'_>) -> Result<Self, Error> {
98 use crate::KeyUsagePurpose;
99 use x509_parser::prelude::FromDer;
100
101 let csr = x509_parser::certification_request::X509CertificationRequest::from_der(csr)
102 .map_err(|_| Error::CouldNotParseCertificationRequest)?
103 .1;
104 csr.verify_signature().map_err(|_| Error::RingUnspecified)?;
105 let alg_oid = csr
106 .signature_algorithm
107 .algorithm
108 .iter()
109 .ok_or(Error::CouldNotParseCertificationRequest)?
110 .collect::<Vec<_>>();
111 let alg = SignatureAlgorithm::from_oid(&alg_oid)?;
112
113 let info = &csr.certification_request_info;
114 let mut params = CertificateParams {
115 distinguished_name: DistinguishedName::from_name(&info.subject)?,
116 ..CertificateParams::default()
117 };
118 let raw = info.subject_pki.subject_public_key.data.to_vec();
119
120 if let Some(extensions) = csr.requested_extensions() {
121 for ext in extensions {
122 match ext {
123 x509_parser::extensions::ParsedExtension::KeyUsage(key_usage) => {
124 params.key_usages =
126 KeyUsagePurpose::from_u16(key_usage.flags.reverse_bits());
127 },
128 x509_parser::extensions::ParsedExtension::SubjectAlternativeName(san) => {
129 for name in &san.general_names {
130 params
131 .subject_alt_names
132 .push(SanType::try_from_general(name)?);
133 }
134 },
135 x509_parser::extensions::ParsedExtension::ExtendedKeyUsage(eku) => {
136 if eku.any {
137 params.insert_extended_key_usage(crate::ExtendedKeyUsagePurpose::Any);
138 }
139 if eku.server_auth {
140 params.insert_extended_key_usage(
141 crate::ExtendedKeyUsagePurpose::ServerAuth,
142 );
143 }
144 if eku.client_auth {
145 params.insert_extended_key_usage(
146 crate::ExtendedKeyUsagePurpose::ClientAuth,
147 );
148 }
149 if eku.code_signing {
150 params.insert_extended_key_usage(
151 crate::ExtendedKeyUsagePurpose::CodeSigning,
152 );
153 }
154 if eku.email_protection {
155 params.insert_extended_key_usage(
156 crate::ExtendedKeyUsagePurpose::EmailProtection,
157 );
158 }
159 if eku.time_stamping {
160 params.insert_extended_key_usage(
161 crate::ExtendedKeyUsagePurpose::TimeStamping,
162 );
163 }
164 if eku.ocsp_signing {
165 params.insert_extended_key_usage(
166 crate::ExtendedKeyUsagePurpose::OcspSigning,
167 );
168 }
169 if !eku.other.is_empty() {
170 return Err(Error::UnsupportedExtension);
171 }
172 },
173 _ => return Err(Error::UnsupportedExtension),
174 }
175 }
176 }
177
178 Ok(Self {
185 params,
186 public_key: PublicKey { alg, raw },
187 })
188 }
189
190 pub fn signed_by(
203 self,
204 issuer: &Certificate,
205 issuer_key: &KeyPair,
206 ) -> Result<Certificate, Error> {
207 let issuer = Issuer {
208 distinguished_name: &issuer.params.distinguished_name,
209 key_identifier_method: &issuer.params.key_identifier_method,
210 key_usages: &issuer.params.key_usages,
211 key_pair: issuer_key,
212 };
213
214 let der = self
215 .params
216 .serialize_der_with_signer(&self.public_key, issuer)?;
217 let subject_public_key_info = yasna::construct_der(|writer| {
218 serialize_public_key_der(&self.public_key, writer);
219 });
220 Ok(Certificate {
221 params: self.params,
222 subject_public_key_info,
223 der,
224 })
225 }
226}