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))]
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(boringssl)]
118mod client_hello;
119mod connector;
120mod error;
121#[cfg(test)]
122mod test;
123
124#[cfg(boringssl)]
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(boringssl)] {
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(boringssl))]
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(boringssl))]
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(boringssl))]
184 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
185 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
186
187 #[cfg(not(boringssl))]
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))]
233 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
234
235 #[cfg(any(boringssl, ossl102, ossl110, libressl332))]
239 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
240
241 #[cfg(any(boringssl, ossl102, ossl110, libressl332))]
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))]
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))]
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))]
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(boringssl)]
453type SslBitType = c_int;
454#[cfg(not(boringssl))]
455type SslBitType = c_long;
456
457#[cfg(boringssl)]
458type SslTimeTy = u64;
459#[cfg(not(boringssl))]
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))]
678#[derive(Debug, Copy, Clone, PartialEq, Eq)]
679pub struct AlpnError(c_int);
680
681#[cfg(any(ossl102, libressl261, boringssl))]
682impl AlpnError {
683 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
685
686 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
688}
689
690#[cfg(ossl111)]
694#[derive(Debug, Copy, Clone, PartialEq, Eq)]
695pub struct ClientHelloError(c_int);
696
697#[cfg(ossl111)]
698impl ClientHelloError {
699 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
701
702 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
704}
705
706#[derive(Debug, Copy, Clone, PartialEq, Eq)]
708pub struct TicketKeyStatus(c_int);
709
710impl TicketKeyStatus {
711 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
713 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
715 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
717}
718
719#[derive(Debug, Copy, Clone, PartialEq, Eq)]
721#[cfg(boringssl)]
722pub struct SelectCertError(ffi::ssl_select_cert_result_t);
723
724#[cfg(boringssl)]
725impl SelectCertError {
726 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
728
729 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
731
732 #[cfg(bssl_google)]
738 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
739}
740
741#[cfg(ossl111)]
743#[derive(Debug, Copy, Clone, PartialEq, Eq)]
744pub struct SslCtValidationMode(c_int);
745
746#[cfg(ossl111)]
747impl SslCtValidationMode {
748 pub const PERMISSIVE: SslCtValidationMode =
749 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
750 pub const STRICT: SslCtValidationMode =
751 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
752}
753
754#[derive(Debug, Copy, Clone, PartialEq, Eq)]
756pub struct CertCompressionAlgorithm(c_int);
757
758impl CertCompressionAlgorithm {
759 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
760 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
761 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
762}
763
764#[derive(Debug, Copy, Clone, PartialEq, Eq)]
766pub struct SslVersion(c_int);
767
768impl SslVersion {
769 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
771
772 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
774
775 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
777
778 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
780
781 #[cfg(any(ossl111, libressl340, boringssl))]
785 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
786
787 #[cfg(tongsuo)]
788 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
789
790 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
794
795 #[cfg(any(ossl102, libressl332, boringssl))]
799 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
800}
801
802cfg_if! {
803 if #[cfg(boringssl)] {
804 type SslCacheTy = i64;
805 type SslCacheSize = libc::c_ulong;
806 type MtuTy = u32;
807 type ModeTy = u32;
808 type SizeTy = usize;
809 } else {
810 type SslCacheTy = i64;
811 type SslCacheSize = c_long;
812 type MtuTy = c_long;
813 type ModeTy = c_long;
814 type SizeTy = u32;
815 }
816}
817
818#[corresponds(SSL_select_next_proto)]
829pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
830 unsafe {
831 let mut out = ptr::null_mut();
832 let mut outlen = 0;
833 let r = ffi::SSL_select_next_proto(
834 &mut out,
835 &mut outlen,
836 server.as_ptr(),
837 server.len() as c_uint,
838 client.as_ptr(),
839 client.len() as c_uint,
840 );
841 if r == ffi::OPENSSL_NPN_NEGOTIATED {
842 Some(util::from_raw_parts(out as *const u8, outlen as usize))
843 } else {
844 None
845 }
846 }
847}
848
849pub struct SslContextBuilder(SslContext);
851
852impl SslContextBuilder {
853 #[corresponds(SSL_CTX_new)]
855 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
856 unsafe {
857 init();
858 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
859
860 Ok(SslContextBuilder::from_ptr(ctx))
861 }
862 }
863
864 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
870 SslContextBuilder(SslContext::from_ptr(ctx))
871 }
872
873 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
875 self.0.as_ptr()
876 }
877
878 #[cfg(tongsuo)]
879 #[corresponds(SSL_CTX_enable_ntls)]
880 pub fn enable_ntls(&mut self) {
881 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
882 }
883
884 #[cfg(tongsuo)]
885 #[corresponds(SSL_CTX_disable_ntls)]
886 pub fn disable_ntls(&mut self) {
887 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
888 }
889
890 #[cfg(all(tongsuo, ossl300))]
891 #[corresponds(SSL_CTX_enable_force_ntls)]
892 pub fn enable_force_ntls(&mut self) {
893 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
894 }
895
896 #[cfg(all(tongsuo, ossl300))]
897 #[corresponds(SSL_CTX_disable_force_ntls)]
898 pub fn disable_force_ntls(&mut self) {
899 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
900 }
901
902 #[cfg(tongsuo)]
903 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
904 pub fn enable_sm_tls13_strict(&mut self) {
905 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
906 }
907
908 #[cfg(tongsuo)]
909 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
910 pub fn disable_sm_tls13_strict(&mut self) {
911 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
912 }
913
914 #[corresponds(SSL_CTX_set_verify)]
916 pub fn set_verify(&mut self, mode: SslVerifyMode) {
917 unsafe {
918 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
919 }
920 }
921
922 #[corresponds(SSL_CTX_set_verify)]
929 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
930 where
931 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
932 {
933 unsafe {
934 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
935 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
936 }
937 }
938
939 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
947 pub fn set_servername_callback<F>(&mut self, callback: F)
949 where
950 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
951 {
952 unsafe {
953 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
959 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
960 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
961 }
962 }
963
964 #[corresponds(SSL_CTX_set_verify_depth)]
968 pub fn set_verify_depth(&mut self, depth: u32) {
969 unsafe {
970 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
971 }
972 }
973
974 #[corresponds(SSL_CTX_set0_verify_cert_store)]
978 #[cfg(any(ossl102, boringssl))]
979 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
980 unsafe {
981 let ptr = cert_store.as_ptr();
982 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
983 mem::forget(cert_store);
984
985 Ok(())
986 }
987 }
988
989 #[corresponds(SSL_CTX_set_cert_store)]
991 pub fn set_cert_store(&mut self, cert_store: X509Store) {
992 unsafe {
993 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
994 mem::forget(cert_store);
995 }
996 }
997
998 #[corresponds(SSL_CTX_set_read_ahead)]
1005 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1006 unsafe {
1007 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1008 }
1009 }
1010
1011 #[corresponds(SSL_CTX_set_mode)]
1015 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1016 unsafe {
1017 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1018 SslMode::from_bits_retain(bits)
1019 }
1020 }
1021
1022 #[corresponds(SSL_CTX_clear_mode)]
1024 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1025 unsafe {
1026 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1027 SslMode::from_bits_retain(bits)
1028 }
1029 }
1030
1031 #[corresponds(SSL_CTX_get_mode)]
1033 pub fn mode(&self) -> SslMode {
1034 unsafe {
1035 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1036 SslMode::from_bits_retain(bits)
1037 }
1038 }
1039
1040 #[corresponds(SSL_CTX_set_dh_auto)]
1049 #[cfg(ossl300)]
1050 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1051 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1052 }
1053
1054 #[corresponds(SSL_CTX_set_tmp_dh)]
1056 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1057 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1058 }
1059
1060 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1067 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1068 where
1069 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1070 {
1071 unsafe {
1072 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1073
1074 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1075 }
1076 }
1077
1078 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1080 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1081 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1082 }
1083
1084 #[corresponds(SSL_CTX_set_default_verify_paths)]
1089 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1090 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1091 }
1092
1093 #[corresponds(SSL_CTX_load_verify_locations)]
1097 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1098 self.load_verify_locations(Some(file.as_ref()), None)
1099 }
1100
1101 #[corresponds(SSL_CTX_load_verify_locations)]
1103 pub fn load_verify_locations(
1104 &mut self,
1105 ca_file: Option<&Path>,
1106 ca_path: Option<&Path>,
1107 ) -> Result<(), ErrorStack> {
1108 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1109 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1110 unsafe {
1111 cvt(ffi::SSL_CTX_load_verify_locations(
1112 self.as_ptr(),
1113 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1114 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1115 ))
1116 .map(|_| ())
1117 }
1118 }
1119
1120 #[corresponds(SSL_CTX_set_client_CA_list)]
1125 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1126 unsafe {
1127 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1128 mem::forget(list);
1129 }
1130 }
1131
1132 #[corresponds(SSL_CTX_add_client_CA)]
1135 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1136 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1137 }
1138
1139 #[corresponds(SSL_CTX_set_session_id_context)]
1148 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1149 unsafe {
1150 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1151 cvt(ffi::SSL_CTX_set_session_id_context(
1152 self.as_ptr(),
1153 sid_ctx.as_ptr(),
1154 sid_ctx.len() as SizeTy,
1155 ))
1156 .map(|_| ())
1157 }
1158 }
1159
1160 #[corresponds(SSL_CTX_use_certificate_file)]
1166 pub fn set_certificate_file<P: AsRef<Path>>(
1167 &mut self,
1168 file: P,
1169 file_type: SslFiletype,
1170 ) -> Result<(), ErrorStack> {
1171 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1172 unsafe {
1173 cvt(ffi::SSL_CTX_use_certificate_file(
1174 self.as_ptr(),
1175 file.as_ptr() as *const _,
1176 file_type.as_raw(),
1177 ))
1178 .map(|_| ())
1179 }
1180 }
1181
1182 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1188 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1189 &mut self,
1190 file: P,
1191 ) -> Result<(), ErrorStack> {
1192 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1193 unsafe {
1194 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1195 self.as_ptr(),
1196 file.as_ptr() as *const _,
1197 ))
1198 .map(|_| ())
1199 }
1200 }
1201
1202 #[corresponds(SSL_CTX_use_certificate)]
1206 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1207 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1208 }
1209
1210 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1215 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1216 unsafe {
1217 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1218 mem::forget(cert);
1219 Ok(())
1220 }
1221 }
1222
1223 #[cfg(tongsuo)]
1224 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1225 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1226 &mut self,
1227 file: P,
1228 file_type: SslFiletype,
1229 ) -> Result<(), ErrorStack> {
1230 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1231 unsafe {
1232 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1233 self.as_ptr(),
1234 file.as_ptr() as *const _,
1235 file_type.as_raw(),
1236 ))
1237 .map(|_| ())
1238 }
1239 }
1240
1241 #[cfg(tongsuo)]
1242 #[corresponds(SSL_CTX_use_enc_certificate)]
1243 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1244 unsafe {
1245 cvt(ffi::SSL_CTX_use_enc_certificate(
1246 self.as_ptr(),
1247 cert.as_ptr(),
1248 ))
1249 .map(|_| ())
1250 }
1251 }
1252
1253 #[cfg(tongsuo)]
1254 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1255 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1256 &mut self,
1257 file: P,
1258 file_type: SslFiletype,
1259 ) -> Result<(), ErrorStack> {
1260 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1261 unsafe {
1262 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1263 self.as_ptr(),
1264 file.as_ptr() as *const _,
1265 file_type.as_raw(),
1266 ))
1267 .map(|_| ())
1268 }
1269 }
1270
1271 #[cfg(tongsuo)]
1272 #[corresponds(SSL_CTX_use_sign_certificate)]
1273 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1274 unsafe {
1275 cvt(ffi::SSL_CTX_use_sign_certificate(
1276 self.as_ptr(),
1277 cert.as_ptr(),
1278 ))
1279 .map(|_| ())
1280 }
1281 }
1282
1283 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1285 pub fn set_private_key_file<P: AsRef<Path>>(
1286 &mut self,
1287 file: P,
1288 file_type: SslFiletype,
1289 ) -> Result<(), ErrorStack> {
1290 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1291 unsafe {
1292 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1293 self.as_ptr(),
1294 file.as_ptr() as *const _,
1295 file_type.as_raw(),
1296 ))
1297 .map(|_| ())
1298 }
1299 }
1300
1301 #[corresponds(SSL_CTX_use_PrivateKey)]
1303 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1304 where
1305 T: HasPrivate,
1306 {
1307 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1308 }
1309
1310 #[cfg(tongsuo)]
1311 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1312 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1313 &mut self,
1314 file: P,
1315 file_type: SslFiletype,
1316 ) -> Result<(), ErrorStack> {
1317 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1318 unsafe {
1319 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1320 self.as_ptr(),
1321 file.as_ptr() as *const _,
1322 file_type.as_raw(),
1323 ))
1324 .map(|_| ())
1325 }
1326 }
1327
1328 #[cfg(tongsuo)]
1329 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1330 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1331 where
1332 T: HasPrivate,
1333 {
1334 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1335 }
1336
1337 #[cfg(tongsuo)]
1338 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1339 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1340 &mut self,
1341 file: P,
1342 file_type: SslFiletype,
1343 ) -> Result<(), ErrorStack> {
1344 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1345 unsafe {
1346 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1347 self.as_ptr(),
1348 file.as_ptr() as *const _,
1349 file_type.as_raw(),
1350 ))
1351 .map(|_| ())
1352 }
1353 }
1354
1355 #[cfg(tongsuo)]
1356 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1357 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1358 where
1359 T: HasPrivate,
1360 {
1361 unsafe {
1362 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1363 self.as_ptr(),
1364 key.as_ptr(),
1365 ))
1366 .map(|_| ())
1367 }
1368 }
1369
1370 #[corresponds(SSL_CTX_set_cipher_list)]
1378 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1379 let cipher_list = CString::new(cipher_list).unwrap();
1380 unsafe {
1381 cvt(ffi::SSL_CTX_set_cipher_list(
1382 self.as_ptr(),
1383 cipher_list.as_ptr() as *const _,
1384 ))
1385 .map(|_| ())
1386 }
1387 }
1388
1389 #[corresponds(SSL_CTX_set_ciphersuites)]
1398 #[cfg(any(ossl111, libressl340, bssl_aws))]
1399 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1400 let cipher_list = CString::new(cipher_list).unwrap();
1401 unsafe {
1402 cvt(ffi::SSL_CTX_set_ciphersuites(
1403 self.as_ptr(),
1404 cipher_list.as_ptr() as *const _,
1405 ))
1406 .map(|_| ())
1407 }
1408 }
1409
1410 #[corresponds(SSL_CTX_set_ecdh_auto)]
1414 #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1415 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1416 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1417 }
1418
1419 #[corresponds(SSL_CTX_set_options)]
1426 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1427 let bits =
1428 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1429 SslOptions::from_bits_retain(bits)
1430 }
1431
1432 #[corresponds(SSL_CTX_get_options)]
1434 pub fn options(&self) -> SslOptions {
1435 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1436 SslOptions::from_bits_retain(bits)
1437 }
1438
1439 #[corresponds(SSL_CTX_clear_options)]
1441 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1442 let bits =
1443 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1444 SslOptions::from_bits_retain(bits)
1445 }
1446
1447 #[corresponds(SSL_CTX_set_min_proto_version)]
1454 #[cfg(any(ossl110, libressl261, boringssl))]
1455 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1456 unsafe {
1457 cvt(ffi::SSL_CTX_set_min_proto_version(
1458 self.as_ptr(),
1459 version.map_or(0, |v| v.0 as _),
1460 ))
1461 .map(|_| ())
1462 }
1463 }
1464
1465 #[corresponds(SSL_CTX_set_max_proto_version)]
1472 #[cfg(any(ossl110, libressl261, boringssl))]
1473 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1474 unsafe {
1475 cvt(ffi::SSL_CTX_set_max_proto_version(
1476 self.as_ptr(),
1477 version.map_or(0, |v| v.0 as _),
1478 ))
1479 .map(|_| ())
1480 }
1481 }
1482
1483 #[corresponds(SSL_CTX_get_min_proto_version)]
1490 #[cfg(any(ossl110g, libressl270))]
1491 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1492 unsafe {
1493 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1494 if r == 0 {
1495 None
1496 } else {
1497 Some(SslVersion(r))
1498 }
1499 }
1500 }
1501
1502 #[corresponds(SSL_CTX_get_max_proto_version)]
1509 #[cfg(any(ossl110g, libressl270))]
1510 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1511 unsafe {
1512 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1513 if r == 0 {
1514 None
1515 } else {
1516 Some(SslVersion(r))
1517 }
1518 }
1519 }
1520
1521 #[corresponds(SSL_CTX_set_alpn_protos)]
1530 #[cfg(any(ossl102, libressl261, boringssl))]
1531 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1532 unsafe {
1533 assert!(protocols.len() <= c_uint::MAX as usize);
1534 let r = ffi::SSL_CTX_set_alpn_protos(
1535 self.as_ptr(),
1536 protocols.as_ptr(),
1537 protocols.len() as _,
1538 );
1539 if r == 0 {
1541 Ok(())
1542 } else {
1543 Err(ErrorStack::get())
1544 }
1545 }
1546 }
1547
1548 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1550 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1551 unsafe {
1552 let cstr = CString::new(protocols).unwrap();
1553
1554 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1555 if r == 0 {
1557 Ok(())
1558 } else {
1559 Err(ErrorStack::get())
1560 }
1561 }
1562 }
1563
1564 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1577 #[cfg(any(ossl102, libressl261, boringssl))]
1578 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1579 where
1580 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1581 {
1582 unsafe {
1583 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1584 ffi::SSL_CTX_set_alpn_select_cb(
1585 self.as_ptr(),
1586 Some(callbacks::raw_alpn_select::<F>),
1587 ptr::null_mut(),
1588 );
1589 }
1590 }
1591
1592 #[corresponds(SSL_CTX_check_private_key)]
1594 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1595 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1596 }
1597
1598 #[corresponds(SSL_CTX_get_cert_store)]
1600 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1601 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1602 }
1603
1604 #[corresponds(SSL_CTX_get_cert_store)]
1606 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1607 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1608 }
1609
1610 #[corresponds(SSL_CTX_get0_param)]
1614 #[cfg(any(ossl102, boringssl, libressl261))]
1615 pub fn verify_param(&self) -> &X509VerifyParamRef {
1616 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1617 }
1618
1619 #[corresponds(SSL_CTX_get0_param)]
1623 #[cfg(any(ossl102, boringssl, libressl261))]
1624 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1625 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1626 }
1627
1628 #[cfg(any(boringssl, tongsuo))]
1636 pub fn add_cert_decompression_alg<F>(
1637 &mut self,
1638 alg_id: CertCompressionAlgorithm,
1639 decompress: F,
1640 ) -> Result<(), ErrorStack>
1641 where
1642 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1643 {
1644 unsafe {
1645 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1646 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1647 self.as_ptr(),
1648 alg_id.0 as _,
1649 None,
1650 Some(raw_cert_decompression::<F>),
1651 ))
1652 .map(|_| ())
1653 }
1654 }
1655
1656 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1658 #[cfg(ossl320)]
1659 pub fn set_cert_comp_preference(
1660 &mut self,
1661 algs: &[CertCompressionAlgorithm],
1662 ) -> Result<(), ErrorStack> {
1663 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1664 unsafe {
1665 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1666 self.as_ptr(),
1667 algs.as_mut_ptr(),
1668 algs.len(),
1669 ))
1670 .map(|_| ())
1671 }
1672 }
1673
1674 #[cfg(boringssl)]
1682 pub fn enable_ocsp_stapling(&mut self) {
1683 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1684 }
1685
1686 #[cfg(boringssl)]
1694 pub fn enable_signed_cert_timestamps(&mut self) {
1695 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1696 }
1697
1698 #[cfg(boringssl)]
1706 pub fn set_grease_enabled(&mut self, enabled: bool) {
1707 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1708 }
1709
1710 #[cfg(boringssl)]
1718 pub fn set_permute_extensions(&mut self, enabled: bool) {
1719 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1720 }
1721
1722 #[corresponds(SSL_CTX_enable_ct)]
1724 #[cfg(ossl111)]
1725 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1726 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1727 }
1728
1729 #[corresponds(SSL_CTX_ct_is_enabled)]
1731 #[cfg(ossl111)]
1732 pub fn ct_is_enabled(&self) -> bool {
1733 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1734 }
1735
1736 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1738 #[cfg(not(boringssl))]
1739 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1740 unsafe {
1741 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1742 .map(|_| ())
1743 }
1744 }
1745
1746 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1759 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1760 where
1761 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1762 {
1763 unsafe {
1764 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1765 cvt(
1766 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1767 as c_int,
1768 )
1769 .map(|_| ())
1770 }
1771 }
1772
1773 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1774 #[cfg(ossl300)]
1775 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1776 where
1777 F: Fn(
1778 &mut SslRef,
1779 &mut [u8],
1780 &mut [u8],
1781 &mut CipherCtxRef,
1782 &mut MacCtxRef,
1783 bool,
1784 ) -> Result<TicketKeyStatus, ErrorStack>
1785 + 'static
1786 + Sync
1787 + Send,
1788 {
1789 unsafe {
1790 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1791 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1792 self.as_ptr(),
1793 Some(raw_tlsext_ticket_key_evp::<F>),
1794 ) as c_int)
1795 .map(|_| ())
1796 }
1797 }
1798
1799 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1800 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1801 where
1802 F: Fn(
1803 &mut SslRef,
1804 &mut [u8],
1805 &mut [u8],
1806 &mut CipherCtxRef,
1807 &mut HMacCtxRef,
1808 bool,
1809 ) -> Result<TicketKeyStatus, ErrorStack>
1810 + 'static
1811 + Sync
1812 + Send,
1813 {
1814 unsafe {
1815 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1816 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1817 self.as_ptr(),
1818 Some(raw_tlsext_ticket_key::<F>),
1819 ) as c_int)
1820 .map(|_| ())
1821 }
1822 }
1823
1824 #[corresponds(SSL_CTX_set_psk_client_callback)]
1830 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1831 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1832 where
1833 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1834 + 'static
1835 + Sync
1836 + Send,
1837 {
1838 unsafe {
1839 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1840 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1841 }
1842 }
1843
1844 #[corresponds(SSL_CTX_set_psk_server_callback)]
1850 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1851 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1852 where
1853 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1854 + 'static
1855 + Sync
1856 + Send,
1857 {
1858 unsafe {
1859 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1860 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1861 }
1862 }
1863
1864 #[corresponds(SSL_CTX_sess_set_new_cb)]
1878 pub fn set_new_session_callback<F>(&mut self, callback: F)
1879 where
1880 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1881 {
1882 unsafe {
1883 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1884 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1885 }
1886 }
1887
1888 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1892 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1893 where
1894 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1895 {
1896 unsafe {
1897 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1898 ffi::SSL_CTX_sess_set_remove_cb(
1899 self.as_ptr(),
1900 Some(callbacks::raw_remove_session::<F>),
1901 );
1902 }
1903 }
1904
1905 #[corresponds(SSL_CTX_sess_set_get_cb)]
1916 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1917 where
1918 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1919 {
1920 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1921 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1922 }
1923
1924 #[corresponds(SSL_CTX_set_keylog_callback)]
1932 #[cfg(any(ossl111, boringssl))]
1933 pub fn set_keylog_callback<F>(&mut self, callback: F)
1934 where
1935 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1936 {
1937 unsafe {
1938 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1939 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1940 }
1941 }
1942
1943 #[corresponds(SSL_CTX_set_session_cache_mode)]
1947 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1948 unsafe {
1949 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1950 SslSessionCacheMode::from_bits_retain(bits)
1951 }
1952 }
1953
1954 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1960 #[cfg(ossl111)]
1961 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1962 where
1963 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1964 {
1965 unsafe {
1966 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1967 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1968 self.as_ptr(),
1969 Some(raw_stateless_cookie_generate::<F>),
1970 );
1971 }
1972 }
1973
1974 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1983 #[cfg(ossl111)]
1984 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1985 where
1986 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1987 {
1988 unsafe {
1989 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1990 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1991 self.as_ptr(),
1992 Some(raw_stateless_cookie_verify::<F>),
1993 )
1994 }
1995 }
1996
1997 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
2002 #[cfg(not(boringssl))]
2003 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
2004 where
2005 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
2006 {
2007 unsafe {
2008 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2009 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2010 }
2011 }
2012
2013 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2018 #[cfg(not(boringssl))]
2019 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2020 where
2021 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2022 {
2023 unsafe {
2024 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2025 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2026 }
2027 }
2028
2029 #[corresponds(SSL_CTX_set_ex_data)]
2035 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2036 self.set_ex_data_inner(index, data);
2037 }
2038
2039 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2040 match self.ex_data_mut(index) {
2041 Some(v) => {
2042 *v = data;
2043 (v as *mut T).cast()
2044 }
2045 _ => unsafe {
2046 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2047 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2048 data
2049 },
2050 }
2051 }
2052
2053 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2054 unsafe {
2055 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2056 if data.is_null() {
2057 None
2058 } else {
2059 Some(&mut *data.cast())
2060 }
2061 }
2062 }
2063
2064 #[corresponds(SSL_CTX_add_custom_ext)]
2068 #[cfg(ossl111)]
2069 pub fn add_custom_ext<AddFn, ParseFn, T>(
2070 &mut self,
2071 ext_type: u16,
2072 context: ExtensionContext,
2073 add_cb: AddFn,
2074 parse_cb: ParseFn,
2075 ) -> Result<(), ErrorStack>
2076 where
2077 AddFn: Fn(
2078 &mut SslRef,
2079 ExtensionContext,
2080 Option<(usize, &X509Ref)>,
2081 ) -> Result<Option<T>, SslAlert>
2082 + 'static
2083 + Sync
2084 + Send,
2085 T: AsRef<[u8]> + 'static + Sync + Send,
2086 ParseFn: Fn(
2087 &mut SslRef,
2088 ExtensionContext,
2089 &[u8],
2090 Option<(usize, &X509Ref)>,
2091 ) -> Result<(), SslAlert>
2092 + 'static
2093 + Sync
2094 + Send,
2095 {
2096 let ret = unsafe {
2097 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2098 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2099
2100 ffi::SSL_CTX_add_custom_ext(
2101 self.as_ptr(),
2102 ext_type as c_uint,
2103 context.bits(),
2104 Some(raw_custom_ext_add::<AddFn, T>),
2105 Some(raw_custom_ext_free::<T>),
2106 ptr::null_mut(),
2107 Some(raw_custom_ext_parse::<ParseFn>),
2108 ptr::null_mut(),
2109 )
2110 };
2111 if ret == 1 {
2112 Ok(())
2113 } else {
2114 Err(ErrorStack::get())
2115 }
2116 }
2117
2118 #[corresponds(SSL_CTX_set_max_early_data)]
2124 #[cfg(any(ossl111, libressl340))]
2125 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2126 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2127 Ok(())
2128 } else {
2129 Err(ErrorStack::get())
2130 }
2131 }
2132
2133 #[cfg(boringssl)]
2143 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2144 where
2145 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2146 {
2147 unsafe {
2148 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2149 ffi::SSL_CTX_set_select_certificate_cb(
2150 self.as_ptr(),
2151 Some(callbacks::raw_select_cert::<F>),
2152 );
2153 }
2154 }
2155
2156 #[corresponds(SSL_CTX_set_client_hello_cb)]
2160 #[cfg(ossl111)]
2161 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2162 where
2163 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2164 {
2165 unsafe {
2166 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2167 ffi::SSL_CTX_set_client_hello_cb(
2168 self.as_ptr(),
2169 Some(callbacks::raw_client_hello::<F>),
2170 ptr,
2171 );
2172 }
2173 }
2174
2175 #[corresponds(SSL_CTX_sess_set_cache_size)]
2179 #[allow(clippy::useless_conversion)]
2180 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2181 unsafe {
2182 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2183 }
2184 }
2185
2186 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2190 #[cfg(ossl102)]
2191 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2192 let sigalgs = CString::new(sigalgs).unwrap();
2193 unsafe {
2194 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2195 .map(|_| ())
2196 }
2197 }
2198
2199 #[corresponds(SSL_CTX_set1_groups_list)]
2203 #[cfg(any(ossl111, boringssl, libressl251))]
2204 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2205 let groups = CString::new(groups).unwrap();
2206 unsafe {
2207 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2208 }
2209 }
2210
2211 #[corresponds(SSL_CTX_set_num_tickets)]
2216 #[cfg(any(ossl111, boringssl))]
2217 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2218 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2219 }
2220
2221 #[corresponds(SSL_CTX_set_security_level)]
2226 #[cfg(any(ossl110, libressl360))]
2227 pub fn set_security_level(&mut self, level: u32) {
2228 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2229 }
2230
2231 pub fn build(self) -> SslContext {
2233 self.0
2234 }
2235}
2236
2237foreign_type_and_impl_send_sync! {
2238 type CType = ffi::SSL_CTX;
2239 fn drop = ffi::SSL_CTX_free;
2240
2241 pub struct SslContext;
2246
2247 pub struct SslContextRef;
2251}
2252
2253impl Clone for SslContext {
2254 fn clone(&self) -> Self {
2255 (**self).to_owned()
2256 }
2257}
2258
2259impl ToOwned for SslContextRef {
2260 type Owned = SslContext;
2261
2262 fn to_owned(&self) -> Self::Owned {
2263 unsafe {
2264 SSL_CTX_up_ref(self.as_ptr());
2265 SslContext::from_ptr(self.as_ptr())
2266 }
2267 }
2268}
2269
2270impl fmt::Debug for SslContext {
2272 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2273 write!(fmt, "SslContext")
2274 }
2275}
2276
2277impl SslContext {
2278 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2280 SslContextBuilder::new(method)
2281 }
2282
2283 #[corresponds(SSL_CTX_get_ex_new_index)]
2288 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2289 where
2290 T: 'static + Sync + Send,
2291 {
2292 unsafe {
2293 ffi::init();
2294 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2295 Ok(Index::from_raw(idx))
2296 }
2297 }
2298
2299 fn cached_ex_index<T>() -> Index<SslContext, T>
2301 where
2302 T: 'static + Sync + Send,
2303 {
2304 unsafe {
2305 let idx = *INDEXES
2306 .lock()
2307 .unwrap_or_else(|e| e.into_inner())
2308 .entry(TypeId::of::<T>())
2309 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2310 Index::from_raw(idx)
2311 }
2312 }
2313}
2314
2315impl SslContextRef {
2316 #[corresponds(SSL_CTX_get0_certificate)]
2320 #[cfg(any(ossl102, libressl270))]
2321 pub fn certificate(&self) -> Option<&X509Ref> {
2322 unsafe {
2323 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2324 X509Ref::from_const_ptr_opt(ptr)
2325 }
2326 }
2327
2328 #[corresponds(SSL_CTX_get0_privatekey)]
2332 #[cfg(any(ossl102, libressl340))]
2333 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2334 unsafe {
2335 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2336 PKeyRef::from_const_ptr_opt(ptr)
2337 }
2338 }
2339
2340 #[corresponds(SSL_CTX_get_cert_store)]
2342 pub fn cert_store(&self) -> &X509StoreRef {
2343 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2344 }
2345
2346 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2348 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2349 unsafe {
2350 let mut chain = ptr::null_mut();
2351 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2352 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2353 }
2354 }
2355
2356 #[corresponds(SSL_CTX_get_ex_data)]
2358 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2359 unsafe {
2360 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2361 if data.is_null() {
2362 None
2363 } else {
2364 Some(&*(data as *const T))
2365 }
2366 }
2367 }
2368
2369 #[corresponds(SSL_CTX_get_max_early_data)]
2373 #[cfg(any(ossl111, libressl340))]
2374 pub fn max_early_data(&self) -> u32 {
2375 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2376 }
2377
2378 #[corresponds(SSL_CTX_add_session)]
2387 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2388 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2389 }
2390
2391 #[corresponds(SSL_CTX_remove_session)]
2400 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2401 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2402 }
2403
2404 #[corresponds(SSL_CTX_sess_get_cache_size)]
2408 #[allow(clippy::unnecessary_cast)]
2409 pub fn session_cache_size(&self) -> i64 {
2410 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2411 }
2412
2413 #[corresponds(SSL_CTX_get_verify_mode)]
2417 pub fn verify_mode(&self) -> SslVerifyMode {
2418 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2419 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2420 }
2421
2422 #[corresponds(SSL_CTX_get_num_tickets)]
2427 #[cfg(ossl111)]
2428 pub fn num_tickets(&self) -> usize {
2429 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2430 }
2431
2432 #[corresponds(SSL_CTX_get_security_level)]
2437 #[cfg(any(ossl110, libressl360))]
2438 pub fn security_level(&self) -> u32 {
2439 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2440 }
2441}
2442
2443pub struct CipherBits {
2445 pub secret: i32,
2447
2448 pub algorithm: i32,
2450}
2451
2452pub struct SslCipher(*mut ffi::SSL_CIPHER);
2454
2455impl ForeignType for SslCipher {
2456 type CType = ffi::SSL_CIPHER;
2457 type Ref = SslCipherRef;
2458
2459 #[inline]
2460 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2461 SslCipher(ptr)
2462 }
2463
2464 #[inline]
2465 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2466 self.0
2467 }
2468}
2469
2470impl Stackable for SslCipher {
2471 type StackType = ffi::stack_st_SSL_CIPHER;
2472}
2473
2474impl Deref for SslCipher {
2475 type Target = SslCipherRef;
2476
2477 fn deref(&self) -> &SslCipherRef {
2478 unsafe { SslCipherRef::from_ptr(self.0) }
2479 }
2480}
2481
2482impl DerefMut for SslCipher {
2483 fn deref_mut(&mut self) -> &mut SslCipherRef {
2484 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2485 }
2486}
2487
2488pub struct SslCipherRef(Opaque);
2492
2493impl ForeignTypeRef for SslCipherRef {
2494 type CType = ffi::SSL_CIPHER;
2495}
2496
2497impl SslCipherRef {
2498 #[corresponds(SSL_CIPHER_get_name)]
2500 pub fn name(&self) -> &'static str {
2501 unsafe {
2502 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2503 CStr::from_ptr(ptr).to_str().unwrap()
2504 }
2505 }
2506
2507 #[corresponds(SSL_CIPHER_standard_name)]
2511 #[cfg(ossl111)]
2512 pub fn standard_name(&self) -> Option<&'static str> {
2513 unsafe {
2514 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2515 if ptr.is_null() {
2516 None
2517 } else {
2518 Some(CStr::from_ptr(ptr).to_str().unwrap())
2519 }
2520 }
2521 }
2522
2523 #[corresponds(SSL_CIPHER_get_version)]
2525 pub fn version(&self) -> &'static str {
2526 let version = unsafe {
2527 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2528 CStr::from_ptr(ptr as *const _)
2529 };
2530
2531 str::from_utf8(version.to_bytes()).unwrap()
2532 }
2533
2534 #[corresponds(SSL_CIPHER_get_bits)]
2536 #[allow(clippy::useless_conversion)]
2537 pub fn bits(&self) -> CipherBits {
2538 unsafe {
2539 let mut algo_bits = 0;
2540 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2541 CipherBits {
2542 secret: secret_bits.into(),
2543 algorithm: algo_bits.into(),
2544 }
2545 }
2546 }
2547
2548 #[corresponds(SSL_CIPHER_description)]
2550 pub fn description(&self) -> String {
2551 unsafe {
2552 let mut buf = [0; 128];
2554 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2555 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2556 }
2557 }
2558
2559 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2563 #[cfg(ossl111)]
2564 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2565 unsafe {
2566 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2567 if ptr.is_null() {
2568 None
2569 } else {
2570 Some(MessageDigest::from_ptr(ptr))
2571 }
2572 }
2573 }
2574
2575 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2579 #[cfg(any(ossl110, libressl270))]
2580 pub fn cipher_nid(&self) -> Option<Nid> {
2581 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2582 if n == 0 {
2583 None
2584 } else {
2585 Some(Nid::from_raw(n))
2586 }
2587 }
2588}
2589
2590impl fmt::Debug for SslCipherRef {
2591 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2592 write!(fmt, "{}", self.name())
2593 }
2594}
2595
2596#[derive(Debug)]
2598pub struct CipherLists {
2599 pub suites: Stack<SslCipher>,
2600 pub signalling_suites: Stack<SslCipher>,
2601}
2602
2603foreign_type_and_impl_send_sync! {
2604 type CType = ffi::SSL_SESSION;
2605 fn drop = ffi::SSL_SESSION_free;
2606
2607 pub struct SslSession;
2611
2612 pub struct SslSessionRef;
2616}
2617
2618impl Clone for SslSession {
2619 fn clone(&self) -> SslSession {
2620 SslSessionRef::to_owned(self)
2621 }
2622}
2623
2624impl SslSession {
2625 from_der! {
2626 #[corresponds(d2i_SSL_SESSION)]
2628 from_der,
2629 SslSession,
2630 ffi::d2i_SSL_SESSION
2631 }
2632}
2633
2634impl ToOwned for SslSessionRef {
2635 type Owned = SslSession;
2636
2637 fn to_owned(&self) -> SslSession {
2638 unsafe {
2639 SSL_SESSION_up_ref(self.as_ptr());
2640 SslSession(self.as_ptr())
2641 }
2642 }
2643}
2644
2645impl SslSessionRef {
2646 #[corresponds(SSL_SESSION_get_id)]
2648 pub fn id(&self) -> &[u8] {
2649 unsafe {
2650 let mut len = 0;
2651 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2652 #[allow(clippy::unnecessary_cast)]
2653 util::from_raw_parts(p as *const u8, len as usize)
2654 }
2655 }
2656
2657 #[corresponds(SSL_SESSION_get_master_key)]
2659 pub fn master_key_len(&self) -> usize {
2660 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2661 }
2662
2663 #[corresponds(SSL_SESSION_get_master_key)]
2667 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2668 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2669 }
2670
2671 #[corresponds(SSL_SESSION_get_max_early_data)]
2675 #[cfg(any(ossl111, libressl340))]
2676 pub fn max_early_data(&self) -> u32 {
2677 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2678 }
2679
2680 #[corresponds(SSL_SESSION_get_time)]
2682 #[allow(clippy::useless_conversion)]
2683 pub fn time(&self) -> SslTimeTy {
2684 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2685 }
2686
2687 #[corresponds(SSL_SESSION_get_timeout)]
2691 #[allow(clippy::useless_conversion)]
2692 pub fn timeout(&self) -> i64 {
2693 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2694 }
2695
2696 #[corresponds(SSL_SESSION_get_protocol_version)]
2700 #[cfg(any(ossl110, libressl270))]
2701 pub fn protocol_version(&self) -> SslVersion {
2702 unsafe {
2703 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2704 SslVersion(version)
2705 }
2706 }
2707
2708 #[corresponds(SSL_SESSION_get_protocol_version)]
2710 #[cfg(boringssl)]
2711 pub fn protocol_version(&self) -> SslVersion {
2712 unsafe {
2713 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2714 SslVersion(version as _)
2715 }
2716 }
2717
2718 to_der! {
2719 #[corresponds(i2d_SSL_SESSION)]
2721 to_der,
2722 ffi::i2d_SSL_SESSION
2723 }
2724}
2725
2726foreign_type_and_impl_send_sync! {
2727 type CType = ffi::SSL;
2728 fn drop = ffi::SSL_free;
2729
2730 pub struct Ssl;
2737
2738 pub struct SslRef;
2742}
2743
2744impl fmt::Debug for Ssl {
2745 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2746 fmt::Debug::fmt(&**self, fmt)
2747 }
2748}
2749
2750impl Ssl {
2751 #[corresponds(SSL_get_ex_new_index)]
2756 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2757 where
2758 T: 'static + Sync + Send,
2759 {
2760 unsafe {
2761 ffi::init();
2762 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2763 Ok(Index::from_raw(idx))
2764 }
2765 }
2766
2767 fn cached_ex_index<T>() -> Index<Ssl, T>
2769 where
2770 T: 'static + Sync + Send,
2771 {
2772 unsafe {
2773 let idx = *SSL_INDEXES
2774 .lock()
2775 .unwrap_or_else(|e| e.into_inner())
2776 .entry(TypeId::of::<T>())
2777 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2778 Index::from_raw(idx)
2779 }
2780 }
2781
2782 #[corresponds(SSL_new)]
2784 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2785 let session_ctx_index = try_get_session_ctx_index()?;
2786 unsafe {
2787 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2788 let mut ssl = Ssl::from_ptr(ptr);
2789 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2790
2791 Ok(ssl)
2792 }
2793 }
2794
2795 #[corresponds(SSL_connect)]
2801 #[allow(deprecated)]
2802 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2803 where
2804 S: Read + Write,
2805 {
2806 SslStreamBuilder::new(self, stream).connect()
2807 }
2808
2809 #[corresponds(SSL_accept)]
2816 #[allow(deprecated)]
2817 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2818 where
2819 S: Read + Write,
2820 {
2821 SslStreamBuilder::new(self, stream).accept()
2822 }
2823}
2824
2825impl fmt::Debug for SslRef {
2826 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2827 fmt.debug_struct("Ssl")
2828 .field("state", &self.state_string_long())
2829 .field("verify_result", &self.verify_result())
2830 .finish()
2831 }
2832}
2833
2834impl SslRef {
2835 #[cfg(not(feature = "tongsuo"))]
2836 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2837 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2838 }
2839
2840 #[cfg(feature = "tongsuo")]
2841 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2842 unsafe {
2843 let bio = ffi::SSL_get_rbio(self.as_ptr());
2844 bio::find_correct_bio(bio)
2845 }
2846 }
2847
2848 fn get_error(&self, ret: c_int) -> ErrorCode {
2849 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2850 }
2851
2852 #[corresponds(SSL_set_mode)]
2856 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2857 unsafe {
2858 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2859 SslMode::from_bits_retain(bits)
2860 }
2861 }
2862
2863 #[corresponds(SSL_clear_mode)]
2865 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2866 unsafe {
2867 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2868 SslMode::from_bits_retain(bits)
2869 }
2870 }
2871
2872 #[corresponds(SSL_get_mode)]
2874 pub fn mode(&self) -> SslMode {
2875 unsafe {
2876 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2877 SslMode::from_bits_retain(bits)
2878 }
2879 }
2880
2881 #[corresponds(SSL_set_connect_state)]
2883 pub fn set_connect_state(&mut self) {
2884 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2885 }
2886
2887 #[corresponds(SSL_set_accept_state)]
2889 pub fn set_accept_state(&mut self) {
2890 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2891 }
2892
2893 #[cfg(boringssl)]
2894 #[corresponds(SSL_ech_accepted)]
2895 pub fn ech_accepted(&self) -> bool {
2896 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2897 }
2898
2899 #[cfg(tongsuo)]
2900 #[corresponds(SSL_is_ntls)]
2901 pub fn is_ntls(&mut self) -> bool {
2902 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2903 }
2904
2905 #[cfg(tongsuo)]
2906 #[corresponds(SSL_enable_ntls)]
2907 pub fn enable_ntls(&mut self) {
2908 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2909 }
2910
2911 #[cfg(tongsuo)]
2912 #[corresponds(SSL_disable_ntls)]
2913 pub fn disable_ntls(&mut self) {
2914 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2915 }
2916
2917 #[cfg(all(tongsuo, ossl300))]
2918 #[corresponds(SSL_enable_force_ntls)]
2919 pub fn enable_force_ntls(&mut self) {
2920 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2921 }
2922
2923 #[cfg(all(tongsuo, ossl300))]
2924 #[corresponds(SSL_disable_force_ntls)]
2925 pub fn disable_force_ntls(&mut self) {
2926 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2927 }
2928
2929 #[cfg(tongsuo)]
2930 #[corresponds(SSL_enable_sm_tls13_strict)]
2931 pub fn enable_sm_tls13_strict(&mut self) {
2932 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2933 }
2934
2935 #[cfg(tongsuo)]
2936 #[corresponds(SSL_disable_sm_tls13_strict)]
2937 pub fn disable_sm_tls13_strict(&mut self) {
2938 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2939 }
2940
2941 #[corresponds(SSL_set_verify)]
2945 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2946 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2947 }
2948
2949 #[corresponds(SSL_set_verify_mode)]
2951 pub fn verify_mode(&self) -> SslVerifyMode {
2952 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2953 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2954 }
2955
2956 #[corresponds(SSL_set_verify)]
2960 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2961 where
2962 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2963 {
2964 unsafe {
2965 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2967 ffi::SSL_set_verify(
2968 self.as_ptr(),
2969 mode.bits() as c_int,
2970 Some(ssl_raw_verify::<F>),
2971 );
2972 }
2973 }
2974
2975 #[corresponds(SSL_set_dh_auto)]
2979 #[cfg(ossl300)]
2980 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2981 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2982 }
2983
2984 #[corresponds(SSL_set_tmp_dh)]
2988 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2989 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2990 }
2991
2992 #[corresponds(SSL_set_tmp_dh_callback)]
2996 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2997 where
2998 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2999 {
3000 unsafe {
3001 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3003 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3004 }
3005 }
3006
3007 #[corresponds(SSL_set_tmp_ecdh)]
3011 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3012 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3013 }
3014
3015 #[corresponds(SSL_set_ecdh_auto)]
3021 #[cfg(any(all(ossl102, not(ossl110)), libressl))]
3022 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3023 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
3024 }
3025
3026 #[corresponds(SSL_set_alpn_protos)]
3032 #[cfg(any(ossl102, libressl261, boringssl))]
3033 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3034 unsafe {
3035 assert!(protocols.len() <= c_uint::MAX as usize);
3036 let r =
3037 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3038 if r == 0 {
3040 Ok(())
3041 } else {
3042 Err(ErrorStack::get())
3043 }
3044 }
3045 }
3046
3047 #[corresponds(SSL_get_current_cipher)]
3049 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3050 unsafe {
3051 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3052
3053 SslCipherRef::from_const_ptr_opt(ptr)
3054 }
3055 }
3056
3057 #[corresponds(SSL_state_string)]
3059 pub fn state_string(&self) -> &'static str {
3060 let state = unsafe {
3061 let ptr = ffi::SSL_state_string(self.as_ptr());
3062 CStr::from_ptr(ptr as *const _)
3063 };
3064
3065 str::from_utf8(state.to_bytes()).unwrap()
3066 }
3067
3068 #[corresponds(SSL_state_string_long)]
3070 pub fn state_string_long(&self) -> &'static str {
3071 let state = unsafe {
3072 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3073 CStr::from_ptr(ptr as *const _)
3074 };
3075
3076 str::from_utf8(state.to_bytes()).unwrap()
3077 }
3078
3079 #[corresponds(SSL_set_tlsext_host_name)]
3083 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3084 let cstr = CString::new(hostname).unwrap();
3085 unsafe {
3086 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3087 .map(|_| ())
3088 }
3089 }
3090
3091 #[corresponds(SSL_get_peer_certificate)]
3093 pub fn peer_certificate(&self) -> Option<X509> {
3094 unsafe {
3095 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3096 X509::from_ptr_opt(ptr)
3097 }
3098 }
3099
3100 #[corresponds(SSL_get_peer_cert_chain)]
3105 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3106 unsafe {
3107 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3108 StackRef::from_const_ptr_opt(ptr)
3109 }
3110 }
3111
3112 #[corresponds(SSL_get0_verified_chain)]
3122 #[cfg(ossl110)]
3123 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3124 unsafe {
3125 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3126 StackRef::from_const_ptr_opt(ptr)
3127 }
3128 }
3129
3130 #[corresponds(SSL_get_certificate)]
3132 pub fn certificate(&self) -> Option<&X509Ref> {
3133 unsafe {
3134 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3135 X509Ref::from_const_ptr_opt(ptr)
3136 }
3137 }
3138
3139 #[corresponds(SSL_get_privatekey)]
3143 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3144 unsafe {
3145 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3146 PKeyRef::from_const_ptr_opt(ptr)
3147 }
3148 }
3149
3150 #[corresponds(SSL_version)]
3152 pub fn version2(&self) -> Option<SslVersion> {
3153 unsafe {
3154 let r = ffi::SSL_version(self.as_ptr());
3155 if r == 0 {
3156 None
3157 } else {
3158 Some(SslVersion(r))
3159 }
3160 }
3161 }
3162
3163 #[corresponds(SSL_get_version)]
3165 pub fn version_str(&self) -> &'static str {
3166 let version = unsafe {
3167 let ptr = ffi::SSL_get_version(self.as_ptr());
3168 CStr::from_ptr(ptr as *const _)
3169 };
3170
3171 str::from_utf8(version.to_bytes()).unwrap()
3172 }
3173
3174 #[corresponds(SSL_get0_alpn_selected)]
3181 #[cfg(any(ossl102, libressl261, boringssl))]
3182 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3183 unsafe {
3184 let mut data: *const c_uchar = ptr::null();
3185 let mut len: c_uint = 0;
3186 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3189
3190 if data.is_null() {
3191 None
3192 } else {
3193 Some(util::from_raw_parts(data, len as usize))
3194 }
3195 }
3196 }
3197
3198 #[corresponds(SSL_set_tlsext_use_srtp)]
3200 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3201 unsafe {
3202 let cstr = CString::new(protocols).unwrap();
3203
3204 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3205 if r == 0 {
3207 Ok(())
3208 } else {
3209 Err(ErrorStack::get())
3210 }
3211 }
3212 }
3213
3214 #[corresponds(SSL_get_srtp_profiles)]
3218 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3219 unsafe {
3220 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3221
3222 StackRef::from_const_ptr_opt(chain)
3223 }
3224 }
3225
3226 #[corresponds(SSL_get_selected_srtp_profile)]
3230 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3231 unsafe {
3232 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3233
3234 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3235 }
3236 }
3237
3238 #[corresponds(SSL_pending)]
3243 pub fn pending(&self) -> usize {
3244 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3245 }
3246
3247 #[corresponds(SSL_get_servername)]
3260 pub fn servername(&self, type_: NameType) -> Option<&str> {
3262 self.servername_raw(type_)
3263 .and_then(|b| str::from_utf8(b).ok())
3264 }
3265
3266 #[corresponds(SSL_get_servername)]
3274 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3275 unsafe {
3276 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3277 if name.is_null() {
3278 None
3279 } else {
3280 Some(CStr::from_ptr(name as *const _).to_bytes())
3281 }
3282 }
3283 }
3284
3285 #[corresponds(SSL_set_SSL_CTX)]
3289 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3290 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3291 }
3292
3293 #[corresponds(SSL_get_SSL_CTX)]
3295 pub fn ssl_context(&self) -> &SslContextRef {
3296 unsafe {
3297 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3298 SslContextRef::from_ptr(ssl_ctx)
3299 }
3300 }
3301
3302 #[corresponds(SSL_get0_param)]
3306 #[cfg(any(ossl102, boringssl, libressl261))]
3307 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3308 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3309 }
3310
3311 #[corresponds(SSL_get_verify_result)]
3313 pub fn verify_result(&self) -> X509VerifyResult {
3314 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3315 }
3316
3317 #[corresponds(SSL_get_session)]
3319 pub fn session(&self) -> Option<&SslSessionRef> {
3320 unsafe {
3321 let p = ffi::SSL_get_session(self.as_ptr());
3322 SslSessionRef::from_const_ptr_opt(p)
3323 }
3324 }
3325
3326 #[corresponds(SSL_get_client_random)]
3333 #[cfg(any(ossl110, libressl270))]
3334 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3335 unsafe {
3336 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3337 }
3338 }
3339
3340 #[corresponds(SSL_get_server_random)]
3347 #[cfg(any(ossl110, libressl270))]
3348 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3349 unsafe {
3350 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3351 }
3352 }
3353
3354 #[corresponds(SSL_export_keying_material)]
3356 pub fn export_keying_material(
3357 &self,
3358 out: &mut [u8],
3359 label: &str,
3360 context: Option<&[u8]>,
3361 ) -> Result<(), ErrorStack> {
3362 unsafe {
3363 let (context, contextlen, use_context) = match context {
3364 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3365 None => (ptr::null(), 0, 0),
3366 };
3367 cvt(ffi::SSL_export_keying_material(
3368 self.as_ptr(),
3369 out.as_mut_ptr() as *mut c_uchar,
3370 out.len(),
3371 label.as_ptr() as *const c_char,
3372 label.len(),
3373 context,
3374 contextlen,
3375 use_context,
3376 ))
3377 .map(|_| ())
3378 }
3379 }
3380
3381 #[corresponds(SSL_export_keying_material_early)]
3388 #[cfg(ossl111)]
3389 pub fn export_keying_material_early(
3390 &self,
3391 out: &mut [u8],
3392 label: &str,
3393 context: &[u8],
3394 ) -> Result<(), ErrorStack> {
3395 unsafe {
3396 cvt(ffi::SSL_export_keying_material_early(
3397 self.as_ptr(),
3398 out.as_mut_ptr() as *mut c_uchar,
3399 out.len(),
3400 label.as_ptr() as *const c_char,
3401 label.len(),
3402 context.as_ptr() as *const c_uchar,
3403 context.len(),
3404 ))
3405 .map(|_| ())
3406 }
3407 }
3408
3409 #[corresponds(SSL_set_session)]
3420 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3421 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3422 }
3423
3424 #[corresponds(SSL_session_reused)]
3426 pub fn session_reused(&self) -> bool {
3427 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3428 }
3429
3430 #[cfg(boringssl)]
3438 pub fn enable_ocsp_stapling(&mut self) {
3439 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3440 }
3441
3442 #[cfg(boringssl)]
3450 pub fn enable_signed_cert_timestamps(&mut self) {
3451 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3452 }
3453
3454 #[cfg(boringssl)]
3462 pub fn set_permute_extensions(&mut self, enabled: bool) {
3463 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3464 }
3465
3466 #[corresponds(SSL_enable_ct)]
3468 #[cfg(ossl111)]
3469 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3470 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3471 }
3472
3473 #[corresponds(SSL_ct_is_enabled)]
3475 #[cfg(ossl111)]
3476 pub fn ct_is_enabled(&self) -> bool {
3477 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3478 }
3479
3480 #[corresponds(SSL_set_tlsext_status_type)]
3482 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3483 unsafe {
3484 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3485 }
3486 }
3487
3488 #[corresponds(SSL_get_extms_support)]
3492 #[cfg(ossl110)]
3493 pub fn extms_support(&self) -> Option<bool> {
3494 unsafe {
3495 match ffi::SSL_get_extms_support(self.as_ptr()) {
3496 -1 => None,
3497 ret => Some(ret != 0),
3498 }
3499 }
3500 }
3501
3502 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3504 #[cfg(not(boringssl))]
3505 pub fn ocsp_status(&self) -> Option<&[u8]> {
3506 unsafe {
3507 let mut p = ptr::null_mut();
3508 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3509
3510 if len < 0 {
3511 None
3512 } else {
3513 Some(util::from_raw_parts(p as *const u8, len as usize))
3514 }
3515 }
3516 }
3517
3518 #[corresponds(SSL_get0_ocsp_response)]
3520 #[cfg(boringssl)]
3521 pub fn ocsp_status(&self) -> Option<&[u8]> {
3522 unsafe {
3523 let mut p = ptr::null();
3524 let mut len: usize = 0;
3525 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3526
3527 if len == 0 {
3528 None
3529 } else {
3530 Some(util::from_raw_parts(p as *const u8, len))
3531 }
3532 }
3533 }
3534
3535 #[corresponds(SSL_set_tlsext_status_ocsp_resp)]
3537 #[cfg(not(boringssl))]
3538 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3539 unsafe {
3540 assert!(response.len() <= c_int::MAX as usize);
3541 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3542 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3543 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3544 self.as_ptr(),
3545 p as *mut c_uchar,
3546 response.len() as c_long,
3547 ) as c_int)
3548 .map(|_| ())
3549 .map_err(|e| {
3550 ffi::OPENSSL_free(p);
3551 e
3552 })
3553 }
3554 }
3555
3556 #[corresponds(SSL_set_ocsp_response)]
3558 #[cfg(boringssl)]
3559 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3560 unsafe {
3561 cvt(ffi::SSL_set_ocsp_response(
3562 self.as_ptr(),
3563 response.as_ptr(),
3564 response.len(),
3565 ))
3566 .map(|_| ())
3567 }
3568 }
3569
3570 #[corresponds(SSL_is_server)]
3572 pub fn is_server(&self) -> bool {
3573 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3574 }
3575
3576 #[corresponds(SSL_set_ex_data)]
3582 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3583 match self.ex_data_mut(index) {
3584 Some(v) => *v = data,
3585 None => unsafe {
3586 let data = Box::new(data);
3587 ffi::SSL_set_ex_data(
3588 self.as_ptr(),
3589 index.as_raw(),
3590 Box::into_raw(data) as *mut c_void,
3591 );
3592 },
3593 }
3594 }
3595
3596 #[corresponds(SSL_get_ex_data)]
3598 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3599 unsafe {
3600 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3601 if data.is_null() {
3602 None
3603 } else {
3604 Some(&*(data as *const T))
3605 }
3606 }
3607 }
3608
3609 #[corresponds(SSL_get_ex_data)]
3611 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3612 unsafe {
3613 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3614 if data.is_null() {
3615 None
3616 } else {
3617 Some(&mut *(data as *mut T))
3618 }
3619 }
3620 }
3621
3622 #[corresponds(SSL_set_max_early_data)]
3626 #[cfg(any(ossl111, libressl340))]
3627 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3628 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3629 Ok(())
3630 } else {
3631 Err(ErrorStack::get())
3632 }
3633 }
3634
3635 #[corresponds(SSL_get_max_early_data)]
3639 #[cfg(any(ossl111, libressl340))]
3640 pub fn max_early_data(&self) -> u32 {
3641 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3642 }
3643
3644 #[corresponds(SSL_get_finished)]
3649 pub fn finished(&self, buf: &mut [u8]) -> usize {
3650 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3651 }
3652
3653 #[corresponds(SSL_get_peer_finished)]
3659 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3660 unsafe {
3661 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3662 }
3663 }
3664
3665 #[corresponds(SSL_is_init_finished)]
3667 #[cfg(ossl110)]
3668 pub fn is_init_finished(&self) -> bool {
3669 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3670 }
3671
3672 #[corresponds(SSL_client_hello_isv2)]
3678 #[cfg(ossl111)]
3679 pub fn client_hello_isv2(&self) -> bool {
3680 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3681 }
3682
3683 #[corresponds(SSL_client_hello_get0_legacy_version)]
3689 #[cfg(ossl111)]
3690 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3691 unsafe {
3692 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3693 if version == 0 {
3694 None
3695 } else {
3696 Some(SslVersion(version as c_int))
3697 }
3698 }
3699 }
3700
3701 #[corresponds(SSL_client_hello_get0_random)]
3707 #[cfg(ossl111)]
3708 pub fn client_hello_random(&self) -> Option<&[u8]> {
3709 unsafe {
3710 let mut ptr = ptr::null();
3711 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3712 if len == 0 {
3713 None
3714 } else {
3715 Some(util::from_raw_parts(ptr, len))
3716 }
3717 }
3718 }
3719
3720 #[corresponds(SSL_client_hello_get0_session_id)]
3726 #[cfg(ossl111)]
3727 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3728 unsafe {
3729 let mut ptr = ptr::null();
3730 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3731 if len == 0 {
3732 None
3733 } else {
3734 Some(util::from_raw_parts(ptr, len))
3735 }
3736 }
3737 }
3738
3739 #[corresponds(SSL_client_hello_get0_ciphers)]
3745 #[cfg(ossl111)]
3746 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3747 unsafe {
3748 let mut ptr = ptr::null();
3749 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3750 if len == 0 {
3751 None
3752 } else {
3753 Some(util::from_raw_parts(ptr, len))
3754 }
3755 }
3756 }
3757
3758 #[cfg(ossl111)]
3764 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3765 unsafe {
3766 let mut ptr = ptr::null();
3767 let mut len = 0usize;
3768 let r = ffi::SSL_client_hello_get0_ext(
3769 self.as_ptr(),
3770 ext_type.as_raw() as _,
3771 &mut ptr,
3772 &mut len,
3773 );
3774 if r == 0 {
3775 None
3776 } else {
3777 Some(util::from_raw_parts(ptr, len))
3778 }
3779 }
3780 }
3781
3782 #[corresponds(SSL_bytes_to_cipher_list)]
3787 #[cfg(ossl111)]
3788 pub fn bytes_to_cipher_list(
3789 &self,
3790 bytes: &[u8],
3791 isv2format: bool,
3792 ) -> Result<CipherLists, ErrorStack> {
3793 unsafe {
3794 let ptr = bytes.as_ptr();
3795 let len = bytes.len();
3796 let mut sk = ptr::null_mut();
3797 let mut scsvs = ptr::null_mut();
3798 let res = ffi::SSL_bytes_to_cipher_list(
3799 self.as_ptr(),
3800 ptr,
3801 len,
3802 isv2format as c_int,
3803 &mut sk,
3804 &mut scsvs,
3805 );
3806 if res == 1 {
3807 Ok(CipherLists {
3808 suites: Stack::from_ptr(sk),
3809 signalling_suites: Stack::from_ptr(scsvs),
3810 })
3811 } else {
3812 Err(ErrorStack::get())
3813 }
3814 }
3815 }
3816
3817 #[corresponds(SSL_client_hello_get0_compression_methods)]
3823 #[cfg(ossl111)]
3824 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3825 unsafe {
3826 let mut ptr = ptr::null();
3827 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3828 if len == 0 {
3829 None
3830 } else {
3831 Some(util::from_raw_parts(ptr, len))
3832 }
3833 }
3834 }
3835
3836 #[corresponds(SSL_set_mtu)]
3838 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3839 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3840 }
3841
3842 #[corresponds(SSL_get_psk_identity_hint)]
3846 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3847 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3848 unsafe {
3849 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3850 if ptr.is_null() {
3851 None
3852 } else {
3853 Some(CStr::from_ptr(ptr).to_bytes())
3854 }
3855 }
3856 }
3857
3858 #[corresponds(SSL_get_psk_identity)]
3860 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3861 pub fn psk_identity(&self) -> Option<&[u8]> {
3862 unsafe {
3863 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3864 if ptr.is_null() {
3865 None
3866 } else {
3867 Some(CStr::from_ptr(ptr).to_bytes())
3868 }
3869 }
3870 }
3871
3872 #[corresponds(SSL_add0_chain_cert)]
3873 #[cfg(any(ossl102, boringssl))]
3874 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3875 unsafe {
3876 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3877 mem::forget(chain);
3878 }
3879 Ok(())
3880 }
3881
3882 #[cfg(not(boringssl))]
3884 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3885 unsafe {
3886 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3887 };
3888 Ok(())
3889 }
3890
3891 #[corresponds(SSL_use_Private_Key_file)]
3893 pub fn set_private_key_file<P: AsRef<Path>>(
3894 &mut self,
3895 path: P,
3896 ssl_file_type: SslFiletype,
3897 ) -> Result<(), ErrorStack> {
3898 let p = path.as_ref().as_os_str().to_str().unwrap();
3899 let key_file = CString::new(p).unwrap();
3900 unsafe {
3901 cvt(ffi::SSL_use_PrivateKey_file(
3902 self.as_ptr(),
3903 key_file.as_ptr(),
3904 ssl_file_type.as_raw(),
3905 ))?;
3906 };
3907 Ok(())
3908 }
3909
3910 #[corresponds(SSL_use_PrivateKey)]
3912 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3913 unsafe {
3914 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3915 };
3916 Ok(())
3917 }
3918
3919 #[cfg(tongsuo)]
3920 #[corresponds(SSL_use_enc_Private_Key_file)]
3921 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3922 &mut self,
3923 path: P,
3924 ssl_file_type: SslFiletype,
3925 ) -> Result<(), ErrorStack> {
3926 let p = path.as_ref().as_os_str().to_str().unwrap();
3927 let key_file = CString::new(p).unwrap();
3928 unsafe {
3929 cvt(ffi::SSL_use_enc_PrivateKey_file(
3930 self.as_ptr(),
3931 key_file.as_ptr(),
3932 ssl_file_type.as_raw(),
3933 ))?;
3934 };
3935 Ok(())
3936 }
3937
3938 #[cfg(tongsuo)]
3939 #[corresponds(SSL_use_enc_PrivateKey)]
3940 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3941 unsafe {
3942 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3943 };
3944 Ok(())
3945 }
3946
3947 #[cfg(tongsuo)]
3948 #[corresponds(SSL_use_sign_Private_Key_file)]
3949 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3950 &mut self,
3951 path: P,
3952 ssl_file_type: SslFiletype,
3953 ) -> Result<(), ErrorStack> {
3954 let p = path.as_ref().as_os_str().to_str().unwrap();
3955 let key_file = CString::new(p).unwrap();
3956 unsafe {
3957 cvt(ffi::SSL_use_sign_PrivateKey_file(
3958 self.as_ptr(),
3959 key_file.as_ptr(),
3960 ssl_file_type.as_raw(),
3961 ))?;
3962 };
3963 Ok(())
3964 }
3965
3966 #[cfg(tongsuo)]
3967 #[corresponds(SSL_use_sign_PrivateKey)]
3968 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3969 unsafe {
3970 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3971 };
3972 Ok(())
3973 }
3974
3975 #[corresponds(SSL_use_certificate)]
3977 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3978 unsafe {
3979 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3980 };
3981 Ok(())
3982 }
3983
3984 #[cfg(tongsuo)]
3985 #[corresponds(SSL_use_enc_certificate)]
3986 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3987 unsafe {
3988 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
3989 };
3990 Ok(())
3991 }
3992
3993 #[cfg(tongsuo)]
3994 #[corresponds(SSL_use_sign_certificate)]
3995 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3996 unsafe {
3997 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
3998 };
3999 Ok(())
4000 }
4001
4002 #[corresponds(SSL_use_certificate_chain_file)]
4008 #[cfg(any(ossl110, libressl332))]
4009 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4010 &mut self,
4011 path: P,
4012 ) -> Result<(), ErrorStack> {
4013 let p = path.as_ref().as_os_str().to_str().unwrap();
4014 let cert_file = CString::new(p).unwrap();
4015 unsafe {
4016 cvt(ffi::SSL_use_certificate_chain_file(
4017 self.as_ptr(),
4018 cert_file.as_ptr(),
4019 ))?;
4020 };
4021 Ok(())
4022 }
4023
4024 #[corresponds(SSL_add_client_CA)]
4026 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4027 unsafe {
4028 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4029 };
4030 Ok(())
4031 }
4032
4033 #[corresponds(SSL_set_client_CA_list)]
4035 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4036 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4037 mem::forget(list);
4038 }
4039
4040 #[corresponds(SSL_set_min_proto_version)]
4047 #[cfg(any(ossl110, libressl261, boringssl))]
4048 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4049 unsafe {
4050 cvt(ffi::SSL_set_min_proto_version(
4051 self.as_ptr(),
4052 version.map_or(0, |v| v.0 as _),
4053 ))
4054 .map(|_| ())
4055 }
4056 }
4057
4058 #[corresponds(SSL_set_max_proto_version)]
4065 #[cfg(any(ossl110, libressl261, boringssl))]
4066 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4067 unsafe {
4068 cvt(ffi::SSL_set_max_proto_version(
4069 self.as_ptr(),
4070 version.map_or(0, |v| v.0 as _),
4071 ))
4072 .map(|_| ())
4073 }
4074 }
4075
4076 #[corresponds(SSL_set_ciphersuites)]
4085 #[cfg(any(ossl111, libressl340))]
4086 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4087 let cipher_list = CString::new(cipher_list).unwrap();
4088 unsafe {
4089 cvt(ffi::SSL_set_ciphersuites(
4090 self.as_ptr(),
4091 cipher_list.as_ptr() as *const _,
4092 ))
4093 .map(|_| ())
4094 }
4095 }
4096
4097 #[corresponds(SSL_set_cipher_list)]
4105 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4106 let cipher_list = CString::new(cipher_list).unwrap();
4107 unsafe {
4108 cvt(ffi::SSL_set_cipher_list(
4109 self.as_ptr(),
4110 cipher_list.as_ptr() as *const _,
4111 ))
4112 .map(|_| ())
4113 }
4114 }
4115
4116 #[corresponds(SSL_set_cert_store)]
4118 #[cfg(any(ossl102, boringssl))]
4119 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4120 unsafe {
4121 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4122 mem::forget(cert_store);
4123 Ok(())
4124 }
4125 }
4126
4127 #[corresponds(SSL_set_num_tickets)]
4132 #[cfg(ossl111)]
4133 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4134 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4135 }
4136
4137 #[corresponds(SSL_get_num_tickets)]
4142 #[cfg(ossl111)]
4143 pub fn num_tickets(&self) -> usize {
4144 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4145 }
4146
4147 #[corresponds(SSL_set_security_level)]
4152 #[cfg(any(ossl110, libressl360))]
4153 pub fn set_security_level(&mut self, level: u32) {
4154 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4155 }
4156
4157 #[corresponds(SSL_get_security_level)]
4162 #[cfg(any(ossl110, libressl360))]
4163 pub fn security_level(&self) -> u32 {
4164 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4165 }
4166
4167 #[corresponds(SSL_get_peer_tmp_key)]
4172 #[cfg(ossl300)]
4173 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4174 unsafe {
4175 let mut key = ptr::null_mut();
4176 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4177 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4178 Err(e) => Err(e),
4179 }
4180 }
4181 }
4182
4183 #[corresponds(SSL_get_tmp_key)]
4188 #[cfg(ossl300)]
4189 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4190 unsafe {
4191 let mut key = ptr::null_mut();
4192 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4193 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4194 Err(e) => Err(e),
4195 }
4196 }
4197 }
4198}
4199
4200#[derive(Debug)]
4202pub struct MidHandshakeSslStream<S> {
4203 stream: SslStream<S>,
4204 error: Error,
4205}
4206
4207impl<S> MidHandshakeSslStream<S> {
4208 pub fn get_ref(&self) -> &S {
4210 self.stream.get_ref()
4211 }
4212
4213 pub fn get_mut(&mut self) -> &mut S {
4215 self.stream.get_mut()
4216 }
4217
4218 pub fn ssl(&self) -> &SslRef {
4220 self.stream.ssl()
4221 }
4222
4223 pub fn ssl_mut(&mut self) -> &mut SslRef {
4225 self.stream.ssl_mut()
4226 }
4227
4228 pub fn error(&self) -> &Error {
4230 &self.error
4231 }
4232
4233 pub fn into_error(self) -> Error {
4235 self.error
4236 }
4237}
4238
4239impl<S> MidHandshakeSslStream<S>
4240where
4241 S: Read + Write,
4242{
4243 #[corresponds(SSL_do_handshake)]
4246 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4247 match self.stream.do_handshake() {
4248 Ok(()) => Ok(self.stream),
4249 Err(error) => {
4250 self.error = error;
4251 match self.error.code() {
4252 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4253 Err(HandshakeError::WouldBlock(self))
4254 }
4255 _ => Err(HandshakeError::Failure(self)),
4256 }
4257 }
4258 }
4259 }
4260}
4261
4262pub struct SslStream<S> {
4264 ssl: ManuallyDrop<Ssl>,
4265 method: ManuallyDrop<BioMethod>,
4266 _p: PhantomData<S>,
4267}
4268
4269impl<S> Drop for SslStream<S> {
4270 fn drop(&mut self) {
4271 unsafe {
4273 ManuallyDrop::drop(&mut self.ssl);
4274 ManuallyDrop::drop(&mut self.method);
4275 }
4276 }
4277}
4278
4279impl<S> fmt::Debug for SslStream<S>
4280where
4281 S: fmt::Debug,
4282{
4283 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4284 fmt.debug_struct("SslStream")
4285 .field("stream", &self.get_ref())
4286 .field("ssl", &self.ssl())
4287 .finish()
4288 }
4289}
4290
4291impl<S: Read + Write> SslStream<S> {
4292 #[corresponds(SSL_set_bio)]
4300 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4301 let (bio, method) = bio::new(stream)?;
4302 unsafe {
4303 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4304 }
4305
4306 Ok(SslStream {
4307 ssl: ManuallyDrop::new(ssl),
4308 method: ManuallyDrop::new(method),
4309 _p: PhantomData,
4310 })
4311 }
4312
4313 #[corresponds(SSL_read_early_data)]
4322 #[cfg(any(ossl111, libressl340))]
4323 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4324 let mut read = 0;
4325 let ret = unsafe {
4326 ffi::SSL_read_early_data(
4327 self.ssl.as_ptr(),
4328 buf.as_ptr() as *mut c_void,
4329 buf.len(),
4330 &mut read,
4331 )
4332 };
4333 match ret {
4334 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4335 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4336 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4337 _ => unreachable!(),
4338 }
4339 }
4340
4341 #[corresponds(SSL_write_early_data)]
4348 #[cfg(any(ossl111, libressl340))]
4349 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4350 let mut written = 0;
4351 let ret = unsafe {
4352 ffi::SSL_write_early_data(
4353 self.ssl.as_ptr(),
4354 buf.as_ptr() as *const c_void,
4355 buf.len(),
4356 &mut written,
4357 )
4358 };
4359 if ret > 0 {
4360 Ok(written)
4361 } else {
4362 Err(self.make_error(ret))
4363 }
4364 }
4365
4366 #[corresponds(SSL_connect)]
4373 pub fn connect(&mut self) -> Result<(), Error> {
4374 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4375 if ret > 0 {
4376 Ok(())
4377 } else {
4378 Err(self.make_error(ret))
4379 }
4380 }
4381
4382 #[corresponds(SSL_accept)]
4389 pub fn accept(&mut self) -> Result<(), Error> {
4390 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4391 if ret > 0 {
4392 Ok(())
4393 } else {
4394 Err(self.make_error(ret))
4395 }
4396 }
4397
4398 #[corresponds(SSL_do_handshake)]
4402 pub fn do_handshake(&mut self) -> Result<(), Error> {
4403 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4404 if ret > 0 {
4405 Ok(())
4406 } else {
4407 Err(self.make_error(ret))
4408 }
4409 }
4410
4411 #[corresponds(SSL_stateless)]
4422 #[cfg(ossl111)]
4423 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4424 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4425 1 => Ok(true),
4426 0 => Ok(false),
4427 -1 => Err(ErrorStack::get()),
4428 _ => unreachable!(),
4429 }
4430 }
4431
4432 #[corresponds(SSL_read_ex)]
4439 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4440 loop {
4441 match self.ssl_read_uninit(buf) {
4442 Ok(n) => return Ok(n),
4443 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4444 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4445 return Ok(0);
4446 }
4447 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4448 Err(e) => {
4449 return Err(e
4450 .into_io_error()
4451 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4452 }
4453 }
4454 }
4455 }
4456
4457 #[corresponds(SSL_read_ex)]
4462 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4463 unsafe {
4465 self.ssl_read_uninit(util::from_raw_parts_mut(
4466 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4467 buf.len(),
4468 ))
4469 }
4470 }
4471
4472 #[corresponds(SSL_read_ex)]
4479 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4480 cfg_if! {
4481 if #[cfg(any(ossl111, libressl350))] {
4482 let mut readbytes = 0;
4483 let ret = unsafe {
4484 ffi::SSL_read_ex(
4485 self.ssl().as_ptr(),
4486 buf.as_mut_ptr().cast(),
4487 buf.len(),
4488 &mut readbytes,
4489 )
4490 };
4491
4492 if ret > 0 {
4493 Ok(readbytes)
4494 } else {
4495 Err(self.make_error(ret))
4496 }
4497 } else {
4498 if buf.is_empty() {
4499 return Ok(0);
4500 }
4501
4502 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4503 let ret = unsafe {
4504 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4505 };
4506 if ret > 0 {
4507 Ok(ret as usize)
4508 } else {
4509 Err(self.make_error(ret))
4510 }
4511 }
4512 }
4513 }
4514
4515 #[corresponds(SSL_write_ex)]
4520 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4521 cfg_if! {
4522 if #[cfg(any(ossl111, libressl350))] {
4523 let mut written = 0;
4524 let ret = unsafe {
4525 ffi::SSL_write_ex(
4526 self.ssl().as_ptr(),
4527 buf.as_ptr().cast(),
4528 buf.len(),
4529 &mut written,
4530 )
4531 };
4532
4533 if ret > 0 {
4534 Ok(written)
4535 } else {
4536 Err(self.make_error(ret))
4537 }
4538 } else {
4539 if buf.is_empty() {
4540 return Ok(0);
4541 }
4542
4543 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4544 let ret = unsafe {
4545 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4546 };
4547 if ret > 0 {
4548 Ok(ret as usize)
4549 } else {
4550 Err(self.make_error(ret))
4551 }
4552 }
4553 }
4554 }
4555
4556 #[corresponds(SSL_peek_ex)]
4558 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4559 cfg_if! {
4560 if #[cfg(any(ossl111, libressl350))] {
4561 let mut readbytes = 0;
4562 let ret = unsafe {
4563 ffi::SSL_peek_ex(
4564 self.ssl().as_ptr(),
4565 buf.as_mut_ptr().cast(),
4566 buf.len(),
4567 &mut readbytes,
4568 )
4569 };
4570
4571 if ret > 0 {
4572 Ok(readbytes)
4573 } else {
4574 Err(self.make_error(ret))
4575 }
4576 } else {
4577 if buf.is_empty() {
4578 return Ok(0);
4579 }
4580
4581 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4582 let ret = unsafe {
4583 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4584 };
4585 if ret > 0 {
4586 Ok(ret as usize)
4587 } else {
4588 Err(self.make_error(ret))
4589 }
4590 }
4591 }
4592 }
4593
4594 #[corresponds(SSL_shutdown)]
4604 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4605 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4606 0 => Ok(ShutdownResult::Sent),
4607 1 => Ok(ShutdownResult::Received),
4608 n => Err(self.make_error(n)),
4609 }
4610 }
4611
4612 #[corresponds(SSL_get_shutdown)]
4614 pub fn get_shutdown(&mut self) -> ShutdownState {
4615 unsafe {
4616 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4617 ShutdownState::from_bits_retain(bits)
4618 }
4619 }
4620
4621 #[corresponds(SSL_set_shutdown)]
4626 pub fn set_shutdown(&mut self, state: ShutdownState) {
4627 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4628 }
4629}
4630
4631impl<S> SslStream<S> {
4632 fn make_error(&mut self, ret: c_int) -> Error {
4633 self.check_panic();
4634
4635 let code = self.ssl.get_error(ret);
4636
4637 let cause = match code {
4638 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4639 ErrorCode::SYSCALL => {
4640 let errs = ErrorStack::get();
4641 if errs.errors().is_empty() {
4642 self.get_bio_error().map(InnerError::Io)
4643 } else {
4644 Some(InnerError::Ssl(errs))
4645 }
4646 }
4647 ErrorCode::ZERO_RETURN => None,
4648 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4649 self.get_bio_error().map(InnerError::Io)
4650 }
4651 _ => None,
4652 };
4653
4654 Error { code, cause }
4655 }
4656
4657 fn check_panic(&mut self) {
4658 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4659 resume_unwind(err)
4660 }
4661 }
4662
4663 fn get_bio_error(&mut self) -> Option<io::Error> {
4664 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4665 }
4666
4667 pub fn get_ref(&self) -> &S {
4669 unsafe {
4670 let bio = self.ssl.get_raw_rbio();
4671 bio::get_ref(bio)
4672 }
4673 }
4674
4675 pub fn get_mut(&mut self) -> &mut S {
4682 unsafe {
4683 let bio = self.ssl.get_raw_rbio();
4684 bio::get_mut(bio)
4685 }
4686 }
4687
4688 pub fn ssl(&self) -> &SslRef {
4690 &self.ssl
4691 }
4692
4693 pub fn ssl_mut(&mut self) -> &mut SslRef {
4695 &mut self.ssl
4696 }
4697}
4698
4699impl<S: Read + Write> Read for SslStream<S> {
4700 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4701 unsafe {
4703 self.read_uninit(util::from_raw_parts_mut(
4704 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4705 buf.len(),
4706 ))
4707 }
4708 }
4709}
4710
4711impl<S: Read + Write> Write for SslStream<S> {
4712 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4713 loop {
4714 match self.ssl_write(buf) {
4715 Ok(n) => return Ok(n),
4716 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4717 Err(e) => {
4718 return Err(e
4719 .into_io_error()
4720 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4721 }
4722 }
4723 }
4724 }
4725
4726 fn flush(&mut self) -> io::Result<()> {
4727 self.get_mut().flush()
4728 }
4729}
4730
4731#[deprecated(
4733 since = "0.10.32",
4734 note = "use the methods directly on Ssl/SslStream instead"
4735)]
4736pub struct SslStreamBuilder<S> {
4737 inner: SslStream<S>,
4738}
4739
4740#[allow(deprecated)]
4741impl<S> SslStreamBuilder<S>
4742where
4743 S: Read + Write,
4744{
4745 pub fn new(ssl: Ssl, stream: S) -> Self {
4747 Self {
4748 inner: SslStream::new(ssl, stream).unwrap(),
4749 }
4750 }
4751
4752 #[corresponds(SSL_stateless)]
4763 #[cfg(ossl111)]
4764 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4765 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4766 1 => Ok(true),
4767 0 => Ok(false),
4768 -1 => Err(ErrorStack::get()),
4769 _ => unreachable!(),
4770 }
4771 }
4772
4773 #[corresponds(SSL_set_connect_state)]
4775 pub fn set_connect_state(&mut self) {
4776 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4777 }
4778
4779 #[corresponds(SSL_set_accept_state)]
4781 pub fn set_accept_state(&mut self) {
4782 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4783 }
4784
4785 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4787 match self.inner.connect() {
4788 Ok(()) => Ok(self.inner),
4789 Err(error) => match error.code() {
4790 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4791 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4792 stream: self.inner,
4793 error,
4794 }))
4795 }
4796 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4797 stream: self.inner,
4798 error,
4799 })),
4800 },
4801 }
4802 }
4803
4804 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4806 match self.inner.accept() {
4807 Ok(()) => Ok(self.inner),
4808 Err(error) => match error.code() {
4809 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4810 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4811 stream: self.inner,
4812 error,
4813 }))
4814 }
4815 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4816 stream: self.inner,
4817 error,
4818 })),
4819 },
4820 }
4821 }
4822
4823 #[corresponds(SSL_do_handshake)]
4827 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4828 match self.inner.do_handshake() {
4829 Ok(()) => Ok(self.inner),
4830 Err(error) => match error.code() {
4831 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4832 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4833 stream: self.inner,
4834 error,
4835 }))
4836 }
4837 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4838 stream: self.inner,
4839 error,
4840 })),
4841 },
4842 }
4843 }
4844
4845 #[corresponds(SSL_read_early_data)]
4855 #[cfg(any(ossl111, libressl340))]
4856 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4857 self.inner.read_early_data(buf)
4858 }
4859
4860 #[corresponds(SSL_write_early_data)]
4867 #[cfg(any(ossl111, libressl340))]
4868 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4869 self.inner.write_early_data(buf)
4870 }
4871}
4872
4873#[allow(deprecated)]
4874impl<S> SslStreamBuilder<S> {
4875 pub fn get_ref(&self) -> &S {
4877 unsafe {
4878 let bio = self.inner.ssl.get_raw_rbio();
4879 bio::get_ref(bio)
4880 }
4881 }
4882
4883 pub fn get_mut(&mut self) -> &mut S {
4890 unsafe {
4891 let bio = self.inner.ssl.get_raw_rbio();
4892 bio::get_mut(bio)
4893 }
4894 }
4895
4896 pub fn ssl(&self) -> &SslRef {
4898 &self.inner.ssl
4899 }
4900
4901 pub fn ssl_mut(&mut self) -> &mut SslRef {
4903 &mut self.inner.ssl
4904 }
4905}
4906
4907#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4909pub enum ShutdownResult {
4910 Sent,
4912
4913 Received,
4915}
4916
4917bitflags! {
4918 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4920 #[repr(transparent)]
4921 pub struct ShutdownState: c_int {
4922 const SENT = ffi::SSL_SENT_SHUTDOWN;
4924 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4926 }
4927}
4928
4929cfg_if! {
4930 if #[cfg(any(boringssl, ossl110, libressl273))] {
4931 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4932 } else {
4933 #[allow(bad_style)]
4934 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4935 ffi::CRYPTO_add_lock(
4936 &mut (*ssl).references,
4937 1,
4938 ffi::CRYPTO_LOCK_SSL_CTX,
4939 "mod.rs\0".as_ptr() as *const _,
4940 line!() as c_int,
4941 );
4942 0
4943 }
4944
4945 #[allow(bad_style)]
4946 pub unsafe fn SSL_SESSION_get_master_key(
4947 session: *const ffi::SSL_SESSION,
4948 out: *mut c_uchar,
4949 mut outlen: usize,
4950 ) -> usize {
4951 if outlen == 0 {
4952 return (*session).master_key_length as usize;
4953 }
4954 if outlen > (*session).master_key_length as usize {
4955 outlen = (*session).master_key_length as usize;
4956 }
4957 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
4958 outlen
4959 }
4960
4961 #[allow(bad_style)]
4962 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
4963 (*s).server
4964 }
4965
4966 #[allow(bad_style)]
4967 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
4968 ffi::CRYPTO_add_lock(
4969 &mut (*ses).references,
4970 1,
4971 ffi::CRYPTO_LOCK_SSL_CTX,
4972 "mod.rs\0".as_ptr() as *const _,
4973 line!() as c_int,
4974 );
4975 0
4976 }
4977 }
4978}
4979
4980cfg_if! {
4981 if #[cfg(ossl300)] {
4982 use ffi::SSL_get1_peer_certificate;
4983 } else {
4984 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4985 }
4986}
4987cfg_if! {
4988 if #[cfg(any(boringssl, ossl110, libressl291))] {
4989 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
4990 } else {
4991 use ffi::{
4992 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
4993 SSLv23_server_method as TLS_server_method,
4994 };
4995 }
4996}
4997cfg_if! {
4998 if #[cfg(ossl110)] {
4999 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5000 ffi::CRYPTO_get_ex_new_index(
5001 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5002 0,
5003 ptr::null_mut(),
5004 None,
5005 None,
5006 f,
5007 )
5008 }
5009
5010 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5011 ffi::CRYPTO_get_ex_new_index(
5012 ffi::CRYPTO_EX_INDEX_SSL,
5013 0,
5014 ptr::null_mut(),
5015 None,
5016 None,
5017 f,
5018 )
5019 }
5020 } else {
5021 use std::sync::Once;
5022
5023 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5024 static ONCE: Once = Once::new();
5026 ONCE.call_once(|| {
5027 cfg_if! {
5028 if #[cfg(not(boringssl))] {
5029 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5030 } else {
5031 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5032 }
5033 }
5034 });
5035
5036 cfg_if! {
5037 if #[cfg(not(boringssl))] {
5038 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5039 } else {
5040 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5041 }
5042 }
5043 }
5044
5045 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5046 static ONCE: Once = Once::new();
5048 ONCE.call_once(|| {
5049 #[cfg(not(boringssl))]
5050 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5051 #[cfg(boringssl)]
5052 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5053 });
5054
5055 #[cfg(not(boringssl))]
5056 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5057 #[cfg(boringssl)]
5058 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5059 }
5060 }
5061}