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, libressl270))]
73use crate::nid::Nid;
74use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
75#[cfg(ossl300)]
76use crate::pkey::{PKey, Public};
77use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
78use crate::ssl::bio::BioMethod;
79use crate::ssl::callbacks::*;
80use crate::ssl::error::InnerError;
81use crate::stack::{Stack, StackRef, Stackable};
82use crate::util;
83use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
84use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
85#[cfg(any(ossl102, boringssl, libressl261, awslc))]
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, libressl340, awslc))]
233 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
234
235 #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
239 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
240
241 #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
245 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
246
247 #[cfg(any(ossl102, ossl110))]
263 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
264
265 #[cfg(any(boringssl, ossl110h, awslc))]
269 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
270
271 #[cfg(ossl111)]
276 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
277
278 #[cfg(ossl111)]
290 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
291 }
292}
293
294bitflags! {
295 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
297 #[repr(transparent)]
298 pub struct SslMode: SslBitType {
299 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
305
306 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
309
310 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
320
321 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
327
328 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
332
333 #[cfg(not(libressl))]
341 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
342
343 #[cfg(ossl110)]
350 const ASYNC = ffi::SSL_MODE_ASYNC;
351 }
352}
353
354#[derive(Copy, Clone)]
356pub struct SslMethod(*const ffi::SSL_METHOD);
357
358impl SslMethod {
359 #[corresponds(TLS_method)]
361 pub fn tls() -> SslMethod {
362 unsafe { SslMethod(TLS_method()) }
363 }
364
365 #[corresponds(DTLS_method)]
367 pub fn dtls() -> SslMethod {
368 unsafe { SslMethod(DTLS_method()) }
369 }
370
371 #[corresponds(TLS_client_method)]
373 pub fn tls_client() -> SslMethod {
374 unsafe { SslMethod(TLS_client_method()) }
375 }
376
377 #[corresponds(TLS_server_method)]
379 pub fn tls_server() -> SslMethod {
380 unsafe { SslMethod(TLS_server_method()) }
381 }
382
383 #[cfg(tongsuo)]
384 #[corresponds(NTLS_client_method)]
385 pub fn ntls_client() -> SslMethod {
386 unsafe { SslMethod(ffi::NTLS_client_method()) }
387 }
388
389 #[cfg(tongsuo)]
390 #[corresponds(NTLS_server_method)]
391 pub fn ntls_server() -> SslMethod {
392 unsafe { SslMethod(ffi::NTLS_server_method()) }
393 }
394
395 #[corresponds(DTLS_client_method)]
397 #[cfg(any(boringssl, ossl110, libressl291, awslc))]
398 pub fn dtls_client() -> SslMethod {
399 unsafe { SslMethod(DTLS_client_method()) }
400 }
401
402 #[corresponds(DTLS_server_method)]
404 #[cfg(any(boringssl, ossl110, libressl291, awslc))]
405 pub fn dtls_server() -> SslMethod {
406 unsafe { SslMethod(DTLS_server_method()) }
407 }
408
409 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
415 SslMethod(ptr)
416 }
417
418 #[allow(clippy::trivially_copy_pass_by_ref)]
420 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
421 self.0
422 }
423}
424
425unsafe impl Sync for SslMethod {}
426unsafe impl Send for SslMethod {}
427
428bitflags! {
429 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
431 #[repr(transparent)]
432 pub struct SslVerifyMode: i32 {
433 const PEER = ffi::SSL_VERIFY_PEER;
437
438 const NONE = ffi::SSL_VERIFY_NONE;
444
445 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
449 }
450}
451
452#[cfg(any(boringssl, awslc))]
453type SslBitType = c_int;
454#[cfg(not(any(boringssl, awslc)))]
455type SslBitType = c_long;
456
457#[cfg(any(boringssl, awslc))]
458type SslTimeTy = u64;
459#[cfg(not(any(boringssl, awslc)))]
460type SslTimeTy = c_long;
461
462bitflags! {
463 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
465 #[repr(transparent)]
466 pub struct SslSessionCacheMode: SslBitType {
467 const OFF = ffi::SSL_SESS_CACHE_OFF;
469
470 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
477
478 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
482
483 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
485
486 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
488
489 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
491
492 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
494
495 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
497 }
498}
499
500#[cfg(ossl111)]
501bitflags! {
502 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
504 #[repr(transparent)]
505 pub struct ExtensionContext: c_uint {
506 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
508 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
510 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
512 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
514 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
516 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
518 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
520 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
521 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
523 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
524 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
525 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
526 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
527 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
528 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
529 }
530}
531
532#[derive(Copy, Clone)]
534pub struct TlsExtType(c_uint);
535
536impl TlsExtType {
537 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
541
542 pub const ALPN: TlsExtType =
546 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
547
548 pub fn from_raw(raw: c_uint) -> TlsExtType {
550 TlsExtType(raw)
551 }
552
553 #[allow(clippy::trivially_copy_pass_by_ref)]
555 pub fn as_raw(&self) -> c_uint {
556 self.0
557 }
558}
559
560#[derive(Copy, Clone)]
562pub struct SslFiletype(c_int);
563
564impl SslFiletype {
565 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
569
570 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
574
575 pub fn from_raw(raw: c_int) -> SslFiletype {
577 SslFiletype(raw)
578 }
579
580 #[allow(clippy::trivially_copy_pass_by_ref)]
582 pub fn as_raw(&self) -> c_int {
583 self.0
584 }
585}
586
587#[derive(Copy, Clone)]
589pub struct StatusType(c_int);
590
591impl StatusType {
592 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
594
595 pub fn from_raw(raw: c_int) -> StatusType {
597 StatusType(raw)
598 }
599
600 #[allow(clippy::trivially_copy_pass_by_ref)]
602 pub fn as_raw(&self) -> c_int {
603 self.0
604 }
605}
606
607#[derive(Copy, Clone)]
609pub struct NameType(c_int);
610
611impl NameType {
612 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
614
615 pub fn from_raw(raw: c_int) -> StatusType {
617 StatusType(raw)
618 }
619
620 #[allow(clippy::trivially_copy_pass_by_ref)]
622 pub fn as_raw(&self) -> c_int {
623 self.0
624 }
625}
626
627static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
628static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
629static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
630
631fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
632 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
633}
634
635unsafe extern "C" fn free_data_box<T>(
636 _parent: *mut c_void,
637 ptr: *mut c_void,
638 _ad: *mut ffi::CRYPTO_EX_DATA,
639 _idx: c_int,
640 _argl: c_long,
641 _argp: *mut c_void,
642) {
643 if !ptr.is_null() {
644 let _ = Box::<T>::from_raw(ptr as *mut T);
645 }
646}
647
648#[derive(Debug, Copy, Clone, PartialEq, Eq)]
650pub struct SniError(c_int);
651
652impl SniError {
653 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
655
656 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
658
659 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
660}
661
662#[derive(Debug, Copy, Clone, PartialEq, Eq)]
664pub struct SslAlert(c_int);
665
666impl SslAlert {
667 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
669 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
670 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
671 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
672}
673
674#[derive(Debug, Copy, Clone, PartialEq, Eq)]
676pub struct AlpnError(c_int);
677
678impl AlpnError {
679 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
681
682 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
684}
685
686#[cfg(ossl111)]
690#[derive(Debug, Copy, Clone, PartialEq, Eq)]
691pub struct ClientHelloError(c_int);
692
693#[cfg(ossl111)]
694impl ClientHelloError {
695 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
697
698 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
700}
701
702#[derive(Debug, Copy, Clone, PartialEq, Eq)]
704pub struct TicketKeyStatus(c_int);
705
706impl TicketKeyStatus {
707 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
709 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
711 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
713}
714
715#[derive(Debug, Copy, Clone, PartialEq, Eq)]
717#[cfg(any(boringssl, awslc))]
718pub struct SelectCertError(ffi::ssl_select_cert_result_t);
719
720#[cfg(any(boringssl, awslc))]
721impl SelectCertError {
722 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
724
725 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
727
728 #[cfg(boringssl)]
734 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
735}
736
737#[cfg(ossl111)]
739#[derive(Debug, Copy, Clone, PartialEq, Eq)]
740pub struct SslCtValidationMode(c_int);
741
742#[cfg(ossl111)]
743impl SslCtValidationMode {
744 pub const PERMISSIVE: SslCtValidationMode =
745 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
746 pub const STRICT: SslCtValidationMode =
747 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
748}
749
750#[derive(Debug, Copy, Clone, PartialEq, Eq)]
752pub struct CertCompressionAlgorithm(c_int);
753
754impl CertCompressionAlgorithm {
755 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
756 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
757 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
758}
759
760#[derive(Debug, Copy, Clone, PartialEq, Eq)]
762pub struct SslVersion(c_int);
763
764impl SslVersion {
765 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
767
768 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
770
771 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
773
774 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
776
777 #[cfg(any(ossl111, libressl340, boringssl, awslc))]
781 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
782
783 #[cfg(tongsuo)]
784 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
785
786 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
790
791 #[cfg(any(ossl102, libressl332, boringssl, awslc))]
795 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
796}
797
798cfg_if! {
799 if #[cfg(any(boringssl, awslc))] {
800 type SslCacheTy = i64;
801 type SslCacheSize = libc::c_ulong;
802 type MtuTy = u32;
803 type ModeTy = u32;
804 type SizeTy = usize;
805 } else {
806 type SslCacheTy = i64;
807 type SslCacheSize = c_long;
808 type MtuTy = c_long;
809 type ModeTy = c_long;
810 type SizeTy = u32;
811 }
812}
813
814#[corresponds(SSL_select_next_proto)]
825pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
826 unsafe {
827 let mut out = ptr::null_mut();
828 let mut outlen = 0;
829 let r = ffi::SSL_select_next_proto(
830 &mut out,
831 &mut outlen,
832 server.as_ptr(),
833 server.len() as c_uint,
834 client.as_ptr(),
835 client.len() as c_uint,
836 );
837 if r == ffi::OPENSSL_NPN_NEGOTIATED {
838 Some(util::from_raw_parts(out as *const u8, outlen as usize))
839 } else {
840 None
841 }
842 }
843}
844
845pub struct SslContextBuilder(SslContext);
847
848impl SslContextBuilder {
849 #[corresponds(SSL_CTX_new)]
851 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
852 unsafe {
853 init();
854 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
855
856 Ok(SslContextBuilder::from_ptr(ctx))
857 }
858 }
859
860 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
866 SslContextBuilder(SslContext::from_ptr(ctx))
867 }
868
869 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
871 self.0.as_ptr()
872 }
873
874 #[cfg(tongsuo)]
875 #[corresponds(SSL_CTX_enable_ntls)]
876 pub fn enable_ntls(&mut self) {
877 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
878 }
879
880 #[cfg(tongsuo)]
881 #[corresponds(SSL_CTX_disable_ntls)]
882 pub fn disable_ntls(&mut self) {
883 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
884 }
885
886 #[cfg(all(tongsuo, ossl300))]
887 #[corresponds(SSL_CTX_enable_force_ntls)]
888 pub fn enable_force_ntls(&mut self) {
889 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
890 }
891
892 #[cfg(all(tongsuo, ossl300))]
893 #[corresponds(SSL_CTX_disable_force_ntls)]
894 pub fn disable_force_ntls(&mut self) {
895 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
896 }
897
898 #[cfg(tongsuo)]
899 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
900 pub fn enable_sm_tls13_strict(&mut self) {
901 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
902 }
903
904 #[cfg(tongsuo)]
905 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
906 pub fn disable_sm_tls13_strict(&mut self) {
907 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
908 }
909
910 #[corresponds(SSL_CTX_set_verify)]
912 pub fn set_verify(&mut self, mode: SslVerifyMode) {
913 unsafe {
914 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
915 }
916 }
917
918 #[corresponds(SSL_CTX_set_verify)]
925 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
926 where
927 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
928 {
929 unsafe {
930 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
931 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
932 }
933 }
934
935 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
943 pub fn set_servername_callback<F>(&mut self, callback: F)
945 where
946 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
947 {
948 unsafe {
949 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
955 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
956 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
957 }
958 }
959
960 #[corresponds(SSL_CTX_set_verify_depth)]
964 pub fn set_verify_depth(&mut self, depth: u32) {
965 unsafe {
966 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
967 }
968 }
969
970 #[corresponds(SSL_CTX_set0_verify_cert_store)]
974 #[cfg(any(ossl102, boringssl, awslc))]
975 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
976 unsafe {
977 let ptr = cert_store.as_ptr();
978 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
979 mem::forget(cert_store);
980
981 Ok(())
982 }
983 }
984
985 #[corresponds(SSL_CTX_set_cert_store)]
987 pub fn set_cert_store(&mut self, cert_store: X509Store) {
988 unsafe {
989 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
990 mem::forget(cert_store);
991 }
992 }
993
994 #[corresponds(SSL_CTX_set_read_ahead)]
1001 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1002 unsafe {
1003 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1004 }
1005 }
1006
1007 #[corresponds(SSL_CTX_set_mode)]
1011 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1012 unsafe {
1013 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1014 SslMode::from_bits_retain(bits)
1015 }
1016 }
1017
1018 #[corresponds(SSL_CTX_clear_mode)]
1020 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1021 unsafe {
1022 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1023 SslMode::from_bits_retain(bits)
1024 }
1025 }
1026
1027 #[corresponds(SSL_CTX_get_mode)]
1029 pub fn mode(&self) -> SslMode {
1030 unsafe {
1031 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1032 SslMode::from_bits_retain(bits)
1033 }
1034 }
1035
1036 #[corresponds(SSL_CTX_set_dh_auto)]
1045 #[cfg(ossl300)]
1046 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1047 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1048 }
1049
1050 #[corresponds(SSL_CTX_set_tmp_dh)]
1052 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1053 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1054 }
1055
1056 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1063 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1064 where
1065 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1066 {
1067 unsafe {
1068 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1069
1070 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1071 }
1072 }
1073
1074 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1076 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1077 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1078 }
1079
1080 #[corresponds(SSL_CTX_set_default_verify_paths)]
1085 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1086 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1087 }
1088
1089 #[corresponds(SSL_CTX_load_verify_locations)]
1093 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1094 self.load_verify_locations(Some(file.as_ref()), None)
1095 }
1096
1097 #[corresponds(SSL_CTX_load_verify_locations)]
1099 pub fn load_verify_locations(
1100 &mut self,
1101 ca_file: Option<&Path>,
1102 ca_path: Option<&Path>,
1103 ) -> Result<(), ErrorStack> {
1104 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1105 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1106 unsafe {
1107 cvt(ffi::SSL_CTX_load_verify_locations(
1108 self.as_ptr(),
1109 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1110 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1111 ))
1112 .map(|_| ())
1113 }
1114 }
1115
1116 #[corresponds(SSL_CTX_set_client_CA_list)]
1121 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1122 unsafe {
1123 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1124 mem::forget(list);
1125 }
1126 }
1127
1128 #[corresponds(SSL_CTX_add_client_CA)]
1131 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1132 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1133 }
1134
1135 #[corresponds(SSL_CTX_set_session_id_context)]
1144 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1145 unsafe {
1146 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1147 cvt(ffi::SSL_CTX_set_session_id_context(
1148 self.as_ptr(),
1149 sid_ctx.as_ptr(),
1150 sid_ctx.len() as SizeTy,
1151 ))
1152 .map(|_| ())
1153 }
1154 }
1155
1156 #[corresponds(SSL_CTX_use_certificate_file)]
1162 pub fn set_certificate_file<P: AsRef<Path>>(
1163 &mut self,
1164 file: P,
1165 file_type: SslFiletype,
1166 ) -> Result<(), ErrorStack> {
1167 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1168 unsafe {
1169 cvt(ffi::SSL_CTX_use_certificate_file(
1170 self.as_ptr(),
1171 file.as_ptr() as *const _,
1172 file_type.as_raw(),
1173 ))
1174 .map(|_| ())
1175 }
1176 }
1177
1178 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1184 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1185 &mut self,
1186 file: P,
1187 ) -> Result<(), ErrorStack> {
1188 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1189 unsafe {
1190 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1191 self.as_ptr(),
1192 file.as_ptr() as *const _,
1193 ))
1194 .map(|_| ())
1195 }
1196 }
1197
1198 #[corresponds(SSL_CTX_use_certificate)]
1202 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1203 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1204 }
1205
1206 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1211 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1212 unsafe {
1213 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1214 mem::forget(cert);
1215 Ok(())
1216 }
1217 }
1218
1219 #[cfg(tongsuo)]
1220 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1221 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1222 &mut self,
1223 file: P,
1224 file_type: SslFiletype,
1225 ) -> Result<(), ErrorStack> {
1226 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1227 unsafe {
1228 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1229 self.as_ptr(),
1230 file.as_ptr() as *const _,
1231 file_type.as_raw(),
1232 ))
1233 .map(|_| ())
1234 }
1235 }
1236
1237 #[cfg(tongsuo)]
1238 #[corresponds(SSL_CTX_use_enc_certificate)]
1239 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1240 unsafe {
1241 cvt(ffi::SSL_CTX_use_enc_certificate(
1242 self.as_ptr(),
1243 cert.as_ptr(),
1244 ))
1245 .map(|_| ())
1246 }
1247 }
1248
1249 #[cfg(tongsuo)]
1250 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1251 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1252 &mut self,
1253 file: P,
1254 file_type: SslFiletype,
1255 ) -> Result<(), ErrorStack> {
1256 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1257 unsafe {
1258 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1259 self.as_ptr(),
1260 file.as_ptr() as *const _,
1261 file_type.as_raw(),
1262 ))
1263 .map(|_| ())
1264 }
1265 }
1266
1267 #[cfg(tongsuo)]
1268 #[corresponds(SSL_CTX_use_sign_certificate)]
1269 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1270 unsafe {
1271 cvt(ffi::SSL_CTX_use_sign_certificate(
1272 self.as_ptr(),
1273 cert.as_ptr(),
1274 ))
1275 .map(|_| ())
1276 }
1277 }
1278
1279 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1281 pub fn set_private_key_file<P: AsRef<Path>>(
1282 &mut self,
1283 file: P,
1284 file_type: SslFiletype,
1285 ) -> Result<(), ErrorStack> {
1286 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1287 unsafe {
1288 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1289 self.as_ptr(),
1290 file.as_ptr() as *const _,
1291 file_type.as_raw(),
1292 ))
1293 .map(|_| ())
1294 }
1295 }
1296
1297 #[corresponds(SSL_CTX_use_PrivateKey)]
1299 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1300 where
1301 T: HasPrivate,
1302 {
1303 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1304 }
1305
1306 #[cfg(tongsuo)]
1307 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1308 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1309 &mut self,
1310 file: P,
1311 file_type: SslFiletype,
1312 ) -> Result<(), ErrorStack> {
1313 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1314 unsafe {
1315 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1316 self.as_ptr(),
1317 file.as_ptr() as *const _,
1318 file_type.as_raw(),
1319 ))
1320 .map(|_| ())
1321 }
1322 }
1323
1324 #[cfg(tongsuo)]
1325 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1326 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1327 where
1328 T: HasPrivate,
1329 {
1330 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1331 }
1332
1333 #[cfg(tongsuo)]
1334 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1335 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1336 &mut self,
1337 file: P,
1338 file_type: SslFiletype,
1339 ) -> Result<(), ErrorStack> {
1340 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1341 unsafe {
1342 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1343 self.as_ptr(),
1344 file.as_ptr() as *const _,
1345 file_type.as_raw(),
1346 ))
1347 .map(|_| ())
1348 }
1349 }
1350
1351 #[cfg(tongsuo)]
1352 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1353 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1354 where
1355 T: HasPrivate,
1356 {
1357 unsafe {
1358 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1359 self.as_ptr(),
1360 key.as_ptr(),
1361 ))
1362 .map(|_| ())
1363 }
1364 }
1365
1366 #[corresponds(SSL_CTX_set_cipher_list)]
1374 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1375 let cipher_list = CString::new(cipher_list).unwrap();
1376 unsafe {
1377 cvt(ffi::SSL_CTX_set_cipher_list(
1378 self.as_ptr(),
1379 cipher_list.as_ptr() as *const _,
1380 ))
1381 .map(|_| ())
1382 }
1383 }
1384
1385 #[corresponds(SSL_CTX_set_ciphersuites)]
1394 #[cfg(any(ossl111, libressl340, awslc))]
1395 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1396 let cipher_list = CString::new(cipher_list).unwrap();
1397 unsafe {
1398 cvt(ffi::SSL_CTX_set_ciphersuites(
1399 self.as_ptr(),
1400 cipher_list.as_ptr() as *const _,
1401 ))
1402 .map(|_| ())
1403 }
1404 }
1405
1406 #[corresponds(SSL_CTX_set_ecdh_auto)]
1410 #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1411 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1412 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1413 }
1414
1415 #[corresponds(SSL_CTX_set_options)]
1422 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1423 let bits =
1424 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1425 SslOptions::from_bits_retain(bits)
1426 }
1427
1428 #[corresponds(SSL_CTX_get_options)]
1430 pub fn options(&self) -> SslOptions {
1431 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1432 SslOptions::from_bits_retain(bits)
1433 }
1434
1435 #[corresponds(SSL_CTX_clear_options)]
1437 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1438 let bits =
1439 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1440 SslOptions::from_bits_retain(bits)
1441 }
1442
1443 #[corresponds(SSL_CTX_set_min_proto_version)]
1450 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1451 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1452 unsafe {
1453 cvt(ffi::SSL_CTX_set_min_proto_version(
1454 self.as_ptr(),
1455 version.map_or(0, |v| v.0 as _),
1456 ))
1457 .map(|_| ())
1458 }
1459 }
1460
1461 #[corresponds(SSL_CTX_set_max_proto_version)]
1468 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1469 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1470 unsafe {
1471 cvt(ffi::SSL_CTX_set_max_proto_version(
1472 self.as_ptr(),
1473 version.map_or(0, |v| v.0 as _),
1474 ))
1475 .map(|_| ())
1476 }
1477 }
1478
1479 #[corresponds(SSL_CTX_get_min_proto_version)]
1486 #[cfg(any(ossl110g, libressl270))]
1487 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1488 unsafe {
1489 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1490 if r == 0 {
1491 None
1492 } else {
1493 Some(SslVersion(r))
1494 }
1495 }
1496 }
1497
1498 #[corresponds(SSL_CTX_get_max_proto_version)]
1505 #[cfg(any(ossl110g, libressl270))]
1506 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1507 unsafe {
1508 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1509 if r == 0 {
1510 None
1511 } else {
1512 Some(SslVersion(r))
1513 }
1514 }
1515 }
1516
1517 #[corresponds(SSL_CTX_set_alpn_protos)]
1526 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
1527 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1528 unsafe {
1529 assert!(protocols.len() <= c_uint::MAX as usize);
1530 let r = ffi::SSL_CTX_set_alpn_protos(
1531 self.as_ptr(),
1532 protocols.as_ptr(),
1533 protocols.len() as _,
1534 );
1535 if r == 0 {
1537 Ok(())
1538 } else {
1539 Err(ErrorStack::get())
1540 }
1541 }
1542 }
1543
1544 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1546 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1547 unsafe {
1548 let cstr = CString::new(protocols).unwrap();
1549
1550 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1551 if r == 0 {
1553 Ok(())
1554 } else {
1555 Err(ErrorStack::get())
1556 }
1557 }
1558 }
1559
1560 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1571 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1572 where
1573 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1574 {
1575 unsafe {
1576 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1577 ffi::SSL_CTX_set_alpn_select_cb(
1578 self.as_ptr(),
1579 Some(callbacks::raw_alpn_select::<F>),
1580 ptr::null_mut(),
1581 );
1582 }
1583 }
1584
1585 #[corresponds(SSL_CTX_check_private_key)]
1587 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1588 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1589 }
1590
1591 #[corresponds(SSL_CTX_get_cert_store)]
1593 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1594 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1595 }
1596
1597 #[corresponds(SSL_CTX_get_cert_store)]
1599 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1600 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1601 }
1602
1603 #[corresponds(SSL_CTX_get0_param)]
1607 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1608 pub fn verify_param(&self) -> &X509VerifyParamRef {
1609 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1610 }
1611
1612 #[corresponds(SSL_CTX_get0_param)]
1616 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1617 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1618 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1619 }
1620
1621 #[cfg(any(boringssl, tongsuo, awslc))]
1629 pub fn add_cert_decompression_alg<F>(
1630 &mut self,
1631 alg_id: CertCompressionAlgorithm,
1632 decompress: F,
1633 ) -> Result<(), ErrorStack>
1634 where
1635 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1636 {
1637 unsafe {
1638 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1639 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1640 self.as_ptr(),
1641 alg_id.0 as _,
1642 None,
1643 Some(raw_cert_decompression::<F>),
1644 ))
1645 .map(|_| ())
1646 }
1647 }
1648
1649 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1651 #[cfg(ossl320)]
1652 pub fn set_cert_comp_preference(
1653 &mut self,
1654 algs: &[CertCompressionAlgorithm],
1655 ) -> Result<(), ErrorStack> {
1656 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1657 unsafe {
1658 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1659 self.as_ptr(),
1660 algs.as_mut_ptr(),
1661 algs.len(),
1662 ))
1663 .map(|_| ())
1664 }
1665 }
1666
1667 #[cfg(any(boringssl, awslc))]
1675 pub fn enable_ocsp_stapling(&mut self) {
1676 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1677 }
1678
1679 #[cfg(any(boringssl, awslc))]
1687 pub fn enable_signed_cert_timestamps(&mut self) {
1688 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1689 }
1690
1691 #[cfg(any(boringssl, awslc))]
1699 pub fn set_grease_enabled(&mut self, enabled: bool) {
1700 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1701 }
1702
1703 #[cfg(any(boringssl, awslc))]
1711 pub fn set_permute_extensions(&mut self, enabled: bool) {
1712 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1713 }
1714
1715 #[corresponds(SSL_CTX_enable_ct)]
1717 #[cfg(ossl111)]
1718 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1719 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1720 }
1721
1722 #[corresponds(SSL_CTX_ct_is_enabled)]
1724 #[cfg(ossl111)]
1725 pub fn ct_is_enabled(&self) -> bool {
1726 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1727 }
1728
1729 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1731 #[cfg(not(any(boringssl, awslc)))]
1732 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1733 unsafe {
1734 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1735 .map(|_| ())
1736 }
1737 }
1738
1739 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1752 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1753 where
1754 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1755 {
1756 unsafe {
1757 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1758 cvt(
1759 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1760 as c_int,
1761 )
1762 .map(|_| ())
1763 }
1764 }
1765
1766 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1767 #[cfg(ossl300)]
1768 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1769 where
1770 F: Fn(
1771 &mut SslRef,
1772 &mut [u8],
1773 &mut [u8],
1774 &mut CipherCtxRef,
1775 &mut MacCtxRef,
1776 bool,
1777 ) -> Result<TicketKeyStatus, ErrorStack>
1778 + 'static
1779 + Sync
1780 + Send,
1781 {
1782 unsafe {
1783 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1784 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1785 self.as_ptr(),
1786 Some(raw_tlsext_ticket_key_evp::<F>),
1787 ) as c_int)
1788 .map(|_| ())
1789 }
1790 }
1791
1792 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1793 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1794 where
1795 F: Fn(
1796 &mut SslRef,
1797 &mut [u8],
1798 &mut [u8],
1799 &mut CipherCtxRef,
1800 &mut HMacCtxRef,
1801 bool,
1802 ) -> Result<TicketKeyStatus, ErrorStack>
1803 + 'static
1804 + Sync
1805 + Send,
1806 {
1807 unsafe {
1808 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1809 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1810 self.as_ptr(),
1811 Some(raw_tlsext_ticket_key::<F>),
1812 ) as c_int)
1813 .map(|_| ())
1814 }
1815 }
1816
1817 #[corresponds(SSL_CTX_set_psk_client_callback)]
1823 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1824 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1825 where
1826 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1827 + 'static
1828 + Sync
1829 + Send,
1830 {
1831 unsafe {
1832 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1833 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1834 }
1835 }
1836
1837 #[corresponds(SSL_CTX_set_psk_server_callback)]
1843 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1844 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1845 where
1846 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1847 + 'static
1848 + Sync
1849 + Send,
1850 {
1851 unsafe {
1852 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1853 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1854 }
1855 }
1856
1857 #[corresponds(SSL_CTX_sess_set_new_cb)]
1871 pub fn set_new_session_callback<F>(&mut self, callback: F)
1872 where
1873 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1874 {
1875 unsafe {
1876 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1877 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1878 }
1879 }
1880
1881 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1885 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1886 where
1887 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1888 {
1889 unsafe {
1890 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1891 ffi::SSL_CTX_sess_set_remove_cb(
1892 self.as_ptr(),
1893 Some(callbacks::raw_remove_session::<F>),
1894 );
1895 }
1896 }
1897
1898 #[corresponds(SSL_CTX_sess_set_get_cb)]
1909 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1910 where
1911 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1912 {
1913 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1914 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1915 }
1916
1917 #[corresponds(SSL_CTX_set_keylog_callback)]
1925 #[cfg(any(ossl111, boringssl, awslc))]
1926 pub fn set_keylog_callback<F>(&mut self, callback: F)
1927 where
1928 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1929 {
1930 unsafe {
1931 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1932 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1933 }
1934 }
1935
1936 #[corresponds(SSL_CTX_set_session_cache_mode)]
1940 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1941 unsafe {
1942 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1943 SslSessionCacheMode::from_bits_retain(bits)
1944 }
1945 }
1946
1947 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1953 #[cfg(ossl111)]
1954 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1955 where
1956 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1957 {
1958 unsafe {
1959 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1960 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1961 self.as_ptr(),
1962 Some(raw_stateless_cookie_generate::<F>),
1963 );
1964 }
1965 }
1966
1967 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1976 #[cfg(ossl111)]
1977 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1978 where
1979 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1980 {
1981 unsafe {
1982 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1983 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1984 self.as_ptr(),
1985 Some(raw_stateless_cookie_verify::<F>),
1986 )
1987 }
1988 }
1989
1990 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1995 #[cfg(not(any(boringssl, awslc)))]
1996 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1997 where
1998 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1999 {
2000 unsafe {
2001 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2002 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2003 }
2004 }
2005
2006 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2011 #[cfg(not(any(boringssl, awslc)))]
2012 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2013 where
2014 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2015 {
2016 unsafe {
2017 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2018 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2019 }
2020 }
2021
2022 #[corresponds(SSL_CTX_set_ex_data)]
2028 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2029 self.set_ex_data_inner(index, data);
2030 }
2031
2032 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2033 match self.ex_data_mut(index) {
2034 Some(v) => {
2035 *v = data;
2036 (v as *mut T).cast()
2037 }
2038 _ => unsafe {
2039 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2040 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2041 data
2042 },
2043 }
2044 }
2045
2046 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2047 unsafe {
2048 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2049 if data.is_null() {
2050 None
2051 } else {
2052 Some(&mut *data.cast())
2053 }
2054 }
2055 }
2056
2057 #[corresponds(SSL_CTX_add_custom_ext)]
2061 #[cfg(ossl111)]
2062 pub fn add_custom_ext<AddFn, ParseFn, T>(
2063 &mut self,
2064 ext_type: u16,
2065 context: ExtensionContext,
2066 add_cb: AddFn,
2067 parse_cb: ParseFn,
2068 ) -> Result<(), ErrorStack>
2069 where
2070 AddFn: Fn(
2071 &mut SslRef,
2072 ExtensionContext,
2073 Option<(usize, &X509Ref)>,
2074 ) -> Result<Option<T>, SslAlert>
2075 + 'static
2076 + Sync
2077 + Send,
2078 T: AsRef<[u8]> + 'static + Sync + Send,
2079 ParseFn: Fn(
2080 &mut SslRef,
2081 ExtensionContext,
2082 &[u8],
2083 Option<(usize, &X509Ref)>,
2084 ) -> Result<(), SslAlert>
2085 + 'static
2086 + Sync
2087 + Send,
2088 {
2089 let ret = unsafe {
2090 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2091 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2092
2093 ffi::SSL_CTX_add_custom_ext(
2094 self.as_ptr(),
2095 ext_type as c_uint,
2096 context.bits(),
2097 Some(raw_custom_ext_add::<AddFn, T>),
2098 Some(raw_custom_ext_free::<T>),
2099 ptr::null_mut(),
2100 Some(raw_custom_ext_parse::<ParseFn>),
2101 ptr::null_mut(),
2102 )
2103 };
2104 if ret == 1 {
2105 Ok(())
2106 } else {
2107 Err(ErrorStack::get())
2108 }
2109 }
2110
2111 #[corresponds(SSL_CTX_set_max_early_data)]
2117 #[cfg(any(ossl111, libressl340))]
2118 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2119 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2120 Ok(())
2121 } else {
2122 Err(ErrorStack::get())
2123 }
2124 }
2125
2126 #[cfg(any(boringssl, awslc))]
2136 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2137 where
2138 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2139 {
2140 unsafe {
2141 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2142 ffi::SSL_CTX_set_select_certificate_cb(
2143 self.as_ptr(),
2144 Some(callbacks::raw_select_cert::<F>),
2145 );
2146 }
2147 }
2148
2149 #[corresponds(SSL_CTX_set_client_hello_cb)]
2153 #[cfg(ossl111)]
2154 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2155 where
2156 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2157 {
2158 unsafe {
2159 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2160 ffi::SSL_CTX_set_client_hello_cb(
2161 self.as_ptr(),
2162 Some(callbacks::raw_client_hello::<F>),
2163 ptr,
2164 );
2165 }
2166 }
2167
2168 #[corresponds(SSL_CTX_set_info_callback)]
2171 pub fn set_info_callback<F>(&mut self, callback: F)
2172 where
2173 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2174 {
2175 unsafe {
2176 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2177 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2178 }
2179 }
2180
2181 #[corresponds(SSL_CTX_sess_set_cache_size)]
2185 #[allow(clippy::useless_conversion)]
2186 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2187 unsafe {
2188 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2189 }
2190 }
2191
2192 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2196 #[cfg(ossl102)]
2197 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2198 let sigalgs = CString::new(sigalgs).unwrap();
2199 unsafe {
2200 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2201 .map(|_| ())
2202 }
2203 }
2204
2205 #[corresponds(SSL_CTX_set1_groups_list)]
2209 #[cfg(any(ossl111, boringssl, libressl251, awslc))]
2210 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2211 let groups = CString::new(groups).unwrap();
2212 unsafe {
2213 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2214 }
2215 }
2216
2217 #[corresponds(SSL_CTX_set_num_tickets)]
2222 #[cfg(any(ossl111, boringssl, awslc))]
2223 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2224 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2225 }
2226
2227 #[corresponds(SSL_CTX_set_security_level)]
2232 #[cfg(any(ossl110, libressl360))]
2233 pub fn set_security_level(&mut self, level: u32) {
2234 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2235 }
2236
2237 pub fn build(self) -> SslContext {
2239 self.0
2240 }
2241}
2242
2243foreign_type_and_impl_send_sync! {
2244 type CType = ffi::SSL_CTX;
2245 fn drop = ffi::SSL_CTX_free;
2246
2247 pub struct SslContext;
2252
2253 pub struct SslContextRef;
2257}
2258
2259impl Clone for SslContext {
2260 fn clone(&self) -> Self {
2261 (**self).to_owned()
2262 }
2263}
2264
2265impl ToOwned for SslContextRef {
2266 type Owned = SslContext;
2267
2268 fn to_owned(&self) -> Self::Owned {
2269 unsafe {
2270 SSL_CTX_up_ref(self.as_ptr());
2271 SslContext::from_ptr(self.as_ptr())
2272 }
2273 }
2274}
2275
2276impl fmt::Debug for SslContext {
2278 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2279 write!(fmt, "SslContext")
2280 }
2281}
2282
2283impl SslContext {
2284 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2286 SslContextBuilder::new(method)
2287 }
2288
2289 #[corresponds(SSL_CTX_get_ex_new_index)]
2294 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2295 where
2296 T: 'static + Sync + Send,
2297 {
2298 unsafe {
2299 ffi::init();
2300 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2301 Ok(Index::from_raw(idx))
2302 }
2303 }
2304
2305 fn cached_ex_index<T>() -> Index<SslContext, T>
2307 where
2308 T: 'static + Sync + Send,
2309 {
2310 unsafe {
2311 let idx = *INDEXES
2312 .lock()
2313 .unwrap_or_else(|e| e.into_inner())
2314 .entry(TypeId::of::<T>())
2315 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2316 Index::from_raw(idx)
2317 }
2318 }
2319}
2320
2321impl SslContextRef {
2322 #[corresponds(SSL_CTX_get0_certificate)]
2326 #[cfg(any(ossl102, libressl270))]
2327 pub fn certificate(&self) -> Option<&X509Ref> {
2328 unsafe {
2329 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2330 X509Ref::from_const_ptr_opt(ptr)
2331 }
2332 }
2333
2334 #[corresponds(SSL_CTX_get0_privatekey)]
2338 #[cfg(any(ossl102, libressl340))]
2339 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2340 unsafe {
2341 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2342 PKeyRef::from_const_ptr_opt(ptr)
2343 }
2344 }
2345
2346 #[corresponds(SSL_CTX_get_cert_store)]
2348 pub fn cert_store(&self) -> &X509StoreRef {
2349 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2350 }
2351
2352 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2354 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2355 unsafe {
2356 let mut chain = ptr::null_mut();
2357 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2358 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2359 }
2360 }
2361
2362 #[corresponds(SSL_CTX_get_ex_data)]
2364 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2365 unsafe {
2366 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2367 if data.is_null() {
2368 None
2369 } else {
2370 Some(&*(data as *const T))
2371 }
2372 }
2373 }
2374
2375 #[corresponds(SSL_CTX_get_max_early_data)]
2379 #[cfg(any(ossl111, libressl340))]
2380 pub fn max_early_data(&self) -> u32 {
2381 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2382 }
2383
2384 #[corresponds(SSL_CTX_add_session)]
2393 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2394 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2395 }
2396
2397 #[corresponds(SSL_CTX_remove_session)]
2406 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2407 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2408 }
2409
2410 #[corresponds(SSL_CTX_sess_get_cache_size)]
2414 #[allow(clippy::unnecessary_cast)]
2415 pub fn session_cache_size(&self) -> i64 {
2416 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2417 }
2418
2419 #[corresponds(SSL_CTX_get_verify_mode)]
2423 pub fn verify_mode(&self) -> SslVerifyMode {
2424 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2425 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2426 }
2427
2428 #[corresponds(SSL_CTX_get_num_tickets)]
2433 #[cfg(ossl111)]
2434 pub fn num_tickets(&self) -> usize {
2435 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2436 }
2437
2438 #[corresponds(SSL_CTX_get_security_level)]
2443 #[cfg(any(ossl110, libressl360))]
2444 pub fn security_level(&self) -> u32 {
2445 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2446 }
2447}
2448
2449pub struct CipherBits {
2451 pub secret: i32,
2453
2454 pub algorithm: i32,
2456}
2457
2458pub struct SslCipher(*mut ffi::SSL_CIPHER);
2460
2461impl ForeignType for SslCipher {
2462 type CType = ffi::SSL_CIPHER;
2463 type Ref = SslCipherRef;
2464
2465 #[inline]
2466 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2467 SslCipher(ptr)
2468 }
2469
2470 #[inline]
2471 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2472 self.0
2473 }
2474}
2475
2476impl Stackable for SslCipher {
2477 type StackType = ffi::stack_st_SSL_CIPHER;
2478}
2479
2480impl Deref for SslCipher {
2481 type Target = SslCipherRef;
2482
2483 fn deref(&self) -> &SslCipherRef {
2484 unsafe { SslCipherRef::from_ptr(self.0) }
2485 }
2486}
2487
2488impl DerefMut for SslCipher {
2489 fn deref_mut(&mut self) -> &mut SslCipherRef {
2490 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2491 }
2492}
2493
2494pub struct SslCipherRef(Opaque);
2498
2499impl ForeignTypeRef for SslCipherRef {
2500 type CType = ffi::SSL_CIPHER;
2501}
2502
2503impl SslCipherRef {
2504 #[corresponds(SSL_CIPHER_get_name)]
2506 pub fn name(&self) -> &'static str {
2507 unsafe {
2508 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2509 CStr::from_ptr(ptr).to_str().unwrap()
2510 }
2511 }
2512
2513 #[corresponds(SSL_CIPHER_standard_name)]
2517 #[cfg(ossl111)]
2518 pub fn standard_name(&self) -> Option<&'static str> {
2519 unsafe {
2520 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2521 if ptr.is_null() {
2522 None
2523 } else {
2524 Some(CStr::from_ptr(ptr).to_str().unwrap())
2525 }
2526 }
2527 }
2528
2529 #[corresponds(SSL_CIPHER_get_version)]
2531 pub fn version(&self) -> &'static str {
2532 let version = unsafe {
2533 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2534 CStr::from_ptr(ptr as *const _)
2535 };
2536
2537 str::from_utf8(version.to_bytes()).unwrap()
2538 }
2539
2540 #[corresponds(SSL_CIPHER_get_bits)]
2542 #[allow(clippy::useless_conversion)]
2543 pub fn bits(&self) -> CipherBits {
2544 unsafe {
2545 let mut algo_bits = 0;
2546 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2547 CipherBits {
2548 secret: secret_bits.into(),
2549 algorithm: algo_bits.into(),
2550 }
2551 }
2552 }
2553
2554 #[corresponds(SSL_CIPHER_description)]
2556 pub fn description(&self) -> String {
2557 unsafe {
2558 let mut buf = [0; 128];
2560 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2561 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2562 }
2563 }
2564
2565 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2569 #[cfg(ossl111)]
2570 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2571 unsafe {
2572 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2573 if ptr.is_null() {
2574 None
2575 } else {
2576 Some(MessageDigest::from_ptr(ptr))
2577 }
2578 }
2579 }
2580
2581 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2585 #[cfg(any(ossl110, libressl270))]
2586 pub fn cipher_nid(&self) -> Option<Nid> {
2587 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2588 if n == 0 {
2589 None
2590 } else {
2591 Some(Nid::from_raw(n))
2592 }
2593 }
2594}
2595
2596impl fmt::Debug for SslCipherRef {
2597 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2598 write!(fmt, "{}", self.name())
2599 }
2600}
2601
2602#[derive(Debug)]
2604pub struct CipherLists {
2605 pub suites: Stack<SslCipher>,
2606 pub signalling_suites: Stack<SslCipher>,
2607}
2608
2609foreign_type_and_impl_send_sync! {
2610 type CType = ffi::SSL_SESSION;
2611 fn drop = ffi::SSL_SESSION_free;
2612
2613 pub struct SslSession;
2617
2618 pub struct SslSessionRef;
2622}
2623
2624impl Clone for SslSession {
2625 fn clone(&self) -> SslSession {
2626 SslSessionRef::to_owned(self)
2627 }
2628}
2629
2630impl SslSession {
2631 from_der! {
2632 #[corresponds(d2i_SSL_SESSION)]
2634 from_der,
2635 SslSession,
2636 ffi::d2i_SSL_SESSION
2637 }
2638}
2639
2640impl ToOwned for SslSessionRef {
2641 type Owned = SslSession;
2642
2643 fn to_owned(&self) -> SslSession {
2644 unsafe {
2645 SSL_SESSION_up_ref(self.as_ptr());
2646 SslSession(self.as_ptr())
2647 }
2648 }
2649}
2650
2651impl SslSessionRef {
2652 #[corresponds(SSL_SESSION_get_id)]
2654 pub fn id(&self) -> &[u8] {
2655 unsafe {
2656 let mut len = 0;
2657 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2658 #[allow(clippy::unnecessary_cast)]
2659 util::from_raw_parts(p as *const u8, len as usize)
2660 }
2661 }
2662
2663 #[corresponds(SSL_SESSION_get_master_key)]
2665 pub fn master_key_len(&self) -> usize {
2666 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2667 }
2668
2669 #[corresponds(SSL_SESSION_get_master_key)]
2673 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2674 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2675 }
2676
2677 #[corresponds(SSL_SESSION_get_max_early_data)]
2681 #[cfg(any(ossl111, libressl340))]
2682 pub fn max_early_data(&self) -> u32 {
2683 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2684 }
2685
2686 #[corresponds(SSL_SESSION_get_time)]
2688 #[allow(clippy::useless_conversion)]
2689 pub fn time(&self) -> SslTimeTy {
2690 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2691 }
2692
2693 #[corresponds(SSL_SESSION_get_timeout)]
2697 #[allow(clippy::useless_conversion)]
2698 pub fn timeout(&self) -> i64 {
2699 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2700 }
2701
2702 #[corresponds(SSL_SESSION_get_protocol_version)]
2706 #[cfg(any(ossl110, libressl270))]
2707 pub fn protocol_version(&self) -> SslVersion {
2708 unsafe {
2709 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2710 SslVersion(version)
2711 }
2712 }
2713
2714 #[corresponds(SSL_SESSION_get_protocol_version)]
2716 #[cfg(any(boringssl, awslc))]
2717 pub fn protocol_version(&self) -> SslVersion {
2718 unsafe {
2719 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2720 SslVersion(version as _)
2721 }
2722 }
2723
2724 to_der! {
2725 #[corresponds(i2d_SSL_SESSION)]
2727 to_der,
2728 ffi::i2d_SSL_SESSION
2729 }
2730}
2731
2732foreign_type_and_impl_send_sync! {
2733 type CType = ffi::SSL;
2734 fn drop = ffi::SSL_free;
2735
2736 pub struct Ssl;
2743
2744 pub struct SslRef;
2748}
2749
2750impl fmt::Debug for Ssl {
2751 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2752 fmt::Debug::fmt(&**self, fmt)
2753 }
2754}
2755
2756impl Ssl {
2757 #[corresponds(SSL_get_ex_new_index)]
2762 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2763 where
2764 T: 'static + Sync + Send,
2765 {
2766 unsafe {
2767 ffi::init();
2768 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2769 Ok(Index::from_raw(idx))
2770 }
2771 }
2772
2773 fn cached_ex_index<T>() -> Index<Ssl, T>
2775 where
2776 T: 'static + Sync + Send,
2777 {
2778 unsafe {
2779 let idx = *SSL_INDEXES
2780 .lock()
2781 .unwrap_or_else(|e| e.into_inner())
2782 .entry(TypeId::of::<T>())
2783 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2784 Index::from_raw(idx)
2785 }
2786 }
2787
2788 #[corresponds(SSL_new)]
2790 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2791 let session_ctx_index = try_get_session_ctx_index()?;
2792 unsafe {
2793 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2794 let mut ssl = Ssl::from_ptr(ptr);
2795 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2796
2797 Ok(ssl)
2798 }
2799 }
2800
2801 #[corresponds(SSL_connect)]
2807 #[allow(deprecated)]
2808 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2809 where
2810 S: Read + Write,
2811 {
2812 SslStreamBuilder::new(self, stream).connect()
2813 }
2814
2815 #[corresponds(SSL_accept)]
2822 #[allow(deprecated)]
2823 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2824 where
2825 S: Read + Write,
2826 {
2827 SslStreamBuilder::new(self, stream).accept()
2828 }
2829}
2830
2831impl fmt::Debug for SslRef {
2832 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2833 fmt.debug_struct("Ssl")
2834 .field("state", &self.state_string_long())
2835 .field("verify_result", &self.verify_result())
2836 .finish()
2837 }
2838}
2839
2840impl SslRef {
2841 #[cfg(not(feature = "tongsuo"))]
2842 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2843 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2844 }
2845
2846 #[cfg(feature = "tongsuo")]
2847 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2848 unsafe {
2849 let bio = ffi::SSL_get_rbio(self.as_ptr());
2850 bio::find_correct_bio(bio)
2851 }
2852 }
2853
2854 fn get_error(&self, ret: c_int) -> ErrorCode {
2855 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2856 }
2857
2858 #[corresponds(SSL_set_mode)]
2862 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2863 unsafe {
2864 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2865 SslMode::from_bits_retain(bits)
2866 }
2867 }
2868
2869 #[corresponds(SSL_clear_mode)]
2871 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2872 unsafe {
2873 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2874 SslMode::from_bits_retain(bits)
2875 }
2876 }
2877
2878 #[corresponds(SSL_get_mode)]
2880 pub fn mode(&self) -> SslMode {
2881 unsafe {
2882 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2883 SslMode::from_bits_retain(bits)
2884 }
2885 }
2886
2887 #[corresponds(SSL_set_connect_state)]
2889 pub fn set_connect_state(&mut self) {
2890 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2891 }
2892
2893 #[corresponds(SSL_set_accept_state)]
2895 pub fn set_accept_state(&mut self) {
2896 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2897 }
2898
2899 #[cfg(any(boringssl, awslc))]
2900 #[corresponds(SSL_ech_accepted)]
2901 pub fn ech_accepted(&self) -> bool {
2902 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2903 }
2904
2905 #[cfg(tongsuo)]
2906 #[corresponds(SSL_is_ntls)]
2907 pub fn is_ntls(&mut self) -> bool {
2908 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2909 }
2910
2911 #[cfg(tongsuo)]
2912 #[corresponds(SSL_enable_ntls)]
2913 pub fn enable_ntls(&mut self) {
2914 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2915 }
2916
2917 #[cfg(tongsuo)]
2918 #[corresponds(SSL_disable_ntls)]
2919 pub fn disable_ntls(&mut self) {
2920 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2921 }
2922
2923 #[cfg(all(tongsuo, ossl300))]
2924 #[corresponds(SSL_enable_force_ntls)]
2925 pub fn enable_force_ntls(&mut self) {
2926 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2927 }
2928
2929 #[cfg(all(tongsuo, ossl300))]
2930 #[corresponds(SSL_disable_force_ntls)]
2931 pub fn disable_force_ntls(&mut self) {
2932 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2933 }
2934
2935 #[cfg(tongsuo)]
2936 #[corresponds(SSL_enable_sm_tls13_strict)]
2937 pub fn enable_sm_tls13_strict(&mut self) {
2938 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2939 }
2940
2941 #[cfg(tongsuo)]
2942 #[corresponds(SSL_disable_sm_tls13_strict)]
2943 pub fn disable_sm_tls13_strict(&mut self) {
2944 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2945 }
2946
2947 #[corresponds(SSL_set_verify)]
2951 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2952 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2953 }
2954
2955 #[corresponds(SSL_set_verify_mode)]
2957 pub fn verify_mode(&self) -> SslVerifyMode {
2958 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2959 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2960 }
2961
2962 #[corresponds(SSL_set_verify)]
2966 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2967 where
2968 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2969 {
2970 unsafe {
2971 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2973 ffi::SSL_set_verify(
2974 self.as_ptr(),
2975 mode.bits() as c_int,
2976 Some(ssl_raw_verify::<F>),
2977 );
2978 }
2979 }
2980
2981 #[corresponds(SSL_set_info_callback)]
2984 pub fn set_info_callback<F>(&mut self, callback: F)
2985 where
2986 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2987 {
2988 unsafe {
2989 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2991 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
2992 }
2993 }
2994
2995 #[corresponds(SSL_set_dh_auto)]
2999 #[cfg(ossl300)]
3000 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3001 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
3002 }
3003
3004 #[corresponds(SSL_set_tmp_dh)]
3008 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3009 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3010 }
3011
3012 #[corresponds(SSL_set_tmp_dh_callback)]
3016 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3017 where
3018 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3019 {
3020 unsafe {
3021 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3023 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3024 }
3025 }
3026
3027 #[corresponds(SSL_set_tmp_ecdh)]
3031 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3032 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3033 }
3034
3035 #[corresponds(SSL_set_ecdh_auto)]
3041 #[cfg(any(all(ossl102, not(ossl110)), libressl))]
3042 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3043 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
3044 }
3045
3046 #[corresponds(SSL_set_alpn_protos)]
3052 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3053 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3054 unsafe {
3055 assert!(protocols.len() <= c_uint::MAX as usize);
3056 let r =
3057 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3058 if r == 0 {
3060 Ok(())
3061 } else {
3062 Err(ErrorStack::get())
3063 }
3064 }
3065 }
3066
3067 #[corresponds(SSL_get_current_cipher)]
3069 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3070 unsafe {
3071 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3072
3073 SslCipherRef::from_const_ptr_opt(ptr)
3074 }
3075 }
3076
3077 #[corresponds(SSL_state_string)]
3079 pub fn state_string(&self) -> &'static str {
3080 let state = unsafe {
3081 let ptr = ffi::SSL_state_string(self.as_ptr());
3082 CStr::from_ptr(ptr as *const _)
3083 };
3084
3085 str::from_utf8(state.to_bytes()).unwrap()
3086 }
3087
3088 #[corresponds(SSL_state_string_long)]
3090 pub fn state_string_long(&self) -> &'static str {
3091 let state = unsafe {
3092 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3093 CStr::from_ptr(ptr as *const _)
3094 };
3095
3096 str::from_utf8(state.to_bytes()).unwrap()
3097 }
3098
3099 #[corresponds(SSL_set_tlsext_host_name)]
3103 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3104 let cstr = CString::new(hostname).unwrap();
3105 unsafe {
3106 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3107 .map(|_| ())
3108 }
3109 }
3110
3111 #[corresponds(SSL_get_peer_certificate)]
3113 pub fn peer_certificate(&self) -> Option<X509> {
3114 unsafe {
3115 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3116 X509::from_ptr_opt(ptr)
3117 }
3118 }
3119
3120 #[corresponds(SSL_get_peer_cert_chain)]
3125 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3126 unsafe {
3127 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3128 StackRef::from_const_ptr_opt(ptr)
3129 }
3130 }
3131
3132 #[corresponds(SSL_get0_verified_chain)]
3142 #[cfg(ossl110)]
3143 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3144 unsafe {
3145 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3146 StackRef::from_const_ptr_opt(ptr)
3147 }
3148 }
3149
3150 #[corresponds(SSL_get_certificate)]
3152 pub fn certificate(&self) -> Option<&X509Ref> {
3153 unsafe {
3154 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3155 X509Ref::from_const_ptr_opt(ptr)
3156 }
3157 }
3158
3159 #[corresponds(SSL_get_privatekey)]
3163 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3164 unsafe {
3165 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3166 PKeyRef::from_const_ptr_opt(ptr)
3167 }
3168 }
3169
3170 #[corresponds(SSL_version)]
3172 pub fn version2(&self) -> Option<SslVersion> {
3173 unsafe {
3174 let r = ffi::SSL_version(self.as_ptr());
3175 if r == 0 {
3176 None
3177 } else {
3178 Some(SslVersion(r))
3179 }
3180 }
3181 }
3182
3183 #[corresponds(SSL_get_version)]
3185 pub fn version_str(&self) -> &'static str {
3186 let version = unsafe {
3187 let ptr = ffi::SSL_get_version(self.as_ptr());
3188 CStr::from_ptr(ptr as *const _)
3189 };
3190
3191 str::from_utf8(version.to_bytes()).unwrap()
3192 }
3193
3194 #[corresponds(SSL_get0_alpn_selected)]
3201 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3202 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3203 unsafe {
3204 let mut data: *const c_uchar = ptr::null();
3205 let mut len: c_uint = 0;
3206 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3209
3210 if data.is_null() {
3211 None
3212 } else {
3213 Some(util::from_raw_parts(data, len as usize))
3214 }
3215 }
3216 }
3217
3218 #[corresponds(SSL_set_tlsext_use_srtp)]
3220 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3221 unsafe {
3222 let cstr = CString::new(protocols).unwrap();
3223
3224 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3225 if r == 0 {
3227 Ok(())
3228 } else {
3229 Err(ErrorStack::get())
3230 }
3231 }
3232 }
3233
3234 #[corresponds(SSL_get_srtp_profiles)]
3238 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3239 unsafe {
3240 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3241
3242 StackRef::from_const_ptr_opt(chain)
3243 }
3244 }
3245
3246 #[corresponds(SSL_get_selected_srtp_profile)]
3250 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3251 unsafe {
3252 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3253
3254 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3255 }
3256 }
3257
3258 #[corresponds(SSL_pending)]
3263 pub fn pending(&self) -> usize {
3264 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3265 }
3266
3267 #[corresponds(SSL_get_servername)]
3280 pub fn servername(&self, type_: NameType) -> Option<&str> {
3282 self.servername_raw(type_)
3283 .and_then(|b| str::from_utf8(b).ok())
3284 }
3285
3286 #[corresponds(SSL_get_servername)]
3294 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3295 unsafe {
3296 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3297 if name.is_null() {
3298 None
3299 } else {
3300 Some(CStr::from_ptr(name as *const _).to_bytes())
3301 }
3302 }
3303 }
3304
3305 #[corresponds(SSL_set_SSL_CTX)]
3309 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3310 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3311 }
3312
3313 #[corresponds(SSL_get_SSL_CTX)]
3315 pub fn ssl_context(&self) -> &SslContextRef {
3316 unsafe {
3317 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3318 SslContextRef::from_ptr(ssl_ctx)
3319 }
3320 }
3321
3322 #[corresponds(SSL_get0_param)]
3326 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
3327 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3328 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3329 }
3330
3331 #[corresponds(SSL_get_verify_result)]
3333 pub fn verify_result(&self) -> X509VerifyResult {
3334 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3335 }
3336
3337 #[corresponds(SSL_get_session)]
3339 pub fn session(&self) -> Option<&SslSessionRef> {
3340 unsafe {
3341 let p = ffi::SSL_get_session(self.as_ptr());
3342 SslSessionRef::from_const_ptr_opt(p)
3343 }
3344 }
3345
3346 #[corresponds(SSL_get_client_random)]
3353 #[cfg(any(ossl110, libressl270))]
3354 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3355 unsafe {
3356 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3357 }
3358 }
3359
3360 #[corresponds(SSL_get_server_random)]
3367 #[cfg(any(ossl110, libressl270))]
3368 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3369 unsafe {
3370 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3371 }
3372 }
3373
3374 #[corresponds(SSL_export_keying_material)]
3376 pub fn export_keying_material(
3377 &self,
3378 out: &mut [u8],
3379 label: &str,
3380 context: Option<&[u8]>,
3381 ) -> Result<(), ErrorStack> {
3382 unsafe {
3383 let (context, contextlen, use_context) = match context {
3384 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3385 None => (ptr::null(), 0, 0),
3386 };
3387 cvt(ffi::SSL_export_keying_material(
3388 self.as_ptr(),
3389 out.as_mut_ptr() as *mut c_uchar,
3390 out.len(),
3391 label.as_ptr() as *const c_char,
3392 label.len(),
3393 context,
3394 contextlen,
3395 use_context,
3396 ))
3397 .map(|_| ())
3398 }
3399 }
3400
3401 #[corresponds(SSL_export_keying_material_early)]
3408 #[cfg(ossl111)]
3409 pub fn export_keying_material_early(
3410 &self,
3411 out: &mut [u8],
3412 label: &str,
3413 context: &[u8],
3414 ) -> Result<(), ErrorStack> {
3415 unsafe {
3416 cvt(ffi::SSL_export_keying_material_early(
3417 self.as_ptr(),
3418 out.as_mut_ptr() as *mut c_uchar,
3419 out.len(),
3420 label.as_ptr() as *const c_char,
3421 label.len(),
3422 context.as_ptr() as *const c_uchar,
3423 context.len(),
3424 ))
3425 .map(|_| ())
3426 }
3427 }
3428
3429 #[corresponds(SSL_set_session)]
3440 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3441 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3442 }
3443
3444 #[corresponds(SSL_session_reused)]
3446 pub fn session_reused(&self) -> bool {
3447 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3448 }
3449
3450 #[cfg(any(boringssl, awslc))]
3458 pub fn enable_ocsp_stapling(&mut self) {
3459 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3460 }
3461
3462 #[cfg(any(boringssl, awslc))]
3470 pub fn enable_signed_cert_timestamps(&mut self) {
3471 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3472 }
3473
3474 #[cfg(any(boringssl, awslc))]
3482 pub fn set_permute_extensions(&mut self, enabled: bool) {
3483 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3484 }
3485
3486 #[corresponds(SSL_enable_ct)]
3488 #[cfg(ossl111)]
3489 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3490 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3491 }
3492
3493 #[corresponds(SSL_ct_is_enabled)]
3495 #[cfg(ossl111)]
3496 pub fn ct_is_enabled(&self) -> bool {
3497 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3498 }
3499
3500 #[corresponds(SSL_set_tlsext_status_type)]
3502 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3503 unsafe {
3504 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3505 }
3506 }
3507
3508 #[corresponds(SSL_get_extms_support)]
3512 #[cfg(ossl110)]
3513 pub fn extms_support(&self) -> Option<bool> {
3514 unsafe {
3515 match ffi::SSL_get_extms_support(self.as_ptr()) {
3516 -1 => None,
3517 ret => Some(ret != 0),
3518 }
3519 }
3520 }
3521
3522 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3524 #[cfg(not(any(boringssl, awslc)))]
3525 pub fn ocsp_status(&self) -> Option<&[u8]> {
3526 unsafe {
3527 let mut p = ptr::null_mut();
3528 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3529
3530 if len < 0 {
3531 None
3532 } else {
3533 Some(util::from_raw_parts(p as *const u8, len as usize))
3534 }
3535 }
3536 }
3537
3538 #[corresponds(SSL_get0_ocsp_response)]
3540 #[cfg(any(boringssl, awslc))]
3541 pub fn ocsp_status(&self) -> Option<&[u8]> {
3542 unsafe {
3543 let mut p = ptr::null();
3544 let mut len: usize = 0;
3545 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3546
3547 if len == 0 {
3548 None
3549 } else {
3550 Some(util::from_raw_parts(p as *const u8, len))
3551 }
3552 }
3553 }
3554
3555 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3557 #[cfg(not(any(boringssl, awslc)))]
3558 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3559 unsafe {
3560 assert!(response.len() <= c_int::MAX as usize);
3561 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3562 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3563 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3564 self.as_ptr(),
3565 p as *mut c_uchar,
3566 response.len() as c_long,
3567 ) as c_int)
3568 .map(|_| ())
3569 .map_err(|e| {
3570 ffi::OPENSSL_free(p);
3571 e
3572 })
3573 }
3574 }
3575
3576 #[corresponds(SSL_set_ocsp_response)]
3578 #[cfg(any(boringssl, awslc))]
3579 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3580 unsafe {
3581 cvt(ffi::SSL_set_ocsp_response(
3582 self.as_ptr(),
3583 response.as_ptr(),
3584 response.len(),
3585 ))
3586 .map(|_| ())
3587 }
3588 }
3589
3590 #[corresponds(SSL_is_server)]
3592 pub fn is_server(&self) -> bool {
3593 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3594 }
3595
3596 #[corresponds(SSL_set_ex_data)]
3602 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3603 match self.ex_data_mut(index) {
3604 Some(v) => *v = data,
3605 None => unsafe {
3606 let data = Box::new(data);
3607 ffi::SSL_set_ex_data(
3608 self.as_ptr(),
3609 index.as_raw(),
3610 Box::into_raw(data) as *mut c_void,
3611 );
3612 },
3613 }
3614 }
3615
3616 #[corresponds(SSL_get_ex_data)]
3618 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3619 unsafe {
3620 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3621 if data.is_null() {
3622 None
3623 } else {
3624 Some(&*(data as *const T))
3625 }
3626 }
3627 }
3628
3629 #[corresponds(SSL_get_ex_data)]
3631 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3632 unsafe {
3633 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3634 if data.is_null() {
3635 None
3636 } else {
3637 Some(&mut *(data as *mut T))
3638 }
3639 }
3640 }
3641
3642 #[corresponds(SSL_set_max_early_data)]
3646 #[cfg(any(ossl111, libressl340))]
3647 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3648 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3649 Ok(())
3650 } else {
3651 Err(ErrorStack::get())
3652 }
3653 }
3654
3655 #[corresponds(SSL_get_max_early_data)]
3659 #[cfg(any(ossl111, libressl340))]
3660 pub fn max_early_data(&self) -> u32 {
3661 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3662 }
3663
3664 #[corresponds(SSL_get_finished)]
3669 pub fn finished(&self, buf: &mut [u8]) -> usize {
3670 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3671 }
3672
3673 #[corresponds(SSL_get_peer_finished)]
3679 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3680 unsafe {
3681 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3682 }
3683 }
3684
3685 #[corresponds(SSL_is_init_finished)]
3687 #[cfg(ossl110)]
3688 pub fn is_init_finished(&self) -> bool {
3689 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3690 }
3691
3692 #[corresponds(SSL_client_hello_isv2)]
3698 #[cfg(ossl111)]
3699 pub fn client_hello_isv2(&self) -> bool {
3700 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3701 }
3702
3703 #[corresponds(SSL_client_hello_get0_legacy_version)]
3709 #[cfg(ossl111)]
3710 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3711 unsafe {
3712 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3713 if version == 0 {
3714 None
3715 } else {
3716 Some(SslVersion(version as c_int))
3717 }
3718 }
3719 }
3720
3721 #[corresponds(SSL_client_hello_get0_random)]
3727 #[cfg(ossl111)]
3728 pub fn client_hello_random(&self) -> Option<&[u8]> {
3729 unsafe {
3730 let mut ptr = ptr::null();
3731 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3732 if len == 0 {
3733 None
3734 } else {
3735 Some(util::from_raw_parts(ptr, len))
3736 }
3737 }
3738 }
3739
3740 #[corresponds(SSL_client_hello_get0_session_id)]
3746 #[cfg(ossl111)]
3747 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3748 unsafe {
3749 let mut ptr = ptr::null();
3750 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3751 if len == 0 {
3752 None
3753 } else {
3754 Some(util::from_raw_parts(ptr, len))
3755 }
3756 }
3757 }
3758
3759 #[corresponds(SSL_client_hello_get0_ciphers)]
3765 #[cfg(ossl111)]
3766 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3767 unsafe {
3768 let mut ptr = ptr::null();
3769 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3770 if len == 0 {
3771 None
3772 } else {
3773 Some(util::from_raw_parts(ptr, len))
3774 }
3775 }
3776 }
3777
3778 #[cfg(ossl111)]
3784 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3785 unsafe {
3786 let mut ptr = ptr::null();
3787 let mut len = 0usize;
3788 let r = ffi::SSL_client_hello_get0_ext(
3789 self.as_ptr(),
3790 ext_type.as_raw() as _,
3791 &mut ptr,
3792 &mut len,
3793 );
3794 if r == 0 {
3795 None
3796 } else {
3797 Some(util::from_raw_parts(ptr, len))
3798 }
3799 }
3800 }
3801
3802 #[corresponds(SSL_bytes_to_cipher_list)]
3807 #[cfg(ossl111)]
3808 pub fn bytes_to_cipher_list(
3809 &self,
3810 bytes: &[u8],
3811 isv2format: bool,
3812 ) -> Result<CipherLists, ErrorStack> {
3813 unsafe {
3814 let ptr = bytes.as_ptr();
3815 let len = bytes.len();
3816 let mut sk = ptr::null_mut();
3817 let mut scsvs = ptr::null_mut();
3818 let res = ffi::SSL_bytes_to_cipher_list(
3819 self.as_ptr(),
3820 ptr,
3821 len,
3822 isv2format as c_int,
3823 &mut sk,
3824 &mut scsvs,
3825 );
3826 if res == 1 {
3827 Ok(CipherLists {
3828 suites: Stack::from_ptr(sk),
3829 signalling_suites: Stack::from_ptr(scsvs),
3830 })
3831 } else {
3832 Err(ErrorStack::get())
3833 }
3834 }
3835 }
3836
3837 #[corresponds(SSL_client_hello_get0_compression_methods)]
3843 #[cfg(ossl111)]
3844 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3845 unsafe {
3846 let mut ptr = ptr::null();
3847 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3848 if len == 0 {
3849 None
3850 } else {
3851 Some(util::from_raw_parts(ptr, len))
3852 }
3853 }
3854 }
3855
3856 #[corresponds(SSL_set_mtu)]
3858 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3859 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3860 }
3861
3862 #[corresponds(SSL_get_psk_identity_hint)]
3866 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3867 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3868 unsafe {
3869 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3870 if ptr.is_null() {
3871 None
3872 } else {
3873 Some(CStr::from_ptr(ptr).to_bytes())
3874 }
3875 }
3876 }
3877
3878 #[corresponds(SSL_get_psk_identity)]
3880 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3881 pub fn psk_identity(&self) -> Option<&[u8]> {
3882 unsafe {
3883 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3884 if ptr.is_null() {
3885 None
3886 } else {
3887 Some(CStr::from_ptr(ptr).to_bytes())
3888 }
3889 }
3890 }
3891
3892 #[corresponds(SSL_add0_chain_cert)]
3893 #[cfg(any(ossl102, boringssl, awslc))]
3894 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3895 unsafe {
3896 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3897 mem::forget(chain);
3898 }
3899 Ok(())
3900 }
3901
3902 #[cfg(not(any(boringssl, awslc)))]
3904 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3905 unsafe {
3906 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3907 };
3908 Ok(())
3909 }
3910
3911 #[corresponds(SSL_use_Private_Key_file)]
3913 pub fn set_private_key_file<P: AsRef<Path>>(
3914 &mut self,
3915 path: P,
3916 ssl_file_type: SslFiletype,
3917 ) -> Result<(), ErrorStack> {
3918 let p = path.as_ref().as_os_str().to_str().unwrap();
3919 let key_file = CString::new(p).unwrap();
3920 unsafe {
3921 cvt(ffi::SSL_use_PrivateKey_file(
3922 self.as_ptr(),
3923 key_file.as_ptr(),
3924 ssl_file_type.as_raw(),
3925 ))?;
3926 };
3927 Ok(())
3928 }
3929
3930 #[corresponds(SSL_use_PrivateKey)]
3932 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3933 unsafe {
3934 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3935 };
3936 Ok(())
3937 }
3938
3939 #[cfg(tongsuo)]
3940 #[corresponds(SSL_use_enc_Private_Key_file)]
3941 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3942 &mut self,
3943 path: P,
3944 ssl_file_type: SslFiletype,
3945 ) -> Result<(), ErrorStack> {
3946 let p = path.as_ref().as_os_str().to_str().unwrap();
3947 let key_file = CString::new(p).unwrap();
3948 unsafe {
3949 cvt(ffi::SSL_use_enc_PrivateKey_file(
3950 self.as_ptr(),
3951 key_file.as_ptr(),
3952 ssl_file_type.as_raw(),
3953 ))?;
3954 };
3955 Ok(())
3956 }
3957
3958 #[cfg(tongsuo)]
3959 #[corresponds(SSL_use_enc_PrivateKey)]
3960 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3961 unsafe {
3962 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3963 };
3964 Ok(())
3965 }
3966
3967 #[cfg(tongsuo)]
3968 #[corresponds(SSL_use_sign_Private_Key_file)]
3969 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3970 &mut self,
3971 path: P,
3972 ssl_file_type: SslFiletype,
3973 ) -> Result<(), ErrorStack> {
3974 let p = path.as_ref().as_os_str().to_str().unwrap();
3975 let key_file = CString::new(p).unwrap();
3976 unsafe {
3977 cvt(ffi::SSL_use_sign_PrivateKey_file(
3978 self.as_ptr(),
3979 key_file.as_ptr(),
3980 ssl_file_type.as_raw(),
3981 ))?;
3982 };
3983 Ok(())
3984 }
3985
3986 #[cfg(tongsuo)]
3987 #[corresponds(SSL_use_sign_PrivateKey)]
3988 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3989 unsafe {
3990 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3991 };
3992 Ok(())
3993 }
3994
3995 #[corresponds(SSL_use_certificate)]
3997 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3998 unsafe {
3999 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4000 };
4001 Ok(())
4002 }
4003
4004 #[cfg(tongsuo)]
4005 #[corresponds(SSL_use_enc_certificate)]
4006 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4007 unsafe {
4008 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4009 };
4010 Ok(())
4011 }
4012
4013 #[cfg(tongsuo)]
4014 #[corresponds(SSL_use_sign_certificate)]
4015 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4016 unsafe {
4017 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4018 };
4019 Ok(())
4020 }
4021
4022 #[corresponds(SSL_use_certificate_chain_file)]
4028 #[cfg(any(ossl110, libressl332))]
4029 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4030 &mut self,
4031 path: P,
4032 ) -> Result<(), ErrorStack> {
4033 let p = path.as_ref().as_os_str().to_str().unwrap();
4034 let cert_file = CString::new(p).unwrap();
4035 unsafe {
4036 cvt(ffi::SSL_use_certificate_chain_file(
4037 self.as_ptr(),
4038 cert_file.as_ptr(),
4039 ))?;
4040 };
4041 Ok(())
4042 }
4043
4044 #[corresponds(SSL_add_client_CA)]
4046 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4047 unsafe {
4048 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4049 };
4050 Ok(())
4051 }
4052
4053 #[corresponds(SSL_set_client_CA_list)]
4055 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4056 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4057 mem::forget(list);
4058 }
4059
4060 #[corresponds(SSL_set_min_proto_version)]
4067 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4068 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4069 unsafe {
4070 cvt(ffi::SSL_set_min_proto_version(
4071 self.as_ptr(),
4072 version.map_or(0, |v| v.0 as _),
4073 ))
4074 .map(|_| ())
4075 }
4076 }
4077
4078 #[corresponds(SSL_set_max_proto_version)]
4085 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4086 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4087 unsafe {
4088 cvt(ffi::SSL_set_max_proto_version(
4089 self.as_ptr(),
4090 version.map_or(0, |v| v.0 as _),
4091 ))
4092 .map(|_| ())
4093 }
4094 }
4095
4096 #[corresponds(SSL_set_ciphersuites)]
4105 #[cfg(any(ossl111, libressl340))]
4106 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4107 let cipher_list = CString::new(cipher_list).unwrap();
4108 unsafe {
4109 cvt(ffi::SSL_set_ciphersuites(
4110 self.as_ptr(),
4111 cipher_list.as_ptr() as *const _,
4112 ))
4113 .map(|_| ())
4114 }
4115 }
4116
4117 #[corresponds(SSL_set_cipher_list)]
4125 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4126 let cipher_list = CString::new(cipher_list).unwrap();
4127 unsafe {
4128 cvt(ffi::SSL_set_cipher_list(
4129 self.as_ptr(),
4130 cipher_list.as_ptr() as *const _,
4131 ))
4132 .map(|_| ())
4133 }
4134 }
4135
4136 #[corresponds(SSL_set_cert_store)]
4138 #[cfg(any(ossl102, boringssl, awslc))]
4139 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4140 unsafe {
4141 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4142 mem::forget(cert_store);
4143 Ok(())
4144 }
4145 }
4146
4147 #[corresponds(SSL_set_num_tickets)]
4152 #[cfg(ossl111)]
4153 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4154 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4155 }
4156
4157 #[corresponds(SSL_get_num_tickets)]
4162 #[cfg(ossl111)]
4163 pub fn num_tickets(&self) -> usize {
4164 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4165 }
4166
4167 #[corresponds(SSL_set_security_level)]
4172 #[cfg(any(ossl110, libressl360))]
4173 pub fn set_security_level(&mut self, level: u32) {
4174 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4175 }
4176
4177 #[corresponds(SSL_get_security_level)]
4182 #[cfg(any(ossl110, libressl360))]
4183 pub fn security_level(&self) -> u32 {
4184 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4185 }
4186
4187 #[corresponds(SSL_get_peer_tmp_key)]
4192 #[cfg(ossl300)]
4193 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4194 unsafe {
4195 let mut key = ptr::null_mut();
4196 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4197 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4198 Err(e) => Err(e),
4199 }
4200 }
4201 }
4202
4203 #[corresponds(SSL_get_tmp_key)]
4208 #[cfg(ossl300)]
4209 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4210 unsafe {
4211 let mut key = ptr::null_mut();
4212 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4213 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4214 Err(e) => Err(e),
4215 }
4216 }
4217 }
4218}
4219
4220#[derive(Debug)]
4222pub struct MidHandshakeSslStream<S> {
4223 stream: SslStream<S>,
4224 error: Error,
4225}
4226
4227impl<S> MidHandshakeSslStream<S> {
4228 pub fn get_ref(&self) -> &S {
4230 self.stream.get_ref()
4231 }
4232
4233 pub fn get_mut(&mut self) -> &mut S {
4235 self.stream.get_mut()
4236 }
4237
4238 pub fn ssl(&self) -> &SslRef {
4240 self.stream.ssl()
4241 }
4242
4243 pub fn ssl_mut(&mut self) -> &mut SslRef {
4245 self.stream.ssl_mut()
4246 }
4247
4248 pub fn error(&self) -> &Error {
4250 &self.error
4251 }
4252
4253 pub fn into_error(self) -> Error {
4255 self.error
4256 }
4257}
4258
4259impl<S> MidHandshakeSslStream<S>
4260where
4261 S: Read + Write,
4262{
4263 #[corresponds(SSL_do_handshake)]
4266 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4267 match self.stream.do_handshake() {
4268 Ok(()) => Ok(self.stream),
4269 Err(error) => {
4270 self.error = error;
4271 match self.error.code() {
4272 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4273 Err(HandshakeError::WouldBlock(self))
4274 }
4275 _ => Err(HandshakeError::Failure(self)),
4276 }
4277 }
4278 }
4279 }
4280}
4281
4282pub struct SslStream<S> {
4284 ssl: ManuallyDrop<Ssl>,
4285 method: ManuallyDrop<BioMethod>,
4286 _p: PhantomData<S>,
4287}
4288
4289impl<S> Drop for SslStream<S> {
4290 fn drop(&mut self) {
4291 unsafe {
4293 ManuallyDrop::drop(&mut self.ssl);
4294 ManuallyDrop::drop(&mut self.method);
4295 }
4296 }
4297}
4298
4299impl<S> fmt::Debug for SslStream<S>
4300where
4301 S: fmt::Debug,
4302{
4303 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4304 fmt.debug_struct("SslStream")
4305 .field("stream", &self.get_ref())
4306 .field("ssl", &self.ssl())
4307 .finish()
4308 }
4309}
4310
4311impl<S: Read + Write> SslStream<S> {
4312 #[corresponds(SSL_set_bio)]
4320 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4321 let (bio, method) = bio::new(stream)?;
4322 unsafe {
4323 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4324 }
4325
4326 Ok(SslStream {
4327 ssl: ManuallyDrop::new(ssl),
4328 method: ManuallyDrop::new(method),
4329 _p: PhantomData,
4330 })
4331 }
4332
4333 #[corresponds(SSL_read_early_data)]
4342 #[cfg(any(ossl111, libressl340))]
4343 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4344 let mut read = 0;
4345 let ret = unsafe {
4346 ffi::SSL_read_early_data(
4347 self.ssl.as_ptr(),
4348 buf.as_ptr() as *mut c_void,
4349 buf.len(),
4350 &mut read,
4351 )
4352 };
4353 match ret {
4354 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4355 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4356 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4357 _ => unreachable!(),
4358 }
4359 }
4360
4361 #[corresponds(SSL_write_early_data)]
4368 #[cfg(any(ossl111, libressl340))]
4369 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4370 let mut written = 0;
4371 let ret = unsafe {
4372 ffi::SSL_write_early_data(
4373 self.ssl.as_ptr(),
4374 buf.as_ptr() as *const c_void,
4375 buf.len(),
4376 &mut written,
4377 )
4378 };
4379 if ret > 0 {
4380 Ok(written)
4381 } else {
4382 Err(self.make_error(ret))
4383 }
4384 }
4385
4386 #[corresponds(SSL_connect)]
4393 pub fn connect(&mut self) -> Result<(), Error> {
4394 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4395 if ret > 0 {
4396 Ok(())
4397 } else {
4398 Err(self.make_error(ret))
4399 }
4400 }
4401
4402 #[corresponds(SSL_accept)]
4409 pub fn accept(&mut self) -> Result<(), Error> {
4410 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4411 if ret > 0 {
4412 Ok(())
4413 } else {
4414 Err(self.make_error(ret))
4415 }
4416 }
4417
4418 #[corresponds(SSL_do_handshake)]
4422 pub fn do_handshake(&mut self) -> Result<(), Error> {
4423 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4424 if ret > 0 {
4425 Ok(())
4426 } else {
4427 Err(self.make_error(ret))
4428 }
4429 }
4430
4431 #[corresponds(SSL_stateless)]
4442 #[cfg(ossl111)]
4443 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4444 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4445 1 => Ok(true),
4446 0 => Ok(false),
4447 -1 => Err(ErrorStack::get()),
4448 _ => unreachable!(),
4449 }
4450 }
4451
4452 #[corresponds(SSL_read_ex)]
4459 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4460 loop {
4461 match self.ssl_read_uninit(buf) {
4462 Ok(n) => return Ok(n),
4463 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4464 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4465 return Ok(0);
4466 }
4467 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4468 Err(e) => {
4469 return Err(e
4470 .into_io_error()
4471 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4472 }
4473 }
4474 }
4475 }
4476
4477 #[corresponds(SSL_read_ex)]
4482 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4483 unsafe {
4485 self.ssl_read_uninit(util::from_raw_parts_mut(
4486 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4487 buf.len(),
4488 ))
4489 }
4490 }
4491
4492 #[corresponds(SSL_read_ex)]
4499 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4500 cfg_if! {
4501 if #[cfg(any(ossl111, libressl350))] {
4502 let mut readbytes = 0;
4503 let ret = unsafe {
4504 ffi::SSL_read_ex(
4505 self.ssl().as_ptr(),
4506 buf.as_mut_ptr().cast(),
4507 buf.len(),
4508 &mut readbytes,
4509 )
4510 };
4511
4512 if ret > 0 {
4513 Ok(readbytes)
4514 } else {
4515 Err(self.make_error(ret))
4516 }
4517 } else {
4518 if buf.is_empty() {
4519 return Ok(0);
4520 }
4521
4522 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4523 let ret = unsafe {
4524 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4525 };
4526 if ret > 0 {
4527 Ok(ret as usize)
4528 } else {
4529 Err(self.make_error(ret))
4530 }
4531 }
4532 }
4533 }
4534
4535 #[corresponds(SSL_write_ex)]
4540 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4541 cfg_if! {
4542 if #[cfg(any(ossl111, libressl350))] {
4543 let mut written = 0;
4544 let ret = unsafe {
4545 ffi::SSL_write_ex(
4546 self.ssl().as_ptr(),
4547 buf.as_ptr().cast(),
4548 buf.len(),
4549 &mut written,
4550 )
4551 };
4552
4553 if ret > 0 {
4554 Ok(written)
4555 } else {
4556 Err(self.make_error(ret))
4557 }
4558 } else {
4559 if buf.is_empty() {
4560 return Ok(0);
4561 }
4562
4563 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4564 let ret = unsafe {
4565 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4566 };
4567 if ret > 0 {
4568 Ok(ret as usize)
4569 } else {
4570 Err(self.make_error(ret))
4571 }
4572 }
4573 }
4574 }
4575
4576 #[corresponds(SSL_peek_ex)]
4578 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4579 cfg_if! {
4580 if #[cfg(any(ossl111, libressl350))] {
4581 let mut readbytes = 0;
4582 let ret = unsafe {
4583 ffi::SSL_peek_ex(
4584 self.ssl().as_ptr(),
4585 buf.as_mut_ptr().cast(),
4586 buf.len(),
4587 &mut readbytes,
4588 )
4589 };
4590
4591 if ret > 0 {
4592 Ok(readbytes)
4593 } else {
4594 Err(self.make_error(ret))
4595 }
4596 } else {
4597 if buf.is_empty() {
4598 return Ok(0);
4599 }
4600
4601 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4602 let ret = unsafe {
4603 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4604 };
4605 if ret > 0 {
4606 Ok(ret as usize)
4607 } else {
4608 Err(self.make_error(ret))
4609 }
4610 }
4611 }
4612 }
4613
4614 #[corresponds(SSL_shutdown)]
4624 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4625 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4626 0 => Ok(ShutdownResult::Sent),
4627 1 => Ok(ShutdownResult::Received),
4628 n => Err(self.make_error(n)),
4629 }
4630 }
4631
4632 #[corresponds(SSL_get_shutdown)]
4634 pub fn get_shutdown(&mut self) -> ShutdownState {
4635 unsafe {
4636 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4637 ShutdownState::from_bits_retain(bits)
4638 }
4639 }
4640
4641 #[corresponds(SSL_set_shutdown)]
4646 pub fn set_shutdown(&mut self, state: ShutdownState) {
4647 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4648 }
4649}
4650
4651impl<S> SslStream<S> {
4652 fn make_error(&mut self, ret: c_int) -> Error {
4653 self.check_panic();
4654
4655 let code = self.ssl.get_error(ret);
4656
4657 let cause = match code {
4658 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4659 ErrorCode::SYSCALL => {
4660 let errs = ErrorStack::get();
4661 if errs.errors().is_empty() {
4662 self.get_bio_error().map(InnerError::Io)
4663 } else {
4664 Some(InnerError::Ssl(errs))
4665 }
4666 }
4667 ErrorCode::ZERO_RETURN => None,
4668 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4669 self.get_bio_error().map(InnerError::Io)
4670 }
4671 _ => None,
4672 };
4673
4674 Error { code, cause }
4675 }
4676
4677 fn check_panic(&mut self) {
4678 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4679 resume_unwind(err)
4680 }
4681 }
4682
4683 fn get_bio_error(&mut self) -> Option<io::Error> {
4684 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4685 }
4686
4687 pub fn get_ref(&self) -> &S {
4689 unsafe {
4690 let bio = self.ssl.get_raw_rbio();
4691 bio::get_ref(bio)
4692 }
4693 }
4694
4695 pub fn get_mut(&mut self) -> &mut S {
4702 unsafe {
4703 let bio = self.ssl.get_raw_rbio();
4704 bio::get_mut(bio)
4705 }
4706 }
4707
4708 pub fn ssl(&self) -> &SslRef {
4710 &self.ssl
4711 }
4712
4713 pub fn ssl_mut(&mut self) -> &mut SslRef {
4715 &mut self.ssl
4716 }
4717}
4718
4719impl<S: Read + Write> Read for SslStream<S> {
4720 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4721 unsafe {
4723 self.read_uninit(util::from_raw_parts_mut(
4724 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4725 buf.len(),
4726 ))
4727 }
4728 }
4729}
4730
4731impl<S: Read + Write> Write for SslStream<S> {
4732 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4733 loop {
4734 match self.ssl_write(buf) {
4735 Ok(n) => return Ok(n),
4736 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4737 Err(e) => {
4738 return Err(e
4739 .into_io_error()
4740 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4741 }
4742 }
4743 }
4744 }
4745
4746 fn flush(&mut self) -> io::Result<()> {
4747 self.get_mut().flush()
4748 }
4749}
4750
4751#[deprecated(
4753 since = "0.10.32",
4754 note = "use the methods directly on Ssl/SslStream instead"
4755)]
4756pub struct SslStreamBuilder<S> {
4757 inner: SslStream<S>,
4758}
4759
4760#[allow(deprecated)]
4761impl<S> SslStreamBuilder<S>
4762where
4763 S: Read + Write,
4764{
4765 pub fn new(ssl: Ssl, stream: S) -> Self {
4767 Self {
4768 inner: SslStream::new(ssl, stream).unwrap(),
4769 }
4770 }
4771
4772 #[corresponds(SSL_stateless)]
4783 #[cfg(ossl111)]
4784 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4785 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4786 1 => Ok(true),
4787 0 => Ok(false),
4788 -1 => Err(ErrorStack::get()),
4789 _ => unreachable!(),
4790 }
4791 }
4792
4793 #[corresponds(SSL_set_connect_state)]
4795 pub fn set_connect_state(&mut self) {
4796 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4797 }
4798
4799 #[corresponds(SSL_set_accept_state)]
4801 pub fn set_accept_state(&mut self) {
4802 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4803 }
4804
4805 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4807 match self.inner.connect() {
4808 Ok(()) => Ok(self.inner),
4809 Err(error) => match error.code() {
4810 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4811 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4812 stream: self.inner,
4813 error,
4814 }))
4815 }
4816 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4817 stream: self.inner,
4818 error,
4819 })),
4820 },
4821 }
4822 }
4823
4824 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4826 match self.inner.accept() {
4827 Ok(()) => Ok(self.inner),
4828 Err(error) => match error.code() {
4829 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4830 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4831 stream: self.inner,
4832 error,
4833 }))
4834 }
4835 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4836 stream: self.inner,
4837 error,
4838 })),
4839 },
4840 }
4841 }
4842
4843 #[corresponds(SSL_do_handshake)]
4847 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4848 match self.inner.do_handshake() {
4849 Ok(()) => Ok(self.inner),
4850 Err(error) => match error.code() {
4851 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4852 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4853 stream: self.inner,
4854 error,
4855 }))
4856 }
4857 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4858 stream: self.inner,
4859 error,
4860 })),
4861 },
4862 }
4863 }
4864
4865 #[corresponds(SSL_read_early_data)]
4875 #[cfg(any(ossl111, libressl340))]
4876 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4877 self.inner.read_early_data(buf)
4878 }
4879
4880 #[corresponds(SSL_write_early_data)]
4887 #[cfg(any(ossl111, libressl340))]
4888 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4889 self.inner.write_early_data(buf)
4890 }
4891}
4892
4893#[allow(deprecated)]
4894impl<S> SslStreamBuilder<S> {
4895 pub fn get_ref(&self) -> &S {
4897 unsafe {
4898 let bio = self.inner.ssl.get_raw_rbio();
4899 bio::get_ref(bio)
4900 }
4901 }
4902
4903 pub fn get_mut(&mut self) -> &mut S {
4910 unsafe {
4911 let bio = self.inner.ssl.get_raw_rbio();
4912 bio::get_mut(bio)
4913 }
4914 }
4915
4916 pub fn ssl(&self) -> &SslRef {
4918 &self.inner.ssl
4919 }
4920
4921 pub fn ssl_mut(&mut self) -> &mut SslRef {
4923 &mut self.inner.ssl
4924 }
4925}
4926
4927#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4929pub enum ShutdownResult {
4930 Sent,
4932
4933 Received,
4935}
4936
4937bitflags! {
4938 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4940 #[repr(transparent)]
4941 pub struct ShutdownState: c_int {
4942 const SENT = ffi::SSL_SENT_SHUTDOWN;
4944 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4946 }
4947}
4948
4949cfg_if! {
4950 if #[cfg(any(boringssl, ossl110, libressl273, awslc))] {
4951 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4952 } else {
4953 #[allow(bad_style)]
4954 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4955 ffi::CRYPTO_add_lock(
4956 &mut (*ssl).references,
4957 1,
4958 ffi::CRYPTO_LOCK_SSL_CTX,
4959 "mod.rs\0".as_ptr() as *const _,
4960 line!() as c_int,
4961 );
4962 0
4963 }
4964
4965 #[allow(bad_style)]
4966 pub unsafe fn SSL_SESSION_get_master_key(
4967 session: *const ffi::SSL_SESSION,
4968 out: *mut c_uchar,
4969 mut outlen: usize,
4970 ) -> usize {
4971 if outlen == 0 {
4972 return (*session).master_key_length as usize;
4973 }
4974 if outlen > (*session).master_key_length as usize {
4975 outlen = (*session).master_key_length as usize;
4976 }
4977 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
4978 outlen
4979 }
4980
4981 #[allow(bad_style)]
4982 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
4983 (*s).server
4984 }
4985
4986 #[allow(bad_style)]
4987 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
4988 ffi::CRYPTO_add_lock(
4989 &mut (*ses).references,
4990 1,
4991 ffi::CRYPTO_LOCK_SSL_CTX,
4992 "mod.rs\0".as_ptr() as *const _,
4993 line!() as c_int,
4994 );
4995 0
4996 }
4997 }
4998}
4999
5000cfg_if! {
5001 if #[cfg(ossl300)] {
5002 use ffi::SSL_get1_peer_certificate;
5003 } else {
5004 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
5005 }
5006}
5007cfg_if! {
5008 if #[cfg(any(boringssl, ossl110, libressl291, awslc))] {
5009 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
5010 } else {
5011 use ffi::{
5012 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
5013 SSLv23_server_method as TLS_server_method,
5014 };
5015 }
5016}
5017cfg_if! {
5018 if #[cfg(ossl110)] {
5019 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5020 ffi::CRYPTO_get_ex_new_index(
5021 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5022 0,
5023 ptr::null_mut(),
5024 None,
5025 None,
5026 f,
5027 )
5028 }
5029
5030 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5031 ffi::CRYPTO_get_ex_new_index(
5032 ffi::CRYPTO_EX_INDEX_SSL,
5033 0,
5034 ptr::null_mut(),
5035 None,
5036 None,
5037 f,
5038 )
5039 }
5040 } else {
5041 use std::sync::Once;
5042
5043 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5044 static ONCE: Once = Once::new();
5046 ONCE.call_once(|| {
5047 cfg_if! {
5048 if #[cfg(not(any(boringssl, awslc)))] {
5049 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5050 } else {
5051 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5052 }
5053 }
5054 });
5055
5056 cfg_if! {
5057 if #[cfg(not(any(boringssl, awslc)))] {
5058 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5059 } else {
5060 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5061 }
5062 }
5063 }
5064
5065 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5066 static ONCE: Once = Once::new();
5068 ONCE.call_once(|| {
5069 #[cfg(not(any(boringssl, awslc)))]
5070 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5071 #[cfg(any(boringssl, awslc))]
5072 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5073 });
5074
5075 #[cfg(not(any(boringssl, awslc)))]
5076 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5077 #[cfg(any(boringssl, awslc))]
5078 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5079 }
5080 }
5081}