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 #[cfg(not(any(boringssl, awslc)))]
451 const CLIENT_ONCE = ffi::SSL_VERIFY_CLIENT_ONCE;
452
453 #[cfg(ossl111)]
460 const POST_HANDSHAKE = ffi::SSL_VERIFY_POST_HANDSHAKE;
461 }
462}
463
464#[cfg(any(boringssl, awslc))]
465type SslBitType = c_int;
466#[cfg(not(any(boringssl, awslc)))]
467type SslBitType = c_long;
468
469#[cfg(any(boringssl, awslc))]
470type SslTimeTy = u64;
471#[cfg(not(any(boringssl, awslc)))]
472type SslTimeTy = c_long;
473
474bitflags! {
475 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
477 #[repr(transparent)]
478 pub struct SslSessionCacheMode: SslBitType {
479 const OFF = ffi::SSL_SESS_CACHE_OFF;
481
482 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
489
490 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
494
495 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
497
498 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
500
501 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
503
504 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
506
507 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
509 }
510}
511
512#[cfg(ossl111)]
513bitflags! {
514 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
516 #[repr(transparent)]
517 pub struct ExtensionContext: c_uint {
518 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
520 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
522 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
524 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
526 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
528 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
530 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
532 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
533 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
535 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
536 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
537 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
538 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
539 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
540 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
541 }
542}
543
544#[derive(Copy, Clone)]
546pub struct TlsExtType(c_uint);
547
548impl TlsExtType {
549 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
553
554 pub const ALPN: TlsExtType =
558 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
559
560 pub fn from_raw(raw: c_uint) -> TlsExtType {
562 TlsExtType(raw)
563 }
564
565 #[allow(clippy::trivially_copy_pass_by_ref)]
567 pub fn as_raw(&self) -> c_uint {
568 self.0
569 }
570}
571
572#[derive(Copy, Clone)]
574pub struct SslFiletype(c_int);
575
576impl SslFiletype {
577 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
581
582 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
586
587 pub fn from_raw(raw: c_int) -> SslFiletype {
589 SslFiletype(raw)
590 }
591
592 #[allow(clippy::trivially_copy_pass_by_ref)]
594 pub fn as_raw(&self) -> c_int {
595 self.0
596 }
597}
598
599#[derive(Copy, Clone)]
601pub struct StatusType(c_int);
602
603impl StatusType {
604 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
606
607 pub fn from_raw(raw: c_int) -> StatusType {
609 StatusType(raw)
610 }
611
612 #[allow(clippy::trivially_copy_pass_by_ref)]
614 pub fn as_raw(&self) -> c_int {
615 self.0
616 }
617}
618
619#[derive(Copy, Clone)]
621pub struct NameType(c_int);
622
623impl NameType {
624 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
626
627 pub fn from_raw(raw: c_int) -> StatusType {
629 StatusType(raw)
630 }
631
632 #[allow(clippy::trivially_copy_pass_by_ref)]
634 pub fn as_raw(&self) -> c_int {
635 self.0
636 }
637}
638
639static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
640 LazyLock::new(|| Mutex::new(HashMap::new()));
641static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
642 LazyLock::new(|| Mutex::new(HashMap::new()));
643static SESSION_CTX_INDEX: OnceLock<Index<Ssl, SslContext>> = OnceLock::new();
644
645fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
646 if let Some(idx) = SESSION_CTX_INDEX.get() {
649 return Ok(idx);
650 }
651 let new = Ssl::new_ex_index::<SslContext>()?;
652 Ok(SESSION_CTX_INDEX.get_or_init(|| new))
653}
654
655unsafe extern "C" fn free_data_box<T>(
656 _parent: *mut c_void,
657 ptr: *mut c_void,
658 _ad: *mut ffi::CRYPTO_EX_DATA,
659 _idx: c_int,
660 _argl: c_long,
661 _argp: *mut c_void,
662) {
663 if !ptr.is_null() {
664 let _ = Box::<T>::from_raw(ptr as *mut T);
665 }
666}
667
668#[derive(Debug, Copy, Clone, PartialEq, Eq)]
670pub struct SniError(c_int);
671
672impl SniError {
673 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
675
676 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
678
679 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
680}
681
682#[derive(Debug, Copy, Clone, PartialEq, Eq)]
684pub struct SslAlert(c_int);
685
686impl SslAlert {
687 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
689 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
690 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
691 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
692}
693
694#[derive(Debug, Copy, Clone, PartialEq, Eq)]
698pub struct AlpnError(c_int);
699
700impl AlpnError {
701 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
703
704 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
706}
707
708#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
712#[derive(Debug, Copy, Clone, PartialEq, Eq)]
713pub struct ClientHelloError(c_int);
714
715#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
716impl ClientHelloError {
717 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
719
720 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
722}
723
724#[derive(Debug, Copy, Clone, PartialEq, Eq)]
726pub struct TicketKeyStatus(c_int);
727
728impl TicketKeyStatus {
729 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
731 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
733 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
735}
736
737#[derive(Debug, Copy, Clone, PartialEq, Eq)]
739#[cfg(any(boringssl, awslc))]
740pub struct SelectCertError(ffi::ssl_select_cert_result_t);
741
742#[cfg(any(boringssl, awslc))]
743impl SelectCertError {
744 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
746
747 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
749
750 #[cfg(boringssl)]
756 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
757}
758
759#[cfg(ossl111)]
761#[derive(Debug, Copy, Clone, PartialEq, Eq)]
762pub struct SslCtValidationMode(c_int);
763
764#[cfg(ossl111)]
765impl SslCtValidationMode {
766 pub const PERMISSIVE: SslCtValidationMode =
767 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
768 pub const STRICT: SslCtValidationMode =
769 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
770}
771
772#[derive(Debug, Copy, Clone, PartialEq, Eq)]
774pub struct CertCompressionAlgorithm(c_int);
775
776impl CertCompressionAlgorithm {
777 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
778 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
779 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
780}
781
782#[derive(Debug, Copy, Clone, PartialEq, Eq)]
784pub struct SslVersion(c_int);
785
786impl SslVersion {
787 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
789
790 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
792
793 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
795
796 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
798
799 #[cfg(any(ossl111, libressl, boringssl, awslc))]
803 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
804
805 #[cfg(tongsuo)]
806 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
807
808 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
812
813 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
817}
818
819cfg_if! {
820 if #[cfg(any(boringssl, awslc))] {
821 type SslCacheTy = i64;
822 type SslCacheSize = libc::c_ulong;
823 type MtuTy = u32;
824 type ModeTy = u32;
825 type SizeTy = usize;
826 } else {
827 type SslCacheTy = i64;
828 type SslCacheSize = c_long;
829 type MtuTy = c_long;
830 type ModeTy = c_long;
831 type SizeTy = u32;
832 }
833}
834
835#[corresponds(SSL_select_next_proto)]
846pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
847 unsafe {
848 let mut out = ptr::null_mut();
849 let mut outlen = 0;
850 let r = ffi::SSL_select_next_proto(
851 &mut out,
852 &mut outlen,
853 server.as_ptr(),
854 server.len() as c_uint,
855 client.as_ptr(),
856 client.len() as c_uint,
857 );
858 if r == ffi::OPENSSL_NPN_NEGOTIATED {
859 Some(util::from_raw_parts(out as *const u8, outlen as usize))
860 } else {
861 None
862 }
863 }
864}
865
866pub struct SslContextBuilder(SslContext);
868
869impl SslContextBuilder {
870 #[corresponds(SSL_CTX_new)]
872 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
873 unsafe {
874 init();
875 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
876
877 Ok(SslContextBuilder::from_ptr(ctx))
878 }
879 }
880
881 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
887 SslContextBuilder(SslContext::from_ptr(ctx))
888 }
889
890 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
892 self.0.as_ptr()
893 }
894
895 #[cfg(tongsuo)]
896 #[corresponds(SSL_CTX_enable_ntls)]
897 pub fn enable_ntls(&mut self) {
898 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
899 }
900
901 #[cfg(tongsuo)]
902 #[corresponds(SSL_CTX_disable_ntls)]
903 pub fn disable_ntls(&mut self) {
904 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
905 }
906
907 #[cfg(all(tongsuo, ossl300))]
908 #[corresponds(SSL_CTX_enable_force_ntls)]
909 pub fn enable_force_ntls(&mut self) {
910 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
911 }
912
913 #[cfg(all(tongsuo, ossl300))]
914 #[corresponds(SSL_CTX_disable_force_ntls)]
915 pub fn disable_force_ntls(&mut self) {
916 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
917 }
918
919 #[cfg(tongsuo)]
920 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
921 pub fn enable_sm_tls13_strict(&mut self) {
922 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
923 }
924
925 #[cfg(tongsuo)]
926 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
927 pub fn disable_sm_tls13_strict(&mut self) {
928 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
929 }
930
931 #[corresponds(SSL_CTX_set_verify)]
933 pub fn set_verify(&mut self, mode: SslVerifyMode) {
934 unsafe {
935 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
936 }
937 }
938
939 #[corresponds(SSL_CTX_set_verify)]
946 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
947 where
948 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
949 {
950 unsafe {
951 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
952 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
953 }
954 }
955
956 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
964 pub fn set_servername_callback<F>(&mut self, callback: F)
966 where
967 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
968 {
969 unsafe {
970 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
976 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
977 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
978 }
979 }
980
981 #[corresponds(SSL_CTX_set_verify_depth)]
985 pub fn set_verify_depth(&mut self, depth: u32) {
986 unsafe {
987 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
988 }
989 }
990
991 #[corresponds(SSL_CTX_set0_verify_cert_store)]
995 #[cfg(any(ossl110, boringssl, awslc))]
996 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
997 unsafe {
998 let ptr = cert_store.as_ptr();
999 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
1000 mem::forget(cert_store);
1001
1002 Ok(())
1003 }
1004 }
1005
1006 #[corresponds(SSL_CTX_set_cert_store)]
1008 pub fn set_cert_store(&mut self, cert_store: X509Store) {
1009 unsafe {
1010 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
1011 mem::forget(cert_store);
1012 }
1013 }
1014
1015 #[corresponds(SSL_CTX_set_read_ahead)]
1022 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1023 unsafe {
1024 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1025 }
1026 }
1027
1028 #[corresponds(SSL_CTX_set_mode)]
1032 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1033 unsafe {
1034 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1035 SslMode::from_bits_retain(bits)
1036 }
1037 }
1038
1039 #[corresponds(SSL_CTX_clear_mode)]
1041 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1042 unsafe {
1043 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1044 SslMode::from_bits_retain(bits)
1045 }
1046 }
1047
1048 #[corresponds(SSL_CTX_get_mode)]
1050 pub fn mode(&self) -> SslMode {
1051 unsafe {
1052 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1053 SslMode::from_bits_retain(bits)
1054 }
1055 }
1056
1057 #[corresponds(SSL_CTX_set_dh_auto)]
1066 #[cfg(ossl300)]
1067 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1068 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
1069 }
1070
1071 #[corresponds(SSL_CTX_set_tmp_dh)]
1073 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1074 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1075 }
1076
1077 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1084 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1085 where
1086 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1087 {
1088 unsafe {
1089 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1090
1091 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1092 }
1093 }
1094
1095 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1097 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1098 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1099 }
1100
1101 #[corresponds(SSL_CTX_set_default_verify_paths)]
1106 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1107 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1108 }
1109
1110 #[corresponds(SSL_CTX_load_verify_locations)]
1114 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1115 self.load_verify_locations(Some(file.as_ref()), None)
1116 }
1117
1118 #[corresponds(SSL_CTX_load_verify_locations)]
1120 pub fn load_verify_locations(
1121 &mut self,
1122 ca_file: Option<&Path>,
1123 ca_path: Option<&Path>,
1124 ) -> Result<(), ErrorStack> {
1125 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1126 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1127 unsafe {
1128 cvt(ffi::SSL_CTX_load_verify_locations(
1129 self.as_ptr(),
1130 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1131 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1132 ))
1133 .map(|_| ())
1134 }
1135 }
1136
1137 #[corresponds(SSL_CTX_set_client_CA_list)]
1142 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1143 unsafe {
1144 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1145 mem::forget(list);
1146 }
1147 }
1148
1149 #[corresponds(SSL_CTX_add_client_CA)]
1152 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1153 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1154 }
1155
1156 #[corresponds(SSL_CTX_set_session_id_context)]
1165 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1166 unsafe {
1167 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1168 cvt(ffi::SSL_CTX_set_session_id_context(
1169 self.as_ptr(),
1170 sid_ctx.as_ptr(),
1171 sid_ctx.len() as SizeTy,
1172 ))
1173 .map(|_| ())
1174 }
1175 }
1176
1177 #[corresponds(SSL_CTX_use_certificate_file)]
1183 pub fn set_certificate_file<P: AsRef<Path>>(
1184 &mut self,
1185 file: P,
1186 file_type: SslFiletype,
1187 ) -> Result<(), ErrorStack> {
1188 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1189 unsafe {
1190 cvt(ffi::SSL_CTX_use_certificate_file(
1191 self.as_ptr(),
1192 file.as_ptr() as *const _,
1193 file_type.as_raw(),
1194 ))
1195 .map(|_| ())
1196 }
1197 }
1198
1199 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1205 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1206 &mut self,
1207 file: P,
1208 ) -> Result<(), ErrorStack> {
1209 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1210 unsafe {
1211 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1212 self.as_ptr(),
1213 file.as_ptr() as *const _,
1214 ))
1215 .map(|_| ())
1216 }
1217 }
1218
1219 #[corresponds(SSL_CTX_use_certificate)]
1223 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1224 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1225 }
1226
1227 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1232 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1233 unsafe {
1234 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1235 mem::forget(cert);
1236 Ok(())
1237 }
1238 }
1239
1240 #[cfg(tongsuo)]
1241 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1242 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1243 &mut self,
1244 file: P,
1245 file_type: SslFiletype,
1246 ) -> Result<(), ErrorStack> {
1247 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1248 unsafe {
1249 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1250 self.as_ptr(),
1251 file.as_ptr() as *const _,
1252 file_type.as_raw(),
1253 ))
1254 .map(|_| ())
1255 }
1256 }
1257
1258 #[cfg(tongsuo)]
1259 #[corresponds(SSL_CTX_use_enc_certificate)]
1260 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1261 unsafe {
1262 cvt(ffi::SSL_CTX_use_enc_certificate(
1263 self.as_ptr(),
1264 cert.as_ptr(),
1265 ))
1266 .map(|_| ())
1267 }
1268 }
1269
1270 #[cfg(tongsuo)]
1271 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1272 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1273 &mut self,
1274 file: P,
1275 file_type: SslFiletype,
1276 ) -> Result<(), ErrorStack> {
1277 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1278 unsafe {
1279 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1280 self.as_ptr(),
1281 file.as_ptr() as *const _,
1282 file_type.as_raw(),
1283 ))
1284 .map(|_| ())
1285 }
1286 }
1287
1288 #[cfg(tongsuo)]
1289 #[corresponds(SSL_CTX_use_sign_certificate)]
1290 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1291 unsafe {
1292 cvt(ffi::SSL_CTX_use_sign_certificate(
1293 self.as_ptr(),
1294 cert.as_ptr(),
1295 ))
1296 .map(|_| ())
1297 }
1298 }
1299
1300 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1302 pub fn set_private_key_file<P: AsRef<Path>>(
1303 &mut self,
1304 file: P,
1305 file_type: SslFiletype,
1306 ) -> Result<(), ErrorStack> {
1307 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1308 unsafe {
1309 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1310 self.as_ptr(),
1311 file.as_ptr() as *const _,
1312 file_type.as_raw(),
1313 ))
1314 .map(|_| ())
1315 }
1316 }
1317
1318 #[corresponds(SSL_CTX_use_PrivateKey)]
1320 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1321 where
1322 T: HasPrivate,
1323 {
1324 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1325 }
1326
1327 #[cfg(tongsuo)]
1328 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1329 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1330 &mut self,
1331 file: P,
1332 file_type: SslFiletype,
1333 ) -> Result<(), ErrorStack> {
1334 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1335 unsafe {
1336 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1337 self.as_ptr(),
1338 file.as_ptr() as *const _,
1339 file_type.as_raw(),
1340 ))
1341 .map(|_| ())
1342 }
1343 }
1344
1345 #[cfg(tongsuo)]
1346 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1347 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1348 where
1349 T: HasPrivate,
1350 {
1351 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1352 }
1353
1354 #[cfg(tongsuo)]
1355 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1356 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1357 &mut self,
1358 file: P,
1359 file_type: SslFiletype,
1360 ) -> Result<(), ErrorStack> {
1361 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1362 unsafe {
1363 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1364 self.as_ptr(),
1365 file.as_ptr() as *const _,
1366 file_type.as_raw(),
1367 ))
1368 .map(|_| ())
1369 }
1370 }
1371
1372 #[cfg(tongsuo)]
1373 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1374 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1375 where
1376 T: HasPrivate,
1377 {
1378 unsafe {
1379 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1380 self.as_ptr(),
1381 key.as_ptr(),
1382 ))
1383 .map(|_| ())
1384 }
1385 }
1386
1387 #[corresponds(SSL_CTX_set_cipher_list)]
1395 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1396 let cipher_list = CString::new(cipher_list).unwrap();
1397 unsafe {
1398 cvt(ffi::SSL_CTX_set_cipher_list(
1399 self.as_ptr(),
1400 cipher_list.as_ptr() as *const _,
1401 ))
1402 .map(|_| ())
1403 }
1404 }
1405
1406 #[corresponds(SSL_CTX_set_ciphersuites)]
1415 #[cfg(any(ossl111, libressl, awslc))]
1416 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1417 let cipher_list = CString::new(cipher_list).unwrap();
1418 unsafe {
1419 cvt(ffi::SSL_CTX_set_ciphersuites(
1420 self.as_ptr(),
1421 cipher_list.as_ptr() as *const _,
1422 ))
1423 .map(|_| ())
1424 }
1425 }
1426
1427 #[corresponds(SSL_CTX_set_ecdh_auto)]
1431 #[cfg(libressl)]
1432 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1433 unsafe {
1434 cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ())
1435 }
1436 }
1437
1438 #[corresponds(SSL_CTX_set_options)]
1445 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1446 let bits =
1447 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1448 SslOptions::from_bits_retain(bits)
1449 }
1450
1451 #[corresponds(SSL_CTX_get_options)]
1453 pub fn options(&self) -> SslOptions {
1454 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1455 SslOptions::from_bits_retain(bits)
1456 }
1457
1458 #[corresponds(SSL_CTX_clear_options)]
1460 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1461 let bits =
1462 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1463 SslOptions::from_bits_retain(bits)
1464 }
1465
1466 #[corresponds(SSL_CTX_set_min_proto_version)]
1471 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1472 unsafe {
1473 cvt(ffi::SSL_CTX_set_min_proto_version(
1474 self.as_ptr(),
1475 version.map_or(0, |v| v.0 as _),
1476 ))
1477 .map(|_| ())
1478 }
1479 }
1480
1481 #[corresponds(SSL_CTX_set_max_proto_version)]
1486 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1487 unsafe {
1488 cvt(ffi::SSL_CTX_set_max_proto_version(
1489 self.as_ptr(),
1490 version.map_or(0, |v| v.0 as _),
1491 ))
1492 .map(|_| ())
1493 }
1494 }
1495
1496 #[corresponds(SSL_CTX_get_min_proto_version)]
1503 #[cfg(any(ossl110g, libressl))]
1504 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1505 unsafe {
1506 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1507 if r == 0 {
1508 None
1509 } else {
1510 Some(SslVersion(r))
1511 }
1512 }
1513 }
1514
1515 #[corresponds(SSL_CTX_get_max_proto_version)]
1522 #[cfg(any(ossl110g, libressl))]
1523 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1524 unsafe {
1525 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1526 if r == 0 {
1527 None
1528 } else {
1529 Some(SslVersion(r))
1530 }
1531 }
1532 }
1533
1534 #[corresponds(SSL_CTX_set_alpn_protos)]
1543 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1544 unsafe {
1545 assert!(protocols.len() <= c_uint::MAX as usize);
1546 let r = ffi::SSL_CTX_set_alpn_protos(
1547 self.as_ptr(),
1548 protocols.as_ptr(),
1549 protocols.len() as _,
1550 );
1551 if r == 0 {
1553 Ok(())
1554 } else {
1555 Err(ErrorStack::get())
1556 }
1557 }
1558 }
1559
1560 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1562 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1563 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1564 unsafe {
1565 let cstr = CString::new(protocols).unwrap();
1566
1567 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1568 if r == 0 {
1570 Ok(())
1571 } else {
1572 Err(ErrorStack::get())
1573 }
1574 }
1575 }
1576
1577 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1588 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1589 where
1590 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1591 {
1592 unsafe {
1593 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1594 ffi::SSL_CTX_set_alpn_select_cb(
1595 self.as_ptr(),
1596 Some(callbacks::raw_alpn_select::<F>),
1597 ptr::null_mut(),
1598 );
1599 }
1600 }
1601
1602 #[corresponds(SSL_CTX_check_private_key)]
1604 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1605 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1606 }
1607
1608 #[corresponds(SSL_CTX_get_cert_store)]
1610 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1611 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1612 }
1613
1614 #[corresponds(SSL_CTX_get_cert_store)]
1616 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1617 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1618 }
1619
1620 #[corresponds(SSL_CTX_get0_param)]
1624 pub fn verify_param(&self) -> &X509VerifyParamRef {
1625 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1626 }
1627
1628 #[corresponds(SSL_CTX_get0_param)]
1632 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1633 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1634 }
1635
1636 #[cfg(any(boringssl, tongsuo, awslc))]
1644 pub fn add_cert_decompression_alg<F>(
1645 &mut self,
1646 alg_id: CertCompressionAlgorithm,
1647 decompress: F,
1648 ) -> Result<(), ErrorStack>
1649 where
1650 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1651 {
1652 unsafe {
1653 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1654 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1655 self.as_ptr(),
1656 alg_id.0 as _,
1657 None,
1658 Some(raw_cert_decompression::<F>),
1659 ))
1660 .map(|_| ())
1661 }
1662 }
1663
1664 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1666 #[cfg(ossl320)]
1667 pub fn set_cert_comp_preference(
1668 &mut self,
1669 algs: &[CertCompressionAlgorithm],
1670 ) -> Result<(), ErrorStack> {
1671 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1672 unsafe {
1673 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1674 self.as_ptr(),
1675 algs.as_mut_ptr(),
1676 algs.len(),
1677 ))
1678 .map(|_| ())
1679 }
1680 }
1681
1682 #[cfg(any(boringssl, awslc))]
1690 pub fn enable_ocsp_stapling(&mut self) {
1691 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1692 }
1693
1694 #[cfg(any(boringssl, awslc))]
1702 pub fn enable_signed_cert_timestamps(&mut self) {
1703 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1704 }
1705
1706 #[cfg(any(boringssl, awslc))]
1714 pub fn set_grease_enabled(&mut self, enabled: bool) {
1715 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1716 }
1717
1718 #[cfg(any(boringssl, awslc))]
1726 pub fn set_permute_extensions(&mut self, enabled: bool) {
1727 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1728 }
1729
1730 #[corresponds(SSL_CTX_enable_ct)]
1732 #[cfg(ossl111)]
1733 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1734 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1735 }
1736
1737 #[corresponds(SSL_CTX_ct_is_enabled)]
1739 #[cfg(ossl111)]
1740 pub fn ct_is_enabled(&self) -> bool {
1741 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1742 }
1743
1744 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1746 #[cfg(not(any(boringssl, awslc)))]
1747 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1748 unsafe {
1749 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1750 .map(|_| ())
1751 }
1752 }
1753
1754 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1767 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1768 where
1769 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1770 {
1771 unsafe {
1772 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1773 cvt(
1774 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1775 as c_int,
1776 )
1777 .map(|_| ())
1778 }
1779 }
1780
1781 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1782 #[cfg(ossl300)]
1783 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1784 where
1785 F: Fn(
1786 &mut SslRef,
1787 &mut [u8],
1788 &mut [u8],
1789 &mut CipherCtxRef,
1790 &mut MacCtxRef,
1791 bool,
1792 ) -> Result<TicketKeyStatus, ErrorStack>
1793 + 'static
1794 + Sync
1795 + Send,
1796 {
1797 unsafe {
1798 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1799 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1800 self.as_ptr(),
1801 Some(raw_tlsext_ticket_key_evp::<F>),
1802 ) as c_int)
1803 .map(|_| ())
1804 }
1805 }
1806
1807 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1808 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1809 where
1810 F: Fn(
1811 &mut SslRef,
1812 &mut [u8],
1813 &mut [u8],
1814 &mut CipherCtxRef,
1815 &mut HMacCtxRef,
1816 bool,
1817 ) -> Result<TicketKeyStatus, ErrorStack>
1818 + 'static
1819 + Sync
1820 + Send,
1821 {
1822 unsafe {
1823 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1824 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1825 self.as_ptr(),
1826 Some(raw_tlsext_ticket_key::<F>),
1827 ) as c_int)
1828 .map(|_| ())
1829 }
1830 }
1831
1832 #[corresponds(SSL_CTX_set_psk_client_callback)]
1838 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1839 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1840 where
1841 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1842 + 'static
1843 + Sync
1844 + Send,
1845 {
1846 unsafe {
1847 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1848 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1849 }
1850 }
1851
1852 #[corresponds(SSL_CTX_set_psk_server_callback)]
1858 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1859 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1860 where
1861 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1862 + 'static
1863 + Sync
1864 + Send,
1865 {
1866 unsafe {
1867 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1868 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1869 }
1870 }
1871
1872 #[corresponds(SSL_CTX_sess_set_new_cb)]
1886 pub fn set_new_session_callback<F>(&mut self, callback: F)
1887 where
1888 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1889 {
1890 unsafe {
1891 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1892 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1893 }
1894 }
1895
1896 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1900 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1901 where
1902 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1903 {
1904 unsafe {
1905 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1906 ffi::SSL_CTX_sess_set_remove_cb(
1907 self.as_ptr(),
1908 Some(callbacks::raw_remove_session::<F>),
1909 );
1910 }
1911 }
1912
1913 #[corresponds(SSL_CTX_sess_set_get_cb)]
1924 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1925 where
1926 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1927 {
1928 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1929 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1930 }
1931
1932 #[corresponds(SSL_CTX_set_keylog_callback)]
1940 #[cfg(any(ossl111, boringssl, awslc))]
1941 pub fn set_keylog_callback<F>(&mut self, callback: F)
1942 where
1943 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1944 {
1945 unsafe {
1946 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1947 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1948 }
1949 }
1950
1951 #[corresponds(SSL_CTX_set_session_cache_mode)]
1955 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1956 unsafe {
1957 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1958 SslSessionCacheMode::from_bits_retain(bits)
1959 }
1960 }
1961
1962 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1968 #[cfg(ossl111)]
1969 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1970 where
1971 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1972 {
1973 unsafe {
1974 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1975 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1976 self.as_ptr(),
1977 Some(raw_stateless_cookie_generate::<F>),
1978 );
1979 }
1980 }
1981
1982 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1991 #[cfg(ossl111)]
1992 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1993 where
1994 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1995 {
1996 unsafe {
1997 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1998 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1999 self.as_ptr(),
2000 Some(raw_stateless_cookie_verify::<F>),
2001 )
2002 }
2003 }
2004
2005 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
2010 #[cfg(not(any(boringssl, awslc)))]
2011 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
2012 where
2013 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
2014 {
2015 unsafe {
2016 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2017 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2018 }
2019 }
2020
2021 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2026 #[cfg(not(any(boringssl, awslc)))]
2027 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2028 where
2029 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2030 {
2031 unsafe {
2032 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2033 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2034 }
2035 }
2036
2037 #[corresponds(SSL_CTX_set_ex_data)]
2043 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2044 self.set_ex_data_inner(index, data);
2045 }
2046
2047 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2048 match self.ex_data_mut(index) {
2049 Some(v) => {
2050 *v = data;
2051 (v as *mut T).cast()
2052 }
2053 _ => unsafe {
2054 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2055 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2056 data
2057 },
2058 }
2059 }
2060
2061 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2062 unsafe {
2063 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2064 if data.is_null() {
2065 None
2066 } else {
2067 Some(&mut *data.cast())
2068 }
2069 }
2070 }
2071
2072 #[corresponds(SSL_CTX_add_custom_ext)]
2076 #[cfg(ossl111)]
2077 pub fn add_custom_ext<AddFn, ParseFn, T>(
2078 &mut self,
2079 ext_type: u16,
2080 context: ExtensionContext,
2081 add_cb: AddFn,
2082 parse_cb: ParseFn,
2083 ) -> Result<(), ErrorStack>
2084 where
2085 AddFn: Fn(
2086 &mut SslRef,
2087 ExtensionContext,
2088 Option<(usize, &X509Ref)>,
2089 ) -> Result<Option<T>, SslAlert>
2090 + 'static
2091 + Sync
2092 + Send,
2093 T: AsRef<[u8]> + 'static + Sync + Send,
2094 ParseFn: Fn(
2095 &mut SslRef,
2096 ExtensionContext,
2097 &[u8],
2098 Option<(usize, &X509Ref)>,
2099 ) -> Result<(), SslAlert>
2100 + 'static
2101 + Sync
2102 + Send,
2103 {
2104 let ret = unsafe {
2105 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2106 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2107
2108 ffi::SSL_CTX_add_custom_ext(
2109 self.as_ptr(),
2110 ext_type as c_uint,
2111 context.bits(),
2112 Some(raw_custom_ext_add::<AddFn, T>),
2113 Some(raw_custom_ext_free::<T>),
2114 ptr::null_mut(),
2115 Some(raw_custom_ext_parse::<ParseFn>),
2116 ptr::null_mut(),
2117 )
2118 };
2119 if ret == 1 {
2120 Ok(())
2121 } else {
2122 Err(ErrorStack::get())
2123 }
2124 }
2125
2126 #[corresponds(SSL_CTX_set_max_early_data)]
2132 #[cfg(any(ossl111, libressl))]
2133 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2134 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2135 Ok(())
2136 } else {
2137 Err(ErrorStack::get())
2138 }
2139 }
2140
2141 #[cfg(any(boringssl, awslc))]
2151 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2152 where
2153 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2154 {
2155 unsafe {
2156 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2157 ffi::SSL_CTX_set_select_certificate_cb(
2158 self.as_ptr(),
2159 Some(callbacks::raw_select_cert::<F>),
2160 );
2161 }
2162 }
2163
2164 #[corresponds(SSL_CTX_set_client_hello_cb)]
2168 #[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
2169 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2170 where
2171 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2172 {
2173 unsafe {
2174 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2175 ffi::SSL_CTX_set_client_hello_cb(
2176 self.as_ptr(),
2177 Some(callbacks::raw_client_hello::<F>),
2178 ptr,
2179 );
2180 }
2181 }
2182
2183 #[corresponds(SSL_CTX_set_info_callback)]
2186 pub fn set_info_callback<F>(&mut self, callback: F)
2187 where
2188 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2189 {
2190 unsafe {
2191 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2192 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2193 }
2194 }
2195
2196 #[corresponds(SSL_CTX_sess_set_cache_size)]
2200 #[allow(clippy::useless_conversion)]
2201 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2202 unsafe {
2203 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2204 }
2205 }
2206
2207 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2211 #[cfg(ossl110)]
2212 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2213 let sigalgs = CString::new(sigalgs).unwrap();
2214 unsafe {
2215 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2216 .map(|_| ())
2217 }
2218 }
2219
2220 #[corresponds(SSL_CTX_set1_groups_list)]
2224 #[cfg(any(ossl111, boringssl, libressl, awslc))]
2225 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2226 let groups = CString::new(groups).unwrap();
2227 unsafe {
2228 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2229 }
2230 }
2231
2232 #[corresponds(SSL_CTX_set_num_tickets)]
2237 #[cfg(any(ossl111, boringssl, awslc))]
2238 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2239 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2240 }
2241
2242 #[corresponds(SSL_CTX_set_security_level)]
2247 #[cfg(any(ossl110, libressl360))]
2248 pub fn set_security_level(&mut self, level: u32) {
2249 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2250 }
2251
2252 pub fn build(self) -> SslContext {
2254 self.0
2255 }
2256}
2257
2258foreign_type_and_impl_send_sync! {
2259 type CType = ffi::SSL_CTX;
2260 fn drop = ffi::SSL_CTX_free;
2261
2262 pub struct SslContext;
2267
2268 pub struct SslContextRef;
2272}
2273
2274impl Clone for SslContext {
2275 fn clone(&self) -> Self {
2276 (**self).to_owned()
2277 }
2278}
2279
2280impl ToOwned for SslContextRef {
2281 type Owned = SslContext;
2282
2283 fn to_owned(&self) -> Self::Owned {
2284 unsafe {
2285 let r = SSL_CTX_up_ref(self.as_ptr());
2286 assert!(r == 1);
2287 SslContext::from_ptr(self.as_ptr())
2288 }
2289 }
2290}
2291
2292impl fmt::Debug for SslContext {
2294 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2295 write!(fmt, "SslContext")
2296 }
2297}
2298
2299impl SslContext {
2300 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2302 SslContextBuilder::new(method)
2303 }
2304
2305 #[corresponds(SSL_CTX_get_ex_new_index)]
2310 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2311 where
2312 T: 'static + Sync + Send,
2313 {
2314 unsafe {
2315 ffi::init();
2316 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2317 Ok(Index::from_raw(idx))
2318 }
2319 }
2320
2321 fn cached_ex_index<T>() -> Index<SslContext, T>
2323 where
2324 T: 'static + Sync + Send,
2325 {
2326 unsafe {
2327 let idx = *INDEXES
2328 .lock()
2329 .unwrap_or_else(|e| e.into_inner())
2330 .entry(TypeId::of::<T>())
2331 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2332 Index::from_raw(idx)
2333 }
2334 }
2335}
2336
2337impl SslContextRef {
2338 #[corresponds(SSL_CTX_get0_certificate)]
2342 #[cfg(any(ossl110, libressl))]
2343 pub fn certificate(&self) -> Option<&X509Ref> {
2344 unsafe {
2345 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2346 X509Ref::from_const_ptr_opt(ptr)
2347 }
2348 }
2349
2350 #[corresponds(SSL_CTX_get0_privatekey)]
2354 #[cfg(any(ossl110, libressl))]
2355 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2356 unsafe {
2357 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2358 PKeyRef::from_const_ptr_opt(ptr)
2359 }
2360 }
2361
2362 #[corresponds(SSL_CTX_get_cert_store)]
2364 pub fn cert_store(&self) -> &X509StoreRef {
2365 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2366 }
2367
2368 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2370 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2371 unsafe {
2372 let mut chain = ptr::null_mut();
2373 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2374 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2375 }
2376 }
2377
2378 #[corresponds(SSL_CTX_get_ex_data)]
2380 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2381 unsafe {
2382 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2383 if data.is_null() {
2384 None
2385 } else {
2386 Some(&*(data as *const T))
2387 }
2388 }
2389 }
2390
2391 #[corresponds(SSL_CTX_get_max_early_data)]
2395 #[cfg(any(ossl111, libressl))]
2396 pub fn max_early_data(&self) -> u32 {
2397 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2398 }
2399
2400 #[corresponds(SSL_CTX_add_session)]
2409 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2410 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2411 }
2412
2413 #[corresponds(SSL_CTX_remove_session)]
2422 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2423 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2424 }
2425
2426 #[corresponds(SSL_CTX_sess_get_cache_size)]
2430 #[allow(clippy::unnecessary_cast)]
2431 pub fn session_cache_size(&self) -> i64 {
2432 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2433 }
2434
2435 #[corresponds(SSL_CTX_get_verify_mode)]
2439 pub fn verify_mode(&self) -> SslVerifyMode {
2440 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2441 SslVerifyMode::from_bits_retain(mode)
2442 }
2443
2444 #[corresponds(SSL_CTX_get_num_tickets)]
2449 #[cfg(ossl111)]
2450 pub fn num_tickets(&self) -> usize {
2451 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2452 }
2453
2454 #[corresponds(SSL_CTX_get_security_level)]
2459 #[cfg(any(ossl110, libressl360))]
2460 pub fn security_level(&self) -> u32 {
2461 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2462 }
2463}
2464
2465pub struct CipherBits {
2467 pub secret: i32,
2469
2470 pub algorithm: i32,
2472}
2473
2474pub struct SslCipher(*mut ffi::SSL_CIPHER);
2476
2477impl ForeignType for SslCipher {
2478 type CType = ffi::SSL_CIPHER;
2479 type Ref = SslCipherRef;
2480
2481 #[inline]
2482 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2483 SslCipher(ptr)
2484 }
2485
2486 #[inline]
2487 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2488 self.0
2489 }
2490}
2491
2492impl Stackable for SslCipher {
2493 type StackType = ffi::stack_st_SSL_CIPHER;
2494}
2495
2496impl Deref for SslCipher {
2497 type Target = SslCipherRef;
2498
2499 fn deref(&self) -> &SslCipherRef {
2500 unsafe { SslCipherRef::from_ptr(self.0) }
2501 }
2502}
2503
2504impl DerefMut for SslCipher {
2505 fn deref_mut(&mut self) -> &mut SslCipherRef {
2506 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2507 }
2508}
2509
2510pub struct SslCipherRef(Opaque);
2514
2515impl ForeignTypeRef for SslCipherRef {
2516 type CType = ffi::SSL_CIPHER;
2517}
2518
2519impl SslCipherRef {
2520 #[corresponds(SSL_CIPHER_get_name)]
2522 pub fn name(&self) -> &'static str {
2523 unsafe {
2524 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2525 CStr::from_ptr(ptr).to_str().unwrap()
2526 }
2527 }
2528
2529 #[corresponds(SSL_CIPHER_standard_name)]
2533 #[cfg(ossl111)]
2534 pub fn standard_name(&self) -> Option<&'static str> {
2535 unsafe {
2536 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2537 if ptr.is_null() {
2538 None
2539 } else {
2540 Some(CStr::from_ptr(ptr).to_str().unwrap())
2541 }
2542 }
2543 }
2544
2545 #[corresponds(SSL_CIPHER_get_version)]
2547 pub fn version(&self) -> &'static str {
2548 let version = unsafe {
2549 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2550 CStr::from_ptr(ptr as *const _)
2551 };
2552
2553 str::from_utf8(version.to_bytes()).unwrap()
2554 }
2555
2556 #[corresponds(SSL_CIPHER_get_bits)]
2558 #[allow(clippy::useless_conversion)]
2559 pub fn bits(&self) -> CipherBits {
2560 unsafe {
2561 let mut algo_bits = 0;
2562 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2563 CipherBits {
2564 secret: secret_bits.into(),
2565 algorithm: algo_bits.into(),
2566 }
2567 }
2568 }
2569
2570 #[corresponds(SSL_CIPHER_description)]
2572 pub fn description(&self) -> String {
2573 unsafe {
2574 let mut buf = [0; 128];
2576 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2577 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2578 }
2579 }
2580
2581 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2585 #[cfg(ossl111)]
2586 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2587 unsafe {
2588 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2589 if ptr.is_null() {
2590 None
2591 } else {
2592 Some(MessageDigest::from_ptr(ptr))
2593 }
2594 }
2595 }
2596
2597 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2601 #[cfg(any(ossl110, libressl))]
2602 pub fn cipher_nid(&self) -> Option<Nid> {
2603 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2604 if n == 0 {
2605 None
2606 } else {
2607 Some(Nid::from_raw(n))
2608 }
2609 }
2610
2611 #[corresponds(SSL_CIPHER_get_protocol_id)]
2615 #[cfg(ossl111)]
2616 pub fn protocol_id(&self) -> [u8; 2] {
2617 unsafe {
2618 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2619 id.to_be_bytes()
2620 }
2621 }
2622}
2623
2624impl fmt::Debug for SslCipherRef {
2625 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2626 write!(fmt, "{}", self.name())
2627 }
2628}
2629
2630#[derive(Debug)]
2632pub struct CipherLists {
2633 pub suites: Stack<SslCipher>,
2634 pub signalling_suites: Stack<SslCipher>,
2635}
2636
2637foreign_type_and_impl_send_sync! {
2638 type CType = ffi::SSL_SESSION;
2639 fn drop = ffi::SSL_SESSION_free;
2640
2641 pub struct SslSession;
2645
2646 pub struct SslSessionRef;
2650}
2651
2652impl Clone for SslSession {
2653 fn clone(&self) -> SslSession {
2654 SslSessionRef::to_owned(self)
2655 }
2656}
2657
2658impl SslSession {
2659 from_der! {
2660 #[corresponds(d2i_SSL_SESSION)]
2662 from_der,
2663 SslSession,
2664 ffi::d2i_SSL_SESSION
2665 }
2666}
2667
2668impl ToOwned for SslSessionRef {
2669 type Owned = SslSession;
2670
2671 fn to_owned(&self) -> SslSession {
2672 unsafe {
2673 let r = SSL_SESSION_up_ref(self.as_ptr());
2674 assert!(r == 1);
2675 SslSession(self.as_ptr())
2676 }
2677 }
2678}
2679
2680impl SslSessionRef {
2681 #[corresponds(SSL_SESSION_get_id)]
2683 pub fn id(&self) -> &[u8] {
2684 unsafe {
2685 let mut len = 0;
2686 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2687 #[allow(clippy::unnecessary_cast)]
2688 util::from_raw_parts(p as *const u8, len as usize)
2689 }
2690 }
2691
2692 #[corresponds(SSL_SESSION_get_master_key)]
2694 pub fn master_key_len(&self) -> usize {
2695 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2696 }
2697
2698 #[corresponds(SSL_SESSION_get_master_key)]
2702 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2703 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2704 }
2705
2706 #[corresponds(SSL_SESSION_get_max_early_data)]
2710 #[cfg(any(ossl111, libressl))]
2711 pub fn max_early_data(&self) -> u32 {
2712 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2713 }
2714
2715 #[corresponds(SSL_SESSION_get_time)]
2717 #[allow(clippy::useless_conversion)]
2718 pub fn time(&self) -> SslTimeTy {
2719 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2720 }
2721
2722 #[corresponds(SSL_SESSION_get_timeout)]
2726 #[allow(clippy::useless_conversion)]
2727 pub fn timeout(&self) -> i64 {
2728 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2729 }
2730
2731 #[corresponds(SSL_SESSION_get_protocol_version)]
2735 #[cfg(any(ossl110, libressl))]
2736 pub fn protocol_version(&self) -> SslVersion {
2737 unsafe {
2738 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2739 SslVersion(version)
2740 }
2741 }
2742
2743 #[corresponds(SSL_SESSION_get_protocol_version)]
2745 #[cfg(any(boringssl, awslc))]
2746 pub fn protocol_version(&self) -> SslVersion {
2747 unsafe {
2748 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2749 SslVersion(version as _)
2750 }
2751 }
2752
2753 to_der! {
2754 #[corresponds(i2d_SSL_SESSION)]
2756 to_der,
2757 ffi::i2d_SSL_SESSION
2758 }
2759}
2760
2761foreign_type_and_impl_send_sync! {
2762 type CType = ffi::SSL;
2763 fn drop = ffi::SSL_free;
2764
2765 pub struct Ssl;
2772
2773 pub struct SslRef;
2777}
2778
2779impl fmt::Debug for Ssl {
2780 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2781 fmt::Debug::fmt(&**self, fmt)
2782 }
2783}
2784
2785impl Ssl {
2786 #[corresponds(SSL_get_ex_new_index)]
2791 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2792 where
2793 T: 'static + Sync + Send,
2794 {
2795 unsafe {
2796 ffi::init();
2797 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2798 Ok(Index::from_raw(idx))
2799 }
2800 }
2801
2802 fn cached_ex_index<T>() -> Index<Ssl, T>
2804 where
2805 T: 'static + Sync + Send,
2806 {
2807 unsafe {
2808 let idx = *SSL_INDEXES
2809 .lock()
2810 .unwrap_or_else(|e| e.into_inner())
2811 .entry(TypeId::of::<T>())
2812 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2813 Index::from_raw(idx)
2814 }
2815 }
2816
2817 #[corresponds(SSL_new)]
2819 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2820 let session_ctx_index = try_get_session_ctx_index()?;
2821 unsafe {
2822 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2823 let mut ssl = Ssl::from_ptr(ptr);
2824 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2825
2826 Ok(ssl)
2827 }
2828 }
2829
2830 #[corresponds(SSL_connect)]
2836 #[allow(deprecated)]
2837 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2838 where
2839 S: Read + Write,
2840 {
2841 SslStreamBuilder::new(self, stream).connect()
2842 }
2843
2844 #[corresponds(SSL_accept)]
2851 #[allow(deprecated)]
2852 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2853 where
2854 S: Read + Write,
2855 {
2856 SslStreamBuilder::new(self, stream).accept()
2857 }
2858}
2859
2860impl fmt::Debug for SslRef {
2861 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2862 fmt.debug_struct("Ssl")
2863 .field("state", &self.state_string_long())
2864 .field("verify_result", &self.verify_result())
2865 .finish()
2866 }
2867}
2868
2869impl SslRef {
2870 #[cfg(not(feature = "tongsuo"))]
2871 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2872 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2873 }
2874
2875 #[cfg(feature = "tongsuo")]
2876 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2877 unsafe {
2878 let bio = ffi::SSL_get_rbio(self.as_ptr());
2879 bio::find_correct_bio(bio)
2880 }
2881 }
2882
2883 fn get_error(&self, ret: c_int) -> ErrorCode {
2884 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2885 }
2886
2887 #[corresponds(SSL_set_mode)]
2891 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2892 unsafe {
2893 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2894 SslMode::from_bits_retain(bits)
2895 }
2896 }
2897
2898 #[corresponds(SSL_clear_mode)]
2900 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2901 unsafe {
2902 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2903 SslMode::from_bits_retain(bits)
2904 }
2905 }
2906
2907 #[corresponds(SSL_get_mode)]
2909 pub fn mode(&self) -> SslMode {
2910 unsafe {
2911 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2912 SslMode::from_bits_retain(bits)
2913 }
2914 }
2915
2916 #[corresponds(SSL_set_connect_state)]
2918 pub fn set_connect_state(&mut self) {
2919 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2920 }
2921
2922 #[corresponds(SSL_set_accept_state)]
2924 pub fn set_accept_state(&mut self) {
2925 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2926 }
2927
2928 #[cfg(any(boringssl, awslc))]
2929 #[corresponds(SSL_ech_accepted)]
2930 pub fn ech_accepted(&self) -> bool {
2931 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2932 }
2933
2934 #[cfg(tongsuo)]
2935 #[corresponds(SSL_is_ntls)]
2936 pub fn is_ntls(&mut self) -> bool {
2937 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2938 }
2939
2940 #[cfg(tongsuo)]
2941 #[corresponds(SSL_enable_ntls)]
2942 pub fn enable_ntls(&mut self) {
2943 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2944 }
2945
2946 #[cfg(tongsuo)]
2947 #[corresponds(SSL_disable_ntls)]
2948 pub fn disable_ntls(&mut self) {
2949 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2950 }
2951
2952 #[cfg(all(tongsuo, ossl300))]
2953 #[corresponds(SSL_enable_force_ntls)]
2954 pub fn enable_force_ntls(&mut self) {
2955 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2956 }
2957
2958 #[cfg(all(tongsuo, ossl300))]
2959 #[corresponds(SSL_disable_force_ntls)]
2960 pub fn disable_force_ntls(&mut self) {
2961 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2962 }
2963
2964 #[cfg(tongsuo)]
2965 #[corresponds(SSL_enable_sm_tls13_strict)]
2966 pub fn enable_sm_tls13_strict(&mut self) {
2967 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2968 }
2969
2970 #[cfg(tongsuo)]
2971 #[corresponds(SSL_disable_sm_tls13_strict)]
2972 pub fn disable_sm_tls13_strict(&mut self) {
2973 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2974 }
2975
2976 #[corresponds(SSL_set_verify)]
2980 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2981 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2982 }
2983
2984 #[corresponds(SSL_set_verify_mode)]
2986 pub fn verify_mode(&self) -> SslVerifyMode {
2987 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2988 SslVerifyMode::from_bits_retain(mode)
2989 }
2990
2991 #[corresponds(SSL_set_verify)]
2995 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2996 where
2997 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2998 {
2999 unsafe {
3000 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
3002 ffi::SSL_set_verify(
3003 self.as_ptr(),
3004 mode.bits() as c_int,
3005 Some(ssl_raw_verify::<F>),
3006 );
3007 }
3008 }
3009
3010 #[corresponds(SSL_set_info_callback)]
3013 pub fn set_info_callback<F>(&mut self, callback: F)
3014 where
3015 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
3016 {
3017 unsafe {
3018 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3020 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
3021 }
3022 }
3023
3024 #[corresponds(SSL_set_dh_auto)]
3028 #[cfg(ossl300)]
3029 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3030 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3031 }
3032
3033 #[corresponds(SSL_set_tmp_dh)]
3037 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3038 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3039 }
3040
3041 #[corresponds(SSL_set_tmp_dh_callback)]
3045 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3046 where
3047 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3048 {
3049 unsafe {
3050 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3052 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3053 }
3054 }
3055
3056 #[corresponds(SSL_set_tmp_ecdh)]
3060 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3061 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3062 }
3063
3064 #[corresponds(SSL_set_ecdh_auto)]
3070 #[cfg(libressl)]
3071 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3072 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3073 }
3074
3075 #[corresponds(SSL_set_alpn_protos)]
3081 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3082 unsafe {
3083 assert!(protocols.len() <= c_uint::MAX as usize);
3084 let r =
3085 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3086 if r == 0 {
3088 Ok(())
3089 } else {
3090 Err(ErrorStack::get())
3091 }
3092 }
3093 }
3094
3095 #[corresponds(SSL_get_current_cipher)]
3097 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3098 unsafe {
3099 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3100
3101 SslCipherRef::from_const_ptr_opt(ptr)
3102 }
3103 }
3104
3105 #[corresponds(SSL_state_string)]
3107 pub fn state_string(&self) -> &'static str {
3108 let state = unsafe {
3109 let ptr = ffi::SSL_state_string(self.as_ptr());
3110 CStr::from_ptr(ptr as *const _)
3111 };
3112
3113 str::from_utf8(state.to_bytes()).unwrap()
3114 }
3115
3116 #[corresponds(SSL_state_string_long)]
3118 pub fn state_string_long(&self) -> &'static str {
3119 let state = unsafe {
3120 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3121 CStr::from_ptr(ptr as *const _)
3122 };
3123
3124 str::from_utf8(state.to_bytes()).unwrap()
3125 }
3126
3127 #[corresponds(SSL_set_tlsext_host_name)]
3131 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3132 let cstr = CString::new(hostname).unwrap();
3133 unsafe {
3134 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3135 .map(|_| ())
3136 }
3137 }
3138
3139 #[corresponds(SSL_get_peer_certificate)]
3141 pub fn peer_certificate(&self) -> Option<X509> {
3142 unsafe {
3143 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3144 X509::from_ptr_opt(ptr)
3145 }
3146 }
3147
3148 #[corresponds(SSL_get_peer_cert_chain)]
3153 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3154 unsafe {
3155 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3156 StackRef::from_const_ptr_opt(ptr)
3157 }
3158 }
3159
3160 #[corresponds(SSL_get0_verified_chain)]
3170 #[cfg(ossl110)]
3171 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3172 unsafe {
3173 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3174 StackRef::from_const_ptr_opt(ptr)
3175 }
3176 }
3177
3178 #[corresponds(SSL_get_certificate)]
3180 pub fn certificate(&self) -> Option<&X509Ref> {
3181 unsafe {
3182 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3183 X509Ref::from_const_ptr_opt(ptr)
3184 }
3185 }
3186
3187 #[corresponds(SSL_get_privatekey)]
3191 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3192 unsafe {
3193 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3194 PKeyRef::from_const_ptr_opt(ptr)
3195 }
3196 }
3197
3198 #[corresponds(SSL_version)]
3200 pub fn version2(&self) -> Option<SslVersion> {
3201 unsafe {
3202 let r = ffi::SSL_version(self.as_ptr());
3203 if r == 0 {
3204 None
3205 } else {
3206 Some(SslVersion(r))
3207 }
3208 }
3209 }
3210
3211 #[corresponds(SSL_get_version)]
3213 pub fn version_str(&self) -> &'static str {
3214 let version = unsafe {
3215 let ptr = ffi::SSL_get_version(self.as_ptr());
3216 CStr::from_ptr(ptr as *const _)
3217 };
3218
3219 str::from_utf8(version.to_bytes()).unwrap()
3220 }
3221
3222 #[corresponds(SSL_get0_alpn_selected)]
3229 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3230 unsafe {
3231 let mut data: *const c_uchar = ptr::null();
3232 let mut len: c_uint = 0;
3233 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3236
3237 if data.is_null() {
3238 None
3239 } else {
3240 Some(util::from_raw_parts(data, len as usize))
3241 }
3242 }
3243 }
3244
3245 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3247 #[corresponds(SSL_set_tlsext_use_srtp)]
3248 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3249 unsafe {
3250 let cstr = CString::new(protocols).unwrap();
3251
3252 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3253 if r == 0 {
3255 Ok(())
3256 } else {
3257 Err(ErrorStack::get())
3258 }
3259 }
3260 }
3261
3262 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3266 #[corresponds(SSL_get_srtp_profiles)]
3267 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3268 unsafe {
3269 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3270
3271 StackRef::from_const_ptr_opt(chain)
3272 }
3273 }
3274
3275 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3279 #[corresponds(SSL_get_selected_srtp_profile)]
3280 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3281 unsafe {
3282 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3283
3284 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3285 }
3286 }
3287
3288 #[corresponds(SSL_pending)]
3293 pub fn pending(&self) -> usize {
3294 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3295 }
3296
3297 #[corresponds(SSL_get_servername)]
3310 pub fn servername(&self, type_: NameType) -> Option<&str> {
3312 self.servername_raw(type_)
3313 .and_then(|b| str::from_utf8(b).ok())
3314 }
3315
3316 #[corresponds(SSL_get_servername)]
3324 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3325 unsafe {
3326 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3327 if name.is_null() {
3328 None
3329 } else {
3330 Some(CStr::from_ptr(name as *const _).to_bytes())
3331 }
3332 }
3333 }
3334
3335 #[corresponds(SSL_set_SSL_CTX)]
3339 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3340 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3341 }
3342
3343 #[corresponds(SSL_get_SSL_CTX)]
3345 pub fn ssl_context(&self) -> &SslContextRef {
3346 unsafe {
3347 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3348 SslContextRef::from_ptr(ssl_ctx)
3349 }
3350 }
3351
3352 #[corresponds(SSL_get0_param)]
3356 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3357 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3358 }
3359
3360 #[corresponds(SSL_get_verify_result)]
3362 pub fn verify_result(&self) -> X509VerifyResult {
3363 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3364 }
3365
3366 #[corresponds(SSL_get_session)]
3368 pub fn session(&self) -> Option<&SslSessionRef> {
3369 unsafe {
3370 let p = ffi::SSL_get_session(self.as_ptr());
3371 SslSessionRef::from_const_ptr_opt(p)
3372 }
3373 }
3374
3375 #[corresponds(SSL_get_client_random)]
3382 #[cfg(any(ossl110, libressl))]
3383 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3384 unsafe {
3385 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3386 }
3387 }
3388
3389 #[corresponds(SSL_get_server_random)]
3396 #[cfg(any(ossl110, libressl))]
3397 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3398 unsafe {
3399 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3400 }
3401 }
3402
3403 #[corresponds(SSL_export_keying_material)]
3405 pub fn export_keying_material(
3406 &self,
3407 out: &mut [u8],
3408 label: &str,
3409 context: Option<&[u8]>,
3410 ) -> Result<(), ErrorStack> {
3411 unsafe {
3412 let (context, contextlen, use_context) = match context {
3413 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3414 None => (ptr::null(), 0, 0),
3415 };
3416 cvt(ffi::SSL_export_keying_material(
3417 self.as_ptr(),
3418 out.as_mut_ptr() as *mut c_uchar,
3419 out.len(),
3420 label.as_ptr() as *const c_char,
3421 label.len(),
3422 context,
3423 contextlen,
3424 use_context,
3425 ))
3426 .map(|_| ())
3427 }
3428 }
3429
3430 #[corresponds(SSL_export_keying_material_early)]
3437 #[cfg(ossl111)]
3438 pub fn export_keying_material_early(
3439 &self,
3440 out: &mut [u8],
3441 label: &str,
3442 context: &[u8],
3443 ) -> Result<(), ErrorStack> {
3444 unsafe {
3445 cvt(ffi::SSL_export_keying_material_early(
3446 self.as_ptr(),
3447 out.as_mut_ptr() as *mut c_uchar,
3448 out.len(),
3449 label.as_ptr() as *const c_char,
3450 label.len(),
3451 context.as_ptr() as *const c_uchar,
3452 context.len(),
3453 ))
3454 .map(|_| ())
3455 }
3456 }
3457
3458 #[corresponds(SSL_set_session)]
3469 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3470 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3471 }
3472
3473 #[corresponds(SSL_session_reused)]
3475 pub fn session_reused(&self) -> bool {
3476 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3477 }
3478
3479 #[cfg(any(boringssl, awslc))]
3487 pub fn enable_ocsp_stapling(&mut self) {
3488 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3489 }
3490
3491 #[cfg(any(boringssl, awslc))]
3499 pub fn enable_signed_cert_timestamps(&mut self) {
3500 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3501 }
3502
3503 #[cfg(any(boringssl, awslc))]
3511 pub fn set_permute_extensions(&mut self, enabled: bool) {
3512 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3513 }
3514
3515 #[corresponds(SSL_enable_ct)]
3517 #[cfg(ossl111)]
3518 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3519 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3520 }
3521
3522 #[corresponds(SSL_ct_is_enabled)]
3524 #[cfg(ossl111)]
3525 pub fn ct_is_enabled(&self) -> bool {
3526 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3527 }
3528
3529 #[corresponds(SSL_set_tlsext_status_type)]
3531 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3532 unsafe {
3533 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3534 }
3535 }
3536
3537 #[corresponds(SSL_get_extms_support)]
3541 #[cfg(ossl110)]
3542 pub fn extms_support(&self) -> Option<bool> {
3543 unsafe {
3544 match ffi::SSL_get_extms_support(self.as_ptr()) {
3545 -1 => None,
3546 ret => Some(ret != 0),
3547 }
3548 }
3549 }
3550
3551 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3553 #[cfg(not(any(boringssl, awslc)))]
3554 pub fn ocsp_status(&self) -> Option<&[u8]> {
3555 unsafe {
3556 let mut p = ptr::null_mut();
3557 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3558
3559 if len < 0 {
3560 None
3561 } else {
3562 Some(util::from_raw_parts(p as *const u8, len as usize))
3563 }
3564 }
3565 }
3566
3567 #[corresponds(SSL_get0_ocsp_response)]
3569 #[cfg(any(boringssl, awslc))]
3570 pub fn ocsp_status(&self) -> Option<&[u8]> {
3571 unsafe {
3572 let mut p = ptr::null();
3573 let mut len: usize = 0;
3574 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3575
3576 if len == 0 {
3577 None
3578 } else {
3579 Some(util::from_raw_parts(p as *const u8, len))
3580 }
3581 }
3582 }
3583
3584 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3586 #[cfg(not(any(boringssl, awslc)))]
3587 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3588 unsafe {
3589 assert!(response.len() <= c_int::MAX as usize);
3590 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3591 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3592 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3593 self.as_ptr(),
3594 p as *mut c_uchar,
3595 response.len() as c_long,
3596 ) as c_int)
3597 .map(|_| ())
3598 .inspect_err(|_| {
3599 ffi::OPENSSL_free(p);
3600 })
3601 }
3602 }
3603
3604 #[corresponds(SSL_set_ocsp_response)]
3606 #[cfg(any(boringssl, awslc))]
3607 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3608 unsafe {
3609 cvt(ffi::SSL_set_ocsp_response(
3610 self.as_ptr(),
3611 response.as_ptr(),
3612 response.len(),
3613 ))
3614 .map(|_| ())
3615 }
3616 }
3617
3618 #[corresponds(SSL_is_server)]
3620 pub fn is_server(&self) -> bool {
3621 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3622 }
3623
3624 #[corresponds(SSL_set_ex_data)]
3630 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3631 match self.ex_data_mut(index) {
3632 Some(v) => *v = data,
3633 None => unsafe {
3634 let data = Box::new(data);
3635 ffi::SSL_set_ex_data(
3636 self.as_ptr(),
3637 index.as_raw(),
3638 Box::into_raw(data) as *mut c_void,
3639 );
3640 },
3641 }
3642 }
3643
3644 #[corresponds(SSL_get_ex_data)]
3646 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3647 unsafe {
3648 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3649 if data.is_null() {
3650 None
3651 } else {
3652 Some(&*(data as *const T))
3653 }
3654 }
3655 }
3656
3657 #[corresponds(SSL_get_ex_data)]
3659 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3660 unsafe {
3661 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3662 if data.is_null() {
3663 None
3664 } else {
3665 Some(&mut *(data as *mut T))
3666 }
3667 }
3668 }
3669
3670 #[corresponds(SSL_set_max_early_data)]
3674 #[cfg(any(ossl111, libressl))]
3675 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3676 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3677 Ok(())
3678 } else {
3679 Err(ErrorStack::get())
3680 }
3681 }
3682
3683 #[corresponds(SSL_get_max_early_data)]
3687 #[cfg(any(ossl111, libressl))]
3688 pub fn max_early_data(&self) -> u32 {
3689 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3690 }
3691
3692 #[corresponds(SSL_get_finished)]
3697 pub fn finished(&self, buf: &mut [u8]) -> usize {
3698 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3699 }
3700
3701 #[corresponds(SSL_get_peer_finished)]
3707 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3708 unsafe {
3709 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3710 }
3711 }
3712
3713 #[corresponds(SSL_is_init_finished)]
3715 #[cfg(ossl110)]
3716 pub fn is_init_finished(&self) -> bool {
3717 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3718 }
3719
3720 #[corresponds(SSL_client_hello_isv2)]
3726 #[cfg(ossl111)]
3727 pub fn client_hello_isv2(&self) -> bool {
3728 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3729 }
3730
3731 #[corresponds(SSL_client_hello_get0_legacy_version)]
3737 #[cfg(ossl111)]
3738 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3739 unsafe {
3740 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3741 if version == 0 {
3742 None
3743 } else {
3744 Some(SslVersion(version as c_int))
3745 }
3746 }
3747 }
3748
3749 #[corresponds(SSL_client_hello_get0_random)]
3755 #[cfg(ossl111)]
3756 pub fn client_hello_random(&self) -> Option<&[u8]> {
3757 unsafe {
3758 let mut ptr = ptr::null();
3759 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3760 if len == 0 {
3761 None
3762 } else {
3763 Some(util::from_raw_parts(ptr, len))
3764 }
3765 }
3766 }
3767
3768 #[corresponds(SSL_client_hello_get0_session_id)]
3774 #[cfg(ossl111)]
3775 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3776 unsafe {
3777 let mut ptr = ptr::null();
3778 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3779 if len == 0 {
3780 None
3781 } else {
3782 Some(util::from_raw_parts(ptr, len))
3783 }
3784 }
3785 }
3786
3787 #[corresponds(SSL_client_hello_get0_ciphers)]
3793 #[cfg(ossl111)]
3794 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3795 unsafe {
3796 let mut ptr = ptr::null();
3797 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3798 if len == 0 {
3799 None
3800 } else {
3801 Some(util::from_raw_parts(ptr, len))
3802 }
3803 }
3804 }
3805
3806 #[cfg(ossl111)]
3812 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3813 unsafe {
3814 let mut ptr = ptr::null();
3815 let mut len = 0usize;
3816 let r = ffi::SSL_client_hello_get0_ext(
3817 self.as_ptr(),
3818 ext_type.as_raw() as _,
3819 &mut ptr,
3820 &mut len,
3821 );
3822 if r == 0 {
3823 None
3824 } else {
3825 Some(util::from_raw_parts(ptr, len))
3826 }
3827 }
3828 }
3829
3830 #[corresponds(SSL_bytes_to_cipher_list)]
3835 #[cfg(ossl111)]
3836 pub fn bytes_to_cipher_list(
3837 &self,
3838 bytes: &[u8],
3839 isv2format: bool,
3840 ) -> Result<CipherLists, ErrorStack> {
3841 unsafe {
3842 let ptr = bytes.as_ptr();
3843 let len = bytes.len();
3844 let mut sk = ptr::null_mut();
3845 let mut scsvs = ptr::null_mut();
3846 let res = ffi::SSL_bytes_to_cipher_list(
3847 self.as_ptr(),
3848 ptr,
3849 len,
3850 isv2format as c_int,
3851 &mut sk,
3852 &mut scsvs,
3853 );
3854 if res == 1 {
3855 Ok(CipherLists {
3856 suites: Stack::from_ptr(sk),
3857 signalling_suites: Stack::from_ptr(scsvs),
3858 })
3859 } else {
3860 Err(ErrorStack::get())
3861 }
3862 }
3863 }
3864
3865 #[corresponds(SSL_client_hello_get0_compression_methods)]
3871 #[cfg(ossl111)]
3872 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3873 unsafe {
3874 let mut ptr = ptr::null();
3875 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3876 if len == 0 {
3877 None
3878 } else {
3879 Some(util::from_raw_parts(ptr, len))
3880 }
3881 }
3882 }
3883
3884 #[corresponds(SSL_set_mtu)]
3886 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3887 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3888 }
3889
3890 #[corresponds(SSL_get_psk_identity_hint)]
3894 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3895 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3896 unsafe {
3897 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3898 if ptr.is_null() {
3899 None
3900 } else {
3901 Some(CStr::from_ptr(ptr).to_bytes())
3902 }
3903 }
3904 }
3905
3906 #[corresponds(SSL_get_psk_identity)]
3908 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3909 pub fn psk_identity(&self) -> Option<&[u8]> {
3910 unsafe {
3911 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3912 if ptr.is_null() {
3913 None
3914 } else {
3915 Some(CStr::from_ptr(ptr).to_bytes())
3916 }
3917 }
3918 }
3919
3920 #[corresponds(SSL_add0_chain_cert)]
3921 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3922 unsafe {
3923 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3924 mem::forget(chain);
3925 }
3926 Ok(())
3927 }
3928
3929 #[cfg(not(any(boringssl, awslc)))]
3931 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3932 unsafe {
3933 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3934 };
3935 Ok(())
3936 }
3937
3938 #[corresponds(SSL_use_Private_Key_file)]
3940 pub fn set_private_key_file<P: AsRef<Path>>(
3941 &mut self,
3942 path: P,
3943 ssl_file_type: SslFiletype,
3944 ) -> Result<(), ErrorStack> {
3945 let p = path.as_ref().as_os_str().to_str().unwrap();
3946 let key_file = CString::new(p).unwrap();
3947 unsafe {
3948 cvt(ffi::SSL_use_PrivateKey_file(
3949 self.as_ptr(),
3950 key_file.as_ptr(),
3951 ssl_file_type.as_raw(),
3952 ))?;
3953 };
3954 Ok(())
3955 }
3956
3957 #[corresponds(SSL_use_PrivateKey)]
3959 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3960 unsafe {
3961 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3962 };
3963 Ok(())
3964 }
3965
3966 #[cfg(tongsuo)]
3967 #[corresponds(SSL_use_enc_Private_Key_file)]
3968 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3969 &mut self,
3970 path: P,
3971 ssl_file_type: SslFiletype,
3972 ) -> Result<(), ErrorStack> {
3973 let p = path.as_ref().as_os_str().to_str().unwrap();
3974 let key_file = CString::new(p).unwrap();
3975 unsafe {
3976 cvt(ffi::SSL_use_enc_PrivateKey_file(
3977 self.as_ptr(),
3978 key_file.as_ptr(),
3979 ssl_file_type.as_raw(),
3980 ))?;
3981 };
3982 Ok(())
3983 }
3984
3985 #[cfg(tongsuo)]
3986 #[corresponds(SSL_use_enc_PrivateKey)]
3987 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3988 unsafe {
3989 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3990 };
3991 Ok(())
3992 }
3993
3994 #[cfg(tongsuo)]
3995 #[corresponds(SSL_use_sign_Private_Key_file)]
3996 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3997 &mut self,
3998 path: P,
3999 ssl_file_type: SslFiletype,
4000 ) -> Result<(), ErrorStack> {
4001 let p = path.as_ref().as_os_str().to_str().unwrap();
4002 let key_file = CString::new(p).unwrap();
4003 unsafe {
4004 cvt(ffi::SSL_use_sign_PrivateKey_file(
4005 self.as_ptr(),
4006 key_file.as_ptr(),
4007 ssl_file_type.as_raw(),
4008 ))?;
4009 };
4010 Ok(())
4011 }
4012
4013 #[cfg(tongsuo)]
4014 #[corresponds(SSL_use_sign_PrivateKey)]
4015 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
4016 unsafe {
4017 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
4018 };
4019 Ok(())
4020 }
4021
4022 #[corresponds(SSL_use_certificate)]
4024 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4025 unsafe {
4026 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4027 };
4028 Ok(())
4029 }
4030
4031 #[cfg(tongsuo)]
4032 #[corresponds(SSL_use_enc_certificate)]
4033 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4034 unsafe {
4035 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4036 };
4037 Ok(())
4038 }
4039
4040 #[cfg(tongsuo)]
4041 #[corresponds(SSL_use_sign_certificate)]
4042 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4043 unsafe {
4044 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4045 };
4046 Ok(())
4047 }
4048
4049 #[corresponds(SSL_use_certificate_chain_file)]
4055 #[cfg(any(ossl110, libressl))]
4056 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4057 &mut self,
4058 path: P,
4059 ) -> Result<(), ErrorStack> {
4060 let p = path.as_ref().as_os_str().to_str().unwrap();
4061 let cert_file = CString::new(p).unwrap();
4062 unsafe {
4063 cvt(ffi::SSL_use_certificate_chain_file(
4064 self.as_ptr(),
4065 cert_file.as_ptr(),
4066 ))?;
4067 };
4068 Ok(())
4069 }
4070
4071 #[corresponds(SSL_add_client_CA)]
4073 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4074 unsafe {
4075 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4076 };
4077 Ok(())
4078 }
4079
4080 #[corresponds(SSL_set_client_CA_list)]
4082 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4083 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4084 mem::forget(list);
4085 }
4086
4087 #[corresponds(SSL_set_min_proto_version)]
4092 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4093 unsafe {
4094 cvt(ffi::SSL_set_min_proto_version(
4095 self.as_ptr(),
4096 version.map_or(0, |v| v.0 as _),
4097 ))
4098 .map(|_| ())
4099 }
4100 }
4101
4102 #[corresponds(SSL_set_max_proto_version)]
4107 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4108 unsafe {
4109 cvt(ffi::SSL_set_max_proto_version(
4110 self.as_ptr(),
4111 version.map_or(0, |v| v.0 as _),
4112 ))
4113 .map(|_| ())
4114 }
4115 }
4116
4117 #[corresponds(SSL_set_ciphersuites)]
4126 #[cfg(any(ossl111, libressl))]
4127 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4128 let cipher_list = CString::new(cipher_list).unwrap();
4129 unsafe {
4130 cvt(ffi::SSL_set_ciphersuites(
4131 self.as_ptr(),
4132 cipher_list.as_ptr() as *const _,
4133 ))
4134 .map(|_| ())
4135 }
4136 }
4137
4138 #[corresponds(SSL_set_cipher_list)]
4146 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4147 let cipher_list = CString::new(cipher_list).unwrap();
4148 unsafe {
4149 cvt(ffi::SSL_set_cipher_list(
4150 self.as_ptr(),
4151 cipher_list.as_ptr() as *const _,
4152 ))
4153 .map(|_| ())
4154 }
4155 }
4156
4157 #[corresponds(SSL_set_cert_store)]
4159 #[cfg(any(ossl110, boringssl, awslc))]
4160 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4161 unsafe {
4162 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4163 mem::forget(cert_store);
4164 Ok(())
4165 }
4166 }
4167
4168 #[corresponds(SSL_set_num_tickets)]
4173 #[cfg(ossl111)]
4174 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4175 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4176 }
4177
4178 #[corresponds(SSL_get_num_tickets)]
4183 #[cfg(ossl111)]
4184 pub fn num_tickets(&self) -> usize {
4185 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4186 }
4187
4188 #[corresponds(SSL_set_security_level)]
4193 #[cfg(any(ossl110, libressl360))]
4194 pub fn set_security_level(&mut self, level: u32) {
4195 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4196 }
4197
4198 #[corresponds(SSL_get_security_level)]
4203 #[cfg(any(ossl110, libressl360))]
4204 pub fn security_level(&self) -> u32 {
4205 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4206 }
4207
4208 #[corresponds(SSL_get_peer_tmp_key)]
4213 #[cfg(ossl300)]
4214 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4215 unsafe {
4216 let mut key = ptr::null_mut();
4217 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4218 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4219 Err(e) => Err(e),
4220 }
4221 }
4222 }
4223
4224 #[corresponds(SSL_get_tmp_key)]
4229 #[cfg(ossl300)]
4230 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4231 unsafe {
4232 let mut key = ptr::null_mut();
4233 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4234 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4235 Err(e) => Err(e),
4236 }
4237 }
4238 }
4239}
4240
4241#[derive(Debug)]
4243pub struct MidHandshakeSslStream<S> {
4244 stream: SslStream<S>,
4245 error: Error,
4246}
4247
4248impl<S> MidHandshakeSslStream<S> {
4249 pub fn get_ref(&self) -> &S {
4251 self.stream.get_ref()
4252 }
4253
4254 pub fn get_mut(&mut self) -> &mut S {
4256 self.stream.get_mut()
4257 }
4258
4259 pub fn ssl(&self) -> &SslRef {
4261 self.stream.ssl()
4262 }
4263
4264 pub fn ssl_mut(&mut self) -> &mut SslRef {
4266 self.stream.ssl_mut()
4267 }
4268
4269 pub fn error(&self) -> &Error {
4271 &self.error
4272 }
4273
4274 pub fn into_error(self) -> Error {
4276 self.error
4277 }
4278}
4279
4280impl<S> MidHandshakeSslStream<S>
4281where
4282 S: Read + Write,
4283{
4284 #[corresponds(SSL_do_handshake)]
4287 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4288 match self.stream.do_handshake() {
4289 Ok(()) => Ok(self.stream),
4290 Err(error) => {
4291 self.error = error;
4292 match self.error.code() {
4293 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4294 Err(HandshakeError::WouldBlock(self))
4295 }
4296 _ => Err(HandshakeError::Failure(self)),
4297 }
4298 }
4299 }
4300 }
4301}
4302
4303pub struct SslStream<S> {
4305 ssl: ManuallyDrop<Ssl>,
4306 method: ManuallyDrop<BioMethod>,
4307 _p: PhantomData<S>,
4308}
4309
4310impl<S> Drop for SslStream<S> {
4311 fn drop(&mut self) {
4312 unsafe {
4314 ManuallyDrop::drop(&mut self.ssl);
4315 ManuallyDrop::drop(&mut self.method);
4316 }
4317 }
4318}
4319
4320impl<S> fmt::Debug for SslStream<S>
4321where
4322 S: fmt::Debug,
4323{
4324 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4325 fmt.debug_struct("SslStream")
4326 .field("stream", &self.get_ref())
4327 .field("ssl", &self.ssl())
4328 .finish()
4329 }
4330}
4331
4332impl<S: Read + Write> SslStream<S> {
4333 #[corresponds(SSL_set_bio)]
4341 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4342 let (bio, method) = bio::new(stream)?;
4343 unsafe {
4344 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4345 }
4346
4347 Ok(SslStream {
4348 ssl: ManuallyDrop::new(ssl),
4349 method: ManuallyDrop::new(method),
4350 _p: PhantomData,
4351 })
4352 }
4353
4354 #[corresponds(SSL_read_early_data)]
4363 #[cfg(any(ossl111, libressl))]
4364 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4365 let mut read = 0;
4366 let ret = unsafe {
4367 ffi::SSL_read_early_data(
4368 self.ssl.as_ptr(),
4369 buf.as_ptr() as *mut c_void,
4370 buf.len(),
4371 &mut read,
4372 )
4373 };
4374 match ret {
4375 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4376 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4377 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4378 _ => unreachable!(),
4379 }
4380 }
4381
4382 #[corresponds(SSL_write_early_data)]
4389 #[cfg(any(ossl111, libressl))]
4390 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4391 let mut written = 0;
4392 let ret = unsafe {
4393 ffi::SSL_write_early_data(
4394 self.ssl.as_ptr(),
4395 buf.as_ptr() as *const c_void,
4396 buf.len(),
4397 &mut written,
4398 )
4399 };
4400 if ret > 0 {
4401 Ok(written)
4402 } else {
4403 Err(self.make_error(ret))
4404 }
4405 }
4406
4407 #[corresponds(SSL_connect)]
4414 pub fn connect(&mut self) -> Result<(), Error> {
4415 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4416 if ret > 0 {
4417 Ok(())
4418 } else {
4419 Err(self.make_error(ret))
4420 }
4421 }
4422
4423 #[corresponds(SSL_accept)]
4430 pub fn accept(&mut self) -> Result<(), Error> {
4431 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4432 if ret > 0 {
4433 Ok(())
4434 } else {
4435 Err(self.make_error(ret))
4436 }
4437 }
4438
4439 #[corresponds(SSL_do_handshake)]
4443 pub fn do_handshake(&mut self) -> Result<(), Error> {
4444 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4445 if ret > 0 {
4446 Ok(())
4447 } else {
4448 Err(self.make_error(ret))
4449 }
4450 }
4451
4452 #[corresponds(SSL_stateless)]
4463 #[cfg(ossl111)]
4464 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4465 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4466 1 => Ok(true),
4467 0 => Ok(false),
4468 -1 => Err(ErrorStack::get()),
4469 _ => unreachable!(),
4470 }
4471 }
4472
4473 #[corresponds(SSL_read_ex)]
4480 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4481 loop {
4482 match self.ssl_read_uninit(buf) {
4483 Ok(n) => return Ok(n),
4484 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4485 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4486 return Ok(0);
4487 }
4488 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4489 Err(e) => {
4490 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4491 }
4492 }
4493 }
4494 }
4495
4496 #[corresponds(SSL_read_ex)]
4501 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4502 unsafe {
4504 self.ssl_read_uninit(util::from_raw_parts_mut(
4505 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4506 buf.len(),
4507 ))
4508 }
4509 }
4510
4511 #[corresponds(SSL_read_ex)]
4518 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4519 if buf.is_empty() {
4520 return Ok(0);
4521 }
4522
4523 cfg_if! {
4524 if #[cfg(any(ossl111, libressl))] {
4525 let mut readbytes = 0;
4526 let ret = unsafe {
4527 ffi::SSL_read_ex(
4528 self.ssl().as_ptr(),
4529 buf.as_mut_ptr().cast(),
4530 buf.len(),
4531 &mut readbytes,
4532 )
4533 };
4534
4535 if ret > 0 {
4536 Ok(readbytes)
4537 } else {
4538 Err(self.make_error(ret))
4539 }
4540 } else {
4541 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4542 let ret = unsafe {
4543 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4544 };
4545 if ret > 0 {
4546 Ok(ret as usize)
4547 } else {
4548 Err(self.make_error(ret))
4549 }
4550 }
4551 }
4552 }
4553
4554 #[corresponds(SSL_write_ex)]
4559 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4560 if buf.is_empty() {
4561 return Ok(0);
4562 }
4563
4564 cfg_if! {
4565 if #[cfg(any(ossl111, libressl))] {
4566 let mut written = 0;
4567 let ret = unsafe {
4568 ffi::SSL_write_ex(
4569 self.ssl().as_ptr(),
4570 buf.as_ptr().cast(),
4571 buf.len(),
4572 &mut written,
4573 )
4574 };
4575
4576 if ret > 0 {
4577 Ok(written)
4578 } else {
4579 Err(self.make_error(ret))
4580 }
4581 } else {
4582 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4583 let ret = unsafe {
4584 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4585 };
4586 if ret > 0 {
4587 Ok(ret as usize)
4588 } else {
4589 Err(self.make_error(ret))
4590 }
4591 }
4592 }
4593 }
4594
4595 #[corresponds(SSL_peek_ex)]
4597 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4598 unsafe {
4600 self.ssl_peek_uninit(util::from_raw_parts_mut(
4601 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4602 buf.len(),
4603 ))
4604 }
4605 }
4606
4607 #[corresponds(SSL_peek_ex)]
4614 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4615 cfg_if! {
4616 if #[cfg(any(ossl111, libressl))] {
4617 let mut readbytes = 0;
4618 let ret = unsafe {
4619 ffi::SSL_peek_ex(
4620 self.ssl().as_ptr(),
4621 buf.as_mut_ptr().cast(),
4622 buf.len(),
4623 &mut readbytes,
4624 )
4625 };
4626
4627 if ret > 0 {
4628 Ok(readbytes)
4629 } else {
4630 Err(self.make_error(ret))
4631 }
4632 } else {
4633 if buf.is_empty() {
4634 return Ok(0);
4635 }
4636
4637 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4638 let ret = unsafe {
4639 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4640 };
4641 if ret > 0 {
4642 Ok(ret as usize)
4643 } else {
4644 Err(self.make_error(ret))
4645 }
4646 }
4647 }
4648 }
4649
4650 #[corresponds(SSL_shutdown)]
4660 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4661 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4662 0 => Ok(ShutdownResult::Sent),
4663 1 => Ok(ShutdownResult::Received),
4664 n => Err(self.make_error(n)),
4665 }
4666 }
4667
4668 #[corresponds(SSL_get_shutdown)]
4670 pub fn get_shutdown(&mut self) -> ShutdownState {
4671 unsafe {
4672 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4673 ShutdownState::from_bits_retain(bits)
4674 }
4675 }
4676
4677 #[corresponds(SSL_set_shutdown)]
4682 pub fn set_shutdown(&mut self, state: ShutdownState) {
4683 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4684 }
4685}
4686
4687impl<S> SslStream<S> {
4688 fn make_error(&mut self, ret: c_int) -> Error {
4689 self.check_panic();
4690
4691 let code = self.ssl.get_error(ret);
4692
4693 let cause = match code {
4694 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4695 ErrorCode::SYSCALL => {
4696 let errs = ErrorStack::get();
4697 if errs.errors().is_empty() {
4698 self.get_bio_error().map(InnerError::Io)
4699 } else {
4700 Some(InnerError::Ssl(errs))
4701 }
4702 }
4703 ErrorCode::ZERO_RETURN => None,
4704 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4705 self.get_bio_error().map(InnerError::Io)
4706 }
4707 _ => None,
4708 };
4709
4710 Error { code, cause }
4711 }
4712
4713 fn check_panic(&mut self) {
4714 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4715 resume_unwind(err)
4716 }
4717 }
4718
4719 fn get_bio_error(&mut self) -> Option<io::Error> {
4720 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4721 }
4722
4723 pub fn get_ref(&self) -> &S {
4725 unsafe {
4726 let bio = self.ssl.get_raw_rbio();
4727 bio::get_ref(bio)
4728 }
4729 }
4730
4731 pub fn get_mut(&mut self) -> &mut S {
4738 unsafe {
4739 let bio = self.ssl.get_raw_rbio();
4740 bio::get_mut(bio)
4741 }
4742 }
4743
4744 pub fn ssl(&self) -> &SslRef {
4746 &self.ssl
4747 }
4748
4749 pub fn ssl_mut(&mut self) -> &mut SslRef {
4751 &mut self.ssl
4752 }
4753}
4754
4755impl<S: Read + Write> Read for SslStream<S> {
4756 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4757 unsafe {
4759 self.read_uninit(util::from_raw_parts_mut(
4760 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4761 buf.len(),
4762 ))
4763 }
4764 }
4765}
4766
4767impl<S: Read + Write> Write for SslStream<S> {
4768 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4769 loop {
4770 match self.ssl_write(buf) {
4771 Ok(n) => return Ok(n),
4772 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4773 Err(e) => {
4774 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4775 }
4776 }
4777 }
4778 }
4779
4780 fn flush(&mut self) -> io::Result<()> {
4781 self.get_mut().flush()
4782 }
4783}
4784
4785#[deprecated(
4787 since = "0.10.32",
4788 note = "use the methods directly on Ssl/SslStream instead"
4789)]
4790pub struct SslStreamBuilder<S> {
4791 inner: SslStream<S>,
4792}
4793
4794#[allow(deprecated)]
4795impl<S> SslStreamBuilder<S>
4796where
4797 S: Read + Write,
4798{
4799 pub fn new(ssl: Ssl, stream: S) -> Self {
4801 Self {
4802 inner: SslStream::new(ssl, stream).unwrap(),
4803 }
4804 }
4805
4806 #[corresponds(SSL_stateless)]
4817 #[cfg(ossl111)]
4818 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4819 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4820 1 => Ok(true),
4821 0 => Ok(false),
4822 -1 => Err(ErrorStack::get()),
4823 _ => unreachable!(),
4824 }
4825 }
4826
4827 #[corresponds(SSL_set_connect_state)]
4829 pub fn set_connect_state(&mut self) {
4830 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4831 }
4832
4833 #[corresponds(SSL_set_accept_state)]
4835 pub fn set_accept_state(&mut self) {
4836 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4837 }
4838
4839 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4841 match self.inner.connect() {
4842 Ok(()) => Ok(self.inner),
4843 Err(error) => match error.code() {
4844 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4845 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4846 stream: self.inner,
4847 error,
4848 }))
4849 }
4850 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4851 stream: self.inner,
4852 error,
4853 })),
4854 },
4855 }
4856 }
4857
4858 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4860 match self.inner.accept() {
4861 Ok(()) => Ok(self.inner),
4862 Err(error) => match error.code() {
4863 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4864 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4865 stream: self.inner,
4866 error,
4867 }))
4868 }
4869 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4870 stream: self.inner,
4871 error,
4872 })),
4873 },
4874 }
4875 }
4876
4877 #[corresponds(SSL_do_handshake)]
4881 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4882 match self.inner.do_handshake() {
4883 Ok(()) => Ok(self.inner),
4884 Err(error) => match error.code() {
4885 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4886 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4887 stream: self.inner,
4888 error,
4889 }))
4890 }
4891 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4892 stream: self.inner,
4893 error,
4894 })),
4895 },
4896 }
4897 }
4898
4899 #[corresponds(SSL_read_early_data)]
4909 #[cfg(any(ossl111, libressl))]
4910 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4911 self.inner.read_early_data(buf)
4912 }
4913
4914 #[corresponds(SSL_write_early_data)]
4921 #[cfg(any(ossl111, libressl))]
4922 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4923 self.inner.write_early_data(buf)
4924 }
4925}
4926
4927#[allow(deprecated)]
4928impl<S> SslStreamBuilder<S> {
4929 pub fn get_ref(&self) -> &S {
4931 unsafe {
4932 let bio = self.inner.ssl.get_raw_rbio();
4933 bio::get_ref(bio)
4934 }
4935 }
4936
4937 pub fn get_mut(&mut self) -> &mut S {
4944 unsafe {
4945 let bio = self.inner.ssl.get_raw_rbio();
4946 bio::get_mut(bio)
4947 }
4948 }
4949
4950 pub fn ssl(&self) -> &SslRef {
4952 &self.inner.ssl
4953 }
4954
4955 pub fn ssl_mut(&mut self) -> &mut SslRef {
4957 &mut self.inner.ssl
4958 }
4959}
4960
4961#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4963pub enum ShutdownResult {
4964 Sent,
4966
4967 Received,
4969}
4970
4971bitflags! {
4972 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4974 #[repr(transparent)]
4975 pub struct ShutdownState: c_int {
4976 const SENT = ffi::SSL_SENT_SHUTDOWN;
4978 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4980 }
4981}
4982
4983use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4984cfg_if! {
4985 if #[cfg(ossl300)] {
4986 use ffi::SSL_get1_peer_certificate;
4987 } else {
4988 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4989 }
4990}
4991use ffi::{
4992 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4993 TLS_server_method,
4994};
4995cfg_if! {
4996 if #[cfg(ossl110)] {
4997 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4998 ffi::CRYPTO_get_ex_new_index(
4999 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5000 0,
5001 ptr::null_mut(),
5002 None,
5003 None,
5004 f,
5005 )
5006 }
5007
5008 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5009 ffi::CRYPTO_get_ex_new_index(
5010 ffi::CRYPTO_EX_INDEX_SSL,
5011 0,
5012 ptr::null_mut(),
5013 None,
5014 None,
5015 f,
5016 )
5017 }
5018 } else {
5019 use std::sync::Once;
5020
5021 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5022 static ONCE: Once = Once::new();
5024 ONCE.call_once(|| {
5025 cfg_if! {
5026 if #[cfg(not(any(boringssl, awslc)))] {
5027 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5028 } else {
5029 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5030 }
5031 }
5032 });
5033
5034 cfg_if! {
5035 if #[cfg(not(any(boringssl, awslc)))] {
5036 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5037 } else {
5038 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5039 }
5040 }
5041 }
5042
5043 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5044 static ONCE: Once = Once::new();
5046 ONCE.call_once(|| {
5047 #[cfg(not(any(boringssl, awslc)))]
5048 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5049 #[cfg(any(boringssl, awslc))]
5050 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5051 });
5052
5053 #[cfg(not(any(boringssl, awslc)))]
5054 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5055 #[cfg(any(boringssl, awslc))]
5056 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5057 }
5058 }
5059}