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 once_cell::sync::{Lazy, OnceCell};
94use openssl_macros::corresponds;
95use std::any::TypeId;
96use std::collections::HashMap;
97use std::ffi::{CStr, CString};
98use std::fmt;
99use std::io;
100use std::io::prelude::*;
101use std::marker::PhantomData;
102use std::mem::{self, ManuallyDrop, MaybeUninit};
103use std::ops::{Deref, DerefMut};
104use std::panic::resume_unwind;
105use std::path::Path;
106use std::ptr;
107use std::str;
108use std::sync::{Arc, Mutex};
109
110pub use crate::ssl::connector::{
111 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
112};
113pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
114
115mod bio;
116mod callbacks;
117#[cfg(any(boringssl, awslc))]
118mod client_hello;
119mod connector;
120mod error;
121#[cfg(test)]
122mod test;
123
124#[cfg(any(boringssl, awslc))]
125pub use client_hello::ClientHello;
126
127#[corresponds(OPENSSL_cipher_name)]
133#[cfg(ossl111)]
134pub fn cipher_name(std_name: &str) -> &'static str {
135 unsafe {
136 ffi::init();
137
138 let s = CString::new(std_name).unwrap();
139 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
140 CStr::from_ptr(ptr).to_str().unwrap()
141 }
142}
143
144cfg_if! {
145 if #[cfg(ossl300)] {
146 type SslOptionsRepr = u64;
147 } else if #[cfg(any(boringssl, awslc))] {
148 type SslOptionsRepr = u32;
149 } else {
150 type SslOptionsRepr = libc::c_ulong;
151 }
152}
153
154bitflags! {
155 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
157 #[repr(transparent)]
158 pub struct SslOptions: SslOptionsRepr {
159 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
161
162 #[cfg(ossl300)]
165 const IGNORE_UNEXPECTED_EOF = ffi::SSL_OP_IGNORE_UNEXPECTED_EOF as SslOptionsRepr;
166
167 #[cfg(not(any(boringssl, awslc)))]
169 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
170
171 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
175
176 #[cfg(not(any(boringssl, awslc)))]
182 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
183
184 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
186
187 #[cfg(not(any(boringssl, awslc)))]
189 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
190 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
191
192 #[cfg(not(any(boringssl, awslc)))]
194 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
195
196 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
199 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
200
201 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
205
206 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
210
211 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
215
216 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
218
219 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
221
222 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
224
225 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
227
228 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
230
231 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
233
234 #[cfg(any(ossl111, boringssl, libressl, awslc))]
238 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
239
240 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
242
243 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
245
246 #[cfg(ossl110)]
262 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
263
264 #[cfg(any(boringssl, ossl110h, awslc))]
268 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
269
270 #[cfg(ossl111)]
275 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
276
277 #[cfg(ossl111)]
289 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
290 }
291}
292
293bitflags! {
294 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
296 #[repr(transparent)]
297 pub struct SslMode: SslBitType {
298 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
304
305 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
308
309 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
319
320 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
326
327 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
331
332 #[cfg(not(libressl))]
340 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
341
342 #[cfg(ossl110)]
349 const ASYNC = ffi::SSL_MODE_ASYNC;
350 }
351}
352
353#[derive(Copy, Clone)]
355pub struct SslMethod(*const ffi::SSL_METHOD);
356
357impl SslMethod {
358 #[corresponds(TLS_method)]
360 pub fn tls() -> SslMethod {
361 unsafe { SslMethod(TLS_method()) }
362 }
363
364 #[corresponds(DTLS_method)]
366 pub fn dtls() -> SslMethod {
367 unsafe { SslMethod(DTLS_method()) }
368 }
369
370 #[corresponds(TLS_client_method)]
372 pub fn tls_client() -> SslMethod {
373 unsafe { SslMethod(TLS_client_method()) }
374 }
375
376 #[corresponds(TLS_server_method)]
378 pub fn tls_server() -> SslMethod {
379 unsafe { SslMethod(TLS_server_method()) }
380 }
381
382 #[cfg(tongsuo)]
383 #[corresponds(NTLS_client_method)]
384 pub fn ntls_client() -> SslMethod {
385 unsafe { SslMethod(ffi::NTLS_client_method()) }
386 }
387
388 #[cfg(tongsuo)]
389 #[corresponds(NTLS_server_method)]
390 pub fn ntls_server() -> SslMethod {
391 unsafe { SslMethod(ffi::NTLS_server_method()) }
392 }
393
394 #[corresponds(DTLS_client_method)]
396 pub fn dtls_client() -> SslMethod {
397 unsafe { SslMethod(DTLS_client_method()) }
398 }
399
400 #[corresponds(DTLS_server_method)]
402 pub fn dtls_server() -> SslMethod {
403 unsafe { SslMethod(DTLS_server_method()) }
404 }
405
406 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
412 SslMethod(ptr)
413 }
414
415 #[allow(clippy::trivially_copy_pass_by_ref)]
417 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
418 self.0
419 }
420}
421
422unsafe impl Sync for SslMethod {}
423unsafe impl Send for SslMethod {}
424
425bitflags! {
426 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
428 #[repr(transparent)]
429 pub struct SslVerifyMode: i32 {
430 const PEER = ffi::SSL_VERIFY_PEER;
434
435 const NONE = ffi::SSL_VERIFY_NONE;
441
442 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
446 }
447}
448
449#[cfg(any(boringssl, awslc))]
450type SslBitType = c_int;
451#[cfg(not(any(boringssl, awslc)))]
452type SslBitType = c_long;
453
454#[cfg(any(boringssl, awslc))]
455type SslTimeTy = u64;
456#[cfg(not(any(boringssl, awslc)))]
457type SslTimeTy = c_long;
458
459bitflags! {
460 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
462 #[repr(transparent)]
463 pub struct SslSessionCacheMode: SslBitType {
464 const OFF = ffi::SSL_SESS_CACHE_OFF;
466
467 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
474
475 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
479
480 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
482
483 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
485
486 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
488
489 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
491
492 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
494 }
495}
496
497#[cfg(ossl111)]
498bitflags! {
499 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
501 #[repr(transparent)]
502 pub struct ExtensionContext: c_uint {
503 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
505 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
507 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
509 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
511 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
513 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
515 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
517 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
518 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
520 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
521 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
522 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
523 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
524 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
525 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
526 }
527}
528
529#[derive(Copy, Clone)]
531pub struct TlsExtType(c_uint);
532
533impl TlsExtType {
534 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
538
539 pub const ALPN: TlsExtType =
543 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
544
545 pub fn from_raw(raw: c_uint) -> TlsExtType {
547 TlsExtType(raw)
548 }
549
550 #[allow(clippy::trivially_copy_pass_by_ref)]
552 pub fn as_raw(&self) -> c_uint {
553 self.0
554 }
555}
556
557#[derive(Copy, Clone)]
559pub struct SslFiletype(c_int);
560
561impl SslFiletype {
562 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
566
567 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
571
572 pub fn from_raw(raw: c_int) -> SslFiletype {
574 SslFiletype(raw)
575 }
576
577 #[allow(clippy::trivially_copy_pass_by_ref)]
579 pub fn as_raw(&self) -> c_int {
580 self.0
581 }
582}
583
584#[derive(Copy, Clone)]
586pub struct StatusType(c_int);
587
588impl StatusType {
589 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
591
592 pub fn from_raw(raw: c_int) -> StatusType {
594 StatusType(raw)
595 }
596
597 #[allow(clippy::trivially_copy_pass_by_ref)]
599 pub fn as_raw(&self) -> c_int {
600 self.0
601 }
602}
603
604#[derive(Copy, Clone)]
606pub struct NameType(c_int);
607
608impl NameType {
609 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
611
612 pub fn from_raw(raw: c_int) -> StatusType {
614 StatusType(raw)
615 }
616
617 #[allow(clippy::trivially_copy_pass_by_ref)]
619 pub fn as_raw(&self) -> c_int {
620 self.0
621 }
622}
623
624static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
625static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
626static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
627
628fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
629 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
630}
631
632unsafe extern "C" fn free_data_box<T>(
633 _parent: *mut c_void,
634 ptr: *mut c_void,
635 _ad: *mut ffi::CRYPTO_EX_DATA,
636 _idx: c_int,
637 _argl: c_long,
638 _argp: *mut c_void,
639) {
640 if !ptr.is_null() {
641 let _ = Box::<T>::from_raw(ptr as *mut T);
642 }
643}
644
645#[derive(Debug, Copy, Clone, PartialEq, Eq)]
647pub struct SniError(c_int);
648
649impl SniError {
650 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
652
653 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
655
656 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
657}
658
659#[derive(Debug, Copy, Clone, PartialEq, Eq)]
661pub struct SslAlert(c_int);
662
663impl SslAlert {
664 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
666 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
667 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
668 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
669}
670
671#[derive(Debug, Copy, Clone, PartialEq, Eq)]
675pub struct AlpnError(c_int);
676
677impl AlpnError {
678 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
680
681 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
683}
684
685#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
689#[derive(Debug, Copy, Clone, PartialEq, Eq)]
690pub struct ClientHelloError(c_int);
691
692#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
693impl ClientHelloError {
694 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
696
697 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
699}
700
701#[derive(Debug, Copy, Clone, PartialEq, Eq)]
703pub struct TicketKeyStatus(c_int);
704
705impl TicketKeyStatus {
706 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
708 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
710 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
712}
713
714#[derive(Debug, Copy, Clone, PartialEq, Eq)]
716#[cfg(any(boringssl, awslc))]
717pub struct SelectCertError(ffi::ssl_select_cert_result_t);
718
719#[cfg(any(boringssl, awslc))]
720impl SelectCertError {
721 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
723
724 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
726
727 #[cfg(boringssl)]
733 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
734}
735
736#[cfg(ossl111)]
738#[derive(Debug, Copy, Clone, PartialEq, Eq)]
739pub struct SslCtValidationMode(c_int);
740
741#[cfg(ossl111)]
742impl SslCtValidationMode {
743 pub const PERMISSIVE: SslCtValidationMode =
744 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
745 pub const STRICT: SslCtValidationMode =
746 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
747}
748
749#[derive(Debug, Copy, Clone, PartialEq, Eq)]
751pub struct CertCompressionAlgorithm(c_int);
752
753impl CertCompressionAlgorithm {
754 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
755 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
756 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
757}
758
759#[derive(Debug, Copy, Clone, PartialEq, Eq)]
761pub struct SslVersion(c_int);
762
763impl SslVersion {
764 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
766
767 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
769
770 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
772
773 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
775
776 #[cfg(any(ossl111, libressl, boringssl, awslc))]
780 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
781
782 #[cfg(tongsuo)]
783 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
784
785 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
789
790 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
794}
795
796cfg_if! {
797 if #[cfg(any(boringssl, awslc))] {
798 type SslCacheTy = i64;
799 type SslCacheSize = libc::c_ulong;
800 type MtuTy = u32;
801 type ModeTy = u32;
802 type SizeTy = usize;
803 } else {
804 type SslCacheTy = i64;
805 type SslCacheSize = c_long;
806 type MtuTy = c_long;
807 type ModeTy = c_long;
808 type SizeTy = u32;
809 }
810}
811
812#[corresponds(SSL_select_next_proto)]
823pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
824 unsafe {
825 let mut out = ptr::null_mut();
826 let mut outlen = 0;
827 let r = ffi::SSL_select_next_proto(
828 &mut out,
829 &mut outlen,
830 server.as_ptr(),
831 server.len() as c_uint,
832 client.as_ptr(),
833 client.len() as c_uint,
834 );
835 if r == ffi::OPENSSL_NPN_NEGOTIATED {
836 Some(util::from_raw_parts(out as *const u8, outlen as usize))
837 } else {
838 None
839 }
840 }
841}
842
843pub struct SslContextBuilder(SslContext);
845
846impl SslContextBuilder {
847 #[corresponds(SSL_CTX_new)]
849 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
850 unsafe {
851 init();
852 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
853
854 Ok(SslContextBuilder::from_ptr(ctx))
855 }
856 }
857
858 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
864 SslContextBuilder(SslContext::from_ptr(ctx))
865 }
866
867 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
869 self.0.as_ptr()
870 }
871
872 #[cfg(tongsuo)]
873 #[corresponds(SSL_CTX_enable_ntls)]
874 pub fn enable_ntls(&mut self) {
875 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
876 }
877
878 #[cfg(tongsuo)]
879 #[corresponds(SSL_CTX_disable_ntls)]
880 pub fn disable_ntls(&mut self) {
881 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
882 }
883
884 #[cfg(all(tongsuo, ossl300))]
885 #[corresponds(SSL_CTX_enable_force_ntls)]
886 pub fn enable_force_ntls(&mut self) {
887 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
888 }
889
890 #[cfg(all(tongsuo, ossl300))]
891 #[corresponds(SSL_CTX_disable_force_ntls)]
892 pub fn disable_force_ntls(&mut self) {
893 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
894 }
895
896 #[cfg(tongsuo)]
897 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
898 pub fn enable_sm_tls13_strict(&mut self) {
899 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
900 }
901
902 #[cfg(tongsuo)]
903 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
904 pub fn disable_sm_tls13_strict(&mut self) {
905 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
906 }
907
908 #[corresponds(SSL_CTX_set_verify)]
910 pub fn set_verify(&mut self, mode: SslVerifyMode) {
911 unsafe {
912 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
913 }
914 }
915
916 #[corresponds(SSL_CTX_set_verify)]
923 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
924 where
925 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
926 {
927 unsafe {
928 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
929 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
930 }
931 }
932
933 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
941 pub fn set_servername_callback<F>(&mut self, callback: F)
943 where
944 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
945 {
946 unsafe {
947 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
953 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
954 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
955 }
956 }
957
958 #[corresponds(SSL_CTX_set_verify_depth)]
962 pub fn set_verify_depth(&mut self, depth: u32) {
963 unsafe {
964 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
965 }
966 }
967
968 #[corresponds(SSL_CTX_set0_verify_cert_store)]
972 #[cfg(any(ossl110, boringssl, awslc))]
973 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
974 unsafe {
975 let ptr = cert_store.as_ptr();
976 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
977 mem::forget(cert_store);
978
979 Ok(())
980 }
981 }
982
983 #[corresponds(SSL_CTX_set_cert_store)]
985 pub fn set_cert_store(&mut self, cert_store: X509Store) {
986 unsafe {
987 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
988 mem::forget(cert_store);
989 }
990 }
991
992 #[corresponds(SSL_CTX_set_read_ahead)]
999 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1000 unsafe {
1001 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1002 }
1003 }
1004
1005 #[corresponds(SSL_CTX_set_mode)]
1009 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1010 unsafe {
1011 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1012 SslMode::from_bits_retain(bits)
1013 }
1014 }
1015
1016 #[corresponds(SSL_CTX_clear_mode)]
1018 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1019 unsafe {
1020 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1021 SslMode::from_bits_retain(bits)
1022 }
1023 }
1024
1025 #[corresponds(SSL_CTX_get_mode)]
1027 pub fn mode(&self) -> SslMode {
1028 unsafe {
1029 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1030 SslMode::from_bits_retain(bits)
1031 }
1032 }
1033
1034 #[corresponds(SSL_CTX_set_dh_auto)]
1043 #[cfg(ossl300)]
1044 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1045 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
1046 }
1047
1048 #[corresponds(SSL_CTX_set_tmp_dh)]
1050 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1051 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1052 }
1053
1054 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1061 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1062 where
1063 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1064 {
1065 unsafe {
1066 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1067
1068 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1069 }
1070 }
1071
1072 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1074 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1075 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1076 }
1077
1078 #[corresponds(SSL_CTX_set_default_verify_paths)]
1083 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1084 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1085 }
1086
1087 #[corresponds(SSL_CTX_load_verify_locations)]
1091 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1092 self.load_verify_locations(Some(file.as_ref()), None)
1093 }
1094
1095 #[corresponds(SSL_CTX_load_verify_locations)]
1097 pub fn load_verify_locations(
1098 &mut self,
1099 ca_file: Option<&Path>,
1100 ca_path: Option<&Path>,
1101 ) -> Result<(), ErrorStack> {
1102 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1103 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1104 unsafe {
1105 cvt(ffi::SSL_CTX_load_verify_locations(
1106 self.as_ptr(),
1107 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1108 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1109 ))
1110 .map(|_| ())
1111 }
1112 }
1113
1114 #[corresponds(SSL_CTX_set_client_CA_list)]
1119 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1120 unsafe {
1121 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1122 mem::forget(list);
1123 }
1124 }
1125
1126 #[corresponds(SSL_CTX_add_client_CA)]
1129 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1130 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1131 }
1132
1133 #[corresponds(SSL_CTX_set_session_id_context)]
1142 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1143 unsafe {
1144 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1145 cvt(ffi::SSL_CTX_set_session_id_context(
1146 self.as_ptr(),
1147 sid_ctx.as_ptr(),
1148 sid_ctx.len() as SizeTy,
1149 ))
1150 .map(|_| ())
1151 }
1152 }
1153
1154 #[corresponds(SSL_CTX_use_certificate_file)]
1160 pub fn set_certificate_file<P: AsRef<Path>>(
1161 &mut self,
1162 file: P,
1163 file_type: SslFiletype,
1164 ) -> Result<(), ErrorStack> {
1165 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1166 unsafe {
1167 cvt(ffi::SSL_CTX_use_certificate_file(
1168 self.as_ptr(),
1169 file.as_ptr() as *const _,
1170 file_type.as_raw(),
1171 ))
1172 .map(|_| ())
1173 }
1174 }
1175
1176 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1182 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1183 &mut self,
1184 file: P,
1185 ) -> Result<(), ErrorStack> {
1186 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1187 unsafe {
1188 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1189 self.as_ptr(),
1190 file.as_ptr() as *const _,
1191 ))
1192 .map(|_| ())
1193 }
1194 }
1195
1196 #[corresponds(SSL_CTX_use_certificate)]
1200 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1201 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1202 }
1203
1204 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1209 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1210 unsafe {
1211 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1212 mem::forget(cert);
1213 Ok(())
1214 }
1215 }
1216
1217 #[cfg(tongsuo)]
1218 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1219 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1220 &mut self,
1221 file: P,
1222 file_type: SslFiletype,
1223 ) -> Result<(), ErrorStack> {
1224 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1225 unsafe {
1226 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1227 self.as_ptr(),
1228 file.as_ptr() as *const _,
1229 file_type.as_raw(),
1230 ))
1231 .map(|_| ())
1232 }
1233 }
1234
1235 #[cfg(tongsuo)]
1236 #[corresponds(SSL_CTX_use_enc_certificate)]
1237 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1238 unsafe {
1239 cvt(ffi::SSL_CTX_use_enc_certificate(
1240 self.as_ptr(),
1241 cert.as_ptr(),
1242 ))
1243 .map(|_| ())
1244 }
1245 }
1246
1247 #[cfg(tongsuo)]
1248 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1249 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1250 &mut self,
1251 file: P,
1252 file_type: SslFiletype,
1253 ) -> Result<(), ErrorStack> {
1254 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1255 unsafe {
1256 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1257 self.as_ptr(),
1258 file.as_ptr() as *const _,
1259 file_type.as_raw(),
1260 ))
1261 .map(|_| ())
1262 }
1263 }
1264
1265 #[cfg(tongsuo)]
1266 #[corresponds(SSL_CTX_use_sign_certificate)]
1267 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1268 unsafe {
1269 cvt(ffi::SSL_CTX_use_sign_certificate(
1270 self.as_ptr(),
1271 cert.as_ptr(),
1272 ))
1273 .map(|_| ())
1274 }
1275 }
1276
1277 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1279 pub fn set_private_key_file<P: AsRef<Path>>(
1280 &mut self,
1281 file: P,
1282 file_type: SslFiletype,
1283 ) -> Result<(), ErrorStack> {
1284 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1285 unsafe {
1286 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1287 self.as_ptr(),
1288 file.as_ptr() as *const _,
1289 file_type.as_raw(),
1290 ))
1291 .map(|_| ())
1292 }
1293 }
1294
1295 #[corresponds(SSL_CTX_use_PrivateKey)]
1297 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1298 where
1299 T: HasPrivate,
1300 {
1301 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1302 }
1303
1304 #[cfg(tongsuo)]
1305 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1306 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1307 &mut self,
1308 file: P,
1309 file_type: SslFiletype,
1310 ) -> Result<(), ErrorStack> {
1311 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1312 unsafe {
1313 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1314 self.as_ptr(),
1315 file.as_ptr() as *const _,
1316 file_type.as_raw(),
1317 ))
1318 .map(|_| ())
1319 }
1320 }
1321
1322 #[cfg(tongsuo)]
1323 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1324 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1325 where
1326 T: HasPrivate,
1327 {
1328 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1329 }
1330
1331 #[cfg(tongsuo)]
1332 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1333 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1334 &mut self,
1335 file: P,
1336 file_type: SslFiletype,
1337 ) -> Result<(), ErrorStack> {
1338 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1339 unsafe {
1340 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1341 self.as_ptr(),
1342 file.as_ptr() as *const _,
1343 file_type.as_raw(),
1344 ))
1345 .map(|_| ())
1346 }
1347 }
1348
1349 #[cfg(tongsuo)]
1350 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1351 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1352 where
1353 T: HasPrivate,
1354 {
1355 unsafe {
1356 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1357 self.as_ptr(),
1358 key.as_ptr(),
1359 ))
1360 .map(|_| ())
1361 }
1362 }
1363
1364 #[corresponds(SSL_CTX_set_cipher_list)]
1372 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1373 let cipher_list = CString::new(cipher_list).unwrap();
1374 unsafe {
1375 cvt(ffi::SSL_CTX_set_cipher_list(
1376 self.as_ptr(),
1377 cipher_list.as_ptr() as *const _,
1378 ))
1379 .map(|_| ())
1380 }
1381 }
1382
1383 #[corresponds(SSL_CTX_set_ciphersuites)]
1392 #[cfg(any(ossl111, libressl, awslc))]
1393 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1394 let cipher_list = CString::new(cipher_list).unwrap();
1395 unsafe {
1396 cvt(ffi::SSL_CTX_set_ciphersuites(
1397 self.as_ptr(),
1398 cipher_list.as_ptr() as *const _,
1399 ))
1400 .map(|_| ())
1401 }
1402 }
1403
1404 #[corresponds(SSL_CTX_set_ecdh_auto)]
1408 #[cfg(libressl)]
1409 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1410 unsafe {
1411 cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ())
1412 }
1413 }
1414
1415 #[corresponds(SSL_CTX_set_options)]
1422 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1423 let bits =
1424 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1425 SslOptions::from_bits_retain(bits)
1426 }
1427
1428 #[corresponds(SSL_CTX_get_options)]
1430 pub fn options(&self) -> SslOptions {
1431 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1432 SslOptions::from_bits_retain(bits)
1433 }
1434
1435 #[corresponds(SSL_CTX_clear_options)]
1437 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1438 let bits =
1439 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1440 SslOptions::from_bits_retain(bits)
1441 }
1442
1443 #[corresponds(SSL_CTX_set_min_proto_version)]
1448 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1449 unsafe {
1450 cvt(ffi::SSL_CTX_set_min_proto_version(
1451 self.as_ptr(),
1452 version.map_or(0, |v| v.0 as _),
1453 ))
1454 .map(|_| ())
1455 }
1456 }
1457
1458 #[corresponds(SSL_CTX_set_max_proto_version)]
1463 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1464 unsafe {
1465 cvt(ffi::SSL_CTX_set_max_proto_version(
1466 self.as_ptr(),
1467 version.map_or(0, |v| v.0 as _),
1468 ))
1469 .map(|_| ())
1470 }
1471 }
1472
1473 #[corresponds(SSL_CTX_get_min_proto_version)]
1480 #[cfg(any(ossl110g, libressl))]
1481 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1482 unsafe {
1483 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1484 if r == 0 {
1485 None
1486 } else {
1487 Some(SslVersion(r))
1488 }
1489 }
1490 }
1491
1492 #[corresponds(SSL_CTX_get_max_proto_version)]
1499 #[cfg(any(ossl110g, libressl))]
1500 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1501 unsafe {
1502 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1503 if r == 0 {
1504 None
1505 } else {
1506 Some(SslVersion(r))
1507 }
1508 }
1509 }
1510
1511 #[corresponds(SSL_CTX_set_alpn_protos)]
1520 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1521 unsafe {
1522 assert!(protocols.len() <= c_uint::MAX as usize);
1523 let r = ffi::SSL_CTX_set_alpn_protos(
1524 self.as_ptr(),
1525 protocols.as_ptr(),
1526 protocols.len() as _,
1527 );
1528 if r == 0 {
1530 Ok(())
1531 } else {
1532 Err(ErrorStack::get())
1533 }
1534 }
1535 }
1536
1537 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1539 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1540 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1541 unsafe {
1542 let cstr = CString::new(protocols).unwrap();
1543
1544 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1545 if r == 0 {
1547 Ok(())
1548 } else {
1549 Err(ErrorStack::get())
1550 }
1551 }
1552 }
1553
1554 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1565 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1566 where
1567 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1568 {
1569 unsafe {
1570 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1571 ffi::SSL_CTX_set_alpn_select_cb(
1572 self.as_ptr(),
1573 Some(callbacks::raw_alpn_select::<F>),
1574 ptr::null_mut(),
1575 );
1576 }
1577 }
1578
1579 #[corresponds(SSL_CTX_check_private_key)]
1581 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1582 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1583 }
1584
1585 #[corresponds(SSL_CTX_get_cert_store)]
1587 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1588 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1589 }
1590
1591 #[corresponds(SSL_CTX_get_cert_store)]
1593 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1594 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1595 }
1596
1597 #[corresponds(SSL_CTX_get0_param)]
1601 pub fn verify_param(&self) -> &X509VerifyParamRef {
1602 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1603 }
1604
1605 #[corresponds(SSL_CTX_get0_param)]
1609 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1610 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1611 }
1612
1613 #[cfg(any(boringssl, tongsuo, awslc))]
1621 pub fn add_cert_decompression_alg<F>(
1622 &mut self,
1623 alg_id: CertCompressionAlgorithm,
1624 decompress: F,
1625 ) -> Result<(), ErrorStack>
1626 where
1627 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1628 {
1629 unsafe {
1630 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1631 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1632 self.as_ptr(),
1633 alg_id.0 as _,
1634 None,
1635 Some(raw_cert_decompression::<F>),
1636 ))
1637 .map(|_| ())
1638 }
1639 }
1640
1641 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1643 #[cfg(ossl320)]
1644 pub fn set_cert_comp_preference(
1645 &mut self,
1646 algs: &[CertCompressionAlgorithm],
1647 ) -> Result<(), ErrorStack> {
1648 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1649 unsafe {
1650 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1651 self.as_ptr(),
1652 algs.as_mut_ptr(),
1653 algs.len(),
1654 ))
1655 .map(|_| ())
1656 }
1657 }
1658
1659 #[cfg(any(boringssl, awslc))]
1667 pub fn enable_ocsp_stapling(&mut self) {
1668 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1669 }
1670
1671 #[cfg(any(boringssl, awslc))]
1679 pub fn enable_signed_cert_timestamps(&mut self) {
1680 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1681 }
1682
1683 #[cfg(any(boringssl, awslc))]
1691 pub fn set_grease_enabled(&mut self, enabled: bool) {
1692 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1693 }
1694
1695 #[cfg(any(boringssl, awslc))]
1703 pub fn set_permute_extensions(&mut self, enabled: bool) {
1704 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1705 }
1706
1707 #[corresponds(SSL_CTX_enable_ct)]
1709 #[cfg(ossl111)]
1710 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1711 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1712 }
1713
1714 #[corresponds(SSL_CTX_ct_is_enabled)]
1716 #[cfg(ossl111)]
1717 pub fn ct_is_enabled(&self) -> bool {
1718 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1719 }
1720
1721 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1723 #[cfg(not(any(boringssl, awslc)))]
1724 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1725 unsafe {
1726 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1727 .map(|_| ())
1728 }
1729 }
1730
1731 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1744 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1745 where
1746 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1747 {
1748 unsafe {
1749 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1750 cvt(
1751 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1752 as c_int,
1753 )
1754 .map(|_| ())
1755 }
1756 }
1757
1758 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1759 #[cfg(ossl300)]
1760 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1761 where
1762 F: Fn(
1763 &mut SslRef,
1764 &mut [u8],
1765 &mut [u8],
1766 &mut CipherCtxRef,
1767 &mut MacCtxRef,
1768 bool,
1769 ) -> Result<TicketKeyStatus, ErrorStack>
1770 + 'static
1771 + Sync
1772 + Send,
1773 {
1774 unsafe {
1775 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1776 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1777 self.as_ptr(),
1778 Some(raw_tlsext_ticket_key_evp::<F>),
1779 ) as c_int)
1780 .map(|_| ())
1781 }
1782 }
1783
1784 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1785 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1786 where
1787 F: Fn(
1788 &mut SslRef,
1789 &mut [u8],
1790 &mut [u8],
1791 &mut CipherCtxRef,
1792 &mut HMacCtxRef,
1793 bool,
1794 ) -> Result<TicketKeyStatus, ErrorStack>
1795 + 'static
1796 + Sync
1797 + Send,
1798 {
1799 unsafe {
1800 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1801 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1802 self.as_ptr(),
1803 Some(raw_tlsext_ticket_key::<F>),
1804 ) as c_int)
1805 .map(|_| ())
1806 }
1807 }
1808
1809 #[corresponds(SSL_CTX_set_psk_client_callback)]
1815 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1816 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1817 where
1818 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1819 + 'static
1820 + Sync
1821 + Send,
1822 {
1823 unsafe {
1824 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1825 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1826 }
1827 }
1828
1829 #[corresponds(SSL_CTX_set_psk_server_callback)]
1835 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1836 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1837 where
1838 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1839 + 'static
1840 + Sync
1841 + Send,
1842 {
1843 unsafe {
1844 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1845 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1846 }
1847 }
1848
1849 #[corresponds(SSL_CTX_sess_set_new_cb)]
1863 pub fn set_new_session_callback<F>(&mut self, callback: F)
1864 where
1865 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1866 {
1867 unsafe {
1868 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1869 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1870 }
1871 }
1872
1873 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1877 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1878 where
1879 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1880 {
1881 unsafe {
1882 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1883 ffi::SSL_CTX_sess_set_remove_cb(
1884 self.as_ptr(),
1885 Some(callbacks::raw_remove_session::<F>),
1886 );
1887 }
1888 }
1889
1890 #[corresponds(SSL_CTX_sess_set_get_cb)]
1901 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1902 where
1903 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1904 {
1905 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1906 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1907 }
1908
1909 #[corresponds(SSL_CTX_set_keylog_callback)]
1917 #[cfg(any(ossl111, boringssl, awslc))]
1918 pub fn set_keylog_callback<F>(&mut self, callback: F)
1919 where
1920 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1921 {
1922 unsafe {
1923 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1924 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1925 }
1926 }
1927
1928 #[corresponds(SSL_CTX_set_session_cache_mode)]
1932 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1933 unsafe {
1934 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1935 SslSessionCacheMode::from_bits_retain(bits)
1936 }
1937 }
1938
1939 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1945 #[cfg(ossl111)]
1946 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1947 where
1948 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1949 {
1950 unsafe {
1951 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1952 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1953 self.as_ptr(),
1954 Some(raw_stateless_cookie_generate::<F>),
1955 );
1956 }
1957 }
1958
1959 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1968 #[cfg(ossl111)]
1969 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1970 where
1971 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1972 {
1973 unsafe {
1974 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1975 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1976 self.as_ptr(),
1977 Some(raw_stateless_cookie_verify::<F>),
1978 )
1979 }
1980 }
1981
1982 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1987 #[cfg(not(any(boringssl, awslc)))]
1988 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1989 where
1990 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1991 {
1992 unsafe {
1993 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1994 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1995 }
1996 }
1997
1998 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2003 #[cfg(not(any(boringssl, awslc)))]
2004 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2005 where
2006 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2007 {
2008 unsafe {
2009 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2010 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2011 }
2012 }
2013
2014 #[corresponds(SSL_CTX_set_ex_data)]
2020 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2021 self.set_ex_data_inner(index, data);
2022 }
2023
2024 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2025 match self.ex_data_mut(index) {
2026 Some(v) => {
2027 *v = data;
2028 (v as *mut T).cast()
2029 }
2030 _ => unsafe {
2031 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2032 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2033 data
2034 },
2035 }
2036 }
2037
2038 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2039 unsafe {
2040 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2041 if data.is_null() {
2042 None
2043 } else {
2044 Some(&mut *data.cast())
2045 }
2046 }
2047 }
2048
2049 #[corresponds(SSL_CTX_add_custom_ext)]
2053 #[cfg(ossl111)]
2054 pub fn add_custom_ext<AddFn, ParseFn, T>(
2055 &mut self,
2056 ext_type: u16,
2057 context: ExtensionContext,
2058 add_cb: AddFn,
2059 parse_cb: ParseFn,
2060 ) -> Result<(), ErrorStack>
2061 where
2062 AddFn: Fn(
2063 &mut SslRef,
2064 ExtensionContext,
2065 Option<(usize, &X509Ref)>,
2066 ) -> Result<Option<T>, SslAlert>
2067 + 'static
2068 + Sync
2069 + Send,
2070 T: AsRef<[u8]> + 'static + Sync + Send,
2071 ParseFn: Fn(
2072 &mut SslRef,
2073 ExtensionContext,
2074 &[u8],
2075 Option<(usize, &X509Ref)>,
2076 ) -> Result<(), SslAlert>
2077 + 'static
2078 + Sync
2079 + Send,
2080 {
2081 let ret = unsafe {
2082 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2083 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2084
2085 ffi::SSL_CTX_add_custom_ext(
2086 self.as_ptr(),
2087 ext_type as c_uint,
2088 context.bits(),
2089 Some(raw_custom_ext_add::<AddFn, T>),
2090 Some(raw_custom_ext_free::<T>),
2091 ptr::null_mut(),
2092 Some(raw_custom_ext_parse::<ParseFn>),
2093 ptr::null_mut(),
2094 )
2095 };
2096 if ret == 1 {
2097 Ok(())
2098 } else {
2099 Err(ErrorStack::get())
2100 }
2101 }
2102
2103 #[corresponds(SSL_CTX_set_max_early_data)]
2109 #[cfg(any(ossl111, libressl))]
2110 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2111 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2112 Ok(())
2113 } else {
2114 Err(ErrorStack::get())
2115 }
2116 }
2117
2118 #[cfg(any(boringssl, awslc))]
2128 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2129 where
2130 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2131 {
2132 unsafe {
2133 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2134 ffi::SSL_CTX_set_select_certificate_cb(
2135 self.as_ptr(),
2136 Some(callbacks::raw_select_cert::<F>),
2137 );
2138 }
2139 }
2140
2141 #[corresponds(SSL_CTX_set_client_hello_cb)]
2145 #[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
2146 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2147 where
2148 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2149 {
2150 unsafe {
2151 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2152 ffi::SSL_CTX_set_client_hello_cb(
2153 self.as_ptr(),
2154 Some(callbacks::raw_client_hello::<F>),
2155 ptr,
2156 );
2157 }
2158 }
2159
2160 #[corresponds(SSL_CTX_set_info_callback)]
2163 pub fn set_info_callback<F>(&mut self, callback: F)
2164 where
2165 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2166 {
2167 unsafe {
2168 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2169 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2170 }
2171 }
2172
2173 #[corresponds(SSL_CTX_sess_set_cache_size)]
2177 #[allow(clippy::useless_conversion)]
2178 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2179 unsafe {
2180 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2181 }
2182 }
2183
2184 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2188 #[cfg(ossl110)]
2189 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2190 let sigalgs = CString::new(sigalgs).unwrap();
2191 unsafe {
2192 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2193 .map(|_| ())
2194 }
2195 }
2196
2197 #[corresponds(SSL_CTX_set1_groups_list)]
2201 #[cfg(any(ossl111, boringssl, libressl, awslc))]
2202 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2203 let groups = CString::new(groups).unwrap();
2204 unsafe {
2205 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2206 }
2207 }
2208
2209 #[corresponds(SSL_CTX_set_num_tickets)]
2214 #[cfg(any(ossl111, boringssl, awslc))]
2215 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2216 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2217 }
2218
2219 #[corresponds(SSL_CTX_set_security_level)]
2224 #[cfg(any(ossl110, libressl360))]
2225 pub fn set_security_level(&mut self, level: u32) {
2226 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2227 }
2228
2229 pub fn build(self) -> SslContext {
2231 self.0
2232 }
2233}
2234
2235foreign_type_and_impl_send_sync! {
2236 type CType = ffi::SSL_CTX;
2237 fn drop = ffi::SSL_CTX_free;
2238
2239 pub struct SslContext;
2244
2245 pub struct SslContextRef;
2249}
2250
2251impl Clone for SslContext {
2252 fn clone(&self) -> Self {
2253 (**self).to_owned()
2254 }
2255}
2256
2257impl ToOwned for SslContextRef {
2258 type Owned = SslContext;
2259
2260 fn to_owned(&self) -> Self::Owned {
2261 unsafe {
2262 SSL_CTX_up_ref(self.as_ptr());
2263 SslContext::from_ptr(self.as_ptr())
2264 }
2265 }
2266}
2267
2268impl fmt::Debug for SslContext {
2270 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2271 write!(fmt, "SslContext")
2272 }
2273}
2274
2275impl SslContext {
2276 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2278 SslContextBuilder::new(method)
2279 }
2280
2281 #[corresponds(SSL_CTX_get_ex_new_index)]
2286 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2287 where
2288 T: 'static + Sync + Send,
2289 {
2290 unsafe {
2291 ffi::init();
2292 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2293 Ok(Index::from_raw(idx))
2294 }
2295 }
2296
2297 fn cached_ex_index<T>() -> Index<SslContext, T>
2299 where
2300 T: 'static + Sync + Send,
2301 {
2302 unsafe {
2303 let idx = *INDEXES
2304 .lock()
2305 .unwrap_or_else(|e| e.into_inner())
2306 .entry(TypeId::of::<T>())
2307 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2308 Index::from_raw(idx)
2309 }
2310 }
2311}
2312
2313impl SslContextRef {
2314 #[corresponds(SSL_CTX_get0_certificate)]
2318 #[cfg(any(ossl110, libressl))]
2319 pub fn certificate(&self) -> Option<&X509Ref> {
2320 unsafe {
2321 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2322 X509Ref::from_const_ptr_opt(ptr)
2323 }
2324 }
2325
2326 #[corresponds(SSL_CTX_get0_privatekey)]
2330 #[cfg(any(ossl110, libressl))]
2331 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2332 unsafe {
2333 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2334 PKeyRef::from_const_ptr_opt(ptr)
2335 }
2336 }
2337
2338 #[corresponds(SSL_CTX_get_cert_store)]
2340 pub fn cert_store(&self) -> &X509StoreRef {
2341 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2342 }
2343
2344 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2346 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2347 unsafe {
2348 let mut chain = ptr::null_mut();
2349 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2350 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2351 }
2352 }
2353
2354 #[corresponds(SSL_CTX_get_ex_data)]
2356 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2357 unsafe {
2358 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2359 if data.is_null() {
2360 None
2361 } else {
2362 Some(&*(data as *const T))
2363 }
2364 }
2365 }
2366
2367 #[corresponds(SSL_CTX_get_max_early_data)]
2371 #[cfg(any(ossl111, libressl))]
2372 pub fn max_early_data(&self) -> u32 {
2373 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2374 }
2375
2376 #[corresponds(SSL_CTX_add_session)]
2385 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2386 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2387 }
2388
2389 #[corresponds(SSL_CTX_remove_session)]
2398 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2399 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2400 }
2401
2402 #[corresponds(SSL_CTX_sess_get_cache_size)]
2406 #[allow(clippy::unnecessary_cast)]
2407 pub fn session_cache_size(&self) -> i64 {
2408 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2409 }
2410
2411 #[corresponds(SSL_CTX_get_verify_mode)]
2415 pub fn verify_mode(&self) -> SslVerifyMode {
2416 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2417 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2418 }
2419
2420 #[corresponds(SSL_CTX_get_num_tickets)]
2425 #[cfg(ossl111)]
2426 pub fn num_tickets(&self) -> usize {
2427 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2428 }
2429
2430 #[corresponds(SSL_CTX_get_security_level)]
2435 #[cfg(any(ossl110, libressl360))]
2436 pub fn security_level(&self) -> u32 {
2437 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2438 }
2439}
2440
2441pub struct CipherBits {
2443 pub secret: i32,
2445
2446 pub algorithm: i32,
2448}
2449
2450pub struct SslCipher(*mut ffi::SSL_CIPHER);
2452
2453impl ForeignType for SslCipher {
2454 type CType = ffi::SSL_CIPHER;
2455 type Ref = SslCipherRef;
2456
2457 #[inline]
2458 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2459 SslCipher(ptr)
2460 }
2461
2462 #[inline]
2463 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2464 self.0
2465 }
2466}
2467
2468impl Stackable for SslCipher {
2469 type StackType = ffi::stack_st_SSL_CIPHER;
2470}
2471
2472impl Deref for SslCipher {
2473 type Target = SslCipherRef;
2474
2475 fn deref(&self) -> &SslCipherRef {
2476 unsafe { SslCipherRef::from_ptr(self.0) }
2477 }
2478}
2479
2480impl DerefMut for SslCipher {
2481 fn deref_mut(&mut self) -> &mut SslCipherRef {
2482 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2483 }
2484}
2485
2486pub struct SslCipherRef(Opaque);
2490
2491impl ForeignTypeRef for SslCipherRef {
2492 type CType = ffi::SSL_CIPHER;
2493}
2494
2495impl SslCipherRef {
2496 #[corresponds(SSL_CIPHER_get_name)]
2498 pub fn name(&self) -> &'static str {
2499 unsafe {
2500 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2501 CStr::from_ptr(ptr).to_str().unwrap()
2502 }
2503 }
2504
2505 #[corresponds(SSL_CIPHER_standard_name)]
2509 #[cfg(ossl111)]
2510 pub fn standard_name(&self) -> Option<&'static str> {
2511 unsafe {
2512 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2513 if ptr.is_null() {
2514 None
2515 } else {
2516 Some(CStr::from_ptr(ptr).to_str().unwrap())
2517 }
2518 }
2519 }
2520
2521 #[corresponds(SSL_CIPHER_get_version)]
2523 pub fn version(&self) -> &'static str {
2524 let version = unsafe {
2525 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2526 CStr::from_ptr(ptr as *const _)
2527 };
2528
2529 str::from_utf8(version.to_bytes()).unwrap()
2530 }
2531
2532 #[corresponds(SSL_CIPHER_get_bits)]
2534 #[allow(clippy::useless_conversion)]
2535 pub fn bits(&self) -> CipherBits {
2536 unsafe {
2537 let mut algo_bits = 0;
2538 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2539 CipherBits {
2540 secret: secret_bits.into(),
2541 algorithm: algo_bits.into(),
2542 }
2543 }
2544 }
2545
2546 #[corresponds(SSL_CIPHER_description)]
2548 pub fn description(&self) -> String {
2549 unsafe {
2550 let mut buf = [0; 128];
2552 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2553 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2554 }
2555 }
2556
2557 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2561 #[cfg(ossl111)]
2562 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2563 unsafe {
2564 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2565 if ptr.is_null() {
2566 None
2567 } else {
2568 Some(MessageDigest::from_ptr(ptr))
2569 }
2570 }
2571 }
2572
2573 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2577 #[cfg(any(ossl110, libressl))]
2578 pub fn cipher_nid(&self) -> Option<Nid> {
2579 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2580 if n == 0 {
2581 None
2582 } else {
2583 Some(Nid::from_raw(n))
2584 }
2585 }
2586
2587 #[corresponds(SSL_CIPHER_get_protocol_id)]
2591 #[cfg(ossl111)]
2592 pub fn protocol_id(&self) -> [u8; 2] {
2593 unsafe {
2594 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2595 id.to_be_bytes()
2596 }
2597 }
2598}
2599
2600impl fmt::Debug for SslCipherRef {
2601 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2602 write!(fmt, "{}", self.name())
2603 }
2604}
2605
2606#[derive(Debug)]
2608pub struct CipherLists {
2609 pub suites: Stack<SslCipher>,
2610 pub signalling_suites: Stack<SslCipher>,
2611}
2612
2613foreign_type_and_impl_send_sync! {
2614 type CType = ffi::SSL_SESSION;
2615 fn drop = ffi::SSL_SESSION_free;
2616
2617 pub struct SslSession;
2621
2622 pub struct SslSessionRef;
2626}
2627
2628impl Clone for SslSession {
2629 fn clone(&self) -> SslSession {
2630 SslSessionRef::to_owned(self)
2631 }
2632}
2633
2634impl SslSession {
2635 from_der! {
2636 #[corresponds(d2i_SSL_SESSION)]
2638 from_der,
2639 SslSession,
2640 ffi::d2i_SSL_SESSION
2641 }
2642}
2643
2644impl ToOwned for SslSessionRef {
2645 type Owned = SslSession;
2646
2647 fn to_owned(&self) -> SslSession {
2648 unsafe {
2649 SSL_SESSION_up_ref(self.as_ptr());
2650 SslSession(self.as_ptr())
2651 }
2652 }
2653}
2654
2655impl SslSessionRef {
2656 #[corresponds(SSL_SESSION_get_id)]
2658 pub fn id(&self) -> &[u8] {
2659 unsafe {
2660 let mut len = 0;
2661 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2662 #[allow(clippy::unnecessary_cast)]
2663 util::from_raw_parts(p as *const u8, len as usize)
2664 }
2665 }
2666
2667 #[corresponds(SSL_SESSION_get_master_key)]
2669 pub fn master_key_len(&self) -> usize {
2670 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2671 }
2672
2673 #[corresponds(SSL_SESSION_get_master_key)]
2677 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2678 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2679 }
2680
2681 #[corresponds(SSL_SESSION_get_max_early_data)]
2685 #[cfg(any(ossl111, libressl))]
2686 pub fn max_early_data(&self) -> u32 {
2687 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2688 }
2689
2690 #[corresponds(SSL_SESSION_get_time)]
2692 #[allow(clippy::useless_conversion)]
2693 pub fn time(&self) -> SslTimeTy {
2694 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2695 }
2696
2697 #[corresponds(SSL_SESSION_get_timeout)]
2701 #[allow(clippy::useless_conversion)]
2702 pub fn timeout(&self) -> i64 {
2703 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2704 }
2705
2706 #[corresponds(SSL_SESSION_get_protocol_version)]
2710 #[cfg(any(ossl110, libressl))]
2711 pub fn protocol_version(&self) -> SslVersion {
2712 unsafe {
2713 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2714 SslVersion(version)
2715 }
2716 }
2717
2718 #[corresponds(SSL_SESSION_get_protocol_version)]
2720 #[cfg(any(boringssl, awslc))]
2721 pub fn protocol_version(&self) -> SslVersion {
2722 unsafe {
2723 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2724 SslVersion(version as _)
2725 }
2726 }
2727
2728 to_der! {
2729 #[corresponds(i2d_SSL_SESSION)]
2731 to_der,
2732 ffi::i2d_SSL_SESSION
2733 }
2734}
2735
2736foreign_type_and_impl_send_sync! {
2737 type CType = ffi::SSL;
2738 fn drop = ffi::SSL_free;
2739
2740 pub struct Ssl;
2747
2748 pub struct SslRef;
2752}
2753
2754impl fmt::Debug for Ssl {
2755 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2756 fmt::Debug::fmt(&**self, fmt)
2757 }
2758}
2759
2760impl Ssl {
2761 #[corresponds(SSL_get_ex_new_index)]
2766 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2767 where
2768 T: 'static + Sync + Send,
2769 {
2770 unsafe {
2771 ffi::init();
2772 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2773 Ok(Index::from_raw(idx))
2774 }
2775 }
2776
2777 fn cached_ex_index<T>() -> Index<Ssl, T>
2779 where
2780 T: 'static + Sync + Send,
2781 {
2782 unsafe {
2783 let idx = *SSL_INDEXES
2784 .lock()
2785 .unwrap_or_else(|e| e.into_inner())
2786 .entry(TypeId::of::<T>())
2787 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2788 Index::from_raw(idx)
2789 }
2790 }
2791
2792 #[corresponds(SSL_new)]
2794 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2795 let session_ctx_index = try_get_session_ctx_index()?;
2796 unsafe {
2797 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2798 let mut ssl = Ssl::from_ptr(ptr);
2799 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2800
2801 Ok(ssl)
2802 }
2803 }
2804
2805 #[corresponds(SSL_connect)]
2811 #[allow(deprecated)]
2812 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2813 where
2814 S: Read + Write,
2815 {
2816 SslStreamBuilder::new(self, stream).connect()
2817 }
2818
2819 #[corresponds(SSL_accept)]
2826 #[allow(deprecated)]
2827 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2828 where
2829 S: Read + Write,
2830 {
2831 SslStreamBuilder::new(self, stream).accept()
2832 }
2833}
2834
2835impl fmt::Debug for SslRef {
2836 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2837 fmt.debug_struct("Ssl")
2838 .field("state", &self.state_string_long())
2839 .field("verify_result", &self.verify_result())
2840 .finish()
2841 }
2842}
2843
2844impl SslRef {
2845 #[cfg(not(feature = "tongsuo"))]
2846 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2847 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2848 }
2849
2850 #[cfg(feature = "tongsuo")]
2851 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2852 unsafe {
2853 let bio = ffi::SSL_get_rbio(self.as_ptr());
2854 bio::find_correct_bio(bio)
2855 }
2856 }
2857
2858 fn get_error(&self, ret: c_int) -> ErrorCode {
2859 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2860 }
2861
2862 #[corresponds(SSL_set_mode)]
2866 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2867 unsafe {
2868 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2869 SslMode::from_bits_retain(bits)
2870 }
2871 }
2872
2873 #[corresponds(SSL_clear_mode)]
2875 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2876 unsafe {
2877 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2878 SslMode::from_bits_retain(bits)
2879 }
2880 }
2881
2882 #[corresponds(SSL_get_mode)]
2884 pub fn mode(&self) -> SslMode {
2885 unsafe {
2886 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2887 SslMode::from_bits_retain(bits)
2888 }
2889 }
2890
2891 #[corresponds(SSL_set_connect_state)]
2893 pub fn set_connect_state(&mut self) {
2894 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2895 }
2896
2897 #[corresponds(SSL_set_accept_state)]
2899 pub fn set_accept_state(&mut self) {
2900 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2901 }
2902
2903 #[cfg(any(boringssl, awslc))]
2904 #[corresponds(SSL_ech_accepted)]
2905 pub fn ech_accepted(&self) -> bool {
2906 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2907 }
2908
2909 #[cfg(tongsuo)]
2910 #[corresponds(SSL_is_ntls)]
2911 pub fn is_ntls(&mut self) -> bool {
2912 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2913 }
2914
2915 #[cfg(tongsuo)]
2916 #[corresponds(SSL_enable_ntls)]
2917 pub fn enable_ntls(&mut self) {
2918 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2919 }
2920
2921 #[cfg(tongsuo)]
2922 #[corresponds(SSL_disable_ntls)]
2923 pub fn disable_ntls(&mut self) {
2924 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2925 }
2926
2927 #[cfg(all(tongsuo, ossl300))]
2928 #[corresponds(SSL_enable_force_ntls)]
2929 pub fn enable_force_ntls(&mut self) {
2930 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2931 }
2932
2933 #[cfg(all(tongsuo, ossl300))]
2934 #[corresponds(SSL_disable_force_ntls)]
2935 pub fn disable_force_ntls(&mut self) {
2936 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2937 }
2938
2939 #[cfg(tongsuo)]
2940 #[corresponds(SSL_enable_sm_tls13_strict)]
2941 pub fn enable_sm_tls13_strict(&mut self) {
2942 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2943 }
2944
2945 #[cfg(tongsuo)]
2946 #[corresponds(SSL_disable_sm_tls13_strict)]
2947 pub fn disable_sm_tls13_strict(&mut self) {
2948 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2949 }
2950
2951 #[corresponds(SSL_set_verify)]
2955 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2956 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2957 }
2958
2959 #[corresponds(SSL_set_verify_mode)]
2961 pub fn verify_mode(&self) -> SslVerifyMode {
2962 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2963 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2964 }
2965
2966 #[corresponds(SSL_set_verify)]
2970 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2971 where
2972 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2973 {
2974 unsafe {
2975 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2977 ffi::SSL_set_verify(
2978 self.as_ptr(),
2979 mode.bits() as c_int,
2980 Some(ssl_raw_verify::<F>),
2981 );
2982 }
2983 }
2984
2985 #[corresponds(SSL_set_info_callback)]
2988 pub fn set_info_callback<F>(&mut self, callback: F)
2989 where
2990 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2991 {
2992 unsafe {
2993 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2995 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
2996 }
2997 }
2998
2999 #[corresponds(SSL_set_dh_auto)]
3003 #[cfg(ossl300)]
3004 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3005 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3006 }
3007
3008 #[corresponds(SSL_set_tmp_dh)]
3012 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3013 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3014 }
3015
3016 #[corresponds(SSL_set_tmp_dh_callback)]
3020 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3021 where
3022 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3023 {
3024 unsafe {
3025 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3027 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3028 }
3029 }
3030
3031 #[corresponds(SSL_set_tmp_ecdh)]
3035 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3036 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3037 }
3038
3039 #[corresponds(SSL_set_ecdh_auto)]
3045 #[cfg(libressl)]
3046 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3047 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3048 }
3049
3050 #[corresponds(SSL_set_alpn_protos)]
3056 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3057 unsafe {
3058 assert!(protocols.len() <= c_uint::MAX as usize);
3059 let r =
3060 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3061 if r == 0 {
3063 Ok(())
3064 } else {
3065 Err(ErrorStack::get())
3066 }
3067 }
3068 }
3069
3070 #[corresponds(SSL_get_current_cipher)]
3072 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3073 unsafe {
3074 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3075
3076 SslCipherRef::from_const_ptr_opt(ptr)
3077 }
3078 }
3079
3080 #[corresponds(SSL_state_string)]
3082 pub fn state_string(&self) -> &'static str {
3083 let state = unsafe {
3084 let ptr = ffi::SSL_state_string(self.as_ptr());
3085 CStr::from_ptr(ptr as *const _)
3086 };
3087
3088 str::from_utf8(state.to_bytes()).unwrap()
3089 }
3090
3091 #[corresponds(SSL_state_string_long)]
3093 pub fn state_string_long(&self) -> &'static str {
3094 let state = unsafe {
3095 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3096 CStr::from_ptr(ptr as *const _)
3097 };
3098
3099 str::from_utf8(state.to_bytes()).unwrap()
3100 }
3101
3102 #[corresponds(SSL_set_tlsext_host_name)]
3106 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3107 let cstr = CString::new(hostname).unwrap();
3108 unsafe {
3109 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3110 .map(|_| ())
3111 }
3112 }
3113
3114 #[corresponds(SSL_get_peer_certificate)]
3116 pub fn peer_certificate(&self) -> Option<X509> {
3117 unsafe {
3118 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3119 X509::from_ptr_opt(ptr)
3120 }
3121 }
3122
3123 #[corresponds(SSL_get_peer_cert_chain)]
3128 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3129 unsafe {
3130 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3131 StackRef::from_const_ptr_opt(ptr)
3132 }
3133 }
3134
3135 #[corresponds(SSL_get0_verified_chain)]
3145 #[cfg(ossl110)]
3146 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3147 unsafe {
3148 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3149 StackRef::from_const_ptr_opt(ptr)
3150 }
3151 }
3152
3153 #[corresponds(SSL_get_certificate)]
3155 pub fn certificate(&self) -> Option<&X509Ref> {
3156 unsafe {
3157 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3158 X509Ref::from_const_ptr_opt(ptr)
3159 }
3160 }
3161
3162 #[corresponds(SSL_get_privatekey)]
3166 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3167 unsafe {
3168 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3169 PKeyRef::from_const_ptr_opt(ptr)
3170 }
3171 }
3172
3173 #[corresponds(SSL_version)]
3175 pub fn version2(&self) -> Option<SslVersion> {
3176 unsafe {
3177 let r = ffi::SSL_version(self.as_ptr());
3178 if r == 0 {
3179 None
3180 } else {
3181 Some(SslVersion(r))
3182 }
3183 }
3184 }
3185
3186 #[corresponds(SSL_get_version)]
3188 pub fn version_str(&self) -> &'static str {
3189 let version = unsafe {
3190 let ptr = ffi::SSL_get_version(self.as_ptr());
3191 CStr::from_ptr(ptr as *const _)
3192 };
3193
3194 str::from_utf8(version.to_bytes()).unwrap()
3195 }
3196
3197 #[corresponds(SSL_get0_alpn_selected)]
3204 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3205 unsafe {
3206 let mut data: *const c_uchar = ptr::null();
3207 let mut len: c_uint = 0;
3208 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3211
3212 if data.is_null() {
3213 None
3214 } else {
3215 Some(util::from_raw_parts(data, len as usize))
3216 }
3217 }
3218 }
3219
3220 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3222 #[corresponds(SSL_set_tlsext_use_srtp)]
3223 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3224 unsafe {
3225 let cstr = CString::new(protocols).unwrap();
3226
3227 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3228 if r == 0 {
3230 Ok(())
3231 } else {
3232 Err(ErrorStack::get())
3233 }
3234 }
3235 }
3236
3237 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3241 #[corresponds(SSL_get_srtp_profiles)]
3242 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3243 unsafe {
3244 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3245
3246 StackRef::from_const_ptr_opt(chain)
3247 }
3248 }
3249
3250 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3254 #[corresponds(SSL_get_selected_srtp_profile)]
3255 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3256 unsafe {
3257 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3258
3259 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3260 }
3261 }
3262
3263 #[corresponds(SSL_pending)]
3268 pub fn pending(&self) -> usize {
3269 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3270 }
3271
3272 #[corresponds(SSL_get_servername)]
3285 pub fn servername(&self, type_: NameType) -> Option<&str> {
3287 self.servername_raw(type_)
3288 .and_then(|b| str::from_utf8(b).ok())
3289 }
3290
3291 #[corresponds(SSL_get_servername)]
3299 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3300 unsafe {
3301 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3302 if name.is_null() {
3303 None
3304 } else {
3305 Some(CStr::from_ptr(name as *const _).to_bytes())
3306 }
3307 }
3308 }
3309
3310 #[corresponds(SSL_set_SSL_CTX)]
3314 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3315 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3316 }
3317
3318 #[corresponds(SSL_get_SSL_CTX)]
3320 pub fn ssl_context(&self) -> &SslContextRef {
3321 unsafe {
3322 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3323 SslContextRef::from_ptr(ssl_ctx)
3324 }
3325 }
3326
3327 #[corresponds(SSL_get0_param)]
3331 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3332 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3333 }
3334
3335 #[corresponds(SSL_get_verify_result)]
3337 pub fn verify_result(&self) -> X509VerifyResult {
3338 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3339 }
3340
3341 #[corresponds(SSL_get_session)]
3343 pub fn session(&self) -> Option<&SslSessionRef> {
3344 unsafe {
3345 let p = ffi::SSL_get_session(self.as_ptr());
3346 SslSessionRef::from_const_ptr_opt(p)
3347 }
3348 }
3349
3350 #[corresponds(SSL_get_client_random)]
3357 #[cfg(any(ossl110, libressl))]
3358 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3359 unsafe {
3360 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3361 }
3362 }
3363
3364 #[corresponds(SSL_get_server_random)]
3371 #[cfg(any(ossl110, libressl))]
3372 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3373 unsafe {
3374 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3375 }
3376 }
3377
3378 #[corresponds(SSL_export_keying_material)]
3380 pub fn export_keying_material(
3381 &self,
3382 out: &mut [u8],
3383 label: &str,
3384 context: Option<&[u8]>,
3385 ) -> Result<(), ErrorStack> {
3386 unsafe {
3387 let (context, contextlen, use_context) = match context {
3388 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3389 None => (ptr::null(), 0, 0),
3390 };
3391 cvt(ffi::SSL_export_keying_material(
3392 self.as_ptr(),
3393 out.as_mut_ptr() as *mut c_uchar,
3394 out.len(),
3395 label.as_ptr() as *const c_char,
3396 label.len(),
3397 context,
3398 contextlen,
3399 use_context,
3400 ))
3401 .map(|_| ())
3402 }
3403 }
3404
3405 #[corresponds(SSL_export_keying_material_early)]
3412 #[cfg(ossl111)]
3413 pub fn export_keying_material_early(
3414 &self,
3415 out: &mut [u8],
3416 label: &str,
3417 context: &[u8],
3418 ) -> Result<(), ErrorStack> {
3419 unsafe {
3420 cvt(ffi::SSL_export_keying_material_early(
3421 self.as_ptr(),
3422 out.as_mut_ptr() as *mut c_uchar,
3423 out.len(),
3424 label.as_ptr() as *const c_char,
3425 label.len(),
3426 context.as_ptr() as *const c_uchar,
3427 context.len(),
3428 ))
3429 .map(|_| ())
3430 }
3431 }
3432
3433 #[corresponds(SSL_set_session)]
3444 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3445 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3446 }
3447
3448 #[corresponds(SSL_session_reused)]
3450 pub fn session_reused(&self) -> bool {
3451 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3452 }
3453
3454 #[cfg(any(boringssl, awslc))]
3462 pub fn enable_ocsp_stapling(&mut self) {
3463 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3464 }
3465
3466 #[cfg(any(boringssl, awslc))]
3474 pub fn enable_signed_cert_timestamps(&mut self) {
3475 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3476 }
3477
3478 #[cfg(any(boringssl, awslc))]
3486 pub fn set_permute_extensions(&mut self, enabled: bool) {
3487 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3488 }
3489
3490 #[corresponds(SSL_enable_ct)]
3492 #[cfg(ossl111)]
3493 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3494 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3495 }
3496
3497 #[corresponds(SSL_ct_is_enabled)]
3499 #[cfg(ossl111)]
3500 pub fn ct_is_enabled(&self) -> bool {
3501 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3502 }
3503
3504 #[corresponds(SSL_set_tlsext_status_type)]
3506 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3507 unsafe {
3508 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3509 }
3510 }
3511
3512 #[corresponds(SSL_get_extms_support)]
3516 #[cfg(ossl110)]
3517 pub fn extms_support(&self) -> Option<bool> {
3518 unsafe {
3519 match ffi::SSL_get_extms_support(self.as_ptr()) {
3520 -1 => None,
3521 ret => Some(ret != 0),
3522 }
3523 }
3524 }
3525
3526 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3528 #[cfg(not(any(boringssl, awslc)))]
3529 pub fn ocsp_status(&self) -> Option<&[u8]> {
3530 unsafe {
3531 let mut p = ptr::null_mut();
3532 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3533
3534 if len < 0 {
3535 None
3536 } else {
3537 Some(util::from_raw_parts(p as *const u8, len as usize))
3538 }
3539 }
3540 }
3541
3542 #[corresponds(SSL_get0_ocsp_response)]
3544 #[cfg(any(boringssl, awslc))]
3545 pub fn ocsp_status(&self) -> Option<&[u8]> {
3546 unsafe {
3547 let mut p = ptr::null();
3548 let mut len: usize = 0;
3549 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3550
3551 if len == 0 {
3552 None
3553 } else {
3554 Some(util::from_raw_parts(p as *const u8, len))
3555 }
3556 }
3557 }
3558
3559 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3561 #[cfg(not(any(boringssl, awslc)))]
3562 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3563 unsafe {
3564 assert!(response.len() <= c_int::MAX as usize);
3565 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3566 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3567 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3568 self.as_ptr(),
3569 p as *mut c_uchar,
3570 response.len() as c_long,
3571 ) as c_int)
3572 .map(|_| ())
3573 .inspect_err(|_e| {
3574 ffi::OPENSSL_free(p);
3575 })
3576 }
3577 }
3578
3579 #[corresponds(SSL_set_ocsp_response)]
3581 #[cfg(any(boringssl, awslc))]
3582 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3583 unsafe {
3584 cvt(ffi::SSL_set_ocsp_response(
3585 self.as_ptr(),
3586 response.as_ptr(),
3587 response.len(),
3588 ))
3589 .map(|_| ())
3590 }
3591 }
3592
3593 #[corresponds(SSL_is_server)]
3595 pub fn is_server(&self) -> bool {
3596 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3597 }
3598
3599 #[corresponds(SSL_set_ex_data)]
3605 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3606 match self.ex_data_mut(index) {
3607 Some(v) => *v = data,
3608 None => unsafe {
3609 let data = Box::new(data);
3610 ffi::SSL_set_ex_data(
3611 self.as_ptr(),
3612 index.as_raw(),
3613 Box::into_raw(data) as *mut c_void,
3614 );
3615 },
3616 }
3617 }
3618
3619 #[corresponds(SSL_get_ex_data)]
3621 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3622 unsafe {
3623 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3624 if data.is_null() {
3625 None
3626 } else {
3627 Some(&*(data as *const T))
3628 }
3629 }
3630 }
3631
3632 #[corresponds(SSL_get_ex_data)]
3634 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3635 unsafe {
3636 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3637 if data.is_null() {
3638 None
3639 } else {
3640 Some(&mut *(data as *mut T))
3641 }
3642 }
3643 }
3644
3645 #[corresponds(SSL_set_max_early_data)]
3649 #[cfg(any(ossl111, libressl))]
3650 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3651 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3652 Ok(())
3653 } else {
3654 Err(ErrorStack::get())
3655 }
3656 }
3657
3658 #[corresponds(SSL_get_max_early_data)]
3662 #[cfg(any(ossl111, libressl))]
3663 pub fn max_early_data(&self) -> u32 {
3664 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3665 }
3666
3667 #[corresponds(SSL_get_finished)]
3672 pub fn finished(&self, buf: &mut [u8]) -> usize {
3673 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3674 }
3675
3676 #[corresponds(SSL_get_peer_finished)]
3682 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3683 unsafe {
3684 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3685 }
3686 }
3687
3688 #[corresponds(SSL_is_init_finished)]
3690 #[cfg(ossl110)]
3691 pub fn is_init_finished(&self) -> bool {
3692 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3693 }
3694
3695 #[corresponds(SSL_client_hello_isv2)]
3701 #[cfg(ossl111)]
3702 pub fn client_hello_isv2(&self) -> bool {
3703 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3704 }
3705
3706 #[corresponds(SSL_client_hello_get0_legacy_version)]
3712 #[cfg(ossl111)]
3713 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3714 unsafe {
3715 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3716 if version == 0 {
3717 None
3718 } else {
3719 Some(SslVersion(version as c_int))
3720 }
3721 }
3722 }
3723
3724 #[corresponds(SSL_client_hello_get0_random)]
3730 #[cfg(ossl111)]
3731 pub fn client_hello_random(&self) -> Option<&[u8]> {
3732 unsafe {
3733 let mut ptr = ptr::null();
3734 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3735 if len == 0 {
3736 None
3737 } else {
3738 Some(util::from_raw_parts(ptr, len))
3739 }
3740 }
3741 }
3742
3743 #[corresponds(SSL_client_hello_get0_session_id)]
3749 #[cfg(ossl111)]
3750 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3751 unsafe {
3752 let mut ptr = ptr::null();
3753 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3754 if len == 0 {
3755 None
3756 } else {
3757 Some(util::from_raw_parts(ptr, len))
3758 }
3759 }
3760 }
3761
3762 #[corresponds(SSL_client_hello_get0_ciphers)]
3768 #[cfg(ossl111)]
3769 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3770 unsafe {
3771 let mut ptr = ptr::null();
3772 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3773 if len == 0 {
3774 None
3775 } else {
3776 Some(util::from_raw_parts(ptr, len))
3777 }
3778 }
3779 }
3780
3781 #[cfg(ossl111)]
3787 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3788 unsafe {
3789 let mut ptr = ptr::null();
3790 let mut len = 0usize;
3791 let r = ffi::SSL_client_hello_get0_ext(
3792 self.as_ptr(),
3793 ext_type.as_raw() as _,
3794 &mut ptr,
3795 &mut len,
3796 );
3797 if r == 0 {
3798 None
3799 } else {
3800 Some(util::from_raw_parts(ptr, len))
3801 }
3802 }
3803 }
3804
3805 #[corresponds(SSL_bytes_to_cipher_list)]
3810 #[cfg(ossl111)]
3811 pub fn bytes_to_cipher_list(
3812 &self,
3813 bytes: &[u8],
3814 isv2format: bool,
3815 ) -> Result<CipherLists, ErrorStack> {
3816 unsafe {
3817 let ptr = bytes.as_ptr();
3818 let len = bytes.len();
3819 let mut sk = ptr::null_mut();
3820 let mut scsvs = ptr::null_mut();
3821 let res = ffi::SSL_bytes_to_cipher_list(
3822 self.as_ptr(),
3823 ptr,
3824 len,
3825 isv2format as c_int,
3826 &mut sk,
3827 &mut scsvs,
3828 );
3829 if res == 1 {
3830 Ok(CipherLists {
3831 suites: Stack::from_ptr(sk),
3832 signalling_suites: Stack::from_ptr(scsvs),
3833 })
3834 } else {
3835 Err(ErrorStack::get())
3836 }
3837 }
3838 }
3839
3840 #[corresponds(SSL_client_hello_get0_compression_methods)]
3846 #[cfg(ossl111)]
3847 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3848 unsafe {
3849 let mut ptr = ptr::null();
3850 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3851 if len == 0 {
3852 None
3853 } else {
3854 Some(util::from_raw_parts(ptr, len))
3855 }
3856 }
3857 }
3858
3859 #[corresponds(SSL_set_mtu)]
3861 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3862 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3863 }
3864
3865 #[corresponds(SSL_get_psk_identity_hint)]
3869 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3870 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3871 unsafe {
3872 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3873 if ptr.is_null() {
3874 None
3875 } else {
3876 Some(CStr::from_ptr(ptr).to_bytes())
3877 }
3878 }
3879 }
3880
3881 #[corresponds(SSL_get_psk_identity)]
3883 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3884 pub fn psk_identity(&self) -> Option<&[u8]> {
3885 unsafe {
3886 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3887 if ptr.is_null() {
3888 None
3889 } else {
3890 Some(CStr::from_ptr(ptr).to_bytes())
3891 }
3892 }
3893 }
3894
3895 #[corresponds(SSL_add0_chain_cert)]
3896 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3897 unsafe {
3898 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3899 mem::forget(chain);
3900 }
3901 Ok(())
3902 }
3903
3904 #[cfg(not(any(boringssl, awslc)))]
3906 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3907 unsafe {
3908 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3909 };
3910 Ok(())
3911 }
3912
3913 #[corresponds(SSL_use_Private_Key_file)]
3915 pub fn set_private_key_file<P: AsRef<Path>>(
3916 &mut self,
3917 path: P,
3918 ssl_file_type: SslFiletype,
3919 ) -> Result<(), ErrorStack> {
3920 let p = path.as_ref().as_os_str().to_str().unwrap();
3921 let key_file = CString::new(p).unwrap();
3922 unsafe {
3923 cvt(ffi::SSL_use_PrivateKey_file(
3924 self.as_ptr(),
3925 key_file.as_ptr(),
3926 ssl_file_type.as_raw(),
3927 ))?;
3928 };
3929 Ok(())
3930 }
3931
3932 #[corresponds(SSL_use_PrivateKey)]
3934 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3935 unsafe {
3936 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3937 };
3938 Ok(())
3939 }
3940
3941 #[cfg(tongsuo)]
3942 #[corresponds(SSL_use_enc_Private_Key_file)]
3943 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3944 &mut self,
3945 path: P,
3946 ssl_file_type: SslFiletype,
3947 ) -> Result<(), ErrorStack> {
3948 let p = path.as_ref().as_os_str().to_str().unwrap();
3949 let key_file = CString::new(p).unwrap();
3950 unsafe {
3951 cvt(ffi::SSL_use_enc_PrivateKey_file(
3952 self.as_ptr(),
3953 key_file.as_ptr(),
3954 ssl_file_type.as_raw(),
3955 ))?;
3956 };
3957 Ok(())
3958 }
3959
3960 #[cfg(tongsuo)]
3961 #[corresponds(SSL_use_enc_PrivateKey)]
3962 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3963 unsafe {
3964 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3965 };
3966 Ok(())
3967 }
3968
3969 #[cfg(tongsuo)]
3970 #[corresponds(SSL_use_sign_Private_Key_file)]
3971 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3972 &mut self,
3973 path: P,
3974 ssl_file_type: SslFiletype,
3975 ) -> Result<(), ErrorStack> {
3976 let p = path.as_ref().as_os_str().to_str().unwrap();
3977 let key_file = CString::new(p).unwrap();
3978 unsafe {
3979 cvt(ffi::SSL_use_sign_PrivateKey_file(
3980 self.as_ptr(),
3981 key_file.as_ptr(),
3982 ssl_file_type.as_raw(),
3983 ))?;
3984 };
3985 Ok(())
3986 }
3987
3988 #[cfg(tongsuo)]
3989 #[corresponds(SSL_use_sign_PrivateKey)]
3990 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3991 unsafe {
3992 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3993 };
3994 Ok(())
3995 }
3996
3997 #[corresponds(SSL_use_certificate)]
3999 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4000 unsafe {
4001 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4002 };
4003 Ok(())
4004 }
4005
4006 #[cfg(tongsuo)]
4007 #[corresponds(SSL_use_enc_certificate)]
4008 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4009 unsafe {
4010 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4011 };
4012 Ok(())
4013 }
4014
4015 #[cfg(tongsuo)]
4016 #[corresponds(SSL_use_sign_certificate)]
4017 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4018 unsafe {
4019 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4020 };
4021 Ok(())
4022 }
4023
4024 #[corresponds(SSL_use_certificate_chain_file)]
4030 #[cfg(any(ossl110, libressl))]
4031 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4032 &mut self,
4033 path: P,
4034 ) -> Result<(), ErrorStack> {
4035 let p = path.as_ref().as_os_str().to_str().unwrap();
4036 let cert_file = CString::new(p).unwrap();
4037 unsafe {
4038 cvt(ffi::SSL_use_certificate_chain_file(
4039 self.as_ptr(),
4040 cert_file.as_ptr(),
4041 ))?;
4042 };
4043 Ok(())
4044 }
4045
4046 #[corresponds(SSL_add_client_CA)]
4048 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4049 unsafe {
4050 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4051 };
4052 Ok(())
4053 }
4054
4055 #[corresponds(SSL_set_client_CA_list)]
4057 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4058 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4059 mem::forget(list);
4060 }
4061
4062 #[corresponds(SSL_set_min_proto_version)]
4067 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4068 unsafe {
4069 cvt(ffi::SSL_set_min_proto_version(
4070 self.as_ptr(),
4071 version.map_or(0, |v| v.0 as _),
4072 ))
4073 .map(|_| ())
4074 }
4075 }
4076
4077 #[corresponds(SSL_set_max_proto_version)]
4082 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4083 unsafe {
4084 cvt(ffi::SSL_set_max_proto_version(
4085 self.as_ptr(),
4086 version.map_or(0, |v| v.0 as _),
4087 ))
4088 .map(|_| ())
4089 }
4090 }
4091
4092 #[corresponds(SSL_set_ciphersuites)]
4101 #[cfg(any(ossl111, libressl))]
4102 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4103 let cipher_list = CString::new(cipher_list).unwrap();
4104 unsafe {
4105 cvt(ffi::SSL_set_ciphersuites(
4106 self.as_ptr(),
4107 cipher_list.as_ptr() as *const _,
4108 ))
4109 .map(|_| ())
4110 }
4111 }
4112
4113 #[corresponds(SSL_set_cipher_list)]
4121 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4122 let cipher_list = CString::new(cipher_list).unwrap();
4123 unsafe {
4124 cvt(ffi::SSL_set_cipher_list(
4125 self.as_ptr(),
4126 cipher_list.as_ptr() as *const _,
4127 ))
4128 .map(|_| ())
4129 }
4130 }
4131
4132 #[corresponds(SSL_set_cert_store)]
4134 #[cfg(any(ossl110, boringssl, awslc))]
4135 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4136 unsafe {
4137 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4138 mem::forget(cert_store);
4139 Ok(())
4140 }
4141 }
4142
4143 #[corresponds(SSL_set_num_tickets)]
4148 #[cfg(ossl111)]
4149 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4150 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4151 }
4152
4153 #[corresponds(SSL_get_num_tickets)]
4158 #[cfg(ossl111)]
4159 pub fn num_tickets(&self) -> usize {
4160 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4161 }
4162
4163 #[corresponds(SSL_set_security_level)]
4168 #[cfg(any(ossl110, libressl360))]
4169 pub fn set_security_level(&mut self, level: u32) {
4170 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4171 }
4172
4173 #[corresponds(SSL_get_security_level)]
4178 #[cfg(any(ossl110, libressl360))]
4179 pub fn security_level(&self) -> u32 {
4180 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4181 }
4182
4183 #[corresponds(SSL_get_peer_tmp_key)]
4188 #[cfg(ossl300)]
4189 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4190 unsafe {
4191 let mut key = ptr::null_mut();
4192 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4193 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4194 Err(e) => Err(e),
4195 }
4196 }
4197 }
4198
4199 #[corresponds(SSL_get_tmp_key)]
4204 #[cfg(ossl300)]
4205 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4206 unsafe {
4207 let mut key = ptr::null_mut();
4208 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4209 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4210 Err(e) => Err(e),
4211 }
4212 }
4213 }
4214}
4215
4216#[derive(Debug)]
4218pub struct MidHandshakeSslStream<S> {
4219 stream: SslStream<S>,
4220 error: Error,
4221}
4222
4223impl<S> MidHandshakeSslStream<S> {
4224 pub fn get_ref(&self) -> &S {
4226 self.stream.get_ref()
4227 }
4228
4229 pub fn get_mut(&mut self) -> &mut S {
4231 self.stream.get_mut()
4232 }
4233
4234 pub fn ssl(&self) -> &SslRef {
4236 self.stream.ssl()
4237 }
4238
4239 pub fn ssl_mut(&mut self) -> &mut SslRef {
4241 self.stream.ssl_mut()
4242 }
4243
4244 pub fn error(&self) -> &Error {
4246 &self.error
4247 }
4248
4249 pub fn into_error(self) -> Error {
4251 self.error
4252 }
4253}
4254
4255impl<S> MidHandshakeSslStream<S>
4256where
4257 S: Read + Write,
4258{
4259 #[corresponds(SSL_do_handshake)]
4262 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4263 match self.stream.do_handshake() {
4264 Ok(()) => Ok(self.stream),
4265 Err(error) => {
4266 self.error = error;
4267 match self.error.code() {
4268 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4269 Err(HandshakeError::WouldBlock(self))
4270 }
4271 _ => Err(HandshakeError::Failure(self)),
4272 }
4273 }
4274 }
4275 }
4276}
4277
4278pub struct SslStream<S> {
4280 ssl: ManuallyDrop<Ssl>,
4281 method: ManuallyDrop<BioMethod>,
4282 _p: PhantomData<S>,
4283}
4284
4285impl<S> Drop for SslStream<S> {
4286 fn drop(&mut self) {
4287 unsafe {
4289 ManuallyDrop::drop(&mut self.ssl);
4290 ManuallyDrop::drop(&mut self.method);
4291 }
4292 }
4293}
4294
4295impl<S> fmt::Debug for SslStream<S>
4296where
4297 S: fmt::Debug,
4298{
4299 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4300 fmt.debug_struct("SslStream")
4301 .field("stream", &self.get_ref())
4302 .field("ssl", &self.ssl())
4303 .finish()
4304 }
4305}
4306
4307impl<S: Read + Write> SslStream<S> {
4308 #[corresponds(SSL_set_bio)]
4316 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4317 let (bio, method) = bio::new(stream)?;
4318 unsafe {
4319 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4320 }
4321
4322 Ok(SslStream {
4323 ssl: ManuallyDrop::new(ssl),
4324 method: ManuallyDrop::new(method),
4325 _p: PhantomData,
4326 })
4327 }
4328
4329 #[corresponds(SSL_read_early_data)]
4338 #[cfg(any(ossl111, libressl))]
4339 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4340 let mut read = 0;
4341 let ret = unsafe {
4342 ffi::SSL_read_early_data(
4343 self.ssl.as_ptr(),
4344 buf.as_ptr() as *mut c_void,
4345 buf.len(),
4346 &mut read,
4347 )
4348 };
4349 match ret {
4350 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4351 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4352 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4353 _ => unreachable!(),
4354 }
4355 }
4356
4357 #[corresponds(SSL_write_early_data)]
4364 #[cfg(any(ossl111, libressl))]
4365 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4366 let mut written = 0;
4367 let ret = unsafe {
4368 ffi::SSL_write_early_data(
4369 self.ssl.as_ptr(),
4370 buf.as_ptr() as *const c_void,
4371 buf.len(),
4372 &mut written,
4373 )
4374 };
4375 if ret > 0 {
4376 Ok(written)
4377 } else {
4378 Err(self.make_error(ret))
4379 }
4380 }
4381
4382 #[corresponds(SSL_connect)]
4389 pub fn connect(&mut self) -> Result<(), Error> {
4390 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4391 if ret > 0 {
4392 Ok(())
4393 } else {
4394 Err(self.make_error(ret))
4395 }
4396 }
4397
4398 #[corresponds(SSL_accept)]
4405 pub fn accept(&mut self) -> Result<(), Error> {
4406 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4407 if ret > 0 {
4408 Ok(())
4409 } else {
4410 Err(self.make_error(ret))
4411 }
4412 }
4413
4414 #[corresponds(SSL_do_handshake)]
4418 pub fn do_handshake(&mut self) -> Result<(), Error> {
4419 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4420 if ret > 0 {
4421 Ok(())
4422 } else {
4423 Err(self.make_error(ret))
4424 }
4425 }
4426
4427 #[corresponds(SSL_stateless)]
4438 #[cfg(ossl111)]
4439 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4440 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4441 1 => Ok(true),
4442 0 => Ok(false),
4443 -1 => Err(ErrorStack::get()),
4444 _ => unreachable!(),
4445 }
4446 }
4447
4448 #[corresponds(SSL_read_ex)]
4455 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4456 loop {
4457 match self.ssl_read_uninit(buf) {
4458 Ok(n) => return Ok(n),
4459 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4460 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4461 return Ok(0);
4462 }
4463 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4464 Err(e) => {
4465 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4466 }
4467 }
4468 }
4469 }
4470
4471 #[corresponds(SSL_read_ex)]
4476 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4477 unsafe {
4479 self.ssl_read_uninit(util::from_raw_parts_mut(
4480 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4481 buf.len(),
4482 ))
4483 }
4484 }
4485
4486 #[corresponds(SSL_read_ex)]
4493 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4494 if buf.is_empty() {
4495 return Ok(0);
4496 }
4497
4498 cfg_if! {
4499 if #[cfg(any(ossl111, libressl))] {
4500 let mut readbytes = 0;
4501 let ret = unsafe {
4502 ffi::SSL_read_ex(
4503 self.ssl().as_ptr(),
4504 buf.as_mut_ptr().cast(),
4505 buf.len(),
4506 &mut readbytes,
4507 )
4508 };
4509
4510 if ret > 0 {
4511 Ok(readbytes)
4512 } else {
4513 Err(self.make_error(ret))
4514 }
4515 } else {
4516 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4517 let ret = unsafe {
4518 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4519 };
4520 if ret > 0 {
4521 Ok(ret as usize)
4522 } else {
4523 Err(self.make_error(ret))
4524 }
4525 }
4526 }
4527 }
4528
4529 #[corresponds(SSL_write_ex)]
4534 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4535 if buf.is_empty() {
4536 return Ok(0);
4537 }
4538
4539 cfg_if! {
4540 if #[cfg(any(ossl111, libressl))] {
4541 let mut written = 0;
4542 let ret = unsafe {
4543 ffi::SSL_write_ex(
4544 self.ssl().as_ptr(),
4545 buf.as_ptr().cast(),
4546 buf.len(),
4547 &mut written,
4548 )
4549 };
4550
4551 if ret > 0 {
4552 Ok(written)
4553 } else {
4554 Err(self.make_error(ret))
4555 }
4556 } else {
4557 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4558 let ret = unsafe {
4559 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4560 };
4561 if ret > 0 {
4562 Ok(ret as usize)
4563 } else {
4564 Err(self.make_error(ret))
4565 }
4566 }
4567 }
4568 }
4569
4570 #[corresponds(SSL_peek_ex)]
4572 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4573 unsafe {
4575 self.ssl_peek_uninit(util::from_raw_parts_mut(
4576 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4577 buf.len(),
4578 ))
4579 }
4580 }
4581
4582 #[corresponds(SSL_peek_ex)]
4589 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4590 cfg_if! {
4591 if #[cfg(any(ossl111, libressl))] {
4592 let mut readbytes = 0;
4593 let ret = unsafe {
4594 ffi::SSL_peek_ex(
4595 self.ssl().as_ptr(),
4596 buf.as_mut_ptr().cast(),
4597 buf.len(),
4598 &mut readbytes,
4599 )
4600 };
4601
4602 if ret > 0 {
4603 Ok(readbytes)
4604 } else {
4605 Err(self.make_error(ret))
4606 }
4607 } else {
4608 if buf.is_empty() {
4609 return Ok(0);
4610 }
4611
4612 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4613 let ret = unsafe {
4614 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4615 };
4616 if ret > 0 {
4617 Ok(ret as usize)
4618 } else {
4619 Err(self.make_error(ret))
4620 }
4621 }
4622 }
4623 }
4624
4625 #[corresponds(SSL_shutdown)]
4635 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4636 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4637 0 => Ok(ShutdownResult::Sent),
4638 1 => Ok(ShutdownResult::Received),
4639 n => Err(self.make_error(n)),
4640 }
4641 }
4642
4643 #[corresponds(SSL_get_shutdown)]
4645 pub fn get_shutdown(&mut self) -> ShutdownState {
4646 unsafe {
4647 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4648 ShutdownState::from_bits_retain(bits)
4649 }
4650 }
4651
4652 #[corresponds(SSL_set_shutdown)]
4657 pub fn set_shutdown(&mut self, state: ShutdownState) {
4658 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4659 }
4660}
4661
4662impl<S> SslStream<S> {
4663 fn make_error(&mut self, ret: c_int) -> Error {
4664 self.check_panic();
4665
4666 let code = self.ssl.get_error(ret);
4667
4668 let cause = match code {
4669 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4670 ErrorCode::SYSCALL => {
4671 let errs = ErrorStack::get();
4672 if errs.errors().is_empty() {
4673 self.get_bio_error().map(InnerError::Io)
4674 } else {
4675 Some(InnerError::Ssl(errs))
4676 }
4677 }
4678 ErrorCode::ZERO_RETURN => None,
4679 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4680 self.get_bio_error().map(InnerError::Io)
4681 }
4682 _ => None,
4683 };
4684
4685 Error { code, cause }
4686 }
4687
4688 fn check_panic(&mut self) {
4689 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4690 resume_unwind(err)
4691 }
4692 }
4693
4694 fn get_bio_error(&mut self) -> Option<io::Error> {
4695 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4696 }
4697
4698 pub fn get_ref(&self) -> &S {
4700 unsafe {
4701 let bio = self.ssl.get_raw_rbio();
4702 bio::get_ref(bio)
4703 }
4704 }
4705
4706 pub fn get_mut(&mut self) -> &mut S {
4713 unsafe {
4714 let bio = self.ssl.get_raw_rbio();
4715 bio::get_mut(bio)
4716 }
4717 }
4718
4719 pub fn ssl(&self) -> &SslRef {
4721 &self.ssl
4722 }
4723
4724 pub fn ssl_mut(&mut self) -> &mut SslRef {
4726 &mut self.ssl
4727 }
4728}
4729
4730impl<S: Read + Write> Read for SslStream<S> {
4731 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4732 unsafe {
4734 self.read_uninit(util::from_raw_parts_mut(
4735 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4736 buf.len(),
4737 ))
4738 }
4739 }
4740}
4741
4742impl<S: Read + Write> Write for SslStream<S> {
4743 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4744 loop {
4745 match self.ssl_write(buf) {
4746 Ok(n) => return Ok(n),
4747 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4748 Err(e) => {
4749 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4750 }
4751 }
4752 }
4753 }
4754
4755 fn flush(&mut self) -> io::Result<()> {
4756 self.get_mut().flush()
4757 }
4758}
4759
4760#[deprecated(
4762 since = "0.10.32",
4763 note = "use the methods directly on Ssl/SslStream instead"
4764)]
4765pub struct SslStreamBuilder<S> {
4766 inner: SslStream<S>,
4767}
4768
4769#[allow(deprecated)]
4770impl<S> SslStreamBuilder<S>
4771where
4772 S: Read + Write,
4773{
4774 pub fn new(ssl: Ssl, stream: S) -> Self {
4776 Self {
4777 inner: SslStream::new(ssl, stream).unwrap(),
4778 }
4779 }
4780
4781 #[corresponds(SSL_stateless)]
4792 #[cfg(ossl111)]
4793 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4794 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4795 1 => Ok(true),
4796 0 => Ok(false),
4797 -1 => Err(ErrorStack::get()),
4798 _ => unreachable!(),
4799 }
4800 }
4801
4802 #[corresponds(SSL_set_connect_state)]
4804 pub fn set_connect_state(&mut self) {
4805 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4806 }
4807
4808 #[corresponds(SSL_set_accept_state)]
4810 pub fn set_accept_state(&mut self) {
4811 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4812 }
4813
4814 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4816 match self.inner.connect() {
4817 Ok(()) => Ok(self.inner),
4818 Err(error) => match error.code() {
4819 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4820 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4821 stream: self.inner,
4822 error,
4823 }))
4824 }
4825 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4826 stream: self.inner,
4827 error,
4828 })),
4829 },
4830 }
4831 }
4832
4833 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4835 match self.inner.accept() {
4836 Ok(()) => Ok(self.inner),
4837 Err(error) => match error.code() {
4838 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4839 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4840 stream: self.inner,
4841 error,
4842 }))
4843 }
4844 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4845 stream: self.inner,
4846 error,
4847 })),
4848 },
4849 }
4850 }
4851
4852 #[corresponds(SSL_do_handshake)]
4856 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4857 match self.inner.do_handshake() {
4858 Ok(()) => Ok(self.inner),
4859 Err(error) => match error.code() {
4860 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4861 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4862 stream: self.inner,
4863 error,
4864 }))
4865 }
4866 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4867 stream: self.inner,
4868 error,
4869 })),
4870 },
4871 }
4872 }
4873
4874 #[corresponds(SSL_read_early_data)]
4884 #[cfg(any(ossl111, libressl))]
4885 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4886 self.inner.read_early_data(buf)
4887 }
4888
4889 #[corresponds(SSL_write_early_data)]
4896 #[cfg(any(ossl111, libressl))]
4897 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4898 self.inner.write_early_data(buf)
4899 }
4900}
4901
4902#[allow(deprecated)]
4903impl<S> SslStreamBuilder<S> {
4904 pub fn get_ref(&self) -> &S {
4906 unsafe {
4907 let bio = self.inner.ssl.get_raw_rbio();
4908 bio::get_ref(bio)
4909 }
4910 }
4911
4912 pub fn get_mut(&mut self) -> &mut S {
4919 unsafe {
4920 let bio = self.inner.ssl.get_raw_rbio();
4921 bio::get_mut(bio)
4922 }
4923 }
4924
4925 pub fn ssl(&self) -> &SslRef {
4927 &self.inner.ssl
4928 }
4929
4930 pub fn ssl_mut(&mut self) -> &mut SslRef {
4932 &mut self.inner.ssl
4933 }
4934}
4935
4936#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4938pub enum ShutdownResult {
4939 Sent,
4941
4942 Received,
4944}
4945
4946bitflags! {
4947 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4949 #[repr(transparent)]
4950 pub struct ShutdownState: c_int {
4951 const SENT = ffi::SSL_SENT_SHUTDOWN;
4953 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4955 }
4956}
4957
4958use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4959cfg_if! {
4960 if #[cfg(ossl300)] {
4961 use ffi::SSL_get1_peer_certificate;
4962 } else {
4963 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4964 }
4965}
4966use ffi::{
4967 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4968 TLS_server_method,
4969};
4970cfg_if! {
4971 if #[cfg(ossl110)] {
4972 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4973 ffi::CRYPTO_get_ex_new_index(
4974 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4975 0,
4976 ptr::null_mut(),
4977 None,
4978 None,
4979 f,
4980 )
4981 }
4982
4983 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4984 ffi::CRYPTO_get_ex_new_index(
4985 ffi::CRYPTO_EX_INDEX_SSL,
4986 0,
4987 ptr::null_mut(),
4988 None,
4989 None,
4990 f,
4991 )
4992 }
4993 } else {
4994 use std::sync::Once;
4995
4996 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4997 static ONCE: Once = Once::new();
4999 ONCE.call_once(|| {
5000 cfg_if! {
5001 if #[cfg(not(any(boringssl, awslc)))] {
5002 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5003 } else {
5004 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5005 }
5006 }
5007 });
5008
5009 cfg_if! {
5010 if #[cfg(not(any(boringssl, awslc)))] {
5011 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5012 } else {
5013 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5014 }
5015 }
5016 }
5017
5018 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5019 static ONCE: Once = Once::new();
5021 ONCE.call_once(|| {
5022 #[cfg(not(any(boringssl, awslc)))]
5023 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5024 #[cfg(any(boringssl, awslc))]
5025 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5026 });
5027
5028 #[cfg(not(any(boringssl, awslc)))]
5029 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5030 #[cfg(any(boringssl, awslc))]
5031 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5032 }
5033 }
5034}