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_set_info_callback)]
2181 pub fn set_info_callback<F>(&mut self, callback: F)
2182 where
2183 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2184 {
2185 unsafe {
2186 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2187 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2188 }
2189 }
2190
2191 #[corresponds(SSL_CTX_sess_set_cache_size)]
2195 #[allow(clippy::useless_conversion)]
2196 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2197 unsafe {
2198 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2199 }
2200 }
2201
2202 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2206 #[cfg(ossl102)]
2207 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2208 let sigalgs = CString::new(sigalgs).unwrap();
2209 unsafe {
2210 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2211 .map(|_| ())
2212 }
2213 }
2214
2215 #[corresponds(SSL_CTX_set1_groups_list)]
2219 #[cfg(any(ossl111, boringssl, libressl251, awslc))]
2220 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2221 let groups = CString::new(groups).unwrap();
2222 unsafe {
2223 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2224 }
2225 }
2226
2227 #[corresponds(SSL_CTX_set_num_tickets)]
2232 #[cfg(any(ossl111, boringssl, awslc))]
2233 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2234 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2235 }
2236
2237 #[corresponds(SSL_CTX_set_security_level)]
2242 #[cfg(any(ossl110, libressl360))]
2243 pub fn set_security_level(&mut self, level: u32) {
2244 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2245 }
2246
2247 pub fn build(self) -> SslContext {
2249 self.0
2250 }
2251}
2252
2253foreign_type_and_impl_send_sync! {
2254 type CType = ffi::SSL_CTX;
2255 fn drop = ffi::SSL_CTX_free;
2256
2257 pub struct SslContext;
2262
2263 pub struct SslContextRef;
2267}
2268
2269impl Clone for SslContext {
2270 fn clone(&self) -> Self {
2271 (**self).to_owned()
2272 }
2273}
2274
2275impl ToOwned for SslContextRef {
2276 type Owned = SslContext;
2277
2278 fn to_owned(&self) -> Self::Owned {
2279 unsafe {
2280 SSL_CTX_up_ref(self.as_ptr());
2281 SslContext::from_ptr(self.as_ptr())
2282 }
2283 }
2284}
2285
2286impl fmt::Debug for SslContext {
2288 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2289 write!(fmt, "SslContext")
2290 }
2291}
2292
2293impl SslContext {
2294 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2296 SslContextBuilder::new(method)
2297 }
2298
2299 #[corresponds(SSL_CTX_get_ex_new_index)]
2304 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2305 where
2306 T: 'static + Sync + Send,
2307 {
2308 unsafe {
2309 ffi::init();
2310 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2311 Ok(Index::from_raw(idx))
2312 }
2313 }
2314
2315 fn cached_ex_index<T>() -> Index<SslContext, T>
2317 where
2318 T: 'static + Sync + Send,
2319 {
2320 unsafe {
2321 let idx = *INDEXES
2322 .lock()
2323 .unwrap_or_else(|e| e.into_inner())
2324 .entry(TypeId::of::<T>())
2325 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2326 Index::from_raw(idx)
2327 }
2328 }
2329}
2330
2331impl SslContextRef {
2332 #[corresponds(SSL_CTX_get0_certificate)]
2336 #[cfg(any(ossl102, libressl270))]
2337 pub fn certificate(&self) -> Option<&X509Ref> {
2338 unsafe {
2339 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2340 X509Ref::from_const_ptr_opt(ptr)
2341 }
2342 }
2343
2344 #[corresponds(SSL_CTX_get0_privatekey)]
2348 #[cfg(any(ossl102, libressl340))]
2349 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2350 unsafe {
2351 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2352 PKeyRef::from_const_ptr_opt(ptr)
2353 }
2354 }
2355
2356 #[corresponds(SSL_CTX_get_cert_store)]
2358 pub fn cert_store(&self) -> &X509StoreRef {
2359 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2360 }
2361
2362 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2364 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2365 unsafe {
2366 let mut chain = ptr::null_mut();
2367 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2368 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2369 }
2370 }
2371
2372 #[corresponds(SSL_CTX_get_ex_data)]
2374 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2375 unsafe {
2376 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2377 if data.is_null() {
2378 None
2379 } else {
2380 Some(&*(data as *const T))
2381 }
2382 }
2383 }
2384
2385 #[corresponds(SSL_CTX_get_max_early_data)]
2389 #[cfg(any(ossl111, libressl340))]
2390 pub fn max_early_data(&self) -> u32 {
2391 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2392 }
2393
2394 #[corresponds(SSL_CTX_add_session)]
2403 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2404 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2405 }
2406
2407 #[corresponds(SSL_CTX_remove_session)]
2416 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2417 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2418 }
2419
2420 #[corresponds(SSL_CTX_sess_get_cache_size)]
2424 #[allow(clippy::unnecessary_cast)]
2425 pub fn session_cache_size(&self) -> i64 {
2426 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2427 }
2428
2429 #[corresponds(SSL_CTX_get_verify_mode)]
2433 pub fn verify_mode(&self) -> SslVerifyMode {
2434 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2435 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2436 }
2437
2438 #[corresponds(SSL_CTX_get_num_tickets)]
2443 #[cfg(ossl111)]
2444 pub fn num_tickets(&self) -> usize {
2445 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2446 }
2447
2448 #[corresponds(SSL_CTX_get_security_level)]
2453 #[cfg(any(ossl110, libressl360))]
2454 pub fn security_level(&self) -> u32 {
2455 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2456 }
2457}
2458
2459pub struct CipherBits {
2461 pub secret: i32,
2463
2464 pub algorithm: i32,
2466}
2467
2468pub struct SslCipher(*mut ffi::SSL_CIPHER);
2470
2471impl ForeignType for SslCipher {
2472 type CType = ffi::SSL_CIPHER;
2473 type Ref = SslCipherRef;
2474
2475 #[inline]
2476 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2477 SslCipher(ptr)
2478 }
2479
2480 #[inline]
2481 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2482 self.0
2483 }
2484}
2485
2486impl Stackable for SslCipher {
2487 type StackType = ffi::stack_st_SSL_CIPHER;
2488}
2489
2490impl Deref for SslCipher {
2491 type Target = SslCipherRef;
2492
2493 fn deref(&self) -> &SslCipherRef {
2494 unsafe { SslCipherRef::from_ptr(self.0) }
2495 }
2496}
2497
2498impl DerefMut for SslCipher {
2499 fn deref_mut(&mut self) -> &mut SslCipherRef {
2500 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2501 }
2502}
2503
2504pub struct SslCipherRef(Opaque);
2508
2509impl ForeignTypeRef for SslCipherRef {
2510 type CType = ffi::SSL_CIPHER;
2511}
2512
2513impl SslCipherRef {
2514 #[corresponds(SSL_CIPHER_get_name)]
2516 pub fn name(&self) -> &'static str {
2517 unsafe {
2518 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2519 CStr::from_ptr(ptr).to_str().unwrap()
2520 }
2521 }
2522
2523 #[corresponds(SSL_CIPHER_standard_name)]
2527 #[cfg(ossl111)]
2528 pub fn standard_name(&self) -> Option<&'static str> {
2529 unsafe {
2530 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2531 if ptr.is_null() {
2532 None
2533 } else {
2534 Some(CStr::from_ptr(ptr).to_str().unwrap())
2535 }
2536 }
2537 }
2538
2539 #[corresponds(SSL_CIPHER_get_version)]
2541 pub fn version(&self) -> &'static str {
2542 let version = unsafe {
2543 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2544 CStr::from_ptr(ptr as *const _)
2545 };
2546
2547 str::from_utf8(version.to_bytes()).unwrap()
2548 }
2549
2550 #[corresponds(SSL_CIPHER_get_bits)]
2552 #[allow(clippy::useless_conversion)]
2553 pub fn bits(&self) -> CipherBits {
2554 unsafe {
2555 let mut algo_bits = 0;
2556 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2557 CipherBits {
2558 secret: secret_bits.into(),
2559 algorithm: algo_bits.into(),
2560 }
2561 }
2562 }
2563
2564 #[corresponds(SSL_CIPHER_description)]
2566 pub fn description(&self) -> String {
2567 unsafe {
2568 let mut buf = [0; 128];
2570 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2571 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2572 }
2573 }
2574
2575 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2579 #[cfg(ossl111)]
2580 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2581 unsafe {
2582 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2583 if ptr.is_null() {
2584 None
2585 } else {
2586 Some(MessageDigest::from_ptr(ptr))
2587 }
2588 }
2589 }
2590
2591 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2595 #[cfg(any(ossl110, libressl270))]
2596 pub fn cipher_nid(&self) -> Option<Nid> {
2597 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2598 if n == 0 {
2599 None
2600 } else {
2601 Some(Nid::from_raw(n))
2602 }
2603 }
2604}
2605
2606impl fmt::Debug for SslCipherRef {
2607 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2608 write!(fmt, "{}", self.name())
2609 }
2610}
2611
2612#[derive(Debug)]
2614pub struct CipherLists {
2615 pub suites: Stack<SslCipher>,
2616 pub signalling_suites: Stack<SslCipher>,
2617}
2618
2619foreign_type_and_impl_send_sync! {
2620 type CType = ffi::SSL_SESSION;
2621 fn drop = ffi::SSL_SESSION_free;
2622
2623 pub struct SslSession;
2627
2628 pub struct SslSessionRef;
2632}
2633
2634impl Clone for SslSession {
2635 fn clone(&self) -> SslSession {
2636 SslSessionRef::to_owned(self)
2637 }
2638}
2639
2640impl SslSession {
2641 from_der! {
2642 #[corresponds(d2i_SSL_SESSION)]
2644 from_der,
2645 SslSession,
2646 ffi::d2i_SSL_SESSION
2647 }
2648}
2649
2650impl ToOwned for SslSessionRef {
2651 type Owned = SslSession;
2652
2653 fn to_owned(&self) -> SslSession {
2654 unsafe {
2655 SSL_SESSION_up_ref(self.as_ptr());
2656 SslSession(self.as_ptr())
2657 }
2658 }
2659}
2660
2661impl SslSessionRef {
2662 #[corresponds(SSL_SESSION_get_id)]
2664 pub fn id(&self) -> &[u8] {
2665 unsafe {
2666 let mut len = 0;
2667 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2668 #[allow(clippy::unnecessary_cast)]
2669 util::from_raw_parts(p as *const u8, len as usize)
2670 }
2671 }
2672
2673 #[corresponds(SSL_SESSION_get_master_key)]
2675 pub fn master_key_len(&self) -> usize {
2676 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2677 }
2678
2679 #[corresponds(SSL_SESSION_get_master_key)]
2683 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2684 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2685 }
2686
2687 #[corresponds(SSL_SESSION_get_max_early_data)]
2691 #[cfg(any(ossl111, libressl340))]
2692 pub fn max_early_data(&self) -> u32 {
2693 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2694 }
2695
2696 #[corresponds(SSL_SESSION_get_time)]
2698 #[allow(clippy::useless_conversion)]
2699 pub fn time(&self) -> SslTimeTy {
2700 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2701 }
2702
2703 #[corresponds(SSL_SESSION_get_timeout)]
2707 #[allow(clippy::useless_conversion)]
2708 pub fn timeout(&self) -> i64 {
2709 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2710 }
2711
2712 #[corresponds(SSL_SESSION_get_protocol_version)]
2716 #[cfg(any(ossl110, libressl270))]
2717 pub fn protocol_version(&self) -> SslVersion {
2718 unsafe {
2719 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2720 SslVersion(version)
2721 }
2722 }
2723
2724 #[corresponds(SSL_SESSION_get_protocol_version)]
2726 #[cfg(any(boringssl, awslc))]
2727 pub fn protocol_version(&self) -> SslVersion {
2728 unsafe {
2729 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2730 SslVersion(version as _)
2731 }
2732 }
2733
2734 to_der! {
2735 #[corresponds(i2d_SSL_SESSION)]
2737 to_der,
2738 ffi::i2d_SSL_SESSION
2739 }
2740}
2741
2742foreign_type_and_impl_send_sync! {
2743 type CType = ffi::SSL;
2744 fn drop = ffi::SSL_free;
2745
2746 pub struct Ssl;
2753
2754 pub struct SslRef;
2758}
2759
2760impl fmt::Debug for Ssl {
2761 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2762 fmt::Debug::fmt(&**self, fmt)
2763 }
2764}
2765
2766impl Ssl {
2767 #[corresponds(SSL_get_ex_new_index)]
2772 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2773 where
2774 T: 'static + Sync + Send,
2775 {
2776 unsafe {
2777 ffi::init();
2778 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2779 Ok(Index::from_raw(idx))
2780 }
2781 }
2782
2783 fn cached_ex_index<T>() -> Index<Ssl, T>
2785 where
2786 T: 'static + Sync + Send,
2787 {
2788 unsafe {
2789 let idx = *SSL_INDEXES
2790 .lock()
2791 .unwrap_or_else(|e| e.into_inner())
2792 .entry(TypeId::of::<T>())
2793 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2794 Index::from_raw(idx)
2795 }
2796 }
2797
2798 #[corresponds(SSL_new)]
2800 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2801 let session_ctx_index = try_get_session_ctx_index()?;
2802 unsafe {
2803 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2804 let mut ssl = Ssl::from_ptr(ptr);
2805 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2806
2807 Ok(ssl)
2808 }
2809 }
2810
2811 #[corresponds(SSL_connect)]
2817 #[allow(deprecated)]
2818 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2819 where
2820 S: Read + Write,
2821 {
2822 SslStreamBuilder::new(self, stream).connect()
2823 }
2824
2825 #[corresponds(SSL_accept)]
2832 #[allow(deprecated)]
2833 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2834 where
2835 S: Read + Write,
2836 {
2837 SslStreamBuilder::new(self, stream).accept()
2838 }
2839}
2840
2841impl fmt::Debug for SslRef {
2842 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2843 fmt.debug_struct("Ssl")
2844 .field("state", &self.state_string_long())
2845 .field("verify_result", &self.verify_result())
2846 .finish()
2847 }
2848}
2849
2850impl SslRef {
2851 #[cfg(not(feature = "tongsuo"))]
2852 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2853 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2854 }
2855
2856 #[cfg(feature = "tongsuo")]
2857 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2858 unsafe {
2859 let bio = ffi::SSL_get_rbio(self.as_ptr());
2860 bio::find_correct_bio(bio)
2861 }
2862 }
2863
2864 fn get_error(&self, ret: c_int) -> ErrorCode {
2865 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2866 }
2867
2868 #[corresponds(SSL_set_mode)]
2872 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2873 unsafe {
2874 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2875 SslMode::from_bits_retain(bits)
2876 }
2877 }
2878
2879 #[corresponds(SSL_clear_mode)]
2881 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2882 unsafe {
2883 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2884 SslMode::from_bits_retain(bits)
2885 }
2886 }
2887
2888 #[corresponds(SSL_get_mode)]
2890 pub fn mode(&self) -> SslMode {
2891 unsafe {
2892 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2893 SslMode::from_bits_retain(bits)
2894 }
2895 }
2896
2897 #[corresponds(SSL_set_connect_state)]
2899 pub fn set_connect_state(&mut self) {
2900 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2901 }
2902
2903 #[corresponds(SSL_set_accept_state)]
2905 pub fn set_accept_state(&mut self) {
2906 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2907 }
2908
2909 #[cfg(any(boringssl, awslc))]
2910 #[corresponds(SSL_ech_accepted)]
2911 pub fn ech_accepted(&self) -> bool {
2912 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2913 }
2914
2915 #[cfg(tongsuo)]
2916 #[corresponds(SSL_is_ntls)]
2917 pub fn is_ntls(&mut self) -> bool {
2918 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2919 }
2920
2921 #[cfg(tongsuo)]
2922 #[corresponds(SSL_enable_ntls)]
2923 pub fn enable_ntls(&mut self) {
2924 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2925 }
2926
2927 #[cfg(tongsuo)]
2928 #[corresponds(SSL_disable_ntls)]
2929 pub fn disable_ntls(&mut self) {
2930 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2931 }
2932
2933 #[cfg(all(tongsuo, ossl300))]
2934 #[corresponds(SSL_enable_force_ntls)]
2935 pub fn enable_force_ntls(&mut self) {
2936 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2937 }
2938
2939 #[cfg(all(tongsuo, ossl300))]
2940 #[corresponds(SSL_disable_force_ntls)]
2941 pub fn disable_force_ntls(&mut self) {
2942 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2943 }
2944
2945 #[cfg(tongsuo)]
2946 #[corresponds(SSL_enable_sm_tls13_strict)]
2947 pub fn enable_sm_tls13_strict(&mut self) {
2948 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2949 }
2950
2951 #[cfg(tongsuo)]
2952 #[corresponds(SSL_disable_sm_tls13_strict)]
2953 pub fn disable_sm_tls13_strict(&mut self) {
2954 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2955 }
2956
2957 #[corresponds(SSL_set_verify)]
2961 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2962 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2963 }
2964
2965 #[corresponds(SSL_set_verify_mode)]
2967 pub fn verify_mode(&self) -> SslVerifyMode {
2968 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2969 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2970 }
2971
2972 #[corresponds(SSL_set_verify)]
2976 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2977 where
2978 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2979 {
2980 unsafe {
2981 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2983 ffi::SSL_set_verify(
2984 self.as_ptr(),
2985 mode.bits() as c_int,
2986 Some(ssl_raw_verify::<F>),
2987 );
2988 }
2989 }
2990
2991 #[corresponds(SSL_set_info_callback)]
2994 pub fn set_info_callback<F>(&mut self, callback: F)
2995 where
2996 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2997 {
2998 unsafe {
2999 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3001 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
3002 }
3003 }
3004
3005 #[corresponds(SSL_set_dh_auto)]
3009 #[cfg(ossl300)]
3010 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3011 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
3012 }
3013
3014 #[corresponds(SSL_set_tmp_dh)]
3018 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3019 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3020 }
3021
3022 #[corresponds(SSL_set_tmp_dh_callback)]
3026 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3027 where
3028 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3029 {
3030 unsafe {
3031 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3033 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3034 }
3035 }
3036
3037 #[corresponds(SSL_set_tmp_ecdh)]
3041 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3042 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3043 }
3044
3045 #[corresponds(SSL_set_ecdh_auto)]
3051 #[cfg(any(all(ossl102, not(ossl110)), libressl))]
3052 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3053 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
3054 }
3055
3056 #[corresponds(SSL_set_alpn_protos)]
3062 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3063 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3064 unsafe {
3065 assert!(protocols.len() <= c_uint::MAX as usize);
3066 let r =
3067 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3068 if r == 0 {
3070 Ok(())
3071 } else {
3072 Err(ErrorStack::get())
3073 }
3074 }
3075 }
3076
3077 #[corresponds(SSL_get_current_cipher)]
3079 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3080 unsafe {
3081 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3082
3083 SslCipherRef::from_const_ptr_opt(ptr)
3084 }
3085 }
3086
3087 #[corresponds(SSL_state_string)]
3089 pub fn state_string(&self) -> &'static str {
3090 let state = unsafe {
3091 let ptr = ffi::SSL_state_string(self.as_ptr());
3092 CStr::from_ptr(ptr as *const _)
3093 };
3094
3095 str::from_utf8(state.to_bytes()).unwrap()
3096 }
3097
3098 #[corresponds(SSL_state_string_long)]
3100 pub fn state_string_long(&self) -> &'static str {
3101 let state = unsafe {
3102 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3103 CStr::from_ptr(ptr as *const _)
3104 };
3105
3106 str::from_utf8(state.to_bytes()).unwrap()
3107 }
3108
3109 #[corresponds(SSL_set_tlsext_host_name)]
3113 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3114 let cstr = CString::new(hostname).unwrap();
3115 unsafe {
3116 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3117 .map(|_| ())
3118 }
3119 }
3120
3121 #[corresponds(SSL_get_peer_certificate)]
3123 pub fn peer_certificate(&self) -> Option<X509> {
3124 unsafe {
3125 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3126 X509::from_ptr_opt(ptr)
3127 }
3128 }
3129
3130 #[corresponds(SSL_get_peer_cert_chain)]
3135 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3136 unsafe {
3137 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3138 StackRef::from_const_ptr_opt(ptr)
3139 }
3140 }
3141
3142 #[corresponds(SSL_get0_verified_chain)]
3152 #[cfg(ossl110)]
3153 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3154 unsafe {
3155 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3156 StackRef::from_const_ptr_opt(ptr)
3157 }
3158 }
3159
3160 #[corresponds(SSL_get_certificate)]
3162 pub fn certificate(&self) -> Option<&X509Ref> {
3163 unsafe {
3164 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3165 X509Ref::from_const_ptr_opt(ptr)
3166 }
3167 }
3168
3169 #[corresponds(SSL_get_privatekey)]
3173 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3174 unsafe {
3175 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3176 PKeyRef::from_const_ptr_opt(ptr)
3177 }
3178 }
3179
3180 #[corresponds(SSL_version)]
3182 pub fn version2(&self) -> Option<SslVersion> {
3183 unsafe {
3184 let r = ffi::SSL_version(self.as_ptr());
3185 if r == 0 {
3186 None
3187 } else {
3188 Some(SslVersion(r))
3189 }
3190 }
3191 }
3192
3193 #[corresponds(SSL_get_version)]
3195 pub fn version_str(&self) -> &'static str {
3196 let version = unsafe {
3197 let ptr = ffi::SSL_get_version(self.as_ptr());
3198 CStr::from_ptr(ptr as *const _)
3199 };
3200
3201 str::from_utf8(version.to_bytes()).unwrap()
3202 }
3203
3204 #[corresponds(SSL_get0_alpn_selected)]
3211 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3212 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3213 unsafe {
3214 let mut data: *const c_uchar = ptr::null();
3215 let mut len: c_uint = 0;
3216 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3219
3220 if data.is_null() {
3221 None
3222 } else {
3223 Some(util::from_raw_parts(data, len as usize))
3224 }
3225 }
3226 }
3227
3228 #[corresponds(SSL_set_tlsext_use_srtp)]
3230 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3231 unsafe {
3232 let cstr = CString::new(protocols).unwrap();
3233
3234 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3235 if r == 0 {
3237 Ok(())
3238 } else {
3239 Err(ErrorStack::get())
3240 }
3241 }
3242 }
3243
3244 #[corresponds(SSL_get_srtp_profiles)]
3248 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3249 unsafe {
3250 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3251
3252 StackRef::from_const_ptr_opt(chain)
3253 }
3254 }
3255
3256 #[corresponds(SSL_get_selected_srtp_profile)]
3260 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3261 unsafe {
3262 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3263
3264 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3265 }
3266 }
3267
3268 #[corresponds(SSL_pending)]
3273 pub fn pending(&self) -> usize {
3274 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3275 }
3276
3277 #[corresponds(SSL_get_servername)]
3290 pub fn servername(&self, type_: NameType) -> Option<&str> {
3292 self.servername_raw(type_)
3293 .and_then(|b| str::from_utf8(b).ok())
3294 }
3295
3296 #[corresponds(SSL_get_servername)]
3304 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3305 unsafe {
3306 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3307 if name.is_null() {
3308 None
3309 } else {
3310 Some(CStr::from_ptr(name as *const _).to_bytes())
3311 }
3312 }
3313 }
3314
3315 #[corresponds(SSL_set_SSL_CTX)]
3319 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3320 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3321 }
3322
3323 #[corresponds(SSL_get_SSL_CTX)]
3325 pub fn ssl_context(&self) -> &SslContextRef {
3326 unsafe {
3327 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3328 SslContextRef::from_ptr(ssl_ctx)
3329 }
3330 }
3331
3332 #[corresponds(SSL_get0_param)]
3336 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
3337 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3338 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3339 }
3340
3341 #[corresponds(SSL_get_verify_result)]
3343 pub fn verify_result(&self) -> X509VerifyResult {
3344 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3345 }
3346
3347 #[corresponds(SSL_get_session)]
3349 pub fn session(&self) -> Option<&SslSessionRef> {
3350 unsafe {
3351 let p = ffi::SSL_get_session(self.as_ptr());
3352 SslSessionRef::from_const_ptr_opt(p)
3353 }
3354 }
3355
3356 #[corresponds(SSL_get_client_random)]
3363 #[cfg(any(ossl110, libressl270))]
3364 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3365 unsafe {
3366 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3367 }
3368 }
3369
3370 #[corresponds(SSL_get_server_random)]
3377 #[cfg(any(ossl110, libressl270))]
3378 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3379 unsafe {
3380 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3381 }
3382 }
3383
3384 #[corresponds(SSL_export_keying_material)]
3386 pub fn export_keying_material(
3387 &self,
3388 out: &mut [u8],
3389 label: &str,
3390 context: Option<&[u8]>,
3391 ) -> Result<(), ErrorStack> {
3392 unsafe {
3393 let (context, contextlen, use_context) = match context {
3394 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3395 None => (ptr::null(), 0, 0),
3396 };
3397 cvt(ffi::SSL_export_keying_material(
3398 self.as_ptr(),
3399 out.as_mut_ptr() as *mut c_uchar,
3400 out.len(),
3401 label.as_ptr() as *const c_char,
3402 label.len(),
3403 context,
3404 contextlen,
3405 use_context,
3406 ))
3407 .map(|_| ())
3408 }
3409 }
3410
3411 #[corresponds(SSL_export_keying_material_early)]
3418 #[cfg(ossl111)]
3419 pub fn export_keying_material_early(
3420 &self,
3421 out: &mut [u8],
3422 label: &str,
3423 context: &[u8],
3424 ) -> Result<(), ErrorStack> {
3425 unsafe {
3426 cvt(ffi::SSL_export_keying_material_early(
3427 self.as_ptr(),
3428 out.as_mut_ptr() as *mut c_uchar,
3429 out.len(),
3430 label.as_ptr() as *const c_char,
3431 label.len(),
3432 context.as_ptr() as *const c_uchar,
3433 context.len(),
3434 ))
3435 .map(|_| ())
3436 }
3437 }
3438
3439 #[corresponds(SSL_set_session)]
3450 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3451 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3452 }
3453
3454 #[corresponds(SSL_session_reused)]
3456 pub fn session_reused(&self) -> bool {
3457 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3458 }
3459
3460 #[cfg(any(boringssl, awslc))]
3468 pub fn enable_ocsp_stapling(&mut self) {
3469 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3470 }
3471
3472 #[cfg(any(boringssl, awslc))]
3480 pub fn enable_signed_cert_timestamps(&mut self) {
3481 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3482 }
3483
3484 #[cfg(any(boringssl, awslc))]
3492 pub fn set_permute_extensions(&mut self, enabled: bool) {
3493 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3494 }
3495
3496 #[corresponds(SSL_enable_ct)]
3498 #[cfg(ossl111)]
3499 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3500 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3501 }
3502
3503 #[corresponds(SSL_ct_is_enabled)]
3505 #[cfg(ossl111)]
3506 pub fn ct_is_enabled(&self) -> bool {
3507 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3508 }
3509
3510 #[corresponds(SSL_set_tlsext_status_type)]
3512 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3513 unsafe {
3514 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3515 }
3516 }
3517
3518 #[corresponds(SSL_get_extms_support)]
3522 #[cfg(ossl110)]
3523 pub fn extms_support(&self) -> Option<bool> {
3524 unsafe {
3525 match ffi::SSL_get_extms_support(self.as_ptr()) {
3526 -1 => None,
3527 ret => Some(ret != 0),
3528 }
3529 }
3530 }
3531
3532 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3534 #[cfg(not(any(boringssl, awslc)))]
3535 pub fn ocsp_status(&self) -> Option<&[u8]> {
3536 unsafe {
3537 let mut p = ptr::null_mut();
3538 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3539
3540 if len < 0 {
3541 None
3542 } else {
3543 Some(util::from_raw_parts(p as *const u8, len as usize))
3544 }
3545 }
3546 }
3547
3548 #[corresponds(SSL_get0_ocsp_response)]
3550 #[cfg(any(boringssl, awslc))]
3551 pub fn ocsp_status(&self) -> Option<&[u8]> {
3552 unsafe {
3553 let mut p = ptr::null();
3554 let mut len: usize = 0;
3555 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3556
3557 if len == 0 {
3558 None
3559 } else {
3560 Some(util::from_raw_parts(p as *const u8, len))
3561 }
3562 }
3563 }
3564
3565 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3567 #[cfg(not(any(boringssl, awslc)))]
3568 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3569 unsafe {
3570 assert!(response.len() <= c_int::MAX as usize);
3571 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3572 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3573 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3574 self.as_ptr(),
3575 p as *mut c_uchar,
3576 response.len() as c_long,
3577 ) as c_int)
3578 .map(|_| ())
3579 .map_err(|e| {
3580 ffi::OPENSSL_free(p);
3581 e
3582 })
3583 }
3584 }
3585
3586 #[corresponds(SSL_set_ocsp_response)]
3588 #[cfg(any(boringssl, awslc))]
3589 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3590 unsafe {
3591 cvt(ffi::SSL_set_ocsp_response(
3592 self.as_ptr(),
3593 response.as_ptr(),
3594 response.len(),
3595 ))
3596 .map(|_| ())
3597 }
3598 }
3599
3600 #[corresponds(SSL_is_server)]
3602 pub fn is_server(&self) -> bool {
3603 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3604 }
3605
3606 #[corresponds(SSL_set_ex_data)]
3612 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3613 match self.ex_data_mut(index) {
3614 Some(v) => *v = data,
3615 None => unsafe {
3616 let data = Box::new(data);
3617 ffi::SSL_set_ex_data(
3618 self.as_ptr(),
3619 index.as_raw(),
3620 Box::into_raw(data) as *mut c_void,
3621 );
3622 },
3623 }
3624 }
3625
3626 #[corresponds(SSL_get_ex_data)]
3628 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3629 unsafe {
3630 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3631 if data.is_null() {
3632 None
3633 } else {
3634 Some(&*(data as *const T))
3635 }
3636 }
3637 }
3638
3639 #[corresponds(SSL_get_ex_data)]
3641 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3642 unsafe {
3643 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3644 if data.is_null() {
3645 None
3646 } else {
3647 Some(&mut *(data as *mut T))
3648 }
3649 }
3650 }
3651
3652 #[corresponds(SSL_set_max_early_data)]
3656 #[cfg(any(ossl111, libressl340))]
3657 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3658 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3659 Ok(())
3660 } else {
3661 Err(ErrorStack::get())
3662 }
3663 }
3664
3665 #[corresponds(SSL_get_max_early_data)]
3669 #[cfg(any(ossl111, libressl340))]
3670 pub fn max_early_data(&self) -> u32 {
3671 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3672 }
3673
3674 #[corresponds(SSL_get_finished)]
3679 pub fn finished(&self, buf: &mut [u8]) -> usize {
3680 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3681 }
3682
3683 #[corresponds(SSL_get_peer_finished)]
3689 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3690 unsafe {
3691 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3692 }
3693 }
3694
3695 #[corresponds(SSL_is_init_finished)]
3697 #[cfg(ossl110)]
3698 pub fn is_init_finished(&self) -> bool {
3699 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3700 }
3701
3702 #[corresponds(SSL_client_hello_isv2)]
3708 #[cfg(ossl111)]
3709 pub fn client_hello_isv2(&self) -> bool {
3710 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3711 }
3712
3713 #[corresponds(SSL_client_hello_get0_legacy_version)]
3719 #[cfg(ossl111)]
3720 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3721 unsafe {
3722 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3723 if version == 0 {
3724 None
3725 } else {
3726 Some(SslVersion(version as c_int))
3727 }
3728 }
3729 }
3730
3731 #[corresponds(SSL_client_hello_get0_random)]
3737 #[cfg(ossl111)]
3738 pub fn client_hello_random(&self) -> Option<&[u8]> {
3739 unsafe {
3740 let mut ptr = ptr::null();
3741 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3742 if len == 0 {
3743 None
3744 } else {
3745 Some(util::from_raw_parts(ptr, len))
3746 }
3747 }
3748 }
3749
3750 #[corresponds(SSL_client_hello_get0_session_id)]
3756 #[cfg(ossl111)]
3757 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3758 unsafe {
3759 let mut ptr = ptr::null();
3760 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3761 if len == 0 {
3762 None
3763 } else {
3764 Some(util::from_raw_parts(ptr, len))
3765 }
3766 }
3767 }
3768
3769 #[corresponds(SSL_client_hello_get0_ciphers)]
3775 #[cfg(ossl111)]
3776 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3777 unsafe {
3778 let mut ptr = ptr::null();
3779 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3780 if len == 0 {
3781 None
3782 } else {
3783 Some(util::from_raw_parts(ptr, len))
3784 }
3785 }
3786 }
3787
3788 #[cfg(ossl111)]
3794 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3795 unsafe {
3796 let mut ptr = ptr::null();
3797 let mut len = 0usize;
3798 let r = ffi::SSL_client_hello_get0_ext(
3799 self.as_ptr(),
3800 ext_type.as_raw() as _,
3801 &mut ptr,
3802 &mut len,
3803 );
3804 if r == 0 {
3805 None
3806 } else {
3807 Some(util::from_raw_parts(ptr, len))
3808 }
3809 }
3810 }
3811
3812 #[corresponds(SSL_bytes_to_cipher_list)]
3817 #[cfg(ossl111)]
3818 pub fn bytes_to_cipher_list(
3819 &self,
3820 bytes: &[u8],
3821 isv2format: bool,
3822 ) -> Result<CipherLists, ErrorStack> {
3823 unsafe {
3824 let ptr = bytes.as_ptr();
3825 let len = bytes.len();
3826 let mut sk = ptr::null_mut();
3827 let mut scsvs = ptr::null_mut();
3828 let res = ffi::SSL_bytes_to_cipher_list(
3829 self.as_ptr(),
3830 ptr,
3831 len,
3832 isv2format as c_int,
3833 &mut sk,
3834 &mut scsvs,
3835 );
3836 if res == 1 {
3837 Ok(CipherLists {
3838 suites: Stack::from_ptr(sk),
3839 signalling_suites: Stack::from_ptr(scsvs),
3840 })
3841 } else {
3842 Err(ErrorStack::get())
3843 }
3844 }
3845 }
3846
3847 #[corresponds(SSL_client_hello_get0_compression_methods)]
3853 #[cfg(ossl111)]
3854 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3855 unsafe {
3856 let mut ptr = ptr::null();
3857 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3858 if len == 0 {
3859 None
3860 } else {
3861 Some(util::from_raw_parts(ptr, len))
3862 }
3863 }
3864 }
3865
3866 #[corresponds(SSL_set_mtu)]
3868 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3869 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3870 }
3871
3872 #[corresponds(SSL_get_psk_identity_hint)]
3876 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3877 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3878 unsafe {
3879 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3880 if ptr.is_null() {
3881 None
3882 } else {
3883 Some(CStr::from_ptr(ptr).to_bytes())
3884 }
3885 }
3886 }
3887
3888 #[corresponds(SSL_get_psk_identity)]
3890 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3891 pub fn psk_identity(&self) -> Option<&[u8]> {
3892 unsafe {
3893 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3894 if ptr.is_null() {
3895 None
3896 } else {
3897 Some(CStr::from_ptr(ptr).to_bytes())
3898 }
3899 }
3900 }
3901
3902 #[corresponds(SSL_add0_chain_cert)]
3903 #[cfg(any(ossl102, boringssl, awslc))]
3904 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3905 unsafe {
3906 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3907 mem::forget(chain);
3908 }
3909 Ok(())
3910 }
3911
3912 #[cfg(not(any(boringssl, awslc)))]
3914 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3915 unsafe {
3916 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3917 };
3918 Ok(())
3919 }
3920
3921 #[corresponds(SSL_use_Private_Key_file)]
3923 pub fn set_private_key_file<P: AsRef<Path>>(
3924 &mut self,
3925 path: P,
3926 ssl_file_type: SslFiletype,
3927 ) -> Result<(), ErrorStack> {
3928 let p = path.as_ref().as_os_str().to_str().unwrap();
3929 let key_file = CString::new(p).unwrap();
3930 unsafe {
3931 cvt(ffi::SSL_use_PrivateKey_file(
3932 self.as_ptr(),
3933 key_file.as_ptr(),
3934 ssl_file_type.as_raw(),
3935 ))?;
3936 };
3937 Ok(())
3938 }
3939
3940 #[corresponds(SSL_use_PrivateKey)]
3942 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3943 unsafe {
3944 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3945 };
3946 Ok(())
3947 }
3948
3949 #[cfg(tongsuo)]
3950 #[corresponds(SSL_use_enc_Private_Key_file)]
3951 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3952 &mut self,
3953 path: P,
3954 ssl_file_type: SslFiletype,
3955 ) -> Result<(), ErrorStack> {
3956 let p = path.as_ref().as_os_str().to_str().unwrap();
3957 let key_file = CString::new(p).unwrap();
3958 unsafe {
3959 cvt(ffi::SSL_use_enc_PrivateKey_file(
3960 self.as_ptr(),
3961 key_file.as_ptr(),
3962 ssl_file_type.as_raw(),
3963 ))?;
3964 };
3965 Ok(())
3966 }
3967
3968 #[cfg(tongsuo)]
3969 #[corresponds(SSL_use_enc_PrivateKey)]
3970 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3971 unsafe {
3972 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3973 };
3974 Ok(())
3975 }
3976
3977 #[cfg(tongsuo)]
3978 #[corresponds(SSL_use_sign_Private_Key_file)]
3979 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3980 &mut self,
3981 path: P,
3982 ssl_file_type: SslFiletype,
3983 ) -> Result<(), ErrorStack> {
3984 let p = path.as_ref().as_os_str().to_str().unwrap();
3985 let key_file = CString::new(p).unwrap();
3986 unsafe {
3987 cvt(ffi::SSL_use_sign_PrivateKey_file(
3988 self.as_ptr(),
3989 key_file.as_ptr(),
3990 ssl_file_type.as_raw(),
3991 ))?;
3992 };
3993 Ok(())
3994 }
3995
3996 #[cfg(tongsuo)]
3997 #[corresponds(SSL_use_sign_PrivateKey)]
3998 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3999 unsafe {
4000 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
4001 };
4002 Ok(())
4003 }
4004
4005 #[corresponds(SSL_use_certificate)]
4007 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4008 unsafe {
4009 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4010 };
4011 Ok(())
4012 }
4013
4014 #[cfg(tongsuo)]
4015 #[corresponds(SSL_use_enc_certificate)]
4016 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4017 unsafe {
4018 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4019 };
4020 Ok(())
4021 }
4022
4023 #[cfg(tongsuo)]
4024 #[corresponds(SSL_use_sign_certificate)]
4025 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4026 unsafe {
4027 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4028 };
4029 Ok(())
4030 }
4031
4032 #[corresponds(SSL_use_certificate_chain_file)]
4038 #[cfg(any(ossl110, libressl332))]
4039 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4040 &mut self,
4041 path: P,
4042 ) -> Result<(), ErrorStack> {
4043 let p = path.as_ref().as_os_str().to_str().unwrap();
4044 let cert_file = CString::new(p).unwrap();
4045 unsafe {
4046 cvt(ffi::SSL_use_certificate_chain_file(
4047 self.as_ptr(),
4048 cert_file.as_ptr(),
4049 ))?;
4050 };
4051 Ok(())
4052 }
4053
4054 #[corresponds(SSL_add_client_CA)]
4056 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4057 unsafe {
4058 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4059 };
4060 Ok(())
4061 }
4062
4063 #[corresponds(SSL_set_client_CA_list)]
4065 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4066 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4067 mem::forget(list);
4068 }
4069
4070 #[corresponds(SSL_set_min_proto_version)]
4077 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4078 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4079 unsafe {
4080 cvt(ffi::SSL_set_min_proto_version(
4081 self.as_ptr(),
4082 version.map_or(0, |v| v.0 as _),
4083 ))
4084 .map(|_| ())
4085 }
4086 }
4087
4088 #[corresponds(SSL_set_max_proto_version)]
4095 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4096 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4097 unsafe {
4098 cvt(ffi::SSL_set_max_proto_version(
4099 self.as_ptr(),
4100 version.map_or(0, |v| v.0 as _),
4101 ))
4102 .map(|_| ())
4103 }
4104 }
4105
4106 #[corresponds(SSL_set_ciphersuites)]
4115 #[cfg(any(ossl111, libressl340))]
4116 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4117 let cipher_list = CString::new(cipher_list).unwrap();
4118 unsafe {
4119 cvt(ffi::SSL_set_ciphersuites(
4120 self.as_ptr(),
4121 cipher_list.as_ptr() as *const _,
4122 ))
4123 .map(|_| ())
4124 }
4125 }
4126
4127 #[corresponds(SSL_set_cipher_list)]
4135 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4136 let cipher_list = CString::new(cipher_list).unwrap();
4137 unsafe {
4138 cvt(ffi::SSL_set_cipher_list(
4139 self.as_ptr(),
4140 cipher_list.as_ptr() as *const _,
4141 ))
4142 .map(|_| ())
4143 }
4144 }
4145
4146 #[corresponds(SSL_set_cert_store)]
4148 #[cfg(any(ossl102, boringssl, awslc))]
4149 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4150 unsafe {
4151 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4152 mem::forget(cert_store);
4153 Ok(())
4154 }
4155 }
4156
4157 #[corresponds(SSL_set_num_tickets)]
4162 #[cfg(ossl111)]
4163 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4164 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4165 }
4166
4167 #[corresponds(SSL_get_num_tickets)]
4172 #[cfg(ossl111)]
4173 pub fn num_tickets(&self) -> usize {
4174 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4175 }
4176
4177 #[corresponds(SSL_set_security_level)]
4182 #[cfg(any(ossl110, libressl360))]
4183 pub fn set_security_level(&mut self, level: u32) {
4184 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4185 }
4186
4187 #[corresponds(SSL_get_security_level)]
4192 #[cfg(any(ossl110, libressl360))]
4193 pub fn security_level(&self) -> u32 {
4194 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4195 }
4196
4197 #[corresponds(SSL_get_peer_tmp_key)]
4202 #[cfg(ossl300)]
4203 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4204 unsafe {
4205 let mut key = ptr::null_mut();
4206 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4207 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4208 Err(e) => Err(e),
4209 }
4210 }
4211 }
4212
4213 #[corresponds(SSL_get_tmp_key)]
4218 #[cfg(ossl300)]
4219 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4220 unsafe {
4221 let mut key = ptr::null_mut();
4222 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4223 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4224 Err(e) => Err(e),
4225 }
4226 }
4227 }
4228}
4229
4230#[derive(Debug)]
4232pub struct MidHandshakeSslStream<S> {
4233 stream: SslStream<S>,
4234 error: Error,
4235}
4236
4237impl<S> MidHandshakeSslStream<S> {
4238 pub fn get_ref(&self) -> &S {
4240 self.stream.get_ref()
4241 }
4242
4243 pub fn get_mut(&mut self) -> &mut S {
4245 self.stream.get_mut()
4246 }
4247
4248 pub fn ssl(&self) -> &SslRef {
4250 self.stream.ssl()
4251 }
4252
4253 pub fn ssl_mut(&mut self) -> &mut SslRef {
4255 self.stream.ssl_mut()
4256 }
4257
4258 pub fn error(&self) -> &Error {
4260 &self.error
4261 }
4262
4263 pub fn into_error(self) -> Error {
4265 self.error
4266 }
4267}
4268
4269impl<S> MidHandshakeSslStream<S>
4270where
4271 S: Read + Write,
4272{
4273 #[corresponds(SSL_do_handshake)]
4276 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4277 match self.stream.do_handshake() {
4278 Ok(()) => Ok(self.stream),
4279 Err(error) => {
4280 self.error = error;
4281 match self.error.code() {
4282 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4283 Err(HandshakeError::WouldBlock(self))
4284 }
4285 _ => Err(HandshakeError::Failure(self)),
4286 }
4287 }
4288 }
4289 }
4290}
4291
4292pub struct SslStream<S> {
4294 ssl: ManuallyDrop<Ssl>,
4295 method: ManuallyDrop<BioMethod>,
4296 _p: PhantomData<S>,
4297}
4298
4299impl<S> Drop for SslStream<S> {
4300 fn drop(&mut self) {
4301 unsafe {
4303 ManuallyDrop::drop(&mut self.ssl);
4304 ManuallyDrop::drop(&mut self.method);
4305 }
4306 }
4307}
4308
4309impl<S> fmt::Debug for SslStream<S>
4310where
4311 S: fmt::Debug,
4312{
4313 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4314 fmt.debug_struct("SslStream")
4315 .field("stream", &self.get_ref())
4316 .field("ssl", &self.ssl())
4317 .finish()
4318 }
4319}
4320
4321impl<S: Read + Write> SslStream<S> {
4322 #[corresponds(SSL_set_bio)]
4330 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4331 let (bio, method) = bio::new(stream)?;
4332 unsafe {
4333 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4334 }
4335
4336 Ok(SslStream {
4337 ssl: ManuallyDrop::new(ssl),
4338 method: ManuallyDrop::new(method),
4339 _p: PhantomData,
4340 })
4341 }
4342
4343 #[corresponds(SSL_read_early_data)]
4352 #[cfg(any(ossl111, libressl340))]
4353 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4354 let mut read = 0;
4355 let ret = unsafe {
4356 ffi::SSL_read_early_data(
4357 self.ssl.as_ptr(),
4358 buf.as_ptr() as *mut c_void,
4359 buf.len(),
4360 &mut read,
4361 )
4362 };
4363 match ret {
4364 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4365 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4366 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4367 _ => unreachable!(),
4368 }
4369 }
4370
4371 #[corresponds(SSL_write_early_data)]
4378 #[cfg(any(ossl111, libressl340))]
4379 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4380 let mut written = 0;
4381 let ret = unsafe {
4382 ffi::SSL_write_early_data(
4383 self.ssl.as_ptr(),
4384 buf.as_ptr() as *const c_void,
4385 buf.len(),
4386 &mut written,
4387 )
4388 };
4389 if ret > 0 {
4390 Ok(written)
4391 } else {
4392 Err(self.make_error(ret))
4393 }
4394 }
4395
4396 #[corresponds(SSL_connect)]
4403 pub fn connect(&mut self) -> Result<(), Error> {
4404 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4405 if ret > 0 {
4406 Ok(())
4407 } else {
4408 Err(self.make_error(ret))
4409 }
4410 }
4411
4412 #[corresponds(SSL_accept)]
4419 pub fn accept(&mut self) -> Result<(), Error> {
4420 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4421 if ret > 0 {
4422 Ok(())
4423 } else {
4424 Err(self.make_error(ret))
4425 }
4426 }
4427
4428 #[corresponds(SSL_do_handshake)]
4432 pub fn do_handshake(&mut self) -> Result<(), Error> {
4433 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4434 if ret > 0 {
4435 Ok(())
4436 } else {
4437 Err(self.make_error(ret))
4438 }
4439 }
4440
4441 #[corresponds(SSL_stateless)]
4452 #[cfg(ossl111)]
4453 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4454 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4455 1 => Ok(true),
4456 0 => Ok(false),
4457 -1 => Err(ErrorStack::get()),
4458 _ => unreachable!(),
4459 }
4460 }
4461
4462 #[corresponds(SSL_read_ex)]
4469 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4470 loop {
4471 match self.ssl_read_uninit(buf) {
4472 Ok(n) => return Ok(n),
4473 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4474 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4475 return Ok(0);
4476 }
4477 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4478 Err(e) => {
4479 return Err(e
4480 .into_io_error()
4481 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4482 }
4483 }
4484 }
4485 }
4486
4487 #[corresponds(SSL_read_ex)]
4492 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4493 unsafe {
4495 self.ssl_read_uninit(util::from_raw_parts_mut(
4496 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4497 buf.len(),
4498 ))
4499 }
4500 }
4501
4502 #[corresponds(SSL_read_ex)]
4509 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4510 cfg_if! {
4511 if #[cfg(any(ossl111, libressl350))] {
4512 let mut readbytes = 0;
4513 let ret = unsafe {
4514 ffi::SSL_read_ex(
4515 self.ssl().as_ptr(),
4516 buf.as_mut_ptr().cast(),
4517 buf.len(),
4518 &mut readbytes,
4519 )
4520 };
4521
4522 if ret > 0 {
4523 Ok(readbytes)
4524 } else {
4525 Err(self.make_error(ret))
4526 }
4527 } else {
4528 if buf.is_empty() {
4529 return Ok(0);
4530 }
4531
4532 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4533 let ret = unsafe {
4534 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4535 };
4536 if ret > 0 {
4537 Ok(ret as usize)
4538 } else {
4539 Err(self.make_error(ret))
4540 }
4541 }
4542 }
4543 }
4544
4545 #[corresponds(SSL_write_ex)]
4550 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4551 cfg_if! {
4552 if #[cfg(any(ossl111, libressl350))] {
4553 let mut written = 0;
4554 let ret = unsafe {
4555 ffi::SSL_write_ex(
4556 self.ssl().as_ptr(),
4557 buf.as_ptr().cast(),
4558 buf.len(),
4559 &mut written,
4560 )
4561 };
4562
4563 if ret > 0 {
4564 Ok(written)
4565 } else {
4566 Err(self.make_error(ret))
4567 }
4568 } else {
4569 if buf.is_empty() {
4570 return Ok(0);
4571 }
4572
4573 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4574 let ret = unsafe {
4575 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4576 };
4577 if ret > 0 {
4578 Ok(ret as usize)
4579 } else {
4580 Err(self.make_error(ret))
4581 }
4582 }
4583 }
4584 }
4585
4586 #[corresponds(SSL_peek_ex)]
4588 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4589 cfg_if! {
4590 if #[cfg(any(ossl111, libressl350))] {
4591 let mut readbytes = 0;
4592 let ret = unsafe {
4593 ffi::SSL_peek_ex(
4594 self.ssl().as_ptr(),
4595 buf.as_mut_ptr().cast(),
4596 buf.len(),
4597 &mut readbytes,
4598 )
4599 };
4600
4601 if ret > 0 {
4602 Ok(readbytes)
4603 } else {
4604 Err(self.make_error(ret))
4605 }
4606 } else {
4607 if buf.is_empty() {
4608 return Ok(0);
4609 }
4610
4611 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4612 let ret = unsafe {
4613 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4614 };
4615 if ret > 0 {
4616 Ok(ret as usize)
4617 } else {
4618 Err(self.make_error(ret))
4619 }
4620 }
4621 }
4622 }
4623
4624 #[corresponds(SSL_shutdown)]
4634 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4635 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4636 0 => Ok(ShutdownResult::Sent),
4637 1 => Ok(ShutdownResult::Received),
4638 n => Err(self.make_error(n)),
4639 }
4640 }
4641
4642 #[corresponds(SSL_get_shutdown)]
4644 pub fn get_shutdown(&mut self) -> ShutdownState {
4645 unsafe {
4646 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4647 ShutdownState::from_bits_retain(bits)
4648 }
4649 }
4650
4651 #[corresponds(SSL_set_shutdown)]
4656 pub fn set_shutdown(&mut self, state: ShutdownState) {
4657 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4658 }
4659}
4660
4661impl<S> SslStream<S> {
4662 fn make_error(&mut self, ret: c_int) -> Error {
4663 self.check_panic();
4664
4665 let code = self.ssl.get_error(ret);
4666
4667 let cause = match code {
4668 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4669 ErrorCode::SYSCALL => {
4670 let errs = ErrorStack::get();
4671 if errs.errors().is_empty() {
4672 self.get_bio_error().map(InnerError::Io)
4673 } else {
4674 Some(InnerError::Ssl(errs))
4675 }
4676 }
4677 ErrorCode::ZERO_RETURN => None,
4678 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4679 self.get_bio_error().map(InnerError::Io)
4680 }
4681 _ => None,
4682 };
4683
4684 Error { code, cause }
4685 }
4686
4687 fn check_panic(&mut self) {
4688 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4689 resume_unwind(err)
4690 }
4691 }
4692
4693 fn get_bio_error(&mut self) -> Option<io::Error> {
4694 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4695 }
4696
4697 pub fn get_ref(&self) -> &S {
4699 unsafe {
4700 let bio = self.ssl.get_raw_rbio();
4701 bio::get_ref(bio)
4702 }
4703 }
4704
4705 pub fn get_mut(&mut self) -> &mut S {
4712 unsafe {
4713 let bio = self.ssl.get_raw_rbio();
4714 bio::get_mut(bio)
4715 }
4716 }
4717
4718 pub fn ssl(&self) -> &SslRef {
4720 &self.ssl
4721 }
4722
4723 pub fn ssl_mut(&mut self) -> &mut SslRef {
4725 &mut self.ssl
4726 }
4727}
4728
4729impl<S: Read + Write> Read for SslStream<S> {
4730 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4731 unsafe {
4733 self.read_uninit(util::from_raw_parts_mut(
4734 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4735 buf.len(),
4736 ))
4737 }
4738 }
4739}
4740
4741impl<S: Read + Write> Write for SslStream<S> {
4742 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4743 loop {
4744 match self.ssl_write(buf) {
4745 Ok(n) => return Ok(n),
4746 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4747 Err(e) => {
4748 return Err(e
4749 .into_io_error()
4750 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4751 }
4752 }
4753 }
4754 }
4755
4756 fn flush(&mut self) -> io::Result<()> {
4757 self.get_mut().flush()
4758 }
4759}
4760
4761#[deprecated(
4763 since = "0.10.32",
4764 note = "use the methods directly on Ssl/SslStream instead"
4765)]
4766pub struct SslStreamBuilder<S> {
4767 inner: SslStream<S>,
4768}
4769
4770#[allow(deprecated)]
4771impl<S> SslStreamBuilder<S>
4772where
4773 S: Read + Write,
4774{
4775 pub fn new(ssl: Ssl, stream: S) -> Self {
4777 Self {
4778 inner: SslStream::new(ssl, stream).unwrap(),
4779 }
4780 }
4781
4782 #[corresponds(SSL_stateless)]
4793 #[cfg(ossl111)]
4794 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4795 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4796 1 => Ok(true),
4797 0 => Ok(false),
4798 -1 => Err(ErrorStack::get()),
4799 _ => unreachable!(),
4800 }
4801 }
4802
4803 #[corresponds(SSL_set_connect_state)]
4805 pub fn set_connect_state(&mut self) {
4806 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4807 }
4808
4809 #[corresponds(SSL_set_accept_state)]
4811 pub fn set_accept_state(&mut self) {
4812 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4813 }
4814
4815 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4817 match self.inner.connect() {
4818 Ok(()) => Ok(self.inner),
4819 Err(error) => match error.code() {
4820 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4821 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4822 stream: self.inner,
4823 error,
4824 }))
4825 }
4826 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4827 stream: self.inner,
4828 error,
4829 })),
4830 },
4831 }
4832 }
4833
4834 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4836 match self.inner.accept() {
4837 Ok(()) => Ok(self.inner),
4838 Err(error) => match error.code() {
4839 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4840 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4841 stream: self.inner,
4842 error,
4843 }))
4844 }
4845 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4846 stream: self.inner,
4847 error,
4848 })),
4849 },
4850 }
4851 }
4852
4853 #[corresponds(SSL_do_handshake)]
4857 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4858 match self.inner.do_handshake() {
4859 Ok(()) => Ok(self.inner),
4860 Err(error) => match error.code() {
4861 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4862 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4863 stream: self.inner,
4864 error,
4865 }))
4866 }
4867 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4868 stream: self.inner,
4869 error,
4870 })),
4871 },
4872 }
4873 }
4874
4875 #[corresponds(SSL_read_early_data)]
4885 #[cfg(any(ossl111, libressl340))]
4886 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4887 self.inner.read_early_data(buf)
4888 }
4889
4890 #[corresponds(SSL_write_early_data)]
4897 #[cfg(any(ossl111, libressl340))]
4898 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4899 self.inner.write_early_data(buf)
4900 }
4901}
4902
4903#[allow(deprecated)]
4904impl<S> SslStreamBuilder<S> {
4905 pub fn get_ref(&self) -> &S {
4907 unsafe {
4908 let bio = self.inner.ssl.get_raw_rbio();
4909 bio::get_ref(bio)
4910 }
4911 }
4912
4913 pub fn get_mut(&mut self) -> &mut S {
4920 unsafe {
4921 let bio = self.inner.ssl.get_raw_rbio();
4922 bio::get_mut(bio)
4923 }
4924 }
4925
4926 pub fn ssl(&self) -> &SslRef {
4928 &self.inner.ssl
4929 }
4930
4931 pub fn ssl_mut(&mut self) -> &mut SslRef {
4933 &mut self.inner.ssl
4934 }
4935}
4936
4937#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4939pub enum ShutdownResult {
4940 Sent,
4942
4943 Received,
4945}
4946
4947bitflags! {
4948 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4950 #[repr(transparent)]
4951 pub struct ShutdownState: c_int {
4952 const SENT = ffi::SSL_SENT_SHUTDOWN;
4954 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4956 }
4957}
4958
4959cfg_if! {
4960 if #[cfg(any(boringssl, ossl110, libressl273, awslc))] {
4961 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4962 } else {
4963 #[allow(bad_style)]
4964 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4965 ffi::CRYPTO_add_lock(
4966 &mut (*ssl).references,
4967 1,
4968 ffi::CRYPTO_LOCK_SSL_CTX,
4969 "mod.rs\0".as_ptr() as *const _,
4970 line!() as c_int,
4971 );
4972 0
4973 }
4974
4975 #[allow(bad_style)]
4976 pub unsafe fn SSL_SESSION_get_master_key(
4977 session: *const ffi::SSL_SESSION,
4978 out: *mut c_uchar,
4979 mut outlen: usize,
4980 ) -> usize {
4981 if outlen == 0 {
4982 return (*session).master_key_length as usize;
4983 }
4984 if outlen > (*session).master_key_length as usize {
4985 outlen = (*session).master_key_length as usize;
4986 }
4987 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
4988 outlen
4989 }
4990
4991 #[allow(bad_style)]
4992 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
4993 (*s).server
4994 }
4995
4996 #[allow(bad_style)]
4997 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
4998 ffi::CRYPTO_add_lock(
4999 &mut (*ses).references,
5000 1,
5001 ffi::CRYPTO_LOCK_SSL_CTX,
5002 "mod.rs\0".as_ptr() as *const _,
5003 line!() as c_int,
5004 );
5005 0
5006 }
5007 }
5008}
5009
5010cfg_if! {
5011 if #[cfg(ossl300)] {
5012 use ffi::SSL_get1_peer_certificate;
5013 } else {
5014 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
5015 }
5016}
5017cfg_if! {
5018 if #[cfg(any(boringssl, ossl110, libressl291, awslc))] {
5019 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
5020 } else {
5021 use ffi::{
5022 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
5023 SSLv23_server_method as TLS_server_method,
5024 };
5025 }
5026}
5027cfg_if! {
5028 if #[cfg(ossl110)] {
5029 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5030 ffi::CRYPTO_get_ex_new_index(
5031 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5032 0,
5033 ptr::null_mut(),
5034 None,
5035 None,
5036 f,
5037 )
5038 }
5039
5040 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5041 ffi::CRYPTO_get_ex_new_index(
5042 ffi::CRYPTO_EX_INDEX_SSL,
5043 0,
5044 ptr::null_mut(),
5045 None,
5046 None,
5047 f,
5048 )
5049 }
5050 } else {
5051 use std::sync::Once;
5052
5053 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5054 static ONCE: Once = Once::new();
5056 ONCE.call_once(|| {
5057 cfg_if! {
5058 if #[cfg(not(any(boringssl, awslc)))] {
5059 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5060 } else {
5061 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5062 }
5063 }
5064 });
5065
5066 cfg_if! {
5067 if #[cfg(not(any(boringssl, awslc)))] {
5068 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5069 } else {
5070 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5071 }
5072 }
5073 }
5074
5075 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5076 static ONCE: Once = Once::new();
5078 ONCE.call_once(|| {
5079 #[cfg(not(any(boringssl, awslc)))]
5080 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5081 #[cfg(any(boringssl, awslc))]
5082 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5083 });
5084
5085 #[cfg(not(any(boringssl, awslc)))]
5086 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5087 #[cfg(any(boringssl, awslc))]
5088 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5089 }
5090 }
5091}