1#[cfg(feature = "__rustls")]
47use rustls::{
48 client::danger::HandshakeSignatureValid, client::danger::ServerCertVerified,
49 client::danger::ServerCertVerifier, crypto::WebPkiSupportedAlgorithms,
50 server::ParsedCertificate, DigitallySignedStruct, Error as TLSError, RootCertStore,
51 SignatureScheme,
52};
53use rustls_pki_types::pem::PemObject;
54#[cfg(feature = "__rustls")]
55use rustls_pki_types::{ServerName, UnixTime};
56use std::{
57 fmt,
58 io::{BufRead, BufReader},
59 sync::Arc,
60};
61
62#[cfg(feature = "__rustls")]
64pub struct CertificateRevocationList {
65 #[cfg(feature = "__rustls")]
66 inner: rustls_pki_types::CertificateRevocationListDer<'static>,
67}
68
69#[derive(Clone)]
71pub struct Certificate {
72 #[cfg(feature = "__native-tls")]
73 native: native_tls_crate::Certificate,
74 #[cfg(feature = "__rustls")]
75 original: Cert,
76}
77
78#[cfg(feature = "__rustls")]
79#[derive(Clone)]
80enum Cert {
81 Der(Vec<u8>),
82 Pem(Vec<u8>),
83}
84
85#[derive(Clone)]
87pub struct Identity {
88 #[cfg_attr(
89 not(any(feature = "__native-tls", feature = "__rustls")),
90 allow(unused)
91 )]
92 inner: ClientCert,
93}
94
95enum ClientCert {
96 #[cfg(feature = "__native-tls")]
97 Pkcs12(native_tls_crate::Identity),
98 #[cfg(feature = "__native-tls")]
99 Pkcs8(native_tls_crate::Identity),
100 #[cfg(feature = "__rustls")]
101 Pem {
102 key: rustls_pki_types::PrivateKeyDer<'static>,
103 certs: Vec<rustls_pki_types::CertificateDer<'static>>,
104 },
105}
106
107impl Clone for ClientCert {
108 fn clone(&self) -> Self {
109 match self {
110 #[cfg(feature = "__native-tls")]
111 Self::Pkcs8(i) => Self::Pkcs8(i.clone()),
112 #[cfg(feature = "__native-tls")]
113 Self::Pkcs12(i) => Self::Pkcs12(i.clone()),
114 #[cfg(feature = "__rustls")]
115 ClientCert::Pem { key, certs } => ClientCert::Pem {
116 key: key.clone_key(),
117 certs: certs.clone(),
118 },
119 #[cfg_attr(
120 any(feature = "__native-tls", feature = "__rustls"),
121 allow(unreachable_patterns)
122 )]
123 _ => unreachable!(),
124 }
125 }
126}
127
128impl Certificate {
129 pub fn from_der(der: &[u8]) -> crate::Result<Certificate> {
146 Ok(Certificate {
147 #[cfg(feature = "__native-tls")]
148 native: native_tls_crate::Certificate::from_der(der).map_err(crate::error::builder)?,
149 #[cfg(feature = "__rustls")]
150 original: Cert::Der(der.to_owned()),
151 })
152 }
153
154 pub fn from_pem(pem: &[u8]) -> crate::Result<Certificate> {
171 Ok(Certificate {
172 #[cfg(feature = "__native-tls")]
173 native: native_tls_crate::Certificate::from_pem(pem).map_err(crate::error::builder)?,
174 #[cfg(feature = "__rustls")]
175 original: Cert::Pem(pem.to_owned()),
176 })
177 }
178
179 pub fn from_pem_bundle(pem_bundle: &[u8]) -> crate::Result<Vec<Certificate>> {
197 let mut reader = BufReader::new(pem_bundle);
198
199 Self::read_pem_certs(&mut reader)?
200 .iter()
201 .map(|cert_vec| Certificate::from_der(cert_vec))
202 .collect::<crate::Result<Vec<Certificate>>>()
203 }
204
205 #[cfg(feature = "__native-tls")]
213 pub(crate) fn add_to_native_tls(self, tls: &mut native_tls_crate::TlsConnectorBuilder) {
214 tls.add_root_certificate(self.native);
215 }
216
217 #[cfg(feature = "__rustls")]
218 pub(crate) fn add_to_rustls(
219 self,
220 root_cert_store: &mut rustls::RootCertStore,
221 ) -> crate::Result<()> {
222 use std::io::Cursor;
223
224 match self.original {
225 Cert::Der(buf) => root_cert_store
226 .add(buf.into())
227 .map_err(crate::error::builder)?,
228 Cert::Pem(buf) => {
229 let mut reader = Cursor::new(buf);
230 let certs = Self::read_pem_certs(&mut reader)?;
231 for c in certs {
232 root_cert_store
233 .add(c.into())
234 .map_err(crate::error::builder)?;
235 }
236 }
237 }
238 Ok(())
239 }
240
241 fn read_pem_certs(reader: &mut impl BufRead) -> crate::Result<Vec<Vec<u8>>> {
242 rustls_pki_types::CertificateDer::pem_reader_iter(reader)
243 .map(|result| match result {
244 Ok(cert) => Ok(cert.as_ref().to_vec()),
245 Err(_) => Err(crate::error::builder("invalid certificate encoding")),
246 })
247 .collect()
248 }
249}
250
251impl Identity {
252 #[cfg(feature = "__native-tls")]
284 pub fn from_pkcs12_der(der: &[u8], password: &str) -> crate::Result<Identity> {
285 Ok(Identity {
286 inner: ClientCert::Pkcs12(
287 native_tls_crate::Identity::from_pkcs12(der, password)
288 .map_err(crate::error::builder)?,
289 ),
290 })
291 }
292
293 #[cfg(feature = "__native-tls")]
318 pub fn from_pkcs8_pem(pem: &[u8], key: &[u8]) -> crate::Result<Identity> {
319 Ok(Identity {
320 inner: ClientCert::Pkcs8(
321 native_tls_crate::Identity::from_pkcs8(pem, key).map_err(crate::error::builder)?,
322 ),
323 })
324 }
325
326 #[cfg(feature = "__rustls")]
352 pub fn from_pem(buf: &[u8]) -> crate::Result<Identity> {
353 use rustls_pki_types::{pem::SectionKind, PrivateKeyDer};
354 use std::io::Cursor;
355
356 let (key, certs) = {
357 let mut pem = Cursor::new(buf);
358 let mut sk = Vec::<rustls_pki_types::PrivateKeyDer>::new();
359 let mut certs = Vec::<rustls_pki_types::CertificateDer>::new();
360
361 while let Some((kind, data)) =
362 rustls_pki_types::pem::from_buf(&mut pem).map_err(|_| {
363 crate::error::builder(TLSError::General(String::from(
364 "Invalid identity PEM file",
365 )))
366 })?
367 {
368 match kind {
369 SectionKind::Certificate => certs.push(data.into()),
370 SectionKind::PrivateKey => sk.push(PrivateKeyDer::Pkcs8(data.into())),
371 SectionKind::RsaPrivateKey => sk.push(PrivateKeyDer::Pkcs1(data.into())),
372 SectionKind::EcPrivateKey => sk.push(PrivateKeyDer::Sec1(data.into())),
373 _ => {
374 return Err(crate::error::builder(TLSError::General(String::from(
375 "No valid certificate was found",
376 ))))
377 }
378 }
379 }
380
381 if let (Some(sk), false) = (sk.pop(), certs.is_empty()) {
382 (sk, certs)
383 } else {
384 return Err(crate::error::builder(TLSError::General(String::from(
385 "private key or certificate not found",
386 ))));
387 }
388 };
389
390 Ok(Identity {
391 inner: ClientCert::Pem { key, certs },
392 })
393 }
394
395 #[cfg(feature = "__native-tls")]
396 pub(crate) fn add_to_native_tls(
397 self,
398 tls: &mut native_tls_crate::TlsConnectorBuilder,
399 ) -> crate::Result<()> {
400 match self.inner {
401 ClientCert::Pkcs12(id) | ClientCert::Pkcs8(id) => {
402 tls.identity(id);
403 Ok(())
404 }
405 #[cfg(feature = "__rustls")]
406 ClientCert::Pem { .. } => Err(crate::error::builder("incompatible TLS identity type")),
407 }
408 }
409
410 #[cfg(feature = "__rustls")]
411 pub(crate) fn add_to_rustls(
412 self,
413 config_builder: rustls::ConfigBuilder<
414 rustls::ClientConfig,
415 rustls::client::WantsClientCert,
417 >,
418 ) -> crate::Result<rustls::ClientConfig> {
419 match self.inner {
420 ClientCert::Pem { key, certs } => config_builder
421 .with_client_auth_cert(certs, key)
422 .map_err(crate::error::builder),
423 #[cfg(feature = "__native-tls")]
424 ClientCert::Pkcs12(..) | ClientCert::Pkcs8(..) => {
425 Err(crate::error::builder("incompatible TLS identity type"))
426 }
427 }
428 }
429}
430
431#[cfg(feature = "__rustls")]
432impl CertificateRevocationList {
433 #[cfg(feature = "__rustls")]
454 pub fn from_pem(pem: &[u8]) -> crate::Result<CertificateRevocationList> {
455 Ok(CertificateRevocationList {
456 #[cfg(feature = "__rustls")]
457 inner: rustls_pki_types::CertificateRevocationListDer::from_pem_slice(pem)
458 .map_err(|_| crate::error::builder("invalid crl encoding"))?,
459 })
460 }
461
462 #[cfg(feature = "__rustls")]
484 pub fn from_pem_bundle(pem_bundle: &[u8]) -> crate::Result<Vec<CertificateRevocationList>> {
485 rustls_pki_types::CertificateRevocationListDer::pem_slice_iter(pem_bundle)
486 .map(|result| match result {
487 Ok(crl) => Ok(CertificateRevocationList { inner: crl }),
488 Err(_) => Err(crate::error::builder("invalid crl encoding")),
489 })
490 .collect::<crate::Result<Vec<CertificateRevocationList>>>()
491 }
492
493 #[cfg(feature = "__rustls")]
494 pub(crate) fn as_rustls_crl<'a>(&self) -> rustls_pki_types::CertificateRevocationListDer<'a> {
495 self.inner.clone()
496 }
497}
498
499impl fmt::Debug for Certificate {
500 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
501 f.debug_struct("Certificate").finish()
502 }
503}
504
505impl fmt::Debug for Identity {
506 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
507 f.debug_struct("Identity").finish()
508 }
509}
510
511#[cfg(feature = "__rustls")]
512impl fmt::Debug for CertificateRevocationList {
513 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
514 f.debug_struct("CertificateRevocationList").finish()
515 }
516}
517
518#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
520pub struct Version(InnerVersion);
521
522#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
523#[non_exhaustive]
524enum InnerVersion {
525 Tls1_0,
526 Tls1_1,
527 Tls1_2,
528 Tls1_3,
529}
530
531impl Version {
534 pub const TLS_1_0: Version = Version(InnerVersion::Tls1_0);
536 pub const TLS_1_1: Version = Version(InnerVersion::Tls1_1);
538 pub const TLS_1_2: Version = Version(InnerVersion::Tls1_2);
540 pub const TLS_1_3: Version = Version(InnerVersion::Tls1_3);
542
543 #[cfg(feature = "__native-tls")]
544 pub(crate) fn to_native_tls(self) -> Option<native_tls_crate::Protocol> {
545 match self.0 {
546 InnerVersion::Tls1_0 => Some(native_tls_crate::Protocol::Tlsv10),
547 InnerVersion::Tls1_1 => Some(native_tls_crate::Protocol::Tlsv11),
548 InnerVersion::Tls1_2 => Some(native_tls_crate::Protocol::Tlsv12),
549 InnerVersion::Tls1_3 => None,
550 }
551 }
552
553 #[cfg(feature = "__rustls")]
554 pub(crate) fn from_rustls(version: rustls::ProtocolVersion) -> Option<Self> {
555 match version {
556 rustls::ProtocolVersion::SSLv2 => None,
557 rustls::ProtocolVersion::SSLv3 => None,
558 rustls::ProtocolVersion::TLSv1_0 => Some(Self(InnerVersion::Tls1_0)),
559 rustls::ProtocolVersion::TLSv1_1 => Some(Self(InnerVersion::Tls1_1)),
560 rustls::ProtocolVersion::TLSv1_2 => Some(Self(InnerVersion::Tls1_2)),
561 rustls::ProtocolVersion::TLSv1_3 => Some(Self(InnerVersion::Tls1_3)),
562 _ => None,
563 }
564 }
565}
566
567pub(crate) enum TlsBackend {
568 #[allow(dead_code)]
570 #[cfg(feature = "__native-tls")]
571 NativeTls,
572 #[cfg(feature = "__native-tls")]
573 BuiltNativeTls(native_tls_crate::TlsConnector),
574 #[cfg(feature = "__rustls")]
575 Rustls,
576 #[cfg(feature = "__rustls")]
577 BuiltRustls(Box<rustls::ClientConfig>),
578 #[cfg(any(feature = "__native-tls", feature = "__rustls",))]
579 UnknownPreconfigured,
580}
581
582impl fmt::Debug for TlsBackend {
583 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
584 match self {
585 #[cfg(feature = "__native-tls")]
586 TlsBackend::NativeTls => write!(f, "NativeTls"),
587 #[cfg(feature = "__native-tls")]
588 TlsBackend::BuiltNativeTls(_) => write!(f, "BuiltNativeTls"),
589 #[cfg(feature = "__rustls")]
590 TlsBackend::Rustls => write!(f, "Rustls"),
591 #[cfg(feature = "__rustls")]
592 TlsBackend::BuiltRustls(_) => write!(f, "BuiltRustls"),
593 #[cfg(any(feature = "__native-tls", feature = "__rustls",))]
594 TlsBackend::UnknownPreconfigured => write!(f, "UnknownPreconfigured"),
595 }
596 }
597}
598
599#[allow(clippy::derivable_impls)]
600impl Default for TlsBackend {
601 fn default() -> TlsBackend {
602 #[cfg(any(
603 all(feature = "__rustls", not(feature = "__native-tls")),
604 feature = "http3"
605 ))]
606 {
607 TlsBackend::Rustls
608 }
609
610 #[cfg(all(feature = "__native-tls", not(feature = "http3")))]
611 {
612 TlsBackend::NativeTls
613 }
614 }
615}
616
617#[cfg(feature = "__rustls")]
618pub(crate) fn rustls_store(certs: Vec<Certificate>) -> crate::Result<RootCertStore> {
619 let mut root_cert_store = rustls::RootCertStore::empty();
620 for cert in certs {
621 cert.add_to_rustls(&mut root_cert_store)?;
622 }
623 Ok(root_cert_store)
624}
625
626#[cfg(feature = "__rustls")]
628pub fn default_root_store() -> &'static rustls::RootCertStore {
629 static DEFAULT_ROOTS: std::sync::OnceLock<rustls::RootCertStore> = std::sync::OnceLock::new();
630 DEFAULT_ROOTS.get_or_init(|| {
631 let mut roots = rustls::RootCertStore::empty();
632 roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
633 let native = rustls_native_certs::load_native_certs();
634 for err in &native.errors {
635 log::warn!("failed to load native root certificate: {err}");
636 }
637 if !native.certs.is_empty() {
638 roots.add_parsable_certificates(native.certs);
639 }
640 roots
641 })
642}
643
644#[cfg(feature = "__rustls")]
649pub fn default_root_store_arc() -> Arc<rustls::RootCertStore> {
650 static DEFAULT_ROOTS_ARC: std::sync::OnceLock<Arc<rustls::RootCertStore>> =
651 std::sync::OnceLock::new();
652 DEFAULT_ROOTS_ARC
653 .get_or_init(|| Arc::new(default_root_store().clone()))
654 .clone()
655}
656
657#[cfg(feature = "__rustls")]
659pub fn merged_root_store(certs: Vec<Certificate>) -> crate::Result<RootCertStore> {
660 let mut store = default_root_store().clone();
661 for cert in certs {
662 cert.add_to_rustls(&mut store)?;
663 }
664 Ok(store)
665}
666
667#[cfg(feature = "__rustls")]
668#[derive(Debug)]
669pub(crate) struct NoVerifier;
670
671#[cfg(feature = "__rustls")]
672impl ServerCertVerifier for NoVerifier {
673 fn verify_server_cert(
674 &self,
675 _end_entity: &rustls_pki_types::CertificateDer,
676 _intermediates: &[rustls_pki_types::CertificateDer],
677 _server_name: &ServerName,
678 _ocsp_response: &[u8],
679 _now: UnixTime,
680 ) -> Result<ServerCertVerified, TLSError> {
681 Ok(ServerCertVerified::assertion())
682 }
683
684 fn verify_tls12_signature(
685 &self,
686 _message: &[u8],
687 _cert: &rustls_pki_types::CertificateDer,
688 _dss: &DigitallySignedStruct,
689 ) -> Result<HandshakeSignatureValid, TLSError> {
690 Ok(HandshakeSignatureValid::assertion())
691 }
692
693 fn verify_tls13_signature(
694 &self,
695 _message: &[u8],
696 _cert: &rustls_pki_types::CertificateDer,
697 _dss: &DigitallySignedStruct,
698 ) -> Result<HandshakeSignatureValid, TLSError> {
699 Ok(HandshakeSignatureValid::assertion())
700 }
701
702 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
703 vec![
704 SignatureScheme::RSA_PKCS1_SHA1,
705 SignatureScheme::ECDSA_SHA1_Legacy,
706 SignatureScheme::RSA_PKCS1_SHA256,
707 SignatureScheme::ECDSA_NISTP256_SHA256,
708 SignatureScheme::RSA_PKCS1_SHA384,
709 SignatureScheme::ECDSA_NISTP384_SHA384,
710 SignatureScheme::RSA_PKCS1_SHA512,
711 SignatureScheme::ECDSA_NISTP521_SHA512,
712 SignatureScheme::RSA_PSS_SHA256,
713 SignatureScheme::RSA_PSS_SHA384,
714 SignatureScheme::RSA_PSS_SHA512,
715 SignatureScheme::ED25519,
716 SignatureScheme::ED448,
717 ]
718 }
719}
720
721#[cfg(feature = "__rustls")]
722#[derive(Debug)]
723pub(crate) struct IgnoreHostname {
724 roots: RootCertStore,
725 signature_algorithms: WebPkiSupportedAlgorithms,
726}
727
728#[cfg(feature = "__rustls")]
729impl IgnoreHostname {
730 pub(crate) fn new(
731 roots: RootCertStore,
732 signature_algorithms: WebPkiSupportedAlgorithms,
733 ) -> Self {
734 Self {
735 roots,
736 signature_algorithms,
737 }
738 }
739}
740
741#[cfg(feature = "__rustls")]
742impl ServerCertVerifier for IgnoreHostname {
743 fn verify_server_cert(
744 &self,
745 end_entity: &rustls_pki_types::CertificateDer<'_>,
746 intermediates: &[rustls_pki_types::CertificateDer<'_>],
747 _server_name: &ServerName<'_>,
748 _ocsp_response: &[u8],
749 now: UnixTime,
750 ) -> Result<ServerCertVerified, TLSError> {
751 let cert = ParsedCertificate::try_from(end_entity)?;
752
753 rustls::client::verify_server_cert_signed_by_trust_anchor(
754 &cert,
755 &self.roots,
756 intermediates,
757 now,
758 self.signature_algorithms.all,
759 )?;
760 Ok(ServerCertVerified::assertion())
761 }
762
763 fn verify_tls12_signature(
764 &self,
765 message: &[u8],
766 cert: &rustls_pki_types::CertificateDer<'_>,
767 dss: &DigitallySignedStruct,
768 ) -> Result<HandshakeSignatureValid, TLSError> {
769 rustls::crypto::verify_tls12_signature(message, cert, dss, &self.signature_algorithms)
770 }
771
772 fn verify_tls13_signature(
773 &self,
774 message: &[u8],
775 cert: &rustls_pki_types::CertificateDer<'_>,
776 dss: &DigitallySignedStruct,
777 ) -> Result<HandshakeSignatureValid, TLSError> {
778 rustls::crypto::verify_tls13_signature(message, cert, dss, &self.signature_algorithms)
779 }
780
781 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
782 self.signature_algorithms.supported_schemes()
783 }
784}
785
786#[derive(Clone)]
789pub struct TlsInfo {
790 pub(crate) peer_certificate: Option<Vec<u8>>,
791}
792
793impl TlsInfo {
794 pub fn peer_certificate(&self) -> Option<&[u8]> {
796 self.peer_certificate.as_ref().map(|der| &der[..])
797 }
798}
799
800impl std::fmt::Debug for TlsInfo {
801 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
802 f.debug_struct("TlsInfo").finish()
803 }
804}
805
806#[cfg(test)]
807mod tests {
808 use super::*;
809
810 #[cfg(feature = "__native-tls")]
811 #[test]
812 fn certificate_from_der_invalid() {
813 Certificate::from_der(b"not der").unwrap_err();
814 }
815
816 #[cfg(feature = "__native-tls")]
817 #[test]
818 fn certificate_from_pem_invalid() {
819 Certificate::from_pem(b"not pem").unwrap_err();
820 }
821
822 #[cfg(feature = "__native-tls")]
823 #[test]
824 fn identity_from_pkcs12_der_invalid() {
825 Identity::from_pkcs12_der(b"not der", "nope").unwrap_err();
826 }
827
828 #[cfg(feature = "__native-tls")]
829 #[test]
830 fn identity_from_pkcs8_pem_invalid() {
831 Identity::from_pkcs8_pem(b"not pem", b"not key").unwrap_err();
832 }
833
834 #[cfg(feature = "__rustls")]
835 #[test]
836 fn identity_from_pem_invalid() {
837 Identity::from_pem(b"not pem").unwrap_err();
838 }
839
840 #[cfg(feature = "__rustls")]
841 #[test]
842 fn identity_from_pem_pkcs1_key() {
843 let pem = b"-----BEGIN CERTIFICATE-----\n\
844 -----END CERTIFICATE-----\n\
845 -----BEGIN RSA PRIVATE KEY-----\n\
846 -----END RSA PRIVATE KEY-----\n";
847
848 Identity::from_pem(pem).unwrap();
849 }
850
851 #[test]
852 fn certificates_from_pem_bundle() {
853 const PEM_BUNDLE: &[u8] = b"
854 -----BEGIN CERTIFICATE-----
855 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
856 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
857 Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
858 A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
859 Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
860 ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
861 QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
862 ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
863 BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
864 YyRIHN8wfdVoOw==
865 -----END CERTIFICATE-----
866
867 -----BEGIN CERTIFICATE-----
868 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
869 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
870 Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
871 A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
872 Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
873 9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
874 M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
875 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
876 MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
877 CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
878 1KyLa2tJElMzrdfkviT8tQp21KW8EA==
879 -----END CERTIFICATE-----
880 ";
881
882 assert!(Certificate::from_pem_bundle(PEM_BUNDLE).is_ok())
883 }
884
885 #[cfg(feature = "__rustls")]
886 #[test]
887 fn crl_from_pem() {
888 let pem = b"-----BEGIN X509 CRL-----\n-----END X509 CRL-----\n";
889
890 CertificateRevocationList::from_pem(pem).unwrap();
891 }
892
893 #[cfg(feature = "__rustls")]
894 #[test]
895 fn crl_from_pem_bundle() {
896 let pem_bundle = std::fs::read("tests/support/crl.pem").unwrap();
897
898 let result = CertificateRevocationList::from_pem_bundle(&pem_bundle);
899
900 assert!(result.is_ok());
901 let result = result.unwrap();
902 assert_eq!(result.len(), 1);
903 }
904}