1#[cfg(ossl300)]
61use crate::cvt_long;
62use crate::dh::{Dh, DhRef};
63use crate::ec::EcKeyRef;
64use crate::error::ErrorStack;
65use crate::ex_data::Index;
66#[cfg(ossl111)]
67use crate::hash::MessageDigest;
68#[cfg(any(ossl110, libressl))]
69use crate::nid::Nid;
70use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
71#[cfg(ossl300)]
72use crate::pkey::{PKey, Public};
73#[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
74use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
75use crate::ssl::bio::BioMethod;
76use crate::ssl::callbacks::*;
77use crate::ssl::error::InnerError;
78use crate::stack::{Stack, StackRef, Stackable};
79use crate::util;
80use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
81use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
82use crate::x509::verify::X509VerifyParamRef;
83use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
84use crate::{cvt, cvt_n, cvt_p, init};
85use bitflags::bitflags;
86use cfg_if::cfg_if;
87use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
88use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
89use openssl_macros::corresponds;
90use std::any::TypeId;
91use std::collections::HashMap;
92use std::ffi::{CStr, CString};
93use std::fmt;
94use std::io;
95use std::io::prelude::*;
96use std::marker::PhantomData;
97use std::mem::{self, ManuallyDrop, MaybeUninit};
98use std::ops::{Deref, DerefMut};
99use std::panic::resume_unwind;
100use std::path::Path;
101use std::ptr;
102use std::str;
103use std::sync::{Arc, LazyLock, Mutex, OnceLock};
104
105pub use crate::ssl::connector::{
106 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
107};
108pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
109
110mod bio;
111mod callbacks;
112mod connector;
113mod error;
114#[cfg(test)]
115mod test;
116
117#[corresponds(OPENSSL_cipher_name)]
123#[cfg(ossl111)]
124pub fn cipher_name(std_name: &str) -> &'static str {
125 unsafe {
126 ffi::init();
127
128 let s = CString::new(std_name).unwrap();
129 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
130 CStr::from_ptr(ptr).to_str().unwrap()
131 }
132}
133
134cfg_if! {
135 if #[cfg(ossl300)] {
136 type SslOptionsRepr = u64;
137 } else if #[cfg(any(boringssl, awslc))] {
138 type SslOptionsRepr = u32;
139 } else {
140 type SslOptionsRepr = libc::c_ulong;
141 }
142}
143
144bitflags! {
145 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
147 #[repr(transparent)]
148 pub struct SslOptions: SslOptionsRepr {
149 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
151
152 #[cfg(ossl300)]
155 const IGNORE_UNEXPECTED_EOF = ffi::SSL_OP_IGNORE_UNEXPECTED_EOF as SslOptionsRepr;
156
157 #[cfg(not(any(boringssl, awslc)))]
159 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
160
161 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
165
166 #[cfg(not(any(boringssl, awslc)))]
172 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
173
174 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
176
177 #[cfg(not(any(boringssl, awslc)))]
179 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
180 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
181
182 #[cfg(not(any(boringssl, awslc)))]
184 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
185
186 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
189 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
190
191 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
195
196 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
200
201 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
205
206 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
208
209 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
211
212 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
214
215 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
217
218 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
220
221 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
223
224 #[cfg(any(ossl111, boringssl, libressl, awslc))]
228 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
229
230 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
232
233 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
235
236 #[cfg(ossl110)]
252 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
253
254 #[cfg(any(boringssl, ossl110h, awslc))]
258 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
259
260 #[cfg(ossl111)]
265 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
266
267 #[cfg(ossl111)]
279 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
280 }
281}
282
283bitflags! {
284 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
286 #[repr(transparent)]
287 pub struct SslMode: SslBitType {
288 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
294
295 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
298
299 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
309
310 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
316
317 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
321
322 #[cfg(not(libressl))]
330 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
331 }
332}
333
334#[derive(Copy, Clone)]
336pub struct SslMethod(*const ffi::SSL_METHOD);
337
338impl SslMethod {
339 #[corresponds(TLS_method)]
341 pub fn tls() -> SslMethod {
342 unsafe { SslMethod(TLS_method()) }
343 }
344
345 #[corresponds(DTLS_method)]
347 pub fn dtls() -> SslMethod {
348 unsafe { SslMethod(DTLS_method()) }
349 }
350
351 #[corresponds(TLS_client_method)]
353 pub fn tls_client() -> SslMethod {
354 unsafe { SslMethod(TLS_client_method()) }
355 }
356
357 #[corresponds(TLS_server_method)]
359 pub fn tls_server() -> SslMethod {
360 unsafe { SslMethod(TLS_server_method()) }
361 }
362
363 #[corresponds(DTLS_client_method)]
365 pub fn dtls_client() -> SslMethod {
366 unsafe { SslMethod(DTLS_client_method()) }
367 }
368
369 #[corresponds(DTLS_server_method)]
371 pub fn dtls_server() -> SslMethod {
372 unsafe { SslMethod(DTLS_server_method()) }
373 }
374
375 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
381 SslMethod(ptr)
382 }
383
384 #[allow(clippy::trivially_copy_pass_by_ref)]
386 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
387 self.0
388 }
389}
390
391unsafe impl Sync for SslMethod {}
392unsafe impl Send for SslMethod {}
393
394bitflags! {
395 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
397 #[repr(transparent)]
398 pub struct SslVerifyMode: i32 {
399 const PEER = ffi::SSL_VERIFY_PEER;
403
404 const NONE = ffi::SSL_VERIFY_NONE;
410
411 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
415
416 #[cfg(not(any(boringssl, awslc)))]
421 const CLIENT_ONCE = ffi::SSL_VERIFY_CLIENT_ONCE;
422
423 #[cfg(ossl111)]
430 const POST_HANDSHAKE = ffi::SSL_VERIFY_POST_HANDSHAKE;
431 }
432}
433
434#[cfg(any(boringssl, awslc))]
435type SslBitType = c_int;
436#[cfg(not(any(boringssl, awslc)))]
437type SslBitType = c_long;
438
439#[cfg(any(boringssl, awslc))]
440type SslTimeTy = u64;
441#[cfg(not(any(boringssl, awslc)))]
442type SslTimeTy = c_long;
443
444bitflags! {
445 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
447 #[repr(transparent)]
448 pub struct SslSessionCacheMode: SslBitType {
449 const OFF = ffi::SSL_SESS_CACHE_OFF;
451
452 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
459
460 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
464
465 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
467
468 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
470
471 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
473
474 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
476
477 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
479 }
480}
481
482#[cfg(ossl111)]
483bitflags! {
484 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
486 #[repr(transparent)]
487 pub struct ExtensionContext: c_uint {
488 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
490 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
492 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
494 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
496 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
498 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
500 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
502 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
503 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
505 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
506 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
507 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
508 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
509 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
510 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
511 }
512}
513
514#[derive(Copy, Clone)]
516pub struct SslFiletype(c_int);
517
518impl SslFiletype {
519 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
523
524 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
528
529 pub fn from_raw(raw: c_int) -> SslFiletype {
531 SslFiletype(raw)
532 }
533
534 #[allow(clippy::trivially_copy_pass_by_ref)]
536 pub fn as_raw(&self) -> c_int {
537 self.0
538 }
539}
540
541#[derive(Copy, Clone)]
543pub struct StatusType(c_int);
544
545impl StatusType {
546 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
548
549 pub fn from_raw(raw: c_int) -> StatusType {
551 StatusType(raw)
552 }
553
554 #[allow(clippy::trivially_copy_pass_by_ref)]
556 pub fn as_raw(&self) -> c_int {
557 self.0
558 }
559}
560
561#[derive(Copy, Clone)]
563pub struct NameType(c_int);
564
565impl NameType {
566 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
568
569 pub fn from_raw(raw: c_int) -> StatusType {
571 StatusType(raw)
572 }
573
574 #[allow(clippy::trivially_copy_pass_by_ref)]
576 pub fn as_raw(&self) -> c_int {
577 self.0
578 }
579}
580
581static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
582 LazyLock::new(|| Mutex::new(HashMap::new()));
583static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
584 LazyLock::new(|| Mutex::new(HashMap::new()));
585static SESSION_CTX_INDEX: OnceLock<Index<Ssl, SslContext>> = OnceLock::new();
586
587fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
588 if let Some(idx) = SESSION_CTX_INDEX.get() {
591 return Ok(idx);
592 }
593 let new = Ssl::new_ex_index::<SslContext>()?;
594 Ok(SESSION_CTX_INDEX.get_or_init(|| new))
595}
596
597unsafe extern "C" fn free_data_box<T>(
598 _parent: *mut c_void,
599 ptr: *mut c_void,
600 _ad: *mut ffi::CRYPTO_EX_DATA,
601 _idx: c_int,
602 _argl: c_long,
603 _argp: *mut c_void,
604) {
605 if !ptr.is_null() {
606 let _ = Box::<T>::from_raw(ptr as *mut T);
607 }
608}
609
610#[derive(Debug, Copy, Clone, PartialEq, Eq)]
612pub struct SniError(c_int);
613
614impl SniError {
615 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
617
618 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
620
621 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
622}
623
624#[derive(Debug, Copy, Clone, PartialEq, Eq)]
629pub struct SslAlert(c_int);
630
631impl SslAlert {
632 pub const CLOSE_NOTIFY: SslAlert = SslAlert(ffi::SSL_AD_CLOSE_NOTIFY);
633 pub const UNEXPECTED_MESSAGE: SslAlert = SslAlert(ffi::SSL_AD_UNEXPECTED_MESSAGE);
634 pub const BAD_RECORD_MAC: SslAlert = SslAlert(ffi::SSL_AD_BAD_RECORD_MAC);
635 pub const DECRYPTION_FAILED: SslAlert = SslAlert(ffi::SSL_AD_DECRYPTION_FAILED);
636 pub const RECORD_OVERFLOW: SslAlert = SslAlert(ffi::SSL_AD_RECORD_OVERFLOW);
637 pub const DECOMPRESSION_FAILURE: SslAlert = SslAlert(ffi::SSL_AD_DECOMPRESSION_FAILURE);
638 pub const HANDSHAKE_FAILURE: SslAlert = SslAlert(ffi::SSL_AD_HANDSHAKE_FAILURE);
639 pub const NO_CERTIFICATE: SslAlert = SslAlert(ffi::SSL_AD_NO_CERTIFICATE);
640 pub const BAD_CERTIFICATE: SslAlert = SslAlert(ffi::SSL_AD_BAD_CERTIFICATE);
641 pub const UNSUPPORTED_CERTIFICATE: SslAlert = SslAlert(ffi::SSL_AD_UNSUPPORTED_CERTIFICATE);
642 pub const CERTIFICATE_REVOKED: SslAlert = SslAlert(ffi::SSL_AD_CERTIFICATE_REVOKED);
643 pub const CERTIFICATE_EXPIRED: SslAlert = SslAlert(ffi::SSL_AD_CERTIFICATE_EXPIRED);
644 pub const CERTIFICATE_UNKNOWN: SslAlert = SslAlert(ffi::SSL_AD_CERTIFICATE_UNKNOWN);
645 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
646 pub const UNKNOWN_CA: SslAlert = SslAlert(ffi::SSL_AD_UNKNOWN_CA);
647 pub const ACCESS_DENIED: SslAlert = SslAlert(ffi::SSL_AD_ACCESS_DENIED);
648 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
649 pub const DECRYPT_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECRYPT_ERROR);
650 pub const EXPORT_RESTRICTION: SslAlert = SslAlert(ffi::SSL_AD_EXPORT_RESTRICTION);
651 pub const PROTOCOL_VERSION: SslAlert = SslAlert(ffi::SSL_AD_PROTOCOL_VERSION);
652 pub const INSUFFICIENT_SECURITY: SslAlert = SslAlert(ffi::SSL_AD_INSUFFICIENT_SECURITY);
653 pub const INTERNAL_ERROR: SslAlert = SslAlert(ffi::SSL_AD_INTERNAL_ERROR);
654 pub const INAPPROPRIATE_FALLBACK: SslAlert = SslAlert(ffi::SSL_AD_INAPPROPRIATE_FALLBACK);
655 pub const USER_CANCELLED: SslAlert = SslAlert(ffi::SSL_AD_USER_CANCELLED);
656 pub const NO_RENEGOTIATION: SslAlert = SslAlert(ffi::SSL_AD_NO_RENEGOTIATION);
657 #[cfg(any(ossl111, libressl, boringssl, awslc))]
658 pub const MISSING_EXTENSION: SslAlert = SslAlert(ffi::SSL_AD_MISSING_EXTENSION);
659 pub const UNSUPPORTED_EXTENSION: SslAlert = SslAlert(ffi::SSL_AD_UNSUPPORTED_EXTENSION);
660 pub const CERTIFICATE_UNOBTAINABLE: SslAlert = SslAlert(ffi::SSL_AD_CERTIFICATE_UNOBTAINABLE);
661 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
662 pub const BAD_CERTIFICATE_STATUS_RESPONSE: SslAlert =
663 SslAlert(ffi::SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
664 pub const BAD_CERTIFICATE_HASH_VALUE: SslAlert =
665 SslAlert(ffi::SSL_AD_BAD_CERTIFICATE_HASH_VALUE);
666 pub const UNKNOWN_PSK_IDENTITY: SslAlert = SslAlert(ffi::SSL_AD_UNKNOWN_PSK_IDENTITY);
667 #[cfg(any(ossl111, libressl, boringssl, awslc))]
668 pub const CERTIFICATE_REQUIRED: SslAlert = SslAlert(ffi::SSL_AD_CERTIFICATE_REQUIRED);
669 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
670
671 pub fn reason_code(&self) -> c_int {
676 self.0 + ffi::SSL_AD_REASON_OFFSET
677 }
678
679 pub fn from_reason_code(reason: c_int) -> Option<SslAlert> {
684 let description = reason - ffi::SSL_AD_REASON_OFFSET;
685 if (0..=255).contains(&description) {
686 Some(SslAlert(description))
687 } else {
688 None
689 }
690 }
691}
692
693impl fmt::Display for SslAlert {
694 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
695 let description = unsafe {
698 let ptr = ffi::SSL_alert_desc_string_long(self.0);
699 CStr::from_ptr(ptr).to_str().unwrap()
700 };
701 fmt.write_str(description)
702 }
703}
704
705#[derive(Debug, Copy, Clone, PartialEq, Eq)]
709pub struct AlpnError(c_int);
710
711impl AlpnError {
712 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
714
715 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
717}
718
719#[cfg(ossl111)]
723#[derive(Debug, Copy, Clone, PartialEq, Eq)]
724pub struct ClientHelloResponse(c_int);
725
726#[cfg(ossl111)]
727impl ClientHelloResponse {
728 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
730
731 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
733}
734
735#[derive(Debug, Copy, Clone, PartialEq, Eq)]
737pub struct SslVersion(c_int);
738
739impl SslVersion {
740 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
742
743 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
745
746 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
748
749 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
751
752 #[cfg(any(ossl111, libressl, boringssl, awslc))]
756 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
757
758 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
762
763 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
767}
768
769cfg_if! {
770 if #[cfg(any(boringssl, awslc))] {
771 type SslCacheTy = i64;
772 type SslCacheSize = libc::c_ulong;
773 type MtuTy = u32;
774 type SizeTy = usize;
775 } else {
776 type SslCacheTy = i64;
777 type SslCacheSize = c_long;
778 type MtuTy = c_long;
779 type SizeTy = u32;
780 }
781}
782
783#[corresponds(SSL_select_next_proto)]
794pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
795 unsafe {
796 let mut out = ptr::null_mut();
797 let mut outlen = 0;
798 let r = ffi::SSL_select_next_proto(
799 &mut out,
800 &mut outlen,
801 server.as_ptr(),
802 server.len() as c_uint,
803 client.as_ptr(),
804 client.len() as c_uint,
805 );
806 if r == ffi::OPENSSL_NPN_NEGOTIATED {
807 Some(util::from_raw_parts(out as *const u8, outlen as usize))
808 } else {
809 None
810 }
811 }
812}
813
814pub struct SslContextBuilder(SslContext);
816
817impl SslContextBuilder {
818 #[corresponds(SSL_CTX_new)]
820 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
821 unsafe {
822 init();
823 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
824
825 Ok(SslContextBuilder::from_ptr(ctx))
826 }
827 }
828
829 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
835 SslContextBuilder(SslContext::from_ptr(ctx))
836 }
837
838 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
840 self.0.as_ptr()
841 }
842
843 #[corresponds(SSL_CTX_set_verify)]
845 pub fn set_verify(&mut self, mode: SslVerifyMode) {
846 unsafe {
847 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
848 }
849 }
850
851 #[corresponds(SSL_CTX_set_verify)]
858 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
859 where
860 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
861 {
862 unsafe {
863 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
864 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
865 }
866 }
867
868 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
876 pub fn set_servername_callback<F>(&mut self, callback: F)
878 where
879 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
880 {
881 unsafe {
882 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
888 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
889 #[cfg(any(boringssl, awslc))]
890 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
891 #[cfg(not(any(boringssl, awslc)))]
892 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
893 self.as_ptr(),
894 Some(raw_sni::<F>),
895 );
896 }
897 }
898
899 #[corresponds(SSL_CTX_set_verify_depth)]
903 pub fn set_verify_depth(&mut self, depth: u32) {
904 unsafe {
905 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
906 }
907 }
908
909 #[corresponds(SSL_CTX_set0_verify_cert_store)]
913 #[cfg(ossl110)]
914 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
915 unsafe {
916 let ptr = cert_store.as_ptr();
917 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
918 mem::forget(cert_store);
919
920 Ok(())
921 }
922 }
923
924 #[corresponds(SSL_CTX_set_cert_store)]
926 pub fn set_cert_store(&mut self, cert_store: X509Store) {
927 unsafe {
928 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
929 mem::forget(cert_store);
930 }
931 }
932
933 #[corresponds(SSL_CTX_set_read_ahead)]
940 pub fn set_read_ahead(&mut self, read_ahead: bool) {
941 unsafe {
942 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
943 }
944 }
945
946 #[corresponds(SSL_CTX_set_mode)]
948 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
949 unsafe {
950 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
951 SslMode::from_bits_retain(bits)
952 }
953 }
954
955 #[corresponds(SSL_CTX_set_tmp_dh)]
957 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
958 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
959 }
960
961 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
968 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
969 where
970 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
971 {
972 unsafe {
973 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
974
975 #[cfg(not(any(boringssl, awslc)))]
976 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
977 #[cfg(any(boringssl, awslc))]
978 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
979 }
980 }
981
982 #[corresponds(SSL_CTX_set_tmp_ecdh)]
984 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
985 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
986 }
987
988 #[corresponds(SSL_CTX_set_default_verify_paths)]
993 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
994 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
995 }
996
997 #[corresponds(SSL_CTX_load_verify_locations)]
1001 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1002 self.load_verify_locations(Some(file.as_ref()), None)
1003 }
1004
1005 #[corresponds(SSL_CTX_load_verify_locations)]
1007 pub fn load_verify_locations(
1008 &mut self,
1009 ca_file: Option<&Path>,
1010 ca_path: Option<&Path>,
1011 ) -> Result<(), ErrorStack> {
1012 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1013 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1014 unsafe {
1015 cvt(ffi::SSL_CTX_load_verify_locations(
1016 self.as_ptr(),
1017 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1018 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1019 ))
1020 .map(|_| ())
1021 }
1022 }
1023
1024 #[corresponds(SSL_CTX_set_client_CA_list)]
1029 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1030 unsafe {
1031 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1032 mem::forget(list);
1033 }
1034 }
1035
1036 #[corresponds(SSL_CTX_add_client_CA)]
1039 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1040 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1041 }
1042
1043 #[corresponds(SSL_CTX_set_session_id_context)]
1052 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1053 unsafe {
1054 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1055 cvt(ffi::SSL_CTX_set_session_id_context(
1056 self.as_ptr(),
1057 sid_ctx.as_ptr(),
1058 sid_ctx.len() as SizeTy,
1059 ))
1060 .map(|_| ())
1061 }
1062 }
1063
1064 #[corresponds(SSL_CTX_use_certificate_file)]
1070 pub fn set_certificate_file<P: AsRef<Path>>(
1071 &mut self,
1072 file: P,
1073 file_type: SslFiletype,
1074 ) -> Result<(), ErrorStack> {
1075 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1076 unsafe {
1077 cvt(ffi::SSL_CTX_use_certificate_file(
1078 self.as_ptr(),
1079 file.as_ptr() as *const _,
1080 file_type.as_raw(),
1081 ))
1082 .map(|_| ())
1083 }
1084 }
1085
1086 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1092 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1093 &mut self,
1094 file: P,
1095 ) -> Result<(), ErrorStack> {
1096 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1097 unsafe {
1098 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1099 self.as_ptr(),
1100 file.as_ptr() as *const _,
1101 ))
1102 .map(|_| ())
1103 }
1104 }
1105
1106 #[corresponds(SSL_CTX_use_certificate)]
1110 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1111 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1112 }
1113
1114 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1119 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1120 unsafe {
1121 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1122 mem::forget(cert);
1123 Ok(())
1124 }
1125 }
1126
1127 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1129 pub fn set_private_key_file<P: AsRef<Path>>(
1130 &mut self,
1131 file: P,
1132 file_type: SslFiletype,
1133 ) -> Result<(), ErrorStack> {
1134 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1135 unsafe {
1136 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1137 self.as_ptr(),
1138 file.as_ptr() as *const _,
1139 file_type.as_raw(),
1140 ))
1141 .map(|_| ())
1142 }
1143 }
1144
1145 #[corresponds(SSL_CTX_use_PrivateKey)]
1147 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1148 where
1149 T: HasPrivate,
1150 {
1151 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1152 }
1153
1154 #[corresponds(SSL_CTX_set_cipher_list)]
1162 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1163 let cipher_list = CString::new(cipher_list).unwrap();
1164 unsafe {
1165 cvt(ffi::SSL_CTX_set_cipher_list(
1166 self.as_ptr(),
1167 cipher_list.as_ptr() as *const _,
1168 ))
1169 .map(|_| ())
1170 }
1171 }
1172
1173 #[corresponds(SSL_CTX_set_ciphersuites)]
1182 #[cfg(any(ossl111, libressl))]
1183 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1184 let cipher_list = CString::new(cipher_list).unwrap();
1185 unsafe {
1186 cvt(ffi::SSL_CTX_set_ciphersuites(
1187 self.as_ptr(),
1188 cipher_list.as_ptr() as *const _,
1189 ))
1190 .map(|_| ())
1191 }
1192 }
1193
1194 #[corresponds(SSL_CTX_set_ecdh_auto)]
1198 #[cfg(libressl)]
1199 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1200 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1201 }
1202
1203 #[corresponds(SSL_CTX_set_options)]
1210 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1211 let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
1212 SslOptions::from_bits_retain(bits)
1213 }
1214
1215 #[corresponds(SSL_CTX_get_options)]
1217 pub fn options(&self) -> SslOptions {
1218 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
1219 SslOptions::from_bits_retain(bits)
1220 }
1221
1222 #[corresponds(SSL_CTX_clear_options)]
1224 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1225 let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
1226 SslOptions::from_bits_retain(bits)
1227 }
1228
1229 #[corresponds(SSL_CTX_set_min_proto_version)]
1234 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1235 unsafe {
1236 cvt(ffi::SSL_CTX_set_min_proto_version(
1237 self.as_ptr(),
1238 version.map_or(0, |v| v.0 as _),
1239 ))
1240 .map(|_| ())
1241 }
1242 }
1243
1244 #[corresponds(SSL_CTX_set_max_proto_version)]
1249 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1250 unsafe {
1251 cvt(ffi::SSL_CTX_set_max_proto_version(
1252 self.as_ptr(),
1253 version.map_or(0, |v| v.0 as _),
1254 ))
1255 .map(|_| ())
1256 }
1257 }
1258
1259 #[corresponds(SSL_CTX_get_min_proto_version)]
1266 #[cfg(any(ossl110g, libressl))]
1267 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1268 unsafe {
1269 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1270 if r == 0 {
1271 None
1272 } else {
1273 Some(SslVersion(r))
1274 }
1275 }
1276 }
1277
1278 #[corresponds(SSL_CTX_get_max_proto_version)]
1285 #[cfg(any(ossl110g, libressl))]
1286 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1287 unsafe {
1288 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1289 if r == 0 {
1290 None
1291 } else {
1292 Some(SslVersion(r))
1293 }
1294 }
1295 }
1296
1297 #[corresponds(SSL_CTX_set_alpn_protos)]
1306 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1307 unsafe {
1308 assert!(protocols.len() <= c_uint::MAX as usize);
1309 let r = ffi::SSL_CTX_set_alpn_protos(
1310 self.as_ptr(),
1311 protocols.as_ptr(),
1312 protocols.len() as _,
1313 );
1314 if r == 0 {
1316 Ok(())
1317 } else {
1318 Err(ErrorStack::get())
1319 }
1320 }
1321 }
1322
1323 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1325 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1326 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1327 unsafe {
1328 let cstr = CString::new(protocols).unwrap();
1329
1330 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1331 if r == 0 {
1333 Ok(())
1334 } else {
1335 Err(ErrorStack::get())
1336 }
1337 }
1338 }
1339
1340 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1353 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1354 where
1355 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1356 {
1357 unsafe {
1358 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1359 #[cfg(not(any(boringssl, awslc)))]
1360 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1361 self.as_ptr(),
1362 Some(callbacks::raw_alpn_select::<F>),
1363 ptr::null_mut(),
1364 );
1365 #[cfg(any(boringssl, awslc))]
1366 ffi::SSL_CTX_set_alpn_select_cb(
1367 self.as_ptr(),
1368 Some(callbacks::raw_alpn_select::<F>),
1369 ptr::null_mut(),
1370 );
1371 }
1372 }
1373
1374 #[corresponds(SSL_CTX_check_private_key)]
1376 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1377 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1378 }
1379
1380 #[corresponds(SSL_CTX_get_cert_store)]
1382 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1383 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1384 }
1385
1386 #[corresponds(SSL_CTX_get_cert_store)]
1388 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1389 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1390 }
1391
1392 #[corresponds(SSL_CTX_get0_param)]
1396 pub fn verify_param(&self) -> &X509VerifyParamRef {
1397 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1398 }
1399
1400 #[corresponds(SSL_CTX_get0_param)]
1404 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1405 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1406 }
1407
1408 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1421 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1422 where
1423 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1424 {
1425 unsafe {
1426 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1427 cvt(
1428 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1429 as c_int,
1430 )
1431 .map(|_| ())
1432 }
1433 }
1434
1435 #[corresponds(SSL_CTX_set_psk_client_callback)]
1441 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1442 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1443 where
1444 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1445 + 'static
1446 + Sync
1447 + Send,
1448 {
1449 unsafe {
1450 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1451 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1452 }
1453 }
1454
1455 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1456 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1457 pub fn set_psk_callback<F>(&mut self, callback: F)
1458 where
1459 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1460 + 'static
1461 + Sync
1462 + Send,
1463 {
1464 self.set_psk_client_callback(callback)
1465 }
1466
1467 #[corresponds(SSL_CTX_set_psk_server_callback)]
1473 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1474 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1475 where
1476 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1477 + 'static
1478 + Sync
1479 + Send,
1480 {
1481 unsafe {
1482 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1483 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1484 }
1485 }
1486
1487 #[corresponds(SSL_CTX_sess_set_new_cb)]
1501 pub fn set_new_session_callback<F>(&mut self, callback: F)
1502 where
1503 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1504 {
1505 unsafe {
1506 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1507 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1508 }
1509 }
1510
1511 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1515 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1516 where
1517 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1518 {
1519 unsafe {
1520 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1521 ffi::SSL_CTX_sess_set_remove_cb(
1522 self.as_ptr(),
1523 Some(callbacks::raw_remove_session::<F>),
1524 );
1525 }
1526 }
1527
1528 #[corresponds(SSL_CTX_sess_set_get_cb)]
1539 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1540 where
1541 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1542 {
1543 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1544 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1545 }
1546
1547 #[corresponds(SSL_CTX_set_keylog_callback)]
1555 #[cfg(any(ossl111, boringssl, awslc))]
1556 pub fn set_keylog_callback<F>(&mut self, callback: F)
1557 where
1558 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1559 {
1560 unsafe {
1561 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1562 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1563 }
1564 }
1565
1566 #[corresponds(SSL_CTX_set_session_cache_mode)]
1570 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1571 unsafe {
1572 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1573 SslSessionCacheMode::from_bits_retain(bits)
1574 }
1575 }
1576
1577 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1583 #[cfg(ossl111)]
1584 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1585 where
1586 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1587 {
1588 unsafe {
1589 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1590 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1591 self.as_ptr(),
1592 Some(raw_stateless_cookie_generate::<F>),
1593 );
1594 }
1595 }
1596
1597 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1606 #[cfg(ossl111)]
1607 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1608 where
1609 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1610 {
1611 unsafe {
1612 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1613 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1614 self.as_ptr(),
1615 Some(raw_stateless_cookie_verify::<F>),
1616 )
1617 }
1618 }
1619
1620 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1625 #[cfg(not(any(boringssl, awslc)))]
1626 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1627 where
1628 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1629 {
1630 unsafe {
1631 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1632 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1633 }
1634 }
1635
1636 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1641 #[cfg(not(any(boringssl, awslc)))]
1642 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1643 where
1644 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1645 {
1646 unsafe {
1647 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1648 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1649 }
1650 }
1651
1652 #[corresponds(SSL_CTX_set_ex_data)]
1658 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1659 self.set_ex_data_inner(index, data);
1660 }
1661
1662 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1663 match self.ex_data_mut(index) {
1664 Some(v) => {
1665 *v = data;
1666 (v as *mut T).cast()
1667 }
1668 _ => unsafe {
1669 let data = Box::into_raw(Box::new(data)) as *mut c_void;
1670 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1671 data
1672 },
1673 }
1674 }
1675
1676 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1677 unsafe {
1678 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1679 if data.is_null() {
1680 None
1681 } else {
1682 Some(&mut *data.cast())
1683 }
1684 }
1685 }
1686
1687 #[corresponds(SSL_CTX_add_custom_ext)]
1691 #[cfg(ossl111)]
1692 pub fn add_custom_ext<AddFn, ParseFn, T>(
1693 &mut self,
1694 ext_type: u16,
1695 context: ExtensionContext,
1696 add_cb: AddFn,
1697 parse_cb: ParseFn,
1698 ) -> Result<(), ErrorStack>
1699 where
1700 AddFn: Fn(
1701 &mut SslRef,
1702 ExtensionContext,
1703 Option<(usize, &X509Ref)>,
1704 ) -> Result<Option<T>, SslAlert>
1705 + 'static
1706 + Sync
1707 + Send,
1708 T: AsRef<[u8]> + 'static + Sync + Send,
1709 ParseFn: Fn(
1710 &mut SslRef,
1711 ExtensionContext,
1712 &[u8],
1713 Option<(usize, &X509Ref)>,
1714 ) -> Result<(), SslAlert>
1715 + 'static
1716 + Sync
1717 + Send,
1718 {
1719 let ret = unsafe {
1720 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1721 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1722
1723 ffi::SSL_CTX_add_custom_ext(
1724 self.as_ptr(),
1725 ext_type as c_uint,
1726 context.bits(),
1727 Some(raw_custom_ext_add::<AddFn, T>),
1728 Some(raw_custom_ext_free::<T>),
1729 ptr::null_mut(),
1730 Some(raw_custom_ext_parse::<ParseFn>),
1731 ptr::null_mut(),
1732 )
1733 };
1734 if ret == 1 {
1735 Ok(())
1736 } else {
1737 Err(ErrorStack::get())
1738 }
1739 }
1740
1741 #[corresponds(SSL_CTX_set_max_early_data)]
1747 #[cfg(any(ossl111, libressl))]
1748 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1749 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1750 Ok(())
1751 } else {
1752 Err(ErrorStack::get())
1753 }
1754 }
1755
1756 #[corresponds(SSL_CTX_set_client_hello_cb)]
1760 #[cfg(ossl111)]
1761 pub fn set_client_hello_callback<F>(&mut self, callback: F)
1762 where
1763 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1764 + 'static
1765 + Sync
1766 + Send,
1767 {
1768 unsafe {
1769 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1770 ffi::SSL_CTX_set_client_hello_cb(
1771 self.as_ptr(),
1772 Some(callbacks::raw_client_hello::<F>),
1773 ptr,
1774 );
1775 }
1776 }
1777
1778 #[corresponds(SSL_CTX_sess_set_cache_size)]
1782 #[allow(clippy::useless_conversion)]
1783 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1784 unsafe {
1785 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1786 }
1787 }
1788
1789 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1793 #[cfg(ossl110)]
1794 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1795 let sigalgs = CString::new(sigalgs).unwrap();
1796 unsafe {
1797 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1798 .map(|_| ())
1799 }
1800 }
1801
1802 #[corresponds(SSL_CTX_set1_groups_list)]
1806 #[cfg(any(ossl111, boringssl, libressl, awslc))]
1807 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1808 let groups = CString::new(groups).unwrap();
1809 unsafe {
1810 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1811 }
1812 }
1813
1814 #[corresponds(SSL_CTX_set_num_tickets)]
1819 #[cfg(ossl111)]
1820 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1821 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1822 }
1823
1824 #[corresponds(SSL_CTX_set_security_level)]
1829 #[cfg(any(ossl110, libressl360))]
1830 pub fn set_security_level(&mut self, level: u32) {
1831 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1832 }
1833
1834 pub fn build(self) -> SslContext {
1836 self.0
1837 }
1838}
1839
1840foreign_type_and_impl_send_sync! {
1841 type CType = ffi::SSL_CTX;
1842 fn drop = ffi::SSL_CTX_free;
1843
1844 pub struct SslContext;
1849
1850 pub struct SslContextRef;
1854}
1855
1856impl Clone for SslContext {
1857 fn clone(&self) -> Self {
1858 (**self).to_owned()
1859 }
1860}
1861
1862impl ToOwned for SslContextRef {
1863 type Owned = SslContext;
1864
1865 fn to_owned(&self) -> Self::Owned {
1866 unsafe {
1867 let r = SSL_CTX_up_ref(self.as_ptr());
1868 assert!(r == 1);
1869 SslContext::from_ptr(self.as_ptr())
1870 }
1871 }
1872}
1873
1874impl fmt::Debug for SslContext {
1876 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1877 write!(fmt, "SslContext")
1878 }
1879}
1880
1881impl SslContext {
1882 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1884 SslContextBuilder::new(method)
1885 }
1886
1887 #[corresponds(SSL_CTX_get_ex_new_index)]
1892 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1893 where
1894 T: 'static + Sync + Send,
1895 {
1896 unsafe {
1897 ffi::init();
1898 #[cfg(any(boringssl, awslc))]
1899 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1900 #[cfg(not(any(boringssl, awslc)))]
1901 let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1902 Ok(Index::from_raw(idx))
1903 }
1904 }
1905
1906 fn cached_ex_index<T>() -> Index<SslContext, T>
1908 where
1909 T: 'static + Sync + Send,
1910 {
1911 unsafe {
1912 let idx = *INDEXES
1913 .lock()
1914 .unwrap_or_else(|e| e.into_inner())
1915 .entry(TypeId::of::<T>())
1916 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1917 Index::from_raw(idx)
1918 }
1919 }
1920}
1921
1922impl SslContextRef {
1923 #[corresponds(SSL_CTX_get0_certificate)]
1927 #[cfg(any(ossl110, libressl))]
1928 pub fn certificate(&self) -> Option<&X509Ref> {
1929 unsafe {
1930 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1931 X509Ref::from_const_ptr_opt(ptr)
1932 }
1933 }
1934
1935 #[corresponds(SSL_CTX_get0_privatekey)]
1939 #[cfg(any(ossl110, libressl))]
1940 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1941 unsafe {
1942 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1943 PKeyRef::from_const_ptr_opt(ptr)
1944 }
1945 }
1946
1947 #[corresponds(SSL_CTX_get_cert_store)]
1949 pub fn cert_store(&self) -> &X509StoreRef {
1950 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1951 }
1952
1953 #[corresponds(SSL_CTX_get_extra_chain_certs)]
1955 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1956 unsafe {
1957 let mut chain = ptr::null_mut();
1958 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1959 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1960 }
1961 }
1962
1963 #[corresponds(SSL_CTX_get_ex_data)]
1965 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1966 unsafe {
1967 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1968 if data.is_null() {
1969 None
1970 } else {
1971 Some(&*(data as *const T))
1972 }
1973 }
1974 }
1975
1976 #[corresponds(SSL_CTX_get_max_early_data)]
1980 #[cfg(any(ossl111, libressl))]
1981 pub fn max_early_data(&self) -> u32 {
1982 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1983 }
1984
1985 #[corresponds(SSL_CTX_add_session)]
1994 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1995 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1996 }
1997
1998 #[corresponds(SSL_CTX_remove_session)]
2007 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2008 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2009 }
2010
2011 #[corresponds(SSL_CTX_sess_get_cache_size)]
2015 #[allow(clippy::unnecessary_cast)]
2016 pub fn session_cache_size(&self) -> i64 {
2017 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2018 }
2019
2020 #[corresponds(SSL_CTX_get_verify_mode)]
2024 pub fn verify_mode(&self) -> SslVerifyMode {
2025 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2026 SslVerifyMode::from_bits_retain(mode)
2027 }
2028
2029 #[corresponds(SSL_CTX_get_num_tickets)]
2034 #[cfg(ossl111)]
2035 pub fn num_tickets(&self) -> usize {
2036 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2037 }
2038
2039 #[corresponds(SSL_CTX_get_security_level)]
2044 #[cfg(any(ossl110, libressl360))]
2045 pub fn security_level(&self) -> u32 {
2046 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2047 }
2048}
2049
2050pub struct CipherBits {
2052 pub secret: i32,
2054
2055 pub algorithm: i32,
2057}
2058
2059pub struct SslCipher(*mut ffi::SSL_CIPHER);
2061
2062impl ForeignType for SslCipher {
2063 type CType = ffi::SSL_CIPHER;
2064 type Ref = SslCipherRef;
2065
2066 #[inline]
2067 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2068 SslCipher(ptr)
2069 }
2070
2071 #[inline]
2072 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2073 self.0
2074 }
2075}
2076
2077impl Stackable for SslCipher {
2078 type StackType = ffi::stack_st_SSL_CIPHER;
2079}
2080
2081impl Deref for SslCipher {
2082 type Target = SslCipherRef;
2083
2084 fn deref(&self) -> &SslCipherRef {
2085 unsafe { SslCipherRef::from_ptr(self.0) }
2086 }
2087}
2088
2089impl DerefMut for SslCipher {
2090 fn deref_mut(&mut self) -> &mut SslCipherRef {
2091 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2092 }
2093}
2094
2095pub struct SslCipherRef(Opaque);
2099
2100impl ForeignTypeRef for SslCipherRef {
2101 type CType = ffi::SSL_CIPHER;
2102}
2103
2104impl SslCipherRef {
2105 #[corresponds(SSL_CIPHER_get_name)]
2107 pub fn name(&self) -> &'static str {
2108 unsafe {
2109 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2110 CStr::from_ptr(ptr).to_str().unwrap()
2111 }
2112 }
2113
2114 #[corresponds(SSL_CIPHER_standard_name)]
2118 #[cfg(ossl111)]
2119 pub fn standard_name(&self) -> Option<&'static str> {
2120 unsafe {
2121 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2122 if ptr.is_null() {
2123 None
2124 } else {
2125 Some(CStr::from_ptr(ptr).to_str().unwrap())
2126 }
2127 }
2128 }
2129
2130 #[corresponds(SSL_CIPHER_get_version)]
2132 pub fn version(&self) -> &'static str {
2133 let version = unsafe {
2134 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2135 CStr::from_ptr(ptr as *const _)
2136 };
2137
2138 str::from_utf8(version.to_bytes()).unwrap()
2139 }
2140
2141 #[corresponds(SSL_CIPHER_get_bits)]
2143 #[allow(clippy::useless_conversion)]
2144 pub fn bits(&self) -> CipherBits {
2145 unsafe {
2146 let mut algo_bits = 0;
2147 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2148 CipherBits {
2149 secret: secret_bits.into(),
2150 algorithm: algo_bits.into(),
2151 }
2152 }
2153 }
2154
2155 #[corresponds(SSL_CIPHER_description)]
2157 pub fn description(&self) -> String {
2158 unsafe {
2159 let mut buf = [0; 128];
2161 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2162 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2163 }
2164 }
2165
2166 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2170 #[cfg(ossl111)]
2171 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2172 unsafe {
2173 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2174 if ptr.is_null() {
2175 None
2176 } else {
2177 Some(MessageDigest::from_ptr(ptr))
2178 }
2179 }
2180 }
2181
2182 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2186 #[cfg(any(ossl110, libressl))]
2187 pub fn cipher_nid(&self) -> Option<Nid> {
2188 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2189 if n == 0 {
2190 None
2191 } else {
2192 Some(Nid::from_raw(n))
2193 }
2194 }
2195
2196 #[corresponds(SSL_CIPHER_get_protocol_id)]
2200 #[cfg(ossl111)]
2201 pub fn protocol_id(&self) -> [u8; 2] {
2202 unsafe {
2203 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2204 id.to_be_bytes()
2205 }
2206 }
2207}
2208
2209impl fmt::Debug for SslCipherRef {
2210 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2211 write!(fmt, "{}", self.name())
2212 }
2213}
2214
2215#[derive(Debug)]
2217pub struct CipherLists {
2218 pub suites: Stack<SslCipher>,
2219 pub signalling_suites: Stack<SslCipher>,
2220}
2221
2222foreign_type_and_impl_send_sync! {
2223 type CType = ffi::SSL_SESSION;
2224 fn drop = ffi::SSL_SESSION_free;
2225
2226 pub struct SslSession;
2230
2231 pub struct SslSessionRef;
2235}
2236
2237impl Clone for SslSession {
2238 fn clone(&self) -> SslSession {
2239 SslSessionRef::to_owned(self)
2240 }
2241}
2242
2243impl SslSession {
2244 from_der! {
2245 #[corresponds(d2i_SSL_SESSION)]
2247 from_der,
2248 SslSession,
2249 ffi::d2i_SSL_SESSION
2250 }
2251}
2252
2253impl ToOwned for SslSessionRef {
2254 type Owned = SslSession;
2255
2256 fn to_owned(&self) -> SslSession {
2257 unsafe {
2258 let r = SSL_SESSION_up_ref(self.as_ptr());
2259 assert!(r == 1);
2260 SslSession(self.as_ptr())
2261 }
2262 }
2263}
2264
2265impl SslSessionRef {
2266 #[corresponds(SSL_SESSION_get_id)]
2268 pub fn id(&self) -> &[u8] {
2269 unsafe {
2270 let mut len = 0;
2271 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2272 #[allow(clippy::unnecessary_cast)]
2273 util::from_raw_parts(p as *const u8, len as usize)
2274 }
2275 }
2276
2277 #[corresponds(SSL_SESSION_get_master_key)]
2279 pub fn master_key_len(&self) -> usize {
2280 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2281 }
2282
2283 #[corresponds(SSL_SESSION_get_master_key)]
2287 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2288 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2289 }
2290
2291 #[corresponds(SSL_SESSION_get_max_early_data)]
2295 #[cfg(any(ossl111, libressl))]
2296 pub fn max_early_data(&self) -> u32 {
2297 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2298 }
2299
2300 #[corresponds(SSL_SESSION_get_time)]
2302 #[allow(clippy::useless_conversion)]
2303 pub fn time(&self) -> SslTimeTy {
2304 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2305 }
2306
2307 #[corresponds(SSL_SESSION_get_timeout)]
2311 #[allow(clippy::useless_conversion)]
2312 pub fn timeout(&self) -> i64 {
2313 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2314 }
2315
2316 #[corresponds(SSL_SESSION_get_protocol_version)]
2320 #[cfg(any(ossl110, libressl))]
2321 pub fn protocol_version(&self) -> SslVersion {
2322 unsafe {
2323 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2324 SslVersion(version)
2325 }
2326 }
2327
2328 to_der! {
2329 #[corresponds(i2d_SSL_SESSION)]
2331 to_der,
2332 ffi::i2d_SSL_SESSION
2333 }
2334}
2335
2336foreign_type_and_impl_send_sync! {
2337 type CType = ffi::SSL;
2338 fn drop = ffi::SSL_free;
2339
2340 pub struct Ssl;
2347
2348 pub struct SslRef;
2352}
2353
2354impl fmt::Debug for Ssl {
2355 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2356 fmt::Debug::fmt(&**self, fmt)
2357 }
2358}
2359
2360impl Ssl {
2361 #[corresponds(SSL_get_ex_new_index)]
2366 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2367 where
2368 T: 'static + Sync + Send,
2369 {
2370 unsafe {
2371 ffi::init();
2372 #[cfg(any(boringssl, awslc))]
2373 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2374 #[cfg(not(any(boringssl, awslc)))]
2375 let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
2376 Ok(Index::from_raw(idx))
2377 }
2378 }
2379
2380 fn cached_ex_index<T>() -> Index<Ssl, T>
2382 where
2383 T: 'static + Sync + Send,
2384 {
2385 unsafe {
2386 let idx = *SSL_INDEXES
2387 .lock()
2388 .unwrap_or_else(|e| e.into_inner())
2389 .entry(TypeId::of::<T>())
2390 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2391 Index::from_raw(idx)
2392 }
2393 }
2394
2395 #[corresponds(SSL_new)]
2397 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2398 let session_ctx_index = try_get_session_ctx_index()?;
2399 unsafe {
2400 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2401 let mut ssl = Ssl::from_ptr(ptr);
2402 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2403
2404 Ok(ssl)
2405 }
2406 }
2407
2408 #[corresponds(SSL_connect)]
2414 #[allow(deprecated)]
2415 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2416 where
2417 S: Read + Write,
2418 {
2419 SslStreamBuilder::new(self, stream).connect()
2420 }
2421
2422 #[corresponds(SSL_accept)]
2429 #[allow(deprecated)]
2430 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2431 where
2432 S: Read + Write,
2433 {
2434 SslStreamBuilder::new(self, stream).accept()
2435 }
2436}
2437
2438impl fmt::Debug for SslRef {
2439 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2440 fmt.debug_struct("Ssl")
2441 .field("state", &self.state_string_long())
2442 .field("verify_result", &self.verify_result())
2443 .finish()
2444 }
2445}
2446
2447impl SslRef {
2448 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2449 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2450 }
2451
2452 fn get_error(&self, ret: c_int) -> ErrorCode {
2453 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2454 }
2455
2456 #[corresponds(SSL_set_connect_state)]
2458 pub fn set_connect_state(&mut self) {
2459 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2460 }
2461
2462 #[corresponds(SSL_set_accept_state)]
2464 pub fn set_accept_state(&mut self) {
2465 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2466 }
2467
2468 #[corresponds(SSL_set_verify)]
2472 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2473 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2474 }
2475
2476 #[corresponds(SSL_set_verify_mode)]
2478 pub fn verify_mode(&self) -> SslVerifyMode {
2479 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2480 SslVerifyMode::from_bits_retain(mode)
2481 }
2482
2483 #[corresponds(SSL_set_verify)]
2487 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2488 where
2489 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2490 {
2491 unsafe {
2492 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2494 ffi::SSL_set_verify(
2495 self.as_ptr(),
2496 mode.bits() as c_int,
2497 Some(ssl_raw_verify::<F>),
2498 );
2499 }
2500 }
2501
2502 #[corresponds(SSL_set_tmp_dh)]
2506 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2507 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2508 }
2509
2510 #[corresponds(SSL_set_tmp_dh_callback)]
2514 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2515 where
2516 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2517 {
2518 unsafe {
2519 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2521 #[cfg(any(boringssl, awslc))]
2522 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2523 #[cfg(not(any(boringssl, awslc)))]
2524 ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2525 }
2526 }
2527
2528 #[corresponds(SSL_set_tmp_ecdh)]
2532 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
2533 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
2534 }
2535
2536 #[corresponds(SSL_set_ecdh_auto)]
2542 #[cfg(libressl)]
2543 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2544 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2545 }
2546
2547 #[corresponds(SSL_set_alpn_protos)]
2553 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2554 unsafe {
2555 assert!(protocols.len() <= c_uint::MAX as usize);
2556 let r =
2557 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2558 if r == 0 {
2560 Ok(())
2561 } else {
2562 Err(ErrorStack::get())
2563 }
2564 }
2565 }
2566
2567 #[corresponds(SSL_get_current_cipher)]
2569 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2570 unsafe {
2571 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2572
2573 SslCipherRef::from_const_ptr_opt(ptr)
2574 }
2575 }
2576
2577 #[corresponds(SSL_state_string)]
2579 pub fn state_string(&self) -> &'static str {
2580 let state = unsafe {
2581 let ptr = ffi::SSL_state_string(self.as_ptr());
2582 CStr::from_ptr(ptr as *const _)
2583 };
2584
2585 str::from_utf8(state.to_bytes()).unwrap()
2586 }
2587
2588 #[corresponds(SSL_state_string_long)]
2590 pub fn state_string_long(&self) -> &'static str {
2591 let state = unsafe {
2592 let ptr = ffi::SSL_state_string_long(self.as_ptr());
2593 CStr::from_ptr(ptr as *const _)
2594 };
2595
2596 str::from_utf8(state.to_bytes()).unwrap()
2597 }
2598
2599 #[corresponds(SSL_set_tlsext_host_name)]
2603 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2604 let cstr = CString::new(hostname).unwrap();
2605 unsafe {
2606 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2607 .map(|_| ())
2608 }
2609 }
2610
2611 #[corresponds(SSL_get_peer_certificate)]
2613 pub fn peer_certificate(&self) -> Option<X509> {
2614 unsafe {
2615 let ptr = SSL_get1_peer_certificate(self.as_ptr());
2616 X509::from_ptr_opt(ptr)
2617 }
2618 }
2619
2620 #[corresponds(SSL_get_peer_cert_chain)]
2625 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2626 unsafe {
2627 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2628 StackRef::from_const_ptr_opt(ptr)
2629 }
2630 }
2631
2632 #[corresponds(SSL_get0_verified_chain)]
2642 #[cfg(ossl110)]
2643 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2644 unsafe {
2645 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2646 StackRef::from_const_ptr_opt(ptr)
2647 }
2648 }
2649
2650 #[corresponds(SSL_get_certificate)]
2652 pub fn certificate(&self) -> Option<&X509Ref> {
2653 unsafe {
2654 let ptr = ffi::SSL_get_certificate(self.as_ptr());
2655 X509Ref::from_const_ptr_opt(ptr)
2656 }
2657 }
2658
2659 #[corresponds(SSL_get_privatekey)]
2663 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2664 unsafe {
2665 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2666 PKeyRef::from_const_ptr_opt(ptr)
2667 }
2668 }
2669
2670 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2671 pub fn version(&self) -> &str {
2672 self.version_str()
2673 }
2674
2675 #[corresponds(SSL_version)]
2677 pub fn version2(&self) -> Option<SslVersion> {
2678 unsafe {
2679 let r = ffi::SSL_version(self.as_ptr());
2680 if r == 0 {
2681 None
2682 } else {
2683 Some(SslVersion(r))
2684 }
2685 }
2686 }
2687
2688 #[corresponds(SSL_get_version)]
2690 pub fn version_str(&self) -> &'static str {
2691 let version = unsafe {
2692 let ptr = ffi::SSL_get_version(self.as_ptr());
2693 CStr::from_ptr(ptr as *const _)
2694 };
2695
2696 str::from_utf8(version.to_bytes()).unwrap()
2697 }
2698
2699 #[corresponds(SSL_get0_alpn_selected)]
2706 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2707 unsafe {
2708 let mut data: *const c_uchar = ptr::null();
2709 let mut len: c_uint = 0;
2710 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2713
2714 if data.is_null() {
2715 None
2716 } else {
2717 Some(util::from_raw_parts(data, len as usize))
2718 }
2719 }
2720 }
2721
2722 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2724 #[corresponds(SSL_set_tlsext_use_srtp)]
2725 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2726 unsafe {
2727 let cstr = CString::new(protocols).unwrap();
2728
2729 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2730 if r == 0 {
2732 Ok(())
2733 } else {
2734 Err(ErrorStack::get())
2735 }
2736 }
2737 }
2738
2739 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2743 #[corresponds(SSL_get_srtp_profiles)]
2744 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
2745 unsafe {
2746 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
2747
2748 StackRef::from_const_ptr_opt(chain)
2749 }
2750 }
2751
2752 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2756 #[corresponds(SSL_get_selected_srtp_profile)]
2757 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2758 unsafe {
2759 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2760
2761 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2762 }
2763 }
2764
2765 #[corresponds(SSL_pending)]
2770 pub fn pending(&self) -> usize {
2771 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2772 }
2773
2774 #[corresponds(SSL_get_servername)]
2787 pub fn servername(&self, type_: NameType) -> Option<&str> {
2789 self.servername_raw(type_)
2790 .and_then(|b| str::from_utf8(b).ok())
2791 }
2792
2793 #[corresponds(SSL_get_servername)]
2801 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2802 unsafe {
2803 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2804 if name.is_null() {
2805 None
2806 } else {
2807 Some(CStr::from_ptr(name as *const _).to_bytes())
2808 }
2809 }
2810 }
2811
2812 #[corresponds(SSL_set_SSL_CTX)]
2816 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2817 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2818 }
2819
2820 #[corresponds(SSL_get_SSL_CTX)]
2822 pub fn ssl_context(&self) -> &SslContextRef {
2823 unsafe {
2824 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2825 SslContextRef::from_ptr(ssl_ctx)
2826 }
2827 }
2828
2829 #[corresponds(SSL_get0_param)]
2833 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
2834 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
2835 }
2836
2837 #[corresponds(SSL_get_verify_result)]
2839 pub fn verify_result(&self) -> X509VerifyResult {
2840 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
2841 }
2842
2843 #[corresponds(SSL_get_session)]
2845 pub fn session(&self) -> Option<&SslSessionRef> {
2846 unsafe {
2847 let p = ffi::SSL_get_session(self.as_ptr());
2848 SslSessionRef::from_const_ptr_opt(p)
2849 }
2850 }
2851
2852 #[corresponds(SSL_get_client_random)]
2859 #[cfg(any(ossl110, libressl))]
2860 pub fn client_random(&self, buf: &mut [u8]) -> usize {
2861 unsafe {
2862 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2863 }
2864 }
2865
2866 #[corresponds(SSL_get_server_random)]
2873 #[cfg(any(ossl110, libressl))]
2874 pub fn server_random(&self, buf: &mut [u8]) -> usize {
2875 unsafe {
2876 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2877 }
2878 }
2879
2880 #[corresponds(SSL_export_keying_material)]
2882 pub fn export_keying_material(
2883 &self,
2884 out: &mut [u8],
2885 label: &str,
2886 context: Option<&[u8]>,
2887 ) -> Result<(), ErrorStack> {
2888 unsafe {
2889 let (context, contextlen, use_context) = match context {
2890 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
2891 None => (ptr::null(), 0, 0),
2892 };
2893 cvt(ffi::SSL_export_keying_material(
2894 self.as_ptr(),
2895 out.as_mut_ptr() as *mut c_uchar,
2896 out.len(),
2897 label.as_ptr() as *const c_char,
2898 label.len(),
2899 context,
2900 contextlen,
2901 use_context,
2902 ))
2903 .map(|_| ())
2904 }
2905 }
2906
2907 #[corresponds(SSL_export_keying_material_early)]
2914 #[cfg(ossl111)]
2915 pub fn export_keying_material_early(
2916 &self,
2917 out: &mut [u8],
2918 label: &str,
2919 context: &[u8],
2920 ) -> Result<(), ErrorStack> {
2921 unsafe {
2922 cvt(ffi::SSL_export_keying_material_early(
2923 self.as_ptr(),
2924 out.as_mut_ptr() as *mut c_uchar,
2925 out.len(),
2926 label.as_ptr() as *const c_char,
2927 label.len(),
2928 context.as_ptr() as *const c_uchar,
2929 context.len(),
2930 ))
2931 .map(|_| ())
2932 }
2933 }
2934
2935 #[corresponds(SSL_set_session)]
2946 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
2947 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
2948 }
2949
2950 #[corresponds(SSL_session_reused)]
2952 pub fn session_reused(&self) -> bool {
2953 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
2954 }
2955
2956 #[corresponds(SSL_set_tlsext_status_type)]
2958 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
2959 unsafe {
2960 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
2961 }
2962 }
2963
2964 #[corresponds(SSL_get_extms_support)]
2968 #[cfg(ossl110)]
2969 pub fn extms_support(&self) -> Option<bool> {
2970 unsafe {
2971 match ffi::SSL_get_extms_support(self.as_ptr()) {
2972 -1 => None,
2973 ret => Some(ret != 0),
2974 }
2975 }
2976 }
2977
2978 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
2980 #[cfg(not(any(boringssl, awslc)))]
2981 pub fn ocsp_status(&self) -> Option<&[u8]> {
2982 unsafe {
2983 let mut p = ptr::null_mut();
2984 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
2985
2986 if len < 0 {
2987 None
2988 } else {
2989 Some(util::from_raw_parts(p as *const u8, len as usize))
2990 }
2991 }
2992 }
2993
2994 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
2996 #[cfg(not(any(boringssl, awslc)))]
2997 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
2998 unsafe {
2999 assert!(response.len() <= c_int::MAX as usize);
3000 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3001 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3002 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3003 self.as_ptr(),
3004 p as *mut c_uchar,
3005 response.len() as c_long,
3006 ) as c_int)
3007 .map(|_| ())
3008 .inspect_err(|_| {
3009 ffi::OPENSSL_free(p);
3010 })
3011 }
3012 }
3013
3014 #[corresponds(SSL_is_server)]
3016 pub fn is_server(&self) -> bool {
3017 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3018 }
3019
3020 #[corresponds(SSL_set_ex_data)]
3026 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3027 match self.ex_data_mut(index) {
3028 Some(v) => *v = data,
3029 None => unsafe {
3030 let data = Box::new(data);
3031 ffi::SSL_set_ex_data(
3032 self.as_ptr(),
3033 index.as_raw(),
3034 Box::into_raw(data) as *mut c_void,
3035 );
3036 },
3037 }
3038 }
3039
3040 #[corresponds(SSL_get_ex_data)]
3042 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3043 unsafe {
3044 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3045 if data.is_null() {
3046 None
3047 } else {
3048 Some(&*(data as *const T))
3049 }
3050 }
3051 }
3052
3053 #[corresponds(SSL_get_ex_data)]
3055 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3056 unsafe {
3057 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3058 if data.is_null() {
3059 None
3060 } else {
3061 Some(&mut *(data as *mut T))
3062 }
3063 }
3064 }
3065
3066 #[corresponds(SSL_set_max_early_data)]
3070 #[cfg(any(ossl111, libressl))]
3071 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3072 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3073 Ok(())
3074 } else {
3075 Err(ErrorStack::get())
3076 }
3077 }
3078
3079 #[corresponds(SSL_get_max_early_data)]
3083 #[cfg(any(ossl111, libressl))]
3084 pub fn max_early_data(&self) -> u32 {
3085 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3086 }
3087
3088 #[corresponds(SSL_get_finished)]
3093 pub fn finished(&self, buf: &mut [u8]) -> usize {
3094 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3095 }
3096
3097 #[corresponds(SSL_get_peer_finished)]
3103 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3104 unsafe {
3105 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3106 }
3107 }
3108
3109 #[corresponds(SSL_is_init_finished)]
3111 #[cfg(ossl110)]
3112 pub fn is_init_finished(&self) -> bool {
3113 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3114 }
3115
3116 #[corresponds(SSL_client_hello_isv2)]
3122 #[cfg(ossl111)]
3123 pub fn client_hello_isv2(&self) -> bool {
3124 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3125 }
3126
3127 #[corresponds(SSL_client_hello_get0_legacy_version)]
3133 #[cfg(ossl111)]
3134 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3135 unsafe {
3136 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3137 if version == 0 {
3138 None
3139 } else {
3140 Some(SslVersion(version as c_int))
3141 }
3142 }
3143 }
3144
3145 #[corresponds(SSL_client_hello_get0_random)]
3151 #[cfg(ossl111)]
3152 pub fn client_hello_random(&self) -> Option<&[u8]> {
3153 unsafe {
3154 let mut ptr = ptr::null();
3155 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3156 if len == 0 {
3157 None
3158 } else {
3159 Some(util::from_raw_parts(ptr, len))
3160 }
3161 }
3162 }
3163
3164 #[corresponds(SSL_client_hello_get0_session_id)]
3170 #[cfg(ossl111)]
3171 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3172 unsafe {
3173 let mut ptr = ptr::null();
3174 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3175 if len == 0 {
3176 None
3177 } else {
3178 Some(util::from_raw_parts(ptr, len))
3179 }
3180 }
3181 }
3182
3183 #[corresponds(SSL_client_hello_get0_ciphers)]
3189 #[cfg(ossl111)]
3190 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3191 unsafe {
3192 let mut ptr = ptr::null();
3193 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3194 if len == 0 {
3195 None
3196 } else {
3197 Some(util::from_raw_parts(ptr, len))
3198 }
3199 }
3200 }
3201
3202 #[corresponds(SSL_bytes_to_cipher_list)]
3207 #[cfg(ossl111)]
3208 pub fn bytes_to_cipher_list(
3209 &self,
3210 bytes: &[u8],
3211 isv2format: bool,
3212 ) -> Result<CipherLists, ErrorStack> {
3213 unsafe {
3214 let ptr = bytes.as_ptr();
3215 let len = bytes.len();
3216 let mut sk = ptr::null_mut();
3217 let mut scsvs = ptr::null_mut();
3218 let res = ffi::SSL_bytes_to_cipher_list(
3219 self.as_ptr(),
3220 ptr,
3221 len,
3222 isv2format as c_int,
3223 &mut sk,
3224 &mut scsvs,
3225 );
3226 if res == 1 {
3227 Ok(CipherLists {
3228 suites: Stack::from_ptr(sk),
3229 signalling_suites: Stack::from_ptr(scsvs),
3230 })
3231 } else {
3232 Err(ErrorStack::get())
3233 }
3234 }
3235 }
3236
3237 #[corresponds(SSL_client_hello_get0_compression_methods)]
3243 #[cfg(ossl111)]
3244 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3245 unsafe {
3246 let mut ptr = ptr::null();
3247 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3248 if len == 0 {
3249 None
3250 } else {
3251 Some(util::from_raw_parts(ptr, len))
3252 }
3253 }
3254 }
3255
3256 #[corresponds(SSL_set_mtu)]
3258 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3259 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3260 }
3261
3262 #[corresponds(SSL_get_psk_identity_hint)]
3266 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3267 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3268 unsafe {
3269 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3270 if ptr.is_null() {
3271 None
3272 } else {
3273 Some(CStr::from_ptr(ptr).to_bytes())
3274 }
3275 }
3276 }
3277
3278 #[corresponds(SSL_get_psk_identity)]
3280 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3281 pub fn psk_identity(&self) -> Option<&[u8]> {
3282 unsafe {
3283 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3284 if ptr.is_null() {
3285 None
3286 } else {
3287 Some(CStr::from_ptr(ptr).to_bytes())
3288 }
3289 }
3290 }
3291
3292 #[corresponds(SSL_add0_chain_cert)]
3293 #[cfg(ossl110)]
3294 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3295 unsafe {
3296 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3297 mem::forget(chain);
3298 }
3299 Ok(())
3300 }
3301
3302 #[cfg(not(any(boringssl, awslc)))]
3304 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3305 unsafe {
3306 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3307 };
3308 Ok(())
3309 }
3310
3311 #[corresponds(SSL_use_Private_Key_file)]
3313 pub fn set_private_key_file<P: AsRef<Path>>(
3314 &mut self,
3315 path: P,
3316 ssl_file_type: SslFiletype,
3317 ) -> Result<(), ErrorStack> {
3318 let p = path.as_ref().as_os_str().to_str().unwrap();
3319 let key_file = CString::new(p).unwrap();
3320 unsafe {
3321 cvt(ffi::SSL_use_PrivateKey_file(
3322 self.as_ptr(),
3323 key_file.as_ptr(),
3324 ssl_file_type.as_raw(),
3325 ))?;
3326 };
3327 Ok(())
3328 }
3329
3330 #[corresponds(SSL_use_PrivateKey)]
3332 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3333 unsafe {
3334 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3335 };
3336 Ok(())
3337 }
3338
3339 #[corresponds(SSL_use_certificate)]
3341 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3342 unsafe {
3343 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3344 };
3345 Ok(())
3346 }
3347
3348 #[corresponds(SSL_use_certificate_chain_file)]
3354 #[cfg(any(ossl110, libressl))]
3355 pub fn set_certificate_chain_file<P: AsRef<Path>>(
3356 &mut self,
3357 path: P,
3358 ) -> Result<(), ErrorStack> {
3359 let p = path.as_ref().as_os_str().to_str().unwrap();
3360 let cert_file = CString::new(p).unwrap();
3361 unsafe {
3362 cvt(ffi::SSL_use_certificate_chain_file(
3363 self.as_ptr(),
3364 cert_file.as_ptr(),
3365 ))?;
3366 };
3367 Ok(())
3368 }
3369
3370 #[corresponds(SSL_add_client_CA)]
3372 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
3373 unsafe {
3374 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
3375 };
3376 Ok(())
3377 }
3378
3379 #[corresponds(SSL_set_client_CA_list)]
3381 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3382 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3383 mem::forget(list);
3384 }
3385
3386 #[corresponds(SSL_set_min_proto_version)]
3391 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3392 unsafe {
3393 cvt(ffi::SSL_set_min_proto_version(
3394 self.as_ptr(),
3395 version.map_or(0, |v| v.0 as _),
3396 ))
3397 .map(|_| ())
3398 }
3399 }
3400
3401 #[corresponds(SSL_set_max_proto_version)]
3406 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3407 unsafe {
3408 cvt(ffi::SSL_set_max_proto_version(
3409 self.as_ptr(),
3410 version.map_or(0, |v| v.0 as _),
3411 ))
3412 .map(|_| ())
3413 }
3414 }
3415
3416 #[corresponds(SSL_set_ciphersuites)]
3425 #[cfg(any(ossl111, libressl))]
3426 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3427 let cipher_list = CString::new(cipher_list).unwrap();
3428 unsafe {
3429 cvt(ffi::SSL_set_ciphersuites(
3430 self.as_ptr(),
3431 cipher_list.as_ptr() as *const _,
3432 ))
3433 .map(|_| ())
3434 }
3435 }
3436
3437 #[corresponds(SSL_set_cipher_list)]
3445 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3446 let cipher_list = CString::new(cipher_list).unwrap();
3447 unsafe {
3448 cvt(ffi::SSL_set_cipher_list(
3449 self.as_ptr(),
3450 cipher_list.as_ptr() as *const _,
3451 ))
3452 .map(|_| ())
3453 }
3454 }
3455
3456 #[corresponds(SSL_set_cert_store)]
3458 #[cfg(ossl110)]
3459 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3460 unsafe {
3461 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
3462 mem::forget(cert_store);
3463 Ok(())
3464 }
3465 }
3466
3467 #[corresponds(SSL_set_num_tickets)]
3472 #[cfg(ossl111)]
3473 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
3474 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
3475 }
3476
3477 #[corresponds(SSL_get_num_tickets)]
3482 #[cfg(ossl111)]
3483 pub fn num_tickets(&self) -> usize {
3484 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
3485 }
3486
3487 #[corresponds(SSL_set_security_level)]
3492 #[cfg(any(ossl110, libressl360))]
3493 pub fn set_security_level(&mut self, level: u32) {
3494 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
3495 }
3496
3497 #[corresponds(SSL_get_security_level)]
3502 #[cfg(any(ossl110, libressl360))]
3503 pub fn security_level(&self) -> u32 {
3504 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
3505 }
3506
3507 #[corresponds(SSL_get_peer_tmp_key)]
3512 #[cfg(ossl300)]
3513 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
3514 unsafe {
3515 let mut key = ptr::null_mut();
3516 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
3517 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
3518 Err(e) => Err(e),
3519 }
3520 }
3521 }
3522
3523 #[corresponds(SSL_get_tmp_key)]
3528 #[cfg(ossl300)]
3529 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
3530 unsafe {
3531 let mut key = ptr::null_mut();
3532 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
3533 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
3534 Err(e) => Err(e),
3535 }
3536 }
3537 }
3538}
3539
3540#[derive(Debug)]
3542pub struct MidHandshakeSslStream<S> {
3543 stream: SslStream<S>,
3544 error: Error,
3545}
3546
3547impl<S> MidHandshakeSslStream<S> {
3548 pub fn get_ref(&self) -> &S {
3550 self.stream.get_ref()
3551 }
3552
3553 pub fn get_mut(&mut self) -> &mut S {
3555 self.stream.get_mut()
3556 }
3557
3558 pub fn ssl(&self) -> &SslRef {
3560 self.stream.ssl()
3561 }
3562
3563 pub fn error(&self) -> &Error {
3565 &self.error
3566 }
3567
3568 pub fn into_error(self) -> Error {
3570 self.error
3571 }
3572}
3573
3574impl<S> MidHandshakeSslStream<S>
3575where
3576 S: Read + Write,
3577{
3578 #[corresponds(SSL_do_handshake)]
3581 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3582 match self.stream.do_handshake() {
3583 Ok(()) => Ok(self.stream),
3584 Err(error) => {
3585 self.error = error;
3586 match self.error.code() {
3587 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3588 Err(HandshakeError::WouldBlock(self))
3589 }
3590 _ => Err(HandshakeError::Failure(self)),
3591 }
3592 }
3593 }
3594 }
3595}
3596
3597pub struct SslStream<S> {
3599 ssl: ManuallyDrop<Ssl>,
3600 method: ManuallyDrop<BioMethod>,
3601 _p: PhantomData<S>,
3602}
3603
3604impl<S> Drop for SslStream<S> {
3605 fn drop(&mut self) {
3606 unsafe {
3608 ManuallyDrop::drop(&mut self.ssl);
3609 ManuallyDrop::drop(&mut self.method);
3610 }
3611 }
3612}
3613
3614impl<S> fmt::Debug for SslStream<S>
3615where
3616 S: fmt::Debug,
3617{
3618 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3619 fmt.debug_struct("SslStream")
3620 .field("stream", &self.get_ref())
3621 .field("ssl", &self.ssl())
3622 .finish()
3623 }
3624}
3625
3626impl<S: Read + Write> SslStream<S> {
3627 #[corresponds(SSL_set_bio)]
3635 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3636 let (bio, method) = bio::new(stream)?;
3637 unsafe {
3638 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3639 }
3640
3641 Ok(SslStream {
3642 ssl: ManuallyDrop::new(ssl),
3643 method: ManuallyDrop::new(method),
3644 _p: PhantomData,
3645 })
3646 }
3647
3648 #[deprecated(
3656 since = "0.10.32",
3657 note = "use Ssl::from_ptr and SslStream::new instead"
3658 )]
3659 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3660 let ssl = Ssl::from_ptr(ssl);
3661 Self::new(ssl, stream).unwrap()
3662 }
3663
3664 #[corresponds(SSL_read_early_data)]
3673 #[cfg(any(ossl111, libressl))]
3674 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3675 let mut read = 0;
3676 let ret = unsafe {
3677 ffi::SSL_read_early_data(
3678 self.ssl.as_ptr(),
3679 buf.as_ptr() as *mut c_void,
3680 buf.len(),
3681 &mut read,
3682 )
3683 };
3684 match ret {
3685 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
3686 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
3687 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
3688 _ => unreachable!(),
3689 }
3690 }
3691
3692 #[corresponds(SSL_write_early_data)]
3699 #[cfg(any(ossl111, libressl))]
3700 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
3701 let mut written = 0;
3702 let ret = unsafe {
3703 ffi::SSL_write_early_data(
3704 self.ssl.as_ptr(),
3705 buf.as_ptr() as *const c_void,
3706 buf.len(),
3707 &mut written,
3708 )
3709 };
3710 if ret > 0 {
3711 Ok(written)
3712 } else {
3713 Err(self.make_error(ret))
3714 }
3715 }
3716
3717 #[corresponds(SSL_connect)]
3724 pub fn connect(&mut self) -> Result<(), Error> {
3725 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
3726 if ret > 0 {
3727 Ok(())
3728 } else {
3729 Err(self.make_error(ret))
3730 }
3731 }
3732
3733 #[corresponds(SSL_accept)]
3740 pub fn accept(&mut self) -> Result<(), Error> {
3741 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
3742 if ret > 0 {
3743 Ok(())
3744 } else {
3745 Err(self.make_error(ret))
3746 }
3747 }
3748
3749 #[corresponds(SSL_do_handshake)]
3753 pub fn do_handshake(&mut self) -> Result<(), Error> {
3754 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
3755 if ret > 0 {
3756 Ok(())
3757 } else {
3758 Err(self.make_error(ret))
3759 }
3760 }
3761
3762 #[corresponds(SSL_stateless)]
3773 #[cfg(ossl111)]
3774 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
3775 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
3776 1 => Ok(true),
3777 0 => Ok(false),
3778 -1 => Err(ErrorStack::get()),
3779 _ => unreachable!(),
3780 }
3781 }
3782
3783 #[corresponds(SSL_read_ex)]
3790 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3791 loop {
3792 match self.ssl_read_uninit(buf) {
3793 Ok(n) => return Ok(n),
3794 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3795 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3796 return Ok(0);
3797 }
3798 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3799 Err(e) => {
3800 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
3801 }
3802 }
3803 }
3804 }
3805
3806 #[corresponds(SSL_read_ex)]
3811 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3812 unsafe {
3814 self.ssl_read_uninit(util::from_raw_parts_mut(
3815 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3816 buf.len(),
3817 ))
3818 }
3819 }
3820
3821 #[corresponds(SSL_read_ex)]
3828 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3829 if buf.is_empty() {
3830 return Ok(0);
3831 }
3832
3833 cfg_if! {
3834 if #[cfg(any(ossl111, libressl))] {
3835 let mut readbytes = 0;
3836 let ret = unsafe {
3837 ffi::SSL_read_ex(
3838 self.ssl().as_ptr(),
3839 buf.as_mut_ptr().cast(),
3840 buf.len(),
3841 &mut readbytes,
3842 )
3843 };
3844
3845 if ret > 0 {
3846 Ok(readbytes)
3847 } else {
3848 Err(self.make_error(ret))
3849 }
3850 } else {
3851 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3852 let ret = unsafe {
3853 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3854 };
3855 if ret > 0 {
3856 Ok(ret as usize)
3857 } else {
3858 Err(self.make_error(ret))
3859 }
3860 }
3861 }
3862 }
3863
3864 #[corresponds(SSL_write_ex)]
3869 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3870 if buf.is_empty() {
3871 return Ok(0);
3872 }
3873
3874 cfg_if! {
3875 if #[cfg(any(ossl111, libressl))] {
3876 let mut written = 0;
3877 let ret = unsafe {
3878 ffi::SSL_write_ex(
3879 self.ssl().as_ptr(),
3880 buf.as_ptr().cast(),
3881 buf.len(),
3882 &mut written,
3883 )
3884 };
3885
3886 if ret > 0 {
3887 Ok(written)
3888 } else {
3889 Err(self.make_error(ret))
3890 }
3891 } else {
3892 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3893 let ret = unsafe {
3894 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
3895 };
3896 if ret > 0 {
3897 Ok(ret as usize)
3898 } else {
3899 Err(self.make_error(ret))
3900 }
3901 }
3902 }
3903 }
3904
3905 #[corresponds(SSL_peek_ex)]
3907 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3908 cfg_if! {
3909 if #[cfg(any(ossl111, libressl))] {
3910 let mut readbytes = 0;
3911 let ret = unsafe {
3912 ffi::SSL_peek_ex(
3913 self.ssl().as_ptr(),
3914 buf.as_mut_ptr().cast(),
3915 buf.len(),
3916 &mut readbytes,
3917 )
3918 };
3919
3920 if ret > 0 {
3921 Ok(readbytes)
3922 } else {
3923 Err(self.make_error(ret))
3924 }
3925 } else {
3926 if buf.is_empty() {
3927 return Ok(0);
3928 }
3929
3930 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3931 let ret = unsafe {
3932 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3933 };
3934 if ret > 0 {
3935 Ok(ret as usize)
3936 } else {
3937 Err(self.make_error(ret))
3938 }
3939 }
3940 }
3941 }
3942
3943 #[corresponds(SSL_shutdown)]
3953 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
3954 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
3955 0 => Ok(ShutdownResult::Sent),
3956 1 => Ok(ShutdownResult::Received),
3957 n => Err(self.make_error(n)),
3958 }
3959 }
3960
3961 #[corresponds(SSL_get_shutdown)]
3963 pub fn get_shutdown(&mut self) -> ShutdownState {
3964 unsafe {
3965 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
3966 ShutdownState::from_bits_retain(bits)
3967 }
3968 }
3969
3970 #[corresponds(SSL_set_shutdown)]
3975 pub fn set_shutdown(&mut self, state: ShutdownState) {
3976 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
3977 }
3978}
3979
3980impl<S> SslStream<S> {
3981 fn make_error(&mut self, ret: c_int) -> Error {
3982 self.check_panic();
3983
3984 let code = self.ssl.get_error(ret);
3985
3986 let cause = match code {
3987 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
3988 ErrorCode::SYSCALL => {
3989 let errs = ErrorStack::get();
3990 if errs.errors().is_empty() {
3991 self.get_bio_error().map(InnerError::Io)
3992 } else {
3993 Some(InnerError::Ssl(errs))
3994 }
3995 }
3996 ErrorCode::ZERO_RETURN => None,
3997 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3998 self.get_bio_error().map(InnerError::Io)
3999 }
4000 _ => None,
4001 };
4002
4003 Error { code, cause }
4004 }
4005
4006 fn check_panic(&mut self) {
4007 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4008 resume_unwind(err)
4009 }
4010 }
4011
4012 fn get_bio_error(&mut self) -> Option<io::Error> {
4013 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4014 }
4015
4016 pub fn get_ref(&self) -> &S {
4018 unsafe {
4019 let bio = self.ssl.get_raw_rbio();
4020 bio::get_ref(bio)
4021 }
4022 }
4023
4024 pub fn get_mut(&mut self) -> &mut S {
4031 unsafe {
4032 let bio = self.ssl.get_raw_rbio();
4033 bio::get_mut(bio)
4034 }
4035 }
4036
4037 pub fn ssl(&self) -> &SslRef {
4039 &self.ssl
4040 }
4041}
4042
4043impl<S: Read + Write> Read for SslStream<S> {
4044 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4045 unsafe {
4047 self.read_uninit(util::from_raw_parts_mut(
4048 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4049 buf.len(),
4050 ))
4051 }
4052 }
4053}
4054
4055impl<S: Read + Write> Write for SslStream<S> {
4056 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4057 loop {
4058 match self.ssl_write(buf) {
4059 Ok(n) => return Ok(n),
4060 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4061 Err(e) => {
4062 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4063 }
4064 }
4065 }
4066 }
4067
4068 fn flush(&mut self) -> io::Result<()> {
4069 self.get_mut().flush()
4070 }
4071}
4072
4073#[deprecated(
4075 since = "0.10.32",
4076 note = "use the methods directly on Ssl/SslStream instead"
4077)]
4078pub struct SslStreamBuilder<S> {
4079 inner: SslStream<S>,
4080}
4081
4082#[allow(deprecated)]
4083impl<S> SslStreamBuilder<S>
4084where
4085 S: Read + Write,
4086{
4087 pub fn new(ssl: Ssl, stream: S) -> Self {
4089 Self {
4090 inner: SslStream::new(ssl, stream).unwrap(),
4091 }
4092 }
4093
4094 #[corresponds(SSL_stateless)]
4105 #[cfg(ossl111)]
4106 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4107 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4108 1 => Ok(true),
4109 0 => Ok(false),
4110 -1 => Err(ErrorStack::get()),
4111 _ => unreachable!(),
4112 }
4113 }
4114
4115 #[corresponds(SSL_set_connect_state)]
4117 pub fn set_connect_state(&mut self) {
4118 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4119 }
4120
4121 #[corresponds(SSL_set_accept_state)]
4123 pub fn set_accept_state(&mut self) {
4124 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4125 }
4126
4127 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4129 match self.inner.connect() {
4130 Ok(()) => Ok(self.inner),
4131 Err(error) => match error.code() {
4132 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4133 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4134 stream: self.inner,
4135 error,
4136 }))
4137 }
4138 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4139 stream: self.inner,
4140 error,
4141 })),
4142 },
4143 }
4144 }
4145
4146 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4148 match self.inner.accept() {
4149 Ok(()) => Ok(self.inner),
4150 Err(error) => match error.code() {
4151 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4152 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4153 stream: self.inner,
4154 error,
4155 }))
4156 }
4157 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4158 stream: self.inner,
4159 error,
4160 })),
4161 },
4162 }
4163 }
4164
4165 #[corresponds(SSL_do_handshake)]
4169 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4170 match self.inner.do_handshake() {
4171 Ok(()) => Ok(self.inner),
4172 Err(error) => match error.code() {
4173 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4174 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4175 stream: self.inner,
4176 error,
4177 }))
4178 }
4179 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4180 stream: self.inner,
4181 error,
4182 })),
4183 },
4184 }
4185 }
4186
4187 #[corresponds(SSL_read_early_data)]
4197 #[cfg(any(ossl111, libressl))]
4198 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4199 self.inner.read_early_data(buf)
4200 }
4201
4202 #[corresponds(SSL_write_early_data)]
4209 #[cfg(any(ossl111, libressl))]
4210 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4211 self.inner.write_early_data(buf)
4212 }
4213}
4214
4215#[allow(deprecated)]
4216impl<S> SslStreamBuilder<S> {
4217 pub fn get_ref(&self) -> &S {
4219 unsafe {
4220 let bio = self.inner.ssl.get_raw_rbio();
4221 bio::get_ref(bio)
4222 }
4223 }
4224
4225 pub fn get_mut(&mut self) -> &mut S {
4232 unsafe {
4233 let bio = self.inner.ssl.get_raw_rbio();
4234 bio::get_mut(bio)
4235 }
4236 }
4237
4238 pub fn ssl(&self) -> &SslRef {
4240 &self.inner.ssl
4241 }
4242
4243 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4251 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4252 unsafe {
4253 let bio = self.inner.ssl.get_raw_rbio();
4254 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4255 }
4256 }
4257}
4258
4259#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4261pub enum ShutdownResult {
4262 Sent,
4264
4265 Received,
4267}
4268
4269bitflags! {
4270 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4272 #[repr(transparent)]
4273 pub struct ShutdownState: c_int {
4274 const SENT = ffi::SSL_SENT_SHUTDOWN;
4276 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4278 }
4279}
4280
4281use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4282cfg_if! {
4283 if #[cfg(ossl300)] {
4284 use ffi::SSL_get1_peer_certificate;
4285 } else {
4286 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4287 }
4288}
4289use ffi::{
4290 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4291 TLS_server_method,
4292};
4293cfg_if! {
4294 if #[cfg(ossl110)] {
4295 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4296 ffi::CRYPTO_get_ex_new_index(
4297 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4298 0,
4299 ptr::null_mut(),
4300 None,
4301 None,
4302 Some(f),
4303 )
4304 }
4305
4306 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4307 ffi::CRYPTO_get_ex_new_index(
4308 ffi::CRYPTO_EX_INDEX_SSL,
4309 0,
4310 ptr::null_mut(),
4311 None,
4312 None,
4313 Some(f),
4314 )
4315 }
4316 } else {
4317 use std::sync::Once;
4318
4319 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4320 static ONCE: Once = Once::new();
4322 ONCE.call_once(|| {
4323 cfg_if! {
4324 if #[cfg(not(any(boringssl, awslc)))] {
4325 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4326 } else {
4327 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4328 }
4329 }
4330 });
4331
4332 cfg_if! {
4333 if #[cfg(not(any(boringssl, awslc)))] {
4334 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
4335 } else {
4336 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4337 }
4338 }
4339 }
4340
4341 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4342 static ONCE: Once = Once::new();
4344 ONCE.call_once(|| {
4345 #[cfg(not(any(boringssl, awslc)))]
4346 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4347 #[cfg(any(boringssl, awslc))]
4348 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4349 });
4350
4351 #[cfg(not(any(boringssl, awslc)))]
4352 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
4353 #[cfg(any(boringssl, awslc))]
4354 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
4355 }
4356 }
4357}
4358
4359#[cfg(test)]
4360mod alert_tests {
4361 use super::SslAlert;
4362
4363 #[test]
4364 fn reason_code_is_description_plus_offset() {
4365 assert_eq!(SslAlert::CLOSE_NOTIFY.reason_code(), 1000);
4366 assert_eq!(SslAlert::DECODE_ERROR.reason_code(), 1050);
4367 assert_eq!(SslAlert(109).reason_code(), 1109);
4368 }
4369
4370 #[test]
4371 fn from_reason_code_maps_alerts() {
4372 assert_eq!(
4373 SslAlert::from_reason_code(1000),
4374 Some(SslAlert::CLOSE_NOTIFY)
4375 );
4376 assert_eq!(
4377 SslAlert::from_reason_code(1050),
4378 Some(SslAlert::DECODE_ERROR)
4379 );
4380 assert_eq!(SslAlert::from_reason_code(1109), Some(SslAlert(109)));
4383 }
4384
4385 #[test]
4386 fn from_reason_code_rejects_non_alert_codes() {
4387 assert_eq!(SslAlert::from_reason_code(0), None);
4389 assert_eq!(SslAlert::from_reason_code(267), None);
4390 assert_eq!(SslAlert::from_reason_code(999), None);
4391 assert_eq!(SslAlert::from_reason_code(1256), None);
4393 }
4394
4395 #[test]
4396 fn display_uses_long_description() {
4397 assert_eq!(SslAlert::CLOSE_NOTIFY.to_string(), "close notify");
4398 assert_eq!(SslAlert::HANDSHAKE_FAILURE.to_string(), "handshake failure");
4399 assert_eq!(SslAlert::DECODE_ERROR.to_string(), "decode error");
4400 assert_eq!(SslAlert(255).to_string(), "unknown");
4402 }
4403
4404 #[test]
4405 fn reason_code_round_trips() {
4406 let alerts = [
4407 SslAlert::CLOSE_NOTIFY,
4408 SslAlert::HANDSHAKE_FAILURE,
4409 SslAlert::ILLEGAL_PARAMETER,
4410 SslAlert::DECODE_ERROR,
4411 SslAlert::UNRECOGNIZED_NAME,
4412 SslAlert(109),
4413 SslAlert(116),
4414 SslAlert::NO_APPLICATION_PROTOCOL,
4415 ];
4416 for alert in alerts {
4417 assert_eq!(SslAlert::from_reason_code(alert.reason_code()), Some(alert));
4418 }
4419 }
4420}