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(ossl102)]
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(ossl102, 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(any(libressl, all(ossl102, not(ossl110))))]
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(ossl102)]
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(ossl102, 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(ossl102, 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(any(all(ossl102, not(ossl110)), 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 #[cfg(any(ossl102, libressl291, boringssl, awslc))]
3901 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3902 unsafe {
3903 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3904 mem::forget(chain);
3905 }
3906 Ok(())
3907 }
3908
3909 #[cfg(not(any(boringssl, awslc)))]
3911 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3912 unsafe {
3913 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3914 };
3915 Ok(())
3916 }
3917
3918 #[corresponds(SSL_use_Private_Key_file)]
3920 pub fn set_private_key_file<P: AsRef<Path>>(
3921 &mut self,
3922 path: P,
3923 ssl_file_type: SslFiletype,
3924 ) -> Result<(), ErrorStack> {
3925 let p = path.as_ref().as_os_str().to_str().unwrap();
3926 let key_file = CString::new(p).unwrap();
3927 unsafe {
3928 cvt(ffi::SSL_use_PrivateKey_file(
3929 self.as_ptr(),
3930 key_file.as_ptr(),
3931 ssl_file_type.as_raw(),
3932 ))?;
3933 };
3934 Ok(())
3935 }
3936
3937 #[corresponds(SSL_use_PrivateKey)]
3939 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3940 unsafe {
3941 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3942 };
3943 Ok(())
3944 }
3945
3946 #[cfg(tongsuo)]
3947 #[corresponds(SSL_use_enc_Private_Key_file)]
3948 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3949 &mut self,
3950 path: P,
3951 ssl_file_type: SslFiletype,
3952 ) -> Result<(), ErrorStack> {
3953 let p = path.as_ref().as_os_str().to_str().unwrap();
3954 let key_file = CString::new(p).unwrap();
3955 unsafe {
3956 cvt(ffi::SSL_use_enc_PrivateKey_file(
3957 self.as_ptr(),
3958 key_file.as_ptr(),
3959 ssl_file_type.as_raw(),
3960 ))?;
3961 };
3962 Ok(())
3963 }
3964
3965 #[cfg(tongsuo)]
3966 #[corresponds(SSL_use_enc_PrivateKey)]
3967 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3968 unsafe {
3969 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3970 };
3971 Ok(())
3972 }
3973
3974 #[cfg(tongsuo)]
3975 #[corresponds(SSL_use_sign_Private_Key_file)]
3976 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3977 &mut self,
3978 path: P,
3979 ssl_file_type: SslFiletype,
3980 ) -> Result<(), ErrorStack> {
3981 let p = path.as_ref().as_os_str().to_str().unwrap();
3982 let key_file = CString::new(p).unwrap();
3983 unsafe {
3984 cvt(ffi::SSL_use_sign_PrivateKey_file(
3985 self.as_ptr(),
3986 key_file.as_ptr(),
3987 ssl_file_type.as_raw(),
3988 ))?;
3989 };
3990 Ok(())
3991 }
3992
3993 #[cfg(tongsuo)]
3994 #[corresponds(SSL_use_sign_PrivateKey)]
3995 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3996 unsafe {
3997 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3998 };
3999 Ok(())
4000 }
4001
4002 #[corresponds(SSL_use_certificate)]
4004 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4005 unsafe {
4006 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4007 };
4008 Ok(())
4009 }
4010
4011 #[cfg(tongsuo)]
4012 #[corresponds(SSL_use_enc_certificate)]
4013 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4014 unsafe {
4015 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4016 };
4017 Ok(())
4018 }
4019
4020 #[cfg(tongsuo)]
4021 #[corresponds(SSL_use_sign_certificate)]
4022 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4023 unsafe {
4024 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4025 };
4026 Ok(())
4027 }
4028
4029 #[corresponds(SSL_use_certificate_chain_file)]
4035 #[cfg(any(ossl110, libressl))]
4036 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4037 &mut self,
4038 path: P,
4039 ) -> Result<(), ErrorStack> {
4040 let p = path.as_ref().as_os_str().to_str().unwrap();
4041 let cert_file = CString::new(p).unwrap();
4042 unsafe {
4043 cvt(ffi::SSL_use_certificate_chain_file(
4044 self.as_ptr(),
4045 cert_file.as_ptr(),
4046 ))?;
4047 };
4048 Ok(())
4049 }
4050
4051 #[corresponds(SSL_add_client_CA)]
4053 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4054 unsafe {
4055 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4056 };
4057 Ok(())
4058 }
4059
4060 #[corresponds(SSL_set_client_CA_list)]
4062 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4063 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4064 mem::forget(list);
4065 }
4066
4067 #[corresponds(SSL_set_min_proto_version)]
4074 #[cfg(any(ossl110, libressl, boringssl, awslc))]
4075 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4076 unsafe {
4077 cvt(ffi::SSL_set_min_proto_version(
4078 self.as_ptr(),
4079 version.map_or(0, |v| v.0 as _),
4080 ))
4081 .map(|_| ())
4082 }
4083 }
4084
4085 #[corresponds(SSL_set_max_proto_version)]
4092 #[cfg(any(ossl110, libressl, boringssl, awslc))]
4093 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4094 unsafe {
4095 cvt(ffi::SSL_set_max_proto_version(
4096 self.as_ptr(),
4097 version.map_or(0, |v| v.0 as _),
4098 ))
4099 .map(|_| ())
4100 }
4101 }
4102
4103 #[corresponds(SSL_set_ciphersuites)]
4112 #[cfg(any(ossl111, libressl))]
4113 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4114 let cipher_list = CString::new(cipher_list).unwrap();
4115 unsafe {
4116 cvt(ffi::SSL_set_ciphersuites(
4117 self.as_ptr(),
4118 cipher_list.as_ptr() as *const _,
4119 ))
4120 .map(|_| ())
4121 }
4122 }
4123
4124 #[corresponds(SSL_set_cipher_list)]
4132 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4133 let cipher_list = CString::new(cipher_list).unwrap();
4134 unsafe {
4135 cvt(ffi::SSL_set_cipher_list(
4136 self.as_ptr(),
4137 cipher_list.as_ptr() as *const _,
4138 ))
4139 .map(|_| ())
4140 }
4141 }
4142
4143 #[corresponds(SSL_set_cert_store)]
4145 #[cfg(any(ossl102, boringssl, awslc))]
4146 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4147 unsafe {
4148 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4149 mem::forget(cert_store);
4150 Ok(())
4151 }
4152 }
4153
4154 #[corresponds(SSL_set_num_tickets)]
4159 #[cfg(ossl111)]
4160 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4161 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4162 }
4163
4164 #[corresponds(SSL_get_num_tickets)]
4169 #[cfg(ossl111)]
4170 pub fn num_tickets(&self) -> usize {
4171 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4172 }
4173
4174 #[corresponds(SSL_set_security_level)]
4179 #[cfg(any(ossl110, libressl360))]
4180 pub fn set_security_level(&mut self, level: u32) {
4181 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4182 }
4183
4184 #[corresponds(SSL_get_security_level)]
4189 #[cfg(any(ossl110, libressl360))]
4190 pub fn security_level(&self) -> u32 {
4191 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4192 }
4193
4194 #[corresponds(SSL_get_peer_tmp_key)]
4199 #[cfg(ossl300)]
4200 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4201 unsafe {
4202 let mut key = ptr::null_mut();
4203 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4204 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4205 Err(e) => Err(e),
4206 }
4207 }
4208 }
4209
4210 #[corresponds(SSL_get_tmp_key)]
4215 #[cfg(ossl300)]
4216 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4217 unsafe {
4218 let mut key = ptr::null_mut();
4219 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4220 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4221 Err(e) => Err(e),
4222 }
4223 }
4224 }
4225}
4226
4227#[derive(Debug)]
4229pub struct MidHandshakeSslStream<S> {
4230 stream: SslStream<S>,
4231 error: Error,
4232}
4233
4234impl<S> MidHandshakeSslStream<S> {
4235 pub fn get_ref(&self) -> &S {
4237 self.stream.get_ref()
4238 }
4239
4240 pub fn get_mut(&mut self) -> &mut S {
4242 self.stream.get_mut()
4243 }
4244
4245 pub fn ssl(&self) -> &SslRef {
4247 self.stream.ssl()
4248 }
4249
4250 pub fn ssl_mut(&mut self) -> &mut SslRef {
4252 self.stream.ssl_mut()
4253 }
4254
4255 pub fn error(&self) -> &Error {
4257 &self.error
4258 }
4259
4260 pub fn into_error(self) -> Error {
4262 self.error
4263 }
4264}
4265
4266impl<S> MidHandshakeSslStream<S>
4267where
4268 S: Read + Write,
4269{
4270 #[corresponds(SSL_do_handshake)]
4273 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4274 match self.stream.do_handshake() {
4275 Ok(()) => Ok(self.stream),
4276 Err(error) => {
4277 self.error = error;
4278 match self.error.code() {
4279 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4280 Err(HandshakeError::WouldBlock(self))
4281 }
4282 _ => Err(HandshakeError::Failure(self)),
4283 }
4284 }
4285 }
4286 }
4287}
4288
4289pub struct SslStream<S> {
4291 ssl: ManuallyDrop<Ssl>,
4292 method: ManuallyDrop<BioMethod>,
4293 _p: PhantomData<S>,
4294}
4295
4296impl<S> Drop for SslStream<S> {
4297 fn drop(&mut self) {
4298 unsafe {
4300 ManuallyDrop::drop(&mut self.ssl);
4301 ManuallyDrop::drop(&mut self.method);
4302 }
4303 }
4304}
4305
4306impl<S> fmt::Debug for SslStream<S>
4307where
4308 S: fmt::Debug,
4309{
4310 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4311 fmt.debug_struct("SslStream")
4312 .field("stream", &self.get_ref())
4313 .field("ssl", &self.ssl())
4314 .finish()
4315 }
4316}
4317
4318impl<S: Read + Write> SslStream<S> {
4319 #[corresponds(SSL_set_bio)]
4327 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4328 let (bio, method) = bio::new(stream)?;
4329 unsafe {
4330 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4331 }
4332
4333 Ok(SslStream {
4334 ssl: ManuallyDrop::new(ssl),
4335 method: ManuallyDrop::new(method),
4336 _p: PhantomData,
4337 })
4338 }
4339
4340 #[corresponds(SSL_read_early_data)]
4349 #[cfg(any(ossl111, libressl))]
4350 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4351 let mut read = 0;
4352 let ret = unsafe {
4353 ffi::SSL_read_early_data(
4354 self.ssl.as_ptr(),
4355 buf.as_ptr() as *mut c_void,
4356 buf.len(),
4357 &mut read,
4358 )
4359 };
4360 match ret {
4361 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4362 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4363 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4364 _ => unreachable!(),
4365 }
4366 }
4367
4368 #[corresponds(SSL_write_early_data)]
4375 #[cfg(any(ossl111, libressl))]
4376 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4377 let mut written = 0;
4378 let ret = unsafe {
4379 ffi::SSL_write_early_data(
4380 self.ssl.as_ptr(),
4381 buf.as_ptr() as *const c_void,
4382 buf.len(),
4383 &mut written,
4384 )
4385 };
4386 if ret > 0 {
4387 Ok(written)
4388 } else {
4389 Err(self.make_error(ret))
4390 }
4391 }
4392
4393 #[corresponds(SSL_connect)]
4400 pub fn connect(&mut self) -> Result<(), Error> {
4401 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4402 if ret > 0 {
4403 Ok(())
4404 } else {
4405 Err(self.make_error(ret))
4406 }
4407 }
4408
4409 #[corresponds(SSL_accept)]
4416 pub fn accept(&mut self) -> Result<(), Error> {
4417 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4418 if ret > 0 {
4419 Ok(())
4420 } else {
4421 Err(self.make_error(ret))
4422 }
4423 }
4424
4425 #[corresponds(SSL_do_handshake)]
4429 pub fn do_handshake(&mut self) -> Result<(), Error> {
4430 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4431 if ret > 0 {
4432 Ok(())
4433 } else {
4434 Err(self.make_error(ret))
4435 }
4436 }
4437
4438 #[corresponds(SSL_stateless)]
4449 #[cfg(ossl111)]
4450 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4451 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4452 1 => Ok(true),
4453 0 => Ok(false),
4454 -1 => Err(ErrorStack::get()),
4455 _ => unreachable!(),
4456 }
4457 }
4458
4459 #[corresponds(SSL_read_ex)]
4466 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4467 loop {
4468 match self.ssl_read_uninit(buf) {
4469 Ok(n) => return Ok(n),
4470 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4471 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4472 return Ok(0);
4473 }
4474 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4475 Err(e) => {
4476 return Err(e
4477 .into_io_error()
4478 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4479 }
4480 }
4481 }
4482 }
4483
4484 #[corresponds(SSL_read_ex)]
4489 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4490 unsafe {
4492 self.ssl_read_uninit(util::from_raw_parts_mut(
4493 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4494 buf.len(),
4495 ))
4496 }
4497 }
4498
4499 #[corresponds(SSL_read_ex)]
4506 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4507 cfg_if! {
4508 if #[cfg(any(ossl111, libressl))] {
4509 let mut readbytes = 0;
4510 let ret = unsafe {
4511 ffi::SSL_read_ex(
4512 self.ssl().as_ptr(),
4513 buf.as_mut_ptr().cast(),
4514 buf.len(),
4515 &mut readbytes,
4516 )
4517 };
4518
4519 if ret > 0 {
4520 Ok(readbytes)
4521 } else {
4522 Err(self.make_error(ret))
4523 }
4524 } else {
4525 if buf.is_empty() {
4526 return Ok(0);
4527 }
4528
4529 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4530 let ret = unsafe {
4531 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4532 };
4533 if ret > 0 {
4534 Ok(ret as usize)
4535 } else {
4536 Err(self.make_error(ret))
4537 }
4538 }
4539 }
4540 }
4541
4542 #[corresponds(SSL_write_ex)]
4547 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4548 cfg_if! {
4549 if #[cfg(any(ossl111, libressl))] {
4550 let mut written = 0;
4551 let ret = unsafe {
4552 ffi::SSL_write_ex(
4553 self.ssl().as_ptr(),
4554 buf.as_ptr().cast(),
4555 buf.len(),
4556 &mut written,
4557 )
4558 };
4559
4560 if ret > 0 {
4561 Ok(written)
4562 } else {
4563 Err(self.make_error(ret))
4564 }
4565 } else {
4566 if buf.is_empty() {
4567 return Ok(0);
4568 }
4569
4570 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4571 let ret = unsafe {
4572 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4573 };
4574 if ret > 0 {
4575 Ok(ret as usize)
4576 } else {
4577 Err(self.make_error(ret))
4578 }
4579 }
4580 }
4581 }
4582
4583 #[corresponds(SSL_peek_ex)]
4585 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4586 unsafe {
4588 self.ssl_peek_uninit(util::from_raw_parts_mut(
4589 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4590 buf.len(),
4591 ))
4592 }
4593 }
4594
4595 #[corresponds(SSL_peek_ex)]
4602 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4603 cfg_if! {
4604 if #[cfg(any(ossl111, libressl))] {
4605 let mut readbytes = 0;
4606 let ret = unsafe {
4607 ffi::SSL_peek_ex(
4608 self.ssl().as_ptr(),
4609 buf.as_mut_ptr().cast(),
4610 buf.len(),
4611 &mut readbytes,
4612 )
4613 };
4614
4615 if ret > 0 {
4616 Ok(readbytes)
4617 } else {
4618 Err(self.make_error(ret))
4619 }
4620 } else {
4621 if buf.is_empty() {
4622 return Ok(0);
4623 }
4624
4625 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4626 let ret = unsafe {
4627 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4628 };
4629 if ret > 0 {
4630 Ok(ret as usize)
4631 } else {
4632 Err(self.make_error(ret))
4633 }
4634 }
4635 }
4636 }
4637
4638 #[corresponds(SSL_shutdown)]
4648 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4649 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4650 0 => Ok(ShutdownResult::Sent),
4651 1 => Ok(ShutdownResult::Received),
4652 n => Err(self.make_error(n)),
4653 }
4654 }
4655
4656 #[corresponds(SSL_get_shutdown)]
4658 pub fn get_shutdown(&mut self) -> ShutdownState {
4659 unsafe {
4660 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4661 ShutdownState::from_bits_retain(bits)
4662 }
4663 }
4664
4665 #[corresponds(SSL_set_shutdown)]
4670 pub fn set_shutdown(&mut self, state: ShutdownState) {
4671 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4672 }
4673}
4674
4675impl<S> SslStream<S> {
4676 fn make_error(&mut self, ret: c_int) -> Error {
4677 self.check_panic();
4678
4679 let code = self.ssl.get_error(ret);
4680
4681 let cause = match code {
4682 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4683 ErrorCode::SYSCALL => {
4684 let errs = ErrorStack::get();
4685 if errs.errors().is_empty() {
4686 self.get_bio_error().map(InnerError::Io)
4687 } else {
4688 Some(InnerError::Ssl(errs))
4689 }
4690 }
4691 ErrorCode::ZERO_RETURN => None,
4692 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4693 self.get_bio_error().map(InnerError::Io)
4694 }
4695 _ => None,
4696 };
4697
4698 Error { code, cause }
4699 }
4700
4701 fn check_panic(&mut self) {
4702 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4703 resume_unwind(err)
4704 }
4705 }
4706
4707 fn get_bio_error(&mut self) -> Option<io::Error> {
4708 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4709 }
4710
4711 pub fn get_ref(&self) -> &S {
4713 unsafe {
4714 let bio = self.ssl.get_raw_rbio();
4715 bio::get_ref(bio)
4716 }
4717 }
4718
4719 pub fn get_mut(&mut self) -> &mut S {
4726 unsafe {
4727 let bio = self.ssl.get_raw_rbio();
4728 bio::get_mut(bio)
4729 }
4730 }
4731
4732 pub fn ssl(&self) -> &SslRef {
4734 &self.ssl
4735 }
4736
4737 pub fn ssl_mut(&mut self) -> &mut SslRef {
4739 &mut self.ssl
4740 }
4741}
4742
4743impl<S: Read + Write> Read for SslStream<S> {
4744 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4745 unsafe {
4747 self.read_uninit(util::from_raw_parts_mut(
4748 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4749 buf.len(),
4750 ))
4751 }
4752 }
4753}
4754
4755impl<S: Read + Write> Write for SslStream<S> {
4756 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4757 loop {
4758 match self.ssl_write(buf) {
4759 Ok(n) => return Ok(n),
4760 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4761 Err(e) => {
4762 return Err(e
4763 .into_io_error()
4764 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4765 }
4766 }
4767 }
4768 }
4769
4770 fn flush(&mut self) -> io::Result<()> {
4771 self.get_mut().flush()
4772 }
4773}
4774
4775#[deprecated(
4777 since = "0.10.32",
4778 note = "use the methods directly on Ssl/SslStream instead"
4779)]
4780pub struct SslStreamBuilder<S> {
4781 inner: SslStream<S>,
4782}
4783
4784#[allow(deprecated)]
4785impl<S> SslStreamBuilder<S>
4786where
4787 S: Read + Write,
4788{
4789 pub fn new(ssl: Ssl, stream: S) -> Self {
4791 Self {
4792 inner: SslStream::new(ssl, stream).unwrap(),
4793 }
4794 }
4795
4796 #[corresponds(SSL_stateless)]
4807 #[cfg(ossl111)]
4808 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4809 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4810 1 => Ok(true),
4811 0 => Ok(false),
4812 -1 => Err(ErrorStack::get()),
4813 _ => unreachable!(),
4814 }
4815 }
4816
4817 #[corresponds(SSL_set_connect_state)]
4819 pub fn set_connect_state(&mut self) {
4820 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4821 }
4822
4823 #[corresponds(SSL_set_accept_state)]
4825 pub fn set_accept_state(&mut self) {
4826 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4827 }
4828
4829 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4831 match self.inner.connect() {
4832 Ok(()) => Ok(self.inner),
4833 Err(error) => match error.code() {
4834 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4835 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4836 stream: self.inner,
4837 error,
4838 }))
4839 }
4840 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4841 stream: self.inner,
4842 error,
4843 })),
4844 },
4845 }
4846 }
4847
4848 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4850 match self.inner.accept() {
4851 Ok(()) => Ok(self.inner),
4852 Err(error) => match error.code() {
4853 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4854 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4855 stream: self.inner,
4856 error,
4857 }))
4858 }
4859 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4860 stream: self.inner,
4861 error,
4862 })),
4863 },
4864 }
4865 }
4866
4867 #[corresponds(SSL_do_handshake)]
4871 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4872 match self.inner.do_handshake() {
4873 Ok(()) => Ok(self.inner),
4874 Err(error) => match error.code() {
4875 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4876 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4877 stream: self.inner,
4878 error,
4879 }))
4880 }
4881 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4882 stream: self.inner,
4883 error,
4884 })),
4885 },
4886 }
4887 }
4888
4889 #[corresponds(SSL_read_early_data)]
4899 #[cfg(any(ossl111, libressl))]
4900 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4901 self.inner.read_early_data(buf)
4902 }
4903
4904 #[corresponds(SSL_write_early_data)]
4911 #[cfg(any(ossl111, libressl))]
4912 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4913 self.inner.write_early_data(buf)
4914 }
4915}
4916
4917#[allow(deprecated)]
4918impl<S> SslStreamBuilder<S> {
4919 pub fn get_ref(&self) -> &S {
4921 unsafe {
4922 let bio = self.inner.ssl.get_raw_rbio();
4923 bio::get_ref(bio)
4924 }
4925 }
4926
4927 pub fn get_mut(&mut self) -> &mut S {
4934 unsafe {
4935 let bio = self.inner.ssl.get_raw_rbio();
4936 bio::get_mut(bio)
4937 }
4938 }
4939
4940 pub fn ssl(&self) -> &SslRef {
4942 &self.inner.ssl
4943 }
4944
4945 pub fn ssl_mut(&mut self) -> &mut SslRef {
4947 &mut self.inner.ssl
4948 }
4949}
4950
4951#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4953pub enum ShutdownResult {
4954 Sent,
4956
4957 Received,
4959}
4960
4961bitflags! {
4962 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4964 #[repr(transparent)]
4965 pub struct ShutdownState: c_int {
4966 const SENT = ffi::SSL_SENT_SHUTDOWN;
4968 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4970 }
4971}
4972
4973cfg_if! {
4974 if #[cfg(any(boringssl, ossl110, libressl, awslc))] {
4975 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4976 } else {
4977 #[allow(bad_style)]
4978 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4979 ffi::CRYPTO_add_lock(
4980 &mut (*ssl).references,
4981 1,
4982 ffi::CRYPTO_LOCK_SSL_CTX,
4983 "mod.rs\0".as_ptr() as *const _,
4984 line!() as c_int,
4985 );
4986 0
4987 }
4988
4989 #[allow(bad_style)]
4990 pub unsafe fn SSL_SESSION_get_master_key(
4991 session: *const ffi::SSL_SESSION,
4992 out: *mut c_uchar,
4993 mut outlen: usize,
4994 ) -> usize {
4995 if outlen == 0 {
4996 return (*session).master_key_length as usize;
4997 }
4998 if outlen > (*session).master_key_length as usize {
4999 outlen = (*session).master_key_length as usize;
5000 }
5001 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
5002 outlen
5003 }
5004
5005 #[allow(bad_style)]
5006 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
5007 (*s).server
5008 }
5009
5010 #[allow(bad_style)]
5011 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
5012 ffi::CRYPTO_add_lock(
5013 &mut (*ses).references,
5014 1,
5015 ffi::CRYPTO_LOCK_SSL_CTX,
5016 "mod.rs\0".as_ptr() as *const _,
5017 line!() as c_int,
5018 );
5019 0
5020 }
5021 }
5022}
5023
5024cfg_if! {
5025 if #[cfg(ossl300)] {
5026 use ffi::SSL_get1_peer_certificate;
5027 } else {
5028 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
5029 }
5030}
5031cfg_if! {
5032 if #[cfg(any(boringssl, ossl110, libressl, awslc))] {
5033 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
5034 } else {
5035 use ffi::{
5036 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
5037 SSLv23_server_method as TLS_server_method,
5038 };
5039 }
5040}
5041cfg_if! {
5042 if #[cfg(ossl110)] {
5043 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5044 ffi::CRYPTO_get_ex_new_index(
5045 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5046 0,
5047 ptr::null_mut(),
5048 None,
5049 None,
5050 f,
5051 )
5052 }
5053
5054 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5055 ffi::CRYPTO_get_ex_new_index(
5056 ffi::CRYPTO_EX_INDEX_SSL,
5057 0,
5058 ptr::null_mut(),
5059 None,
5060 None,
5061 f,
5062 )
5063 }
5064 } else {
5065 use std::sync::Once;
5066
5067 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5068 static ONCE: Once = Once::new();
5070 ONCE.call_once(|| {
5071 cfg_if! {
5072 if #[cfg(not(any(boringssl, awslc)))] {
5073 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5074 } else {
5075 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5076 }
5077 }
5078 });
5079
5080 cfg_if! {
5081 if #[cfg(not(any(boringssl, awslc)))] {
5082 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5083 } else {
5084 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5085 }
5086 }
5087 }
5088
5089 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5090 static ONCE: Once = Once::new();
5092 ONCE.call_once(|| {
5093 #[cfg(not(any(boringssl, awslc)))]
5094 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5095 #[cfg(any(boringssl, awslc))]
5096 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5097 });
5098
5099 #[cfg(not(any(boringssl, awslc)))]
5100 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5101 #[cfg(any(boringssl, awslc))]
5102 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5103 }
5104 }
5105}