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(not(any(boringssl, awslc)))]
155 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
156
157 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
161
162 #[cfg(not(any(boringssl, awslc)))]
168 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
169
170 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
172
173 #[cfg(not(any(boringssl, awslc)))]
175 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
176 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
177
178 #[cfg(not(any(boringssl, awslc)))]
180 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
181
182 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
185 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
186
187 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
191
192 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
196
197 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
201
202 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
204
205 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
207
208 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
210
211 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
213
214 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
216
217 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
219
220 #[cfg(any(ossl111, boringssl, libressl, awslc))]
224 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
225
226 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
228
229 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
231
232 #[cfg(ossl110)]
248 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
249
250 #[cfg(any(boringssl, ossl110h, awslc))]
254 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
255
256 #[cfg(ossl111)]
261 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
262
263 #[cfg(ossl111)]
275 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
276 }
277}
278
279bitflags! {
280 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
282 #[repr(transparent)]
283 pub struct SslMode: SslBitType {
284 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
290
291 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
294
295 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
305
306 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
312
313 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
317
318 #[cfg(not(libressl))]
326 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
327 }
328}
329
330#[derive(Copy, Clone)]
332pub struct SslMethod(*const ffi::SSL_METHOD);
333
334impl SslMethod {
335 #[corresponds(TLS_method)]
337 pub fn tls() -> SslMethod {
338 unsafe { SslMethod(TLS_method()) }
339 }
340
341 #[corresponds(DTLS_method)]
343 pub fn dtls() -> SslMethod {
344 unsafe { SslMethod(DTLS_method()) }
345 }
346
347 #[corresponds(TLS_client_method)]
349 pub fn tls_client() -> SslMethod {
350 unsafe { SslMethod(TLS_client_method()) }
351 }
352
353 #[corresponds(TLS_server_method)]
355 pub fn tls_server() -> SslMethod {
356 unsafe { SslMethod(TLS_server_method()) }
357 }
358
359 #[corresponds(DTLS_client_method)]
361 pub fn dtls_client() -> SslMethod {
362 unsafe { SslMethod(DTLS_client_method()) }
363 }
364
365 #[corresponds(DTLS_server_method)]
367 pub fn dtls_server() -> SslMethod {
368 unsafe { SslMethod(DTLS_server_method()) }
369 }
370
371 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
377 SslMethod(ptr)
378 }
379
380 #[allow(clippy::trivially_copy_pass_by_ref)]
382 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
383 self.0
384 }
385}
386
387unsafe impl Sync for SslMethod {}
388unsafe impl Send for SslMethod {}
389
390bitflags! {
391 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
393 #[repr(transparent)]
394 pub struct SslVerifyMode: i32 {
395 const PEER = ffi::SSL_VERIFY_PEER;
399
400 const NONE = ffi::SSL_VERIFY_NONE;
406
407 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
411 }
412}
413
414#[cfg(any(boringssl, awslc))]
415type SslBitType = c_int;
416#[cfg(not(any(boringssl, awslc)))]
417type SslBitType = c_long;
418
419#[cfg(any(boringssl, awslc))]
420type SslTimeTy = u64;
421#[cfg(not(any(boringssl, awslc)))]
422type SslTimeTy = c_long;
423
424bitflags! {
425 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
427 #[repr(transparent)]
428 pub struct SslSessionCacheMode: SslBitType {
429 const OFF = ffi::SSL_SESS_CACHE_OFF;
431
432 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
439
440 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
444
445 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
447
448 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
450
451 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
453
454 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
456
457 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
459 }
460}
461
462#[cfg(ossl111)]
463bitflags! {
464 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
466 #[repr(transparent)]
467 pub struct ExtensionContext: c_uint {
468 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
470 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
472 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
474 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
476 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
478 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
480 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
482 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
483 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
485 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
486 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
487 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
488 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
489 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
490 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
491 }
492}
493
494#[derive(Copy, Clone)]
496pub struct SslFiletype(c_int);
497
498impl SslFiletype {
499 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
503
504 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
508
509 pub fn from_raw(raw: c_int) -> SslFiletype {
511 SslFiletype(raw)
512 }
513
514 #[allow(clippy::trivially_copy_pass_by_ref)]
516 pub fn as_raw(&self) -> c_int {
517 self.0
518 }
519}
520
521#[derive(Copy, Clone)]
523pub struct StatusType(c_int);
524
525impl StatusType {
526 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
528
529 pub fn from_raw(raw: c_int) -> StatusType {
531 StatusType(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 NameType(c_int);
544
545impl NameType {
546 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
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
561static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
562static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
563static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
564
565fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
566 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
567}
568
569unsafe extern "C" fn free_data_box<T>(
570 _parent: *mut c_void,
571 ptr: *mut c_void,
572 _ad: *mut ffi::CRYPTO_EX_DATA,
573 _idx: c_int,
574 _argl: c_long,
575 _argp: *mut c_void,
576) {
577 if !ptr.is_null() {
578 let _ = Box::<T>::from_raw(ptr as *mut T);
579 }
580}
581
582#[derive(Debug, Copy, Clone, PartialEq, Eq)]
584pub struct SniError(c_int);
585
586impl SniError {
587 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
589
590 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
592
593 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
594}
595
596#[derive(Debug, Copy, Clone, PartialEq, Eq)]
598pub struct SslAlert(c_int);
599
600impl SslAlert {
601 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
603 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
604 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
605}
606
607#[derive(Debug, Copy, Clone, PartialEq, Eq)]
611pub struct AlpnError(c_int);
612
613impl AlpnError {
614 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
616
617 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
619}
620
621#[cfg(ossl111)]
625#[derive(Debug, Copy, Clone, PartialEq, Eq)]
626pub struct ClientHelloResponse(c_int);
627
628#[cfg(ossl111)]
629impl ClientHelloResponse {
630 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
632
633 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
635}
636
637#[derive(Debug, Copy, Clone, PartialEq, Eq)]
639pub struct SslVersion(c_int);
640
641impl SslVersion {
642 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
644
645 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
647
648 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
650
651 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
653
654 #[cfg(any(ossl111, libressl, boringssl, awslc))]
658 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
659
660 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
664
665 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
669}
670
671cfg_if! {
672 if #[cfg(any(boringssl, awslc))] {
673 type SslCacheTy = i64;
674 type SslCacheSize = libc::c_ulong;
675 type MtuTy = u32;
676 type SizeTy = usize;
677 } else {
678 type SslCacheTy = i64;
679 type SslCacheSize = c_long;
680 type MtuTy = c_long;
681 type SizeTy = u32;
682 }
683}
684
685#[corresponds(SSL_select_next_proto)]
696pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
697 unsafe {
698 let mut out = ptr::null_mut();
699 let mut outlen = 0;
700 let r = ffi::SSL_select_next_proto(
701 &mut out,
702 &mut outlen,
703 server.as_ptr(),
704 server.len() as c_uint,
705 client.as_ptr(),
706 client.len() as c_uint,
707 );
708 if r == ffi::OPENSSL_NPN_NEGOTIATED {
709 Some(util::from_raw_parts(out as *const u8, outlen as usize))
710 } else {
711 None
712 }
713 }
714}
715
716pub struct SslContextBuilder(SslContext);
718
719impl SslContextBuilder {
720 #[corresponds(SSL_CTX_new)]
722 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
723 unsafe {
724 init();
725 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
726
727 Ok(SslContextBuilder::from_ptr(ctx))
728 }
729 }
730
731 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
737 SslContextBuilder(SslContext::from_ptr(ctx))
738 }
739
740 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
742 self.0.as_ptr()
743 }
744
745 #[corresponds(SSL_CTX_set_verify)]
747 pub fn set_verify(&mut self, mode: SslVerifyMode) {
748 unsafe {
749 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
750 }
751 }
752
753 #[corresponds(SSL_CTX_set_verify)]
760 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
761 where
762 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
763 {
764 unsafe {
765 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
766 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
767 }
768 }
769
770 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
778 pub fn set_servername_callback<F>(&mut self, callback: F)
780 where
781 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
782 {
783 unsafe {
784 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
790 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
791 #[cfg(any(boringssl, awslc))]
792 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
793 #[cfg(not(any(boringssl, awslc)))]
794 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
795 self.as_ptr(),
796 Some(raw_sni::<F>),
797 );
798 }
799 }
800
801 #[corresponds(SSL_CTX_set_verify_depth)]
805 pub fn set_verify_depth(&mut self, depth: u32) {
806 unsafe {
807 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
808 }
809 }
810
811 #[corresponds(SSL_CTX_set0_verify_cert_store)]
815 #[cfg(ossl110)]
816 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
817 unsafe {
818 let ptr = cert_store.as_ptr();
819 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
820 mem::forget(cert_store);
821
822 Ok(())
823 }
824 }
825
826 #[corresponds(SSL_CTX_set_cert_store)]
828 pub fn set_cert_store(&mut self, cert_store: X509Store) {
829 unsafe {
830 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
831 mem::forget(cert_store);
832 }
833 }
834
835 #[corresponds(SSL_CTX_set_read_ahead)]
842 pub fn set_read_ahead(&mut self, read_ahead: bool) {
843 unsafe {
844 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
845 }
846 }
847
848 #[corresponds(SSL_CTX_set_mode)]
850 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
851 unsafe {
852 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
853 SslMode::from_bits_retain(bits)
854 }
855 }
856
857 #[corresponds(SSL_CTX_set_tmp_dh)]
859 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
860 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
861 }
862
863 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
870 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
871 where
872 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
873 {
874 unsafe {
875 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
876
877 #[cfg(not(any(boringssl, awslc)))]
878 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
879 #[cfg(any(boringssl, awslc))]
880 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
881 }
882 }
883
884 #[corresponds(SSL_CTX_set_tmp_ecdh)]
886 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
887 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
888 }
889
890 #[corresponds(SSL_CTX_set_default_verify_paths)]
895 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
896 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
897 }
898
899 #[corresponds(SSL_CTX_load_verify_locations)]
903 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
904 self.load_verify_locations(Some(file.as_ref()), None)
905 }
906
907 #[corresponds(SSL_CTX_load_verify_locations)]
909 pub fn load_verify_locations(
910 &mut self,
911 ca_file: Option<&Path>,
912 ca_path: Option<&Path>,
913 ) -> Result<(), ErrorStack> {
914 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
915 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
916 unsafe {
917 cvt(ffi::SSL_CTX_load_verify_locations(
918 self.as_ptr(),
919 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
920 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
921 ))
922 .map(|_| ())
923 }
924 }
925
926 #[corresponds(SSL_CTX_set_client_CA_list)]
931 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
932 unsafe {
933 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
934 mem::forget(list);
935 }
936 }
937
938 #[corresponds(SSL_CTX_add_client_CA)]
941 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
942 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
943 }
944
945 #[corresponds(SSL_CTX_set_session_id_context)]
954 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
955 unsafe {
956 assert!(sid_ctx.len() <= c_uint::MAX as usize);
957 cvt(ffi::SSL_CTX_set_session_id_context(
958 self.as_ptr(),
959 sid_ctx.as_ptr(),
960 sid_ctx.len() as SizeTy,
961 ))
962 .map(|_| ())
963 }
964 }
965
966 #[corresponds(SSL_CTX_use_certificate_file)]
972 pub fn set_certificate_file<P: AsRef<Path>>(
973 &mut self,
974 file: P,
975 file_type: SslFiletype,
976 ) -> Result<(), ErrorStack> {
977 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
978 unsafe {
979 cvt(ffi::SSL_CTX_use_certificate_file(
980 self.as_ptr(),
981 file.as_ptr() as *const _,
982 file_type.as_raw(),
983 ))
984 .map(|_| ())
985 }
986 }
987
988 #[corresponds(SSL_CTX_use_certificate_chain_file)]
994 pub fn set_certificate_chain_file<P: AsRef<Path>>(
995 &mut self,
996 file: P,
997 ) -> Result<(), ErrorStack> {
998 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
999 unsafe {
1000 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1001 self.as_ptr(),
1002 file.as_ptr() as *const _,
1003 ))
1004 .map(|_| ())
1005 }
1006 }
1007
1008 #[corresponds(SSL_CTX_use_certificate)]
1012 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1013 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1014 }
1015
1016 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1021 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1022 unsafe {
1023 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1024 mem::forget(cert);
1025 Ok(())
1026 }
1027 }
1028
1029 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1031 pub fn set_private_key_file<P: AsRef<Path>>(
1032 &mut self,
1033 file: P,
1034 file_type: SslFiletype,
1035 ) -> Result<(), ErrorStack> {
1036 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1037 unsafe {
1038 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1039 self.as_ptr(),
1040 file.as_ptr() as *const _,
1041 file_type.as_raw(),
1042 ))
1043 .map(|_| ())
1044 }
1045 }
1046
1047 #[corresponds(SSL_CTX_use_PrivateKey)]
1049 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1050 where
1051 T: HasPrivate,
1052 {
1053 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1054 }
1055
1056 #[corresponds(SSL_CTX_set_cipher_list)]
1064 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1065 let cipher_list = CString::new(cipher_list).unwrap();
1066 unsafe {
1067 cvt(ffi::SSL_CTX_set_cipher_list(
1068 self.as_ptr(),
1069 cipher_list.as_ptr() as *const _,
1070 ))
1071 .map(|_| ())
1072 }
1073 }
1074
1075 #[corresponds(SSL_CTX_set_ciphersuites)]
1084 #[cfg(any(ossl111, libressl))]
1085 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1086 let cipher_list = CString::new(cipher_list).unwrap();
1087 unsafe {
1088 cvt(ffi::SSL_CTX_set_ciphersuites(
1089 self.as_ptr(),
1090 cipher_list.as_ptr() as *const _,
1091 ))
1092 .map(|_| ())
1093 }
1094 }
1095
1096 #[corresponds(SSL_CTX_set_ecdh_auto)]
1100 #[cfg(libressl)]
1101 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1102 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1103 }
1104
1105 #[corresponds(SSL_CTX_set_options)]
1112 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1113 let bits =
1114 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1115 SslOptions::from_bits_retain(bits)
1116 }
1117
1118 #[corresponds(SSL_CTX_get_options)]
1120 pub fn options(&self) -> SslOptions {
1121 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1122 SslOptions::from_bits_retain(bits)
1123 }
1124
1125 #[corresponds(SSL_CTX_clear_options)]
1127 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1128 let bits =
1129 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1130 SslOptions::from_bits_retain(bits)
1131 }
1132
1133 #[corresponds(SSL_CTX_set_min_proto_version)]
1138 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1139 unsafe {
1140 cvt(ffi::SSL_CTX_set_min_proto_version(
1141 self.as_ptr(),
1142 version.map_or(0, |v| v.0 as _),
1143 ))
1144 .map(|_| ())
1145 }
1146 }
1147
1148 #[corresponds(SSL_CTX_set_max_proto_version)]
1153 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1154 unsafe {
1155 cvt(ffi::SSL_CTX_set_max_proto_version(
1156 self.as_ptr(),
1157 version.map_or(0, |v| v.0 as _),
1158 ))
1159 .map(|_| ())
1160 }
1161 }
1162
1163 #[corresponds(SSL_CTX_get_min_proto_version)]
1170 #[cfg(any(ossl110g, libressl))]
1171 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1172 unsafe {
1173 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1174 if r == 0 {
1175 None
1176 } else {
1177 Some(SslVersion(r))
1178 }
1179 }
1180 }
1181
1182 #[corresponds(SSL_CTX_get_max_proto_version)]
1189 #[cfg(any(ossl110g, libressl))]
1190 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1191 unsafe {
1192 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1193 if r == 0 {
1194 None
1195 } else {
1196 Some(SslVersion(r))
1197 }
1198 }
1199 }
1200
1201 #[corresponds(SSL_CTX_set_alpn_protos)]
1210 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1211 unsafe {
1212 assert!(protocols.len() <= c_uint::MAX as usize);
1213 let r = ffi::SSL_CTX_set_alpn_protos(
1214 self.as_ptr(),
1215 protocols.as_ptr(),
1216 protocols.len() as _,
1217 );
1218 if r == 0 {
1220 Ok(())
1221 } else {
1222 Err(ErrorStack::get())
1223 }
1224 }
1225 }
1226
1227 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1229 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1230 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1231 unsafe {
1232 let cstr = CString::new(protocols).unwrap();
1233
1234 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1235 if r == 0 {
1237 Ok(())
1238 } else {
1239 Err(ErrorStack::get())
1240 }
1241 }
1242 }
1243
1244 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1257 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1258 where
1259 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1260 {
1261 unsafe {
1262 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1263 #[cfg(not(any(boringssl, awslc)))]
1264 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1265 self.as_ptr(),
1266 Some(callbacks::raw_alpn_select::<F>),
1267 ptr::null_mut(),
1268 );
1269 #[cfg(any(boringssl, awslc))]
1270 ffi::SSL_CTX_set_alpn_select_cb(
1271 self.as_ptr(),
1272 Some(callbacks::raw_alpn_select::<F>),
1273 ptr::null_mut(),
1274 );
1275 }
1276 }
1277
1278 #[corresponds(SSL_CTX_check_private_key)]
1280 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1281 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1282 }
1283
1284 #[corresponds(SSL_CTX_get_cert_store)]
1286 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1287 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1288 }
1289
1290 #[corresponds(SSL_CTX_get_cert_store)]
1292 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1293 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1294 }
1295
1296 #[corresponds(SSL_CTX_get0_param)]
1300 pub fn verify_param(&self) -> &X509VerifyParamRef {
1301 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1302 }
1303
1304 #[corresponds(SSL_CTX_get0_param)]
1308 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1309 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1310 }
1311
1312 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1325 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1326 where
1327 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1328 {
1329 unsafe {
1330 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1331 cvt(
1332 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1333 as c_int,
1334 )
1335 .map(|_| ())
1336 }
1337 }
1338
1339 #[corresponds(SSL_CTX_set_psk_client_callback)]
1345 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1346 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1347 where
1348 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1349 + 'static
1350 + Sync
1351 + Send,
1352 {
1353 unsafe {
1354 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1355 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1356 }
1357 }
1358
1359 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1360 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1361 pub fn set_psk_callback<F>(&mut self, callback: F)
1362 where
1363 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1364 + 'static
1365 + Sync
1366 + Send,
1367 {
1368 self.set_psk_client_callback(callback)
1369 }
1370
1371 #[corresponds(SSL_CTX_set_psk_server_callback)]
1377 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1378 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1379 where
1380 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1381 + 'static
1382 + Sync
1383 + Send,
1384 {
1385 unsafe {
1386 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1387 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1388 }
1389 }
1390
1391 #[corresponds(SSL_CTX_sess_set_new_cb)]
1405 pub fn set_new_session_callback<F>(&mut self, callback: F)
1406 where
1407 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1408 {
1409 unsafe {
1410 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1411 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1412 }
1413 }
1414
1415 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1419 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1420 where
1421 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1422 {
1423 unsafe {
1424 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1425 ffi::SSL_CTX_sess_set_remove_cb(
1426 self.as_ptr(),
1427 Some(callbacks::raw_remove_session::<F>),
1428 );
1429 }
1430 }
1431
1432 #[corresponds(SSL_CTX_sess_set_get_cb)]
1443 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1444 where
1445 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1446 {
1447 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1448 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1449 }
1450
1451 #[corresponds(SSL_CTX_set_keylog_callback)]
1459 #[cfg(any(ossl111, boringssl, awslc))]
1460 pub fn set_keylog_callback<F>(&mut self, callback: F)
1461 where
1462 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1463 {
1464 unsafe {
1465 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1466 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1467 }
1468 }
1469
1470 #[corresponds(SSL_CTX_set_session_cache_mode)]
1474 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1475 unsafe {
1476 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1477 SslSessionCacheMode::from_bits_retain(bits)
1478 }
1479 }
1480
1481 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1487 #[cfg(ossl111)]
1488 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1489 where
1490 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1491 {
1492 unsafe {
1493 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1494 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1495 self.as_ptr(),
1496 Some(raw_stateless_cookie_generate::<F>),
1497 );
1498 }
1499 }
1500
1501 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1510 #[cfg(ossl111)]
1511 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1512 where
1513 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1514 {
1515 unsafe {
1516 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1517 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1518 self.as_ptr(),
1519 Some(raw_stateless_cookie_verify::<F>),
1520 )
1521 }
1522 }
1523
1524 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1529 #[cfg(not(any(boringssl, awslc)))]
1530 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1531 where
1532 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1533 {
1534 unsafe {
1535 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1536 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1537 }
1538 }
1539
1540 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1545 #[cfg(not(any(boringssl, awslc)))]
1546 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1547 where
1548 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1549 {
1550 unsafe {
1551 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1552 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1553 }
1554 }
1555
1556 #[corresponds(SSL_CTX_set_ex_data)]
1562 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1563 self.set_ex_data_inner(index, data);
1564 }
1565
1566 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1567 match self.ex_data_mut(index) {
1568 Some(v) => {
1569 *v = data;
1570 (v as *mut T).cast()
1571 }
1572 _ => unsafe {
1573 let data = Box::into_raw(Box::new(data)) as *mut c_void;
1574 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1575 data
1576 },
1577 }
1578 }
1579
1580 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1581 unsafe {
1582 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1583 if data.is_null() {
1584 None
1585 } else {
1586 Some(&mut *data.cast())
1587 }
1588 }
1589 }
1590
1591 #[corresponds(SSL_CTX_add_custom_ext)]
1595 #[cfg(ossl111)]
1596 pub fn add_custom_ext<AddFn, ParseFn, T>(
1597 &mut self,
1598 ext_type: u16,
1599 context: ExtensionContext,
1600 add_cb: AddFn,
1601 parse_cb: ParseFn,
1602 ) -> Result<(), ErrorStack>
1603 where
1604 AddFn: Fn(
1605 &mut SslRef,
1606 ExtensionContext,
1607 Option<(usize, &X509Ref)>,
1608 ) -> Result<Option<T>, SslAlert>
1609 + 'static
1610 + Sync
1611 + Send,
1612 T: AsRef<[u8]> + 'static + Sync + Send,
1613 ParseFn: Fn(
1614 &mut SslRef,
1615 ExtensionContext,
1616 &[u8],
1617 Option<(usize, &X509Ref)>,
1618 ) -> Result<(), SslAlert>
1619 + 'static
1620 + Sync
1621 + Send,
1622 {
1623 let ret = unsafe {
1624 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1625 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1626
1627 ffi::SSL_CTX_add_custom_ext(
1628 self.as_ptr(),
1629 ext_type as c_uint,
1630 context.bits(),
1631 Some(raw_custom_ext_add::<AddFn, T>),
1632 Some(raw_custom_ext_free::<T>),
1633 ptr::null_mut(),
1634 Some(raw_custom_ext_parse::<ParseFn>),
1635 ptr::null_mut(),
1636 )
1637 };
1638 if ret == 1 {
1639 Ok(())
1640 } else {
1641 Err(ErrorStack::get())
1642 }
1643 }
1644
1645 #[corresponds(SSL_CTX_set_max_early_data)]
1651 #[cfg(any(ossl111, libressl))]
1652 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1653 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1654 Ok(())
1655 } else {
1656 Err(ErrorStack::get())
1657 }
1658 }
1659
1660 #[corresponds(SSL_CTX_set_client_hello_cb)]
1664 #[cfg(ossl111)]
1665 pub fn set_client_hello_callback<F>(&mut self, callback: F)
1666 where
1667 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1668 + 'static
1669 + Sync
1670 + Send,
1671 {
1672 unsafe {
1673 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1674 ffi::SSL_CTX_set_client_hello_cb(
1675 self.as_ptr(),
1676 Some(callbacks::raw_client_hello::<F>),
1677 ptr,
1678 );
1679 }
1680 }
1681
1682 #[corresponds(SSL_CTX_sess_set_cache_size)]
1686 #[allow(clippy::useless_conversion)]
1687 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1688 unsafe {
1689 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1690 }
1691 }
1692
1693 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1697 #[cfg(ossl110)]
1698 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1699 let sigalgs = CString::new(sigalgs).unwrap();
1700 unsafe {
1701 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1702 .map(|_| ())
1703 }
1704 }
1705
1706 #[corresponds(SSL_CTX_set1_groups_list)]
1710 #[cfg(any(ossl111, boringssl, libressl, awslc))]
1711 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1712 let groups = CString::new(groups).unwrap();
1713 unsafe {
1714 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1715 }
1716 }
1717
1718 #[corresponds(SSL_CTX_set_num_tickets)]
1723 #[cfg(ossl111)]
1724 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1725 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1726 }
1727
1728 #[corresponds(SSL_CTX_set_security_level)]
1733 #[cfg(any(ossl110, libressl360))]
1734 pub fn set_security_level(&mut self, level: u32) {
1735 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1736 }
1737
1738 pub fn build(self) -> SslContext {
1740 self.0
1741 }
1742}
1743
1744foreign_type_and_impl_send_sync! {
1745 type CType = ffi::SSL_CTX;
1746 fn drop = ffi::SSL_CTX_free;
1747
1748 pub struct SslContext;
1753
1754 pub struct SslContextRef;
1758}
1759
1760impl Clone for SslContext {
1761 fn clone(&self) -> Self {
1762 (**self).to_owned()
1763 }
1764}
1765
1766impl ToOwned for SslContextRef {
1767 type Owned = SslContext;
1768
1769 fn to_owned(&self) -> Self::Owned {
1770 unsafe {
1771 SSL_CTX_up_ref(self.as_ptr());
1772 SslContext::from_ptr(self.as_ptr())
1773 }
1774 }
1775}
1776
1777impl fmt::Debug for SslContext {
1779 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1780 write!(fmt, "SslContext")
1781 }
1782}
1783
1784impl SslContext {
1785 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1787 SslContextBuilder::new(method)
1788 }
1789
1790 #[corresponds(SSL_CTX_get_ex_new_index)]
1795 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1796 where
1797 T: 'static + Sync + Send,
1798 {
1799 unsafe {
1800 ffi::init();
1801 #[cfg(any(boringssl, awslc))]
1802 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1803 #[cfg(not(any(boringssl, awslc)))]
1804 let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1805 Ok(Index::from_raw(idx))
1806 }
1807 }
1808
1809 fn cached_ex_index<T>() -> Index<SslContext, T>
1811 where
1812 T: 'static + Sync + Send,
1813 {
1814 unsafe {
1815 let idx = *INDEXES
1816 .lock()
1817 .unwrap_or_else(|e| e.into_inner())
1818 .entry(TypeId::of::<T>())
1819 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1820 Index::from_raw(idx)
1821 }
1822 }
1823}
1824
1825impl SslContextRef {
1826 #[corresponds(SSL_CTX_get0_certificate)]
1830 #[cfg(any(ossl110, libressl))]
1831 pub fn certificate(&self) -> Option<&X509Ref> {
1832 unsafe {
1833 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1834 X509Ref::from_const_ptr_opt(ptr)
1835 }
1836 }
1837
1838 #[corresponds(SSL_CTX_get0_privatekey)]
1842 #[cfg(any(ossl110, libressl))]
1843 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1844 unsafe {
1845 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1846 PKeyRef::from_const_ptr_opt(ptr)
1847 }
1848 }
1849
1850 #[corresponds(SSL_CTX_get_cert_store)]
1852 pub fn cert_store(&self) -> &X509StoreRef {
1853 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1854 }
1855
1856 #[corresponds(SSL_CTX_get_extra_chain_certs)]
1858 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1859 unsafe {
1860 let mut chain = ptr::null_mut();
1861 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1862 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1863 }
1864 }
1865
1866 #[corresponds(SSL_CTX_get_ex_data)]
1868 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1869 unsafe {
1870 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1871 if data.is_null() {
1872 None
1873 } else {
1874 Some(&*(data as *const T))
1875 }
1876 }
1877 }
1878
1879 #[corresponds(SSL_CTX_get_max_early_data)]
1883 #[cfg(any(ossl111, libressl))]
1884 pub fn max_early_data(&self) -> u32 {
1885 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1886 }
1887
1888 #[corresponds(SSL_CTX_add_session)]
1897 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1898 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1899 }
1900
1901 #[corresponds(SSL_CTX_remove_session)]
1910 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
1911 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
1912 }
1913
1914 #[corresponds(SSL_CTX_sess_get_cache_size)]
1918 #[allow(clippy::unnecessary_cast)]
1919 pub fn session_cache_size(&self) -> i64 {
1920 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
1921 }
1922
1923 #[corresponds(SSL_CTX_get_verify_mode)]
1927 pub fn verify_mode(&self) -> SslVerifyMode {
1928 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
1929 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
1930 }
1931
1932 #[corresponds(SSL_CTX_get_num_tickets)]
1937 #[cfg(ossl111)]
1938 pub fn num_tickets(&self) -> usize {
1939 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
1940 }
1941
1942 #[corresponds(SSL_CTX_get_security_level)]
1947 #[cfg(any(ossl110, libressl360))]
1948 pub fn security_level(&self) -> u32 {
1949 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
1950 }
1951}
1952
1953pub struct CipherBits {
1955 pub secret: i32,
1957
1958 pub algorithm: i32,
1960}
1961
1962pub struct SslCipher(*mut ffi::SSL_CIPHER);
1964
1965impl ForeignType for SslCipher {
1966 type CType = ffi::SSL_CIPHER;
1967 type Ref = SslCipherRef;
1968
1969 #[inline]
1970 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
1971 SslCipher(ptr)
1972 }
1973
1974 #[inline]
1975 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
1976 self.0
1977 }
1978}
1979
1980impl Stackable for SslCipher {
1981 type StackType = ffi::stack_st_SSL_CIPHER;
1982}
1983
1984impl Deref for SslCipher {
1985 type Target = SslCipherRef;
1986
1987 fn deref(&self) -> &SslCipherRef {
1988 unsafe { SslCipherRef::from_ptr(self.0) }
1989 }
1990}
1991
1992impl DerefMut for SslCipher {
1993 fn deref_mut(&mut self) -> &mut SslCipherRef {
1994 unsafe { SslCipherRef::from_ptr_mut(self.0) }
1995 }
1996}
1997
1998pub struct SslCipherRef(Opaque);
2002
2003impl ForeignTypeRef for SslCipherRef {
2004 type CType = ffi::SSL_CIPHER;
2005}
2006
2007impl SslCipherRef {
2008 #[corresponds(SSL_CIPHER_get_name)]
2010 pub fn name(&self) -> &'static str {
2011 unsafe {
2012 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2013 CStr::from_ptr(ptr).to_str().unwrap()
2014 }
2015 }
2016
2017 #[corresponds(SSL_CIPHER_standard_name)]
2021 #[cfg(ossl111)]
2022 pub fn standard_name(&self) -> Option<&'static str> {
2023 unsafe {
2024 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2025 if ptr.is_null() {
2026 None
2027 } else {
2028 Some(CStr::from_ptr(ptr).to_str().unwrap())
2029 }
2030 }
2031 }
2032
2033 #[corresponds(SSL_CIPHER_get_version)]
2035 pub fn version(&self) -> &'static str {
2036 let version = unsafe {
2037 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2038 CStr::from_ptr(ptr as *const _)
2039 };
2040
2041 str::from_utf8(version.to_bytes()).unwrap()
2042 }
2043
2044 #[corresponds(SSL_CIPHER_get_bits)]
2046 #[allow(clippy::useless_conversion)]
2047 pub fn bits(&self) -> CipherBits {
2048 unsafe {
2049 let mut algo_bits = 0;
2050 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2051 CipherBits {
2052 secret: secret_bits.into(),
2053 algorithm: algo_bits.into(),
2054 }
2055 }
2056 }
2057
2058 #[corresponds(SSL_CIPHER_description)]
2060 pub fn description(&self) -> String {
2061 unsafe {
2062 let mut buf = [0; 128];
2064 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2065 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2066 }
2067 }
2068
2069 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2073 #[cfg(ossl111)]
2074 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2075 unsafe {
2076 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2077 if ptr.is_null() {
2078 None
2079 } else {
2080 Some(MessageDigest::from_ptr(ptr))
2081 }
2082 }
2083 }
2084
2085 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2089 #[cfg(any(ossl110, libressl))]
2090 pub fn cipher_nid(&self) -> Option<Nid> {
2091 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2092 if n == 0 {
2093 None
2094 } else {
2095 Some(Nid::from_raw(n))
2096 }
2097 }
2098
2099 #[corresponds(SSL_CIPHER_get_protocol_id)]
2103 #[cfg(ossl111)]
2104 pub fn protocol_id(&self) -> [u8; 2] {
2105 unsafe {
2106 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2107 id.to_be_bytes()
2108 }
2109 }
2110}
2111
2112impl fmt::Debug for SslCipherRef {
2113 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2114 write!(fmt, "{}", self.name())
2115 }
2116}
2117
2118#[derive(Debug)]
2120pub struct CipherLists {
2121 pub suites: Stack<SslCipher>,
2122 pub signalling_suites: Stack<SslCipher>,
2123}
2124
2125foreign_type_and_impl_send_sync! {
2126 type CType = ffi::SSL_SESSION;
2127 fn drop = ffi::SSL_SESSION_free;
2128
2129 pub struct SslSession;
2133
2134 pub struct SslSessionRef;
2138}
2139
2140impl Clone for SslSession {
2141 fn clone(&self) -> SslSession {
2142 SslSessionRef::to_owned(self)
2143 }
2144}
2145
2146impl SslSession {
2147 from_der! {
2148 #[corresponds(d2i_SSL_SESSION)]
2150 from_der,
2151 SslSession,
2152 ffi::d2i_SSL_SESSION
2153 }
2154}
2155
2156impl ToOwned for SslSessionRef {
2157 type Owned = SslSession;
2158
2159 fn to_owned(&self) -> SslSession {
2160 unsafe {
2161 SSL_SESSION_up_ref(self.as_ptr());
2162 SslSession(self.as_ptr())
2163 }
2164 }
2165}
2166
2167impl SslSessionRef {
2168 #[corresponds(SSL_SESSION_get_id)]
2170 pub fn id(&self) -> &[u8] {
2171 unsafe {
2172 let mut len = 0;
2173 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2174 #[allow(clippy::unnecessary_cast)]
2175 util::from_raw_parts(p as *const u8, len as usize)
2176 }
2177 }
2178
2179 #[corresponds(SSL_SESSION_get_master_key)]
2181 pub fn master_key_len(&self) -> usize {
2182 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2183 }
2184
2185 #[corresponds(SSL_SESSION_get_master_key)]
2189 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2190 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2191 }
2192
2193 #[corresponds(SSL_SESSION_get_max_early_data)]
2197 #[cfg(any(ossl111, libressl))]
2198 pub fn max_early_data(&self) -> u32 {
2199 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2200 }
2201
2202 #[corresponds(SSL_SESSION_get_time)]
2204 #[allow(clippy::useless_conversion)]
2205 pub fn time(&self) -> SslTimeTy {
2206 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2207 }
2208
2209 #[corresponds(SSL_SESSION_get_timeout)]
2213 #[allow(clippy::useless_conversion)]
2214 pub fn timeout(&self) -> i64 {
2215 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2216 }
2217
2218 #[corresponds(SSL_SESSION_get_protocol_version)]
2222 #[cfg(any(ossl110, libressl))]
2223 pub fn protocol_version(&self) -> SslVersion {
2224 unsafe {
2225 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2226 SslVersion(version)
2227 }
2228 }
2229
2230 to_der! {
2231 #[corresponds(i2d_SSL_SESSION)]
2233 to_der,
2234 ffi::i2d_SSL_SESSION
2235 }
2236}
2237
2238foreign_type_and_impl_send_sync! {
2239 type CType = ffi::SSL;
2240 fn drop = ffi::SSL_free;
2241
2242 pub struct Ssl;
2249
2250 pub struct SslRef;
2254}
2255
2256impl fmt::Debug for Ssl {
2257 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2258 fmt::Debug::fmt(&**self, fmt)
2259 }
2260}
2261
2262impl Ssl {
2263 #[corresponds(SSL_get_ex_new_index)]
2268 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2269 where
2270 T: 'static + Sync + Send,
2271 {
2272 unsafe {
2273 ffi::init();
2274 #[cfg(any(boringssl, awslc))]
2275 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2276 #[cfg(not(any(boringssl, awslc)))]
2277 let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
2278 Ok(Index::from_raw(idx))
2279 }
2280 }
2281
2282 fn cached_ex_index<T>() -> Index<Ssl, T>
2284 where
2285 T: 'static + Sync + Send,
2286 {
2287 unsafe {
2288 let idx = *SSL_INDEXES
2289 .lock()
2290 .unwrap_or_else(|e| e.into_inner())
2291 .entry(TypeId::of::<T>())
2292 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2293 Index::from_raw(idx)
2294 }
2295 }
2296
2297 #[corresponds(SSL_new)]
2299 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2300 let session_ctx_index = try_get_session_ctx_index()?;
2301 unsafe {
2302 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2303 let mut ssl = Ssl::from_ptr(ptr);
2304 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2305
2306 Ok(ssl)
2307 }
2308 }
2309
2310 #[corresponds(SSL_connect)]
2316 #[allow(deprecated)]
2317 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2318 where
2319 S: Read + Write,
2320 {
2321 SslStreamBuilder::new(self, stream).connect()
2322 }
2323
2324 #[corresponds(SSL_accept)]
2331 #[allow(deprecated)]
2332 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2333 where
2334 S: Read + Write,
2335 {
2336 SslStreamBuilder::new(self, stream).accept()
2337 }
2338}
2339
2340impl fmt::Debug for SslRef {
2341 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2342 fmt.debug_struct("Ssl")
2343 .field("state", &self.state_string_long())
2344 .field("verify_result", &self.verify_result())
2345 .finish()
2346 }
2347}
2348
2349impl SslRef {
2350 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2351 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2352 }
2353
2354 fn get_error(&self, ret: c_int) -> ErrorCode {
2355 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2356 }
2357
2358 #[corresponds(SSL_set_connect_state)]
2360 pub fn set_connect_state(&mut self) {
2361 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2362 }
2363
2364 #[corresponds(SSL_set_accept_state)]
2366 pub fn set_accept_state(&mut self) {
2367 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2368 }
2369
2370 #[corresponds(SSL_set_verify)]
2374 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2375 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2376 }
2377
2378 #[corresponds(SSL_set_verify_mode)]
2380 pub fn verify_mode(&self) -> SslVerifyMode {
2381 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2382 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2383 }
2384
2385 #[corresponds(SSL_set_verify)]
2389 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2390 where
2391 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2392 {
2393 unsafe {
2394 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2396 ffi::SSL_set_verify(
2397 self.as_ptr(),
2398 mode.bits() as c_int,
2399 Some(ssl_raw_verify::<F>),
2400 );
2401 }
2402 }
2403
2404 #[corresponds(SSL_set_tmp_dh)]
2408 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2409 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2410 }
2411
2412 #[corresponds(SSL_set_tmp_dh_callback)]
2416 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2417 where
2418 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2419 {
2420 unsafe {
2421 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2423 #[cfg(any(boringssl, awslc))]
2424 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2425 #[cfg(not(any(boringssl, awslc)))]
2426 ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2427 }
2428 }
2429
2430 #[corresponds(SSL_set_tmp_ecdh)]
2434 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
2435 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
2436 }
2437
2438 #[corresponds(SSL_set_ecdh_auto)]
2444 #[cfg(libressl)]
2445 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2446 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2447 }
2448
2449 #[corresponds(SSL_set_alpn_protos)]
2455 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2456 unsafe {
2457 assert!(protocols.len() <= c_uint::MAX as usize);
2458 let r =
2459 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2460 if r == 0 {
2462 Ok(())
2463 } else {
2464 Err(ErrorStack::get())
2465 }
2466 }
2467 }
2468
2469 #[corresponds(SSL_get_current_cipher)]
2471 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2472 unsafe {
2473 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2474
2475 SslCipherRef::from_const_ptr_opt(ptr)
2476 }
2477 }
2478
2479 #[corresponds(SSL_state_string)]
2481 pub fn state_string(&self) -> &'static str {
2482 let state = unsafe {
2483 let ptr = ffi::SSL_state_string(self.as_ptr());
2484 CStr::from_ptr(ptr as *const _)
2485 };
2486
2487 str::from_utf8(state.to_bytes()).unwrap()
2488 }
2489
2490 #[corresponds(SSL_state_string_long)]
2492 pub fn state_string_long(&self) -> &'static str {
2493 let state = unsafe {
2494 let ptr = ffi::SSL_state_string_long(self.as_ptr());
2495 CStr::from_ptr(ptr as *const _)
2496 };
2497
2498 str::from_utf8(state.to_bytes()).unwrap()
2499 }
2500
2501 #[corresponds(SSL_set_tlsext_host_name)]
2505 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2506 let cstr = CString::new(hostname).unwrap();
2507 unsafe {
2508 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2509 .map(|_| ())
2510 }
2511 }
2512
2513 #[corresponds(SSL_get_peer_certificate)]
2515 pub fn peer_certificate(&self) -> Option<X509> {
2516 unsafe {
2517 let ptr = SSL_get1_peer_certificate(self.as_ptr());
2518 X509::from_ptr_opt(ptr)
2519 }
2520 }
2521
2522 #[corresponds(SSL_get_peer_cert_chain)]
2527 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2528 unsafe {
2529 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2530 StackRef::from_const_ptr_opt(ptr)
2531 }
2532 }
2533
2534 #[corresponds(SSL_get0_verified_chain)]
2544 #[cfg(ossl110)]
2545 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2546 unsafe {
2547 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2548 StackRef::from_const_ptr_opt(ptr)
2549 }
2550 }
2551
2552 #[corresponds(SSL_get_certificate)]
2554 pub fn certificate(&self) -> Option<&X509Ref> {
2555 unsafe {
2556 let ptr = ffi::SSL_get_certificate(self.as_ptr());
2557 X509Ref::from_const_ptr_opt(ptr)
2558 }
2559 }
2560
2561 #[corresponds(SSL_get_privatekey)]
2565 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2566 unsafe {
2567 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2568 PKeyRef::from_const_ptr_opt(ptr)
2569 }
2570 }
2571
2572 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2573 pub fn version(&self) -> &str {
2574 self.version_str()
2575 }
2576
2577 #[corresponds(SSL_version)]
2579 pub fn version2(&self) -> Option<SslVersion> {
2580 unsafe {
2581 let r = ffi::SSL_version(self.as_ptr());
2582 if r == 0 {
2583 None
2584 } else {
2585 Some(SslVersion(r))
2586 }
2587 }
2588 }
2589
2590 #[corresponds(SSL_get_version)]
2592 pub fn version_str(&self) -> &'static str {
2593 let version = unsafe {
2594 let ptr = ffi::SSL_get_version(self.as_ptr());
2595 CStr::from_ptr(ptr as *const _)
2596 };
2597
2598 str::from_utf8(version.to_bytes()).unwrap()
2599 }
2600
2601 #[corresponds(SSL_get0_alpn_selected)]
2608 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2609 unsafe {
2610 let mut data: *const c_uchar = ptr::null();
2611 let mut len: c_uint = 0;
2612 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2615
2616 if data.is_null() {
2617 None
2618 } else {
2619 Some(util::from_raw_parts(data, len as usize))
2620 }
2621 }
2622 }
2623
2624 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2626 #[corresponds(SSL_set_tlsext_use_srtp)]
2627 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2628 unsafe {
2629 let cstr = CString::new(protocols).unwrap();
2630
2631 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2632 if r == 0 {
2634 Ok(())
2635 } else {
2636 Err(ErrorStack::get())
2637 }
2638 }
2639 }
2640
2641 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2645 #[corresponds(SSL_get_srtp_profiles)]
2646 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
2647 unsafe {
2648 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
2649
2650 StackRef::from_const_ptr_opt(chain)
2651 }
2652 }
2653
2654 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2658 #[corresponds(SSL_get_selected_srtp_profile)]
2659 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2660 unsafe {
2661 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2662
2663 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2664 }
2665 }
2666
2667 #[corresponds(SSL_pending)]
2672 pub fn pending(&self) -> usize {
2673 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2674 }
2675
2676 #[corresponds(SSL_get_servername)]
2689 pub fn servername(&self, type_: NameType) -> Option<&str> {
2691 self.servername_raw(type_)
2692 .and_then(|b| str::from_utf8(b).ok())
2693 }
2694
2695 #[corresponds(SSL_get_servername)]
2703 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2704 unsafe {
2705 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2706 if name.is_null() {
2707 None
2708 } else {
2709 Some(CStr::from_ptr(name as *const _).to_bytes())
2710 }
2711 }
2712 }
2713
2714 #[corresponds(SSL_set_SSL_CTX)]
2718 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2719 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2720 }
2721
2722 #[corresponds(SSL_get_SSL_CTX)]
2724 pub fn ssl_context(&self) -> &SslContextRef {
2725 unsafe {
2726 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2727 SslContextRef::from_ptr(ssl_ctx)
2728 }
2729 }
2730
2731 #[corresponds(SSL_get0_param)]
2735 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
2736 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
2737 }
2738
2739 #[corresponds(SSL_get_verify_result)]
2741 pub fn verify_result(&self) -> X509VerifyResult {
2742 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
2743 }
2744
2745 #[corresponds(SSL_get_session)]
2747 pub fn session(&self) -> Option<&SslSessionRef> {
2748 unsafe {
2749 let p = ffi::SSL_get_session(self.as_ptr());
2750 SslSessionRef::from_const_ptr_opt(p)
2751 }
2752 }
2753
2754 #[corresponds(SSL_get_client_random)]
2761 #[cfg(any(ossl110, libressl))]
2762 pub fn client_random(&self, buf: &mut [u8]) -> usize {
2763 unsafe {
2764 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2765 }
2766 }
2767
2768 #[corresponds(SSL_get_server_random)]
2775 #[cfg(any(ossl110, libressl))]
2776 pub fn server_random(&self, buf: &mut [u8]) -> usize {
2777 unsafe {
2778 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2779 }
2780 }
2781
2782 #[corresponds(SSL_export_keying_material)]
2784 pub fn export_keying_material(
2785 &self,
2786 out: &mut [u8],
2787 label: &str,
2788 context: Option<&[u8]>,
2789 ) -> Result<(), ErrorStack> {
2790 unsafe {
2791 let (context, contextlen, use_context) = match context {
2792 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
2793 None => (ptr::null(), 0, 0),
2794 };
2795 cvt(ffi::SSL_export_keying_material(
2796 self.as_ptr(),
2797 out.as_mut_ptr() as *mut c_uchar,
2798 out.len(),
2799 label.as_ptr() as *const c_char,
2800 label.len(),
2801 context,
2802 contextlen,
2803 use_context,
2804 ))
2805 .map(|_| ())
2806 }
2807 }
2808
2809 #[corresponds(SSL_export_keying_material_early)]
2816 #[cfg(ossl111)]
2817 pub fn export_keying_material_early(
2818 &self,
2819 out: &mut [u8],
2820 label: &str,
2821 context: &[u8],
2822 ) -> Result<(), ErrorStack> {
2823 unsafe {
2824 cvt(ffi::SSL_export_keying_material_early(
2825 self.as_ptr(),
2826 out.as_mut_ptr() as *mut c_uchar,
2827 out.len(),
2828 label.as_ptr() as *const c_char,
2829 label.len(),
2830 context.as_ptr() as *const c_uchar,
2831 context.len(),
2832 ))
2833 .map(|_| ())
2834 }
2835 }
2836
2837 #[corresponds(SSL_set_session)]
2848 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
2849 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
2850 }
2851
2852 #[corresponds(SSL_session_reused)]
2854 pub fn session_reused(&self) -> bool {
2855 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
2856 }
2857
2858 #[corresponds(SSL_set_tlsext_status_type)]
2860 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
2861 unsafe {
2862 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
2863 }
2864 }
2865
2866 #[corresponds(SSL_get_extms_support)]
2870 #[cfg(ossl110)]
2871 pub fn extms_support(&self) -> Option<bool> {
2872 unsafe {
2873 match ffi::SSL_get_extms_support(self.as_ptr()) {
2874 -1 => None,
2875 ret => Some(ret != 0),
2876 }
2877 }
2878 }
2879
2880 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
2882 #[cfg(not(any(boringssl, awslc)))]
2883 pub fn ocsp_status(&self) -> Option<&[u8]> {
2884 unsafe {
2885 let mut p = ptr::null_mut();
2886 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
2887
2888 if len < 0 {
2889 None
2890 } else {
2891 Some(util::from_raw_parts(p as *const u8, len as usize))
2892 }
2893 }
2894 }
2895
2896 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
2898 #[cfg(not(any(boringssl, awslc)))]
2899 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
2900 unsafe {
2901 assert!(response.len() <= c_int::MAX as usize);
2902 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
2903 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
2904 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
2905 self.as_ptr(),
2906 p as *mut c_uchar,
2907 response.len() as c_long,
2908 ) as c_int)
2909 .map(|_| ())
2910 .map_err(|e| {
2911 ffi::OPENSSL_free(p);
2912 e
2913 })
2914 }
2915 }
2916
2917 #[corresponds(SSL_is_server)]
2919 pub fn is_server(&self) -> bool {
2920 unsafe { SSL_is_server(self.as_ptr()) != 0 }
2921 }
2922
2923 #[corresponds(SSL_set_ex_data)]
2929 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
2930 match self.ex_data_mut(index) {
2931 Some(v) => *v = data,
2932 None => unsafe {
2933 let data = Box::new(data);
2934 ffi::SSL_set_ex_data(
2935 self.as_ptr(),
2936 index.as_raw(),
2937 Box::into_raw(data) as *mut c_void,
2938 );
2939 },
2940 }
2941 }
2942
2943 #[corresponds(SSL_get_ex_data)]
2945 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
2946 unsafe {
2947 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2948 if data.is_null() {
2949 None
2950 } else {
2951 Some(&*(data as *const T))
2952 }
2953 }
2954 }
2955
2956 #[corresponds(SSL_get_ex_data)]
2958 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
2959 unsafe {
2960 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2961 if data.is_null() {
2962 None
2963 } else {
2964 Some(&mut *(data as *mut T))
2965 }
2966 }
2967 }
2968
2969 #[corresponds(SSL_set_max_early_data)]
2973 #[cfg(any(ossl111, libressl))]
2974 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2975 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2976 Ok(())
2977 } else {
2978 Err(ErrorStack::get())
2979 }
2980 }
2981
2982 #[corresponds(SSL_get_max_early_data)]
2986 #[cfg(any(ossl111, libressl))]
2987 pub fn max_early_data(&self) -> u32 {
2988 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
2989 }
2990
2991 #[corresponds(SSL_get_finished)]
2996 pub fn finished(&self, buf: &mut [u8]) -> usize {
2997 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
2998 }
2999
3000 #[corresponds(SSL_get_peer_finished)]
3006 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3007 unsafe {
3008 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3009 }
3010 }
3011
3012 #[corresponds(SSL_is_init_finished)]
3014 #[cfg(ossl110)]
3015 pub fn is_init_finished(&self) -> bool {
3016 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3017 }
3018
3019 #[corresponds(SSL_client_hello_isv2)]
3025 #[cfg(ossl111)]
3026 pub fn client_hello_isv2(&self) -> bool {
3027 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3028 }
3029
3030 #[corresponds(SSL_client_hello_get0_legacy_version)]
3036 #[cfg(ossl111)]
3037 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3038 unsafe {
3039 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3040 if version == 0 {
3041 None
3042 } else {
3043 Some(SslVersion(version as c_int))
3044 }
3045 }
3046 }
3047
3048 #[corresponds(SSL_client_hello_get0_random)]
3054 #[cfg(ossl111)]
3055 pub fn client_hello_random(&self) -> Option<&[u8]> {
3056 unsafe {
3057 let mut ptr = ptr::null();
3058 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3059 if len == 0 {
3060 None
3061 } else {
3062 Some(util::from_raw_parts(ptr, len))
3063 }
3064 }
3065 }
3066
3067 #[corresponds(SSL_client_hello_get0_session_id)]
3073 #[cfg(ossl111)]
3074 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3075 unsafe {
3076 let mut ptr = ptr::null();
3077 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3078 if len == 0 {
3079 None
3080 } else {
3081 Some(util::from_raw_parts(ptr, len))
3082 }
3083 }
3084 }
3085
3086 #[corresponds(SSL_client_hello_get0_ciphers)]
3092 #[cfg(ossl111)]
3093 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3094 unsafe {
3095 let mut ptr = ptr::null();
3096 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3097 if len == 0 {
3098 None
3099 } else {
3100 Some(util::from_raw_parts(ptr, len))
3101 }
3102 }
3103 }
3104
3105 #[corresponds(SSL_bytes_to_cipher_list)]
3110 #[cfg(ossl111)]
3111 pub fn bytes_to_cipher_list(
3112 &self,
3113 bytes: &[u8],
3114 isv2format: bool,
3115 ) -> Result<CipherLists, ErrorStack> {
3116 unsafe {
3117 let ptr = bytes.as_ptr();
3118 let len = bytes.len();
3119 let mut sk = ptr::null_mut();
3120 let mut scsvs = ptr::null_mut();
3121 let res = ffi::SSL_bytes_to_cipher_list(
3122 self.as_ptr(),
3123 ptr,
3124 len,
3125 isv2format as c_int,
3126 &mut sk,
3127 &mut scsvs,
3128 );
3129 if res == 1 {
3130 Ok(CipherLists {
3131 suites: Stack::from_ptr(sk),
3132 signalling_suites: Stack::from_ptr(scsvs),
3133 })
3134 } else {
3135 Err(ErrorStack::get())
3136 }
3137 }
3138 }
3139
3140 #[corresponds(SSL_client_hello_get0_compression_methods)]
3146 #[cfg(ossl111)]
3147 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3148 unsafe {
3149 let mut ptr = ptr::null();
3150 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3151 if len == 0 {
3152 None
3153 } else {
3154 Some(util::from_raw_parts(ptr, len))
3155 }
3156 }
3157 }
3158
3159 #[corresponds(SSL_set_mtu)]
3161 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3162 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3163 }
3164
3165 #[corresponds(SSL_get_psk_identity_hint)]
3169 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3170 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3171 unsafe {
3172 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3173 if ptr.is_null() {
3174 None
3175 } else {
3176 Some(CStr::from_ptr(ptr).to_bytes())
3177 }
3178 }
3179 }
3180
3181 #[corresponds(SSL_get_psk_identity)]
3183 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3184 pub fn psk_identity(&self) -> Option<&[u8]> {
3185 unsafe {
3186 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3187 if ptr.is_null() {
3188 None
3189 } else {
3190 Some(CStr::from_ptr(ptr).to_bytes())
3191 }
3192 }
3193 }
3194
3195 #[corresponds(SSL_add0_chain_cert)]
3196 #[cfg(ossl110)]
3197 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3198 unsafe {
3199 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3200 mem::forget(chain);
3201 }
3202 Ok(())
3203 }
3204
3205 #[cfg(not(any(boringssl, awslc)))]
3207 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3208 unsafe {
3209 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3210 };
3211 Ok(())
3212 }
3213
3214 #[corresponds(SSL_use_Private_Key_file)]
3216 pub fn set_private_key_file<P: AsRef<Path>>(
3217 &mut self,
3218 path: P,
3219 ssl_file_type: SslFiletype,
3220 ) -> Result<(), ErrorStack> {
3221 let p = path.as_ref().as_os_str().to_str().unwrap();
3222 let key_file = CString::new(p).unwrap();
3223 unsafe {
3224 cvt(ffi::SSL_use_PrivateKey_file(
3225 self.as_ptr(),
3226 key_file.as_ptr(),
3227 ssl_file_type.as_raw(),
3228 ))?;
3229 };
3230 Ok(())
3231 }
3232
3233 #[corresponds(SSL_use_PrivateKey)]
3235 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3236 unsafe {
3237 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3238 };
3239 Ok(())
3240 }
3241
3242 #[corresponds(SSL_use_certificate)]
3244 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3245 unsafe {
3246 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3247 };
3248 Ok(())
3249 }
3250
3251 #[corresponds(SSL_use_certificate_chain_file)]
3257 #[cfg(any(ossl110, libressl))]
3258 pub fn set_certificate_chain_file<P: AsRef<Path>>(
3259 &mut self,
3260 path: P,
3261 ) -> Result<(), ErrorStack> {
3262 let p = path.as_ref().as_os_str().to_str().unwrap();
3263 let cert_file = CString::new(p).unwrap();
3264 unsafe {
3265 cvt(ffi::SSL_use_certificate_chain_file(
3266 self.as_ptr(),
3267 cert_file.as_ptr(),
3268 ))?;
3269 };
3270 Ok(())
3271 }
3272
3273 #[corresponds(SSL_add_client_CA)]
3275 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
3276 unsafe {
3277 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
3278 };
3279 Ok(())
3280 }
3281
3282 #[corresponds(SSL_set_client_CA_list)]
3284 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3285 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3286 mem::forget(list);
3287 }
3288
3289 #[corresponds(SSL_set_min_proto_version)]
3294 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3295 unsafe {
3296 cvt(ffi::SSL_set_min_proto_version(
3297 self.as_ptr(),
3298 version.map_or(0, |v| v.0 as _),
3299 ))
3300 .map(|_| ())
3301 }
3302 }
3303
3304 #[corresponds(SSL_set_max_proto_version)]
3309 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3310 unsafe {
3311 cvt(ffi::SSL_set_max_proto_version(
3312 self.as_ptr(),
3313 version.map_or(0, |v| v.0 as _),
3314 ))
3315 .map(|_| ())
3316 }
3317 }
3318
3319 #[corresponds(SSL_set_ciphersuites)]
3328 #[cfg(any(ossl111, libressl))]
3329 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3330 let cipher_list = CString::new(cipher_list).unwrap();
3331 unsafe {
3332 cvt(ffi::SSL_set_ciphersuites(
3333 self.as_ptr(),
3334 cipher_list.as_ptr() as *const _,
3335 ))
3336 .map(|_| ())
3337 }
3338 }
3339
3340 #[corresponds(SSL_set_cipher_list)]
3348 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3349 let cipher_list = CString::new(cipher_list).unwrap();
3350 unsafe {
3351 cvt(ffi::SSL_set_cipher_list(
3352 self.as_ptr(),
3353 cipher_list.as_ptr() as *const _,
3354 ))
3355 .map(|_| ())
3356 }
3357 }
3358
3359 #[corresponds(SSL_set_cert_store)]
3361 #[cfg(ossl110)]
3362 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3363 unsafe {
3364 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
3365 mem::forget(cert_store);
3366 Ok(())
3367 }
3368 }
3369
3370 #[corresponds(SSL_set_num_tickets)]
3375 #[cfg(ossl111)]
3376 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
3377 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
3378 }
3379
3380 #[corresponds(SSL_get_num_tickets)]
3385 #[cfg(ossl111)]
3386 pub fn num_tickets(&self) -> usize {
3387 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
3388 }
3389
3390 #[corresponds(SSL_set_security_level)]
3395 #[cfg(any(ossl110, libressl360))]
3396 pub fn set_security_level(&mut self, level: u32) {
3397 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
3398 }
3399
3400 #[corresponds(SSL_get_security_level)]
3405 #[cfg(any(ossl110, libressl360))]
3406 pub fn security_level(&self) -> u32 {
3407 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
3408 }
3409
3410 #[corresponds(SSL_get_peer_tmp_key)]
3415 #[cfg(ossl300)]
3416 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
3417 unsafe {
3418 let mut key = ptr::null_mut();
3419 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
3420 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
3421 Err(e) => Err(e),
3422 }
3423 }
3424 }
3425
3426 #[corresponds(SSL_get_tmp_key)]
3431 #[cfg(ossl300)]
3432 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
3433 unsafe {
3434 let mut key = ptr::null_mut();
3435 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
3436 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
3437 Err(e) => Err(e),
3438 }
3439 }
3440 }
3441}
3442
3443#[derive(Debug)]
3445pub struct MidHandshakeSslStream<S> {
3446 stream: SslStream<S>,
3447 error: Error,
3448}
3449
3450impl<S> MidHandshakeSslStream<S> {
3451 pub fn get_ref(&self) -> &S {
3453 self.stream.get_ref()
3454 }
3455
3456 pub fn get_mut(&mut self) -> &mut S {
3458 self.stream.get_mut()
3459 }
3460
3461 pub fn ssl(&self) -> &SslRef {
3463 self.stream.ssl()
3464 }
3465
3466 pub fn error(&self) -> &Error {
3468 &self.error
3469 }
3470
3471 pub fn into_error(self) -> Error {
3473 self.error
3474 }
3475}
3476
3477impl<S> MidHandshakeSslStream<S>
3478where
3479 S: Read + Write,
3480{
3481 #[corresponds(SSL_do_handshake)]
3484 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3485 match self.stream.do_handshake() {
3486 Ok(()) => Ok(self.stream),
3487 Err(error) => {
3488 self.error = error;
3489 match self.error.code() {
3490 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3491 Err(HandshakeError::WouldBlock(self))
3492 }
3493 _ => Err(HandshakeError::Failure(self)),
3494 }
3495 }
3496 }
3497 }
3498}
3499
3500pub struct SslStream<S> {
3502 ssl: ManuallyDrop<Ssl>,
3503 method: ManuallyDrop<BioMethod>,
3504 _p: PhantomData<S>,
3505}
3506
3507impl<S> Drop for SslStream<S> {
3508 fn drop(&mut self) {
3509 unsafe {
3511 ManuallyDrop::drop(&mut self.ssl);
3512 ManuallyDrop::drop(&mut self.method);
3513 }
3514 }
3515}
3516
3517impl<S> fmt::Debug for SslStream<S>
3518where
3519 S: fmt::Debug,
3520{
3521 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3522 fmt.debug_struct("SslStream")
3523 .field("stream", &self.get_ref())
3524 .field("ssl", &self.ssl())
3525 .finish()
3526 }
3527}
3528
3529impl<S: Read + Write> SslStream<S> {
3530 #[corresponds(SSL_set_bio)]
3538 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3539 let (bio, method) = bio::new(stream)?;
3540 unsafe {
3541 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3542 }
3543
3544 Ok(SslStream {
3545 ssl: ManuallyDrop::new(ssl),
3546 method: ManuallyDrop::new(method),
3547 _p: PhantomData,
3548 })
3549 }
3550
3551 #[deprecated(
3559 since = "0.10.32",
3560 note = "use Ssl::from_ptr and SslStream::new instead"
3561 )]
3562 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3563 let ssl = Ssl::from_ptr(ssl);
3564 Self::new(ssl, stream).unwrap()
3565 }
3566
3567 #[corresponds(SSL_read_early_data)]
3576 #[cfg(any(ossl111, libressl))]
3577 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3578 let mut read = 0;
3579 let ret = unsafe {
3580 ffi::SSL_read_early_data(
3581 self.ssl.as_ptr(),
3582 buf.as_ptr() as *mut c_void,
3583 buf.len(),
3584 &mut read,
3585 )
3586 };
3587 match ret {
3588 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
3589 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
3590 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
3591 _ => unreachable!(),
3592 }
3593 }
3594
3595 #[corresponds(SSL_write_early_data)]
3602 #[cfg(any(ossl111, libressl))]
3603 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
3604 let mut written = 0;
3605 let ret = unsafe {
3606 ffi::SSL_write_early_data(
3607 self.ssl.as_ptr(),
3608 buf.as_ptr() as *const c_void,
3609 buf.len(),
3610 &mut written,
3611 )
3612 };
3613 if ret > 0 {
3614 Ok(written)
3615 } else {
3616 Err(self.make_error(ret))
3617 }
3618 }
3619
3620 #[corresponds(SSL_connect)]
3627 pub fn connect(&mut self) -> Result<(), Error> {
3628 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
3629 if ret > 0 {
3630 Ok(())
3631 } else {
3632 Err(self.make_error(ret))
3633 }
3634 }
3635
3636 #[corresponds(SSL_accept)]
3643 pub fn accept(&mut self) -> Result<(), Error> {
3644 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
3645 if ret > 0 {
3646 Ok(())
3647 } else {
3648 Err(self.make_error(ret))
3649 }
3650 }
3651
3652 #[corresponds(SSL_do_handshake)]
3656 pub fn do_handshake(&mut self) -> Result<(), Error> {
3657 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
3658 if ret > 0 {
3659 Ok(())
3660 } else {
3661 Err(self.make_error(ret))
3662 }
3663 }
3664
3665 #[corresponds(SSL_stateless)]
3676 #[cfg(ossl111)]
3677 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
3678 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
3679 1 => Ok(true),
3680 0 => Ok(false),
3681 -1 => Err(ErrorStack::get()),
3682 _ => unreachable!(),
3683 }
3684 }
3685
3686 #[corresponds(SSL_read_ex)]
3693 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3694 loop {
3695 match self.ssl_read_uninit(buf) {
3696 Ok(n) => return Ok(n),
3697 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3698 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3699 return Ok(0);
3700 }
3701 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3702 Err(e) => {
3703 return Err(e
3704 .into_io_error()
3705 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
3706 }
3707 }
3708 }
3709 }
3710
3711 #[corresponds(SSL_read_ex)]
3716 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3717 unsafe {
3719 self.ssl_read_uninit(util::from_raw_parts_mut(
3720 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3721 buf.len(),
3722 ))
3723 }
3724 }
3725
3726 #[corresponds(SSL_read_ex)]
3733 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3734 cfg_if! {
3735 if #[cfg(any(ossl111, libressl))] {
3736 let mut readbytes = 0;
3737 let ret = unsafe {
3738 ffi::SSL_read_ex(
3739 self.ssl().as_ptr(),
3740 buf.as_mut_ptr().cast(),
3741 buf.len(),
3742 &mut readbytes,
3743 )
3744 };
3745
3746 if ret > 0 {
3747 Ok(readbytes)
3748 } else {
3749 Err(self.make_error(ret))
3750 }
3751 } else {
3752 if buf.is_empty() {
3753 return Ok(0);
3754 }
3755
3756 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3757 let ret = unsafe {
3758 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3759 };
3760 if ret > 0 {
3761 Ok(ret as usize)
3762 } else {
3763 Err(self.make_error(ret))
3764 }
3765 }
3766 }
3767 }
3768
3769 #[corresponds(SSL_write_ex)]
3774 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3775 cfg_if! {
3776 if #[cfg(any(ossl111, libressl))] {
3777 let mut written = 0;
3778 let ret = unsafe {
3779 ffi::SSL_write_ex(
3780 self.ssl().as_ptr(),
3781 buf.as_ptr().cast(),
3782 buf.len(),
3783 &mut written,
3784 )
3785 };
3786
3787 if ret > 0 {
3788 Ok(written)
3789 } else {
3790 Err(self.make_error(ret))
3791 }
3792 } else {
3793 if buf.is_empty() {
3794 return Ok(0);
3795 }
3796
3797 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3798 let ret = unsafe {
3799 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
3800 };
3801 if ret > 0 {
3802 Ok(ret as usize)
3803 } else {
3804 Err(self.make_error(ret))
3805 }
3806 }
3807 }
3808 }
3809
3810 #[corresponds(SSL_peek_ex)]
3812 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3813 cfg_if! {
3814 if #[cfg(any(ossl111, libressl))] {
3815 let mut readbytes = 0;
3816 let ret = unsafe {
3817 ffi::SSL_peek_ex(
3818 self.ssl().as_ptr(),
3819 buf.as_mut_ptr().cast(),
3820 buf.len(),
3821 &mut readbytes,
3822 )
3823 };
3824
3825 if ret > 0 {
3826 Ok(readbytes)
3827 } else {
3828 Err(self.make_error(ret))
3829 }
3830 } else {
3831 if buf.is_empty() {
3832 return Ok(0);
3833 }
3834
3835 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3836 let ret = unsafe {
3837 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3838 };
3839 if ret > 0 {
3840 Ok(ret as usize)
3841 } else {
3842 Err(self.make_error(ret))
3843 }
3844 }
3845 }
3846 }
3847
3848 #[corresponds(SSL_shutdown)]
3858 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
3859 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
3860 0 => Ok(ShutdownResult::Sent),
3861 1 => Ok(ShutdownResult::Received),
3862 n => Err(self.make_error(n)),
3863 }
3864 }
3865
3866 #[corresponds(SSL_get_shutdown)]
3868 pub fn get_shutdown(&mut self) -> ShutdownState {
3869 unsafe {
3870 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
3871 ShutdownState::from_bits_retain(bits)
3872 }
3873 }
3874
3875 #[corresponds(SSL_set_shutdown)]
3880 pub fn set_shutdown(&mut self, state: ShutdownState) {
3881 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
3882 }
3883}
3884
3885impl<S> SslStream<S> {
3886 fn make_error(&mut self, ret: c_int) -> Error {
3887 self.check_panic();
3888
3889 let code = self.ssl.get_error(ret);
3890
3891 let cause = match code {
3892 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
3893 ErrorCode::SYSCALL => {
3894 let errs = ErrorStack::get();
3895 if errs.errors().is_empty() {
3896 self.get_bio_error().map(InnerError::Io)
3897 } else {
3898 Some(InnerError::Ssl(errs))
3899 }
3900 }
3901 ErrorCode::ZERO_RETURN => None,
3902 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3903 self.get_bio_error().map(InnerError::Io)
3904 }
3905 _ => None,
3906 };
3907
3908 Error { code, cause }
3909 }
3910
3911 fn check_panic(&mut self) {
3912 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
3913 resume_unwind(err)
3914 }
3915 }
3916
3917 fn get_bio_error(&mut self) -> Option<io::Error> {
3918 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
3919 }
3920
3921 pub fn get_ref(&self) -> &S {
3923 unsafe {
3924 let bio = self.ssl.get_raw_rbio();
3925 bio::get_ref(bio)
3926 }
3927 }
3928
3929 pub fn get_mut(&mut self) -> &mut S {
3936 unsafe {
3937 let bio = self.ssl.get_raw_rbio();
3938 bio::get_mut(bio)
3939 }
3940 }
3941
3942 pub fn ssl(&self) -> &SslRef {
3944 &self.ssl
3945 }
3946}
3947
3948impl<S: Read + Write> Read for SslStream<S> {
3949 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3950 unsafe {
3952 self.read_uninit(util::from_raw_parts_mut(
3953 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3954 buf.len(),
3955 ))
3956 }
3957 }
3958}
3959
3960impl<S: Read + Write> Write for SslStream<S> {
3961 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
3962 loop {
3963 match self.ssl_write(buf) {
3964 Ok(n) => return Ok(n),
3965 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3966 Err(e) => {
3967 return Err(e
3968 .into_io_error()
3969 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
3970 }
3971 }
3972 }
3973 }
3974
3975 fn flush(&mut self) -> io::Result<()> {
3976 self.get_mut().flush()
3977 }
3978}
3979
3980#[deprecated(
3982 since = "0.10.32",
3983 note = "use the methods directly on Ssl/SslStream instead"
3984)]
3985pub struct SslStreamBuilder<S> {
3986 inner: SslStream<S>,
3987}
3988
3989#[allow(deprecated)]
3990impl<S> SslStreamBuilder<S>
3991where
3992 S: Read + Write,
3993{
3994 pub fn new(ssl: Ssl, stream: S) -> Self {
3996 Self {
3997 inner: SslStream::new(ssl, stream).unwrap(),
3998 }
3999 }
4000
4001 #[corresponds(SSL_stateless)]
4012 #[cfg(ossl111)]
4013 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4014 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4015 1 => Ok(true),
4016 0 => Ok(false),
4017 -1 => Err(ErrorStack::get()),
4018 _ => unreachable!(),
4019 }
4020 }
4021
4022 #[corresponds(SSL_set_connect_state)]
4024 pub fn set_connect_state(&mut self) {
4025 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4026 }
4027
4028 #[corresponds(SSL_set_accept_state)]
4030 pub fn set_accept_state(&mut self) {
4031 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4032 }
4033
4034 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4036 match self.inner.connect() {
4037 Ok(()) => Ok(self.inner),
4038 Err(error) => match error.code() {
4039 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4040 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4041 stream: self.inner,
4042 error,
4043 }))
4044 }
4045 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4046 stream: self.inner,
4047 error,
4048 })),
4049 },
4050 }
4051 }
4052
4053 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4055 match self.inner.accept() {
4056 Ok(()) => Ok(self.inner),
4057 Err(error) => match error.code() {
4058 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4059 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4060 stream: self.inner,
4061 error,
4062 }))
4063 }
4064 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4065 stream: self.inner,
4066 error,
4067 })),
4068 },
4069 }
4070 }
4071
4072 #[corresponds(SSL_do_handshake)]
4076 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4077 match self.inner.do_handshake() {
4078 Ok(()) => Ok(self.inner),
4079 Err(error) => match error.code() {
4080 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4081 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4082 stream: self.inner,
4083 error,
4084 }))
4085 }
4086 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4087 stream: self.inner,
4088 error,
4089 })),
4090 },
4091 }
4092 }
4093
4094 #[corresponds(SSL_read_early_data)]
4104 #[cfg(any(ossl111, libressl))]
4105 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4106 self.inner.read_early_data(buf)
4107 }
4108
4109 #[corresponds(SSL_write_early_data)]
4116 #[cfg(any(ossl111, libressl))]
4117 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4118 self.inner.write_early_data(buf)
4119 }
4120}
4121
4122#[allow(deprecated)]
4123impl<S> SslStreamBuilder<S> {
4124 pub fn get_ref(&self) -> &S {
4126 unsafe {
4127 let bio = self.inner.ssl.get_raw_rbio();
4128 bio::get_ref(bio)
4129 }
4130 }
4131
4132 pub fn get_mut(&mut self) -> &mut S {
4139 unsafe {
4140 let bio = self.inner.ssl.get_raw_rbio();
4141 bio::get_mut(bio)
4142 }
4143 }
4144
4145 pub fn ssl(&self) -> &SslRef {
4147 &self.inner.ssl
4148 }
4149
4150 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4158 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4159 unsafe {
4160 let bio = self.inner.ssl.get_raw_rbio();
4161 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4162 }
4163 }
4164}
4165
4166#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4168pub enum ShutdownResult {
4169 Sent,
4171
4172 Received,
4174}
4175
4176bitflags! {
4177 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4179 #[repr(transparent)]
4180 pub struct ShutdownState: c_int {
4181 const SENT = ffi::SSL_SENT_SHUTDOWN;
4183 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4185 }
4186}
4187
4188use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4189cfg_if! {
4190 if #[cfg(ossl300)] {
4191 use ffi::SSL_get1_peer_certificate;
4192 } else {
4193 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4194 }
4195}
4196use ffi::{
4197 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4198 TLS_server_method,
4199};
4200cfg_if! {
4201 if #[cfg(ossl110)] {
4202 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4203 ffi::CRYPTO_get_ex_new_index(
4204 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4205 0,
4206 ptr::null_mut(),
4207 None,
4208 None,
4209 Some(f),
4210 )
4211 }
4212
4213 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4214 ffi::CRYPTO_get_ex_new_index(
4215 ffi::CRYPTO_EX_INDEX_SSL,
4216 0,
4217 ptr::null_mut(),
4218 None,
4219 None,
4220 Some(f),
4221 )
4222 }
4223 } else {
4224 use std::sync::Once;
4225
4226 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4227 static ONCE: Once = Once::new();
4229 ONCE.call_once(|| {
4230 cfg_if! {
4231 if #[cfg(not(any(boringssl, awslc)))] {
4232 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4233 } else {
4234 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4235 }
4236 }
4237 });
4238
4239 cfg_if! {
4240 if #[cfg(not(any(boringssl, awslc)))] {
4241 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
4242 } else {
4243 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4244 }
4245 }
4246 }
4247
4248 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4249 static ONCE: Once = Once::new();
4251 ONCE.call_once(|| {
4252 #[cfg(not(any(boringssl, awslc)))]
4253 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4254 #[cfg(any(boringssl, awslc))]
4255 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4256 });
4257
4258 #[cfg(not(any(boringssl, awslc)))]
4259 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
4260 #[cfg(any(boringssl, awslc))]
4261 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
4262 }
4263 }
4264}