1 use crate::hash::HashAlgorithm;
2 use crate::key::{PrivateKey, PublicKey};
3 use crate::pem::{parse_pem, Pem, PemError};
4 use crate::signature::{SignatureAlgorithm, SignatureError};
5 use crate::x509::csr::{Csr, CsrError};
6 use crate::x509::date::UTCDate;
7 use crate::x509::key_id_gen_method::{KeyIdGenError, KeyIdGenMethod};
8 use crate::x509::name::{DirectoryName, GeneralNames};
9 use picky_asn1::bit_string::BitString;
10 use picky_asn1::wrapper::{ApplicationTag0, ApplicationTag3, IntegerAsn1};
11 use picky_asn1_der::Asn1DerError;
12 use picky_asn1_x509::{
13     oids, AlgorithmIdentifier, AuthorityKeyIdentifier, BasicConstraints, Certificate, ExtendedKeyUsage, Extension,
14     ExtensionView, Extensions, KeyIdentifier, KeyUsage, Name, SubjectPublicKeyInfo, TBSCertificate, Validity, Version,
15 };
16 use std::cell::RefCell;
17 use thiserror::Error;
18 
19 #[derive(Debug, Error)]
20 pub enum CertError {
21     /// couldn't generate certificate
22     #[error("couldn't generate certificate: {source}")]
23     CertGeneration { source: Box<CertError> },
24 
25     /// invalid certificate
26     #[error("invalid certificate '{id}': {source}")]
27     InvalidCertificate { id: String, source: Box<CertError> },
28 
29     /// ASN1 serialization error
30     #[error("(ASN1) couldn't serialize {element}: {source}")]
31     Asn1Serialization {
32         element: &'static str,
33         source: Asn1DerError,
34     },
35 
36     /// ASN1 deserialization error
37     #[error("(ASN1) couldn't deserialize {element}: {source}")]
38     Asn1Deserialization {
39         element: &'static str,
40         source: Asn1DerError,
41     },
42 
43     /// signature error
44     #[error("signature error: {source}")]
45     Signature { source: SignatureError },
46 
47     /// key id generation error
48     #[error("key id generation error: {source}")]
49     KeyIdGen { source: KeyIdGenError },
50 
51     /// CA chain error
52     #[error("CA chain error: {source}")]
53     InvalidChain { source: CaChainError },
54 
55     /// CSR error
56     #[error("CSR error: {source}")]
57     InvalidCsr { source: CsrError },
58 
59     /// extension not found
60     #[error("extension not found: {name}")]
61     ExtensionNotFound { name: &'static str },
62 
63     /// missing required builder argument
64     #[error("missing required builder argument `{arg}`")]
65     MissingBuilderArgument { arg: &'static str },
66 
67     /// certificate is not yet valid
68     #[error("certificate is not yet valid (not before: {not_before}, now: {now})")]
69     CertificateNotYetValid { not_before: UTCDate, now: UTCDate },
70 
71     /// certificate expired
72     #[error("certificate expired (not after: {not_after}, now: {now})")]
73     CertificateExpired { not_after: UTCDate, now: UTCDate },
74 
75     /// invalid PEM label error
76     #[error("invalid PEM label: {label}")]
77     InvalidPemLabel { label: String },
78 
79     /// invalid PEM provided
80     #[error("invalid PEM provided: {source}")]
81     Pem { source: PemError },
82 }
83 
84 impl From<PemError> for CertError {
from(e: PemError) -> Self85     fn from(e: PemError) -> Self {
86         Self::Pem { source: e }
87     }
88 }
89 
90 #[derive(Debug, Error)]
91 pub enum CaChainError {
92     /// chain depth does't satisfy basic constraints extension
93     #[error(
94         "chain depth doesn't satisfy basic constraints extension: certificate '{cert_id}' has pathlen of {pathlen}"
95     )]
96     TooDeep { cert_id: String, pathlen: u8 },
97 
98     /// chain is missing a root certificate
99     #[error("chain is missing a root certificate")]
100     NoRoot,
101 
102     /// issuer certificate is not a CA
103     #[error("issuer certificate '{issuer_id}' is not a CA")]
104     IssuerIsNotCA { issuer_id: String },
105 
106     /// authority key id doesn't match
107     #[error("authority key id doesn't match (expected: {}, got: {})", base64::encode(&.expected), base64::encode(&.actual))]
108     AuthorityKeyIdMismatch { expected: Vec<u8>, actual: Vec<u8> },
109 
110     /// issuer name doesn't match
111     #[error("issuer name doesn't match (expected: {expected}, got: {actual})")]
112     IssuerNameMismatch { expected: String, actual: String },
113 }
114 
115 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
116 pub enum CertType {
117     Root,
118     Intermediate,
119     Leaf,
120     Unknown,
121 }
122 
123 const CERT_PEM_LABEL: &str = "CERTIFICATE";
124 
125 #[derive(Clone, Debug, PartialEq)]
126 pub struct Cert(Certificate);
127 
128 impl From<Certificate> for Cert {
from(certificate: Certificate) -> Self129     fn from(certificate: Certificate) -> Self {
130         Self(certificate)
131     }
132 }
133 
134 impl From<Cert> for Certificate {
from(certificate: Cert) -> Self135     fn from(certificate: Cert) -> Self {
136         certificate.0
137     }
138 }
139 
140 macro_rules! find_ext {
141     ($oid:expr, $certificate:ident, $ext_name:literal) => {{
142         let key_identifier_oid = $oid;
143         ($certificate.tbs_certificate.extensions.0)
144             .0
145             .iter()
146             .find(|ext| ext.extn_id() == &key_identifier_oid)
147             .ok_or(CertError::ExtensionNotFound { name: $ext_name })
148     }};
149 }
150 
151 impl Cert {
from_der<T: ?Sized + AsRef<[u8]>>(der: &T) -> Result<Self, CertError>152     pub fn from_der<T: ?Sized + AsRef<[u8]>>(der: &T) -> Result<Self, CertError> {
153         Ok(Self(picky_asn1_der::from_bytes(der.as_ref()).map_err(|e| {
154             CertError::Asn1Deserialization {
155                 source: e,
156                 element: "certificate",
157             }
158         })?))
159     }
160 
from_pem(pem: &Pem) -> Result<Self, CertError>161     pub fn from_pem(pem: &Pem) -> Result<Self, CertError> {
162         match pem.label() {
163             CERT_PEM_LABEL => Self::from_der(pem.data()),
164             _ => Err(CertError::InvalidPemLabel {
165                 label: pem.label().to_owned(),
166             }),
167         }
168     }
169 
from_pem_str(pem_str: &str) -> Result<Self, CertError>170     pub fn from_pem_str(pem_str: &str) -> Result<Self, CertError> {
171         let pem = parse_pem(pem_str)?;
172         Self::from_pem(&pem)
173     }
174 
to_der(&self) -> Result<Vec<u8>, CertError>175     pub fn to_der(&self) -> Result<Vec<u8>, CertError> {
176         picky_asn1_der::to_vec(&self.0).map_err(|e| CertError::Asn1Serialization {
177             source: e,
178             element: "certificate",
179         })
180     }
181 
to_pem(&self) -> Result<Pem<'static>, CertError>182     pub fn to_pem(&self) -> Result<Pem<'static>, CertError> {
183         Ok(Pem::new(CERT_PEM_LABEL, self.to_der()?))
184     }
185 
ty(&self) -> CertType186     pub fn ty(&self) -> CertType {
187         if let Some(ca) = self.basic_constraints().map(|bc| bc.ca()).unwrap_or(None) {
188             if ca {
189                 if self.subject_name() == self.issuer_name() {
190                     CertType::Root
191                 } else {
192                     CertType::Intermediate
193                 }
194             } else {
195                 CertType::Leaf
196             }
197         } else {
198             CertType::Unknown
199         }
200     }
201 
serial_number(&self) -> &IntegerAsn1202     pub fn serial_number(&self) -> &IntegerAsn1 {
203         &self.0.tbs_certificate.serial_number
204     }
205 
signature_algorithm(&self) -> &AlgorithmIdentifier206     pub fn signature_algorithm(&self) -> &AlgorithmIdentifier {
207         &self.0.tbs_certificate.signature
208     }
209 
valid_not_before(&self) -> UTCDate210     pub fn valid_not_before(&self) -> UTCDate {
211         self.0.tbs_certificate.validity.not_before.clone().into()
212     }
213 
valid_not_after(&self) -> UTCDate214     pub fn valid_not_after(&self) -> UTCDate {
215         self.0.tbs_certificate.validity.not_after.clone().into()
216     }
217 
subject_key_identifier(&self) -> Result<&[u8], CertError>218     pub fn subject_key_identifier(&self) -> Result<&[u8], CertError> {
219         let certificate = &self.0;
220 
221         let ext = find_ext!(oids::subject_key_identifier(), certificate, "subject key identifier")?;
222         match ext.extn_value() {
223             ExtensionView::SubjectKeyIdentifier(ski) => Ok(&ski.0),
224             _ => unreachable!("invalid extension (expected subject key identifier)"),
225         }
226     }
227 
authority_key_identifier(&self) -> Result<&AuthorityKeyIdentifier, CertError>228     pub fn authority_key_identifier(&self) -> Result<&AuthorityKeyIdentifier, CertError> {
229         let certificate = &self.0;
230 
231         let ext = find_ext!(
232             oids::authority_key_identifier(),
233             certificate,
234             "authority key identifier"
235         )?;
236         match ext.extn_value() {
237             ExtensionView::AuthorityKeyIdentifier(aki) => Ok(aki),
238             _ => unreachable!("invalid extension (expected authority key identifier)"),
239         }
240     }
241 
basic_constraints(&self) -> Result<&BasicConstraints, CertError>242     pub fn basic_constraints(&self) -> Result<&BasicConstraints, CertError> {
243         let certificate = &self.0;
244         let ext = find_ext!(oids::basic_constraints(), certificate, "basic constraints")?;
245         match ext.extn_value() {
246             ExtensionView::BasicConstraints(bc) => Ok(bc),
247             _ => unreachable!("invalid extension (expected basic constraints)"),
248         }
249     }
250 
subject_name(&self) -> DirectoryName251     pub fn subject_name(&self) -> DirectoryName {
252         self.0.tbs_certificate.subject.clone().into()
253     }
254 
issuer_name(&self) -> DirectoryName255     pub fn issuer_name(&self) -> DirectoryName {
256         self.0.tbs_certificate.issuer.clone().into()
257     }
258 
extensions(&self) -> &[Extension]259     pub fn extensions(&self) -> &[Extension] {
260         (self.0.tbs_certificate.extensions.0).0.as_slice()
261     }
262 
public_key(&self) -> &PublicKey263     pub fn public_key(&self) -> &PublicKey {
264         (&self.0.tbs_certificate.subject_public_key_info).into()
265     }
266 
into_public_key(self) -> PublicKey267     pub fn into_public_key(self) -> PublicKey {
268         self.0.tbs_certificate.subject_public_key_info.into()
269     }
270 
is_parent_of(&self, other: &Cert) -> Result<(), CertError>271     pub fn is_parent_of(&self, other: &Cert) -> Result<(), CertError> {
272         if let Ok(other_aki) = other.authority_key_identifier() {
273             if let Some(other_aki) = other_aki.key_identifier() {
274                 let parent_ski = self
275                     .subject_key_identifier()
276                     .map_err(|e| CertError::InvalidCertificate {
277                         source: Box::new(e),
278                         id: self.subject_name().to_string(),
279                     })?;
280 
281                 if parent_ski != other_aki {
282                     return Err(CaChainError::AuthorityKeyIdMismatch {
283                         expected: other_aki.to_vec(),
284                         actual: parent_ski.to_vec(),
285                     })
286                     .map_err(|e| CertError::InvalidChain { source: e })
287                     .map_err(|e| CertError::InvalidCertificate {
288                         source: Box::new(e),
289                         id: other.subject_name().to_string(),
290                     });
291                 }
292             }
293         }
294 
295         let other_issuer_name = other.issuer_name();
296         let self_subject_name = self.subject_name();
297         if other_issuer_name != self_subject_name {
298             return Err(CaChainError::IssuerNameMismatch {
299                 expected: other_issuer_name.to_string(),
300                 actual: self_subject_name.to_string(),
301             })
302             .map_err(|e| CertError::InvalidChain { source: e })
303             .map_err(|e| CertError::InvalidCertificate {
304                 source: Box::new(e),
305                 id: other.subject_name().to_string(),
306             });
307         }
308 
309         Ok(())
310     }
311 
verifier<'a, 'b, Chain: Iterator<Item = &'b Cert>>(&'a self) -> CertValidator<'a, 'b, Chain>312     pub fn verifier<'a, 'b, Chain: Iterator<Item = &'b Cert>>(&'a self) -> CertValidator<'a, 'b, Chain> {
313         CertValidator {
314             cert: self,
315             inner: RefCell::new(CertValidatorInner {
316                 strictness: Default::default(),
317                 now: None,
318                 chain: None,
319             }),
320         }
321     }
322 }
323 
324 // === certificate verifier === /
325 
326 #[derive(Debug, Clone)]
327 enum ValidityCheck<'a> {
328     Interval { lower: &'a UTCDate, upper: &'a UTCDate },
329     Exact(&'a UTCDate),
330 }
331 
332 #[derive(Debug, Clone)]
333 struct CheckStrictness {
334     require_not_before_check: bool,
335     require_not_after_check: bool,
336     require_chain_check: bool,
337 }
338 
339 impl Default for CheckStrictness {
default() -> Self340     fn default() -> Self {
341         Self {
342             require_not_before_check: true,
343             require_not_after_check: true,
344             require_chain_check: true,
345         }
346     }
347 }
348 
349 #[derive(Clone, Debug)]
350 struct CertValidatorInner<'a, 'b, Chain: Iterator<Item = &'b Cert>> {
351     strictness: CheckStrictness,
352     now: Option<ValidityCheck<'a>>,
353     chain: Option<Chain>,
354 }
355 
356 /// Utility to verify x509 `Cert`s
357 #[derive(Clone, Debug)]
358 pub struct CertValidator<'a, 'b, Chain: Iterator<Item = &'b Cert>> {
359     cert: &'a Cert,
360     inner: RefCell<CertValidatorInner<'a, 'b, Chain>>,
361 }
362 
363 impl<'a, 'b, Chain: Iterator<Item = &'b Cert>> CertValidator<'a, 'b, Chain> {
364     #[inline]
exact_date(&self, exact: &'a UTCDate) -> &Self365     pub fn exact_date(&self, exact: &'a UTCDate) -> &Self {
366         self.inner.borrow_mut().now = Some(ValidityCheck::Exact(exact));
367         self
368     }
369 
370     #[inline]
interval_date(&self, lower: &'a UTCDate, upper: &'a UTCDate) -> &Self371     pub fn interval_date(&self, lower: &'a UTCDate, upper: &'a UTCDate) -> &Self {
372         self.inner.borrow_mut().now = Some(ValidityCheck::Interval { lower, upper });
373         self
374     }
375 
376     #[inline]
chain(&self, chain: Chain) -> &Self377     pub fn chain(&self, chain: Chain) -> &Self {
378         self.inner.borrow_mut().chain = Some(chain);
379         self
380     }
381 
382     #[inline]
require_not_before_check(&self) -> &Self383     pub fn require_not_before_check(&self) -> &Self {
384         self.inner.borrow_mut().strictness.require_not_before_check = true;
385         self
386     }
387 
388     #[inline]
require_not_after_check(&self) -> &Self389     pub fn require_not_after_check(&self) -> &Self {
390         self.inner.borrow_mut().strictness.require_not_after_check = true;
391         self
392     }
393 
394     #[inline]
require_chain_check(&self) -> &Self395     pub fn require_chain_check(&self) -> &Self {
396         self.inner.borrow_mut().strictness.require_chain_check = true;
397         self
398     }
399 
400     #[inline]
ignore_not_before_check(&self) -> &Self401     pub fn ignore_not_before_check(&self) -> &Self {
402         self.inner.borrow_mut().strictness.require_not_before_check = false;
403         self
404     }
405 
406     #[inline]
ignore_not_after_check(&self) -> &Self407     pub fn ignore_not_after_check(&self) -> &Self {
408         self.inner.borrow_mut().strictness.require_not_after_check = false;
409         self
410     }
411 
412     #[inline]
ignore_chain_check(&self) -> &Self413     pub fn ignore_chain_check(&self) -> &Self {
414         self.inner.borrow_mut().strictness.require_chain_check = false;
415         self
416     }
417 
verify(&self) -> Result<(), CertError>418     pub fn verify(&self) -> Result<(), CertError> {
419         let mut inner = self.inner.borrow_mut();
420 
421         if (inner.strictness.require_not_after_check || inner.strictness.require_not_before_check)
422             && inner.now.is_none()
423         {
424             return Err(CertError::MissingBuilderArgument { arg: "now" });
425         }
426 
427         if let Some(now) = &inner.now {
428             verify_cert_validity(self.cert, &inner.strictness, now.clone()).map_err(|e| {
429                 CertError::InvalidCertificate {
430                     source: Box::new(e),
431                     id: self.cert.subject_name().to_string(),
432                 }
433             })?;
434         }
435 
436         if !inner.strictness.require_chain_check {
437             return Ok(());
438         }
439 
440         let chain = if let Some(chain) = inner.chain.take() {
441             chain
442         } else {
443             return Err(CertError::MissingBuilderArgument { arg: "chain" });
444         };
445 
446         let mut current_cert = self.cert;
447 
448         for (number_certs, parent_cert) in chain.enumerate() {
449             // check basic constraints
450             match parent_cert
451                 .basic_constraints()
452                 .map(|bc| (bc.ca(), bc.pathlen()))
453                 .unwrap_or((None, None))
454             {
455                 (Some(false), _) => {
456                     return Err(CaChainError::IssuerIsNotCA {
457                         issuer_id: parent_cert.subject_name().to_string(),
458                     })
459                     .map_err(|e| CertError::InvalidChain { source: e });
460                 }
461                 (_, Some(pathlen)) if usize::from(pathlen) < number_certs => {
462                     return Err(CaChainError::TooDeep {
463                         cert_id: parent_cert.subject_name().to_string(),
464                         pathlen,
465                     })
466                     .map_err(|e| CertError::InvalidChain { source: e });
467                 }
468                 _ => {}
469             }
470 
471             // verify parent validity
472             if let Some(now) = &inner.now {
473                 verify_cert_validity(parent_cert, &inner.strictness, now.clone()).map_err(|e| {
474                     CertError::InvalidCertificate {
475                         source: Box::new(e),
476                         id: parent_cert.subject_name().to_string(),
477                     }
478                 })?;
479             }
480 
481             // check parent_cert is the parent of current_cert
482             parent_cert.is_parent_of(current_cert)?;
483 
484             // validate current cert signature using parent public key
485             let hash_type = SignatureAlgorithm::from_algorithm_identifier(&current_cert.0.signature_algorithm)
486                 .map_err(|e| CertError::Signature { source: e })?;
487             let public_key = &parent_cert.0.tbs_certificate.subject_public_key_info;
488             let msg = picky_asn1_der::to_vec(&current_cert.0.tbs_certificate)
489                 .map_err(|e| CertError::Asn1Serialization {
490                     source: e,
491                     element: "tbs certificate",
492                 })
493                 .map_err(|e| CertError::InvalidCertificate {
494                     source: Box::new(e),
495                     id: current_cert.subject_name().to_string(),
496                 })?;
497             hash_type
498                 .verify(
499                     &public_key.clone().into(),
500                     &msg,
501                     current_cert.0.signature_value.0.payload_view(),
502                 )
503                 .map_err(|e| CertError::Signature { source: e })
504                 .map_err(|e| CertError::InvalidCertificate {
505                     source: Box::new(e),
506                     id: current_cert.subject_name().to_string(),
507                 })?;
508 
509             current_cert = parent_cert;
510         }
511 
512         // make sure `current_cert` (the last certificate of the chain) is a root CA
513         if current_cert.ty() != CertType::Root {
514             return Err(CaChainError::NoRoot).map_err(|e| CertError::InvalidChain { source: e });
515         }
516 
517         Ok(())
518     }
519 }
520 
verify_cert_validity(cert: &Cert, strictness: &CheckStrictness, now: ValidityCheck<'_>) -> Result<(), CertError>521 fn verify_cert_validity(cert: &Cert, strictness: &CheckStrictness, now: ValidityCheck<'_>) -> Result<(), CertError> {
522     let validity = &cert.0.tbs_certificate.validity;
523     let not_before: UTCDate = validity.not_before.clone().into();
524     let not_after: UTCDate = validity.not_after.clone().into();
525 
526     match now {
527         ValidityCheck::Interval { lower, upper } => {
528             if not_before.gt(upper) && strictness.require_not_before_check {
529                 return Err(CertError::CertificateNotYetValid {
530                     not_before,
531                     now: upper.clone(),
532                 });
533             }
534 
535             if not_after.lt(lower) && strictness.require_not_after_check {
536                 return Err(CertError::CertificateExpired {
537                     not_after,
538                     now: lower.clone(),
539                 });
540             }
541         }
542         ValidityCheck::Exact(now) => {
543             if not_before.gt(now) && strictness.require_not_before_check {
544                 return Err(CertError::CertificateNotYetValid {
545                     not_before,
546                     now: now.clone(),
547                 });
548             }
549 
550             if not_after.lt(now) && strictness.require_not_after_check {
551                 return Err(CertError::CertificateExpired {
552                     not_after,
553                     now: now.clone(),
554                 });
555             }
556         }
557     }
558 
559     Ok(())
560 }
561 
562 // === builder === //
563 
564 #[derive(Clone, Debug)]
565 enum SubjectInfos {
566     Csr(Csr),
567     NameAndPublicKey { name: DirectoryName, public_key: PublicKey },
568 }
569 
570 #[derive(Clone, Debug)]
571 struct IssuerInfos<'a> {
572     name: DirectoryName,
573     key: &'a PrivateKey,
574     self_signed: bool,
575 }
576 
577 // Statically checks the field actually exists and returns a &'static str of the field name
578 macro_rules! field_str {
579     ($field:ident) => {{
580         const _: fn() = || {
581             let CertificateBuilderInner { $field: _, .. };
582         };
583         stringify!($field)
584     }};
585 }
586 
587 #[derive(Default, Clone, Debug)]
588 struct CertificateBuilderInner<'a> {
589     valid_from: Option<UTCDate>,
590     valid_to: Option<UTCDate>,
591     subject_infos: Option<SubjectInfos>,
592     issuer_infos: Option<IssuerInfos<'a>>,
593     authority_key_identifier: Option<Vec<u8>>,
594     ca: Option<bool>,
595     pathlen: Option<u8>,
596     signature_hash_type: Option<SignatureAlgorithm>,
597     key_id_gen_method: Option<KeyIdGenMethod>,
598     key_usage: Option<KeyUsage>,
599     extended_key_usage: Option<ExtendedKeyUsage>,
600     subject_alt_name: Option<GeneralNames>,
601     issuer_alt_name: Option<GeneralNames>,
602     serial_number: Option<Vec<u8>>,
603     inherit_extensions_from_csr_attributes: bool,
604 }
605 
606 #[derive(Default, Clone, Debug)]
607 pub struct CertificateBuilder<'a> {
608     inner: RefCell<CertificateBuilderInner<'a>>,
609 }
610 
611 impl<'a> CertificateBuilder<'a> {
new() -> Self612     pub fn new() -> Self {
613         Self::default()
614     }
615 
616     /// Required
617     #[inline]
validity(&self, valid_from: UTCDate, valid_to: UTCDate) -> &Self618     pub fn validity(&self, valid_from: UTCDate, valid_to: UTCDate) -> &Self {
619         let mut inner_mut = self.inner.borrow_mut();
620         inner_mut.valid_from = Some(valid_from);
621         inner_mut.valid_to = Some(valid_to);
622         drop(inner_mut);
623         self
624     }
625 
626     /// Required (alternatives: `subject_from_csr`, `self_signed`)
627     #[inline]
subject(&self, subject_name: DirectoryName, public_key: PublicKey) -> &Self628     pub fn subject(&self, subject_name: DirectoryName, public_key: PublicKey) -> &Self {
629         self.inner.borrow_mut().subject_infos = Some(SubjectInfos::NameAndPublicKey {
630             name: subject_name,
631             public_key,
632         });
633         self
634     }
635 
636     /// Required (alternatives: `subject`, `self_signed`)
637     #[inline]
subject_from_csr(&self, csr: Csr) -> &Self638     pub fn subject_from_csr(&self, csr: Csr) -> &Self {
639         self.inner.borrow_mut().subject_infos = Some(SubjectInfos::Csr(csr));
640         self
641     }
642 
643     /// Required (alternative: `self_signed`, `issuer_cert`)
644     #[inline]
issuer(&self, issuer_name: DirectoryName, issuer_key: &'a PrivateKey) -> &Self645     pub fn issuer(&self, issuer_name: DirectoryName, issuer_key: &'a PrivateKey) -> &Self {
646         self.inner.borrow_mut().issuer_infos = Some(IssuerInfos {
647             name: issuer_name,
648             key: issuer_key,
649             self_signed: false,
650         });
651         self
652     }
653 
654     /// Required (alternative: `issuer`, `issuer_cert`)
655     #[inline]
self_signed(&self, name: DirectoryName, key: &'a PrivateKey) -> &Self656     pub fn self_signed(&self, name: DirectoryName, key: &'a PrivateKey) -> &Self {
657         self.inner.borrow_mut().issuer_infos = Some(IssuerInfos {
658             name,
659             key,
660             self_signed: true,
661         });
662         self
663     }
664 
665     /// Required (alternative: `issuer`, `self_signed`)
666     #[inline]
issuer_cert(&self, issuer_cert: &Cert, issuer_key: &'a PrivateKey) -> &Self667     pub fn issuer_cert(&self, issuer_cert: &Cert, issuer_key: &'a PrivateKey) -> &Self {
668         let builder = self.issuer(issuer_cert.subject_name(), &issuer_key);
669 
670         if let Ok(issuer_ski) = issuer_cert.subject_key_identifier() {
671             self.authority_key_identifier(issuer_ski.to_vec())
672         } else {
673             builder
674         }
675     }
676 
677     /// Optional (alternative: `issuer_cert`, `self_signed`)
678     #[inline]
authority_key_identifier(&self, aki: Vec<u8>) -> &Self679     pub fn authority_key_identifier(&self, aki: Vec<u8>) -> &Self {
680         self.inner.borrow_mut().authority_key_identifier = Some(aki);
681         self
682     }
683 
684     /// Optional
685     #[inline]
ca(&self, ca: bool) -> &Self686     pub fn ca(&self, ca: bool) -> &Self {
687         self.inner.borrow_mut().ca = Some(ca);
688         self
689     }
690 
691     /// Optional
692     #[inline]
pathlen(&self, pathlen: u8) -> &Self693     pub fn pathlen(&self, pathlen: u8) -> &Self {
694         self.inner.borrow_mut().pathlen = Some(pathlen);
695         self
696     }
697 
698     /// Optional
699     #[inline]
signature_hash_type(&self, signature_hash_type: SignatureAlgorithm) -> &Self700     pub fn signature_hash_type(&self, signature_hash_type: SignatureAlgorithm) -> &Self {
701         self.inner.borrow_mut().signature_hash_type = Some(signature_hash_type);
702         self
703     }
704 
705     /// Optional
706     #[inline]
key_id_gen_method(&self, key_id_gen_method: KeyIdGenMethod) -> &Self707     pub fn key_id_gen_method(&self, key_id_gen_method: KeyIdGenMethod) -> &Self {
708         self.inner.borrow_mut().key_id_gen_method = Some(key_id_gen_method);
709         self
710     }
711 
712     /// Optional
713     #[inline]
key_usage(&self, key_usage: KeyUsage) -> &Self714     pub fn key_usage(&self, key_usage: KeyUsage) -> &Self {
715         self.inner.borrow_mut().key_usage = Some(key_usage);
716         self
717     }
718 
719     /// Optional
720     #[inline]
extended_key_usage(&self, extended_key_usage: ExtendedKeyUsage) -> &Self721     pub fn extended_key_usage(&self, extended_key_usage: ExtendedKeyUsage) -> &Self {
722         self.inner.borrow_mut().extended_key_usage = Some(extended_key_usage);
723         self
724     }
725 
726     /// Optional
727     #[inline]
subject_alt_name(&self, subject_alt_name: GeneralNames) -> &Self728     pub fn subject_alt_name(&self, subject_alt_name: GeneralNames) -> &Self {
729         self.inner.borrow_mut().subject_alt_name = Some(subject_alt_name);
730         self
731     }
732 
733     /// Optional
734     #[inline]
issuer_alt_name(&self, issuer_alt_name: GeneralNames) -> &Self735     pub fn issuer_alt_name(&self, issuer_alt_name: GeneralNames) -> &Self {
736         self.inner.borrow_mut().issuer_alt_name = Some(issuer_alt_name);
737         self
738     }
739 
740     /// Optional
741     ///
742     /// Bypass picky serial number generator by providing your own.
743     #[inline]
serial_number(&self, unsigned_integer_bytes: Vec<u8>) -> &Self744     pub fn serial_number(&self, unsigned_integer_bytes: Vec<u8>) -> &Self {
745         self.inner.borrow_mut().serial_number = Some(unsigned_integer_bytes);
746         self
747     }
748 
749     /// Optional
750     ///
751     /// Inherit extensions from the "extension request" attribute of the provided CSR if applicable
752     /// Extensions already present will be ignored.
753     #[inline]
inherit_extensions_from_csr_attributes(&self, inherit: bool) -> &Self754     pub fn inherit_extensions_from_csr_attributes(&self, inherit: bool) -> &Self {
755         self.inner.borrow_mut().inherit_extensions_from_csr_attributes = inherit;
756         self
757     }
758 
build(&self) -> Result<Cert, CertError>759     pub fn build(&self) -> Result<Cert, CertError> {
760         let mut inner = self.inner.borrow_mut();
761 
762         let valid_from = inner.valid_from.take().ok_or(CertError::MissingBuilderArgument {
763             arg: field_str!(valid_from),
764         })?;
765         let valid_to = inner.valid_to.take().ok_or(CertError::MissingBuilderArgument {
766             arg: field_str!(valid_to),
767         })?;
768 
769         let signature_hash_type = inner
770             .signature_hash_type
771             .take()
772             .unwrap_or(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_256));
773 
774         let key_id_gen_method = inner
775             .key_id_gen_method
776             .take()
777             .unwrap_or(KeyIdGenMethod::SPKFullDER(HashAlgorithm::SHA2_256));
778 
779         let issuer_infos = inner.issuer_infos.take().ok_or(CertError::MissingBuilderArgument {
780             arg: field_str!(issuer_infos),
781         })?;
782         let (issuer_name, issuer_key, aki, subject_infos) = {
783             let (aki, subject_infos) = if issuer_infos.self_signed {
784                 let public_key = issuer_infos.key.to_public_key();
785                 let aki = key_id_gen_method
786                     .generate_from(&public_key)
787                     .map_err(|e| CertError::KeyIdGen { source: e })
788                     .map_err(|e| CertError::CertGeneration { source: Box::new(e) })?;
789                 let subject_infos = SubjectInfos::NameAndPublicKey {
790                     name: issuer_infos.name.clone(),
791                     public_key,
792                 };
793                 (aki, subject_infos)
794             } else {
795                 let aki = inner
796                     .authority_key_identifier
797                     .take()
798                     .ok_or(CertError::MissingBuilderArgument {
799                         arg: field_str!(authority_key_identifier),
800                     })?;
801                 let subject_infos = inner.subject_infos.take().ok_or(CertError::MissingBuilderArgument {
802                     arg: field_str!(subject_infos),
803                 })?;
804                 (aki, subject_infos)
805             };
806 
807             (issuer_infos.name, issuer_infos.key, aki, subject_infos)
808         };
809         let (subject_name, subject_public_key, ext_req) = match subject_infos {
810             SubjectInfos::Csr(csr) => {
811                 csr.verify().map_err(|e| CertError::InvalidCsr { source: e })?;
812 
813                 let ext_req = csr
814                     .0
815                     .certification_request_info
816                     .attributes
817                     .0
818                     .into_iter()
819                     .find_map(|attr| match attr.value {
820                         picky_asn1_x509::AttributeValue::Extensions(set_of_extensions) => {
821                             set_of_extensions.0.into_iter().next()
822                         }
823                         _ => None,
824                     });
825 
826                 let subject_name = csr.0.certification_request_info.subject.into();
827                 let subject_public_key = csr.0.certification_request_info.subject_public_key_info.into();
828 
829                 (subject_name, subject_public_key, ext_req)
830             }
831             SubjectInfos::NameAndPublicKey { name, public_key } => (name, public_key, None),
832         };
833 
834         let ca = inner.ca.take().unwrap_or(false);
835         let pathlen = inner.pathlen.take();
836         let key_usage_opt = inner.key_usage.take();
837         let extended_key_usage_opt = inner.extended_key_usage.take();
838         let subject_alt_name_opt = inner.subject_alt_name.take();
839         let issuer_alt_name_opt = inner.issuer_alt_name.take();
840 
841         let serial_number = if let Some(unsigned_integer_bytes) = inner.serial_number.take() {
842             IntegerAsn1::from_bytes_be_unsigned(unsigned_integer_bytes)
843         } else {
844             generate_serial_number()
845         };
846 
847         let inherit_extensions_from_csr_attributes = inner.inherit_extensions_from_csr_attributes;
848 
849         drop(inner);
850 
851         let validity = Validity {
852             not_before: valid_from.into(),
853             not_after: valid_to.into(),
854         };
855 
856         let extensions = {
857             let mut extensions = Vec::new();
858 
859             // key usage + basic constraints
860             if let Some(key_usage) = key_usage_opt {
861                 if key_usage.digital_signature() {
862                     extensions.push(Extension::new_basic_constraints(ca, pathlen).into_critical());
863                 } else {
864                     extensions.push(Extension::new_basic_constraints(ca, pathlen).into_non_critical());
865                 }
866                 extensions.push(Extension::new_key_usage(key_usage));
867             } else {
868                 extensions.push(Extension::new_basic_constraints(ca, pathlen).into_non_critical());
869             }
870 
871             // eku
872             if let Some(extended_key_usage) = extended_key_usage_opt {
873                 extensions.push(Extension::new_extended_key_usage(extended_key_usage));
874             }
875 
876             // san
877             if let Some(san) = subject_alt_name_opt {
878                 extensions.push(Extension::new_subject_alt_name(san));
879             }
880 
881             // ian
882             if let Some(ian) = issuer_alt_name_opt {
883                 extensions.push(Extension::new_issuer_alt_name(ian));
884             }
885 
886             // ski
887             let ski = key_id_gen_method
888                 .generate_from(&subject_public_key)
889                 .map_err(|e| CertError::KeyIdGen { source: e })
890                 .map_err(|e| CertError::CertGeneration { source: Box::new(e) })?;
891             extensions.push(Extension::new_subject_key_identifier(ski));
892 
893             // aki
894             extensions.push(Extension::new_authority_key_identifier(
895                 KeyIdentifier::from(aki),
896                 None,
897                 None,
898             ));
899 
900             // inherit extensions from csr "request extension" attribute if allowed to
901             match ext_req {
902                 Some(requested_exts) if inherit_extensions_from_csr_attributes => {
903                     for requested_ext in requested_exts.0 {
904                         if !extensions.iter().any(|o| requested_ext.extn_id() == o.extn_id()) {
905                             extensions.push(requested_ext);
906                         }
907                     }
908                 }
909                 _ => {}
910             }
911 
912             Extensions(extensions)
913         };
914 
915         let tbs_certificate = TBSCertificate {
916             version: ApplicationTag0(Version::V3),
917             serial_number,
918             signature: AlgorithmIdentifier::from(signature_hash_type),
919             issuer: Name::from(issuer_name),
920             validity,
921             subject: Name::from(subject_name),
922             subject_public_key_info: SubjectPublicKeyInfo::from(subject_public_key),
923             extensions: ApplicationTag3(extensions),
924         };
925 
926         let tbs_der = picky_asn1_der::to_vec(&tbs_certificate)
927             .map_err(|e| CertError::Asn1Serialization {
928                 source: e,
929                 element: "tbs certificate",
930             })
931             .map_err(|e| CertError::CertGeneration { source: Box::new(e) })?;
932         let signature_value = BitString::with_bytes(
933             signature_hash_type
934                 .sign(&tbs_der, issuer_key)
935                 .map_err(|e| CertError::Signature { source: e })
936                 .map_err(|e| CertError::CertGeneration { source: Box::new(e) })?,
937         );
938 
939         Ok(Cert(Certificate {
940             tbs_certificate,
941             signature_algorithm: signature_hash_type.into(),
942             signature_value: signature_value.into(),
943         }))
944     }
945 }
946 
generate_serial_number() -> IntegerAsn1947 fn generate_serial_number() -> IntegerAsn1 {
948     let x = rand::random::<u32>();
949     let b1 = ((x >> 24) & 0xff) as u8;
950     let b2 = ((x >> 16) & 0xff) as u8;
951     let b3 = ((x >> 8) & 0xff) as u8;
952     let b4 = (x & 0xff) as u8;
953     // serial number MUST be a positive integer
954     IntegerAsn1::from_bytes_be_unsigned(vec![b1, b2, b3, b4])
955 }
956 
957 #[cfg(test)]
958 mod tests {
959     use super::*;
960     use crate::pem::{parse_pem, Pem};
961     use crate::x509::csr::Attribute;
962 
963     #[test]
read_pem_and_parse_certificate()964     fn read_pem_and_parse_certificate() {
965         let pem = parse_pem(crate::test_files::INTERMEDIATE_CA.as_bytes()).unwrap();
966         let cert = Cert::from_der(pem.data()).unwrap();
967 
968         assert_eq!(cert.serial_number(), &vec![1]);
969         assert_eq!(
970             Into::<String>::into(cert.signature_algorithm().oid()).as_str(),
971             oids::SHA1_WITH_RSA_ENCRYPTION
972         );
973         assert_eq!(cert.valid_not_before(), UTCDate::new(2011, 2, 12, 14, 44, 6).unwrap());
974         assert_eq!(cert.valid_not_after(), UTCDate::new(2021, 2, 12, 14, 44, 6).unwrap());
975 
976         assert_eq!(cert.issuer_name().to_string(), "C=NL,O=PolarSSL,CN=PolarSSL Test CA");
977     }
978 
979     #[test]
get_identifier()980     fn get_identifier() {
981         let pem = crate::test_files::RSA_2048_PK_1
982             .parse::<Pem>()
983             .expect("couldn't parse pem");
984         let private_key = PrivateKey::from_pkcs8(pem.data()).expect("couldn't extract private key from pkcs8");
985 
986         // validity
987         let valid_from = UTCDate::ymd(2019, 10, 10).unwrap();
988         let valid_to = UTCDate::ymd(2019, 10, 11).unwrap();
989 
990         let root = CertificateBuilder::new()
991             .validity(valid_from, valid_to)
992             .self_signed(DirectoryName::new_common_name("test"), &private_key)
993             .ca(true)
994             .build()
995             .expect("couldn't generate root ca");
996 
997         root.subject_key_identifier()
998             .expect("couldn't get subject key identifier");
999         root.authority_key_identifier()
1000             .expect("couldn't get authority key identifier");
1001 
1002         assert_eq!(root.ty(), CertType::Root);
1003     }
1004 
1005     #[test]
key_id_and_cert()1006     fn key_id_and_cert() {
1007         let kid = "c4a7b1a47b2c71fadbe14b9075ffc41560858910";
1008         let pem = crate::test_files::ROOT_CA.parse::<Pem>().expect("couldn't parse PEM");
1009         let cert = Cert::from_der(pem.data()).expect("couldn't deserialize certificate");
1010         assert_eq!(cert.ty(), CertType::Root);
1011         let key_id = cert
1012             .subject_key_identifier()
1013             .expect("couldn't get subject key identifier");
1014         pretty_assertions::assert_eq!(hex::encode(&key_id), kid);
1015     }
1016 
parse_key(pem_str: &str) -> PrivateKey1017     fn parse_key(pem_str: &str) -> PrivateKey {
1018         let pem = pem_str.parse::<Pem>().unwrap();
1019         PrivateKey::from_pkcs8(pem.data()).unwrap()
1020     }
1021 
1022     #[test]
valid_ca_chain()1023     fn valid_ca_chain() {
1024         let root_key = parse_key(crate::test_files::RSA_2048_PK_1);
1025         let intermediate_key = parse_key(crate::test_files::RSA_2048_PK_2);
1026         let leaf_key = parse_key(crate::test_files::RSA_2048_PK_3);
1027 
1028         let root = CertificateBuilder::new()
1029             .validity(UTCDate::ymd(2065, 6, 15).unwrap(), UTCDate::ymd(2070, 6, 15).unwrap())
1030             .self_signed(DirectoryName::new_common_name("TheFuture.usodakedo Root CA"), &root_key)
1031             .ca(true)
1032             .signature_hash_type(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_512))
1033             .key_id_gen_method(KeyIdGenMethod::SPKFullDER(HashAlgorithm::SHA2_384))
1034             .build()
1035             .expect("couldn't build root ca");
1036         assert_eq!(root.ty(), CertType::Root);
1037 
1038         let intermediate = CertificateBuilder::new()
1039             .validity(UTCDate::ymd(2068, 1, 1).unwrap(), UTCDate::ymd(2071, 1, 1).unwrap())
1040             .subject(
1041                 DirectoryName::new_common_name("TheFuture.usodakedo Authority"),
1042                 intermediate_key.to_public_key(),
1043             )
1044             .issuer_cert(&root, &root_key)
1045             .signature_hash_type(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_224))
1046             .key_id_gen_method(KeyIdGenMethod::SPKValueHashedLeftmost160(HashAlgorithm::SHA1))
1047             .ca(true)
1048             .pathlen(0)
1049             .build()
1050             .expect("couldn't build intermediate ca");
1051         assert_eq!(intermediate.ty(), CertType::Intermediate);
1052 
1053         let csr = Csr::generate(
1054             DirectoryName::new_common_name("ChillingInTheFuture.usobakkari"),
1055             &leaf_key,
1056             SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA1),
1057         )
1058         .unwrap();
1059 
1060         let signed_leaf = CertificateBuilder::new()
1061             .validity(UTCDate::ymd(2069, 1, 1).unwrap(), UTCDate::ymd(2072, 1, 1).unwrap())
1062             .subject_from_csr(csr)
1063             .issuer_cert(&intermediate, &intermediate_key)
1064             .signature_hash_type(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_384))
1065             .key_id_gen_method(KeyIdGenMethod::SPKFullDER(HashAlgorithm::SHA2_512))
1066             .pathlen(0) // not meaningful in non-CA certificates
1067             .build()
1068             .expect("couldn't build signed leaf");
1069         assert_eq!(signed_leaf.ty(), CertType::Leaf);
1070 
1071         let chain = [intermediate, root];
1072 
1073         // check with exact date
1074         signed_leaf
1075             .verifier()
1076             .chain(chain.iter())
1077             .exact_date(&UTCDate::ymd(2069, 10, 1).unwrap())
1078             .verify()
1079             .expect("couldn't verify chain");
1080 
1081         // check with interval date
1082         signed_leaf
1083             .verifier()
1084             .chain(chain.iter())
1085             .interval_date(
1086                 &UTCDate::new(2068, 12, 31, 23, 59, 59).unwrap(),
1087                 &UTCDate::ymd(2069, 1, 1).unwrap(),
1088             )
1089             .verify()
1090             .expect("couldn't verify chain with interval date");
1091 
1092         // check with ignore not before
1093         signed_leaf
1094             .verifier()
1095             .chain(chain.iter())
1096             .exact_date(&UTCDate::new(2068, 12, 31, 23, 59, 59).unwrap())
1097             .ignore_not_before_check()
1098             .verify()
1099             .expect("couldn't verify chain with interval date");
1100 
1101         // check with no date validity check
1102         signed_leaf
1103             .verifier()
1104             .chain(chain.iter())
1105             .ignore_not_after_check()
1106             .ignore_not_before_check()
1107             .verify()
1108             .expect("couldn't verify chain with no date validity check");
1109 
1110         let expired_err = signed_leaf
1111             .verifier()
1112             .chain(chain.iter())
1113             .exact_date(&UTCDate::ymd(2080, 10, 1).unwrap())
1114             .verify()
1115             .unwrap_err();
1116         assert_eq!(
1117             expired_err.to_string(),
1118             "invalid certificate \'CN=ChillingInTheFuture.usobakkari\': \
1119             certificate expired (not after: 2072-01-01 00:00:00, now: 2080-10-01 00:00:00)"
1120         );
1121 
1122         let intermediate_expired_err = signed_leaf
1123             .verifier()
1124             .chain(chain.iter())
1125             .exact_date(&UTCDate::ymd(2071, 6, 1).unwrap())
1126             .verify()
1127             .unwrap_err();
1128         assert_eq!(
1129             intermediate_expired_err.to_string(),
1130             "invalid certificate \'CN=TheFuture.usodakedo Authority\': \
1131             certificate expired (not after: 2071-01-01 00:00:00, now: 2071-06-01 00:00:00)"
1132         );
1133 
1134         let root_expired_err = signed_leaf
1135             .verifier()
1136             .chain(chain.iter())
1137             .exact_date(&UTCDate::ymd(2070, 6, 16).unwrap())
1138             .verify()
1139             .unwrap_err();
1140         assert_eq!(
1141             root_expired_err.to_string(),
1142             "invalid certificate \'CN=TheFuture.usodakedo Root CA\': \
1143             certificate expired (not after: 2070-06-15 00:00:00, now: 2070-06-16 00:00:00)"
1144         );
1145 
1146         let still_in_2019_err = signed_leaf
1147             .verifier()
1148             .chain(chain.iter())
1149             .exact_date(&UTCDate::ymd(2019, 11, 14).unwrap())
1150             .verify()
1151             .unwrap_err();
1152         assert_eq!(
1153             still_in_2019_err.to_string(),
1154             "invalid certificate \'CN=ChillingInTheFuture.usobakkari\': \
1155             certificate is not yet valid (not before: 2069-01-01 00:00:00, now: 2019-11-14 00:00:00)"
1156         );
1157 
1158         let not_yet_valid_with_interval_err = signed_leaf
1159             .verifier()
1160             .chain(chain.iter())
1161             .interval_date(
1162                 &UTCDate::ymd(2068, 12, 30).unwrap(),
1163                 &UTCDate::ymd(2068, 12, 31).unwrap(),
1164             )
1165             .verify()
1166             .unwrap_err();
1167         assert_eq!(
1168             not_yet_valid_with_interval_err.to_string(),
1169             "invalid certificate \'CN=ChillingInTheFuture.usobakkari\': \
1170             certificate is not yet valid (not before: 2069-01-01 00:00:00, now: 2068-12-31 00:00:00)"
1171         );
1172 
1173         let date_is_missing_err = signed_leaf.verifier().chain(chain.iter()).verify().unwrap_err();
1174         assert_eq!(
1175             date_is_missing_err.to_string(),
1176             "missing required builder argument `now`"
1177         );
1178     }
1179 
1180     #[test]
malicious_ca_chain()1181     fn malicious_ca_chain() {
1182         let root_key = parse_key(crate::test_files::RSA_2048_PK_1);
1183         let intermediate_key = parse_key(crate::test_files::RSA_2048_PK_2);
1184         let leaf_key = parse_key(crate::test_files::RSA_2048_PK_3);
1185         let malicious_root_key = parse_key(crate::test_files::RSA_2048_PK_4);
1186 
1187         let root = CertificateBuilder::new()
1188             .validity(UTCDate::ymd(2065, 6, 15).unwrap(), UTCDate::ymd(2070, 6, 15).unwrap())
1189             .self_signed(DirectoryName::new_common_name("VerySafe Root CA"), &root_key)
1190             .ca(true)
1191             .pathlen(1)
1192             .signature_hash_type(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA1))
1193             .key_id_gen_method(KeyIdGenMethod::SPKFullDER(HashAlgorithm::SHA2_224))
1194             .build()
1195             .expect("couldn't build root ca");
1196 
1197         let intermediate = CertificateBuilder::new()
1198             .validity(UTCDate::ymd(2068, 1, 1).unwrap(), UTCDate::ymd(2071, 1, 1).unwrap())
1199             .subject(
1200                 DirectoryName::new_common_name("V.E.R.Y Legitimate VerySafe Authority"),
1201                 intermediate_key.to_public_key(),
1202             )
1203             .issuer_cert(&root, &malicious_root_key)
1204             .signature_hash_type(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_512))
1205             .key_id_gen_method(KeyIdGenMethod::SPKValueHashedLeftmost160(HashAlgorithm::SHA2_384))
1206             .ca(true)
1207             .pathlen(0)
1208             .build()
1209             .expect("couldn't build intermediate ca");
1210 
1211         let csr = Csr::generate(
1212             DirectoryName::new_common_name("I Trust This V.E.R.Y Legitimate Intermediate Certificate"),
1213             &leaf_key,
1214             SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA1),
1215         )
1216         .unwrap();
1217 
1218         let signed_leaf = CertificateBuilder::new()
1219             .validity(UTCDate::ymd(2069, 1, 1).unwrap(), UTCDate::ymd(2072, 1, 1).unwrap())
1220             .subject_from_csr(csr)
1221             .issuer_cert(&intermediate, &intermediate_key)
1222             .signature_hash_type(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_224))
1223             .key_id_gen_method(KeyIdGenMethod::SPKFullDER(HashAlgorithm::SHA2_384))
1224             .build()
1225             .expect("couldn't build signed leaf");
1226 
1227         let chain = [intermediate, root];
1228 
1229         let root_missing_err = signed_leaf
1230             .verifier()
1231             .chain(chain[..1].iter())
1232             .exact_date(&UTCDate::ymd(2069, 10, 1).unwrap())
1233             .verify()
1234             .unwrap_err();
1235         assert_eq!(
1236             root_missing_err.to_string(),
1237             "CA chain error: chain is missing a root certificate"
1238         );
1239 
1240         let invalid_sig_err = signed_leaf
1241             .verifier()
1242             .chain(chain.iter())
1243             .exact_date(&UTCDate::ymd(2069, 10, 1).unwrap())
1244             .verify()
1245             .unwrap_err();
1246         assert_eq!(
1247             invalid_sig_err.to_string(),
1248             "invalid certificate \'CN=V.E.R.Y Legitimate VerySafe Authority\': signature error: invalid signature"
1249         );
1250     }
1251 
1252     #[test]
invalid_basic_constraints_chain()1253     fn invalid_basic_constraints_chain() {
1254         let root_key = parse_key(crate::test_files::RSA_2048_PK_1);
1255         let intermediate_key = parse_key(crate::test_files::RSA_2048_PK_2);
1256         let leaf_key = parse_key(crate::test_files::RSA_2048_PK_3);
1257 
1258         let root = CertificateBuilder::new()
1259             .validity(UTCDate::ymd(2065, 6, 15).unwrap(), UTCDate::ymd(2070, 6, 15).unwrap())
1260             .self_signed(DirectoryName::new_common_name("VerySafe Root CA"), &root_key)
1261             .ca(true)
1262             .pathlen(0)
1263             .build()
1264             .expect("couldn't build root ca");
1265 
1266         let intermediate = CertificateBuilder::new()
1267             .validity(UTCDate::ymd(2068, 1, 1).unwrap(), UTCDate::ymd(2071, 1, 1).unwrap())
1268             .subject(
1269                 DirectoryName::new_common_name("V.E.R.Y Legitimate VerySafe Authority"),
1270                 intermediate_key.to_public_key(),
1271             )
1272             .issuer_cert(&root, &root_key)
1273             .ca(true)
1274             .pathlen(0)
1275             .build()
1276             .expect("couldn't build intermediate ca");
1277 
1278         let csr = Csr::generate(
1279             DirectoryName::new_common_name("I Trust This V.E.R.Y Legitimate Intermediate Certificate"),
1280             &leaf_key,
1281             SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA1),
1282         )
1283         .unwrap();
1284 
1285         let signed_leaf = CertificateBuilder::new()
1286             .validity(UTCDate::ymd(2069, 1, 1).unwrap(), UTCDate::ymd(2072, 1, 1).unwrap())
1287             .subject_from_csr(csr.clone())
1288             .issuer_cert(&intermediate, &intermediate_key)
1289             .build()
1290             .expect("couldn't build signed leaf");
1291 
1292         let chain = [intermediate.clone(), root.clone()];
1293 
1294         let invalid_pathlen_err = signed_leaf
1295             .verifier()
1296             .chain(chain.iter())
1297             .exact_date(&UTCDate::ymd(2069, 10, 1).unwrap())
1298             .verify()
1299             .unwrap_err();
1300         assert_eq!(
1301             invalid_pathlen_err.to_string(),
1302             "CA chain error: chain depth doesn\'t satisfy basic constraints extension: \
1303             certificate \'CN=VerySafe Root CA\' has pathlen of 0"
1304         );
1305 
1306         let invalid_issuer_signed_leaf = CertificateBuilder::new()
1307             .validity(UTCDate::ymd(2069, 1, 1).unwrap(), UTCDate::ymd(2072, 1, 1).unwrap())
1308             .subject_from_csr(csr)
1309             .issuer_cert(&signed_leaf, &leaf_key)
1310             .build()
1311             .expect("couldn't build invalid issuer signed leaf");
1312 
1313         let chain = [signed_leaf, intermediate.clone(), root.clone()];
1314 
1315         let invalid_issuer_err = invalid_issuer_signed_leaf
1316             .verifier()
1317             .chain(chain.iter())
1318             .exact_date(&UTCDate::ymd(2069, 10, 1).unwrap())
1319             .verify()
1320             .unwrap_err();
1321         assert_eq!(
1322             invalid_issuer_err.to_string(),
1323             "CA chain error: issuer certificate \'CN=I Trust This V.E.R.Y Legitimate Intermediate Certificate\' is not a CA"
1324         );
1325     }
1326 
1327     #[test]
bypass_serial_number_generator()1328     fn bypass_serial_number_generator() {
1329         let root_key = parse_key(crate::test_files::RSA_2048_PK_1);
1330 
1331         let unsigned_integer_bytes = [21, 84, 58, 122];
1332 
1333         let cert = CertificateBuilder::new()
1334             .validity(UTCDate::ymd(2065, 6, 15).unwrap(), UTCDate::ymd(2070, 6, 15).unwrap())
1335             .self_signed(DirectoryName::new_common_name("TheFuture.usodakedo Root CA"), &root_key)
1336             .ca(true)
1337             .signature_hash_type(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_512))
1338             .key_id_gen_method(KeyIdGenMethod::SPKFullDER(HashAlgorithm::SHA2_384))
1339             .serial_number(unsigned_integer_bytes.to_vec())
1340             .build()
1341             .expect("couldn't build root ca");
1342 
1343         assert_eq!(cert.serial_number().as_unsigned_bytes_be(), unsigned_integer_bytes);
1344     }
1345 
1346     #[test]
validity_encoding()1347     fn validity_encoding() {
1348         use picky_asn1_x509::validity::Time;
1349 
1350         let root_key = parse_key(crate::test_files::RSA_2048_PK_1);
1351 
1352         let cert = CertificateBuilder::new()
1353             .validity(UTCDate::ymd(2045, 6, 15).unwrap(), UTCDate::ymd(2055, 6, 15).unwrap())
1354             .self_signed(DirectoryName::new_common_name("Am I valid"), &root_key)
1355             .ca(true)
1356             .signature_hash_type(SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA1))
1357             .key_id_gen_method(KeyIdGenMethod::SPKFullDER(HashAlgorithm::SHA2_224))
1358             .build()
1359             .expect("couldn't build root ca");
1360 
1361         let validity = &cert.0.tbs_certificate.validity;
1362 
1363         assert!(matches!(validity.not_before, Time::UTC(_)));
1364         assert!(matches!(validity.not_after, Time::Generalized(_)));
1365     }
1366 
1367     #[test]
inherit_requested_extensions_by_csr()1368     fn inherit_requested_extensions_by_csr() {
1369         use crate::x509::name::GeneralName;
1370 
1371         let root_key = parse_key(crate::test_files::RSA_2048_PK_1);
1372         let leaf_key = parse_key(crate::test_files::RSA_2048_PK_3);
1373 
1374         let root = CertificateBuilder::new()
1375             .validity(UTCDate::ymd(2065, 6, 15).unwrap(), UTCDate::ymd(2070, 6, 15).unwrap())
1376             .self_signed(DirectoryName::new_common_name("VerySafe Root CA"), &root_key)
1377             .ca(true)
1378             .pathlen(0)
1379             .build()
1380             .expect("couldn't build root ca");
1381 
1382         let extensions =
1383             vec![Extension::new_subject_alt_name(GeneralName::new_dns_name("localhost").unwrap()).into_non_critical()];
1384         let attr = Attribute::new_extension_request(extensions);
1385         let csr = Csr::generate_with_attributes(
1386             DirectoryName::new_common_name("I want more extensions"),
1387             &leaf_key,
1388             SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_256),
1389             vec![attr],
1390         )
1391         .unwrap();
1392 
1393         let signed_leaf = CertificateBuilder::new()
1394             .validity(UTCDate::ymd(2069, 1, 1).unwrap(), UTCDate::ymd(2072, 1, 1).unwrap())
1395             .subject_from_csr(csr)
1396             .issuer_cert(&root, &root_key)
1397             .inherit_extensions_from_csr_attributes(true)
1398             .build()
1399             .expect("couldn't build signed leaf");
1400 
1401         let subject_alt_name = signed_leaf
1402             .extensions()
1403             .iter()
1404             .find_map(|ext| match ext.extn_value() {
1405                 ExtensionView::SubjectAltName(gn) => match gn.0.first().unwrap() {
1406                     picky_asn1_x509::GeneralName::DNSName(name) => Some(name.to_string()),
1407                     _ => None,
1408                 },
1409                 _ => None,
1410             })
1411             .unwrap();
1412 
1413         assert_eq!(subject_alt_name, "localhost");
1414     }
1415 }
1416