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#[cfg(any(ossl102, libressl261, boringssl, awslc))]
678#[derive(Debug, Copy, Clone, PartialEq, Eq)]
679pub struct AlpnError(c_int);
680
681#[cfg(any(ossl102, libressl261, boringssl, awslc))]
682impl AlpnError {
683 #[cfg(any(ossl110, boringssl, awslc))]
687 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
688
689 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
691}
692
693#[cfg(ossl111)]
697#[derive(Debug, Copy, Clone, PartialEq, Eq)]
698pub struct ClientHelloError(c_int);
699
700#[cfg(ossl111)]
701impl ClientHelloError {
702 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
704
705 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
707}
708
709#[derive(Debug, Copy, Clone, PartialEq, Eq)]
711pub struct TicketKeyStatus(c_int);
712
713impl TicketKeyStatus {
714 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
716 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
718 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
720}
721
722#[derive(Debug, Copy, Clone, PartialEq, Eq)]
724#[cfg(any(boringssl, awslc))]
725pub struct SelectCertError(ffi::ssl_select_cert_result_t);
726
727#[cfg(any(boringssl, awslc))]
728impl SelectCertError {
729 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
731
732 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
734
735 #[cfg(boringssl)]
741 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
742}
743
744#[cfg(ossl111)]
746#[derive(Debug, Copy, Clone, PartialEq, Eq)]
747pub struct SslCtValidationMode(c_int);
748
749#[cfg(ossl111)]
750impl SslCtValidationMode {
751 pub const PERMISSIVE: SslCtValidationMode =
752 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
753 pub const STRICT: SslCtValidationMode =
754 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
755}
756
757#[derive(Debug, Copy, Clone, PartialEq, Eq)]
759pub struct CertCompressionAlgorithm(c_int);
760
761impl CertCompressionAlgorithm {
762 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
763 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
764 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
765}
766
767#[derive(Debug, Copy, Clone, PartialEq, Eq)]
769pub struct SslVersion(c_int);
770
771impl SslVersion {
772 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
774
775 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
777
778 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
780
781 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
783
784 #[cfg(any(ossl111, libressl340, boringssl, awslc))]
788 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
789
790 #[cfg(tongsuo)]
791 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
792
793 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
797
798 #[cfg(any(ossl102, libressl332, boringssl, awslc))]
802 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
803}
804
805cfg_if! {
806 if #[cfg(any(boringssl, awslc))] {
807 type SslCacheTy = i64;
808 type SslCacheSize = libc::c_ulong;
809 type MtuTy = u32;
810 type ModeTy = u32;
811 type SizeTy = usize;
812 } else {
813 type SslCacheTy = i64;
814 type SslCacheSize = c_long;
815 type MtuTy = c_long;
816 type ModeTy = c_long;
817 type SizeTy = u32;
818 }
819}
820
821#[corresponds(SSL_select_next_proto)]
832pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
833 unsafe {
834 let mut out = ptr::null_mut();
835 let mut outlen = 0;
836 let r = ffi::SSL_select_next_proto(
837 &mut out,
838 &mut outlen,
839 server.as_ptr(),
840 server.len() as c_uint,
841 client.as_ptr(),
842 client.len() as c_uint,
843 );
844 if r == ffi::OPENSSL_NPN_NEGOTIATED {
845 Some(util::from_raw_parts(out as *const u8, outlen as usize))
846 } else {
847 None
848 }
849 }
850}
851
852pub struct SslContextBuilder(SslContext);
854
855impl SslContextBuilder {
856 #[corresponds(SSL_CTX_new)]
858 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
859 unsafe {
860 init();
861 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
862
863 Ok(SslContextBuilder::from_ptr(ctx))
864 }
865 }
866
867 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
873 SslContextBuilder(SslContext::from_ptr(ctx))
874 }
875
876 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
878 self.0.as_ptr()
879 }
880
881 #[cfg(tongsuo)]
882 #[corresponds(SSL_CTX_enable_ntls)]
883 pub fn enable_ntls(&mut self) {
884 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
885 }
886
887 #[cfg(tongsuo)]
888 #[corresponds(SSL_CTX_disable_ntls)]
889 pub fn disable_ntls(&mut self) {
890 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
891 }
892
893 #[cfg(all(tongsuo, ossl300))]
894 #[corresponds(SSL_CTX_enable_force_ntls)]
895 pub fn enable_force_ntls(&mut self) {
896 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
897 }
898
899 #[cfg(all(tongsuo, ossl300))]
900 #[corresponds(SSL_CTX_disable_force_ntls)]
901 pub fn disable_force_ntls(&mut self) {
902 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
903 }
904
905 #[cfg(tongsuo)]
906 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
907 pub fn enable_sm_tls13_strict(&mut self) {
908 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
909 }
910
911 #[cfg(tongsuo)]
912 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
913 pub fn disable_sm_tls13_strict(&mut self) {
914 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
915 }
916
917 #[corresponds(SSL_CTX_set_verify)]
919 pub fn set_verify(&mut self, mode: SslVerifyMode) {
920 unsafe {
921 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
922 }
923 }
924
925 #[corresponds(SSL_CTX_set_verify)]
932 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
933 where
934 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
935 {
936 unsafe {
937 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
938 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
939 }
940 }
941
942 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
950 pub fn set_servername_callback<F>(&mut self, callback: F)
952 where
953 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
954 {
955 unsafe {
956 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
962 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
963 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
964 }
965 }
966
967 #[corresponds(SSL_CTX_set_verify_depth)]
971 pub fn set_verify_depth(&mut self, depth: u32) {
972 unsafe {
973 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
974 }
975 }
976
977 #[corresponds(SSL_CTX_set0_verify_cert_store)]
981 #[cfg(any(ossl102, boringssl, awslc))]
982 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
983 unsafe {
984 let ptr = cert_store.as_ptr();
985 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
986 mem::forget(cert_store);
987
988 Ok(())
989 }
990 }
991
992 #[corresponds(SSL_CTX_set_cert_store)]
994 pub fn set_cert_store(&mut self, cert_store: X509Store) {
995 unsafe {
996 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
997 mem::forget(cert_store);
998 }
999 }
1000
1001 #[corresponds(SSL_CTX_set_read_ahead)]
1008 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1009 unsafe {
1010 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1011 }
1012 }
1013
1014 #[corresponds(SSL_CTX_set_mode)]
1018 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1019 unsafe {
1020 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1021 SslMode::from_bits_retain(bits)
1022 }
1023 }
1024
1025 #[corresponds(SSL_CTX_clear_mode)]
1027 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1028 unsafe {
1029 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1030 SslMode::from_bits_retain(bits)
1031 }
1032 }
1033
1034 #[corresponds(SSL_CTX_get_mode)]
1036 pub fn mode(&self) -> SslMode {
1037 unsafe {
1038 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1039 SslMode::from_bits_retain(bits)
1040 }
1041 }
1042
1043 #[corresponds(SSL_CTX_set_dh_auto)]
1052 #[cfg(ossl300)]
1053 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1054 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1055 }
1056
1057 #[corresponds(SSL_CTX_set_tmp_dh)]
1059 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1060 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1061 }
1062
1063 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1070 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1071 where
1072 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1073 {
1074 unsafe {
1075 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1076
1077 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1078 }
1079 }
1080
1081 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1083 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1084 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1085 }
1086
1087 #[corresponds(SSL_CTX_set_default_verify_paths)]
1092 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1093 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1094 }
1095
1096 #[corresponds(SSL_CTX_load_verify_locations)]
1100 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1101 self.load_verify_locations(Some(file.as_ref()), None)
1102 }
1103
1104 #[corresponds(SSL_CTX_load_verify_locations)]
1106 pub fn load_verify_locations(
1107 &mut self,
1108 ca_file: Option<&Path>,
1109 ca_path: Option<&Path>,
1110 ) -> Result<(), ErrorStack> {
1111 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1112 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1113 unsafe {
1114 cvt(ffi::SSL_CTX_load_verify_locations(
1115 self.as_ptr(),
1116 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1117 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1118 ))
1119 .map(|_| ())
1120 }
1121 }
1122
1123 #[corresponds(SSL_CTX_set_client_CA_list)]
1128 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1129 unsafe {
1130 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1131 mem::forget(list);
1132 }
1133 }
1134
1135 #[corresponds(SSL_CTX_add_client_CA)]
1138 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1139 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1140 }
1141
1142 #[corresponds(SSL_CTX_set_session_id_context)]
1151 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1152 unsafe {
1153 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1154 cvt(ffi::SSL_CTX_set_session_id_context(
1155 self.as_ptr(),
1156 sid_ctx.as_ptr(),
1157 sid_ctx.len() as SizeTy,
1158 ))
1159 .map(|_| ())
1160 }
1161 }
1162
1163 #[corresponds(SSL_CTX_use_certificate_file)]
1169 pub fn set_certificate_file<P: AsRef<Path>>(
1170 &mut self,
1171 file: P,
1172 file_type: SslFiletype,
1173 ) -> Result<(), ErrorStack> {
1174 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1175 unsafe {
1176 cvt(ffi::SSL_CTX_use_certificate_file(
1177 self.as_ptr(),
1178 file.as_ptr() as *const _,
1179 file_type.as_raw(),
1180 ))
1181 .map(|_| ())
1182 }
1183 }
1184
1185 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1191 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1192 &mut self,
1193 file: P,
1194 ) -> Result<(), ErrorStack> {
1195 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1196 unsafe {
1197 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1198 self.as_ptr(),
1199 file.as_ptr() as *const _,
1200 ))
1201 .map(|_| ())
1202 }
1203 }
1204
1205 #[corresponds(SSL_CTX_use_certificate)]
1209 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1210 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1211 }
1212
1213 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1218 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1219 unsafe {
1220 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1221 mem::forget(cert);
1222 Ok(())
1223 }
1224 }
1225
1226 #[cfg(tongsuo)]
1227 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1228 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1229 &mut self,
1230 file: P,
1231 file_type: SslFiletype,
1232 ) -> Result<(), ErrorStack> {
1233 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1234 unsafe {
1235 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1236 self.as_ptr(),
1237 file.as_ptr() as *const _,
1238 file_type.as_raw(),
1239 ))
1240 .map(|_| ())
1241 }
1242 }
1243
1244 #[cfg(tongsuo)]
1245 #[corresponds(SSL_CTX_use_enc_certificate)]
1246 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1247 unsafe {
1248 cvt(ffi::SSL_CTX_use_enc_certificate(
1249 self.as_ptr(),
1250 cert.as_ptr(),
1251 ))
1252 .map(|_| ())
1253 }
1254 }
1255
1256 #[cfg(tongsuo)]
1257 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1258 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1259 &mut self,
1260 file: P,
1261 file_type: SslFiletype,
1262 ) -> Result<(), ErrorStack> {
1263 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1264 unsafe {
1265 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1266 self.as_ptr(),
1267 file.as_ptr() as *const _,
1268 file_type.as_raw(),
1269 ))
1270 .map(|_| ())
1271 }
1272 }
1273
1274 #[cfg(tongsuo)]
1275 #[corresponds(SSL_CTX_use_sign_certificate)]
1276 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1277 unsafe {
1278 cvt(ffi::SSL_CTX_use_sign_certificate(
1279 self.as_ptr(),
1280 cert.as_ptr(),
1281 ))
1282 .map(|_| ())
1283 }
1284 }
1285
1286 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1288 pub fn set_private_key_file<P: AsRef<Path>>(
1289 &mut self,
1290 file: P,
1291 file_type: SslFiletype,
1292 ) -> Result<(), ErrorStack> {
1293 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1294 unsafe {
1295 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1296 self.as_ptr(),
1297 file.as_ptr() as *const _,
1298 file_type.as_raw(),
1299 ))
1300 .map(|_| ())
1301 }
1302 }
1303
1304 #[corresponds(SSL_CTX_use_PrivateKey)]
1306 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1307 where
1308 T: HasPrivate,
1309 {
1310 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1311 }
1312
1313 #[cfg(tongsuo)]
1314 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1315 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1316 &mut self,
1317 file: P,
1318 file_type: SslFiletype,
1319 ) -> Result<(), ErrorStack> {
1320 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1321 unsafe {
1322 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1323 self.as_ptr(),
1324 file.as_ptr() as *const _,
1325 file_type.as_raw(),
1326 ))
1327 .map(|_| ())
1328 }
1329 }
1330
1331 #[cfg(tongsuo)]
1332 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1333 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1334 where
1335 T: HasPrivate,
1336 {
1337 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1338 }
1339
1340 #[cfg(tongsuo)]
1341 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1342 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1343 &mut self,
1344 file: P,
1345 file_type: SslFiletype,
1346 ) -> Result<(), ErrorStack> {
1347 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1348 unsafe {
1349 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1350 self.as_ptr(),
1351 file.as_ptr() as *const _,
1352 file_type.as_raw(),
1353 ))
1354 .map(|_| ())
1355 }
1356 }
1357
1358 #[cfg(tongsuo)]
1359 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1360 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1361 where
1362 T: HasPrivate,
1363 {
1364 unsafe {
1365 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1366 self.as_ptr(),
1367 key.as_ptr(),
1368 ))
1369 .map(|_| ())
1370 }
1371 }
1372
1373 #[corresponds(SSL_CTX_set_cipher_list)]
1381 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1382 let cipher_list = CString::new(cipher_list).unwrap();
1383 unsafe {
1384 cvt(ffi::SSL_CTX_set_cipher_list(
1385 self.as_ptr(),
1386 cipher_list.as_ptr() as *const _,
1387 ))
1388 .map(|_| ())
1389 }
1390 }
1391
1392 #[corresponds(SSL_CTX_set_ciphersuites)]
1401 #[cfg(any(ossl111, libressl340, awslc))]
1402 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1403 let cipher_list = CString::new(cipher_list).unwrap();
1404 unsafe {
1405 cvt(ffi::SSL_CTX_set_ciphersuites(
1406 self.as_ptr(),
1407 cipher_list.as_ptr() as *const _,
1408 ))
1409 .map(|_| ())
1410 }
1411 }
1412
1413 #[corresponds(SSL_CTX_set_ecdh_auto)]
1417 #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1418 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1419 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1420 }
1421
1422 #[corresponds(SSL_CTX_set_options)]
1429 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1430 let bits =
1431 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1432 SslOptions::from_bits_retain(bits)
1433 }
1434
1435 #[corresponds(SSL_CTX_get_options)]
1437 pub fn options(&self) -> SslOptions {
1438 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1439 SslOptions::from_bits_retain(bits)
1440 }
1441
1442 #[corresponds(SSL_CTX_clear_options)]
1444 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1445 let bits =
1446 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1447 SslOptions::from_bits_retain(bits)
1448 }
1449
1450 #[corresponds(SSL_CTX_set_min_proto_version)]
1457 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1458 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1459 unsafe {
1460 cvt(ffi::SSL_CTX_set_min_proto_version(
1461 self.as_ptr(),
1462 version.map_or(0, |v| v.0 as _),
1463 ))
1464 .map(|_| ())
1465 }
1466 }
1467
1468 #[corresponds(SSL_CTX_set_max_proto_version)]
1475 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1476 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1477 unsafe {
1478 cvt(ffi::SSL_CTX_set_max_proto_version(
1479 self.as_ptr(),
1480 version.map_or(0, |v| v.0 as _),
1481 ))
1482 .map(|_| ())
1483 }
1484 }
1485
1486 #[corresponds(SSL_CTX_get_min_proto_version)]
1493 #[cfg(any(ossl110g, libressl270))]
1494 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1495 unsafe {
1496 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1497 if r == 0 {
1498 None
1499 } else {
1500 Some(SslVersion(r))
1501 }
1502 }
1503 }
1504
1505 #[corresponds(SSL_CTX_get_max_proto_version)]
1512 #[cfg(any(ossl110g, libressl270))]
1513 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1514 unsafe {
1515 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1516 if r == 0 {
1517 None
1518 } else {
1519 Some(SslVersion(r))
1520 }
1521 }
1522 }
1523
1524 #[corresponds(SSL_CTX_set_alpn_protos)]
1533 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
1534 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1535 unsafe {
1536 assert!(protocols.len() <= c_uint::MAX as usize);
1537 let r = ffi::SSL_CTX_set_alpn_protos(
1538 self.as_ptr(),
1539 protocols.as_ptr(),
1540 protocols.len() as _,
1541 );
1542 if r == 0 {
1544 Ok(())
1545 } else {
1546 Err(ErrorStack::get())
1547 }
1548 }
1549 }
1550
1551 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1553 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1554 unsafe {
1555 let cstr = CString::new(protocols).unwrap();
1556
1557 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1558 if r == 0 {
1560 Ok(())
1561 } else {
1562 Err(ErrorStack::get())
1563 }
1564 }
1565 }
1566
1567 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1580 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
1581 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1582 where
1583 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1584 {
1585 unsafe {
1586 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1587 ffi::SSL_CTX_set_alpn_select_cb(
1588 self.as_ptr(),
1589 Some(callbacks::raw_alpn_select::<F>),
1590 ptr::null_mut(),
1591 );
1592 }
1593 }
1594
1595 #[corresponds(SSL_CTX_check_private_key)]
1597 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1598 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1599 }
1600
1601 #[corresponds(SSL_CTX_get_cert_store)]
1603 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1604 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1605 }
1606
1607 #[corresponds(SSL_CTX_get_cert_store)]
1609 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1610 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1611 }
1612
1613 #[corresponds(SSL_CTX_get0_param)]
1617 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1618 pub fn verify_param(&self) -> &X509VerifyParamRef {
1619 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1620 }
1621
1622 #[corresponds(SSL_CTX_get0_param)]
1626 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1627 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1628 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1629 }
1630
1631 #[cfg(any(boringssl, tongsuo, awslc))]
1639 pub fn add_cert_decompression_alg<F>(
1640 &mut self,
1641 alg_id: CertCompressionAlgorithm,
1642 decompress: F,
1643 ) -> Result<(), ErrorStack>
1644 where
1645 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1646 {
1647 unsafe {
1648 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1649 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1650 self.as_ptr(),
1651 alg_id.0 as _,
1652 None,
1653 Some(raw_cert_decompression::<F>),
1654 ))
1655 .map(|_| ())
1656 }
1657 }
1658
1659 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1661 #[cfg(ossl320)]
1662 pub fn set_cert_comp_preference(
1663 &mut self,
1664 algs: &[CertCompressionAlgorithm],
1665 ) -> Result<(), ErrorStack> {
1666 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1667 unsafe {
1668 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1669 self.as_ptr(),
1670 algs.as_mut_ptr(),
1671 algs.len(),
1672 ))
1673 .map(|_| ())
1674 }
1675 }
1676
1677 #[cfg(any(boringssl, awslc))]
1685 pub fn enable_ocsp_stapling(&mut self) {
1686 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1687 }
1688
1689 #[cfg(any(boringssl, awslc))]
1697 pub fn enable_signed_cert_timestamps(&mut self) {
1698 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1699 }
1700
1701 #[cfg(any(boringssl, awslc))]
1709 pub fn set_grease_enabled(&mut self, enabled: bool) {
1710 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1711 }
1712
1713 #[cfg(any(boringssl, awslc))]
1721 pub fn set_permute_extensions(&mut self, enabled: bool) {
1722 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1723 }
1724
1725 #[corresponds(SSL_CTX_enable_ct)]
1727 #[cfg(ossl111)]
1728 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1729 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1730 }
1731
1732 #[corresponds(SSL_CTX_ct_is_enabled)]
1734 #[cfg(ossl111)]
1735 pub fn ct_is_enabled(&self) -> bool {
1736 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1737 }
1738
1739 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1741 #[cfg(not(any(boringssl, awslc)))]
1742 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1743 unsafe {
1744 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1745 .map(|_| ())
1746 }
1747 }
1748
1749 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1762 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1763 where
1764 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1765 {
1766 unsafe {
1767 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1768 cvt(
1769 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1770 as c_int,
1771 )
1772 .map(|_| ())
1773 }
1774 }
1775
1776 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1777 #[cfg(ossl300)]
1778 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1779 where
1780 F: Fn(
1781 &mut SslRef,
1782 &mut [u8],
1783 &mut [u8],
1784 &mut CipherCtxRef,
1785 &mut MacCtxRef,
1786 bool,
1787 ) -> Result<TicketKeyStatus, ErrorStack>
1788 + 'static
1789 + Sync
1790 + Send,
1791 {
1792 unsafe {
1793 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1794 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1795 self.as_ptr(),
1796 Some(raw_tlsext_ticket_key_evp::<F>),
1797 ) as c_int)
1798 .map(|_| ())
1799 }
1800 }
1801
1802 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1803 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1804 where
1805 F: Fn(
1806 &mut SslRef,
1807 &mut [u8],
1808 &mut [u8],
1809 &mut CipherCtxRef,
1810 &mut HMacCtxRef,
1811 bool,
1812 ) -> Result<TicketKeyStatus, ErrorStack>
1813 + 'static
1814 + Sync
1815 + Send,
1816 {
1817 unsafe {
1818 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1819 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1820 self.as_ptr(),
1821 Some(raw_tlsext_ticket_key::<F>),
1822 ) as c_int)
1823 .map(|_| ())
1824 }
1825 }
1826
1827 #[corresponds(SSL_CTX_set_psk_client_callback)]
1833 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1834 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1835 where
1836 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1837 + 'static
1838 + Sync
1839 + Send,
1840 {
1841 unsafe {
1842 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1843 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1844 }
1845 }
1846
1847 #[corresponds(SSL_CTX_set_psk_server_callback)]
1853 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1854 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1855 where
1856 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1857 + 'static
1858 + Sync
1859 + Send,
1860 {
1861 unsafe {
1862 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1863 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1864 }
1865 }
1866
1867 #[corresponds(SSL_CTX_sess_set_new_cb)]
1881 pub fn set_new_session_callback<F>(&mut self, callback: F)
1882 where
1883 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1884 {
1885 unsafe {
1886 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1887 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1888 }
1889 }
1890
1891 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1895 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1896 where
1897 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1898 {
1899 unsafe {
1900 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1901 ffi::SSL_CTX_sess_set_remove_cb(
1902 self.as_ptr(),
1903 Some(callbacks::raw_remove_session::<F>),
1904 );
1905 }
1906 }
1907
1908 #[corresponds(SSL_CTX_sess_set_get_cb)]
1919 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1920 where
1921 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1922 {
1923 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1924 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1925 }
1926
1927 #[corresponds(SSL_CTX_set_keylog_callback)]
1935 #[cfg(any(ossl111, boringssl, awslc))]
1936 pub fn set_keylog_callback<F>(&mut self, callback: F)
1937 where
1938 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1939 {
1940 unsafe {
1941 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1942 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1943 }
1944 }
1945
1946 #[corresponds(SSL_CTX_set_session_cache_mode)]
1950 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1951 unsafe {
1952 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1953 SslSessionCacheMode::from_bits_retain(bits)
1954 }
1955 }
1956
1957 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1963 #[cfg(ossl111)]
1964 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1965 where
1966 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1967 {
1968 unsafe {
1969 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1970 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1971 self.as_ptr(),
1972 Some(raw_stateless_cookie_generate::<F>),
1973 );
1974 }
1975 }
1976
1977 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1986 #[cfg(ossl111)]
1987 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1988 where
1989 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1990 {
1991 unsafe {
1992 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1993 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1994 self.as_ptr(),
1995 Some(raw_stateless_cookie_verify::<F>),
1996 )
1997 }
1998 }
1999
2000 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
2005 #[cfg(not(any(boringssl, awslc)))]
2006 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
2007 where
2008 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
2009 {
2010 unsafe {
2011 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2012 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2013 }
2014 }
2015
2016 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2021 #[cfg(not(any(boringssl, awslc)))]
2022 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2023 where
2024 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2025 {
2026 unsafe {
2027 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2028 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2029 }
2030 }
2031
2032 #[corresponds(SSL_CTX_set_ex_data)]
2038 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2039 self.set_ex_data_inner(index, data);
2040 }
2041
2042 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2043 match self.ex_data_mut(index) {
2044 Some(v) => {
2045 *v = data;
2046 (v as *mut T).cast()
2047 }
2048 _ => unsafe {
2049 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2050 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2051 data
2052 },
2053 }
2054 }
2055
2056 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2057 unsafe {
2058 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2059 if data.is_null() {
2060 None
2061 } else {
2062 Some(&mut *data.cast())
2063 }
2064 }
2065 }
2066
2067 #[corresponds(SSL_CTX_add_custom_ext)]
2071 #[cfg(ossl111)]
2072 pub fn add_custom_ext<AddFn, ParseFn, T>(
2073 &mut self,
2074 ext_type: u16,
2075 context: ExtensionContext,
2076 add_cb: AddFn,
2077 parse_cb: ParseFn,
2078 ) -> Result<(), ErrorStack>
2079 where
2080 AddFn: Fn(
2081 &mut SslRef,
2082 ExtensionContext,
2083 Option<(usize, &X509Ref)>,
2084 ) -> Result<Option<T>, SslAlert>
2085 + 'static
2086 + Sync
2087 + Send,
2088 T: AsRef<[u8]> + 'static + Sync + Send,
2089 ParseFn: Fn(
2090 &mut SslRef,
2091 ExtensionContext,
2092 &[u8],
2093 Option<(usize, &X509Ref)>,
2094 ) -> Result<(), SslAlert>
2095 + 'static
2096 + Sync
2097 + Send,
2098 {
2099 let ret = unsafe {
2100 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2101 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2102
2103 ffi::SSL_CTX_add_custom_ext(
2104 self.as_ptr(),
2105 ext_type as c_uint,
2106 context.bits(),
2107 Some(raw_custom_ext_add::<AddFn, T>),
2108 Some(raw_custom_ext_free::<T>),
2109 ptr::null_mut(),
2110 Some(raw_custom_ext_parse::<ParseFn>),
2111 ptr::null_mut(),
2112 )
2113 };
2114 if ret == 1 {
2115 Ok(())
2116 } else {
2117 Err(ErrorStack::get())
2118 }
2119 }
2120
2121 #[corresponds(SSL_CTX_set_max_early_data)]
2127 #[cfg(any(ossl111, libressl340))]
2128 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2129 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2130 Ok(())
2131 } else {
2132 Err(ErrorStack::get())
2133 }
2134 }
2135
2136 #[cfg(any(boringssl, awslc))]
2146 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2147 where
2148 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2149 {
2150 unsafe {
2151 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2152 ffi::SSL_CTX_set_select_certificate_cb(
2153 self.as_ptr(),
2154 Some(callbacks::raw_select_cert::<F>),
2155 );
2156 }
2157 }
2158
2159 #[corresponds(SSL_CTX_set_client_hello_cb)]
2163 #[cfg(ossl111)]
2164 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2165 where
2166 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2167 {
2168 unsafe {
2169 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2170 ffi::SSL_CTX_set_client_hello_cb(
2171 self.as_ptr(),
2172 Some(callbacks::raw_client_hello::<F>),
2173 ptr,
2174 );
2175 }
2176 }
2177
2178 #[corresponds(SSL_CTX_sess_set_cache_size)]
2182 #[allow(clippy::useless_conversion)]
2183 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2184 unsafe {
2185 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2186 }
2187 }
2188
2189 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2193 #[cfg(ossl102)]
2194 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2195 let sigalgs = CString::new(sigalgs).unwrap();
2196 unsafe {
2197 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2198 .map(|_| ())
2199 }
2200 }
2201
2202 #[corresponds(SSL_CTX_set1_groups_list)]
2206 #[cfg(any(ossl111, boringssl, libressl251, awslc))]
2207 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2208 let groups = CString::new(groups).unwrap();
2209 unsafe {
2210 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2211 }
2212 }
2213
2214 #[corresponds(SSL_CTX_set_num_tickets)]
2219 #[cfg(any(ossl111, boringssl, awslc))]
2220 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2221 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2222 }
2223
2224 #[corresponds(SSL_CTX_set_security_level)]
2229 #[cfg(any(ossl110, libressl360))]
2230 pub fn set_security_level(&mut self, level: u32) {
2231 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2232 }
2233
2234 pub fn build(self) -> SslContext {
2236 self.0
2237 }
2238}
2239
2240foreign_type_and_impl_send_sync! {
2241 type CType = ffi::SSL_CTX;
2242 fn drop = ffi::SSL_CTX_free;
2243
2244 pub struct SslContext;
2249
2250 pub struct SslContextRef;
2254}
2255
2256impl Clone for SslContext {
2257 fn clone(&self) -> Self {
2258 (**self).to_owned()
2259 }
2260}
2261
2262impl ToOwned for SslContextRef {
2263 type Owned = SslContext;
2264
2265 fn to_owned(&self) -> Self::Owned {
2266 unsafe {
2267 SSL_CTX_up_ref(self.as_ptr());
2268 SslContext::from_ptr(self.as_ptr())
2269 }
2270 }
2271}
2272
2273impl fmt::Debug for SslContext {
2275 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2276 write!(fmt, "SslContext")
2277 }
2278}
2279
2280impl SslContext {
2281 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2283 SslContextBuilder::new(method)
2284 }
2285
2286 #[corresponds(SSL_CTX_get_ex_new_index)]
2291 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2292 where
2293 T: 'static + Sync + Send,
2294 {
2295 unsafe {
2296 ffi::init();
2297 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2298 Ok(Index::from_raw(idx))
2299 }
2300 }
2301
2302 fn cached_ex_index<T>() -> Index<SslContext, T>
2304 where
2305 T: 'static + Sync + Send,
2306 {
2307 unsafe {
2308 let idx = *INDEXES
2309 .lock()
2310 .unwrap_or_else(|e| e.into_inner())
2311 .entry(TypeId::of::<T>())
2312 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2313 Index::from_raw(idx)
2314 }
2315 }
2316}
2317
2318impl SslContextRef {
2319 #[corresponds(SSL_CTX_get0_certificate)]
2323 #[cfg(any(ossl102, libressl270))]
2324 pub fn certificate(&self) -> Option<&X509Ref> {
2325 unsafe {
2326 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2327 X509Ref::from_const_ptr_opt(ptr)
2328 }
2329 }
2330
2331 #[corresponds(SSL_CTX_get0_privatekey)]
2335 #[cfg(any(ossl102, libressl340))]
2336 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2337 unsafe {
2338 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2339 PKeyRef::from_const_ptr_opt(ptr)
2340 }
2341 }
2342
2343 #[corresponds(SSL_CTX_get_cert_store)]
2345 pub fn cert_store(&self) -> &X509StoreRef {
2346 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2347 }
2348
2349 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2351 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2352 unsafe {
2353 let mut chain = ptr::null_mut();
2354 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2355 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2356 }
2357 }
2358
2359 #[corresponds(SSL_CTX_get_ex_data)]
2361 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2362 unsafe {
2363 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2364 if data.is_null() {
2365 None
2366 } else {
2367 Some(&*(data as *const T))
2368 }
2369 }
2370 }
2371
2372 #[corresponds(SSL_CTX_get_max_early_data)]
2376 #[cfg(any(ossl111, libressl340))]
2377 pub fn max_early_data(&self) -> u32 {
2378 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2379 }
2380
2381 #[corresponds(SSL_CTX_add_session)]
2390 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2391 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2392 }
2393
2394 #[corresponds(SSL_CTX_remove_session)]
2403 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2404 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2405 }
2406
2407 #[corresponds(SSL_CTX_sess_get_cache_size)]
2411 #[allow(clippy::unnecessary_cast)]
2412 pub fn session_cache_size(&self) -> i64 {
2413 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2414 }
2415
2416 #[corresponds(SSL_CTX_get_verify_mode)]
2420 pub fn verify_mode(&self) -> SslVerifyMode {
2421 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2422 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2423 }
2424
2425 #[corresponds(SSL_CTX_get_num_tickets)]
2430 #[cfg(ossl111)]
2431 pub fn num_tickets(&self) -> usize {
2432 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2433 }
2434
2435 #[corresponds(SSL_CTX_get_security_level)]
2440 #[cfg(any(ossl110, libressl360))]
2441 pub fn security_level(&self) -> u32 {
2442 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2443 }
2444}
2445
2446pub struct CipherBits {
2448 pub secret: i32,
2450
2451 pub algorithm: i32,
2453}
2454
2455pub struct SslCipher(*mut ffi::SSL_CIPHER);
2457
2458impl ForeignType for SslCipher {
2459 type CType = ffi::SSL_CIPHER;
2460 type Ref = SslCipherRef;
2461
2462 #[inline]
2463 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2464 SslCipher(ptr)
2465 }
2466
2467 #[inline]
2468 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2469 self.0
2470 }
2471}
2472
2473impl Stackable for SslCipher {
2474 type StackType = ffi::stack_st_SSL_CIPHER;
2475}
2476
2477impl Deref for SslCipher {
2478 type Target = SslCipherRef;
2479
2480 fn deref(&self) -> &SslCipherRef {
2481 unsafe { SslCipherRef::from_ptr(self.0) }
2482 }
2483}
2484
2485impl DerefMut for SslCipher {
2486 fn deref_mut(&mut self) -> &mut SslCipherRef {
2487 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2488 }
2489}
2490
2491pub struct SslCipherRef(Opaque);
2495
2496impl ForeignTypeRef for SslCipherRef {
2497 type CType = ffi::SSL_CIPHER;
2498}
2499
2500impl SslCipherRef {
2501 #[corresponds(SSL_CIPHER_get_name)]
2503 pub fn name(&self) -> &'static str {
2504 unsafe {
2505 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2506 CStr::from_ptr(ptr).to_str().unwrap()
2507 }
2508 }
2509
2510 #[corresponds(SSL_CIPHER_standard_name)]
2514 #[cfg(ossl111)]
2515 pub fn standard_name(&self) -> Option<&'static str> {
2516 unsafe {
2517 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2518 if ptr.is_null() {
2519 None
2520 } else {
2521 Some(CStr::from_ptr(ptr).to_str().unwrap())
2522 }
2523 }
2524 }
2525
2526 #[corresponds(SSL_CIPHER_get_version)]
2528 pub fn version(&self) -> &'static str {
2529 let version = unsafe {
2530 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2531 CStr::from_ptr(ptr as *const _)
2532 };
2533
2534 str::from_utf8(version.to_bytes()).unwrap()
2535 }
2536
2537 #[corresponds(SSL_CIPHER_get_bits)]
2539 #[allow(clippy::useless_conversion)]
2540 pub fn bits(&self) -> CipherBits {
2541 unsafe {
2542 let mut algo_bits = 0;
2543 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2544 CipherBits {
2545 secret: secret_bits.into(),
2546 algorithm: algo_bits.into(),
2547 }
2548 }
2549 }
2550
2551 #[corresponds(SSL_CIPHER_description)]
2553 pub fn description(&self) -> String {
2554 unsafe {
2555 let mut buf = [0; 128];
2557 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2558 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2559 }
2560 }
2561
2562 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2566 #[cfg(ossl111)]
2567 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2568 unsafe {
2569 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2570 if ptr.is_null() {
2571 None
2572 } else {
2573 Some(MessageDigest::from_ptr(ptr))
2574 }
2575 }
2576 }
2577
2578 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2582 #[cfg(any(ossl110, libressl270))]
2583 pub fn cipher_nid(&self) -> Option<Nid> {
2584 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2585 if n == 0 {
2586 None
2587 } else {
2588 Some(Nid::from_raw(n))
2589 }
2590 }
2591}
2592
2593impl fmt::Debug for SslCipherRef {
2594 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2595 write!(fmt, "{}", self.name())
2596 }
2597}
2598
2599#[derive(Debug)]
2601pub struct CipherLists {
2602 pub suites: Stack<SslCipher>,
2603 pub signalling_suites: Stack<SslCipher>,
2604}
2605
2606foreign_type_and_impl_send_sync! {
2607 type CType = ffi::SSL_SESSION;
2608 fn drop = ffi::SSL_SESSION_free;
2609
2610 pub struct SslSession;
2614
2615 pub struct SslSessionRef;
2619}
2620
2621impl Clone for SslSession {
2622 fn clone(&self) -> SslSession {
2623 SslSessionRef::to_owned(self)
2624 }
2625}
2626
2627impl SslSession {
2628 from_der! {
2629 #[corresponds(d2i_SSL_SESSION)]
2631 from_der,
2632 SslSession,
2633 ffi::d2i_SSL_SESSION
2634 }
2635}
2636
2637impl ToOwned for SslSessionRef {
2638 type Owned = SslSession;
2639
2640 fn to_owned(&self) -> SslSession {
2641 unsafe {
2642 SSL_SESSION_up_ref(self.as_ptr());
2643 SslSession(self.as_ptr())
2644 }
2645 }
2646}
2647
2648impl SslSessionRef {
2649 #[corresponds(SSL_SESSION_get_id)]
2651 pub fn id(&self) -> &[u8] {
2652 unsafe {
2653 let mut len = 0;
2654 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2655 #[allow(clippy::unnecessary_cast)]
2656 util::from_raw_parts(p as *const u8, len as usize)
2657 }
2658 }
2659
2660 #[corresponds(SSL_SESSION_get_master_key)]
2662 pub fn master_key_len(&self) -> usize {
2663 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2664 }
2665
2666 #[corresponds(SSL_SESSION_get_master_key)]
2670 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2671 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2672 }
2673
2674 #[corresponds(SSL_SESSION_get_max_early_data)]
2678 #[cfg(any(ossl111, libressl340))]
2679 pub fn max_early_data(&self) -> u32 {
2680 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2681 }
2682
2683 #[corresponds(SSL_SESSION_get_time)]
2685 #[allow(clippy::useless_conversion)]
2686 pub fn time(&self) -> SslTimeTy {
2687 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2688 }
2689
2690 #[corresponds(SSL_SESSION_get_timeout)]
2694 #[allow(clippy::useless_conversion)]
2695 pub fn timeout(&self) -> i64 {
2696 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2697 }
2698
2699 #[corresponds(SSL_SESSION_get_protocol_version)]
2703 #[cfg(any(ossl110, libressl270))]
2704 pub fn protocol_version(&self) -> SslVersion {
2705 unsafe {
2706 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2707 SslVersion(version)
2708 }
2709 }
2710
2711 #[corresponds(SSL_SESSION_get_protocol_version)]
2713 #[cfg(any(boringssl, awslc))]
2714 pub fn protocol_version(&self) -> SslVersion {
2715 unsafe {
2716 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2717 SslVersion(version as _)
2718 }
2719 }
2720
2721 to_der! {
2722 #[corresponds(i2d_SSL_SESSION)]
2724 to_der,
2725 ffi::i2d_SSL_SESSION
2726 }
2727}
2728
2729foreign_type_and_impl_send_sync! {
2730 type CType = ffi::SSL;
2731 fn drop = ffi::SSL_free;
2732
2733 pub struct Ssl;
2740
2741 pub struct SslRef;
2745}
2746
2747impl fmt::Debug for Ssl {
2748 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2749 fmt::Debug::fmt(&**self, fmt)
2750 }
2751}
2752
2753impl Ssl {
2754 #[corresponds(SSL_get_ex_new_index)]
2759 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2760 where
2761 T: 'static + Sync + Send,
2762 {
2763 unsafe {
2764 ffi::init();
2765 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2766 Ok(Index::from_raw(idx))
2767 }
2768 }
2769
2770 fn cached_ex_index<T>() -> Index<Ssl, T>
2772 where
2773 T: 'static + Sync + Send,
2774 {
2775 unsafe {
2776 let idx = *SSL_INDEXES
2777 .lock()
2778 .unwrap_or_else(|e| e.into_inner())
2779 .entry(TypeId::of::<T>())
2780 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2781 Index::from_raw(idx)
2782 }
2783 }
2784
2785 #[corresponds(SSL_new)]
2787 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2788 let session_ctx_index = try_get_session_ctx_index()?;
2789 unsafe {
2790 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2791 let mut ssl = Ssl::from_ptr(ptr);
2792 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2793
2794 Ok(ssl)
2795 }
2796 }
2797
2798 #[corresponds(SSL_connect)]
2804 #[allow(deprecated)]
2805 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2806 where
2807 S: Read + Write,
2808 {
2809 SslStreamBuilder::new(self, stream).connect()
2810 }
2811
2812 #[corresponds(SSL_accept)]
2819 #[allow(deprecated)]
2820 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2821 where
2822 S: Read + Write,
2823 {
2824 SslStreamBuilder::new(self, stream).accept()
2825 }
2826}
2827
2828impl fmt::Debug for SslRef {
2829 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2830 fmt.debug_struct("Ssl")
2831 .field("state", &self.state_string_long())
2832 .field("verify_result", &self.verify_result())
2833 .finish()
2834 }
2835}
2836
2837impl SslRef {
2838 #[cfg(not(feature = "tongsuo"))]
2839 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2840 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2841 }
2842
2843 #[cfg(feature = "tongsuo")]
2844 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2845 unsafe {
2846 let bio = ffi::SSL_get_rbio(self.as_ptr());
2847 bio::find_correct_bio(bio)
2848 }
2849 }
2850
2851 fn get_error(&self, ret: c_int) -> ErrorCode {
2852 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2853 }
2854
2855 #[corresponds(SSL_set_mode)]
2859 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2860 unsafe {
2861 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2862 SslMode::from_bits_retain(bits)
2863 }
2864 }
2865
2866 #[corresponds(SSL_clear_mode)]
2868 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2869 unsafe {
2870 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2871 SslMode::from_bits_retain(bits)
2872 }
2873 }
2874
2875 #[corresponds(SSL_get_mode)]
2877 pub fn mode(&self) -> SslMode {
2878 unsafe {
2879 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2880 SslMode::from_bits_retain(bits)
2881 }
2882 }
2883
2884 #[corresponds(SSL_set_connect_state)]
2886 pub fn set_connect_state(&mut self) {
2887 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2888 }
2889
2890 #[corresponds(SSL_set_accept_state)]
2892 pub fn set_accept_state(&mut self) {
2893 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2894 }
2895
2896 #[cfg(any(boringssl, awslc))]
2897 #[corresponds(SSL_ech_accepted)]
2898 pub fn ech_accepted(&self) -> bool {
2899 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2900 }
2901
2902 #[cfg(tongsuo)]
2903 #[corresponds(SSL_is_ntls)]
2904 pub fn is_ntls(&mut self) -> bool {
2905 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2906 }
2907
2908 #[cfg(tongsuo)]
2909 #[corresponds(SSL_enable_ntls)]
2910 pub fn enable_ntls(&mut self) {
2911 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2912 }
2913
2914 #[cfg(tongsuo)]
2915 #[corresponds(SSL_disable_ntls)]
2916 pub fn disable_ntls(&mut self) {
2917 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2918 }
2919
2920 #[cfg(all(tongsuo, ossl300))]
2921 #[corresponds(SSL_enable_force_ntls)]
2922 pub fn enable_force_ntls(&mut self) {
2923 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2924 }
2925
2926 #[cfg(all(tongsuo, ossl300))]
2927 #[corresponds(SSL_disable_force_ntls)]
2928 pub fn disable_force_ntls(&mut self) {
2929 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2930 }
2931
2932 #[cfg(tongsuo)]
2933 #[corresponds(SSL_enable_sm_tls13_strict)]
2934 pub fn enable_sm_tls13_strict(&mut self) {
2935 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2936 }
2937
2938 #[cfg(tongsuo)]
2939 #[corresponds(SSL_disable_sm_tls13_strict)]
2940 pub fn disable_sm_tls13_strict(&mut self) {
2941 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2942 }
2943
2944 #[corresponds(SSL_set_verify)]
2948 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2949 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2950 }
2951
2952 #[corresponds(SSL_set_verify_mode)]
2954 pub fn verify_mode(&self) -> SslVerifyMode {
2955 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2956 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2957 }
2958
2959 #[corresponds(SSL_set_verify)]
2963 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2964 where
2965 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2966 {
2967 unsafe {
2968 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2970 ffi::SSL_set_verify(
2971 self.as_ptr(),
2972 mode.bits() as c_int,
2973 Some(ssl_raw_verify::<F>),
2974 );
2975 }
2976 }
2977
2978 #[corresponds(SSL_set_dh_auto)]
2982 #[cfg(ossl300)]
2983 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2984 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2985 }
2986
2987 #[corresponds(SSL_set_tmp_dh)]
2991 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2992 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2993 }
2994
2995 #[corresponds(SSL_set_tmp_dh_callback)]
2999 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3000 where
3001 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3002 {
3003 unsafe {
3004 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3006 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3007 }
3008 }
3009
3010 #[corresponds(SSL_set_tmp_ecdh)]
3014 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3015 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3016 }
3017
3018 #[corresponds(SSL_set_ecdh_auto)]
3024 #[cfg(any(all(ossl102, not(ossl110)), libressl))]
3025 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3026 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
3027 }
3028
3029 #[corresponds(SSL_set_alpn_protos)]
3035 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3036 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3037 unsafe {
3038 assert!(protocols.len() <= c_uint::MAX as usize);
3039 let r =
3040 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3041 if r == 0 {
3043 Ok(())
3044 } else {
3045 Err(ErrorStack::get())
3046 }
3047 }
3048 }
3049
3050 #[corresponds(SSL_get_current_cipher)]
3052 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3053 unsafe {
3054 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3055
3056 SslCipherRef::from_const_ptr_opt(ptr)
3057 }
3058 }
3059
3060 #[corresponds(SSL_state_string)]
3062 pub fn state_string(&self) -> &'static str {
3063 let state = unsafe {
3064 let ptr = ffi::SSL_state_string(self.as_ptr());
3065 CStr::from_ptr(ptr as *const _)
3066 };
3067
3068 str::from_utf8(state.to_bytes()).unwrap()
3069 }
3070
3071 #[corresponds(SSL_state_string_long)]
3073 pub fn state_string_long(&self) -> &'static str {
3074 let state = unsafe {
3075 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3076 CStr::from_ptr(ptr as *const _)
3077 };
3078
3079 str::from_utf8(state.to_bytes()).unwrap()
3080 }
3081
3082 #[corresponds(SSL_set_tlsext_host_name)]
3086 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3087 let cstr = CString::new(hostname).unwrap();
3088 unsafe {
3089 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3090 .map(|_| ())
3091 }
3092 }
3093
3094 #[corresponds(SSL_get_peer_certificate)]
3096 pub fn peer_certificate(&self) -> Option<X509> {
3097 unsafe {
3098 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3099 X509::from_ptr_opt(ptr)
3100 }
3101 }
3102
3103 #[corresponds(SSL_get_peer_cert_chain)]
3108 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3109 unsafe {
3110 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3111 StackRef::from_const_ptr_opt(ptr)
3112 }
3113 }
3114
3115 #[corresponds(SSL_get0_verified_chain)]
3125 #[cfg(ossl110)]
3126 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3127 unsafe {
3128 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3129 StackRef::from_const_ptr_opt(ptr)
3130 }
3131 }
3132
3133 #[corresponds(SSL_get_certificate)]
3135 pub fn certificate(&self) -> Option<&X509Ref> {
3136 unsafe {
3137 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3138 X509Ref::from_const_ptr_opt(ptr)
3139 }
3140 }
3141
3142 #[corresponds(SSL_get_privatekey)]
3146 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3147 unsafe {
3148 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3149 PKeyRef::from_const_ptr_opt(ptr)
3150 }
3151 }
3152
3153 #[corresponds(SSL_version)]
3155 pub fn version2(&self) -> Option<SslVersion> {
3156 unsafe {
3157 let r = ffi::SSL_version(self.as_ptr());
3158 if r == 0 {
3159 None
3160 } else {
3161 Some(SslVersion(r))
3162 }
3163 }
3164 }
3165
3166 #[corresponds(SSL_get_version)]
3168 pub fn version_str(&self) -> &'static str {
3169 let version = unsafe {
3170 let ptr = ffi::SSL_get_version(self.as_ptr());
3171 CStr::from_ptr(ptr as *const _)
3172 };
3173
3174 str::from_utf8(version.to_bytes()).unwrap()
3175 }
3176
3177 #[corresponds(SSL_get0_alpn_selected)]
3184 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3185 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3186 unsafe {
3187 let mut data: *const c_uchar = ptr::null();
3188 let mut len: c_uint = 0;
3189 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3192
3193 if data.is_null() {
3194 None
3195 } else {
3196 Some(util::from_raw_parts(data, len as usize))
3197 }
3198 }
3199 }
3200
3201 #[corresponds(SSL_set_tlsext_use_srtp)]
3203 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3204 unsafe {
3205 let cstr = CString::new(protocols).unwrap();
3206
3207 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3208 if r == 0 {
3210 Ok(())
3211 } else {
3212 Err(ErrorStack::get())
3213 }
3214 }
3215 }
3216
3217 #[corresponds(SSL_get_srtp_profiles)]
3221 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3222 unsafe {
3223 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3224
3225 StackRef::from_const_ptr_opt(chain)
3226 }
3227 }
3228
3229 #[corresponds(SSL_get_selected_srtp_profile)]
3233 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3234 unsafe {
3235 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3236
3237 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3238 }
3239 }
3240
3241 #[corresponds(SSL_pending)]
3246 pub fn pending(&self) -> usize {
3247 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3248 }
3249
3250 #[corresponds(SSL_get_servername)]
3263 pub fn servername(&self, type_: NameType) -> Option<&str> {
3265 self.servername_raw(type_)
3266 .and_then(|b| str::from_utf8(b).ok())
3267 }
3268
3269 #[corresponds(SSL_get_servername)]
3277 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3278 unsafe {
3279 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3280 if name.is_null() {
3281 None
3282 } else {
3283 Some(CStr::from_ptr(name as *const _).to_bytes())
3284 }
3285 }
3286 }
3287
3288 #[corresponds(SSL_set_SSL_CTX)]
3292 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3293 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3294 }
3295
3296 #[corresponds(SSL_get_SSL_CTX)]
3298 pub fn ssl_context(&self) -> &SslContextRef {
3299 unsafe {
3300 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3301 SslContextRef::from_ptr(ssl_ctx)
3302 }
3303 }
3304
3305 #[corresponds(SSL_get0_param)]
3309 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
3310 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3311 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3312 }
3313
3314 #[corresponds(SSL_get_verify_result)]
3316 pub fn verify_result(&self) -> X509VerifyResult {
3317 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3318 }
3319
3320 #[corresponds(SSL_get_session)]
3322 pub fn session(&self) -> Option<&SslSessionRef> {
3323 unsafe {
3324 let p = ffi::SSL_get_session(self.as_ptr());
3325 SslSessionRef::from_const_ptr_opt(p)
3326 }
3327 }
3328
3329 #[corresponds(SSL_get_client_random)]
3336 #[cfg(any(ossl110, libressl270))]
3337 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3338 unsafe {
3339 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3340 }
3341 }
3342
3343 #[corresponds(SSL_get_server_random)]
3350 #[cfg(any(ossl110, libressl270))]
3351 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3352 unsafe {
3353 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3354 }
3355 }
3356
3357 #[corresponds(SSL_export_keying_material)]
3359 pub fn export_keying_material(
3360 &self,
3361 out: &mut [u8],
3362 label: &str,
3363 context: Option<&[u8]>,
3364 ) -> Result<(), ErrorStack> {
3365 unsafe {
3366 let (context, contextlen, use_context) = match context {
3367 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3368 None => (ptr::null(), 0, 0),
3369 };
3370 cvt(ffi::SSL_export_keying_material(
3371 self.as_ptr(),
3372 out.as_mut_ptr() as *mut c_uchar,
3373 out.len(),
3374 label.as_ptr() as *const c_char,
3375 label.len(),
3376 context,
3377 contextlen,
3378 use_context,
3379 ))
3380 .map(|_| ())
3381 }
3382 }
3383
3384 #[corresponds(SSL_export_keying_material_early)]
3391 #[cfg(ossl111)]
3392 pub fn export_keying_material_early(
3393 &self,
3394 out: &mut [u8],
3395 label: &str,
3396 context: &[u8],
3397 ) -> Result<(), ErrorStack> {
3398 unsafe {
3399 cvt(ffi::SSL_export_keying_material_early(
3400 self.as_ptr(),
3401 out.as_mut_ptr() as *mut c_uchar,
3402 out.len(),
3403 label.as_ptr() as *const c_char,
3404 label.len(),
3405 context.as_ptr() as *const c_uchar,
3406 context.len(),
3407 ))
3408 .map(|_| ())
3409 }
3410 }
3411
3412 #[corresponds(SSL_set_session)]
3423 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3424 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3425 }
3426
3427 #[corresponds(SSL_session_reused)]
3429 pub fn session_reused(&self) -> bool {
3430 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3431 }
3432
3433 #[cfg(any(boringssl, awslc))]
3441 pub fn enable_ocsp_stapling(&mut self) {
3442 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3443 }
3444
3445 #[cfg(any(boringssl, awslc))]
3453 pub fn enable_signed_cert_timestamps(&mut self) {
3454 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3455 }
3456
3457 #[cfg(any(boringssl, awslc))]
3465 pub fn set_permute_extensions(&mut self, enabled: bool) {
3466 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3467 }
3468
3469 #[corresponds(SSL_enable_ct)]
3471 #[cfg(ossl111)]
3472 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3473 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3474 }
3475
3476 #[corresponds(SSL_ct_is_enabled)]
3478 #[cfg(ossl111)]
3479 pub fn ct_is_enabled(&self) -> bool {
3480 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3481 }
3482
3483 #[corresponds(SSL_set_tlsext_status_type)]
3485 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3486 unsafe {
3487 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3488 }
3489 }
3490
3491 #[corresponds(SSL_get_extms_support)]
3495 #[cfg(ossl110)]
3496 pub fn extms_support(&self) -> Option<bool> {
3497 unsafe {
3498 match ffi::SSL_get_extms_support(self.as_ptr()) {
3499 -1 => None,
3500 ret => Some(ret != 0),
3501 }
3502 }
3503 }
3504
3505 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3507 #[cfg(not(any(boringssl, awslc)))]
3508 pub fn ocsp_status(&self) -> Option<&[u8]> {
3509 unsafe {
3510 let mut p = ptr::null_mut();
3511 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3512
3513 if len < 0 {
3514 None
3515 } else {
3516 Some(util::from_raw_parts(p as *const u8, len as usize))
3517 }
3518 }
3519 }
3520
3521 #[corresponds(SSL_get0_ocsp_response)]
3523 #[cfg(any(boringssl, awslc))]
3524 pub fn ocsp_status(&self) -> Option<&[u8]> {
3525 unsafe {
3526 let mut p = ptr::null();
3527 let mut len: usize = 0;
3528 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3529
3530 if len == 0 {
3531 None
3532 } else {
3533 Some(util::from_raw_parts(p as *const u8, len))
3534 }
3535 }
3536 }
3537
3538 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3540 #[cfg(not(any(boringssl, awslc)))]
3541 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3542 unsafe {
3543 assert!(response.len() <= c_int::MAX as usize);
3544 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3545 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3546 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3547 self.as_ptr(),
3548 p as *mut c_uchar,
3549 response.len() as c_long,
3550 ) as c_int)
3551 .map(|_| ())
3552 .map_err(|e| {
3553 ffi::OPENSSL_free(p);
3554 e
3555 })
3556 }
3557 }
3558
3559 #[corresponds(SSL_set_ocsp_response)]
3561 #[cfg(any(boringssl, awslc))]
3562 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3563 unsafe {
3564 cvt(ffi::SSL_set_ocsp_response(
3565 self.as_ptr(),
3566 response.as_ptr(),
3567 response.len(),
3568 ))
3569 .map(|_| ())
3570 }
3571 }
3572
3573 #[corresponds(SSL_is_server)]
3575 pub fn is_server(&self) -> bool {
3576 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3577 }
3578
3579 #[corresponds(SSL_set_ex_data)]
3585 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3586 match self.ex_data_mut(index) {
3587 Some(v) => *v = data,
3588 None => unsafe {
3589 let data = Box::new(data);
3590 ffi::SSL_set_ex_data(
3591 self.as_ptr(),
3592 index.as_raw(),
3593 Box::into_raw(data) as *mut c_void,
3594 );
3595 },
3596 }
3597 }
3598
3599 #[corresponds(SSL_get_ex_data)]
3601 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3602 unsafe {
3603 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3604 if data.is_null() {
3605 None
3606 } else {
3607 Some(&*(data as *const T))
3608 }
3609 }
3610 }
3611
3612 #[corresponds(SSL_get_ex_data)]
3614 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3615 unsafe {
3616 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3617 if data.is_null() {
3618 None
3619 } else {
3620 Some(&mut *(data as *mut T))
3621 }
3622 }
3623 }
3624
3625 #[corresponds(SSL_set_max_early_data)]
3629 #[cfg(any(ossl111, libressl340))]
3630 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3631 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3632 Ok(())
3633 } else {
3634 Err(ErrorStack::get())
3635 }
3636 }
3637
3638 #[corresponds(SSL_get_max_early_data)]
3642 #[cfg(any(ossl111, libressl340))]
3643 pub fn max_early_data(&self) -> u32 {
3644 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3645 }
3646
3647 #[corresponds(SSL_get_finished)]
3652 pub fn finished(&self, buf: &mut [u8]) -> usize {
3653 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3654 }
3655
3656 #[corresponds(SSL_get_peer_finished)]
3662 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3663 unsafe {
3664 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3665 }
3666 }
3667
3668 #[corresponds(SSL_is_init_finished)]
3670 #[cfg(ossl110)]
3671 pub fn is_init_finished(&self) -> bool {
3672 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3673 }
3674
3675 #[corresponds(SSL_client_hello_isv2)]
3681 #[cfg(ossl111)]
3682 pub fn client_hello_isv2(&self) -> bool {
3683 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3684 }
3685
3686 #[corresponds(SSL_client_hello_get0_legacy_version)]
3692 #[cfg(ossl111)]
3693 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3694 unsafe {
3695 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3696 if version == 0 {
3697 None
3698 } else {
3699 Some(SslVersion(version as c_int))
3700 }
3701 }
3702 }
3703
3704 #[corresponds(SSL_client_hello_get0_random)]
3710 #[cfg(ossl111)]
3711 pub fn client_hello_random(&self) -> Option<&[u8]> {
3712 unsafe {
3713 let mut ptr = ptr::null();
3714 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3715 if len == 0 {
3716 None
3717 } else {
3718 Some(util::from_raw_parts(ptr, len))
3719 }
3720 }
3721 }
3722
3723 #[corresponds(SSL_client_hello_get0_session_id)]
3729 #[cfg(ossl111)]
3730 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3731 unsafe {
3732 let mut ptr = ptr::null();
3733 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3734 if len == 0 {
3735 None
3736 } else {
3737 Some(util::from_raw_parts(ptr, len))
3738 }
3739 }
3740 }
3741
3742 #[corresponds(SSL_client_hello_get0_ciphers)]
3748 #[cfg(ossl111)]
3749 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3750 unsafe {
3751 let mut ptr = ptr::null();
3752 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3753 if len == 0 {
3754 None
3755 } else {
3756 Some(util::from_raw_parts(ptr, len))
3757 }
3758 }
3759 }
3760
3761 #[cfg(ossl111)]
3767 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3768 unsafe {
3769 let mut ptr = ptr::null();
3770 let mut len = 0usize;
3771 let r = ffi::SSL_client_hello_get0_ext(
3772 self.as_ptr(),
3773 ext_type.as_raw() as _,
3774 &mut ptr,
3775 &mut len,
3776 );
3777 if r == 0 {
3778 None
3779 } else {
3780 Some(util::from_raw_parts(ptr, len))
3781 }
3782 }
3783 }
3784
3785 #[corresponds(SSL_bytes_to_cipher_list)]
3790 #[cfg(ossl111)]
3791 pub fn bytes_to_cipher_list(
3792 &self,
3793 bytes: &[u8],
3794 isv2format: bool,
3795 ) -> Result<CipherLists, ErrorStack> {
3796 unsafe {
3797 let ptr = bytes.as_ptr();
3798 let len = bytes.len();
3799 let mut sk = ptr::null_mut();
3800 let mut scsvs = ptr::null_mut();
3801 let res = ffi::SSL_bytes_to_cipher_list(
3802 self.as_ptr(),
3803 ptr,
3804 len,
3805 isv2format as c_int,
3806 &mut sk,
3807 &mut scsvs,
3808 );
3809 if res == 1 {
3810 Ok(CipherLists {
3811 suites: Stack::from_ptr(sk),
3812 signalling_suites: Stack::from_ptr(scsvs),
3813 })
3814 } else {
3815 Err(ErrorStack::get())
3816 }
3817 }
3818 }
3819
3820 #[corresponds(SSL_client_hello_get0_compression_methods)]
3826 #[cfg(ossl111)]
3827 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3828 unsafe {
3829 let mut ptr = ptr::null();
3830 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3831 if len == 0 {
3832 None
3833 } else {
3834 Some(util::from_raw_parts(ptr, len))
3835 }
3836 }
3837 }
3838
3839 #[corresponds(SSL_set_mtu)]
3841 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3842 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3843 }
3844
3845 #[corresponds(SSL_get_psk_identity_hint)]
3849 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3850 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3851 unsafe {
3852 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3853 if ptr.is_null() {
3854 None
3855 } else {
3856 Some(CStr::from_ptr(ptr).to_bytes())
3857 }
3858 }
3859 }
3860
3861 #[corresponds(SSL_get_psk_identity)]
3863 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3864 pub fn psk_identity(&self) -> Option<&[u8]> {
3865 unsafe {
3866 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3867 if ptr.is_null() {
3868 None
3869 } else {
3870 Some(CStr::from_ptr(ptr).to_bytes())
3871 }
3872 }
3873 }
3874
3875 #[corresponds(SSL_add0_chain_cert)]
3876 #[cfg(any(ossl102, boringssl, awslc))]
3877 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3878 unsafe {
3879 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3880 mem::forget(chain);
3881 }
3882 Ok(())
3883 }
3884
3885 #[cfg(not(any(boringssl, awslc)))]
3887 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3888 unsafe {
3889 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3890 };
3891 Ok(())
3892 }
3893
3894 #[corresponds(SSL_use_Private_Key_file)]
3896 pub fn set_private_key_file<P: AsRef<Path>>(
3897 &mut self,
3898 path: P,
3899 ssl_file_type: SslFiletype,
3900 ) -> Result<(), ErrorStack> {
3901 let p = path.as_ref().as_os_str().to_str().unwrap();
3902 let key_file = CString::new(p).unwrap();
3903 unsafe {
3904 cvt(ffi::SSL_use_PrivateKey_file(
3905 self.as_ptr(),
3906 key_file.as_ptr(),
3907 ssl_file_type.as_raw(),
3908 ))?;
3909 };
3910 Ok(())
3911 }
3912
3913 #[corresponds(SSL_use_PrivateKey)]
3915 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3916 unsafe {
3917 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3918 };
3919 Ok(())
3920 }
3921
3922 #[cfg(tongsuo)]
3923 #[corresponds(SSL_use_enc_Private_Key_file)]
3924 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3925 &mut self,
3926 path: P,
3927 ssl_file_type: SslFiletype,
3928 ) -> Result<(), ErrorStack> {
3929 let p = path.as_ref().as_os_str().to_str().unwrap();
3930 let key_file = CString::new(p).unwrap();
3931 unsafe {
3932 cvt(ffi::SSL_use_enc_PrivateKey_file(
3933 self.as_ptr(),
3934 key_file.as_ptr(),
3935 ssl_file_type.as_raw(),
3936 ))?;
3937 };
3938 Ok(())
3939 }
3940
3941 #[cfg(tongsuo)]
3942 #[corresponds(SSL_use_enc_PrivateKey)]
3943 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3944 unsafe {
3945 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3946 };
3947 Ok(())
3948 }
3949
3950 #[cfg(tongsuo)]
3951 #[corresponds(SSL_use_sign_Private_Key_file)]
3952 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3953 &mut self,
3954 path: P,
3955 ssl_file_type: SslFiletype,
3956 ) -> Result<(), ErrorStack> {
3957 let p = path.as_ref().as_os_str().to_str().unwrap();
3958 let key_file = CString::new(p).unwrap();
3959 unsafe {
3960 cvt(ffi::SSL_use_sign_PrivateKey_file(
3961 self.as_ptr(),
3962 key_file.as_ptr(),
3963 ssl_file_type.as_raw(),
3964 ))?;
3965 };
3966 Ok(())
3967 }
3968
3969 #[cfg(tongsuo)]
3970 #[corresponds(SSL_use_sign_PrivateKey)]
3971 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3972 unsafe {
3973 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3974 };
3975 Ok(())
3976 }
3977
3978 #[corresponds(SSL_use_certificate)]
3980 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3981 unsafe {
3982 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3983 };
3984 Ok(())
3985 }
3986
3987 #[cfg(tongsuo)]
3988 #[corresponds(SSL_use_enc_certificate)]
3989 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3990 unsafe {
3991 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
3992 };
3993 Ok(())
3994 }
3995
3996 #[cfg(tongsuo)]
3997 #[corresponds(SSL_use_sign_certificate)]
3998 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3999 unsafe {
4000 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4001 };
4002 Ok(())
4003 }
4004
4005 #[corresponds(SSL_use_certificate_chain_file)]
4011 #[cfg(any(ossl110, libressl332))]
4012 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4013 &mut self,
4014 path: P,
4015 ) -> Result<(), ErrorStack> {
4016 let p = path.as_ref().as_os_str().to_str().unwrap();
4017 let cert_file = CString::new(p).unwrap();
4018 unsafe {
4019 cvt(ffi::SSL_use_certificate_chain_file(
4020 self.as_ptr(),
4021 cert_file.as_ptr(),
4022 ))?;
4023 };
4024 Ok(())
4025 }
4026
4027 #[corresponds(SSL_add_client_CA)]
4029 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4030 unsafe {
4031 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4032 };
4033 Ok(())
4034 }
4035
4036 #[corresponds(SSL_set_client_CA_list)]
4038 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4039 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4040 mem::forget(list);
4041 }
4042
4043 #[corresponds(SSL_set_min_proto_version)]
4050 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4051 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4052 unsafe {
4053 cvt(ffi::SSL_set_min_proto_version(
4054 self.as_ptr(),
4055 version.map_or(0, |v| v.0 as _),
4056 ))
4057 .map(|_| ())
4058 }
4059 }
4060
4061 #[corresponds(SSL_set_max_proto_version)]
4068 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4069 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4070 unsafe {
4071 cvt(ffi::SSL_set_max_proto_version(
4072 self.as_ptr(),
4073 version.map_or(0, |v| v.0 as _),
4074 ))
4075 .map(|_| ())
4076 }
4077 }
4078
4079 #[corresponds(SSL_set_ciphersuites)]
4088 #[cfg(any(ossl111, libressl340))]
4089 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4090 let cipher_list = CString::new(cipher_list).unwrap();
4091 unsafe {
4092 cvt(ffi::SSL_set_ciphersuites(
4093 self.as_ptr(),
4094 cipher_list.as_ptr() as *const _,
4095 ))
4096 .map(|_| ())
4097 }
4098 }
4099
4100 #[corresponds(SSL_set_cipher_list)]
4108 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4109 let cipher_list = CString::new(cipher_list).unwrap();
4110 unsafe {
4111 cvt(ffi::SSL_set_cipher_list(
4112 self.as_ptr(),
4113 cipher_list.as_ptr() as *const _,
4114 ))
4115 .map(|_| ())
4116 }
4117 }
4118
4119 #[corresponds(SSL_set_cert_store)]
4121 #[cfg(any(ossl102, boringssl, awslc))]
4122 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4123 unsafe {
4124 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4125 mem::forget(cert_store);
4126 Ok(())
4127 }
4128 }
4129
4130 #[corresponds(SSL_set_num_tickets)]
4135 #[cfg(ossl111)]
4136 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4137 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4138 }
4139
4140 #[corresponds(SSL_get_num_tickets)]
4145 #[cfg(ossl111)]
4146 pub fn num_tickets(&self) -> usize {
4147 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4148 }
4149
4150 #[corresponds(SSL_set_security_level)]
4155 #[cfg(any(ossl110, libressl360))]
4156 pub fn set_security_level(&mut self, level: u32) {
4157 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4158 }
4159
4160 #[corresponds(SSL_get_security_level)]
4165 #[cfg(any(ossl110, libressl360))]
4166 pub fn security_level(&self) -> u32 {
4167 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4168 }
4169
4170 #[corresponds(SSL_get_peer_tmp_key)]
4175 #[cfg(ossl300)]
4176 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4177 unsafe {
4178 let mut key = ptr::null_mut();
4179 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4180 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4181 Err(e) => Err(e),
4182 }
4183 }
4184 }
4185
4186 #[corresponds(SSL_get_tmp_key)]
4191 #[cfg(ossl300)]
4192 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4193 unsafe {
4194 let mut key = ptr::null_mut();
4195 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4196 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4197 Err(e) => Err(e),
4198 }
4199 }
4200 }
4201}
4202
4203#[derive(Debug)]
4205pub struct MidHandshakeSslStream<S> {
4206 stream: SslStream<S>,
4207 error: Error,
4208}
4209
4210impl<S> MidHandshakeSslStream<S> {
4211 pub fn get_ref(&self) -> &S {
4213 self.stream.get_ref()
4214 }
4215
4216 pub fn get_mut(&mut self) -> &mut S {
4218 self.stream.get_mut()
4219 }
4220
4221 pub fn ssl(&self) -> &SslRef {
4223 self.stream.ssl()
4224 }
4225
4226 pub fn ssl_mut(&mut self) -> &mut SslRef {
4228 self.stream.ssl_mut()
4229 }
4230
4231 pub fn error(&self) -> &Error {
4233 &self.error
4234 }
4235
4236 pub fn into_error(self) -> Error {
4238 self.error
4239 }
4240}
4241
4242impl<S> MidHandshakeSslStream<S>
4243where
4244 S: Read + Write,
4245{
4246 #[corresponds(SSL_do_handshake)]
4249 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4250 match self.stream.do_handshake() {
4251 Ok(()) => Ok(self.stream),
4252 Err(error) => {
4253 self.error = error;
4254 match self.error.code() {
4255 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4256 Err(HandshakeError::WouldBlock(self))
4257 }
4258 _ => Err(HandshakeError::Failure(self)),
4259 }
4260 }
4261 }
4262 }
4263}
4264
4265pub struct SslStream<S> {
4267 ssl: ManuallyDrop<Ssl>,
4268 method: ManuallyDrop<BioMethod>,
4269 _p: PhantomData<S>,
4270}
4271
4272impl<S> Drop for SslStream<S> {
4273 fn drop(&mut self) {
4274 unsafe {
4276 ManuallyDrop::drop(&mut self.ssl);
4277 ManuallyDrop::drop(&mut self.method);
4278 }
4279 }
4280}
4281
4282impl<S> fmt::Debug for SslStream<S>
4283where
4284 S: fmt::Debug,
4285{
4286 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4287 fmt.debug_struct("SslStream")
4288 .field("stream", &self.get_ref())
4289 .field("ssl", &self.ssl())
4290 .finish()
4291 }
4292}
4293
4294impl<S: Read + Write> SslStream<S> {
4295 #[corresponds(SSL_set_bio)]
4303 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4304 let (bio, method) = bio::new(stream)?;
4305 unsafe {
4306 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4307 }
4308
4309 Ok(SslStream {
4310 ssl: ManuallyDrop::new(ssl),
4311 method: ManuallyDrop::new(method),
4312 _p: PhantomData,
4313 })
4314 }
4315
4316 #[corresponds(SSL_read_early_data)]
4325 #[cfg(any(ossl111, libressl340))]
4326 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4327 let mut read = 0;
4328 let ret = unsafe {
4329 ffi::SSL_read_early_data(
4330 self.ssl.as_ptr(),
4331 buf.as_ptr() as *mut c_void,
4332 buf.len(),
4333 &mut read,
4334 )
4335 };
4336 match ret {
4337 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4338 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4339 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4340 _ => unreachable!(),
4341 }
4342 }
4343
4344 #[corresponds(SSL_write_early_data)]
4351 #[cfg(any(ossl111, libressl340))]
4352 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4353 let mut written = 0;
4354 let ret = unsafe {
4355 ffi::SSL_write_early_data(
4356 self.ssl.as_ptr(),
4357 buf.as_ptr() as *const c_void,
4358 buf.len(),
4359 &mut written,
4360 )
4361 };
4362 if ret > 0 {
4363 Ok(written)
4364 } else {
4365 Err(self.make_error(ret))
4366 }
4367 }
4368
4369 #[corresponds(SSL_connect)]
4376 pub fn connect(&mut self) -> Result<(), Error> {
4377 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4378 if ret > 0 {
4379 Ok(())
4380 } else {
4381 Err(self.make_error(ret))
4382 }
4383 }
4384
4385 #[corresponds(SSL_accept)]
4392 pub fn accept(&mut self) -> Result<(), Error> {
4393 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4394 if ret > 0 {
4395 Ok(())
4396 } else {
4397 Err(self.make_error(ret))
4398 }
4399 }
4400
4401 #[corresponds(SSL_do_handshake)]
4405 pub fn do_handshake(&mut self) -> Result<(), Error> {
4406 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4407 if ret > 0 {
4408 Ok(())
4409 } else {
4410 Err(self.make_error(ret))
4411 }
4412 }
4413
4414 #[corresponds(SSL_stateless)]
4425 #[cfg(ossl111)]
4426 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4427 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4428 1 => Ok(true),
4429 0 => Ok(false),
4430 -1 => Err(ErrorStack::get()),
4431 _ => unreachable!(),
4432 }
4433 }
4434
4435 #[corresponds(SSL_read_ex)]
4442 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4443 loop {
4444 match self.ssl_read_uninit(buf) {
4445 Ok(n) => return Ok(n),
4446 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4447 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4448 return Ok(0);
4449 }
4450 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4451 Err(e) => {
4452 return Err(e
4453 .into_io_error()
4454 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4455 }
4456 }
4457 }
4458 }
4459
4460 #[corresponds(SSL_read_ex)]
4465 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4466 unsafe {
4468 self.ssl_read_uninit(util::from_raw_parts_mut(
4469 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4470 buf.len(),
4471 ))
4472 }
4473 }
4474
4475 #[corresponds(SSL_read_ex)]
4482 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4483 cfg_if! {
4484 if #[cfg(any(ossl111, libressl350))] {
4485 let mut readbytes = 0;
4486 let ret = unsafe {
4487 ffi::SSL_read_ex(
4488 self.ssl().as_ptr(),
4489 buf.as_mut_ptr().cast(),
4490 buf.len(),
4491 &mut readbytes,
4492 )
4493 };
4494
4495 if ret > 0 {
4496 Ok(readbytes)
4497 } else {
4498 Err(self.make_error(ret))
4499 }
4500 } else {
4501 if buf.is_empty() {
4502 return Ok(0);
4503 }
4504
4505 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4506 let ret = unsafe {
4507 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4508 };
4509 if ret > 0 {
4510 Ok(ret as usize)
4511 } else {
4512 Err(self.make_error(ret))
4513 }
4514 }
4515 }
4516 }
4517
4518 #[corresponds(SSL_write_ex)]
4523 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4524 cfg_if! {
4525 if #[cfg(any(ossl111, libressl350))] {
4526 let mut written = 0;
4527 let ret = unsafe {
4528 ffi::SSL_write_ex(
4529 self.ssl().as_ptr(),
4530 buf.as_ptr().cast(),
4531 buf.len(),
4532 &mut written,
4533 )
4534 };
4535
4536 if ret > 0 {
4537 Ok(written)
4538 } else {
4539 Err(self.make_error(ret))
4540 }
4541 } else {
4542 if buf.is_empty() {
4543 return Ok(0);
4544 }
4545
4546 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4547 let ret = unsafe {
4548 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4549 };
4550 if ret > 0 {
4551 Ok(ret as usize)
4552 } else {
4553 Err(self.make_error(ret))
4554 }
4555 }
4556 }
4557 }
4558
4559 #[corresponds(SSL_peek_ex)]
4561 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4562 cfg_if! {
4563 if #[cfg(any(ossl111, libressl350))] {
4564 let mut readbytes = 0;
4565 let ret = unsafe {
4566 ffi::SSL_peek_ex(
4567 self.ssl().as_ptr(),
4568 buf.as_mut_ptr().cast(),
4569 buf.len(),
4570 &mut readbytes,
4571 )
4572 };
4573
4574 if ret > 0 {
4575 Ok(readbytes)
4576 } else {
4577 Err(self.make_error(ret))
4578 }
4579 } else {
4580 if buf.is_empty() {
4581 return Ok(0);
4582 }
4583
4584 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4585 let ret = unsafe {
4586 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4587 };
4588 if ret > 0 {
4589 Ok(ret as usize)
4590 } else {
4591 Err(self.make_error(ret))
4592 }
4593 }
4594 }
4595 }
4596
4597 #[corresponds(SSL_shutdown)]
4607 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4608 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4609 0 => Ok(ShutdownResult::Sent),
4610 1 => Ok(ShutdownResult::Received),
4611 n => Err(self.make_error(n)),
4612 }
4613 }
4614
4615 #[corresponds(SSL_get_shutdown)]
4617 pub fn get_shutdown(&mut self) -> ShutdownState {
4618 unsafe {
4619 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4620 ShutdownState::from_bits_retain(bits)
4621 }
4622 }
4623
4624 #[corresponds(SSL_set_shutdown)]
4629 pub fn set_shutdown(&mut self, state: ShutdownState) {
4630 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4631 }
4632}
4633
4634impl<S> SslStream<S> {
4635 fn make_error(&mut self, ret: c_int) -> Error {
4636 self.check_panic();
4637
4638 let code = self.ssl.get_error(ret);
4639
4640 let cause = match code {
4641 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4642 ErrorCode::SYSCALL => {
4643 let errs = ErrorStack::get();
4644 if errs.errors().is_empty() {
4645 self.get_bio_error().map(InnerError::Io)
4646 } else {
4647 Some(InnerError::Ssl(errs))
4648 }
4649 }
4650 ErrorCode::ZERO_RETURN => None,
4651 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4652 self.get_bio_error().map(InnerError::Io)
4653 }
4654 _ => None,
4655 };
4656
4657 Error { code, cause }
4658 }
4659
4660 fn check_panic(&mut self) {
4661 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4662 resume_unwind(err)
4663 }
4664 }
4665
4666 fn get_bio_error(&mut self) -> Option<io::Error> {
4667 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4668 }
4669
4670 pub fn get_ref(&self) -> &S {
4672 unsafe {
4673 let bio = self.ssl.get_raw_rbio();
4674 bio::get_ref(bio)
4675 }
4676 }
4677
4678 pub fn get_mut(&mut self) -> &mut S {
4685 unsafe {
4686 let bio = self.ssl.get_raw_rbio();
4687 bio::get_mut(bio)
4688 }
4689 }
4690
4691 pub fn ssl(&self) -> &SslRef {
4693 &self.ssl
4694 }
4695
4696 pub fn ssl_mut(&mut self) -> &mut SslRef {
4698 &mut self.ssl
4699 }
4700}
4701
4702impl<S: Read + Write> Read for SslStream<S> {
4703 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4704 unsafe {
4706 self.read_uninit(util::from_raw_parts_mut(
4707 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4708 buf.len(),
4709 ))
4710 }
4711 }
4712}
4713
4714impl<S: Read + Write> Write for SslStream<S> {
4715 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4716 loop {
4717 match self.ssl_write(buf) {
4718 Ok(n) => return Ok(n),
4719 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4720 Err(e) => {
4721 return Err(e
4722 .into_io_error()
4723 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4724 }
4725 }
4726 }
4727 }
4728
4729 fn flush(&mut self) -> io::Result<()> {
4730 self.get_mut().flush()
4731 }
4732}
4733
4734#[deprecated(
4736 since = "0.10.32",
4737 note = "use the methods directly on Ssl/SslStream instead"
4738)]
4739pub struct SslStreamBuilder<S> {
4740 inner: SslStream<S>,
4741}
4742
4743#[allow(deprecated)]
4744impl<S> SslStreamBuilder<S>
4745where
4746 S: Read + Write,
4747{
4748 pub fn new(ssl: Ssl, stream: S) -> Self {
4750 Self {
4751 inner: SslStream::new(ssl, stream).unwrap(),
4752 }
4753 }
4754
4755 #[corresponds(SSL_stateless)]
4766 #[cfg(ossl111)]
4767 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4768 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4769 1 => Ok(true),
4770 0 => Ok(false),
4771 -1 => Err(ErrorStack::get()),
4772 _ => unreachable!(),
4773 }
4774 }
4775
4776 #[corresponds(SSL_set_connect_state)]
4778 pub fn set_connect_state(&mut self) {
4779 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4780 }
4781
4782 #[corresponds(SSL_set_accept_state)]
4784 pub fn set_accept_state(&mut self) {
4785 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4786 }
4787
4788 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4790 match self.inner.connect() {
4791 Ok(()) => Ok(self.inner),
4792 Err(error) => match error.code() {
4793 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4794 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4795 stream: self.inner,
4796 error,
4797 }))
4798 }
4799 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4800 stream: self.inner,
4801 error,
4802 })),
4803 },
4804 }
4805 }
4806
4807 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4809 match self.inner.accept() {
4810 Ok(()) => Ok(self.inner),
4811 Err(error) => match error.code() {
4812 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4813 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4814 stream: self.inner,
4815 error,
4816 }))
4817 }
4818 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4819 stream: self.inner,
4820 error,
4821 })),
4822 },
4823 }
4824 }
4825
4826 #[corresponds(SSL_do_handshake)]
4830 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4831 match self.inner.do_handshake() {
4832 Ok(()) => Ok(self.inner),
4833 Err(error) => match error.code() {
4834 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4835 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4836 stream: self.inner,
4837 error,
4838 }))
4839 }
4840 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4841 stream: self.inner,
4842 error,
4843 })),
4844 },
4845 }
4846 }
4847
4848 #[corresponds(SSL_read_early_data)]
4858 #[cfg(any(ossl111, libressl340))]
4859 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4860 self.inner.read_early_data(buf)
4861 }
4862
4863 #[corresponds(SSL_write_early_data)]
4870 #[cfg(any(ossl111, libressl340))]
4871 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4872 self.inner.write_early_data(buf)
4873 }
4874}
4875
4876#[allow(deprecated)]
4877impl<S> SslStreamBuilder<S> {
4878 pub fn get_ref(&self) -> &S {
4880 unsafe {
4881 let bio = self.inner.ssl.get_raw_rbio();
4882 bio::get_ref(bio)
4883 }
4884 }
4885
4886 pub fn get_mut(&mut self) -> &mut S {
4893 unsafe {
4894 let bio = self.inner.ssl.get_raw_rbio();
4895 bio::get_mut(bio)
4896 }
4897 }
4898
4899 pub fn ssl(&self) -> &SslRef {
4901 &self.inner.ssl
4902 }
4903
4904 pub fn ssl_mut(&mut self) -> &mut SslRef {
4906 &mut self.inner.ssl
4907 }
4908}
4909
4910#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4912pub enum ShutdownResult {
4913 Sent,
4915
4916 Received,
4918}
4919
4920bitflags! {
4921 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4923 #[repr(transparent)]
4924 pub struct ShutdownState: c_int {
4925 const SENT = ffi::SSL_SENT_SHUTDOWN;
4927 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4929 }
4930}
4931
4932cfg_if! {
4933 if #[cfg(any(boringssl, ossl110, libressl273, awslc))] {
4934 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4935 } else {
4936 #[allow(bad_style)]
4937 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4938 ffi::CRYPTO_add_lock(
4939 &mut (*ssl).references,
4940 1,
4941 ffi::CRYPTO_LOCK_SSL_CTX,
4942 "mod.rs\0".as_ptr() as *const _,
4943 line!() as c_int,
4944 );
4945 0
4946 }
4947
4948 #[allow(bad_style)]
4949 pub unsafe fn SSL_SESSION_get_master_key(
4950 session: *const ffi::SSL_SESSION,
4951 out: *mut c_uchar,
4952 mut outlen: usize,
4953 ) -> usize {
4954 if outlen == 0 {
4955 return (*session).master_key_length as usize;
4956 }
4957 if outlen > (*session).master_key_length as usize {
4958 outlen = (*session).master_key_length as usize;
4959 }
4960 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
4961 outlen
4962 }
4963
4964 #[allow(bad_style)]
4965 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
4966 (*s).server
4967 }
4968
4969 #[allow(bad_style)]
4970 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
4971 ffi::CRYPTO_add_lock(
4972 &mut (*ses).references,
4973 1,
4974 ffi::CRYPTO_LOCK_SSL_CTX,
4975 "mod.rs\0".as_ptr() as *const _,
4976 line!() as c_int,
4977 );
4978 0
4979 }
4980 }
4981}
4982
4983cfg_if! {
4984 if #[cfg(ossl300)] {
4985 use ffi::SSL_get1_peer_certificate;
4986 } else {
4987 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4988 }
4989}
4990cfg_if! {
4991 if #[cfg(any(boringssl, ossl110, libressl291, awslc))] {
4992 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
4993 } else {
4994 use ffi::{
4995 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
4996 SSLv23_server_method as TLS_server_method,
4997 };
4998 }
4999}
5000cfg_if! {
5001 if #[cfg(ossl110)] {
5002 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5003 ffi::CRYPTO_get_ex_new_index(
5004 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5005 0,
5006 ptr::null_mut(),
5007 None,
5008 None,
5009 f,
5010 )
5011 }
5012
5013 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5014 ffi::CRYPTO_get_ex_new_index(
5015 ffi::CRYPTO_EX_INDEX_SSL,
5016 0,
5017 ptr::null_mut(),
5018 None,
5019 None,
5020 f,
5021 )
5022 }
5023 } else {
5024 use std::sync::Once;
5025
5026 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5027 static ONCE: Once = Once::new();
5029 ONCE.call_once(|| {
5030 cfg_if! {
5031 if #[cfg(not(any(boringssl, awslc)))] {
5032 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5033 } else {
5034 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5035 }
5036 }
5037 });
5038
5039 cfg_if! {
5040 if #[cfg(not(any(boringssl, awslc)))] {
5041 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5042 } else {
5043 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5044 }
5045 }
5046 }
5047
5048 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5049 static ONCE: Once = Once::new();
5051 ONCE.call_once(|| {
5052 #[cfg(not(any(boringssl, awslc)))]
5053 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5054 #[cfg(any(boringssl, awslc))]
5055 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5056 });
5057
5058 #[cfg(not(any(boringssl, awslc)))]
5059 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5060 #[cfg(any(boringssl, awslc))]
5061 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5062 }
5063 }
5064}