1use crate::cipher_ctx::CipherCtxRef;
61#[cfg(ossl300)]
62use crate::cvt_long;
63use crate::dh::{Dh, DhRef};
64use crate::ec::EcKeyRef;
65use crate::error::ErrorStack;
66use crate::ex_data::Index;
67#[cfg(ossl111)]
68use crate::hash::MessageDigest;
69use crate::hmac::HMacCtxRef;
70#[cfg(ossl300)]
71use crate::mac_ctx::MacCtxRef;
72#[cfg(any(ossl110, libressl))]
73use crate::nid::Nid;
74use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
75#[cfg(ossl300)]
76use crate::pkey::{PKey, Public};
77#[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
78use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
79use crate::ssl::bio::BioMethod;
80use crate::ssl::callbacks::*;
81use crate::ssl::error::InnerError;
82use crate::stack::{Stack, StackRef, Stackable};
83use crate::util;
84use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
85use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
86use crate::x509::verify::X509VerifyParamRef;
87use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
88use crate::{cvt, cvt_n, cvt_p, init};
89use bitflags::bitflags;
90use cfg_if::cfg_if;
91use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
92use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
93use openssl_macros::corresponds;
94use std::any::TypeId;
95use std::collections::HashMap;
96use std::ffi::{CStr, CString};
97use std::fmt;
98use std::io;
99use std::io::prelude::*;
100use std::marker::PhantomData;
101use std::mem::{self, ManuallyDrop, MaybeUninit};
102use std::ops::{Deref, DerefMut};
103use std::panic::resume_unwind;
104use std::path::Path;
105use std::ptr;
106use std::str;
107use std::sync::{Arc, LazyLock, Mutex, OnceLock};
108
109pub use crate::ssl::connector::{
110 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
111};
112pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
113
114mod bio;
115mod callbacks;
116#[cfg(any(boringssl, awslc))]
117mod client_hello;
118mod connector;
119mod error;
120#[cfg(test)]
121mod test;
122
123#[cfg(any(boringssl, awslc))]
124pub use client_hello::ClientHello;
125
126#[corresponds(OPENSSL_cipher_name)]
132#[cfg(ossl111)]
133pub fn cipher_name(std_name: &str) -> &'static str {
134 unsafe {
135 ffi::init();
136
137 let s = CString::new(std_name).unwrap();
138 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
139 CStr::from_ptr(ptr).to_str().unwrap()
140 }
141}
142
143cfg_if! {
144 if #[cfg(ossl300)] {
145 type SslOptionsRepr = u64;
146 } else if #[cfg(any(boringssl, awslc))] {
147 type SslOptionsRepr = u32;
148 } else {
149 type SslOptionsRepr = libc::c_ulong;
150 }
151}
152
153bitflags! {
154 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
156 #[repr(transparent)]
157 pub struct SslOptions: SslOptionsRepr {
158 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
160
161 #[cfg(ossl300)]
164 const IGNORE_UNEXPECTED_EOF = ffi::SSL_OP_IGNORE_UNEXPECTED_EOF as SslOptionsRepr;
165
166 #[cfg(not(any(boringssl, awslc)))]
168 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
169
170 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
174
175 #[cfg(not(any(boringssl, awslc)))]
181 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
182
183 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
185
186 #[cfg(not(any(boringssl, awslc)))]
188 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
189 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
190
191 #[cfg(not(any(boringssl, awslc)))]
193 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
194
195 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
198 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
199
200 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
204
205 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
209
210 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
214
215 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
217
218 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
220
221 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
223
224 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
226
227 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
229
230 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
232
233 #[cfg(any(ossl111, boringssl, libressl, awslc))]
237 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
238
239 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
241
242 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
244
245 #[cfg(ossl110)]
261 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
262
263 #[cfg(any(boringssl, ossl110h, awslc))]
267 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
268
269 #[cfg(ossl111)]
274 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
275
276 #[cfg(ossl111)]
288 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
289 }
290}
291
292bitflags! {
293 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
295 #[repr(transparent)]
296 pub struct SslMode: SslBitType {
297 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
303
304 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
307
308 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
318
319 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
325
326 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
330
331 #[cfg(not(libressl))]
339 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
340
341 #[cfg(ossl110)]
348 const ASYNC = ffi::SSL_MODE_ASYNC;
349 }
350}
351
352#[derive(Copy, Clone)]
354pub struct SslMethod(*const ffi::SSL_METHOD);
355
356impl SslMethod {
357 #[corresponds(TLS_method)]
359 pub fn tls() -> SslMethod {
360 unsafe { SslMethod(TLS_method()) }
361 }
362
363 #[corresponds(DTLS_method)]
365 pub fn dtls() -> SslMethod {
366 unsafe { SslMethod(DTLS_method()) }
367 }
368
369 #[corresponds(TLS_client_method)]
371 pub fn tls_client() -> SslMethod {
372 unsafe { SslMethod(TLS_client_method()) }
373 }
374
375 #[corresponds(TLS_server_method)]
377 pub fn tls_server() -> SslMethod {
378 unsafe { SslMethod(TLS_server_method()) }
379 }
380
381 #[cfg(tongsuo)]
382 #[corresponds(NTLS_client_method)]
383 pub fn ntls_client() -> SslMethod {
384 unsafe { SslMethod(ffi::NTLS_client_method()) }
385 }
386
387 #[cfg(tongsuo)]
388 #[corresponds(NTLS_server_method)]
389 pub fn ntls_server() -> SslMethod {
390 unsafe { SslMethod(ffi::NTLS_server_method()) }
391 }
392
393 #[corresponds(DTLS_client_method)]
395 pub fn dtls_client() -> SslMethod {
396 unsafe { SslMethod(DTLS_client_method()) }
397 }
398
399 #[corresponds(DTLS_server_method)]
401 pub fn dtls_server() -> SslMethod {
402 unsafe { SslMethod(DTLS_server_method()) }
403 }
404
405 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
411 SslMethod(ptr)
412 }
413
414 #[allow(clippy::trivially_copy_pass_by_ref)]
416 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
417 self.0
418 }
419}
420
421unsafe impl Sync for SslMethod {}
422unsafe impl Send for SslMethod {}
423
424bitflags! {
425 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
427 #[repr(transparent)]
428 pub struct SslVerifyMode: i32 {
429 const PEER = ffi::SSL_VERIFY_PEER;
433
434 const NONE = ffi::SSL_VERIFY_NONE;
440
441 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
445
446 #[cfg(not(any(boringssl, awslc)))]
451 const CLIENT_ONCE = ffi::SSL_VERIFY_CLIENT_ONCE;
452
453 #[cfg(ossl111)]
460 const POST_HANDSHAKE = ffi::SSL_VERIFY_POST_HANDSHAKE;
461 }
462}
463
464#[cfg(any(boringssl, awslc))]
465type SslBitType = c_int;
466#[cfg(not(any(boringssl, awslc)))]
467type SslBitType = c_long;
468
469#[cfg(any(boringssl, awslc))]
470type SslTimeTy = u64;
471#[cfg(not(any(boringssl, awslc)))]
472type SslTimeTy = c_long;
473
474bitflags! {
475 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
477 #[repr(transparent)]
478 pub struct SslSessionCacheMode: SslBitType {
479 const OFF = ffi::SSL_SESS_CACHE_OFF;
481
482 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
489
490 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
494
495 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
497
498 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
500
501 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
503
504 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
506
507 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
509 }
510}
511
512#[cfg(ossl111)]
513bitflags! {
514 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
516 #[repr(transparent)]
517 pub struct ExtensionContext: c_uint {
518 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
520 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
522 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
524 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
526 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
528 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
530 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
532 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
533 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
535 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
536 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
537 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
538 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
539 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
540 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
541 }
542}
543
544#[derive(Copy, Clone)]
546pub struct TlsExtType(c_uint);
547
548impl TlsExtType {
549 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
553
554 pub const ALPN: TlsExtType =
558 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
559
560 pub fn from_raw(raw: c_uint) -> TlsExtType {
562 TlsExtType(raw)
563 }
564
565 #[allow(clippy::trivially_copy_pass_by_ref)]
567 pub fn as_raw(&self) -> c_uint {
568 self.0
569 }
570}
571
572#[derive(Copy, Clone)]
574pub struct SslFiletype(c_int);
575
576impl SslFiletype {
577 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
581
582 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
586
587 pub fn from_raw(raw: c_int) -> SslFiletype {
589 SslFiletype(raw)
590 }
591
592 #[allow(clippy::trivially_copy_pass_by_ref)]
594 pub fn as_raw(&self) -> c_int {
595 self.0
596 }
597}
598
599#[derive(Copy, Clone)]
601pub struct StatusType(c_int);
602
603impl StatusType {
604 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
606
607 pub fn from_raw(raw: c_int) -> StatusType {
609 StatusType(raw)
610 }
611
612 #[allow(clippy::trivially_copy_pass_by_ref)]
614 pub fn as_raw(&self) -> c_int {
615 self.0
616 }
617}
618
619#[derive(Copy, Clone)]
621pub struct NameType(c_int);
622
623impl NameType {
624 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
626
627 pub fn from_raw(raw: c_int) -> StatusType {
629 StatusType(raw)
630 }
631
632 #[allow(clippy::trivially_copy_pass_by_ref)]
634 pub fn as_raw(&self) -> c_int {
635 self.0
636 }
637}
638
639static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
640 LazyLock::new(|| Mutex::new(HashMap::new()));
641static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
642 LazyLock::new(|| Mutex::new(HashMap::new()));
643static SESSION_CTX_INDEX: OnceLock<Index<Ssl, SslContext>> = OnceLock::new();
644
645fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
646 if let Some(idx) = SESSION_CTX_INDEX.get() {
649 return Ok(idx);
650 }
651 let new = Ssl::new_ex_index::<SslContext>()?;
652 Ok(SESSION_CTX_INDEX.get_or_init(|| new))
653}
654
655unsafe extern "C" fn free_data_box<T>(
656 _parent: *mut c_void,
657 ptr: *mut c_void,
658 _ad: *mut ffi::CRYPTO_EX_DATA,
659 _idx: c_int,
660 _argl: c_long,
661 _argp: *mut c_void,
662) {
663 if !ptr.is_null() {
664 let _ = Box::<T>::from_raw(ptr as *mut T);
665 }
666}
667
668#[derive(Debug, Copy, Clone, PartialEq, Eq)]
670pub struct SniError(c_int);
671
672impl SniError {
673 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
675
676 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
678
679 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
680}
681
682#[derive(Debug, Copy, Clone, PartialEq, Eq)]
684pub struct SslAlert(c_int);
685
686impl SslAlert {
687 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
689 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
690 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
691 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
692}
693
694#[derive(Debug, Copy, Clone, PartialEq, Eq)]
698pub struct AlpnError(c_int);
699
700impl AlpnError {
701 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
703
704 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
706}
707
708#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
712#[derive(Debug, Copy, Clone, PartialEq, Eq)]
713pub struct ClientHelloError(c_int);
714
715#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
716impl ClientHelloError {
717 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
719
720 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
722}
723
724#[derive(Debug, Copy, Clone, PartialEq, Eq)]
726pub struct TicketKeyStatus(c_int);
727
728impl TicketKeyStatus {
729 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
731 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
733 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
735}
736
737#[derive(Debug, Copy, Clone, PartialEq, Eq)]
739#[cfg(any(boringssl, awslc))]
740pub struct SelectCertError(ffi::ssl_select_cert_result_t);
741
742#[cfg(any(boringssl, awslc))]
743impl SelectCertError {
744 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
746
747 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
749
750 #[cfg(boringssl)]
756 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
757}
758
759#[cfg(ossl111)]
761#[derive(Debug, Copy, Clone, PartialEq, Eq)]
762pub struct SslCtValidationMode(c_int);
763
764#[cfg(ossl111)]
765impl SslCtValidationMode {
766 pub const PERMISSIVE: SslCtValidationMode =
767 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
768 pub const STRICT: SslCtValidationMode =
769 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
770}
771
772#[derive(Debug, Copy, Clone, PartialEq, Eq)]
774pub struct CertCompressionAlgorithm(c_int);
775
776impl CertCompressionAlgorithm {
777 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
778 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
779 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
780}
781
782#[derive(Debug, Copy, Clone, PartialEq, Eq)]
784pub struct SslVersion(c_int);
785
786impl SslVersion {
787 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
789
790 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
792
793 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
795
796 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
798
799 #[cfg(any(ossl111, libressl, boringssl, awslc))]
803 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
804
805 #[cfg(tongsuo)]
806 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
807
808 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
812
813 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
817}
818
819cfg_if! {
820 if #[cfg(any(boringssl, awslc))] {
821 type SslCacheTy = i64;
822 type SslCacheSize = libc::c_ulong;
823 type MtuTy = u32;
824 type ModeTy = u32;
825 type SizeTy = usize;
826 } else {
827 type SslCacheTy = i64;
828 type SslCacheSize = c_long;
829 type MtuTy = c_long;
830 type ModeTy = c_long;
831 type SizeTy = u32;
832 }
833}
834
835#[corresponds(SSL_select_next_proto)]
846pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
847 unsafe {
848 let mut out = ptr::null_mut();
849 let mut outlen = 0;
850 let r = ffi::SSL_select_next_proto(
851 &mut out,
852 &mut outlen,
853 server.as_ptr(),
854 server.len() as c_uint,
855 client.as_ptr(),
856 client.len() as c_uint,
857 );
858 if r == ffi::OPENSSL_NPN_NEGOTIATED {
859 Some(util::from_raw_parts(out as *const u8, outlen as usize))
860 } else {
861 None
862 }
863 }
864}
865
866pub struct SslContextBuilder(SslContext);
868
869impl SslContextBuilder {
870 #[corresponds(SSL_CTX_new)]
872 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
873 unsafe {
874 init();
875 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
876
877 Ok(SslContextBuilder::from_ptr(ctx))
878 }
879 }
880
881 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
887 SslContextBuilder(SslContext::from_ptr(ctx))
888 }
889
890 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
892 self.0.as_ptr()
893 }
894
895 #[cfg(tongsuo)]
896 #[corresponds(SSL_CTX_enable_ntls)]
897 pub fn enable_ntls(&mut self) {
898 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
899 }
900
901 #[cfg(tongsuo)]
902 #[corresponds(SSL_CTX_disable_ntls)]
903 pub fn disable_ntls(&mut self) {
904 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
905 }
906
907 #[cfg(all(tongsuo, ossl300))]
908 #[corresponds(SSL_CTX_enable_force_ntls)]
909 pub fn enable_force_ntls(&mut self) {
910 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
911 }
912
913 #[cfg(all(tongsuo, ossl300))]
914 #[corresponds(SSL_CTX_disable_force_ntls)]
915 pub fn disable_force_ntls(&mut self) {
916 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
917 }
918
919 #[cfg(tongsuo)]
920 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
921 pub fn enable_sm_tls13_strict(&mut self) {
922 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
923 }
924
925 #[cfg(tongsuo)]
926 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
927 pub fn disable_sm_tls13_strict(&mut self) {
928 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
929 }
930
931 #[corresponds(SSL_CTX_set_verify)]
933 pub fn set_verify(&mut self, mode: SslVerifyMode) {
934 unsafe {
935 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
936 }
937 }
938
939 #[corresponds(SSL_CTX_set_verify)]
946 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
947 where
948 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
949 {
950 unsafe {
951 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
952 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
953 }
954 }
955
956 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
964 pub fn set_servername_callback<F>(&mut self, callback: F)
966 where
967 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
968 {
969 unsafe {
970 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
976 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
977 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
978 }
979 }
980
981 #[corresponds(SSL_CTX_set_verify_depth)]
985 pub fn set_verify_depth(&mut self, depth: u32) {
986 unsafe {
987 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
988 }
989 }
990
991 #[corresponds(SSL_CTX_set0_verify_cert_store)]
995 #[cfg(any(ossl110, boringssl, awslc))]
996 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
997 unsafe {
998 let ptr = cert_store.as_ptr();
999 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
1000 mem::forget(cert_store);
1001
1002 Ok(())
1003 }
1004 }
1005
1006 #[corresponds(SSL_CTX_set_cert_store)]
1008 pub fn set_cert_store(&mut self, cert_store: X509Store) {
1009 unsafe {
1010 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
1011 mem::forget(cert_store);
1012 }
1013 }
1014
1015 #[corresponds(SSL_CTX_set_read_ahead)]
1022 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1023 unsafe {
1024 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1025 }
1026 }
1027
1028 #[corresponds(SSL_CTX_set_mode)]
1032 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1033 unsafe {
1034 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1035 SslMode::from_bits_retain(bits)
1036 }
1037 }
1038
1039 #[corresponds(SSL_CTX_clear_mode)]
1041 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1042 unsafe {
1043 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1044 SslMode::from_bits_retain(bits)
1045 }
1046 }
1047
1048 #[corresponds(SSL_CTX_get_mode)]
1050 pub fn mode(&self) -> SslMode {
1051 unsafe {
1052 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1053 SslMode::from_bits_retain(bits)
1054 }
1055 }
1056
1057 #[corresponds(SSL_CTX_set_dh_auto)]
1066 #[cfg(ossl300)]
1067 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1068 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
1069 }
1070
1071 #[corresponds(SSL_CTX_set_tmp_dh)]
1073 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1074 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1075 }
1076
1077 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1084 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1085 where
1086 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1087 {
1088 unsafe {
1089 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1090
1091 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1092 }
1093 }
1094
1095 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1097 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1098 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1099 }
1100
1101 #[corresponds(SSL_CTX_set_default_verify_paths)]
1106 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1107 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1108 }
1109
1110 #[corresponds(SSL_CTX_load_verify_locations)]
1114 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1115 self.load_verify_locations(Some(file.as_ref()), None)
1116 }
1117
1118 #[corresponds(SSL_CTX_load_verify_locations)]
1120 pub fn load_verify_locations(
1121 &mut self,
1122 ca_file: Option<&Path>,
1123 ca_path: Option<&Path>,
1124 ) -> Result<(), ErrorStack> {
1125 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1126 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1127 unsafe {
1128 cvt(ffi::SSL_CTX_load_verify_locations(
1129 self.as_ptr(),
1130 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1131 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1132 ))
1133 .map(|_| ())
1134 }
1135 }
1136
1137 #[corresponds(SSL_CTX_set_client_CA_list)]
1142 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1143 unsafe {
1144 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1145 mem::forget(list);
1146 }
1147 }
1148
1149 #[corresponds(SSL_CTX_add_client_CA)]
1152 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1153 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1154 }
1155
1156 #[corresponds(SSL_CTX_set_session_id_context)]
1165 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1166 unsafe {
1167 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1168 cvt(ffi::SSL_CTX_set_session_id_context(
1169 self.as_ptr(),
1170 sid_ctx.as_ptr(),
1171 sid_ctx.len() as SizeTy,
1172 ))
1173 .map(|_| ())
1174 }
1175 }
1176
1177 #[corresponds(SSL_CTX_use_certificate_file)]
1183 pub fn set_certificate_file<P: AsRef<Path>>(
1184 &mut self,
1185 file: P,
1186 file_type: SslFiletype,
1187 ) -> Result<(), ErrorStack> {
1188 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1189 unsafe {
1190 cvt(ffi::SSL_CTX_use_certificate_file(
1191 self.as_ptr(),
1192 file.as_ptr() as *const _,
1193 file_type.as_raw(),
1194 ))
1195 .map(|_| ())
1196 }
1197 }
1198
1199 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1205 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1206 &mut self,
1207 file: P,
1208 ) -> Result<(), ErrorStack> {
1209 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1210 unsafe {
1211 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1212 self.as_ptr(),
1213 file.as_ptr() as *const _,
1214 ))
1215 .map(|_| ())
1216 }
1217 }
1218
1219 #[corresponds(SSL_CTX_use_certificate)]
1223 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1224 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1225 }
1226
1227 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1232 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1233 unsafe {
1234 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1235 mem::forget(cert);
1236 Ok(())
1237 }
1238 }
1239
1240 #[cfg(tongsuo)]
1241 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1242 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1243 &mut self,
1244 file: P,
1245 file_type: SslFiletype,
1246 ) -> Result<(), ErrorStack> {
1247 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1248 unsafe {
1249 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1250 self.as_ptr(),
1251 file.as_ptr() as *const _,
1252 file_type.as_raw(),
1253 ))
1254 .map(|_| ())
1255 }
1256 }
1257
1258 #[cfg(tongsuo)]
1259 #[corresponds(SSL_CTX_use_enc_certificate)]
1260 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1261 unsafe {
1262 cvt(ffi::SSL_CTX_use_enc_certificate(
1263 self.as_ptr(),
1264 cert.as_ptr(),
1265 ))
1266 .map(|_| ())
1267 }
1268 }
1269
1270 #[cfg(tongsuo)]
1271 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1272 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1273 &mut self,
1274 file: P,
1275 file_type: SslFiletype,
1276 ) -> Result<(), ErrorStack> {
1277 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1278 unsafe {
1279 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1280 self.as_ptr(),
1281 file.as_ptr() as *const _,
1282 file_type.as_raw(),
1283 ))
1284 .map(|_| ())
1285 }
1286 }
1287
1288 #[cfg(tongsuo)]
1289 #[corresponds(SSL_CTX_use_sign_certificate)]
1290 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1291 unsafe {
1292 cvt(ffi::SSL_CTX_use_sign_certificate(
1293 self.as_ptr(),
1294 cert.as_ptr(),
1295 ))
1296 .map(|_| ())
1297 }
1298 }
1299
1300 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1302 pub fn set_private_key_file<P: AsRef<Path>>(
1303 &mut self,
1304 file: P,
1305 file_type: SslFiletype,
1306 ) -> Result<(), ErrorStack> {
1307 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1308 unsafe {
1309 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1310 self.as_ptr(),
1311 file.as_ptr() as *const _,
1312 file_type.as_raw(),
1313 ))
1314 .map(|_| ())
1315 }
1316 }
1317
1318 #[corresponds(SSL_CTX_use_PrivateKey)]
1320 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1321 where
1322 T: HasPrivate,
1323 {
1324 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1325 }
1326
1327 #[cfg(tongsuo)]
1328 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1329 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1330 &mut self,
1331 file: P,
1332 file_type: SslFiletype,
1333 ) -> Result<(), ErrorStack> {
1334 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1335 unsafe {
1336 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1337 self.as_ptr(),
1338 file.as_ptr() as *const _,
1339 file_type.as_raw(),
1340 ))
1341 .map(|_| ())
1342 }
1343 }
1344
1345 #[cfg(tongsuo)]
1346 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1347 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1348 where
1349 T: HasPrivate,
1350 {
1351 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1352 }
1353
1354 #[cfg(tongsuo)]
1355 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1356 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1357 &mut self,
1358 file: P,
1359 file_type: SslFiletype,
1360 ) -> Result<(), ErrorStack> {
1361 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1362 unsafe {
1363 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1364 self.as_ptr(),
1365 file.as_ptr() as *const _,
1366 file_type.as_raw(),
1367 ))
1368 .map(|_| ())
1369 }
1370 }
1371
1372 #[cfg(tongsuo)]
1373 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1374 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1375 where
1376 T: HasPrivate,
1377 {
1378 unsafe {
1379 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1380 self.as_ptr(),
1381 key.as_ptr(),
1382 ))
1383 .map(|_| ())
1384 }
1385 }
1386
1387 #[corresponds(SSL_CTX_set_cipher_list)]
1395 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1396 let cipher_list = CString::new(cipher_list).unwrap();
1397 unsafe {
1398 cvt(ffi::SSL_CTX_set_cipher_list(
1399 self.as_ptr(),
1400 cipher_list.as_ptr() as *const _,
1401 ))
1402 .map(|_| ())
1403 }
1404 }
1405
1406 #[corresponds(SSL_CTX_set_ciphersuites)]
1415 #[cfg(any(ossl111, libressl, awslc))]
1416 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1417 let cipher_list = CString::new(cipher_list).unwrap();
1418 unsafe {
1419 cvt(ffi::SSL_CTX_set_ciphersuites(
1420 self.as_ptr(),
1421 cipher_list.as_ptr() as *const _,
1422 ))
1423 .map(|_| ())
1424 }
1425 }
1426
1427 #[corresponds(SSL_CTX_set_ecdh_auto)]
1431 #[cfg(libressl)]
1432 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1433 unsafe {
1434 cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ())
1435 }
1436 }
1437
1438 #[corresponds(SSL_CTX_set_options)]
1445 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1446 let bits =
1447 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1448 SslOptions::from_bits_retain(bits)
1449 }
1450
1451 #[corresponds(SSL_CTX_get_options)]
1453 pub fn options(&self) -> SslOptions {
1454 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1455 SslOptions::from_bits_retain(bits)
1456 }
1457
1458 #[corresponds(SSL_CTX_clear_options)]
1460 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1461 let bits =
1462 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1463 SslOptions::from_bits_retain(bits)
1464 }
1465
1466 #[corresponds(SSL_CTX_set_min_proto_version)]
1471 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1472 unsafe {
1473 cvt(ffi::SSL_CTX_set_min_proto_version(
1474 self.as_ptr(),
1475 version.map_or(0, |v| v.0 as _),
1476 ))
1477 .map(|_| ())
1478 }
1479 }
1480
1481 #[corresponds(SSL_CTX_set_max_proto_version)]
1486 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1487 unsafe {
1488 cvt(ffi::SSL_CTX_set_max_proto_version(
1489 self.as_ptr(),
1490 version.map_or(0, |v| v.0 as _),
1491 ))
1492 .map(|_| ())
1493 }
1494 }
1495
1496 #[corresponds(SSL_CTX_get_min_proto_version)]
1503 #[cfg(any(ossl110g, libressl))]
1504 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1505 unsafe {
1506 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1507 if r == 0 {
1508 None
1509 } else {
1510 Some(SslVersion(r))
1511 }
1512 }
1513 }
1514
1515 #[corresponds(SSL_CTX_get_max_proto_version)]
1522 #[cfg(any(ossl110g, libressl))]
1523 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1524 unsafe {
1525 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1526 if r == 0 {
1527 None
1528 } else {
1529 Some(SslVersion(r))
1530 }
1531 }
1532 }
1533
1534 #[corresponds(SSL_CTX_set_alpn_protos)]
1543 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1544 unsafe {
1545 assert!(protocols.len() <= c_uint::MAX as usize);
1546 let r = ffi::SSL_CTX_set_alpn_protos(
1547 self.as_ptr(),
1548 protocols.as_ptr(),
1549 protocols.len() as _,
1550 );
1551 if r == 0 {
1553 Ok(())
1554 } else {
1555 Err(ErrorStack::get())
1556 }
1557 }
1558 }
1559
1560 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1562 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1563 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1564 unsafe {
1565 let cstr = CString::new(protocols).unwrap();
1566
1567 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1568 if r == 0 {
1570 Ok(())
1571 } else {
1572 Err(ErrorStack::get())
1573 }
1574 }
1575 }
1576
1577 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1588 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1589 where
1590 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1591 {
1592 unsafe {
1593 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1594 ffi::SSL_CTX_set_alpn_select_cb(
1595 self.as_ptr(),
1596 Some(callbacks::raw_alpn_select::<F>),
1597 ptr::null_mut(),
1598 );
1599 }
1600 }
1601
1602 #[corresponds(SSL_CTX_check_private_key)]
1604 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1605 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1606 }
1607
1608 #[corresponds(SSL_CTX_get_cert_store)]
1610 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1611 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1612 }
1613
1614 #[corresponds(SSL_CTX_get_cert_store)]
1616 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1617 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1618 }
1619
1620 #[corresponds(SSL_CTX_get0_param)]
1624 pub fn verify_param(&self) -> &X509VerifyParamRef {
1625 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1626 }
1627
1628 #[corresponds(SSL_CTX_get0_param)]
1632 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1633 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1634 }
1635
1636 #[cfg(any(boringssl, tongsuo, awslc))]
1644 pub fn add_cert_decompression_alg<F>(
1645 &mut self,
1646 alg_id: CertCompressionAlgorithm,
1647 decompress: F,
1648 ) -> Result<(), ErrorStack>
1649 where
1650 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1651 {
1652 unsafe {
1653 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1654 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1655 self.as_ptr(),
1656 alg_id.0 as _,
1657 None,
1658 Some(raw_cert_decompression::<F>),
1659 ))
1660 .map(|_| ())
1661 }
1662 }
1663
1664 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1666 #[cfg(ossl320)]
1667 pub fn set_cert_comp_preference(
1668 &mut self,
1669 algs: &[CertCompressionAlgorithm],
1670 ) -> Result<(), ErrorStack> {
1671 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1672 unsafe {
1673 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1674 self.as_ptr(),
1675 algs.as_mut_ptr(),
1676 algs.len(),
1677 ))
1678 .map(|_| ())
1679 }
1680 }
1681
1682 #[cfg(any(boringssl, awslc))]
1690 pub fn enable_ocsp_stapling(&mut self) {
1691 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1692 }
1693
1694 #[cfg(any(boringssl, awslc))]
1702 pub fn enable_signed_cert_timestamps(&mut self) {
1703 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1704 }
1705
1706 #[cfg(any(boringssl, awslc))]
1714 pub fn set_grease_enabled(&mut self, enabled: bool) {
1715 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1716 }
1717
1718 #[cfg(any(boringssl, awslc))]
1726 pub fn set_permute_extensions(&mut self, enabled: bool) {
1727 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1728 }
1729
1730 #[corresponds(SSL_CTX_enable_ct)]
1732 #[cfg(ossl111)]
1733 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1734 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1735 }
1736
1737 #[corresponds(SSL_CTX_ct_is_enabled)]
1739 #[cfg(ossl111)]
1740 pub fn ct_is_enabled(&self) -> bool {
1741 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1742 }
1743
1744 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1746 #[cfg(not(any(boringssl, awslc)))]
1747 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1748 unsafe {
1749 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1750 .map(|_| ())
1751 }
1752 }
1753
1754 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1767 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1768 where
1769 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1770 {
1771 unsafe {
1772 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1773 cvt(
1774 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1775 as c_int,
1776 )
1777 .map(|_| ())
1778 }
1779 }
1780
1781 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1782 #[cfg(ossl300)]
1783 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1784 where
1785 F: Fn(
1786 &mut SslRef,
1787 &mut [u8],
1788 &mut [u8],
1789 &mut CipherCtxRef,
1790 &mut MacCtxRef,
1791 bool,
1792 ) -> Result<TicketKeyStatus, ErrorStack>
1793 + 'static
1794 + Sync
1795 + Send,
1796 {
1797 unsafe {
1798 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1799 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1800 self.as_ptr(),
1801 Some(raw_tlsext_ticket_key_evp::<F>),
1802 ) as c_int)
1803 .map(|_| ())
1804 }
1805 }
1806
1807 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1808 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1809 where
1810 F: Fn(
1811 &mut SslRef,
1812 &mut [u8],
1813 &mut [u8],
1814 &mut CipherCtxRef,
1815 &mut HMacCtxRef,
1816 bool,
1817 ) -> Result<TicketKeyStatus, ErrorStack>
1818 + 'static
1819 + Sync
1820 + Send,
1821 {
1822 unsafe {
1823 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1824 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1825 self.as_ptr(),
1826 Some(raw_tlsext_ticket_key::<F>),
1827 ) as c_int)
1828 .map(|_| ())
1829 }
1830 }
1831
1832 #[corresponds(SSL_CTX_set_psk_client_callback)]
1838 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1839 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1840 where
1841 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1842 + 'static
1843 + Sync
1844 + Send,
1845 {
1846 unsafe {
1847 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1848 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1849 }
1850 }
1851
1852 #[corresponds(SSL_CTX_set_psk_server_callback)]
1858 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1859 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1860 where
1861 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1862 + 'static
1863 + Sync
1864 + Send,
1865 {
1866 unsafe {
1867 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1868 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1869 }
1870 }
1871
1872 #[corresponds(SSL_CTX_sess_set_new_cb)]
1886 pub fn set_new_session_callback<F>(&mut self, callback: F)
1887 where
1888 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1889 {
1890 unsafe {
1891 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1892 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1893 }
1894 }
1895
1896 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1900 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1901 where
1902 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1903 {
1904 unsafe {
1905 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1906 ffi::SSL_CTX_sess_set_remove_cb(
1907 self.as_ptr(),
1908 Some(callbacks::raw_remove_session::<F>),
1909 );
1910 }
1911 }
1912
1913 #[corresponds(SSL_CTX_sess_set_get_cb)]
1924 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1925 where
1926 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1927 {
1928 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1929 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1930 }
1931
1932 #[corresponds(SSL_CTX_set_keylog_callback)]
1940 #[cfg(any(ossl111, boringssl, awslc))]
1941 pub fn set_keylog_callback<F>(&mut self, callback: F)
1942 where
1943 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1944 {
1945 unsafe {
1946 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1947 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1948 }
1949 }
1950
1951 #[corresponds(SSL_CTX_set_session_cache_mode)]
1955 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1956 unsafe {
1957 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1958 SslSessionCacheMode::from_bits_retain(bits)
1959 }
1960 }
1961
1962 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1968 #[cfg(ossl111)]
1969 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1970 where
1971 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1972 {
1973 unsafe {
1974 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1975 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1976 self.as_ptr(),
1977 Some(raw_stateless_cookie_generate::<F>),
1978 );
1979 }
1980 }
1981
1982 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1991 #[cfg(ossl111)]
1992 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1993 where
1994 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1995 {
1996 unsafe {
1997 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1998 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1999 self.as_ptr(),
2000 Some(raw_stateless_cookie_verify::<F>),
2001 )
2002 }
2003 }
2004
2005 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
2010 #[cfg(not(any(boringssl, awslc)))]
2011 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
2012 where
2013 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
2014 {
2015 unsafe {
2016 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2017 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2018 }
2019 }
2020
2021 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2026 #[cfg(not(any(boringssl, awslc)))]
2027 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2028 where
2029 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2030 {
2031 unsafe {
2032 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2033 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2034 }
2035 }
2036
2037 #[corresponds(SSL_CTX_set_ex_data)]
2043 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2044 self.set_ex_data_inner(index, data);
2045 }
2046
2047 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2048 match self.ex_data_mut(index) {
2049 Some(v) => {
2050 *v = data;
2051 (v as *mut T).cast()
2052 }
2053 _ => unsafe {
2054 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2055 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2056 data
2057 },
2058 }
2059 }
2060
2061 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2062 unsafe {
2063 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2064 if data.is_null() {
2065 None
2066 } else {
2067 Some(&mut *data.cast())
2068 }
2069 }
2070 }
2071
2072 #[corresponds(SSL_CTX_add_custom_ext)]
2076 #[cfg(ossl111)]
2077 pub fn add_custom_ext<AddFn, ParseFn, T>(
2078 &mut self,
2079 ext_type: u16,
2080 context: ExtensionContext,
2081 add_cb: AddFn,
2082 parse_cb: ParseFn,
2083 ) -> Result<(), ErrorStack>
2084 where
2085 AddFn: Fn(
2086 &mut SslRef,
2087 ExtensionContext,
2088 Option<(usize, &X509Ref)>,
2089 ) -> Result<Option<T>, SslAlert>
2090 + 'static
2091 + Sync
2092 + Send,
2093 T: AsRef<[u8]> + 'static + Sync + Send,
2094 ParseFn: Fn(
2095 &mut SslRef,
2096 ExtensionContext,
2097 &[u8],
2098 Option<(usize, &X509Ref)>,
2099 ) -> Result<(), SslAlert>
2100 + 'static
2101 + Sync
2102 + Send,
2103 {
2104 let ret = unsafe {
2105 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2106 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2107
2108 ffi::SSL_CTX_add_custom_ext(
2109 self.as_ptr(),
2110 ext_type as c_uint,
2111 context.bits(),
2112 Some(raw_custom_ext_add::<AddFn, T>),
2113 Some(raw_custom_ext_free::<T>),
2114 ptr::null_mut(),
2115 Some(raw_custom_ext_parse::<ParseFn>),
2116 ptr::null_mut(),
2117 )
2118 };
2119 if ret == 1 {
2120 Ok(())
2121 } else {
2122 Err(ErrorStack::get())
2123 }
2124 }
2125
2126 #[corresponds(SSL_CTX_set_max_early_data)]
2132 #[cfg(any(ossl111, libressl))]
2133 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2134 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2135 Ok(())
2136 } else {
2137 Err(ErrorStack::get())
2138 }
2139 }
2140
2141 #[cfg(any(boringssl, awslc))]
2151 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2152 where
2153 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2154 {
2155 unsafe {
2156 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2157 ffi::SSL_CTX_set_select_certificate_cb(
2158 self.as_ptr(),
2159 Some(callbacks::raw_select_cert::<F>),
2160 );
2161 }
2162 }
2163
2164 #[corresponds(SSL_CTX_set_client_hello_cb)]
2168 #[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
2169 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2170 where
2171 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2172 {
2173 unsafe {
2174 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2175 ffi::SSL_CTX_set_client_hello_cb(
2176 self.as_ptr(),
2177 Some(callbacks::raw_client_hello::<F>),
2178 ptr,
2179 );
2180 }
2181 }
2182
2183 #[corresponds(SSL_CTX_set_info_callback)]
2186 pub fn set_info_callback<F>(&mut self, callback: F)
2187 where
2188 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2189 {
2190 unsafe {
2191 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2192 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2193 }
2194 }
2195
2196 #[corresponds(SSL_CTX_sess_set_cache_size)]
2200 #[allow(clippy::useless_conversion)]
2201 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2202 unsafe {
2203 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2204 }
2205 }
2206
2207 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2211 #[cfg(ossl110)]
2212 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2213 let sigalgs = CString::new(sigalgs).unwrap();
2214 unsafe {
2215 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2216 .map(|_| ())
2217 }
2218 }
2219
2220 #[corresponds(SSL_CTX_set1_groups_list)]
2224 #[cfg(any(ossl111, boringssl, libressl, awslc))]
2225 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2226 let groups = CString::new(groups).unwrap();
2227 unsafe {
2228 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2229 }
2230 }
2231
2232 #[corresponds(SSL_CTX_set_num_tickets)]
2237 #[cfg(any(ossl111, boringssl, awslc))]
2238 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2239 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2240 }
2241
2242 #[corresponds(SSL_CTX_set_security_level)]
2247 #[cfg(any(ossl110, libressl360))]
2248 pub fn set_security_level(&mut self, level: u32) {
2249 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2250 }
2251
2252 pub fn build(self) -> SslContext {
2254 self.0
2255 }
2256}
2257
2258foreign_type_and_impl_send_sync! {
2259 type CType = ffi::SSL_CTX;
2260 fn drop = ffi::SSL_CTX_free;
2261
2262 pub struct SslContext;
2267
2268 pub struct SslContextRef;
2272}
2273
2274impl Clone for SslContext {
2275 fn clone(&self) -> Self {
2276 (**self).to_owned()
2277 }
2278}
2279
2280impl ToOwned for SslContextRef {
2281 type Owned = SslContext;
2282
2283 fn to_owned(&self) -> Self::Owned {
2284 unsafe {
2285 SSL_CTX_up_ref(self.as_ptr());
2286 SslContext::from_ptr(self.as_ptr())
2287 }
2288 }
2289}
2290
2291impl fmt::Debug for SslContext {
2293 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2294 write!(fmt, "SslContext")
2295 }
2296}
2297
2298impl SslContext {
2299 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2301 SslContextBuilder::new(method)
2302 }
2303
2304 #[corresponds(SSL_CTX_get_ex_new_index)]
2309 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2310 where
2311 T: 'static + Sync + Send,
2312 {
2313 unsafe {
2314 ffi::init();
2315 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2316 Ok(Index::from_raw(idx))
2317 }
2318 }
2319
2320 fn cached_ex_index<T>() -> Index<SslContext, T>
2322 where
2323 T: 'static + Sync + Send,
2324 {
2325 unsafe {
2326 let idx = *INDEXES
2327 .lock()
2328 .unwrap_or_else(|e| e.into_inner())
2329 .entry(TypeId::of::<T>())
2330 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2331 Index::from_raw(idx)
2332 }
2333 }
2334}
2335
2336impl SslContextRef {
2337 #[corresponds(SSL_CTX_get0_certificate)]
2341 #[cfg(any(ossl110, libressl))]
2342 pub fn certificate(&self) -> Option<&X509Ref> {
2343 unsafe {
2344 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2345 X509Ref::from_const_ptr_opt(ptr)
2346 }
2347 }
2348
2349 #[corresponds(SSL_CTX_get0_privatekey)]
2353 #[cfg(any(ossl110, libressl))]
2354 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2355 unsafe {
2356 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2357 PKeyRef::from_const_ptr_opt(ptr)
2358 }
2359 }
2360
2361 #[corresponds(SSL_CTX_get_cert_store)]
2363 pub fn cert_store(&self) -> &X509StoreRef {
2364 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2365 }
2366
2367 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2369 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2370 unsafe {
2371 let mut chain = ptr::null_mut();
2372 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2373 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2374 }
2375 }
2376
2377 #[corresponds(SSL_CTX_get_ex_data)]
2379 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2380 unsafe {
2381 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2382 if data.is_null() {
2383 None
2384 } else {
2385 Some(&*(data as *const T))
2386 }
2387 }
2388 }
2389
2390 #[corresponds(SSL_CTX_get_max_early_data)]
2394 #[cfg(any(ossl111, libressl))]
2395 pub fn max_early_data(&self) -> u32 {
2396 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2397 }
2398
2399 #[corresponds(SSL_CTX_add_session)]
2408 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2409 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2410 }
2411
2412 #[corresponds(SSL_CTX_remove_session)]
2421 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2422 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2423 }
2424
2425 #[corresponds(SSL_CTX_sess_get_cache_size)]
2429 #[allow(clippy::unnecessary_cast)]
2430 pub fn session_cache_size(&self) -> i64 {
2431 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2432 }
2433
2434 #[corresponds(SSL_CTX_get_verify_mode)]
2438 pub fn verify_mode(&self) -> SslVerifyMode {
2439 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2440 SslVerifyMode::from_bits_retain(mode)
2441 }
2442
2443 #[corresponds(SSL_CTX_get_num_tickets)]
2448 #[cfg(ossl111)]
2449 pub fn num_tickets(&self) -> usize {
2450 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2451 }
2452
2453 #[corresponds(SSL_CTX_get_security_level)]
2458 #[cfg(any(ossl110, libressl360))]
2459 pub fn security_level(&self) -> u32 {
2460 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2461 }
2462}
2463
2464pub struct CipherBits {
2466 pub secret: i32,
2468
2469 pub algorithm: i32,
2471}
2472
2473pub struct SslCipher(*mut ffi::SSL_CIPHER);
2475
2476impl ForeignType for SslCipher {
2477 type CType = ffi::SSL_CIPHER;
2478 type Ref = SslCipherRef;
2479
2480 #[inline]
2481 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2482 SslCipher(ptr)
2483 }
2484
2485 #[inline]
2486 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2487 self.0
2488 }
2489}
2490
2491impl Stackable for SslCipher {
2492 type StackType = ffi::stack_st_SSL_CIPHER;
2493}
2494
2495impl Deref for SslCipher {
2496 type Target = SslCipherRef;
2497
2498 fn deref(&self) -> &SslCipherRef {
2499 unsafe { SslCipherRef::from_ptr(self.0) }
2500 }
2501}
2502
2503impl DerefMut for SslCipher {
2504 fn deref_mut(&mut self) -> &mut SslCipherRef {
2505 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2506 }
2507}
2508
2509pub struct SslCipherRef(Opaque);
2513
2514impl ForeignTypeRef for SslCipherRef {
2515 type CType = ffi::SSL_CIPHER;
2516}
2517
2518impl SslCipherRef {
2519 #[corresponds(SSL_CIPHER_get_name)]
2521 pub fn name(&self) -> &'static str {
2522 unsafe {
2523 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2524 CStr::from_ptr(ptr).to_str().unwrap()
2525 }
2526 }
2527
2528 #[corresponds(SSL_CIPHER_standard_name)]
2532 #[cfg(ossl111)]
2533 pub fn standard_name(&self) -> Option<&'static str> {
2534 unsafe {
2535 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2536 if ptr.is_null() {
2537 None
2538 } else {
2539 Some(CStr::from_ptr(ptr).to_str().unwrap())
2540 }
2541 }
2542 }
2543
2544 #[corresponds(SSL_CIPHER_get_version)]
2546 pub fn version(&self) -> &'static str {
2547 let version = unsafe {
2548 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2549 CStr::from_ptr(ptr as *const _)
2550 };
2551
2552 str::from_utf8(version.to_bytes()).unwrap()
2553 }
2554
2555 #[corresponds(SSL_CIPHER_get_bits)]
2557 #[allow(clippy::useless_conversion)]
2558 pub fn bits(&self) -> CipherBits {
2559 unsafe {
2560 let mut algo_bits = 0;
2561 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2562 CipherBits {
2563 secret: secret_bits.into(),
2564 algorithm: algo_bits.into(),
2565 }
2566 }
2567 }
2568
2569 #[corresponds(SSL_CIPHER_description)]
2571 pub fn description(&self) -> String {
2572 unsafe {
2573 let mut buf = [0; 128];
2575 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2576 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2577 }
2578 }
2579
2580 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2584 #[cfg(ossl111)]
2585 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2586 unsafe {
2587 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2588 if ptr.is_null() {
2589 None
2590 } else {
2591 Some(MessageDigest::from_ptr(ptr))
2592 }
2593 }
2594 }
2595
2596 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2600 #[cfg(any(ossl110, libressl))]
2601 pub fn cipher_nid(&self) -> Option<Nid> {
2602 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2603 if n == 0 {
2604 None
2605 } else {
2606 Some(Nid::from_raw(n))
2607 }
2608 }
2609
2610 #[corresponds(SSL_CIPHER_get_protocol_id)]
2614 #[cfg(ossl111)]
2615 pub fn protocol_id(&self) -> [u8; 2] {
2616 unsafe {
2617 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2618 id.to_be_bytes()
2619 }
2620 }
2621}
2622
2623impl fmt::Debug for SslCipherRef {
2624 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2625 write!(fmt, "{}", self.name())
2626 }
2627}
2628
2629#[derive(Debug)]
2631pub struct CipherLists {
2632 pub suites: Stack<SslCipher>,
2633 pub signalling_suites: Stack<SslCipher>,
2634}
2635
2636foreign_type_and_impl_send_sync! {
2637 type CType = ffi::SSL_SESSION;
2638 fn drop = ffi::SSL_SESSION_free;
2639
2640 pub struct SslSession;
2644
2645 pub struct SslSessionRef;
2649}
2650
2651impl Clone for SslSession {
2652 fn clone(&self) -> SslSession {
2653 SslSessionRef::to_owned(self)
2654 }
2655}
2656
2657impl SslSession {
2658 from_der! {
2659 #[corresponds(d2i_SSL_SESSION)]
2661 from_der,
2662 SslSession,
2663 ffi::d2i_SSL_SESSION
2664 }
2665}
2666
2667impl ToOwned for SslSessionRef {
2668 type Owned = SslSession;
2669
2670 fn to_owned(&self) -> SslSession {
2671 unsafe {
2672 SSL_SESSION_up_ref(self.as_ptr());
2673 SslSession(self.as_ptr())
2674 }
2675 }
2676}
2677
2678impl SslSessionRef {
2679 #[corresponds(SSL_SESSION_get_id)]
2681 pub fn id(&self) -> &[u8] {
2682 unsafe {
2683 let mut len = 0;
2684 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2685 #[allow(clippy::unnecessary_cast)]
2686 util::from_raw_parts(p as *const u8, len as usize)
2687 }
2688 }
2689
2690 #[corresponds(SSL_SESSION_get_master_key)]
2692 pub fn master_key_len(&self) -> usize {
2693 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2694 }
2695
2696 #[corresponds(SSL_SESSION_get_master_key)]
2700 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2701 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2702 }
2703
2704 #[corresponds(SSL_SESSION_get_max_early_data)]
2708 #[cfg(any(ossl111, libressl))]
2709 pub fn max_early_data(&self) -> u32 {
2710 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2711 }
2712
2713 #[corresponds(SSL_SESSION_get_time)]
2715 #[allow(clippy::useless_conversion)]
2716 pub fn time(&self) -> SslTimeTy {
2717 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2718 }
2719
2720 #[corresponds(SSL_SESSION_get_timeout)]
2724 #[allow(clippy::useless_conversion)]
2725 pub fn timeout(&self) -> i64 {
2726 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2727 }
2728
2729 #[corresponds(SSL_SESSION_get_protocol_version)]
2733 #[cfg(any(ossl110, libressl))]
2734 pub fn protocol_version(&self) -> SslVersion {
2735 unsafe {
2736 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2737 SslVersion(version)
2738 }
2739 }
2740
2741 #[corresponds(SSL_SESSION_get_protocol_version)]
2743 #[cfg(any(boringssl, awslc))]
2744 pub fn protocol_version(&self) -> SslVersion {
2745 unsafe {
2746 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2747 SslVersion(version as _)
2748 }
2749 }
2750
2751 to_der! {
2752 #[corresponds(i2d_SSL_SESSION)]
2754 to_der,
2755 ffi::i2d_SSL_SESSION
2756 }
2757}
2758
2759foreign_type_and_impl_send_sync! {
2760 type CType = ffi::SSL;
2761 fn drop = ffi::SSL_free;
2762
2763 pub struct Ssl;
2770
2771 pub struct SslRef;
2775}
2776
2777impl fmt::Debug for Ssl {
2778 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2779 fmt::Debug::fmt(&**self, fmt)
2780 }
2781}
2782
2783impl Ssl {
2784 #[corresponds(SSL_get_ex_new_index)]
2789 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2790 where
2791 T: 'static + Sync + Send,
2792 {
2793 unsafe {
2794 ffi::init();
2795 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2796 Ok(Index::from_raw(idx))
2797 }
2798 }
2799
2800 fn cached_ex_index<T>() -> Index<Ssl, T>
2802 where
2803 T: 'static + Sync + Send,
2804 {
2805 unsafe {
2806 let idx = *SSL_INDEXES
2807 .lock()
2808 .unwrap_or_else(|e| e.into_inner())
2809 .entry(TypeId::of::<T>())
2810 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2811 Index::from_raw(idx)
2812 }
2813 }
2814
2815 #[corresponds(SSL_new)]
2817 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2818 let session_ctx_index = try_get_session_ctx_index()?;
2819 unsafe {
2820 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2821 let mut ssl = Ssl::from_ptr(ptr);
2822 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2823
2824 Ok(ssl)
2825 }
2826 }
2827
2828 #[corresponds(SSL_connect)]
2834 #[allow(deprecated)]
2835 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2836 where
2837 S: Read + Write,
2838 {
2839 SslStreamBuilder::new(self, stream).connect()
2840 }
2841
2842 #[corresponds(SSL_accept)]
2849 #[allow(deprecated)]
2850 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2851 where
2852 S: Read + Write,
2853 {
2854 SslStreamBuilder::new(self, stream).accept()
2855 }
2856}
2857
2858impl fmt::Debug for SslRef {
2859 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2860 fmt.debug_struct("Ssl")
2861 .field("state", &self.state_string_long())
2862 .field("verify_result", &self.verify_result())
2863 .finish()
2864 }
2865}
2866
2867impl SslRef {
2868 #[cfg(not(feature = "tongsuo"))]
2869 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2870 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2871 }
2872
2873 #[cfg(feature = "tongsuo")]
2874 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2875 unsafe {
2876 let bio = ffi::SSL_get_rbio(self.as_ptr());
2877 bio::find_correct_bio(bio)
2878 }
2879 }
2880
2881 fn get_error(&self, ret: c_int) -> ErrorCode {
2882 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2883 }
2884
2885 #[corresponds(SSL_set_mode)]
2889 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2890 unsafe {
2891 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2892 SslMode::from_bits_retain(bits)
2893 }
2894 }
2895
2896 #[corresponds(SSL_clear_mode)]
2898 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2899 unsafe {
2900 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2901 SslMode::from_bits_retain(bits)
2902 }
2903 }
2904
2905 #[corresponds(SSL_get_mode)]
2907 pub fn mode(&self) -> SslMode {
2908 unsafe {
2909 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2910 SslMode::from_bits_retain(bits)
2911 }
2912 }
2913
2914 #[corresponds(SSL_set_connect_state)]
2916 pub fn set_connect_state(&mut self) {
2917 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2918 }
2919
2920 #[corresponds(SSL_set_accept_state)]
2922 pub fn set_accept_state(&mut self) {
2923 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2924 }
2925
2926 #[cfg(any(boringssl, awslc))]
2927 #[corresponds(SSL_ech_accepted)]
2928 pub fn ech_accepted(&self) -> bool {
2929 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2930 }
2931
2932 #[cfg(tongsuo)]
2933 #[corresponds(SSL_is_ntls)]
2934 pub fn is_ntls(&mut self) -> bool {
2935 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2936 }
2937
2938 #[cfg(tongsuo)]
2939 #[corresponds(SSL_enable_ntls)]
2940 pub fn enable_ntls(&mut self) {
2941 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2942 }
2943
2944 #[cfg(tongsuo)]
2945 #[corresponds(SSL_disable_ntls)]
2946 pub fn disable_ntls(&mut self) {
2947 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2948 }
2949
2950 #[cfg(all(tongsuo, ossl300))]
2951 #[corresponds(SSL_enable_force_ntls)]
2952 pub fn enable_force_ntls(&mut self) {
2953 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2954 }
2955
2956 #[cfg(all(tongsuo, ossl300))]
2957 #[corresponds(SSL_disable_force_ntls)]
2958 pub fn disable_force_ntls(&mut self) {
2959 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2960 }
2961
2962 #[cfg(tongsuo)]
2963 #[corresponds(SSL_enable_sm_tls13_strict)]
2964 pub fn enable_sm_tls13_strict(&mut self) {
2965 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2966 }
2967
2968 #[cfg(tongsuo)]
2969 #[corresponds(SSL_disable_sm_tls13_strict)]
2970 pub fn disable_sm_tls13_strict(&mut self) {
2971 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2972 }
2973
2974 #[corresponds(SSL_set_verify)]
2978 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2979 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2980 }
2981
2982 #[corresponds(SSL_set_verify_mode)]
2984 pub fn verify_mode(&self) -> SslVerifyMode {
2985 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2986 SslVerifyMode::from_bits_retain(mode)
2987 }
2988
2989 #[corresponds(SSL_set_verify)]
2993 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2994 where
2995 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2996 {
2997 unsafe {
2998 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
3000 ffi::SSL_set_verify(
3001 self.as_ptr(),
3002 mode.bits() as c_int,
3003 Some(ssl_raw_verify::<F>),
3004 );
3005 }
3006 }
3007
3008 #[corresponds(SSL_set_info_callback)]
3011 pub fn set_info_callback<F>(&mut self, callback: F)
3012 where
3013 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
3014 {
3015 unsafe {
3016 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3018 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
3019 }
3020 }
3021
3022 #[corresponds(SSL_set_dh_auto)]
3026 #[cfg(ossl300)]
3027 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3028 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3029 }
3030
3031 #[corresponds(SSL_set_tmp_dh)]
3035 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3036 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3037 }
3038
3039 #[corresponds(SSL_set_tmp_dh_callback)]
3043 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3044 where
3045 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3046 {
3047 unsafe {
3048 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3050 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3051 }
3052 }
3053
3054 #[corresponds(SSL_set_tmp_ecdh)]
3058 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3059 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3060 }
3061
3062 #[corresponds(SSL_set_ecdh_auto)]
3068 #[cfg(libressl)]
3069 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3070 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3071 }
3072
3073 #[corresponds(SSL_set_alpn_protos)]
3079 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3080 unsafe {
3081 assert!(protocols.len() <= c_uint::MAX as usize);
3082 let r =
3083 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3084 if r == 0 {
3086 Ok(())
3087 } else {
3088 Err(ErrorStack::get())
3089 }
3090 }
3091 }
3092
3093 #[corresponds(SSL_get_current_cipher)]
3095 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3096 unsafe {
3097 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3098
3099 SslCipherRef::from_const_ptr_opt(ptr)
3100 }
3101 }
3102
3103 #[corresponds(SSL_state_string)]
3105 pub fn state_string(&self) -> &'static str {
3106 let state = unsafe {
3107 let ptr = ffi::SSL_state_string(self.as_ptr());
3108 CStr::from_ptr(ptr as *const _)
3109 };
3110
3111 str::from_utf8(state.to_bytes()).unwrap()
3112 }
3113
3114 #[corresponds(SSL_state_string_long)]
3116 pub fn state_string_long(&self) -> &'static str {
3117 let state = unsafe {
3118 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3119 CStr::from_ptr(ptr as *const _)
3120 };
3121
3122 str::from_utf8(state.to_bytes()).unwrap()
3123 }
3124
3125 #[corresponds(SSL_set_tlsext_host_name)]
3129 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3130 let cstr = CString::new(hostname).unwrap();
3131 unsafe {
3132 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3133 .map(|_| ())
3134 }
3135 }
3136
3137 #[corresponds(SSL_get_peer_certificate)]
3139 pub fn peer_certificate(&self) -> Option<X509> {
3140 unsafe {
3141 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3142 X509::from_ptr_opt(ptr)
3143 }
3144 }
3145
3146 #[corresponds(SSL_get_peer_cert_chain)]
3151 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3152 unsafe {
3153 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3154 StackRef::from_const_ptr_opt(ptr)
3155 }
3156 }
3157
3158 #[corresponds(SSL_get0_verified_chain)]
3168 #[cfg(ossl110)]
3169 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3170 unsafe {
3171 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3172 StackRef::from_const_ptr_opt(ptr)
3173 }
3174 }
3175
3176 #[corresponds(SSL_get_certificate)]
3178 pub fn certificate(&self) -> Option<&X509Ref> {
3179 unsafe {
3180 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3181 X509Ref::from_const_ptr_opt(ptr)
3182 }
3183 }
3184
3185 #[corresponds(SSL_get_privatekey)]
3189 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3190 unsafe {
3191 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3192 PKeyRef::from_const_ptr_opt(ptr)
3193 }
3194 }
3195
3196 #[corresponds(SSL_version)]
3198 pub fn version2(&self) -> Option<SslVersion> {
3199 unsafe {
3200 let r = ffi::SSL_version(self.as_ptr());
3201 if r == 0 {
3202 None
3203 } else {
3204 Some(SslVersion(r))
3205 }
3206 }
3207 }
3208
3209 #[corresponds(SSL_get_version)]
3211 pub fn version_str(&self) -> &'static str {
3212 let version = unsafe {
3213 let ptr = ffi::SSL_get_version(self.as_ptr());
3214 CStr::from_ptr(ptr as *const _)
3215 };
3216
3217 str::from_utf8(version.to_bytes()).unwrap()
3218 }
3219
3220 #[corresponds(SSL_get0_alpn_selected)]
3227 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3228 unsafe {
3229 let mut data: *const c_uchar = ptr::null();
3230 let mut len: c_uint = 0;
3231 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3234
3235 if data.is_null() {
3236 None
3237 } else {
3238 Some(util::from_raw_parts(data, len as usize))
3239 }
3240 }
3241 }
3242
3243 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3245 #[corresponds(SSL_set_tlsext_use_srtp)]
3246 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3247 unsafe {
3248 let cstr = CString::new(protocols).unwrap();
3249
3250 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3251 if r == 0 {
3253 Ok(())
3254 } else {
3255 Err(ErrorStack::get())
3256 }
3257 }
3258 }
3259
3260 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3264 #[corresponds(SSL_get_srtp_profiles)]
3265 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3266 unsafe {
3267 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3268
3269 StackRef::from_const_ptr_opt(chain)
3270 }
3271 }
3272
3273 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3277 #[corresponds(SSL_get_selected_srtp_profile)]
3278 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3279 unsafe {
3280 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3281
3282 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3283 }
3284 }
3285
3286 #[corresponds(SSL_pending)]
3291 pub fn pending(&self) -> usize {
3292 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3293 }
3294
3295 #[corresponds(SSL_get_servername)]
3308 pub fn servername(&self, type_: NameType) -> Option<&str> {
3310 self.servername_raw(type_)
3311 .and_then(|b| str::from_utf8(b).ok())
3312 }
3313
3314 #[corresponds(SSL_get_servername)]
3322 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3323 unsafe {
3324 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3325 if name.is_null() {
3326 None
3327 } else {
3328 Some(CStr::from_ptr(name as *const _).to_bytes())
3329 }
3330 }
3331 }
3332
3333 #[corresponds(SSL_set_SSL_CTX)]
3337 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3338 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3339 }
3340
3341 #[corresponds(SSL_get_SSL_CTX)]
3343 pub fn ssl_context(&self) -> &SslContextRef {
3344 unsafe {
3345 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3346 SslContextRef::from_ptr(ssl_ctx)
3347 }
3348 }
3349
3350 #[corresponds(SSL_get0_param)]
3354 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3355 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3356 }
3357
3358 #[corresponds(SSL_get_verify_result)]
3360 pub fn verify_result(&self) -> X509VerifyResult {
3361 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3362 }
3363
3364 #[corresponds(SSL_get_session)]
3366 pub fn session(&self) -> Option<&SslSessionRef> {
3367 unsafe {
3368 let p = ffi::SSL_get_session(self.as_ptr());
3369 SslSessionRef::from_const_ptr_opt(p)
3370 }
3371 }
3372
3373 #[corresponds(SSL_get_client_random)]
3380 #[cfg(any(ossl110, libressl))]
3381 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3382 unsafe {
3383 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3384 }
3385 }
3386
3387 #[corresponds(SSL_get_server_random)]
3394 #[cfg(any(ossl110, libressl))]
3395 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3396 unsafe {
3397 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3398 }
3399 }
3400
3401 #[corresponds(SSL_export_keying_material)]
3403 pub fn export_keying_material(
3404 &self,
3405 out: &mut [u8],
3406 label: &str,
3407 context: Option<&[u8]>,
3408 ) -> Result<(), ErrorStack> {
3409 unsafe {
3410 let (context, contextlen, use_context) = match context {
3411 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3412 None => (ptr::null(), 0, 0),
3413 };
3414 cvt(ffi::SSL_export_keying_material(
3415 self.as_ptr(),
3416 out.as_mut_ptr() as *mut c_uchar,
3417 out.len(),
3418 label.as_ptr() as *const c_char,
3419 label.len(),
3420 context,
3421 contextlen,
3422 use_context,
3423 ))
3424 .map(|_| ())
3425 }
3426 }
3427
3428 #[corresponds(SSL_export_keying_material_early)]
3435 #[cfg(ossl111)]
3436 pub fn export_keying_material_early(
3437 &self,
3438 out: &mut [u8],
3439 label: &str,
3440 context: &[u8],
3441 ) -> Result<(), ErrorStack> {
3442 unsafe {
3443 cvt(ffi::SSL_export_keying_material_early(
3444 self.as_ptr(),
3445 out.as_mut_ptr() as *mut c_uchar,
3446 out.len(),
3447 label.as_ptr() as *const c_char,
3448 label.len(),
3449 context.as_ptr() as *const c_uchar,
3450 context.len(),
3451 ))
3452 .map(|_| ())
3453 }
3454 }
3455
3456 #[corresponds(SSL_set_session)]
3467 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3468 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3469 }
3470
3471 #[corresponds(SSL_session_reused)]
3473 pub fn session_reused(&self) -> bool {
3474 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3475 }
3476
3477 #[cfg(any(boringssl, awslc))]
3485 pub fn enable_ocsp_stapling(&mut self) {
3486 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3487 }
3488
3489 #[cfg(any(boringssl, awslc))]
3497 pub fn enable_signed_cert_timestamps(&mut self) {
3498 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3499 }
3500
3501 #[cfg(any(boringssl, awslc))]
3509 pub fn set_permute_extensions(&mut self, enabled: bool) {
3510 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3511 }
3512
3513 #[corresponds(SSL_enable_ct)]
3515 #[cfg(ossl111)]
3516 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3517 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3518 }
3519
3520 #[corresponds(SSL_ct_is_enabled)]
3522 #[cfg(ossl111)]
3523 pub fn ct_is_enabled(&self) -> bool {
3524 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3525 }
3526
3527 #[corresponds(SSL_set_tlsext_status_type)]
3529 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3530 unsafe {
3531 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3532 }
3533 }
3534
3535 #[corresponds(SSL_get_extms_support)]
3539 #[cfg(ossl110)]
3540 pub fn extms_support(&self) -> Option<bool> {
3541 unsafe {
3542 match ffi::SSL_get_extms_support(self.as_ptr()) {
3543 -1 => None,
3544 ret => Some(ret != 0),
3545 }
3546 }
3547 }
3548
3549 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3551 #[cfg(not(any(boringssl, awslc)))]
3552 pub fn ocsp_status(&self) -> Option<&[u8]> {
3553 unsafe {
3554 let mut p = ptr::null_mut();
3555 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3556
3557 if len < 0 {
3558 None
3559 } else {
3560 Some(util::from_raw_parts(p as *const u8, len as usize))
3561 }
3562 }
3563 }
3564
3565 #[corresponds(SSL_get0_ocsp_response)]
3567 #[cfg(any(boringssl, awslc))]
3568 pub fn ocsp_status(&self) -> Option<&[u8]> {
3569 unsafe {
3570 let mut p = ptr::null();
3571 let mut len: usize = 0;
3572 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3573
3574 if len == 0 {
3575 None
3576 } else {
3577 Some(util::from_raw_parts(p as *const u8, len))
3578 }
3579 }
3580 }
3581
3582 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3584 #[cfg(not(any(boringssl, awslc)))]
3585 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3586 unsafe {
3587 assert!(response.len() <= c_int::MAX as usize);
3588 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3589 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3590 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3591 self.as_ptr(),
3592 p as *mut c_uchar,
3593 response.len() as c_long,
3594 ) as c_int)
3595 .map(|_| ())
3596 .inspect_err(|_| {
3597 ffi::OPENSSL_free(p);
3598 })
3599 }
3600 }
3601
3602 #[corresponds(SSL_set_ocsp_response)]
3604 #[cfg(any(boringssl, awslc))]
3605 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3606 unsafe {
3607 cvt(ffi::SSL_set_ocsp_response(
3608 self.as_ptr(),
3609 response.as_ptr(),
3610 response.len(),
3611 ))
3612 .map(|_| ())
3613 }
3614 }
3615
3616 #[corresponds(SSL_is_server)]
3618 pub fn is_server(&self) -> bool {
3619 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3620 }
3621
3622 #[corresponds(SSL_set_ex_data)]
3628 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3629 match self.ex_data_mut(index) {
3630 Some(v) => *v = data,
3631 None => unsafe {
3632 let data = Box::new(data);
3633 ffi::SSL_set_ex_data(
3634 self.as_ptr(),
3635 index.as_raw(),
3636 Box::into_raw(data) as *mut c_void,
3637 );
3638 },
3639 }
3640 }
3641
3642 #[corresponds(SSL_get_ex_data)]
3644 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3645 unsafe {
3646 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3647 if data.is_null() {
3648 None
3649 } else {
3650 Some(&*(data as *const T))
3651 }
3652 }
3653 }
3654
3655 #[corresponds(SSL_get_ex_data)]
3657 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3658 unsafe {
3659 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3660 if data.is_null() {
3661 None
3662 } else {
3663 Some(&mut *(data as *mut T))
3664 }
3665 }
3666 }
3667
3668 #[corresponds(SSL_set_max_early_data)]
3672 #[cfg(any(ossl111, libressl))]
3673 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3674 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3675 Ok(())
3676 } else {
3677 Err(ErrorStack::get())
3678 }
3679 }
3680
3681 #[corresponds(SSL_get_max_early_data)]
3685 #[cfg(any(ossl111, libressl))]
3686 pub fn max_early_data(&self) -> u32 {
3687 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3688 }
3689
3690 #[corresponds(SSL_get_finished)]
3695 pub fn finished(&self, buf: &mut [u8]) -> usize {
3696 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3697 }
3698
3699 #[corresponds(SSL_get_peer_finished)]
3705 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3706 unsafe {
3707 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3708 }
3709 }
3710
3711 #[corresponds(SSL_is_init_finished)]
3713 #[cfg(ossl110)]
3714 pub fn is_init_finished(&self) -> bool {
3715 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3716 }
3717
3718 #[corresponds(SSL_client_hello_isv2)]
3724 #[cfg(ossl111)]
3725 pub fn client_hello_isv2(&self) -> bool {
3726 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3727 }
3728
3729 #[corresponds(SSL_client_hello_get0_legacy_version)]
3735 #[cfg(ossl111)]
3736 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3737 unsafe {
3738 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3739 if version == 0 {
3740 None
3741 } else {
3742 Some(SslVersion(version as c_int))
3743 }
3744 }
3745 }
3746
3747 #[corresponds(SSL_client_hello_get0_random)]
3753 #[cfg(ossl111)]
3754 pub fn client_hello_random(&self) -> Option<&[u8]> {
3755 unsafe {
3756 let mut ptr = ptr::null();
3757 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3758 if len == 0 {
3759 None
3760 } else {
3761 Some(util::from_raw_parts(ptr, len))
3762 }
3763 }
3764 }
3765
3766 #[corresponds(SSL_client_hello_get0_session_id)]
3772 #[cfg(ossl111)]
3773 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3774 unsafe {
3775 let mut ptr = ptr::null();
3776 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3777 if len == 0 {
3778 None
3779 } else {
3780 Some(util::from_raw_parts(ptr, len))
3781 }
3782 }
3783 }
3784
3785 #[corresponds(SSL_client_hello_get0_ciphers)]
3791 #[cfg(ossl111)]
3792 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3793 unsafe {
3794 let mut ptr = ptr::null();
3795 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3796 if len == 0 {
3797 None
3798 } else {
3799 Some(util::from_raw_parts(ptr, len))
3800 }
3801 }
3802 }
3803
3804 #[cfg(ossl111)]
3810 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3811 unsafe {
3812 let mut ptr = ptr::null();
3813 let mut len = 0usize;
3814 let r = ffi::SSL_client_hello_get0_ext(
3815 self.as_ptr(),
3816 ext_type.as_raw() as _,
3817 &mut ptr,
3818 &mut len,
3819 );
3820 if r == 0 {
3821 None
3822 } else {
3823 Some(util::from_raw_parts(ptr, len))
3824 }
3825 }
3826 }
3827
3828 #[corresponds(SSL_bytes_to_cipher_list)]
3833 #[cfg(ossl111)]
3834 pub fn bytes_to_cipher_list(
3835 &self,
3836 bytes: &[u8],
3837 isv2format: bool,
3838 ) -> Result<CipherLists, ErrorStack> {
3839 unsafe {
3840 let ptr = bytes.as_ptr();
3841 let len = bytes.len();
3842 let mut sk = ptr::null_mut();
3843 let mut scsvs = ptr::null_mut();
3844 let res = ffi::SSL_bytes_to_cipher_list(
3845 self.as_ptr(),
3846 ptr,
3847 len,
3848 isv2format as c_int,
3849 &mut sk,
3850 &mut scsvs,
3851 );
3852 if res == 1 {
3853 Ok(CipherLists {
3854 suites: Stack::from_ptr(sk),
3855 signalling_suites: Stack::from_ptr(scsvs),
3856 })
3857 } else {
3858 Err(ErrorStack::get())
3859 }
3860 }
3861 }
3862
3863 #[corresponds(SSL_client_hello_get0_compression_methods)]
3869 #[cfg(ossl111)]
3870 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3871 unsafe {
3872 let mut ptr = ptr::null();
3873 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3874 if len == 0 {
3875 None
3876 } else {
3877 Some(util::from_raw_parts(ptr, len))
3878 }
3879 }
3880 }
3881
3882 #[corresponds(SSL_set_mtu)]
3884 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3885 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3886 }
3887
3888 #[corresponds(SSL_get_psk_identity_hint)]
3892 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3893 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3894 unsafe {
3895 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3896 if ptr.is_null() {
3897 None
3898 } else {
3899 Some(CStr::from_ptr(ptr).to_bytes())
3900 }
3901 }
3902 }
3903
3904 #[corresponds(SSL_get_psk_identity)]
3906 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3907 pub fn psk_identity(&self) -> Option<&[u8]> {
3908 unsafe {
3909 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3910 if ptr.is_null() {
3911 None
3912 } else {
3913 Some(CStr::from_ptr(ptr).to_bytes())
3914 }
3915 }
3916 }
3917
3918 #[corresponds(SSL_add0_chain_cert)]
3919 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3920 unsafe {
3921 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3922 mem::forget(chain);
3923 }
3924 Ok(())
3925 }
3926
3927 #[cfg(not(any(boringssl, awslc)))]
3929 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3930 unsafe {
3931 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3932 };
3933 Ok(())
3934 }
3935
3936 #[corresponds(SSL_use_Private_Key_file)]
3938 pub fn set_private_key_file<P: AsRef<Path>>(
3939 &mut self,
3940 path: P,
3941 ssl_file_type: SslFiletype,
3942 ) -> Result<(), ErrorStack> {
3943 let p = path.as_ref().as_os_str().to_str().unwrap();
3944 let key_file = CString::new(p).unwrap();
3945 unsafe {
3946 cvt(ffi::SSL_use_PrivateKey_file(
3947 self.as_ptr(),
3948 key_file.as_ptr(),
3949 ssl_file_type.as_raw(),
3950 ))?;
3951 };
3952 Ok(())
3953 }
3954
3955 #[corresponds(SSL_use_PrivateKey)]
3957 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3958 unsafe {
3959 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3960 };
3961 Ok(())
3962 }
3963
3964 #[cfg(tongsuo)]
3965 #[corresponds(SSL_use_enc_Private_Key_file)]
3966 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3967 &mut self,
3968 path: P,
3969 ssl_file_type: SslFiletype,
3970 ) -> Result<(), ErrorStack> {
3971 let p = path.as_ref().as_os_str().to_str().unwrap();
3972 let key_file = CString::new(p).unwrap();
3973 unsafe {
3974 cvt(ffi::SSL_use_enc_PrivateKey_file(
3975 self.as_ptr(),
3976 key_file.as_ptr(),
3977 ssl_file_type.as_raw(),
3978 ))?;
3979 };
3980 Ok(())
3981 }
3982
3983 #[cfg(tongsuo)]
3984 #[corresponds(SSL_use_enc_PrivateKey)]
3985 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3986 unsafe {
3987 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3988 };
3989 Ok(())
3990 }
3991
3992 #[cfg(tongsuo)]
3993 #[corresponds(SSL_use_sign_Private_Key_file)]
3994 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3995 &mut self,
3996 path: P,
3997 ssl_file_type: SslFiletype,
3998 ) -> Result<(), ErrorStack> {
3999 let p = path.as_ref().as_os_str().to_str().unwrap();
4000 let key_file = CString::new(p).unwrap();
4001 unsafe {
4002 cvt(ffi::SSL_use_sign_PrivateKey_file(
4003 self.as_ptr(),
4004 key_file.as_ptr(),
4005 ssl_file_type.as_raw(),
4006 ))?;
4007 };
4008 Ok(())
4009 }
4010
4011 #[cfg(tongsuo)]
4012 #[corresponds(SSL_use_sign_PrivateKey)]
4013 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
4014 unsafe {
4015 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
4016 };
4017 Ok(())
4018 }
4019
4020 #[corresponds(SSL_use_certificate)]
4022 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4023 unsafe {
4024 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4025 };
4026 Ok(())
4027 }
4028
4029 #[cfg(tongsuo)]
4030 #[corresponds(SSL_use_enc_certificate)]
4031 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4032 unsafe {
4033 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4034 };
4035 Ok(())
4036 }
4037
4038 #[cfg(tongsuo)]
4039 #[corresponds(SSL_use_sign_certificate)]
4040 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4041 unsafe {
4042 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4043 };
4044 Ok(())
4045 }
4046
4047 #[corresponds(SSL_use_certificate_chain_file)]
4053 #[cfg(any(ossl110, libressl))]
4054 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4055 &mut self,
4056 path: P,
4057 ) -> Result<(), ErrorStack> {
4058 let p = path.as_ref().as_os_str().to_str().unwrap();
4059 let cert_file = CString::new(p).unwrap();
4060 unsafe {
4061 cvt(ffi::SSL_use_certificate_chain_file(
4062 self.as_ptr(),
4063 cert_file.as_ptr(),
4064 ))?;
4065 };
4066 Ok(())
4067 }
4068
4069 #[corresponds(SSL_add_client_CA)]
4071 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4072 unsafe {
4073 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4074 };
4075 Ok(())
4076 }
4077
4078 #[corresponds(SSL_set_client_CA_list)]
4080 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4081 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4082 mem::forget(list);
4083 }
4084
4085 #[corresponds(SSL_set_min_proto_version)]
4090 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4091 unsafe {
4092 cvt(ffi::SSL_set_min_proto_version(
4093 self.as_ptr(),
4094 version.map_or(0, |v| v.0 as _),
4095 ))
4096 .map(|_| ())
4097 }
4098 }
4099
4100 #[corresponds(SSL_set_max_proto_version)]
4105 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4106 unsafe {
4107 cvt(ffi::SSL_set_max_proto_version(
4108 self.as_ptr(),
4109 version.map_or(0, |v| v.0 as _),
4110 ))
4111 .map(|_| ())
4112 }
4113 }
4114
4115 #[corresponds(SSL_set_ciphersuites)]
4124 #[cfg(any(ossl111, libressl))]
4125 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4126 let cipher_list = CString::new(cipher_list).unwrap();
4127 unsafe {
4128 cvt(ffi::SSL_set_ciphersuites(
4129 self.as_ptr(),
4130 cipher_list.as_ptr() as *const _,
4131 ))
4132 .map(|_| ())
4133 }
4134 }
4135
4136 #[corresponds(SSL_set_cipher_list)]
4144 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4145 let cipher_list = CString::new(cipher_list).unwrap();
4146 unsafe {
4147 cvt(ffi::SSL_set_cipher_list(
4148 self.as_ptr(),
4149 cipher_list.as_ptr() as *const _,
4150 ))
4151 .map(|_| ())
4152 }
4153 }
4154
4155 #[corresponds(SSL_set_cert_store)]
4157 #[cfg(any(ossl110, boringssl, awslc))]
4158 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4159 unsafe {
4160 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4161 mem::forget(cert_store);
4162 Ok(())
4163 }
4164 }
4165
4166 #[corresponds(SSL_set_num_tickets)]
4171 #[cfg(ossl111)]
4172 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4173 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4174 }
4175
4176 #[corresponds(SSL_get_num_tickets)]
4181 #[cfg(ossl111)]
4182 pub fn num_tickets(&self) -> usize {
4183 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4184 }
4185
4186 #[corresponds(SSL_set_security_level)]
4191 #[cfg(any(ossl110, libressl360))]
4192 pub fn set_security_level(&mut self, level: u32) {
4193 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4194 }
4195
4196 #[corresponds(SSL_get_security_level)]
4201 #[cfg(any(ossl110, libressl360))]
4202 pub fn security_level(&self) -> u32 {
4203 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4204 }
4205
4206 #[corresponds(SSL_get_peer_tmp_key)]
4211 #[cfg(ossl300)]
4212 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4213 unsafe {
4214 let mut key = ptr::null_mut();
4215 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4216 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4217 Err(e) => Err(e),
4218 }
4219 }
4220 }
4221
4222 #[corresponds(SSL_get_tmp_key)]
4227 #[cfg(ossl300)]
4228 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4229 unsafe {
4230 let mut key = ptr::null_mut();
4231 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4232 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4233 Err(e) => Err(e),
4234 }
4235 }
4236 }
4237}
4238
4239#[derive(Debug)]
4241pub struct MidHandshakeSslStream<S> {
4242 stream: SslStream<S>,
4243 error: Error,
4244}
4245
4246impl<S> MidHandshakeSslStream<S> {
4247 pub fn get_ref(&self) -> &S {
4249 self.stream.get_ref()
4250 }
4251
4252 pub fn get_mut(&mut self) -> &mut S {
4254 self.stream.get_mut()
4255 }
4256
4257 pub fn ssl(&self) -> &SslRef {
4259 self.stream.ssl()
4260 }
4261
4262 pub fn ssl_mut(&mut self) -> &mut SslRef {
4264 self.stream.ssl_mut()
4265 }
4266
4267 pub fn error(&self) -> &Error {
4269 &self.error
4270 }
4271
4272 pub fn into_error(self) -> Error {
4274 self.error
4275 }
4276}
4277
4278impl<S> MidHandshakeSslStream<S>
4279where
4280 S: Read + Write,
4281{
4282 #[corresponds(SSL_do_handshake)]
4285 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4286 match self.stream.do_handshake() {
4287 Ok(()) => Ok(self.stream),
4288 Err(error) => {
4289 self.error = error;
4290 match self.error.code() {
4291 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4292 Err(HandshakeError::WouldBlock(self))
4293 }
4294 _ => Err(HandshakeError::Failure(self)),
4295 }
4296 }
4297 }
4298 }
4299}
4300
4301pub struct SslStream<S> {
4303 ssl: ManuallyDrop<Ssl>,
4304 method: ManuallyDrop<BioMethod>,
4305 _p: PhantomData<S>,
4306}
4307
4308impl<S> Drop for SslStream<S> {
4309 fn drop(&mut self) {
4310 unsafe {
4312 ManuallyDrop::drop(&mut self.ssl);
4313 ManuallyDrop::drop(&mut self.method);
4314 }
4315 }
4316}
4317
4318impl<S> fmt::Debug for SslStream<S>
4319where
4320 S: fmt::Debug,
4321{
4322 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4323 fmt.debug_struct("SslStream")
4324 .field("stream", &self.get_ref())
4325 .field("ssl", &self.ssl())
4326 .finish()
4327 }
4328}
4329
4330impl<S: Read + Write> SslStream<S> {
4331 #[corresponds(SSL_set_bio)]
4339 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4340 let (bio, method) = bio::new(stream)?;
4341 unsafe {
4342 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4343 }
4344
4345 Ok(SslStream {
4346 ssl: ManuallyDrop::new(ssl),
4347 method: ManuallyDrop::new(method),
4348 _p: PhantomData,
4349 })
4350 }
4351
4352 #[corresponds(SSL_read_early_data)]
4361 #[cfg(any(ossl111, libressl))]
4362 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4363 let mut read = 0;
4364 let ret = unsafe {
4365 ffi::SSL_read_early_data(
4366 self.ssl.as_ptr(),
4367 buf.as_ptr() as *mut c_void,
4368 buf.len(),
4369 &mut read,
4370 )
4371 };
4372 match ret {
4373 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4374 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4375 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4376 _ => unreachable!(),
4377 }
4378 }
4379
4380 #[corresponds(SSL_write_early_data)]
4387 #[cfg(any(ossl111, libressl))]
4388 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4389 let mut written = 0;
4390 let ret = unsafe {
4391 ffi::SSL_write_early_data(
4392 self.ssl.as_ptr(),
4393 buf.as_ptr() as *const c_void,
4394 buf.len(),
4395 &mut written,
4396 )
4397 };
4398 if ret > 0 {
4399 Ok(written)
4400 } else {
4401 Err(self.make_error(ret))
4402 }
4403 }
4404
4405 #[corresponds(SSL_connect)]
4412 pub fn connect(&mut self) -> Result<(), Error> {
4413 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4414 if ret > 0 {
4415 Ok(())
4416 } else {
4417 Err(self.make_error(ret))
4418 }
4419 }
4420
4421 #[corresponds(SSL_accept)]
4428 pub fn accept(&mut self) -> Result<(), Error> {
4429 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4430 if ret > 0 {
4431 Ok(())
4432 } else {
4433 Err(self.make_error(ret))
4434 }
4435 }
4436
4437 #[corresponds(SSL_do_handshake)]
4441 pub fn do_handshake(&mut self) -> Result<(), Error> {
4442 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4443 if ret > 0 {
4444 Ok(())
4445 } else {
4446 Err(self.make_error(ret))
4447 }
4448 }
4449
4450 #[corresponds(SSL_stateless)]
4461 #[cfg(ossl111)]
4462 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4463 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4464 1 => Ok(true),
4465 0 => Ok(false),
4466 -1 => Err(ErrorStack::get()),
4467 _ => unreachable!(),
4468 }
4469 }
4470
4471 #[corresponds(SSL_read_ex)]
4478 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4479 loop {
4480 match self.ssl_read_uninit(buf) {
4481 Ok(n) => return Ok(n),
4482 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4483 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4484 return Ok(0);
4485 }
4486 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4487 Err(e) => {
4488 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4489 }
4490 }
4491 }
4492 }
4493
4494 #[corresponds(SSL_read_ex)]
4499 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4500 unsafe {
4502 self.ssl_read_uninit(util::from_raw_parts_mut(
4503 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4504 buf.len(),
4505 ))
4506 }
4507 }
4508
4509 #[corresponds(SSL_read_ex)]
4516 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4517 if buf.is_empty() {
4518 return Ok(0);
4519 }
4520
4521 cfg_if! {
4522 if #[cfg(any(ossl111, libressl))] {
4523 let mut readbytes = 0;
4524 let ret = unsafe {
4525 ffi::SSL_read_ex(
4526 self.ssl().as_ptr(),
4527 buf.as_mut_ptr().cast(),
4528 buf.len(),
4529 &mut readbytes,
4530 )
4531 };
4532
4533 if ret > 0 {
4534 Ok(readbytes)
4535 } else {
4536 Err(self.make_error(ret))
4537 }
4538 } else {
4539 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4540 let ret = unsafe {
4541 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4542 };
4543 if ret > 0 {
4544 Ok(ret as usize)
4545 } else {
4546 Err(self.make_error(ret))
4547 }
4548 }
4549 }
4550 }
4551
4552 #[corresponds(SSL_write_ex)]
4557 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4558 if buf.is_empty() {
4559 return Ok(0);
4560 }
4561
4562 cfg_if! {
4563 if #[cfg(any(ossl111, libressl))] {
4564 let mut written = 0;
4565 let ret = unsafe {
4566 ffi::SSL_write_ex(
4567 self.ssl().as_ptr(),
4568 buf.as_ptr().cast(),
4569 buf.len(),
4570 &mut written,
4571 )
4572 };
4573
4574 if ret > 0 {
4575 Ok(written)
4576 } else {
4577 Err(self.make_error(ret))
4578 }
4579 } else {
4580 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4581 let ret = unsafe {
4582 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4583 };
4584 if ret > 0 {
4585 Ok(ret as usize)
4586 } else {
4587 Err(self.make_error(ret))
4588 }
4589 }
4590 }
4591 }
4592
4593 #[corresponds(SSL_peek_ex)]
4595 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4596 unsafe {
4598 self.ssl_peek_uninit(util::from_raw_parts_mut(
4599 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4600 buf.len(),
4601 ))
4602 }
4603 }
4604
4605 #[corresponds(SSL_peek_ex)]
4612 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4613 cfg_if! {
4614 if #[cfg(any(ossl111, libressl))] {
4615 let mut readbytes = 0;
4616 let ret = unsafe {
4617 ffi::SSL_peek_ex(
4618 self.ssl().as_ptr(),
4619 buf.as_mut_ptr().cast(),
4620 buf.len(),
4621 &mut readbytes,
4622 )
4623 };
4624
4625 if ret > 0 {
4626 Ok(readbytes)
4627 } else {
4628 Err(self.make_error(ret))
4629 }
4630 } else {
4631 if buf.is_empty() {
4632 return Ok(0);
4633 }
4634
4635 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4636 let ret = unsafe {
4637 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4638 };
4639 if ret > 0 {
4640 Ok(ret as usize)
4641 } else {
4642 Err(self.make_error(ret))
4643 }
4644 }
4645 }
4646 }
4647
4648 #[corresponds(SSL_shutdown)]
4658 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4659 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4660 0 => Ok(ShutdownResult::Sent),
4661 1 => Ok(ShutdownResult::Received),
4662 n => Err(self.make_error(n)),
4663 }
4664 }
4665
4666 #[corresponds(SSL_get_shutdown)]
4668 pub fn get_shutdown(&mut self) -> ShutdownState {
4669 unsafe {
4670 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4671 ShutdownState::from_bits_retain(bits)
4672 }
4673 }
4674
4675 #[corresponds(SSL_set_shutdown)]
4680 pub fn set_shutdown(&mut self, state: ShutdownState) {
4681 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4682 }
4683}
4684
4685impl<S> SslStream<S> {
4686 fn make_error(&mut self, ret: c_int) -> Error {
4687 self.check_panic();
4688
4689 let code = self.ssl.get_error(ret);
4690
4691 let cause = match code {
4692 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4693 ErrorCode::SYSCALL => {
4694 let errs = ErrorStack::get();
4695 if errs.errors().is_empty() {
4696 self.get_bio_error().map(InnerError::Io)
4697 } else {
4698 Some(InnerError::Ssl(errs))
4699 }
4700 }
4701 ErrorCode::ZERO_RETURN => None,
4702 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4703 self.get_bio_error().map(InnerError::Io)
4704 }
4705 _ => None,
4706 };
4707
4708 Error { code, cause }
4709 }
4710
4711 fn check_panic(&mut self) {
4712 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4713 resume_unwind(err)
4714 }
4715 }
4716
4717 fn get_bio_error(&mut self) -> Option<io::Error> {
4718 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4719 }
4720
4721 pub fn get_ref(&self) -> &S {
4723 unsafe {
4724 let bio = self.ssl.get_raw_rbio();
4725 bio::get_ref(bio)
4726 }
4727 }
4728
4729 pub fn get_mut(&mut self) -> &mut S {
4736 unsafe {
4737 let bio = self.ssl.get_raw_rbio();
4738 bio::get_mut(bio)
4739 }
4740 }
4741
4742 pub fn ssl(&self) -> &SslRef {
4744 &self.ssl
4745 }
4746
4747 pub fn ssl_mut(&mut self) -> &mut SslRef {
4749 &mut self.ssl
4750 }
4751}
4752
4753impl<S: Read + Write> Read for SslStream<S> {
4754 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4755 unsafe {
4757 self.read_uninit(util::from_raw_parts_mut(
4758 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4759 buf.len(),
4760 ))
4761 }
4762 }
4763}
4764
4765impl<S: Read + Write> Write for SslStream<S> {
4766 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4767 loop {
4768 match self.ssl_write(buf) {
4769 Ok(n) => return Ok(n),
4770 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4771 Err(e) => {
4772 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4773 }
4774 }
4775 }
4776 }
4777
4778 fn flush(&mut self) -> io::Result<()> {
4779 self.get_mut().flush()
4780 }
4781}
4782
4783#[deprecated(
4785 since = "0.10.32",
4786 note = "use the methods directly on Ssl/SslStream instead"
4787)]
4788pub struct SslStreamBuilder<S> {
4789 inner: SslStream<S>,
4790}
4791
4792#[allow(deprecated)]
4793impl<S> SslStreamBuilder<S>
4794where
4795 S: Read + Write,
4796{
4797 pub fn new(ssl: Ssl, stream: S) -> Self {
4799 Self {
4800 inner: SslStream::new(ssl, stream).unwrap(),
4801 }
4802 }
4803
4804 #[corresponds(SSL_stateless)]
4815 #[cfg(ossl111)]
4816 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4817 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4818 1 => Ok(true),
4819 0 => Ok(false),
4820 -1 => Err(ErrorStack::get()),
4821 _ => unreachable!(),
4822 }
4823 }
4824
4825 #[corresponds(SSL_set_connect_state)]
4827 pub fn set_connect_state(&mut self) {
4828 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4829 }
4830
4831 #[corresponds(SSL_set_accept_state)]
4833 pub fn set_accept_state(&mut self) {
4834 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4835 }
4836
4837 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4839 match self.inner.connect() {
4840 Ok(()) => Ok(self.inner),
4841 Err(error) => match error.code() {
4842 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4843 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4844 stream: self.inner,
4845 error,
4846 }))
4847 }
4848 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4849 stream: self.inner,
4850 error,
4851 })),
4852 },
4853 }
4854 }
4855
4856 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4858 match self.inner.accept() {
4859 Ok(()) => Ok(self.inner),
4860 Err(error) => match error.code() {
4861 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4862 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4863 stream: self.inner,
4864 error,
4865 }))
4866 }
4867 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4868 stream: self.inner,
4869 error,
4870 })),
4871 },
4872 }
4873 }
4874
4875 #[corresponds(SSL_do_handshake)]
4879 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4880 match self.inner.do_handshake() {
4881 Ok(()) => Ok(self.inner),
4882 Err(error) => match error.code() {
4883 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4884 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4885 stream: self.inner,
4886 error,
4887 }))
4888 }
4889 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4890 stream: self.inner,
4891 error,
4892 })),
4893 },
4894 }
4895 }
4896
4897 #[corresponds(SSL_read_early_data)]
4907 #[cfg(any(ossl111, libressl))]
4908 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4909 self.inner.read_early_data(buf)
4910 }
4911
4912 #[corresponds(SSL_write_early_data)]
4919 #[cfg(any(ossl111, libressl))]
4920 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4921 self.inner.write_early_data(buf)
4922 }
4923}
4924
4925#[allow(deprecated)]
4926impl<S> SslStreamBuilder<S> {
4927 pub fn get_ref(&self) -> &S {
4929 unsafe {
4930 let bio = self.inner.ssl.get_raw_rbio();
4931 bio::get_ref(bio)
4932 }
4933 }
4934
4935 pub fn get_mut(&mut self) -> &mut S {
4942 unsafe {
4943 let bio = self.inner.ssl.get_raw_rbio();
4944 bio::get_mut(bio)
4945 }
4946 }
4947
4948 pub fn ssl(&self) -> &SslRef {
4950 &self.inner.ssl
4951 }
4952
4953 pub fn ssl_mut(&mut self) -> &mut SslRef {
4955 &mut self.inner.ssl
4956 }
4957}
4958
4959#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4961pub enum ShutdownResult {
4962 Sent,
4964
4965 Received,
4967}
4968
4969bitflags! {
4970 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4972 #[repr(transparent)]
4973 pub struct ShutdownState: c_int {
4974 const SENT = ffi::SSL_SENT_SHUTDOWN;
4976 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4978 }
4979}
4980
4981use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4982cfg_if! {
4983 if #[cfg(ossl300)] {
4984 use ffi::SSL_get1_peer_certificate;
4985 } else {
4986 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4987 }
4988}
4989use ffi::{
4990 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4991 TLS_server_method,
4992};
4993cfg_if! {
4994 if #[cfg(ossl110)] {
4995 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4996 ffi::CRYPTO_get_ex_new_index(
4997 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4998 0,
4999 ptr::null_mut(),
5000 None,
5001 None,
5002 f,
5003 )
5004 }
5005
5006 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5007 ffi::CRYPTO_get_ex_new_index(
5008 ffi::CRYPTO_EX_INDEX_SSL,
5009 0,
5010 ptr::null_mut(),
5011 None,
5012 None,
5013 f,
5014 )
5015 }
5016 } else {
5017 use std::sync::Once;
5018
5019 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5020 static ONCE: Once = Once::new();
5022 ONCE.call_once(|| {
5023 cfg_if! {
5024 if #[cfg(not(any(boringssl, awslc)))] {
5025 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5026 } else {
5027 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5028 }
5029 }
5030 });
5031
5032 cfg_if! {
5033 if #[cfg(not(any(boringssl, awslc)))] {
5034 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5035 } else {
5036 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5037 }
5038 }
5039 }
5040
5041 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5042 static ONCE: Once = Once::new();
5044 ONCE.call_once(|| {
5045 #[cfg(not(any(boringssl, awslc)))]
5046 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5047 #[cfg(any(boringssl, awslc))]
5048 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5049 });
5050
5051 #[cfg(not(any(boringssl, awslc)))]
5052 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5053 #[cfg(any(boringssl, awslc))]
5054 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5055 }
5056 }
5057}