1#[cfg(ossl300)]
61use crate::cvt_long;
62use crate::dh::{Dh, DhRef};
63use crate::ec::EcKeyRef;
64use crate::error::ErrorStack;
65use crate::ex_data::Index;
66#[cfg(ossl111)]
67use crate::hash::MessageDigest;
68#[cfg(any(ossl110, libressl))]
69use crate::nid::Nid;
70use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
71#[cfg(ossl300)]
72use crate::pkey::{PKey, Public};
73#[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
74use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
75use crate::ssl::bio::BioMethod;
76use crate::ssl::callbacks::*;
77use crate::ssl::error::InnerError;
78use crate::stack::{Stack, StackRef, Stackable};
79use crate::util;
80use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
81use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
82use crate::x509::verify::X509VerifyParamRef;
83use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
84use crate::{cvt, cvt_n, cvt_p, init};
85use bitflags::bitflags;
86use cfg_if::cfg_if;
87use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
88use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
89use openssl_macros::corresponds;
90use std::any::TypeId;
91use std::collections::HashMap;
92use std::ffi::{CStr, CString};
93use std::fmt;
94use std::io;
95use std::io::prelude::*;
96use std::marker::PhantomData;
97use std::mem::{self, ManuallyDrop, MaybeUninit};
98use std::ops::{Deref, DerefMut};
99use std::panic::resume_unwind;
100use std::path::Path;
101use std::ptr;
102use std::str;
103use std::sync::{Arc, LazyLock, Mutex, OnceLock};
104
105pub use crate::ssl::connector::{
106 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
107};
108pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
109
110mod bio;
111mod callbacks;
112mod connector;
113mod error;
114#[cfg(test)]
115mod test;
116
117#[corresponds(OPENSSL_cipher_name)]
123#[cfg(ossl111)]
124pub fn cipher_name(std_name: &str) -> &'static str {
125 unsafe {
126 ffi::init();
127
128 let s = CString::new(std_name).unwrap();
129 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
130 CStr::from_ptr(ptr).to_str().unwrap()
131 }
132}
133
134cfg_if! {
135 if #[cfg(ossl300)] {
136 type SslOptionsRepr = u64;
137 } else if #[cfg(any(boringssl, awslc))] {
138 type SslOptionsRepr = u32;
139 } else {
140 type SslOptionsRepr = libc::c_ulong;
141 }
142}
143
144bitflags! {
145 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
147 #[repr(transparent)]
148 pub struct SslOptions: SslOptionsRepr {
149 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
151
152 #[cfg(ossl300)]
155 const IGNORE_UNEXPECTED_EOF = ffi::SSL_OP_IGNORE_UNEXPECTED_EOF as SslOptionsRepr;
156
157 #[cfg(not(any(boringssl, awslc)))]
159 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
160
161 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
165
166 #[cfg(not(any(boringssl, awslc)))]
172 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
173
174 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
176
177 #[cfg(not(any(boringssl, awslc)))]
179 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
180 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
181
182 #[cfg(not(any(boringssl, awslc)))]
184 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
185
186 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
189 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
190
191 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
195
196 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
200
201 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
205
206 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
208
209 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
211
212 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
214
215 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
217
218 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
220
221 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
223
224 #[cfg(any(ossl111, boringssl, libressl, awslc))]
228 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
229
230 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
232
233 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
235
236 #[cfg(ossl110)]
252 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
253
254 #[cfg(any(boringssl, ossl110h, awslc))]
258 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
259
260 #[cfg(ossl111)]
265 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
266
267 #[cfg(ossl111)]
279 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
280 }
281}
282
283bitflags! {
284 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
286 #[repr(transparent)]
287 pub struct SslMode: SslBitType {
288 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
294
295 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
298
299 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
309
310 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
316
317 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
321
322 #[cfg(not(libressl))]
330 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
331 }
332}
333
334#[derive(Copy, Clone)]
336pub struct SslMethod(*const ffi::SSL_METHOD);
337
338impl SslMethod {
339 #[corresponds(TLS_method)]
341 pub fn tls() -> SslMethod {
342 unsafe { SslMethod(TLS_method()) }
343 }
344
345 #[corresponds(DTLS_method)]
347 pub fn dtls() -> SslMethod {
348 unsafe { SslMethod(DTLS_method()) }
349 }
350
351 #[corresponds(TLS_client_method)]
353 pub fn tls_client() -> SslMethod {
354 unsafe { SslMethod(TLS_client_method()) }
355 }
356
357 #[corresponds(TLS_server_method)]
359 pub fn tls_server() -> SslMethod {
360 unsafe { SslMethod(TLS_server_method()) }
361 }
362
363 #[corresponds(DTLS_client_method)]
365 pub fn dtls_client() -> SslMethod {
366 unsafe { SslMethod(DTLS_client_method()) }
367 }
368
369 #[corresponds(DTLS_server_method)]
371 pub fn dtls_server() -> SslMethod {
372 unsafe { SslMethod(DTLS_server_method()) }
373 }
374
375 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
381 SslMethod(ptr)
382 }
383
384 #[allow(clippy::trivially_copy_pass_by_ref)]
386 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
387 self.0
388 }
389}
390
391unsafe impl Sync for SslMethod {}
392unsafe impl Send for SslMethod {}
393
394bitflags! {
395 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
397 #[repr(transparent)]
398 pub struct SslVerifyMode: i32 {
399 const PEER = ffi::SSL_VERIFY_PEER;
403
404 const NONE = ffi::SSL_VERIFY_NONE;
410
411 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
415 }
416}
417
418#[cfg(any(boringssl, awslc))]
419type SslBitType = c_int;
420#[cfg(not(any(boringssl, awslc)))]
421type SslBitType = c_long;
422
423#[cfg(any(boringssl, awslc))]
424type SslTimeTy = u64;
425#[cfg(not(any(boringssl, awslc)))]
426type SslTimeTy = c_long;
427
428bitflags! {
429 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
431 #[repr(transparent)]
432 pub struct SslSessionCacheMode: SslBitType {
433 const OFF = ffi::SSL_SESS_CACHE_OFF;
435
436 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
443
444 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
448
449 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
451
452 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
454
455 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
457
458 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
460
461 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
463 }
464}
465
466#[cfg(ossl111)]
467bitflags! {
468 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
470 #[repr(transparent)]
471 pub struct ExtensionContext: c_uint {
472 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
474 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
476 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
478 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
480 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
482 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
484 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
486 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
487 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
489 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
490 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
491 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
492 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
493 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
494 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
495 }
496}
497
498#[derive(Copy, Clone)]
500pub struct SslFiletype(c_int);
501
502impl SslFiletype {
503 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
507
508 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
512
513 pub fn from_raw(raw: c_int) -> SslFiletype {
515 SslFiletype(raw)
516 }
517
518 #[allow(clippy::trivially_copy_pass_by_ref)]
520 pub fn as_raw(&self) -> c_int {
521 self.0
522 }
523}
524
525#[derive(Copy, Clone)]
527pub struct StatusType(c_int);
528
529impl StatusType {
530 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
532
533 pub fn from_raw(raw: c_int) -> StatusType {
535 StatusType(raw)
536 }
537
538 #[allow(clippy::trivially_copy_pass_by_ref)]
540 pub fn as_raw(&self) -> c_int {
541 self.0
542 }
543}
544
545#[derive(Copy, Clone)]
547pub struct NameType(c_int);
548
549impl NameType {
550 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
552
553 pub fn from_raw(raw: c_int) -> StatusType {
555 StatusType(raw)
556 }
557
558 #[allow(clippy::trivially_copy_pass_by_ref)]
560 pub fn as_raw(&self) -> c_int {
561 self.0
562 }
563}
564
565static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
566 LazyLock::new(|| Mutex::new(HashMap::new()));
567static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
568 LazyLock::new(|| Mutex::new(HashMap::new()));
569static SESSION_CTX_INDEX: OnceLock<Index<Ssl, SslContext>> = OnceLock::new();
570
571fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
572 if let Some(idx) = SESSION_CTX_INDEX.get() {
575 return Ok(idx);
576 }
577 let new = Ssl::new_ex_index::<SslContext>()?;
578 Ok(SESSION_CTX_INDEX.get_or_init(|| new))
579}
580
581unsafe extern "C" fn free_data_box<T>(
582 _parent: *mut c_void,
583 ptr: *mut c_void,
584 _ad: *mut ffi::CRYPTO_EX_DATA,
585 _idx: c_int,
586 _argl: c_long,
587 _argp: *mut c_void,
588) {
589 if !ptr.is_null() {
590 let _ = Box::<T>::from_raw(ptr as *mut T);
591 }
592}
593
594#[derive(Debug, Copy, Clone, PartialEq, Eq)]
596pub struct SniError(c_int);
597
598impl SniError {
599 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
601
602 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
604
605 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
606}
607
608#[derive(Debug, Copy, Clone, PartialEq, Eq)]
610pub struct SslAlert(c_int);
611
612impl SslAlert {
613 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
615 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
616 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
617}
618
619#[derive(Debug, Copy, Clone, PartialEq, Eq)]
623pub struct AlpnError(c_int);
624
625impl AlpnError {
626 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
628
629 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
631}
632
633#[cfg(ossl111)]
637#[derive(Debug, Copy, Clone, PartialEq, Eq)]
638pub struct ClientHelloResponse(c_int);
639
640#[cfg(ossl111)]
641impl ClientHelloResponse {
642 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
644
645 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
647}
648
649#[derive(Debug, Copy, Clone, PartialEq, Eq)]
651pub struct SslVersion(c_int);
652
653impl SslVersion {
654 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
656
657 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
659
660 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
662
663 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
665
666 #[cfg(any(ossl111, libressl, boringssl, awslc))]
670 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
671
672 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
676
677 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
681}
682
683cfg_if! {
684 if #[cfg(any(boringssl, awslc))] {
685 type SslCacheTy = i64;
686 type SslCacheSize = libc::c_ulong;
687 type MtuTy = u32;
688 type SizeTy = usize;
689 } else {
690 type SslCacheTy = i64;
691 type SslCacheSize = c_long;
692 type MtuTy = c_long;
693 type SizeTy = u32;
694 }
695}
696
697#[corresponds(SSL_select_next_proto)]
708pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
709 unsafe {
710 let mut out = ptr::null_mut();
711 let mut outlen = 0;
712 let r = ffi::SSL_select_next_proto(
713 &mut out,
714 &mut outlen,
715 server.as_ptr(),
716 server.len() as c_uint,
717 client.as_ptr(),
718 client.len() as c_uint,
719 );
720 if r == ffi::OPENSSL_NPN_NEGOTIATED {
721 Some(util::from_raw_parts(out as *const u8, outlen as usize))
722 } else {
723 None
724 }
725 }
726}
727
728pub struct SslContextBuilder(SslContext);
730
731impl SslContextBuilder {
732 #[corresponds(SSL_CTX_new)]
734 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
735 unsafe {
736 init();
737 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
738
739 Ok(SslContextBuilder::from_ptr(ctx))
740 }
741 }
742
743 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
749 SslContextBuilder(SslContext::from_ptr(ctx))
750 }
751
752 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
754 self.0.as_ptr()
755 }
756
757 #[corresponds(SSL_CTX_set_verify)]
759 pub fn set_verify(&mut self, mode: SslVerifyMode) {
760 unsafe {
761 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
762 }
763 }
764
765 #[corresponds(SSL_CTX_set_verify)]
772 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
773 where
774 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
775 {
776 unsafe {
777 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
778 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
779 }
780 }
781
782 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
790 pub fn set_servername_callback<F>(&mut self, callback: F)
792 where
793 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
794 {
795 unsafe {
796 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
802 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
803 #[cfg(any(boringssl, awslc))]
804 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
805 #[cfg(not(any(boringssl, awslc)))]
806 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
807 self.as_ptr(),
808 Some(raw_sni::<F>),
809 );
810 }
811 }
812
813 #[corresponds(SSL_CTX_set_verify_depth)]
817 pub fn set_verify_depth(&mut self, depth: u32) {
818 unsafe {
819 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
820 }
821 }
822
823 #[corresponds(SSL_CTX_set0_verify_cert_store)]
827 #[cfg(ossl110)]
828 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
829 unsafe {
830 let ptr = cert_store.as_ptr();
831 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
832 mem::forget(cert_store);
833
834 Ok(())
835 }
836 }
837
838 #[corresponds(SSL_CTX_set_cert_store)]
840 pub fn set_cert_store(&mut self, cert_store: X509Store) {
841 unsafe {
842 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
843 mem::forget(cert_store);
844 }
845 }
846
847 #[corresponds(SSL_CTX_set_read_ahead)]
854 pub fn set_read_ahead(&mut self, read_ahead: bool) {
855 unsafe {
856 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
857 }
858 }
859
860 #[corresponds(SSL_CTX_set_mode)]
862 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
863 unsafe {
864 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
865 SslMode::from_bits_retain(bits)
866 }
867 }
868
869 #[corresponds(SSL_CTX_set_tmp_dh)]
871 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
872 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
873 }
874
875 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
882 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
883 where
884 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
885 {
886 unsafe {
887 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
888
889 #[cfg(not(any(boringssl, awslc)))]
890 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
891 #[cfg(any(boringssl, awslc))]
892 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
893 }
894 }
895
896 #[corresponds(SSL_CTX_set_tmp_ecdh)]
898 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
899 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
900 }
901
902 #[corresponds(SSL_CTX_set_default_verify_paths)]
907 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
908 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
909 }
910
911 #[corresponds(SSL_CTX_load_verify_locations)]
915 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
916 self.load_verify_locations(Some(file.as_ref()), None)
917 }
918
919 #[corresponds(SSL_CTX_load_verify_locations)]
921 pub fn load_verify_locations(
922 &mut self,
923 ca_file: Option<&Path>,
924 ca_path: Option<&Path>,
925 ) -> Result<(), ErrorStack> {
926 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
927 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
928 unsafe {
929 cvt(ffi::SSL_CTX_load_verify_locations(
930 self.as_ptr(),
931 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
932 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
933 ))
934 .map(|_| ())
935 }
936 }
937
938 #[corresponds(SSL_CTX_set_client_CA_list)]
943 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
944 unsafe {
945 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
946 mem::forget(list);
947 }
948 }
949
950 #[corresponds(SSL_CTX_add_client_CA)]
953 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
954 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
955 }
956
957 #[corresponds(SSL_CTX_set_session_id_context)]
966 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
967 unsafe {
968 assert!(sid_ctx.len() <= c_uint::MAX as usize);
969 cvt(ffi::SSL_CTX_set_session_id_context(
970 self.as_ptr(),
971 sid_ctx.as_ptr(),
972 sid_ctx.len() as SizeTy,
973 ))
974 .map(|_| ())
975 }
976 }
977
978 #[corresponds(SSL_CTX_use_certificate_file)]
984 pub fn set_certificate_file<P: AsRef<Path>>(
985 &mut self,
986 file: P,
987 file_type: SslFiletype,
988 ) -> Result<(), ErrorStack> {
989 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
990 unsafe {
991 cvt(ffi::SSL_CTX_use_certificate_file(
992 self.as_ptr(),
993 file.as_ptr() as *const _,
994 file_type.as_raw(),
995 ))
996 .map(|_| ())
997 }
998 }
999
1000 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1006 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1007 &mut self,
1008 file: P,
1009 ) -> Result<(), ErrorStack> {
1010 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1011 unsafe {
1012 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1013 self.as_ptr(),
1014 file.as_ptr() as *const _,
1015 ))
1016 .map(|_| ())
1017 }
1018 }
1019
1020 #[corresponds(SSL_CTX_use_certificate)]
1024 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1025 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1026 }
1027
1028 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1033 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1034 unsafe {
1035 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1036 mem::forget(cert);
1037 Ok(())
1038 }
1039 }
1040
1041 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1043 pub fn set_private_key_file<P: AsRef<Path>>(
1044 &mut self,
1045 file: P,
1046 file_type: SslFiletype,
1047 ) -> Result<(), ErrorStack> {
1048 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1049 unsafe {
1050 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1051 self.as_ptr(),
1052 file.as_ptr() as *const _,
1053 file_type.as_raw(),
1054 ))
1055 .map(|_| ())
1056 }
1057 }
1058
1059 #[corresponds(SSL_CTX_use_PrivateKey)]
1061 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1062 where
1063 T: HasPrivate,
1064 {
1065 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1066 }
1067
1068 #[corresponds(SSL_CTX_set_cipher_list)]
1076 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1077 let cipher_list = CString::new(cipher_list).unwrap();
1078 unsafe {
1079 cvt(ffi::SSL_CTX_set_cipher_list(
1080 self.as_ptr(),
1081 cipher_list.as_ptr() as *const _,
1082 ))
1083 .map(|_| ())
1084 }
1085 }
1086
1087 #[corresponds(SSL_CTX_set_ciphersuites)]
1096 #[cfg(any(ossl111, libressl))]
1097 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1098 let cipher_list = CString::new(cipher_list).unwrap();
1099 unsafe {
1100 cvt(ffi::SSL_CTX_set_ciphersuites(
1101 self.as_ptr(),
1102 cipher_list.as_ptr() as *const _,
1103 ))
1104 .map(|_| ())
1105 }
1106 }
1107
1108 #[corresponds(SSL_CTX_set_ecdh_auto)]
1112 #[cfg(libressl)]
1113 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1114 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1115 }
1116
1117 #[corresponds(SSL_CTX_set_options)]
1124 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1125 let bits =
1126 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1127 SslOptions::from_bits_retain(bits)
1128 }
1129
1130 #[corresponds(SSL_CTX_get_options)]
1132 pub fn options(&self) -> SslOptions {
1133 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1134 SslOptions::from_bits_retain(bits)
1135 }
1136
1137 #[corresponds(SSL_CTX_clear_options)]
1139 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1140 let bits =
1141 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1142 SslOptions::from_bits_retain(bits)
1143 }
1144
1145 #[corresponds(SSL_CTX_set_min_proto_version)]
1150 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1151 unsafe {
1152 cvt(ffi::SSL_CTX_set_min_proto_version(
1153 self.as_ptr(),
1154 version.map_or(0, |v| v.0 as _),
1155 ))
1156 .map(|_| ())
1157 }
1158 }
1159
1160 #[corresponds(SSL_CTX_set_max_proto_version)]
1165 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1166 unsafe {
1167 cvt(ffi::SSL_CTX_set_max_proto_version(
1168 self.as_ptr(),
1169 version.map_or(0, |v| v.0 as _),
1170 ))
1171 .map(|_| ())
1172 }
1173 }
1174
1175 #[corresponds(SSL_CTX_get_min_proto_version)]
1182 #[cfg(any(ossl110g, libressl))]
1183 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1184 unsafe {
1185 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1186 if r == 0 {
1187 None
1188 } else {
1189 Some(SslVersion(r))
1190 }
1191 }
1192 }
1193
1194 #[corresponds(SSL_CTX_get_max_proto_version)]
1201 #[cfg(any(ossl110g, libressl))]
1202 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1203 unsafe {
1204 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1205 if r == 0 {
1206 None
1207 } else {
1208 Some(SslVersion(r))
1209 }
1210 }
1211 }
1212
1213 #[corresponds(SSL_CTX_set_alpn_protos)]
1222 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1223 unsafe {
1224 assert!(protocols.len() <= c_uint::MAX as usize);
1225 let r = ffi::SSL_CTX_set_alpn_protos(
1226 self.as_ptr(),
1227 protocols.as_ptr(),
1228 protocols.len() as _,
1229 );
1230 if r == 0 {
1232 Ok(())
1233 } else {
1234 Err(ErrorStack::get())
1235 }
1236 }
1237 }
1238
1239 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1241 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1242 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1243 unsafe {
1244 let cstr = CString::new(protocols).unwrap();
1245
1246 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1247 if r == 0 {
1249 Ok(())
1250 } else {
1251 Err(ErrorStack::get())
1252 }
1253 }
1254 }
1255
1256 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1269 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1270 where
1271 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1272 {
1273 unsafe {
1274 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1275 #[cfg(not(any(boringssl, awslc)))]
1276 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1277 self.as_ptr(),
1278 Some(callbacks::raw_alpn_select::<F>),
1279 ptr::null_mut(),
1280 );
1281 #[cfg(any(boringssl, awslc))]
1282 ffi::SSL_CTX_set_alpn_select_cb(
1283 self.as_ptr(),
1284 Some(callbacks::raw_alpn_select::<F>),
1285 ptr::null_mut(),
1286 );
1287 }
1288 }
1289
1290 #[corresponds(SSL_CTX_check_private_key)]
1292 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1293 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1294 }
1295
1296 #[corresponds(SSL_CTX_get_cert_store)]
1298 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1299 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1300 }
1301
1302 #[corresponds(SSL_CTX_get_cert_store)]
1304 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1305 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1306 }
1307
1308 #[corresponds(SSL_CTX_get0_param)]
1312 pub fn verify_param(&self) -> &X509VerifyParamRef {
1313 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1314 }
1315
1316 #[corresponds(SSL_CTX_get0_param)]
1320 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1321 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1322 }
1323
1324 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1337 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1338 where
1339 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1340 {
1341 unsafe {
1342 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1343 cvt(
1344 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1345 as c_int,
1346 )
1347 .map(|_| ())
1348 }
1349 }
1350
1351 #[corresponds(SSL_CTX_set_psk_client_callback)]
1357 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1358 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1359 where
1360 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1361 + 'static
1362 + Sync
1363 + Send,
1364 {
1365 unsafe {
1366 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1367 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1368 }
1369 }
1370
1371 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1372 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1373 pub fn set_psk_callback<F>(&mut self, callback: F)
1374 where
1375 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1376 + 'static
1377 + Sync
1378 + Send,
1379 {
1380 self.set_psk_client_callback(callback)
1381 }
1382
1383 #[corresponds(SSL_CTX_set_psk_server_callback)]
1389 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1390 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1391 where
1392 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1393 + 'static
1394 + Sync
1395 + Send,
1396 {
1397 unsafe {
1398 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1399 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1400 }
1401 }
1402
1403 #[corresponds(SSL_CTX_sess_set_new_cb)]
1417 pub fn set_new_session_callback<F>(&mut self, callback: F)
1418 where
1419 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1420 {
1421 unsafe {
1422 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1423 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1424 }
1425 }
1426
1427 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1431 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1432 where
1433 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1434 {
1435 unsafe {
1436 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1437 ffi::SSL_CTX_sess_set_remove_cb(
1438 self.as_ptr(),
1439 Some(callbacks::raw_remove_session::<F>),
1440 );
1441 }
1442 }
1443
1444 #[corresponds(SSL_CTX_sess_set_get_cb)]
1455 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1456 where
1457 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1458 {
1459 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1460 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1461 }
1462
1463 #[corresponds(SSL_CTX_set_keylog_callback)]
1471 #[cfg(any(ossl111, boringssl, awslc))]
1472 pub fn set_keylog_callback<F>(&mut self, callback: F)
1473 where
1474 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1475 {
1476 unsafe {
1477 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1478 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1479 }
1480 }
1481
1482 #[corresponds(SSL_CTX_set_session_cache_mode)]
1486 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1487 unsafe {
1488 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1489 SslSessionCacheMode::from_bits_retain(bits)
1490 }
1491 }
1492
1493 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1499 #[cfg(ossl111)]
1500 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1501 where
1502 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1503 {
1504 unsafe {
1505 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1506 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1507 self.as_ptr(),
1508 Some(raw_stateless_cookie_generate::<F>),
1509 );
1510 }
1511 }
1512
1513 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1522 #[cfg(ossl111)]
1523 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1524 where
1525 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1526 {
1527 unsafe {
1528 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1529 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1530 self.as_ptr(),
1531 Some(raw_stateless_cookie_verify::<F>),
1532 )
1533 }
1534 }
1535
1536 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1541 #[cfg(not(any(boringssl, awslc)))]
1542 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1543 where
1544 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1545 {
1546 unsafe {
1547 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1548 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1549 }
1550 }
1551
1552 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1557 #[cfg(not(any(boringssl, awslc)))]
1558 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1559 where
1560 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1561 {
1562 unsafe {
1563 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1564 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1565 }
1566 }
1567
1568 #[corresponds(SSL_CTX_set_ex_data)]
1574 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1575 self.set_ex_data_inner(index, data);
1576 }
1577
1578 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1579 match self.ex_data_mut(index) {
1580 Some(v) => {
1581 *v = data;
1582 (v as *mut T).cast()
1583 }
1584 _ => unsafe {
1585 let data = Box::into_raw(Box::new(data)) as *mut c_void;
1586 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1587 data
1588 },
1589 }
1590 }
1591
1592 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1593 unsafe {
1594 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1595 if data.is_null() {
1596 None
1597 } else {
1598 Some(&mut *data.cast())
1599 }
1600 }
1601 }
1602
1603 #[corresponds(SSL_CTX_add_custom_ext)]
1607 #[cfg(ossl111)]
1608 pub fn add_custom_ext<AddFn, ParseFn, T>(
1609 &mut self,
1610 ext_type: u16,
1611 context: ExtensionContext,
1612 add_cb: AddFn,
1613 parse_cb: ParseFn,
1614 ) -> Result<(), ErrorStack>
1615 where
1616 AddFn: Fn(
1617 &mut SslRef,
1618 ExtensionContext,
1619 Option<(usize, &X509Ref)>,
1620 ) -> Result<Option<T>, SslAlert>
1621 + 'static
1622 + Sync
1623 + Send,
1624 T: AsRef<[u8]> + 'static + Sync + Send,
1625 ParseFn: Fn(
1626 &mut SslRef,
1627 ExtensionContext,
1628 &[u8],
1629 Option<(usize, &X509Ref)>,
1630 ) -> Result<(), SslAlert>
1631 + 'static
1632 + Sync
1633 + Send,
1634 {
1635 let ret = unsafe {
1636 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1637 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1638
1639 ffi::SSL_CTX_add_custom_ext(
1640 self.as_ptr(),
1641 ext_type as c_uint,
1642 context.bits(),
1643 Some(raw_custom_ext_add::<AddFn, T>),
1644 Some(raw_custom_ext_free::<T>),
1645 ptr::null_mut(),
1646 Some(raw_custom_ext_parse::<ParseFn>),
1647 ptr::null_mut(),
1648 )
1649 };
1650 if ret == 1 {
1651 Ok(())
1652 } else {
1653 Err(ErrorStack::get())
1654 }
1655 }
1656
1657 #[corresponds(SSL_CTX_set_max_early_data)]
1663 #[cfg(any(ossl111, libressl))]
1664 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1665 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1666 Ok(())
1667 } else {
1668 Err(ErrorStack::get())
1669 }
1670 }
1671
1672 #[corresponds(SSL_CTX_set_client_hello_cb)]
1676 #[cfg(ossl111)]
1677 pub fn set_client_hello_callback<F>(&mut self, callback: F)
1678 where
1679 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1680 + 'static
1681 + Sync
1682 + Send,
1683 {
1684 unsafe {
1685 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1686 ffi::SSL_CTX_set_client_hello_cb(
1687 self.as_ptr(),
1688 Some(callbacks::raw_client_hello::<F>),
1689 ptr,
1690 );
1691 }
1692 }
1693
1694 #[corresponds(SSL_CTX_sess_set_cache_size)]
1698 #[allow(clippy::useless_conversion)]
1699 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1700 unsafe {
1701 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1702 }
1703 }
1704
1705 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1709 #[cfg(ossl110)]
1710 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1711 let sigalgs = CString::new(sigalgs).unwrap();
1712 unsafe {
1713 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1714 .map(|_| ())
1715 }
1716 }
1717
1718 #[corresponds(SSL_CTX_set1_groups_list)]
1722 #[cfg(any(ossl111, boringssl, libressl, awslc))]
1723 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1724 let groups = CString::new(groups).unwrap();
1725 unsafe {
1726 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1727 }
1728 }
1729
1730 #[corresponds(SSL_CTX_set_num_tickets)]
1735 #[cfg(ossl111)]
1736 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1737 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1738 }
1739
1740 #[corresponds(SSL_CTX_set_security_level)]
1745 #[cfg(any(ossl110, libressl360))]
1746 pub fn set_security_level(&mut self, level: u32) {
1747 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1748 }
1749
1750 pub fn build(self) -> SslContext {
1752 self.0
1753 }
1754}
1755
1756foreign_type_and_impl_send_sync! {
1757 type CType = ffi::SSL_CTX;
1758 fn drop = ffi::SSL_CTX_free;
1759
1760 pub struct SslContext;
1765
1766 pub struct SslContextRef;
1770}
1771
1772impl Clone for SslContext {
1773 fn clone(&self) -> Self {
1774 (**self).to_owned()
1775 }
1776}
1777
1778impl ToOwned for SslContextRef {
1779 type Owned = SslContext;
1780
1781 fn to_owned(&self) -> Self::Owned {
1782 unsafe {
1783 SSL_CTX_up_ref(self.as_ptr());
1784 SslContext::from_ptr(self.as_ptr())
1785 }
1786 }
1787}
1788
1789impl fmt::Debug for SslContext {
1791 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1792 write!(fmt, "SslContext")
1793 }
1794}
1795
1796impl SslContext {
1797 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1799 SslContextBuilder::new(method)
1800 }
1801
1802 #[corresponds(SSL_CTX_get_ex_new_index)]
1807 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1808 where
1809 T: 'static + Sync + Send,
1810 {
1811 unsafe {
1812 ffi::init();
1813 #[cfg(any(boringssl, awslc))]
1814 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1815 #[cfg(not(any(boringssl, awslc)))]
1816 let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1817 Ok(Index::from_raw(idx))
1818 }
1819 }
1820
1821 fn cached_ex_index<T>() -> Index<SslContext, T>
1823 where
1824 T: 'static + Sync + Send,
1825 {
1826 unsafe {
1827 let idx = *INDEXES
1828 .lock()
1829 .unwrap_or_else(|e| e.into_inner())
1830 .entry(TypeId::of::<T>())
1831 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1832 Index::from_raw(idx)
1833 }
1834 }
1835}
1836
1837impl SslContextRef {
1838 #[corresponds(SSL_CTX_get0_certificate)]
1842 #[cfg(any(ossl110, libressl))]
1843 pub fn certificate(&self) -> Option<&X509Ref> {
1844 unsafe {
1845 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1846 X509Ref::from_const_ptr_opt(ptr)
1847 }
1848 }
1849
1850 #[corresponds(SSL_CTX_get0_privatekey)]
1854 #[cfg(any(ossl110, libressl))]
1855 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1856 unsafe {
1857 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1858 PKeyRef::from_const_ptr_opt(ptr)
1859 }
1860 }
1861
1862 #[corresponds(SSL_CTX_get_cert_store)]
1864 pub fn cert_store(&self) -> &X509StoreRef {
1865 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1866 }
1867
1868 #[corresponds(SSL_CTX_get_extra_chain_certs)]
1870 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1871 unsafe {
1872 let mut chain = ptr::null_mut();
1873 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1874 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1875 }
1876 }
1877
1878 #[corresponds(SSL_CTX_get_ex_data)]
1880 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1881 unsafe {
1882 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1883 if data.is_null() {
1884 None
1885 } else {
1886 Some(&*(data as *const T))
1887 }
1888 }
1889 }
1890
1891 #[corresponds(SSL_CTX_get_max_early_data)]
1895 #[cfg(any(ossl111, libressl))]
1896 pub fn max_early_data(&self) -> u32 {
1897 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1898 }
1899
1900 #[corresponds(SSL_CTX_add_session)]
1909 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1910 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1911 }
1912
1913 #[corresponds(SSL_CTX_remove_session)]
1922 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
1923 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
1924 }
1925
1926 #[corresponds(SSL_CTX_sess_get_cache_size)]
1930 #[allow(clippy::unnecessary_cast)]
1931 pub fn session_cache_size(&self) -> i64 {
1932 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
1933 }
1934
1935 #[corresponds(SSL_CTX_get_verify_mode)]
1939 pub fn verify_mode(&self) -> SslVerifyMode {
1940 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
1941 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
1942 }
1943
1944 #[corresponds(SSL_CTX_get_num_tickets)]
1949 #[cfg(ossl111)]
1950 pub fn num_tickets(&self) -> usize {
1951 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
1952 }
1953
1954 #[corresponds(SSL_CTX_get_security_level)]
1959 #[cfg(any(ossl110, libressl360))]
1960 pub fn security_level(&self) -> u32 {
1961 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
1962 }
1963}
1964
1965pub struct CipherBits {
1967 pub secret: i32,
1969
1970 pub algorithm: i32,
1972}
1973
1974pub struct SslCipher(*mut ffi::SSL_CIPHER);
1976
1977impl ForeignType for SslCipher {
1978 type CType = ffi::SSL_CIPHER;
1979 type Ref = SslCipherRef;
1980
1981 #[inline]
1982 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
1983 SslCipher(ptr)
1984 }
1985
1986 #[inline]
1987 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
1988 self.0
1989 }
1990}
1991
1992impl Stackable for SslCipher {
1993 type StackType = ffi::stack_st_SSL_CIPHER;
1994}
1995
1996impl Deref for SslCipher {
1997 type Target = SslCipherRef;
1998
1999 fn deref(&self) -> &SslCipherRef {
2000 unsafe { SslCipherRef::from_ptr(self.0) }
2001 }
2002}
2003
2004impl DerefMut for SslCipher {
2005 fn deref_mut(&mut self) -> &mut SslCipherRef {
2006 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2007 }
2008}
2009
2010pub struct SslCipherRef(Opaque);
2014
2015impl ForeignTypeRef for SslCipherRef {
2016 type CType = ffi::SSL_CIPHER;
2017}
2018
2019impl SslCipherRef {
2020 #[corresponds(SSL_CIPHER_get_name)]
2022 pub fn name(&self) -> &'static str {
2023 unsafe {
2024 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2025 CStr::from_ptr(ptr).to_str().unwrap()
2026 }
2027 }
2028
2029 #[corresponds(SSL_CIPHER_standard_name)]
2033 #[cfg(ossl111)]
2034 pub fn standard_name(&self) -> Option<&'static str> {
2035 unsafe {
2036 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2037 if ptr.is_null() {
2038 None
2039 } else {
2040 Some(CStr::from_ptr(ptr).to_str().unwrap())
2041 }
2042 }
2043 }
2044
2045 #[corresponds(SSL_CIPHER_get_version)]
2047 pub fn version(&self) -> &'static str {
2048 let version = unsafe {
2049 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2050 CStr::from_ptr(ptr as *const _)
2051 };
2052
2053 str::from_utf8(version.to_bytes()).unwrap()
2054 }
2055
2056 #[corresponds(SSL_CIPHER_get_bits)]
2058 #[allow(clippy::useless_conversion)]
2059 pub fn bits(&self) -> CipherBits {
2060 unsafe {
2061 let mut algo_bits = 0;
2062 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2063 CipherBits {
2064 secret: secret_bits.into(),
2065 algorithm: algo_bits.into(),
2066 }
2067 }
2068 }
2069
2070 #[corresponds(SSL_CIPHER_description)]
2072 pub fn description(&self) -> String {
2073 unsafe {
2074 let mut buf = [0; 128];
2076 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2077 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2078 }
2079 }
2080
2081 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2085 #[cfg(ossl111)]
2086 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2087 unsafe {
2088 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2089 if ptr.is_null() {
2090 None
2091 } else {
2092 Some(MessageDigest::from_ptr(ptr))
2093 }
2094 }
2095 }
2096
2097 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2101 #[cfg(any(ossl110, libressl))]
2102 pub fn cipher_nid(&self) -> Option<Nid> {
2103 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2104 if n == 0 {
2105 None
2106 } else {
2107 Some(Nid::from_raw(n))
2108 }
2109 }
2110
2111 #[corresponds(SSL_CIPHER_get_protocol_id)]
2115 #[cfg(ossl111)]
2116 pub fn protocol_id(&self) -> [u8; 2] {
2117 unsafe {
2118 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2119 id.to_be_bytes()
2120 }
2121 }
2122}
2123
2124impl fmt::Debug for SslCipherRef {
2125 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2126 write!(fmt, "{}", self.name())
2127 }
2128}
2129
2130#[derive(Debug)]
2132pub struct CipherLists {
2133 pub suites: Stack<SslCipher>,
2134 pub signalling_suites: Stack<SslCipher>,
2135}
2136
2137foreign_type_and_impl_send_sync! {
2138 type CType = ffi::SSL_SESSION;
2139 fn drop = ffi::SSL_SESSION_free;
2140
2141 pub struct SslSession;
2145
2146 pub struct SslSessionRef;
2150}
2151
2152impl Clone for SslSession {
2153 fn clone(&self) -> SslSession {
2154 SslSessionRef::to_owned(self)
2155 }
2156}
2157
2158impl SslSession {
2159 from_der! {
2160 #[corresponds(d2i_SSL_SESSION)]
2162 from_der,
2163 SslSession,
2164 ffi::d2i_SSL_SESSION
2165 }
2166}
2167
2168impl ToOwned for SslSessionRef {
2169 type Owned = SslSession;
2170
2171 fn to_owned(&self) -> SslSession {
2172 unsafe {
2173 SSL_SESSION_up_ref(self.as_ptr());
2174 SslSession(self.as_ptr())
2175 }
2176 }
2177}
2178
2179impl SslSessionRef {
2180 #[corresponds(SSL_SESSION_get_id)]
2182 pub fn id(&self) -> &[u8] {
2183 unsafe {
2184 let mut len = 0;
2185 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2186 #[allow(clippy::unnecessary_cast)]
2187 util::from_raw_parts(p as *const u8, len as usize)
2188 }
2189 }
2190
2191 #[corresponds(SSL_SESSION_get_master_key)]
2193 pub fn master_key_len(&self) -> usize {
2194 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2195 }
2196
2197 #[corresponds(SSL_SESSION_get_master_key)]
2201 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2202 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2203 }
2204
2205 #[corresponds(SSL_SESSION_get_max_early_data)]
2209 #[cfg(any(ossl111, libressl))]
2210 pub fn max_early_data(&self) -> u32 {
2211 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2212 }
2213
2214 #[corresponds(SSL_SESSION_get_time)]
2216 #[allow(clippy::useless_conversion)]
2217 pub fn time(&self) -> SslTimeTy {
2218 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2219 }
2220
2221 #[corresponds(SSL_SESSION_get_timeout)]
2225 #[allow(clippy::useless_conversion)]
2226 pub fn timeout(&self) -> i64 {
2227 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2228 }
2229
2230 #[corresponds(SSL_SESSION_get_protocol_version)]
2234 #[cfg(any(ossl110, libressl))]
2235 pub fn protocol_version(&self) -> SslVersion {
2236 unsafe {
2237 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2238 SslVersion(version)
2239 }
2240 }
2241
2242 to_der! {
2243 #[corresponds(i2d_SSL_SESSION)]
2245 to_der,
2246 ffi::i2d_SSL_SESSION
2247 }
2248}
2249
2250foreign_type_and_impl_send_sync! {
2251 type CType = ffi::SSL;
2252 fn drop = ffi::SSL_free;
2253
2254 pub struct Ssl;
2261
2262 pub struct SslRef;
2266}
2267
2268impl fmt::Debug for Ssl {
2269 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2270 fmt::Debug::fmt(&**self, fmt)
2271 }
2272}
2273
2274impl Ssl {
2275 #[corresponds(SSL_get_ex_new_index)]
2280 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2281 where
2282 T: 'static + Sync + Send,
2283 {
2284 unsafe {
2285 ffi::init();
2286 #[cfg(any(boringssl, awslc))]
2287 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2288 #[cfg(not(any(boringssl, awslc)))]
2289 let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
2290 Ok(Index::from_raw(idx))
2291 }
2292 }
2293
2294 fn cached_ex_index<T>() -> Index<Ssl, T>
2296 where
2297 T: 'static + Sync + Send,
2298 {
2299 unsafe {
2300 let idx = *SSL_INDEXES
2301 .lock()
2302 .unwrap_or_else(|e| e.into_inner())
2303 .entry(TypeId::of::<T>())
2304 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2305 Index::from_raw(idx)
2306 }
2307 }
2308
2309 #[corresponds(SSL_new)]
2311 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2312 let session_ctx_index = try_get_session_ctx_index()?;
2313 unsafe {
2314 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2315 let mut ssl = Ssl::from_ptr(ptr);
2316 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2317
2318 Ok(ssl)
2319 }
2320 }
2321
2322 #[corresponds(SSL_connect)]
2328 #[allow(deprecated)]
2329 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2330 where
2331 S: Read + Write,
2332 {
2333 SslStreamBuilder::new(self, stream).connect()
2334 }
2335
2336 #[corresponds(SSL_accept)]
2343 #[allow(deprecated)]
2344 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2345 where
2346 S: Read + Write,
2347 {
2348 SslStreamBuilder::new(self, stream).accept()
2349 }
2350}
2351
2352impl fmt::Debug for SslRef {
2353 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2354 fmt.debug_struct("Ssl")
2355 .field("state", &self.state_string_long())
2356 .field("verify_result", &self.verify_result())
2357 .finish()
2358 }
2359}
2360
2361impl SslRef {
2362 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2363 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2364 }
2365
2366 fn get_error(&self, ret: c_int) -> ErrorCode {
2367 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2368 }
2369
2370 #[corresponds(SSL_set_connect_state)]
2372 pub fn set_connect_state(&mut self) {
2373 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2374 }
2375
2376 #[corresponds(SSL_set_accept_state)]
2378 pub fn set_accept_state(&mut self) {
2379 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2380 }
2381
2382 #[corresponds(SSL_set_verify)]
2386 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2387 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2388 }
2389
2390 #[corresponds(SSL_set_verify_mode)]
2392 pub fn verify_mode(&self) -> SslVerifyMode {
2393 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2394 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2395 }
2396
2397 #[corresponds(SSL_set_verify)]
2401 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2402 where
2403 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2404 {
2405 unsafe {
2406 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2408 ffi::SSL_set_verify(
2409 self.as_ptr(),
2410 mode.bits() as c_int,
2411 Some(ssl_raw_verify::<F>),
2412 );
2413 }
2414 }
2415
2416 #[corresponds(SSL_set_tmp_dh)]
2420 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2421 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2422 }
2423
2424 #[corresponds(SSL_set_tmp_dh_callback)]
2428 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2429 where
2430 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2431 {
2432 unsafe {
2433 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2435 #[cfg(any(boringssl, awslc))]
2436 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2437 #[cfg(not(any(boringssl, awslc)))]
2438 ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2439 }
2440 }
2441
2442 #[corresponds(SSL_set_tmp_ecdh)]
2446 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
2447 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
2448 }
2449
2450 #[corresponds(SSL_set_ecdh_auto)]
2456 #[cfg(libressl)]
2457 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2458 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2459 }
2460
2461 #[corresponds(SSL_set_alpn_protos)]
2467 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2468 unsafe {
2469 assert!(protocols.len() <= c_uint::MAX as usize);
2470 let r =
2471 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2472 if r == 0 {
2474 Ok(())
2475 } else {
2476 Err(ErrorStack::get())
2477 }
2478 }
2479 }
2480
2481 #[corresponds(SSL_get_current_cipher)]
2483 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2484 unsafe {
2485 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2486
2487 SslCipherRef::from_const_ptr_opt(ptr)
2488 }
2489 }
2490
2491 #[corresponds(SSL_state_string)]
2493 pub fn state_string(&self) -> &'static str {
2494 let state = unsafe {
2495 let ptr = ffi::SSL_state_string(self.as_ptr());
2496 CStr::from_ptr(ptr as *const _)
2497 };
2498
2499 str::from_utf8(state.to_bytes()).unwrap()
2500 }
2501
2502 #[corresponds(SSL_state_string_long)]
2504 pub fn state_string_long(&self) -> &'static str {
2505 let state = unsafe {
2506 let ptr = ffi::SSL_state_string_long(self.as_ptr());
2507 CStr::from_ptr(ptr as *const _)
2508 };
2509
2510 str::from_utf8(state.to_bytes()).unwrap()
2511 }
2512
2513 #[corresponds(SSL_set_tlsext_host_name)]
2517 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2518 let cstr = CString::new(hostname).unwrap();
2519 unsafe {
2520 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2521 .map(|_| ())
2522 }
2523 }
2524
2525 #[corresponds(SSL_get_peer_certificate)]
2527 pub fn peer_certificate(&self) -> Option<X509> {
2528 unsafe {
2529 let ptr = SSL_get1_peer_certificate(self.as_ptr());
2530 X509::from_ptr_opt(ptr)
2531 }
2532 }
2533
2534 #[corresponds(SSL_get_peer_cert_chain)]
2539 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2540 unsafe {
2541 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2542 StackRef::from_const_ptr_opt(ptr)
2543 }
2544 }
2545
2546 #[corresponds(SSL_get0_verified_chain)]
2556 #[cfg(ossl110)]
2557 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2558 unsafe {
2559 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2560 StackRef::from_const_ptr_opt(ptr)
2561 }
2562 }
2563
2564 #[corresponds(SSL_get_certificate)]
2566 pub fn certificate(&self) -> Option<&X509Ref> {
2567 unsafe {
2568 let ptr = ffi::SSL_get_certificate(self.as_ptr());
2569 X509Ref::from_const_ptr_opt(ptr)
2570 }
2571 }
2572
2573 #[corresponds(SSL_get_privatekey)]
2577 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2578 unsafe {
2579 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2580 PKeyRef::from_const_ptr_opt(ptr)
2581 }
2582 }
2583
2584 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2585 pub fn version(&self) -> &str {
2586 self.version_str()
2587 }
2588
2589 #[corresponds(SSL_version)]
2591 pub fn version2(&self) -> Option<SslVersion> {
2592 unsafe {
2593 let r = ffi::SSL_version(self.as_ptr());
2594 if r == 0 {
2595 None
2596 } else {
2597 Some(SslVersion(r))
2598 }
2599 }
2600 }
2601
2602 #[corresponds(SSL_get_version)]
2604 pub fn version_str(&self) -> &'static str {
2605 let version = unsafe {
2606 let ptr = ffi::SSL_get_version(self.as_ptr());
2607 CStr::from_ptr(ptr as *const _)
2608 };
2609
2610 str::from_utf8(version.to_bytes()).unwrap()
2611 }
2612
2613 #[corresponds(SSL_get0_alpn_selected)]
2620 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2621 unsafe {
2622 let mut data: *const c_uchar = ptr::null();
2623 let mut len: c_uint = 0;
2624 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2627
2628 if data.is_null() {
2629 None
2630 } else {
2631 Some(util::from_raw_parts(data, len as usize))
2632 }
2633 }
2634 }
2635
2636 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2638 #[corresponds(SSL_set_tlsext_use_srtp)]
2639 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2640 unsafe {
2641 let cstr = CString::new(protocols).unwrap();
2642
2643 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2644 if r == 0 {
2646 Ok(())
2647 } else {
2648 Err(ErrorStack::get())
2649 }
2650 }
2651 }
2652
2653 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2657 #[corresponds(SSL_get_srtp_profiles)]
2658 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
2659 unsafe {
2660 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
2661
2662 StackRef::from_const_ptr_opt(chain)
2663 }
2664 }
2665
2666 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2670 #[corresponds(SSL_get_selected_srtp_profile)]
2671 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2672 unsafe {
2673 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2674
2675 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2676 }
2677 }
2678
2679 #[corresponds(SSL_pending)]
2684 pub fn pending(&self) -> usize {
2685 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2686 }
2687
2688 #[corresponds(SSL_get_servername)]
2701 pub fn servername(&self, type_: NameType) -> Option<&str> {
2703 self.servername_raw(type_)
2704 .and_then(|b| str::from_utf8(b).ok())
2705 }
2706
2707 #[corresponds(SSL_get_servername)]
2715 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2716 unsafe {
2717 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2718 if name.is_null() {
2719 None
2720 } else {
2721 Some(CStr::from_ptr(name as *const _).to_bytes())
2722 }
2723 }
2724 }
2725
2726 #[corresponds(SSL_set_SSL_CTX)]
2730 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2731 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2732 }
2733
2734 #[corresponds(SSL_get_SSL_CTX)]
2736 pub fn ssl_context(&self) -> &SslContextRef {
2737 unsafe {
2738 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2739 SslContextRef::from_ptr(ssl_ctx)
2740 }
2741 }
2742
2743 #[corresponds(SSL_get0_param)]
2747 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
2748 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
2749 }
2750
2751 #[corresponds(SSL_get_verify_result)]
2753 pub fn verify_result(&self) -> X509VerifyResult {
2754 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
2755 }
2756
2757 #[corresponds(SSL_get_session)]
2759 pub fn session(&self) -> Option<&SslSessionRef> {
2760 unsafe {
2761 let p = ffi::SSL_get_session(self.as_ptr());
2762 SslSessionRef::from_const_ptr_opt(p)
2763 }
2764 }
2765
2766 #[corresponds(SSL_get_client_random)]
2773 #[cfg(any(ossl110, libressl))]
2774 pub fn client_random(&self, buf: &mut [u8]) -> usize {
2775 unsafe {
2776 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2777 }
2778 }
2779
2780 #[corresponds(SSL_get_server_random)]
2787 #[cfg(any(ossl110, libressl))]
2788 pub fn server_random(&self, buf: &mut [u8]) -> usize {
2789 unsafe {
2790 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2791 }
2792 }
2793
2794 #[corresponds(SSL_export_keying_material)]
2796 pub fn export_keying_material(
2797 &self,
2798 out: &mut [u8],
2799 label: &str,
2800 context: Option<&[u8]>,
2801 ) -> Result<(), ErrorStack> {
2802 unsafe {
2803 let (context, contextlen, use_context) = match context {
2804 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
2805 None => (ptr::null(), 0, 0),
2806 };
2807 cvt(ffi::SSL_export_keying_material(
2808 self.as_ptr(),
2809 out.as_mut_ptr() as *mut c_uchar,
2810 out.len(),
2811 label.as_ptr() as *const c_char,
2812 label.len(),
2813 context,
2814 contextlen,
2815 use_context,
2816 ))
2817 .map(|_| ())
2818 }
2819 }
2820
2821 #[corresponds(SSL_export_keying_material_early)]
2828 #[cfg(ossl111)]
2829 pub fn export_keying_material_early(
2830 &self,
2831 out: &mut [u8],
2832 label: &str,
2833 context: &[u8],
2834 ) -> Result<(), ErrorStack> {
2835 unsafe {
2836 cvt(ffi::SSL_export_keying_material_early(
2837 self.as_ptr(),
2838 out.as_mut_ptr() as *mut c_uchar,
2839 out.len(),
2840 label.as_ptr() as *const c_char,
2841 label.len(),
2842 context.as_ptr() as *const c_uchar,
2843 context.len(),
2844 ))
2845 .map(|_| ())
2846 }
2847 }
2848
2849 #[corresponds(SSL_set_session)]
2860 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
2861 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
2862 }
2863
2864 #[corresponds(SSL_session_reused)]
2866 pub fn session_reused(&self) -> bool {
2867 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
2868 }
2869
2870 #[corresponds(SSL_set_tlsext_status_type)]
2872 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
2873 unsafe {
2874 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
2875 }
2876 }
2877
2878 #[corresponds(SSL_get_extms_support)]
2882 #[cfg(ossl110)]
2883 pub fn extms_support(&self) -> Option<bool> {
2884 unsafe {
2885 match ffi::SSL_get_extms_support(self.as_ptr()) {
2886 -1 => None,
2887 ret => Some(ret != 0),
2888 }
2889 }
2890 }
2891
2892 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
2894 #[cfg(not(any(boringssl, awslc)))]
2895 pub fn ocsp_status(&self) -> Option<&[u8]> {
2896 unsafe {
2897 let mut p = ptr::null_mut();
2898 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
2899
2900 if len < 0 {
2901 None
2902 } else {
2903 Some(util::from_raw_parts(p as *const u8, len as usize))
2904 }
2905 }
2906 }
2907
2908 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
2910 #[cfg(not(any(boringssl, awslc)))]
2911 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
2912 unsafe {
2913 assert!(response.len() <= c_int::MAX as usize);
2914 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
2915 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
2916 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
2917 self.as_ptr(),
2918 p as *mut c_uchar,
2919 response.len() as c_long,
2920 ) as c_int)
2921 .map(|_| ())
2922 .inspect_err(|_| {
2923 ffi::OPENSSL_free(p);
2924 })
2925 }
2926 }
2927
2928 #[corresponds(SSL_is_server)]
2930 pub fn is_server(&self) -> bool {
2931 unsafe { SSL_is_server(self.as_ptr()) != 0 }
2932 }
2933
2934 #[corresponds(SSL_set_ex_data)]
2940 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
2941 match self.ex_data_mut(index) {
2942 Some(v) => *v = data,
2943 None => unsafe {
2944 let data = Box::new(data);
2945 ffi::SSL_set_ex_data(
2946 self.as_ptr(),
2947 index.as_raw(),
2948 Box::into_raw(data) as *mut c_void,
2949 );
2950 },
2951 }
2952 }
2953
2954 #[corresponds(SSL_get_ex_data)]
2956 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
2957 unsafe {
2958 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2959 if data.is_null() {
2960 None
2961 } else {
2962 Some(&*(data as *const T))
2963 }
2964 }
2965 }
2966
2967 #[corresponds(SSL_get_ex_data)]
2969 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
2970 unsafe {
2971 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2972 if data.is_null() {
2973 None
2974 } else {
2975 Some(&mut *(data as *mut T))
2976 }
2977 }
2978 }
2979
2980 #[corresponds(SSL_set_max_early_data)]
2984 #[cfg(any(ossl111, libressl))]
2985 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2986 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2987 Ok(())
2988 } else {
2989 Err(ErrorStack::get())
2990 }
2991 }
2992
2993 #[corresponds(SSL_get_max_early_data)]
2997 #[cfg(any(ossl111, libressl))]
2998 pub fn max_early_data(&self) -> u32 {
2999 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3000 }
3001
3002 #[corresponds(SSL_get_finished)]
3007 pub fn finished(&self, buf: &mut [u8]) -> usize {
3008 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3009 }
3010
3011 #[corresponds(SSL_get_peer_finished)]
3017 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3018 unsafe {
3019 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3020 }
3021 }
3022
3023 #[corresponds(SSL_is_init_finished)]
3025 #[cfg(ossl110)]
3026 pub fn is_init_finished(&self) -> bool {
3027 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3028 }
3029
3030 #[corresponds(SSL_client_hello_isv2)]
3036 #[cfg(ossl111)]
3037 pub fn client_hello_isv2(&self) -> bool {
3038 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3039 }
3040
3041 #[corresponds(SSL_client_hello_get0_legacy_version)]
3047 #[cfg(ossl111)]
3048 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3049 unsafe {
3050 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3051 if version == 0 {
3052 None
3053 } else {
3054 Some(SslVersion(version as c_int))
3055 }
3056 }
3057 }
3058
3059 #[corresponds(SSL_client_hello_get0_random)]
3065 #[cfg(ossl111)]
3066 pub fn client_hello_random(&self) -> Option<&[u8]> {
3067 unsafe {
3068 let mut ptr = ptr::null();
3069 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3070 if len == 0 {
3071 None
3072 } else {
3073 Some(util::from_raw_parts(ptr, len))
3074 }
3075 }
3076 }
3077
3078 #[corresponds(SSL_client_hello_get0_session_id)]
3084 #[cfg(ossl111)]
3085 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3086 unsafe {
3087 let mut ptr = ptr::null();
3088 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3089 if len == 0 {
3090 None
3091 } else {
3092 Some(util::from_raw_parts(ptr, len))
3093 }
3094 }
3095 }
3096
3097 #[corresponds(SSL_client_hello_get0_ciphers)]
3103 #[cfg(ossl111)]
3104 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3105 unsafe {
3106 let mut ptr = ptr::null();
3107 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3108 if len == 0 {
3109 None
3110 } else {
3111 Some(util::from_raw_parts(ptr, len))
3112 }
3113 }
3114 }
3115
3116 #[corresponds(SSL_bytes_to_cipher_list)]
3121 #[cfg(ossl111)]
3122 pub fn bytes_to_cipher_list(
3123 &self,
3124 bytes: &[u8],
3125 isv2format: bool,
3126 ) -> Result<CipherLists, ErrorStack> {
3127 unsafe {
3128 let ptr = bytes.as_ptr();
3129 let len = bytes.len();
3130 let mut sk = ptr::null_mut();
3131 let mut scsvs = ptr::null_mut();
3132 let res = ffi::SSL_bytes_to_cipher_list(
3133 self.as_ptr(),
3134 ptr,
3135 len,
3136 isv2format as c_int,
3137 &mut sk,
3138 &mut scsvs,
3139 );
3140 if res == 1 {
3141 Ok(CipherLists {
3142 suites: Stack::from_ptr(sk),
3143 signalling_suites: Stack::from_ptr(scsvs),
3144 })
3145 } else {
3146 Err(ErrorStack::get())
3147 }
3148 }
3149 }
3150
3151 #[corresponds(SSL_client_hello_get0_compression_methods)]
3157 #[cfg(ossl111)]
3158 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3159 unsafe {
3160 let mut ptr = ptr::null();
3161 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3162 if len == 0 {
3163 None
3164 } else {
3165 Some(util::from_raw_parts(ptr, len))
3166 }
3167 }
3168 }
3169
3170 #[corresponds(SSL_set_mtu)]
3172 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3173 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3174 }
3175
3176 #[corresponds(SSL_get_psk_identity_hint)]
3180 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3181 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3182 unsafe {
3183 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3184 if ptr.is_null() {
3185 None
3186 } else {
3187 Some(CStr::from_ptr(ptr).to_bytes())
3188 }
3189 }
3190 }
3191
3192 #[corresponds(SSL_get_psk_identity)]
3194 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3195 pub fn psk_identity(&self) -> Option<&[u8]> {
3196 unsafe {
3197 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3198 if ptr.is_null() {
3199 None
3200 } else {
3201 Some(CStr::from_ptr(ptr).to_bytes())
3202 }
3203 }
3204 }
3205
3206 #[corresponds(SSL_add0_chain_cert)]
3207 #[cfg(ossl110)]
3208 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3209 unsafe {
3210 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3211 mem::forget(chain);
3212 }
3213 Ok(())
3214 }
3215
3216 #[cfg(not(any(boringssl, awslc)))]
3218 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3219 unsafe {
3220 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3221 };
3222 Ok(())
3223 }
3224
3225 #[corresponds(SSL_use_Private_Key_file)]
3227 pub fn set_private_key_file<P: AsRef<Path>>(
3228 &mut self,
3229 path: P,
3230 ssl_file_type: SslFiletype,
3231 ) -> Result<(), ErrorStack> {
3232 let p = path.as_ref().as_os_str().to_str().unwrap();
3233 let key_file = CString::new(p).unwrap();
3234 unsafe {
3235 cvt(ffi::SSL_use_PrivateKey_file(
3236 self.as_ptr(),
3237 key_file.as_ptr(),
3238 ssl_file_type.as_raw(),
3239 ))?;
3240 };
3241 Ok(())
3242 }
3243
3244 #[corresponds(SSL_use_PrivateKey)]
3246 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3247 unsafe {
3248 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3249 };
3250 Ok(())
3251 }
3252
3253 #[corresponds(SSL_use_certificate)]
3255 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3256 unsafe {
3257 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3258 };
3259 Ok(())
3260 }
3261
3262 #[corresponds(SSL_use_certificate_chain_file)]
3268 #[cfg(any(ossl110, libressl))]
3269 pub fn set_certificate_chain_file<P: AsRef<Path>>(
3270 &mut self,
3271 path: P,
3272 ) -> Result<(), ErrorStack> {
3273 let p = path.as_ref().as_os_str().to_str().unwrap();
3274 let cert_file = CString::new(p).unwrap();
3275 unsafe {
3276 cvt(ffi::SSL_use_certificate_chain_file(
3277 self.as_ptr(),
3278 cert_file.as_ptr(),
3279 ))?;
3280 };
3281 Ok(())
3282 }
3283
3284 #[corresponds(SSL_add_client_CA)]
3286 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
3287 unsafe {
3288 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
3289 };
3290 Ok(())
3291 }
3292
3293 #[corresponds(SSL_set_client_CA_list)]
3295 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3296 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3297 mem::forget(list);
3298 }
3299
3300 #[corresponds(SSL_set_min_proto_version)]
3305 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3306 unsafe {
3307 cvt(ffi::SSL_set_min_proto_version(
3308 self.as_ptr(),
3309 version.map_or(0, |v| v.0 as _),
3310 ))
3311 .map(|_| ())
3312 }
3313 }
3314
3315 #[corresponds(SSL_set_max_proto_version)]
3320 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3321 unsafe {
3322 cvt(ffi::SSL_set_max_proto_version(
3323 self.as_ptr(),
3324 version.map_or(0, |v| v.0 as _),
3325 ))
3326 .map(|_| ())
3327 }
3328 }
3329
3330 #[corresponds(SSL_set_ciphersuites)]
3339 #[cfg(any(ossl111, libressl))]
3340 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3341 let cipher_list = CString::new(cipher_list).unwrap();
3342 unsafe {
3343 cvt(ffi::SSL_set_ciphersuites(
3344 self.as_ptr(),
3345 cipher_list.as_ptr() as *const _,
3346 ))
3347 .map(|_| ())
3348 }
3349 }
3350
3351 #[corresponds(SSL_set_cipher_list)]
3359 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3360 let cipher_list = CString::new(cipher_list).unwrap();
3361 unsafe {
3362 cvt(ffi::SSL_set_cipher_list(
3363 self.as_ptr(),
3364 cipher_list.as_ptr() as *const _,
3365 ))
3366 .map(|_| ())
3367 }
3368 }
3369
3370 #[corresponds(SSL_set_cert_store)]
3372 #[cfg(ossl110)]
3373 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3374 unsafe {
3375 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
3376 mem::forget(cert_store);
3377 Ok(())
3378 }
3379 }
3380
3381 #[corresponds(SSL_set_num_tickets)]
3386 #[cfg(ossl111)]
3387 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
3388 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
3389 }
3390
3391 #[corresponds(SSL_get_num_tickets)]
3396 #[cfg(ossl111)]
3397 pub fn num_tickets(&self) -> usize {
3398 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
3399 }
3400
3401 #[corresponds(SSL_set_security_level)]
3406 #[cfg(any(ossl110, libressl360))]
3407 pub fn set_security_level(&mut self, level: u32) {
3408 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
3409 }
3410
3411 #[corresponds(SSL_get_security_level)]
3416 #[cfg(any(ossl110, libressl360))]
3417 pub fn security_level(&self) -> u32 {
3418 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
3419 }
3420
3421 #[corresponds(SSL_get_peer_tmp_key)]
3426 #[cfg(ossl300)]
3427 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
3428 unsafe {
3429 let mut key = ptr::null_mut();
3430 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
3431 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
3432 Err(e) => Err(e),
3433 }
3434 }
3435 }
3436
3437 #[corresponds(SSL_get_tmp_key)]
3442 #[cfg(ossl300)]
3443 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
3444 unsafe {
3445 let mut key = ptr::null_mut();
3446 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
3447 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
3448 Err(e) => Err(e),
3449 }
3450 }
3451 }
3452}
3453
3454#[derive(Debug)]
3456pub struct MidHandshakeSslStream<S> {
3457 stream: SslStream<S>,
3458 error: Error,
3459}
3460
3461impl<S> MidHandshakeSslStream<S> {
3462 pub fn get_ref(&self) -> &S {
3464 self.stream.get_ref()
3465 }
3466
3467 pub fn get_mut(&mut self) -> &mut S {
3469 self.stream.get_mut()
3470 }
3471
3472 pub fn ssl(&self) -> &SslRef {
3474 self.stream.ssl()
3475 }
3476
3477 pub fn error(&self) -> &Error {
3479 &self.error
3480 }
3481
3482 pub fn into_error(self) -> Error {
3484 self.error
3485 }
3486}
3487
3488impl<S> MidHandshakeSslStream<S>
3489where
3490 S: Read + Write,
3491{
3492 #[corresponds(SSL_do_handshake)]
3495 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3496 match self.stream.do_handshake() {
3497 Ok(()) => Ok(self.stream),
3498 Err(error) => {
3499 self.error = error;
3500 match self.error.code() {
3501 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3502 Err(HandshakeError::WouldBlock(self))
3503 }
3504 _ => Err(HandshakeError::Failure(self)),
3505 }
3506 }
3507 }
3508 }
3509}
3510
3511pub struct SslStream<S> {
3513 ssl: ManuallyDrop<Ssl>,
3514 method: ManuallyDrop<BioMethod>,
3515 _p: PhantomData<S>,
3516}
3517
3518impl<S> Drop for SslStream<S> {
3519 fn drop(&mut self) {
3520 unsafe {
3522 ManuallyDrop::drop(&mut self.ssl);
3523 ManuallyDrop::drop(&mut self.method);
3524 }
3525 }
3526}
3527
3528impl<S> fmt::Debug for SslStream<S>
3529where
3530 S: fmt::Debug,
3531{
3532 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3533 fmt.debug_struct("SslStream")
3534 .field("stream", &self.get_ref())
3535 .field("ssl", &self.ssl())
3536 .finish()
3537 }
3538}
3539
3540impl<S: Read + Write> SslStream<S> {
3541 #[corresponds(SSL_set_bio)]
3549 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3550 let (bio, method) = bio::new(stream)?;
3551 unsafe {
3552 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3553 }
3554
3555 Ok(SslStream {
3556 ssl: ManuallyDrop::new(ssl),
3557 method: ManuallyDrop::new(method),
3558 _p: PhantomData,
3559 })
3560 }
3561
3562 #[deprecated(
3570 since = "0.10.32",
3571 note = "use Ssl::from_ptr and SslStream::new instead"
3572 )]
3573 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3574 let ssl = Ssl::from_ptr(ssl);
3575 Self::new(ssl, stream).unwrap()
3576 }
3577
3578 #[corresponds(SSL_read_early_data)]
3587 #[cfg(any(ossl111, libressl))]
3588 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3589 let mut read = 0;
3590 let ret = unsafe {
3591 ffi::SSL_read_early_data(
3592 self.ssl.as_ptr(),
3593 buf.as_ptr() as *mut c_void,
3594 buf.len(),
3595 &mut read,
3596 )
3597 };
3598 match ret {
3599 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
3600 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
3601 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
3602 _ => unreachable!(),
3603 }
3604 }
3605
3606 #[corresponds(SSL_write_early_data)]
3613 #[cfg(any(ossl111, libressl))]
3614 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
3615 let mut written = 0;
3616 let ret = unsafe {
3617 ffi::SSL_write_early_data(
3618 self.ssl.as_ptr(),
3619 buf.as_ptr() as *const c_void,
3620 buf.len(),
3621 &mut written,
3622 )
3623 };
3624 if ret > 0 {
3625 Ok(written)
3626 } else {
3627 Err(self.make_error(ret))
3628 }
3629 }
3630
3631 #[corresponds(SSL_connect)]
3638 pub fn connect(&mut self) -> Result<(), Error> {
3639 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
3640 if ret > 0 {
3641 Ok(())
3642 } else {
3643 Err(self.make_error(ret))
3644 }
3645 }
3646
3647 #[corresponds(SSL_accept)]
3654 pub fn accept(&mut self) -> Result<(), Error> {
3655 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
3656 if ret > 0 {
3657 Ok(())
3658 } else {
3659 Err(self.make_error(ret))
3660 }
3661 }
3662
3663 #[corresponds(SSL_do_handshake)]
3667 pub fn do_handshake(&mut self) -> Result<(), Error> {
3668 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
3669 if ret > 0 {
3670 Ok(())
3671 } else {
3672 Err(self.make_error(ret))
3673 }
3674 }
3675
3676 #[corresponds(SSL_stateless)]
3687 #[cfg(ossl111)]
3688 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
3689 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
3690 1 => Ok(true),
3691 0 => Ok(false),
3692 -1 => Err(ErrorStack::get()),
3693 _ => unreachable!(),
3694 }
3695 }
3696
3697 #[corresponds(SSL_read_ex)]
3704 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3705 loop {
3706 match self.ssl_read_uninit(buf) {
3707 Ok(n) => return Ok(n),
3708 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3709 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3710 return Ok(0);
3711 }
3712 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3713 Err(e) => {
3714 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
3715 }
3716 }
3717 }
3718 }
3719
3720 #[corresponds(SSL_read_ex)]
3725 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3726 unsafe {
3728 self.ssl_read_uninit(util::from_raw_parts_mut(
3729 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3730 buf.len(),
3731 ))
3732 }
3733 }
3734
3735 #[corresponds(SSL_read_ex)]
3742 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3743 if buf.is_empty() {
3744 return Ok(0);
3745 }
3746
3747 cfg_if! {
3748 if #[cfg(any(ossl111, libressl))] {
3749 let mut readbytes = 0;
3750 let ret = unsafe {
3751 ffi::SSL_read_ex(
3752 self.ssl().as_ptr(),
3753 buf.as_mut_ptr().cast(),
3754 buf.len(),
3755 &mut readbytes,
3756 )
3757 };
3758
3759 if ret > 0 {
3760 Ok(readbytes)
3761 } else {
3762 Err(self.make_error(ret))
3763 }
3764 } else {
3765 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3766 let ret = unsafe {
3767 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3768 };
3769 if ret > 0 {
3770 Ok(ret as usize)
3771 } else {
3772 Err(self.make_error(ret))
3773 }
3774 }
3775 }
3776 }
3777
3778 #[corresponds(SSL_write_ex)]
3783 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3784 if buf.is_empty() {
3785 return Ok(0);
3786 }
3787
3788 cfg_if! {
3789 if #[cfg(any(ossl111, libressl))] {
3790 let mut written = 0;
3791 let ret = unsafe {
3792 ffi::SSL_write_ex(
3793 self.ssl().as_ptr(),
3794 buf.as_ptr().cast(),
3795 buf.len(),
3796 &mut written,
3797 )
3798 };
3799
3800 if ret > 0 {
3801 Ok(written)
3802 } else {
3803 Err(self.make_error(ret))
3804 }
3805 } else {
3806 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3807 let ret = unsafe {
3808 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
3809 };
3810 if ret > 0 {
3811 Ok(ret as usize)
3812 } else {
3813 Err(self.make_error(ret))
3814 }
3815 }
3816 }
3817 }
3818
3819 #[corresponds(SSL_peek_ex)]
3821 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3822 cfg_if! {
3823 if #[cfg(any(ossl111, libressl))] {
3824 let mut readbytes = 0;
3825 let ret = unsafe {
3826 ffi::SSL_peek_ex(
3827 self.ssl().as_ptr(),
3828 buf.as_mut_ptr().cast(),
3829 buf.len(),
3830 &mut readbytes,
3831 )
3832 };
3833
3834 if ret > 0 {
3835 Ok(readbytes)
3836 } else {
3837 Err(self.make_error(ret))
3838 }
3839 } else {
3840 if buf.is_empty() {
3841 return Ok(0);
3842 }
3843
3844 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3845 let ret = unsafe {
3846 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3847 };
3848 if ret > 0 {
3849 Ok(ret as usize)
3850 } else {
3851 Err(self.make_error(ret))
3852 }
3853 }
3854 }
3855 }
3856
3857 #[corresponds(SSL_shutdown)]
3867 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
3868 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
3869 0 => Ok(ShutdownResult::Sent),
3870 1 => Ok(ShutdownResult::Received),
3871 n => Err(self.make_error(n)),
3872 }
3873 }
3874
3875 #[corresponds(SSL_get_shutdown)]
3877 pub fn get_shutdown(&mut self) -> ShutdownState {
3878 unsafe {
3879 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
3880 ShutdownState::from_bits_retain(bits)
3881 }
3882 }
3883
3884 #[corresponds(SSL_set_shutdown)]
3889 pub fn set_shutdown(&mut self, state: ShutdownState) {
3890 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
3891 }
3892}
3893
3894impl<S> SslStream<S> {
3895 fn make_error(&mut self, ret: c_int) -> Error {
3896 self.check_panic();
3897
3898 let code = self.ssl.get_error(ret);
3899
3900 let cause = match code {
3901 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
3902 ErrorCode::SYSCALL => {
3903 let errs = ErrorStack::get();
3904 if errs.errors().is_empty() {
3905 self.get_bio_error().map(InnerError::Io)
3906 } else {
3907 Some(InnerError::Ssl(errs))
3908 }
3909 }
3910 ErrorCode::ZERO_RETURN => None,
3911 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3912 self.get_bio_error().map(InnerError::Io)
3913 }
3914 _ => None,
3915 };
3916
3917 Error { code, cause }
3918 }
3919
3920 fn check_panic(&mut self) {
3921 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
3922 resume_unwind(err)
3923 }
3924 }
3925
3926 fn get_bio_error(&mut self) -> Option<io::Error> {
3927 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
3928 }
3929
3930 pub fn get_ref(&self) -> &S {
3932 unsafe {
3933 let bio = self.ssl.get_raw_rbio();
3934 bio::get_ref(bio)
3935 }
3936 }
3937
3938 pub fn get_mut(&mut self) -> &mut S {
3945 unsafe {
3946 let bio = self.ssl.get_raw_rbio();
3947 bio::get_mut(bio)
3948 }
3949 }
3950
3951 pub fn ssl(&self) -> &SslRef {
3953 &self.ssl
3954 }
3955}
3956
3957impl<S: Read + Write> Read for SslStream<S> {
3958 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3959 unsafe {
3961 self.read_uninit(util::from_raw_parts_mut(
3962 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3963 buf.len(),
3964 ))
3965 }
3966 }
3967}
3968
3969impl<S: Read + Write> Write for SslStream<S> {
3970 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
3971 loop {
3972 match self.ssl_write(buf) {
3973 Ok(n) => return Ok(n),
3974 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3975 Err(e) => {
3976 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
3977 }
3978 }
3979 }
3980 }
3981
3982 fn flush(&mut self) -> io::Result<()> {
3983 self.get_mut().flush()
3984 }
3985}
3986
3987#[deprecated(
3989 since = "0.10.32",
3990 note = "use the methods directly on Ssl/SslStream instead"
3991)]
3992pub struct SslStreamBuilder<S> {
3993 inner: SslStream<S>,
3994}
3995
3996#[allow(deprecated)]
3997impl<S> SslStreamBuilder<S>
3998where
3999 S: Read + Write,
4000{
4001 pub fn new(ssl: Ssl, stream: S) -> Self {
4003 Self {
4004 inner: SslStream::new(ssl, stream).unwrap(),
4005 }
4006 }
4007
4008 #[corresponds(SSL_stateless)]
4019 #[cfg(ossl111)]
4020 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4021 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4022 1 => Ok(true),
4023 0 => Ok(false),
4024 -1 => Err(ErrorStack::get()),
4025 _ => unreachable!(),
4026 }
4027 }
4028
4029 #[corresponds(SSL_set_connect_state)]
4031 pub fn set_connect_state(&mut self) {
4032 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4033 }
4034
4035 #[corresponds(SSL_set_accept_state)]
4037 pub fn set_accept_state(&mut self) {
4038 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4039 }
4040
4041 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4043 match self.inner.connect() {
4044 Ok(()) => Ok(self.inner),
4045 Err(error) => match error.code() {
4046 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4047 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4048 stream: self.inner,
4049 error,
4050 }))
4051 }
4052 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4053 stream: self.inner,
4054 error,
4055 })),
4056 },
4057 }
4058 }
4059
4060 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4062 match self.inner.accept() {
4063 Ok(()) => Ok(self.inner),
4064 Err(error) => match error.code() {
4065 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4066 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4067 stream: self.inner,
4068 error,
4069 }))
4070 }
4071 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4072 stream: self.inner,
4073 error,
4074 })),
4075 },
4076 }
4077 }
4078
4079 #[corresponds(SSL_do_handshake)]
4083 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4084 match self.inner.do_handshake() {
4085 Ok(()) => Ok(self.inner),
4086 Err(error) => match error.code() {
4087 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4088 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4089 stream: self.inner,
4090 error,
4091 }))
4092 }
4093 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4094 stream: self.inner,
4095 error,
4096 })),
4097 },
4098 }
4099 }
4100
4101 #[corresponds(SSL_read_early_data)]
4111 #[cfg(any(ossl111, libressl))]
4112 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4113 self.inner.read_early_data(buf)
4114 }
4115
4116 #[corresponds(SSL_write_early_data)]
4123 #[cfg(any(ossl111, libressl))]
4124 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4125 self.inner.write_early_data(buf)
4126 }
4127}
4128
4129#[allow(deprecated)]
4130impl<S> SslStreamBuilder<S> {
4131 pub fn get_ref(&self) -> &S {
4133 unsafe {
4134 let bio = self.inner.ssl.get_raw_rbio();
4135 bio::get_ref(bio)
4136 }
4137 }
4138
4139 pub fn get_mut(&mut self) -> &mut S {
4146 unsafe {
4147 let bio = self.inner.ssl.get_raw_rbio();
4148 bio::get_mut(bio)
4149 }
4150 }
4151
4152 pub fn ssl(&self) -> &SslRef {
4154 &self.inner.ssl
4155 }
4156
4157 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4165 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4166 unsafe {
4167 let bio = self.inner.ssl.get_raw_rbio();
4168 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4169 }
4170 }
4171}
4172
4173#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4175pub enum ShutdownResult {
4176 Sent,
4178
4179 Received,
4181}
4182
4183bitflags! {
4184 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4186 #[repr(transparent)]
4187 pub struct ShutdownState: c_int {
4188 const SENT = ffi::SSL_SENT_SHUTDOWN;
4190 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4192 }
4193}
4194
4195use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4196cfg_if! {
4197 if #[cfg(ossl300)] {
4198 use ffi::SSL_get1_peer_certificate;
4199 } else {
4200 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4201 }
4202}
4203use ffi::{
4204 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4205 TLS_server_method,
4206};
4207cfg_if! {
4208 if #[cfg(ossl110)] {
4209 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4210 ffi::CRYPTO_get_ex_new_index(
4211 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4212 0,
4213 ptr::null_mut(),
4214 None,
4215 None,
4216 Some(f),
4217 )
4218 }
4219
4220 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4221 ffi::CRYPTO_get_ex_new_index(
4222 ffi::CRYPTO_EX_INDEX_SSL,
4223 0,
4224 ptr::null_mut(),
4225 None,
4226 None,
4227 Some(f),
4228 )
4229 }
4230 } else {
4231 use std::sync::Once;
4232
4233 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4234 static ONCE: Once = Once::new();
4236 ONCE.call_once(|| {
4237 cfg_if! {
4238 if #[cfg(not(any(boringssl, awslc)))] {
4239 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4240 } else {
4241 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4242 }
4243 }
4244 });
4245
4246 cfg_if! {
4247 if #[cfg(not(any(boringssl, awslc)))] {
4248 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
4249 } else {
4250 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4251 }
4252 }
4253 }
4254
4255 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4256 static ONCE: Once = Once::new();
4258 ONCE.call_once(|| {
4259 #[cfg(not(any(boringssl, awslc)))]
4260 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4261 #[cfg(any(boringssl, awslc))]
4262 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4263 });
4264
4265 #[cfg(not(any(boringssl, awslc)))]
4266 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
4267 #[cfg(any(boringssl, awslc))]
4268 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
4269 }
4270 }
4271}