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(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")]
626#[cfg(any(all(unix, not(target_os = "android")), target_os = "windows"))]
627pub(crate) fn rustls_der(
628 certs: Vec<Certificate>,
629) -> crate::Result<Vec<rustls_pki_types::CertificateDer<'static>>> {
630 let mut ders = Vec::with_capacity(certs.len());
631 for cert in certs {
632 match cert.original {
633 Cert::Der(buf) => ders.push(buf.into()),
634 Cert::Pem(buf) => {
635 let mut reader = std::io::Cursor::new(buf);
636 let pems = Certificate::read_pem_certs(&mut reader)?;
637 for c in pems {
638 ders.push(c.into());
639 }
640 }
641 }
642 }
643 Ok(ders)
644}
645
646#[cfg(feature = "__rustls")]
647#[derive(Debug)]
648pub(crate) struct NoVerifier;
649
650#[cfg(feature = "__rustls")]
651impl ServerCertVerifier for NoVerifier {
652 fn verify_server_cert(
653 &self,
654 _end_entity: &rustls_pki_types::CertificateDer,
655 _intermediates: &[rustls_pki_types::CertificateDer],
656 _server_name: &ServerName,
657 _ocsp_response: &[u8],
658 _now: UnixTime,
659 ) -> Result<ServerCertVerified, TLSError> {
660 Ok(ServerCertVerified::assertion())
661 }
662
663 fn verify_tls12_signature(
664 &self,
665 _message: &[u8],
666 _cert: &rustls_pki_types::CertificateDer,
667 _dss: &DigitallySignedStruct,
668 ) -> Result<HandshakeSignatureValid, TLSError> {
669 Ok(HandshakeSignatureValid::assertion())
670 }
671
672 fn verify_tls13_signature(
673 &self,
674 _message: &[u8],
675 _cert: &rustls_pki_types::CertificateDer,
676 _dss: &DigitallySignedStruct,
677 ) -> Result<HandshakeSignatureValid, TLSError> {
678 Ok(HandshakeSignatureValid::assertion())
679 }
680
681 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
682 vec![
683 SignatureScheme::RSA_PKCS1_SHA1,
684 SignatureScheme::ECDSA_SHA1_Legacy,
685 SignatureScheme::RSA_PKCS1_SHA256,
686 SignatureScheme::ECDSA_NISTP256_SHA256,
687 SignatureScheme::RSA_PKCS1_SHA384,
688 SignatureScheme::ECDSA_NISTP384_SHA384,
689 SignatureScheme::RSA_PKCS1_SHA512,
690 SignatureScheme::ECDSA_NISTP521_SHA512,
691 SignatureScheme::RSA_PSS_SHA256,
692 SignatureScheme::RSA_PSS_SHA384,
693 SignatureScheme::RSA_PSS_SHA512,
694 SignatureScheme::ED25519,
695 SignatureScheme::ED448,
696 ]
697 }
698}
699
700#[cfg(feature = "__rustls")]
701#[derive(Debug)]
702pub(crate) struct IgnoreHostname {
703 roots: RootCertStore,
704 signature_algorithms: WebPkiSupportedAlgorithms,
705}
706
707#[cfg(feature = "__rustls")]
708impl IgnoreHostname {
709 pub(crate) fn new(
710 roots: RootCertStore,
711 signature_algorithms: WebPkiSupportedAlgorithms,
712 ) -> Self {
713 Self {
714 roots,
715 signature_algorithms,
716 }
717 }
718}
719
720#[cfg(feature = "__rustls")]
721impl ServerCertVerifier for IgnoreHostname {
722 fn verify_server_cert(
723 &self,
724 end_entity: &rustls_pki_types::CertificateDer<'_>,
725 intermediates: &[rustls_pki_types::CertificateDer<'_>],
726 _server_name: &ServerName<'_>,
727 _ocsp_response: &[u8],
728 now: UnixTime,
729 ) -> Result<ServerCertVerified, TLSError> {
730 let cert = ParsedCertificate::try_from(end_entity)?;
731
732 rustls::client::verify_server_cert_signed_by_trust_anchor(
733 &cert,
734 &self.roots,
735 intermediates,
736 now,
737 self.signature_algorithms.all,
738 )?;
739 Ok(ServerCertVerified::assertion())
740 }
741
742 fn verify_tls12_signature(
743 &self,
744 message: &[u8],
745 cert: &rustls_pki_types::CertificateDer<'_>,
746 dss: &DigitallySignedStruct,
747 ) -> Result<HandshakeSignatureValid, TLSError> {
748 rustls::crypto::verify_tls12_signature(message, cert, dss, &self.signature_algorithms)
749 }
750
751 fn verify_tls13_signature(
752 &self,
753 message: &[u8],
754 cert: &rustls_pki_types::CertificateDer<'_>,
755 dss: &DigitallySignedStruct,
756 ) -> Result<HandshakeSignatureValid, TLSError> {
757 rustls::crypto::verify_tls13_signature(message, cert, dss, &self.signature_algorithms)
758 }
759
760 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
761 self.signature_algorithms.supported_schemes()
762 }
763}
764
765#[derive(Clone)]
768pub struct TlsInfo {
769 pub(crate) peer_certificate: Option<Vec<u8>>,
770}
771
772impl TlsInfo {
773 pub fn peer_certificate(&self) -> Option<&[u8]> {
775 self.peer_certificate.as_ref().map(|der| &der[..])
776 }
777}
778
779impl std::fmt::Debug for TlsInfo {
780 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
781 f.debug_struct("TlsInfo").finish()
782 }
783}
784
785#[cfg(test)]
786mod tests {
787 use super::*;
788
789 #[cfg(feature = "__native-tls")]
790 #[test]
791 fn certificate_from_der_invalid() {
792 Certificate::from_der(b"not der").unwrap_err();
793 }
794
795 #[cfg(feature = "__native-tls")]
796 #[test]
797 fn certificate_from_pem_invalid() {
798 Certificate::from_pem(b"not pem").unwrap_err();
799 }
800
801 #[cfg(feature = "__native-tls")]
802 #[test]
803 fn identity_from_pkcs12_der_invalid() {
804 Identity::from_pkcs12_der(b"not der", "nope").unwrap_err();
805 }
806
807 #[cfg(feature = "__native-tls")]
808 #[test]
809 fn identity_from_pkcs8_pem_invalid() {
810 Identity::from_pkcs8_pem(b"not pem", b"not key").unwrap_err();
811 }
812
813 #[cfg(feature = "__rustls")]
814 #[test]
815 fn identity_from_pem_invalid() {
816 Identity::from_pem(b"not pem").unwrap_err();
817 }
818
819 #[cfg(feature = "__rustls")]
820 #[test]
821 fn identity_from_pem_pkcs1_key() {
822 let pem = b"-----BEGIN CERTIFICATE-----\n\
823 -----END CERTIFICATE-----\n\
824 -----BEGIN RSA PRIVATE KEY-----\n\
825 -----END RSA PRIVATE KEY-----\n";
826
827 Identity::from_pem(pem).unwrap();
828 }
829
830 #[test]
831 fn certificates_from_pem_bundle() {
832 const PEM_BUNDLE: &[u8] = b"
833 -----BEGIN CERTIFICATE-----
834 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
835 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
836 Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
837 A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
838 Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
839 ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
840 QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
841 ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
842 BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
843 YyRIHN8wfdVoOw==
844 -----END CERTIFICATE-----
845
846 -----BEGIN CERTIFICATE-----
847 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
848 MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
849 Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
850 A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
851 Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
852 9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
853 M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
854 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
855 MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
856 CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
857 1KyLa2tJElMzrdfkviT8tQp21KW8EA==
858 -----END CERTIFICATE-----
859 ";
860
861 assert!(Certificate::from_pem_bundle(PEM_BUNDLE).is_ok())
862 }
863
864 #[cfg(feature = "__rustls")]
865 #[test]
866 fn crl_from_pem() {
867 let pem = b"-----BEGIN X509 CRL-----\n-----END X509 CRL-----\n";
868
869 CertificateRevocationList::from_pem(pem).unwrap();
870 }
871
872 #[cfg(feature = "__rustls")]
873 #[test]
874 fn invalid_crl_from_pem() {
875 CertificateRevocationList::from_pem(b"Invalid").unwrap_err();
876 }
877
878 #[cfg(feature = "__rustls")]
879 #[test]
880 fn crl_from_pem_bundle() {
881 let pem_bundle = std::fs::read("tests/support/crl.pem").unwrap();
882
883 let result = CertificateRevocationList::from_pem_bundle(&pem_bundle);
884
885 assert!(result.is_ok());
886 let result = result.unwrap();
887 assert_eq!(result.len(), 1);
888 }
889}