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(not(any(boringssl, awslc)))]
164 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
165
166 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
170
171 #[cfg(not(any(boringssl, awslc)))]
177 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
178
179 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
181
182 #[cfg(not(any(boringssl, awslc)))]
184 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
185 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
186
187 #[cfg(not(any(boringssl, awslc)))]
189 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
190
191 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
194 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
195
196 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
200
201 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
205
206 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
210
211 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
213
214 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
216
217 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
219
220 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
222
223 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
225
226 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
228
229 #[cfg(any(boringssl, ossl111, libressl, awslc))]
233 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
234
235 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
237
238 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
240
241 #[cfg(ossl110)]
257 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
258
259 #[cfg(any(boringssl, ossl110h, awslc))]
263 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
264
265 #[cfg(ossl111)]
270 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
271
272 #[cfg(ossl111)]
284 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
285 }
286}
287
288bitflags! {
289 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
291 #[repr(transparent)]
292 pub struct SslMode: SslBitType {
293 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
299
300 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
303
304 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
314
315 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
321
322 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
326
327 #[cfg(not(libressl))]
335 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
336
337 #[cfg(ossl110)]
344 const ASYNC = ffi::SSL_MODE_ASYNC;
345 }
346}
347
348#[derive(Copy, Clone)]
350pub struct SslMethod(*const ffi::SSL_METHOD);
351
352impl SslMethod {
353 #[corresponds(TLS_method)]
355 pub fn tls() -> SslMethod {
356 unsafe { SslMethod(TLS_method()) }
357 }
358
359 #[corresponds(DTLS_method)]
361 pub fn dtls() -> SslMethod {
362 unsafe { SslMethod(DTLS_method()) }
363 }
364
365 #[corresponds(TLS_client_method)]
367 pub fn tls_client() -> SslMethod {
368 unsafe { SslMethod(TLS_client_method()) }
369 }
370
371 #[corresponds(TLS_server_method)]
373 pub fn tls_server() -> SslMethod {
374 unsafe { SslMethod(TLS_server_method()) }
375 }
376
377 #[cfg(tongsuo)]
378 #[corresponds(NTLS_client_method)]
379 pub fn ntls_client() -> SslMethod {
380 unsafe { SslMethod(ffi::NTLS_client_method()) }
381 }
382
383 #[cfg(tongsuo)]
384 #[corresponds(NTLS_server_method)]
385 pub fn ntls_server() -> SslMethod {
386 unsafe { SslMethod(ffi::NTLS_server_method()) }
387 }
388
389 #[corresponds(DTLS_client_method)]
391 #[cfg(any(boringssl, ossl110, libressl, awslc))]
392 pub fn dtls_client() -> SslMethod {
393 unsafe { SslMethod(DTLS_client_method()) }
394 }
395
396 #[corresponds(DTLS_server_method)]
398 #[cfg(any(boringssl, ossl110, libressl, awslc))]
399 pub fn dtls_server() -> SslMethod {
400 unsafe { SslMethod(DTLS_server_method()) }
401 }
402
403 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
409 SslMethod(ptr)
410 }
411
412 #[allow(clippy::trivially_copy_pass_by_ref)]
414 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
415 self.0
416 }
417}
418
419unsafe impl Sync for SslMethod {}
420unsafe impl Send for SslMethod {}
421
422bitflags! {
423 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
425 #[repr(transparent)]
426 pub struct SslVerifyMode: i32 {
427 const PEER = ffi::SSL_VERIFY_PEER;
431
432 const NONE = ffi::SSL_VERIFY_NONE;
438
439 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
443 }
444}
445
446#[cfg(any(boringssl, awslc))]
447type SslBitType = c_int;
448#[cfg(not(any(boringssl, awslc)))]
449type SslBitType = c_long;
450
451#[cfg(any(boringssl, awslc))]
452type SslTimeTy = u64;
453#[cfg(not(any(boringssl, awslc)))]
454type SslTimeTy = c_long;
455
456bitflags! {
457 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
459 #[repr(transparent)]
460 pub struct SslSessionCacheMode: SslBitType {
461 const OFF = ffi::SSL_SESS_CACHE_OFF;
463
464 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
471
472 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
476
477 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
479
480 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
482
483 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
485
486 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
488
489 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
491 }
492}
493
494#[cfg(ossl111)]
495bitflags! {
496 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
498 #[repr(transparent)]
499 pub struct ExtensionContext: c_uint {
500 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
502 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
504 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
506 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
508 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
510 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
512 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
514 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
515 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
517 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
518 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
519 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
520 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
521 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
522 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
523 }
524}
525
526#[derive(Copy, Clone)]
528pub struct TlsExtType(c_uint);
529
530impl TlsExtType {
531 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
535
536 pub const ALPN: TlsExtType =
540 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
541
542 pub fn from_raw(raw: c_uint) -> TlsExtType {
544 TlsExtType(raw)
545 }
546
547 #[allow(clippy::trivially_copy_pass_by_ref)]
549 pub fn as_raw(&self) -> c_uint {
550 self.0
551 }
552}
553
554#[derive(Copy, Clone)]
556pub struct SslFiletype(c_int);
557
558impl SslFiletype {
559 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
563
564 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
568
569 pub fn from_raw(raw: c_int) -> SslFiletype {
571 SslFiletype(raw)
572 }
573
574 #[allow(clippy::trivially_copy_pass_by_ref)]
576 pub fn as_raw(&self) -> c_int {
577 self.0
578 }
579}
580
581#[derive(Copy, Clone)]
583pub struct StatusType(c_int);
584
585impl StatusType {
586 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
588
589 pub fn from_raw(raw: c_int) -> StatusType {
591 StatusType(raw)
592 }
593
594 #[allow(clippy::trivially_copy_pass_by_ref)]
596 pub fn as_raw(&self) -> c_int {
597 self.0
598 }
599}
600
601#[derive(Copy, Clone)]
603pub struct NameType(c_int);
604
605impl NameType {
606 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
608
609 pub fn from_raw(raw: c_int) -> StatusType {
611 StatusType(raw)
612 }
613
614 #[allow(clippy::trivially_copy_pass_by_ref)]
616 pub fn as_raw(&self) -> c_int {
617 self.0
618 }
619}
620
621static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
622static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
623static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
624
625fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
626 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
627}
628
629unsafe extern "C" fn free_data_box<T>(
630 _parent: *mut c_void,
631 ptr: *mut c_void,
632 _ad: *mut ffi::CRYPTO_EX_DATA,
633 _idx: c_int,
634 _argl: c_long,
635 _argp: *mut c_void,
636) {
637 if !ptr.is_null() {
638 let _ = Box::<T>::from_raw(ptr as *mut T);
639 }
640}
641
642#[derive(Debug, Copy, Clone, PartialEq, Eq)]
644pub struct SniError(c_int);
645
646impl SniError {
647 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
649
650 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
652
653 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
654}
655
656#[derive(Debug, Copy, Clone, PartialEq, Eq)]
658pub struct SslAlert(c_int);
659
660impl SslAlert {
661 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
663 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
664 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
665 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
666}
667
668#[derive(Debug, Copy, Clone, PartialEq, Eq)]
672pub struct AlpnError(c_int);
673
674impl AlpnError {
675 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
677
678 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
680}
681
682#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
686#[derive(Debug, Copy, Clone, PartialEq, Eq)]
687pub struct ClientHelloError(c_int);
688
689#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
690impl ClientHelloError {
691 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
693
694 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
696}
697
698#[derive(Debug, Copy, Clone, PartialEq, Eq)]
700pub struct TicketKeyStatus(c_int);
701
702impl TicketKeyStatus {
703 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
705 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
707 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
709}
710
711#[derive(Debug, Copy, Clone, PartialEq, Eq)]
713#[cfg(any(boringssl, awslc))]
714pub struct SelectCertError(ffi::ssl_select_cert_result_t);
715
716#[cfg(any(boringssl, awslc))]
717impl SelectCertError {
718 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
720
721 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
723
724 #[cfg(boringssl)]
730 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
731}
732
733#[cfg(ossl111)]
735#[derive(Debug, Copy, Clone, PartialEq, Eq)]
736pub struct SslCtValidationMode(c_int);
737
738#[cfg(ossl111)]
739impl SslCtValidationMode {
740 pub const PERMISSIVE: SslCtValidationMode =
741 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
742 pub const STRICT: SslCtValidationMode =
743 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
744}
745
746#[derive(Debug, Copy, Clone, PartialEq, Eq)]
748pub struct CertCompressionAlgorithm(c_int);
749
750impl CertCompressionAlgorithm {
751 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
752 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
753 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
754}
755
756#[derive(Debug, Copy, Clone, PartialEq, Eq)]
758pub struct SslVersion(c_int);
759
760impl SslVersion {
761 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
763
764 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
766
767 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
769
770 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
772
773 #[cfg(any(ossl111, libressl, boringssl, awslc))]
777 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
778
779 #[cfg(tongsuo)]
780 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
781
782 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
786
787 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
791}
792
793cfg_if! {
794 if #[cfg(any(boringssl, awslc))] {
795 type SslCacheTy = i64;
796 type SslCacheSize = libc::c_ulong;
797 type MtuTy = u32;
798 type ModeTy = u32;
799 type SizeTy = usize;
800 } else {
801 type SslCacheTy = i64;
802 type SslCacheSize = c_long;
803 type MtuTy = c_long;
804 type ModeTy = c_long;
805 type SizeTy = u32;
806 }
807}
808
809#[corresponds(SSL_select_next_proto)]
820pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
821 unsafe {
822 let mut out = ptr::null_mut();
823 let mut outlen = 0;
824 let r = ffi::SSL_select_next_proto(
825 &mut out,
826 &mut outlen,
827 server.as_ptr(),
828 server.len() as c_uint,
829 client.as_ptr(),
830 client.len() as c_uint,
831 );
832 if r == ffi::OPENSSL_NPN_NEGOTIATED {
833 Some(util::from_raw_parts(out as *const u8, outlen as usize))
834 } else {
835 None
836 }
837 }
838}
839
840pub struct SslContextBuilder(SslContext);
842
843impl SslContextBuilder {
844 #[corresponds(SSL_CTX_new)]
846 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
847 unsafe {
848 init();
849 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
850
851 Ok(SslContextBuilder::from_ptr(ctx))
852 }
853 }
854
855 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
861 SslContextBuilder(SslContext::from_ptr(ctx))
862 }
863
864 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
866 self.0.as_ptr()
867 }
868
869 #[cfg(tongsuo)]
870 #[corresponds(SSL_CTX_enable_ntls)]
871 pub fn enable_ntls(&mut self) {
872 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
873 }
874
875 #[cfg(tongsuo)]
876 #[corresponds(SSL_CTX_disable_ntls)]
877 pub fn disable_ntls(&mut self) {
878 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
879 }
880
881 #[cfg(all(tongsuo, ossl300))]
882 #[corresponds(SSL_CTX_enable_force_ntls)]
883 pub fn enable_force_ntls(&mut self) {
884 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
885 }
886
887 #[cfg(all(tongsuo, ossl300))]
888 #[corresponds(SSL_CTX_disable_force_ntls)]
889 pub fn disable_force_ntls(&mut self) {
890 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
891 }
892
893 #[cfg(tongsuo)]
894 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
895 pub fn enable_sm_tls13_strict(&mut self) {
896 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
897 }
898
899 #[cfg(tongsuo)]
900 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
901 pub fn disable_sm_tls13_strict(&mut self) {
902 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
903 }
904
905 #[corresponds(SSL_CTX_set_verify)]
907 pub fn set_verify(&mut self, mode: SslVerifyMode) {
908 unsafe {
909 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
910 }
911 }
912
913 #[corresponds(SSL_CTX_set_verify)]
920 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
921 where
922 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
923 {
924 unsafe {
925 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
926 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
927 }
928 }
929
930 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
938 pub fn set_servername_callback<F>(&mut self, callback: F)
940 where
941 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
942 {
943 unsafe {
944 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
950 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
951 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
952 }
953 }
954
955 #[corresponds(SSL_CTX_set_verify_depth)]
959 pub fn set_verify_depth(&mut self, depth: u32) {
960 unsafe {
961 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
962 }
963 }
964
965 #[corresponds(SSL_CTX_set0_verify_cert_store)]
969 #[cfg(any(ossl110, boringssl, awslc))]
970 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
971 unsafe {
972 let ptr = cert_store.as_ptr();
973 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
974 mem::forget(cert_store);
975
976 Ok(())
977 }
978 }
979
980 #[corresponds(SSL_CTX_set_cert_store)]
982 pub fn set_cert_store(&mut self, cert_store: X509Store) {
983 unsafe {
984 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
985 mem::forget(cert_store);
986 }
987 }
988
989 #[corresponds(SSL_CTX_set_read_ahead)]
996 pub fn set_read_ahead(&mut self, read_ahead: bool) {
997 unsafe {
998 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
999 }
1000 }
1001
1002 #[corresponds(SSL_CTX_set_mode)]
1006 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1007 unsafe {
1008 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1009 SslMode::from_bits_retain(bits)
1010 }
1011 }
1012
1013 #[corresponds(SSL_CTX_clear_mode)]
1015 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1016 unsafe {
1017 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1018 SslMode::from_bits_retain(bits)
1019 }
1020 }
1021
1022 #[corresponds(SSL_CTX_get_mode)]
1024 pub fn mode(&self) -> SslMode {
1025 unsafe {
1026 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1027 SslMode::from_bits_retain(bits)
1028 }
1029 }
1030
1031 #[corresponds(SSL_CTX_set_dh_auto)]
1040 #[cfg(ossl300)]
1041 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1042 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
1043 }
1044
1045 #[corresponds(SSL_CTX_set_tmp_dh)]
1047 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1048 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1049 }
1050
1051 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1058 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1059 where
1060 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1061 {
1062 unsafe {
1063 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1064
1065 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1066 }
1067 }
1068
1069 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1071 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1072 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1073 }
1074
1075 #[corresponds(SSL_CTX_set_default_verify_paths)]
1080 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1081 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1082 }
1083
1084 #[corresponds(SSL_CTX_load_verify_locations)]
1088 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1089 self.load_verify_locations(Some(file.as_ref()), None)
1090 }
1091
1092 #[corresponds(SSL_CTX_load_verify_locations)]
1094 pub fn load_verify_locations(
1095 &mut self,
1096 ca_file: Option<&Path>,
1097 ca_path: Option<&Path>,
1098 ) -> Result<(), ErrorStack> {
1099 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1100 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1101 unsafe {
1102 cvt(ffi::SSL_CTX_load_verify_locations(
1103 self.as_ptr(),
1104 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1105 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1106 ))
1107 .map(|_| ())
1108 }
1109 }
1110
1111 #[corresponds(SSL_CTX_set_client_CA_list)]
1116 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1117 unsafe {
1118 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1119 mem::forget(list);
1120 }
1121 }
1122
1123 #[corresponds(SSL_CTX_add_client_CA)]
1126 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1127 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1128 }
1129
1130 #[corresponds(SSL_CTX_set_session_id_context)]
1139 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1140 unsafe {
1141 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1142 cvt(ffi::SSL_CTX_set_session_id_context(
1143 self.as_ptr(),
1144 sid_ctx.as_ptr(),
1145 sid_ctx.len() as SizeTy,
1146 ))
1147 .map(|_| ())
1148 }
1149 }
1150
1151 #[corresponds(SSL_CTX_use_certificate_file)]
1157 pub fn set_certificate_file<P: AsRef<Path>>(
1158 &mut self,
1159 file: P,
1160 file_type: SslFiletype,
1161 ) -> Result<(), ErrorStack> {
1162 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1163 unsafe {
1164 cvt(ffi::SSL_CTX_use_certificate_file(
1165 self.as_ptr(),
1166 file.as_ptr() as *const _,
1167 file_type.as_raw(),
1168 ))
1169 .map(|_| ())
1170 }
1171 }
1172
1173 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1179 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1180 &mut self,
1181 file: P,
1182 ) -> Result<(), ErrorStack> {
1183 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1184 unsafe {
1185 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1186 self.as_ptr(),
1187 file.as_ptr() as *const _,
1188 ))
1189 .map(|_| ())
1190 }
1191 }
1192
1193 #[corresponds(SSL_CTX_use_certificate)]
1197 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1198 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1199 }
1200
1201 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1206 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1207 unsafe {
1208 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1209 mem::forget(cert);
1210 Ok(())
1211 }
1212 }
1213
1214 #[cfg(tongsuo)]
1215 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1216 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1217 &mut self,
1218 file: P,
1219 file_type: SslFiletype,
1220 ) -> Result<(), ErrorStack> {
1221 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1222 unsafe {
1223 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1224 self.as_ptr(),
1225 file.as_ptr() as *const _,
1226 file_type.as_raw(),
1227 ))
1228 .map(|_| ())
1229 }
1230 }
1231
1232 #[cfg(tongsuo)]
1233 #[corresponds(SSL_CTX_use_enc_certificate)]
1234 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1235 unsafe {
1236 cvt(ffi::SSL_CTX_use_enc_certificate(
1237 self.as_ptr(),
1238 cert.as_ptr(),
1239 ))
1240 .map(|_| ())
1241 }
1242 }
1243
1244 #[cfg(tongsuo)]
1245 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1246 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1247 &mut self,
1248 file: P,
1249 file_type: SslFiletype,
1250 ) -> Result<(), ErrorStack> {
1251 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1252 unsafe {
1253 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1254 self.as_ptr(),
1255 file.as_ptr() as *const _,
1256 file_type.as_raw(),
1257 ))
1258 .map(|_| ())
1259 }
1260 }
1261
1262 #[cfg(tongsuo)]
1263 #[corresponds(SSL_CTX_use_sign_certificate)]
1264 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1265 unsafe {
1266 cvt(ffi::SSL_CTX_use_sign_certificate(
1267 self.as_ptr(),
1268 cert.as_ptr(),
1269 ))
1270 .map(|_| ())
1271 }
1272 }
1273
1274 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1276 pub fn set_private_key_file<P: AsRef<Path>>(
1277 &mut self,
1278 file: P,
1279 file_type: SslFiletype,
1280 ) -> Result<(), ErrorStack> {
1281 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1282 unsafe {
1283 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1284 self.as_ptr(),
1285 file.as_ptr() as *const _,
1286 file_type.as_raw(),
1287 ))
1288 .map(|_| ())
1289 }
1290 }
1291
1292 #[corresponds(SSL_CTX_use_PrivateKey)]
1294 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1295 where
1296 T: HasPrivate,
1297 {
1298 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1299 }
1300
1301 #[cfg(tongsuo)]
1302 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1303 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1304 &mut self,
1305 file: P,
1306 file_type: SslFiletype,
1307 ) -> Result<(), ErrorStack> {
1308 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1309 unsafe {
1310 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1311 self.as_ptr(),
1312 file.as_ptr() as *const _,
1313 file_type.as_raw(),
1314 ))
1315 .map(|_| ())
1316 }
1317 }
1318
1319 #[cfg(tongsuo)]
1320 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1321 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1322 where
1323 T: HasPrivate,
1324 {
1325 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1326 }
1327
1328 #[cfg(tongsuo)]
1329 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1330 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1331 &mut self,
1332 file: P,
1333 file_type: SslFiletype,
1334 ) -> Result<(), ErrorStack> {
1335 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1336 unsafe {
1337 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1338 self.as_ptr(),
1339 file.as_ptr() as *const _,
1340 file_type.as_raw(),
1341 ))
1342 .map(|_| ())
1343 }
1344 }
1345
1346 #[cfg(tongsuo)]
1347 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1348 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1349 where
1350 T: HasPrivate,
1351 {
1352 unsafe {
1353 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1354 self.as_ptr(),
1355 key.as_ptr(),
1356 ))
1357 .map(|_| ())
1358 }
1359 }
1360
1361 #[corresponds(SSL_CTX_set_cipher_list)]
1369 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1370 let cipher_list = CString::new(cipher_list).unwrap();
1371 unsafe {
1372 cvt(ffi::SSL_CTX_set_cipher_list(
1373 self.as_ptr(),
1374 cipher_list.as_ptr() as *const _,
1375 ))
1376 .map(|_| ())
1377 }
1378 }
1379
1380 #[corresponds(SSL_CTX_set_ciphersuites)]
1389 #[cfg(any(ossl111, libressl, awslc))]
1390 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1391 let cipher_list = CString::new(cipher_list).unwrap();
1392 unsafe {
1393 cvt(ffi::SSL_CTX_set_ciphersuites(
1394 self.as_ptr(),
1395 cipher_list.as_ptr() as *const _,
1396 ))
1397 .map(|_| ())
1398 }
1399 }
1400
1401 #[corresponds(SSL_CTX_set_ecdh_auto)]
1405 #[cfg(libressl)]
1406 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1407 unsafe {
1408 cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ())
1409 }
1410 }
1411
1412 #[corresponds(SSL_CTX_set_options)]
1419 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1420 let bits =
1421 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1422 SslOptions::from_bits_retain(bits)
1423 }
1424
1425 #[corresponds(SSL_CTX_get_options)]
1427 pub fn options(&self) -> SslOptions {
1428 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1429 SslOptions::from_bits_retain(bits)
1430 }
1431
1432 #[corresponds(SSL_CTX_clear_options)]
1434 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1435 let bits =
1436 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1437 SslOptions::from_bits_retain(bits)
1438 }
1439
1440 #[corresponds(SSL_CTX_set_min_proto_version)]
1447 #[cfg(any(ossl110, libressl, boringssl, awslc))]
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)]
1465 #[cfg(any(ossl110, libressl, boringssl, awslc))]
1466 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1467 unsafe {
1468 cvt(ffi::SSL_CTX_set_max_proto_version(
1469 self.as_ptr(),
1470 version.map_or(0, |v| v.0 as _),
1471 ))
1472 .map(|_| ())
1473 }
1474 }
1475
1476 #[corresponds(SSL_CTX_get_min_proto_version)]
1483 #[cfg(any(ossl110g, libressl))]
1484 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1485 unsafe {
1486 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1487 if r == 0 {
1488 None
1489 } else {
1490 Some(SslVersion(r))
1491 }
1492 }
1493 }
1494
1495 #[corresponds(SSL_CTX_get_max_proto_version)]
1502 #[cfg(any(ossl110g, libressl))]
1503 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1504 unsafe {
1505 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1506 if r == 0 {
1507 None
1508 } else {
1509 Some(SslVersion(r))
1510 }
1511 }
1512 }
1513
1514 #[corresponds(SSL_CTX_set_alpn_protos)]
1523 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1524 unsafe {
1525 assert!(protocols.len() <= c_uint::MAX as usize);
1526 let r = ffi::SSL_CTX_set_alpn_protos(
1527 self.as_ptr(),
1528 protocols.as_ptr(),
1529 protocols.len() as _,
1530 );
1531 if r == 0 {
1533 Ok(())
1534 } else {
1535 Err(ErrorStack::get())
1536 }
1537 }
1538 }
1539
1540 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1542 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1543 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1544 unsafe {
1545 let cstr = CString::new(protocols).unwrap();
1546
1547 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1548 if r == 0 {
1550 Ok(())
1551 } else {
1552 Err(ErrorStack::get())
1553 }
1554 }
1555 }
1556
1557 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1568 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1569 where
1570 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1571 {
1572 unsafe {
1573 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1574 ffi::SSL_CTX_set_alpn_select_cb(
1575 self.as_ptr(),
1576 Some(callbacks::raw_alpn_select::<F>),
1577 ptr::null_mut(),
1578 );
1579 }
1580 }
1581
1582 #[corresponds(SSL_CTX_check_private_key)]
1584 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1585 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1586 }
1587
1588 #[corresponds(SSL_CTX_get_cert_store)]
1590 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1591 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1592 }
1593
1594 #[corresponds(SSL_CTX_get_cert_store)]
1596 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1597 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1598 }
1599
1600 #[corresponds(SSL_CTX_get0_param)]
1604 pub fn verify_param(&self) -> &X509VerifyParamRef {
1605 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1606 }
1607
1608 #[corresponds(SSL_CTX_get0_param)]
1612 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1613 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1614 }
1615
1616 #[cfg(any(boringssl, tongsuo, awslc))]
1624 pub fn add_cert_decompression_alg<F>(
1625 &mut self,
1626 alg_id: CertCompressionAlgorithm,
1627 decompress: F,
1628 ) -> Result<(), ErrorStack>
1629 where
1630 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1631 {
1632 unsafe {
1633 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1634 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1635 self.as_ptr(),
1636 alg_id.0 as _,
1637 None,
1638 Some(raw_cert_decompression::<F>),
1639 ))
1640 .map(|_| ())
1641 }
1642 }
1643
1644 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1646 #[cfg(ossl320)]
1647 pub fn set_cert_comp_preference(
1648 &mut self,
1649 algs: &[CertCompressionAlgorithm],
1650 ) -> Result<(), ErrorStack> {
1651 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1652 unsafe {
1653 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1654 self.as_ptr(),
1655 algs.as_mut_ptr(),
1656 algs.len(),
1657 ))
1658 .map(|_| ())
1659 }
1660 }
1661
1662 #[cfg(any(boringssl, awslc))]
1670 pub fn enable_ocsp_stapling(&mut self) {
1671 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1672 }
1673
1674 #[cfg(any(boringssl, awslc))]
1682 pub fn enable_signed_cert_timestamps(&mut self) {
1683 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1684 }
1685
1686 #[cfg(any(boringssl, awslc))]
1694 pub fn set_grease_enabled(&mut self, enabled: bool) {
1695 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1696 }
1697
1698 #[cfg(any(boringssl, awslc))]
1706 pub fn set_permute_extensions(&mut self, enabled: bool) {
1707 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1708 }
1709
1710 #[corresponds(SSL_CTX_enable_ct)]
1712 #[cfg(ossl111)]
1713 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1714 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1715 }
1716
1717 #[corresponds(SSL_CTX_ct_is_enabled)]
1719 #[cfg(ossl111)]
1720 pub fn ct_is_enabled(&self) -> bool {
1721 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1722 }
1723
1724 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1726 #[cfg(not(any(boringssl, awslc)))]
1727 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1728 unsafe {
1729 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1730 .map(|_| ())
1731 }
1732 }
1733
1734 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1747 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1748 where
1749 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1750 {
1751 unsafe {
1752 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1753 cvt(
1754 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1755 as c_int,
1756 )
1757 .map(|_| ())
1758 }
1759 }
1760
1761 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1762 #[cfg(ossl300)]
1763 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1764 where
1765 F: Fn(
1766 &mut SslRef,
1767 &mut [u8],
1768 &mut [u8],
1769 &mut CipherCtxRef,
1770 &mut MacCtxRef,
1771 bool,
1772 ) -> Result<TicketKeyStatus, ErrorStack>
1773 + 'static
1774 + Sync
1775 + Send,
1776 {
1777 unsafe {
1778 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1779 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1780 self.as_ptr(),
1781 Some(raw_tlsext_ticket_key_evp::<F>),
1782 ) as c_int)
1783 .map(|_| ())
1784 }
1785 }
1786
1787 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1788 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1789 where
1790 F: Fn(
1791 &mut SslRef,
1792 &mut [u8],
1793 &mut [u8],
1794 &mut CipherCtxRef,
1795 &mut HMacCtxRef,
1796 bool,
1797 ) -> Result<TicketKeyStatus, ErrorStack>
1798 + 'static
1799 + Sync
1800 + Send,
1801 {
1802 unsafe {
1803 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1804 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1805 self.as_ptr(),
1806 Some(raw_tlsext_ticket_key::<F>),
1807 ) as c_int)
1808 .map(|_| ())
1809 }
1810 }
1811
1812 #[corresponds(SSL_CTX_set_psk_client_callback)]
1818 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1819 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1820 where
1821 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1822 + 'static
1823 + Sync
1824 + Send,
1825 {
1826 unsafe {
1827 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1828 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1829 }
1830 }
1831
1832 #[corresponds(SSL_CTX_set_psk_server_callback)]
1838 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1839 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1840 where
1841 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1842 + 'static
1843 + Sync
1844 + Send,
1845 {
1846 unsafe {
1847 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1848 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1849 }
1850 }
1851
1852 #[corresponds(SSL_CTX_sess_set_new_cb)]
1866 pub fn set_new_session_callback<F>(&mut self, callback: F)
1867 where
1868 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1869 {
1870 unsafe {
1871 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1872 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1873 }
1874 }
1875
1876 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1880 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1881 where
1882 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1883 {
1884 unsafe {
1885 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1886 ffi::SSL_CTX_sess_set_remove_cb(
1887 self.as_ptr(),
1888 Some(callbacks::raw_remove_session::<F>),
1889 );
1890 }
1891 }
1892
1893 #[corresponds(SSL_CTX_sess_set_get_cb)]
1904 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1905 where
1906 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1907 {
1908 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1909 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1910 }
1911
1912 #[corresponds(SSL_CTX_set_keylog_callback)]
1920 #[cfg(any(ossl111, boringssl, awslc))]
1921 pub fn set_keylog_callback<F>(&mut self, callback: F)
1922 where
1923 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1924 {
1925 unsafe {
1926 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1927 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1928 }
1929 }
1930
1931 #[corresponds(SSL_CTX_set_session_cache_mode)]
1935 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1936 unsafe {
1937 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1938 SslSessionCacheMode::from_bits_retain(bits)
1939 }
1940 }
1941
1942 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1948 #[cfg(ossl111)]
1949 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1950 where
1951 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1952 {
1953 unsafe {
1954 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1955 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1956 self.as_ptr(),
1957 Some(raw_stateless_cookie_generate::<F>),
1958 );
1959 }
1960 }
1961
1962 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1971 #[cfg(ossl111)]
1972 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1973 where
1974 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1975 {
1976 unsafe {
1977 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1978 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1979 self.as_ptr(),
1980 Some(raw_stateless_cookie_verify::<F>),
1981 )
1982 }
1983 }
1984
1985 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1990 #[cfg(not(any(boringssl, awslc)))]
1991 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1992 where
1993 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1994 {
1995 unsafe {
1996 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1997 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1998 }
1999 }
2000
2001 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2006 #[cfg(not(any(boringssl, awslc)))]
2007 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2008 where
2009 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2010 {
2011 unsafe {
2012 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2013 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2014 }
2015 }
2016
2017 #[corresponds(SSL_CTX_set_ex_data)]
2023 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2024 self.set_ex_data_inner(index, data);
2025 }
2026
2027 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2028 match self.ex_data_mut(index) {
2029 Some(v) => {
2030 *v = data;
2031 (v as *mut T).cast()
2032 }
2033 _ => unsafe {
2034 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2035 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2036 data
2037 },
2038 }
2039 }
2040
2041 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2042 unsafe {
2043 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2044 if data.is_null() {
2045 None
2046 } else {
2047 Some(&mut *data.cast())
2048 }
2049 }
2050 }
2051
2052 #[corresponds(SSL_CTX_add_custom_ext)]
2056 #[cfg(ossl111)]
2057 pub fn add_custom_ext<AddFn, ParseFn, T>(
2058 &mut self,
2059 ext_type: u16,
2060 context: ExtensionContext,
2061 add_cb: AddFn,
2062 parse_cb: ParseFn,
2063 ) -> Result<(), ErrorStack>
2064 where
2065 AddFn: Fn(
2066 &mut SslRef,
2067 ExtensionContext,
2068 Option<(usize, &X509Ref)>,
2069 ) -> Result<Option<T>, SslAlert>
2070 + 'static
2071 + Sync
2072 + Send,
2073 T: AsRef<[u8]> + 'static + Sync + Send,
2074 ParseFn: Fn(
2075 &mut SslRef,
2076 ExtensionContext,
2077 &[u8],
2078 Option<(usize, &X509Ref)>,
2079 ) -> Result<(), SslAlert>
2080 + 'static
2081 + Sync
2082 + Send,
2083 {
2084 let ret = unsafe {
2085 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2086 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2087
2088 ffi::SSL_CTX_add_custom_ext(
2089 self.as_ptr(),
2090 ext_type as c_uint,
2091 context.bits(),
2092 Some(raw_custom_ext_add::<AddFn, T>),
2093 Some(raw_custom_ext_free::<T>),
2094 ptr::null_mut(),
2095 Some(raw_custom_ext_parse::<ParseFn>),
2096 ptr::null_mut(),
2097 )
2098 };
2099 if ret == 1 {
2100 Ok(())
2101 } else {
2102 Err(ErrorStack::get())
2103 }
2104 }
2105
2106 #[corresponds(SSL_CTX_set_max_early_data)]
2112 #[cfg(any(ossl111, libressl))]
2113 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2114 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2115 Ok(())
2116 } else {
2117 Err(ErrorStack::get())
2118 }
2119 }
2120
2121 #[cfg(any(boringssl, awslc))]
2131 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2132 where
2133 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2134 {
2135 unsafe {
2136 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2137 ffi::SSL_CTX_set_select_certificate_cb(
2138 self.as_ptr(),
2139 Some(callbacks::raw_select_cert::<F>),
2140 );
2141 }
2142 }
2143
2144 #[corresponds(SSL_CTX_set_client_hello_cb)]
2148 #[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
2149 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2150 where
2151 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2152 {
2153 unsafe {
2154 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2155 ffi::SSL_CTX_set_client_hello_cb(
2156 self.as_ptr(),
2157 Some(callbacks::raw_client_hello::<F>),
2158 ptr,
2159 );
2160 }
2161 }
2162
2163 #[corresponds(SSL_CTX_set_info_callback)]
2166 pub fn set_info_callback<F>(&mut self, callback: F)
2167 where
2168 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2169 {
2170 unsafe {
2171 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2172 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2173 }
2174 }
2175
2176 #[corresponds(SSL_CTX_sess_set_cache_size)]
2180 #[allow(clippy::useless_conversion)]
2181 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2182 unsafe {
2183 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2184 }
2185 }
2186
2187 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2191 #[cfg(ossl110)]
2192 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2193 let sigalgs = CString::new(sigalgs).unwrap();
2194 unsafe {
2195 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2196 .map(|_| ())
2197 }
2198 }
2199
2200 #[corresponds(SSL_CTX_set1_groups_list)]
2204 #[cfg(any(ossl111, boringssl, libressl, awslc))]
2205 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2206 let groups = CString::new(groups).unwrap();
2207 unsafe {
2208 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2209 }
2210 }
2211
2212 #[corresponds(SSL_CTX_set_num_tickets)]
2217 #[cfg(any(ossl111, boringssl, awslc))]
2218 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2219 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2220 }
2221
2222 #[corresponds(SSL_CTX_set_security_level)]
2227 #[cfg(any(ossl110, libressl360))]
2228 pub fn set_security_level(&mut self, level: u32) {
2229 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2230 }
2231
2232 pub fn build(self) -> SslContext {
2234 self.0
2235 }
2236}
2237
2238foreign_type_and_impl_send_sync! {
2239 type CType = ffi::SSL_CTX;
2240 fn drop = ffi::SSL_CTX_free;
2241
2242 pub struct SslContext;
2247
2248 pub struct SslContextRef;
2252}
2253
2254impl Clone for SslContext {
2255 fn clone(&self) -> Self {
2256 (**self).to_owned()
2257 }
2258}
2259
2260impl ToOwned for SslContextRef {
2261 type Owned = SslContext;
2262
2263 fn to_owned(&self) -> Self::Owned {
2264 unsafe {
2265 SSL_CTX_up_ref(self.as_ptr());
2266 SslContext::from_ptr(self.as_ptr())
2267 }
2268 }
2269}
2270
2271impl fmt::Debug for SslContext {
2273 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2274 write!(fmt, "SslContext")
2275 }
2276}
2277
2278impl SslContext {
2279 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2281 SslContextBuilder::new(method)
2282 }
2283
2284 #[corresponds(SSL_CTX_get_ex_new_index)]
2289 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2290 where
2291 T: 'static + Sync + Send,
2292 {
2293 unsafe {
2294 ffi::init();
2295 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2296 Ok(Index::from_raw(idx))
2297 }
2298 }
2299
2300 fn cached_ex_index<T>() -> Index<SslContext, T>
2302 where
2303 T: 'static + Sync + Send,
2304 {
2305 unsafe {
2306 let idx = *INDEXES
2307 .lock()
2308 .unwrap_or_else(|e| e.into_inner())
2309 .entry(TypeId::of::<T>())
2310 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2311 Index::from_raw(idx)
2312 }
2313 }
2314}
2315
2316impl SslContextRef {
2317 #[corresponds(SSL_CTX_get0_certificate)]
2321 #[cfg(any(ossl110, libressl))]
2322 pub fn certificate(&self) -> Option<&X509Ref> {
2323 unsafe {
2324 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2325 X509Ref::from_const_ptr_opt(ptr)
2326 }
2327 }
2328
2329 #[corresponds(SSL_CTX_get0_privatekey)]
2333 #[cfg(any(ossl110, libressl))]
2334 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2335 unsafe {
2336 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2337 PKeyRef::from_const_ptr_opt(ptr)
2338 }
2339 }
2340
2341 #[corresponds(SSL_CTX_get_cert_store)]
2343 pub fn cert_store(&self) -> &X509StoreRef {
2344 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2345 }
2346
2347 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2349 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2350 unsafe {
2351 let mut chain = ptr::null_mut();
2352 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2353 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2354 }
2355 }
2356
2357 #[corresponds(SSL_CTX_get_ex_data)]
2359 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2360 unsafe {
2361 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2362 if data.is_null() {
2363 None
2364 } else {
2365 Some(&*(data as *const T))
2366 }
2367 }
2368 }
2369
2370 #[corresponds(SSL_CTX_get_max_early_data)]
2374 #[cfg(any(ossl111, libressl))]
2375 pub fn max_early_data(&self) -> u32 {
2376 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2377 }
2378
2379 #[corresponds(SSL_CTX_add_session)]
2388 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2389 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2390 }
2391
2392 #[corresponds(SSL_CTX_remove_session)]
2401 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2402 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2403 }
2404
2405 #[corresponds(SSL_CTX_sess_get_cache_size)]
2409 #[allow(clippy::unnecessary_cast)]
2410 pub fn session_cache_size(&self) -> i64 {
2411 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2412 }
2413
2414 #[corresponds(SSL_CTX_get_verify_mode)]
2418 pub fn verify_mode(&self) -> SslVerifyMode {
2419 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2420 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2421 }
2422
2423 #[corresponds(SSL_CTX_get_num_tickets)]
2428 #[cfg(ossl111)]
2429 pub fn num_tickets(&self) -> usize {
2430 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2431 }
2432
2433 #[corresponds(SSL_CTX_get_security_level)]
2438 #[cfg(any(ossl110, libressl360))]
2439 pub fn security_level(&self) -> u32 {
2440 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2441 }
2442}
2443
2444pub struct CipherBits {
2446 pub secret: i32,
2448
2449 pub algorithm: i32,
2451}
2452
2453pub struct SslCipher(*mut ffi::SSL_CIPHER);
2455
2456impl ForeignType for SslCipher {
2457 type CType = ffi::SSL_CIPHER;
2458 type Ref = SslCipherRef;
2459
2460 #[inline]
2461 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2462 SslCipher(ptr)
2463 }
2464
2465 #[inline]
2466 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2467 self.0
2468 }
2469}
2470
2471impl Stackable for SslCipher {
2472 type StackType = ffi::stack_st_SSL_CIPHER;
2473}
2474
2475impl Deref for SslCipher {
2476 type Target = SslCipherRef;
2477
2478 fn deref(&self) -> &SslCipherRef {
2479 unsafe { SslCipherRef::from_ptr(self.0) }
2480 }
2481}
2482
2483impl DerefMut for SslCipher {
2484 fn deref_mut(&mut self) -> &mut SslCipherRef {
2485 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2486 }
2487}
2488
2489pub struct SslCipherRef(Opaque);
2493
2494impl ForeignTypeRef for SslCipherRef {
2495 type CType = ffi::SSL_CIPHER;
2496}
2497
2498impl SslCipherRef {
2499 #[corresponds(SSL_CIPHER_get_name)]
2501 pub fn name(&self) -> &'static str {
2502 unsafe {
2503 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2504 CStr::from_ptr(ptr).to_str().unwrap()
2505 }
2506 }
2507
2508 #[corresponds(SSL_CIPHER_standard_name)]
2512 #[cfg(ossl111)]
2513 pub fn standard_name(&self) -> Option<&'static str> {
2514 unsafe {
2515 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2516 if ptr.is_null() {
2517 None
2518 } else {
2519 Some(CStr::from_ptr(ptr).to_str().unwrap())
2520 }
2521 }
2522 }
2523
2524 #[corresponds(SSL_CIPHER_get_version)]
2526 pub fn version(&self) -> &'static str {
2527 let version = unsafe {
2528 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2529 CStr::from_ptr(ptr as *const _)
2530 };
2531
2532 str::from_utf8(version.to_bytes()).unwrap()
2533 }
2534
2535 #[corresponds(SSL_CIPHER_get_bits)]
2537 #[allow(clippy::useless_conversion)]
2538 pub fn bits(&self) -> CipherBits {
2539 unsafe {
2540 let mut algo_bits = 0;
2541 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2542 CipherBits {
2543 secret: secret_bits.into(),
2544 algorithm: algo_bits.into(),
2545 }
2546 }
2547 }
2548
2549 #[corresponds(SSL_CIPHER_description)]
2551 pub fn description(&self) -> String {
2552 unsafe {
2553 let mut buf = [0; 128];
2555 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2556 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2557 }
2558 }
2559
2560 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2564 #[cfg(ossl111)]
2565 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2566 unsafe {
2567 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2568 if ptr.is_null() {
2569 None
2570 } else {
2571 Some(MessageDigest::from_ptr(ptr))
2572 }
2573 }
2574 }
2575
2576 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2580 #[cfg(any(ossl110, libressl))]
2581 pub fn cipher_nid(&self) -> Option<Nid> {
2582 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2583 if n == 0 {
2584 None
2585 } else {
2586 Some(Nid::from_raw(n))
2587 }
2588 }
2589
2590 #[corresponds(SSL_CIPHER_get_protocol_id)]
2594 #[cfg(ossl111)]
2595 pub fn protocol_id(&self) -> [u8; 2] {
2596 unsafe {
2597 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2598 id.to_be_bytes()
2599 }
2600 }
2601}
2602
2603impl fmt::Debug for SslCipherRef {
2604 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2605 write!(fmt, "{}", self.name())
2606 }
2607}
2608
2609#[derive(Debug)]
2611pub struct CipherLists {
2612 pub suites: Stack<SslCipher>,
2613 pub signalling_suites: Stack<SslCipher>,
2614}
2615
2616foreign_type_and_impl_send_sync! {
2617 type CType = ffi::SSL_SESSION;
2618 fn drop = ffi::SSL_SESSION_free;
2619
2620 pub struct SslSession;
2624
2625 pub struct SslSessionRef;
2629}
2630
2631impl Clone for SslSession {
2632 fn clone(&self) -> SslSession {
2633 SslSessionRef::to_owned(self)
2634 }
2635}
2636
2637impl SslSession {
2638 from_der! {
2639 #[corresponds(d2i_SSL_SESSION)]
2641 from_der,
2642 SslSession,
2643 ffi::d2i_SSL_SESSION
2644 }
2645}
2646
2647impl ToOwned for SslSessionRef {
2648 type Owned = SslSession;
2649
2650 fn to_owned(&self) -> SslSession {
2651 unsafe {
2652 SSL_SESSION_up_ref(self.as_ptr());
2653 SslSession(self.as_ptr())
2654 }
2655 }
2656}
2657
2658impl SslSessionRef {
2659 #[corresponds(SSL_SESSION_get_id)]
2661 pub fn id(&self) -> &[u8] {
2662 unsafe {
2663 let mut len = 0;
2664 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2665 #[allow(clippy::unnecessary_cast)]
2666 util::from_raw_parts(p as *const u8, len as usize)
2667 }
2668 }
2669
2670 #[corresponds(SSL_SESSION_get_master_key)]
2672 pub fn master_key_len(&self) -> usize {
2673 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2674 }
2675
2676 #[corresponds(SSL_SESSION_get_master_key)]
2680 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2681 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2682 }
2683
2684 #[corresponds(SSL_SESSION_get_max_early_data)]
2688 #[cfg(any(ossl111, libressl))]
2689 pub fn max_early_data(&self) -> u32 {
2690 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2691 }
2692
2693 #[corresponds(SSL_SESSION_get_time)]
2695 #[allow(clippy::useless_conversion)]
2696 pub fn time(&self) -> SslTimeTy {
2697 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2698 }
2699
2700 #[corresponds(SSL_SESSION_get_timeout)]
2704 #[allow(clippy::useless_conversion)]
2705 pub fn timeout(&self) -> i64 {
2706 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2707 }
2708
2709 #[corresponds(SSL_SESSION_get_protocol_version)]
2713 #[cfg(any(ossl110, libressl))]
2714 pub fn protocol_version(&self) -> SslVersion {
2715 unsafe {
2716 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2717 SslVersion(version)
2718 }
2719 }
2720
2721 #[corresponds(SSL_SESSION_get_protocol_version)]
2723 #[cfg(any(boringssl, awslc))]
2724 pub fn protocol_version(&self) -> SslVersion {
2725 unsafe {
2726 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2727 SslVersion(version as _)
2728 }
2729 }
2730
2731 to_der! {
2732 #[corresponds(i2d_SSL_SESSION)]
2734 to_der,
2735 ffi::i2d_SSL_SESSION
2736 }
2737}
2738
2739foreign_type_and_impl_send_sync! {
2740 type CType = ffi::SSL;
2741 fn drop = ffi::SSL_free;
2742
2743 pub struct Ssl;
2750
2751 pub struct SslRef;
2755}
2756
2757impl fmt::Debug for Ssl {
2758 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2759 fmt::Debug::fmt(&**self, fmt)
2760 }
2761}
2762
2763impl Ssl {
2764 #[corresponds(SSL_get_ex_new_index)]
2769 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2770 where
2771 T: 'static + Sync + Send,
2772 {
2773 unsafe {
2774 ffi::init();
2775 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2776 Ok(Index::from_raw(idx))
2777 }
2778 }
2779
2780 fn cached_ex_index<T>() -> Index<Ssl, T>
2782 where
2783 T: 'static + Sync + Send,
2784 {
2785 unsafe {
2786 let idx = *SSL_INDEXES
2787 .lock()
2788 .unwrap_or_else(|e| e.into_inner())
2789 .entry(TypeId::of::<T>())
2790 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2791 Index::from_raw(idx)
2792 }
2793 }
2794
2795 #[corresponds(SSL_new)]
2797 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2798 let session_ctx_index = try_get_session_ctx_index()?;
2799 unsafe {
2800 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2801 let mut ssl = Ssl::from_ptr(ptr);
2802 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2803
2804 Ok(ssl)
2805 }
2806 }
2807
2808 #[corresponds(SSL_connect)]
2814 #[allow(deprecated)]
2815 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2816 where
2817 S: Read + Write,
2818 {
2819 SslStreamBuilder::new(self, stream).connect()
2820 }
2821
2822 #[corresponds(SSL_accept)]
2829 #[allow(deprecated)]
2830 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2831 where
2832 S: Read + Write,
2833 {
2834 SslStreamBuilder::new(self, stream).accept()
2835 }
2836}
2837
2838impl fmt::Debug for SslRef {
2839 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2840 fmt.debug_struct("Ssl")
2841 .field("state", &self.state_string_long())
2842 .field("verify_result", &self.verify_result())
2843 .finish()
2844 }
2845}
2846
2847impl SslRef {
2848 #[cfg(not(feature = "tongsuo"))]
2849 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2850 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2851 }
2852
2853 #[cfg(feature = "tongsuo")]
2854 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2855 unsafe {
2856 let bio = ffi::SSL_get_rbio(self.as_ptr());
2857 bio::find_correct_bio(bio)
2858 }
2859 }
2860
2861 fn get_error(&self, ret: c_int) -> ErrorCode {
2862 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2863 }
2864
2865 #[corresponds(SSL_set_mode)]
2869 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2870 unsafe {
2871 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2872 SslMode::from_bits_retain(bits)
2873 }
2874 }
2875
2876 #[corresponds(SSL_clear_mode)]
2878 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2879 unsafe {
2880 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2881 SslMode::from_bits_retain(bits)
2882 }
2883 }
2884
2885 #[corresponds(SSL_get_mode)]
2887 pub fn mode(&self) -> SslMode {
2888 unsafe {
2889 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2890 SslMode::from_bits_retain(bits)
2891 }
2892 }
2893
2894 #[corresponds(SSL_set_connect_state)]
2896 pub fn set_connect_state(&mut self) {
2897 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2898 }
2899
2900 #[corresponds(SSL_set_accept_state)]
2902 pub fn set_accept_state(&mut self) {
2903 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2904 }
2905
2906 #[cfg(any(boringssl, awslc))]
2907 #[corresponds(SSL_ech_accepted)]
2908 pub fn ech_accepted(&self) -> bool {
2909 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2910 }
2911
2912 #[cfg(tongsuo)]
2913 #[corresponds(SSL_is_ntls)]
2914 pub fn is_ntls(&mut self) -> bool {
2915 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2916 }
2917
2918 #[cfg(tongsuo)]
2919 #[corresponds(SSL_enable_ntls)]
2920 pub fn enable_ntls(&mut self) {
2921 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2922 }
2923
2924 #[cfg(tongsuo)]
2925 #[corresponds(SSL_disable_ntls)]
2926 pub fn disable_ntls(&mut self) {
2927 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2928 }
2929
2930 #[cfg(all(tongsuo, ossl300))]
2931 #[corresponds(SSL_enable_force_ntls)]
2932 pub fn enable_force_ntls(&mut self) {
2933 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2934 }
2935
2936 #[cfg(all(tongsuo, ossl300))]
2937 #[corresponds(SSL_disable_force_ntls)]
2938 pub fn disable_force_ntls(&mut self) {
2939 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2940 }
2941
2942 #[cfg(tongsuo)]
2943 #[corresponds(SSL_enable_sm_tls13_strict)]
2944 pub fn enable_sm_tls13_strict(&mut self) {
2945 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2946 }
2947
2948 #[cfg(tongsuo)]
2949 #[corresponds(SSL_disable_sm_tls13_strict)]
2950 pub fn disable_sm_tls13_strict(&mut self) {
2951 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2952 }
2953
2954 #[corresponds(SSL_set_verify)]
2958 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2959 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2960 }
2961
2962 #[corresponds(SSL_set_verify_mode)]
2964 pub fn verify_mode(&self) -> SslVerifyMode {
2965 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2966 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2967 }
2968
2969 #[corresponds(SSL_set_verify)]
2973 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2974 where
2975 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2976 {
2977 unsafe {
2978 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2980 ffi::SSL_set_verify(
2981 self.as_ptr(),
2982 mode.bits() as c_int,
2983 Some(ssl_raw_verify::<F>),
2984 );
2985 }
2986 }
2987
2988 #[corresponds(SSL_set_info_callback)]
2991 pub fn set_info_callback<F>(&mut self, callback: F)
2992 where
2993 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2994 {
2995 unsafe {
2996 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2998 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
2999 }
3000 }
3001
3002 #[corresponds(SSL_set_dh_auto)]
3006 #[cfg(ossl300)]
3007 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3008 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3009 }
3010
3011 #[corresponds(SSL_set_tmp_dh)]
3015 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3016 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3017 }
3018
3019 #[corresponds(SSL_set_tmp_dh_callback)]
3023 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3024 where
3025 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3026 {
3027 unsafe {
3028 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3030 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3031 }
3032 }
3033
3034 #[corresponds(SSL_set_tmp_ecdh)]
3038 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3039 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3040 }
3041
3042 #[corresponds(SSL_set_ecdh_auto)]
3048 #[cfg(libressl)]
3049 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3050 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3051 }
3052
3053 #[corresponds(SSL_set_alpn_protos)]
3059 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3060 unsafe {
3061 assert!(protocols.len() <= c_uint::MAX as usize);
3062 let r =
3063 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3064 if r == 0 {
3066 Ok(())
3067 } else {
3068 Err(ErrorStack::get())
3069 }
3070 }
3071 }
3072
3073 #[corresponds(SSL_get_current_cipher)]
3075 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3076 unsafe {
3077 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3078
3079 SslCipherRef::from_const_ptr_opt(ptr)
3080 }
3081 }
3082
3083 #[corresponds(SSL_state_string)]
3085 pub fn state_string(&self) -> &'static str {
3086 let state = unsafe {
3087 let ptr = ffi::SSL_state_string(self.as_ptr());
3088 CStr::from_ptr(ptr as *const _)
3089 };
3090
3091 str::from_utf8(state.to_bytes()).unwrap()
3092 }
3093
3094 #[corresponds(SSL_state_string_long)]
3096 pub fn state_string_long(&self) -> &'static str {
3097 let state = unsafe {
3098 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3099 CStr::from_ptr(ptr as *const _)
3100 };
3101
3102 str::from_utf8(state.to_bytes()).unwrap()
3103 }
3104
3105 #[corresponds(SSL_set_tlsext_host_name)]
3109 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3110 let cstr = CString::new(hostname).unwrap();
3111 unsafe {
3112 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3113 .map(|_| ())
3114 }
3115 }
3116
3117 #[corresponds(SSL_get_peer_certificate)]
3119 pub fn peer_certificate(&self) -> Option<X509> {
3120 unsafe {
3121 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3122 X509::from_ptr_opt(ptr)
3123 }
3124 }
3125
3126 #[corresponds(SSL_get_peer_cert_chain)]
3131 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3132 unsafe {
3133 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3134 StackRef::from_const_ptr_opt(ptr)
3135 }
3136 }
3137
3138 #[corresponds(SSL_get0_verified_chain)]
3148 #[cfg(ossl110)]
3149 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3150 unsafe {
3151 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3152 StackRef::from_const_ptr_opt(ptr)
3153 }
3154 }
3155
3156 #[corresponds(SSL_get_certificate)]
3158 pub fn certificate(&self) -> Option<&X509Ref> {
3159 unsafe {
3160 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3161 X509Ref::from_const_ptr_opt(ptr)
3162 }
3163 }
3164
3165 #[corresponds(SSL_get_privatekey)]
3169 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3170 unsafe {
3171 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3172 PKeyRef::from_const_ptr_opt(ptr)
3173 }
3174 }
3175
3176 #[corresponds(SSL_version)]
3178 pub fn version2(&self) -> Option<SslVersion> {
3179 unsafe {
3180 let r = ffi::SSL_version(self.as_ptr());
3181 if r == 0 {
3182 None
3183 } else {
3184 Some(SslVersion(r))
3185 }
3186 }
3187 }
3188
3189 #[corresponds(SSL_get_version)]
3191 pub fn version_str(&self) -> &'static str {
3192 let version = unsafe {
3193 let ptr = ffi::SSL_get_version(self.as_ptr());
3194 CStr::from_ptr(ptr as *const _)
3195 };
3196
3197 str::from_utf8(version.to_bytes()).unwrap()
3198 }
3199
3200 #[corresponds(SSL_get0_alpn_selected)]
3207 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3208 unsafe {
3209 let mut data: *const c_uchar = ptr::null();
3210 let mut len: c_uint = 0;
3211 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3214
3215 if data.is_null() {
3216 None
3217 } else {
3218 Some(util::from_raw_parts(data, len as usize))
3219 }
3220 }
3221 }
3222
3223 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3225 #[corresponds(SSL_set_tlsext_use_srtp)]
3226 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3227 unsafe {
3228 let cstr = CString::new(protocols).unwrap();
3229
3230 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3231 if r == 0 {
3233 Ok(())
3234 } else {
3235 Err(ErrorStack::get())
3236 }
3237 }
3238 }
3239
3240 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3244 #[corresponds(SSL_get_srtp_profiles)]
3245 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3246 unsafe {
3247 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3248
3249 StackRef::from_const_ptr_opt(chain)
3250 }
3251 }
3252
3253 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3257 #[corresponds(SSL_get_selected_srtp_profile)]
3258 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3259 unsafe {
3260 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3261
3262 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3263 }
3264 }
3265
3266 #[corresponds(SSL_pending)]
3271 pub fn pending(&self) -> usize {
3272 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3273 }
3274
3275 #[corresponds(SSL_get_servername)]
3288 pub fn servername(&self, type_: NameType) -> Option<&str> {
3290 self.servername_raw(type_)
3291 .and_then(|b| str::from_utf8(b).ok())
3292 }
3293
3294 #[corresponds(SSL_get_servername)]
3302 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3303 unsafe {
3304 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3305 if name.is_null() {
3306 None
3307 } else {
3308 Some(CStr::from_ptr(name as *const _).to_bytes())
3309 }
3310 }
3311 }
3312
3313 #[corresponds(SSL_set_SSL_CTX)]
3317 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3318 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3319 }
3320
3321 #[corresponds(SSL_get_SSL_CTX)]
3323 pub fn ssl_context(&self) -> &SslContextRef {
3324 unsafe {
3325 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3326 SslContextRef::from_ptr(ssl_ctx)
3327 }
3328 }
3329
3330 #[corresponds(SSL_get0_param)]
3334 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3335 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3336 }
3337
3338 #[corresponds(SSL_get_verify_result)]
3340 pub fn verify_result(&self) -> X509VerifyResult {
3341 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3342 }
3343
3344 #[corresponds(SSL_get_session)]
3346 pub fn session(&self) -> Option<&SslSessionRef> {
3347 unsafe {
3348 let p = ffi::SSL_get_session(self.as_ptr());
3349 SslSessionRef::from_const_ptr_opt(p)
3350 }
3351 }
3352
3353 #[corresponds(SSL_get_client_random)]
3360 #[cfg(any(ossl110, libressl))]
3361 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3362 unsafe {
3363 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3364 }
3365 }
3366
3367 #[corresponds(SSL_get_server_random)]
3374 #[cfg(any(ossl110, libressl))]
3375 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3376 unsafe {
3377 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3378 }
3379 }
3380
3381 #[corresponds(SSL_export_keying_material)]
3383 pub fn export_keying_material(
3384 &self,
3385 out: &mut [u8],
3386 label: &str,
3387 context: Option<&[u8]>,
3388 ) -> Result<(), ErrorStack> {
3389 unsafe {
3390 let (context, contextlen, use_context) = match context {
3391 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3392 None => (ptr::null(), 0, 0),
3393 };
3394 cvt(ffi::SSL_export_keying_material(
3395 self.as_ptr(),
3396 out.as_mut_ptr() as *mut c_uchar,
3397 out.len(),
3398 label.as_ptr() as *const c_char,
3399 label.len(),
3400 context,
3401 contextlen,
3402 use_context,
3403 ))
3404 .map(|_| ())
3405 }
3406 }
3407
3408 #[corresponds(SSL_export_keying_material_early)]
3415 #[cfg(ossl111)]
3416 pub fn export_keying_material_early(
3417 &self,
3418 out: &mut [u8],
3419 label: &str,
3420 context: &[u8],
3421 ) -> Result<(), ErrorStack> {
3422 unsafe {
3423 cvt(ffi::SSL_export_keying_material_early(
3424 self.as_ptr(),
3425 out.as_mut_ptr() as *mut c_uchar,
3426 out.len(),
3427 label.as_ptr() as *const c_char,
3428 label.len(),
3429 context.as_ptr() as *const c_uchar,
3430 context.len(),
3431 ))
3432 .map(|_| ())
3433 }
3434 }
3435
3436 #[corresponds(SSL_set_session)]
3447 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3448 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3449 }
3450
3451 #[corresponds(SSL_session_reused)]
3453 pub fn session_reused(&self) -> bool {
3454 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3455 }
3456
3457 #[cfg(any(boringssl, awslc))]
3465 pub fn enable_ocsp_stapling(&mut self) {
3466 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3467 }
3468
3469 #[cfg(any(boringssl, awslc))]
3477 pub fn enable_signed_cert_timestamps(&mut self) {
3478 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3479 }
3480
3481 #[cfg(any(boringssl, awslc))]
3489 pub fn set_permute_extensions(&mut self, enabled: bool) {
3490 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3491 }
3492
3493 #[corresponds(SSL_enable_ct)]
3495 #[cfg(ossl111)]
3496 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3497 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3498 }
3499
3500 #[corresponds(SSL_ct_is_enabled)]
3502 #[cfg(ossl111)]
3503 pub fn ct_is_enabled(&self) -> bool {
3504 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3505 }
3506
3507 #[corresponds(SSL_set_tlsext_status_type)]
3509 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3510 unsafe {
3511 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3512 }
3513 }
3514
3515 #[corresponds(SSL_get_extms_support)]
3519 #[cfg(ossl110)]
3520 pub fn extms_support(&self) -> Option<bool> {
3521 unsafe {
3522 match ffi::SSL_get_extms_support(self.as_ptr()) {
3523 -1 => None,
3524 ret => Some(ret != 0),
3525 }
3526 }
3527 }
3528
3529 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3531 #[cfg(not(any(boringssl, awslc)))]
3532 pub fn ocsp_status(&self) -> Option<&[u8]> {
3533 unsafe {
3534 let mut p = ptr::null_mut();
3535 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3536
3537 if len < 0 {
3538 None
3539 } else {
3540 Some(util::from_raw_parts(p as *const u8, len as usize))
3541 }
3542 }
3543 }
3544
3545 #[corresponds(SSL_get0_ocsp_response)]
3547 #[cfg(any(boringssl, awslc))]
3548 pub fn ocsp_status(&self) -> Option<&[u8]> {
3549 unsafe {
3550 let mut p = ptr::null();
3551 let mut len: usize = 0;
3552 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3553
3554 if len == 0 {
3555 None
3556 } else {
3557 Some(util::from_raw_parts(p as *const u8, len))
3558 }
3559 }
3560 }
3561
3562 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3564 #[cfg(not(any(boringssl, awslc)))]
3565 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3566 unsafe {
3567 assert!(response.len() <= c_int::MAX as usize);
3568 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3569 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3570 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3571 self.as_ptr(),
3572 p as *mut c_uchar,
3573 response.len() as c_long,
3574 ) as c_int)
3575 .map(|_| ())
3576 .map_err(|e| {
3577 ffi::OPENSSL_free(p);
3578 e
3579 })
3580 }
3581 }
3582
3583 #[corresponds(SSL_set_ocsp_response)]
3585 #[cfg(any(boringssl, awslc))]
3586 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3587 unsafe {
3588 cvt(ffi::SSL_set_ocsp_response(
3589 self.as_ptr(),
3590 response.as_ptr(),
3591 response.len(),
3592 ))
3593 .map(|_| ())
3594 }
3595 }
3596
3597 #[corresponds(SSL_is_server)]
3599 pub fn is_server(&self) -> bool {
3600 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3601 }
3602
3603 #[corresponds(SSL_set_ex_data)]
3609 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3610 match self.ex_data_mut(index) {
3611 Some(v) => *v = data,
3612 None => unsafe {
3613 let data = Box::new(data);
3614 ffi::SSL_set_ex_data(
3615 self.as_ptr(),
3616 index.as_raw(),
3617 Box::into_raw(data) as *mut c_void,
3618 );
3619 },
3620 }
3621 }
3622
3623 #[corresponds(SSL_get_ex_data)]
3625 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3626 unsafe {
3627 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3628 if data.is_null() {
3629 None
3630 } else {
3631 Some(&*(data as *const T))
3632 }
3633 }
3634 }
3635
3636 #[corresponds(SSL_get_ex_data)]
3638 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3639 unsafe {
3640 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3641 if data.is_null() {
3642 None
3643 } else {
3644 Some(&mut *(data as *mut T))
3645 }
3646 }
3647 }
3648
3649 #[corresponds(SSL_set_max_early_data)]
3653 #[cfg(any(ossl111, libressl))]
3654 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3655 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3656 Ok(())
3657 } else {
3658 Err(ErrorStack::get())
3659 }
3660 }
3661
3662 #[corresponds(SSL_get_max_early_data)]
3666 #[cfg(any(ossl111, libressl))]
3667 pub fn max_early_data(&self) -> u32 {
3668 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3669 }
3670
3671 #[corresponds(SSL_get_finished)]
3676 pub fn finished(&self, buf: &mut [u8]) -> usize {
3677 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3678 }
3679
3680 #[corresponds(SSL_get_peer_finished)]
3686 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3687 unsafe {
3688 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3689 }
3690 }
3691
3692 #[corresponds(SSL_is_init_finished)]
3694 #[cfg(ossl110)]
3695 pub fn is_init_finished(&self) -> bool {
3696 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3697 }
3698
3699 #[corresponds(SSL_client_hello_isv2)]
3705 #[cfg(ossl111)]
3706 pub fn client_hello_isv2(&self) -> bool {
3707 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3708 }
3709
3710 #[corresponds(SSL_client_hello_get0_legacy_version)]
3716 #[cfg(ossl111)]
3717 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3718 unsafe {
3719 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3720 if version == 0 {
3721 None
3722 } else {
3723 Some(SslVersion(version as c_int))
3724 }
3725 }
3726 }
3727
3728 #[corresponds(SSL_client_hello_get0_random)]
3734 #[cfg(ossl111)]
3735 pub fn client_hello_random(&self) -> Option<&[u8]> {
3736 unsafe {
3737 let mut ptr = ptr::null();
3738 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3739 if len == 0 {
3740 None
3741 } else {
3742 Some(util::from_raw_parts(ptr, len))
3743 }
3744 }
3745 }
3746
3747 #[corresponds(SSL_client_hello_get0_session_id)]
3753 #[cfg(ossl111)]
3754 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3755 unsafe {
3756 let mut ptr = ptr::null();
3757 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3758 if len == 0 {
3759 None
3760 } else {
3761 Some(util::from_raw_parts(ptr, len))
3762 }
3763 }
3764 }
3765
3766 #[corresponds(SSL_client_hello_get0_ciphers)]
3772 #[cfg(ossl111)]
3773 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3774 unsafe {
3775 let mut ptr = ptr::null();
3776 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3777 if len == 0 {
3778 None
3779 } else {
3780 Some(util::from_raw_parts(ptr, len))
3781 }
3782 }
3783 }
3784
3785 #[cfg(ossl111)]
3791 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3792 unsafe {
3793 let mut ptr = ptr::null();
3794 let mut len = 0usize;
3795 let r = ffi::SSL_client_hello_get0_ext(
3796 self.as_ptr(),
3797 ext_type.as_raw() as _,
3798 &mut ptr,
3799 &mut len,
3800 );
3801 if r == 0 {
3802 None
3803 } else {
3804 Some(util::from_raw_parts(ptr, len))
3805 }
3806 }
3807 }
3808
3809 #[corresponds(SSL_bytes_to_cipher_list)]
3814 #[cfg(ossl111)]
3815 pub fn bytes_to_cipher_list(
3816 &self,
3817 bytes: &[u8],
3818 isv2format: bool,
3819 ) -> Result<CipherLists, ErrorStack> {
3820 unsafe {
3821 let ptr = bytes.as_ptr();
3822 let len = bytes.len();
3823 let mut sk = ptr::null_mut();
3824 let mut scsvs = ptr::null_mut();
3825 let res = ffi::SSL_bytes_to_cipher_list(
3826 self.as_ptr(),
3827 ptr,
3828 len,
3829 isv2format as c_int,
3830 &mut sk,
3831 &mut scsvs,
3832 );
3833 if res == 1 {
3834 Ok(CipherLists {
3835 suites: Stack::from_ptr(sk),
3836 signalling_suites: Stack::from_ptr(scsvs),
3837 })
3838 } else {
3839 Err(ErrorStack::get())
3840 }
3841 }
3842 }
3843
3844 #[corresponds(SSL_client_hello_get0_compression_methods)]
3850 #[cfg(ossl111)]
3851 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3852 unsafe {
3853 let mut ptr = ptr::null();
3854 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3855 if len == 0 {
3856 None
3857 } else {
3858 Some(util::from_raw_parts(ptr, len))
3859 }
3860 }
3861 }
3862
3863 #[corresponds(SSL_set_mtu)]
3865 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3866 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3867 }
3868
3869 #[corresponds(SSL_get_psk_identity_hint)]
3873 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3874 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3875 unsafe {
3876 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3877 if ptr.is_null() {
3878 None
3879 } else {
3880 Some(CStr::from_ptr(ptr).to_bytes())
3881 }
3882 }
3883 }
3884
3885 #[corresponds(SSL_get_psk_identity)]
3887 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3888 pub fn psk_identity(&self) -> Option<&[u8]> {
3889 unsafe {
3890 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3891 if ptr.is_null() {
3892 None
3893 } else {
3894 Some(CStr::from_ptr(ptr).to_bytes())
3895 }
3896 }
3897 }
3898
3899 #[corresponds(SSL_add0_chain_cert)]
3900 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3901 unsafe {
3902 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3903 mem::forget(chain);
3904 }
3905 Ok(())
3906 }
3907
3908 #[cfg(not(any(boringssl, awslc)))]
3910 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3911 unsafe {
3912 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3913 };
3914 Ok(())
3915 }
3916
3917 #[corresponds(SSL_use_Private_Key_file)]
3919 pub fn set_private_key_file<P: AsRef<Path>>(
3920 &mut self,
3921 path: P,
3922 ssl_file_type: SslFiletype,
3923 ) -> Result<(), ErrorStack> {
3924 let p = path.as_ref().as_os_str().to_str().unwrap();
3925 let key_file = CString::new(p).unwrap();
3926 unsafe {
3927 cvt(ffi::SSL_use_PrivateKey_file(
3928 self.as_ptr(),
3929 key_file.as_ptr(),
3930 ssl_file_type.as_raw(),
3931 ))?;
3932 };
3933 Ok(())
3934 }
3935
3936 #[corresponds(SSL_use_PrivateKey)]
3938 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3939 unsafe {
3940 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3941 };
3942 Ok(())
3943 }
3944
3945 #[cfg(tongsuo)]
3946 #[corresponds(SSL_use_enc_Private_Key_file)]
3947 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3948 &mut self,
3949 path: P,
3950 ssl_file_type: SslFiletype,
3951 ) -> Result<(), ErrorStack> {
3952 let p = path.as_ref().as_os_str().to_str().unwrap();
3953 let key_file = CString::new(p).unwrap();
3954 unsafe {
3955 cvt(ffi::SSL_use_enc_PrivateKey_file(
3956 self.as_ptr(),
3957 key_file.as_ptr(),
3958 ssl_file_type.as_raw(),
3959 ))?;
3960 };
3961 Ok(())
3962 }
3963
3964 #[cfg(tongsuo)]
3965 #[corresponds(SSL_use_enc_PrivateKey)]
3966 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3967 unsafe {
3968 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3969 };
3970 Ok(())
3971 }
3972
3973 #[cfg(tongsuo)]
3974 #[corresponds(SSL_use_sign_Private_Key_file)]
3975 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3976 &mut self,
3977 path: P,
3978 ssl_file_type: SslFiletype,
3979 ) -> Result<(), ErrorStack> {
3980 let p = path.as_ref().as_os_str().to_str().unwrap();
3981 let key_file = CString::new(p).unwrap();
3982 unsafe {
3983 cvt(ffi::SSL_use_sign_PrivateKey_file(
3984 self.as_ptr(),
3985 key_file.as_ptr(),
3986 ssl_file_type.as_raw(),
3987 ))?;
3988 };
3989 Ok(())
3990 }
3991
3992 #[cfg(tongsuo)]
3993 #[corresponds(SSL_use_sign_PrivateKey)]
3994 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3995 unsafe {
3996 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3997 };
3998 Ok(())
3999 }
4000
4001 #[corresponds(SSL_use_certificate)]
4003 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4004 unsafe {
4005 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4006 };
4007 Ok(())
4008 }
4009
4010 #[cfg(tongsuo)]
4011 #[corresponds(SSL_use_enc_certificate)]
4012 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4013 unsafe {
4014 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4015 };
4016 Ok(())
4017 }
4018
4019 #[cfg(tongsuo)]
4020 #[corresponds(SSL_use_sign_certificate)]
4021 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4022 unsafe {
4023 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4024 };
4025 Ok(())
4026 }
4027
4028 #[corresponds(SSL_use_certificate_chain_file)]
4034 #[cfg(any(ossl110, libressl))]
4035 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4036 &mut self,
4037 path: P,
4038 ) -> Result<(), ErrorStack> {
4039 let p = path.as_ref().as_os_str().to_str().unwrap();
4040 let cert_file = CString::new(p).unwrap();
4041 unsafe {
4042 cvt(ffi::SSL_use_certificate_chain_file(
4043 self.as_ptr(),
4044 cert_file.as_ptr(),
4045 ))?;
4046 };
4047 Ok(())
4048 }
4049
4050 #[corresponds(SSL_add_client_CA)]
4052 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4053 unsafe {
4054 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4055 };
4056 Ok(())
4057 }
4058
4059 #[corresponds(SSL_set_client_CA_list)]
4061 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4062 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4063 mem::forget(list);
4064 }
4065
4066 #[corresponds(SSL_set_min_proto_version)]
4073 #[cfg(any(ossl110, libressl, boringssl, awslc))]
4074 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4075 unsafe {
4076 cvt(ffi::SSL_set_min_proto_version(
4077 self.as_ptr(),
4078 version.map_or(0, |v| v.0 as _),
4079 ))
4080 .map(|_| ())
4081 }
4082 }
4083
4084 #[corresponds(SSL_set_max_proto_version)]
4091 #[cfg(any(ossl110, libressl, boringssl, awslc))]
4092 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4093 unsafe {
4094 cvt(ffi::SSL_set_max_proto_version(
4095 self.as_ptr(),
4096 version.map_or(0, |v| v.0 as _),
4097 ))
4098 .map(|_| ())
4099 }
4100 }
4101
4102 #[corresponds(SSL_set_ciphersuites)]
4111 #[cfg(any(ossl111, libressl))]
4112 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4113 let cipher_list = CString::new(cipher_list).unwrap();
4114 unsafe {
4115 cvt(ffi::SSL_set_ciphersuites(
4116 self.as_ptr(),
4117 cipher_list.as_ptr() as *const _,
4118 ))
4119 .map(|_| ())
4120 }
4121 }
4122
4123 #[corresponds(SSL_set_cipher_list)]
4131 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4132 let cipher_list = CString::new(cipher_list).unwrap();
4133 unsafe {
4134 cvt(ffi::SSL_set_cipher_list(
4135 self.as_ptr(),
4136 cipher_list.as_ptr() as *const _,
4137 ))
4138 .map(|_| ())
4139 }
4140 }
4141
4142 #[corresponds(SSL_set_cert_store)]
4144 #[cfg(any(ossl110, boringssl, awslc))]
4145 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4146 unsafe {
4147 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4148 mem::forget(cert_store);
4149 Ok(())
4150 }
4151 }
4152
4153 #[corresponds(SSL_set_num_tickets)]
4158 #[cfg(ossl111)]
4159 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4160 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4161 }
4162
4163 #[corresponds(SSL_get_num_tickets)]
4168 #[cfg(ossl111)]
4169 pub fn num_tickets(&self) -> usize {
4170 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4171 }
4172
4173 #[corresponds(SSL_set_security_level)]
4178 #[cfg(any(ossl110, libressl360))]
4179 pub fn set_security_level(&mut self, level: u32) {
4180 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4181 }
4182
4183 #[corresponds(SSL_get_security_level)]
4188 #[cfg(any(ossl110, libressl360))]
4189 pub fn security_level(&self) -> u32 {
4190 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4191 }
4192
4193 #[corresponds(SSL_get_peer_tmp_key)]
4198 #[cfg(ossl300)]
4199 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4200 unsafe {
4201 let mut key = ptr::null_mut();
4202 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4203 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4204 Err(e) => Err(e),
4205 }
4206 }
4207 }
4208
4209 #[corresponds(SSL_get_tmp_key)]
4214 #[cfg(ossl300)]
4215 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4216 unsafe {
4217 let mut key = ptr::null_mut();
4218 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4219 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4220 Err(e) => Err(e),
4221 }
4222 }
4223 }
4224}
4225
4226#[derive(Debug)]
4228pub struct MidHandshakeSslStream<S> {
4229 stream: SslStream<S>,
4230 error: Error,
4231}
4232
4233impl<S> MidHandshakeSslStream<S> {
4234 pub fn get_ref(&self) -> &S {
4236 self.stream.get_ref()
4237 }
4238
4239 pub fn get_mut(&mut self) -> &mut S {
4241 self.stream.get_mut()
4242 }
4243
4244 pub fn ssl(&self) -> &SslRef {
4246 self.stream.ssl()
4247 }
4248
4249 pub fn ssl_mut(&mut self) -> &mut SslRef {
4251 self.stream.ssl_mut()
4252 }
4253
4254 pub fn error(&self) -> &Error {
4256 &self.error
4257 }
4258
4259 pub fn into_error(self) -> Error {
4261 self.error
4262 }
4263}
4264
4265impl<S> MidHandshakeSslStream<S>
4266where
4267 S: Read + Write,
4268{
4269 #[corresponds(SSL_do_handshake)]
4272 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4273 match self.stream.do_handshake() {
4274 Ok(()) => Ok(self.stream),
4275 Err(error) => {
4276 self.error = error;
4277 match self.error.code() {
4278 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4279 Err(HandshakeError::WouldBlock(self))
4280 }
4281 _ => Err(HandshakeError::Failure(self)),
4282 }
4283 }
4284 }
4285 }
4286}
4287
4288pub struct SslStream<S> {
4290 ssl: ManuallyDrop<Ssl>,
4291 method: ManuallyDrop<BioMethod>,
4292 _p: PhantomData<S>,
4293}
4294
4295impl<S> Drop for SslStream<S> {
4296 fn drop(&mut self) {
4297 unsafe {
4299 ManuallyDrop::drop(&mut self.ssl);
4300 ManuallyDrop::drop(&mut self.method);
4301 }
4302 }
4303}
4304
4305impl<S> fmt::Debug for SslStream<S>
4306where
4307 S: fmt::Debug,
4308{
4309 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4310 fmt.debug_struct("SslStream")
4311 .field("stream", &self.get_ref())
4312 .field("ssl", &self.ssl())
4313 .finish()
4314 }
4315}
4316
4317impl<S: Read + Write> SslStream<S> {
4318 #[corresponds(SSL_set_bio)]
4326 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4327 let (bio, method) = bio::new(stream)?;
4328 unsafe {
4329 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4330 }
4331
4332 Ok(SslStream {
4333 ssl: ManuallyDrop::new(ssl),
4334 method: ManuallyDrop::new(method),
4335 _p: PhantomData,
4336 })
4337 }
4338
4339 #[corresponds(SSL_read_early_data)]
4348 #[cfg(any(ossl111, libressl))]
4349 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4350 let mut read = 0;
4351 let ret = unsafe {
4352 ffi::SSL_read_early_data(
4353 self.ssl.as_ptr(),
4354 buf.as_ptr() as *mut c_void,
4355 buf.len(),
4356 &mut read,
4357 )
4358 };
4359 match ret {
4360 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4361 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4362 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4363 _ => unreachable!(),
4364 }
4365 }
4366
4367 #[corresponds(SSL_write_early_data)]
4374 #[cfg(any(ossl111, libressl))]
4375 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4376 let mut written = 0;
4377 let ret = unsafe {
4378 ffi::SSL_write_early_data(
4379 self.ssl.as_ptr(),
4380 buf.as_ptr() as *const c_void,
4381 buf.len(),
4382 &mut written,
4383 )
4384 };
4385 if ret > 0 {
4386 Ok(written)
4387 } else {
4388 Err(self.make_error(ret))
4389 }
4390 }
4391
4392 #[corresponds(SSL_connect)]
4399 pub fn connect(&mut self) -> Result<(), Error> {
4400 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4401 if ret > 0 {
4402 Ok(())
4403 } else {
4404 Err(self.make_error(ret))
4405 }
4406 }
4407
4408 #[corresponds(SSL_accept)]
4415 pub fn accept(&mut self) -> Result<(), Error> {
4416 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4417 if ret > 0 {
4418 Ok(())
4419 } else {
4420 Err(self.make_error(ret))
4421 }
4422 }
4423
4424 #[corresponds(SSL_do_handshake)]
4428 pub fn do_handshake(&mut self) -> Result<(), Error> {
4429 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4430 if ret > 0 {
4431 Ok(())
4432 } else {
4433 Err(self.make_error(ret))
4434 }
4435 }
4436
4437 #[corresponds(SSL_stateless)]
4448 #[cfg(ossl111)]
4449 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4450 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4451 1 => Ok(true),
4452 0 => Ok(false),
4453 -1 => Err(ErrorStack::get()),
4454 _ => unreachable!(),
4455 }
4456 }
4457
4458 #[corresponds(SSL_read_ex)]
4465 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4466 loop {
4467 match self.ssl_read_uninit(buf) {
4468 Ok(n) => return Ok(n),
4469 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4470 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4471 return Ok(0);
4472 }
4473 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4474 Err(e) => {
4475 return Err(e
4476 .into_io_error()
4477 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4478 }
4479 }
4480 }
4481 }
4482
4483 #[corresponds(SSL_read_ex)]
4488 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4489 unsafe {
4491 self.ssl_read_uninit(util::from_raw_parts_mut(
4492 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4493 buf.len(),
4494 ))
4495 }
4496 }
4497
4498 #[corresponds(SSL_read_ex)]
4505 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4506 cfg_if! {
4507 if #[cfg(any(ossl111, libressl))] {
4508 let mut readbytes = 0;
4509 let ret = unsafe {
4510 ffi::SSL_read_ex(
4511 self.ssl().as_ptr(),
4512 buf.as_mut_ptr().cast(),
4513 buf.len(),
4514 &mut readbytes,
4515 )
4516 };
4517
4518 if ret > 0 {
4519 Ok(readbytes)
4520 } else {
4521 Err(self.make_error(ret))
4522 }
4523 } else {
4524 if buf.is_empty() {
4525 return Ok(0);
4526 }
4527
4528 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4529 let ret = unsafe {
4530 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4531 };
4532 if ret > 0 {
4533 Ok(ret as usize)
4534 } else {
4535 Err(self.make_error(ret))
4536 }
4537 }
4538 }
4539 }
4540
4541 #[corresponds(SSL_write_ex)]
4546 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4547 cfg_if! {
4548 if #[cfg(any(ossl111, libressl))] {
4549 let mut written = 0;
4550 let ret = unsafe {
4551 ffi::SSL_write_ex(
4552 self.ssl().as_ptr(),
4553 buf.as_ptr().cast(),
4554 buf.len(),
4555 &mut written,
4556 )
4557 };
4558
4559 if ret > 0 {
4560 Ok(written)
4561 } else {
4562 Err(self.make_error(ret))
4563 }
4564 } else {
4565 if buf.is_empty() {
4566 return Ok(0);
4567 }
4568
4569 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4570 let ret = unsafe {
4571 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4572 };
4573 if ret > 0 {
4574 Ok(ret as usize)
4575 } else {
4576 Err(self.make_error(ret))
4577 }
4578 }
4579 }
4580 }
4581
4582 #[corresponds(SSL_peek_ex)]
4584 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4585 unsafe {
4587 self.ssl_peek_uninit(util::from_raw_parts_mut(
4588 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4589 buf.len(),
4590 ))
4591 }
4592 }
4593
4594 #[corresponds(SSL_peek_ex)]
4601 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4602 cfg_if! {
4603 if #[cfg(any(ossl111, libressl))] {
4604 let mut readbytes = 0;
4605 let ret = unsafe {
4606 ffi::SSL_peek_ex(
4607 self.ssl().as_ptr(),
4608 buf.as_mut_ptr().cast(),
4609 buf.len(),
4610 &mut readbytes,
4611 )
4612 };
4613
4614 if ret > 0 {
4615 Ok(readbytes)
4616 } else {
4617 Err(self.make_error(ret))
4618 }
4619 } else {
4620 if buf.is_empty() {
4621 return Ok(0);
4622 }
4623
4624 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4625 let ret = unsafe {
4626 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4627 };
4628 if ret > 0 {
4629 Ok(ret as usize)
4630 } else {
4631 Err(self.make_error(ret))
4632 }
4633 }
4634 }
4635 }
4636
4637 #[corresponds(SSL_shutdown)]
4647 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4648 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4649 0 => Ok(ShutdownResult::Sent),
4650 1 => Ok(ShutdownResult::Received),
4651 n => Err(self.make_error(n)),
4652 }
4653 }
4654
4655 #[corresponds(SSL_get_shutdown)]
4657 pub fn get_shutdown(&mut self) -> ShutdownState {
4658 unsafe {
4659 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4660 ShutdownState::from_bits_retain(bits)
4661 }
4662 }
4663
4664 #[corresponds(SSL_set_shutdown)]
4669 pub fn set_shutdown(&mut self, state: ShutdownState) {
4670 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4671 }
4672}
4673
4674impl<S> SslStream<S> {
4675 fn make_error(&mut self, ret: c_int) -> Error {
4676 self.check_panic();
4677
4678 let code = self.ssl.get_error(ret);
4679
4680 let cause = match code {
4681 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4682 ErrorCode::SYSCALL => {
4683 let errs = ErrorStack::get();
4684 if errs.errors().is_empty() {
4685 self.get_bio_error().map(InnerError::Io)
4686 } else {
4687 Some(InnerError::Ssl(errs))
4688 }
4689 }
4690 ErrorCode::ZERO_RETURN => None,
4691 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4692 self.get_bio_error().map(InnerError::Io)
4693 }
4694 _ => None,
4695 };
4696
4697 Error { code, cause }
4698 }
4699
4700 fn check_panic(&mut self) {
4701 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4702 resume_unwind(err)
4703 }
4704 }
4705
4706 fn get_bio_error(&mut self) -> Option<io::Error> {
4707 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4708 }
4709
4710 pub fn get_ref(&self) -> &S {
4712 unsafe {
4713 let bio = self.ssl.get_raw_rbio();
4714 bio::get_ref(bio)
4715 }
4716 }
4717
4718 pub fn get_mut(&mut self) -> &mut S {
4725 unsafe {
4726 let bio = self.ssl.get_raw_rbio();
4727 bio::get_mut(bio)
4728 }
4729 }
4730
4731 pub fn ssl(&self) -> &SslRef {
4733 &self.ssl
4734 }
4735
4736 pub fn ssl_mut(&mut self) -> &mut SslRef {
4738 &mut self.ssl
4739 }
4740}
4741
4742impl<S: Read + Write> Read for SslStream<S> {
4743 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4744 unsafe {
4746 self.read_uninit(util::from_raw_parts_mut(
4747 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4748 buf.len(),
4749 ))
4750 }
4751 }
4752}
4753
4754impl<S: Read + Write> Write for SslStream<S> {
4755 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4756 loop {
4757 match self.ssl_write(buf) {
4758 Ok(n) => return Ok(n),
4759 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4760 Err(e) => {
4761 return Err(e
4762 .into_io_error()
4763 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4764 }
4765 }
4766 }
4767 }
4768
4769 fn flush(&mut self) -> io::Result<()> {
4770 self.get_mut().flush()
4771 }
4772}
4773
4774#[deprecated(
4776 since = "0.10.32",
4777 note = "use the methods directly on Ssl/SslStream instead"
4778)]
4779pub struct SslStreamBuilder<S> {
4780 inner: SslStream<S>,
4781}
4782
4783#[allow(deprecated)]
4784impl<S> SslStreamBuilder<S>
4785where
4786 S: Read + Write,
4787{
4788 pub fn new(ssl: Ssl, stream: S) -> Self {
4790 Self {
4791 inner: SslStream::new(ssl, stream).unwrap(),
4792 }
4793 }
4794
4795 #[corresponds(SSL_stateless)]
4806 #[cfg(ossl111)]
4807 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4808 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4809 1 => Ok(true),
4810 0 => Ok(false),
4811 -1 => Err(ErrorStack::get()),
4812 _ => unreachable!(),
4813 }
4814 }
4815
4816 #[corresponds(SSL_set_connect_state)]
4818 pub fn set_connect_state(&mut self) {
4819 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4820 }
4821
4822 #[corresponds(SSL_set_accept_state)]
4824 pub fn set_accept_state(&mut self) {
4825 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4826 }
4827
4828 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4830 match self.inner.connect() {
4831 Ok(()) => Ok(self.inner),
4832 Err(error) => match error.code() {
4833 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4834 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4835 stream: self.inner,
4836 error,
4837 }))
4838 }
4839 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4840 stream: self.inner,
4841 error,
4842 })),
4843 },
4844 }
4845 }
4846
4847 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4849 match self.inner.accept() {
4850 Ok(()) => Ok(self.inner),
4851 Err(error) => match error.code() {
4852 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4853 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4854 stream: self.inner,
4855 error,
4856 }))
4857 }
4858 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4859 stream: self.inner,
4860 error,
4861 })),
4862 },
4863 }
4864 }
4865
4866 #[corresponds(SSL_do_handshake)]
4870 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4871 match self.inner.do_handshake() {
4872 Ok(()) => Ok(self.inner),
4873 Err(error) => match error.code() {
4874 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4875 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4876 stream: self.inner,
4877 error,
4878 }))
4879 }
4880 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4881 stream: self.inner,
4882 error,
4883 })),
4884 },
4885 }
4886 }
4887
4888 #[corresponds(SSL_read_early_data)]
4898 #[cfg(any(ossl111, libressl))]
4899 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4900 self.inner.read_early_data(buf)
4901 }
4902
4903 #[corresponds(SSL_write_early_data)]
4910 #[cfg(any(ossl111, libressl))]
4911 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4912 self.inner.write_early_data(buf)
4913 }
4914}
4915
4916#[allow(deprecated)]
4917impl<S> SslStreamBuilder<S> {
4918 pub fn get_ref(&self) -> &S {
4920 unsafe {
4921 let bio = self.inner.ssl.get_raw_rbio();
4922 bio::get_ref(bio)
4923 }
4924 }
4925
4926 pub fn get_mut(&mut self) -> &mut S {
4933 unsafe {
4934 let bio = self.inner.ssl.get_raw_rbio();
4935 bio::get_mut(bio)
4936 }
4937 }
4938
4939 pub fn ssl(&self) -> &SslRef {
4941 &self.inner.ssl
4942 }
4943
4944 pub fn ssl_mut(&mut self) -> &mut SslRef {
4946 &mut self.inner.ssl
4947 }
4948}
4949
4950#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4952pub enum ShutdownResult {
4953 Sent,
4955
4956 Received,
4958}
4959
4960bitflags! {
4961 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4963 #[repr(transparent)]
4964 pub struct ShutdownState: c_int {
4965 const SENT = ffi::SSL_SENT_SHUTDOWN;
4967 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4969 }
4970}
4971
4972cfg_if! {
4973 if #[cfg(any(boringssl, ossl110, libressl, awslc))] {
4974 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4975 } else {
4976 #[allow(bad_style)]
4977 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4978 ffi::CRYPTO_add_lock(
4979 &mut (*ssl).references,
4980 1,
4981 ffi::CRYPTO_LOCK_SSL_CTX,
4982 "mod.rs\0".as_ptr() as *const _,
4983 line!() as c_int,
4984 );
4985 0
4986 }
4987
4988 #[allow(bad_style)]
4989 pub unsafe fn SSL_SESSION_get_master_key(
4990 session: *const ffi::SSL_SESSION,
4991 out: *mut c_uchar,
4992 mut outlen: usize,
4993 ) -> usize {
4994 if outlen == 0 {
4995 return (*session).master_key_length as usize;
4996 }
4997 if outlen > (*session).master_key_length as usize {
4998 outlen = (*session).master_key_length as usize;
4999 }
5000 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
5001 outlen
5002 }
5003
5004 #[allow(bad_style)]
5005 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
5006 (*s).server
5007 }
5008
5009 #[allow(bad_style)]
5010 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
5011 ffi::CRYPTO_add_lock(
5012 &mut (*ses).references,
5013 1,
5014 ffi::CRYPTO_LOCK_SSL_CTX,
5015 "mod.rs\0".as_ptr() as *const _,
5016 line!() as c_int,
5017 );
5018 0
5019 }
5020 }
5021}
5022
5023cfg_if! {
5024 if #[cfg(ossl300)] {
5025 use ffi::SSL_get1_peer_certificate;
5026 } else {
5027 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
5028 }
5029}
5030cfg_if! {
5031 if #[cfg(any(boringssl, ossl110, libressl, awslc))] {
5032 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
5033 } else {
5034 use ffi::{
5035 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
5036 SSLv23_server_method as TLS_server_method,
5037 };
5038 }
5039}
5040cfg_if! {
5041 if #[cfg(ossl110)] {
5042 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5043 ffi::CRYPTO_get_ex_new_index(
5044 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5045 0,
5046 ptr::null_mut(),
5047 None,
5048 None,
5049 f,
5050 )
5051 }
5052
5053 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5054 ffi::CRYPTO_get_ex_new_index(
5055 ffi::CRYPTO_EX_INDEX_SSL,
5056 0,
5057 ptr::null_mut(),
5058 None,
5059 None,
5060 f,
5061 )
5062 }
5063 } else {
5064 use std::sync::Once;
5065
5066 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5067 static ONCE: Once = Once::new();
5069 ONCE.call_once(|| {
5070 cfg_if! {
5071 if #[cfg(not(any(boringssl, awslc)))] {
5072 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5073 } else {
5074 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5075 }
5076 }
5077 });
5078
5079 cfg_if! {
5080 if #[cfg(not(any(boringssl, awslc)))] {
5081 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5082 } else {
5083 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5084 }
5085 }
5086 }
5087
5088 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5089 static ONCE: Once = Once::new();
5091 ONCE.call_once(|| {
5092 #[cfg(not(any(boringssl, awslc)))]
5093 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5094 #[cfg(any(boringssl, awslc))]
5095 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5096 });
5097
5098 #[cfg(not(any(boringssl, awslc)))]
5099 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5100 #[cfg(any(boringssl, awslc))]
5101 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5102 }
5103 }
5104}