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.to_vec()),
457 })
458 }
459
460 #[cfg(feature = "__rustls")]
482 pub fn from_pem_bundle(pem_bundle: &[u8]) -> crate::Result<Vec<CertificateRevocationList>> {
483 rustls_pki_types::CertificateRevocationListDer::pem_slice_iter(pem_bundle)
484 .map(|result| match result {
485 Ok(crl) => Ok(CertificateRevocationList { inner: crl }),
486 Err(_) => Err(crate::error::builder("invalid crl encoding")),
487 })
488 .collect::<crate::Result<Vec<CertificateRevocationList>>>()
489 }
490
491 #[cfg(feature = "__rustls")]
492 pub(crate) fn as_rustls_crl<'a>(&self) -> rustls_pki_types::CertificateRevocationListDer<'a> {
493 self.inner.clone()
494 }
495}
496
497impl fmt::Debug for Certificate {
498 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
499 f.debug_struct("Certificate").finish()
500 }
501}
502
503impl fmt::Debug for Identity {
504 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
505 f.debug_struct("Identity").finish()
506 }
507}
508
509#[cfg(feature = "__rustls")]
510impl fmt::Debug for CertificateRevocationList {
511 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
512 f.debug_struct("CertificateRevocationList").finish()
513 }
514}
515
516#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
518pub struct Version(InnerVersion);
519
520#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
521#[non_exhaustive]
522enum InnerVersion {
523 Tls1_0,
524 Tls1_1,
525 Tls1_2,
526 Tls1_3,
527}
528
529impl Version {
532 pub const TLS_1_0: Version = Version(InnerVersion::Tls1_0);
534 pub const TLS_1_1: Version = Version(InnerVersion::Tls1_1);
536 pub const TLS_1_2: Version = Version(InnerVersion::Tls1_2);
538 pub const TLS_1_3: Version = Version(InnerVersion::Tls1_3);
540
541 #[cfg(feature = "__native-tls")]
542 pub(crate) fn to_native_tls(self) -> Option<native_tls_crate::Protocol> {
543 match self.0 {
544 InnerVersion::Tls1_0 => Some(native_tls_crate::Protocol::Tlsv10),
545 InnerVersion::Tls1_1 => Some(native_tls_crate::Protocol::Tlsv11),
546 InnerVersion::Tls1_2 => Some(native_tls_crate::Protocol::Tlsv12),
547 InnerVersion::Tls1_3 => None,
548 }
549 }
550
551 #[cfg(feature = "__rustls")]
552 pub(crate) fn from_rustls(version: rustls::ProtocolVersion) -> Option<Self> {
553 match version {
554 rustls::ProtocolVersion::SSLv2 => None,
555 rustls::ProtocolVersion::SSLv3 => None,
556 rustls::ProtocolVersion::TLSv1_0 => Some(Self(InnerVersion::Tls1_0)),
557 rustls::ProtocolVersion::TLSv1_1 => Some(Self(InnerVersion::Tls1_1)),
558 rustls::ProtocolVersion::TLSv1_2 => Some(Self(InnerVersion::Tls1_2)),
559 rustls::ProtocolVersion::TLSv1_3 => Some(Self(InnerVersion::Tls1_3)),
560 _ => None,
561 }
562 }
563}
564
565pub(crate) enum TlsBackend {
566 #[allow(dead_code)]
568 #[cfg(feature = "__native-tls")]
569 NativeTls,
570 #[cfg(feature = "__native-tls")]
571 BuiltNativeTls(native_tls_crate::TlsConnector),
572 #[cfg(feature = "__rustls")]
573 Rustls,
574 #[cfg(feature = "__rustls")]
575 BuiltRustls(rustls::ClientConfig),
576 #[cfg(any(feature = "__native-tls", feature = "__rustls",))]
577 UnknownPreconfigured,
578}
579
580impl fmt::Debug for TlsBackend {
581 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
582 match self {
583 #[cfg(feature = "__native-tls")]
584 TlsBackend::NativeTls => write!(f, "NativeTls"),
585 #[cfg(feature = "__native-tls")]
586 TlsBackend::BuiltNativeTls(_) => write!(f, "BuiltNativeTls"),
587 #[cfg(feature = "__rustls")]
588 TlsBackend::Rustls => write!(f, "Rustls"),
589 #[cfg(feature = "__rustls")]
590 TlsBackend::BuiltRustls(_) => write!(f, "BuiltRustls"),
591 #[cfg(any(feature = "__native-tls", feature = "__rustls",))]
592 TlsBackend::UnknownPreconfigured => write!(f, "UnknownPreconfigured"),
593 }
594 }
595}
596
597#[allow(clippy::derivable_impls)]
598impl Default for TlsBackend {
599 fn default() -> TlsBackend {
600 #[cfg(any(
601 all(feature = "__rustls", not(feature = "__native-tls")),
602 feature = "http3"
603 ))]
604 {
605 TlsBackend::Rustls
606 }
607
608 #[cfg(all(feature = "__native-tls", not(feature = "http3")))]
609 {
610 TlsBackend::NativeTls
611 }
612 }
613}
614
615#[cfg(feature = "__rustls")]
616pub(crate) fn rustls_store(certs: Vec<Certificate>) -> crate::Result<RootCertStore> {
617 let mut root_cert_store = rustls::RootCertStore::empty();
618 for cert in certs {
619 cert.add_to_rustls(&mut root_cert_store)?;
620 }
621 Ok(root_cert_store)
622}
623
624#[cfg(feature = "__rustls")]
625#[cfg(any(all(unix, not(target_os = "android")), target_os = "windows"))]
626pub(crate) fn rustls_der(
627 certs: Vec<Certificate>,
628) -> crate::Result<Vec<rustls_pki_types::CertificateDer<'static>>> {
629 let mut ders = Vec::with_capacity(certs.len());
630 for cert in certs {
631 match cert.original {
632 Cert::Der(buf) => ders.push(buf.into()),
633 Cert::Pem(buf) => {
634 let mut reader = std::io::Cursor::new(buf);
635 let pems = Certificate::read_pem_certs(&mut reader)?;
636 for c in pems {
637 ders.push(c.into());
638 }
639 }
640 }
641 }
642 Ok(ders)
643}
644
645#[cfg(feature = "__rustls")]
646#[derive(Debug)]
647pub(crate) struct NoVerifier;
648
649#[cfg(feature = "__rustls")]
650impl ServerCertVerifier for NoVerifier {
651 fn verify_server_cert(
652 &self,
653 _end_entity: &rustls_pki_types::CertificateDer,
654 _intermediates: &[rustls_pki_types::CertificateDer],
655 _server_name: &ServerName,
656 _ocsp_response: &[u8],
657 _now: UnixTime,
658 ) -> Result<ServerCertVerified, TLSError> {
659 Ok(ServerCertVerified::assertion())
660 }
661
662 fn verify_tls12_signature(
663 &self,
664 _message: &[u8],
665 _cert: &rustls_pki_types::CertificateDer,
666 _dss: &DigitallySignedStruct,
667 ) -> Result<HandshakeSignatureValid, TLSError> {
668 Ok(HandshakeSignatureValid::assertion())
669 }
670
671 fn verify_tls13_signature(
672 &self,
673 _message: &[u8],
674 _cert: &rustls_pki_types::CertificateDer,
675 _dss: &DigitallySignedStruct,
676 ) -> Result<HandshakeSignatureValid, TLSError> {
677 Ok(HandshakeSignatureValid::assertion())
678 }
679
680 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
681 vec![
682 SignatureScheme::RSA_PKCS1_SHA1,
683 SignatureScheme::ECDSA_SHA1_Legacy,
684 SignatureScheme::RSA_PKCS1_SHA256,
685 SignatureScheme::ECDSA_NISTP256_SHA256,
686 SignatureScheme::RSA_PKCS1_SHA384,
687 SignatureScheme::ECDSA_NISTP384_SHA384,
688 SignatureScheme::RSA_PKCS1_SHA512,
689 SignatureScheme::ECDSA_NISTP521_SHA512,
690 SignatureScheme::RSA_PSS_SHA256,
691 SignatureScheme::RSA_PSS_SHA384,
692 SignatureScheme::RSA_PSS_SHA512,
693 SignatureScheme::ED25519,
694 SignatureScheme::ED448,
695 ]
696 }
697}
698
699#[cfg(feature = "__rustls")]
700#[derive(Debug)]
701pub(crate) struct IgnoreHostname {
702 roots: RootCertStore,
703 signature_algorithms: WebPkiSupportedAlgorithms,
704}
705
706#[cfg(feature = "__rustls")]
707impl IgnoreHostname {
708 pub(crate) fn new(
709 roots: RootCertStore,
710 signature_algorithms: WebPkiSupportedAlgorithms,
711 ) -> Self {
712 Self {
713 roots,
714 signature_algorithms,
715 }
716 }
717}
718
719#[cfg(feature = "__rustls")]
720impl ServerCertVerifier for IgnoreHostname {
721 fn verify_server_cert(
722 &self,
723 end_entity: &rustls_pki_types::CertificateDer<'_>,
724 intermediates: &[rustls_pki_types::CertificateDer<'_>],
725 _server_name: &ServerName<'_>,
726 _ocsp_response: &[u8],
727 now: UnixTime,
728 ) -> Result<ServerCertVerified, TLSError> {
729 let cert = ParsedCertificate::try_from(end_entity)?;
730
731 rustls::client::verify_server_cert_signed_by_trust_anchor(
732 &cert,
733 &self.roots,
734 intermediates,
735 now,
736 self.signature_algorithms.all,
737 )?;
738 Ok(ServerCertVerified::assertion())
739 }
740
741 fn verify_tls12_signature(
742 &self,
743 message: &[u8],
744 cert: &rustls_pki_types::CertificateDer<'_>,
745 dss: &DigitallySignedStruct,
746 ) -> Result<HandshakeSignatureValid, TLSError> {
747 rustls::crypto::verify_tls12_signature(message, cert, dss, &self.signature_algorithms)
748 }
749
750 fn verify_tls13_signature(
751 &self,
752 message: &[u8],
753 cert: &rustls_pki_types::CertificateDer<'_>,
754 dss: &DigitallySignedStruct,
755 ) -> Result<HandshakeSignatureValid, TLSError> {
756 rustls::crypto::verify_tls13_signature(message, cert, dss, &self.signature_algorithms)
757 }
758
759 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
760 self.signature_algorithms.supported_schemes()
761 }
762}
763
764#[derive(Clone)]
767pub struct TlsInfo {
768 pub(crate) peer_certificate: Option<Vec<u8>>,
769}
770
771impl TlsInfo {
772 pub fn peer_certificate(&self) -> Option<&[u8]> {
774 self.peer_certificate.as_ref().map(|der| &der[..])
775 }
776}
777
778impl std::fmt::Debug for TlsInfo {
779 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
780 f.debug_struct("TlsInfo").finish()
781 }
782}
783
784#[cfg(test)]
785mod tests {
786 use super::*;
787
788 #[cfg(feature = "__native-tls")]
789 #[test]
790 fn certificate_from_der_invalid() {
791 Certificate::from_der(b"not der").unwrap_err();
792 }
793
794 #[cfg(feature = "__native-tls")]
795 #[test]
796 fn certificate_from_pem_invalid() {
797 Certificate::from_pem(b"not pem").unwrap_err();
798 }
799
800 #[cfg(feature = "__native-tls")]
801 #[test]
802 fn identity_from_pkcs12_der_invalid() {
803 Identity::from_pkcs12_der(b"not der", "nope").unwrap_err();
804 }
805
806 #[cfg(feature = "__native-tls")]
807 #[test]
808 fn identity_from_pkcs8_pem_invalid() {
809 Identity::from_pkcs8_pem(b"not pem", b"not key").unwrap_err();
810 }
811
812 #[cfg(feature = "__rustls")]
813 #[test]
814 fn identity_from_pem_invalid() {
815 Identity::from_pem(b"not pem").unwrap_err();
816 }
817
818 #[cfg(feature = "__rustls")]
819 #[test]
820 fn identity_from_pem_pkcs1_key() {
821 let pem = b"-----BEGIN CERTIFICATE-----\n\
822 -----END CERTIFICATE-----\n\
823 -----BEGIN RSA PRIVATE KEY-----\n\
824 -----END RSA PRIVATE KEY-----\n";
825
826 Identity::from_pem(pem).unwrap();
827 }
828
829 #[test]
830 fn certificates_from_pem_bundle() {
831 const PEM_BUNDLE: &[u8] = b"
832 -----BEGIN CERTIFICATE-----
833 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
834 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
835 Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
836 A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
837 Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
838 ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
839 QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
840 ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
841 BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
842 YyRIHN8wfdVoOw==
843 -----END CERTIFICATE-----
844
845 -----BEGIN CERTIFICATE-----
846 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
847 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
848 Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
849 A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
850 Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
851 9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
852 M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
853 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
854 MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
855 CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
856 1KyLa2tJElMzrdfkviT8tQp21KW8EA==
857 -----END CERTIFICATE-----
858 ";
859
860 assert!(Certificate::from_pem_bundle(PEM_BUNDLE).is_ok())
861 }
862
863 #[cfg(feature = "__rustls")]
864 #[test]
865 fn crl_from_pem() {
866 let pem = b"-----BEGIN X509 CRL-----\n-----END X509 CRL-----\n";
867
868 CertificateRevocationList::from_pem(pem).unwrap();
869 }
870
871 #[cfg(feature = "__rustls")]
872 #[test]
873 fn crl_from_pem_bundle() {
874 let pem_bundle = std::fs::read("tests/support/crl.pem").unwrap();
875
876 let result = CertificateRevocationList::from_pem_bundle(&pem_bundle);
877
878 assert!(result.is_ok());
879 let result = result.unwrap();
880 assert_eq!(result.len(), 1);
881 }
882}