1use crate::cipher_ctx::CipherCtxRef;
61#[cfg(ossl300)]
62use crate::cvt_long;
63use crate::dh::{Dh, DhRef};
64use crate::ec::EcKeyRef;
65use crate::error::ErrorStack;
66use crate::ex_data::Index;
67#[cfg(ossl111)]
68use crate::hash::MessageDigest;
69use crate::hmac::HMacCtxRef;
70#[cfg(ossl300)]
71use crate::mac_ctx::MacCtxRef;
72#[cfg(any(ossl110, libressl270))]
73use crate::nid::Nid;
74use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
75#[cfg(ossl300)]
76use crate::pkey::{PKey, Public};
77#[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
78use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
79use crate::ssl::bio::BioMethod;
80use crate::ssl::callbacks::*;
81use crate::ssl::error::InnerError;
82use crate::stack::{Stack, StackRef, Stackable};
83use crate::util;
84use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
85use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
86#[cfg(any(ossl102, boringssl, libressl261, awslc))]
87use crate::x509::verify::X509VerifyParamRef;
88use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
89use crate::{cvt, cvt_n, cvt_p, init};
90use bitflags::bitflags;
91use cfg_if::cfg_if;
92use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
93use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
94use once_cell::sync::{Lazy, OnceCell};
95use openssl_macros::corresponds;
96use std::any::TypeId;
97use std::collections::HashMap;
98use std::ffi::{CStr, CString};
99use std::fmt;
100use std::io;
101use std::io::prelude::*;
102use std::marker::PhantomData;
103use std::mem::{self, ManuallyDrop, MaybeUninit};
104use std::ops::{Deref, DerefMut};
105use std::panic::resume_unwind;
106use std::path::Path;
107use std::ptr;
108use std::str;
109use std::sync::{Arc, Mutex};
110
111pub use crate::ssl::connector::{
112 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
113};
114pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
115
116mod bio;
117mod callbacks;
118#[cfg(any(boringssl, awslc))]
119mod client_hello;
120mod connector;
121mod error;
122#[cfg(test)]
123mod test;
124
125#[cfg(any(boringssl, awslc))]
126pub use client_hello::ClientHello;
127
128#[corresponds(OPENSSL_cipher_name)]
134#[cfg(ossl111)]
135pub fn cipher_name(std_name: &str) -> &'static str {
136 unsafe {
137 ffi::init();
138
139 let s = CString::new(std_name).unwrap();
140 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
141 CStr::from_ptr(ptr).to_str().unwrap()
142 }
143}
144
145cfg_if! {
146 if #[cfg(ossl300)] {
147 type SslOptionsRepr = u64;
148 } else if #[cfg(any(boringssl, awslc))] {
149 type SslOptionsRepr = u32;
150 } else {
151 type SslOptionsRepr = libc::c_ulong;
152 }
153}
154
155bitflags! {
156 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
158 #[repr(transparent)]
159 pub struct SslOptions: SslOptionsRepr {
160 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
162
163 #[cfg(not(any(boringssl, awslc)))]
165 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
166
167 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
171
172 #[cfg(not(any(boringssl, awslc)))]
178 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
179
180 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
182
183 #[cfg(not(any(boringssl, awslc)))]
185 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
186 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
187
188 #[cfg(not(any(boringssl, awslc)))]
190 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
191
192 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
195 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
196
197 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
201
202 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
206
207 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
211
212 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
214
215 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
217
218 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
220
221 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
223
224 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
226
227 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
229
230 #[cfg(any(boringssl, ossl111, libressl340, awslc))]
234 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
235
236 #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
240 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
241
242 #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
246 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
247
248 #[cfg(any(ossl102, ossl110))]
264 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
265
266 #[cfg(any(boringssl, ossl110h, awslc))]
270 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
271
272 #[cfg(ossl111)]
277 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
278
279 #[cfg(ossl111)]
291 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
292 }
293}
294
295bitflags! {
296 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
298 #[repr(transparent)]
299 pub struct SslMode: SslBitType {
300 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
306
307 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
310
311 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
321
322 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
328
329 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
333
334 #[cfg(not(libressl))]
342 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
343
344 #[cfg(ossl110)]
351 const ASYNC = ffi::SSL_MODE_ASYNC;
352 }
353}
354
355#[derive(Copy, Clone)]
357pub struct SslMethod(*const ffi::SSL_METHOD);
358
359impl SslMethod {
360 #[corresponds(TLS_method)]
362 pub fn tls() -> SslMethod {
363 unsafe { SslMethod(TLS_method()) }
364 }
365
366 #[corresponds(DTLS_method)]
368 pub fn dtls() -> SslMethod {
369 unsafe { SslMethod(DTLS_method()) }
370 }
371
372 #[corresponds(TLS_client_method)]
374 pub fn tls_client() -> SslMethod {
375 unsafe { SslMethod(TLS_client_method()) }
376 }
377
378 #[corresponds(TLS_server_method)]
380 pub fn tls_server() -> SslMethod {
381 unsafe { SslMethod(TLS_server_method()) }
382 }
383
384 #[cfg(tongsuo)]
385 #[corresponds(NTLS_client_method)]
386 pub fn ntls_client() -> SslMethod {
387 unsafe { SslMethod(ffi::NTLS_client_method()) }
388 }
389
390 #[cfg(tongsuo)]
391 #[corresponds(NTLS_server_method)]
392 pub fn ntls_server() -> SslMethod {
393 unsafe { SslMethod(ffi::NTLS_server_method()) }
394 }
395
396 #[corresponds(DTLS_client_method)]
398 #[cfg(any(boringssl, ossl110, libressl291, awslc))]
399 pub fn dtls_client() -> SslMethod {
400 unsafe { SslMethod(DTLS_client_method()) }
401 }
402
403 #[corresponds(DTLS_server_method)]
405 #[cfg(any(boringssl, ossl110, libressl291, awslc))]
406 pub fn dtls_server() -> SslMethod {
407 unsafe { SslMethod(DTLS_server_method()) }
408 }
409
410 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
416 SslMethod(ptr)
417 }
418
419 #[allow(clippy::trivially_copy_pass_by_ref)]
421 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
422 self.0
423 }
424}
425
426unsafe impl Sync for SslMethod {}
427unsafe impl Send for SslMethod {}
428
429bitflags! {
430 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
432 #[repr(transparent)]
433 pub struct SslVerifyMode: i32 {
434 const PEER = ffi::SSL_VERIFY_PEER;
438
439 const NONE = ffi::SSL_VERIFY_NONE;
445
446 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
450 }
451}
452
453#[cfg(any(boringssl, awslc))]
454type SslBitType = c_int;
455#[cfg(not(any(boringssl, awslc)))]
456type SslBitType = c_long;
457
458#[cfg(any(boringssl, awslc))]
459type SslTimeTy = u64;
460#[cfg(not(any(boringssl, awslc)))]
461type SslTimeTy = c_long;
462
463bitflags! {
464 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
466 #[repr(transparent)]
467 pub struct SslSessionCacheMode: SslBitType {
468 const OFF = ffi::SSL_SESS_CACHE_OFF;
470
471 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
478
479 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
483
484 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
486
487 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
489
490 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
492
493 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
495
496 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
498 }
499}
500
501#[cfg(ossl111)]
502bitflags! {
503 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
505 #[repr(transparent)]
506 pub struct ExtensionContext: c_uint {
507 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
509 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
511 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
513 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
515 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
517 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
519 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
521 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
522 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
524 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
525 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
526 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
527 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
528 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
529 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
530 }
531}
532
533#[derive(Copy, Clone)]
535pub struct TlsExtType(c_uint);
536
537impl TlsExtType {
538 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
542
543 pub const ALPN: TlsExtType =
547 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
548
549 pub fn from_raw(raw: c_uint) -> TlsExtType {
551 TlsExtType(raw)
552 }
553
554 #[allow(clippy::trivially_copy_pass_by_ref)]
556 pub fn as_raw(&self) -> c_uint {
557 self.0
558 }
559}
560
561#[derive(Copy, Clone)]
563pub struct SslFiletype(c_int);
564
565impl SslFiletype {
566 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
570
571 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
575
576 pub fn from_raw(raw: c_int) -> SslFiletype {
578 SslFiletype(raw)
579 }
580
581 #[allow(clippy::trivially_copy_pass_by_ref)]
583 pub fn as_raw(&self) -> c_int {
584 self.0
585 }
586}
587
588#[derive(Copy, Clone)]
590pub struct StatusType(c_int);
591
592impl StatusType {
593 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
595
596 pub fn from_raw(raw: c_int) -> StatusType {
598 StatusType(raw)
599 }
600
601 #[allow(clippy::trivially_copy_pass_by_ref)]
603 pub fn as_raw(&self) -> c_int {
604 self.0
605 }
606}
607
608#[derive(Copy, Clone)]
610pub struct NameType(c_int);
611
612impl NameType {
613 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
615
616 pub fn from_raw(raw: c_int) -> StatusType {
618 StatusType(raw)
619 }
620
621 #[allow(clippy::trivially_copy_pass_by_ref)]
623 pub fn as_raw(&self) -> c_int {
624 self.0
625 }
626}
627
628static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
629static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
630static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
631
632fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
633 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
634}
635
636unsafe extern "C" fn free_data_box<T>(
637 _parent: *mut c_void,
638 ptr: *mut c_void,
639 _ad: *mut ffi::CRYPTO_EX_DATA,
640 _idx: c_int,
641 _argl: c_long,
642 _argp: *mut c_void,
643) {
644 if !ptr.is_null() {
645 let _ = Box::<T>::from_raw(ptr as *mut T);
646 }
647}
648
649#[derive(Debug, Copy, Clone, PartialEq, Eq)]
651pub struct SniError(c_int);
652
653impl SniError {
654 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
656
657 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
659
660 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
661}
662
663#[derive(Debug, Copy, Clone, PartialEq, Eq)]
665pub struct SslAlert(c_int);
666
667impl SslAlert {
668 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
670 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
671 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
672 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
673}
674
675#[derive(Debug, Copy, Clone, PartialEq, Eq)]
677pub struct AlpnError(c_int);
678
679impl AlpnError {
680 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
682
683 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
685}
686
687#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
691#[derive(Debug, Copy, Clone, PartialEq, Eq)]
692pub struct ClientHelloError(c_int);
693
694#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
695impl ClientHelloError {
696 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
698
699 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
701}
702
703#[derive(Debug, Copy, Clone, PartialEq, Eq)]
705pub struct TicketKeyStatus(c_int);
706
707impl TicketKeyStatus {
708 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
710 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
712 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
714}
715
716#[derive(Debug, Copy, Clone, PartialEq, Eq)]
718#[cfg(any(boringssl, awslc))]
719pub struct SelectCertError(ffi::ssl_select_cert_result_t);
720
721#[cfg(any(boringssl, awslc))]
722impl SelectCertError {
723 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
725
726 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
728
729 #[cfg(boringssl)]
735 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
736}
737
738#[cfg(ossl111)]
740#[derive(Debug, Copy, Clone, PartialEq, Eq)]
741pub struct SslCtValidationMode(c_int);
742
743#[cfg(ossl111)]
744impl SslCtValidationMode {
745 pub const PERMISSIVE: SslCtValidationMode =
746 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
747 pub const STRICT: SslCtValidationMode =
748 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
749}
750
751#[derive(Debug, Copy, Clone, PartialEq, Eq)]
753pub struct CertCompressionAlgorithm(c_int);
754
755impl CertCompressionAlgorithm {
756 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
757 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
758 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
759}
760
761#[derive(Debug, Copy, Clone, PartialEq, Eq)]
763pub struct SslVersion(c_int);
764
765impl SslVersion {
766 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
768
769 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
771
772 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
774
775 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
777
778 #[cfg(any(ossl111, libressl340, boringssl, awslc))]
782 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
783
784 #[cfg(tongsuo)]
785 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
786
787 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
791
792 #[cfg(any(ossl102, libressl332, boringssl, awslc))]
796 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
797}
798
799cfg_if! {
800 if #[cfg(any(boringssl, awslc))] {
801 type SslCacheTy = i64;
802 type SslCacheSize = libc::c_ulong;
803 type MtuTy = u32;
804 type ModeTy = u32;
805 type SizeTy = usize;
806 } else {
807 type SslCacheTy = i64;
808 type SslCacheSize = c_long;
809 type MtuTy = c_long;
810 type ModeTy = c_long;
811 type SizeTy = u32;
812 }
813}
814
815#[corresponds(SSL_select_next_proto)]
826pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
827 unsafe {
828 let mut out = ptr::null_mut();
829 let mut outlen = 0;
830 let r = ffi::SSL_select_next_proto(
831 &mut out,
832 &mut outlen,
833 server.as_ptr(),
834 server.len() as c_uint,
835 client.as_ptr(),
836 client.len() as c_uint,
837 );
838 if r == ffi::OPENSSL_NPN_NEGOTIATED {
839 Some(util::from_raw_parts(out as *const u8, outlen as usize))
840 } else {
841 None
842 }
843 }
844}
845
846pub struct SslContextBuilder(SslContext);
848
849impl SslContextBuilder {
850 #[corresponds(SSL_CTX_new)]
852 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
853 unsafe {
854 init();
855 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
856
857 Ok(SslContextBuilder::from_ptr(ctx))
858 }
859 }
860
861 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
867 SslContextBuilder(SslContext::from_ptr(ctx))
868 }
869
870 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
872 self.0.as_ptr()
873 }
874
875 #[cfg(tongsuo)]
876 #[corresponds(SSL_CTX_enable_ntls)]
877 pub fn enable_ntls(&mut self) {
878 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
879 }
880
881 #[cfg(tongsuo)]
882 #[corresponds(SSL_CTX_disable_ntls)]
883 pub fn disable_ntls(&mut self) {
884 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
885 }
886
887 #[cfg(all(tongsuo, ossl300))]
888 #[corresponds(SSL_CTX_enable_force_ntls)]
889 pub fn enable_force_ntls(&mut self) {
890 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
891 }
892
893 #[cfg(all(tongsuo, ossl300))]
894 #[corresponds(SSL_CTX_disable_force_ntls)]
895 pub fn disable_force_ntls(&mut self) {
896 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
897 }
898
899 #[cfg(tongsuo)]
900 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
901 pub fn enable_sm_tls13_strict(&mut self) {
902 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
903 }
904
905 #[cfg(tongsuo)]
906 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
907 pub fn disable_sm_tls13_strict(&mut self) {
908 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
909 }
910
911 #[corresponds(SSL_CTX_set_verify)]
913 pub fn set_verify(&mut self, mode: SslVerifyMode) {
914 unsafe {
915 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
916 }
917 }
918
919 #[corresponds(SSL_CTX_set_verify)]
926 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
927 where
928 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
929 {
930 unsafe {
931 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
932 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
933 }
934 }
935
936 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
944 pub fn set_servername_callback<F>(&mut self, callback: F)
946 where
947 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
948 {
949 unsafe {
950 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
956 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
957 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
958 }
959 }
960
961 #[corresponds(SSL_CTX_set_verify_depth)]
965 pub fn set_verify_depth(&mut self, depth: u32) {
966 unsafe {
967 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
968 }
969 }
970
971 #[corresponds(SSL_CTX_set0_verify_cert_store)]
975 #[cfg(any(ossl102, boringssl, awslc))]
976 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
977 unsafe {
978 let ptr = cert_store.as_ptr();
979 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
980 mem::forget(cert_store);
981
982 Ok(())
983 }
984 }
985
986 #[corresponds(SSL_CTX_set_cert_store)]
988 pub fn set_cert_store(&mut self, cert_store: X509Store) {
989 unsafe {
990 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
991 mem::forget(cert_store);
992 }
993 }
994
995 #[corresponds(SSL_CTX_set_read_ahead)]
1002 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1003 unsafe {
1004 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1005 }
1006 }
1007
1008 #[corresponds(SSL_CTX_set_mode)]
1012 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1013 unsafe {
1014 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1015 SslMode::from_bits_retain(bits)
1016 }
1017 }
1018
1019 #[corresponds(SSL_CTX_clear_mode)]
1021 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1022 unsafe {
1023 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1024 SslMode::from_bits_retain(bits)
1025 }
1026 }
1027
1028 #[corresponds(SSL_CTX_get_mode)]
1030 pub fn mode(&self) -> SslMode {
1031 unsafe {
1032 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1033 SslMode::from_bits_retain(bits)
1034 }
1035 }
1036
1037 #[corresponds(SSL_CTX_set_dh_auto)]
1046 #[cfg(ossl300)]
1047 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1048 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
1049 }
1050
1051 #[corresponds(SSL_CTX_set_tmp_dh)]
1053 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1054 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1055 }
1056
1057 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1064 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1065 where
1066 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1067 {
1068 unsafe {
1069 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1070
1071 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1072 }
1073 }
1074
1075 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1077 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1078 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1079 }
1080
1081 #[corresponds(SSL_CTX_set_default_verify_paths)]
1086 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1087 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1088 }
1089
1090 #[corresponds(SSL_CTX_load_verify_locations)]
1094 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1095 self.load_verify_locations(Some(file.as_ref()), None)
1096 }
1097
1098 #[corresponds(SSL_CTX_load_verify_locations)]
1100 pub fn load_verify_locations(
1101 &mut self,
1102 ca_file: Option<&Path>,
1103 ca_path: Option<&Path>,
1104 ) -> Result<(), ErrorStack> {
1105 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1106 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1107 unsafe {
1108 cvt(ffi::SSL_CTX_load_verify_locations(
1109 self.as_ptr(),
1110 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1111 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1112 ))
1113 .map(|_| ())
1114 }
1115 }
1116
1117 #[corresponds(SSL_CTX_set_client_CA_list)]
1122 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1123 unsafe {
1124 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1125 mem::forget(list);
1126 }
1127 }
1128
1129 #[corresponds(SSL_CTX_add_client_CA)]
1132 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1133 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1134 }
1135
1136 #[corresponds(SSL_CTX_set_session_id_context)]
1145 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1146 unsafe {
1147 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1148 cvt(ffi::SSL_CTX_set_session_id_context(
1149 self.as_ptr(),
1150 sid_ctx.as_ptr(),
1151 sid_ctx.len() as SizeTy,
1152 ))
1153 .map(|_| ())
1154 }
1155 }
1156
1157 #[corresponds(SSL_CTX_use_certificate_file)]
1163 pub fn set_certificate_file<P: AsRef<Path>>(
1164 &mut self,
1165 file: P,
1166 file_type: SslFiletype,
1167 ) -> Result<(), ErrorStack> {
1168 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1169 unsafe {
1170 cvt(ffi::SSL_CTX_use_certificate_file(
1171 self.as_ptr(),
1172 file.as_ptr() as *const _,
1173 file_type.as_raw(),
1174 ))
1175 .map(|_| ())
1176 }
1177 }
1178
1179 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1185 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1186 &mut self,
1187 file: P,
1188 ) -> Result<(), ErrorStack> {
1189 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1190 unsafe {
1191 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1192 self.as_ptr(),
1193 file.as_ptr() as *const _,
1194 ))
1195 .map(|_| ())
1196 }
1197 }
1198
1199 #[corresponds(SSL_CTX_use_certificate)]
1203 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1204 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1205 }
1206
1207 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1212 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1213 unsafe {
1214 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1215 mem::forget(cert);
1216 Ok(())
1217 }
1218 }
1219
1220 #[cfg(tongsuo)]
1221 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1222 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1223 &mut self,
1224 file: P,
1225 file_type: SslFiletype,
1226 ) -> Result<(), ErrorStack> {
1227 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1228 unsafe {
1229 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1230 self.as_ptr(),
1231 file.as_ptr() as *const _,
1232 file_type.as_raw(),
1233 ))
1234 .map(|_| ())
1235 }
1236 }
1237
1238 #[cfg(tongsuo)]
1239 #[corresponds(SSL_CTX_use_enc_certificate)]
1240 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1241 unsafe {
1242 cvt(ffi::SSL_CTX_use_enc_certificate(
1243 self.as_ptr(),
1244 cert.as_ptr(),
1245 ))
1246 .map(|_| ())
1247 }
1248 }
1249
1250 #[cfg(tongsuo)]
1251 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1252 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1253 &mut self,
1254 file: P,
1255 file_type: SslFiletype,
1256 ) -> Result<(), ErrorStack> {
1257 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1258 unsafe {
1259 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1260 self.as_ptr(),
1261 file.as_ptr() as *const _,
1262 file_type.as_raw(),
1263 ))
1264 .map(|_| ())
1265 }
1266 }
1267
1268 #[cfg(tongsuo)]
1269 #[corresponds(SSL_CTX_use_sign_certificate)]
1270 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1271 unsafe {
1272 cvt(ffi::SSL_CTX_use_sign_certificate(
1273 self.as_ptr(),
1274 cert.as_ptr(),
1275 ))
1276 .map(|_| ())
1277 }
1278 }
1279
1280 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1282 pub fn set_private_key_file<P: AsRef<Path>>(
1283 &mut self,
1284 file: P,
1285 file_type: SslFiletype,
1286 ) -> Result<(), ErrorStack> {
1287 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1288 unsafe {
1289 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1290 self.as_ptr(),
1291 file.as_ptr() as *const _,
1292 file_type.as_raw(),
1293 ))
1294 .map(|_| ())
1295 }
1296 }
1297
1298 #[corresponds(SSL_CTX_use_PrivateKey)]
1300 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1301 where
1302 T: HasPrivate,
1303 {
1304 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1305 }
1306
1307 #[cfg(tongsuo)]
1308 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1309 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1310 &mut self,
1311 file: P,
1312 file_type: SslFiletype,
1313 ) -> Result<(), ErrorStack> {
1314 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1315 unsafe {
1316 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1317 self.as_ptr(),
1318 file.as_ptr() as *const _,
1319 file_type.as_raw(),
1320 ))
1321 .map(|_| ())
1322 }
1323 }
1324
1325 #[cfg(tongsuo)]
1326 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1327 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1328 where
1329 T: HasPrivate,
1330 {
1331 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1332 }
1333
1334 #[cfg(tongsuo)]
1335 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1336 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1337 &mut self,
1338 file: P,
1339 file_type: SslFiletype,
1340 ) -> Result<(), ErrorStack> {
1341 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1342 unsafe {
1343 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1344 self.as_ptr(),
1345 file.as_ptr() as *const _,
1346 file_type.as_raw(),
1347 ))
1348 .map(|_| ())
1349 }
1350 }
1351
1352 #[cfg(tongsuo)]
1353 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1354 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1355 where
1356 T: HasPrivate,
1357 {
1358 unsafe {
1359 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1360 self.as_ptr(),
1361 key.as_ptr(),
1362 ))
1363 .map(|_| ())
1364 }
1365 }
1366
1367 #[corresponds(SSL_CTX_set_cipher_list)]
1375 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1376 let cipher_list = CString::new(cipher_list).unwrap();
1377 unsafe {
1378 cvt(ffi::SSL_CTX_set_cipher_list(
1379 self.as_ptr(),
1380 cipher_list.as_ptr() as *const _,
1381 ))
1382 .map(|_| ())
1383 }
1384 }
1385
1386 #[corresponds(SSL_CTX_set_ciphersuites)]
1395 #[cfg(any(ossl111, libressl340, awslc))]
1396 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1397 let cipher_list = CString::new(cipher_list).unwrap();
1398 unsafe {
1399 cvt(ffi::SSL_CTX_set_ciphersuites(
1400 self.as_ptr(),
1401 cipher_list.as_ptr() as *const _,
1402 ))
1403 .map(|_| ())
1404 }
1405 }
1406
1407 #[corresponds(SSL_CTX_set_ecdh_auto)]
1411 #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1412 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1413 unsafe {
1414 cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ())
1415 }
1416 }
1417
1418 #[corresponds(SSL_CTX_set_options)]
1425 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1426 let bits =
1427 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1428 SslOptions::from_bits_retain(bits)
1429 }
1430
1431 #[corresponds(SSL_CTX_get_options)]
1433 pub fn options(&self) -> SslOptions {
1434 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1435 SslOptions::from_bits_retain(bits)
1436 }
1437
1438 #[corresponds(SSL_CTX_clear_options)]
1440 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1441 let bits =
1442 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1443 SslOptions::from_bits_retain(bits)
1444 }
1445
1446 #[corresponds(SSL_CTX_set_min_proto_version)]
1453 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1454 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1455 unsafe {
1456 cvt(ffi::SSL_CTX_set_min_proto_version(
1457 self.as_ptr(),
1458 version.map_or(0, |v| v.0 as _),
1459 ))
1460 .map(|_| ())
1461 }
1462 }
1463
1464 #[corresponds(SSL_CTX_set_max_proto_version)]
1471 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1472 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1473 unsafe {
1474 cvt(ffi::SSL_CTX_set_max_proto_version(
1475 self.as_ptr(),
1476 version.map_or(0, |v| v.0 as _),
1477 ))
1478 .map(|_| ())
1479 }
1480 }
1481
1482 #[corresponds(SSL_CTX_get_min_proto_version)]
1489 #[cfg(any(ossl110g, libressl270))]
1490 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1491 unsafe {
1492 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1493 if r == 0 {
1494 None
1495 } else {
1496 Some(SslVersion(r))
1497 }
1498 }
1499 }
1500
1501 #[corresponds(SSL_CTX_get_max_proto_version)]
1508 #[cfg(any(ossl110g, libressl270))]
1509 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1510 unsafe {
1511 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1512 if r == 0 {
1513 None
1514 } else {
1515 Some(SslVersion(r))
1516 }
1517 }
1518 }
1519
1520 #[corresponds(SSL_CTX_set_alpn_protos)]
1529 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
1530 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1531 unsafe {
1532 assert!(protocols.len() <= c_uint::MAX as usize);
1533 let r = ffi::SSL_CTX_set_alpn_protos(
1534 self.as_ptr(),
1535 protocols.as_ptr(),
1536 protocols.len() as _,
1537 );
1538 if r == 0 {
1540 Ok(())
1541 } else {
1542 Err(ErrorStack::get())
1543 }
1544 }
1545 }
1546
1547 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1549 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1550 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1551 unsafe {
1552 let cstr = CString::new(protocols).unwrap();
1553
1554 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1555 if r == 0 {
1557 Ok(())
1558 } else {
1559 Err(ErrorStack::get())
1560 }
1561 }
1562 }
1563
1564 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1575 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1576 where
1577 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1578 {
1579 unsafe {
1580 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1581 ffi::SSL_CTX_set_alpn_select_cb(
1582 self.as_ptr(),
1583 Some(callbacks::raw_alpn_select::<F>),
1584 ptr::null_mut(),
1585 );
1586 }
1587 }
1588
1589 #[corresponds(SSL_CTX_check_private_key)]
1591 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1592 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1593 }
1594
1595 #[corresponds(SSL_CTX_get_cert_store)]
1597 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1598 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1599 }
1600
1601 #[corresponds(SSL_CTX_get_cert_store)]
1603 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1604 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1605 }
1606
1607 #[corresponds(SSL_CTX_get0_param)]
1611 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1612 pub fn verify_param(&self) -> &X509VerifyParamRef {
1613 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1614 }
1615
1616 #[corresponds(SSL_CTX_get0_param)]
1620 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1621 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1622 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1623 }
1624
1625 #[cfg(any(boringssl, tongsuo, awslc))]
1633 pub fn add_cert_decompression_alg<F>(
1634 &mut self,
1635 alg_id: CertCompressionAlgorithm,
1636 decompress: F,
1637 ) -> Result<(), ErrorStack>
1638 where
1639 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1640 {
1641 unsafe {
1642 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1643 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1644 self.as_ptr(),
1645 alg_id.0 as _,
1646 None,
1647 Some(raw_cert_decompression::<F>),
1648 ))
1649 .map(|_| ())
1650 }
1651 }
1652
1653 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1655 #[cfg(ossl320)]
1656 pub fn set_cert_comp_preference(
1657 &mut self,
1658 algs: &[CertCompressionAlgorithm],
1659 ) -> Result<(), ErrorStack> {
1660 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1661 unsafe {
1662 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1663 self.as_ptr(),
1664 algs.as_mut_ptr(),
1665 algs.len(),
1666 ))
1667 .map(|_| ())
1668 }
1669 }
1670
1671 #[cfg(any(boringssl, awslc))]
1679 pub fn enable_ocsp_stapling(&mut self) {
1680 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1681 }
1682
1683 #[cfg(any(boringssl, awslc))]
1691 pub fn enable_signed_cert_timestamps(&mut self) {
1692 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1693 }
1694
1695 #[cfg(any(boringssl, awslc))]
1703 pub fn set_grease_enabled(&mut self, enabled: bool) {
1704 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1705 }
1706
1707 #[cfg(any(boringssl, awslc))]
1715 pub fn set_permute_extensions(&mut self, enabled: bool) {
1716 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1717 }
1718
1719 #[corresponds(SSL_CTX_enable_ct)]
1721 #[cfg(ossl111)]
1722 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1723 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1724 }
1725
1726 #[corresponds(SSL_CTX_ct_is_enabled)]
1728 #[cfg(ossl111)]
1729 pub fn ct_is_enabled(&self) -> bool {
1730 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1731 }
1732
1733 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1735 #[cfg(not(any(boringssl, awslc)))]
1736 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1737 unsafe {
1738 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1739 .map(|_| ())
1740 }
1741 }
1742
1743 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1756 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1757 where
1758 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1759 {
1760 unsafe {
1761 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1762 cvt(
1763 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1764 as c_int,
1765 )
1766 .map(|_| ())
1767 }
1768 }
1769
1770 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1771 #[cfg(ossl300)]
1772 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1773 where
1774 F: Fn(
1775 &mut SslRef,
1776 &mut [u8],
1777 &mut [u8],
1778 &mut CipherCtxRef,
1779 &mut MacCtxRef,
1780 bool,
1781 ) -> Result<TicketKeyStatus, ErrorStack>
1782 + 'static
1783 + Sync
1784 + Send,
1785 {
1786 unsafe {
1787 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1788 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1789 self.as_ptr(),
1790 Some(raw_tlsext_ticket_key_evp::<F>),
1791 ) as c_int)
1792 .map(|_| ())
1793 }
1794 }
1795
1796 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1797 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1798 where
1799 F: Fn(
1800 &mut SslRef,
1801 &mut [u8],
1802 &mut [u8],
1803 &mut CipherCtxRef,
1804 &mut HMacCtxRef,
1805 bool,
1806 ) -> Result<TicketKeyStatus, ErrorStack>
1807 + 'static
1808 + Sync
1809 + Send,
1810 {
1811 unsafe {
1812 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1813 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1814 self.as_ptr(),
1815 Some(raw_tlsext_ticket_key::<F>),
1816 ) as c_int)
1817 .map(|_| ())
1818 }
1819 }
1820
1821 #[corresponds(SSL_CTX_set_psk_client_callback)]
1827 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1828 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1829 where
1830 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1831 + 'static
1832 + Sync
1833 + Send,
1834 {
1835 unsafe {
1836 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1837 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1838 }
1839 }
1840
1841 #[corresponds(SSL_CTX_set_psk_server_callback)]
1847 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1848 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1849 where
1850 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1851 + 'static
1852 + Sync
1853 + Send,
1854 {
1855 unsafe {
1856 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1857 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1858 }
1859 }
1860
1861 #[corresponds(SSL_CTX_sess_set_new_cb)]
1875 pub fn set_new_session_callback<F>(&mut self, callback: F)
1876 where
1877 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1878 {
1879 unsafe {
1880 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1881 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1882 }
1883 }
1884
1885 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1889 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1890 where
1891 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1892 {
1893 unsafe {
1894 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1895 ffi::SSL_CTX_sess_set_remove_cb(
1896 self.as_ptr(),
1897 Some(callbacks::raw_remove_session::<F>),
1898 );
1899 }
1900 }
1901
1902 #[corresponds(SSL_CTX_sess_set_get_cb)]
1913 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1914 where
1915 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1916 {
1917 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1918 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1919 }
1920
1921 #[corresponds(SSL_CTX_set_keylog_callback)]
1929 #[cfg(any(ossl111, boringssl, awslc))]
1930 pub fn set_keylog_callback<F>(&mut self, callback: F)
1931 where
1932 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1933 {
1934 unsafe {
1935 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1936 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1937 }
1938 }
1939
1940 #[corresponds(SSL_CTX_set_session_cache_mode)]
1944 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1945 unsafe {
1946 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1947 SslSessionCacheMode::from_bits_retain(bits)
1948 }
1949 }
1950
1951 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1957 #[cfg(ossl111)]
1958 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1959 where
1960 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1961 {
1962 unsafe {
1963 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1964 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1965 self.as_ptr(),
1966 Some(raw_stateless_cookie_generate::<F>),
1967 );
1968 }
1969 }
1970
1971 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1980 #[cfg(ossl111)]
1981 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1982 where
1983 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1984 {
1985 unsafe {
1986 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1987 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1988 self.as_ptr(),
1989 Some(raw_stateless_cookie_verify::<F>),
1990 )
1991 }
1992 }
1993
1994 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1999 #[cfg(not(any(boringssl, awslc)))]
2000 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
2001 where
2002 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
2003 {
2004 unsafe {
2005 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2006 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2007 }
2008 }
2009
2010 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2015 #[cfg(not(any(boringssl, awslc)))]
2016 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2017 where
2018 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2019 {
2020 unsafe {
2021 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2022 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2023 }
2024 }
2025
2026 #[corresponds(SSL_CTX_set_ex_data)]
2032 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2033 self.set_ex_data_inner(index, data);
2034 }
2035
2036 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2037 match self.ex_data_mut(index) {
2038 Some(v) => {
2039 *v = data;
2040 (v as *mut T).cast()
2041 }
2042 _ => unsafe {
2043 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2044 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2045 data
2046 },
2047 }
2048 }
2049
2050 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2051 unsafe {
2052 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2053 if data.is_null() {
2054 None
2055 } else {
2056 Some(&mut *data.cast())
2057 }
2058 }
2059 }
2060
2061 #[corresponds(SSL_CTX_add_custom_ext)]
2065 #[cfg(ossl111)]
2066 pub fn add_custom_ext<AddFn, ParseFn, T>(
2067 &mut self,
2068 ext_type: u16,
2069 context: ExtensionContext,
2070 add_cb: AddFn,
2071 parse_cb: ParseFn,
2072 ) -> Result<(), ErrorStack>
2073 where
2074 AddFn: Fn(
2075 &mut SslRef,
2076 ExtensionContext,
2077 Option<(usize, &X509Ref)>,
2078 ) -> Result<Option<T>, SslAlert>
2079 + 'static
2080 + Sync
2081 + Send,
2082 T: AsRef<[u8]> + 'static + Sync + Send,
2083 ParseFn: Fn(
2084 &mut SslRef,
2085 ExtensionContext,
2086 &[u8],
2087 Option<(usize, &X509Ref)>,
2088 ) -> Result<(), SslAlert>
2089 + 'static
2090 + Sync
2091 + Send,
2092 {
2093 let ret = unsafe {
2094 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2095 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2096
2097 ffi::SSL_CTX_add_custom_ext(
2098 self.as_ptr(),
2099 ext_type as c_uint,
2100 context.bits(),
2101 Some(raw_custom_ext_add::<AddFn, T>),
2102 Some(raw_custom_ext_free::<T>),
2103 ptr::null_mut(),
2104 Some(raw_custom_ext_parse::<ParseFn>),
2105 ptr::null_mut(),
2106 )
2107 };
2108 if ret == 1 {
2109 Ok(())
2110 } else {
2111 Err(ErrorStack::get())
2112 }
2113 }
2114
2115 #[corresponds(SSL_CTX_set_max_early_data)]
2121 #[cfg(any(ossl111, libressl340))]
2122 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2123 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2124 Ok(())
2125 } else {
2126 Err(ErrorStack::get())
2127 }
2128 }
2129
2130 #[cfg(any(boringssl, awslc))]
2140 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2141 where
2142 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2143 {
2144 unsafe {
2145 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2146 ffi::SSL_CTX_set_select_certificate_cb(
2147 self.as_ptr(),
2148 Some(callbacks::raw_select_cert::<F>),
2149 );
2150 }
2151 }
2152
2153 #[corresponds(SSL_CTX_set_client_hello_cb)]
2157 #[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
2158 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2159 where
2160 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2161 {
2162 unsafe {
2163 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2164 ffi::SSL_CTX_set_client_hello_cb(
2165 self.as_ptr(),
2166 Some(callbacks::raw_client_hello::<F>),
2167 ptr,
2168 );
2169 }
2170 }
2171
2172 #[corresponds(SSL_CTX_set_info_callback)]
2175 pub fn set_info_callback<F>(&mut self, callback: F)
2176 where
2177 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2178 {
2179 unsafe {
2180 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2181 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2182 }
2183 }
2184
2185 #[corresponds(SSL_CTX_sess_set_cache_size)]
2189 #[allow(clippy::useless_conversion)]
2190 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2191 unsafe {
2192 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2193 }
2194 }
2195
2196 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2200 #[cfg(ossl102)]
2201 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2202 let sigalgs = CString::new(sigalgs).unwrap();
2203 unsafe {
2204 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2205 .map(|_| ())
2206 }
2207 }
2208
2209 #[corresponds(SSL_CTX_set1_groups_list)]
2213 #[cfg(any(ossl111, boringssl, libressl251, awslc))]
2214 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2215 let groups = CString::new(groups).unwrap();
2216 unsafe {
2217 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2218 }
2219 }
2220
2221 #[corresponds(SSL_CTX_set_num_tickets)]
2226 #[cfg(any(ossl111, boringssl, awslc))]
2227 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2228 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2229 }
2230
2231 #[corresponds(SSL_CTX_set_security_level)]
2236 #[cfg(any(ossl110, libressl360))]
2237 pub fn set_security_level(&mut self, level: u32) {
2238 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2239 }
2240
2241 pub fn build(self) -> SslContext {
2243 self.0
2244 }
2245}
2246
2247foreign_type_and_impl_send_sync! {
2248 type CType = ffi::SSL_CTX;
2249 fn drop = ffi::SSL_CTX_free;
2250
2251 pub struct SslContext;
2256
2257 pub struct SslContextRef;
2261}
2262
2263impl Clone for SslContext {
2264 fn clone(&self) -> Self {
2265 (**self).to_owned()
2266 }
2267}
2268
2269impl ToOwned for SslContextRef {
2270 type Owned = SslContext;
2271
2272 fn to_owned(&self) -> Self::Owned {
2273 unsafe {
2274 SSL_CTX_up_ref(self.as_ptr());
2275 SslContext::from_ptr(self.as_ptr())
2276 }
2277 }
2278}
2279
2280impl fmt::Debug for SslContext {
2282 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2283 write!(fmt, "SslContext")
2284 }
2285}
2286
2287impl SslContext {
2288 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2290 SslContextBuilder::new(method)
2291 }
2292
2293 #[corresponds(SSL_CTX_get_ex_new_index)]
2298 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2299 where
2300 T: 'static + Sync + Send,
2301 {
2302 unsafe {
2303 ffi::init();
2304 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2305 Ok(Index::from_raw(idx))
2306 }
2307 }
2308
2309 fn cached_ex_index<T>() -> Index<SslContext, T>
2311 where
2312 T: 'static + Sync + Send,
2313 {
2314 unsafe {
2315 let idx = *INDEXES
2316 .lock()
2317 .unwrap_or_else(|e| e.into_inner())
2318 .entry(TypeId::of::<T>())
2319 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2320 Index::from_raw(idx)
2321 }
2322 }
2323}
2324
2325impl SslContextRef {
2326 #[corresponds(SSL_CTX_get0_certificate)]
2330 #[cfg(any(ossl102, libressl270))]
2331 pub fn certificate(&self) -> Option<&X509Ref> {
2332 unsafe {
2333 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2334 X509Ref::from_const_ptr_opt(ptr)
2335 }
2336 }
2337
2338 #[corresponds(SSL_CTX_get0_privatekey)]
2342 #[cfg(any(ossl102, libressl340))]
2343 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2344 unsafe {
2345 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2346 PKeyRef::from_const_ptr_opt(ptr)
2347 }
2348 }
2349
2350 #[corresponds(SSL_CTX_get_cert_store)]
2352 pub fn cert_store(&self) -> &X509StoreRef {
2353 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2354 }
2355
2356 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2358 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2359 unsafe {
2360 let mut chain = ptr::null_mut();
2361 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2362 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2363 }
2364 }
2365
2366 #[corresponds(SSL_CTX_get_ex_data)]
2368 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2369 unsafe {
2370 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2371 if data.is_null() {
2372 None
2373 } else {
2374 Some(&*(data as *const T))
2375 }
2376 }
2377 }
2378
2379 #[corresponds(SSL_CTX_get_max_early_data)]
2383 #[cfg(any(ossl111, libressl340))]
2384 pub fn max_early_data(&self) -> u32 {
2385 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2386 }
2387
2388 #[corresponds(SSL_CTX_add_session)]
2397 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2398 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2399 }
2400
2401 #[corresponds(SSL_CTX_remove_session)]
2410 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2411 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2412 }
2413
2414 #[corresponds(SSL_CTX_sess_get_cache_size)]
2418 #[allow(clippy::unnecessary_cast)]
2419 pub fn session_cache_size(&self) -> i64 {
2420 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2421 }
2422
2423 #[corresponds(SSL_CTX_get_verify_mode)]
2427 pub fn verify_mode(&self) -> SslVerifyMode {
2428 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2429 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2430 }
2431
2432 #[corresponds(SSL_CTX_get_num_tickets)]
2437 #[cfg(ossl111)]
2438 pub fn num_tickets(&self) -> usize {
2439 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2440 }
2441
2442 #[corresponds(SSL_CTX_get_security_level)]
2447 #[cfg(any(ossl110, libressl360))]
2448 pub fn security_level(&self) -> u32 {
2449 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2450 }
2451}
2452
2453pub struct CipherBits {
2455 pub secret: i32,
2457
2458 pub algorithm: i32,
2460}
2461
2462pub struct SslCipher(*mut ffi::SSL_CIPHER);
2464
2465impl ForeignType for SslCipher {
2466 type CType = ffi::SSL_CIPHER;
2467 type Ref = SslCipherRef;
2468
2469 #[inline]
2470 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2471 SslCipher(ptr)
2472 }
2473
2474 #[inline]
2475 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2476 self.0
2477 }
2478}
2479
2480impl Stackable for SslCipher {
2481 type StackType = ffi::stack_st_SSL_CIPHER;
2482}
2483
2484impl Deref for SslCipher {
2485 type Target = SslCipherRef;
2486
2487 fn deref(&self) -> &SslCipherRef {
2488 unsafe { SslCipherRef::from_ptr(self.0) }
2489 }
2490}
2491
2492impl DerefMut for SslCipher {
2493 fn deref_mut(&mut self) -> &mut SslCipherRef {
2494 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2495 }
2496}
2497
2498pub struct SslCipherRef(Opaque);
2502
2503impl ForeignTypeRef for SslCipherRef {
2504 type CType = ffi::SSL_CIPHER;
2505}
2506
2507impl SslCipherRef {
2508 #[corresponds(SSL_CIPHER_get_name)]
2510 pub fn name(&self) -> &'static str {
2511 unsafe {
2512 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2513 CStr::from_ptr(ptr).to_str().unwrap()
2514 }
2515 }
2516
2517 #[corresponds(SSL_CIPHER_standard_name)]
2521 #[cfg(ossl111)]
2522 pub fn standard_name(&self) -> Option<&'static str> {
2523 unsafe {
2524 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2525 if ptr.is_null() {
2526 None
2527 } else {
2528 Some(CStr::from_ptr(ptr).to_str().unwrap())
2529 }
2530 }
2531 }
2532
2533 #[corresponds(SSL_CIPHER_get_version)]
2535 pub fn version(&self) -> &'static str {
2536 let version = unsafe {
2537 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2538 CStr::from_ptr(ptr as *const _)
2539 };
2540
2541 str::from_utf8(version.to_bytes()).unwrap()
2542 }
2543
2544 #[corresponds(SSL_CIPHER_get_bits)]
2546 #[allow(clippy::useless_conversion)]
2547 pub fn bits(&self) -> CipherBits {
2548 unsafe {
2549 let mut algo_bits = 0;
2550 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2551 CipherBits {
2552 secret: secret_bits.into(),
2553 algorithm: algo_bits.into(),
2554 }
2555 }
2556 }
2557
2558 #[corresponds(SSL_CIPHER_description)]
2560 pub fn description(&self) -> String {
2561 unsafe {
2562 let mut buf = [0; 128];
2564 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2565 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2566 }
2567 }
2568
2569 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2573 #[cfg(ossl111)]
2574 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2575 unsafe {
2576 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2577 if ptr.is_null() {
2578 None
2579 } else {
2580 Some(MessageDigest::from_ptr(ptr))
2581 }
2582 }
2583 }
2584
2585 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2589 #[cfg(any(ossl110, libressl270))]
2590 pub fn cipher_nid(&self) -> Option<Nid> {
2591 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2592 if n == 0 {
2593 None
2594 } else {
2595 Some(Nid::from_raw(n))
2596 }
2597 }
2598
2599 #[corresponds(SSL_CIPHER_get_protocol_id)]
2603 #[cfg(ossl111)]
2604 pub fn protocol_id(&self) -> [u8; 2] {
2605 unsafe {
2606 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2607 id.to_be_bytes()
2608 }
2609 }
2610}
2611
2612impl fmt::Debug for SslCipherRef {
2613 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2614 write!(fmt, "{}", self.name())
2615 }
2616}
2617
2618#[derive(Debug)]
2620pub struct CipherLists {
2621 pub suites: Stack<SslCipher>,
2622 pub signalling_suites: Stack<SslCipher>,
2623}
2624
2625foreign_type_and_impl_send_sync! {
2626 type CType = ffi::SSL_SESSION;
2627 fn drop = ffi::SSL_SESSION_free;
2628
2629 pub struct SslSession;
2633
2634 pub struct SslSessionRef;
2638}
2639
2640impl Clone for SslSession {
2641 fn clone(&self) -> SslSession {
2642 SslSessionRef::to_owned(self)
2643 }
2644}
2645
2646impl SslSession {
2647 from_der! {
2648 #[corresponds(d2i_SSL_SESSION)]
2650 from_der,
2651 SslSession,
2652 ffi::d2i_SSL_SESSION
2653 }
2654}
2655
2656impl ToOwned for SslSessionRef {
2657 type Owned = SslSession;
2658
2659 fn to_owned(&self) -> SslSession {
2660 unsafe {
2661 SSL_SESSION_up_ref(self.as_ptr());
2662 SslSession(self.as_ptr())
2663 }
2664 }
2665}
2666
2667impl SslSessionRef {
2668 #[corresponds(SSL_SESSION_get_id)]
2670 pub fn id(&self) -> &[u8] {
2671 unsafe {
2672 let mut len = 0;
2673 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2674 #[allow(clippy::unnecessary_cast)]
2675 util::from_raw_parts(p as *const u8, len as usize)
2676 }
2677 }
2678
2679 #[corresponds(SSL_SESSION_get_master_key)]
2681 pub fn master_key_len(&self) -> usize {
2682 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2683 }
2684
2685 #[corresponds(SSL_SESSION_get_master_key)]
2689 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2690 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2691 }
2692
2693 #[corresponds(SSL_SESSION_get_max_early_data)]
2697 #[cfg(any(ossl111, libressl340))]
2698 pub fn max_early_data(&self) -> u32 {
2699 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2700 }
2701
2702 #[corresponds(SSL_SESSION_get_time)]
2704 #[allow(clippy::useless_conversion)]
2705 pub fn time(&self) -> SslTimeTy {
2706 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2707 }
2708
2709 #[corresponds(SSL_SESSION_get_timeout)]
2713 #[allow(clippy::useless_conversion)]
2714 pub fn timeout(&self) -> i64 {
2715 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2716 }
2717
2718 #[corresponds(SSL_SESSION_get_protocol_version)]
2722 #[cfg(any(ossl110, libressl270))]
2723 pub fn protocol_version(&self) -> SslVersion {
2724 unsafe {
2725 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2726 SslVersion(version)
2727 }
2728 }
2729
2730 #[corresponds(SSL_SESSION_get_protocol_version)]
2732 #[cfg(any(boringssl, awslc))]
2733 pub fn protocol_version(&self) -> SslVersion {
2734 unsafe {
2735 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2736 SslVersion(version as _)
2737 }
2738 }
2739
2740 to_der! {
2741 #[corresponds(i2d_SSL_SESSION)]
2743 to_der,
2744 ffi::i2d_SSL_SESSION
2745 }
2746}
2747
2748foreign_type_and_impl_send_sync! {
2749 type CType = ffi::SSL;
2750 fn drop = ffi::SSL_free;
2751
2752 pub struct Ssl;
2759
2760 pub struct SslRef;
2764}
2765
2766impl fmt::Debug for Ssl {
2767 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2768 fmt::Debug::fmt(&**self, fmt)
2769 }
2770}
2771
2772impl Ssl {
2773 #[corresponds(SSL_get_ex_new_index)]
2778 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2779 where
2780 T: 'static + Sync + Send,
2781 {
2782 unsafe {
2783 ffi::init();
2784 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2785 Ok(Index::from_raw(idx))
2786 }
2787 }
2788
2789 fn cached_ex_index<T>() -> Index<Ssl, T>
2791 where
2792 T: 'static + Sync + Send,
2793 {
2794 unsafe {
2795 let idx = *SSL_INDEXES
2796 .lock()
2797 .unwrap_or_else(|e| e.into_inner())
2798 .entry(TypeId::of::<T>())
2799 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2800 Index::from_raw(idx)
2801 }
2802 }
2803
2804 #[corresponds(SSL_new)]
2806 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2807 let session_ctx_index = try_get_session_ctx_index()?;
2808 unsafe {
2809 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2810 let mut ssl = Ssl::from_ptr(ptr);
2811 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2812
2813 Ok(ssl)
2814 }
2815 }
2816
2817 #[corresponds(SSL_connect)]
2823 #[allow(deprecated)]
2824 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2825 where
2826 S: Read + Write,
2827 {
2828 SslStreamBuilder::new(self, stream).connect()
2829 }
2830
2831 #[corresponds(SSL_accept)]
2838 #[allow(deprecated)]
2839 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2840 where
2841 S: Read + Write,
2842 {
2843 SslStreamBuilder::new(self, stream).accept()
2844 }
2845}
2846
2847impl fmt::Debug for SslRef {
2848 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2849 fmt.debug_struct("Ssl")
2850 .field("state", &self.state_string_long())
2851 .field("verify_result", &self.verify_result())
2852 .finish()
2853 }
2854}
2855
2856impl SslRef {
2857 #[cfg(not(feature = "tongsuo"))]
2858 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2859 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2860 }
2861
2862 #[cfg(feature = "tongsuo")]
2863 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2864 unsafe {
2865 let bio = ffi::SSL_get_rbio(self.as_ptr());
2866 bio::find_correct_bio(bio)
2867 }
2868 }
2869
2870 fn get_error(&self, ret: c_int) -> ErrorCode {
2871 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2872 }
2873
2874 #[corresponds(SSL_set_mode)]
2878 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2879 unsafe {
2880 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2881 SslMode::from_bits_retain(bits)
2882 }
2883 }
2884
2885 #[corresponds(SSL_clear_mode)]
2887 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2888 unsafe {
2889 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2890 SslMode::from_bits_retain(bits)
2891 }
2892 }
2893
2894 #[corresponds(SSL_get_mode)]
2896 pub fn mode(&self) -> SslMode {
2897 unsafe {
2898 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2899 SslMode::from_bits_retain(bits)
2900 }
2901 }
2902
2903 #[corresponds(SSL_set_connect_state)]
2905 pub fn set_connect_state(&mut self) {
2906 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2907 }
2908
2909 #[corresponds(SSL_set_accept_state)]
2911 pub fn set_accept_state(&mut self) {
2912 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2913 }
2914
2915 #[cfg(any(boringssl, awslc))]
2916 #[corresponds(SSL_ech_accepted)]
2917 pub fn ech_accepted(&self) -> bool {
2918 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2919 }
2920
2921 #[cfg(tongsuo)]
2922 #[corresponds(SSL_is_ntls)]
2923 pub fn is_ntls(&mut self) -> bool {
2924 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2925 }
2926
2927 #[cfg(tongsuo)]
2928 #[corresponds(SSL_enable_ntls)]
2929 pub fn enable_ntls(&mut self) {
2930 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2931 }
2932
2933 #[cfg(tongsuo)]
2934 #[corresponds(SSL_disable_ntls)]
2935 pub fn disable_ntls(&mut self) {
2936 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2937 }
2938
2939 #[cfg(all(tongsuo, ossl300))]
2940 #[corresponds(SSL_enable_force_ntls)]
2941 pub fn enable_force_ntls(&mut self) {
2942 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2943 }
2944
2945 #[cfg(all(tongsuo, ossl300))]
2946 #[corresponds(SSL_disable_force_ntls)]
2947 pub fn disable_force_ntls(&mut self) {
2948 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2949 }
2950
2951 #[cfg(tongsuo)]
2952 #[corresponds(SSL_enable_sm_tls13_strict)]
2953 pub fn enable_sm_tls13_strict(&mut self) {
2954 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2955 }
2956
2957 #[cfg(tongsuo)]
2958 #[corresponds(SSL_disable_sm_tls13_strict)]
2959 pub fn disable_sm_tls13_strict(&mut self) {
2960 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2961 }
2962
2963 #[corresponds(SSL_set_verify)]
2967 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2968 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2969 }
2970
2971 #[corresponds(SSL_set_verify_mode)]
2973 pub fn verify_mode(&self) -> SslVerifyMode {
2974 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2975 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2976 }
2977
2978 #[corresponds(SSL_set_verify)]
2982 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2983 where
2984 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2985 {
2986 unsafe {
2987 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2989 ffi::SSL_set_verify(
2990 self.as_ptr(),
2991 mode.bits() as c_int,
2992 Some(ssl_raw_verify::<F>),
2993 );
2994 }
2995 }
2996
2997 #[corresponds(SSL_set_info_callback)]
3000 pub fn set_info_callback<F>(&mut self, callback: F)
3001 where
3002 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
3003 {
3004 unsafe {
3005 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3007 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
3008 }
3009 }
3010
3011 #[corresponds(SSL_set_dh_auto)]
3015 #[cfg(ossl300)]
3016 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3017 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3018 }
3019
3020 #[corresponds(SSL_set_tmp_dh)]
3024 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3025 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3026 }
3027
3028 #[corresponds(SSL_set_tmp_dh_callback)]
3032 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3033 where
3034 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3035 {
3036 unsafe {
3037 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3039 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3040 }
3041 }
3042
3043 #[corresponds(SSL_set_tmp_ecdh)]
3047 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3048 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3049 }
3050
3051 #[corresponds(SSL_set_ecdh_auto)]
3057 #[cfg(any(all(ossl102, not(ossl110)), libressl))]
3058 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3059 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3060 }
3061
3062 #[corresponds(SSL_set_alpn_protos)]
3068 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3069 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3070 unsafe {
3071 assert!(protocols.len() <= c_uint::MAX as usize);
3072 let r =
3073 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3074 if r == 0 {
3076 Ok(())
3077 } else {
3078 Err(ErrorStack::get())
3079 }
3080 }
3081 }
3082
3083 #[corresponds(SSL_get_current_cipher)]
3085 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3086 unsafe {
3087 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3088
3089 SslCipherRef::from_const_ptr_opt(ptr)
3090 }
3091 }
3092
3093 #[corresponds(SSL_state_string)]
3095 pub fn state_string(&self) -> &'static str {
3096 let state = unsafe {
3097 let ptr = ffi::SSL_state_string(self.as_ptr());
3098 CStr::from_ptr(ptr as *const _)
3099 };
3100
3101 str::from_utf8(state.to_bytes()).unwrap()
3102 }
3103
3104 #[corresponds(SSL_state_string_long)]
3106 pub fn state_string_long(&self) -> &'static str {
3107 let state = unsafe {
3108 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3109 CStr::from_ptr(ptr as *const _)
3110 };
3111
3112 str::from_utf8(state.to_bytes()).unwrap()
3113 }
3114
3115 #[corresponds(SSL_set_tlsext_host_name)]
3119 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3120 let cstr = CString::new(hostname).unwrap();
3121 unsafe {
3122 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3123 .map(|_| ())
3124 }
3125 }
3126
3127 #[corresponds(SSL_get_peer_certificate)]
3129 pub fn peer_certificate(&self) -> Option<X509> {
3130 unsafe {
3131 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3132 X509::from_ptr_opt(ptr)
3133 }
3134 }
3135
3136 #[corresponds(SSL_get_peer_cert_chain)]
3141 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3142 unsafe {
3143 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3144 StackRef::from_const_ptr_opt(ptr)
3145 }
3146 }
3147
3148 #[corresponds(SSL_get0_verified_chain)]
3158 #[cfg(ossl110)]
3159 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3160 unsafe {
3161 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3162 StackRef::from_const_ptr_opt(ptr)
3163 }
3164 }
3165
3166 #[corresponds(SSL_get_certificate)]
3168 pub fn certificate(&self) -> Option<&X509Ref> {
3169 unsafe {
3170 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3171 X509Ref::from_const_ptr_opt(ptr)
3172 }
3173 }
3174
3175 #[corresponds(SSL_get_privatekey)]
3179 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3180 unsafe {
3181 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3182 PKeyRef::from_const_ptr_opt(ptr)
3183 }
3184 }
3185
3186 #[corresponds(SSL_version)]
3188 pub fn version2(&self) -> Option<SslVersion> {
3189 unsafe {
3190 let r = ffi::SSL_version(self.as_ptr());
3191 if r == 0 {
3192 None
3193 } else {
3194 Some(SslVersion(r))
3195 }
3196 }
3197 }
3198
3199 #[corresponds(SSL_get_version)]
3201 pub fn version_str(&self) -> &'static str {
3202 let version = unsafe {
3203 let ptr = ffi::SSL_get_version(self.as_ptr());
3204 CStr::from_ptr(ptr as *const _)
3205 };
3206
3207 str::from_utf8(version.to_bytes()).unwrap()
3208 }
3209
3210 #[corresponds(SSL_get0_alpn_selected)]
3217 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3218 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3219 unsafe {
3220 let mut data: *const c_uchar = ptr::null();
3221 let mut len: c_uint = 0;
3222 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3225
3226 if data.is_null() {
3227 None
3228 } else {
3229 Some(util::from_raw_parts(data, len as usize))
3230 }
3231 }
3232 }
3233
3234 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3236 #[corresponds(SSL_set_tlsext_use_srtp)]
3237 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3238 unsafe {
3239 let cstr = CString::new(protocols).unwrap();
3240
3241 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3242 if r == 0 {
3244 Ok(())
3245 } else {
3246 Err(ErrorStack::get())
3247 }
3248 }
3249 }
3250
3251 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3255 #[corresponds(SSL_get_srtp_profiles)]
3256 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3257 unsafe {
3258 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3259
3260 StackRef::from_const_ptr_opt(chain)
3261 }
3262 }
3263
3264 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3268 #[corresponds(SSL_get_selected_srtp_profile)]
3269 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3270 unsafe {
3271 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3272
3273 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3274 }
3275 }
3276
3277 #[corresponds(SSL_pending)]
3282 pub fn pending(&self) -> usize {
3283 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3284 }
3285
3286 #[corresponds(SSL_get_servername)]
3299 pub fn servername(&self, type_: NameType) -> Option<&str> {
3301 self.servername_raw(type_)
3302 .and_then(|b| str::from_utf8(b).ok())
3303 }
3304
3305 #[corresponds(SSL_get_servername)]
3313 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3314 unsafe {
3315 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3316 if name.is_null() {
3317 None
3318 } else {
3319 Some(CStr::from_ptr(name as *const _).to_bytes())
3320 }
3321 }
3322 }
3323
3324 #[corresponds(SSL_set_SSL_CTX)]
3328 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3329 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3330 }
3331
3332 #[corresponds(SSL_get_SSL_CTX)]
3334 pub fn ssl_context(&self) -> &SslContextRef {
3335 unsafe {
3336 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3337 SslContextRef::from_ptr(ssl_ctx)
3338 }
3339 }
3340
3341 #[corresponds(SSL_get0_param)]
3345 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
3346 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3347 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3348 }
3349
3350 #[corresponds(SSL_get_verify_result)]
3352 pub fn verify_result(&self) -> X509VerifyResult {
3353 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3354 }
3355
3356 #[corresponds(SSL_get_session)]
3358 pub fn session(&self) -> Option<&SslSessionRef> {
3359 unsafe {
3360 let p = ffi::SSL_get_session(self.as_ptr());
3361 SslSessionRef::from_const_ptr_opt(p)
3362 }
3363 }
3364
3365 #[corresponds(SSL_get_client_random)]
3372 #[cfg(any(ossl110, libressl270))]
3373 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3374 unsafe {
3375 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3376 }
3377 }
3378
3379 #[corresponds(SSL_get_server_random)]
3386 #[cfg(any(ossl110, libressl270))]
3387 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3388 unsafe {
3389 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3390 }
3391 }
3392
3393 #[corresponds(SSL_export_keying_material)]
3395 pub fn export_keying_material(
3396 &self,
3397 out: &mut [u8],
3398 label: &str,
3399 context: Option<&[u8]>,
3400 ) -> Result<(), ErrorStack> {
3401 unsafe {
3402 let (context, contextlen, use_context) = match context {
3403 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3404 None => (ptr::null(), 0, 0),
3405 };
3406 cvt(ffi::SSL_export_keying_material(
3407 self.as_ptr(),
3408 out.as_mut_ptr() as *mut c_uchar,
3409 out.len(),
3410 label.as_ptr() as *const c_char,
3411 label.len(),
3412 context,
3413 contextlen,
3414 use_context,
3415 ))
3416 .map(|_| ())
3417 }
3418 }
3419
3420 #[corresponds(SSL_export_keying_material_early)]
3427 #[cfg(ossl111)]
3428 pub fn export_keying_material_early(
3429 &self,
3430 out: &mut [u8],
3431 label: &str,
3432 context: &[u8],
3433 ) -> Result<(), ErrorStack> {
3434 unsafe {
3435 cvt(ffi::SSL_export_keying_material_early(
3436 self.as_ptr(),
3437 out.as_mut_ptr() as *mut c_uchar,
3438 out.len(),
3439 label.as_ptr() as *const c_char,
3440 label.len(),
3441 context.as_ptr() as *const c_uchar,
3442 context.len(),
3443 ))
3444 .map(|_| ())
3445 }
3446 }
3447
3448 #[corresponds(SSL_set_session)]
3459 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3460 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3461 }
3462
3463 #[corresponds(SSL_session_reused)]
3465 pub fn session_reused(&self) -> bool {
3466 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3467 }
3468
3469 #[cfg(any(boringssl, awslc))]
3477 pub fn enable_ocsp_stapling(&mut self) {
3478 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3479 }
3480
3481 #[cfg(any(boringssl, awslc))]
3489 pub fn enable_signed_cert_timestamps(&mut self) {
3490 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3491 }
3492
3493 #[cfg(any(boringssl, awslc))]
3501 pub fn set_permute_extensions(&mut self, enabled: bool) {
3502 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3503 }
3504
3505 #[corresponds(SSL_enable_ct)]
3507 #[cfg(ossl111)]
3508 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3509 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3510 }
3511
3512 #[corresponds(SSL_ct_is_enabled)]
3514 #[cfg(ossl111)]
3515 pub fn ct_is_enabled(&self) -> bool {
3516 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3517 }
3518
3519 #[corresponds(SSL_set_tlsext_status_type)]
3521 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3522 unsafe {
3523 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3524 }
3525 }
3526
3527 #[corresponds(SSL_get_extms_support)]
3531 #[cfg(ossl110)]
3532 pub fn extms_support(&self) -> Option<bool> {
3533 unsafe {
3534 match ffi::SSL_get_extms_support(self.as_ptr()) {
3535 -1 => None,
3536 ret => Some(ret != 0),
3537 }
3538 }
3539 }
3540
3541 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3543 #[cfg(not(any(boringssl, awslc)))]
3544 pub fn ocsp_status(&self) -> Option<&[u8]> {
3545 unsafe {
3546 let mut p = ptr::null_mut();
3547 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3548
3549 if len < 0 {
3550 None
3551 } else {
3552 Some(util::from_raw_parts(p as *const u8, len as usize))
3553 }
3554 }
3555 }
3556
3557 #[corresponds(SSL_get0_ocsp_response)]
3559 #[cfg(any(boringssl, awslc))]
3560 pub fn ocsp_status(&self) -> Option<&[u8]> {
3561 unsafe {
3562 let mut p = ptr::null();
3563 let mut len: usize = 0;
3564 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3565
3566 if len == 0 {
3567 None
3568 } else {
3569 Some(util::from_raw_parts(p as *const u8, len))
3570 }
3571 }
3572 }
3573
3574 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3576 #[cfg(not(any(boringssl, awslc)))]
3577 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3578 unsafe {
3579 assert!(response.len() <= c_int::MAX as usize);
3580 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3581 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3582 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3583 self.as_ptr(),
3584 p as *mut c_uchar,
3585 response.len() as c_long,
3586 ) as c_int)
3587 .map(|_| ())
3588 .map_err(|e| {
3589 ffi::OPENSSL_free(p);
3590 e
3591 })
3592 }
3593 }
3594
3595 #[corresponds(SSL_set_ocsp_response)]
3597 #[cfg(any(boringssl, awslc))]
3598 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3599 unsafe {
3600 cvt(ffi::SSL_set_ocsp_response(
3601 self.as_ptr(),
3602 response.as_ptr(),
3603 response.len(),
3604 ))
3605 .map(|_| ())
3606 }
3607 }
3608
3609 #[corresponds(SSL_is_server)]
3611 pub fn is_server(&self) -> bool {
3612 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3613 }
3614
3615 #[corresponds(SSL_set_ex_data)]
3621 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3622 match self.ex_data_mut(index) {
3623 Some(v) => *v = data,
3624 None => unsafe {
3625 let data = Box::new(data);
3626 ffi::SSL_set_ex_data(
3627 self.as_ptr(),
3628 index.as_raw(),
3629 Box::into_raw(data) as *mut c_void,
3630 );
3631 },
3632 }
3633 }
3634
3635 #[corresponds(SSL_get_ex_data)]
3637 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3638 unsafe {
3639 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3640 if data.is_null() {
3641 None
3642 } else {
3643 Some(&*(data as *const T))
3644 }
3645 }
3646 }
3647
3648 #[corresponds(SSL_get_ex_data)]
3650 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3651 unsafe {
3652 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3653 if data.is_null() {
3654 None
3655 } else {
3656 Some(&mut *(data as *mut T))
3657 }
3658 }
3659 }
3660
3661 #[corresponds(SSL_set_max_early_data)]
3665 #[cfg(any(ossl111, libressl340))]
3666 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3667 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3668 Ok(())
3669 } else {
3670 Err(ErrorStack::get())
3671 }
3672 }
3673
3674 #[corresponds(SSL_get_max_early_data)]
3678 #[cfg(any(ossl111, libressl340))]
3679 pub fn max_early_data(&self) -> u32 {
3680 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3681 }
3682
3683 #[corresponds(SSL_get_finished)]
3688 pub fn finished(&self, buf: &mut [u8]) -> usize {
3689 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3690 }
3691
3692 #[corresponds(SSL_get_peer_finished)]
3698 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3699 unsafe {
3700 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3701 }
3702 }
3703
3704 #[corresponds(SSL_is_init_finished)]
3706 #[cfg(ossl110)]
3707 pub fn is_init_finished(&self) -> bool {
3708 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3709 }
3710
3711 #[corresponds(SSL_client_hello_isv2)]
3717 #[cfg(ossl111)]
3718 pub fn client_hello_isv2(&self) -> bool {
3719 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3720 }
3721
3722 #[corresponds(SSL_client_hello_get0_legacy_version)]
3728 #[cfg(ossl111)]
3729 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3730 unsafe {
3731 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3732 if version == 0 {
3733 None
3734 } else {
3735 Some(SslVersion(version as c_int))
3736 }
3737 }
3738 }
3739
3740 #[corresponds(SSL_client_hello_get0_random)]
3746 #[cfg(ossl111)]
3747 pub fn client_hello_random(&self) -> Option<&[u8]> {
3748 unsafe {
3749 let mut ptr = ptr::null();
3750 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3751 if len == 0 {
3752 None
3753 } else {
3754 Some(util::from_raw_parts(ptr, len))
3755 }
3756 }
3757 }
3758
3759 #[corresponds(SSL_client_hello_get0_session_id)]
3765 #[cfg(ossl111)]
3766 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3767 unsafe {
3768 let mut ptr = ptr::null();
3769 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3770 if len == 0 {
3771 None
3772 } else {
3773 Some(util::from_raw_parts(ptr, len))
3774 }
3775 }
3776 }
3777
3778 #[corresponds(SSL_client_hello_get0_ciphers)]
3784 #[cfg(ossl111)]
3785 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3786 unsafe {
3787 let mut ptr = ptr::null();
3788 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3789 if len == 0 {
3790 None
3791 } else {
3792 Some(util::from_raw_parts(ptr, len))
3793 }
3794 }
3795 }
3796
3797 #[cfg(ossl111)]
3803 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3804 unsafe {
3805 let mut ptr = ptr::null();
3806 let mut len = 0usize;
3807 let r = ffi::SSL_client_hello_get0_ext(
3808 self.as_ptr(),
3809 ext_type.as_raw() as _,
3810 &mut ptr,
3811 &mut len,
3812 );
3813 if r == 0 {
3814 None
3815 } else {
3816 Some(util::from_raw_parts(ptr, len))
3817 }
3818 }
3819 }
3820
3821 #[corresponds(SSL_bytes_to_cipher_list)]
3826 #[cfg(ossl111)]
3827 pub fn bytes_to_cipher_list(
3828 &self,
3829 bytes: &[u8],
3830 isv2format: bool,
3831 ) -> Result<CipherLists, ErrorStack> {
3832 unsafe {
3833 let ptr = bytes.as_ptr();
3834 let len = bytes.len();
3835 let mut sk = ptr::null_mut();
3836 let mut scsvs = ptr::null_mut();
3837 let res = ffi::SSL_bytes_to_cipher_list(
3838 self.as_ptr(),
3839 ptr,
3840 len,
3841 isv2format as c_int,
3842 &mut sk,
3843 &mut scsvs,
3844 );
3845 if res == 1 {
3846 Ok(CipherLists {
3847 suites: Stack::from_ptr(sk),
3848 signalling_suites: Stack::from_ptr(scsvs),
3849 })
3850 } else {
3851 Err(ErrorStack::get())
3852 }
3853 }
3854 }
3855
3856 #[corresponds(SSL_client_hello_get0_compression_methods)]
3862 #[cfg(ossl111)]
3863 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3864 unsafe {
3865 let mut ptr = ptr::null();
3866 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3867 if len == 0 {
3868 None
3869 } else {
3870 Some(util::from_raw_parts(ptr, len))
3871 }
3872 }
3873 }
3874
3875 #[corresponds(SSL_set_mtu)]
3877 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3878 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3879 }
3880
3881 #[corresponds(SSL_get_psk_identity_hint)]
3885 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3886 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3887 unsafe {
3888 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3889 if ptr.is_null() {
3890 None
3891 } else {
3892 Some(CStr::from_ptr(ptr).to_bytes())
3893 }
3894 }
3895 }
3896
3897 #[corresponds(SSL_get_psk_identity)]
3899 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3900 pub fn psk_identity(&self) -> Option<&[u8]> {
3901 unsafe {
3902 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3903 if ptr.is_null() {
3904 None
3905 } else {
3906 Some(CStr::from_ptr(ptr).to_bytes())
3907 }
3908 }
3909 }
3910
3911 #[corresponds(SSL_add0_chain_cert)]
3912 #[cfg(any(ossl102, libressl291, boringssl, awslc))]
3913 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3914 unsafe {
3915 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3916 mem::forget(chain);
3917 }
3918 Ok(())
3919 }
3920
3921 #[cfg(not(any(boringssl, awslc)))]
3923 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3924 unsafe {
3925 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3926 };
3927 Ok(())
3928 }
3929
3930 #[corresponds(SSL_use_Private_Key_file)]
3932 pub fn set_private_key_file<P: AsRef<Path>>(
3933 &mut self,
3934 path: P,
3935 ssl_file_type: SslFiletype,
3936 ) -> Result<(), ErrorStack> {
3937 let p = path.as_ref().as_os_str().to_str().unwrap();
3938 let key_file = CString::new(p).unwrap();
3939 unsafe {
3940 cvt(ffi::SSL_use_PrivateKey_file(
3941 self.as_ptr(),
3942 key_file.as_ptr(),
3943 ssl_file_type.as_raw(),
3944 ))?;
3945 };
3946 Ok(())
3947 }
3948
3949 #[corresponds(SSL_use_PrivateKey)]
3951 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3952 unsafe {
3953 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3954 };
3955 Ok(())
3956 }
3957
3958 #[cfg(tongsuo)]
3959 #[corresponds(SSL_use_enc_Private_Key_file)]
3960 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3961 &mut self,
3962 path: P,
3963 ssl_file_type: SslFiletype,
3964 ) -> Result<(), ErrorStack> {
3965 let p = path.as_ref().as_os_str().to_str().unwrap();
3966 let key_file = CString::new(p).unwrap();
3967 unsafe {
3968 cvt(ffi::SSL_use_enc_PrivateKey_file(
3969 self.as_ptr(),
3970 key_file.as_ptr(),
3971 ssl_file_type.as_raw(),
3972 ))?;
3973 };
3974 Ok(())
3975 }
3976
3977 #[cfg(tongsuo)]
3978 #[corresponds(SSL_use_enc_PrivateKey)]
3979 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3980 unsafe {
3981 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3982 };
3983 Ok(())
3984 }
3985
3986 #[cfg(tongsuo)]
3987 #[corresponds(SSL_use_sign_Private_Key_file)]
3988 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3989 &mut self,
3990 path: P,
3991 ssl_file_type: SslFiletype,
3992 ) -> Result<(), ErrorStack> {
3993 let p = path.as_ref().as_os_str().to_str().unwrap();
3994 let key_file = CString::new(p).unwrap();
3995 unsafe {
3996 cvt(ffi::SSL_use_sign_PrivateKey_file(
3997 self.as_ptr(),
3998 key_file.as_ptr(),
3999 ssl_file_type.as_raw(),
4000 ))?;
4001 };
4002 Ok(())
4003 }
4004
4005 #[cfg(tongsuo)]
4006 #[corresponds(SSL_use_sign_PrivateKey)]
4007 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
4008 unsafe {
4009 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
4010 };
4011 Ok(())
4012 }
4013
4014 #[corresponds(SSL_use_certificate)]
4016 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4017 unsafe {
4018 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4019 };
4020 Ok(())
4021 }
4022
4023 #[cfg(tongsuo)]
4024 #[corresponds(SSL_use_enc_certificate)]
4025 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4026 unsafe {
4027 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4028 };
4029 Ok(())
4030 }
4031
4032 #[cfg(tongsuo)]
4033 #[corresponds(SSL_use_sign_certificate)]
4034 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4035 unsafe {
4036 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4037 };
4038 Ok(())
4039 }
4040
4041 #[corresponds(SSL_use_certificate_chain_file)]
4047 #[cfg(any(ossl110, libressl332))]
4048 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4049 &mut self,
4050 path: P,
4051 ) -> Result<(), ErrorStack> {
4052 let p = path.as_ref().as_os_str().to_str().unwrap();
4053 let cert_file = CString::new(p).unwrap();
4054 unsafe {
4055 cvt(ffi::SSL_use_certificate_chain_file(
4056 self.as_ptr(),
4057 cert_file.as_ptr(),
4058 ))?;
4059 };
4060 Ok(())
4061 }
4062
4063 #[corresponds(SSL_add_client_CA)]
4065 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4066 unsafe {
4067 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4068 };
4069 Ok(())
4070 }
4071
4072 #[corresponds(SSL_set_client_CA_list)]
4074 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4075 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4076 mem::forget(list);
4077 }
4078
4079 #[corresponds(SSL_set_min_proto_version)]
4086 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4087 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4088 unsafe {
4089 cvt(ffi::SSL_set_min_proto_version(
4090 self.as_ptr(),
4091 version.map_or(0, |v| v.0 as _),
4092 ))
4093 .map(|_| ())
4094 }
4095 }
4096
4097 #[corresponds(SSL_set_max_proto_version)]
4104 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4105 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4106 unsafe {
4107 cvt(ffi::SSL_set_max_proto_version(
4108 self.as_ptr(),
4109 version.map_or(0, |v| v.0 as _),
4110 ))
4111 .map(|_| ())
4112 }
4113 }
4114
4115 #[corresponds(SSL_set_ciphersuites)]
4124 #[cfg(any(ossl111, libressl340))]
4125 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4126 let cipher_list = CString::new(cipher_list).unwrap();
4127 unsafe {
4128 cvt(ffi::SSL_set_ciphersuites(
4129 self.as_ptr(),
4130 cipher_list.as_ptr() as *const _,
4131 ))
4132 .map(|_| ())
4133 }
4134 }
4135
4136 #[corresponds(SSL_set_cipher_list)]
4144 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4145 let cipher_list = CString::new(cipher_list).unwrap();
4146 unsafe {
4147 cvt(ffi::SSL_set_cipher_list(
4148 self.as_ptr(),
4149 cipher_list.as_ptr() as *const _,
4150 ))
4151 .map(|_| ())
4152 }
4153 }
4154
4155 #[corresponds(SSL_set_cert_store)]
4157 #[cfg(any(ossl102, boringssl, awslc))]
4158 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4159 unsafe {
4160 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4161 mem::forget(cert_store);
4162 Ok(())
4163 }
4164 }
4165
4166 #[corresponds(SSL_set_num_tickets)]
4171 #[cfg(ossl111)]
4172 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4173 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4174 }
4175
4176 #[corresponds(SSL_get_num_tickets)]
4181 #[cfg(ossl111)]
4182 pub fn num_tickets(&self) -> usize {
4183 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4184 }
4185
4186 #[corresponds(SSL_set_security_level)]
4191 #[cfg(any(ossl110, libressl360))]
4192 pub fn set_security_level(&mut self, level: u32) {
4193 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4194 }
4195
4196 #[corresponds(SSL_get_security_level)]
4201 #[cfg(any(ossl110, libressl360))]
4202 pub fn security_level(&self) -> u32 {
4203 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4204 }
4205
4206 #[corresponds(SSL_get_peer_tmp_key)]
4211 #[cfg(ossl300)]
4212 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4213 unsafe {
4214 let mut key = ptr::null_mut();
4215 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4216 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4217 Err(e) => Err(e),
4218 }
4219 }
4220 }
4221
4222 #[corresponds(SSL_get_tmp_key)]
4227 #[cfg(ossl300)]
4228 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4229 unsafe {
4230 let mut key = ptr::null_mut();
4231 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4232 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4233 Err(e) => Err(e),
4234 }
4235 }
4236 }
4237}
4238
4239#[derive(Debug)]
4241pub struct MidHandshakeSslStream<S> {
4242 stream: SslStream<S>,
4243 error: Error,
4244}
4245
4246impl<S> MidHandshakeSslStream<S> {
4247 pub fn get_ref(&self) -> &S {
4249 self.stream.get_ref()
4250 }
4251
4252 pub fn get_mut(&mut self) -> &mut S {
4254 self.stream.get_mut()
4255 }
4256
4257 pub fn ssl(&self) -> &SslRef {
4259 self.stream.ssl()
4260 }
4261
4262 pub fn ssl_mut(&mut self) -> &mut SslRef {
4264 self.stream.ssl_mut()
4265 }
4266
4267 pub fn error(&self) -> &Error {
4269 &self.error
4270 }
4271
4272 pub fn into_error(self) -> Error {
4274 self.error
4275 }
4276}
4277
4278impl<S> MidHandshakeSslStream<S>
4279where
4280 S: Read + Write,
4281{
4282 #[corresponds(SSL_do_handshake)]
4285 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4286 match self.stream.do_handshake() {
4287 Ok(()) => Ok(self.stream),
4288 Err(error) => {
4289 self.error = error;
4290 match self.error.code() {
4291 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4292 Err(HandshakeError::WouldBlock(self))
4293 }
4294 _ => Err(HandshakeError::Failure(self)),
4295 }
4296 }
4297 }
4298 }
4299}
4300
4301pub struct SslStream<S> {
4303 ssl: ManuallyDrop<Ssl>,
4304 method: ManuallyDrop<BioMethod>,
4305 _p: PhantomData<S>,
4306}
4307
4308impl<S> Drop for SslStream<S> {
4309 fn drop(&mut self) {
4310 unsafe {
4312 ManuallyDrop::drop(&mut self.ssl);
4313 ManuallyDrop::drop(&mut self.method);
4314 }
4315 }
4316}
4317
4318impl<S> fmt::Debug for SslStream<S>
4319where
4320 S: fmt::Debug,
4321{
4322 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4323 fmt.debug_struct("SslStream")
4324 .field("stream", &self.get_ref())
4325 .field("ssl", &self.ssl())
4326 .finish()
4327 }
4328}
4329
4330impl<S: Read + Write> SslStream<S> {
4331 #[corresponds(SSL_set_bio)]
4339 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4340 let (bio, method) = bio::new(stream)?;
4341 unsafe {
4342 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4343 }
4344
4345 Ok(SslStream {
4346 ssl: ManuallyDrop::new(ssl),
4347 method: ManuallyDrop::new(method),
4348 _p: PhantomData,
4349 })
4350 }
4351
4352 #[corresponds(SSL_read_early_data)]
4361 #[cfg(any(ossl111, libressl340))]
4362 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4363 let mut read = 0;
4364 let ret = unsafe {
4365 ffi::SSL_read_early_data(
4366 self.ssl.as_ptr(),
4367 buf.as_ptr() as *mut c_void,
4368 buf.len(),
4369 &mut read,
4370 )
4371 };
4372 match ret {
4373 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4374 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4375 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4376 _ => unreachable!(),
4377 }
4378 }
4379
4380 #[corresponds(SSL_write_early_data)]
4387 #[cfg(any(ossl111, libressl340))]
4388 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4389 let mut written = 0;
4390 let ret = unsafe {
4391 ffi::SSL_write_early_data(
4392 self.ssl.as_ptr(),
4393 buf.as_ptr() as *const c_void,
4394 buf.len(),
4395 &mut written,
4396 )
4397 };
4398 if ret > 0 {
4399 Ok(written)
4400 } else {
4401 Err(self.make_error(ret))
4402 }
4403 }
4404
4405 #[corresponds(SSL_connect)]
4412 pub fn connect(&mut self) -> Result<(), Error> {
4413 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4414 if ret > 0 {
4415 Ok(())
4416 } else {
4417 Err(self.make_error(ret))
4418 }
4419 }
4420
4421 #[corresponds(SSL_accept)]
4428 pub fn accept(&mut self) -> Result<(), Error> {
4429 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4430 if ret > 0 {
4431 Ok(())
4432 } else {
4433 Err(self.make_error(ret))
4434 }
4435 }
4436
4437 #[corresponds(SSL_do_handshake)]
4441 pub fn do_handshake(&mut self) -> Result<(), Error> {
4442 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4443 if ret > 0 {
4444 Ok(())
4445 } else {
4446 Err(self.make_error(ret))
4447 }
4448 }
4449
4450 #[corresponds(SSL_stateless)]
4461 #[cfg(ossl111)]
4462 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4463 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4464 1 => Ok(true),
4465 0 => Ok(false),
4466 -1 => Err(ErrorStack::get()),
4467 _ => unreachable!(),
4468 }
4469 }
4470
4471 #[corresponds(SSL_read_ex)]
4478 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4479 loop {
4480 match self.ssl_read_uninit(buf) {
4481 Ok(n) => return Ok(n),
4482 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4483 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4484 return Ok(0);
4485 }
4486 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4487 Err(e) => {
4488 return Err(e
4489 .into_io_error()
4490 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4491 }
4492 }
4493 }
4494 }
4495
4496 #[corresponds(SSL_read_ex)]
4501 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4502 unsafe {
4504 self.ssl_read_uninit(util::from_raw_parts_mut(
4505 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4506 buf.len(),
4507 ))
4508 }
4509 }
4510
4511 #[corresponds(SSL_read_ex)]
4518 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4519 cfg_if! {
4520 if #[cfg(any(ossl111, libressl350))] {
4521 let mut readbytes = 0;
4522 let ret = unsafe {
4523 ffi::SSL_read_ex(
4524 self.ssl().as_ptr(),
4525 buf.as_mut_ptr().cast(),
4526 buf.len(),
4527 &mut readbytes,
4528 )
4529 };
4530
4531 if ret > 0 {
4532 Ok(readbytes)
4533 } else {
4534 Err(self.make_error(ret))
4535 }
4536 } else {
4537 if buf.is_empty() {
4538 return Ok(0);
4539 }
4540
4541 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4542 let ret = unsafe {
4543 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4544 };
4545 if ret > 0 {
4546 Ok(ret as usize)
4547 } else {
4548 Err(self.make_error(ret))
4549 }
4550 }
4551 }
4552 }
4553
4554 #[corresponds(SSL_write_ex)]
4559 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4560 cfg_if! {
4561 if #[cfg(any(ossl111, libressl350))] {
4562 let mut written = 0;
4563 let ret = unsafe {
4564 ffi::SSL_write_ex(
4565 self.ssl().as_ptr(),
4566 buf.as_ptr().cast(),
4567 buf.len(),
4568 &mut written,
4569 )
4570 };
4571
4572 if ret > 0 {
4573 Ok(written)
4574 } else {
4575 Err(self.make_error(ret))
4576 }
4577 } else {
4578 if buf.is_empty() {
4579 return Ok(0);
4580 }
4581
4582 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4583 let ret = unsafe {
4584 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4585 };
4586 if ret > 0 {
4587 Ok(ret as usize)
4588 } else {
4589 Err(self.make_error(ret))
4590 }
4591 }
4592 }
4593 }
4594
4595 #[corresponds(SSL_peek_ex)]
4597 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4598 unsafe {
4600 self.ssl_peek_uninit(util::from_raw_parts_mut(
4601 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4602 buf.len(),
4603 ))
4604 }
4605 }
4606
4607 #[corresponds(SSL_peek_ex)]
4614 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4615 cfg_if! {
4616 if #[cfg(any(ossl111, libressl350))] {
4617 let mut readbytes = 0;
4618 let ret = unsafe {
4619 ffi::SSL_peek_ex(
4620 self.ssl().as_ptr(),
4621 buf.as_mut_ptr().cast(),
4622 buf.len(),
4623 &mut readbytes,
4624 )
4625 };
4626
4627 if ret > 0 {
4628 Ok(readbytes)
4629 } else {
4630 Err(self.make_error(ret))
4631 }
4632 } else {
4633 if buf.is_empty() {
4634 return Ok(0);
4635 }
4636
4637 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4638 let ret = unsafe {
4639 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4640 };
4641 if ret > 0 {
4642 Ok(ret as usize)
4643 } else {
4644 Err(self.make_error(ret))
4645 }
4646 }
4647 }
4648 }
4649
4650 #[corresponds(SSL_shutdown)]
4660 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4661 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4662 0 => Ok(ShutdownResult::Sent),
4663 1 => Ok(ShutdownResult::Received),
4664 n => Err(self.make_error(n)),
4665 }
4666 }
4667
4668 #[corresponds(SSL_get_shutdown)]
4670 pub fn get_shutdown(&mut self) -> ShutdownState {
4671 unsafe {
4672 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4673 ShutdownState::from_bits_retain(bits)
4674 }
4675 }
4676
4677 #[corresponds(SSL_set_shutdown)]
4682 pub fn set_shutdown(&mut self, state: ShutdownState) {
4683 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4684 }
4685}
4686
4687impl<S> SslStream<S> {
4688 fn make_error(&mut self, ret: c_int) -> Error {
4689 self.check_panic();
4690
4691 let code = self.ssl.get_error(ret);
4692
4693 let cause = match code {
4694 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4695 ErrorCode::SYSCALL => {
4696 let errs = ErrorStack::get();
4697 if errs.errors().is_empty() {
4698 self.get_bio_error().map(InnerError::Io)
4699 } else {
4700 Some(InnerError::Ssl(errs))
4701 }
4702 }
4703 ErrorCode::ZERO_RETURN => None,
4704 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4705 self.get_bio_error().map(InnerError::Io)
4706 }
4707 _ => None,
4708 };
4709
4710 Error { code, cause }
4711 }
4712
4713 fn check_panic(&mut self) {
4714 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4715 resume_unwind(err)
4716 }
4717 }
4718
4719 fn get_bio_error(&mut self) -> Option<io::Error> {
4720 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4721 }
4722
4723 pub fn get_ref(&self) -> &S {
4725 unsafe {
4726 let bio = self.ssl.get_raw_rbio();
4727 bio::get_ref(bio)
4728 }
4729 }
4730
4731 pub fn get_mut(&mut self) -> &mut S {
4738 unsafe {
4739 let bio = self.ssl.get_raw_rbio();
4740 bio::get_mut(bio)
4741 }
4742 }
4743
4744 pub fn ssl(&self) -> &SslRef {
4746 &self.ssl
4747 }
4748
4749 pub fn ssl_mut(&mut self) -> &mut SslRef {
4751 &mut self.ssl
4752 }
4753}
4754
4755impl<S: Read + Write> Read for SslStream<S> {
4756 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4757 unsafe {
4759 self.read_uninit(util::from_raw_parts_mut(
4760 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4761 buf.len(),
4762 ))
4763 }
4764 }
4765}
4766
4767impl<S: Read + Write> Write for SslStream<S> {
4768 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4769 loop {
4770 match self.ssl_write(buf) {
4771 Ok(n) => return Ok(n),
4772 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4773 Err(e) => {
4774 return Err(e
4775 .into_io_error()
4776 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4777 }
4778 }
4779 }
4780 }
4781
4782 fn flush(&mut self) -> io::Result<()> {
4783 self.get_mut().flush()
4784 }
4785}
4786
4787#[deprecated(
4789 since = "0.10.32",
4790 note = "use the methods directly on Ssl/SslStream instead"
4791)]
4792pub struct SslStreamBuilder<S> {
4793 inner: SslStream<S>,
4794}
4795
4796#[allow(deprecated)]
4797impl<S> SslStreamBuilder<S>
4798where
4799 S: Read + Write,
4800{
4801 pub fn new(ssl: Ssl, stream: S) -> Self {
4803 Self {
4804 inner: SslStream::new(ssl, stream).unwrap(),
4805 }
4806 }
4807
4808 #[corresponds(SSL_stateless)]
4819 #[cfg(ossl111)]
4820 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4821 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4822 1 => Ok(true),
4823 0 => Ok(false),
4824 -1 => Err(ErrorStack::get()),
4825 _ => unreachable!(),
4826 }
4827 }
4828
4829 #[corresponds(SSL_set_connect_state)]
4831 pub fn set_connect_state(&mut self) {
4832 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4833 }
4834
4835 #[corresponds(SSL_set_accept_state)]
4837 pub fn set_accept_state(&mut self) {
4838 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4839 }
4840
4841 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4843 match self.inner.connect() {
4844 Ok(()) => Ok(self.inner),
4845 Err(error) => match error.code() {
4846 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4847 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4848 stream: self.inner,
4849 error,
4850 }))
4851 }
4852 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4853 stream: self.inner,
4854 error,
4855 })),
4856 },
4857 }
4858 }
4859
4860 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4862 match self.inner.accept() {
4863 Ok(()) => Ok(self.inner),
4864 Err(error) => match error.code() {
4865 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4866 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4867 stream: self.inner,
4868 error,
4869 }))
4870 }
4871 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4872 stream: self.inner,
4873 error,
4874 })),
4875 },
4876 }
4877 }
4878
4879 #[corresponds(SSL_do_handshake)]
4883 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4884 match self.inner.do_handshake() {
4885 Ok(()) => Ok(self.inner),
4886 Err(error) => match error.code() {
4887 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4888 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4889 stream: self.inner,
4890 error,
4891 }))
4892 }
4893 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4894 stream: self.inner,
4895 error,
4896 })),
4897 },
4898 }
4899 }
4900
4901 #[corresponds(SSL_read_early_data)]
4911 #[cfg(any(ossl111, libressl340))]
4912 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4913 self.inner.read_early_data(buf)
4914 }
4915
4916 #[corresponds(SSL_write_early_data)]
4923 #[cfg(any(ossl111, libressl340))]
4924 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4925 self.inner.write_early_data(buf)
4926 }
4927}
4928
4929#[allow(deprecated)]
4930impl<S> SslStreamBuilder<S> {
4931 pub fn get_ref(&self) -> &S {
4933 unsafe {
4934 let bio = self.inner.ssl.get_raw_rbio();
4935 bio::get_ref(bio)
4936 }
4937 }
4938
4939 pub fn get_mut(&mut self) -> &mut S {
4946 unsafe {
4947 let bio = self.inner.ssl.get_raw_rbio();
4948 bio::get_mut(bio)
4949 }
4950 }
4951
4952 pub fn ssl(&self) -> &SslRef {
4954 &self.inner.ssl
4955 }
4956
4957 pub fn ssl_mut(&mut self) -> &mut SslRef {
4959 &mut self.inner.ssl
4960 }
4961}
4962
4963#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4965pub enum ShutdownResult {
4966 Sent,
4968
4969 Received,
4971}
4972
4973bitflags! {
4974 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4976 #[repr(transparent)]
4977 pub struct ShutdownState: c_int {
4978 const SENT = ffi::SSL_SENT_SHUTDOWN;
4980 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4982 }
4983}
4984
4985cfg_if! {
4986 if #[cfg(any(boringssl, ossl110, libressl273, awslc))] {
4987 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4988 } else {
4989 #[allow(bad_style)]
4990 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4991 ffi::CRYPTO_add_lock(
4992 &mut (*ssl).references,
4993 1,
4994 ffi::CRYPTO_LOCK_SSL_CTX,
4995 "mod.rs\0".as_ptr() as *const _,
4996 line!() as c_int,
4997 );
4998 0
4999 }
5000
5001 #[allow(bad_style)]
5002 pub unsafe fn SSL_SESSION_get_master_key(
5003 session: *const ffi::SSL_SESSION,
5004 out: *mut c_uchar,
5005 mut outlen: usize,
5006 ) -> usize {
5007 if outlen == 0 {
5008 return (*session).master_key_length as usize;
5009 }
5010 if outlen > (*session).master_key_length as usize {
5011 outlen = (*session).master_key_length as usize;
5012 }
5013 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
5014 outlen
5015 }
5016
5017 #[allow(bad_style)]
5018 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
5019 (*s).server
5020 }
5021
5022 #[allow(bad_style)]
5023 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
5024 ffi::CRYPTO_add_lock(
5025 &mut (*ses).references,
5026 1,
5027 ffi::CRYPTO_LOCK_SSL_CTX,
5028 "mod.rs\0".as_ptr() as *const _,
5029 line!() as c_int,
5030 );
5031 0
5032 }
5033 }
5034}
5035
5036cfg_if! {
5037 if #[cfg(ossl300)] {
5038 use ffi::SSL_get1_peer_certificate;
5039 } else {
5040 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
5041 }
5042}
5043cfg_if! {
5044 if #[cfg(any(boringssl, ossl110, libressl291, awslc))] {
5045 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
5046 } else {
5047 use ffi::{
5048 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
5049 SSLv23_server_method as TLS_server_method,
5050 };
5051 }
5052}
5053cfg_if! {
5054 if #[cfg(ossl110)] {
5055 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5056 ffi::CRYPTO_get_ex_new_index(
5057 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5058 0,
5059 ptr::null_mut(),
5060 None,
5061 None,
5062 f,
5063 )
5064 }
5065
5066 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5067 ffi::CRYPTO_get_ex_new_index(
5068 ffi::CRYPTO_EX_INDEX_SSL,
5069 0,
5070 ptr::null_mut(),
5071 None,
5072 None,
5073 f,
5074 )
5075 }
5076 } else {
5077 use std::sync::Once;
5078
5079 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5080 static ONCE: Once = Once::new();
5082 ONCE.call_once(|| {
5083 cfg_if! {
5084 if #[cfg(not(any(boringssl, awslc)))] {
5085 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5086 } else {
5087 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5088 }
5089 }
5090 });
5091
5092 cfg_if! {
5093 if #[cfg(not(any(boringssl, awslc)))] {
5094 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5095 } else {
5096 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5097 }
5098 }
5099 }
5100
5101 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5102 static ONCE: Once = Once::new();
5104 ONCE.call_once(|| {
5105 #[cfg(not(any(boringssl, awslc)))]
5106 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5107 #[cfg(any(boringssl, awslc))]
5108 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5109 });
5110
5111 #[cfg(not(any(boringssl, awslc)))]
5112 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5113 #[cfg(any(boringssl, awslc))]
5114 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5115 }
5116 }
5117}