1use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
61use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
62use openssl_macros::corresponds;
63use std::any::TypeId;
64use std::collections::HashMap;
65use std::convert::TryInto;
66use std::ffi::{CStr, CString};
67use std::fmt;
68use std::io;
69use std::io::prelude::*;
70use std::marker::PhantomData;
71use std::mem::{self, ManuallyDrop, MaybeUninit};
72use std::ops::{Deref, DerefMut};
73use std::panic::resume_unwind;
74use std::path::Path;
75use std::ptr::{self, NonNull};
76use std::slice;
77use std::str;
78use std::sync::{Arc, LazyLock, Mutex};
79
80use crate::dh::DhRef;
81use crate::ec::EcKeyRef;
82use crate::error::ErrorStack;
83use crate::ex_data::Index;
84use crate::ffi;
85use crate::nid::Nid;
86use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
87use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
88use crate::ssl::bio::BioMethod;
89use crate::ssl::callbacks::*;
90use crate::ssl::error::InnerError;
91use crate::stack::{Stack, StackRef, Stackable};
92use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
93use crate::x509::verify::X509VerifyParamRef;
94use crate::x509::{
95 X509Name, X509Ref, X509StoreContextRef, X509VerifyError, X509VerifyResult, X509,
96};
97use crate::{cvt, cvt_0i, cvt_n, cvt_p, init};
98
99pub use self::async_callbacks::{
100 AsyncPrivateKeyMethod, AsyncPrivateKeyMethodError, AsyncSelectCertError, BoxCustomVerifyFinish,
101 BoxCustomVerifyFuture, BoxGetSessionFinish, BoxGetSessionFuture, BoxPrivateKeyMethodFinish,
102 BoxPrivateKeyMethodFuture, BoxSelectCertFinish, BoxSelectCertFuture, ExDataFuture,
103};
104pub use self::connector::{
105 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
106};
107#[cfg(not(feature = "fips"))]
108pub use self::ech::{SslEchKeys, SslEchKeysRef};
109pub use self::error::{Error, ErrorCode, HandshakeError};
110
111mod async_callbacks;
112mod bio;
113mod callbacks;
114mod connector;
115#[cfg(not(feature = "fips"))]
116mod ech;
117mod error;
118mod mut_only;
119#[cfg(test)]
120mod test;
121
122bitflags! {
123 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
125 pub struct SslOptions: c_uint {
126 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as _;
128
129 const ALL = ffi::SSL_OP_ALL as _;
131
132 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as _;
136
137 const NO_TICKET = ffi::SSL_OP_NO_TICKET as _;
139
140 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
142 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as _;
143
144 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as _;
146
147 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
150 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as _;
151
152 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as _;
154
155 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as _;
157
158 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as _;
162
163 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as _;
165
166 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as _;
168
169 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as _;
171
172 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as _;
174
175 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as _;
177
178 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as _;
180
181 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as _;
183
184 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as _;
186
187 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as _;
189
190 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as _;
192 }
193}
194
195bitflags! {
196 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
198 pub struct SslMode: c_uint {
199 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE as _;
205
206 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as _;
209
210 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY as _;
220
221 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN as _;
227
228 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS as _;
232
233 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV as _;
241 }
242}
243
244#[derive(Copy, Clone)]
246pub struct SslMethod(*const ffi::SSL_METHOD);
247
248impl SslMethod {
249 #[corresponds(TLS_method)]
251 pub fn tls() -> SslMethod {
252 unsafe { SslMethod(TLS_method()) }
253 }
254
255 #[cfg(feature = "rpk")]
257 pub fn tls_with_buffer() -> SslMethod {
258 unsafe { SslMethod(ffi::TLS_with_buffers_method()) }
259 }
260
261 #[corresponds(DTLS_method)]
263 pub fn dtls() -> SslMethod {
264 unsafe { SslMethod(DTLS_method()) }
265 }
266
267 #[corresponds(TLS_client_method)]
269 pub fn tls_client() -> SslMethod {
270 unsafe { SslMethod(TLS_client_method()) }
271 }
272
273 #[corresponds(TLS_server_method)]
275 pub fn tls_server() -> SslMethod {
276 unsafe { SslMethod(TLS_server_method()) }
277 }
278
279 #[corresponds(TLS_server_method)]
285 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
286 SslMethod(ptr)
287 }
288
289 #[allow(clippy::trivially_copy_pass_by_ref)]
291 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
292 self.0
293 }
294}
295
296unsafe impl Sync for SslMethod {}
297unsafe impl Send for SslMethod {}
298
299bitflags! {
300 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
302 pub struct SslVerifyMode: i32 {
303 const PEER = ffi::SSL_VERIFY_PEER;
307
308 const NONE = ffi::SSL_VERIFY_NONE;
314
315 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
319 }
320}
321
322#[derive(Clone, Copy, Debug, Eq, PartialEq)]
323pub enum SslVerifyError {
324 Invalid(SslAlert),
325 Retry,
326}
327
328bitflags! {
329 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
331 pub struct SslSessionCacheMode: c_int {
332 const OFF = ffi::SSL_SESS_CACHE_OFF;
334
335 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
342
343 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
347
348 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
350
351 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
353
354 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
356
357 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
359
360 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
362 }
363}
364
365#[derive(Copy, Clone)]
367pub struct SslFiletype(c_int);
368
369impl SslFiletype {
370 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
374
375 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
379
380 pub fn from_raw(raw: c_int) -> SslFiletype {
382 SslFiletype(raw)
383 }
384
385 #[allow(clippy::trivially_copy_pass_by_ref)]
387 pub fn as_raw(&self) -> c_int {
388 self.0
389 }
390}
391
392#[derive(Copy, Clone)]
394pub struct StatusType(c_int);
395
396impl StatusType {
397 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
399
400 pub fn from_raw(raw: c_int) -> StatusType {
402 StatusType(raw)
403 }
404
405 #[allow(clippy::trivially_copy_pass_by_ref)]
407 pub fn as_raw(&self) -> c_int {
408 self.0
409 }
410}
411
412#[derive(Copy, Clone)]
414pub struct NameType(c_int);
415
416impl NameType {
417 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
419
420 pub fn from_raw(raw: c_int) -> StatusType {
422 StatusType(raw)
423 }
424
425 #[allow(clippy::trivially_copy_pass_by_ref)]
427 pub fn as_raw(&self) -> c_int {
428 self.0
429 }
430}
431
432static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
433 LazyLock::new(|| Mutex::new(HashMap::new()));
434static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
435 LazyLock::new(|| Mutex::new(HashMap::new()));
436static SESSION_CTX_INDEX: LazyLock<Index<Ssl, SslContext>> =
437 LazyLock::new(|| Ssl::new_ex_index().unwrap());
438#[cfg(feature = "rpk")]
439static RPK_FLAG_INDEX: LazyLock<Index<SslContext, bool>> =
440 LazyLock::new(|| SslContext::new_ex_index().unwrap());
441
442unsafe extern "C" fn free_data_box<T>(
443 _parent: *mut c_void,
444 ptr: *mut c_void,
445 _ad: *mut ffi::CRYPTO_EX_DATA,
446 _idx: c_int,
447 _argl: c_long,
448 _argp: *mut c_void,
449) {
450 if !ptr.is_null() {
451 drop(Box::<T>::from_raw(ptr as *mut T));
452 }
453}
454
455#[derive(Debug, Copy, Clone, PartialEq, Eq)]
457pub struct SniError(c_int);
458
459impl SniError {
460 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
462
463 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
465
466 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
467}
468
469#[derive(Debug, Copy, Clone, PartialEq, Eq)]
471pub struct SslAlert(c_int);
472
473impl SslAlert {
474 pub const CLOSE_NOTIFY: Self = Self(ffi::SSL_AD_CLOSE_NOTIFY);
475 pub const UNEXPECTED_MESSAGE: Self = Self(ffi::SSL_AD_UNEXPECTED_MESSAGE);
476 pub const BAD_RECORD_MAC: Self = Self(ffi::SSL_AD_BAD_RECORD_MAC);
477 pub const DECRYPTION_FAILED: Self = Self(ffi::SSL_AD_DECRYPTION_FAILED);
478 pub const RECORD_OVERFLOW: Self = Self(ffi::SSL_AD_RECORD_OVERFLOW);
479 pub const DECOMPRESSION_FAILURE: Self = Self(ffi::SSL_AD_DECOMPRESSION_FAILURE);
480 pub const HANDSHAKE_FAILURE: Self = Self(ffi::SSL_AD_HANDSHAKE_FAILURE);
481 pub const NO_CERTIFICATE: Self = Self(ffi::SSL_AD_NO_CERTIFICATE);
482 pub const BAD_CERTIFICATE: Self = Self(ffi::SSL_AD_BAD_CERTIFICATE);
483 pub const UNSUPPORTED_CERTIFICATE: Self = Self(ffi::SSL_AD_UNSUPPORTED_CERTIFICATE);
484 pub const CERTIFICATE_REVOKED: Self = Self(ffi::SSL_AD_CERTIFICATE_REVOKED);
485 pub const CERTIFICATE_EXPIRED: Self = Self(ffi::SSL_AD_CERTIFICATE_EXPIRED);
486 pub const CERTIFICATE_UNKNOWN: Self = Self(ffi::SSL_AD_CERTIFICATE_UNKNOWN);
487 pub const ILLEGAL_PARAMETER: Self = Self(ffi::SSL_AD_ILLEGAL_PARAMETER);
488 pub const UNKNOWN_CA: Self = Self(ffi::SSL_AD_UNKNOWN_CA);
489 pub const ACCESS_DENIED: Self = Self(ffi::SSL_AD_ACCESS_DENIED);
490 pub const DECODE_ERROR: Self = Self(ffi::SSL_AD_DECODE_ERROR);
491 pub const DECRYPT_ERROR: Self = Self(ffi::SSL_AD_DECRYPT_ERROR);
492 pub const EXPORT_RESTRICTION: Self = Self(ffi::SSL_AD_EXPORT_RESTRICTION);
493 pub const PROTOCOL_VERSION: Self = Self(ffi::SSL_AD_PROTOCOL_VERSION);
494 pub const INSUFFICIENT_SECURITY: Self = Self(ffi::SSL_AD_INSUFFICIENT_SECURITY);
495 pub const INTERNAL_ERROR: Self = Self(ffi::SSL_AD_INTERNAL_ERROR);
496 pub const INAPPROPRIATE_FALLBACK: Self = Self(ffi::SSL_AD_INAPPROPRIATE_FALLBACK);
497 pub const USER_CANCELLED: Self = Self(ffi::SSL_AD_USER_CANCELLED);
498 pub const NO_RENEGOTIATION: Self = Self(ffi::SSL_AD_NO_RENEGOTIATION);
499 pub const MISSING_EXTENSION: Self = Self(ffi::SSL_AD_MISSING_EXTENSION);
500 pub const UNSUPPORTED_EXTENSION: Self = Self(ffi::SSL_AD_UNSUPPORTED_EXTENSION);
501 pub const CERTIFICATE_UNOBTAINABLE: Self = Self(ffi::SSL_AD_CERTIFICATE_UNOBTAINABLE);
502 pub const UNRECOGNIZED_NAME: Self = Self(ffi::SSL_AD_UNRECOGNIZED_NAME);
503 pub const BAD_CERTIFICATE_STATUS_RESPONSE: Self =
504 Self(ffi::SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
505 pub const BAD_CERTIFICATE_HASH_VALUE: Self = Self(ffi::SSL_AD_BAD_CERTIFICATE_HASH_VALUE);
506 pub const UNKNOWN_PSK_IDENTITY: Self = Self(ffi::SSL_AD_UNKNOWN_PSK_IDENTITY);
507 pub const CERTIFICATE_REQUIRED: Self = Self(ffi::SSL_AD_CERTIFICATE_REQUIRED);
508 pub const NO_APPLICATION_PROTOCOL: Self = Self(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
509}
510
511#[derive(Debug, Copy, Clone, PartialEq, Eq)]
513pub struct AlpnError(c_int);
514
515impl AlpnError {
516 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
518
519 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
521}
522
523#[derive(Debug, Copy, Clone, PartialEq, Eq)]
525pub struct SelectCertError(ffi::ssl_select_cert_result_t);
526
527impl SelectCertError {
528 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_error);
530
531 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_retry);
533}
534
535#[derive(Debug, Copy, Clone, PartialEq, Eq)]
541pub struct ExtensionType(u16);
542
543impl ExtensionType {
544 pub const SERVER_NAME: Self = Self(ffi::TLSEXT_TYPE_server_name as u16);
545 pub const STATUS_REQUEST: Self = Self(ffi::TLSEXT_TYPE_status_request as u16);
546 pub const EC_POINT_FORMATS: Self = Self(ffi::TLSEXT_TYPE_ec_point_formats as u16);
547 pub const SIGNATURE_ALGORITHMS: Self = Self(ffi::TLSEXT_TYPE_signature_algorithms as u16);
548 pub const SRTP: Self = Self(ffi::TLSEXT_TYPE_srtp as u16);
549 pub const APPLICATION_LAYER_PROTOCOL_NEGOTIATION: Self =
550 Self(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as u16);
551 pub const PADDING: Self = Self(ffi::TLSEXT_TYPE_padding as u16);
552 pub const EXTENDED_MASTER_SECRET: Self = Self(ffi::TLSEXT_TYPE_extended_master_secret as u16);
553 pub const QUIC_TRANSPORT_PARAMETERS_LEGACY: Self =
554 Self(ffi::TLSEXT_TYPE_quic_transport_parameters_legacy as u16);
555 pub const QUIC_TRANSPORT_PARAMETERS_STANDARD: Self =
556 Self(ffi::TLSEXT_TYPE_quic_transport_parameters_standard as u16);
557 pub const CERT_COMPRESSION: Self = Self(ffi::TLSEXT_TYPE_cert_compression as u16);
558 pub const SESSION_TICKET: Self = Self(ffi::TLSEXT_TYPE_session_ticket as u16);
559 pub const SUPPORTED_GROUPS: Self = Self(ffi::TLSEXT_TYPE_supported_groups as u16);
560 pub const PRE_SHARED_KEY: Self = Self(ffi::TLSEXT_TYPE_pre_shared_key as u16);
561 pub const EARLY_DATA: Self = Self(ffi::TLSEXT_TYPE_early_data as u16);
562 pub const SUPPORTED_VERSIONS: Self = Self(ffi::TLSEXT_TYPE_supported_versions as u16);
563 pub const COOKIE: Self = Self(ffi::TLSEXT_TYPE_cookie as u16);
564 pub const PSK_KEY_EXCHANGE_MODES: Self = Self(ffi::TLSEXT_TYPE_psk_key_exchange_modes as u16);
565 pub const CERTIFICATE_AUTHORITIES: Self = Self(ffi::TLSEXT_TYPE_certificate_authorities as u16);
566 pub const SIGNATURE_ALGORITHMS_CERT: Self =
567 Self(ffi::TLSEXT_TYPE_signature_algorithms_cert as u16);
568 pub const KEY_SHARE: Self = Self(ffi::TLSEXT_TYPE_key_share as u16);
569 pub const RENEGOTIATE: Self = Self(ffi::TLSEXT_TYPE_renegotiate as u16);
570 pub const DELEGATED_CREDENTIAL: Self = Self(ffi::TLSEXT_TYPE_delegated_credential as u16);
571 pub const APPLICATION_SETTINGS: Self = Self(ffi::TLSEXT_TYPE_application_settings as u16);
572 pub const ENCRYPTED_CLIENT_HELLO: Self = Self(ffi::TLSEXT_TYPE_encrypted_client_hello as u16);
573 pub const CERTIFICATE_TIMESTAMP: Self = Self(ffi::TLSEXT_TYPE_certificate_timestamp as u16);
574 pub const NEXT_PROTO_NEG: Self = Self(ffi::TLSEXT_TYPE_next_proto_neg as u16);
575 pub const CHANNEL_ID: Self = Self(ffi::TLSEXT_TYPE_channel_id as u16);
576}
577
578impl From<u16> for ExtensionType {
579 fn from(value: u16) -> Self {
580 Self(value)
581 }
582}
583
584#[derive(Copy, Clone, PartialEq, Eq)]
586pub struct SslVersion(u16);
587
588impl SslVersion {
589 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION as _);
591
592 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION as _);
594
595 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION as _);
597
598 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION as _);
600
601 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION as _);
603}
604
605impl TryFrom<u16> for SslVersion {
606 type Error = &'static str;
607
608 fn try_from(value: u16) -> Result<Self, Self::Error> {
609 match value as i32 {
610 ffi::SSL3_VERSION
611 | ffi::TLS1_VERSION
612 | ffi::TLS1_1_VERSION
613 | ffi::TLS1_2_VERSION
614 | ffi::TLS1_3_VERSION => Ok(Self(value)),
615 _ => Err("Unknown SslVersion"),
616 }
617 }
618}
619
620impl fmt::Debug for SslVersion {
621 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
622 f.write_str(match *self {
623 Self::SSL3 => "SSL3",
624 Self::TLS1 => "TLS1",
625 Self::TLS1_1 => "TLS1_1",
626 Self::TLS1_2 => "TLS1_2",
627 Self::TLS1_3 => "TLS1_3",
628 _ => return write!(f, "{:#06x}", self.0),
629 })
630 }
631}
632
633impl fmt::Display for SslVersion {
634 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
635 f.write_str(match *self {
636 Self::SSL3 => "SSLv3",
637 Self::TLS1 => "TLSv1",
638 Self::TLS1_1 => "TLSv1.1",
639 Self::TLS1_2 => "TLSv1.2",
640 Self::TLS1_3 => "TLSv1.3",
641 _ => return write!(f, "unknown ({:#06x})", self.0),
642 })
643 }
644}
645
646#[repr(transparent)]
652#[derive(Debug, Copy, Clone, PartialEq, Eq)]
653pub struct SslSignatureAlgorithm(u16);
654
655impl SslSignatureAlgorithm {
656 pub const RSA_PKCS1_SHA1: SslSignatureAlgorithm =
657 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA1 as _);
658
659 pub const RSA_PKCS1_SHA256: SslSignatureAlgorithm =
660 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA256 as _);
661
662 pub const RSA_PKCS1_SHA384: SslSignatureAlgorithm =
663 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA384 as _);
664
665 pub const RSA_PKCS1_SHA512: SslSignatureAlgorithm =
666 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA512 as _);
667
668 pub const RSA_PKCS1_MD5_SHA1: SslSignatureAlgorithm =
669 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_MD5_SHA1 as _);
670
671 pub const ECDSA_SHA1: SslSignatureAlgorithm =
672 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SHA1 as _);
673
674 pub const ECDSA_SECP256R1_SHA256: SslSignatureAlgorithm =
675 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP256R1_SHA256 as _);
676
677 pub const ECDSA_SECP384R1_SHA384: SslSignatureAlgorithm =
678 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP384R1_SHA384 as _);
679
680 pub const ECDSA_SECP521R1_SHA512: SslSignatureAlgorithm =
681 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP521R1_SHA512 as _);
682
683 pub const RSA_PSS_RSAE_SHA256: SslSignatureAlgorithm =
684 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA256 as _);
685
686 pub const RSA_PSS_RSAE_SHA384: SslSignatureAlgorithm =
687 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA384 as _);
688
689 pub const RSA_PSS_RSAE_SHA512: SslSignatureAlgorithm =
690 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA512 as _);
691
692 pub const ED25519: SslSignatureAlgorithm = SslSignatureAlgorithm(ffi::SSL_SIGN_ED25519 as _);
693}
694
695impl From<u16> for SslSignatureAlgorithm {
696 fn from(value: u16) -> Self {
697 Self(value)
698 }
699}
700
701#[repr(transparent)]
703#[derive(Debug, Copy, Clone, PartialEq, Eq)]
704pub struct SslCurve(c_int);
705
706impl SslCurve {
707 pub const SECP224R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP224R1 as _);
708
709 pub const SECP256R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP256R1 as _);
710
711 pub const SECP384R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP384R1 as _);
712
713 pub const SECP521R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP521R1 as _);
714
715 pub const X25519: SslCurve = SslCurve(ffi::SSL_CURVE_X25519 as _);
716
717 #[cfg(not(any(feature = "fips", feature = "fips-precompiled")))]
718 pub const X25519_KYBER768_DRAFT00: SslCurve =
719 SslCurve(ffi::SSL_CURVE_X25519_KYBER768_DRAFT00 as _);
720
721 #[cfg(all(
722 not(any(feature = "fips", feature = "fips-precompiled")),
723 feature = "pq-experimental"
724 ))]
725 pub const X25519_KYBER768_DRAFT00_OLD: SslCurve =
726 SslCurve(ffi::SSL_CURVE_X25519_KYBER768_DRAFT00_OLD as _);
727
728 #[cfg(all(
729 not(any(feature = "fips", feature = "fips-precompiled")),
730 feature = "pq-experimental"
731 ))]
732 pub const X25519_KYBER512_DRAFT00: SslCurve =
733 SslCurve(ffi::SSL_CURVE_X25519_KYBER512_DRAFT00 as _);
734
735 #[cfg(all(
736 not(any(feature = "fips", feature = "fips-precompiled")),
737 feature = "pq-experimental"
738 ))]
739 pub const P256_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::SSL_CURVE_P256_KYBER768_DRAFT00 as _);
740
741 #[cfg(all(
742 not(any(feature = "fips", feature = "fips-precompiled")),
743 feature = "pq-experimental"
744 ))]
745 pub const X25519_MLKEM768: SslCurve = SslCurve(ffi::SSL_CURVE_X25519_MLKEM768 as _);
746
747 #[corresponds(SSL_get_curve_name)]
749 pub fn name(&self) -> Option<&'static str> {
750 unsafe {
751 let ptr = ffi::SSL_get_curve_name(self.0 as u16);
752 if ptr.is_null() {
753 return None;
754 }
755
756 CStr::from_ptr(ptr).to_str().ok()
757 }
758 }
759
760 #[allow(dead_code)]
770 fn nid(&self) -> Option<c_int> {
771 match self.0 {
772 ffi::SSL_CURVE_SECP224R1 => Some(ffi::NID_secp224r1),
773 ffi::SSL_CURVE_SECP256R1 => Some(ffi::NID_X9_62_prime256v1),
774 ffi::SSL_CURVE_SECP384R1 => Some(ffi::NID_secp384r1),
775 ffi::SSL_CURVE_SECP521R1 => Some(ffi::NID_secp521r1),
776 ffi::SSL_CURVE_X25519 => Some(ffi::NID_X25519),
777 #[cfg(not(any(feature = "fips", feature = "fips-precompiled")))]
778 ffi::SSL_CURVE_X25519_KYBER768_DRAFT00 => Some(ffi::NID_X25519Kyber768Draft00),
779 #[cfg(all(
780 not(any(feature = "fips", feature = "fips-precompiled")),
781 feature = "pq-experimental"
782 ))]
783 ffi::SSL_CURVE_X25519_KYBER768_DRAFT00_OLD => Some(ffi::NID_X25519Kyber768Draft00Old),
784 #[cfg(all(
785 not(any(feature = "fips", feature = "fips-precompiled")),
786 feature = "pq-experimental"
787 ))]
788 ffi::SSL_CURVE_X25519_KYBER512_DRAFT00 => Some(ffi::NID_X25519Kyber512Draft00),
789 #[cfg(all(
790 not(any(feature = "fips", feature = "fips-precompiled")),
791 feature = "pq-experimental"
792 ))]
793 ffi::SSL_CURVE_P256_KYBER768_DRAFT00 => Some(ffi::NID_P256Kyber768Draft00),
794 #[cfg(all(
795 not(any(feature = "fips", feature = "fips-precompiled")),
796 feature = "pq-experimental"
797 ))]
798 ffi::SSL_CURVE_X25519_MLKEM768 => Some(ffi::NID_X25519MLKEM768),
799 _ => None,
800 }
801 }
802}
803
804#[derive(Debug, Copy, Clone, PartialEq, Eq)]
806#[cfg(not(feature = "fips-compat"))]
807pub struct CompliancePolicy(ffi::ssl_compliance_policy_t);
808
809#[cfg(not(feature = "fips-compat"))]
810impl CompliancePolicy {
811 pub const NONE: Self = Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_none);
813
814 pub const FIPS_202205: Self =
817 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_fips_202205);
818
819 pub const WPA3_192_202304: Self =
822 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_wpa3_192_202304);
823}
824
825#[derive(Debug, Copy, Clone, PartialEq, Eq)]
827pub struct CertificateCompressionAlgorithm(u16);
828
829impl CertificateCompressionAlgorithm {
830 pub const ZLIB: Self = Self(ffi::TLSEXT_cert_compression_zlib as u16);
831
832 pub const BROTLI: Self = Self(ffi::TLSEXT_cert_compression_brotli as u16);
833}
834
835#[corresponds(SSL_select_next_proto)]
846pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
847 if server.is_empty() || client.is_empty() {
848 return None;
849 }
850
851 unsafe {
852 let mut out = ptr::null_mut();
853 let mut outlen = 0;
854 let r = ffi::SSL_select_next_proto(
855 &mut out,
856 &mut outlen,
857 server.as_ptr(),
858 server.len() as c_uint,
859 client.as_ptr(),
860 client.len() as c_uint,
861 );
862
863 if r == ffi::OPENSSL_NPN_NEGOTIATED {
864 Some(slice::from_raw_parts(out as *const u8, outlen as usize))
865 } else {
866 None
867 }
868 }
869}
870
871#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
873pub struct SslInfoCallbackMode(i32);
874
875impl SslInfoCallbackMode {
876 pub const READ_ALERT: Self = Self(ffi::SSL_CB_READ_ALERT);
878
879 pub const WRITE_ALERT: Self = Self(ffi::SSL_CB_WRITE_ALERT);
881
882 pub const HANDSHAKE_START: Self = Self(ffi::SSL_CB_HANDSHAKE_START);
884
885 pub const HANDSHAKE_DONE: Self = Self(ffi::SSL_CB_HANDSHAKE_DONE);
887
888 pub const ACCEPT_LOOP: Self = Self(ffi::SSL_CB_ACCEPT_LOOP);
890
891 pub const ACCEPT_EXIT: Self = Self(ffi::SSL_CB_ACCEPT_EXIT);
893
894 pub const CONNECT_EXIT: Self = Self(ffi::SSL_CB_CONNECT_EXIT);
896}
897
898#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
901pub enum SslInfoCallbackValue {
902 Unit,
906 Alert(SslInfoCallbackAlert),
910}
911
912#[derive(Hash, Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
913pub struct SslInfoCallbackAlert(c_int);
914
915impl SslInfoCallbackAlert {
916 pub fn alert_level(&self) -> Ssl3AlertLevel {
918 let value = self.0 >> 8;
919 Ssl3AlertLevel(value)
920 }
921
922 pub fn alert(&self) -> SslAlert {
924 let value = self.0 & (u8::MAX as i32);
925 SslAlert(value)
926 }
927}
928
929#[derive(Debug, Copy, Clone, PartialEq, Eq)]
930pub struct Ssl3AlertLevel(c_int);
931
932impl Ssl3AlertLevel {
933 pub const WARNING: Ssl3AlertLevel = Self(ffi::SSL3_AL_WARNING);
934 pub const FATAL: Ssl3AlertLevel = Self(ffi::SSL3_AL_FATAL);
935}
936
937#[cfg(feature = "rpk")]
938extern "C" fn rpk_verify_failure_callback(
939 _ssl: *mut ffi::SSL,
940 _out_alert: *mut u8,
941) -> ffi::ssl_verify_result_t {
942 ffi::ssl_verify_result_t::ssl_verify_invalid
944}
945
946pub struct SslContextBuilder {
948 ctx: SslContext,
949 #[cfg(feature = "rpk")]
950 is_rpk: bool,
951}
952
953#[cfg(feature = "rpk")]
954impl SslContextBuilder {
955 #[corresponds(SSL_CTX_new)]
957 pub fn new_rpk() -> Result<SslContextBuilder, ErrorStack> {
958 unsafe {
959 init();
960 let ctx = cvt_p(ffi::SSL_CTX_new(SslMethod::tls_with_buffer().as_ptr()))?;
961
962 Ok(SslContextBuilder::from_ptr(ctx, true))
963 }
964 }
965
966 pub fn set_rpk_certificate(&mut self, cert: &[u8]) -> Result<(), ErrorStack> {
968 unsafe {
969 cvt(ffi::SSL_CTX_set_server_raw_public_key_certificate(
970 self.as_ptr(),
971 cert.as_ptr(),
972 cert.len() as u32,
973 ))
974 .map(|_| ())
975 }
976 }
977
978 pub fn set_null_chain_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
980 where
981 T: HasPrivate,
982 {
983 unsafe {
984 cvt(ffi::SSL_CTX_set_nullchain_and_key(
985 self.as_ptr(),
986 key.as_ptr(),
987 ptr::null_mut(),
988 ))
989 .map(|_| ())
990 }
991 }
992}
993
994impl SslContextBuilder {
995 #[corresponds(SSL_CTX_new)]
997 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
998 unsafe {
999 init();
1000 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
1001
1002 #[cfg(feature = "rpk")]
1003 {
1004 Ok(SslContextBuilder::from_ptr(ctx, false))
1005 }
1006
1007 #[cfg(not(feature = "rpk"))]
1008 {
1009 Ok(SslContextBuilder::from_ptr(ctx))
1010 }
1011 }
1012 }
1013
1014 #[cfg(feature = "rpk")]
1020 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX, is_rpk: bool) -> SslContextBuilder {
1021 let ctx = SslContext::from_ptr(ctx);
1022 let mut builder = SslContextBuilder { ctx, is_rpk };
1023
1024 builder.set_ex_data(*RPK_FLAG_INDEX, is_rpk);
1025
1026 builder
1027 }
1028
1029 #[cfg(not(feature = "rpk"))]
1035 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
1036 SslContextBuilder {
1037 ctx: SslContext::from_ptr(ctx),
1038 }
1039 }
1040
1041 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
1043 self.ctx.as_ptr()
1044 }
1045
1046 #[corresponds(SSL_CTX_set_cert_verify_callback)]
1066 pub fn set_cert_verify_callback<F>(&mut self, callback: F)
1067 where
1068 F: Fn(&mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1069 {
1070 #[cfg(feature = "rpk")]
1071 assert!(!self.is_rpk, "This API is not supported for RPK");
1072
1073 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1080 unsafe {
1081 ffi::SSL_CTX_set_cert_verify_callback(
1082 self.as_ptr(),
1083 Some(raw_cert_verify::<F>),
1084 ptr::null_mut(),
1085 );
1086 }
1087 }
1088
1089 #[corresponds(SSL_CTX_set_verify)]
1091 pub fn set_verify(&mut self, mode: SslVerifyMode) {
1092 #[cfg(feature = "rpk")]
1093 assert!(!self.is_rpk, "This API is not supported for RPK");
1094
1095 unsafe {
1096 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
1097 }
1098 }
1099
1100 #[corresponds(SSL_CTX_set_verify)]
1117 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1118 where
1119 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1120 {
1121 #[cfg(feature = "rpk")]
1122 assert!(!self.is_rpk, "This API is not supported for RPK");
1123
1124 unsafe {
1125 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1126 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
1127 }
1128 }
1129
1130 #[corresponds(SSL_CTX_set_custom_verify)]
1145 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1146 where
1147 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
1148 {
1149 #[cfg(feature = "rpk")]
1150 assert!(!self.is_rpk, "This API is not supported for RPK");
1151
1152 unsafe {
1153 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1154 ffi::SSL_CTX_set_custom_verify(
1155 self.as_ptr(),
1156 mode.bits() as c_int,
1157 Some(raw_custom_verify::<F>),
1158 );
1159 }
1160 }
1161
1162 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
1172 pub fn set_servername_callback<F>(&mut self, callback: F)
1173 where
1174 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
1175 {
1176 unsafe {
1177 let callback_index = SslContext::cached_ex_index::<F>();
1184
1185 self.ctx.replace_ex_data(callback_index, callback);
1186
1187 let arg = self.ctx.ex_data(callback_index).unwrap() as *const F as *mut c_void;
1188
1189 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
1190 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
1191 }
1192 }
1193
1194 #[corresponds(SSL_CTX_set_verify_depth)]
1198 pub fn set_verify_depth(&mut self, depth: u32) {
1199 #[cfg(feature = "rpk")]
1200 assert!(!self.is_rpk, "This API is not supported for RPK");
1201
1202 unsafe {
1203 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
1204 }
1205 }
1206
1207 #[corresponds(SSL_CTX_set0_verify_cert_store)]
1209 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
1210 #[cfg(feature = "rpk")]
1211 assert!(!self.is_rpk, "This API is not supported for RPK");
1212
1213 unsafe {
1214 cvt(
1215 ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int,
1216 )?;
1217
1218 Ok(())
1219 }
1220 }
1221
1222 #[corresponds(SSL_CTX_set_cert_store)]
1224 pub fn set_cert_store(&mut self, cert_store: X509Store) {
1225 #[cfg(feature = "rpk")]
1226 assert!(!self.is_rpk, "This API is not supported for RPK");
1227
1228 unsafe {
1229 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1230 }
1231 }
1232
1233 #[corresponds(SSL_CTX_set_read_ahead)]
1240 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1241 unsafe {
1242 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as c_int);
1243 }
1244 }
1245
1246 #[corresponds(SSL_CTX_set_mode)]
1248 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1249 let bits = unsafe { ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits()) };
1250 SslMode::from_bits_retain(bits)
1251 }
1252
1253 #[corresponds(SSL_CTX_set_tmp_dh)]
1255 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1256 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1257 }
1258
1259 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1261 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1262 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1263 }
1264
1265 #[corresponds(SSL_CTX_set_default_verify_paths)]
1270 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1271 #[cfg(feature = "rpk")]
1272 assert!(!self.is_rpk, "This API is not supported for RPK");
1273
1274 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1275 }
1276
1277 #[corresponds(SSL_CTX_load_verify_locations)]
1281 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1282 #[cfg(feature = "rpk")]
1283 assert!(!self.is_rpk, "This API is not supported for RPK");
1284
1285 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1286 unsafe {
1287 cvt(ffi::SSL_CTX_load_verify_locations(
1288 self.as_ptr(),
1289 file.as_ptr() as *const _,
1290 ptr::null(),
1291 ))
1292 .map(|_| ())
1293 }
1294 }
1295
1296 #[corresponds(SSL_CTX_set_client_CA_list)]
1301 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1302 #[cfg(feature = "rpk")]
1303 assert!(!self.is_rpk, "This API is not supported for RPK");
1304
1305 unsafe {
1306 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1307 mem::forget(list);
1308 }
1309 }
1310
1311 #[corresponds(SSL_CTX_add_client_CA)]
1314 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1315 #[cfg(feature = "rpk")]
1316 assert!(!self.is_rpk, "This API is not supported for RPK");
1317
1318 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1319 }
1320
1321 #[corresponds(SSL_CTX_set_session_id_context)]
1330 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1331 unsafe {
1332 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1333 cvt(ffi::SSL_CTX_set_session_id_context(
1334 self.as_ptr(),
1335 sid_ctx.as_ptr(),
1336 sid_ctx.len(),
1337 ))
1338 .map(|_| ())
1339 }
1340 }
1341
1342 #[corresponds(SSL_CTX_use_certificate_file)]
1348 pub fn set_certificate_file<P: AsRef<Path>>(
1349 &mut self,
1350 file: P,
1351 file_type: SslFiletype,
1352 ) -> Result<(), ErrorStack> {
1353 #[cfg(feature = "rpk")]
1354 assert!(!self.is_rpk, "This API is not supported for RPK");
1355
1356 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1357 unsafe {
1358 cvt(ffi::SSL_CTX_use_certificate_file(
1359 self.as_ptr(),
1360 file.as_ptr() as *const _,
1361 file_type.as_raw(),
1362 ))
1363 .map(|_| ())
1364 }
1365 }
1366
1367 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1373 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1374 &mut self,
1375 file: P,
1376 ) -> Result<(), ErrorStack> {
1377 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1378 unsafe {
1379 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1380 self.as_ptr(),
1381 file.as_ptr() as *const _,
1382 ))
1383 .map(|_| ())
1384 }
1385 }
1386
1387 #[corresponds(SSL_CTX_use_certificate)]
1391 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1392 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1393 }
1394
1395 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1400 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1401 #[cfg(feature = "rpk")]
1402 assert!(!self.is_rpk, "This API is not supported for RPK");
1403
1404 unsafe {
1405 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.into_ptr()) as c_int)?;
1406 Ok(())
1407 }
1408 }
1409
1410 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1412 pub fn set_private_key_file<P: AsRef<Path>>(
1413 &mut self,
1414 file: P,
1415 file_type: SslFiletype,
1416 ) -> Result<(), ErrorStack> {
1417 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1418 unsafe {
1419 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1420 self.as_ptr(),
1421 file.as_ptr() as *const _,
1422 file_type.as_raw(),
1423 ))
1424 .map(|_| ())
1425 }
1426 }
1427
1428 #[corresponds(SSL_CTX_use_PrivateKey)]
1430 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1431 where
1432 T: HasPrivate,
1433 {
1434 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1435 }
1436
1437 #[corresponds(SSL_CTX_set_cipher_list)]
1447 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1448 let cipher_list = CString::new(cipher_list).unwrap();
1449 unsafe {
1450 cvt(ffi::SSL_CTX_set_cipher_list(
1451 self.as_ptr(),
1452 cipher_list.as_ptr() as *const _,
1453 ))
1454 .map(|_| ())
1455 }
1456 }
1457
1458 #[corresponds(SSL_CTX_get_ciphers)]
1464 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
1465 self.ctx.ciphers()
1466 }
1467
1468 #[corresponds(SSL_CTX_set_options)]
1475 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1476 let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
1477 SslOptions::from_bits_retain(bits)
1478 }
1479
1480 #[corresponds(SSL_CTX_get_options)]
1482 pub fn options(&self) -> SslOptions {
1483 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
1484 SslOptions::from_bits_retain(bits)
1485 }
1486
1487 #[corresponds(SSL_CTX_clear_options)]
1489 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1490 let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
1491 SslOptions::from_bits_retain(bits)
1492 }
1493
1494 #[corresponds(SSL_CTX_set_min_proto_version)]
1499 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1500 unsafe {
1501 cvt(ffi::SSL_CTX_set_min_proto_version(
1502 self.as_ptr(),
1503 version.map_or(0, |v| v.0 as _),
1504 ))
1505 .map(|_| ())
1506 }
1507 }
1508
1509 #[corresponds(SSL_CTX_set_max_proto_version)]
1513 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1514 unsafe {
1515 cvt(ffi::SSL_CTX_set_max_proto_version(
1516 self.as_ptr(),
1517 version.map_or(0, |v| v.0 as _),
1518 ))
1519 .map(|_| ())
1520 }
1521 }
1522
1523 #[corresponds(SSL_CTX_get_min_proto_version)]
1525 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1526 unsafe {
1527 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1528 if r == 0 {
1529 None
1530 } else {
1531 Some(SslVersion(r))
1532 }
1533 }
1534 }
1535
1536 #[corresponds(SSL_CTX_get_max_proto_version)]
1538 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1539 unsafe {
1540 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1541 if r == 0 {
1542 None
1543 } else {
1544 Some(SslVersion(r))
1545 }
1546 }
1547 }
1548
1549 #[corresponds(SSL_CTX_set_alpn_protos)]
1556 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1557 unsafe {
1558 #[cfg_attr(not(feature = "fips-compat"), allow(clippy::unnecessary_cast))]
1559 {
1560 assert!(protocols.len() <= ProtosLen::MAX as usize);
1561 }
1562 let r = ffi::SSL_CTX_set_alpn_protos(
1563 self.as_ptr(),
1564 protocols.as_ptr(),
1565 protocols.len() as ProtosLen,
1566 );
1567 if r == 0 {
1569 Ok(())
1570 } else {
1571 Err(ErrorStack::get())
1572 }
1573 }
1574 }
1575
1576 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1578 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1579 unsafe {
1580 let cstr = CString::new(protocols).unwrap();
1581
1582 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1583 if r == 0 {
1585 Ok(())
1586 } else {
1587 Err(ErrorStack::get())
1588 }
1589 }
1590 }
1591
1592 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1603 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1604 where
1605 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1606 {
1607 unsafe {
1608 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1609 ffi::SSL_CTX_set_alpn_select_cb(
1610 self.as_ptr(),
1611 Some(callbacks::raw_alpn_select::<F>),
1612 ptr::null_mut(),
1613 );
1614 }
1615 }
1616
1617 #[corresponds(SSL_CTX_set_select_certificate_cb)]
1621 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
1622 where
1623 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
1624 {
1625 unsafe {
1626 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1627 ffi::SSL_CTX_set_select_certificate_cb(
1628 self.as_ptr(),
1629 Some(callbacks::raw_select_cert::<F>),
1630 );
1631 }
1632 }
1633
1634 #[corresponds(SSL_CTX_add_cert_compression_alg)]
1638 pub fn add_certificate_compression_algorithm<C>(
1639 &mut self,
1640 compressor: C,
1641 ) -> Result<(), ErrorStack>
1642 where
1643 C: CertificateCompressor,
1644 {
1645 const {
1646 assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered")
1647 };
1648 let success = unsafe {
1649 ffi::SSL_CTX_add_cert_compression_alg(
1650 self.as_ptr(),
1651 C::ALGORITHM.0,
1652 const {
1653 if C::CAN_COMPRESS {
1654 Some(callbacks::raw_ssl_cert_compress::<C>)
1655 } else {
1656 None
1657 }
1658 },
1659 const {
1660 if C::CAN_DECOMPRESS {
1661 Some(callbacks::raw_ssl_cert_decompress::<C>)
1662 } else {
1663 None
1664 }
1665 },
1666 ) == 1
1667 };
1668 if !success {
1669 return Err(ErrorStack::get());
1670 }
1671 self.replace_ex_data(SslContext::cached_ex_index::<C>(), compressor);
1672 Ok(())
1673 }
1674
1675 #[corresponds(SSL_CTX_set_private_key_method)]
1679 pub fn set_private_key_method<M>(&mut self, method: M)
1680 where
1681 M: PrivateKeyMethod,
1682 {
1683 unsafe {
1684 self.replace_ex_data(SslContext::cached_ex_index::<M>(), method);
1685
1686 ffi::SSL_CTX_set_private_key_method(
1687 self.as_ptr(),
1688 &ffi::SSL_PRIVATE_KEY_METHOD {
1689 sign: Some(callbacks::raw_sign::<M>),
1690 decrypt: Some(callbacks::raw_decrypt::<M>),
1691 complete: Some(callbacks::raw_complete::<M>),
1692 },
1693 )
1694 }
1695 }
1696
1697 #[corresponds(SSL_CTX_check_private_key)]
1699 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1700 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1701 }
1702
1703 #[corresponds(SSL_CTX_get_cert_store)]
1705 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1706 #[cfg(feature = "rpk")]
1707 assert!(!self.is_rpk, "This API is not supported for RPK");
1708
1709 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1710 }
1711
1712 #[corresponds(SSL_CTX_get_cert_store)]
1714 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1715 #[cfg(feature = "rpk")]
1716 assert!(!self.is_rpk, "This API is not supported for RPK");
1717
1718 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1719 }
1720
1721 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1734 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1735 where
1736 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1737 {
1738 unsafe {
1739 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1740 cvt(
1741 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1742 as c_int,
1743 )
1744 .map(|_| ())
1745 }
1746 }
1747
1748 #[corresponds(SSL_CTX_set_psk_client_callback)]
1754 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1755 where
1756 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1757 + 'static
1758 + Sync
1759 + Send,
1760 {
1761 unsafe {
1762 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1763 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1764 }
1765 }
1766
1767 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1768 pub fn set_psk_callback<F>(&mut self, callback: F)
1769 where
1770 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1771 + 'static
1772 + Sync
1773 + Send,
1774 {
1775 self.set_psk_client_callback(callback)
1776 }
1777
1778 #[corresponds(SSL_CTX_set_psk_server_callback)]
1784 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1785 where
1786 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1787 + 'static
1788 + Sync
1789 + Send,
1790 {
1791 unsafe {
1792 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1793 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1794 }
1795 }
1796
1797 #[corresponds(SSL_CTX_sess_set_new_cb)]
1811 pub fn set_new_session_callback<F>(&mut self, callback: F)
1812 where
1813 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1814 {
1815 unsafe {
1816 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1817 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1818 }
1819 }
1820
1821 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1825 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1826 where
1827 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1828 {
1829 unsafe {
1830 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1831 ffi::SSL_CTX_sess_set_remove_cb(
1832 self.as_ptr(),
1833 Some(callbacks::raw_remove_session::<F>),
1834 );
1835 }
1836 }
1837
1838 #[corresponds(SSL_CTX_sess_set_get_cb)]
1849 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1850 where
1851 F: Fn(&mut SslRef, &[u8]) -> Result<Option<SslSession>, GetSessionPendingError>
1852 + 'static
1853 + Sync
1854 + Send,
1855 {
1856 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1857 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1858 }
1859
1860 #[corresponds(SSL_CTX_set_keylog_callback)]
1866 pub fn set_keylog_callback<F>(&mut self, callback: F)
1867 where
1868 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1869 {
1870 unsafe {
1871 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1872 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1873 }
1874 }
1875
1876 #[corresponds(SSL_CTX_set_session_cache_mode)]
1880 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1881 unsafe {
1882 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1883 SslSessionCacheMode::from_bits_retain(bits)
1884 }
1885 }
1886
1887 #[corresponds(SSL_CTX_set_ex_data)]
1895 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1896 unsafe {
1897 self.ctx.set_ex_data(index, data);
1898 }
1899 }
1900
1901 #[corresponds(SSL_CTX_set_ex_data)]
1908 pub fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
1909 unsafe { self.ctx.replace_ex_data(index, data) }
1910 }
1911
1912 #[corresponds(SSL_CTX_sess_set_cache_size)]
1916 #[allow(clippy::useless_conversion)]
1917 pub fn set_session_cache_size(&mut self, size: u32) -> u64 {
1918 unsafe { ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size.into()).into() }
1919 }
1920
1921 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1923 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1924 let sigalgs = CString::new(sigalgs).unwrap();
1925 unsafe {
1926 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1927 .map(|_| ())
1928 }
1929 }
1930
1931 #[corresponds(SSL_CTX_set_grease_enabled)]
1933 pub fn set_grease_enabled(&mut self, enabled: bool) {
1934 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as _) }
1935 }
1936
1937 #[corresponds(SSL_CTX_set_permute_extensions)]
1943 #[cfg(not(feature = "fips-compat"))]
1944 pub fn set_permute_extensions(&mut self, enabled: bool) {
1945 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as _) }
1946 }
1947
1948 #[corresponds(SSL_CTX_set_verify_algorithm_prefs)]
1950 pub fn set_verify_algorithm_prefs(
1951 &mut self,
1952 prefs: &[SslSignatureAlgorithm],
1953 ) -> Result<(), ErrorStack> {
1954 unsafe {
1955 cvt_0i(ffi::SSL_CTX_set_verify_algorithm_prefs(
1956 self.as_ptr(),
1957 prefs.as_ptr() as *const _,
1958 prefs.len(),
1959 ))
1960 .map(|_| ())
1961 }
1962 }
1963
1964 #[corresponds(SSL_CTX_enable_signed_cert_timestamps)]
1966 pub fn enable_signed_cert_timestamps(&mut self) {
1967 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1968 }
1969
1970 #[corresponds(SSL_CTX_enable_ocsp_stapling)]
1972 pub fn enable_ocsp_stapling(&mut self) {
1973 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1974 }
1975
1976 #[cfg(not(feature = "kx-safe-default"))]
1982 #[corresponds(SSL_CTX_set1_curves_list)]
1983 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
1984 let curves = CString::new(curves).unwrap();
1985 unsafe {
1986 cvt_0i(ffi::SSL_CTX_set1_curves_list(
1987 self.as_ptr(),
1988 curves.as_ptr() as *const _,
1989 ))
1990 .map(|_| ())
1991 }
1992 }
1993
1994 #[corresponds(SSL_CTX_set1_curves)]
2000 #[cfg(not(feature = "kx-safe-default"))]
2001 pub fn set_curves(&mut self, curves: &[SslCurve]) -> Result<(), ErrorStack> {
2002 let curves: Vec<i32> = curves.iter().filter_map(|curve| curve.nid()).collect();
2003
2004 unsafe {
2005 cvt_0i(ffi::SSL_CTX_set1_curves(
2006 self.as_ptr(),
2007 curves.as_ptr() as *const _,
2008 curves.len(),
2009 ))
2010 .map(|_| ())
2011 }
2012 }
2013
2014 #[corresponds(SSL_CTX_set_compliance_policy)]
2018 #[cfg(not(feature = "fips-compat"))]
2019 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
2020 unsafe { cvt_0i(ffi::SSL_CTX_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
2021 }
2022
2023 #[corresponds(SSL_CTX_set_info_callback)]
2025 pub fn set_info_callback<F>(&mut self, callback: F)
2026 where
2027 F: Fn(&SslRef, SslInfoCallbackMode, SslInfoCallbackValue) + Send + Sync + 'static,
2028 {
2029 unsafe {
2030 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
2031 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info_callback::<F>));
2032 }
2033 }
2034
2035 #[cfg(not(feature = "fips"))]
2040 #[corresponds(SSL_CTX_set1_ech_keys)]
2041 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2042 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())).map(|_| ()) }
2043 }
2044
2045 pub fn build(self) -> SslContext {
2047 self.ctx
2048 }
2049}
2050
2051foreign_type_and_impl_send_sync! {
2052 type CType = ffi::SSL_CTX;
2053 fn drop = ffi::SSL_CTX_free;
2054
2055 pub struct SslContext;
2060}
2061
2062impl Clone for SslContext {
2063 fn clone(&self) -> Self {
2064 (**self).to_owned()
2065 }
2066}
2067
2068impl ToOwned for SslContextRef {
2069 type Owned = SslContext;
2070
2071 fn to_owned(&self) -> Self::Owned {
2072 unsafe {
2073 SSL_CTX_up_ref(self.as_ptr());
2074 SslContext::from_ptr(self.as_ptr())
2075 }
2076 }
2077}
2078
2079impl fmt::Debug for SslContext {
2081 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2082 write!(fmt, "SslContext")
2083 }
2084}
2085
2086impl SslContext {
2087 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2089 SslContextBuilder::new(method)
2090 }
2091
2092 #[corresponds(SSL_CTX_get_ex_new_index)]
2097 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2098 where
2099 T: 'static + Sync + Send,
2100 {
2101 unsafe {
2102 ffi::init();
2103 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2104 Ok(Index::from_raw(idx))
2105 }
2106 }
2107
2108 fn cached_ex_index<T>() -> Index<SslContext, T>
2110 where
2111 T: 'static + Sync + Send,
2112 {
2113 unsafe {
2114 let idx = *INDEXES
2115 .lock()
2116 .unwrap_or_else(|e| e.into_inner())
2117 .entry(TypeId::of::<T>())
2118 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2119 Index::from_raw(idx)
2120 }
2121 }
2122
2123 #[corresponds(SSL_CTX_get_ciphers)]
2129 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
2130 unsafe {
2131 let ciphers = ffi::SSL_CTX_get_ciphers(self.as_ptr());
2132 if ciphers.is_null() {
2133 None
2134 } else {
2135 Some(StackRef::from_ptr(ciphers))
2136 }
2137 }
2138 }
2139}
2140
2141impl SslContextRef {
2142 #[corresponds(SSL_CTX_get0_certificate)]
2144 pub fn certificate(&self) -> Option<&X509Ref> {
2145 #[cfg(feature = "rpk")]
2146 assert!(!self.is_rpk(), "This API is not supported for RPK");
2147
2148 unsafe {
2149 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2150 if ptr.is_null() {
2151 None
2152 } else {
2153 Some(X509Ref::from_ptr(ptr))
2154 }
2155 }
2156 }
2157
2158 #[corresponds(SSL_CTX_get0_privatekey)]
2160 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2161 unsafe {
2162 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2163 if ptr.is_null() {
2164 None
2165 } else {
2166 Some(PKeyRef::from_ptr(ptr))
2167 }
2168 }
2169 }
2170
2171 #[corresponds(SSL_CTX_get_cert_store)]
2173 pub fn cert_store(&self) -> &X509StoreRef {
2174 #[cfg(feature = "rpk")]
2175 assert!(!self.is_rpk(), "This API is not supported for RPK");
2176
2177 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2178 }
2179
2180 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2182 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2183 unsafe {
2184 let mut chain = ptr::null_mut();
2185 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2186 assert!(!chain.is_null());
2187 StackRef::from_ptr(chain)
2188 }
2189 }
2190
2191 #[corresponds(SSL_CTX_get_ex_data)]
2193 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2194 unsafe {
2195 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2196 if data.is_null() {
2197 None
2198 } else {
2199 Some(&*(data as *const T))
2200 }
2201 }
2202 }
2203
2204 #[corresponds(SSL_CTX_get_ex_data)]
2207 unsafe fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2208 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2209 if data.is_null() {
2210 None
2211 } else {
2212 Some(&mut *(data as *mut T))
2213 }
2214 }
2215
2216 #[corresponds(SSL_CTX_set_ex_data)]
2219 unsafe fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2220 unsafe {
2221 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2222 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2223 }
2224 }
2225
2226 #[corresponds(SSL_CTX_set_ex_data)]
2229 unsafe fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2230 if let Some(old) = self.ex_data_mut(index) {
2231 return Some(mem::replace(old, data));
2232 }
2233
2234 self.set_ex_data(index, data);
2235
2236 None
2237 }
2238
2239 #[corresponds(SSL_CTX_add_session)]
2248 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2249 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2250 }
2251
2252 #[corresponds(SSL_CTX_remove_session)]
2261 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2262 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2263 }
2264
2265 #[corresponds(SSL_CTX_sess_get_cache_size)]
2269 #[allow(clippy::useless_conversion)]
2270 pub fn session_cache_size(&self) -> u64 {
2271 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()).into() }
2272 }
2273
2274 #[corresponds(SSL_CTX_get_verify_mode)]
2278 pub fn verify_mode(&self) -> SslVerifyMode {
2279 #[cfg(feature = "rpk")]
2280 assert!(!self.is_rpk(), "This API is not supported for RPK");
2281
2282 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2283 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2284 }
2285
2286 #[cfg(feature = "rpk")]
2288 pub fn is_rpk(&self) -> bool {
2289 self.ex_data(*RPK_FLAG_INDEX).copied().unwrap_or_default()
2290 }
2291
2292 #[cfg(not(feature = "fips"))]
2297 #[corresponds(SSL_CTX_set1_ech_keys)]
2298 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2299 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())).map(|_| ()) }
2300 }
2301}
2302
2303#[derive(Debug)]
2308pub struct GetSessionPendingError;
2309
2310#[cfg(not(feature = "fips-compat"))]
2311type ProtosLen = usize;
2312#[cfg(feature = "fips-compat")]
2313type ProtosLen = libc::c_uint;
2314
2315pub struct CipherBits {
2317 pub secret: i32,
2319
2320 pub algorithm: i32,
2322}
2323
2324#[repr(transparent)]
2325pub struct ClientHello<'ssl>(&'ssl ffi::SSL_CLIENT_HELLO);
2326
2327impl ClientHello<'_> {
2328 #[corresponds(SSL_early_callback_ctx_extension_get)]
2330 pub fn get_extension(&self, ext_type: ExtensionType) -> Option<&[u8]> {
2331 unsafe {
2332 let mut ptr = ptr::null();
2333 let mut len = 0;
2334 let result =
2335 ffi::SSL_early_callback_ctx_extension_get(self.0, ext_type.0, &mut ptr, &mut len);
2336 if result == 0 {
2337 return None;
2338 }
2339 Some(slice::from_raw_parts(ptr, len))
2340 }
2341 }
2342
2343 pub fn ssl_mut(&mut self) -> &mut SslRef {
2344 unsafe { SslRef::from_ptr_mut(self.0.ssl) }
2345 }
2346
2347 pub fn ssl(&self) -> &SslRef {
2348 unsafe { SslRef::from_ptr(self.0.ssl) }
2349 }
2350
2351 pub fn servername(&self, type_: NameType) -> Option<&str> {
2353 self.ssl().servername(type_)
2354 }
2355
2356 pub fn client_version(&self) -> SslVersion {
2358 SslVersion(self.0.version)
2359 }
2360
2361 pub fn version_str(&self) -> &'static str {
2363 self.ssl().version_str()
2364 }
2365
2366 pub fn as_bytes(&self) -> &[u8] {
2368 unsafe { slice::from_raw_parts(self.0.client_hello, self.0.client_hello_len) }
2369 }
2370
2371 pub fn random(&self) -> &[u8] {
2373 unsafe { slice::from_raw_parts(self.0.random, self.0.random_len) }
2374 }
2375
2376 pub fn ciphers(&self) -> &[u8] {
2378 unsafe { slice::from_raw_parts(self.0.cipher_suites, self.0.cipher_suites_len) }
2379 }
2380}
2381
2382pub struct SslCipher(*mut ffi::SSL_CIPHER);
2384
2385impl SslCipher {
2386 #[corresponds(SSL_get_cipher_by_value)]
2387 pub fn from_value(value: u16) -> Option<Self> {
2388 unsafe {
2389 let ptr = ffi::SSL_get_cipher_by_value(value);
2390 if ptr.is_null() {
2391 None
2392 } else {
2393 Some(Self::from_ptr(ptr as *mut ffi::SSL_CIPHER))
2394 }
2395 }
2396 }
2397}
2398
2399impl Stackable for SslCipher {
2400 type StackType = ffi::stack_st_SSL_CIPHER;
2401}
2402
2403unsafe impl ForeignType for SslCipher {
2404 type CType = ffi::SSL_CIPHER;
2405 type Ref = SslCipherRef;
2406
2407 #[inline]
2408 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2409 SslCipher(ptr)
2410 }
2411
2412 #[inline]
2413 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2414 self.0
2415 }
2416}
2417
2418impl Deref for SslCipher {
2419 type Target = SslCipherRef;
2420
2421 fn deref(&self) -> &SslCipherRef {
2422 unsafe { SslCipherRef::from_ptr(self.0) }
2423 }
2424}
2425
2426impl DerefMut for SslCipher {
2427 fn deref_mut(&mut self) -> &mut SslCipherRef {
2428 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2429 }
2430}
2431
2432pub struct SslCipherRef(Opaque);
2436
2437unsafe impl ForeignTypeRef for SslCipherRef {
2438 type CType = ffi::SSL_CIPHER;
2439}
2440
2441impl SslCipherRef {
2442 #[corresponds(SSL_CIPHER_get_name)]
2444 pub fn name(&self) -> &'static str {
2445 unsafe {
2446 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2447 CStr::from_ptr(ptr).to_str().unwrap()
2448 }
2449 }
2450
2451 #[corresponds(SSL_CIPHER_standard_name)]
2453 pub fn standard_name(&self) -> Option<&'static str> {
2454 unsafe {
2455 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2456 if ptr.is_null() {
2457 None
2458 } else {
2459 Some(CStr::from_ptr(ptr).to_str().unwrap())
2460 }
2461 }
2462 }
2463
2464 #[corresponds(SSL_CIPHER_get_version)]
2466 pub fn version(&self) -> &'static str {
2467 let version = unsafe {
2468 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2469 CStr::from_ptr(ptr as *const _)
2470 };
2471
2472 str::from_utf8(version.to_bytes()).unwrap()
2473 }
2474
2475 #[corresponds(SSL_CIPHER_get_bits)]
2477 #[allow(clippy::useless_conversion)]
2478 pub fn bits(&self) -> CipherBits {
2479 unsafe {
2480 let mut algo_bits = 0;
2481 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2482 CipherBits {
2483 secret: secret_bits.into(),
2484 algorithm: algo_bits.into(),
2485 }
2486 }
2487 }
2488
2489 #[corresponds(SSL_CIPHER_description)]
2491 pub fn description(&self) -> String {
2492 unsafe {
2493 let mut buf = [0; 128];
2495 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2496 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2497 }
2498 }
2499
2500 #[corresponds(SSL_CIPHER_is_aead)]
2502 pub fn cipher_is_aead(&self) -> bool {
2503 unsafe { ffi::SSL_CIPHER_is_aead(self.as_ptr()) != 0 }
2504 }
2505
2506 #[corresponds(SSL_CIPHER_get_auth_nid)]
2508 pub fn cipher_auth_nid(&self) -> Option<Nid> {
2509 let n = unsafe { ffi::SSL_CIPHER_get_auth_nid(self.as_ptr()) };
2510 if n == 0 {
2511 None
2512 } else {
2513 Some(Nid::from_raw(n))
2514 }
2515 }
2516
2517 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2519 pub fn cipher_nid(&self) -> Option<Nid> {
2520 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2521 if n == 0 {
2522 None
2523 } else {
2524 Some(Nid::from_raw(n))
2525 }
2526 }
2527}
2528
2529foreign_type_and_impl_send_sync! {
2530 type CType = ffi::SSL_SESSION;
2531 fn drop = ffi::SSL_SESSION_free;
2532
2533 pub struct SslSession;
2537}
2538
2539impl Clone for SslSession {
2540 fn clone(&self) -> SslSession {
2541 SslSessionRef::to_owned(self)
2542 }
2543}
2544
2545impl SslSession {
2546 from_der! {
2547 #[corresponds(d2i_SSL_SESSION)]
2549 from_der,
2550 SslSession,
2551 ffi::d2i_SSL_SESSION,
2552 ::libc::c_long
2553 }
2554}
2555
2556impl ToOwned for SslSessionRef {
2557 type Owned = SslSession;
2558
2559 fn to_owned(&self) -> SslSession {
2560 unsafe {
2561 SSL_SESSION_up_ref(self.as_ptr());
2562 SslSession(NonNull::new_unchecked(self.as_ptr()))
2563 }
2564 }
2565}
2566
2567impl SslSessionRef {
2568 #[corresponds(SSL_SESSION_get_id)]
2570 pub fn id(&self) -> &[u8] {
2571 unsafe {
2572 let mut len = 0;
2573 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2574 slice::from_raw_parts(p, len as usize)
2575 }
2576 }
2577
2578 #[corresponds(SSL_SESSION_get_master_key)]
2580 pub fn master_key_len(&self) -> usize {
2581 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2582 }
2583
2584 #[corresponds(SSL_SESSION_get_master_key)]
2588 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2589 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2590 }
2591
2592 #[corresponds(SSL_SESSION_get_time)]
2594 #[allow(clippy::useless_conversion)]
2595 pub fn time(&self) -> u64 {
2596 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2597 }
2598
2599 #[corresponds(SSL_SESSION_get_timeout)]
2603 #[allow(clippy::useless_conversion)]
2604 pub fn timeout(&self) -> u32 {
2605 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()) }
2606 }
2607
2608 #[corresponds(SSL_SESSION_get_protocol_version)]
2610 pub fn protocol_version(&self) -> SslVersion {
2611 unsafe {
2612 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2613 SslVersion(version)
2614 }
2615 }
2616
2617 to_der! {
2618 #[corresponds(i2d_SSL_SESSION)]
2620 to_der,
2621 ffi::i2d_SSL_SESSION
2622 }
2623}
2624
2625foreign_type_and_impl_send_sync! {
2626 type CType = ffi::SSL;
2627 fn drop = ffi::SSL_free;
2628
2629 pub struct Ssl;
2636}
2637
2638impl fmt::Debug for Ssl {
2639 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2640 fmt::Debug::fmt(&**self, fmt)
2641 }
2642}
2643
2644impl Ssl {
2645 #[corresponds(SSL_get_ex_new_index)]
2650 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2651 where
2652 T: 'static + Sync + Send,
2653 {
2654 unsafe {
2655 ffi::init();
2656 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2657 Ok(Index::from_raw(idx))
2658 }
2659 }
2660
2661 fn cached_ex_index<T>() -> Index<Ssl, T>
2663 where
2664 T: 'static + Sync + Send,
2665 {
2666 unsafe {
2667 let idx = *SSL_INDEXES
2668 .lock()
2669 .unwrap_or_else(|e| e.into_inner())
2670 .entry(TypeId::of::<T>())
2671 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2672 Index::from_raw(idx)
2673 }
2674 }
2675
2676 #[corresponds(SSL_new)]
2680 pub fn new(ctx: &SslContext) -> Result<Ssl, ErrorStack> {
2681 unsafe {
2682 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2683 let mut ssl = Ssl::from_ptr(ptr);
2684 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx.clone());
2685
2686 Ok(ssl)
2687 }
2688 }
2689
2690 #[corresponds(SSL_new)]
2695 pub fn new_from_ref(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2696 unsafe {
2697 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2698 let mut ssl = Ssl::from_ptr(ptr);
2699 SSL_CTX_up_ref(ctx.as_ptr());
2700 let ctx_owned = SslContext::from_ptr(ctx.as_ptr());
2701 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx_owned);
2702
2703 Ok(ssl)
2704 }
2705 }
2706
2707 pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2719 where
2720 S: Read + Write,
2721 {
2722 SslStreamBuilder::new(self, stream).setup_connect()
2723 }
2724
2725 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2735 where
2736 S: Read + Write,
2737 {
2738 self.setup_connect(stream).handshake()
2739 }
2740
2741 pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
2753 where
2754 S: Read + Write,
2755 {
2756 #[cfg(feature = "rpk")]
2757 {
2758 let ctx = self.ssl_context();
2759
2760 if ctx.is_rpk() {
2761 unsafe {
2762 ffi::SSL_CTX_set_custom_verify(
2763 ctx.as_ptr(),
2764 SslVerifyMode::PEER.bits(),
2765 Some(rpk_verify_failure_callback),
2766 );
2767 }
2768 }
2769 }
2770
2771 SslStreamBuilder::new(self, stream).setup_accept()
2772 }
2773
2774 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2786 where
2787 S: Read + Write,
2788 {
2789 self.setup_accept(stream).handshake()
2790 }
2791}
2792
2793impl fmt::Debug for SslRef {
2794 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2795 let mut builder = fmt.debug_struct("Ssl");
2796
2797 builder.field("state", &self.state_string_long());
2798
2799 #[cfg(feature = "rpk")]
2800 if !self.ssl_context().is_rpk() {
2801 builder.field("verify_result", &self.verify_result());
2802 }
2803
2804 #[cfg(not(feature = "rpk"))]
2805 builder.field("verify_result", &self.verify_result());
2806
2807 builder.finish()
2808 }
2809}
2810
2811impl SslRef {
2812 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2813 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2814 }
2815
2816 #[corresponds(SSL_set1_curves_list)]
2817 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2818 let curves = CString::new(curves).unwrap();
2819 unsafe {
2820 cvt_0i(ffi::SSL_set1_curves_list(
2821 self.as_ptr(),
2822 curves.as_ptr() as *const _,
2823 ))
2824 .map(|_| ())
2825 }
2826 }
2827
2828 #[cfg(feature = "kx-safe-default")]
2829 fn client_set_default_curves_list(&mut self) {
2830 let curves = if cfg!(feature = "kx-client-pq-preferred") {
2831 if cfg!(feature = "kx-client-nist-required") {
2832 "P256Kyber768Draft00:P-256:P-384:P-521"
2833 } else {
2834 "X25519MLKEM768:X25519Kyber768Draft00:X25519:P256Kyber768Draft00:P-256:P-384:P-521"
2835 }
2836 } else if cfg!(feature = "kx-client-pq-supported") {
2837 if cfg!(feature = "kx-client-nist-required") {
2838 "P-256:P-384:P-521:P256Kyber768Draft00"
2839 } else {
2840 "X25519:P-256:P-384:P-521:X25519MLKEM768:X25519Kyber768Draft00:P256Kyber768Draft00"
2841 }
2842 } else {
2843 if cfg!(feature = "kx-client-nist-required") {
2844 "P-256:P-384:P-521"
2845 } else {
2846 "X25519:P-256:P-384:P-521"
2847 }
2848 };
2849
2850 self.set_curves_list(curves)
2851 .expect("invalid default client curves list");
2852 }
2853
2854 #[cfg(feature = "kx-safe-default")]
2855 fn server_set_default_curves_list(&mut self) {
2856 self.set_curves_list(
2857 "X25519MLKEM768:X25519Kyber768Draft00:P256Kyber768Draft00:X25519:P-256:P-384",
2858 )
2859 .expect("invalid default server curves list");
2860 }
2861
2862 #[corresponds(SSL_get_curve_id)]
2864 pub fn curve(&self) -> Option<SslCurve> {
2865 let curve_id = unsafe { ffi::SSL_get_curve_id(self.as_ptr()) };
2866 if curve_id == 0 {
2867 return None;
2868 }
2869 Some(SslCurve(curve_id.into()))
2870 }
2871
2872 #[corresponds(SSL_get_error)]
2874 pub fn error_code(&self, ret: c_int) -> ErrorCode {
2875 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2876 }
2877
2878 #[corresponds(SSL_set_verify)]
2882 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2883 #[cfg(feature = "rpk")]
2884 assert!(
2885 !self.ssl_context().is_rpk(),
2886 "This API is not supported for RPK"
2887 );
2888
2889 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2890 }
2891
2892 #[corresponds(SSL_set_verify_depth)]
2896 pub fn set_verify_depth(&mut self, depth: u32) {
2897 #[cfg(feature = "rpk")]
2898 assert!(
2899 !self.ssl_context().is_rpk(),
2900 "This API is not supported for RPK"
2901 );
2902
2903 unsafe {
2904 ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
2905 }
2906 }
2907
2908 #[corresponds(SSL_get_verify_mode)]
2910 pub fn verify_mode(&self) -> SslVerifyMode {
2911 #[cfg(feature = "rpk")]
2912 assert!(
2913 !self.ssl_context().is_rpk(),
2914 "This API is not supported for RPK"
2915 );
2916
2917 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2918 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2919 }
2920
2921 #[corresponds(SSL_set_verify)]
2938 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
2939 where
2940 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2941 {
2942 #[cfg(feature = "rpk")]
2943 assert!(
2944 !self.ssl_context().is_rpk(),
2945 "This API is not supported for RPK"
2946 );
2947
2948 unsafe {
2949 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2951 ffi::SSL_set_verify(
2952 self.as_ptr(),
2953 mode.bits() as c_int,
2954 Some(ssl_raw_verify::<F>),
2955 );
2956 }
2957 }
2958
2959 #[corresponds(SSL_set0_verify_cert_store)]
2961 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
2962 #[cfg(feature = "rpk")]
2963 assert!(
2964 !self.ssl_context().is_rpk(),
2965 "This API is not supported for RPK"
2966 );
2967
2968 unsafe {
2969 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int)?;
2970 Ok(())
2971 }
2972 }
2973
2974 #[corresponds(SSL_set_custom_verify)]
2980 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
2981 where
2982 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
2983 {
2984 #[cfg(feature = "rpk")]
2985 assert!(
2986 !self.ssl_context().is_rpk(),
2987 "This API is not supported for RPK"
2988 );
2989
2990 unsafe {
2991 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2993 ffi::SSL_set_custom_verify(
2994 self.as_ptr(),
2995 mode.bits() as c_int,
2996 Some(ssl_raw_custom_verify::<F>),
2997 );
2998 }
2999 }
3000
3001 #[corresponds(SSL_set_tmp_dh)]
3005 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3006 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3007 }
3008
3009 #[corresponds(SSL_set_tmp_ecdh)]
3013 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3014 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3015 }
3016
3017 #[corresponds(SSL_set_permute_extensions)]
3019 #[cfg(not(feature = "fips-compat"))]
3024 pub fn set_permute_extensions(&mut self, enabled: bool) {
3025 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as _) }
3026 }
3027
3028 #[corresponds(SSL_set_alpn_protos)]
3032 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3033 unsafe {
3034 #[cfg_attr(not(feature = "fips-compat"), allow(clippy::unnecessary_cast))]
3035 {
3036 assert!(protocols.len() <= ProtosLen::MAX as usize);
3037 }
3038 let r = ffi::SSL_set_alpn_protos(
3039 self.as_ptr(),
3040 protocols.as_ptr(),
3041 protocols.len() as ProtosLen,
3042 );
3043 if r == 0 {
3045 Ok(())
3046 } else {
3047 Err(ErrorStack::get())
3048 }
3049 }
3050 }
3051
3052 #[corresponds(SSL_get_ciphers)]
3054 pub fn ciphers(&self) -> &StackRef<SslCipher> {
3055 unsafe {
3056 let cipher_list = ffi::SSL_get_ciphers(self.as_ptr());
3057 StackRef::from_ptr(cipher_list)
3058 }
3059 }
3060
3061 #[corresponds(SSL_get_current_cipher)]
3063 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3064 unsafe {
3065 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3066
3067 if ptr.is_null() {
3068 None
3069 } else {
3070 Some(SslCipherRef::from_ptr(ptr as *mut _))
3071 }
3072 }
3073 }
3074
3075 #[corresponds(SSL_state_string)]
3077 pub fn state_string(&self) -> &'static str {
3078 let state = unsafe {
3079 let ptr = ffi::SSL_state_string(self.as_ptr());
3080 CStr::from_ptr(ptr as *const _)
3081 };
3082
3083 str::from_utf8(state.to_bytes()).unwrap()
3084 }
3085
3086 #[corresponds(SSL_state_string_long)]
3088 pub fn state_string_long(&self) -> &'static str {
3089 let state = unsafe {
3090 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3091 CStr::from_ptr(ptr as *const _)
3092 };
3093
3094 str::from_utf8(state.to_bytes()).unwrap()
3095 }
3096
3097 #[corresponds(SSL_set_tlsext_host_name)]
3101 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3102 let cstr = CString::new(hostname).unwrap();
3103 unsafe {
3104 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3105 .map(|_| ())
3106 }
3107 }
3108
3109 #[corresponds(SSL_get_peer_certificate)]
3111 pub fn peer_certificate(&self) -> Option<X509> {
3112 #[cfg(feature = "rpk")]
3113 assert!(
3114 !self.ssl_context().is_rpk(),
3115 "This API is not supported for RPK"
3116 );
3117
3118 unsafe {
3119 let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
3120 if ptr.is_null() {
3121 None
3122 } else {
3123 Some(X509::from_ptr(ptr))
3124 }
3125 }
3126 }
3127
3128 #[corresponds(SSL_get_peer_certificate)]
3133 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3134 #[cfg(feature = "rpk")]
3135 assert!(
3136 !self.ssl_context().is_rpk(),
3137 "This API is not supported for RPK"
3138 );
3139
3140 unsafe {
3141 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3142 if ptr.is_null() {
3143 None
3144 } else {
3145 Some(StackRef::from_ptr(ptr))
3146 }
3147 }
3148 }
3149
3150 #[corresponds(SSL_get_certificate)]
3152 pub fn certificate(&self) -> Option<&X509Ref> {
3153 #[cfg(feature = "rpk")]
3154 assert!(
3155 !self.ssl_context().is_rpk(),
3156 "This API is not supported for RPK"
3157 );
3158
3159 unsafe {
3160 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3161 if ptr.is_null() {
3162 None
3163 } else {
3164 Some(X509Ref::from_ptr(ptr))
3165 }
3166 }
3167 }
3168
3169 #[corresponds(SSL_get_privatekey)]
3171 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3172 unsafe {
3173 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3174 if ptr.is_null() {
3175 None
3176 } else {
3177 Some(PKeyRef::from_ptr(ptr))
3178 }
3179 }
3180 }
3181
3182 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
3183 pub fn version(&self) -> &str {
3184 self.version_str()
3185 }
3186
3187 #[corresponds(SSL_version)]
3189 pub fn version2(&self) -> Option<SslVersion> {
3190 unsafe {
3191 let r = ffi::SSL_version(self.as_ptr());
3192 if r == 0 {
3193 None
3194 } else {
3195 r.try_into().ok().map(SslVersion)
3196 }
3197 }
3198 }
3199
3200 #[corresponds(SSL_get_version)]
3202 pub fn version_str(&self) -> &'static str {
3203 let version = unsafe {
3204 let ptr = ffi::SSL_get_version(self.as_ptr());
3205 CStr::from_ptr(ptr as *const _)
3206 };
3207
3208 str::from_utf8(version.to_bytes()).unwrap()
3209 }
3210
3211 #[corresponds(SSL_set_min_proto_version)]
3216 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3217 unsafe {
3218 cvt(ffi::SSL_set_min_proto_version(
3219 self.as_ptr(),
3220 version.map_or(0, |v| v.0 as _),
3221 ))
3222 .map(|_| ())
3223 }
3224 }
3225
3226 #[corresponds(SSL_set_max_proto_version)]
3230 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3231 unsafe {
3232 cvt(ffi::SSL_set_max_proto_version(
3233 self.as_ptr(),
3234 version.map_or(0, |v| v.0 as _),
3235 ))
3236 .map(|_| ())
3237 }
3238 }
3239
3240 #[corresponds(SSL_get_min_proto_version)]
3242 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
3243 unsafe {
3244 let r = ffi::SSL_get_min_proto_version(self.as_ptr());
3245 if r == 0 {
3246 None
3247 } else {
3248 Some(SslVersion(r))
3249 }
3250 }
3251 }
3252
3253 #[corresponds(SSL_get_max_proto_version)]
3255 pub fn max_proto_version(&self) -> Option<SslVersion> {
3256 let r = unsafe { ffi::SSL_get_max_proto_version(self.as_ptr()) };
3257 if r == 0 {
3258 None
3259 } else {
3260 Some(SslVersion(r))
3261 }
3262 }
3263
3264 #[corresponds(SSL_get0_alpn_selected)]
3269 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3270 unsafe {
3271 let mut data: *const c_uchar = ptr::null();
3272 let mut len: c_uint = 0;
3273 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3276
3277 if data.is_null() {
3278 None
3279 } else {
3280 Some(slice::from_raw_parts(data, len as usize))
3281 }
3282 }
3283 }
3284
3285 #[corresponds(SSL_set_tlsext_use_srtp)]
3287 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3288 unsafe {
3289 let cstr = CString::new(protocols).unwrap();
3290
3291 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3292 if r == 0 {
3294 Ok(())
3295 } else {
3296 Err(ErrorStack::get())
3297 }
3298 }
3299 }
3300
3301 #[corresponds(SSL_get_strp_profiles)]
3305 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3306 unsafe {
3307 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3308
3309 if chain.is_null() {
3310 None
3311 } else {
3312 Some(StackRef::from_ptr(chain as *mut _))
3313 }
3314 }
3315 }
3316
3317 #[corresponds(SSL_get_selected_srtp_profile)]
3321 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3322 unsafe {
3323 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3324
3325 if profile.is_null() {
3326 None
3327 } else {
3328 Some(SrtpProtectionProfileRef::from_ptr(profile as *mut _))
3329 }
3330 }
3331 }
3332
3333 #[corresponds(SSL_pending)]
3338 pub fn pending(&self) -> usize {
3339 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3340 }
3341
3342 #[corresponds(SSL_get_servername)]
3355 pub fn servername(&self, type_: NameType) -> Option<&str> {
3356 self.servername_raw(type_)
3357 .and_then(|b| str::from_utf8(b).ok())
3358 }
3359
3360 #[corresponds(SSL_get_servername)]
3368 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3369 unsafe {
3370 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3371 if name.is_null() {
3372 None
3373 } else {
3374 Some(CStr::from_ptr(name as *const _).to_bytes())
3375 }
3376 }
3377 }
3378
3379 #[corresponds(SSL_set_SSL_CTX)]
3383 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3384 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3385 }
3386
3387 #[corresponds(SSL_get_SSL_CTX)]
3389 pub fn ssl_context(&self) -> &SslContextRef {
3390 unsafe {
3391 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3392 SslContextRef::from_ptr(ssl_ctx)
3393 }
3394 }
3395
3396 #[corresponds(SSL_get0_param)]
3398 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
3399 #[cfg(feature = "rpk")]
3400 assert!(
3401 !self.ssl_context().is_rpk(),
3402 "This API is not supported for RPK"
3403 );
3404
3405 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3406 }
3407
3408 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3410 self.verify_param_mut()
3411 }
3412
3413 #[corresponds(SSL_get_verify_result)]
3415 pub fn verify_result(&self) -> X509VerifyResult {
3416 #[cfg(feature = "rpk")]
3417 assert!(
3418 !self.ssl_context().is_rpk(),
3419 "This API is not supported for RPK"
3420 );
3421
3422 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3423 }
3424
3425 #[corresponds(SSL_get_session)]
3427 pub fn session(&self) -> Option<&SslSessionRef> {
3428 unsafe {
3429 let p = ffi::SSL_get_session(self.as_ptr());
3430 if p.is_null() {
3431 None
3432 } else {
3433 Some(SslSessionRef::from_ptr(p))
3434 }
3435 }
3436 }
3437
3438 #[corresponds(SSL_get_client_random)]
3443 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3444 unsafe {
3445 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3446 }
3447 }
3448
3449 #[corresponds(SSL_get_server_random)]
3454 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3455 unsafe {
3456 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3457 }
3458 }
3459
3460 #[corresponds(SSL_export_keying_material)]
3462 pub fn export_keying_material(
3463 &self,
3464 out: &mut [u8],
3465 label: &str,
3466 context: Option<&[u8]>,
3467 ) -> Result<(), ErrorStack> {
3468 unsafe {
3469 let (context, contextlen, use_context) = match context {
3470 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3471 None => (ptr::null(), 0, 0),
3472 };
3473 cvt(ffi::SSL_export_keying_material(
3474 self.as_ptr(),
3475 out.as_mut_ptr() as *mut c_uchar,
3476 out.len(),
3477 label.as_ptr() as *const c_char,
3478 label.len(),
3479 context,
3480 contextlen,
3481 use_context,
3482 ))
3483 .map(|_| ())
3484 }
3485 }
3486
3487 #[corresponds(SSL_set_session)]
3498 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3499 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3500 }
3501
3502 #[corresponds(SSL_session_reused)]
3504 pub fn session_reused(&self) -> bool {
3505 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3506 }
3507
3508 #[corresponds(SSL_set_tlsext_status_type)]
3510 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3511 unsafe {
3512 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3513 }
3514 }
3515
3516 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3518 pub fn ocsp_status(&self) -> Option<&[u8]> {
3519 unsafe {
3520 let mut p = ptr::null();
3521 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3522
3523 if len == 0 {
3524 None
3525 } else {
3526 Some(slice::from_raw_parts(p, len))
3527 }
3528 }
3529 }
3530
3531 #[corresponds(SSL_set_tlsext_status_ocsp_resp)]
3533 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3534 unsafe {
3535 assert!(response.len() <= c_int::MAX as usize);
3536 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3537 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3538 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3539 self.as_ptr(),
3540 p as *mut c_uchar,
3541 response.len(),
3542 ) as c_int)
3543 .map(|_| ())
3544 }
3545 }
3546
3547 #[corresponds(SSL_is_server)]
3549 pub fn is_server(&self) -> bool {
3550 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3551 }
3552
3553 #[corresponds(SSL_set_ex_data)]
3561 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3562 if let Some(old) = self.ex_data_mut(index) {
3563 *old = data;
3564
3565 return;
3566 }
3567
3568 unsafe {
3569 let data = Box::new(data);
3570 ffi::SSL_set_ex_data(
3571 self.as_ptr(),
3572 index.as_raw(),
3573 Box::into_raw(data) as *mut c_void,
3574 );
3575 }
3576 }
3577
3578 #[corresponds(SSL_set_ex_data)]
3585 pub fn replace_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) -> Option<T> {
3586 if let Some(old) = self.ex_data_mut(index) {
3587 return Some(mem::replace(old, data));
3588 }
3589
3590 self.set_ex_data(index, data);
3591
3592 None
3593 }
3594
3595 #[corresponds(SSL_get_ex_data)]
3597 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3598 unsafe {
3599 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3600 if data.is_null() {
3601 None
3602 } else {
3603 Some(&*(data as *const T))
3604 }
3605 }
3606 }
3607
3608 #[corresponds(SSL_get_ex_data)]
3610 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3611 unsafe {
3612 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3613 if data.is_null() {
3614 None
3615 } else {
3616 Some(&mut *(data as *mut T))
3617 }
3618 }
3619 }
3620
3621 #[corresponds(SSL_get_finished)]
3626 pub fn finished(&self, buf: &mut [u8]) -> usize {
3627 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3628 }
3629
3630 #[corresponds(SSL_get_peer_finished)]
3636 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3637 unsafe {
3638 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3639 }
3640 }
3641
3642 #[corresponds(SSL_is_init_finished)]
3644 pub fn is_init_finished(&self) -> bool {
3645 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3646 }
3647
3648 #[corresponds(SSL_set_mtu)]
3650 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3651 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_uint) as c_int).map(|_| ()) }
3652 }
3653
3654 #[corresponds(SSL_use_certificate)]
3656 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3657 unsafe {
3658 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3659 }
3660
3661 Ok(())
3662 }
3663
3664 #[corresponds(SSL_set_client_CA_list)]
3669 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3670 #[cfg(feature = "rpk")]
3671 assert!(
3672 !self.ssl_context().is_rpk(),
3673 "This API is not supported for RPK"
3674 );
3675
3676 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3677 mem::forget(list);
3678 }
3679
3680 #[corresponds(SSL_use_PrivateKey)]
3682 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
3683 where
3684 T: HasPrivate,
3685 {
3686 unsafe { cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
3687 }
3688
3689 #[corresponds(SSL_set_mode)]
3692 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
3693 let bits = unsafe { ffi::SSL_set_mode(self.as_ptr(), mode.bits()) };
3694 SslMode::from_bits_retain(bits)
3695 }
3696
3697 #[corresponds(SSL_clear_mode)]
3700 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
3701 let bits = unsafe { ffi::SSL_clear_mode(self.as_ptr(), mode.bits()) };
3702 SslMode::from_bits_retain(bits)
3703 }
3704
3705 #[corresponds(SSL_add1_chain_cert)]
3707 pub fn add_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3708 unsafe { cvt(ffi::SSL_add1_chain_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
3709 }
3710
3711 #[cfg(not(feature = "fips"))]
3719 #[corresponds(SSL_set1_ech_config_list)]
3720 pub fn set_ech_config_list(&mut self, ech_config_list: &[u8]) -> Result<(), ErrorStack> {
3721 unsafe {
3722 cvt_0i(ffi::SSL_set1_ech_config_list(
3723 self.as_ptr(),
3724 ech_config_list.as_ptr(),
3725 ech_config_list.len(),
3726 ))
3727 .map(|_| ())
3728 }
3729 }
3730
3731 #[cfg(not(feature = "fips"))]
3738 #[corresponds(SSL_get0_ech_retry_configs)]
3739 pub fn get_ech_retry_configs(&self) -> Option<&[u8]> {
3740 unsafe {
3741 let mut data = ptr::null();
3742 let mut len: usize = 0;
3743 ffi::SSL_get0_ech_retry_configs(self.as_ptr(), &mut data, &mut len);
3744
3745 if data.is_null() {
3746 None
3747 } else {
3748 Some(slice::from_raw_parts(data, len))
3749 }
3750 }
3751 }
3752
3753 #[cfg(not(feature = "fips"))]
3760 #[corresponds(SSL_get0_ech_name_override)]
3761 pub fn get_ech_name_override(&self) -> Option<&[u8]> {
3762 unsafe {
3763 let mut data: *const c_char = ptr::null();
3764 let mut len: usize = 0;
3765 ffi::SSL_get0_ech_name_override(self.as_ptr(), &mut data, &mut len);
3766
3767 if data.is_null() {
3768 None
3769 } else {
3770 Some(slice::from_raw_parts(data as *const u8, len))
3771 }
3772 }
3773 }
3774
3775 #[cfg(not(feature = "fips"))]
3777 #[corresponds(SSL_ech_accepted)]
3778 pub fn ech_accepted(&self) -> bool {
3779 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
3780 }
3781
3782 #[cfg(not(feature = "fips"))]
3784 #[corresponds(SSL_set_enable_ech_grease)]
3785 pub fn set_enable_ech_grease(&self, enable: bool) {
3786 let enable = if enable { 1 } else { 0 };
3787
3788 unsafe {
3789 ffi::SSL_set_enable_ech_grease(self.as_ptr(), enable);
3790 }
3791 }
3792
3793 #[cfg(not(feature = "fips-compat"))]
3795 #[corresponds(SSL_set_compliance_policy)]
3796 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
3797 unsafe { cvt_0i(ffi::SSL_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
3798 }
3799}
3800
3801#[derive(Debug)]
3803pub struct MidHandshakeSslStream<S> {
3804 stream: SslStream<S>,
3805 error: Error,
3806}
3807
3808impl<S> MidHandshakeSslStream<S> {
3809 pub fn get_ref(&self) -> &S {
3811 self.stream.get_ref()
3812 }
3813
3814 pub fn get_mut(&mut self) -> &mut S {
3816 self.stream.get_mut()
3817 }
3818
3819 pub fn ssl(&self) -> &SslRef {
3821 self.stream.ssl()
3822 }
3823
3824 pub fn ssl_mut(&mut self) -> &mut SslRef {
3826 self.stream.ssl_mut()
3827 }
3828
3829 pub fn error(&self) -> &Error {
3831 &self.error
3832 }
3833
3834 pub fn into_error(self) -> Error {
3836 self.error
3837 }
3838
3839 pub fn into_source_stream(self) -> S {
3841 self.stream.into_inner()
3842 }
3843
3844 pub fn into_parts(self) -> (Error, S) {
3846 (self.error, self.stream.into_inner())
3847 }
3848
3849 #[corresponds(SSL_do_handshake)]
3851 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3852 let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) };
3853 if ret > 0 {
3854 Ok(self.stream)
3855 } else {
3856 self.error = self.stream.make_error(ret);
3857 match self.error.would_block() {
3858 true => Err(HandshakeError::WouldBlock(self)),
3859 false => Err(HandshakeError::Failure(self)),
3860 }
3861 }
3862 }
3863}
3864
3865pub struct SslStream<S> {
3867 ssl: ManuallyDrop<Ssl>,
3868 method: ManuallyDrop<BioMethod>,
3869 _p: PhantomData<S>,
3870}
3871
3872impl<S> Drop for SslStream<S> {
3873 fn drop(&mut self) {
3874 unsafe {
3876 ManuallyDrop::drop(&mut self.ssl);
3877 ManuallyDrop::drop(&mut self.method);
3878 }
3879 }
3880}
3881
3882impl<S> fmt::Debug for SslStream<S>
3883where
3884 S: fmt::Debug,
3885{
3886 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
3887 fmt.debug_struct("SslStream")
3888 .field("stream", &self.get_ref())
3889 .field("ssl", &self.ssl())
3890 .finish()
3891 }
3892}
3893
3894impl<S: Read + Write> SslStream<S> {
3895 fn new_base(ssl: Ssl, stream: S) -> Self {
3896 unsafe {
3897 let (bio, method) = bio::new(stream).unwrap();
3898 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3899
3900 SslStream {
3901 ssl: ManuallyDrop::new(ssl),
3902 method: ManuallyDrop::new(method),
3903 _p: PhantomData,
3904 }
3905 }
3906 }
3907
3908 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3914 Ok(Self::new_base(ssl, stream))
3915 }
3916
3917 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3925 let ssl = Ssl::from_ptr(ssl);
3926 Self::new_base(ssl, stream)
3927 }
3928
3929 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3936 loop {
3937 match self.ssl_read_uninit(buf) {
3938 Ok(n) => return Ok(n),
3939 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3940 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3941 return Ok(0);
3942 }
3943 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3944 Err(e) => {
3945 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
3946 }
3947 }
3948 }
3949 }
3950
3951 #[corresponds(SSL_read)]
3956 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3957 unsafe {
3959 self.ssl_read_uninit(slice::from_raw_parts_mut(
3960 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3961 buf.len(),
3962 ))
3963 }
3964 }
3965
3966 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3973 if buf.is_empty() {
3974 return Ok(0);
3975 }
3976
3977 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3978 let ret = unsafe { ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) };
3979 if ret > 0 {
3980 Ok(ret as usize)
3981 } else {
3982 Err(self.make_error(ret))
3983 }
3984 }
3985
3986 #[corresponds(SSL_write)]
3991 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3992 if buf.is_empty() {
3993 return Ok(0);
3994 }
3995
3996 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3997 let ret = unsafe { ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) };
3998 if ret > 0 {
3999 Ok(ret as usize)
4000 } else {
4001 Err(self.make_error(ret))
4002 }
4003 }
4004
4005 #[corresponds(SSL_shutdown)]
4015 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4016 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4017 0 => Ok(ShutdownResult::Sent),
4018 1 => Ok(ShutdownResult::Received),
4019 n => Err(self.make_error(n)),
4020 }
4021 }
4022
4023 #[corresponds(SSL_get_shutdown)]
4025 pub fn get_shutdown(&mut self) -> ShutdownState {
4026 unsafe {
4027 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4028 ShutdownState::from_bits_retain(bits)
4029 }
4030 }
4031
4032 #[corresponds(SSL_set_shutdown)]
4037 pub fn set_shutdown(&mut self, state: ShutdownState) {
4038 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4039 }
4040
4041 #[corresponds(SSL_connect)]
4043 pub fn connect(&mut self) -> Result<(), Error> {
4044 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4045 if ret > 0 {
4046 Ok(())
4047 } else {
4048 Err(self.make_error(ret))
4049 }
4050 }
4051
4052 #[corresponds(SSL_accept)]
4054 pub fn accept(&mut self) -> Result<(), Error> {
4055 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4056 if ret > 0 {
4057 Ok(())
4058 } else {
4059 Err(self.make_error(ret))
4060 }
4061 }
4062
4063 #[corresponds(SSL_do_handshake)]
4065 pub fn do_handshake(&mut self) -> Result<(), Error> {
4066 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4067 if ret > 0 {
4068 Ok(())
4069 } else {
4070 Err(self.make_error(ret))
4071 }
4072 }
4073}
4074
4075impl<S> SslStream<S> {
4076 fn make_error(&mut self, ret: c_int) -> Error {
4077 self.check_panic();
4078
4079 let code = self.ssl.error_code(ret);
4080
4081 let cause = match code {
4082 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4083 ErrorCode::SYSCALL => {
4084 let errs = ErrorStack::get();
4085 if errs.errors().is_empty() {
4086 self.get_bio_error().map(InnerError::Io)
4087 } else {
4088 Some(InnerError::Ssl(errs))
4089 }
4090 }
4091 ErrorCode::ZERO_RETURN => None,
4092 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4093 self.get_bio_error().map(InnerError::Io)
4094 }
4095 _ => None,
4096 };
4097
4098 Error { code, cause }
4099 }
4100
4101 fn check_panic(&mut self) {
4102 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4103 resume_unwind(err)
4104 }
4105 }
4106
4107 fn get_bio_error(&mut self) -> Option<io::Error> {
4108 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4109 }
4110
4111 pub fn into_inner(self) -> S {
4113 unsafe { bio::take_stream::<S>(self.ssl.get_raw_rbio()) }
4114 }
4115
4116 pub fn get_ref(&self) -> &S {
4118 unsafe {
4119 let bio = self.ssl.get_raw_rbio();
4120 bio::get_ref(bio)
4121 }
4122 }
4123
4124 pub fn get_mut(&mut self) -> &mut S {
4131 unsafe {
4132 let bio = self.ssl.get_raw_rbio();
4133 bio::get_mut(bio)
4134 }
4135 }
4136
4137 pub fn ssl(&self) -> &SslRef {
4139 &self.ssl
4140 }
4141
4142 pub fn ssl_mut(&mut self) -> &mut SslRef {
4144 &mut self.ssl
4145 }
4146}
4147
4148impl<S: Read + Write> Read for SslStream<S> {
4149 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4150 unsafe {
4152 self.read_uninit(slice::from_raw_parts_mut(
4153 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4154 buf.len(),
4155 ))
4156 }
4157 }
4158}
4159
4160impl<S: Read + Write> Write for SslStream<S> {
4161 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4162 loop {
4163 match self.ssl_write(buf) {
4164 Ok(n) => return Ok(n),
4165 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4166 Err(e) => {
4167 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4168 }
4169 }
4170 }
4171 }
4172
4173 fn flush(&mut self) -> io::Result<()> {
4174 self.get_mut().flush()
4175 }
4176}
4177
4178pub struct SslStreamBuilder<S> {
4180 inner: SslStream<S>,
4181}
4182
4183impl<S> SslStreamBuilder<S>
4184where
4185 S: Read + Write,
4186{
4187 pub fn new(ssl: Ssl, stream: S) -> Self {
4189 Self {
4190 inner: SslStream::new_base(ssl, stream),
4191 }
4192 }
4193
4194 #[corresponds(SSL_set_connect_state)]
4196 pub fn set_connect_state(&mut self) {
4197 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4198 }
4199
4200 #[corresponds(SSL_set_accept_state)]
4202 pub fn set_accept_state(&mut self) {
4203 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4204 }
4205
4206 pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
4212 self.set_connect_state();
4213
4214 #[cfg(feature = "kx-safe-default")]
4215 self.inner.ssl.client_set_default_curves_list();
4216
4217 MidHandshakeSslStream {
4218 stream: self.inner,
4219 error: Error {
4220 code: ErrorCode::WANT_WRITE,
4221 cause: Some(InnerError::Io(io::Error::new(
4222 io::ErrorKind::WouldBlock,
4223 "connect handshake has not started yet",
4224 ))),
4225 },
4226 }
4227 }
4228
4229 pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
4234 self.setup_connect().handshake()
4235 }
4236
4237 pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
4243 self.set_accept_state();
4244
4245 #[cfg(feature = "kx-safe-default")]
4246 self.inner.ssl.server_set_default_curves_list();
4247
4248 MidHandshakeSslStream {
4249 stream: self.inner,
4250 error: Error {
4251 code: ErrorCode::WANT_READ,
4252 cause: Some(InnerError::Io(io::Error::new(
4253 io::ErrorKind::WouldBlock,
4254 "accept handshake has not started yet",
4255 ))),
4256 },
4257 }
4258 }
4259
4260 pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
4265 self.setup_accept().handshake()
4266 }
4267
4268 #[corresponds(SSL_do_handshake)]
4272 pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
4273 let mut stream = self.inner;
4274 let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
4275 if ret > 0 {
4276 Ok(stream)
4277 } else {
4278 let error = stream.make_error(ret);
4279 match error.would_block() {
4280 true => Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4281 stream,
4282 error,
4283 })),
4284 false => Err(HandshakeError::Failure(MidHandshakeSslStream {
4285 stream,
4286 error,
4287 })),
4288 }
4289 }
4290 }
4291}
4292
4293impl<S> SslStreamBuilder<S> {
4294 pub fn get_ref(&self) -> &S {
4296 unsafe {
4297 let bio = self.inner.ssl.get_raw_rbio();
4298 bio::get_ref(bio)
4299 }
4300 }
4301
4302 pub fn get_mut(&mut self) -> &mut S {
4309 unsafe {
4310 let bio = self.inner.ssl.get_raw_rbio();
4311 bio::get_mut(bio)
4312 }
4313 }
4314
4315 pub fn ssl(&self) -> &SslRef {
4317 &self.inner.ssl
4318 }
4319
4320 pub fn ssl_mut(&mut self) -> &mut SslRef {
4322 &mut self.inner.ssl
4323 }
4324
4325 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4333 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4334 unsafe {
4335 let bio = self.inner.ssl.get_raw_rbio();
4336 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4337 }
4338 }
4339}
4340
4341#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4343pub enum ShutdownResult {
4344 Sent,
4346
4347 Received,
4349}
4350
4351bitflags! {
4352 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
4354 pub struct ShutdownState: c_int {
4355 const SENT = ffi::SSL_SENT_SHUTDOWN;
4357 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4359 }
4360}
4361
4362pub trait PrivateKeyMethod: Send + Sync + 'static {
4370 fn sign(
4381 &self,
4382 ssl: &mut SslRef,
4383 input: &[u8],
4384 signature_algorithm: SslSignatureAlgorithm,
4385 output: &mut [u8],
4386 ) -> Result<usize, PrivateKeyMethodError>;
4387
4388 fn decrypt(
4403 &self,
4404 ssl: &mut SslRef,
4405 input: &[u8],
4406 output: &mut [u8],
4407 ) -> Result<usize, PrivateKeyMethodError>;
4408
4409 fn complete(&self, ssl: &mut SslRef, output: &mut [u8])
4418 -> Result<usize, PrivateKeyMethodError>;
4419}
4420
4421#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4423pub struct PrivateKeyMethodError(ffi::ssl_private_key_result_t);
4424
4425impl PrivateKeyMethodError {
4426 pub const FAILURE: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_failure);
4428
4429 pub const RETRY: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_retry);
4431}
4432
4433pub trait CertificateCompressor: Send + Sync + 'static {
4435 const ALGORITHM: CertificateCompressionAlgorithm;
4437
4438 const CAN_COMPRESS: bool;
4440
4441 const CAN_DECOMPRESS: bool;
4443
4444 #[allow(unused_variables)]
4446 fn compress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4447 where
4448 W: std::io::Write,
4449 {
4450 Err(std::io::Error::other("not implemented"))
4451 }
4452
4453 #[allow(unused_variables)]
4455 fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4456 where
4457 W: std::io::Write,
4458 {
4459 Err(std::io::Error::other("not implemented"))
4460 }
4461}
4462
4463use crate::ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4464
4465use crate::ffi::{DTLS_method, TLS_client_method, TLS_method, TLS_server_method};
4466
4467use std::sync::Once;
4468
4469unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4470 static ONCE: Once = Once::new();
4472 ONCE.call_once(|| {
4473 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4474 });
4475
4476 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4477}
4478
4479unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4480 static ONCE: Once = Once::new();
4482 ONCE.call_once(|| {
4483 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4484 });
4485
4486 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4487}