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 once_cell::sync::{Lazy, OnceCell};
90use openssl_macros::corresponds;
91use std::any::TypeId;
92use std::collections::HashMap;
93use std::ffi::{CStr, CString};
94use std::fmt;
95use std::io;
96use std::io::prelude::*;
97use std::marker::PhantomData;
98use std::mem::{self, ManuallyDrop, MaybeUninit};
99use std::ops::{Deref, DerefMut};
100use std::panic::resume_unwind;
101use std::path::Path;
102use std::ptr;
103use std::str;
104use std::sync::{Arc, Mutex};
105
106pub use crate::ssl::connector::{
107 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
108};
109pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
110
111mod bio;
112mod callbacks;
113mod connector;
114mod error;
115#[cfg(test)]
116mod test;
117
118#[corresponds(OPENSSL_cipher_name)]
124#[cfg(ossl111)]
125pub fn cipher_name(std_name: &str) -> &'static str {
126 unsafe {
127 ffi::init();
128
129 let s = CString::new(std_name).unwrap();
130 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
131 CStr::from_ptr(ptr).to_str().unwrap()
132 }
133}
134
135cfg_if! {
136 if #[cfg(ossl300)] {
137 type SslOptionsRepr = u64;
138 } else if #[cfg(any(boringssl, awslc))] {
139 type SslOptionsRepr = u32;
140 } else {
141 type SslOptionsRepr = libc::c_ulong;
142 }
143}
144
145bitflags! {
146 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
148 #[repr(transparent)]
149 pub struct SslOptions: SslOptionsRepr {
150 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
152
153 #[cfg(ossl300)]
156 const IGNORE_UNEXPECTED_EOF = ffi::SSL_OP_IGNORE_UNEXPECTED_EOF as SslOptionsRepr;
157
158 #[cfg(not(any(boringssl, awslc)))]
160 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
161
162 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
166
167 #[cfg(not(any(boringssl, awslc)))]
173 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
174
175 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
177
178 #[cfg(not(any(boringssl, awslc)))]
180 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
181 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
182
183 #[cfg(not(any(boringssl, awslc)))]
185 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
186
187 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
190 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
191
192 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
196
197 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
201
202 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
206
207 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
209
210 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
212
213 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
215
216 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
218
219 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
221
222 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
224
225 #[cfg(any(ossl111, boringssl, libressl, awslc))]
229 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
230
231 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
233
234 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
236
237 #[cfg(ossl110)]
253 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
254
255 #[cfg(any(boringssl, ossl110h, awslc))]
259 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
260
261 #[cfg(ossl111)]
266 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
267
268 #[cfg(ossl111)]
280 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
281 }
282}
283
284bitflags! {
285 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
287 #[repr(transparent)]
288 pub struct SslMode: SslBitType {
289 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
295
296 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
299
300 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
310
311 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
317
318 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
322
323 #[cfg(not(libressl))]
331 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
332 }
333}
334
335#[derive(Copy, Clone)]
337pub struct SslMethod(*const ffi::SSL_METHOD);
338
339impl SslMethod {
340 #[corresponds(TLS_method)]
342 pub fn tls() -> SslMethod {
343 unsafe { SslMethod(TLS_method()) }
344 }
345
346 #[corresponds(DTLS_method)]
348 pub fn dtls() -> SslMethod {
349 unsafe { SslMethod(DTLS_method()) }
350 }
351
352 #[corresponds(TLS_client_method)]
354 pub fn tls_client() -> SslMethod {
355 unsafe { SslMethod(TLS_client_method()) }
356 }
357
358 #[corresponds(TLS_server_method)]
360 pub fn tls_server() -> SslMethod {
361 unsafe { SslMethod(TLS_server_method()) }
362 }
363
364 #[corresponds(DTLS_client_method)]
366 pub fn dtls_client() -> SslMethod {
367 unsafe { SslMethod(DTLS_client_method()) }
368 }
369
370 #[corresponds(DTLS_server_method)]
372 pub fn dtls_server() -> SslMethod {
373 unsafe { SslMethod(DTLS_server_method()) }
374 }
375
376 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
382 SslMethod(ptr)
383 }
384
385 #[allow(clippy::trivially_copy_pass_by_ref)]
387 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
388 self.0
389 }
390}
391
392unsafe impl Sync for SslMethod {}
393unsafe impl Send for SslMethod {}
394
395bitflags! {
396 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
398 #[repr(transparent)]
399 pub struct SslVerifyMode: i32 {
400 const PEER = ffi::SSL_VERIFY_PEER;
404
405 const NONE = ffi::SSL_VERIFY_NONE;
411
412 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
416 }
417}
418
419#[cfg(any(boringssl, awslc))]
420type SslBitType = c_int;
421#[cfg(not(any(boringssl, awslc)))]
422type SslBitType = c_long;
423
424#[cfg(any(boringssl, awslc))]
425type SslTimeTy = u64;
426#[cfg(not(any(boringssl, awslc)))]
427type SslTimeTy = c_long;
428
429bitflags! {
430 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
432 #[repr(transparent)]
433 pub struct SslSessionCacheMode: SslBitType {
434 const OFF = ffi::SSL_SESS_CACHE_OFF;
436
437 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
444
445 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
449
450 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
452
453 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
455
456 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
458
459 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
461
462 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
464 }
465}
466
467#[cfg(ossl111)]
468bitflags! {
469 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
471 #[repr(transparent)]
472 pub struct ExtensionContext: c_uint {
473 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
475 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
477 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
479 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
481 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
483 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
485 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
487 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
488 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
490 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
491 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
492 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
493 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
494 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
495 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
496 }
497}
498
499#[derive(Copy, Clone)]
501pub struct SslFiletype(c_int);
502
503impl SslFiletype {
504 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
508
509 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
513
514 pub fn from_raw(raw: c_int) -> SslFiletype {
516 SslFiletype(raw)
517 }
518
519 #[allow(clippy::trivially_copy_pass_by_ref)]
521 pub fn as_raw(&self) -> c_int {
522 self.0
523 }
524}
525
526#[derive(Copy, Clone)]
528pub struct StatusType(c_int);
529
530impl StatusType {
531 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
533
534 pub fn from_raw(raw: c_int) -> StatusType {
536 StatusType(raw)
537 }
538
539 #[allow(clippy::trivially_copy_pass_by_ref)]
541 pub fn as_raw(&self) -> c_int {
542 self.0
543 }
544}
545
546#[derive(Copy, Clone)]
548pub struct NameType(c_int);
549
550impl NameType {
551 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
553
554 pub fn from_raw(raw: c_int) -> StatusType {
556 StatusType(raw)
557 }
558
559 #[allow(clippy::trivially_copy_pass_by_ref)]
561 pub fn as_raw(&self) -> c_int {
562 self.0
563 }
564}
565
566static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
567static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
568static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
569
570fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
571 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
572}
573
574unsafe extern "C" fn free_data_box<T>(
575 _parent: *mut c_void,
576 ptr: *mut c_void,
577 _ad: *mut ffi::CRYPTO_EX_DATA,
578 _idx: c_int,
579 _argl: c_long,
580 _argp: *mut c_void,
581) {
582 if !ptr.is_null() {
583 let _ = Box::<T>::from_raw(ptr as *mut T);
584 }
585}
586
587#[derive(Debug, Copy, Clone, PartialEq, Eq)]
589pub struct SniError(c_int);
590
591impl SniError {
592 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
594
595 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
597
598 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
599}
600
601#[derive(Debug, Copy, Clone, PartialEq, Eq)]
603pub struct SslAlert(c_int);
604
605impl SslAlert {
606 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
608 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
609 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
610}
611
612#[derive(Debug, Copy, Clone, PartialEq, Eq)]
616pub struct AlpnError(c_int);
617
618impl AlpnError {
619 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
621
622 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
624}
625
626#[cfg(ossl111)]
630#[derive(Debug, Copy, Clone, PartialEq, Eq)]
631pub struct ClientHelloResponse(c_int);
632
633#[cfg(ossl111)]
634impl ClientHelloResponse {
635 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
637
638 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
640}
641
642#[derive(Debug, Copy, Clone, PartialEq, Eq)]
644pub struct SslVersion(c_int);
645
646impl SslVersion {
647 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
649
650 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
652
653 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
655
656 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
658
659 #[cfg(any(ossl111, libressl, boringssl, awslc))]
663 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
664
665 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
669
670 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
674}
675
676cfg_if! {
677 if #[cfg(any(boringssl, awslc))] {
678 type SslCacheTy = i64;
679 type SslCacheSize = libc::c_ulong;
680 type MtuTy = u32;
681 type SizeTy = usize;
682 } else {
683 type SslCacheTy = i64;
684 type SslCacheSize = c_long;
685 type MtuTy = c_long;
686 type SizeTy = u32;
687 }
688}
689
690#[corresponds(SSL_select_next_proto)]
701pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
702 unsafe {
703 let mut out = ptr::null_mut();
704 let mut outlen = 0;
705 let r = ffi::SSL_select_next_proto(
706 &mut out,
707 &mut outlen,
708 server.as_ptr(),
709 server.len() as c_uint,
710 client.as_ptr(),
711 client.len() as c_uint,
712 );
713 if r == ffi::OPENSSL_NPN_NEGOTIATED {
714 Some(util::from_raw_parts(out as *const u8, outlen as usize))
715 } else {
716 None
717 }
718 }
719}
720
721pub struct SslContextBuilder(SslContext);
723
724impl SslContextBuilder {
725 #[corresponds(SSL_CTX_new)]
727 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
728 unsafe {
729 init();
730 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
731
732 Ok(SslContextBuilder::from_ptr(ctx))
733 }
734 }
735
736 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
742 SslContextBuilder(SslContext::from_ptr(ctx))
743 }
744
745 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
747 self.0.as_ptr()
748 }
749
750 #[corresponds(SSL_CTX_set_verify)]
752 pub fn set_verify(&mut self, mode: SslVerifyMode) {
753 unsafe {
754 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
755 }
756 }
757
758 #[corresponds(SSL_CTX_set_verify)]
765 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
766 where
767 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
768 {
769 unsafe {
770 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
771 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
772 }
773 }
774
775 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
783 pub fn set_servername_callback<F>(&mut self, callback: F)
785 where
786 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
787 {
788 unsafe {
789 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
795 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
796 #[cfg(any(boringssl, awslc))]
797 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
798 #[cfg(not(any(boringssl, awslc)))]
799 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
800 self.as_ptr(),
801 Some(raw_sni::<F>),
802 );
803 }
804 }
805
806 #[corresponds(SSL_CTX_set_verify_depth)]
810 pub fn set_verify_depth(&mut self, depth: u32) {
811 unsafe {
812 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
813 }
814 }
815
816 #[corresponds(SSL_CTX_set0_verify_cert_store)]
820 #[cfg(ossl110)]
821 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
822 unsafe {
823 let ptr = cert_store.as_ptr();
824 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
825 mem::forget(cert_store);
826
827 Ok(())
828 }
829 }
830
831 #[corresponds(SSL_CTX_set_cert_store)]
833 pub fn set_cert_store(&mut self, cert_store: X509Store) {
834 unsafe {
835 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
836 mem::forget(cert_store);
837 }
838 }
839
840 #[corresponds(SSL_CTX_set_read_ahead)]
847 pub fn set_read_ahead(&mut self, read_ahead: bool) {
848 unsafe {
849 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
850 }
851 }
852
853 #[corresponds(SSL_CTX_set_mode)]
855 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
856 unsafe {
857 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
858 SslMode::from_bits_retain(bits)
859 }
860 }
861
862 #[corresponds(SSL_CTX_set_tmp_dh)]
864 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
865 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
866 }
867
868 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
875 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
876 where
877 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
878 {
879 unsafe {
880 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
881
882 #[cfg(not(any(boringssl, awslc)))]
883 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
884 #[cfg(any(boringssl, awslc))]
885 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
886 }
887 }
888
889 #[corresponds(SSL_CTX_set_tmp_ecdh)]
891 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
892 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
893 }
894
895 #[corresponds(SSL_CTX_set_default_verify_paths)]
900 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
901 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
902 }
903
904 #[corresponds(SSL_CTX_load_verify_locations)]
908 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
909 self.load_verify_locations(Some(file.as_ref()), None)
910 }
911
912 #[corresponds(SSL_CTX_load_verify_locations)]
914 pub fn load_verify_locations(
915 &mut self,
916 ca_file: Option<&Path>,
917 ca_path: Option<&Path>,
918 ) -> Result<(), ErrorStack> {
919 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
920 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
921 unsafe {
922 cvt(ffi::SSL_CTX_load_verify_locations(
923 self.as_ptr(),
924 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
925 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
926 ))
927 .map(|_| ())
928 }
929 }
930
931 #[corresponds(SSL_CTX_set_client_CA_list)]
936 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
937 unsafe {
938 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
939 mem::forget(list);
940 }
941 }
942
943 #[corresponds(SSL_CTX_add_client_CA)]
946 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
947 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
948 }
949
950 #[corresponds(SSL_CTX_set_session_id_context)]
959 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
960 unsafe {
961 assert!(sid_ctx.len() <= c_uint::MAX as usize);
962 cvt(ffi::SSL_CTX_set_session_id_context(
963 self.as_ptr(),
964 sid_ctx.as_ptr(),
965 sid_ctx.len() as SizeTy,
966 ))
967 .map(|_| ())
968 }
969 }
970
971 #[corresponds(SSL_CTX_use_certificate_file)]
977 pub fn set_certificate_file<P: AsRef<Path>>(
978 &mut self,
979 file: P,
980 file_type: SslFiletype,
981 ) -> Result<(), ErrorStack> {
982 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
983 unsafe {
984 cvt(ffi::SSL_CTX_use_certificate_file(
985 self.as_ptr(),
986 file.as_ptr() as *const _,
987 file_type.as_raw(),
988 ))
989 .map(|_| ())
990 }
991 }
992
993 #[corresponds(SSL_CTX_use_certificate_chain_file)]
999 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1000 &mut self,
1001 file: P,
1002 ) -> Result<(), ErrorStack> {
1003 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1004 unsafe {
1005 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1006 self.as_ptr(),
1007 file.as_ptr() as *const _,
1008 ))
1009 .map(|_| ())
1010 }
1011 }
1012
1013 #[corresponds(SSL_CTX_use_certificate)]
1017 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1018 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1019 }
1020
1021 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1026 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1027 unsafe {
1028 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1029 mem::forget(cert);
1030 Ok(())
1031 }
1032 }
1033
1034 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1036 pub fn set_private_key_file<P: AsRef<Path>>(
1037 &mut self,
1038 file: P,
1039 file_type: SslFiletype,
1040 ) -> Result<(), ErrorStack> {
1041 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1042 unsafe {
1043 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1044 self.as_ptr(),
1045 file.as_ptr() as *const _,
1046 file_type.as_raw(),
1047 ))
1048 .map(|_| ())
1049 }
1050 }
1051
1052 #[corresponds(SSL_CTX_use_PrivateKey)]
1054 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1055 where
1056 T: HasPrivate,
1057 {
1058 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1059 }
1060
1061 #[corresponds(SSL_CTX_set_cipher_list)]
1069 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1070 let cipher_list = CString::new(cipher_list).unwrap();
1071 unsafe {
1072 cvt(ffi::SSL_CTX_set_cipher_list(
1073 self.as_ptr(),
1074 cipher_list.as_ptr() as *const _,
1075 ))
1076 .map(|_| ())
1077 }
1078 }
1079
1080 #[corresponds(SSL_CTX_set_ciphersuites)]
1089 #[cfg(any(ossl111, libressl))]
1090 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1091 let cipher_list = CString::new(cipher_list).unwrap();
1092 unsafe {
1093 cvt(ffi::SSL_CTX_set_ciphersuites(
1094 self.as_ptr(),
1095 cipher_list.as_ptr() as *const _,
1096 ))
1097 .map(|_| ())
1098 }
1099 }
1100
1101 #[corresponds(SSL_CTX_set_ecdh_auto)]
1105 #[cfg(libressl)]
1106 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1107 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1108 }
1109
1110 #[corresponds(SSL_CTX_set_options)]
1117 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1118 let bits =
1119 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1120 SslOptions::from_bits_retain(bits)
1121 }
1122
1123 #[corresponds(SSL_CTX_get_options)]
1125 pub fn options(&self) -> SslOptions {
1126 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1127 SslOptions::from_bits_retain(bits)
1128 }
1129
1130 #[corresponds(SSL_CTX_clear_options)]
1132 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1133 let bits =
1134 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1135 SslOptions::from_bits_retain(bits)
1136 }
1137
1138 #[corresponds(SSL_CTX_set_min_proto_version)]
1143 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1144 unsafe {
1145 cvt(ffi::SSL_CTX_set_min_proto_version(
1146 self.as_ptr(),
1147 version.map_or(0, |v| v.0 as _),
1148 ))
1149 .map(|_| ())
1150 }
1151 }
1152
1153 #[corresponds(SSL_CTX_set_max_proto_version)]
1158 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1159 unsafe {
1160 cvt(ffi::SSL_CTX_set_max_proto_version(
1161 self.as_ptr(),
1162 version.map_or(0, |v| v.0 as _),
1163 ))
1164 .map(|_| ())
1165 }
1166 }
1167
1168 #[corresponds(SSL_CTX_get_min_proto_version)]
1175 #[cfg(any(ossl110g, libressl))]
1176 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1177 unsafe {
1178 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1179 if r == 0 {
1180 None
1181 } else {
1182 Some(SslVersion(r))
1183 }
1184 }
1185 }
1186
1187 #[corresponds(SSL_CTX_get_max_proto_version)]
1194 #[cfg(any(ossl110g, libressl))]
1195 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1196 unsafe {
1197 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1198 if r == 0 {
1199 None
1200 } else {
1201 Some(SslVersion(r))
1202 }
1203 }
1204 }
1205
1206 #[corresponds(SSL_CTX_set_alpn_protos)]
1215 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1216 unsafe {
1217 assert!(protocols.len() <= c_uint::MAX as usize);
1218 let r = ffi::SSL_CTX_set_alpn_protos(
1219 self.as_ptr(),
1220 protocols.as_ptr(),
1221 protocols.len() as _,
1222 );
1223 if r == 0 {
1225 Ok(())
1226 } else {
1227 Err(ErrorStack::get())
1228 }
1229 }
1230 }
1231
1232 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1234 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1235 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1236 unsafe {
1237 let cstr = CString::new(protocols).unwrap();
1238
1239 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1240 if r == 0 {
1242 Ok(())
1243 } else {
1244 Err(ErrorStack::get())
1245 }
1246 }
1247 }
1248
1249 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1262 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1263 where
1264 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1265 {
1266 unsafe {
1267 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1268 #[cfg(not(any(boringssl, awslc)))]
1269 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1270 self.as_ptr(),
1271 Some(callbacks::raw_alpn_select::<F>),
1272 ptr::null_mut(),
1273 );
1274 #[cfg(any(boringssl, awslc))]
1275 ffi::SSL_CTX_set_alpn_select_cb(
1276 self.as_ptr(),
1277 Some(callbacks::raw_alpn_select::<F>),
1278 ptr::null_mut(),
1279 );
1280 }
1281 }
1282
1283 #[corresponds(SSL_CTX_check_private_key)]
1285 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1286 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1287 }
1288
1289 #[corresponds(SSL_CTX_get_cert_store)]
1291 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1292 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1293 }
1294
1295 #[corresponds(SSL_CTX_get_cert_store)]
1297 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1298 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1299 }
1300
1301 #[corresponds(SSL_CTX_get0_param)]
1305 pub fn verify_param(&self) -> &X509VerifyParamRef {
1306 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1307 }
1308
1309 #[corresponds(SSL_CTX_get0_param)]
1313 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1314 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1315 }
1316
1317 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1330 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1331 where
1332 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1333 {
1334 unsafe {
1335 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1336 cvt(
1337 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1338 as c_int,
1339 )
1340 .map(|_| ())
1341 }
1342 }
1343
1344 #[corresponds(SSL_CTX_set_psk_client_callback)]
1350 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1351 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1352 where
1353 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1354 + 'static
1355 + Sync
1356 + Send,
1357 {
1358 unsafe {
1359 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1360 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1361 }
1362 }
1363
1364 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1365 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1366 pub fn set_psk_callback<F>(&mut self, callback: F)
1367 where
1368 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1369 + 'static
1370 + Sync
1371 + Send,
1372 {
1373 self.set_psk_client_callback(callback)
1374 }
1375
1376 #[corresponds(SSL_CTX_set_psk_server_callback)]
1382 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1383 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1384 where
1385 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1386 + 'static
1387 + Sync
1388 + Send,
1389 {
1390 unsafe {
1391 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1392 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1393 }
1394 }
1395
1396 #[corresponds(SSL_CTX_sess_set_new_cb)]
1410 pub fn set_new_session_callback<F>(&mut self, callback: F)
1411 where
1412 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1413 {
1414 unsafe {
1415 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1416 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1417 }
1418 }
1419
1420 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1424 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1425 where
1426 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1427 {
1428 unsafe {
1429 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1430 ffi::SSL_CTX_sess_set_remove_cb(
1431 self.as_ptr(),
1432 Some(callbacks::raw_remove_session::<F>),
1433 );
1434 }
1435 }
1436
1437 #[corresponds(SSL_CTX_sess_set_get_cb)]
1448 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1449 where
1450 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1451 {
1452 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1453 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1454 }
1455
1456 #[corresponds(SSL_CTX_set_keylog_callback)]
1464 #[cfg(any(ossl111, boringssl, awslc))]
1465 pub fn set_keylog_callback<F>(&mut self, callback: F)
1466 where
1467 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1468 {
1469 unsafe {
1470 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1471 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1472 }
1473 }
1474
1475 #[corresponds(SSL_CTX_set_session_cache_mode)]
1479 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1480 unsafe {
1481 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1482 SslSessionCacheMode::from_bits_retain(bits)
1483 }
1484 }
1485
1486 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1492 #[cfg(ossl111)]
1493 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1494 where
1495 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1496 {
1497 unsafe {
1498 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1499 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1500 self.as_ptr(),
1501 Some(raw_stateless_cookie_generate::<F>),
1502 );
1503 }
1504 }
1505
1506 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1515 #[cfg(ossl111)]
1516 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1517 where
1518 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1519 {
1520 unsafe {
1521 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1522 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1523 self.as_ptr(),
1524 Some(raw_stateless_cookie_verify::<F>),
1525 )
1526 }
1527 }
1528
1529 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1534 #[cfg(not(any(boringssl, awslc)))]
1535 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1536 where
1537 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1538 {
1539 unsafe {
1540 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1541 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1542 }
1543 }
1544
1545 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1550 #[cfg(not(any(boringssl, awslc)))]
1551 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1552 where
1553 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1554 {
1555 unsafe {
1556 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1557 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1558 }
1559 }
1560
1561 #[corresponds(SSL_CTX_set_ex_data)]
1567 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1568 self.set_ex_data_inner(index, data);
1569 }
1570
1571 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1572 match self.ex_data_mut(index) {
1573 Some(v) => {
1574 *v = data;
1575 (v as *mut T).cast()
1576 }
1577 _ => unsafe {
1578 let data = Box::into_raw(Box::new(data)) as *mut c_void;
1579 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1580 data
1581 },
1582 }
1583 }
1584
1585 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1586 unsafe {
1587 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1588 if data.is_null() {
1589 None
1590 } else {
1591 Some(&mut *data.cast())
1592 }
1593 }
1594 }
1595
1596 #[corresponds(SSL_CTX_add_custom_ext)]
1600 #[cfg(ossl111)]
1601 pub fn add_custom_ext<AddFn, ParseFn, T>(
1602 &mut self,
1603 ext_type: u16,
1604 context: ExtensionContext,
1605 add_cb: AddFn,
1606 parse_cb: ParseFn,
1607 ) -> Result<(), ErrorStack>
1608 where
1609 AddFn: Fn(
1610 &mut SslRef,
1611 ExtensionContext,
1612 Option<(usize, &X509Ref)>,
1613 ) -> Result<Option<T>, SslAlert>
1614 + 'static
1615 + Sync
1616 + Send,
1617 T: AsRef<[u8]> + 'static + Sync + Send,
1618 ParseFn: Fn(
1619 &mut SslRef,
1620 ExtensionContext,
1621 &[u8],
1622 Option<(usize, &X509Ref)>,
1623 ) -> Result<(), SslAlert>
1624 + 'static
1625 + Sync
1626 + Send,
1627 {
1628 let ret = unsafe {
1629 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1630 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1631
1632 ffi::SSL_CTX_add_custom_ext(
1633 self.as_ptr(),
1634 ext_type as c_uint,
1635 context.bits(),
1636 Some(raw_custom_ext_add::<AddFn, T>),
1637 Some(raw_custom_ext_free::<T>),
1638 ptr::null_mut(),
1639 Some(raw_custom_ext_parse::<ParseFn>),
1640 ptr::null_mut(),
1641 )
1642 };
1643 if ret == 1 {
1644 Ok(())
1645 } else {
1646 Err(ErrorStack::get())
1647 }
1648 }
1649
1650 #[corresponds(SSL_CTX_set_max_early_data)]
1656 #[cfg(any(ossl111, libressl))]
1657 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1658 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1659 Ok(())
1660 } else {
1661 Err(ErrorStack::get())
1662 }
1663 }
1664
1665 #[corresponds(SSL_CTX_set_client_hello_cb)]
1669 #[cfg(ossl111)]
1670 pub fn set_client_hello_callback<F>(&mut self, callback: F)
1671 where
1672 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1673 + 'static
1674 + Sync
1675 + Send,
1676 {
1677 unsafe {
1678 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1679 ffi::SSL_CTX_set_client_hello_cb(
1680 self.as_ptr(),
1681 Some(callbacks::raw_client_hello::<F>),
1682 ptr,
1683 );
1684 }
1685 }
1686
1687 #[corresponds(SSL_CTX_sess_set_cache_size)]
1691 #[allow(clippy::useless_conversion)]
1692 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1693 unsafe {
1694 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1695 }
1696 }
1697
1698 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1702 #[cfg(ossl110)]
1703 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1704 let sigalgs = CString::new(sigalgs).unwrap();
1705 unsafe {
1706 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1707 .map(|_| ())
1708 }
1709 }
1710
1711 #[corresponds(SSL_CTX_set1_groups_list)]
1715 #[cfg(any(ossl111, boringssl, libressl, awslc))]
1716 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1717 let groups = CString::new(groups).unwrap();
1718 unsafe {
1719 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1720 }
1721 }
1722
1723 #[corresponds(SSL_CTX_set_num_tickets)]
1728 #[cfg(ossl111)]
1729 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1730 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1731 }
1732
1733 #[corresponds(SSL_CTX_set_security_level)]
1738 #[cfg(any(ossl110, libressl360))]
1739 pub fn set_security_level(&mut self, level: u32) {
1740 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1741 }
1742
1743 pub fn build(self) -> SslContext {
1745 self.0
1746 }
1747}
1748
1749foreign_type_and_impl_send_sync! {
1750 type CType = ffi::SSL_CTX;
1751 fn drop = ffi::SSL_CTX_free;
1752
1753 pub struct SslContext;
1758
1759 pub struct SslContextRef;
1763}
1764
1765impl Clone for SslContext {
1766 fn clone(&self) -> Self {
1767 (**self).to_owned()
1768 }
1769}
1770
1771impl ToOwned for SslContextRef {
1772 type Owned = SslContext;
1773
1774 fn to_owned(&self) -> Self::Owned {
1775 unsafe {
1776 SSL_CTX_up_ref(self.as_ptr());
1777 SslContext::from_ptr(self.as_ptr())
1778 }
1779 }
1780}
1781
1782impl fmt::Debug for SslContext {
1784 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1785 write!(fmt, "SslContext")
1786 }
1787}
1788
1789impl SslContext {
1790 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1792 SslContextBuilder::new(method)
1793 }
1794
1795 #[corresponds(SSL_CTX_get_ex_new_index)]
1800 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1801 where
1802 T: 'static + Sync + Send,
1803 {
1804 unsafe {
1805 ffi::init();
1806 #[cfg(any(boringssl, awslc))]
1807 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1808 #[cfg(not(any(boringssl, awslc)))]
1809 let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1810 Ok(Index::from_raw(idx))
1811 }
1812 }
1813
1814 fn cached_ex_index<T>() -> Index<SslContext, T>
1816 where
1817 T: 'static + Sync + Send,
1818 {
1819 unsafe {
1820 let idx = *INDEXES
1821 .lock()
1822 .unwrap_or_else(|e| e.into_inner())
1823 .entry(TypeId::of::<T>())
1824 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1825 Index::from_raw(idx)
1826 }
1827 }
1828}
1829
1830impl SslContextRef {
1831 #[corresponds(SSL_CTX_get0_certificate)]
1835 #[cfg(any(ossl110, libressl))]
1836 pub fn certificate(&self) -> Option<&X509Ref> {
1837 unsafe {
1838 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1839 X509Ref::from_const_ptr_opt(ptr)
1840 }
1841 }
1842
1843 #[corresponds(SSL_CTX_get0_privatekey)]
1847 #[cfg(any(ossl110, libressl))]
1848 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1849 unsafe {
1850 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1851 PKeyRef::from_const_ptr_opt(ptr)
1852 }
1853 }
1854
1855 #[corresponds(SSL_CTX_get_cert_store)]
1857 pub fn cert_store(&self) -> &X509StoreRef {
1858 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1859 }
1860
1861 #[corresponds(SSL_CTX_get_extra_chain_certs)]
1863 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1864 unsafe {
1865 let mut chain = ptr::null_mut();
1866 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1867 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1868 }
1869 }
1870
1871 #[corresponds(SSL_CTX_get_ex_data)]
1873 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1874 unsafe {
1875 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1876 if data.is_null() {
1877 None
1878 } else {
1879 Some(&*(data as *const T))
1880 }
1881 }
1882 }
1883
1884 #[corresponds(SSL_CTX_get_max_early_data)]
1888 #[cfg(any(ossl111, libressl))]
1889 pub fn max_early_data(&self) -> u32 {
1890 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1891 }
1892
1893 #[corresponds(SSL_CTX_add_session)]
1902 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1903 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1904 }
1905
1906 #[corresponds(SSL_CTX_remove_session)]
1915 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
1916 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
1917 }
1918
1919 #[corresponds(SSL_CTX_sess_get_cache_size)]
1923 #[allow(clippy::unnecessary_cast)]
1924 pub fn session_cache_size(&self) -> i64 {
1925 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
1926 }
1927
1928 #[corresponds(SSL_CTX_get_verify_mode)]
1932 pub fn verify_mode(&self) -> SslVerifyMode {
1933 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
1934 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
1935 }
1936
1937 #[corresponds(SSL_CTX_get_num_tickets)]
1942 #[cfg(ossl111)]
1943 pub fn num_tickets(&self) -> usize {
1944 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
1945 }
1946
1947 #[corresponds(SSL_CTX_get_security_level)]
1952 #[cfg(any(ossl110, libressl360))]
1953 pub fn security_level(&self) -> u32 {
1954 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
1955 }
1956}
1957
1958pub struct CipherBits {
1960 pub secret: i32,
1962
1963 pub algorithm: i32,
1965}
1966
1967pub struct SslCipher(*mut ffi::SSL_CIPHER);
1969
1970impl ForeignType for SslCipher {
1971 type CType = ffi::SSL_CIPHER;
1972 type Ref = SslCipherRef;
1973
1974 #[inline]
1975 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
1976 SslCipher(ptr)
1977 }
1978
1979 #[inline]
1980 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
1981 self.0
1982 }
1983}
1984
1985impl Stackable for SslCipher {
1986 type StackType = ffi::stack_st_SSL_CIPHER;
1987}
1988
1989impl Deref for SslCipher {
1990 type Target = SslCipherRef;
1991
1992 fn deref(&self) -> &SslCipherRef {
1993 unsafe { SslCipherRef::from_ptr(self.0) }
1994 }
1995}
1996
1997impl DerefMut for SslCipher {
1998 fn deref_mut(&mut self) -> &mut SslCipherRef {
1999 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2000 }
2001}
2002
2003pub struct SslCipherRef(Opaque);
2007
2008impl ForeignTypeRef for SslCipherRef {
2009 type CType = ffi::SSL_CIPHER;
2010}
2011
2012impl SslCipherRef {
2013 #[corresponds(SSL_CIPHER_get_name)]
2015 pub fn name(&self) -> &'static str {
2016 unsafe {
2017 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2018 CStr::from_ptr(ptr).to_str().unwrap()
2019 }
2020 }
2021
2022 #[corresponds(SSL_CIPHER_standard_name)]
2026 #[cfg(ossl111)]
2027 pub fn standard_name(&self) -> Option<&'static str> {
2028 unsafe {
2029 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2030 if ptr.is_null() {
2031 None
2032 } else {
2033 Some(CStr::from_ptr(ptr).to_str().unwrap())
2034 }
2035 }
2036 }
2037
2038 #[corresponds(SSL_CIPHER_get_version)]
2040 pub fn version(&self) -> &'static str {
2041 let version = unsafe {
2042 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2043 CStr::from_ptr(ptr as *const _)
2044 };
2045
2046 str::from_utf8(version.to_bytes()).unwrap()
2047 }
2048
2049 #[corresponds(SSL_CIPHER_get_bits)]
2051 #[allow(clippy::useless_conversion)]
2052 pub fn bits(&self) -> CipherBits {
2053 unsafe {
2054 let mut algo_bits = 0;
2055 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2056 CipherBits {
2057 secret: secret_bits.into(),
2058 algorithm: algo_bits.into(),
2059 }
2060 }
2061 }
2062
2063 #[corresponds(SSL_CIPHER_description)]
2065 pub fn description(&self) -> String {
2066 unsafe {
2067 let mut buf = [0; 128];
2069 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2070 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2071 }
2072 }
2073
2074 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2078 #[cfg(ossl111)]
2079 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2080 unsafe {
2081 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2082 if ptr.is_null() {
2083 None
2084 } else {
2085 Some(MessageDigest::from_ptr(ptr))
2086 }
2087 }
2088 }
2089
2090 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2094 #[cfg(any(ossl110, libressl))]
2095 pub fn cipher_nid(&self) -> Option<Nid> {
2096 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2097 if n == 0 {
2098 None
2099 } else {
2100 Some(Nid::from_raw(n))
2101 }
2102 }
2103
2104 #[corresponds(SSL_CIPHER_get_protocol_id)]
2108 #[cfg(ossl111)]
2109 pub fn protocol_id(&self) -> [u8; 2] {
2110 unsafe {
2111 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2112 id.to_be_bytes()
2113 }
2114 }
2115}
2116
2117impl fmt::Debug for SslCipherRef {
2118 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2119 write!(fmt, "{}", self.name())
2120 }
2121}
2122
2123#[derive(Debug)]
2125pub struct CipherLists {
2126 pub suites: Stack<SslCipher>,
2127 pub signalling_suites: Stack<SslCipher>,
2128}
2129
2130foreign_type_and_impl_send_sync! {
2131 type CType = ffi::SSL_SESSION;
2132 fn drop = ffi::SSL_SESSION_free;
2133
2134 pub struct SslSession;
2138
2139 pub struct SslSessionRef;
2143}
2144
2145impl Clone for SslSession {
2146 fn clone(&self) -> SslSession {
2147 SslSessionRef::to_owned(self)
2148 }
2149}
2150
2151impl SslSession {
2152 from_der! {
2153 #[corresponds(d2i_SSL_SESSION)]
2155 from_der,
2156 SslSession,
2157 ffi::d2i_SSL_SESSION
2158 }
2159}
2160
2161impl ToOwned for SslSessionRef {
2162 type Owned = SslSession;
2163
2164 fn to_owned(&self) -> SslSession {
2165 unsafe {
2166 SSL_SESSION_up_ref(self.as_ptr());
2167 SslSession(self.as_ptr())
2168 }
2169 }
2170}
2171
2172impl SslSessionRef {
2173 #[corresponds(SSL_SESSION_get_id)]
2175 pub fn id(&self) -> &[u8] {
2176 unsafe {
2177 let mut len = 0;
2178 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2179 #[allow(clippy::unnecessary_cast)]
2180 util::from_raw_parts(p as *const u8, len as usize)
2181 }
2182 }
2183
2184 #[corresponds(SSL_SESSION_get_master_key)]
2186 pub fn master_key_len(&self) -> usize {
2187 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2188 }
2189
2190 #[corresponds(SSL_SESSION_get_master_key)]
2194 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2195 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2196 }
2197
2198 #[corresponds(SSL_SESSION_get_max_early_data)]
2202 #[cfg(any(ossl111, libressl))]
2203 pub fn max_early_data(&self) -> u32 {
2204 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2205 }
2206
2207 #[corresponds(SSL_SESSION_get_time)]
2209 #[allow(clippy::useless_conversion)]
2210 pub fn time(&self) -> SslTimeTy {
2211 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2212 }
2213
2214 #[corresponds(SSL_SESSION_get_timeout)]
2218 #[allow(clippy::useless_conversion)]
2219 pub fn timeout(&self) -> i64 {
2220 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2221 }
2222
2223 #[corresponds(SSL_SESSION_get_protocol_version)]
2227 #[cfg(any(ossl110, libressl))]
2228 pub fn protocol_version(&self) -> SslVersion {
2229 unsafe {
2230 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2231 SslVersion(version)
2232 }
2233 }
2234
2235 to_der! {
2236 #[corresponds(i2d_SSL_SESSION)]
2238 to_der,
2239 ffi::i2d_SSL_SESSION
2240 }
2241}
2242
2243foreign_type_and_impl_send_sync! {
2244 type CType = ffi::SSL;
2245 fn drop = ffi::SSL_free;
2246
2247 pub struct Ssl;
2254
2255 pub struct SslRef;
2259}
2260
2261impl fmt::Debug for Ssl {
2262 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2263 fmt::Debug::fmt(&**self, fmt)
2264 }
2265}
2266
2267impl Ssl {
2268 #[corresponds(SSL_get_ex_new_index)]
2273 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2274 where
2275 T: 'static + Sync + Send,
2276 {
2277 unsafe {
2278 ffi::init();
2279 #[cfg(any(boringssl, awslc))]
2280 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2281 #[cfg(not(any(boringssl, awslc)))]
2282 let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
2283 Ok(Index::from_raw(idx))
2284 }
2285 }
2286
2287 fn cached_ex_index<T>() -> Index<Ssl, T>
2289 where
2290 T: 'static + Sync + Send,
2291 {
2292 unsafe {
2293 let idx = *SSL_INDEXES
2294 .lock()
2295 .unwrap_or_else(|e| e.into_inner())
2296 .entry(TypeId::of::<T>())
2297 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2298 Index::from_raw(idx)
2299 }
2300 }
2301
2302 #[corresponds(SSL_new)]
2304 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2305 let session_ctx_index = try_get_session_ctx_index()?;
2306 unsafe {
2307 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2308 let mut ssl = Ssl::from_ptr(ptr);
2309 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2310
2311 Ok(ssl)
2312 }
2313 }
2314
2315 #[corresponds(SSL_connect)]
2321 #[allow(deprecated)]
2322 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2323 where
2324 S: Read + Write,
2325 {
2326 SslStreamBuilder::new(self, stream).connect()
2327 }
2328
2329 #[corresponds(SSL_accept)]
2336 #[allow(deprecated)]
2337 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2338 where
2339 S: Read + Write,
2340 {
2341 SslStreamBuilder::new(self, stream).accept()
2342 }
2343}
2344
2345impl fmt::Debug for SslRef {
2346 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2347 fmt.debug_struct("Ssl")
2348 .field("state", &self.state_string_long())
2349 .field("verify_result", &self.verify_result())
2350 .finish()
2351 }
2352}
2353
2354impl SslRef {
2355 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2356 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2357 }
2358
2359 fn get_error(&self, ret: c_int) -> ErrorCode {
2360 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2361 }
2362
2363 #[corresponds(SSL_set_connect_state)]
2365 pub fn set_connect_state(&mut self) {
2366 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2367 }
2368
2369 #[corresponds(SSL_set_accept_state)]
2371 pub fn set_accept_state(&mut self) {
2372 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2373 }
2374
2375 #[corresponds(SSL_set_verify)]
2379 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2380 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2381 }
2382
2383 #[corresponds(SSL_set_verify_mode)]
2385 pub fn verify_mode(&self) -> SslVerifyMode {
2386 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2387 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2388 }
2389
2390 #[corresponds(SSL_set_verify)]
2394 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2395 where
2396 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2397 {
2398 unsafe {
2399 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2401 ffi::SSL_set_verify(
2402 self.as_ptr(),
2403 mode.bits() as c_int,
2404 Some(ssl_raw_verify::<F>),
2405 );
2406 }
2407 }
2408
2409 #[corresponds(SSL_set_tmp_dh)]
2413 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2414 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2415 }
2416
2417 #[corresponds(SSL_set_tmp_dh_callback)]
2421 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2422 where
2423 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2424 {
2425 unsafe {
2426 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2428 #[cfg(any(boringssl, awslc))]
2429 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2430 #[cfg(not(any(boringssl, awslc)))]
2431 ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2432 }
2433 }
2434
2435 #[corresponds(SSL_set_tmp_ecdh)]
2439 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
2440 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
2441 }
2442
2443 #[corresponds(SSL_set_ecdh_auto)]
2449 #[cfg(libressl)]
2450 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2451 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2452 }
2453
2454 #[corresponds(SSL_set_alpn_protos)]
2460 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2461 unsafe {
2462 assert!(protocols.len() <= c_uint::MAX as usize);
2463 let r =
2464 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2465 if r == 0 {
2467 Ok(())
2468 } else {
2469 Err(ErrorStack::get())
2470 }
2471 }
2472 }
2473
2474 #[corresponds(SSL_get_current_cipher)]
2476 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2477 unsafe {
2478 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2479
2480 SslCipherRef::from_const_ptr_opt(ptr)
2481 }
2482 }
2483
2484 #[corresponds(SSL_state_string)]
2486 pub fn state_string(&self) -> &'static str {
2487 let state = unsafe {
2488 let ptr = ffi::SSL_state_string(self.as_ptr());
2489 CStr::from_ptr(ptr as *const _)
2490 };
2491
2492 str::from_utf8(state.to_bytes()).unwrap()
2493 }
2494
2495 #[corresponds(SSL_state_string_long)]
2497 pub fn state_string_long(&self) -> &'static str {
2498 let state = unsafe {
2499 let ptr = ffi::SSL_state_string_long(self.as_ptr());
2500 CStr::from_ptr(ptr as *const _)
2501 };
2502
2503 str::from_utf8(state.to_bytes()).unwrap()
2504 }
2505
2506 #[corresponds(SSL_set_tlsext_host_name)]
2510 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2511 let cstr = CString::new(hostname).unwrap();
2512 unsafe {
2513 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2514 .map(|_| ())
2515 }
2516 }
2517
2518 #[corresponds(SSL_get_peer_certificate)]
2520 pub fn peer_certificate(&self) -> Option<X509> {
2521 unsafe {
2522 let ptr = SSL_get1_peer_certificate(self.as_ptr());
2523 X509::from_ptr_opt(ptr)
2524 }
2525 }
2526
2527 #[corresponds(SSL_get_peer_cert_chain)]
2532 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2533 unsafe {
2534 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2535 StackRef::from_const_ptr_opt(ptr)
2536 }
2537 }
2538
2539 #[corresponds(SSL_get0_verified_chain)]
2549 #[cfg(ossl110)]
2550 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2551 unsafe {
2552 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2553 StackRef::from_const_ptr_opt(ptr)
2554 }
2555 }
2556
2557 #[corresponds(SSL_get_certificate)]
2559 pub fn certificate(&self) -> Option<&X509Ref> {
2560 unsafe {
2561 let ptr = ffi::SSL_get_certificate(self.as_ptr());
2562 X509Ref::from_const_ptr_opt(ptr)
2563 }
2564 }
2565
2566 #[corresponds(SSL_get_privatekey)]
2570 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2571 unsafe {
2572 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2573 PKeyRef::from_const_ptr_opt(ptr)
2574 }
2575 }
2576
2577 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2578 pub fn version(&self) -> &str {
2579 self.version_str()
2580 }
2581
2582 #[corresponds(SSL_version)]
2584 pub fn version2(&self) -> Option<SslVersion> {
2585 unsafe {
2586 let r = ffi::SSL_version(self.as_ptr());
2587 if r == 0 {
2588 None
2589 } else {
2590 Some(SslVersion(r))
2591 }
2592 }
2593 }
2594
2595 #[corresponds(SSL_get_version)]
2597 pub fn version_str(&self) -> &'static str {
2598 let version = unsafe {
2599 let ptr = ffi::SSL_get_version(self.as_ptr());
2600 CStr::from_ptr(ptr as *const _)
2601 };
2602
2603 str::from_utf8(version.to_bytes()).unwrap()
2604 }
2605
2606 #[corresponds(SSL_get0_alpn_selected)]
2613 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2614 unsafe {
2615 let mut data: *const c_uchar = ptr::null();
2616 let mut len: c_uint = 0;
2617 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2620
2621 if data.is_null() {
2622 None
2623 } else {
2624 Some(util::from_raw_parts(data, len as usize))
2625 }
2626 }
2627 }
2628
2629 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2631 #[corresponds(SSL_set_tlsext_use_srtp)]
2632 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2633 unsafe {
2634 let cstr = CString::new(protocols).unwrap();
2635
2636 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2637 if r == 0 {
2639 Ok(())
2640 } else {
2641 Err(ErrorStack::get())
2642 }
2643 }
2644 }
2645
2646 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2650 #[corresponds(SSL_get_srtp_profiles)]
2651 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
2652 unsafe {
2653 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
2654
2655 StackRef::from_const_ptr_opt(chain)
2656 }
2657 }
2658
2659 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2663 #[corresponds(SSL_get_selected_srtp_profile)]
2664 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2665 unsafe {
2666 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2667
2668 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2669 }
2670 }
2671
2672 #[corresponds(SSL_pending)]
2677 pub fn pending(&self) -> usize {
2678 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2679 }
2680
2681 #[corresponds(SSL_get_servername)]
2694 pub fn servername(&self, type_: NameType) -> Option<&str> {
2696 self.servername_raw(type_)
2697 .and_then(|b| str::from_utf8(b).ok())
2698 }
2699
2700 #[corresponds(SSL_get_servername)]
2708 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2709 unsafe {
2710 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2711 if name.is_null() {
2712 None
2713 } else {
2714 Some(CStr::from_ptr(name as *const _).to_bytes())
2715 }
2716 }
2717 }
2718
2719 #[corresponds(SSL_set_SSL_CTX)]
2723 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2724 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2725 }
2726
2727 #[corresponds(SSL_get_SSL_CTX)]
2729 pub fn ssl_context(&self) -> &SslContextRef {
2730 unsafe {
2731 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2732 SslContextRef::from_ptr(ssl_ctx)
2733 }
2734 }
2735
2736 #[corresponds(SSL_get0_param)]
2740 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
2741 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
2742 }
2743
2744 #[corresponds(SSL_get_verify_result)]
2746 pub fn verify_result(&self) -> X509VerifyResult {
2747 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
2748 }
2749
2750 #[corresponds(SSL_get_session)]
2752 pub fn session(&self) -> Option<&SslSessionRef> {
2753 unsafe {
2754 let p = ffi::SSL_get_session(self.as_ptr());
2755 SslSessionRef::from_const_ptr_opt(p)
2756 }
2757 }
2758
2759 #[corresponds(SSL_get_client_random)]
2766 #[cfg(any(ossl110, libressl))]
2767 pub fn client_random(&self, buf: &mut [u8]) -> usize {
2768 unsafe {
2769 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2770 }
2771 }
2772
2773 #[corresponds(SSL_get_server_random)]
2780 #[cfg(any(ossl110, libressl))]
2781 pub fn server_random(&self, buf: &mut [u8]) -> usize {
2782 unsafe {
2783 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2784 }
2785 }
2786
2787 #[corresponds(SSL_export_keying_material)]
2789 pub fn export_keying_material(
2790 &self,
2791 out: &mut [u8],
2792 label: &str,
2793 context: Option<&[u8]>,
2794 ) -> Result<(), ErrorStack> {
2795 unsafe {
2796 let (context, contextlen, use_context) = match context {
2797 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
2798 None => (ptr::null(), 0, 0),
2799 };
2800 cvt(ffi::SSL_export_keying_material(
2801 self.as_ptr(),
2802 out.as_mut_ptr() as *mut c_uchar,
2803 out.len(),
2804 label.as_ptr() as *const c_char,
2805 label.len(),
2806 context,
2807 contextlen,
2808 use_context,
2809 ))
2810 .map(|_| ())
2811 }
2812 }
2813
2814 #[corresponds(SSL_export_keying_material_early)]
2821 #[cfg(ossl111)]
2822 pub fn export_keying_material_early(
2823 &self,
2824 out: &mut [u8],
2825 label: &str,
2826 context: &[u8],
2827 ) -> Result<(), ErrorStack> {
2828 unsafe {
2829 cvt(ffi::SSL_export_keying_material_early(
2830 self.as_ptr(),
2831 out.as_mut_ptr() as *mut c_uchar,
2832 out.len(),
2833 label.as_ptr() as *const c_char,
2834 label.len(),
2835 context.as_ptr() as *const c_uchar,
2836 context.len(),
2837 ))
2838 .map(|_| ())
2839 }
2840 }
2841
2842 #[corresponds(SSL_set_session)]
2853 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
2854 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
2855 }
2856
2857 #[corresponds(SSL_session_reused)]
2859 pub fn session_reused(&self) -> bool {
2860 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
2861 }
2862
2863 #[corresponds(SSL_set_tlsext_status_type)]
2865 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
2866 unsafe {
2867 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
2868 }
2869 }
2870
2871 #[corresponds(SSL_get_extms_support)]
2875 #[cfg(ossl110)]
2876 pub fn extms_support(&self) -> Option<bool> {
2877 unsafe {
2878 match ffi::SSL_get_extms_support(self.as_ptr()) {
2879 -1 => None,
2880 ret => Some(ret != 0),
2881 }
2882 }
2883 }
2884
2885 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
2887 #[cfg(not(any(boringssl, awslc)))]
2888 pub fn ocsp_status(&self) -> Option<&[u8]> {
2889 unsafe {
2890 let mut p = ptr::null_mut();
2891 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
2892
2893 if len < 0 {
2894 None
2895 } else {
2896 Some(util::from_raw_parts(p as *const u8, len as usize))
2897 }
2898 }
2899 }
2900
2901 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
2903 #[cfg(not(any(boringssl, awslc)))]
2904 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
2905 unsafe {
2906 assert!(response.len() <= c_int::MAX as usize);
2907 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
2908 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
2909 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
2910 self.as_ptr(),
2911 p as *mut c_uchar,
2912 response.len() as c_long,
2913 ) as c_int)
2914 .map(|_| ())
2915 .map_err(|e| {
2916 ffi::OPENSSL_free(p);
2917 e
2918 })
2919 }
2920 }
2921
2922 #[corresponds(SSL_is_server)]
2924 pub fn is_server(&self) -> bool {
2925 unsafe { SSL_is_server(self.as_ptr()) != 0 }
2926 }
2927
2928 #[corresponds(SSL_set_ex_data)]
2934 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
2935 match self.ex_data_mut(index) {
2936 Some(v) => *v = data,
2937 None => unsafe {
2938 let data = Box::new(data);
2939 ffi::SSL_set_ex_data(
2940 self.as_ptr(),
2941 index.as_raw(),
2942 Box::into_raw(data) as *mut c_void,
2943 );
2944 },
2945 }
2946 }
2947
2948 #[corresponds(SSL_get_ex_data)]
2950 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
2951 unsafe {
2952 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2953 if data.is_null() {
2954 None
2955 } else {
2956 Some(&*(data as *const T))
2957 }
2958 }
2959 }
2960
2961 #[corresponds(SSL_get_ex_data)]
2963 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
2964 unsafe {
2965 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2966 if data.is_null() {
2967 None
2968 } else {
2969 Some(&mut *(data as *mut T))
2970 }
2971 }
2972 }
2973
2974 #[corresponds(SSL_set_max_early_data)]
2978 #[cfg(any(ossl111, libressl))]
2979 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2980 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2981 Ok(())
2982 } else {
2983 Err(ErrorStack::get())
2984 }
2985 }
2986
2987 #[corresponds(SSL_get_max_early_data)]
2991 #[cfg(any(ossl111, libressl))]
2992 pub fn max_early_data(&self) -> u32 {
2993 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
2994 }
2995
2996 #[corresponds(SSL_get_finished)]
3001 pub fn finished(&self, buf: &mut [u8]) -> usize {
3002 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3003 }
3004
3005 #[corresponds(SSL_get_peer_finished)]
3011 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3012 unsafe {
3013 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3014 }
3015 }
3016
3017 #[corresponds(SSL_is_init_finished)]
3019 #[cfg(ossl110)]
3020 pub fn is_init_finished(&self) -> bool {
3021 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3022 }
3023
3024 #[corresponds(SSL_client_hello_isv2)]
3030 #[cfg(ossl111)]
3031 pub fn client_hello_isv2(&self) -> bool {
3032 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3033 }
3034
3035 #[corresponds(SSL_client_hello_get0_legacy_version)]
3041 #[cfg(ossl111)]
3042 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3043 unsafe {
3044 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3045 if version == 0 {
3046 None
3047 } else {
3048 Some(SslVersion(version as c_int))
3049 }
3050 }
3051 }
3052
3053 #[corresponds(SSL_client_hello_get0_random)]
3059 #[cfg(ossl111)]
3060 pub fn client_hello_random(&self) -> Option<&[u8]> {
3061 unsafe {
3062 let mut ptr = ptr::null();
3063 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3064 if len == 0 {
3065 None
3066 } else {
3067 Some(util::from_raw_parts(ptr, len))
3068 }
3069 }
3070 }
3071
3072 #[corresponds(SSL_client_hello_get0_session_id)]
3078 #[cfg(ossl111)]
3079 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3080 unsafe {
3081 let mut ptr = ptr::null();
3082 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3083 if len == 0 {
3084 None
3085 } else {
3086 Some(util::from_raw_parts(ptr, len))
3087 }
3088 }
3089 }
3090
3091 #[corresponds(SSL_client_hello_get0_ciphers)]
3097 #[cfg(ossl111)]
3098 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3099 unsafe {
3100 let mut ptr = ptr::null();
3101 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3102 if len == 0 {
3103 None
3104 } else {
3105 Some(util::from_raw_parts(ptr, len))
3106 }
3107 }
3108 }
3109
3110 #[corresponds(SSL_bytes_to_cipher_list)]
3115 #[cfg(ossl111)]
3116 pub fn bytes_to_cipher_list(
3117 &self,
3118 bytes: &[u8],
3119 isv2format: bool,
3120 ) -> Result<CipherLists, ErrorStack> {
3121 unsafe {
3122 let ptr = bytes.as_ptr();
3123 let len = bytes.len();
3124 let mut sk = ptr::null_mut();
3125 let mut scsvs = ptr::null_mut();
3126 let res = ffi::SSL_bytes_to_cipher_list(
3127 self.as_ptr(),
3128 ptr,
3129 len,
3130 isv2format as c_int,
3131 &mut sk,
3132 &mut scsvs,
3133 );
3134 if res == 1 {
3135 Ok(CipherLists {
3136 suites: Stack::from_ptr(sk),
3137 signalling_suites: Stack::from_ptr(scsvs),
3138 })
3139 } else {
3140 Err(ErrorStack::get())
3141 }
3142 }
3143 }
3144
3145 #[corresponds(SSL_client_hello_get0_compression_methods)]
3151 #[cfg(ossl111)]
3152 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3153 unsafe {
3154 let mut ptr = ptr::null();
3155 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3156 if len == 0 {
3157 None
3158 } else {
3159 Some(util::from_raw_parts(ptr, len))
3160 }
3161 }
3162 }
3163
3164 #[corresponds(SSL_set_mtu)]
3166 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3167 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3168 }
3169
3170 #[corresponds(SSL_get_psk_identity_hint)]
3174 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3175 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3176 unsafe {
3177 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3178 if ptr.is_null() {
3179 None
3180 } else {
3181 Some(CStr::from_ptr(ptr).to_bytes())
3182 }
3183 }
3184 }
3185
3186 #[corresponds(SSL_get_psk_identity)]
3188 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3189 pub fn psk_identity(&self) -> Option<&[u8]> {
3190 unsafe {
3191 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3192 if ptr.is_null() {
3193 None
3194 } else {
3195 Some(CStr::from_ptr(ptr).to_bytes())
3196 }
3197 }
3198 }
3199
3200 #[corresponds(SSL_add0_chain_cert)]
3201 #[cfg(ossl110)]
3202 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3203 unsafe {
3204 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3205 mem::forget(chain);
3206 }
3207 Ok(())
3208 }
3209
3210 #[cfg(not(any(boringssl, awslc)))]
3212 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3213 unsafe {
3214 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3215 };
3216 Ok(())
3217 }
3218
3219 #[corresponds(SSL_use_Private_Key_file)]
3221 pub fn set_private_key_file<P: AsRef<Path>>(
3222 &mut self,
3223 path: P,
3224 ssl_file_type: SslFiletype,
3225 ) -> Result<(), ErrorStack> {
3226 let p = path.as_ref().as_os_str().to_str().unwrap();
3227 let key_file = CString::new(p).unwrap();
3228 unsafe {
3229 cvt(ffi::SSL_use_PrivateKey_file(
3230 self.as_ptr(),
3231 key_file.as_ptr(),
3232 ssl_file_type.as_raw(),
3233 ))?;
3234 };
3235 Ok(())
3236 }
3237
3238 #[corresponds(SSL_use_PrivateKey)]
3240 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3241 unsafe {
3242 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3243 };
3244 Ok(())
3245 }
3246
3247 #[corresponds(SSL_use_certificate)]
3249 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3250 unsafe {
3251 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3252 };
3253 Ok(())
3254 }
3255
3256 #[corresponds(SSL_use_certificate_chain_file)]
3262 #[cfg(any(ossl110, libressl))]
3263 pub fn set_certificate_chain_file<P: AsRef<Path>>(
3264 &mut self,
3265 path: P,
3266 ) -> Result<(), ErrorStack> {
3267 let p = path.as_ref().as_os_str().to_str().unwrap();
3268 let cert_file = CString::new(p).unwrap();
3269 unsafe {
3270 cvt(ffi::SSL_use_certificate_chain_file(
3271 self.as_ptr(),
3272 cert_file.as_ptr(),
3273 ))?;
3274 };
3275 Ok(())
3276 }
3277
3278 #[corresponds(SSL_add_client_CA)]
3280 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
3281 unsafe {
3282 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
3283 };
3284 Ok(())
3285 }
3286
3287 #[corresponds(SSL_set_client_CA_list)]
3289 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3290 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3291 mem::forget(list);
3292 }
3293
3294 #[corresponds(SSL_set_min_proto_version)]
3299 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3300 unsafe {
3301 cvt(ffi::SSL_set_min_proto_version(
3302 self.as_ptr(),
3303 version.map_or(0, |v| v.0 as _),
3304 ))
3305 .map(|_| ())
3306 }
3307 }
3308
3309 #[corresponds(SSL_set_max_proto_version)]
3314 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3315 unsafe {
3316 cvt(ffi::SSL_set_max_proto_version(
3317 self.as_ptr(),
3318 version.map_or(0, |v| v.0 as _),
3319 ))
3320 .map(|_| ())
3321 }
3322 }
3323
3324 #[corresponds(SSL_set_ciphersuites)]
3333 #[cfg(any(ossl111, libressl))]
3334 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3335 let cipher_list = CString::new(cipher_list).unwrap();
3336 unsafe {
3337 cvt(ffi::SSL_set_ciphersuites(
3338 self.as_ptr(),
3339 cipher_list.as_ptr() as *const _,
3340 ))
3341 .map(|_| ())
3342 }
3343 }
3344
3345 #[corresponds(SSL_set_cipher_list)]
3353 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3354 let cipher_list = CString::new(cipher_list).unwrap();
3355 unsafe {
3356 cvt(ffi::SSL_set_cipher_list(
3357 self.as_ptr(),
3358 cipher_list.as_ptr() as *const _,
3359 ))
3360 .map(|_| ())
3361 }
3362 }
3363
3364 #[corresponds(SSL_set_cert_store)]
3366 #[cfg(ossl110)]
3367 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3368 unsafe {
3369 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
3370 mem::forget(cert_store);
3371 Ok(())
3372 }
3373 }
3374
3375 #[corresponds(SSL_set_num_tickets)]
3380 #[cfg(ossl111)]
3381 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
3382 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
3383 }
3384
3385 #[corresponds(SSL_get_num_tickets)]
3390 #[cfg(ossl111)]
3391 pub fn num_tickets(&self) -> usize {
3392 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
3393 }
3394
3395 #[corresponds(SSL_set_security_level)]
3400 #[cfg(any(ossl110, libressl360))]
3401 pub fn set_security_level(&mut self, level: u32) {
3402 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
3403 }
3404
3405 #[corresponds(SSL_get_security_level)]
3410 #[cfg(any(ossl110, libressl360))]
3411 pub fn security_level(&self) -> u32 {
3412 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
3413 }
3414
3415 #[corresponds(SSL_get_peer_tmp_key)]
3420 #[cfg(ossl300)]
3421 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
3422 unsafe {
3423 let mut key = ptr::null_mut();
3424 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
3425 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
3426 Err(e) => Err(e),
3427 }
3428 }
3429 }
3430
3431 #[corresponds(SSL_get_tmp_key)]
3436 #[cfg(ossl300)]
3437 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
3438 unsafe {
3439 let mut key = ptr::null_mut();
3440 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
3441 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
3442 Err(e) => Err(e),
3443 }
3444 }
3445 }
3446}
3447
3448#[derive(Debug)]
3450pub struct MidHandshakeSslStream<S> {
3451 stream: SslStream<S>,
3452 error: Error,
3453}
3454
3455impl<S> MidHandshakeSslStream<S> {
3456 pub fn get_ref(&self) -> &S {
3458 self.stream.get_ref()
3459 }
3460
3461 pub fn get_mut(&mut self) -> &mut S {
3463 self.stream.get_mut()
3464 }
3465
3466 pub fn ssl(&self) -> &SslRef {
3468 self.stream.ssl()
3469 }
3470
3471 pub fn error(&self) -> &Error {
3473 &self.error
3474 }
3475
3476 pub fn into_error(self) -> Error {
3478 self.error
3479 }
3480}
3481
3482impl<S> MidHandshakeSslStream<S>
3483where
3484 S: Read + Write,
3485{
3486 #[corresponds(SSL_do_handshake)]
3489 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3490 match self.stream.do_handshake() {
3491 Ok(()) => Ok(self.stream),
3492 Err(error) => {
3493 self.error = error;
3494 match self.error.code() {
3495 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3496 Err(HandshakeError::WouldBlock(self))
3497 }
3498 _ => Err(HandshakeError::Failure(self)),
3499 }
3500 }
3501 }
3502 }
3503}
3504
3505pub struct SslStream<S> {
3507 ssl: ManuallyDrop<Ssl>,
3508 method: ManuallyDrop<BioMethod>,
3509 _p: PhantomData<S>,
3510}
3511
3512impl<S> Drop for SslStream<S> {
3513 fn drop(&mut self) {
3514 unsafe {
3516 ManuallyDrop::drop(&mut self.ssl);
3517 ManuallyDrop::drop(&mut self.method);
3518 }
3519 }
3520}
3521
3522impl<S> fmt::Debug for SslStream<S>
3523where
3524 S: fmt::Debug,
3525{
3526 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3527 fmt.debug_struct("SslStream")
3528 .field("stream", &self.get_ref())
3529 .field("ssl", &self.ssl())
3530 .finish()
3531 }
3532}
3533
3534impl<S: Read + Write> SslStream<S> {
3535 #[corresponds(SSL_set_bio)]
3543 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3544 let (bio, method) = bio::new(stream)?;
3545 unsafe {
3546 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3547 }
3548
3549 Ok(SslStream {
3550 ssl: ManuallyDrop::new(ssl),
3551 method: ManuallyDrop::new(method),
3552 _p: PhantomData,
3553 })
3554 }
3555
3556 #[deprecated(
3564 since = "0.10.32",
3565 note = "use Ssl::from_ptr and SslStream::new instead"
3566 )]
3567 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3568 let ssl = Ssl::from_ptr(ssl);
3569 Self::new(ssl, stream).unwrap()
3570 }
3571
3572 #[corresponds(SSL_read_early_data)]
3581 #[cfg(any(ossl111, libressl))]
3582 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3583 let mut read = 0;
3584 let ret = unsafe {
3585 ffi::SSL_read_early_data(
3586 self.ssl.as_ptr(),
3587 buf.as_ptr() as *mut c_void,
3588 buf.len(),
3589 &mut read,
3590 )
3591 };
3592 match ret {
3593 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
3594 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
3595 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
3596 _ => unreachable!(),
3597 }
3598 }
3599
3600 #[corresponds(SSL_write_early_data)]
3607 #[cfg(any(ossl111, libressl))]
3608 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
3609 let mut written = 0;
3610 let ret = unsafe {
3611 ffi::SSL_write_early_data(
3612 self.ssl.as_ptr(),
3613 buf.as_ptr() as *const c_void,
3614 buf.len(),
3615 &mut written,
3616 )
3617 };
3618 if ret > 0 {
3619 Ok(written)
3620 } else {
3621 Err(self.make_error(ret))
3622 }
3623 }
3624
3625 #[corresponds(SSL_connect)]
3632 pub fn connect(&mut self) -> Result<(), Error> {
3633 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
3634 if ret > 0 {
3635 Ok(())
3636 } else {
3637 Err(self.make_error(ret))
3638 }
3639 }
3640
3641 #[corresponds(SSL_accept)]
3648 pub fn accept(&mut self) -> Result<(), Error> {
3649 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
3650 if ret > 0 {
3651 Ok(())
3652 } else {
3653 Err(self.make_error(ret))
3654 }
3655 }
3656
3657 #[corresponds(SSL_do_handshake)]
3661 pub fn do_handshake(&mut self) -> Result<(), Error> {
3662 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
3663 if ret > 0 {
3664 Ok(())
3665 } else {
3666 Err(self.make_error(ret))
3667 }
3668 }
3669
3670 #[corresponds(SSL_stateless)]
3681 #[cfg(ossl111)]
3682 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
3683 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
3684 1 => Ok(true),
3685 0 => Ok(false),
3686 -1 => Err(ErrorStack::get()),
3687 _ => unreachable!(),
3688 }
3689 }
3690
3691 #[corresponds(SSL_read_ex)]
3698 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3699 loop {
3700 match self.ssl_read_uninit(buf) {
3701 Ok(n) => return Ok(n),
3702 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3703 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3704 return Ok(0);
3705 }
3706 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3707 Err(e) => {
3708 return Err(e
3709 .into_io_error()
3710 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
3711 }
3712 }
3713 }
3714 }
3715
3716 #[corresponds(SSL_read_ex)]
3721 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3722 unsafe {
3724 self.ssl_read_uninit(util::from_raw_parts_mut(
3725 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3726 buf.len(),
3727 ))
3728 }
3729 }
3730
3731 #[corresponds(SSL_read_ex)]
3738 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3739 if buf.is_empty() {
3740 return Ok(0);
3741 }
3742
3743 cfg_if! {
3744 if #[cfg(any(ossl111, libressl))] {
3745 let mut readbytes = 0;
3746 let ret = unsafe {
3747 ffi::SSL_read_ex(
3748 self.ssl().as_ptr(),
3749 buf.as_mut_ptr().cast(),
3750 buf.len(),
3751 &mut readbytes,
3752 )
3753 };
3754
3755 if ret > 0 {
3756 Ok(readbytes)
3757 } else {
3758 Err(self.make_error(ret))
3759 }
3760 } else {
3761 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3762 let ret = unsafe {
3763 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3764 };
3765 if ret > 0 {
3766 Ok(ret as usize)
3767 } else {
3768 Err(self.make_error(ret))
3769 }
3770 }
3771 }
3772 }
3773
3774 #[corresponds(SSL_write_ex)]
3779 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3780 if buf.is_empty() {
3781 return Ok(0);
3782 }
3783
3784 cfg_if! {
3785 if #[cfg(any(ossl111, libressl))] {
3786 let mut written = 0;
3787 let ret = unsafe {
3788 ffi::SSL_write_ex(
3789 self.ssl().as_ptr(),
3790 buf.as_ptr().cast(),
3791 buf.len(),
3792 &mut written,
3793 )
3794 };
3795
3796 if ret > 0 {
3797 Ok(written)
3798 } else {
3799 Err(self.make_error(ret))
3800 }
3801 } else {
3802 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3803 let ret = unsafe {
3804 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
3805 };
3806 if ret > 0 {
3807 Ok(ret as usize)
3808 } else {
3809 Err(self.make_error(ret))
3810 }
3811 }
3812 }
3813 }
3814
3815 #[corresponds(SSL_peek_ex)]
3817 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3818 cfg_if! {
3819 if #[cfg(any(ossl111, libressl))] {
3820 let mut readbytes = 0;
3821 let ret = unsafe {
3822 ffi::SSL_peek_ex(
3823 self.ssl().as_ptr(),
3824 buf.as_mut_ptr().cast(),
3825 buf.len(),
3826 &mut readbytes,
3827 )
3828 };
3829
3830 if ret > 0 {
3831 Ok(readbytes)
3832 } else {
3833 Err(self.make_error(ret))
3834 }
3835 } else {
3836 if buf.is_empty() {
3837 return Ok(0);
3838 }
3839
3840 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3841 let ret = unsafe {
3842 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3843 };
3844 if ret > 0 {
3845 Ok(ret as usize)
3846 } else {
3847 Err(self.make_error(ret))
3848 }
3849 }
3850 }
3851 }
3852
3853 #[corresponds(SSL_shutdown)]
3863 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
3864 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
3865 0 => Ok(ShutdownResult::Sent),
3866 1 => Ok(ShutdownResult::Received),
3867 n => Err(self.make_error(n)),
3868 }
3869 }
3870
3871 #[corresponds(SSL_get_shutdown)]
3873 pub fn get_shutdown(&mut self) -> ShutdownState {
3874 unsafe {
3875 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
3876 ShutdownState::from_bits_retain(bits)
3877 }
3878 }
3879
3880 #[corresponds(SSL_set_shutdown)]
3885 pub fn set_shutdown(&mut self, state: ShutdownState) {
3886 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
3887 }
3888}
3889
3890impl<S> SslStream<S> {
3891 fn make_error(&mut self, ret: c_int) -> Error {
3892 self.check_panic();
3893
3894 let code = self.ssl.get_error(ret);
3895
3896 let cause = match code {
3897 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
3898 ErrorCode::SYSCALL => {
3899 let errs = ErrorStack::get();
3900 if errs.errors().is_empty() {
3901 self.get_bio_error().map(InnerError::Io)
3902 } else {
3903 Some(InnerError::Ssl(errs))
3904 }
3905 }
3906 ErrorCode::ZERO_RETURN => None,
3907 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3908 self.get_bio_error().map(InnerError::Io)
3909 }
3910 _ => None,
3911 };
3912
3913 Error { code, cause }
3914 }
3915
3916 fn check_panic(&mut self) {
3917 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
3918 resume_unwind(err)
3919 }
3920 }
3921
3922 fn get_bio_error(&mut self) -> Option<io::Error> {
3923 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
3924 }
3925
3926 pub fn get_ref(&self) -> &S {
3928 unsafe {
3929 let bio = self.ssl.get_raw_rbio();
3930 bio::get_ref(bio)
3931 }
3932 }
3933
3934 pub fn get_mut(&mut self) -> &mut S {
3941 unsafe {
3942 let bio = self.ssl.get_raw_rbio();
3943 bio::get_mut(bio)
3944 }
3945 }
3946
3947 pub fn ssl(&self) -> &SslRef {
3949 &self.ssl
3950 }
3951}
3952
3953impl<S: Read + Write> Read for SslStream<S> {
3954 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3955 unsafe {
3957 self.read_uninit(util::from_raw_parts_mut(
3958 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3959 buf.len(),
3960 ))
3961 }
3962 }
3963}
3964
3965impl<S: Read + Write> Write for SslStream<S> {
3966 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
3967 loop {
3968 match self.ssl_write(buf) {
3969 Ok(n) => return Ok(n),
3970 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3971 Err(e) => {
3972 return Err(e
3973 .into_io_error()
3974 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
3975 }
3976 }
3977 }
3978 }
3979
3980 fn flush(&mut self) -> io::Result<()> {
3981 self.get_mut().flush()
3982 }
3983}
3984
3985#[deprecated(
3987 since = "0.10.32",
3988 note = "use the methods directly on Ssl/SslStream instead"
3989)]
3990pub struct SslStreamBuilder<S> {
3991 inner: SslStream<S>,
3992}
3993
3994#[allow(deprecated)]
3995impl<S> SslStreamBuilder<S>
3996where
3997 S: Read + Write,
3998{
3999 pub fn new(ssl: Ssl, stream: S) -> Self {
4001 Self {
4002 inner: SslStream::new(ssl, stream).unwrap(),
4003 }
4004 }
4005
4006 #[corresponds(SSL_stateless)]
4017 #[cfg(ossl111)]
4018 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4019 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4020 1 => Ok(true),
4021 0 => Ok(false),
4022 -1 => Err(ErrorStack::get()),
4023 _ => unreachable!(),
4024 }
4025 }
4026
4027 #[corresponds(SSL_set_connect_state)]
4029 pub fn set_connect_state(&mut self) {
4030 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4031 }
4032
4033 #[corresponds(SSL_set_accept_state)]
4035 pub fn set_accept_state(&mut self) {
4036 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4037 }
4038
4039 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4041 match self.inner.connect() {
4042 Ok(()) => Ok(self.inner),
4043 Err(error) => match error.code() {
4044 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4045 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4046 stream: self.inner,
4047 error,
4048 }))
4049 }
4050 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4051 stream: self.inner,
4052 error,
4053 })),
4054 },
4055 }
4056 }
4057
4058 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4060 match self.inner.accept() {
4061 Ok(()) => Ok(self.inner),
4062 Err(error) => match error.code() {
4063 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4064 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4065 stream: self.inner,
4066 error,
4067 }))
4068 }
4069 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4070 stream: self.inner,
4071 error,
4072 })),
4073 },
4074 }
4075 }
4076
4077 #[corresponds(SSL_do_handshake)]
4081 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4082 match self.inner.do_handshake() {
4083 Ok(()) => Ok(self.inner),
4084 Err(error) => match error.code() {
4085 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4086 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4087 stream: self.inner,
4088 error,
4089 }))
4090 }
4091 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4092 stream: self.inner,
4093 error,
4094 })),
4095 },
4096 }
4097 }
4098
4099 #[corresponds(SSL_read_early_data)]
4109 #[cfg(any(ossl111, libressl))]
4110 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4111 self.inner.read_early_data(buf)
4112 }
4113
4114 #[corresponds(SSL_write_early_data)]
4121 #[cfg(any(ossl111, libressl))]
4122 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4123 self.inner.write_early_data(buf)
4124 }
4125}
4126
4127#[allow(deprecated)]
4128impl<S> SslStreamBuilder<S> {
4129 pub fn get_ref(&self) -> &S {
4131 unsafe {
4132 let bio = self.inner.ssl.get_raw_rbio();
4133 bio::get_ref(bio)
4134 }
4135 }
4136
4137 pub fn get_mut(&mut self) -> &mut S {
4144 unsafe {
4145 let bio = self.inner.ssl.get_raw_rbio();
4146 bio::get_mut(bio)
4147 }
4148 }
4149
4150 pub fn ssl(&self) -> &SslRef {
4152 &self.inner.ssl
4153 }
4154
4155 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4163 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4164 unsafe {
4165 let bio = self.inner.ssl.get_raw_rbio();
4166 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4167 }
4168 }
4169}
4170
4171#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4173pub enum ShutdownResult {
4174 Sent,
4176
4177 Received,
4179}
4180
4181bitflags! {
4182 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4184 #[repr(transparent)]
4185 pub struct ShutdownState: c_int {
4186 const SENT = ffi::SSL_SENT_SHUTDOWN;
4188 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4190 }
4191}
4192
4193use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4194cfg_if! {
4195 if #[cfg(ossl300)] {
4196 use ffi::SSL_get1_peer_certificate;
4197 } else {
4198 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4199 }
4200}
4201use ffi::{
4202 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4203 TLS_server_method,
4204};
4205cfg_if! {
4206 if #[cfg(ossl110)] {
4207 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4208 ffi::CRYPTO_get_ex_new_index(
4209 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4210 0,
4211 ptr::null_mut(),
4212 None,
4213 None,
4214 Some(f),
4215 )
4216 }
4217
4218 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4219 ffi::CRYPTO_get_ex_new_index(
4220 ffi::CRYPTO_EX_INDEX_SSL,
4221 0,
4222 ptr::null_mut(),
4223 None,
4224 None,
4225 Some(f),
4226 )
4227 }
4228 } else {
4229 use std::sync::Once;
4230
4231 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4232 static ONCE: Once = Once::new();
4234 ONCE.call_once(|| {
4235 cfg_if! {
4236 if #[cfg(not(any(boringssl, awslc)))] {
4237 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4238 } else {
4239 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4240 }
4241 }
4242 });
4243
4244 cfg_if! {
4245 if #[cfg(not(any(boringssl, awslc)))] {
4246 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
4247 } else {
4248 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4249 }
4250 }
4251 }
4252
4253 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4254 static ONCE: Once = Once::new();
4256 ONCE.call_once(|| {
4257 #[cfg(not(any(boringssl, awslc)))]
4258 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4259 #[cfg(any(boringssl, awslc))]
4260 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4261 });
4262
4263 #[cfg(not(any(boringssl, awslc)))]
4264 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
4265 #[cfg(any(boringssl, awslc))]
4266 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
4267 }
4268 }
4269}