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 #[cfg(not(any(boringssl, awslc)))]
421 const CLIENT_ONCE = ffi::SSL_VERIFY_CLIENT_ONCE;
422
423 #[cfg(ossl111)]
430 const POST_HANDSHAKE = ffi::SSL_VERIFY_POST_HANDSHAKE;
431 }
432}
433
434#[cfg(any(boringssl, awslc))]
435type SslBitType = c_int;
436#[cfg(not(any(boringssl, awslc)))]
437type SslBitType = c_long;
438
439#[cfg(any(boringssl, awslc))]
440type SslTimeTy = u64;
441#[cfg(not(any(boringssl, awslc)))]
442type SslTimeTy = c_long;
443
444bitflags! {
445 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
447 #[repr(transparent)]
448 pub struct SslSessionCacheMode: SslBitType {
449 const OFF = ffi::SSL_SESS_CACHE_OFF;
451
452 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
459
460 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
464
465 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
467
468 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
470
471 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
473
474 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
476
477 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
479 }
480}
481
482#[cfg(ossl111)]
483bitflags! {
484 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
486 #[repr(transparent)]
487 pub struct ExtensionContext: c_uint {
488 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
490 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
492 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
494 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
496 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
498 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
500 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
502 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
503 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
505 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
506 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
507 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
508 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
509 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
510 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
511 }
512}
513
514#[derive(Copy, Clone)]
516pub struct SslFiletype(c_int);
517
518impl SslFiletype {
519 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
523
524 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
528
529 pub fn from_raw(raw: c_int) -> SslFiletype {
531 SslFiletype(raw)
532 }
533
534 #[allow(clippy::trivially_copy_pass_by_ref)]
536 pub fn as_raw(&self) -> c_int {
537 self.0
538 }
539}
540
541#[derive(Copy, Clone)]
543pub struct StatusType(c_int);
544
545impl StatusType {
546 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
548
549 pub fn from_raw(raw: c_int) -> StatusType {
551 StatusType(raw)
552 }
553
554 #[allow(clippy::trivially_copy_pass_by_ref)]
556 pub fn as_raw(&self) -> c_int {
557 self.0
558 }
559}
560
561#[derive(Copy, Clone)]
563pub struct NameType(c_int);
564
565impl NameType {
566 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
568
569 pub fn from_raw(raw: c_int) -> StatusType {
571 StatusType(raw)
572 }
573
574 #[allow(clippy::trivially_copy_pass_by_ref)]
576 pub fn as_raw(&self) -> c_int {
577 self.0
578 }
579}
580
581static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
582 LazyLock::new(|| Mutex::new(HashMap::new()));
583static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
584 LazyLock::new(|| Mutex::new(HashMap::new()));
585static SESSION_CTX_INDEX: OnceLock<Index<Ssl, SslContext>> = OnceLock::new();
586
587fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
588 if let Some(idx) = SESSION_CTX_INDEX.get() {
591 return Ok(idx);
592 }
593 let new = Ssl::new_ex_index::<SslContext>()?;
594 Ok(SESSION_CTX_INDEX.get_or_init(|| new))
595}
596
597unsafe extern "C" fn free_data_box<T>(
598 _parent: *mut c_void,
599 ptr: *mut c_void,
600 _ad: *mut ffi::CRYPTO_EX_DATA,
601 _idx: c_int,
602 _argl: c_long,
603 _argp: *mut c_void,
604) {
605 if !ptr.is_null() {
606 let _ = Box::<T>::from_raw(ptr as *mut T);
607 }
608}
609
610#[derive(Debug, Copy, Clone, PartialEq, Eq)]
612pub struct SniError(c_int);
613
614impl SniError {
615 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
617
618 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
620
621 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
622}
623
624#[derive(Debug, Copy, Clone, PartialEq, Eq)]
626pub struct SslAlert(c_int);
627
628impl SslAlert {
629 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
631 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
632 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
633}
634
635#[derive(Debug, Copy, Clone, PartialEq, Eq)]
639pub struct AlpnError(c_int);
640
641impl AlpnError {
642 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
644
645 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
647}
648
649#[cfg(ossl111)]
653#[derive(Debug, Copy, Clone, PartialEq, Eq)]
654pub struct ClientHelloResponse(c_int);
655
656#[cfg(ossl111)]
657impl ClientHelloResponse {
658 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
660
661 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
663}
664
665#[derive(Debug, Copy, Clone, PartialEq, Eq)]
667pub struct SslVersion(c_int);
668
669impl SslVersion {
670 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
672
673 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
675
676 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
678
679 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
681
682 #[cfg(any(ossl111, libressl, boringssl, awslc))]
686 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
687
688 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
692
693 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
697}
698
699cfg_if! {
700 if #[cfg(any(boringssl, awslc))] {
701 type SslCacheTy = i64;
702 type SslCacheSize = libc::c_ulong;
703 type MtuTy = u32;
704 type SizeTy = usize;
705 } else {
706 type SslCacheTy = i64;
707 type SslCacheSize = c_long;
708 type MtuTy = c_long;
709 type SizeTy = u32;
710 }
711}
712
713#[corresponds(SSL_select_next_proto)]
724pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
725 unsafe {
726 let mut out = ptr::null_mut();
727 let mut outlen = 0;
728 let r = ffi::SSL_select_next_proto(
729 &mut out,
730 &mut outlen,
731 server.as_ptr(),
732 server.len() as c_uint,
733 client.as_ptr(),
734 client.len() as c_uint,
735 );
736 if r == ffi::OPENSSL_NPN_NEGOTIATED {
737 Some(util::from_raw_parts(out as *const u8, outlen as usize))
738 } else {
739 None
740 }
741 }
742}
743
744pub struct SslContextBuilder(SslContext);
746
747impl SslContextBuilder {
748 #[corresponds(SSL_CTX_new)]
750 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
751 unsafe {
752 init();
753 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
754
755 Ok(SslContextBuilder::from_ptr(ctx))
756 }
757 }
758
759 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
765 SslContextBuilder(SslContext::from_ptr(ctx))
766 }
767
768 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
770 self.0.as_ptr()
771 }
772
773 #[corresponds(SSL_CTX_set_verify)]
775 pub fn set_verify(&mut self, mode: SslVerifyMode) {
776 unsafe {
777 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
778 }
779 }
780
781 #[corresponds(SSL_CTX_set_verify)]
788 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
789 where
790 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
791 {
792 unsafe {
793 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
794 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
795 }
796 }
797
798 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
806 pub fn set_servername_callback<F>(&mut self, callback: F)
808 where
809 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
810 {
811 unsafe {
812 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
818 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
819 #[cfg(any(boringssl, awslc))]
820 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
821 #[cfg(not(any(boringssl, awslc)))]
822 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
823 self.as_ptr(),
824 Some(raw_sni::<F>),
825 );
826 }
827 }
828
829 #[corresponds(SSL_CTX_set_verify_depth)]
833 pub fn set_verify_depth(&mut self, depth: u32) {
834 unsafe {
835 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
836 }
837 }
838
839 #[corresponds(SSL_CTX_set0_verify_cert_store)]
843 #[cfg(ossl110)]
844 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
845 unsafe {
846 let ptr = cert_store.as_ptr();
847 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
848 mem::forget(cert_store);
849
850 Ok(())
851 }
852 }
853
854 #[corresponds(SSL_CTX_set_cert_store)]
856 pub fn set_cert_store(&mut self, cert_store: X509Store) {
857 unsafe {
858 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
859 mem::forget(cert_store);
860 }
861 }
862
863 #[corresponds(SSL_CTX_set_read_ahead)]
870 pub fn set_read_ahead(&mut self, read_ahead: bool) {
871 unsafe {
872 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
873 }
874 }
875
876 #[corresponds(SSL_CTX_set_mode)]
878 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
879 unsafe {
880 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
881 SslMode::from_bits_retain(bits)
882 }
883 }
884
885 #[corresponds(SSL_CTX_set_tmp_dh)]
887 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
888 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
889 }
890
891 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
898 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
899 where
900 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
901 {
902 unsafe {
903 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
904
905 #[cfg(not(any(boringssl, awslc)))]
906 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
907 #[cfg(any(boringssl, awslc))]
908 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
909 }
910 }
911
912 #[corresponds(SSL_CTX_set_tmp_ecdh)]
914 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
915 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
916 }
917
918 #[corresponds(SSL_CTX_set_default_verify_paths)]
923 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
924 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
925 }
926
927 #[corresponds(SSL_CTX_load_verify_locations)]
931 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
932 self.load_verify_locations(Some(file.as_ref()), None)
933 }
934
935 #[corresponds(SSL_CTX_load_verify_locations)]
937 pub fn load_verify_locations(
938 &mut self,
939 ca_file: Option<&Path>,
940 ca_path: Option<&Path>,
941 ) -> Result<(), ErrorStack> {
942 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
943 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
944 unsafe {
945 cvt(ffi::SSL_CTX_load_verify_locations(
946 self.as_ptr(),
947 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
948 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
949 ))
950 .map(|_| ())
951 }
952 }
953
954 #[corresponds(SSL_CTX_set_client_CA_list)]
959 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
960 unsafe {
961 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
962 mem::forget(list);
963 }
964 }
965
966 #[corresponds(SSL_CTX_add_client_CA)]
969 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
970 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
971 }
972
973 #[corresponds(SSL_CTX_set_session_id_context)]
982 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
983 unsafe {
984 assert!(sid_ctx.len() <= c_uint::MAX as usize);
985 cvt(ffi::SSL_CTX_set_session_id_context(
986 self.as_ptr(),
987 sid_ctx.as_ptr(),
988 sid_ctx.len() as SizeTy,
989 ))
990 .map(|_| ())
991 }
992 }
993
994 #[corresponds(SSL_CTX_use_certificate_file)]
1000 pub fn set_certificate_file<P: AsRef<Path>>(
1001 &mut self,
1002 file: P,
1003 file_type: SslFiletype,
1004 ) -> Result<(), ErrorStack> {
1005 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1006 unsafe {
1007 cvt(ffi::SSL_CTX_use_certificate_file(
1008 self.as_ptr(),
1009 file.as_ptr() as *const _,
1010 file_type.as_raw(),
1011 ))
1012 .map(|_| ())
1013 }
1014 }
1015
1016 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1022 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1023 &mut self,
1024 file: P,
1025 ) -> Result<(), ErrorStack> {
1026 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1027 unsafe {
1028 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1029 self.as_ptr(),
1030 file.as_ptr() as *const _,
1031 ))
1032 .map(|_| ())
1033 }
1034 }
1035
1036 #[corresponds(SSL_CTX_use_certificate)]
1040 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1041 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1042 }
1043
1044 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1049 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1050 unsafe {
1051 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1052 mem::forget(cert);
1053 Ok(())
1054 }
1055 }
1056
1057 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1059 pub fn set_private_key_file<P: AsRef<Path>>(
1060 &mut self,
1061 file: P,
1062 file_type: SslFiletype,
1063 ) -> Result<(), ErrorStack> {
1064 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1065 unsafe {
1066 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1067 self.as_ptr(),
1068 file.as_ptr() as *const _,
1069 file_type.as_raw(),
1070 ))
1071 .map(|_| ())
1072 }
1073 }
1074
1075 #[corresponds(SSL_CTX_use_PrivateKey)]
1077 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1078 where
1079 T: HasPrivate,
1080 {
1081 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1082 }
1083
1084 #[corresponds(SSL_CTX_set_cipher_list)]
1092 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1093 let cipher_list = CString::new(cipher_list).unwrap();
1094 unsafe {
1095 cvt(ffi::SSL_CTX_set_cipher_list(
1096 self.as_ptr(),
1097 cipher_list.as_ptr() as *const _,
1098 ))
1099 .map(|_| ())
1100 }
1101 }
1102
1103 #[corresponds(SSL_CTX_set_ciphersuites)]
1112 #[cfg(any(ossl111, libressl))]
1113 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1114 let cipher_list = CString::new(cipher_list).unwrap();
1115 unsafe {
1116 cvt(ffi::SSL_CTX_set_ciphersuites(
1117 self.as_ptr(),
1118 cipher_list.as_ptr() as *const _,
1119 ))
1120 .map(|_| ())
1121 }
1122 }
1123
1124 #[corresponds(SSL_CTX_set_ecdh_auto)]
1128 #[cfg(libressl)]
1129 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1130 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1131 }
1132
1133 #[corresponds(SSL_CTX_set_options)]
1140 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1141 let bits =
1142 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1143 SslOptions::from_bits_retain(bits)
1144 }
1145
1146 #[corresponds(SSL_CTX_get_options)]
1148 pub fn options(&self) -> SslOptions {
1149 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1150 SslOptions::from_bits_retain(bits)
1151 }
1152
1153 #[corresponds(SSL_CTX_clear_options)]
1155 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1156 let bits =
1157 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1158 SslOptions::from_bits_retain(bits)
1159 }
1160
1161 #[corresponds(SSL_CTX_set_min_proto_version)]
1166 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1167 unsafe {
1168 cvt(ffi::SSL_CTX_set_min_proto_version(
1169 self.as_ptr(),
1170 version.map_or(0, |v| v.0 as _),
1171 ))
1172 .map(|_| ())
1173 }
1174 }
1175
1176 #[corresponds(SSL_CTX_set_max_proto_version)]
1181 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1182 unsafe {
1183 cvt(ffi::SSL_CTX_set_max_proto_version(
1184 self.as_ptr(),
1185 version.map_or(0, |v| v.0 as _),
1186 ))
1187 .map(|_| ())
1188 }
1189 }
1190
1191 #[corresponds(SSL_CTX_get_min_proto_version)]
1198 #[cfg(any(ossl110g, libressl))]
1199 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1200 unsafe {
1201 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1202 if r == 0 {
1203 None
1204 } else {
1205 Some(SslVersion(r))
1206 }
1207 }
1208 }
1209
1210 #[corresponds(SSL_CTX_get_max_proto_version)]
1217 #[cfg(any(ossl110g, libressl))]
1218 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1219 unsafe {
1220 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1221 if r == 0 {
1222 None
1223 } else {
1224 Some(SslVersion(r))
1225 }
1226 }
1227 }
1228
1229 #[corresponds(SSL_CTX_set_alpn_protos)]
1238 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1239 unsafe {
1240 assert!(protocols.len() <= c_uint::MAX as usize);
1241 let r = ffi::SSL_CTX_set_alpn_protos(
1242 self.as_ptr(),
1243 protocols.as_ptr(),
1244 protocols.len() as _,
1245 );
1246 if r == 0 {
1248 Ok(())
1249 } else {
1250 Err(ErrorStack::get())
1251 }
1252 }
1253 }
1254
1255 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1257 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1258 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1259 unsafe {
1260 let cstr = CString::new(protocols).unwrap();
1261
1262 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1263 if r == 0 {
1265 Ok(())
1266 } else {
1267 Err(ErrorStack::get())
1268 }
1269 }
1270 }
1271
1272 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1285 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1286 where
1287 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1288 {
1289 unsafe {
1290 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1291 #[cfg(not(any(boringssl, awslc)))]
1292 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1293 self.as_ptr(),
1294 Some(callbacks::raw_alpn_select::<F>),
1295 ptr::null_mut(),
1296 );
1297 #[cfg(any(boringssl, awslc))]
1298 ffi::SSL_CTX_set_alpn_select_cb(
1299 self.as_ptr(),
1300 Some(callbacks::raw_alpn_select::<F>),
1301 ptr::null_mut(),
1302 );
1303 }
1304 }
1305
1306 #[corresponds(SSL_CTX_check_private_key)]
1308 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1309 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1310 }
1311
1312 #[corresponds(SSL_CTX_get_cert_store)]
1314 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1315 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1316 }
1317
1318 #[corresponds(SSL_CTX_get_cert_store)]
1320 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1321 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1322 }
1323
1324 #[corresponds(SSL_CTX_get0_param)]
1328 pub fn verify_param(&self) -> &X509VerifyParamRef {
1329 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1330 }
1331
1332 #[corresponds(SSL_CTX_get0_param)]
1336 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1337 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1338 }
1339
1340 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1353 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1354 where
1355 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1356 {
1357 unsafe {
1358 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1359 cvt(
1360 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1361 as c_int,
1362 )
1363 .map(|_| ())
1364 }
1365 }
1366
1367 #[corresponds(SSL_CTX_set_psk_client_callback)]
1373 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1374 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1375 where
1376 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1377 + 'static
1378 + Sync
1379 + Send,
1380 {
1381 unsafe {
1382 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1383 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1384 }
1385 }
1386
1387 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1388 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1389 pub fn set_psk_callback<F>(&mut self, callback: F)
1390 where
1391 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1392 + 'static
1393 + Sync
1394 + Send,
1395 {
1396 self.set_psk_client_callback(callback)
1397 }
1398
1399 #[corresponds(SSL_CTX_set_psk_server_callback)]
1405 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1406 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1407 where
1408 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1409 + 'static
1410 + Sync
1411 + Send,
1412 {
1413 unsafe {
1414 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1415 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1416 }
1417 }
1418
1419 #[corresponds(SSL_CTX_sess_set_new_cb)]
1433 pub fn set_new_session_callback<F>(&mut self, callback: F)
1434 where
1435 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1436 {
1437 unsafe {
1438 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1439 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1440 }
1441 }
1442
1443 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1447 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1448 where
1449 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1450 {
1451 unsafe {
1452 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1453 ffi::SSL_CTX_sess_set_remove_cb(
1454 self.as_ptr(),
1455 Some(callbacks::raw_remove_session::<F>),
1456 );
1457 }
1458 }
1459
1460 #[corresponds(SSL_CTX_sess_set_get_cb)]
1471 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1472 where
1473 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1474 {
1475 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1476 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1477 }
1478
1479 #[corresponds(SSL_CTX_set_keylog_callback)]
1487 #[cfg(any(ossl111, boringssl, awslc))]
1488 pub fn set_keylog_callback<F>(&mut self, callback: F)
1489 where
1490 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1491 {
1492 unsafe {
1493 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1494 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1495 }
1496 }
1497
1498 #[corresponds(SSL_CTX_set_session_cache_mode)]
1502 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1503 unsafe {
1504 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1505 SslSessionCacheMode::from_bits_retain(bits)
1506 }
1507 }
1508
1509 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1515 #[cfg(ossl111)]
1516 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1517 where
1518 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1519 {
1520 unsafe {
1521 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1522 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1523 self.as_ptr(),
1524 Some(raw_stateless_cookie_generate::<F>),
1525 );
1526 }
1527 }
1528
1529 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1538 #[cfg(ossl111)]
1539 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1540 where
1541 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1542 {
1543 unsafe {
1544 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1545 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1546 self.as_ptr(),
1547 Some(raw_stateless_cookie_verify::<F>),
1548 )
1549 }
1550 }
1551
1552 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1557 #[cfg(not(any(boringssl, awslc)))]
1558 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1559 where
1560 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1561 {
1562 unsafe {
1563 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1564 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1565 }
1566 }
1567
1568 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1573 #[cfg(not(any(boringssl, awslc)))]
1574 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1575 where
1576 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1577 {
1578 unsafe {
1579 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1580 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1581 }
1582 }
1583
1584 #[corresponds(SSL_CTX_set_ex_data)]
1590 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1591 self.set_ex_data_inner(index, data);
1592 }
1593
1594 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1595 match self.ex_data_mut(index) {
1596 Some(v) => {
1597 *v = data;
1598 (v as *mut T).cast()
1599 }
1600 _ => unsafe {
1601 let data = Box::into_raw(Box::new(data)) as *mut c_void;
1602 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1603 data
1604 },
1605 }
1606 }
1607
1608 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1609 unsafe {
1610 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1611 if data.is_null() {
1612 None
1613 } else {
1614 Some(&mut *data.cast())
1615 }
1616 }
1617 }
1618
1619 #[corresponds(SSL_CTX_add_custom_ext)]
1623 #[cfg(ossl111)]
1624 pub fn add_custom_ext<AddFn, ParseFn, T>(
1625 &mut self,
1626 ext_type: u16,
1627 context: ExtensionContext,
1628 add_cb: AddFn,
1629 parse_cb: ParseFn,
1630 ) -> Result<(), ErrorStack>
1631 where
1632 AddFn: Fn(
1633 &mut SslRef,
1634 ExtensionContext,
1635 Option<(usize, &X509Ref)>,
1636 ) -> Result<Option<T>, SslAlert>
1637 + 'static
1638 + Sync
1639 + Send,
1640 T: AsRef<[u8]> + 'static + Sync + Send,
1641 ParseFn: Fn(
1642 &mut SslRef,
1643 ExtensionContext,
1644 &[u8],
1645 Option<(usize, &X509Ref)>,
1646 ) -> Result<(), SslAlert>
1647 + 'static
1648 + Sync
1649 + Send,
1650 {
1651 let ret = unsafe {
1652 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1653 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1654
1655 ffi::SSL_CTX_add_custom_ext(
1656 self.as_ptr(),
1657 ext_type as c_uint,
1658 context.bits(),
1659 Some(raw_custom_ext_add::<AddFn, T>),
1660 Some(raw_custom_ext_free::<T>),
1661 ptr::null_mut(),
1662 Some(raw_custom_ext_parse::<ParseFn>),
1663 ptr::null_mut(),
1664 )
1665 };
1666 if ret == 1 {
1667 Ok(())
1668 } else {
1669 Err(ErrorStack::get())
1670 }
1671 }
1672
1673 #[corresponds(SSL_CTX_set_max_early_data)]
1679 #[cfg(any(ossl111, libressl))]
1680 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1681 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1682 Ok(())
1683 } else {
1684 Err(ErrorStack::get())
1685 }
1686 }
1687
1688 #[corresponds(SSL_CTX_set_client_hello_cb)]
1692 #[cfg(ossl111)]
1693 pub fn set_client_hello_callback<F>(&mut self, callback: F)
1694 where
1695 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1696 + 'static
1697 + Sync
1698 + Send,
1699 {
1700 unsafe {
1701 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1702 ffi::SSL_CTX_set_client_hello_cb(
1703 self.as_ptr(),
1704 Some(callbacks::raw_client_hello::<F>),
1705 ptr,
1706 );
1707 }
1708 }
1709
1710 #[corresponds(SSL_CTX_sess_set_cache_size)]
1714 #[allow(clippy::useless_conversion)]
1715 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1716 unsafe {
1717 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1718 }
1719 }
1720
1721 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1725 #[cfg(ossl110)]
1726 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1727 let sigalgs = CString::new(sigalgs).unwrap();
1728 unsafe {
1729 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1730 .map(|_| ())
1731 }
1732 }
1733
1734 #[corresponds(SSL_CTX_set1_groups_list)]
1738 #[cfg(any(ossl111, boringssl, libressl, awslc))]
1739 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1740 let groups = CString::new(groups).unwrap();
1741 unsafe {
1742 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1743 }
1744 }
1745
1746 #[corresponds(SSL_CTX_set_num_tickets)]
1751 #[cfg(ossl111)]
1752 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1753 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1754 }
1755
1756 #[corresponds(SSL_CTX_set_security_level)]
1761 #[cfg(any(ossl110, libressl360))]
1762 pub fn set_security_level(&mut self, level: u32) {
1763 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1764 }
1765
1766 pub fn build(self) -> SslContext {
1768 self.0
1769 }
1770}
1771
1772foreign_type_and_impl_send_sync! {
1773 type CType = ffi::SSL_CTX;
1774 fn drop = ffi::SSL_CTX_free;
1775
1776 pub struct SslContext;
1781
1782 pub struct SslContextRef;
1786}
1787
1788impl Clone for SslContext {
1789 fn clone(&self) -> Self {
1790 (**self).to_owned()
1791 }
1792}
1793
1794impl ToOwned for SslContextRef {
1795 type Owned = SslContext;
1796
1797 fn to_owned(&self) -> Self::Owned {
1798 unsafe {
1799 SSL_CTX_up_ref(self.as_ptr());
1800 SslContext::from_ptr(self.as_ptr())
1801 }
1802 }
1803}
1804
1805impl fmt::Debug for SslContext {
1807 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1808 write!(fmt, "SslContext")
1809 }
1810}
1811
1812impl SslContext {
1813 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1815 SslContextBuilder::new(method)
1816 }
1817
1818 #[corresponds(SSL_CTX_get_ex_new_index)]
1823 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1824 where
1825 T: 'static + Sync + Send,
1826 {
1827 unsafe {
1828 ffi::init();
1829 #[cfg(any(boringssl, awslc))]
1830 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1831 #[cfg(not(any(boringssl, awslc)))]
1832 let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1833 Ok(Index::from_raw(idx))
1834 }
1835 }
1836
1837 fn cached_ex_index<T>() -> Index<SslContext, T>
1839 where
1840 T: 'static + Sync + Send,
1841 {
1842 unsafe {
1843 let idx = *INDEXES
1844 .lock()
1845 .unwrap_or_else(|e| e.into_inner())
1846 .entry(TypeId::of::<T>())
1847 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1848 Index::from_raw(idx)
1849 }
1850 }
1851}
1852
1853impl SslContextRef {
1854 #[corresponds(SSL_CTX_get0_certificate)]
1858 #[cfg(any(ossl110, libressl))]
1859 pub fn certificate(&self) -> Option<&X509Ref> {
1860 unsafe {
1861 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1862 X509Ref::from_const_ptr_opt(ptr)
1863 }
1864 }
1865
1866 #[corresponds(SSL_CTX_get0_privatekey)]
1870 #[cfg(any(ossl110, libressl))]
1871 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1872 unsafe {
1873 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1874 PKeyRef::from_const_ptr_opt(ptr)
1875 }
1876 }
1877
1878 #[corresponds(SSL_CTX_get_cert_store)]
1880 pub fn cert_store(&self) -> &X509StoreRef {
1881 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1882 }
1883
1884 #[corresponds(SSL_CTX_get_extra_chain_certs)]
1886 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1887 unsafe {
1888 let mut chain = ptr::null_mut();
1889 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1890 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1891 }
1892 }
1893
1894 #[corresponds(SSL_CTX_get_ex_data)]
1896 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1897 unsafe {
1898 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1899 if data.is_null() {
1900 None
1901 } else {
1902 Some(&*(data as *const T))
1903 }
1904 }
1905 }
1906
1907 #[corresponds(SSL_CTX_get_max_early_data)]
1911 #[cfg(any(ossl111, libressl))]
1912 pub fn max_early_data(&self) -> u32 {
1913 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1914 }
1915
1916 #[corresponds(SSL_CTX_add_session)]
1925 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1926 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1927 }
1928
1929 #[corresponds(SSL_CTX_remove_session)]
1938 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
1939 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
1940 }
1941
1942 #[corresponds(SSL_CTX_sess_get_cache_size)]
1946 #[allow(clippy::unnecessary_cast)]
1947 pub fn session_cache_size(&self) -> i64 {
1948 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
1949 }
1950
1951 #[corresponds(SSL_CTX_get_verify_mode)]
1955 pub fn verify_mode(&self) -> SslVerifyMode {
1956 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
1957 SslVerifyMode::from_bits_retain(mode)
1958 }
1959
1960 #[corresponds(SSL_CTX_get_num_tickets)]
1965 #[cfg(ossl111)]
1966 pub fn num_tickets(&self) -> usize {
1967 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
1968 }
1969
1970 #[corresponds(SSL_CTX_get_security_level)]
1975 #[cfg(any(ossl110, libressl360))]
1976 pub fn security_level(&self) -> u32 {
1977 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
1978 }
1979}
1980
1981pub struct CipherBits {
1983 pub secret: i32,
1985
1986 pub algorithm: i32,
1988}
1989
1990pub struct SslCipher(*mut ffi::SSL_CIPHER);
1992
1993impl ForeignType for SslCipher {
1994 type CType = ffi::SSL_CIPHER;
1995 type Ref = SslCipherRef;
1996
1997 #[inline]
1998 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
1999 SslCipher(ptr)
2000 }
2001
2002 #[inline]
2003 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2004 self.0
2005 }
2006}
2007
2008impl Stackable for SslCipher {
2009 type StackType = ffi::stack_st_SSL_CIPHER;
2010}
2011
2012impl Deref for SslCipher {
2013 type Target = SslCipherRef;
2014
2015 fn deref(&self) -> &SslCipherRef {
2016 unsafe { SslCipherRef::from_ptr(self.0) }
2017 }
2018}
2019
2020impl DerefMut for SslCipher {
2021 fn deref_mut(&mut self) -> &mut SslCipherRef {
2022 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2023 }
2024}
2025
2026pub struct SslCipherRef(Opaque);
2030
2031impl ForeignTypeRef for SslCipherRef {
2032 type CType = ffi::SSL_CIPHER;
2033}
2034
2035impl SslCipherRef {
2036 #[corresponds(SSL_CIPHER_get_name)]
2038 pub fn name(&self) -> &'static str {
2039 unsafe {
2040 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2041 CStr::from_ptr(ptr).to_str().unwrap()
2042 }
2043 }
2044
2045 #[corresponds(SSL_CIPHER_standard_name)]
2049 #[cfg(ossl111)]
2050 pub fn standard_name(&self) -> Option<&'static str> {
2051 unsafe {
2052 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2053 if ptr.is_null() {
2054 None
2055 } else {
2056 Some(CStr::from_ptr(ptr).to_str().unwrap())
2057 }
2058 }
2059 }
2060
2061 #[corresponds(SSL_CIPHER_get_version)]
2063 pub fn version(&self) -> &'static str {
2064 let version = unsafe {
2065 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2066 CStr::from_ptr(ptr as *const _)
2067 };
2068
2069 str::from_utf8(version.to_bytes()).unwrap()
2070 }
2071
2072 #[corresponds(SSL_CIPHER_get_bits)]
2074 #[allow(clippy::useless_conversion)]
2075 pub fn bits(&self) -> CipherBits {
2076 unsafe {
2077 let mut algo_bits = 0;
2078 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2079 CipherBits {
2080 secret: secret_bits.into(),
2081 algorithm: algo_bits.into(),
2082 }
2083 }
2084 }
2085
2086 #[corresponds(SSL_CIPHER_description)]
2088 pub fn description(&self) -> String {
2089 unsafe {
2090 let mut buf = [0; 128];
2092 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2093 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2094 }
2095 }
2096
2097 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2101 #[cfg(ossl111)]
2102 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2103 unsafe {
2104 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2105 if ptr.is_null() {
2106 None
2107 } else {
2108 Some(MessageDigest::from_ptr(ptr))
2109 }
2110 }
2111 }
2112
2113 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2117 #[cfg(any(ossl110, libressl))]
2118 pub fn cipher_nid(&self) -> Option<Nid> {
2119 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2120 if n == 0 {
2121 None
2122 } else {
2123 Some(Nid::from_raw(n))
2124 }
2125 }
2126
2127 #[corresponds(SSL_CIPHER_get_protocol_id)]
2131 #[cfg(ossl111)]
2132 pub fn protocol_id(&self) -> [u8; 2] {
2133 unsafe {
2134 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2135 id.to_be_bytes()
2136 }
2137 }
2138}
2139
2140impl fmt::Debug for SslCipherRef {
2141 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2142 write!(fmt, "{}", self.name())
2143 }
2144}
2145
2146#[derive(Debug)]
2148pub struct CipherLists {
2149 pub suites: Stack<SslCipher>,
2150 pub signalling_suites: Stack<SslCipher>,
2151}
2152
2153foreign_type_and_impl_send_sync! {
2154 type CType = ffi::SSL_SESSION;
2155 fn drop = ffi::SSL_SESSION_free;
2156
2157 pub struct SslSession;
2161
2162 pub struct SslSessionRef;
2166}
2167
2168impl Clone for SslSession {
2169 fn clone(&self) -> SslSession {
2170 SslSessionRef::to_owned(self)
2171 }
2172}
2173
2174impl SslSession {
2175 from_der! {
2176 #[corresponds(d2i_SSL_SESSION)]
2178 from_der,
2179 SslSession,
2180 ffi::d2i_SSL_SESSION
2181 }
2182}
2183
2184impl ToOwned for SslSessionRef {
2185 type Owned = SslSession;
2186
2187 fn to_owned(&self) -> SslSession {
2188 unsafe {
2189 SSL_SESSION_up_ref(self.as_ptr());
2190 SslSession(self.as_ptr())
2191 }
2192 }
2193}
2194
2195impl SslSessionRef {
2196 #[corresponds(SSL_SESSION_get_id)]
2198 pub fn id(&self) -> &[u8] {
2199 unsafe {
2200 let mut len = 0;
2201 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2202 #[allow(clippy::unnecessary_cast)]
2203 util::from_raw_parts(p as *const u8, len as usize)
2204 }
2205 }
2206
2207 #[corresponds(SSL_SESSION_get_master_key)]
2209 pub fn master_key_len(&self) -> usize {
2210 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2211 }
2212
2213 #[corresponds(SSL_SESSION_get_master_key)]
2217 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2218 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2219 }
2220
2221 #[corresponds(SSL_SESSION_get_max_early_data)]
2225 #[cfg(any(ossl111, libressl))]
2226 pub fn max_early_data(&self) -> u32 {
2227 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2228 }
2229
2230 #[corresponds(SSL_SESSION_get_time)]
2232 #[allow(clippy::useless_conversion)]
2233 pub fn time(&self) -> SslTimeTy {
2234 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2235 }
2236
2237 #[corresponds(SSL_SESSION_get_timeout)]
2241 #[allow(clippy::useless_conversion)]
2242 pub fn timeout(&self) -> i64 {
2243 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2244 }
2245
2246 #[corresponds(SSL_SESSION_get_protocol_version)]
2250 #[cfg(any(ossl110, libressl))]
2251 pub fn protocol_version(&self) -> SslVersion {
2252 unsafe {
2253 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2254 SslVersion(version)
2255 }
2256 }
2257
2258 to_der! {
2259 #[corresponds(i2d_SSL_SESSION)]
2261 to_der,
2262 ffi::i2d_SSL_SESSION
2263 }
2264}
2265
2266foreign_type_and_impl_send_sync! {
2267 type CType = ffi::SSL;
2268 fn drop = ffi::SSL_free;
2269
2270 pub struct Ssl;
2277
2278 pub struct SslRef;
2282}
2283
2284impl fmt::Debug for Ssl {
2285 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2286 fmt::Debug::fmt(&**self, fmt)
2287 }
2288}
2289
2290impl Ssl {
2291 #[corresponds(SSL_get_ex_new_index)]
2296 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2297 where
2298 T: 'static + Sync + Send,
2299 {
2300 unsafe {
2301 ffi::init();
2302 #[cfg(any(boringssl, awslc))]
2303 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2304 #[cfg(not(any(boringssl, awslc)))]
2305 let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
2306 Ok(Index::from_raw(idx))
2307 }
2308 }
2309
2310 fn cached_ex_index<T>() -> Index<Ssl, T>
2312 where
2313 T: 'static + Sync + Send,
2314 {
2315 unsafe {
2316 let idx = *SSL_INDEXES
2317 .lock()
2318 .unwrap_or_else(|e| e.into_inner())
2319 .entry(TypeId::of::<T>())
2320 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2321 Index::from_raw(idx)
2322 }
2323 }
2324
2325 #[corresponds(SSL_new)]
2327 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2328 let session_ctx_index = try_get_session_ctx_index()?;
2329 unsafe {
2330 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2331 let mut ssl = Ssl::from_ptr(ptr);
2332 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2333
2334 Ok(ssl)
2335 }
2336 }
2337
2338 #[corresponds(SSL_connect)]
2344 #[allow(deprecated)]
2345 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2346 where
2347 S: Read + Write,
2348 {
2349 SslStreamBuilder::new(self, stream).connect()
2350 }
2351
2352 #[corresponds(SSL_accept)]
2359 #[allow(deprecated)]
2360 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2361 where
2362 S: Read + Write,
2363 {
2364 SslStreamBuilder::new(self, stream).accept()
2365 }
2366}
2367
2368impl fmt::Debug for SslRef {
2369 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2370 fmt.debug_struct("Ssl")
2371 .field("state", &self.state_string_long())
2372 .field("verify_result", &self.verify_result())
2373 .finish()
2374 }
2375}
2376
2377impl SslRef {
2378 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2379 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2380 }
2381
2382 fn get_error(&self, ret: c_int) -> ErrorCode {
2383 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2384 }
2385
2386 #[corresponds(SSL_set_connect_state)]
2388 pub fn set_connect_state(&mut self) {
2389 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2390 }
2391
2392 #[corresponds(SSL_set_accept_state)]
2394 pub fn set_accept_state(&mut self) {
2395 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2396 }
2397
2398 #[corresponds(SSL_set_verify)]
2402 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2403 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2404 }
2405
2406 #[corresponds(SSL_set_verify_mode)]
2408 pub fn verify_mode(&self) -> SslVerifyMode {
2409 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2410 SslVerifyMode::from_bits_retain(mode)
2411 }
2412
2413 #[corresponds(SSL_set_verify)]
2417 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2418 where
2419 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2420 {
2421 unsafe {
2422 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2424 ffi::SSL_set_verify(
2425 self.as_ptr(),
2426 mode.bits() as c_int,
2427 Some(ssl_raw_verify::<F>),
2428 );
2429 }
2430 }
2431
2432 #[corresponds(SSL_set_tmp_dh)]
2436 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2437 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2438 }
2439
2440 #[corresponds(SSL_set_tmp_dh_callback)]
2444 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2445 where
2446 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2447 {
2448 unsafe {
2449 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2451 #[cfg(any(boringssl, awslc))]
2452 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2453 #[cfg(not(any(boringssl, awslc)))]
2454 ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2455 }
2456 }
2457
2458 #[corresponds(SSL_set_tmp_ecdh)]
2462 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
2463 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
2464 }
2465
2466 #[corresponds(SSL_set_ecdh_auto)]
2472 #[cfg(libressl)]
2473 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2474 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2475 }
2476
2477 #[corresponds(SSL_set_alpn_protos)]
2483 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2484 unsafe {
2485 assert!(protocols.len() <= c_uint::MAX as usize);
2486 let r =
2487 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2488 if r == 0 {
2490 Ok(())
2491 } else {
2492 Err(ErrorStack::get())
2493 }
2494 }
2495 }
2496
2497 #[corresponds(SSL_get_current_cipher)]
2499 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2500 unsafe {
2501 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2502
2503 SslCipherRef::from_const_ptr_opt(ptr)
2504 }
2505 }
2506
2507 #[corresponds(SSL_state_string)]
2509 pub fn state_string(&self) -> &'static str {
2510 let state = unsafe {
2511 let ptr = ffi::SSL_state_string(self.as_ptr());
2512 CStr::from_ptr(ptr as *const _)
2513 };
2514
2515 str::from_utf8(state.to_bytes()).unwrap()
2516 }
2517
2518 #[corresponds(SSL_state_string_long)]
2520 pub fn state_string_long(&self) -> &'static str {
2521 let state = unsafe {
2522 let ptr = ffi::SSL_state_string_long(self.as_ptr());
2523 CStr::from_ptr(ptr as *const _)
2524 };
2525
2526 str::from_utf8(state.to_bytes()).unwrap()
2527 }
2528
2529 #[corresponds(SSL_set_tlsext_host_name)]
2533 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2534 let cstr = CString::new(hostname).unwrap();
2535 unsafe {
2536 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2537 .map(|_| ())
2538 }
2539 }
2540
2541 #[corresponds(SSL_get_peer_certificate)]
2543 pub fn peer_certificate(&self) -> Option<X509> {
2544 unsafe {
2545 let ptr = SSL_get1_peer_certificate(self.as_ptr());
2546 X509::from_ptr_opt(ptr)
2547 }
2548 }
2549
2550 #[corresponds(SSL_get_peer_cert_chain)]
2555 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2556 unsafe {
2557 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2558 StackRef::from_const_ptr_opt(ptr)
2559 }
2560 }
2561
2562 #[corresponds(SSL_get0_verified_chain)]
2572 #[cfg(ossl110)]
2573 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2574 unsafe {
2575 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2576 StackRef::from_const_ptr_opt(ptr)
2577 }
2578 }
2579
2580 #[corresponds(SSL_get_certificate)]
2582 pub fn certificate(&self) -> Option<&X509Ref> {
2583 unsafe {
2584 let ptr = ffi::SSL_get_certificate(self.as_ptr());
2585 X509Ref::from_const_ptr_opt(ptr)
2586 }
2587 }
2588
2589 #[corresponds(SSL_get_privatekey)]
2593 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2594 unsafe {
2595 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2596 PKeyRef::from_const_ptr_opt(ptr)
2597 }
2598 }
2599
2600 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2601 pub fn version(&self) -> &str {
2602 self.version_str()
2603 }
2604
2605 #[corresponds(SSL_version)]
2607 pub fn version2(&self) -> Option<SslVersion> {
2608 unsafe {
2609 let r = ffi::SSL_version(self.as_ptr());
2610 if r == 0 {
2611 None
2612 } else {
2613 Some(SslVersion(r))
2614 }
2615 }
2616 }
2617
2618 #[corresponds(SSL_get_version)]
2620 pub fn version_str(&self) -> &'static str {
2621 let version = unsafe {
2622 let ptr = ffi::SSL_get_version(self.as_ptr());
2623 CStr::from_ptr(ptr as *const _)
2624 };
2625
2626 str::from_utf8(version.to_bytes()).unwrap()
2627 }
2628
2629 #[corresponds(SSL_get0_alpn_selected)]
2636 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2637 unsafe {
2638 let mut data: *const c_uchar = ptr::null();
2639 let mut len: c_uint = 0;
2640 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2643
2644 if data.is_null() {
2645 None
2646 } else {
2647 Some(util::from_raw_parts(data, len as usize))
2648 }
2649 }
2650 }
2651
2652 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2654 #[corresponds(SSL_set_tlsext_use_srtp)]
2655 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2656 unsafe {
2657 let cstr = CString::new(protocols).unwrap();
2658
2659 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2660 if r == 0 {
2662 Ok(())
2663 } else {
2664 Err(ErrorStack::get())
2665 }
2666 }
2667 }
2668
2669 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2673 #[corresponds(SSL_get_srtp_profiles)]
2674 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
2675 unsafe {
2676 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
2677
2678 StackRef::from_const_ptr_opt(chain)
2679 }
2680 }
2681
2682 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2686 #[corresponds(SSL_get_selected_srtp_profile)]
2687 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2688 unsafe {
2689 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2690
2691 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2692 }
2693 }
2694
2695 #[corresponds(SSL_pending)]
2700 pub fn pending(&self) -> usize {
2701 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2702 }
2703
2704 #[corresponds(SSL_get_servername)]
2717 pub fn servername(&self, type_: NameType) -> Option<&str> {
2719 self.servername_raw(type_)
2720 .and_then(|b| str::from_utf8(b).ok())
2721 }
2722
2723 #[corresponds(SSL_get_servername)]
2731 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2732 unsafe {
2733 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2734 if name.is_null() {
2735 None
2736 } else {
2737 Some(CStr::from_ptr(name as *const _).to_bytes())
2738 }
2739 }
2740 }
2741
2742 #[corresponds(SSL_set_SSL_CTX)]
2746 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2747 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2748 }
2749
2750 #[corresponds(SSL_get_SSL_CTX)]
2752 pub fn ssl_context(&self) -> &SslContextRef {
2753 unsafe {
2754 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2755 SslContextRef::from_ptr(ssl_ctx)
2756 }
2757 }
2758
2759 #[corresponds(SSL_get0_param)]
2763 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
2764 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
2765 }
2766
2767 #[corresponds(SSL_get_verify_result)]
2769 pub fn verify_result(&self) -> X509VerifyResult {
2770 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
2771 }
2772
2773 #[corresponds(SSL_get_session)]
2775 pub fn session(&self) -> Option<&SslSessionRef> {
2776 unsafe {
2777 let p = ffi::SSL_get_session(self.as_ptr());
2778 SslSessionRef::from_const_ptr_opt(p)
2779 }
2780 }
2781
2782 #[corresponds(SSL_get_client_random)]
2789 #[cfg(any(ossl110, libressl))]
2790 pub fn client_random(&self, buf: &mut [u8]) -> usize {
2791 unsafe {
2792 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2793 }
2794 }
2795
2796 #[corresponds(SSL_get_server_random)]
2803 #[cfg(any(ossl110, libressl))]
2804 pub fn server_random(&self, buf: &mut [u8]) -> usize {
2805 unsafe {
2806 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2807 }
2808 }
2809
2810 #[corresponds(SSL_export_keying_material)]
2812 pub fn export_keying_material(
2813 &self,
2814 out: &mut [u8],
2815 label: &str,
2816 context: Option<&[u8]>,
2817 ) -> Result<(), ErrorStack> {
2818 unsafe {
2819 let (context, contextlen, use_context) = match context {
2820 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
2821 None => (ptr::null(), 0, 0),
2822 };
2823 cvt(ffi::SSL_export_keying_material(
2824 self.as_ptr(),
2825 out.as_mut_ptr() as *mut c_uchar,
2826 out.len(),
2827 label.as_ptr() as *const c_char,
2828 label.len(),
2829 context,
2830 contextlen,
2831 use_context,
2832 ))
2833 .map(|_| ())
2834 }
2835 }
2836
2837 #[corresponds(SSL_export_keying_material_early)]
2844 #[cfg(ossl111)]
2845 pub fn export_keying_material_early(
2846 &self,
2847 out: &mut [u8],
2848 label: &str,
2849 context: &[u8],
2850 ) -> Result<(), ErrorStack> {
2851 unsafe {
2852 cvt(ffi::SSL_export_keying_material_early(
2853 self.as_ptr(),
2854 out.as_mut_ptr() as *mut c_uchar,
2855 out.len(),
2856 label.as_ptr() as *const c_char,
2857 label.len(),
2858 context.as_ptr() as *const c_uchar,
2859 context.len(),
2860 ))
2861 .map(|_| ())
2862 }
2863 }
2864
2865 #[corresponds(SSL_set_session)]
2876 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
2877 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
2878 }
2879
2880 #[corresponds(SSL_session_reused)]
2882 pub fn session_reused(&self) -> bool {
2883 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
2884 }
2885
2886 #[corresponds(SSL_set_tlsext_status_type)]
2888 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
2889 unsafe {
2890 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
2891 }
2892 }
2893
2894 #[corresponds(SSL_get_extms_support)]
2898 #[cfg(ossl110)]
2899 pub fn extms_support(&self) -> Option<bool> {
2900 unsafe {
2901 match ffi::SSL_get_extms_support(self.as_ptr()) {
2902 -1 => None,
2903 ret => Some(ret != 0),
2904 }
2905 }
2906 }
2907
2908 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
2910 #[cfg(not(any(boringssl, awslc)))]
2911 pub fn ocsp_status(&self) -> Option<&[u8]> {
2912 unsafe {
2913 let mut p = ptr::null_mut();
2914 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
2915
2916 if len < 0 {
2917 None
2918 } else {
2919 Some(util::from_raw_parts(p as *const u8, len as usize))
2920 }
2921 }
2922 }
2923
2924 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
2926 #[cfg(not(any(boringssl, awslc)))]
2927 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
2928 unsafe {
2929 assert!(response.len() <= c_int::MAX as usize);
2930 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
2931 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
2932 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
2933 self.as_ptr(),
2934 p as *mut c_uchar,
2935 response.len() as c_long,
2936 ) as c_int)
2937 .map(|_| ())
2938 .inspect_err(|_| {
2939 ffi::OPENSSL_free(p);
2940 })
2941 }
2942 }
2943
2944 #[corresponds(SSL_is_server)]
2946 pub fn is_server(&self) -> bool {
2947 unsafe { SSL_is_server(self.as_ptr()) != 0 }
2948 }
2949
2950 #[corresponds(SSL_set_ex_data)]
2956 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
2957 match self.ex_data_mut(index) {
2958 Some(v) => *v = data,
2959 None => unsafe {
2960 let data = Box::new(data);
2961 ffi::SSL_set_ex_data(
2962 self.as_ptr(),
2963 index.as_raw(),
2964 Box::into_raw(data) as *mut c_void,
2965 );
2966 },
2967 }
2968 }
2969
2970 #[corresponds(SSL_get_ex_data)]
2972 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
2973 unsafe {
2974 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2975 if data.is_null() {
2976 None
2977 } else {
2978 Some(&*(data as *const T))
2979 }
2980 }
2981 }
2982
2983 #[corresponds(SSL_get_ex_data)]
2985 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
2986 unsafe {
2987 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2988 if data.is_null() {
2989 None
2990 } else {
2991 Some(&mut *(data as *mut T))
2992 }
2993 }
2994 }
2995
2996 #[corresponds(SSL_set_max_early_data)]
3000 #[cfg(any(ossl111, libressl))]
3001 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3002 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3003 Ok(())
3004 } else {
3005 Err(ErrorStack::get())
3006 }
3007 }
3008
3009 #[corresponds(SSL_get_max_early_data)]
3013 #[cfg(any(ossl111, libressl))]
3014 pub fn max_early_data(&self) -> u32 {
3015 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3016 }
3017
3018 #[corresponds(SSL_get_finished)]
3023 pub fn finished(&self, buf: &mut [u8]) -> usize {
3024 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3025 }
3026
3027 #[corresponds(SSL_get_peer_finished)]
3033 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3034 unsafe {
3035 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3036 }
3037 }
3038
3039 #[corresponds(SSL_is_init_finished)]
3041 #[cfg(ossl110)]
3042 pub fn is_init_finished(&self) -> bool {
3043 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3044 }
3045
3046 #[corresponds(SSL_client_hello_isv2)]
3052 #[cfg(ossl111)]
3053 pub fn client_hello_isv2(&self) -> bool {
3054 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3055 }
3056
3057 #[corresponds(SSL_client_hello_get0_legacy_version)]
3063 #[cfg(ossl111)]
3064 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3065 unsafe {
3066 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3067 if version == 0 {
3068 None
3069 } else {
3070 Some(SslVersion(version as c_int))
3071 }
3072 }
3073 }
3074
3075 #[corresponds(SSL_client_hello_get0_random)]
3081 #[cfg(ossl111)]
3082 pub fn client_hello_random(&self) -> Option<&[u8]> {
3083 unsafe {
3084 let mut ptr = ptr::null();
3085 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3086 if len == 0 {
3087 None
3088 } else {
3089 Some(util::from_raw_parts(ptr, len))
3090 }
3091 }
3092 }
3093
3094 #[corresponds(SSL_client_hello_get0_session_id)]
3100 #[cfg(ossl111)]
3101 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3102 unsafe {
3103 let mut ptr = ptr::null();
3104 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3105 if len == 0 {
3106 None
3107 } else {
3108 Some(util::from_raw_parts(ptr, len))
3109 }
3110 }
3111 }
3112
3113 #[corresponds(SSL_client_hello_get0_ciphers)]
3119 #[cfg(ossl111)]
3120 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3121 unsafe {
3122 let mut ptr = ptr::null();
3123 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3124 if len == 0 {
3125 None
3126 } else {
3127 Some(util::from_raw_parts(ptr, len))
3128 }
3129 }
3130 }
3131
3132 #[corresponds(SSL_bytes_to_cipher_list)]
3137 #[cfg(ossl111)]
3138 pub fn bytes_to_cipher_list(
3139 &self,
3140 bytes: &[u8],
3141 isv2format: bool,
3142 ) -> Result<CipherLists, ErrorStack> {
3143 unsafe {
3144 let ptr = bytes.as_ptr();
3145 let len = bytes.len();
3146 let mut sk = ptr::null_mut();
3147 let mut scsvs = ptr::null_mut();
3148 let res = ffi::SSL_bytes_to_cipher_list(
3149 self.as_ptr(),
3150 ptr,
3151 len,
3152 isv2format as c_int,
3153 &mut sk,
3154 &mut scsvs,
3155 );
3156 if res == 1 {
3157 Ok(CipherLists {
3158 suites: Stack::from_ptr(sk),
3159 signalling_suites: Stack::from_ptr(scsvs),
3160 })
3161 } else {
3162 Err(ErrorStack::get())
3163 }
3164 }
3165 }
3166
3167 #[corresponds(SSL_client_hello_get0_compression_methods)]
3173 #[cfg(ossl111)]
3174 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3175 unsafe {
3176 let mut ptr = ptr::null();
3177 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3178 if len == 0 {
3179 None
3180 } else {
3181 Some(util::from_raw_parts(ptr, len))
3182 }
3183 }
3184 }
3185
3186 #[corresponds(SSL_set_mtu)]
3188 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3189 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3190 }
3191
3192 #[corresponds(SSL_get_psk_identity_hint)]
3196 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3197 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3198 unsafe {
3199 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3200 if ptr.is_null() {
3201 None
3202 } else {
3203 Some(CStr::from_ptr(ptr).to_bytes())
3204 }
3205 }
3206 }
3207
3208 #[corresponds(SSL_get_psk_identity)]
3210 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3211 pub fn psk_identity(&self) -> Option<&[u8]> {
3212 unsafe {
3213 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3214 if ptr.is_null() {
3215 None
3216 } else {
3217 Some(CStr::from_ptr(ptr).to_bytes())
3218 }
3219 }
3220 }
3221
3222 #[corresponds(SSL_add0_chain_cert)]
3223 #[cfg(ossl110)]
3224 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3225 unsafe {
3226 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3227 mem::forget(chain);
3228 }
3229 Ok(())
3230 }
3231
3232 #[cfg(not(any(boringssl, awslc)))]
3234 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3235 unsafe {
3236 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3237 };
3238 Ok(())
3239 }
3240
3241 #[corresponds(SSL_use_Private_Key_file)]
3243 pub fn set_private_key_file<P: AsRef<Path>>(
3244 &mut self,
3245 path: P,
3246 ssl_file_type: SslFiletype,
3247 ) -> Result<(), ErrorStack> {
3248 let p = path.as_ref().as_os_str().to_str().unwrap();
3249 let key_file = CString::new(p).unwrap();
3250 unsafe {
3251 cvt(ffi::SSL_use_PrivateKey_file(
3252 self.as_ptr(),
3253 key_file.as_ptr(),
3254 ssl_file_type.as_raw(),
3255 ))?;
3256 };
3257 Ok(())
3258 }
3259
3260 #[corresponds(SSL_use_PrivateKey)]
3262 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3263 unsafe {
3264 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3265 };
3266 Ok(())
3267 }
3268
3269 #[corresponds(SSL_use_certificate)]
3271 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3272 unsafe {
3273 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3274 };
3275 Ok(())
3276 }
3277
3278 #[corresponds(SSL_use_certificate_chain_file)]
3284 #[cfg(any(ossl110, libressl))]
3285 pub fn set_certificate_chain_file<P: AsRef<Path>>(
3286 &mut self,
3287 path: P,
3288 ) -> Result<(), ErrorStack> {
3289 let p = path.as_ref().as_os_str().to_str().unwrap();
3290 let cert_file = CString::new(p).unwrap();
3291 unsafe {
3292 cvt(ffi::SSL_use_certificate_chain_file(
3293 self.as_ptr(),
3294 cert_file.as_ptr(),
3295 ))?;
3296 };
3297 Ok(())
3298 }
3299
3300 #[corresponds(SSL_add_client_CA)]
3302 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
3303 unsafe {
3304 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
3305 };
3306 Ok(())
3307 }
3308
3309 #[corresponds(SSL_set_client_CA_list)]
3311 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3312 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3313 mem::forget(list);
3314 }
3315
3316 #[corresponds(SSL_set_min_proto_version)]
3321 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3322 unsafe {
3323 cvt(ffi::SSL_set_min_proto_version(
3324 self.as_ptr(),
3325 version.map_or(0, |v| v.0 as _),
3326 ))
3327 .map(|_| ())
3328 }
3329 }
3330
3331 #[corresponds(SSL_set_max_proto_version)]
3336 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3337 unsafe {
3338 cvt(ffi::SSL_set_max_proto_version(
3339 self.as_ptr(),
3340 version.map_or(0, |v| v.0 as _),
3341 ))
3342 .map(|_| ())
3343 }
3344 }
3345
3346 #[corresponds(SSL_set_ciphersuites)]
3355 #[cfg(any(ossl111, libressl))]
3356 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3357 let cipher_list = CString::new(cipher_list).unwrap();
3358 unsafe {
3359 cvt(ffi::SSL_set_ciphersuites(
3360 self.as_ptr(),
3361 cipher_list.as_ptr() as *const _,
3362 ))
3363 .map(|_| ())
3364 }
3365 }
3366
3367 #[corresponds(SSL_set_cipher_list)]
3375 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3376 let cipher_list = CString::new(cipher_list).unwrap();
3377 unsafe {
3378 cvt(ffi::SSL_set_cipher_list(
3379 self.as_ptr(),
3380 cipher_list.as_ptr() as *const _,
3381 ))
3382 .map(|_| ())
3383 }
3384 }
3385
3386 #[corresponds(SSL_set_cert_store)]
3388 #[cfg(ossl110)]
3389 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3390 unsafe {
3391 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
3392 mem::forget(cert_store);
3393 Ok(())
3394 }
3395 }
3396
3397 #[corresponds(SSL_set_num_tickets)]
3402 #[cfg(ossl111)]
3403 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
3404 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
3405 }
3406
3407 #[corresponds(SSL_get_num_tickets)]
3412 #[cfg(ossl111)]
3413 pub fn num_tickets(&self) -> usize {
3414 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
3415 }
3416
3417 #[corresponds(SSL_set_security_level)]
3422 #[cfg(any(ossl110, libressl360))]
3423 pub fn set_security_level(&mut self, level: u32) {
3424 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
3425 }
3426
3427 #[corresponds(SSL_get_security_level)]
3432 #[cfg(any(ossl110, libressl360))]
3433 pub fn security_level(&self) -> u32 {
3434 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
3435 }
3436
3437 #[corresponds(SSL_get_peer_tmp_key)]
3442 #[cfg(ossl300)]
3443 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
3444 unsafe {
3445 let mut key = ptr::null_mut();
3446 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
3447 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
3448 Err(e) => Err(e),
3449 }
3450 }
3451 }
3452
3453 #[corresponds(SSL_get_tmp_key)]
3458 #[cfg(ossl300)]
3459 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
3460 unsafe {
3461 let mut key = ptr::null_mut();
3462 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
3463 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
3464 Err(e) => Err(e),
3465 }
3466 }
3467 }
3468}
3469
3470#[derive(Debug)]
3472pub struct MidHandshakeSslStream<S> {
3473 stream: SslStream<S>,
3474 error: Error,
3475}
3476
3477impl<S> MidHandshakeSslStream<S> {
3478 pub fn get_ref(&self) -> &S {
3480 self.stream.get_ref()
3481 }
3482
3483 pub fn get_mut(&mut self) -> &mut S {
3485 self.stream.get_mut()
3486 }
3487
3488 pub fn ssl(&self) -> &SslRef {
3490 self.stream.ssl()
3491 }
3492
3493 pub fn error(&self) -> &Error {
3495 &self.error
3496 }
3497
3498 pub fn into_error(self) -> Error {
3500 self.error
3501 }
3502}
3503
3504impl<S> MidHandshakeSslStream<S>
3505where
3506 S: Read + Write,
3507{
3508 #[corresponds(SSL_do_handshake)]
3511 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3512 match self.stream.do_handshake() {
3513 Ok(()) => Ok(self.stream),
3514 Err(error) => {
3515 self.error = error;
3516 match self.error.code() {
3517 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3518 Err(HandshakeError::WouldBlock(self))
3519 }
3520 _ => Err(HandshakeError::Failure(self)),
3521 }
3522 }
3523 }
3524 }
3525}
3526
3527pub struct SslStream<S> {
3529 ssl: ManuallyDrop<Ssl>,
3530 method: ManuallyDrop<BioMethod>,
3531 _p: PhantomData<S>,
3532}
3533
3534impl<S> Drop for SslStream<S> {
3535 fn drop(&mut self) {
3536 unsafe {
3538 ManuallyDrop::drop(&mut self.ssl);
3539 ManuallyDrop::drop(&mut self.method);
3540 }
3541 }
3542}
3543
3544impl<S> fmt::Debug for SslStream<S>
3545where
3546 S: fmt::Debug,
3547{
3548 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3549 fmt.debug_struct("SslStream")
3550 .field("stream", &self.get_ref())
3551 .field("ssl", &self.ssl())
3552 .finish()
3553 }
3554}
3555
3556impl<S: Read + Write> SslStream<S> {
3557 #[corresponds(SSL_set_bio)]
3565 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3566 let (bio, method) = bio::new(stream)?;
3567 unsafe {
3568 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3569 }
3570
3571 Ok(SslStream {
3572 ssl: ManuallyDrop::new(ssl),
3573 method: ManuallyDrop::new(method),
3574 _p: PhantomData,
3575 })
3576 }
3577
3578 #[deprecated(
3586 since = "0.10.32",
3587 note = "use Ssl::from_ptr and SslStream::new instead"
3588 )]
3589 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3590 let ssl = Ssl::from_ptr(ssl);
3591 Self::new(ssl, stream).unwrap()
3592 }
3593
3594 #[corresponds(SSL_read_early_data)]
3603 #[cfg(any(ossl111, libressl))]
3604 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3605 let mut read = 0;
3606 let ret = unsafe {
3607 ffi::SSL_read_early_data(
3608 self.ssl.as_ptr(),
3609 buf.as_ptr() as *mut c_void,
3610 buf.len(),
3611 &mut read,
3612 )
3613 };
3614 match ret {
3615 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
3616 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
3617 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
3618 _ => unreachable!(),
3619 }
3620 }
3621
3622 #[corresponds(SSL_write_early_data)]
3629 #[cfg(any(ossl111, libressl))]
3630 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
3631 let mut written = 0;
3632 let ret = unsafe {
3633 ffi::SSL_write_early_data(
3634 self.ssl.as_ptr(),
3635 buf.as_ptr() as *const c_void,
3636 buf.len(),
3637 &mut written,
3638 )
3639 };
3640 if ret > 0 {
3641 Ok(written)
3642 } else {
3643 Err(self.make_error(ret))
3644 }
3645 }
3646
3647 #[corresponds(SSL_connect)]
3654 pub fn connect(&mut self) -> Result<(), Error> {
3655 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
3656 if ret > 0 {
3657 Ok(())
3658 } else {
3659 Err(self.make_error(ret))
3660 }
3661 }
3662
3663 #[corresponds(SSL_accept)]
3670 pub fn accept(&mut self) -> Result<(), Error> {
3671 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
3672 if ret > 0 {
3673 Ok(())
3674 } else {
3675 Err(self.make_error(ret))
3676 }
3677 }
3678
3679 #[corresponds(SSL_do_handshake)]
3683 pub fn do_handshake(&mut self) -> Result<(), Error> {
3684 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
3685 if ret > 0 {
3686 Ok(())
3687 } else {
3688 Err(self.make_error(ret))
3689 }
3690 }
3691
3692 #[corresponds(SSL_stateless)]
3703 #[cfg(ossl111)]
3704 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
3705 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
3706 1 => Ok(true),
3707 0 => Ok(false),
3708 -1 => Err(ErrorStack::get()),
3709 _ => unreachable!(),
3710 }
3711 }
3712
3713 #[corresponds(SSL_read_ex)]
3720 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3721 loop {
3722 match self.ssl_read_uninit(buf) {
3723 Ok(n) => return Ok(n),
3724 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3725 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3726 return Ok(0);
3727 }
3728 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3729 Err(e) => {
3730 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
3731 }
3732 }
3733 }
3734 }
3735
3736 #[corresponds(SSL_read_ex)]
3741 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3742 unsafe {
3744 self.ssl_read_uninit(util::from_raw_parts_mut(
3745 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3746 buf.len(),
3747 ))
3748 }
3749 }
3750
3751 #[corresponds(SSL_read_ex)]
3758 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3759 if buf.is_empty() {
3760 return Ok(0);
3761 }
3762
3763 cfg_if! {
3764 if #[cfg(any(ossl111, libressl))] {
3765 let mut readbytes = 0;
3766 let ret = unsafe {
3767 ffi::SSL_read_ex(
3768 self.ssl().as_ptr(),
3769 buf.as_mut_ptr().cast(),
3770 buf.len(),
3771 &mut readbytes,
3772 )
3773 };
3774
3775 if ret > 0 {
3776 Ok(readbytes)
3777 } else {
3778 Err(self.make_error(ret))
3779 }
3780 } else {
3781 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3782 let ret = unsafe {
3783 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3784 };
3785 if ret > 0 {
3786 Ok(ret as usize)
3787 } else {
3788 Err(self.make_error(ret))
3789 }
3790 }
3791 }
3792 }
3793
3794 #[corresponds(SSL_write_ex)]
3799 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3800 if buf.is_empty() {
3801 return Ok(0);
3802 }
3803
3804 cfg_if! {
3805 if #[cfg(any(ossl111, libressl))] {
3806 let mut written = 0;
3807 let ret = unsafe {
3808 ffi::SSL_write_ex(
3809 self.ssl().as_ptr(),
3810 buf.as_ptr().cast(),
3811 buf.len(),
3812 &mut written,
3813 )
3814 };
3815
3816 if ret > 0 {
3817 Ok(written)
3818 } else {
3819 Err(self.make_error(ret))
3820 }
3821 } else {
3822 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3823 let ret = unsafe {
3824 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
3825 };
3826 if ret > 0 {
3827 Ok(ret as usize)
3828 } else {
3829 Err(self.make_error(ret))
3830 }
3831 }
3832 }
3833 }
3834
3835 #[corresponds(SSL_peek_ex)]
3837 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3838 cfg_if! {
3839 if #[cfg(any(ossl111, libressl))] {
3840 let mut readbytes = 0;
3841 let ret = unsafe {
3842 ffi::SSL_peek_ex(
3843 self.ssl().as_ptr(),
3844 buf.as_mut_ptr().cast(),
3845 buf.len(),
3846 &mut readbytes,
3847 )
3848 };
3849
3850 if ret > 0 {
3851 Ok(readbytes)
3852 } else {
3853 Err(self.make_error(ret))
3854 }
3855 } else {
3856 if buf.is_empty() {
3857 return Ok(0);
3858 }
3859
3860 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3861 let ret = unsafe {
3862 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3863 };
3864 if ret > 0 {
3865 Ok(ret as usize)
3866 } else {
3867 Err(self.make_error(ret))
3868 }
3869 }
3870 }
3871 }
3872
3873 #[corresponds(SSL_shutdown)]
3883 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
3884 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
3885 0 => Ok(ShutdownResult::Sent),
3886 1 => Ok(ShutdownResult::Received),
3887 n => Err(self.make_error(n)),
3888 }
3889 }
3890
3891 #[corresponds(SSL_get_shutdown)]
3893 pub fn get_shutdown(&mut self) -> ShutdownState {
3894 unsafe {
3895 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
3896 ShutdownState::from_bits_retain(bits)
3897 }
3898 }
3899
3900 #[corresponds(SSL_set_shutdown)]
3905 pub fn set_shutdown(&mut self, state: ShutdownState) {
3906 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
3907 }
3908}
3909
3910impl<S> SslStream<S> {
3911 fn make_error(&mut self, ret: c_int) -> Error {
3912 self.check_panic();
3913
3914 let code = self.ssl.get_error(ret);
3915
3916 let cause = match code {
3917 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
3918 ErrorCode::SYSCALL => {
3919 let errs = ErrorStack::get();
3920 if errs.errors().is_empty() {
3921 self.get_bio_error().map(InnerError::Io)
3922 } else {
3923 Some(InnerError::Ssl(errs))
3924 }
3925 }
3926 ErrorCode::ZERO_RETURN => None,
3927 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3928 self.get_bio_error().map(InnerError::Io)
3929 }
3930 _ => None,
3931 };
3932
3933 Error { code, cause }
3934 }
3935
3936 fn check_panic(&mut self) {
3937 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
3938 resume_unwind(err)
3939 }
3940 }
3941
3942 fn get_bio_error(&mut self) -> Option<io::Error> {
3943 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
3944 }
3945
3946 pub fn get_ref(&self) -> &S {
3948 unsafe {
3949 let bio = self.ssl.get_raw_rbio();
3950 bio::get_ref(bio)
3951 }
3952 }
3953
3954 pub fn get_mut(&mut self) -> &mut S {
3961 unsafe {
3962 let bio = self.ssl.get_raw_rbio();
3963 bio::get_mut(bio)
3964 }
3965 }
3966
3967 pub fn ssl(&self) -> &SslRef {
3969 &self.ssl
3970 }
3971}
3972
3973impl<S: Read + Write> Read for SslStream<S> {
3974 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3975 unsafe {
3977 self.read_uninit(util::from_raw_parts_mut(
3978 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3979 buf.len(),
3980 ))
3981 }
3982 }
3983}
3984
3985impl<S: Read + Write> Write for SslStream<S> {
3986 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
3987 loop {
3988 match self.ssl_write(buf) {
3989 Ok(n) => return Ok(n),
3990 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3991 Err(e) => {
3992 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
3993 }
3994 }
3995 }
3996 }
3997
3998 fn flush(&mut self) -> io::Result<()> {
3999 self.get_mut().flush()
4000 }
4001}
4002
4003#[deprecated(
4005 since = "0.10.32",
4006 note = "use the methods directly on Ssl/SslStream instead"
4007)]
4008pub struct SslStreamBuilder<S> {
4009 inner: SslStream<S>,
4010}
4011
4012#[allow(deprecated)]
4013impl<S> SslStreamBuilder<S>
4014where
4015 S: Read + Write,
4016{
4017 pub fn new(ssl: Ssl, stream: S) -> Self {
4019 Self {
4020 inner: SslStream::new(ssl, stream).unwrap(),
4021 }
4022 }
4023
4024 #[corresponds(SSL_stateless)]
4035 #[cfg(ossl111)]
4036 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4037 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4038 1 => Ok(true),
4039 0 => Ok(false),
4040 -1 => Err(ErrorStack::get()),
4041 _ => unreachable!(),
4042 }
4043 }
4044
4045 #[corresponds(SSL_set_connect_state)]
4047 pub fn set_connect_state(&mut self) {
4048 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4049 }
4050
4051 #[corresponds(SSL_set_accept_state)]
4053 pub fn set_accept_state(&mut self) {
4054 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4055 }
4056
4057 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4059 match self.inner.connect() {
4060 Ok(()) => Ok(self.inner),
4061 Err(error) => match error.code() {
4062 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4063 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4064 stream: self.inner,
4065 error,
4066 }))
4067 }
4068 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4069 stream: self.inner,
4070 error,
4071 })),
4072 },
4073 }
4074 }
4075
4076 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4078 match self.inner.accept() {
4079 Ok(()) => Ok(self.inner),
4080 Err(error) => match error.code() {
4081 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4082 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4083 stream: self.inner,
4084 error,
4085 }))
4086 }
4087 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4088 stream: self.inner,
4089 error,
4090 })),
4091 },
4092 }
4093 }
4094
4095 #[corresponds(SSL_do_handshake)]
4099 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4100 match self.inner.do_handshake() {
4101 Ok(()) => Ok(self.inner),
4102 Err(error) => match error.code() {
4103 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4104 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4105 stream: self.inner,
4106 error,
4107 }))
4108 }
4109 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4110 stream: self.inner,
4111 error,
4112 })),
4113 },
4114 }
4115 }
4116
4117 #[corresponds(SSL_read_early_data)]
4127 #[cfg(any(ossl111, libressl))]
4128 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4129 self.inner.read_early_data(buf)
4130 }
4131
4132 #[corresponds(SSL_write_early_data)]
4139 #[cfg(any(ossl111, libressl))]
4140 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4141 self.inner.write_early_data(buf)
4142 }
4143}
4144
4145#[allow(deprecated)]
4146impl<S> SslStreamBuilder<S> {
4147 pub fn get_ref(&self) -> &S {
4149 unsafe {
4150 let bio = self.inner.ssl.get_raw_rbio();
4151 bio::get_ref(bio)
4152 }
4153 }
4154
4155 pub fn get_mut(&mut self) -> &mut S {
4162 unsafe {
4163 let bio = self.inner.ssl.get_raw_rbio();
4164 bio::get_mut(bio)
4165 }
4166 }
4167
4168 pub fn ssl(&self) -> &SslRef {
4170 &self.inner.ssl
4171 }
4172
4173 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4181 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4182 unsafe {
4183 let bio = self.inner.ssl.get_raw_rbio();
4184 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4185 }
4186 }
4187}
4188
4189#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4191pub enum ShutdownResult {
4192 Sent,
4194
4195 Received,
4197}
4198
4199bitflags! {
4200 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4202 #[repr(transparent)]
4203 pub struct ShutdownState: c_int {
4204 const SENT = ffi::SSL_SENT_SHUTDOWN;
4206 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4208 }
4209}
4210
4211use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4212cfg_if! {
4213 if #[cfg(ossl300)] {
4214 use ffi::SSL_get1_peer_certificate;
4215 } else {
4216 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4217 }
4218}
4219use ffi::{
4220 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4221 TLS_server_method,
4222};
4223cfg_if! {
4224 if #[cfg(ossl110)] {
4225 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4226 ffi::CRYPTO_get_ex_new_index(
4227 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4228 0,
4229 ptr::null_mut(),
4230 None,
4231 None,
4232 Some(f),
4233 )
4234 }
4235
4236 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4237 ffi::CRYPTO_get_ex_new_index(
4238 ffi::CRYPTO_EX_INDEX_SSL,
4239 0,
4240 ptr::null_mut(),
4241 None,
4242 None,
4243 Some(f),
4244 )
4245 }
4246 } else {
4247 use std::sync::Once;
4248
4249 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4250 static ONCE: Once = Once::new();
4252 ONCE.call_once(|| {
4253 cfg_if! {
4254 if #[cfg(not(any(boringssl, awslc)))] {
4255 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4256 } else {
4257 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4258 }
4259 }
4260 });
4261
4262 cfg_if! {
4263 if #[cfg(not(any(boringssl, awslc)))] {
4264 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
4265 } else {
4266 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4267 }
4268 }
4269 }
4270
4271 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4272 static ONCE: Once = Once::new();
4274 ONCE.call_once(|| {
4275 #[cfg(not(any(boringssl, awslc)))]
4276 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4277 #[cfg(any(boringssl, awslc))]
4278 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4279 });
4280
4281 #[cfg(not(any(boringssl, awslc)))]
4282 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
4283 #[cfg(any(boringssl, awslc))]
4284 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
4285 }
4286 }
4287}