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, libressl))]
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};
86use crate::x509::verify::X509VerifyParamRef;
87use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
88use crate::{cvt, cvt_n, cvt_p, init};
89use bitflags::bitflags;
90use cfg_if::cfg_if;
91use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
92use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
93use openssl_macros::corresponds;
94use std::any::TypeId;
95use std::collections::HashMap;
96use std::ffi::{CStr, CString};
97use std::fmt;
98use std::io;
99use std::io::prelude::*;
100use std::marker::PhantomData;
101use std::mem::{self, ManuallyDrop, MaybeUninit};
102use std::ops::{Deref, DerefMut};
103use std::panic::resume_unwind;
104use std::path::Path;
105use std::ptr;
106use std::str;
107use std::sync::{Arc, LazyLock, Mutex, OnceLock};
108
109pub use crate::ssl::connector::{
110 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
111};
112pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
113
114mod bio;
115mod callbacks;
116#[cfg(any(boringssl, awslc))]
117mod client_hello;
118mod connector;
119mod error;
120#[cfg(test)]
121mod test;
122
123#[cfg(any(boringssl, awslc))]
124pub use client_hello::ClientHello;
125
126#[corresponds(OPENSSL_cipher_name)]
132#[cfg(ossl111)]
133pub fn cipher_name(std_name: &str) -> &'static str {
134 unsafe {
135 ffi::init();
136
137 let s = CString::new(std_name).unwrap();
138 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
139 CStr::from_ptr(ptr).to_str().unwrap()
140 }
141}
142
143cfg_if! {
144 if #[cfg(ossl300)] {
145 type SslOptionsRepr = u64;
146 } else if #[cfg(any(boringssl, awslc))] {
147 type SslOptionsRepr = u32;
148 } else {
149 type SslOptionsRepr = libc::c_ulong;
150 }
151}
152
153bitflags! {
154 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
156 #[repr(transparent)]
157 pub struct SslOptions: SslOptionsRepr {
158 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
160
161 #[cfg(ossl300)]
164 const IGNORE_UNEXPECTED_EOF = ffi::SSL_OP_IGNORE_UNEXPECTED_EOF as SslOptionsRepr;
165
166 #[cfg(not(any(boringssl, awslc)))]
168 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
169
170 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
174
175 #[cfg(not(any(boringssl, awslc)))]
181 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
182
183 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
185
186 #[cfg(not(any(boringssl, awslc)))]
188 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
189 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
190
191 #[cfg(not(any(boringssl, awslc)))]
193 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
194
195 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
198 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
199
200 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
204
205 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
209
210 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
214
215 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
217
218 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
220
221 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
223
224 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
226
227 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
229
230 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
232
233 #[cfg(any(ossl111, boringssl, libressl, awslc))]
237 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
238
239 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
241
242 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
244
245 #[cfg(ossl110)]
261 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
262
263 #[cfg(any(boringssl, ossl110h, awslc))]
267 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
268
269 #[cfg(ossl111)]
274 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
275
276 #[cfg(ossl111)]
288 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
289 }
290}
291
292bitflags! {
293 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
295 #[repr(transparent)]
296 pub struct SslMode: SslBitType {
297 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
303
304 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
307
308 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
318
319 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
325
326 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
330
331 #[cfg(not(libressl))]
339 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
340
341 #[cfg(ossl110)]
348 const ASYNC = ffi::SSL_MODE_ASYNC;
349 }
350}
351
352#[derive(Copy, Clone)]
354pub struct SslMethod(*const ffi::SSL_METHOD);
355
356impl SslMethod {
357 #[corresponds(TLS_method)]
359 pub fn tls() -> SslMethod {
360 unsafe { SslMethod(TLS_method()) }
361 }
362
363 #[corresponds(DTLS_method)]
365 pub fn dtls() -> SslMethod {
366 unsafe { SslMethod(DTLS_method()) }
367 }
368
369 #[corresponds(TLS_client_method)]
371 pub fn tls_client() -> SslMethod {
372 unsafe { SslMethod(TLS_client_method()) }
373 }
374
375 #[corresponds(TLS_server_method)]
377 pub fn tls_server() -> SslMethod {
378 unsafe { SslMethod(TLS_server_method()) }
379 }
380
381 #[cfg(tongsuo)]
382 #[corresponds(NTLS_client_method)]
383 pub fn ntls_client() -> SslMethod {
384 unsafe { SslMethod(ffi::NTLS_client_method()) }
385 }
386
387 #[cfg(tongsuo)]
388 #[corresponds(NTLS_server_method)]
389 pub fn ntls_server() -> SslMethod {
390 unsafe { SslMethod(ffi::NTLS_server_method()) }
391 }
392
393 #[corresponds(DTLS_client_method)]
395 pub fn dtls_client() -> SslMethod {
396 unsafe { SslMethod(DTLS_client_method()) }
397 }
398
399 #[corresponds(DTLS_server_method)]
401 pub fn dtls_server() -> SslMethod {
402 unsafe { SslMethod(DTLS_server_method()) }
403 }
404
405 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
411 SslMethod(ptr)
412 }
413
414 #[allow(clippy::trivially_copy_pass_by_ref)]
416 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
417 self.0
418 }
419}
420
421unsafe impl Sync for SslMethod {}
422unsafe impl Send for SslMethod {}
423
424bitflags! {
425 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
427 #[repr(transparent)]
428 pub struct SslVerifyMode: i32 {
429 const PEER = ffi::SSL_VERIFY_PEER;
433
434 const NONE = ffi::SSL_VERIFY_NONE;
440
441 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
445 }
446}
447
448#[cfg(any(boringssl, awslc))]
449type SslBitType = c_int;
450#[cfg(not(any(boringssl, awslc)))]
451type SslBitType = c_long;
452
453#[cfg(any(boringssl, awslc))]
454type SslTimeTy = u64;
455#[cfg(not(any(boringssl, awslc)))]
456type SslTimeTy = c_long;
457
458bitflags! {
459 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
461 #[repr(transparent)]
462 pub struct SslSessionCacheMode: SslBitType {
463 const OFF = ffi::SSL_SESS_CACHE_OFF;
465
466 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
473
474 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
478
479 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
481
482 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
484
485 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
487
488 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
490
491 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
493 }
494}
495
496#[cfg(ossl111)]
497bitflags! {
498 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
500 #[repr(transparent)]
501 pub struct ExtensionContext: c_uint {
502 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
504 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
506 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
508 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
510 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
512 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
514 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
516 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
517 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
519 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
520 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
521 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
522 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
523 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
524 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
525 }
526}
527
528#[derive(Copy, Clone)]
530pub struct TlsExtType(c_uint);
531
532impl TlsExtType {
533 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
537
538 pub const ALPN: TlsExtType =
542 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
543
544 pub fn from_raw(raw: c_uint) -> TlsExtType {
546 TlsExtType(raw)
547 }
548
549 #[allow(clippy::trivially_copy_pass_by_ref)]
551 pub fn as_raw(&self) -> c_uint {
552 self.0
553 }
554}
555
556#[derive(Copy, Clone)]
558pub struct SslFiletype(c_int);
559
560impl SslFiletype {
561 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
565
566 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
570
571 pub fn from_raw(raw: c_int) -> SslFiletype {
573 SslFiletype(raw)
574 }
575
576 #[allow(clippy::trivially_copy_pass_by_ref)]
578 pub fn as_raw(&self) -> c_int {
579 self.0
580 }
581}
582
583#[derive(Copy, Clone)]
585pub struct StatusType(c_int);
586
587impl StatusType {
588 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
590
591 pub fn from_raw(raw: c_int) -> StatusType {
593 StatusType(raw)
594 }
595
596 #[allow(clippy::trivially_copy_pass_by_ref)]
598 pub fn as_raw(&self) -> c_int {
599 self.0
600 }
601}
602
603#[derive(Copy, Clone)]
605pub struct NameType(c_int);
606
607impl NameType {
608 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
610
611 pub fn from_raw(raw: c_int) -> StatusType {
613 StatusType(raw)
614 }
615
616 #[allow(clippy::trivially_copy_pass_by_ref)]
618 pub fn as_raw(&self) -> c_int {
619 self.0
620 }
621}
622
623static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
624 LazyLock::new(|| Mutex::new(HashMap::new()));
625static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
626 LazyLock::new(|| Mutex::new(HashMap::new()));
627static SESSION_CTX_INDEX: OnceLock<Index<Ssl, SslContext>> = OnceLock::new();
628
629fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
630 if let Some(idx) = SESSION_CTX_INDEX.get() {
633 return Ok(idx);
634 }
635 let new = Ssl::new_ex_index::<SslContext>()?;
636 Ok(SESSION_CTX_INDEX.get_or_init(|| new))
637}
638
639unsafe extern "C" fn free_data_box<T>(
640 _parent: *mut c_void,
641 ptr: *mut c_void,
642 _ad: *mut ffi::CRYPTO_EX_DATA,
643 _idx: c_int,
644 _argl: c_long,
645 _argp: *mut c_void,
646) {
647 if !ptr.is_null() {
648 let _ = Box::<T>::from_raw(ptr as *mut T);
649 }
650}
651
652#[derive(Debug, Copy, Clone, PartialEq, Eq)]
654pub struct SniError(c_int);
655
656impl SniError {
657 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
659
660 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
662
663 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
664}
665
666#[derive(Debug, Copy, Clone, PartialEq, Eq)]
668pub struct SslAlert(c_int);
669
670impl SslAlert {
671 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
673 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
674 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
675 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
676}
677
678#[derive(Debug, Copy, Clone, PartialEq, Eq)]
682pub struct AlpnError(c_int);
683
684impl AlpnError {
685 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
687
688 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
690}
691
692#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
696#[derive(Debug, Copy, Clone, PartialEq, Eq)]
697pub struct ClientHelloError(c_int);
698
699#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
700impl ClientHelloError {
701 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
703
704 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
706}
707
708#[derive(Debug, Copy, Clone, PartialEq, Eq)]
710pub struct TicketKeyStatus(c_int);
711
712impl TicketKeyStatus {
713 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
715 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
717 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
719}
720
721#[derive(Debug, Copy, Clone, PartialEq, Eq)]
723#[cfg(any(boringssl, awslc))]
724pub struct SelectCertError(ffi::ssl_select_cert_result_t);
725
726#[cfg(any(boringssl, awslc))]
727impl SelectCertError {
728 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
730
731 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
733
734 #[cfg(boringssl)]
740 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
741}
742
743#[cfg(ossl111)]
745#[derive(Debug, Copy, Clone, PartialEq, Eq)]
746pub struct SslCtValidationMode(c_int);
747
748#[cfg(ossl111)]
749impl SslCtValidationMode {
750 pub const PERMISSIVE: SslCtValidationMode =
751 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
752 pub const STRICT: SslCtValidationMode =
753 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
754}
755
756#[derive(Debug, Copy, Clone, PartialEq, Eq)]
758pub struct CertCompressionAlgorithm(c_int);
759
760impl CertCompressionAlgorithm {
761 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
762 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
763 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
764}
765
766#[derive(Debug, Copy, Clone, PartialEq, Eq)]
768pub struct SslVersion(c_int);
769
770impl SslVersion {
771 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
773
774 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
776
777 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
779
780 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
782
783 #[cfg(any(ossl111, libressl, boringssl, awslc))]
787 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
788
789 #[cfg(tongsuo)]
790 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
791
792 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
796
797 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
801}
802
803cfg_if! {
804 if #[cfg(any(boringssl, awslc))] {
805 type SslCacheTy = i64;
806 type SslCacheSize = libc::c_ulong;
807 type MtuTy = u32;
808 type ModeTy = u32;
809 type SizeTy = usize;
810 } else {
811 type SslCacheTy = i64;
812 type SslCacheSize = c_long;
813 type MtuTy = c_long;
814 type ModeTy = c_long;
815 type SizeTy = u32;
816 }
817}
818
819#[corresponds(SSL_select_next_proto)]
830pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
831 unsafe {
832 let mut out = ptr::null_mut();
833 let mut outlen = 0;
834 let r = ffi::SSL_select_next_proto(
835 &mut out,
836 &mut outlen,
837 server.as_ptr(),
838 server.len() as c_uint,
839 client.as_ptr(),
840 client.len() as c_uint,
841 );
842 if r == ffi::OPENSSL_NPN_NEGOTIATED {
843 Some(util::from_raw_parts(out as *const u8, outlen as usize))
844 } else {
845 None
846 }
847 }
848}
849
850pub struct SslContextBuilder(SslContext);
852
853impl SslContextBuilder {
854 #[corresponds(SSL_CTX_new)]
856 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
857 unsafe {
858 init();
859 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
860
861 Ok(SslContextBuilder::from_ptr(ctx))
862 }
863 }
864
865 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
871 SslContextBuilder(SslContext::from_ptr(ctx))
872 }
873
874 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
876 self.0.as_ptr()
877 }
878
879 #[cfg(tongsuo)]
880 #[corresponds(SSL_CTX_enable_ntls)]
881 pub fn enable_ntls(&mut self) {
882 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
883 }
884
885 #[cfg(tongsuo)]
886 #[corresponds(SSL_CTX_disable_ntls)]
887 pub fn disable_ntls(&mut self) {
888 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
889 }
890
891 #[cfg(all(tongsuo, ossl300))]
892 #[corresponds(SSL_CTX_enable_force_ntls)]
893 pub fn enable_force_ntls(&mut self) {
894 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
895 }
896
897 #[cfg(all(tongsuo, ossl300))]
898 #[corresponds(SSL_CTX_disable_force_ntls)]
899 pub fn disable_force_ntls(&mut self) {
900 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
901 }
902
903 #[cfg(tongsuo)]
904 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
905 pub fn enable_sm_tls13_strict(&mut self) {
906 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
907 }
908
909 #[cfg(tongsuo)]
910 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
911 pub fn disable_sm_tls13_strict(&mut self) {
912 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
913 }
914
915 #[corresponds(SSL_CTX_set_verify)]
917 pub fn set_verify(&mut self, mode: SslVerifyMode) {
918 unsafe {
919 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
920 }
921 }
922
923 #[corresponds(SSL_CTX_set_verify)]
930 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
931 where
932 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
933 {
934 unsafe {
935 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
936 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
937 }
938 }
939
940 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
948 pub fn set_servername_callback<F>(&mut self, callback: F)
950 where
951 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
952 {
953 unsafe {
954 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
960 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
961 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
962 }
963 }
964
965 #[corresponds(SSL_CTX_set_verify_depth)]
969 pub fn set_verify_depth(&mut self, depth: u32) {
970 unsafe {
971 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
972 }
973 }
974
975 #[corresponds(SSL_CTX_set0_verify_cert_store)]
979 #[cfg(any(ossl110, boringssl, awslc))]
980 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
981 unsafe {
982 let ptr = cert_store.as_ptr();
983 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
984 mem::forget(cert_store);
985
986 Ok(())
987 }
988 }
989
990 #[corresponds(SSL_CTX_set_cert_store)]
992 pub fn set_cert_store(&mut self, cert_store: X509Store) {
993 unsafe {
994 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
995 mem::forget(cert_store);
996 }
997 }
998
999 #[corresponds(SSL_CTX_set_read_ahead)]
1006 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1007 unsafe {
1008 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1009 }
1010 }
1011
1012 #[corresponds(SSL_CTX_set_mode)]
1016 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1017 unsafe {
1018 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1019 SslMode::from_bits_retain(bits)
1020 }
1021 }
1022
1023 #[corresponds(SSL_CTX_clear_mode)]
1025 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1026 unsafe {
1027 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1028 SslMode::from_bits_retain(bits)
1029 }
1030 }
1031
1032 #[corresponds(SSL_CTX_get_mode)]
1034 pub fn mode(&self) -> SslMode {
1035 unsafe {
1036 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1037 SslMode::from_bits_retain(bits)
1038 }
1039 }
1040
1041 #[corresponds(SSL_CTX_set_dh_auto)]
1050 #[cfg(ossl300)]
1051 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1052 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
1053 }
1054
1055 #[corresponds(SSL_CTX_set_tmp_dh)]
1057 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1058 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1059 }
1060
1061 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1068 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1069 where
1070 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1071 {
1072 unsafe {
1073 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1074
1075 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1076 }
1077 }
1078
1079 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1081 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1082 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1083 }
1084
1085 #[corresponds(SSL_CTX_set_default_verify_paths)]
1090 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1091 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1092 }
1093
1094 #[corresponds(SSL_CTX_load_verify_locations)]
1098 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1099 self.load_verify_locations(Some(file.as_ref()), None)
1100 }
1101
1102 #[corresponds(SSL_CTX_load_verify_locations)]
1104 pub fn load_verify_locations(
1105 &mut self,
1106 ca_file: Option<&Path>,
1107 ca_path: Option<&Path>,
1108 ) -> Result<(), ErrorStack> {
1109 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1110 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1111 unsafe {
1112 cvt(ffi::SSL_CTX_load_verify_locations(
1113 self.as_ptr(),
1114 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1115 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1116 ))
1117 .map(|_| ())
1118 }
1119 }
1120
1121 #[corresponds(SSL_CTX_set_client_CA_list)]
1126 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1127 unsafe {
1128 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1129 mem::forget(list);
1130 }
1131 }
1132
1133 #[corresponds(SSL_CTX_add_client_CA)]
1136 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1137 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1138 }
1139
1140 #[corresponds(SSL_CTX_set_session_id_context)]
1149 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1150 unsafe {
1151 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1152 cvt(ffi::SSL_CTX_set_session_id_context(
1153 self.as_ptr(),
1154 sid_ctx.as_ptr(),
1155 sid_ctx.len() as SizeTy,
1156 ))
1157 .map(|_| ())
1158 }
1159 }
1160
1161 #[corresponds(SSL_CTX_use_certificate_file)]
1167 pub fn set_certificate_file<P: AsRef<Path>>(
1168 &mut self,
1169 file: P,
1170 file_type: SslFiletype,
1171 ) -> Result<(), ErrorStack> {
1172 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1173 unsafe {
1174 cvt(ffi::SSL_CTX_use_certificate_file(
1175 self.as_ptr(),
1176 file.as_ptr() as *const _,
1177 file_type.as_raw(),
1178 ))
1179 .map(|_| ())
1180 }
1181 }
1182
1183 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1189 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1190 &mut self,
1191 file: P,
1192 ) -> Result<(), ErrorStack> {
1193 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1194 unsafe {
1195 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1196 self.as_ptr(),
1197 file.as_ptr() as *const _,
1198 ))
1199 .map(|_| ())
1200 }
1201 }
1202
1203 #[corresponds(SSL_CTX_use_certificate)]
1207 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1208 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1209 }
1210
1211 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1216 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1217 unsafe {
1218 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1219 mem::forget(cert);
1220 Ok(())
1221 }
1222 }
1223
1224 #[cfg(tongsuo)]
1225 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1226 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1227 &mut self,
1228 file: P,
1229 file_type: SslFiletype,
1230 ) -> Result<(), ErrorStack> {
1231 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1232 unsafe {
1233 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1234 self.as_ptr(),
1235 file.as_ptr() as *const _,
1236 file_type.as_raw(),
1237 ))
1238 .map(|_| ())
1239 }
1240 }
1241
1242 #[cfg(tongsuo)]
1243 #[corresponds(SSL_CTX_use_enc_certificate)]
1244 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1245 unsafe {
1246 cvt(ffi::SSL_CTX_use_enc_certificate(
1247 self.as_ptr(),
1248 cert.as_ptr(),
1249 ))
1250 .map(|_| ())
1251 }
1252 }
1253
1254 #[cfg(tongsuo)]
1255 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1256 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1257 &mut self,
1258 file: P,
1259 file_type: SslFiletype,
1260 ) -> Result<(), ErrorStack> {
1261 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1262 unsafe {
1263 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1264 self.as_ptr(),
1265 file.as_ptr() as *const _,
1266 file_type.as_raw(),
1267 ))
1268 .map(|_| ())
1269 }
1270 }
1271
1272 #[cfg(tongsuo)]
1273 #[corresponds(SSL_CTX_use_sign_certificate)]
1274 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1275 unsafe {
1276 cvt(ffi::SSL_CTX_use_sign_certificate(
1277 self.as_ptr(),
1278 cert.as_ptr(),
1279 ))
1280 .map(|_| ())
1281 }
1282 }
1283
1284 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1286 pub fn set_private_key_file<P: AsRef<Path>>(
1287 &mut self,
1288 file: P,
1289 file_type: SslFiletype,
1290 ) -> Result<(), ErrorStack> {
1291 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1292 unsafe {
1293 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1294 self.as_ptr(),
1295 file.as_ptr() as *const _,
1296 file_type.as_raw(),
1297 ))
1298 .map(|_| ())
1299 }
1300 }
1301
1302 #[corresponds(SSL_CTX_use_PrivateKey)]
1304 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1305 where
1306 T: HasPrivate,
1307 {
1308 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1309 }
1310
1311 #[cfg(tongsuo)]
1312 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1313 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1314 &mut self,
1315 file: P,
1316 file_type: SslFiletype,
1317 ) -> Result<(), ErrorStack> {
1318 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1319 unsafe {
1320 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1321 self.as_ptr(),
1322 file.as_ptr() as *const _,
1323 file_type.as_raw(),
1324 ))
1325 .map(|_| ())
1326 }
1327 }
1328
1329 #[cfg(tongsuo)]
1330 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1331 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1332 where
1333 T: HasPrivate,
1334 {
1335 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1336 }
1337
1338 #[cfg(tongsuo)]
1339 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1340 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1341 &mut self,
1342 file: P,
1343 file_type: SslFiletype,
1344 ) -> Result<(), ErrorStack> {
1345 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1346 unsafe {
1347 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1348 self.as_ptr(),
1349 file.as_ptr() as *const _,
1350 file_type.as_raw(),
1351 ))
1352 .map(|_| ())
1353 }
1354 }
1355
1356 #[cfg(tongsuo)]
1357 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1358 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1359 where
1360 T: HasPrivate,
1361 {
1362 unsafe {
1363 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1364 self.as_ptr(),
1365 key.as_ptr(),
1366 ))
1367 .map(|_| ())
1368 }
1369 }
1370
1371 #[corresponds(SSL_CTX_set_cipher_list)]
1379 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1380 let cipher_list = CString::new(cipher_list).unwrap();
1381 unsafe {
1382 cvt(ffi::SSL_CTX_set_cipher_list(
1383 self.as_ptr(),
1384 cipher_list.as_ptr() as *const _,
1385 ))
1386 .map(|_| ())
1387 }
1388 }
1389
1390 #[corresponds(SSL_CTX_set_ciphersuites)]
1399 #[cfg(any(ossl111, libressl, awslc))]
1400 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1401 let cipher_list = CString::new(cipher_list).unwrap();
1402 unsafe {
1403 cvt(ffi::SSL_CTX_set_ciphersuites(
1404 self.as_ptr(),
1405 cipher_list.as_ptr() as *const _,
1406 ))
1407 .map(|_| ())
1408 }
1409 }
1410
1411 #[corresponds(SSL_CTX_set_ecdh_auto)]
1415 #[cfg(libressl)]
1416 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1417 unsafe {
1418 cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ())
1419 }
1420 }
1421
1422 #[corresponds(SSL_CTX_set_options)]
1429 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1430 let bits =
1431 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1432 SslOptions::from_bits_retain(bits)
1433 }
1434
1435 #[corresponds(SSL_CTX_get_options)]
1437 pub fn options(&self) -> SslOptions {
1438 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1439 SslOptions::from_bits_retain(bits)
1440 }
1441
1442 #[corresponds(SSL_CTX_clear_options)]
1444 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1445 let bits =
1446 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1447 SslOptions::from_bits_retain(bits)
1448 }
1449
1450 #[corresponds(SSL_CTX_set_min_proto_version)]
1455 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1456 unsafe {
1457 cvt(ffi::SSL_CTX_set_min_proto_version(
1458 self.as_ptr(),
1459 version.map_or(0, |v| v.0 as _),
1460 ))
1461 .map(|_| ())
1462 }
1463 }
1464
1465 #[corresponds(SSL_CTX_set_max_proto_version)]
1470 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1471 unsafe {
1472 cvt(ffi::SSL_CTX_set_max_proto_version(
1473 self.as_ptr(),
1474 version.map_or(0, |v| v.0 as _),
1475 ))
1476 .map(|_| ())
1477 }
1478 }
1479
1480 #[corresponds(SSL_CTX_get_min_proto_version)]
1487 #[cfg(any(ossl110g, libressl))]
1488 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1489 unsafe {
1490 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1491 if r == 0 {
1492 None
1493 } else {
1494 Some(SslVersion(r))
1495 }
1496 }
1497 }
1498
1499 #[corresponds(SSL_CTX_get_max_proto_version)]
1506 #[cfg(any(ossl110g, libressl))]
1507 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1508 unsafe {
1509 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1510 if r == 0 {
1511 None
1512 } else {
1513 Some(SslVersion(r))
1514 }
1515 }
1516 }
1517
1518 #[corresponds(SSL_CTX_set_alpn_protos)]
1527 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1528 unsafe {
1529 assert!(protocols.len() <= c_uint::MAX as usize);
1530 let r = ffi::SSL_CTX_set_alpn_protos(
1531 self.as_ptr(),
1532 protocols.as_ptr(),
1533 protocols.len() as _,
1534 );
1535 if r == 0 {
1537 Ok(())
1538 } else {
1539 Err(ErrorStack::get())
1540 }
1541 }
1542 }
1543
1544 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1546 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1547 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1548 unsafe {
1549 let cstr = CString::new(protocols).unwrap();
1550
1551 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1552 if r == 0 {
1554 Ok(())
1555 } else {
1556 Err(ErrorStack::get())
1557 }
1558 }
1559 }
1560
1561 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1572 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1573 where
1574 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1575 {
1576 unsafe {
1577 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1578 ffi::SSL_CTX_set_alpn_select_cb(
1579 self.as_ptr(),
1580 Some(callbacks::raw_alpn_select::<F>),
1581 ptr::null_mut(),
1582 );
1583 }
1584 }
1585
1586 #[corresponds(SSL_CTX_check_private_key)]
1588 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1589 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1590 }
1591
1592 #[corresponds(SSL_CTX_get_cert_store)]
1594 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1595 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1596 }
1597
1598 #[corresponds(SSL_CTX_get_cert_store)]
1600 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1601 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1602 }
1603
1604 #[corresponds(SSL_CTX_get0_param)]
1608 pub fn verify_param(&self) -> &X509VerifyParamRef {
1609 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1610 }
1611
1612 #[corresponds(SSL_CTX_get0_param)]
1616 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1617 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1618 }
1619
1620 #[cfg(any(boringssl, tongsuo, awslc))]
1628 pub fn add_cert_decompression_alg<F>(
1629 &mut self,
1630 alg_id: CertCompressionAlgorithm,
1631 decompress: F,
1632 ) -> Result<(), ErrorStack>
1633 where
1634 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1635 {
1636 unsafe {
1637 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1638 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1639 self.as_ptr(),
1640 alg_id.0 as _,
1641 None,
1642 Some(raw_cert_decompression::<F>),
1643 ))
1644 .map(|_| ())
1645 }
1646 }
1647
1648 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1650 #[cfg(ossl320)]
1651 pub fn set_cert_comp_preference(
1652 &mut self,
1653 algs: &[CertCompressionAlgorithm],
1654 ) -> Result<(), ErrorStack> {
1655 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1656 unsafe {
1657 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1658 self.as_ptr(),
1659 algs.as_mut_ptr(),
1660 algs.len(),
1661 ))
1662 .map(|_| ())
1663 }
1664 }
1665
1666 #[cfg(any(boringssl, awslc))]
1674 pub fn enable_ocsp_stapling(&mut self) {
1675 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1676 }
1677
1678 #[cfg(any(boringssl, awslc))]
1686 pub fn enable_signed_cert_timestamps(&mut self) {
1687 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1688 }
1689
1690 #[cfg(any(boringssl, awslc))]
1698 pub fn set_grease_enabled(&mut self, enabled: bool) {
1699 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1700 }
1701
1702 #[cfg(any(boringssl, awslc))]
1710 pub fn set_permute_extensions(&mut self, enabled: bool) {
1711 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1712 }
1713
1714 #[corresponds(SSL_CTX_enable_ct)]
1716 #[cfg(ossl111)]
1717 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1718 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1719 }
1720
1721 #[corresponds(SSL_CTX_ct_is_enabled)]
1723 #[cfg(ossl111)]
1724 pub fn ct_is_enabled(&self) -> bool {
1725 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1726 }
1727
1728 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1730 #[cfg(not(any(boringssl, awslc)))]
1731 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1732 unsafe {
1733 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1734 .map(|_| ())
1735 }
1736 }
1737
1738 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1751 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1752 where
1753 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1754 {
1755 unsafe {
1756 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1757 cvt(
1758 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1759 as c_int,
1760 )
1761 .map(|_| ())
1762 }
1763 }
1764
1765 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1766 #[cfg(ossl300)]
1767 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1768 where
1769 F: Fn(
1770 &mut SslRef,
1771 &mut [u8],
1772 &mut [u8],
1773 &mut CipherCtxRef,
1774 &mut MacCtxRef,
1775 bool,
1776 ) -> Result<TicketKeyStatus, ErrorStack>
1777 + 'static
1778 + Sync
1779 + Send,
1780 {
1781 unsafe {
1782 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1783 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1784 self.as_ptr(),
1785 Some(raw_tlsext_ticket_key_evp::<F>),
1786 ) as c_int)
1787 .map(|_| ())
1788 }
1789 }
1790
1791 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1792 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1793 where
1794 F: Fn(
1795 &mut SslRef,
1796 &mut [u8],
1797 &mut [u8],
1798 &mut CipherCtxRef,
1799 &mut HMacCtxRef,
1800 bool,
1801 ) -> Result<TicketKeyStatus, ErrorStack>
1802 + 'static
1803 + Sync
1804 + Send,
1805 {
1806 unsafe {
1807 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1808 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1809 self.as_ptr(),
1810 Some(raw_tlsext_ticket_key::<F>),
1811 ) as c_int)
1812 .map(|_| ())
1813 }
1814 }
1815
1816 #[corresponds(SSL_CTX_set_psk_client_callback)]
1822 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1823 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1824 where
1825 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1826 + 'static
1827 + Sync
1828 + Send,
1829 {
1830 unsafe {
1831 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1832 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1833 }
1834 }
1835
1836 #[corresponds(SSL_CTX_set_psk_server_callback)]
1842 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1843 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1844 where
1845 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1846 + 'static
1847 + Sync
1848 + Send,
1849 {
1850 unsafe {
1851 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1852 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1853 }
1854 }
1855
1856 #[corresponds(SSL_CTX_sess_set_new_cb)]
1870 pub fn set_new_session_callback<F>(&mut self, callback: F)
1871 where
1872 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1873 {
1874 unsafe {
1875 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1876 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1877 }
1878 }
1879
1880 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1884 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1885 where
1886 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1887 {
1888 unsafe {
1889 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1890 ffi::SSL_CTX_sess_set_remove_cb(
1891 self.as_ptr(),
1892 Some(callbacks::raw_remove_session::<F>),
1893 );
1894 }
1895 }
1896
1897 #[corresponds(SSL_CTX_sess_set_get_cb)]
1908 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1909 where
1910 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1911 {
1912 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1913 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1914 }
1915
1916 #[corresponds(SSL_CTX_set_keylog_callback)]
1924 #[cfg(any(ossl111, boringssl, awslc))]
1925 pub fn set_keylog_callback<F>(&mut self, callback: F)
1926 where
1927 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1928 {
1929 unsafe {
1930 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1931 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1932 }
1933 }
1934
1935 #[corresponds(SSL_CTX_set_session_cache_mode)]
1939 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1940 unsafe {
1941 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1942 SslSessionCacheMode::from_bits_retain(bits)
1943 }
1944 }
1945
1946 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1952 #[cfg(ossl111)]
1953 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1954 where
1955 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1956 {
1957 unsafe {
1958 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1959 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1960 self.as_ptr(),
1961 Some(raw_stateless_cookie_generate::<F>),
1962 );
1963 }
1964 }
1965
1966 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1975 #[cfg(ossl111)]
1976 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1977 where
1978 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1979 {
1980 unsafe {
1981 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1982 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1983 self.as_ptr(),
1984 Some(raw_stateless_cookie_verify::<F>),
1985 )
1986 }
1987 }
1988
1989 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1994 #[cfg(not(any(boringssl, awslc)))]
1995 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1996 where
1997 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1998 {
1999 unsafe {
2000 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2001 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2002 }
2003 }
2004
2005 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2010 #[cfg(not(any(boringssl, awslc)))]
2011 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2012 where
2013 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2014 {
2015 unsafe {
2016 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2017 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2018 }
2019 }
2020
2021 #[corresponds(SSL_CTX_set_ex_data)]
2027 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2028 self.set_ex_data_inner(index, data);
2029 }
2030
2031 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2032 match self.ex_data_mut(index) {
2033 Some(v) => {
2034 *v = data;
2035 (v as *mut T).cast()
2036 }
2037 _ => unsafe {
2038 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2039 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2040 data
2041 },
2042 }
2043 }
2044
2045 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2046 unsafe {
2047 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2048 if data.is_null() {
2049 None
2050 } else {
2051 Some(&mut *data.cast())
2052 }
2053 }
2054 }
2055
2056 #[corresponds(SSL_CTX_add_custom_ext)]
2060 #[cfg(ossl111)]
2061 pub fn add_custom_ext<AddFn, ParseFn, T>(
2062 &mut self,
2063 ext_type: u16,
2064 context: ExtensionContext,
2065 add_cb: AddFn,
2066 parse_cb: ParseFn,
2067 ) -> Result<(), ErrorStack>
2068 where
2069 AddFn: Fn(
2070 &mut SslRef,
2071 ExtensionContext,
2072 Option<(usize, &X509Ref)>,
2073 ) -> Result<Option<T>, SslAlert>
2074 + 'static
2075 + Sync
2076 + Send,
2077 T: AsRef<[u8]> + 'static + Sync + Send,
2078 ParseFn: Fn(
2079 &mut SslRef,
2080 ExtensionContext,
2081 &[u8],
2082 Option<(usize, &X509Ref)>,
2083 ) -> Result<(), SslAlert>
2084 + 'static
2085 + Sync
2086 + Send,
2087 {
2088 let ret = unsafe {
2089 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2090 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2091
2092 ffi::SSL_CTX_add_custom_ext(
2093 self.as_ptr(),
2094 ext_type as c_uint,
2095 context.bits(),
2096 Some(raw_custom_ext_add::<AddFn, T>),
2097 Some(raw_custom_ext_free::<T>),
2098 ptr::null_mut(),
2099 Some(raw_custom_ext_parse::<ParseFn>),
2100 ptr::null_mut(),
2101 )
2102 };
2103 if ret == 1 {
2104 Ok(())
2105 } else {
2106 Err(ErrorStack::get())
2107 }
2108 }
2109
2110 #[corresponds(SSL_CTX_set_max_early_data)]
2116 #[cfg(any(ossl111, libressl))]
2117 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2118 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2119 Ok(())
2120 } else {
2121 Err(ErrorStack::get())
2122 }
2123 }
2124
2125 #[cfg(any(boringssl, awslc))]
2135 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2136 where
2137 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2138 {
2139 unsafe {
2140 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2141 ffi::SSL_CTX_set_select_certificate_cb(
2142 self.as_ptr(),
2143 Some(callbacks::raw_select_cert::<F>),
2144 );
2145 }
2146 }
2147
2148 #[corresponds(SSL_CTX_set_client_hello_cb)]
2152 #[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
2153 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2154 where
2155 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2156 {
2157 unsafe {
2158 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2159 ffi::SSL_CTX_set_client_hello_cb(
2160 self.as_ptr(),
2161 Some(callbacks::raw_client_hello::<F>),
2162 ptr,
2163 );
2164 }
2165 }
2166
2167 #[corresponds(SSL_CTX_set_info_callback)]
2170 pub fn set_info_callback<F>(&mut self, callback: F)
2171 where
2172 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2173 {
2174 unsafe {
2175 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2176 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2177 }
2178 }
2179
2180 #[corresponds(SSL_CTX_sess_set_cache_size)]
2184 #[allow(clippy::useless_conversion)]
2185 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2186 unsafe {
2187 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2188 }
2189 }
2190
2191 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2195 #[cfg(ossl110)]
2196 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2197 let sigalgs = CString::new(sigalgs).unwrap();
2198 unsafe {
2199 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2200 .map(|_| ())
2201 }
2202 }
2203
2204 #[corresponds(SSL_CTX_set1_groups_list)]
2208 #[cfg(any(ossl111, boringssl, libressl, awslc))]
2209 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2210 let groups = CString::new(groups).unwrap();
2211 unsafe {
2212 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2213 }
2214 }
2215
2216 #[corresponds(SSL_CTX_set_num_tickets)]
2221 #[cfg(any(ossl111, boringssl, awslc))]
2222 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2223 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2224 }
2225
2226 #[corresponds(SSL_CTX_set_security_level)]
2231 #[cfg(any(ossl110, libressl360))]
2232 pub fn set_security_level(&mut self, level: u32) {
2233 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2234 }
2235
2236 pub fn build(self) -> SslContext {
2238 self.0
2239 }
2240}
2241
2242foreign_type_and_impl_send_sync! {
2243 type CType = ffi::SSL_CTX;
2244 fn drop = ffi::SSL_CTX_free;
2245
2246 pub struct SslContext;
2251
2252 pub struct SslContextRef;
2256}
2257
2258impl Clone for SslContext {
2259 fn clone(&self) -> Self {
2260 (**self).to_owned()
2261 }
2262}
2263
2264impl ToOwned for SslContextRef {
2265 type Owned = SslContext;
2266
2267 fn to_owned(&self) -> Self::Owned {
2268 unsafe {
2269 SSL_CTX_up_ref(self.as_ptr());
2270 SslContext::from_ptr(self.as_ptr())
2271 }
2272 }
2273}
2274
2275impl fmt::Debug for SslContext {
2277 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2278 write!(fmt, "SslContext")
2279 }
2280}
2281
2282impl SslContext {
2283 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2285 SslContextBuilder::new(method)
2286 }
2287
2288 #[corresponds(SSL_CTX_get_ex_new_index)]
2293 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2294 where
2295 T: 'static + Sync + Send,
2296 {
2297 unsafe {
2298 ffi::init();
2299 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2300 Ok(Index::from_raw(idx))
2301 }
2302 }
2303
2304 fn cached_ex_index<T>() -> Index<SslContext, T>
2306 where
2307 T: 'static + Sync + Send,
2308 {
2309 unsafe {
2310 let idx = *INDEXES
2311 .lock()
2312 .unwrap_or_else(|e| e.into_inner())
2313 .entry(TypeId::of::<T>())
2314 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2315 Index::from_raw(idx)
2316 }
2317 }
2318}
2319
2320impl SslContextRef {
2321 #[corresponds(SSL_CTX_get0_certificate)]
2325 #[cfg(any(ossl110, libressl))]
2326 pub fn certificate(&self) -> Option<&X509Ref> {
2327 unsafe {
2328 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2329 X509Ref::from_const_ptr_opt(ptr)
2330 }
2331 }
2332
2333 #[corresponds(SSL_CTX_get0_privatekey)]
2337 #[cfg(any(ossl110, libressl))]
2338 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2339 unsafe {
2340 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2341 PKeyRef::from_const_ptr_opt(ptr)
2342 }
2343 }
2344
2345 #[corresponds(SSL_CTX_get_cert_store)]
2347 pub fn cert_store(&self) -> &X509StoreRef {
2348 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2349 }
2350
2351 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2353 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2354 unsafe {
2355 let mut chain = ptr::null_mut();
2356 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2357 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2358 }
2359 }
2360
2361 #[corresponds(SSL_CTX_get_ex_data)]
2363 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2364 unsafe {
2365 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2366 if data.is_null() {
2367 None
2368 } else {
2369 Some(&*(data as *const T))
2370 }
2371 }
2372 }
2373
2374 #[corresponds(SSL_CTX_get_max_early_data)]
2378 #[cfg(any(ossl111, libressl))]
2379 pub fn max_early_data(&self) -> u32 {
2380 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2381 }
2382
2383 #[corresponds(SSL_CTX_add_session)]
2392 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2393 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2394 }
2395
2396 #[corresponds(SSL_CTX_remove_session)]
2405 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2406 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2407 }
2408
2409 #[corresponds(SSL_CTX_sess_get_cache_size)]
2413 #[allow(clippy::unnecessary_cast)]
2414 pub fn session_cache_size(&self) -> i64 {
2415 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2416 }
2417
2418 #[corresponds(SSL_CTX_get_verify_mode)]
2422 pub fn verify_mode(&self) -> SslVerifyMode {
2423 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2424 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2425 }
2426
2427 #[corresponds(SSL_CTX_get_num_tickets)]
2432 #[cfg(ossl111)]
2433 pub fn num_tickets(&self) -> usize {
2434 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2435 }
2436
2437 #[corresponds(SSL_CTX_get_security_level)]
2442 #[cfg(any(ossl110, libressl360))]
2443 pub fn security_level(&self) -> u32 {
2444 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2445 }
2446}
2447
2448pub struct CipherBits {
2450 pub secret: i32,
2452
2453 pub algorithm: i32,
2455}
2456
2457pub struct SslCipher(*mut ffi::SSL_CIPHER);
2459
2460impl ForeignType for SslCipher {
2461 type CType = ffi::SSL_CIPHER;
2462 type Ref = SslCipherRef;
2463
2464 #[inline]
2465 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2466 SslCipher(ptr)
2467 }
2468
2469 #[inline]
2470 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2471 self.0
2472 }
2473}
2474
2475impl Stackable for SslCipher {
2476 type StackType = ffi::stack_st_SSL_CIPHER;
2477}
2478
2479impl Deref for SslCipher {
2480 type Target = SslCipherRef;
2481
2482 fn deref(&self) -> &SslCipherRef {
2483 unsafe { SslCipherRef::from_ptr(self.0) }
2484 }
2485}
2486
2487impl DerefMut for SslCipher {
2488 fn deref_mut(&mut self) -> &mut SslCipherRef {
2489 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2490 }
2491}
2492
2493pub struct SslCipherRef(Opaque);
2497
2498impl ForeignTypeRef for SslCipherRef {
2499 type CType = ffi::SSL_CIPHER;
2500}
2501
2502impl SslCipherRef {
2503 #[corresponds(SSL_CIPHER_get_name)]
2505 pub fn name(&self) -> &'static str {
2506 unsafe {
2507 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2508 CStr::from_ptr(ptr).to_str().unwrap()
2509 }
2510 }
2511
2512 #[corresponds(SSL_CIPHER_standard_name)]
2516 #[cfg(ossl111)]
2517 pub fn standard_name(&self) -> Option<&'static str> {
2518 unsafe {
2519 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2520 if ptr.is_null() {
2521 None
2522 } else {
2523 Some(CStr::from_ptr(ptr).to_str().unwrap())
2524 }
2525 }
2526 }
2527
2528 #[corresponds(SSL_CIPHER_get_version)]
2530 pub fn version(&self) -> &'static str {
2531 let version = unsafe {
2532 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2533 CStr::from_ptr(ptr as *const _)
2534 };
2535
2536 str::from_utf8(version.to_bytes()).unwrap()
2537 }
2538
2539 #[corresponds(SSL_CIPHER_get_bits)]
2541 #[allow(clippy::useless_conversion)]
2542 pub fn bits(&self) -> CipherBits {
2543 unsafe {
2544 let mut algo_bits = 0;
2545 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2546 CipherBits {
2547 secret: secret_bits.into(),
2548 algorithm: algo_bits.into(),
2549 }
2550 }
2551 }
2552
2553 #[corresponds(SSL_CIPHER_description)]
2555 pub fn description(&self) -> String {
2556 unsafe {
2557 let mut buf = [0; 128];
2559 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2560 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2561 }
2562 }
2563
2564 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2568 #[cfg(ossl111)]
2569 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2570 unsafe {
2571 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2572 if ptr.is_null() {
2573 None
2574 } else {
2575 Some(MessageDigest::from_ptr(ptr))
2576 }
2577 }
2578 }
2579
2580 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2584 #[cfg(any(ossl110, libressl))]
2585 pub fn cipher_nid(&self) -> Option<Nid> {
2586 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2587 if n == 0 {
2588 None
2589 } else {
2590 Some(Nid::from_raw(n))
2591 }
2592 }
2593
2594 #[corresponds(SSL_CIPHER_get_protocol_id)]
2598 #[cfg(ossl111)]
2599 pub fn protocol_id(&self) -> [u8; 2] {
2600 unsafe {
2601 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2602 id.to_be_bytes()
2603 }
2604 }
2605}
2606
2607impl fmt::Debug for SslCipherRef {
2608 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2609 write!(fmt, "{}", self.name())
2610 }
2611}
2612
2613#[derive(Debug)]
2615pub struct CipherLists {
2616 pub suites: Stack<SslCipher>,
2617 pub signalling_suites: Stack<SslCipher>,
2618}
2619
2620foreign_type_and_impl_send_sync! {
2621 type CType = ffi::SSL_SESSION;
2622 fn drop = ffi::SSL_SESSION_free;
2623
2624 pub struct SslSession;
2628
2629 pub struct SslSessionRef;
2633}
2634
2635impl Clone for SslSession {
2636 fn clone(&self) -> SslSession {
2637 SslSessionRef::to_owned(self)
2638 }
2639}
2640
2641impl SslSession {
2642 from_der! {
2643 #[corresponds(d2i_SSL_SESSION)]
2645 from_der,
2646 SslSession,
2647 ffi::d2i_SSL_SESSION
2648 }
2649}
2650
2651impl ToOwned for SslSessionRef {
2652 type Owned = SslSession;
2653
2654 fn to_owned(&self) -> SslSession {
2655 unsafe {
2656 SSL_SESSION_up_ref(self.as_ptr());
2657 SslSession(self.as_ptr())
2658 }
2659 }
2660}
2661
2662impl SslSessionRef {
2663 #[corresponds(SSL_SESSION_get_id)]
2665 pub fn id(&self) -> &[u8] {
2666 unsafe {
2667 let mut len = 0;
2668 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2669 #[allow(clippy::unnecessary_cast)]
2670 util::from_raw_parts(p as *const u8, len as usize)
2671 }
2672 }
2673
2674 #[corresponds(SSL_SESSION_get_master_key)]
2676 pub fn master_key_len(&self) -> usize {
2677 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2678 }
2679
2680 #[corresponds(SSL_SESSION_get_master_key)]
2684 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2685 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2686 }
2687
2688 #[corresponds(SSL_SESSION_get_max_early_data)]
2692 #[cfg(any(ossl111, libressl))]
2693 pub fn max_early_data(&self) -> u32 {
2694 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2695 }
2696
2697 #[corresponds(SSL_SESSION_get_time)]
2699 #[allow(clippy::useless_conversion)]
2700 pub fn time(&self) -> SslTimeTy {
2701 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2702 }
2703
2704 #[corresponds(SSL_SESSION_get_timeout)]
2708 #[allow(clippy::useless_conversion)]
2709 pub fn timeout(&self) -> i64 {
2710 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2711 }
2712
2713 #[corresponds(SSL_SESSION_get_protocol_version)]
2717 #[cfg(any(ossl110, libressl))]
2718 pub fn protocol_version(&self) -> SslVersion {
2719 unsafe {
2720 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2721 SslVersion(version)
2722 }
2723 }
2724
2725 #[corresponds(SSL_SESSION_get_protocol_version)]
2727 #[cfg(any(boringssl, awslc))]
2728 pub fn protocol_version(&self) -> SslVersion {
2729 unsafe {
2730 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2731 SslVersion(version as _)
2732 }
2733 }
2734
2735 to_der! {
2736 #[corresponds(i2d_SSL_SESSION)]
2738 to_der,
2739 ffi::i2d_SSL_SESSION
2740 }
2741}
2742
2743foreign_type_and_impl_send_sync! {
2744 type CType = ffi::SSL;
2745 fn drop = ffi::SSL_free;
2746
2747 pub struct Ssl;
2754
2755 pub struct SslRef;
2759}
2760
2761impl fmt::Debug for Ssl {
2762 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2763 fmt::Debug::fmt(&**self, fmt)
2764 }
2765}
2766
2767impl Ssl {
2768 #[corresponds(SSL_get_ex_new_index)]
2773 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2774 where
2775 T: 'static + Sync + Send,
2776 {
2777 unsafe {
2778 ffi::init();
2779 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2780 Ok(Index::from_raw(idx))
2781 }
2782 }
2783
2784 fn cached_ex_index<T>() -> Index<Ssl, T>
2786 where
2787 T: 'static + Sync + Send,
2788 {
2789 unsafe {
2790 let idx = *SSL_INDEXES
2791 .lock()
2792 .unwrap_or_else(|e| e.into_inner())
2793 .entry(TypeId::of::<T>())
2794 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2795 Index::from_raw(idx)
2796 }
2797 }
2798
2799 #[corresponds(SSL_new)]
2801 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2802 let session_ctx_index = try_get_session_ctx_index()?;
2803 unsafe {
2804 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2805 let mut ssl = Ssl::from_ptr(ptr);
2806 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2807
2808 Ok(ssl)
2809 }
2810 }
2811
2812 #[corresponds(SSL_connect)]
2818 #[allow(deprecated)]
2819 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2820 where
2821 S: Read + Write,
2822 {
2823 SslStreamBuilder::new(self, stream).connect()
2824 }
2825
2826 #[corresponds(SSL_accept)]
2833 #[allow(deprecated)]
2834 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2835 where
2836 S: Read + Write,
2837 {
2838 SslStreamBuilder::new(self, stream).accept()
2839 }
2840}
2841
2842impl fmt::Debug for SslRef {
2843 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2844 fmt.debug_struct("Ssl")
2845 .field("state", &self.state_string_long())
2846 .field("verify_result", &self.verify_result())
2847 .finish()
2848 }
2849}
2850
2851impl SslRef {
2852 #[cfg(not(feature = "tongsuo"))]
2853 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2854 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2855 }
2856
2857 #[cfg(feature = "tongsuo")]
2858 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2859 unsafe {
2860 let bio = ffi::SSL_get_rbio(self.as_ptr());
2861 bio::find_correct_bio(bio)
2862 }
2863 }
2864
2865 fn get_error(&self, ret: c_int) -> ErrorCode {
2866 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2867 }
2868
2869 #[corresponds(SSL_set_mode)]
2873 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2874 unsafe {
2875 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2876 SslMode::from_bits_retain(bits)
2877 }
2878 }
2879
2880 #[corresponds(SSL_clear_mode)]
2882 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2883 unsafe {
2884 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2885 SslMode::from_bits_retain(bits)
2886 }
2887 }
2888
2889 #[corresponds(SSL_get_mode)]
2891 pub fn mode(&self) -> SslMode {
2892 unsafe {
2893 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2894 SslMode::from_bits_retain(bits)
2895 }
2896 }
2897
2898 #[corresponds(SSL_set_connect_state)]
2900 pub fn set_connect_state(&mut self) {
2901 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2902 }
2903
2904 #[corresponds(SSL_set_accept_state)]
2906 pub fn set_accept_state(&mut self) {
2907 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2908 }
2909
2910 #[cfg(any(boringssl, awslc))]
2911 #[corresponds(SSL_ech_accepted)]
2912 pub fn ech_accepted(&self) -> bool {
2913 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2914 }
2915
2916 #[cfg(tongsuo)]
2917 #[corresponds(SSL_is_ntls)]
2918 pub fn is_ntls(&mut self) -> bool {
2919 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2920 }
2921
2922 #[cfg(tongsuo)]
2923 #[corresponds(SSL_enable_ntls)]
2924 pub fn enable_ntls(&mut self) {
2925 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2926 }
2927
2928 #[cfg(tongsuo)]
2929 #[corresponds(SSL_disable_ntls)]
2930 pub fn disable_ntls(&mut self) {
2931 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2932 }
2933
2934 #[cfg(all(tongsuo, ossl300))]
2935 #[corresponds(SSL_enable_force_ntls)]
2936 pub fn enable_force_ntls(&mut self) {
2937 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2938 }
2939
2940 #[cfg(all(tongsuo, ossl300))]
2941 #[corresponds(SSL_disable_force_ntls)]
2942 pub fn disable_force_ntls(&mut self) {
2943 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2944 }
2945
2946 #[cfg(tongsuo)]
2947 #[corresponds(SSL_enable_sm_tls13_strict)]
2948 pub fn enable_sm_tls13_strict(&mut self) {
2949 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2950 }
2951
2952 #[cfg(tongsuo)]
2953 #[corresponds(SSL_disable_sm_tls13_strict)]
2954 pub fn disable_sm_tls13_strict(&mut self) {
2955 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2956 }
2957
2958 #[corresponds(SSL_set_verify)]
2962 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2963 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2964 }
2965
2966 #[corresponds(SSL_set_verify_mode)]
2968 pub fn verify_mode(&self) -> SslVerifyMode {
2969 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2970 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2971 }
2972
2973 #[corresponds(SSL_set_verify)]
2977 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2978 where
2979 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2980 {
2981 unsafe {
2982 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2984 ffi::SSL_set_verify(
2985 self.as_ptr(),
2986 mode.bits() as c_int,
2987 Some(ssl_raw_verify::<F>),
2988 );
2989 }
2990 }
2991
2992 #[corresponds(SSL_set_info_callback)]
2995 pub fn set_info_callback<F>(&mut self, callback: F)
2996 where
2997 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2998 {
2999 unsafe {
3000 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3002 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
3003 }
3004 }
3005
3006 #[corresponds(SSL_set_dh_auto)]
3010 #[cfg(ossl300)]
3011 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3012 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3013 }
3014
3015 #[corresponds(SSL_set_tmp_dh)]
3019 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3020 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3021 }
3022
3023 #[corresponds(SSL_set_tmp_dh_callback)]
3027 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3028 where
3029 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3030 {
3031 unsafe {
3032 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3034 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3035 }
3036 }
3037
3038 #[corresponds(SSL_set_tmp_ecdh)]
3042 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3043 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3044 }
3045
3046 #[corresponds(SSL_set_ecdh_auto)]
3052 #[cfg(libressl)]
3053 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3054 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3055 }
3056
3057 #[corresponds(SSL_set_alpn_protos)]
3063 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3064 unsafe {
3065 assert!(protocols.len() <= c_uint::MAX as usize);
3066 let r =
3067 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3068 if r == 0 {
3070 Ok(())
3071 } else {
3072 Err(ErrorStack::get())
3073 }
3074 }
3075 }
3076
3077 #[corresponds(SSL_get_current_cipher)]
3079 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3080 unsafe {
3081 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3082
3083 SslCipherRef::from_const_ptr_opt(ptr)
3084 }
3085 }
3086
3087 #[corresponds(SSL_state_string)]
3089 pub fn state_string(&self) -> &'static str {
3090 let state = unsafe {
3091 let ptr = ffi::SSL_state_string(self.as_ptr());
3092 CStr::from_ptr(ptr as *const _)
3093 };
3094
3095 str::from_utf8(state.to_bytes()).unwrap()
3096 }
3097
3098 #[corresponds(SSL_state_string_long)]
3100 pub fn state_string_long(&self) -> &'static str {
3101 let state = unsafe {
3102 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3103 CStr::from_ptr(ptr as *const _)
3104 };
3105
3106 str::from_utf8(state.to_bytes()).unwrap()
3107 }
3108
3109 #[corresponds(SSL_set_tlsext_host_name)]
3113 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3114 let cstr = CString::new(hostname).unwrap();
3115 unsafe {
3116 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3117 .map(|_| ())
3118 }
3119 }
3120
3121 #[corresponds(SSL_get_peer_certificate)]
3123 pub fn peer_certificate(&self) -> Option<X509> {
3124 unsafe {
3125 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3126 X509::from_ptr_opt(ptr)
3127 }
3128 }
3129
3130 #[corresponds(SSL_get_peer_cert_chain)]
3135 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3136 unsafe {
3137 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3138 StackRef::from_const_ptr_opt(ptr)
3139 }
3140 }
3141
3142 #[corresponds(SSL_get0_verified_chain)]
3152 #[cfg(ossl110)]
3153 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3154 unsafe {
3155 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3156 StackRef::from_const_ptr_opt(ptr)
3157 }
3158 }
3159
3160 #[corresponds(SSL_get_certificate)]
3162 pub fn certificate(&self) -> Option<&X509Ref> {
3163 unsafe {
3164 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3165 X509Ref::from_const_ptr_opt(ptr)
3166 }
3167 }
3168
3169 #[corresponds(SSL_get_privatekey)]
3173 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3174 unsafe {
3175 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3176 PKeyRef::from_const_ptr_opt(ptr)
3177 }
3178 }
3179
3180 #[corresponds(SSL_version)]
3182 pub fn version2(&self) -> Option<SslVersion> {
3183 unsafe {
3184 let r = ffi::SSL_version(self.as_ptr());
3185 if r == 0 {
3186 None
3187 } else {
3188 Some(SslVersion(r))
3189 }
3190 }
3191 }
3192
3193 #[corresponds(SSL_get_version)]
3195 pub fn version_str(&self) -> &'static str {
3196 let version = unsafe {
3197 let ptr = ffi::SSL_get_version(self.as_ptr());
3198 CStr::from_ptr(ptr as *const _)
3199 };
3200
3201 str::from_utf8(version.to_bytes()).unwrap()
3202 }
3203
3204 #[corresponds(SSL_get0_alpn_selected)]
3211 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3212 unsafe {
3213 let mut data: *const c_uchar = ptr::null();
3214 let mut len: c_uint = 0;
3215 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3218
3219 if data.is_null() {
3220 None
3221 } else {
3222 Some(util::from_raw_parts(data, len as usize))
3223 }
3224 }
3225 }
3226
3227 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3229 #[corresponds(SSL_set_tlsext_use_srtp)]
3230 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3231 unsafe {
3232 let cstr = CString::new(protocols).unwrap();
3233
3234 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3235 if r == 0 {
3237 Ok(())
3238 } else {
3239 Err(ErrorStack::get())
3240 }
3241 }
3242 }
3243
3244 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3248 #[corresponds(SSL_get_srtp_profiles)]
3249 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3250 unsafe {
3251 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3252
3253 StackRef::from_const_ptr_opt(chain)
3254 }
3255 }
3256
3257 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3261 #[corresponds(SSL_get_selected_srtp_profile)]
3262 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3263 unsafe {
3264 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3265
3266 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3267 }
3268 }
3269
3270 #[corresponds(SSL_pending)]
3275 pub fn pending(&self) -> usize {
3276 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3277 }
3278
3279 #[corresponds(SSL_get_servername)]
3292 pub fn servername(&self, type_: NameType) -> Option<&str> {
3294 self.servername_raw(type_)
3295 .and_then(|b| str::from_utf8(b).ok())
3296 }
3297
3298 #[corresponds(SSL_get_servername)]
3306 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3307 unsafe {
3308 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3309 if name.is_null() {
3310 None
3311 } else {
3312 Some(CStr::from_ptr(name as *const _).to_bytes())
3313 }
3314 }
3315 }
3316
3317 #[corresponds(SSL_set_SSL_CTX)]
3321 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3322 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3323 }
3324
3325 #[corresponds(SSL_get_SSL_CTX)]
3327 pub fn ssl_context(&self) -> &SslContextRef {
3328 unsafe {
3329 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3330 SslContextRef::from_ptr(ssl_ctx)
3331 }
3332 }
3333
3334 #[corresponds(SSL_get0_param)]
3338 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3339 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3340 }
3341
3342 #[corresponds(SSL_get_verify_result)]
3344 pub fn verify_result(&self) -> X509VerifyResult {
3345 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3346 }
3347
3348 #[corresponds(SSL_get_session)]
3350 pub fn session(&self) -> Option<&SslSessionRef> {
3351 unsafe {
3352 let p = ffi::SSL_get_session(self.as_ptr());
3353 SslSessionRef::from_const_ptr_opt(p)
3354 }
3355 }
3356
3357 #[corresponds(SSL_get_client_random)]
3364 #[cfg(any(ossl110, libressl))]
3365 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3366 unsafe {
3367 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3368 }
3369 }
3370
3371 #[corresponds(SSL_get_server_random)]
3378 #[cfg(any(ossl110, libressl))]
3379 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3380 unsafe {
3381 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3382 }
3383 }
3384
3385 #[corresponds(SSL_export_keying_material)]
3387 pub fn export_keying_material(
3388 &self,
3389 out: &mut [u8],
3390 label: &str,
3391 context: Option<&[u8]>,
3392 ) -> Result<(), ErrorStack> {
3393 unsafe {
3394 let (context, contextlen, use_context) = match context {
3395 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3396 None => (ptr::null(), 0, 0),
3397 };
3398 cvt(ffi::SSL_export_keying_material(
3399 self.as_ptr(),
3400 out.as_mut_ptr() as *mut c_uchar,
3401 out.len(),
3402 label.as_ptr() as *const c_char,
3403 label.len(),
3404 context,
3405 contextlen,
3406 use_context,
3407 ))
3408 .map(|_| ())
3409 }
3410 }
3411
3412 #[corresponds(SSL_export_keying_material_early)]
3419 #[cfg(ossl111)]
3420 pub fn export_keying_material_early(
3421 &self,
3422 out: &mut [u8],
3423 label: &str,
3424 context: &[u8],
3425 ) -> Result<(), ErrorStack> {
3426 unsafe {
3427 cvt(ffi::SSL_export_keying_material_early(
3428 self.as_ptr(),
3429 out.as_mut_ptr() as *mut c_uchar,
3430 out.len(),
3431 label.as_ptr() as *const c_char,
3432 label.len(),
3433 context.as_ptr() as *const c_uchar,
3434 context.len(),
3435 ))
3436 .map(|_| ())
3437 }
3438 }
3439
3440 #[corresponds(SSL_set_session)]
3451 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3452 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3453 }
3454
3455 #[corresponds(SSL_session_reused)]
3457 pub fn session_reused(&self) -> bool {
3458 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3459 }
3460
3461 #[cfg(any(boringssl, awslc))]
3469 pub fn enable_ocsp_stapling(&mut self) {
3470 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3471 }
3472
3473 #[cfg(any(boringssl, awslc))]
3481 pub fn enable_signed_cert_timestamps(&mut self) {
3482 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3483 }
3484
3485 #[cfg(any(boringssl, awslc))]
3493 pub fn set_permute_extensions(&mut self, enabled: bool) {
3494 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3495 }
3496
3497 #[corresponds(SSL_enable_ct)]
3499 #[cfg(ossl111)]
3500 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3501 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3502 }
3503
3504 #[corresponds(SSL_ct_is_enabled)]
3506 #[cfg(ossl111)]
3507 pub fn ct_is_enabled(&self) -> bool {
3508 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3509 }
3510
3511 #[corresponds(SSL_set_tlsext_status_type)]
3513 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3514 unsafe {
3515 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3516 }
3517 }
3518
3519 #[corresponds(SSL_get_extms_support)]
3523 #[cfg(ossl110)]
3524 pub fn extms_support(&self) -> Option<bool> {
3525 unsafe {
3526 match ffi::SSL_get_extms_support(self.as_ptr()) {
3527 -1 => None,
3528 ret => Some(ret != 0),
3529 }
3530 }
3531 }
3532
3533 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3535 #[cfg(not(any(boringssl, awslc)))]
3536 pub fn ocsp_status(&self) -> Option<&[u8]> {
3537 unsafe {
3538 let mut p = ptr::null_mut();
3539 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3540
3541 if len < 0 {
3542 None
3543 } else {
3544 Some(util::from_raw_parts(p as *const u8, len as usize))
3545 }
3546 }
3547 }
3548
3549 #[corresponds(SSL_get0_ocsp_response)]
3551 #[cfg(any(boringssl, awslc))]
3552 pub fn ocsp_status(&self) -> Option<&[u8]> {
3553 unsafe {
3554 let mut p = ptr::null();
3555 let mut len: usize = 0;
3556 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3557
3558 if len == 0 {
3559 None
3560 } else {
3561 Some(util::from_raw_parts(p as *const u8, len))
3562 }
3563 }
3564 }
3565
3566 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3568 #[cfg(not(any(boringssl, awslc)))]
3569 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3570 unsafe {
3571 assert!(response.len() <= c_int::MAX as usize);
3572 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3573 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3574 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3575 self.as_ptr(),
3576 p as *mut c_uchar,
3577 response.len() as c_long,
3578 ) as c_int)
3579 .map(|_| ())
3580 .inspect_err(|_| {
3581 ffi::OPENSSL_free(p);
3582 })
3583 }
3584 }
3585
3586 #[corresponds(SSL_set_ocsp_response)]
3588 #[cfg(any(boringssl, awslc))]
3589 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3590 unsafe {
3591 cvt(ffi::SSL_set_ocsp_response(
3592 self.as_ptr(),
3593 response.as_ptr(),
3594 response.len(),
3595 ))
3596 .map(|_| ())
3597 }
3598 }
3599
3600 #[corresponds(SSL_is_server)]
3602 pub fn is_server(&self) -> bool {
3603 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3604 }
3605
3606 #[corresponds(SSL_set_ex_data)]
3612 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3613 match self.ex_data_mut(index) {
3614 Some(v) => *v = data,
3615 None => unsafe {
3616 let data = Box::new(data);
3617 ffi::SSL_set_ex_data(
3618 self.as_ptr(),
3619 index.as_raw(),
3620 Box::into_raw(data) as *mut c_void,
3621 );
3622 },
3623 }
3624 }
3625
3626 #[corresponds(SSL_get_ex_data)]
3628 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3629 unsafe {
3630 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3631 if data.is_null() {
3632 None
3633 } else {
3634 Some(&*(data as *const T))
3635 }
3636 }
3637 }
3638
3639 #[corresponds(SSL_get_ex_data)]
3641 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3642 unsafe {
3643 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3644 if data.is_null() {
3645 None
3646 } else {
3647 Some(&mut *(data as *mut T))
3648 }
3649 }
3650 }
3651
3652 #[corresponds(SSL_set_max_early_data)]
3656 #[cfg(any(ossl111, libressl))]
3657 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3658 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3659 Ok(())
3660 } else {
3661 Err(ErrorStack::get())
3662 }
3663 }
3664
3665 #[corresponds(SSL_get_max_early_data)]
3669 #[cfg(any(ossl111, libressl))]
3670 pub fn max_early_data(&self) -> u32 {
3671 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3672 }
3673
3674 #[corresponds(SSL_get_finished)]
3679 pub fn finished(&self, buf: &mut [u8]) -> usize {
3680 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3681 }
3682
3683 #[corresponds(SSL_get_peer_finished)]
3689 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3690 unsafe {
3691 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3692 }
3693 }
3694
3695 #[corresponds(SSL_is_init_finished)]
3697 #[cfg(ossl110)]
3698 pub fn is_init_finished(&self) -> bool {
3699 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3700 }
3701
3702 #[corresponds(SSL_client_hello_isv2)]
3708 #[cfg(ossl111)]
3709 pub fn client_hello_isv2(&self) -> bool {
3710 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3711 }
3712
3713 #[corresponds(SSL_client_hello_get0_legacy_version)]
3719 #[cfg(ossl111)]
3720 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3721 unsafe {
3722 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3723 if version == 0 {
3724 None
3725 } else {
3726 Some(SslVersion(version as c_int))
3727 }
3728 }
3729 }
3730
3731 #[corresponds(SSL_client_hello_get0_random)]
3737 #[cfg(ossl111)]
3738 pub fn client_hello_random(&self) -> Option<&[u8]> {
3739 unsafe {
3740 let mut ptr = ptr::null();
3741 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3742 if len == 0 {
3743 None
3744 } else {
3745 Some(util::from_raw_parts(ptr, len))
3746 }
3747 }
3748 }
3749
3750 #[corresponds(SSL_client_hello_get0_session_id)]
3756 #[cfg(ossl111)]
3757 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3758 unsafe {
3759 let mut ptr = ptr::null();
3760 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3761 if len == 0 {
3762 None
3763 } else {
3764 Some(util::from_raw_parts(ptr, len))
3765 }
3766 }
3767 }
3768
3769 #[corresponds(SSL_client_hello_get0_ciphers)]
3775 #[cfg(ossl111)]
3776 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3777 unsafe {
3778 let mut ptr = ptr::null();
3779 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3780 if len == 0 {
3781 None
3782 } else {
3783 Some(util::from_raw_parts(ptr, len))
3784 }
3785 }
3786 }
3787
3788 #[cfg(ossl111)]
3794 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3795 unsafe {
3796 let mut ptr = ptr::null();
3797 let mut len = 0usize;
3798 let r = ffi::SSL_client_hello_get0_ext(
3799 self.as_ptr(),
3800 ext_type.as_raw() as _,
3801 &mut ptr,
3802 &mut len,
3803 );
3804 if r == 0 {
3805 None
3806 } else {
3807 Some(util::from_raw_parts(ptr, len))
3808 }
3809 }
3810 }
3811
3812 #[corresponds(SSL_bytes_to_cipher_list)]
3817 #[cfg(ossl111)]
3818 pub fn bytes_to_cipher_list(
3819 &self,
3820 bytes: &[u8],
3821 isv2format: bool,
3822 ) -> Result<CipherLists, ErrorStack> {
3823 unsafe {
3824 let ptr = bytes.as_ptr();
3825 let len = bytes.len();
3826 let mut sk = ptr::null_mut();
3827 let mut scsvs = ptr::null_mut();
3828 let res = ffi::SSL_bytes_to_cipher_list(
3829 self.as_ptr(),
3830 ptr,
3831 len,
3832 isv2format as c_int,
3833 &mut sk,
3834 &mut scsvs,
3835 );
3836 if res == 1 {
3837 Ok(CipherLists {
3838 suites: Stack::from_ptr(sk),
3839 signalling_suites: Stack::from_ptr(scsvs),
3840 })
3841 } else {
3842 Err(ErrorStack::get())
3843 }
3844 }
3845 }
3846
3847 #[corresponds(SSL_client_hello_get0_compression_methods)]
3853 #[cfg(ossl111)]
3854 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3855 unsafe {
3856 let mut ptr = ptr::null();
3857 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3858 if len == 0 {
3859 None
3860 } else {
3861 Some(util::from_raw_parts(ptr, len))
3862 }
3863 }
3864 }
3865
3866 #[corresponds(SSL_set_mtu)]
3868 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3869 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3870 }
3871
3872 #[corresponds(SSL_get_psk_identity_hint)]
3876 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3877 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3878 unsafe {
3879 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3880 if ptr.is_null() {
3881 None
3882 } else {
3883 Some(CStr::from_ptr(ptr).to_bytes())
3884 }
3885 }
3886 }
3887
3888 #[corresponds(SSL_get_psk_identity)]
3890 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3891 pub fn psk_identity(&self) -> Option<&[u8]> {
3892 unsafe {
3893 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3894 if ptr.is_null() {
3895 None
3896 } else {
3897 Some(CStr::from_ptr(ptr).to_bytes())
3898 }
3899 }
3900 }
3901
3902 #[corresponds(SSL_add0_chain_cert)]
3903 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3904 unsafe {
3905 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3906 mem::forget(chain);
3907 }
3908 Ok(())
3909 }
3910
3911 #[cfg(not(any(boringssl, awslc)))]
3913 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3914 unsafe {
3915 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3916 };
3917 Ok(())
3918 }
3919
3920 #[corresponds(SSL_use_Private_Key_file)]
3922 pub fn set_private_key_file<P: AsRef<Path>>(
3923 &mut self,
3924 path: P,
3925 ssl_file_type: SslFiletype,
3926 ) -> Result<(), ErrorStack> {
3927 let p = path.as_ref().as_os_str().to_str().unwrap();
3928 let key_file = CString::new(p).unwrap();
3929 unsafe {
3930 cvt(ffi::SSL_use_PrivateKey_file(
3931 self.as_ptr(),
3932 key_file.as_ptr(),
3933 ssl_file_type.as_raw(),
3934 ))?;
3935 };
3936 Ok(())
3937 }
3938
3939 #[corresponds(SSL_use_PrivateKey)]
3941 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3942 unsafe {
3943 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3944 };
3945 Ok(())
3946 }
3947
3948 #[cfg(tongsuo)]
3949 #[corresponds(SSL_use_enc_Private_Key_file)]
3950 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3951 &mut self,
3952 path: P,
3953 ssl_file_type: SslFiletype,
3954 ) -> Result<(), ErrorStack> {
3955 let p = path.as_ref().as_os_str().to_str().unwrap();
3956 let key_file = CString::new(p).unwrap();
3957 unsafe {
3958 cvt(ffi::SSL_use_enc_PrivateKey_file(
3959 self.as_ptr(),
3960 key_file.as_ptr(),
3961 ssl_file_type.as_raw(),
3962 ))?;
3963 };
3964 Ok(())
3965 }
3966
3967 #[cfg(tongsuo)]
3968 #[corresponds(SSL_use_enc_PrivateKey)]
3969 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3970 unsafe {
3971 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3972 };
3973 Ok(())
3974 }
3975
3976 #[cfg(tongsuo)]
3977 #[corresponds(SSL_use_sign_Private_Key_file)]
3978 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3979 &mut self,
3980 path: P,
3981 ssl_file_type: SslFiletype,
3982 ) -> Result<(), ErrorStack> {
3983 let p = path.as_ref().as_os_str().to_str().unwrap();
3984 let key_file = CString::new(p).unwrap();
3985 unsafe {
3986 cvt(ffi::SSL_use_sign_PrivateKey_file(
3987 self.as_ptr(),
3988 key_file.as_ptr(),
3989 ssl_file_type.as_raw(),
3990 ))?;
3991 };
3992 Ok(())
3993 }
3994
3995 #[cfg(tongsuo)]
3996 #[corresponds(SSL_use_sign_PrivateKey)]
3997 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3998 unsafe {
3999 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
4000 };
4001 Ok(())
4002 }
4003
4004 #[corresponds(SSL_use_certificate)]
4006 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4007 unsafe {
4008 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4009 };
4010 Ok(())
4011 }
4012
4013 #[cfg(tongsuo)]
4014 #[corresponds(SSL_use_enc_certificate)]
4015 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4016 unsafe {
4017 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4018 };
4019 Ok(())
4020 }
4021
4022 #[cfg(tongsuo)]
4023 #[corresponds(SSL_use_sign_certificate)]
4024 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4025 unsafe {
4026 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4027 };
4028 Ok(())
4029 }
4030
4031 #[corresponds(SSL_use_certificate_chain_file)]
4037 #[cfg(any(ossl110, libressl))]
4038 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4039 &mut self,
4040 path: P,
4041 ) -> Result<(), ErrorStack> {
4042 let p = path.as_ref().as_os_str().to_str().unwrap();
4043 let cert_file = CString::new(p).unwrap();
4044 unsafe {
4045 cvt(ffi::SSL_use_certificate_chain_file(
4046 self.as_ptr(),
4047 cert_file.as_ptr(),
4048 ))?;
4049 };
4050 Ok(())
4051 }
4052
4053 #[corresponds(SSL_add_client_CA)]
4055 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4056 unsafe {
4057 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4058 };
4059 Ok(())
4060 }
4061
4062 #[corresponds(SSL_set_client_CA_list)]
4064 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4065 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4066 mem::forget(list);
4067 }
4068
4069 #[corresponds(SSL_set_min_proto_version)]
4074 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4075 unsafe {
4076 cvt(ffi::SSL_set_min_proto_version(
4077 self.as_ptr(),
4078 version.map_or(0, |v| v.0 as _),
4079 ))
4080 .map(|_| ())
4081 }
4082 }
4083
4084 #[corresponds(SSL_set_max_proto_version)]
4089 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4090 unsafe {
4091 cvt(ffi::SSL_set_max_proto_version(
4092 self.as_ptr(),
4093 version.map_or(0, |v| v.0 as _),
4094 ))
4095 .map(|_| ())
4096 }
4097 }
4098
4099 #[corresponds(SSL_set_ciphersuites)]
4108 #[cfg(any(ossl111, libressl))]
4109 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4110 let cipher_list = CString::new(cipher_list).unwrap();
4111 unsafe {
4112 cvt(ffi::SSL_set_ciphersuites(
4113 self.as_ptr(),
4114 cipher_list.as_ptr() as *const _,
4115 ))
4116 .map(|_| ())
4117 }
4118 }
4119
4120 #[corresponds(SSL_set_cipher_list)]
4128 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4129 let cipher_list = CString::new(cipher_list).unwrap();
4130 unsafe {
4131 cvt(ffi::SSL_set_cipher_list(
4132 self.as_ptr(),
4133 cipher_list.as_ptr() as *const _,
4134 ))
4135 .map(|_| ())
4136 }
4137 }
4138
4139 #[corresponds(SSL_set_cert_store)]
4141 #[cfg(any(ossl110, boringssl, awslc))]
4142 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4143 unsafe {
4144 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4145 mem::forget(cert_store);
4146 Ok(())
4147 }
4148 }
4149
4150 #[corresponds(SSL_set_num_tickets)]
4155 #[cfg(ossl111)]
4156 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4157 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4158 }
4159
4160 #[corresponds(SSL_get_num_tickets)]
4165 #[cfg(ossl111)]
4166 pub fn num_tickets(&self) -> usize {
4167 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4168 }
4169
4170 #[corresponds(SSL_set_security_level)]
4175 #[cfg(any(ossl110, libressl360))]
4176 pub fn set_security_level(&mut self, level: u32) {
4177 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4178 }
4179
4180 #[corresponds(SSL_get_security_level)]
4185 #[cfg(any(ossl110, libressl360))]
4186 pub fn security_level(&self) -> u32 {
4187 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4188 }
4189
4190 #[corresponds(SSL_get_peer_tmp_key)]
4195 #[cfg(ossl300)]
4196 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4197 unsafe {
4198 let mut key = ptr::null_mut();
4199 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4200 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4201 Err(e) => Err(e),
4202 }
4203 }
4204 }
4205
4206 #[corresponds(SSL_get_tmp_key)]
4211 #[cfg(ossl300)]
4212 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4213 unsafe {
4214 let mut key = ptr::null_mut();
4215 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4216 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4217 Err(e) => Err(e),
4218 }
4219 }
4220 }
4221}
4222
4223#[derive(Debug)]
4225pub struct MidHandshakeSslStream<S> {
4226 stream: SslStream<S>,
4227 error: Error,
4228}
4229
4230impl<S> MidHandshakeSslStream<S> {
4231 pub fn get_ref(&self) -> &S {
4233 self.stream.get_ref()
4234 }
4235
4236 pub fn get_mut(&mut self) -> &mut S {
4238 self.stream.get_mut()
4239 }
4240
4241 pub fn ssl(&self) -> &SslRef {
4243 self.stream.ssl()
4244 }
4245
4246 pub fn ssl_mut(&mut self) -> &mut SslRef {
4248 self.stream.ssl_mut()
4249 }
4250
4251 pub fn error(&self) -> &Error {
4253 &self.error
4254 }
4255
4256 pub fn into_error(self) -> Error {
4258 self.error
4259 }
4260}
4261
4262impl<S> MidHandshakeSslStream<S>
4263where
4264 S: Read + Write,
4265{
4266 #[corresponds(SSL_do_handshake)]
4269 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4270 match self.stream.do_handshake() {
4271 Ok(()) => Ok(self.stream),
4272 Err(error) => {
4273 self.error = error;
4274 match self.error.code() {
4275 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4276 Err(HandshakeError::WouldBlock(self))
4277 }
4278 _ => Err(HandshakeError::Failure(self)),
4279 }
4280 }
4281 }
4282 }
4283}
4284
4285pub struct SslStream<S> {
4287 ssl: ManuallyDrop<Ssl>,
4288 method: ManuallyDrop<BioMethod>,
4289 _p: PhantomData<S>,
4290}
4291
4292impl<S> Drop for SslStream<S> {
4293 fn drop(&mut self) {
4294 unsafe {
4296 ManuallyDrop::drop(&mut self.ssl);
4297 ManuallyDrop::drop(&mut self.method);
4298 }
4299 }
4300}
4301
4302impl<S> fmt::Debug for SslStream<S>
4303where
4304 S: fmt::Debug,
4305{
4306 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4307 fmt.debug_struct("SslStream")
4308 .field("stream", &self.get_ref())
4309 .field("ssl", &self.ssl())
4310 .finish()
4311 }
4312}
4313
4314impl<S: Read + Write> SslStream<S> {
4315 #[corresponds(SSL_set_bio)]
4323 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4324 let (bio, method) = bio::new(stream)?;
4325 unsafe {
4326 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4327 }
4328
4329 Ok(SslStream {
4330 ssl: ManuallyDrop::new(ssl),
4331 method: ManuallyDrop::new(method),
4332 _p: PhantomData,
4333 })
4334 }
4335
4336 #[corresponds(SSL_read_early_data)]
4345 #[cfg(any(ossl111, libressl))]
4346 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4347 let mut read = 0;
4348 let ret = unsafe {
4349 ffi::SSL_read_early_data(
4350 self.ssl.as_ptr(),
4351 buf.as_ptr() as *mut c_void,
4352 buf.len(),
4353 &mut read,
4354 )
4355 };
4356 match ret {
4357 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4358 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4359 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4360 _ => unreachable!(),
4361 }
4362 }
4363
4364 #[corresponds(SSL_write_early_data)]
4371 #[cfg(any(ossl111, libressl))]
4372 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4373 let mut written = 0;
4374 let ret = unsafe {
4375 ffi::SSL_write_early_data(
4376 self.ssl.as_ptr(),
4377 buf.as_ptr() as *const c_void,
4378 buf.len(),
4379 &mut written,
4380 )
4381 };
4382 if ret > 0 {
4383 Ok(written)
4384 } else {
4385 Err(self.make_error(ret))
4386 }
4387 }
4388
4389 #[corresponds(SSL_connect)]
4396 pub fn connect(&mut self) -> Result<(), Error> {
4397 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4398 if ret > 0 {
4399 Ok(())
4400 } else {
4401 Err(self.make_error(ret))
4402 }
4403 }
4404
4405 #[corresponds(SSL_accept)]
4412 pub fn accept(&mut self) -> Result<(), Error> {
4413 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4414 if ret > 0 {
4415 Ok(())
4416 } else {
4417 Err(self.make_error(ret))
4418 }
4419 }
4420
4421 #[corresponds(SSL_do_handshake)]
4425 pub fn do_handshake(&mut self) -> Result<(), Error> {
4426 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4427 if ret > 0 {
4428 Ok(())
4429 } else {
4430 Err(self.make_error(ret))
4431 }
4432 }
4433
4434 #[corresponds(SSL_stateless)]
4445 #[cfg(ossl111)]
4446 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4447 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4448 1 => Ok(true),
4449 0 => Ok(false),
4450 -1 => Err(ErrorStack::get()),
4451 _ => unreachable!(),
4452 }
4453 }
4454
4455 #[corresponds(SSL_read_ex)]
4462 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4463 loop {
4464 match self.ssl_read_uninit(buf) {
4465 Ok(n) => return Ok(n),
4466 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4467 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4468 return Ok(0);
4469 }
4470 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4471 Err(e) => {
4472 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4473 }
4474 }
4475 }
4476 }
4477
4478 #[corresponds(SSL_read_ex)]
4483 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4484 unsafe {
4486 self.ssl_read_uninit(util::from_raw_parts_mut(
4487 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4488 buf.len(),
4489 ))
4490 }
4491 }
4492
4493 #[corresponds(SSL_read_ex)]
4500 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4501 if buf.is_empty() {
4502 return Ok(0);
4503 }
4504
4505 cfg_if! {
4506 if #[cfg(any(ossl111, libressl))] {
4507 let mut readbytes = 0;
4508 let ret = unsafe {
4509 ffi::SSL_read_ex(
4510 self.ssl().as_ptr(),
4511 buf.as_mut_ptr().cast(),
4512 buf.len(),
4513 &mut readbytes,
4514 )
4515 };
4516
4517 if ret > 0 {
4518 Ok(readbytes)
4519 } else {
4520 Err(self.make_error(ret))
4521 }
4522 } else {
4523 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4524 let ret = unsafe {
4525 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4526 };
4527 if ret > 0 {
4528 Ok(ret as usize)
4529 } else {
4530 Err(self.make_error(ret))
4531 }
4532 }
4533 }
4534 }
4535
4536 #[corresponds(SSL_write_ex)]
4541 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4542 if buf.is_empty() {
4543 return Ok(0);
4544 }
4545
4546 cfg_if! {
4547 if #[cfg(any(ossl111, libressl))] {
4548 let mut written = 0;
4549 let ret = unsafe {
4550 ffi::SSL_write_ex(
4551 self.ssl().as_ptr(),
4552 buf.as_ptr().cast(),
4553 buf.len(),
4554 &mut written,
4555 )
4556 };
4557
4558 if ret > 0 {
4559 Ok(written)
4560 } else {
4561 Err(self.make_error(ret))
4562 }
4563 } else {
4564 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4565 let ret = unsafe {
4566 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4567 };
4568 if ret > 0 {
4569 Ok(ret as usize)
4570 } else {
4571 Err(self.make_error(ret))
4572 }
4573 }
4574 }
4575 }
4576
4577 #[corresponds(SSL_peek_ex)]
4579 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4580 unsafe {
4582 self.ssl_peek_uninit(util::from_raw_parts_mut(
4583 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4584 buf.len(),
4585 ))
4586 }
4587 }
4588
4589 #[corresponds(SSL_peek_ex)]
4596 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4597 cfg_if! {
4598 if #[cfg(any(ossl111, libressl))] {
4599 let mut readbytes = 0;
4600 let ret = unsafe {
4601 ffi::SSL_peek_ex(
4602 self.ssl().as_ptr(),
4603 buf.as_mut_ptr().cast(),
4604 buf.len(),
4605 &mut readbytes,
4606 )
4607 };
4608
4609 if ret > 0 {
4610 Ok(readbytes)
4611 } else {
4612 Err(self.make_error(ret))
4613 }
4614 } else {
4615 if buf.is_empty() {
4616 return Ok(0);
4617 }
4618
4619 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4620 let ret = unsafe {
4621 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4622 };
4623 if ret > 0 {
4624 Ok(ret as usize)
4625 } else {
4626 Err(self.make_error(ret))
4627 }
4628 }
4629 }
4630 }
4631
4632 #[corresponds(SSL_shutdown)]
4642 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4643 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4644 0 => Ok(ShutdownResult::Sent),
4645 1 => Ok(ShutdownResult::Received),
4646 n => Err(self.make_error(n)),
4647 }
4648 }
4649
4650 #[corresponds(SSL_get_shutdown)]
4652 pub fn get_shutdown(&mut self) -> ShutdownState {
4653 unsafe {
4654 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4655 ShutdownState::from_bits_retain(bits)
4656 }
4657 }
4658
4659 #[corresponds(SSL_set_shutdown)]
4664 pub fn set_shutdown(&mut self, state: ShutdownState) {
4665 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4666 }
4667}
4668
4669impl<S> SslStream<S> {
4670 fn make_error(&mut self, ret: c_int) -> Error {
4671 self.check_panic();
4672
4673 let code = self.ssl.get_error(ret);
4674
4675 let cause = match code {
4676 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4677 ErrorCode::SYSCALL => {
4678 let errs = ErrorStack::get();
4679 if errs.errors().is_empty() {
4680 self.get_bio_error().map(InnerError::Io)
4681 } else {
4682 Some(InnerError::Ssl(errs))
4683 }
4684 }
4685 ErrorCode::ZERO_RETURN => None,
4686 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4687 self.get_bio_error().map(InnerError::Io)
4688 }
4689 _ => None,
4690 };
4691
4692 Error { code, cause }
4693 }
4694
4695 fn check_panic(&mut self) {
4696 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4697 resume_unwind(err)
4698 }
4699 }
4700
4701 fn get_bio_error(&mut self) -> Option<io::Error> {
4702 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4703 }
4704
4705 pub fn get_ref(&self) -> &S {
4707 unsafe {
4708 let bio = self.ssl.get_raw_rbio();
4709 bio::get_ref(bio)
4710 }
4711 }
4712
4713 pub fn get_mut(&mut self) -> &mut S {
4720 unsafe {
4721 let bio = self.ssl.get_raw_rbio();
4722 bio::get_mut(bio)
4723 }
4724 }
4725
4726 pub fn ssl(&self) -> &SslRef {
4728 &self.ssl
4729 }
4730
4731 pub fn ssl_mut(&mut self) -> &mut SslRef {
4733 &mut self.ssl
4734 }
4735}
4736
4737impl<S: Read + Write> Read for SslStream<S> {
4738 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4739 unsafe {
4741 self.read_uninit(util::from_raw_parts_mut(
4742 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4743 buf.len(),
4744 ))
4745 }
4746 }
4747}
4748
4749impl<S: Read + Write> Write for SslStream<S> {
4750 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4751 loop {
4752 match self.ssl_write(buf) {
4753 Ok(n) => return Ok(n),
4754 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4755 Err(e) => {
4756 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4757 }
4758 }
4759 }
4760 }
4761
4762 fn flush(&mut self) -> io::Result<()> {
4763 self.get_mut().flush()
4764 }
4765}
4766
4767#[deprecated(
4769 since = "0.10.32",
4770 note = "use the methods directly on Ssl/SslStream instead"
4771)]
4772pub struct SslStreamBuilder<S> {
4773 inner: SslStream<S>,
4774}
4775
4776#[allow(deprecated)]
4777impl<S> SslStreamBuilder<S>
4778where
4779 S: Read + Write,
4780{
4781 pub fn new(ssl: Ssl, stream: S) -> Self {
4783 Self {
4784 inner: SslStream::new(ssl, stream).unwrap(),
4785 }
4786 }
4787
4788 #[corresponds(SSL_stateless)]
4799 #[cfg(ossl111)]
4800 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4801 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4802 1 => Ok(true),
4803 0 => Ok(false),
4804 -1 => Err(ErrorStack::get()),
4805 _ => unreachable!(),
4806 }
4807 }
4808
4809 #[corresponds(SSL_set_connect_state)]
4811 pub fn set_connect_state(&mut self) {
4812 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4813 }
4814
4815 #[corresponds(SSL_set_accept_state)]
4817 pub fn set_accept_state(&mut self) {
4818 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4819 }
4820
4821 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4823 match self.inner.connect() {
4824 Ok(()) => Ok(self.inner),
4825 Err(error) => match error.code() {
4826 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4827 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4828 stream: self.inner,
4829 error,
4830 }))
4831 }
4832 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4833 stream: self.inner,
4834 error,
4835 })),
4836 },
4837 }
4838 }
4839
4840 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4842 match self.inner.accept() {
4843 Ok(()) => Ok(self.inner),
4844 Err(error) => match error.code() {
4845 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4846 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4847 stream: self.inner,
4848 error,
4849 }))
4850 }
4851 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4852 stream: self.inner,
4853 error,
4854 })),
4855 },
4856 }
4857 }
4858
4859 #[corresponds(SSL_do_handshake)]
4863 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4864 match self.inner.do_handshake() {
4865 Ok(()) => Ok(self.inner),
4866 Err(error) => match error.code() {
4867 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4868 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4869 stream: self.inner,
4870 error,
4871 }))
4872 }
4873 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4874 stream: self.inner,
4875 error,
4876 })),
4877 },
4878 }
4879 }
4880
4881 #[corresponds(SSL_read_early_data)]
4891 #[cfg(any(ossl111, libressl))]
4892 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4893 self.inner.read_early_data(buf)
4894 }
4895
4896 #[corresponds(SSL_write_early_data)]
4903 #[cfg(any(ossl111, libressl))]
4904 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4905 self.inner.write_early_data(buf)
4906 }
4907}
4908
4909#[allow(deprecated)]
4910impl<S> SslStreamBuilder<S> {
4911 pub fn get_ref(&self) -> &S {
4913 unsafe {
4914 let bio = self.inner.ssl.get_raw_rbio();
4915 bio::get_ref(bio)
4916 }
4917 }
4918
4919 pub fn get_mut(&mut self) -> &mut S {
4926 unsafe {
4927 let bio = self.inner.ssl.get_raw_rbio();
4928 bio::get_mut(bio)
4929 }
4930 }
4931
4932 pub fn ssl(&self) -> &SslRef {
4934 &self.inner.ssl
4935 }
4936
4937 pub fn ssl_mut(&mut self) -> &mut SslRef {
4939 &mut self.inner.ssl
4940 }
4941}
4942
4943#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4945pub enum ShutdownResult {
4946 Sent,
4948
4949 Received,
4951}
4952
4953bitflags! {
4954 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4956 #[repr(transparent)]
4957 pub struct ShutdownState: c_int {
4958 const SENT = ffi::SSL_SENT_SHUTDOWN;
4960 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4962 }
4963}
4964
4965use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4966cfg_if! {
4967 if #[cfg(ossl300)] {
4968 use ffi::SSL_get1_peer_certificate;
4969 } else {
4970 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4971 }
4972}
4973use ffi::{
4974 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4975 TLS_server_method,
4976};
4977cfg_if! {
4978 if #[cfg(ossl110)] {
4979 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4980 ffi::CRYPTO_get_ex_new_index(
4981 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4982 0,
4983 ptr::null_mut(),
4984 None,
4985 None,
4986 f,
4987 )
4988 }
4989
4990 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4991 ffi::CRYPTO_get_ex_new_index(
4992 ffi::CRYPTO_EX_INDEX_SSL,
4993 0,
4994 ptr::null_mut(),
4995 None,
4996 None,
4997 f,
4998 )
4999 }
5000 } else {
5001 use std::sync::Once;
5002
5003 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5004 static ONCE: Once = Once::new();
5006 ONCE.call_once(|| {
5007 cfg_if! {
5008 if #[cfg(not(any(boringssl, awslc)))] {
5009 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5010 } else {
5011 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5012 }
5013 }
5014 });
5015
5016 cfg_if! {
5017 if #[cfg(not(any(boringssl, awslc)))] {
5018 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5019 } else {
5020 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5021 }
5022 }
5023 }
5024
5025 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5026 static ONCE: Once = Once::new();
5028 ONCE.call_once(|| {
5029 #[cfg(not(any(boringssl, awslc)))]
5030 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5031 #[cfg(any(boringssl, awslc))]
5032 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5033 });
5034
5035 #[cfg(not(any(boringssl, awslc)))]
5036 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5037 #[cfg(any(boringssl, awslc))]
5038 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5039 }
5040 }
5041}