rcgen/
certificate.rs

1use std::net::IpAddr;
2use std::str::FromStr;
3
4#[cfg(feature = "pem")]
5use pem::Pem;
6use pki_types::{CertificateDer, CertificateSigningRequestDer};
7use time::{Date, Month, OffsetDateTime, PrimitiveDateTime, Time};
8use yasna::models::ObjectIdentifier;
9use yasna::{DERWriter, Tag};
10
11use crate::crl::CrlDistributionPoint;
12use crate::csr::CertificateSigningRequest;
13use crate::key_pair::{serialize_public_key_der, PublicKeyData};
14#[cfg(feature = "crypto")]
15use crate::ring_like::digest;
16#[cfg(feature = "pem")]
17use crate::ENCODE_CONFIG;
18use crate::{
19	oid, write_distinguished_name, write_dt_utc_or_generalized,
20	write_x509_authority_key_identifier, write_x509_extension, DistinguishedName, Error, Issuer,
21	KeyIdMethod, KeyPair, KeyUsagePurpose, SanType, SerialNumber,
22};
23
24/// An issued certificate together with the parameters used to generate it.
25pub struct Certificate {
26	pub(crate) params: CertificateParams,
27	pub(crate) subject_public_key_info: Vec<u8>,
28	pub(crate) der: CertificateDer<'static>,
29}
30
31impl Certificate {
32	/// Returns the certificate parameters
33	pub fn params(&self) -> &CertificateParams {
34		&self.params
35	}
36	/// Calculates a subject key identifier for the certificate subject's public key.
37	/// This key identifier is used in the SubjectKeyIdentifier X.509v3 extension.
38	pub fn key_identifier(&self) -> Vec<u8> {
39		self.params
40			.key_identifier_method
41			.derive(&self.subject_public_key_info)
42	}
43	/// Get the certificate in DER encoded format.
44	///
45	/// [`CertificateDer`] implements `Deref<Target = [u8]>` and `AsRef<[u8]>`, so you can easily
46	/// extract the DER bytes from the return value.
47	pub fn der(&self) -> &CertificateDer<'static> {
48		&self.der
49	}
50	/// Get the certificate in PEM encoded format.
51	#[cfg(feature = "pem")]
52	pub fn pem(&self) -> String {
53		pem::encode_config(&Pem::new("CERTIFICATE", self.der().to_vec()), ENCODE_CONFIG)
54	}
55}
56
57impl From<Certificate> for CertificateDer<'static> {
58	fn from(cert: Certificate) -> Self {
59		cert.der
60	}
61}
62
63/// Parameters used for certificate generation
64#[allow(missing_docs)]
65#[non_exhaustive]
66#[derive(Debug, PartialEq, Eq, Clone)]
67pub struct CertificateParams {
68	pub not_before: OffsetDateTime,
69	pub not_after: OffsetDateTime,
70	pub serial_number: Option<SerialNumber>,
71	pub subject_alt_names: Vec<SanType>,
72	pub distinguished_name: DistinguishedName,
73	pub is_ca: IsCa,
74	pub key_usages: Vec<KeyUsagePurpose>,
75	pub extended_key_usages: Vec<ExtendedKeyUsagePurpose>,
76	pub name_constraints: Option<NameConstraints>,
77	/// An optional list of certificate revocation list (CRL) distribution points as described
78	/// in RFC 5280 Section 4.2.1.13[^1]. Each distribution point contains one or more URIs where
79	/// an up-to-date CRL with scope including this certificate can be retrieved.
80	///
81	/// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.13>
82	pub crl_distribution_points: Vec<CrlDistributionPoint>,
83	pub custom_extensions: Vec<CustomExtension>,
84	/// If `true`, the 'Authority Key Identifier' extension will be added to the generated cert
85	pub use_authority_key_identifier_extension: bool,
86	/// Method to generate key identifiers from public keys
87	///
88	/// Defaults to a truncated SHA-256 digest. See [`KeyIdMethod`] for more information.
89	pub key_identifier_method: KeyIdMethod,
90}
91
92impl Default for CertificateParams {
93	fn default() -> Self {
94		// not_before and not_after set to reasonably long dates
95		let not_before = date_time_ymd(1975, 01, 01);
96		let not_after = date_time_ymd(4096, 01, 01);
97		let mut distinguished_name = DistinguishedName::new();
98		distinguished_name.push(DnType::CommonName, "rcgen self signed cert");
99		CertificateParams {
100			not_before,
101			not_after,
102			serial_number: None,
103			subject_alt_names: Vec::new(),
104			distinguished_name,
105			is_ca: IsCa::NoCa,
106			key_usages: Vec::new(),
107			extended_key_usages: Vec::new(),
108			name_constraints: None,
109			crl_distribution_points: Vec::new(),
110			custom_extensions: Vec::new(),
111			use_authority_key_identifier_extension: false,
112			#[cfg(feature = "crypto")]
113			key_identifier_method: KeyIdMethod::Sha256,
114			#[cfg(not(feature = "crypto"))]
115			key_identifier_method: KeyIdMethod::PreSpecified(Vec::new()),
116		}
117	}
118}
119
120impl CertificateParams {
121	/// Generate certificate parameters with reasonable defaults
122	pub fn new(subject_alt_names: impl Into<Vec<String>>) -> Result<Self, Error> {
123		let subject_alt_names = subject_alt_names
124			.into()
125			.into_iter()
126			.map(|s| {
127				Ok(match IpAddr::from_str(&s) {
128					Ok(ip) => SanType::IpAddress(ip),
129					Err(_) => SanType::DnsName(s.try_into()?),
130				})
131			})
132			.collect::<Result<Vec<_>, _>>()?;
133		Ok(CertificateParams {
134			subject_alt_names,
135			..Default::default()
136		})
137	}
138
139	/// Generate a new certificate from the given parameters, signed by the provided issuer.
140	///
141	/// The returned certificate will have its issuer field set to the subject of the
142	/// provided `issuer`, and the authority key identifier extension will be populated using
143	/// the subject public key of `issuer`. It will be signed by `issuer_key`.
144	///
145	/// Note that no validation of the `issuer` certificate is performed. Rcgen will not require
146	/// the certificate to be a CA certificate, or have key usage extensions that allow signing.
147	///
148	/// The returned [`Certificate`] may be serialized using [`Certificate::der`] and
149	/// [`Certificate::pem`].
150	pub fn signed_by(
151		self,
152		public_key: &impl PublicKeyData,
153		issuer: &Certificate,
154		issuer_key: &KeyPair,
155	) -> Result<Certificate, Error> {
156		let issuer = Issuer {
157			distinguished_name: &issuer.params.distinguished_name,
158			key_identifier_method: &issuer.params.key_identifier_method,
159			key_usages: &issuer.params.key_usages,
160			key_pair: issuer_key,
161		};
162
163		let subject_public_key_info =
164			yasna::construct_der(|writer| serialize_public_key_der(public_key, writer));
165		let der = self.serialize_der_with_signer(public_key, issuer)?;
166		Ok(Certificate {
167			params: self,
168			subject_public_key_info,
169			der,
170		})
171	}
172
173	/// Generates a new self-signed certificate from the given parameters.
174	///
175	/// The returned [`Certificate`] may be serialized using [`Certificate::der`] and
176	/// [`Certificate::pem`].
177	pub fn self_signed(self, key_pair: &KeyPair) -> Result<Certificate, Error> {
178		let issuer = Issuer {
179			distinguished_name: &self.distinguished_name,
180			key_identifier_method: &self.key_identifier_method,
181			key_usages: &self.key_usages,
182			key_pair,
183		};
184
185		let subject_public_key_info = key_pair.public_key_der();
186		let der = self.serialize_der_with_signer(key_pair, issuer)?;
187		Ok(Certificate {
188			params: self,
189			subject_public_key_info,
190			der,
191		})
192	}
193
194	/// Parses an existing ca certificate from the ASCII PEM format.
195	///
196	/// See [`from_ca_cert_der`](Self::from_ca_cert_der) for more details.
197	#[cfg(all(feature = "pem", feature = "x509-parser"))]
198	pub fn from_ca_cert_pem(pem_str: &str) -> Result<Self, Error> {
199		let certificate = pem::parse(pem_str).or(Err(Error::CouldNotParseCertificate))?;
200		Self::from_ca_cert_der(&certificate.contents().into())
201	}
202
203	/// Parses an existing ca certificate from the DER format.
204	///
205	/// This function is only of use if you have an existing CA certificate
206	/// you would like to use to sign a certificate generated by `rcgen`.
207	/// By providing the constructed [`CertificateParams`] and the [`KeyPair`]
208	/// associated with your existing `ca_cert` you can use [`CertificateParams::signed_by()`]
209	/// or [`crate::CertificateSigningRequestParams::signed_by()`] to issue new certificates
210	/// using the CA cert.
211	///
212	/// In general this function only extracts the information needed for signing.
213	/// Other attributes of the [`Certificate`] may be left as defaults.
214	///
215	/// This function assumes the provided certificate is a CA. It will not check
216	/// for the presence of the `BasicConstraints` extension, or perform any other
217	/// validation.
218	///
219	/// [`rustls_pemfile::certs()`] is often used to obtain a [`CertificateDer`] from PEM input.
220	/// If you already have a byte slice containing DER, it can trivially be converted into
221	/// [`CertificateDer`] using the [`Into`] trait.
222	///
223	/// [`rustls_pemfile::certs()`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.certs.html
224	#[cfg(feature = "x509-parser")]
225	pub fn from_ca_cert_der(ca_cert: &CertificateDer<'_>) -> Result<Self, Error> {
226		let (_remainder, x509) = x509_parser::parse_x509_certificate(ca_cert)
227			.or(Err(Error::CouldNotParseCertificate))?;
228
229		let dn = DistinguishedName::from_name(&x509.tbs_certificate.subject)?;
230		let is_ca = Self::convert_x509_is_ca(&x509)?;
231		let validity = x509.validity();
232		let subject_alt_names = Self::convert_x509_subject_alternative_name(&x509)?;
233		let key_usages = Self::convert_x509_key_usages(&x509)?;
234		let extended_key_usages = Self::convert_x509_extended_key_usages(&x509)?;
235		let name_constraints = Self::convert_x509_name_constraints(&x509)?;
236		let serial_number = Some(x509.serial.to_bytes_be().into());
237
238		let key_identifier_method =
239			x509.iter_extensions()
240				.find_map(|ext| match ext.parsed_extension() {
241					x509_parser::extensions::ParsedExtension::SubjectKeyIdentifier(key_id) => {
242						Some(KeyIdMethod::PreSpecified(key_id.0.into()))
243					},
244					_ => None,
245				});
246
247		let key_identifier_method = match key_identifier_method {
248			Some(method) => method,
249			None => {
250				#[cfg(not(feature = "crypto"))]
251				return Err(Error::UnsupportedSignatureAlgorithm);
252				#[cfg(feature = "crypto")]
253				KeyIdMethod::Sha256
254			},
255		};
256
257		Ok(CertificateParams {
258			is_ca,
259			subject_alt_names,
260			key_usages,
261			extended_key_usages,
262			name_constraints,
263			serial_number,
264			key_identifier_method,
265			distinguished_name: dn,
266			not_before: validity.not_before.to_datetime(),
267			not_after: validity.not_after.to_datetime(),
268			..Default::default()
269		})
270	}
271	#[cfg(feature = "x509-parser")]
272	fn convert_x509_is_ca(
273		x509: &x509_parser::certificate::X509Certificate<'_>,
274	) -> Result<IsCa, Error> {
275		use x509_parser::extensions::BasicConstraints as B;
276
277		let basic_constraints = x509
278			.basic_constraints()
279			.or(Err(Error::CouldNotParseCertificate))?
280			.map(|ext| ext.value);
281
282		let is_ca = match basic_constraints {
283			Some(B {
284				ca: true,
285				path_len_constraint: Some(n),
286			}) if *n <= u8::MAX as u32 => IsCa::Ca(BasicConstraints::Constrained(*n as u8)),
287			Some(B {
288				ca: true,
289				path_len_constraint: Some(_),
290			}) => return Err(Error::CouldNotParseCertificate),
291			Some(B {
292				ca: true,
293				path_len_constraint: None,
294			}) => IsCa::Ca(BasicConstraints::Unconstrained),
295			Some(B { ca: false, .. }) => IsCa::ExplicitNoCa,
296			None => IsCa::NoCa,
297		};
298
299		Ok(is_ca)
300	}
301	#[cfg(feature = "x509-parser")]
302	fn convert_x509_subject_alternative_name(
303		x509: &x509_parser::certificate::X509Certificate<'_>,
304	) -> Result<Vec<SanType>, Error> {
305		let sans = x509
306			.subject_alternative_name()
307			.or(Err(Error::CouldNotParseCertificate))?
308			.map(|ext| &ext.value.general_names);
309
310		if let Some(sans) = sans {
311			let mut subject_alt_names = Vec::with_capacity(sans.len());
312			for san in sans {
313				subject_alt_names.push(SanType::try_from_general(san)?);
314			}
315			Ok(subject_alt_names)
316		} else {
317			Ok(Vec::new())
318		}
319	}
320	#[cfg(feature = "x509-parser")]
321	fn convert_x509_key_usages(
322		x509: &x509_parser::certificate::X509Certificate<'_>,
323	) -> Result<Vec<KeyUsagePurpose>, Error> {
324		let key_usage = x509
325			.key_usage()
326			.or(Err(Error::CouldNotParseCertificate))?
327			.map(|ext| ext.value);
328		// This x509 parser stores flags in reversed bit BIT STRING order
329		let flags = key_usage.map_or(0u16, |k| k.flags).reverse_bits();
330		Ok(KeyUsagePurpose::from_u16(flags))
331	}
332	#[cfg(feature = "x509-parser")]
333	fn convert_x509_extended_key_usages(
334		x509: &x509_parser::certificate::X509Certificate<'_>,
335	) -> Result<Vec<ExtendedKeyUsagePurpose>, Error> {
336		let extended_key_usage = x509
337			.extended_key_usage()
338			.or(Err(Error::CouldNotParseCertificate))?
339			.map(|ext| ext.value);
340
341		let mut extended_key_usages = Vec::new();
342		if let Some(extended_key_usage) = extended_key_usage {
343			if extended_key_usage.any {
344				extended_key_usages.push(ExtendedKeyUsagePurpose::Any);
345			}
346			if extended_key_usage.server_auth {
347				extended_key_usages.push(ExtendedKeyUsagePurpose::ServerAuth);
348			}
349			if extended_key_usage.client_auth {
350				extended_key_usages.push(ExtendedKeyUsagePurpose::ClientAuth);
351			}
352			if extended_key_usage.code_signing {
353				extended_key_usages.push(ExtendedKeyUsagePurpose::CodeSigning);
354			}
355			if extended_key_usage.email_protection {
356				extended_key_usages.push(ExtendedKeyUsagePurpose::EmailProtection);
357			}
358			if extended_key_usage.time_stamping {
359				extended_key_usages.push(ExtendedKeyUsagePurpose::TimeStamping);
360			}
361			if extended_key_usage.ocsp_signing {
362				extended_key_usages.push(ExtendedKeyUsagePurpose::OcspSigning);
363			}
364		}
365		Ok(extended_key_usages)
366	}
367	#[cfg(feature = "x509-parser")]
368	fn convert_x509_name_constraints(
369		x509: &x509_parser::certificate::X509Certificate<'_>,
370	) -> Result<Option<NameConstraints>, Error> {
371		let constraints = x509
372			.name_constraints()
373			.or(Err(Error::CouldNotParseCertificate))?
374			.map(|ext| ext.value);
375
376		if let Some(constraints) = constraints {
377			let permitted_subtrees = if let Some(permitted) = &constraints.permitted_subtrees {
378				Self::convert_x509_general_subtrees(permitted)?
379			} else {
380				Vec::new()
381			};
382
383			let excluded_subtrees = if let Some(excluded) = &constraints.excluded_subtrees {
384				Self::convert_x509_general_subtrees(excluded)?
385			} else {
386				Vec::new()
387			};
388
389			let name_constraints = NameConstraints {
390				permitted_subtrees,
391				excluded_subtrees,
392			};
393
394			Ok(Some(name_constraints))
395		} else {
396			Ok(None)
397		}
398	}
399	#[cfg(feature = "x509-parser")]
400	fn convert_x509_general_subtrees(
401		subtrees: &[x509_parser::extensions::GeneralSubtree<'_>],
402	) -> Result<Vec<GeneralSubtree>, Error> {
403		use x509_parser::extensions::GeneralName;
404
405		let mut result = Vec::new();
406		for subtree in subtrees {
407			let subtree = match &subtree.base {
408				GeneralName::RFC822Name(s) => GeneralSubtree::Rfc822Name(s.to_string()),
409				GeneralName::DNSName(s) => GeneralSubtree::DnsName(s.to_string()),
410				GeneralName::DirectoryName(n) => {
411					GeneralSubtree::DirectoryName(DistinguishedName::from_name(n)?)
412				},
413				GeneralName::IPAddress(bytes) if bytes.len() == 8 => {
414					let addr: [u8; 4] = bytes[..4].try_into().unwrap();
415					let mask: [u8; 4] = bytes[4..].try_into().unwrap();
416					GeneralSubtree::IpAddress(CidrSubnet::V4(addr, mask))
417				},
418				GeneralName::IPAddress(bytes) if bytes.len() == 32 => {
419					let addr: [u8; 16] = bytes[..16].try_into().unwrap();
420					let mask: [u8; 16] = bytes[16..].try_into().unwrap();
421					GeneralSubtree::IpAddress(CidrSubnet::V6(addr, mask))
422				},
423				_ => continue,
424			};
425			result.push(subtree);
426		}
427		Ok(result)
428	}
429
430	/// Write a CSR extension request attribute as defined in [RFC 2985].
431	///
432	/// [RFC 2985]: <https://datatracker.ietf.org/doc/html/rfc2985>
433	fn write_extension_request_attribute(&self, writer: DERWriter) {
434		writer.write_sequence(|writer| {
435			writer.next().write_oid(&ObjectIdentifier::from_slice(
436				oid::PKCS_9_AT_EXTENSION_REQUEST,
437			));
438			writer.next().write_set(|writer| {
439				writer.next().write_sequence(|writer| {
440					// Write key_usage
441					self.write_key_usage(writer.next());
442					// Write subject_alt_names
443					self.write_subject_alt_names(writer.next());
444					self.write_extended_key_usage(writer.next());
445
446					// Write custom extensions
447					for ext in &self.custom_extensions {
448						write_x509_extension(writer.next(), &ext.oid, ext.critical, |writer| {
449							writer.write_der(ext.content())
450						});
451					}
452				});
453			});
454		});
455	}
456
457	/// Write a certificate's KeyUsage as defined in RFC 5280.
458	fn write_key_usage(&self, writer: DERWriter) {
459		// RFC 5280 defines 9 key usages, which we detail in our key usage enum
460		// We could use std::mem::variant_count here, but it's experimental
461		const KEY_USAGE_BITS: usize = 9;
462		if self.key_usages.is_empty() {
463			return;
464		}
465
466		// "When present, conforming CAs SHOULD mark this extension as critical."
467		write_x509_extension(writer, oid::KEY_USAGE, true, |writer| {
468			// u16 is large enough to encode the largest possible key usage (two-bytes)
469			let bit_string = self.key_usages.iter().fold(0u16, |bit_string, key_usage| {
470				bit_string | key_usage.to_u16()
471			});
472			writer.write_bitvec_bytes(&bit_string.to_be_bytes(), KEY_USAGE_BITS);
473		});
474	}
475
476	fn write_extended_key_usage(&self, writer: DERWriter) {
477		if !self.extended_key_usages.is_empty() {
478			write_x509_extension(writer, oid::EXT_KEY_USAGE, false, |writer| {
479				writer.write_sequence(|writer| {
480					for usage in &self.extended_key_usages {
481						writer
482							.next()
483							.write_oid(&ObjectIdentifier::from_slice(usage.oid()));
484					}
485				});
486			});
487		}
488	}
489
490	fn write_subject_alt_names(&self, writer: DERWriter) {
491		if self.subject_alt_names.is_empty() {
492			return;
493		}
494
495		write_x509_extension(writer, oid::SUBJECT_ALT_NAME, false, |writer| {
496			writer.write_sequence(|writer| {
497				for san in self.subject_alt_names.iter() {
498					writer.next().write_tagged_implicit(
499						Tag::context(san.tag()),
500						|writer| match san {
501							SanType::Rfc822Name(name)
502							| SanType::DnsName(name)
503							| SanType::URI(name) => writer.write_ia5_string(name.as_str()),
504							SanType::IpAddress(IpAddr::V4(addr)) => {
505								writer.write_bytes(&addr.octets())
506							},
507							SanType::IpAddress(IpAddr::V6(addr)) => {
508								writer.write_bytes(&addr.octets())
509							},
510							SanType::OtherName((oid, value)) => {
511								// otherName SEQUENCE { OID, [0] explicit any defined by oid }
512								// https://datatracker.ietf.org/doc/html/rfc5280#page-38
513								writer.write_sequence(|writer| {
514									writer.next().write_oid(&ObjectIdentifier::from_slice(oid));
515									value.write_der(writer.next());
516								});
517							},
518						},
519					);
520				}
521			});
522		});
523	}
524
525	/// Generate and serialize a certificate signing request (CSR).
526	///
527	/// The constructed CSR will contain attributes based on the certificate parameters,
528	/// and include the subject public key information from `subject_key`. Additionally,
529	/// the CSR will be signed using the subject key.
530	///
531	/// Note that subsequent invocations of `serialize_request()` will not produce the exact
532	/// same output.
533	pub fn serialize_request(
534		&self,
535		subject_key: &KeyPair,
536	) -> Result<CertificateSigningRequest, Error> {
537		self.serialize_request_with_attributes(subject_key, Vec::new())
538	}
539
540	/// Generate and serialize a certificate signing request (CSR) with custom PKCS #10 attributes.
541	/// as defined in [RFC 2986].
542	///
543	/// The constructed CSR will contain attributes based on the certificate parameters,
544	/// and include the subject public key information from `subject_key`. Additionally,
545	/// the CSR will be self-signed using the subject key.
546	///
547	/// Note that subsequent invocations of `serialize_request_with_attributes()` will not produce the exact
548	/// same output.
549	///
550	/// [RFC 2986]: <https://datatracker.ietf.org/doc/html/rfc2986#section-4>
551	pub fn serialize_request_with_attributes(
552		&self,
553		subject_key: &KeyPair,
554		attrs: Vec<Attribute>,
555	) -> Result<CertificateSigningRequest, Error> {
556		// No .. pattern, we use this to ensure every field is used
557		#[deny(unused)]
558		let Self {
559			not_before,
560			not_after,
561			serial_number,
562			subject_alt_names,
563			distinguished_name,
564			is_ca,
565			key_usages,
566			extended_key_usages,
567			name_constraints,
568			crl_distribution_points,
569			custom_extensions,
570			use_authority_key_identifier_extension,
571			key_identifier_method,
572		} = self;
573		// - alg and key_pair will be used by the caller
574		// - not_before and not_after cannot be put in a CSR
575		// - key_identifier_method is here because self.write_extended_key_usage uses it
576		// - There might be a use case for specifying the key identifier
577		// in the CSR, but in the current API it can't be distinguished
578		// from the defaults so this is left for a later version if
579		// needed.
580		let _ = (
581			not_before,
582			not_after,
583			key_identifier_method,
584			extended_key_usages,
585		);
586		if serial_number.is_some()
587			|| *is_ca != IsCa::NoCa
588			|| name_constraints.is_some()
589			|| !crl_distribution_points.is_empty()
590			|| *use_authority_key_identifier_extension
591		{
592			return Err(Error::UnsupportedInCsr);
593		}
594
595		// Whether or not to write an extension request attribute
596		let write_extension_request = !key_usages.is_empty()
597			|| !subject_alt_names.is_empty()
598			|| !extended_key_usages.is_empty()
599			|| !custom_extensions.is_empty();
600
601		let der = subject_key.sign_der(|writer| {
602			// Write version
603			writer.next().write_u8(0);
604			write_distinguished_name(writer.next(), distinguished_name);
605			serialize_public_key_der(subject_key, writer.next());
606
607			// According to the spec in RFC 2986, even if attributes are empty we need the empty attribute tag
608			writer
609				.next()
610				.write_tagged_implicit(Tag::context(0), |writer| {
611					// RFC 2986 specifies that attributes are a SET OF Attribute
612					writer.write_set_of(|writer| {
613						if write_extension_request {
614							self.write_extension_request_attribute(writer.next());
615						}
616
617						for Attribute { oid, values } in attrs {
618							writer.next().write_sequence(|writer| {
619								writer.next().write_oid(&ObjectIdentifier::from_slice(&oid));
620								writer.next().write_der(&values);
621							});
622						}
623					});
624				});
625
626			Ok(())
627		})?;
628
629		Ok(CertificateSigningRequest {
630			der: CertificateSigningRequestDer::from(der),
631		})
632	}
633
634	pub(crate) fn serialize_der_with_signer<K: PublicKeyData>(
635		&self,
636		pub_key: &K,
637		issuer: Issuer<'_>,
638	) -> Result<CertificateDer<'static>, Error> {
639		let der = issuer.key_pair.sign_der(|writer| {
640			let pub_key_spki =
641				yasna::construct_der(|writer| serialize_public_key_der(pub_key, writer));
642			// Write version
643			writer.next().write_tagged(Tag::context(0), |writer| {
644				writer.write_u8(2);
645			});
646			// Write serialNumber
647			if let Some(ref serial) = self.serial_number {
648				writer.next().write_bigint_bytes(serial.as_ref(), true);
649			} else {
650				#[cfg(feature = "crypto")]
651				{
652					let hash = digest::digest(&digest::SHA256, pub_key.der_bytes());
653					// RFC 5280 specifies at most 20 bytes for a serial number
654					let mut sl = hash.as_ref()[0..20].to_vec();
655					sl[0] &= 0x7f; // MSB must be 0 to ensure encoding bignum in 20 bytes
656					writer.next().write_bigint_bytes(&sl, true);
657				}
658				#[cfg(not(feature = "crypto"))]
659				if self.serial_number.is_none() {
660					return Err(Error::MissingSerialNumber);
661				}
662			};
663			// Write signature algorithm
664			issuer.key_pair.alg.write_alg_ident(writer.next());
665			// Write issuer name
666			write_distinguished_name(writer.next(), &issuer.distinguished_name);
667			// Write validity
668			writer.next().write_sequence(|writer| {
669				// Not before
670				write_dt_utc_or_generalized(writer.next(), self.not_before);
671				// Not after
672				write_dt_utc_or_generalized(writer.next(), self.not_after);
673				Ok::<(), Error>(())
674			})?;
675			// Write subject
676			write_distinguished_name(writer.next(), &self.distinguished_name);
677			// Write subjectPublicKeyInfo
678			serialize_public_key_der(pub_key, writer.next());
679			// write extensions
680			let should_write_exts = self.use_authority_key_identifier_extension
681				|| !self.subject_alt_names.is_empty()
682				|| !self.extended_key_usages.is_empty()
683				|| self.name_constraints.iter().any(|c| !c.is_empty())
684				|| matches!(self.is_ca, IsCa::ExplicitNoCa)
685				|| matches!(self.is_ca, IsCa::Ca(_))
686				|| !self.custom_extensions.is_empty();
687			if !should_write_exts {
688				return Ok(());
689			}
690
691			writer.next().write_tagged(Tag::context(3), |writer| {
692				writer.write_sequence(|writer| {
693					if self.use_authority_key_identifier_extension {
694						write_x509_authority_key_identifier(
695							writer.next(),
696							match issuer.key_identifier_method {
697								KeyIdMethod::PreSpecified(aki) => aki.clone(),
698								#[cfg(feature = "crypto")]
699								_ => issuer
700									.key_identifier_method
701									.derive(issuer.key_pair.public_key_der()),
702							},
703						);
704					}
705					// Write subject_alt_names
706					if !self.subject_alt_names.is_empty() {
707						self.write_subject_alt_names(writer.next());
708					}
709
710					// Write standard key usage
711					self.write_key_usage(writer.next());
712
713					// Write extended key usage
714					if !self.extended_key_usages.is_empty() {
715						write_x509_extension(writer.next(), oid::EXT_KEY_USAGE, false, |writer| {
716							writer.write_sequence(|writer| {
717								for usage in self.extended_key_usages.iter() {
718									let oid = ObjectIdentifier::from_slice(usage.oid());
719									writer.next().write_oid(&oid);
720								}
721							});
722						});
723					}
724					if let Some(name_constraints) = &self.name_constraints {
725						// If both trees are empty, the extension must be omitted.
726						if !name_constraints.is_empty() {
727							write_x509_extension(
728								writer.next(),
729								oid::NAME_CONSTRAINTS,
730								true,
731								|writer| {
732									writer.write_sequence(|writer| {
733										if !name_constraints.permitted_subtrees.is_empty() {
734											write_general_subtrees(
735												writer.next(),
736												0,
737												&name_constraints.permitted_subtrees,
738											);
739										}
740										if !name_constraints.excluded_subtrees.is_empty() {
741											write_general_subtrees(
742												writer.next(),
743												1,
744												&name_constraints.excluded_subtrees,
745											);
746										}
747									});
748								},
749							);
750						}
751					}
752					if !self.crl_distribution_points.is_empty() {
753						write_x509_extension(
754							writer.next(),
755							oid::CRL_DISTRIBUTION_POINTS,
756							false,
757							|writer| {
758								writer.write_sequence(|writer| {
759									for distribution_point in &self.crl_distribution_points {
760										distribution_point.write_der(writer.next());
761									}
762								})
763							},
764						);
765					}
766					match self.is_ca {
767						IsCa::Ca(ref constraint) => {
768							// Write subject_key_identifier
769							write_x509_extension(
770								writer.next(),
771								oid::SUBJECT_KEY_IDENTIFIER,
772								false,
773								|writer| {
774									writer.write_bytes(
775										&self.key_identifier_method.derive(pub_key_spki),
776									);
777								},
778							);
779							// Write basic_constraints
780							write_x509_extension(
781								writer.next(),
782								oid::BASIC_CONSTRAINTS,
783								true,
784								|writer| {
785									writer.write_sequence(|writer| {
786										writer.next().write_bool(true); // cA flag
787										if let BasicConstraints::Constrained(path_len_constraint) =
788											constraint
789										{
790											writer.next().write_u8(*path_len_constraint);
791										}
792									});
793								},
794							);
795						},
796						IsCa::ExplicitNoCa => {
797							// Write subject_key_identifier
798							write_x509_extension(
799								writer.next(),
800								oid::SUBJECT_KEY_IDENTIFIER,
801								false,
802								|writer| {
803									writer.write_bytes(
804										&self.key_identifier_method.derive(pub_key_spki),
805									);
806								},
807							);
808							// Write basic_constraints
809							write_x509_extension(
810								writer.next(),
811								oid::BASIC_CONSTRAINTS,
812								true,
813								|writer| {
814									writer.write_sequence(|writer| {
815										writer.next().write_bool(false); // cA flag
816									});
817								},
818							);
819						},
820						IsCa::NoCa => {},
821					}
822
823					// Write the custom extensions
824					for ext in &self.custom_extensions {
825						write_x509_extension(writer.next(), &ext.oid, ext.critical, |writer| {
826							writer.write_der(ext.content())
827						});
828					}
829				});
830			});
831
832			Ok(())
833		})?;
834
835		Ok(der.into())
836	}
837
838	/// Insert an extended key usage (EKU) into the parameters if it does not already exist
839	pub fn insert_extended_key_usage(&mut self, eku: ExtendedKeyUsagePurpose) {
840		if !self.extended_key_usages.contains(&eku) {
841			self.extended_key_usages.push(eku);
842		}
843	}
844}
845
846fn write_general_subtrees(writer: DERWriter, tag: u64, general_subtrees: &[GeneralSubtree]) {
847	writer.write_tagged_implicit(Tag::context(tag), |writer| {
848		writer.write_sequence(|writer| {
849			for subtree in general_subtrees.iter() {
850				writer.next().write_sequence(|writer| {
851					writer
852						.next()
853						.write_tagged_implicit(
854							Tag::context(subtree.tag()),
855							|writer| match subtree {
856								GeneralSubtree::Rfc822Name(name)
857								| GeneralSubtree::DnsName(name) => writer.write_ia5_string(name),
858								GeneralSubtree::DirectoryName(name) => {
859									write_distinguished_name(writer, name)
860								},
861								GeneralSubtree::IpAddress(subnet) => {
862									writer.write_bytes(&subnet.to_bytes())
863								},
864							},
865						);
866					// minimum must be 0 (the default) and maximum must be absent
867				});
868			}
869		});
870	});
871}
872
873/// A PKCS #10 CSR attribute, as defined in [RFC 5280] and constrained
874/// by [RFC 2986].
875///
876/// [RFC 5280]: <https://datatracker.ietf.org/doc/html/rfc5280#appendix-A.1>
877/// [RFC 2986]: <https://datatracker.ietf.org/doc/html/rfc2986#section-4>
878#[derive(Debug, PartialEq, Eq, Hash, Clone)]
879pub struct Attribute {
880	/// `AttributeType` of the `Attribute`, defined as an `OBJECT IDENTIFIER`.
881	pub oid: &'static [u64],
882	/// DER-encoded values of the `Attribute`, defined by [RFC 2986] as:
883	///
884	/// ```text
885	/// SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
886	/// ```
887	///
888	/// [RFC 2986]: https://datatracker.ietf.org/doc/html/rfc2986#section-4
889	pub values: Vec<u8>,
890}
891
892/// A custom extension of a certificate, as specified in
893/// [RFC 5280](https://tools.ietf.org/html/rfc5280#section-4.2)
894#[derive(Debug, PartialEq, Eq, Hash, Clone)]
895pub struct CustomExtension {
896	oid: Vec<u64>,
897	critical: bool,
898
899	/// The content must be DER-encoded
900	content: Vec<u8>,
901}
902
903impl CustomExtension {
904	/// Creates a new acmeIdentifier extension for ACME TLS-ALPN-01
905	/// as specified in [RFC 8737](https://tools.ietf.org/html/rfc8737#section-3)
906	///
907	/// Panics if the passed `sha_digest` parameter doesn't hold 32 bytes (256 bits).
908	pub fn new_acme_identifier(sha_digest: &[u8]) -> Self {
909		assert_eq!(sha_digest.len(), 32, "wrong size of sha_digest");
910		let content = yasna::construct_der(|writer| {
911			writer.write_bytes(sha_digest);
912		});
913		Self {
914			oid: oid::PE_ACME.to_owned(),
915			critical: true,
916			content,
917		}
918	}
919	/// Create a new custom extension with the specified content
920	pub fn from_oid_content(oid: &[u64], content: Vec<u8>) -> Self {
921		Self {
922			oid: oid.to_owned(),
923			critical: false,
924			content,
925		}
926	}
927	/// Sets the criticality flag of the extension.
928	pub fn set_criticality(&mut self, criticality: bool) {
929		self.critical = criticality;
930	}
931	/// Obtains the criticality flag of the extension.
932	pub fn criticality(&self) -> bool {
933		self.critical
934	}
935	/// Obtains the content of the extension.
936	pub fn content(&self) -> &[u8] {
937		&self.content
938	}
939	/// Obtains the OID components of the extensions, as u64 pieces
940	pub fn oid_components(&self) -> impl Iterator<Item = u64> + '_ {
941		self.oid.iter().copied()
942	}
943}
944
945#[derive(Debug, PartialEq, Eq, Hash, Clone)]
946#[non_exhaustive]
947/// The attribute type of a distinguished name entry
948pub enum DnType {
949	/// X520countryName
950	CountryName,
951	/// X520LocalityName
952	LocalityName,
953	/// X520StateOrProvinceName
954	StateOrProvinceName,
955	/// X520OrganizationName
956	OrganizationName,
957	/// X520OrganizationalUnitName
958	OrganizationalUnitName,
959	/// X520CommonName
960	CommonName,
961	/// Custom distinguished name type
962	CustomDnType(Vec<u64>),
963}
964
965impl DnType {
966	pub(crate) fn to_oid(&self) -> ObjectIdentifier {
967		let sl = match self {
968			DnType::CountryName => oid::COUNTRY_NAME,
969			DnType::LocalityName => oid::LOCALITY_NAME,
970			DnType::StateOrProvinceName => oid::STATE_OR_PROVINCE_NAME,
971			DnType::OrganizationName => oid::ORG_NAME,
972			DnType::OrganizationalUnitName => oid::ORG_UNIT_NAME,
973			DnType::CommonName => oid::COMMON_NAME,
974			DnType::CustomDnType(ref oid) => oid.as_slice(),
975		};
976		ObjectIdentifier::from_slice(sl)
977	}
978
979	/// Generate a DnType for the provided OID
980	pub fn from_oid(slice: &[u64]) -> Self {
981		match slice {
982			oid::COUNTRY_NAME => DnType::CountryName,
983			oid::LOCALITY_NAME => DnType::LocalityName,
984			oid::STATE_OR_PROVINCE_NAME => DnType::StateOrProvinceName,
985			oid::ORG_NAME => DnType::OrganizationName,
986			oid::ORG_UNIT_NAME => DnType::OrganizationalUnitName,
987			oid::COMMON_NAME => DnType::CommonName,
988			oid => DnType::CustomDnType(oid.into()),
989		}
990	}
991}
992
993#[derive(Debug, PartialEq, Eq, Hash, Clone)]
994/// One of the purposes contained in the [extended key usage extension](https://tools.ietf.org/html/rfc5280#section-4.2.1.12)
995pub enum ExtendedKeyUsagePurpose {
996	/// anyExtendedKeyUsage
997	Any,
998	/// id-kp-serverAuth
999	ServerAuth,
1000	/// id-kp-clientAuth
1001	ClientAuth,
1002	/// id-kp-codeSigning
1003	CodeSigning,
1004	/// id-kp-emailProtection
1005	EmailProtection,
1006	/// id-kp-timeStamping
1007	TimeStamping,
1008	/// id-kp-OCSPSigning
1009	OcspSigning,
1010	/// A custom purpose not from the pre-specified list of purposes
1011	Other(Vec<u64>),
1012}
1013
1014impl ExtendedKeyUsagePurpose {
1015	fn oid(&self) -> &[u64] {
1016		use ExtendedKeyUsagePurpose::*;
1017		match self {
1018			// anyExtendedKeyUsage
1019			Any => &[2, 5, 29, 37, 0],
1020			// id-kp-*
1021			ServerAuth => &[1, 3, 6, 1, 5, 5, 7, 3, 1],
1022			ClientAuth => &[1, 3, 6, 1, 5, 5, 7, 3, 2],
1023			CodeSigning => &[1, 3, 6, 1, 5, 5, 7, 3, 3],
1024			EmailProtection => &[1, 3, 6, 1, 5, 5, 7, 3, 4],
1025			TimeStamping => &[1, 3, 6, 1, 5, 5, 7, 3, 8],
1026			OcspSigning => &[1, 3, 6, 1, 5, 5, 7, 3, 9],
1027			Other(oid) => oid,
1028		}
1029	}
1030}
1031
1032/// The [NameConstraints extension](https://tools.ietf.org/html/rfc5280#section-4.2.1.10)
1033/// (only relevant for CA certificates)
1034#[derive(Debug, PartialEq, Eq, Clone)]
1035pub struct NameConstraints {
1036	/// A list of subtrees that the domain has to match.
1037	pub permitted_subtrees: Vec<GeneralSubtree>,
1038	/// A list of subtrees that the domain must not match.
1039	///
1040	/// Any name matching an excluded subtree is invalid even if it also matches a permitted subtree.
1041	pub excluded_subtrees: Vec<GeneralSubtree>,
1042}
1043
1044impl NameConstraints {
1045	fn is_empty(&self) -> bool {
1046		self.permitted_subtrees.is_empty() && self.excluded_subtrees.is_empty()
1047	}
1048}
1049
1050#[derive(Debug, PartialEq, Eq, Clone)]
1051#[allow(missing_docs)]
1052#[non_exhaustive]
1053/// General Subtree type.
1054///
1055/// This type has similarities to the [`SanType`] enum but is not equal.
1056/// For example, `GeneralSubtree` has CIDR subnets for ip addresses
1057/// while [`SanType`] has IP addresses.
1058pub enum GeneralSubtree {
1059	/// Also known as E-Mail address
1060	Rfc822Name(String),
1061	DnsName(String),
1062	DirectoryName(DistinguishedName),
1063	IpAddress(CidrSubnet),
1064}
1065
1066impl GeneralSubtree {
1067	fn tag(&self) -> u64 {
1068		// Defined in the GeneralName list in
1069		// https://tools.ietf.org/html/rfc5280#page-38
1070		const TAG_RFC822_NAME: u64 = 1;
1071		const TAG_DNS_NAME: u64 = 2;
1072		const TAG_DIRECTORY_NAME: u64 = 4;
1073		const TAG_IP_ADDRESS: u64 = 7;
1074
1075		match self {
1076			GeneralSubtree::Rfc822Name(_name) => TAG_RFC822_NAME,
1077			GeneralSubtree::DnsName(_name) => TAG_DNS_NAME,
1078			GeneralSubtree::DirectoryName(_name) => TAG_DIRECTORY_NAME,
1079			GeneralSubtree::IpAddress(_addr) => TAG_IP_ADDRESS,
1080		}
1081	}
1082}
1083
1084#[derive(Debug, PartialEq, Eq, Hash, Clone)]
1085#[allow(missing_docs)]
1086/// CIDR subnet, as per [RFC 4632](https://tools.ietf.org/html/rfc4632)
1087///
1088/// You might know CIDR subnets better by their textual representation
1089/// where they consist of an ip address followed by a slash and a prefix
1090/// number, for example `192.168.99.0/24`.
1091///
1092/// The first field in the enum is the address, the second is the mask.
1093/// Both are specified in network byte order.
1094pub enum CidrSubnet {
1095	V4([u8; 4], [u8; 4]),
1096	V6([u8; 16], [u8; 16]),
1097}
1098
1099macro_rules! mask {
1100	($t:ty, $d:expr) => {{
1101		let v = <$t>::max_value();
1102		let v = v.checked_shr($d as u32).unwrap_or(0);
1103		(!v).to_be_bytes()
1104	}};
1105}
1106
1107impl CidrSubnet {
1108	/// Obtains the CidrSubnet from an ip address
1109	/// as well as the specified prefix number.
1110	///
1111	/// ```
1112	/// # use std::net::IpAddr;
1113	/// # use std::str::FromStr;
1114	/// # use rcgen::CidrSubnet;
1115	/// // The "192.0.2.0/24" example from
1116	/// // https://tools.ietf.org/html/rfc5280#page-42
1117	/// let addr = IpAddr::from_str("192.0.2.0").unwrap();
1118	/// let subnet = CidrSubnet::from_addr_prefix(addr, 24);
1119	/// assert_eq!(subnet, CidrSubnet::V4([0xC0, 0x00, 0x02, 0x00], [0xFF, 0xFF, 0xFF, 0x00]));
1120	/// ```
1121	pub fn from_addr_prefix(addr: IpAddr, prefix: u8) -> Self {
1122		match addr {
1123			IpAddr::V4(addr) => Self::from_v4_prefix(addr.octets(), prefix),
1124			IpAddr::V6(addr) => Self::from_v6_prefix(addr.octets(), prefix),
1125		}
1126	}
1127	/// Obtains the CidrSubnet from an IPv4 address in network byte order
1128	/// as well as the specified prefix.
1129	pub fn from_v4_prefix(addr: [u8; 4], prefix: u8) -> Self {
1130		CidrSubnet::V4(addr, mask!(u32, prefix))
1131	}
1132	/// Obtains the CidrSubnet from an IPv6 address in network byte order
1133	/// as well as the specified prefix.
1134	pub fn from_v6_prefix(addr: [u8; 16], prefix: u8) -> Self {
1135		CidrSubnet::V6(addr, mask!(u128, prefix))
1136	}
1137	fn to_bytes(&self) -> Vec<u8> {
1138		let mut res = Vec::new();
1139		match self {
1140			CidrSubnet::V4(addr, mask) => {
1141				res.extend_from_slice(addr);
1142				res.extend_from_slice(mask);
1143			},
1144			CidrSubnet::V6(addr, mask) => {
1145				res.extend_from_slice(addr);
1146				res.extend_from_slice(mask);
1147			},
1148		}
1149		res
1150	}
1151}
1152
1153/// Obtains the CidrSubnet from the well-known
1154/// addr/prefix notation.
1155/// ```
1156/// # use std::str::FromStr;
1157/// # use rcgen::CidrSubnet;
1158/// // The "192.0.2.0/24" example from
1159/// // https://tools.ietf.org/html/rfc5280#page-42
1160/// let subnet = CidrSubnet::from_str("192.0.2.0/24").unwrap();
1161/// assert_eq!(subnet, CidrSubnet::V4([0xC0, 0x00, 0x02, 0x00], [0xFF, 0xFF, 0xFF, 0x00]));
1162/// ```
1163impl FromStr for CidrSubnet {
1164	type Err = ();
1165
1166	fn from_str(s: &str) -> Result<Self, Self::Err> {
1167		let mut iter = s.split('/');
1168		if let (Some(addr_s), Some(prefix_s)) = (iter.next(), iter.next()) {
1169			let addr = IpAddr::from_str(addr_s).map_err(|_| ())?;
1170			let prefix = u8::from_str(prefix_s).map_err(|_| ())?;
1171			Ok(Self::from_addr_prefix(addr, prefix))
1172		} else {
1173			Err(())
1174		}
1175	}
1176}
1177
1178/// Helper to obtain an `OffsetDateTime` from year, month, day values
1179///
1180/// The year, month, day values are assumed to be in UTC.
1181///
1182/// This helper function serves two purposes: first, so that you don't
1183/// have to import the time crate yourself in order to specify date
1184/// information, second so that users don't have to type unproportionately
1185/// long code just to generate an instance of [`OffsetDateTime`].
1186pub fn date_time_ymd(year: i32, month: u8, day: u8) -> OffsetDateTime {
1187	let month = Month::try_from(month).expect("out-of-range month");
1188	let primitive_dt = PrimitiveDateTime::new(
1189		Date::from_calendar_date(year, month, day).expect("invalid or out-of-range date"),
1190		Time::MIDNIGHT,
1191	);
1192	primitive_dt.assume_utc()
1193}
1194
1195/// Whether the certificate is allowed to sign other certificates
1196#[derive(Debug, PartialEq, Eq, Hash, Clone)]
1197pub enum IsCa {
1198	/// The certificate can only sign itself
1199	NoCa,
1200	/// The certificate can only sign itself, adding the extension and `CA:FALSE`
1201	ExplicitNoCa,
1202	/// The certificate may be used to sign other certificates
1203	Ca(BasicConstraints),
1204}
1205
1206/// The path length constraint (only relevant for CA certificates)
1207///
1208/// Sets an optional upper limit on the length of the intermediate certificate chain
1209/// length allowed for this CA certificate (not including the end entity certificate).
1210#[derive(Debug, PartialEq, Eq, Hash, Clone)]
1211pub enum BasicConstraints {
1212	/// No constraint
1213	Unconstrained,
1214	/// Constrain to the contained number of intermediate certificates
1215	Constrained(u8),
1216}
1217
1218#[cfg(test)]
1219mod tests {
1220	#[cfg(feature = "pem")]
1221	use super::*;
1222
1223	#[cfg(feature = "crypto")]
1224	#[test]
1225	fn test_with_key_usages() {
1226		let mut params: CertificateParams = Default::default();
1227
1228		// Set key_usages
1229		params.key_usages = vec![
1230			KeyUsagePurpose::DigitalSignature,
1231			KeyUsagePurpose::KeyEncipherment,
1232			KeyUsagePurpose::ContentCommitment,
1233		];
1234
1235		// This can sign things!
1236		params.is_ca = IsCa::Ca(BasicConstraints::Constrained(0));
1237
1238		// Make the cert
1239		let key_pair = KeyPair::generate().unwrap();
1240		let cert = params.self_signed(&key_pair).unwrap();
1241
1242		// Parse it
1243		let (_rem, cert) = x509_parser::parse_x509_certificate(cert.der()).unwrap();
1244
1245		// Check oid
1246		let key_usage_oid_str = "2.5.29.15";
1247
1248		// Found flag
1249		let mut found = false;
1250
1251		for ext in cert.extensions() {
1252			if key_usage_oid_str == ext.oid.to_id_string() {
1253				match ext.parsed_extension() {
1254					x509_parser::extensions::ParsedExtension::KeyUsage(usage) => {
1255						assert!(usage.flags == 7);
1256						found = true;
1257					},
1258					_ => {},
1259				}
1260			}
1261		}
1262
1263		assert!(found);
1264	}
1265
1266	#[cfg(feature = "crypto")]
1267	#[test]
1268	fn test_with_key_usages_decipheronly_only() {
1269		let mut params: CertificateParams = Default::default();
1270
1271		// Set key_usages
1272		params.key_usages = vec![KeyUsagePurpose::DecipherOnly];
1273
1274		// This can sign things!
1275		params.is_ca = IsCa::Ca(BasicConstraints::Constrained(0));
1276
1277		// Make the cert
1278		let key_pair = KeyPair::generate().unwrap();
1279		let cert = params.self_signed(&key_pair).unwrap();
1280
1281		// Parse it
1282		let (_rem, cert) = x509_parser::parse_x509_certificate(cert.der()).unwrap();
1283
1284		// Check oid
1285		let key_usage_oid_str = "2.5.29.15";
1286
1287		// Found flag
1288		let mut found = false;
1289
1290		for ext in cert.extensions() {
1291			if key_usage_oid_str == ext.oid.to_id_string() {
1292				match ext.parsed_extension() {
1293					x509_parser::extensions::ParsedExtension::KeyUsage(usage) => {
1294						assert!(usage.flags == 256);
1295						found = true;
1296					},
1297					_ => {},
1298				}
1299			}
1300		}
1301
1302		assert!(found);
1303	}
1304
1305	#[cfg(feature = "crypto")]
1306	#[test]
1307	fn test_with_extended_key_usages_any() {
1308		let mut params: CertificateParams = Default::default();
1309
1310		// Set extended_key_usages
1311		params.extended_key_usages = vec![ExtendedKeyUsagePurpose::Any];
1312
1313		// Make the cert
1314		let key_pair = KeyPair::generate().unwrap();
1315		let cert = params.self_signed(&key_pair).unwrap();
1316
1317		// Parse it
1318		let (_rem, cert) = x509_parser::parse_x509_certificate(cert.der()).unwrap();
1319
1320		// Ensure we found it.
1321		let maybe_extension = cert.extended_key_usage().unwrap();
1322		let extension = maybe_extension.unwrap();
1323		assert!(extension.value.any);
1324	}
1325
1326	#[cfg(feature = "crypto")]
1327	#[test]
1328	fn test_with_extended_key_usages_other() {
1329		use x509_parser::der_parser::asn1_rs::Oid;
1330		let mut params: CertificateParams = Default::default();
1331		const OID_1: &[u64] = &[1, 2, 3, 4];
1332		const OID_2: &[u64] = &[1, 2, 3, 4, 5, 6];
1333
1334		// Set extended_key_usages
1335		params.extended_key_usages = vec![
1336			ExtendedKeyUsagePurpose::Other(Vec::from(OID_1)),
1337			ExtendedKeyUsagePurpose::Other(Vec::from(OID_2)),
1338		];
1339
1340		// Make the cert
1341		let key_pair = KeyPair::generate().unwrap();
1342		let cert = params.self_signed(&key_pair).unwrap();
1343
1344		// Parse it
1345		let (_rem, cert) = x509_parser::parse_x509_certificate(cert.der()).unwrap();
1346
1347		// Ensure we found it.
1348		let maybe_extension = cert.extended_key_usage().unwrap();
1349		let extension = maybe_extension.unwrap();
1350
1351		let expected_oids = vec![Oid::from(OID_1).unwrap(), Oid::from(OID_2).unwrap()];
1352		assert_eq!(extension.value.other, expected_oids);
1353	}
1354
1355	#[cfg(feature = "pem")]
1356	mod test_pem_serialization {
1357		use super::*;
1358
1359		#[test]
1360		#[cfg(windows)]
1361		fn test_windows_line_endings() {
1362			let key_pair = KeyPair::generate().unwrap();
1363			let cert = CertificateParams::default().self_signed(&key_pair).unwrap();
1364			assert!(cert.pem().contains("\r\n"));
1365		}
1366
1367		#[test]
1368		#[cfg(not(windows))]
1369		fn test_not_windows_line_endings() {
1370			let key_pair = KeyPair::generate().unwrap();
1371			let cert = CertificateParams::default().self_signed(&key_pair).unwrap();
1372			assert!(!cert.pem().contains('\r'));
1373		}
1374	}
1375
1376	#[cfg(all(feature = "pem", feature = "x509-parser"))]
1377	mod test_key_identifier_from_ca {
1378		use super::*;
1379
1380		#[test]
1381		fn load_ca_and_sign_cert() {
1382			let ca_cert = r#"-----BEGIN CERTIFICATE-----
1383MIIFDTCCAvWgAwIBAgIUVuDfDt/BUVfObGOHsM+L5/qPZfIwDQYJKoZIhvcNAQEL
1384BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjMxMjA4MTAwOTI2WhcNMjQx
1385MTI4MTAwOTI2WjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN
1386AQEBBQADggIPADCCAgoCggIBAKXyZsv7Zwek9yc54IXWjCkMwU4eDMz9Uw06WETF
1387hZtauwDo4usCeYJa/7x8RZbGcI99s/vOMHjIdVzY6g9p5c6qS+7EUBhXARYVB74z
1388XUGwgVGss7lgw+0dNxhQ8F0M2smBXUP9FlJJjJpbWeU+93iynGy+PTXFtYMnOoVI
13894G7YKsG5lX0zBJUNYZslEz6Kp8eRYu7FAdccU0u5bmg02a1WiXOYJeN1+AifUbRN
1390zNInZCqMCFgoHczb0DvKU3QX/xrcBxfr/SNJPqxlecUvsozteUoAFAUF1uTxH31q
1391cVmCHf9I0r6JJoGxs+XMVbH2SJLdsq/+zpjeHz6gy0z4aRMBpaUWUQ9pEENeSq15
1392PXCuX3yPT2BII30mL86OWO6qgms70iALak6xZ/xAT7RT22E1bOF+XJsiUM3OgGF0
1393TPmDcpafEMH4kwzdaC7U5hqhYk9I2lfTMEghV86kUXClExuHEQD4GZLcd1HMD/Wg
1394qOZO4y/t/yzBPNq01FpeilFph/tW6pxr1X7Jloz1/yIuNFK0oXTB24J/TUi+/S1B
1395kavOBg3eNHHDXDjESKtnV+iwo1cFt6LVCrnKhKJ6m95+c+YKQGIrcwkR91OxZ9ZT
1396DEzySsPDpWrteZf3K1VA0Ut41aTKu8pYwxsnVdOiBGaJkOh/lrevI6U9Eg4vVq94
1397hyAZAgMBAAGjUzBRMB0GA1UdDgQWBBSX1HahmxpxNSrH9KGEElYGul1hhDAfBgNV
1398HSMEGDAWgBSX1HahmxpxNSrH9KGEElYGul1hhDAPBgNVHRMBAf8EBTADAQH/MA0G
1399CSqGSIb3DQEBCwUAA4ICAQAhtwt0OrHVITVOzoH3c+7SS/rGd9KGpHG4Z/N7ASs3
14007A2PXFC5XbUuylky0+/nbkN6hhecj+Zwt5x5R8k4saXUZ8xkMfP8RaRxyZ3rUOIC
1401BZhZm1XbQzaWIQjpjyPUWDDa9P0lGsUyrEIQaLjg1J5jYPOD132bmdIuhZtzldTV
1402zeE/4sKdrkj6HZxe1jxAhx2IWm6W+pEAcq1Ld9SmJGOxBVRRKyGsMMw6hCdWfQHv
1403Z8qRIhn3FU6ZKW2jvTGJBIXoK4u454qi6DVxkFZ0OK9VwWVuDLvs2Es95TiZPTq+
1404KJmRHWHF/Ic78XFgxVq0tVaJAs7qoOMjDkehPG1V8eewanlpcaE6rPx0eiPq+nHE
1405gCf0KmKGVM8lQe63obzprkdLKL3T4UDN19K2wqscJcPKK++27OYx2hJaJKmYzF23
14064WhIRzdALTs/2fbB68nVSz7kBtHvsHHS33Q57zEdQq5YeyUaTtCvJJobt70dy9vN
1407YolzLWoY/itEPFtbBAdnJxXlctI3bw4Mzw1d66Wt+//R45+cIe6cJdUIqMHDhsGf
1408U8EuffvDcTJuUzIkyzbyOI15r1TMbRt8vFR0jzagZBCG73lVacH/bYEb2j4Z1ORi
1409L2Fl4tgIQ5tyaTpu9gpJZvPU0VZ/j+1Jdk1c9PJ6xhCjof4nzI9YsLbI8lPtu8K/
1410Ng==
1411-----END CERTIFICATE-----"#;
1412
1413			let ca_key = r#"-----BEGIN PRIVATE KEY-----
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
1463PITGdT9dgN88nHPCle0B1+OY+OZ5
1464-----END PRIVATE KEY-----"#;
1465
1466			let params = CertificateParams::from_ca_cert_pem(ca_cert).unwrap();
1467			let ca_ski = vec![
1468				0x97, 0xD4, 0x76, 0xA1, 0x9B, 0x1A, 0x71, 0x35, 0x2A, 0xC7, 0xF4, 0xA1, 0x84, 0x12,
1469				0x56, 0x06, 0xBA, 0x5D, 0x61, 0x84,
1470			];
1471
1472			assert_eq!(
1473				KeyIdMethod::PreSpecified(ca_ski.clone()),
1474				params.key_identifier_method
1475			);
1476
1477			let ca_kp = KeyPair::from_pem(ca_key).unwrap();
1478			let ca_cert = params.self_signed(&ca_kp).unwrap();
1479			assert_eq!(&ca_ski, &ca_cert.key_identifier());
1480
1481			let (_, x509_ca) = x509_parser::parse_x509_certificate(ca_cert.der()).unwrap();
1482			assert_eq!(
1483				&ca_ski,
1484				&x509_ca
1485					.iter_extensions()
1486					.find_map(|ext| match ext.parsed_extension() {
1487						x509_parser::extensions::ParsedExtension::SubjectKeyIdentifier(key_id) => {
1488							Some(key_id.0.to_vec())
1489						},
1490						_ => None,
1491					})
1492					.unwrap()
1493			);
1494
1495			let ee_key = KeyPair::generate().unwrap();
1496			let mut ee_params = CertificateParams::default();
1497			ee_params.use_authority_key_identifier_extension = true;
1498			let ee_cert = ee_params.signed_by(&ee_key, &ca_cert, &ee_key).unwrap();
1499
1500			let (_, x509_ee) = x509_parser::parse_x509_certificate(ee_cert.der()).unwrap();
1501			assert_eq!(
1502				&ca_ski,
1503				&x509_ee
1504					.iter_extensions()
1505					.find_map(|ext| match ext.parsed_extension() {
1506						x509_parser::extensions::ParsedExtension::AuthorityKeyIdentifier(aki) => {
1507							aki.key_identifier.as_ref().map(|ki| ki.0.to_vec())
1508						},
1509						_ => None,
1510					})
1511					.unwrap()
1512			);
1513		}
1514	}
1515}