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