1use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
61use openssl_macros::corresponds;
62use std::any::TypeId;
63use std::collections::HashMap;
64use std::convert::TryInto;
65use std::ffi::{c_char, c_int, c_uchar, c_uint};
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;
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::hmac::HmacCtxRef;
85use crate::nid::Nid;
86#[cfg(feature = "rpk")]
87use crate::pkey::Public;
88use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
89use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
90use crate::ssl::bio::BioMethod;
91use crate::ssl::callbacks::*;
92use crate::ssl::error::InnerError;
93use crate::stack::{Stack, StackRef, Stackable};
94use crate::symm::CipherCtxRef;
95use crate::try_int;
96use crate::x509::store::{X509Store, X509StoreBuilder, X509StoreBuilderRef, X509StoreRef};
97use crate::x509::verify::X509VerifyParamRef;
98use crate::x509::{
99 X509Name, X509Ref, X509StoreContextRef, X509VerifyError, X509VerifyResult, X509,
100};
101use crate::{cvt, cvt_0i, cvt_n, cvt_p, init};
102use crate::{ffi, free_data_box};
103
104pub use self::async_callbacks::{
105 AsyncPrivateKeyMethod, AsyncPrivateKeyMethodError, AsyncSelectCertError, BoxCustomVerifyFinish,
106 BoxCustomVerifyFuture, BoxGetSessionFinish, BoxGetSessionFuture, BoxPrivateKeyMethodFinish,
107 BoxPrivateKeyMethodFuture, BoxSelectCertFinish, BoxSelectCertFuture, ExDataFuture,
108};
109pub use self::connector::{
110 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
111};
112#[cfg(feature = "credential")]
113pub use self::credential::{SslCredential, SslCredentialBuilder, SslCredentialRef};
114pub use self::ech::{SslEchKeys, SslEchKeysRef};
115pub use self::error::{Error, ErrorCode, HandshakeError};
116
117mod async_callbacks;
118mod bio;
119mod callbacks;
120mod connector;
121#[cfg(feature = "credential")]
122mod credential;
123mod ech;
124mod error;
125mod mut_only;
126#[cfg(test)]
127mod test;
128
129bitflags! {
130 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
132 pub struct SslOptions: c_uint {
133 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as _;
135
136 const ALL = ffi::SSL_OP_ALL as _;
138
139 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as _;
143
144 const NO_TICKET = ffi::SSL_OP_NO_TICKET as _;
146
147 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
149 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as _;
150
151 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as _;
153
154 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
157 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as _;
158
159 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as _;
161
162 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as _;
164
165 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as _;
169
170 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as _;
172
173 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as _;
175
176 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as _;
178
179 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as _;
181
182 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as _;
184
185 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as _;
187
188 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as _;
190
191 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as _;
193
194 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as _;
196
197 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as _;
199 }
200}
201
202bitflags! {
203 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
205 pub struct SslMode: c_uint {
206 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE as _;
212
213 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as _;
216
217 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY as _;
227
228 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN as _;
234
235 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS as _;
239
240 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV as _;
248 }
249}
250
251#[derive(Copy, Clone)]
253pub struct SslMethod {
254 ptr: *const ffi::SSL_METHOD,
255 is_x509_method: bool,
256}
257
258impl SslMethod {
259 #[corresponds(TLS_method)]
261 #[must_use]
262 pub fn tls() -> Self {
263 unsafe {
264 Self {
265 ptr: ffi::TLS_method(),
266 is_x509_method: true,
267 }
268 }
269 }
270
271 #[must_use]
279 pub unsafe fn tls_with_buffer() -> Self {
280 unsafe {
281 Self {
282 ptr: ffi::TLS_with_buffers_method(),
283 is_x509_method: false,
284 }
285 }
286 }
287
288 #[corresponds(DTLS_method)]
290 #[must_use]
291 pub fn dtls() -> Self {
292 unsafe {
293 Self {
294 ptr: ffi::DTLS_method(),
295 is_x509_method: true,
296 }
297 }
298 }
299
300 #[corresponds(TLS_server_method)]
310 #[must_use]
311 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
312 SslMethod {
313 ptr,
314 is_x509_method: false,
315 }
316 }
317
318 pub unsafe fn assume_x509(&mut self) {
326 self.is_x509_method = true;
327 }
328
329 #[allow(clippy::trivially_copy_pass_by_ref)]
331 #[must_use]
332 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
333 self.ptr
334 }
335}
336
337unsafe impl Sync for SslMethod {}
338unsafe impl Send for SslMethod {}
339
340bitflags! {
341 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
343 pub struct SslVerifyMode: i32 {
344 const PEER = ffi::SSL_VERIFY_PEER;
348
349 const NONE = ffi::SSL_VERIFY_NONE;
355
356 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
360 }
361}
362
363#[derive(Clone, Copy, Debug, Eq, PartialEq)]
364pub enum SslVerifyError {
365 Invalid(SslAlert),
366 Retry,
367}
368
369bitflags! {
370 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
372 pub struct SslSessionCacheMode: c_int {
373 const OFF = ffi::SSL_SESS_CACHE_OFF;
375
376 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
383
384 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
388
389 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
391
392 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
394
395 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
397
398 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
400
401 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
403 }
404}
405
406#[derive(Copy, Clone)]
408pub struct SslFiletype(c_int);
409
410impl SslFiletype {
411 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
415
416 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
420
421 #[must_use]
423 pub fn from_raw(raw: c_int) -> SslFiletype {
424 SslFiletype(raw)
425 }
426
427 #[allow(clippy::trivially_copy_pass_by_ref)]
429 #[must_use]
430 pub fn as_raw(&self) -> c_int {
431 self.0
432 }
433}
434
435#[derive(Copy, Clone)]
437pub struct StatusType(c_int);
438
439impl StatusType {
440 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
442
443 #[must_use]
445 pub fn from_raw(raw: c_int) -> StatusType {
446 StatusType(raw)
447 }
448
449 #[allow(clippy::trivially_copy_pass_by_ref)]
451 #[must_use]
452 pub fn as_raw(&self) -> c_int {
453 self.0
454 }
455}
456
457#[derive(Copy, Clone)]
459pub struct NameType(c_int);
460
461impl NameType {
462 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
464
465 #[must_use]
467 pub fn from_raw(raw: c_int) -> StatusType {
468 StatusType(raw)
469 }
470
471 #[allow(clippy::trivially_copy_pass_by_ref)]
473 #[must_use]
474 pub fn as_raw(&self) -> c_int {
475 self.0
476 }
477}
478
479static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
480 LazyLock::new(|| Mutex::new(HashMap::new()));
481static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
482 LazyLock::new(|| Mutex::new(HashMap::new()));
483static SESSION_CTX_INDEX: LazyLock<Index<Ssl, SslContext>> =
484 LazyLock::new(|| Ssl::new_ex_index().unwrap());
485static X509_FLAG_INDEX: LazyLock<Index<SslContext, bool>> =
486 LazyLock::new(|| SslContext::new_ex_index().unwrap());
487
488#[derive(Debug, Copy, Clone, PartialEq, Eq)]
490pub struct SniError(c_int);
491
492impl SniError {
493 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
495
496 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
498
499 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
500}
501
502#[derive(Debug, Copy, Clone, PartialEq, Eq)]
504pub struct SslAlert(c_int);
505
506impl SslAlert {
507 pub const CLOSE_NOTIFY: Self = Self(ffi::SSL_AD_CLOSE_NOTIFY);
508 pub const UNEXPECTED_MESSAGE: Self = Self(ffi::SSL_AD_UNEXPECTED_MESSAGE);
509 pub const BAD_RECORD_MAC: Self = Self(ffi::SSL_AD_BAD_RECORD_MAC);
510 pub const DECRYPTION_FAILED: Self = Self(ffi::SSL_AD_DECRYPTION_FAILED);
511 pub const RECORD_OVERFLOW: Self = Self(ffi::SSL_AD_RECORD_OVERFLOW);
512 pub const DECOMPRESSION_FAILURE: Self = Self(ffi::SSL_AD_DECOMPRESSION_FAILURE);
513 pub const HANDSHAKE_FAILURE: Self = Self(ffi::SSL_AD_HANDSHAKE_FAILURE);
514 pub const NO_CERTIFICATE: Self = Self(ffi::SSL_AD_NO_CERTIFICATE);
515 pub const BAD_CERTIFICATE: Self = Self(ffi::SSL_AD_BAD_CERTIFICATE);
516 pub const UNSUPPORTED_CERTIFICATE: Self = Self(ffi::SSL_AD_UNSUPPORTED_CERTIFICATE);
517 pub const CERTIFICATE_REVOKED: Self = Self(ffi::SSL_AD_CERTIFICATE_REVOKED);
518 pub const CERTIFICATE_EXPIRED: Self = Self(ffi::SSL_AD_CERTIFICATE_EXPIRED);
519 pub const CERTIFICATE_UNKNOWN: Self = Self(ffi::SSL_AD_CERTIFICATE_UNKNOWN);
520 pub const ILLEGAL_PARAMETER: Self = Self(ffi::SSL_AD_ILLEGAL_PARAMETER);
521 pub const UNKNOWN_CA: Self = Self(ffi::SSL_AD_UNKNOWN_CA);
522 pub const ACCESS_DENIED: Self = Self(ffi::SSL_AD_ACCESS_DENIED);
523 pub const DECODE_ERROR: Self = Self(ffi::SSL_AD_DECODE_ERROR);
524 pub const DECRYPT_ERROR: Self = Self(ffi::SSL_AD_DECRYPT_ERROR);
525 pub const EXPORT_RESTRICTION: Self = Self(ffi::SSL_AD_EXPORT_RESTRICTION);
526 pub const PROTOCOL_VERSION: Self = Self(ffi::SSL_AD_PROTOCOL_VERSION);
527 pub const INSUFFICIENT_SECURITY: Self = Self(ffi::SSL_AD_INSUFFICIENT_SECURITY);
528 pub const INTERNAL_ERROR: Self = Self(ffi::SSL_AD_INTERNAL_ERROR);
529 pub const INAPPROPRIATE_FALLBACK: Self = Self(ffi::SSL_AD_INAPPROPRIATE_FALLBACK);
530 pub const USER_CANCELLED: Self = Self(ffi::SSL_AD_USER_CANCELLED);
531 pub const NO_RENEGOTIATION: Self = Self(ffi::SSL_AD_NO_RENEGOTIATION);
532 pub const MISSING_EXTENSION: Self = Self(ffi::SSL_AD_MISSING_EXTENSION);
533 pub const UNSUPPORTED_EXTENSION: Self = Self(ffi::SSL_AD_UNSUPPORTED_EXTENSION);
534 pub const CERTIFICATE_UNOBTAINABLE: Self = Self(ffi::SSL_AD_CERTIFICATE_UNOBTAINABLE);
535 pub const UNRECOGNIZED_NAME: Self = Self(ffi::SSL_AD_UNRECOGNIZED_NAME);
536 pub const BAD_CERTIFICATE_STATUS_RESPONSE: Self =
537 Self(ffi::SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
538 pub const BAD_CERTIFICATE_HASH_VALUE: Self = Self(ffi::SSL_AD_BAD_CERTIFICATE_HASH_VALUE);
539 pub const UNKNOWN_PSK_IDENTITY: Self = Self(ffi::SSL_AD_UNKNOWN_PSK_IDENTITY);
540 pub const CERTIFICATE_REQUIRED: Self = Self(ffi::SSL_AD_CERTIFICATE_REQUIRED);
541 pub const NO_APPLICATION_PROTOCOL: Self = Self(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
542}
543
544#[derive(Debug, Copy, Clone, PartialEq, Eq)]
546pub struct AlpnError(c_int);
547
548impl AlpnError {
549 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
551
552 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
554}
555
556#[derive(Debug, Copy, Clone, PartialEq, Eq)]
558pub struct SelectCertError(ffi::ssl_select_cert_result_t);
559
560impl SelectCertError {
561 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_error);
563
564 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_retry);
566}
567
568#[derive(Debug, Copy, Clone, PartialEq, Eq)]
574pub struct ExtensionType(u16);
575
576impl ExtensionType {
577 pub const SERVER_NAME: Self = Self(ffi::TLSEXT_TYPE_server_name as u16);
578 pub const STATUS_REQUEST: Self = Self(ffi::TLSEXT_TYPE_status_request as u16);
579 pub const EC_POINT_FORMATS: Self = Self(ffi::TLSEXT_TYPE_ec_point_formats as u16);
580 pub const SIGNATURE_ALGORITHMS: Self = Self(ffi::TLSEXT_TYPE_signature_algorithms as u16);
581 pub const SRTP: Self = Self(ffi::TLSEXT_TYPE_srtp as u16);
582 pub const APPLICATION_LAYER_PROTOCOL_NEGOTIATION: Self =
583 Self(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as u16);
584 pub const PADDING: Self = Self(ffi::TLSEXT_TYPE_padding as u16);
585 pub const EXTENDED_MASTER_SECRET: Self = Self(ffi::TLSEXT_TYPE_extended_master_secret as u16);
586 pub const QUIC_TRANSPORT_PARAMETERS_LEGACY: Self =
587 Self(ffi::TLSEXT_TYPE_quic_transport_parameters_legacy as u16);
588 pub const QUIC_TRANSPORT_PARAMETERS_STANDARD: Self =
589 Self(ffi::TLSEXT_TYPE_quic_transport_parameters_standard as u16);
590 pub const CERT_COMPRESSION: Self = Self(ffi::TLSEXT_TYPE_cert_compression as u16);
591 pub const SESSION_TICKET: Self = Self(ffi::TLSEXT_TYPE_session_ticket as u16);
592 pub const SUPPORTED_GROUPS: Self = Self(ffi::TLSEXT_TYPE_supported_groups as u16);
593 pub const PRE_SHARED_KEY: Self = Self(ffi::TLSEXT_TYPE_pre_shared_key as u16);
594 pub const EARLY_DATA: Self = Self(ffi::TLSEXT_TYPE_early_data as u16);
595 pub const SUPPORTED_VERSIONS: Self = Self(ffi::TLSEXT_TYPE_supported_versions as u16);
596 pub const COOKIE: Self = Self(ffi::TLSEXT_TYPE_cookie as u16);
597 pub const PSK_KEY_EXCHANGE_MODES: Self = Self(ffi::TLSEXT_TYPE_psk_key_exchange_modes as u16);
598 pub const CERTIFICATE_AUTHORITIES: Self = Self(ffi::TLSEXT_TYPE_certificate_authorities as u16);
599 pub const SIGNATURE_ALGORITHMS_CERT: Self =
600 Self(ffi::TLSEXT_TYPE_signature_algorithms_cert as u16);
601 pub const KEY_SHARE: Self = Self(ffi::TLSEXT_TYPE_key_share as u16);
602 pub const RENEGOTIATE: Self = Self(ffi::TLSEXT_TYPE_renegotiate as u16);
603 pub const DELEGATED_CREDENTIAL: Self = Self(ffi::TLSEXT_TYPE_delegated_credential as u16);
604 pub const APPLICATION_SETTINGS: Self = Self(ffi::TLSEXT_TYPE_application_settings as u16);
605 pub const ENCRYPTED_CLIENT_HELLO: Self = Self(ffi::TLSEXT_TYPE_encrypted_client_hello as u16);
606 pub const CERTIFICATE_TIMESTAMP: Self = Self(ffi::TLSEXT_TYPE_certificate_timestamp as u16);
607 pub const NEXT_PROTO_NEG: Self = Self(ffi::TLSEXT_TYPE_next_proto_neg as u16);
608 pub const CHANNEL_ID: Self = Self(ffi::TLSEXT_TYPE_channel_id as u16);
609}
610
611impl From<u16> for ExtensionType {
612 fn from(value: u16) -> Self {
613 Self(value)
614 }
615}
616
617#[derive(Copy, Clone, PartialEq, Eq)]
619pub struct SslVersion(u16);
620
621impl SslVersion {
622 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION as _);
624
625 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION as _);
627
628 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION as _);
630
631 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION as _);
633
634 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION as _);
636
637 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION as _);
639
640 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION as _);
642
643 pub const DTLS1_3: SslVersion = SslVersion(ffi::DTLS1_3_VERSION as _);
645}
646
647impl TryFrom<u16> for SslVersion {
648 type Error = &'static str;
649
650 fn try_from(value: u16) -> Result<Self, Self::Error> {
651 match i32::from(value) {
652 ffi::SSL3_VERSION
653 | ffi::TLS1_VERSION
654 | ffi::TLS1_1_VERSION
655 | ffi::TLS1_2_VERSION
656 | ffi::TLS1_3_VERSION
657 | ffi::DTLS1_VERSION
658 | ffi::DTLS1_2_VERSION
659 | ffi::DTLS1_3_VERSION => Ok(Self(value)),
660 _ => Err("Unknown SslVersion"),
661 }
662 }
663}
664
665impl fmt::Debug for SslVersion {
666 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
667 f.write_str(match *self {
668 Self::SSL3 => "SSL3",
669 Self::TLS1 => "TLS1",
670 Self::TLS1_1 => "TLS1_1",
671 Self::TLS1_2 => "TLS1_2",
672 Self::TLS1_3 => "TLS1_3",
673 Self::DTLS1 => "DTLS1",
674 Self::DTLS1_2 => "DTLS1_2",
675 Self::DTLS1_3 => "DTLS1_3",
676 _ => return write!(f, "{:#06x}", self.0),
677 })
678 }
679}
680
681impl fmt::Display for SslVersion {
682 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
683 f.write_str(match *self {
684 Self::SSL3 => "SSLv3",
685 Self::TLS1 => "TLSv1",
686 Self::TLS1_1 => "TLSv1.1",
687 Self::TLS1_2 => "TLSv1.2",
688 Self::TLS1_3 => "TLSv1.3",
689 Self::DTLS1 => "DTLSv1.0",
690 Self::DTLS1_2 => "DTLSv1.2",
691 Self::DTLS1_3 => "DTLSv1.3",
692 _ => return write!(f, "unknown ({:#06x})", self.0),
693 })
694 }
695}
696
697#[repr(transparent)]
703#[derive(Debug, Copy, Clone, PartialEq, Eq)]
704pub struct SslSignatureAlgorithm(u16);
705
706impl SslSignatureAlgorithm {
707 pub const RSA_PKCS1_SHA1: SslSignatureAlgorithm =
708 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA1 as _);
709
710 pub const RSA_PKCS1_SHA256: SslSignatureAlgorithm =
711 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA256 as _);
712
713 pub const RSA_PKCS1_SHA384: SslSignatureAlgorithm =
714 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA384 as _);
715
716 pub const RSA_PKCS1_SHA512: SslSignatureAlgorithm =
717 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA512 as _);
718
719 pub const RSA_PKCS1_MD5_SHA1: SslSignatureAlgorithm =
720 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_MD5_SHA1 as _);
721
722 pub const ECDSA_SHA1: SslSignatureAlgorithm =
723 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SHA1 as _);
724
725 pub const ECDSA_SECP256R1_SHA256: SslSignatureAlgorithm =
726 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP256R1_SHA256 as _);
727
728 pub const ECDSA_SECP384R1_SHA384: SslSignatureAlgorithm =
729 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP384R1_SHA384 as _);
730
731 pub const ECDSA_SECP521R1_SHA512: SslSignatureAlgorithm =
732 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP521R1_SHA512 as _);
733
734 pub const RSA_PSS_RSAE_SHA256: SslSignatureAlgorithm =
735 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA256 as _);
736
737 pub const RSA_PSS_RSAE_SHA384: SslSignatureAlgorithm =
738 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA384 as _);
739
740 pub const RSA_PSS_RSAE_SHA512: SslSignatureAlgorithm =
741 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA512 as _);
742
743 pub const ED25519: SslSignatureAlgorithm = SslSignatureAlgorithm(ffi::SSL_SIGN_ED25519 as _);
744
745 pub const ML_DSA_44: SslSignatureAlgorithm = SslSignatureAlgorithm(0x0904);
749
750 pub const ML_DSA_65: SslSignatureAlgorithm = SslSignatureAlgorithm(0x0905);
751
752 pub const ML_DSA_87: SslSignatureAlgorithm = SslSignatureAlgorithm(0x0906);
753
754 #[corresponds(SSL_get_signature_algorithm_name)]
759 #[must_use]
760 pub fn name(&self) -> Option<&'static str> {
761 unsafe {
762 let ptr = ffi::SSL_get_signature_algorithm_name(self.0, 1);
765 if ptr.is_null() {
766 None
767 } else {
768 CStr::from_ptr(ptr).to_str().ok()
769 }
770 }
771 }
772}
773
774impl fmt::Display for SslSignatureAlgorithm {
775 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
776 match self.name() {
777 Some(name) => f.write_str(name),
778 None => write!(f, "unknown ({:#06x})", self.0),
779 }
780 }
781}
782
783impl From<u16> for SslSignatureAlgorithm {
784 fn from(value: u16) -> Self {
785 Self(value)
786 }
787}
788
789#[derive(Debug, Copy, Clone, PartialEq, Eq)]
791pub struct CompliancePolicy(ffi::ssl_compliance_policy_t);
792
793impl CompliancePolicy {
794 #[cfg(not(feature = "legacy-compat-deprecated"))]
796 pub const NONE: Self = Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_none);
797
798 pub const FIPS_202205: Self =
801 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_fips_202205);
802
803 #[cfg(not(feature = "legacy-compat-deprecated"))]
806 pub const WPA3_192_202304: Self =
807 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_wpa3_192_202304);
808}
809
810#[derive(Debug, Copy, Clone, PartialEq, Eq)]
812pub struct CertificateCompressionAlgorithm(u16);
813
814impl CertificateCompressionAlgorithm {
815 pub const ZLIB: Self = Self(ffi::TLSEXT_cert_compression_zlib as u16);
816
817 pub const BROTLI: Self = Self(ffi::TLSEXT_cert_compression_brotli as u16);
818}
819
820#[corresponds(SSL_select_next_proto)]
831#[must_use]
832pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
833 if server.is_empty() || client.is_empty() {
834 return None;
835 }
836
837 unsafe {
838 let mut out = ptr::null_mut();
839 let mut outlen = 0;
840 let r = ffi::SSL_select_next_proto(
841 &mut out,
842 &mut outlen,
843 server.as_ptr(),
844 try_int(server.len()).ok()?,
845 client.as_ptr(),
846 try_int(client.len()).ok()?,
847 );
848
849 if r == ffi::OPENSSL_NPN_NEGOTIATED {
850 Some(slice::from_raw_parts(out.cast_const(), outlen as usize))
851 } else {
852 None
853 }
854 }
855}
856
857#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
859pub struct SslInfoCallbackMode(i32);
860
861impl SslInfoCallbackMode {
862 pub const READ_ALERT: Self = Self(ffi::SSL_CB_READ_ALERT);
864
865 pub const WRITE_ALERT: Self = Self(ffi::SSL_CB_WRITE_ALERT);
867
868 pub const HANDSHAKE_START: Self = Self(ffi::SSL_CB_HANDSHAKE_START);
870
871 pub const HANDSHAKE_DONE: Self = Self(ffi::SSL_CB_HANDSHAKE_DONE);
873
874 pub const ACCEPT_LOOP: Self = Self(ffi::SSL_CB_ACCEPT_LOOP);
876
877 pub const ACCEPT_EXIT: Self = Self(ffi::SSL_CB_ACCEPT_EXIT);
879
880 pub const CONNECT_EXIT: Self = Self(ffi::SSL_CB_CONNECT_EXIT);
882}
883
884#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
887pub enum SslInfoCallbackValue {
888 Unit,
892 Alert(SslInfoCallbackAlert),
896}
897
898#[derive(Debug, Copy, Clone, PartialEq, Eq)]
900pub enum TicketKeyCallbackResult {
901 Error,
903
904 Noop,
913
914 Success,
919
920 DecryptSuccessRenew,
932}
933
934impl From<TicketKeyCallbackResult> for c_int {
935 fn from(value: TicketKeyCallbackResult) -> Self {
936 match value {
937 TicketKeyCallbackResult::Error => -1,
938 TicketKeyCallbackResult::Noop => 0,
939 TicketKeyCallbackResult::Success => 1,
940 TicketKeyCallbackResult::DecryptSuccessRenew => 2,
941 }
942 }
943}
944
945#[derive(Hash, Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
946pub struct SslInfoCallbackAlert(c_int);
947
948impl SslInfoCallbackAlert {
949 #[must_use]
951 pub fn alert_level(&self) -> Ssl3AlertLevel {
952 let value = self.0 >> 8;
953 Ssl3AlertLevel(value)
954 }
955
956 #[must_use]
958 pub fn alert(&self) -> SslAlert {
959 let value = self.0 & i32::from(u8::MAX);
960 SslAlert(value)
961 }
962}
963
964#[derive(Debug, Copy, Clone, PartialEq, Eq)]
965pub struct Ssl3AlertLevel(c_int);
966
967impl Ssl3AlertLevel {
968 pub const WARNING: Ssl3AlertLevel = Self(ffi::SSL3_AL_WARNING);
969 pub const FATAL: Ssl3AlertLevel = Self(ffi::SSL3_AL_FATAL);
970}
971
972pub struct SslContextBuilder {
974 ctx: SslContext,
975 has_shared_cert_store: bool,
977}
978
979impl SslContextBuilder {
980 #[corresponds(SSL_CTX_new)]
982 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
983 unsafe {
984 init();
985 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
986 let mut builder = SslContextBuilder::from_ptr(ctx);
987
988 if method.is_x509_method {
989 builder.ctx.assume_x509();
990 }
991
992 Ok(builder)
993 }
994 }
995
996 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> Self {
1008 Self {
1009 ctx: unsafe { SslContext::from_ptr(ctx) },
1010 has_shared_cert_store: false,
1011 }
1012 }
1013
1014 pub unsafe fn assume_x509(&mut self) {
1022 unsafe {
1023 self.ctx.assume_x509();
1024 }
1025 }
1026
1027 #[must_use]
1029 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
1030 self.ctx.as_ptr()
1031 }
1032
1033 #[corresponds(SSL_CTX_set_cert_verify_callback)]
1053 pub fn set_cert_verify_callback<F>(&mut self, callback: F)
1054 where
1055 F: Fn(&mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1056 {
1057 self.ctx.check_x509();
1058
1059 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1066 unsafe {
1067 ffi::SSL_CTX_set_cert_verify_callback(
1068 self.as_ptr(),
1069 Some(raw_cert_verify::<F>),
1070 ptr::null_mut(),
1071 );
1072 }
1073 }
1074
1075 #[corresponds(SSL_CTX_set_verify)]
1077 pub fn set_verify(&mut self, mode: SslVerifyMode) {
1078 self.ctx.check_x509();
1079
1080 unsafe {
1081 ffi::SSL_CTX_set_verify(self.as_ptr(), c_int::from(mode.bits()), None);
1082 }
1083 }
1084
1085 #[corresponds(SSL_CTX_set_verify)]
1102 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1103 where
1104 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1105 {
1106 self.ctx.check_x509();
1107
1108 unsafe {
1109 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1110 ffi::SSL_CTX_set_verify(
1111 self.as_ptr(),
1112 c_int::from(mode.bits()),
1113 Some(raw_verify::<F>),
1114 );
1115 }
1116 }
1117
1118 #[corresponds(SSL_CTX_set_custom_verify)]
1133 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1134 where
1135 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
1136 {
1137 unsafe {
1138 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1139 ffi::SSL_CTX_set_custom_verify(
1140 self.as_ptr(),
1141 c_int::from(mode.bits()),
1142 Some(raw_custom_verify::<F>),
1143 );
1144 }
1145 }
1146
1147 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
1157 pub fn set_servername_callback<F>(&mut self, callback: F)
1158 where
1159 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
1160 {
1161 unsafe {
1162 let callback_index = SslContext::cached_ex_index::<F>();
1169
1170 self.ctx.replace_ex_data(callback_index, callback);
1171 let callback = self.ctx.ex_data(callback_index).unwrap();
1172
1173 let arg = std::ptr::from_ref(callback).cast_mut().cast();
1174 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
1175 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
1176 }
1177 }
1178
1179 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1202 pub unsafe fn set_ticket_key_callback<F>(&mut self, callback: F)
1203 where
1204 F: Fn(
1205 &SslRef,
1206 &mut [u8; 16],
1207 &mut [u8; ffi::EVP_MAX_IV_LENGTH as usize],
1208 &mut CipherCtxRef,
1209 &mut HmacCtxRef,
1210 bool,
1211 ) -> TicketKeyCallbackResult
1212 + 'static
1213 + Sync
1214 + Send,
1215 {
1216 self.ctx.check_x509();
1217
1218 unsafe {
1219 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1220 ffi::SSL_CTX_set_tlsext_ticket_key_cb(self.as_ptr(), Some(raw_ticket_key::<F>))
1221 };
1222 }
1223
1224 #[corresponds(SSL_CTX_set_verify_depth)]
1228 pub fn set_verify_depth(&mut self, depth: u32) {
1229 self.ctx.check_x509();
1230
1231 unsafe {
1232 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
1233 }
1234 }
1235
1236 #[corresponds(SSL_CTX_set0_verify_cert_store)]
1238 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
1239 self.ctx.check_x509();
1240
1241 unsafe {
1242 cvt(ffi::SSL_CTX_set0_verify_cert_store(
1243 self.as_ptr(),
1244 cert_store.into_ptr(),
1245 ))
1246 }
1247 }
1248
1249 #[corresponds(SSL_CTX_set_cert_store)]
1256 pub fn set_cert_store(&mut self, cert_store: X509Store) {
1257 self.ctx.check_x509();
1258
1259 self.has_shared_cert_store = true;
1260 unsafe {
1261 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1262 }
1263 }
1264
1265 #[corresponds(SSL_CTX_set_cert_store)]
1267 pub fn set_cert_store_builder(&mut self, cert_store: X509StoreBuilder) {
1268 self.ctx.check_x509();
1269
1270 self.has_shared_cert_store = false;
1271 unsafe {
1272 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1273 }
1274 }
1275
1276 #[corresponds(SSL_CTX_set_cert_store)]
1280 pub fn set_cert_store_ref(&mut self, cert_store: &X509Store) {
1281 self.set_cert_store(cert_store.to_owned());
1282 }
1283
1284 #[corresponds(SSL_CTX_set_read_ahead)]
1291 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1292 unsafe {
1293 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), c_int::from(read_ahead));
1294 }
1295 }
1296
1297 #[corresponds(SSL_CTX_set_mode)]
1299 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1300 let bits = unsafe { ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits()) };
1301 SslMode::from_bits_retain(bits)
1302 }
1303
1304 #[corresponds(SSL_CTX_set_tmp_dh)]
1306 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1307 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr())) }
1308 }
1309
1310 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1312 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1313 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr())) }
1314 }
1315
1316 #[corresponds(SSL_CTX_set_default_verify_paths)]
1321 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1322 self.ctx.check_x509();
1323
1324 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())) }
1325 }
1326
1327 #[corresponds(SSL_CTX_load_verify_locations)]
1331 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1332 self.load_verify_locations(Some(file.as_ref()), None)
1333 }
1334
1335 #[corresponds(SSL_CTX_load_verify_locations)]
1337 pub fn load_verify_locations(
1338 &mut self,
1339 ca_file: Option<&Path>,
1340 ca_path: Option<&Path>,
1341 ) -> Result<(), ErrorStack> {
1342 self.ctx.check_x509();
1343
1344 let ca_file = ca_file.map(path_to_cstring).transpose()?;
1345 let ca_path = ca_path.map(path_to_cstring).transpose()?;
1346
1347 unsafe {
1348 cvt(ffi::SSL_CTX_load_verify_locations(
1349 self.as_ptr(),
1350 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1351 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1352 ))
1353 }
1354 }
1355
1356 #[corresponds(SSL_CTX_set_client_CA_list)]
1361 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1362 self.ctx.check_x509();
1363
1364 unsafe {
1365 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1366 mem::forget(list);
1367 }
1368 }
1369
1370 #[corresponds(SSL_CTX_add_client_CA)]
1373 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1374 self.ctx.check_x509();
1375
1376 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())) }
1377 }
1378
1379 #[corresponds(SSL_CTX_set_session_id_context)]
1388 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1389 unsafe {
1390 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1391 cvt(ffi::SSL_CTX_set_session_id_context(
1392 self.as_ptr(),
1393 sid_ctx.as_ptr(),
1394 sid_ctx.len(),
1395 ))
1396 }
1397 }
1398
1399 #[corresponds(SSL_CTX_use_certificate_file)]
1405 pub fn set_certificate_file<P: AsRef<Path>>(
1406 &mut self,
1407 file: P,
1408 file_type: SslFiletype,
1409 ) -> Result<(), ErrorStack> {
1410 self.ctx.check_x509();
1411
1412 let file = path_to_cstring(file.as_ref())?;
1413 unsafe {
1414 cvt(ffi::SSL_CTX_use_certificate_file(
1415 self.as_ptr(),
1416 file.as_ptr(),
1417 file_type.as_raw(),
1418 ))
1419 }
1420 }
1421
1422 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1428 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1429 &mut self,
1430 file: P,
1431 ) -> Result<(), ErrorStack> {
1432 let file = path_to_cstring(file.as_ref())?;
1433 unsafe {
1434 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1435 self.as_ptr(),
1436 file.as_ptr(),
1437 ))
1438 }
1439 }
1440
1441 #[corresponds(SSL_CTX_use_certificate)]
1445 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1446 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())) }
1447 }
1448
1449 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1454 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1455 self.ctx.check_x509();
1456
1457 unsafe {
1458 cvt(ffi::SSL_CTX_add_extra_chain_cert(
1459 self.as_ptr(),
1460 cert.into_ptr(),
1461 ))
1462 }
1463 }
1464
1465 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1467 pub fn set_private_key_file<P: AsRef<Path>>(
1468 &mut self,
1469 file: P,
1470 file_type: SslFiletype,
1471 ) -> Result<(), ErrorStack> {
1472 let file = path_to_cstring(file.as_ref())?;
1473 unsafe {
1474 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1475 self.as_ptr(),
1476 file.as_ptr(),
1477 file_type.as_raw(),
1478 ))
1479 }
1480 }
1481
1482 #[corresponds(SSL_CTX_use_PrivateKey)]
1484 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1485 where
1486 T: HasPrivate,
1487 {
1488 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())) }
1489 }
1490
1491 #[corresponds(SSL_CTX_set_cipher_list)]
1503 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1504 let cipher_list = CString::new(cipher_list).map_err(ErrorStack::internal_error)?;
1505 unsafe {
1506 cvt(ffi::SSL_CTX_set_cipher_list(
1507 self.as_ptr(),
1508 cipher_list.as_ptr(),
1509 ))
1510 }
1511 }
1512
1513 #[corresponds(SSL_CTX_set_strict_cipher_list)]
1524 pub fn set_strict_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1525 let cipher_list = CString::new(cipher_list).map_err(ErrorStack::internal_error)?;
1526 unsafe {
1527 cvt(ffi::SSL_CTX_set_strict_cipher_list(
1528 self.as_ptr(),
1529 cipher_list.as_ptr(),
1530 ))
1531 }
1532 }
1533
1534 #[corresponds(SSL_CTX_get_ciphers)]
1540 #[must_use]
1541 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
1542 self.ctx.ciphers()
1543 }
1544
1545 #[corresponds(SSL_CTX_set_options)]
1552 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1553 let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
1554 SslOptions::from_bits_retain(bits)
1555 }
1556
1557 #[corresponds(SSL_CTX_get_options)]
1559 #[must_use]
1560 pub fn options(&self) -> SslOptions {
1561 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
1562 SslOptions::from_bits_retain(bits)
1563 }
1564
1565 #[corresponds(SSL_CTX_clear_options)]
1567 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1568 let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
1569 SslOptions::from_bits_retain(bits)
1570 }
1571
1572 #[corresponds(SSL_CTX_set_min_proto_version)]
1577 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1578 unsafe {
1579 cvt(ffi::SSL_CTX_set_min_proto_version(
1580 self.as_ptr(),
1581 version.map_or(0, |v| v.0 as _),
1582 ))
1583 }
1584 }
1585
1586 #[corresponds(SSL_CTX_set_max_proto_version)]
1590 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1591 unsafe {
1592 cvt(ffi::SSL_CTX_set_max_proto_version(
1593 self.as_ptr(),
1594 version.map_or(0, |v| v.0 as _),
1595 ))
1596 }
1597 }
1598
1599 #[corresponds(SSL_CTX_get_min_proto_version)]
1601 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1602 unsafe {
1603 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1604 if r == 0 {
1605 None
1606 } else {
1607 Some(SslVersion(r))
1608 }
1609 }
1610 }
1611
1612 #[corresponds(SSL_CTX_get_max_proto_version)]
1614 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1615 unsafe {
1616 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1617 if r == 0 {
1618 None
1619 } else {
1620 Some(SslVersion(r))
1621 }
1622 }
1623 }
1624
1625 #[corresponds(SSL_CTX_set_alpn_protos)]
1632 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1633 unsafe {
1634 let r = ffi::SSL_CTX_set_alpn_protos(
1635 self.as_ptr(),
1636 protocols.as_ptr(),
1637 try_int(protocols.len())?,
1638 );
1639 if r == 0 {
1641 Ok(())
1642 } else {
1643 Err(ErrorStack::get())
1644 }
1645 }
1646 }
1647
1648 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1650 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1651 unsafe {
1652 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
1653
1654 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1655 if r == 0 {
1657 Ok(())
1658 } else {
1659 Err(ErrorStack::get())
1660 }
1661 }
1662 }
1663
1664 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1675 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1676 where
1677 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1678 {
1679 unsafe {
1680 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1681 ffi::SSL_CTX_set_alpn_select_cb(
1682 self.as_ptr(),
1683 Some(callbacks::raw_alpn_select::<F>),
1684 ptr::null_mut(),
1685 );
1686 }
1687 }
1688
1689 #[corresponds(SSL_CTX_set_select_certificate_cb)]
1693 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
1694 where
1695 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
1696 {
1697 unsafe {
1698 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1699 ffi::SSL_CTX_set_select_certificate_cb(
1700 self.as_ptr(),
1701 Some(callbacks::raw_select_cert::<F>),
1702 );
1703 }
1704 }
1705
1706 #[corresponds(SSL_CTX_add_cert_compression_alg)]
1710 pub fn add_certificate_compression_algorithm<C>(
1711 &mut self,
1712 compressor: C,
1713 ) -> Result<(), ErrorStack>
1714 where
1715 C: CertificateCompressor,
1716 {
1717 const {
1718 assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered");
1719 };
1720 let success = unsafe {
1721 ffi::SSL_CTX_add_cert_compression_alg(
1722 self.as_ptr(),
1723 C::ALGORITHM.0,
1724 const {
1725 if C::CAN_COMPRESS {
1726 Some(callbacks::raw_ssl_cert_compress::<C>)
1727 } else {
1728 None
1729 }
1730 },
1731 const {
1732 if C::CAN_DECOMPRESS {
1733 Some(callbacks::raw_ssl_cert_decompress::<C>)
1734 } else {
1735 None
1736 }
1737 },
1738 ) == 1
1739 };
1740 if !success {
1741 return Err(ErrorStack::get());
1742 }
1743 self.replace_ex_data(SslContext::cached_ex_index::<C>(), compressor);
1744 Ok(())
1745 }
1746
1747 #[corresponds(SSL_CTX_set_private_key_method)]
1751 pub fn set_private_key_method<M>(&mut self, method: M)
1752 where
1753 M: PrivateKeyMethod,
1754 {
1755 unsafe {
1756 self.replace_ex_data(SslContext::cached_ex_index::<M>(), method);
1757
1758 ffi::SSL_CTX_set_private_key_method(
1759 self.as_ptr(),
1760 &ffi::SSL_PRIVATE_KEY_METHOD {
1761 sign: Some(callbacks::raw_sign::<M>),
1762 decrypt: Some(callbacks::raw_decrypt::<M>),
1763 complete: Some(callbacks::raw_complete::<M>),
1764 },
1765 );
1766 }
1767 }
1768
1769 #[corresponds(SSL_CTX_check_private_key)]
1771 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1772 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())) }
1773 }
1774
1775 #[corresponds(SSL_CTX_get_cert_store)]
1777 #[must_use]
1778 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1779 self.ctx.check_x509();
1780
1781 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1782 }
1783
1784 #[corresponds(SSL_CTX_get_cert_store)]
1794 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1795 self.ctx.check_x509();
1796
1797 assert!(
1798 !self.has_shared_cert_store,
1799 "Shared X509Store can't be mutated. Use set_cert_store_builder() instead of set_cert_store()
1800 or completely finish building the cert store setting it."
1801 );
1802 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1805 }
1806
1807 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1820 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1821 where
1822 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1823 {
1824 unsafe {
1825 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1826 cvt(ffi::SSL_CTX_set_tlsext_status_cb(
1827 self.as_ptr(),
1828 Some(raw_tlsext_status::<F>),
1829 ))
1830 }
1831 }
1832
1833 #[corresponds(SSL_CTX_set_psk_client_callback)]
1839 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1840 where
1841 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1842 + 'static
1843 + Sync
1844 + Send,
1845 {
1846 unsafe {
1847 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1848 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1849 }
1850 }
1851
1852 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1853 pub fn set_psk_callback<F>(&mut self, callback: F)
1854 where
1855 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1856 + 'static
1857 + Sync
1858 + Send,
1859 {
1860 self.set_psk_client_callback(callback);
1861 }
1862
1863 #[corresponds(SSL_CTX_set_psk_server_callback)]
1869 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1870 where
1871 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1872 + 'static
1873 + Sync
1874 + Send,
1875 {
1876 unsafe {
1877 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1878 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1879 }
1880 }
1881
1882 #[corresponds(SSL_CTX_sess_set_new_cb)]
1896 pub fn set_new_session_callback<F>(&mut self, callback: F)
1897 where
1898 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1899 {
1900 unsafe {
1901 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1902 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1903 }
1904 }
1905
1906 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1910 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1911 where
1912 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1913 {
1914 unsafe {
1915 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1916 ffi::SSL_CTX_sess_set_remove_cb(
1917 self.as_ptr(),
1918 Some(callbacks::raw_remove_session::<F>),
1919 );
1920 }
1921 }
1922
1923 #[corresponds(SSL_CTX_sess_set_get_cb)]
1934 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1935 where
1936 F: Fn(&mut SslRef, &[u8]) -> Result<Option<SslSession>, GetSessionPendingError>
1937 + 'static
1938 + Sync
1939 + Send,
1940 {
1941 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1942 unsafe {
1943 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1944 }
1945 }
1946
1947 #[corresponds(SSL_CTX_set_keylog_callback)]
1953 pub fn set_keylog_callback<F>(&mut self, callback: F)
1954 where
1955 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1956 {
1957 unsafe {
1958 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1959 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1960 }
1961 }
1962
1963 #[corresponds(SSL_CTX_set_session_cache_mode)]
1967 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1968 unsafe {
1969 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1970 SslSessionCacheMode::from_bits_retain(bits)
1971 }
1972 }
1973
1974 #[corresponds(SSL_CTX_set_ex_data)]
1979 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1980 unsafe {
1981 self.ctx.replace_ex_data(index, data);
1982 }
1983 }
1984
1985 #[corresponds(SSL_CTX_set_ex_data)]
1992 pub fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
1993 unsafe { self.ctx.replace_ex_data(index, data) }
1994 }
1995
1996 #[corresponds(SSL_CTX_sess_set_cache_size)]
2000 #[allow(clippy::useless_conversion)]
2001 pub fn set_session_cache_size(&mut self, size: u32) -> u64 {
2002 unsafe { ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size.into()).into() }
2003 }
2004
2005 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2013 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2014 let sigalgs = CString::new(sigalgs).map_err(ErrorStack::internal_error)?;
2015 unsafe {
2016 cvt(ffi::SSL_CTX_set1_sigalgs_list(
2017 self.as_ptr(),
2018 sigalgs.as_ptr(),
2019 ))
2020 }
2021 }
2022
2023 #[corresponds(SSL_CTX_set_grease_enabled)]
2025 pub fn set_grease_enabled(&mut self, enabled: bool) {
2026 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as _) }
2027 }
2028
2029 #[corresponds(SSL_CTX_set_permute_extensions)]
2031 pub fn set_permute_extensions(&mut self, enabled: bool) {
2032 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as _) }
2033 }
2034
2035 #[corresponds(SSL_CTX_set_verify_algorithm_prefs)]
2037 pub fn set_verify_algorithm_prefs(
2038 &mut self,
2039 prefs: &[SslSignatureAlgorithm],
2040 ) -> Result<(), ErrorStack> {
2041 unsafe {
2042 cvt_0i(ffi::SSL_CTX_set_verify_algorithm_prefs(
2043 self.as_ptr(),
2044 prefs.as_ptr().cast(),
2045 prefs.len(),
2046 ))
2047 .map(|_| ())
2048 }
2049 }
2050
2051 #[corresponds(SSL_CTX_enable_signed_cert_timestamps)]
2053 pub fn enable_signed_cert_timestamps(&mut self) {
2054 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
2055 }
2056
2057 #[corresponds(SSL_CTX_enable_ocsp_stapling)]
2059 pub fn enable_ocsp_stapling(&mut self) {
2060 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
2061 }
2062
2063 #[corresponds(SSL_CTX_set1_curves_list)]
2065 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2066 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2067 unsafe {
2068 cvt_0i(ffi::SSL_CTX_set1_curves_list(
2069 self.as_ptr(),
2070 curves.as_ptr(),
2071 ))
2072 .map(|_| ())
2073 }
2074 }
2075
2076 #[corresponds(SSL_CTX_set_compliance_policy)]
2080 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
2081 unsafe { cvt_0i(ffi::SSL_CTX_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
2082 }
2083
2084 #[corresponds(SSL_CTX_set_info_callback)]
2086 pub fn set_info_callback<F>(&mut self, callback: F)
2087 where
2088 F: Fn(&SslRef, SslInfoCallbackMode, SslInfoCallbackValue) + Send + Sync + 'static,
2089 {
2090 unsafe {
2091 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
2092 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info_callback::<F>));
2093 }
2094 }
2095
2096 #[corresponds(SSL_CTX_set1_ech_keys)]
2101 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2102 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())) }
2103 }
2104
2105 #[corresponds(SSL_CTX_add1_credential)]
2107 #[cfg(feature = "credential")]
2108 pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> {
2109 unsafe {
2110 cvt_0i(ffi::SSL_CTX_add1_credential(
2111 self.as_ptr(),
2112 credential.as_ptr(),
2113 ))
2114 .map(|_| ())
2115 }
2116 }
2117
2118 #[corresponds(SSL_CTX_set1_accepted_peer_cert_types)]
2121 #[cfg(feature = "rpk")]
2122 pub fn set_server_certificate_types(
2123 &mut self,
2124 types: &[CertificateType],
2125 ) -> Result<(), ErrorStack> {
2126 unsafe {
2127 cvt_0i(ffi::SSL_CTX_set1_accepted_peer_cert_types(
2128 self.as_ptr(),
2129 types.as_ptr() as *const u8,
2130 types.len(),
2131 ))
2132 .map(|_| ())
2133 }
2134 }
2135
2136 #[must_use]
2138 pub fn build(self) -> SslContext {
2139 self.ctx
2140 }
2141}
2142
2143foreign_type_and_impl_send_sync! {
2144 type CType = ffi::SSL_CTX;
2145 fn drop = ffi::SSL_CTX_free;
2146
2147 pub struct SslContext;
2152}
2153
2154impl Clone for SslContext {
2155 fn clone(&self) -> Self {
2156 (**self).to_owned()
2157 }
2158}
2159
2160impl ToOwned for SslContextRef {
2161 type Owned = SslContext;
2162
2163 fn to_owned(&self) -> Self::Owned {
2164 unsafe {
2165 SSL_CTX_up_ref(self.as_ptr());
2166 SslContext::from_ptr(self.as_ptr())
2167 }
2168 }
2169}
2170
2171impl fmt::Debug for SslContext {
2173 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2174 write!(fmt, "SslContext")
2175 }
2176}
2177
2178impl SslContext {
2179 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2181 SslContextBuilder::new(method)
2182 }
2183
2184 #[corresponds(SSL_CTX_get_ex_new_index)]
2189 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2190 where
2191 T: 'static + Sync + Send,
2192 {
2193 unsafe {
2194 ffi::init();
2195 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2196 Ok(Index::from_raw(idx))
2197 }
2198 }
2199
2200 fn cached_ex_index<T>() -> Index<SslContext, T>
2202 where
2203 T: 'static + Sync + Send,
2204 {
2205 unsafe {
2206 let idx = *INDEXES
2207 .lock()
2208 .unwrap_or_else(|e| e.into_inner())
2209 .entry(TypeId::of::<T>())
2210 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2211 Index::from_raw(idx)
2212 }
2213 }
2214
2215 #[corresponds(SSL_CTX_get_ciphers)]
2221 #[must_use]
2222 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
2223 unsafe {
2224 let ciphers = ffi::SSL_CTX_get_ciphers(self.as_ptr());
2225 if ciphers.is_null() {
2226 None
2227 } else {
2228 Some(StackRef::from_ptr(ciphers))
2229 }
2230 }
2231 }
2232}
2233
2234impl SslContextRef {
2235 #[corresponds(SSL_CTX_get0_certificate)]
2237 #[must_use]
2238 pub fn certificate(&self) -> Option<&X509Ref> {
2239 self.check_x509();
2240
2241 unsafe {
2242 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2243 if ptr.is_null() {
2244 None
2245 } else {
2246 Some(X509Ref::from_ptr(ptr))
2247 }
2248 }
2249 }
2250
2251 #[corresponds(SSL_CTX_get0_privatekey)]
2253 #[must_use]
2254 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2255 unsafe {
2256 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2257 if ptr.is_null() {
2258 None
2259 } else {
2260 Some(PKeyRef::from_ptr(ptr))
2261 }
2262 }
2263 }
2264
2265 #[corresponds(SSL_CTX_get_cert_store)]
2267 #[must_use]
2268 pub fn cert_store(&self) -> &X509StoreRef {
2269 self.check_x509();
2270
2271 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2272 }
2273
2274 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2276 #[must_use]
2277 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2278 unsafe {
2279 let mut chain = ptr::null_mut();
2280 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2281 assert!(!chain.is_null());
2282 StackRef::from_ptr(chain)
2283 }
2284 }
2285
2286 #[corresponds(SSL_CTX_get_ex_data)]
2288 #[must_use]
2289 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2290 unsafe {
2291 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2292 if data.is_null() {
2293 None
2294 } else {
2295 Some(&*(data as *const T))
2296 }
2297 }
2298 }
2299
2300 #[corresponds(SSL_CTX_get_ex_data)]
2303 unsafe fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2304 unsafe {
2305 ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw())
2306 .cast::<T>()
2307 .as_mut()
2308 }
2309 }
2310
2311 #[corresponds(SSL_CTX_set_ex_data)]
2314 unsafe fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2315 unsafe {
2316 let data = Box::into_raw(Box::new(data));
2317 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data.cast());
2318 }
2319 }
2320
2321 #[corresponds(SSL_CTX_set_ex_data)]
2324 unsafe fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2325 unsafe {
2326 if let Some(old) = self.ex_data_mut(index) {
2327 return Some(mem::replace(old, data));
2328 }
2329
2330 self.set_ex_data(index, data);
2331
2332 None
2333 }
2334 }
2335
2336 #[corresponds(SSL_CTX_add_session)]
2345 #[must_use]
2346 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2347 unsafe { ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0 }
2348 }
2349
2350 #[corresponds(SSL_CTX_remove_session)]
2359 #[must_use]
2360 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2361 unsafe { ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0 }
2362 }
2363
2364 #[corresponds(SSL_CTX_sess_get_cache_size)]
2368 #[allow(clippy::useless_conversion)]
2369 #[must_use]
2370 pub fn session_cache_size(&self) -> u64 {
2371 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()).into() }
2372 }
2373
2374 #[corresponds(SSL_CTX_get_verify_mode)]
2378 #[must_use]
2379 pub fn verify_mode(&self) -> SslVerifyMode {
2380 self.check_x509();
2381
2382 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2383 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2384 }
2385
2386 pub unsafe fn assume_x509(&mut self) {
2394 unsafe {
2395 self.replace_ex_data(*X509_FLAG_INDEX, true);
2396 }
2397 }
2398
2399 #[must_use]
2401 pub fn has_x509_support(&self) -> bool {
2402 self.ex_data(*X509_FLAG_INDEX).copied().unwrap_or_default()
2403 }
2404
2405 #[track_caller]
2406 fn check_x509(&self) {
2407 assert!(
2408 self.has_x509_support(),
2409 "This context is not configured for X.509 certificates"
2410 );
2411 }
2412
2413 #[corresponds(SSL_CTX_set1_ech_keys)]
2418 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2419 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())) }
2420 }
2421
2422 #[corresponds(SSL_CTX_get0_server_certificate_types)]
2424 #[cfg(feature = "rpk")]
2425 #[must_use]
2426 pub fn server_certificate_types(&self) -> Option<&[CertificateType]> {
2427 let mut types = ptr::null();
2428 let mut types_len = 0;
2429 unsafe {
2430 ffi::SSL_CTX_get0_accepted_peer_cert_types(self.as_ptr(), &mut types, &mut types_len);
2431
2432 if types_len == 0 {
2433 return None;
2434 }
2435
2436 Some(slice::from_raw_parts(
2437 types as *const CertificateType,
2438 types_len,
2439 ))
2440 }
2441 }
2442}
2443
2444#[derive(Debug)]
2449pub struct GetSessionPendingError;
2450
2451pub struct CipherBits {
2453 pub secret: i32,
2455
2456 pub algorithm: i32,
2458}
2459
2460#[repr(transparent)]
2461pub struct ClientHello<'ssl>(&'ssl ffi::SSL_CLIENT_HELLO);
2462
2463impl ClientHello<'_> {
2464 #[corresponds(SSL_early_callback_ctx_extension_get)]
2466 #[must_use]
2467 pub fn get_extension(&self, ext_type: ExtensionType) -> Option<&[u8]> {
2468 unsafe {
2469 let mut ptr = ptr::null();
2470 let mut len = 0;
2471 let result =
2472 ffi::SSL_early_callback_ctx_extension_get(self.0, ext_type.0, &mut ptr, &mut len);
2473 if result == 0 {
2474 return None;
2475 }
2476 Some(slice::from_raw_parts(ptr, len))
2477 }
2478 }
2479
2480 pub fn ssl_mut(&mut self) -> &mut SslRef {
2481 unsafe { SslRef::from_ptr_mut(self.0.ssl) }
2482 }
2483
2484 #[must_use]
2485 pub fn ssl(&self) -> &SslRef {
2486 unsafe { SslRef::from_ptr(self.0.ssl) }
2487 }
2488
2489 #[must_use]
2491 pub fn servername(&self, type_: NameType) -> Option<&str> {
2492 self.ssl().servername(type_)
2493 }
2494
2495 #[must_use]
2497 pub fn client_version(&self) -> SslVersion {
2498 SslVersion(self.0.version)
2499 }
2500
2501 #[must_use]
2503 pub fn version_str(&self) -> &'static str {
2504 self.ssl().version_str()
2505 }
2506
2507 #[must_use]
2509 pub fn as_bytes(&self) -> &[u8] {
2510 unsafe { slice::from_raw_parts(self.0.client_hello, self.0.client_hello_len) }
2511 }
2512
2513 #[must_use]
2515 pub fn random(&self) -> &[u8] {
2516 unsafe { slice::from_raw_parts(self.0.random, self.0.random_len) }
2517 }
2518
2519 #[must_use]
2521 pub fn ciphers(&self) -> &[u8] {
2522 unsafe { slice::from_raw_parts(self.0.cipher_suites, self.0.cipher_suites_len) }
2523 }
2524}
2525
2526#[derive(Clone, Copy)]
2528pub struct SslCipher(&'static SslCipherRef);
2529
2530impl SslCipher {
2531 #[corresponds(SSL_get_cipher_by_value)]
2532 #[must_use]
2533 pub fn from_value(value: u16) -> Option<Self> {
2534 unsafe {
2535 let ptr = ffi::SSL_get_cipher_by_value(value);
2536 if ptr.is_null() {
2537 None
2538 } else {
2539 Some(Self::from_ptr(ptr.cast_mut()))
2540 }
2541 }
2542 }
2543}
2544
2545impl Stackable for SslCipher {
2546 type StackType = ffi::stack_st_SSL_CIPHER;
2547}
2548
2549unsafe impl ForeignType for SslCipher {
2550 type CType = ffi::SSL_CIPHER;
2551 type Ref = SslCipherRef;
2552
2553 #[inline]
2554 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2555 SslCipher(unsafe { SslCipherRef::from_ptr(ptr) })
2556 }
2557
2558 #[inline]
2559 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2560 self.0.as_ptr()
2561 }
2562}
2563
2564impl Deref for SslCipher {
2565 type Target = SslCipherRef;
2566
2567 fn deref(&self) -> &SslCipherRef {
2568 self.0
2569 }
2570}
2571
2572pub struct SslCipherRef(Opaque);
2576
2577unsafe impl Send for SslCipherRef {}
2578unsafe impl Sync for SslCipherRef {}
2579
2580unsafe impl ForeignTypeRef for SslCipherRef {
2581 type CType = ffi::SSL_CIPHER;
2582}
2583
2584impl SslCipherRef {
2585 #[corresponds(SSL_CIPHER_get_protocol_id)]
2587 #[must_use]
2588 pub fn protocol_id(&self) -> u16 {
2589 unsafe { ffi::SSL_CIPHER_get_protocol_id(self.as_ptr()) }
2590 }
2591
2592 #[corresponds(SSL_CIPHER_get_name)]
2594 #[must_use]
2595 pub fn name(&self) -> &'static str {
2596 unsafe {
2597 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2598 CStr::from_ptr(ptr).to_str().unwrap()
2599 }
2600 }
2601
2602 #[corresponds(SSL_CIPHER_standard_name)]
2604 #[must_use]
2605 pub fn standard_name(&self) -> Option<&'static str> {
2606 unsafe {
2607 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2608 if ptr.is_null() {
2609 None
2610 } else {
2611 Some(CStr::from_ptr(ptr).to_str().unwrap())
2612 }
2613 }
2614 }
2615
2616 #[corresponds(SSL_CIPHER_get_version)]
2618 #[must_use]
2619 pub fn version(&self) -> &'static str {
2620 let version = unsafe {
2621 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2622 CStr::from_ptr(ptr)
2623 };
2624
2625 version.to_str().unwrap()
2626 }
2627
2628 #[corresponds(SSL_CIPHER_get_bits)]
2630 #[allow(clippy::useless_conversion)]
2631 #[must_use]
2632 pub fn bits(&self) -> CipherBits {
2633 unsafe {
2634 let mut algo_bits = 0;
2635 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2636 CipherBits {
2637 secret: secret_bits.into(),
2638 algorithm: algo_bits.into(),
2639 }
2640 }
2641 }
2642
2643 #[corresponds(SSL_CIPHER_description)]
2645 #[must_use]
2646 pub fn description(&self) -> String {
2647 unsafe {
2648 let mut buf = [0; 128];
2650 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2651 CStr::from_ptr(ptr).to_string_lossy().into_owned()
2652 }
2653 }
2654
2655 #[corresponds(SSL_CIPHER_is_aead)]
2657 #[must_use]
2658 pub fn cipher_is_aead(&self) -> bool {
2659 unsafe { ffi::SSL_CIPHER_is_aead(self.as_ptr()) != 0 }
2660 }
2661
2662 #[corresponds(SSL_CIPHER_get_auth_nid)]
2664 #[must_use]
2665 pub fn cipher_auth_nid(&self) -> Option<Nid> {
2666 let n = unsafe { ffi::SSL_CIPHER_get_auth_nid(self.as_ptr()) };
2667 if n == 0 {
2668 None
2669 } else {
2670 Some(Nid::from_raw(n))
2671 }
2672 }
2673
2674 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2676 #[must_use]
2677 pub fn cipher_nid(&self) -> Option<Nid> {
2678 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2679 if n == 0 {
2680 None
2681 } else {
2682 Some(Nid::from_raw(n))
2683 }
2684 }
2685}
2686
2687foreign_type_and_impl_send_sync! {
2688 type CType = ffi::SSL_SESSION;
2689 fn drop = ffi::SSL_SESSION_free;
2690
2691 pub struct SslSession;
2695}
2696
2697impl Clone for SslSession {
2698 fn clone(&self) -> SslSession {
2699 SslSessionRef::to_owned(self)
2700 }
2701}
2702
2703impl SslSession {
2704 from_der! {
2705 #[corresponds(d2i_SSL_SESSION)]
2707 from_der,
2708 SslSession,
2709 ffi::d2i_SSL_SESSION,
2710 ::libc::c_long
2711 }
2712}
2713
2714impl ToOwned for SslSessionRef {
2715 type Owned = SslSession;
2716
2717 fn to_owned(&self) -> SslSession {
2718 unsafe {
2719 SSL_SESSION_up_ref(self.as_ptr());
2720 SslSession(NonNull::new_unchecked(self.as_ptr()))
2721 }
2722 }
2723}
2724
2725impl SslSessionRef {
2726 #[corresponds(SSL_SESSION_get_id)]
2728 #[must_use]
2729 pub fn id(&self) -> &[u8] {
2730 unsafe {
2731 let mut len = 0;
2732 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2733 slice::from_raw_parts(p, len as usize)
2734 }
2735 }
2736
2737 #[corresponds(SSL_SESSION_get_master_key)]
2739 #[must_use]
2740 pub fn master_key_len(&self) -> usize {
2741 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2742 }
2743
2744 #[corresponds(SSL_SESSION_get_master_key)]
2748 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2749 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2750 }
2751
2752 #[corresponds(SSL_SESSION_get_time)]
2754 #[allow(clippy::useless_conversion)]
2755 #[must_use]
2756 pub fn time(&self) -> u64 {
2757 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2758 }
2759
2760 #[corresponds(SSL_SESSION_get_timeout)]
2764 #[allow(clippy::useless_conversion)]
2765 #[must_use]
2766 pub fn timeout(&self) -> u32 {
2767 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()) }
2768 }
2769
2770 #[corresponds(SSL_SESSION_get_protocol_version)]
2772 #[must_use]
2773 pub fn protocol_version(&self) -> SslVersion {
2774 unsafe {
2775 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2776 SslVersion(version)
2777 }
2778 }
2779
2780 to_der! {
2781 #[corresponds(i2d_SSL_SESSION)]
2783 to_der,
2784 ffi::i2d_SSL_SESSION
2785 }
2786}
2787
2788foreign_type_and_impl_send_sync! {
2789 type CType = ffi::SSL;
2790 fn drop = ffi::SSL_free;
2791
2792 pub struct Ssl;
2799}
2800
2801impl fmt::Debug for Ssl {
2802 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2803 fmt::Debug::fmt(&**self, fmt)
2804 }
2805}
2806
2807impl Ssl {
2808 #[corresponds(SSL_get_ex_new_index)]
2813 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2814 where
2815 T: 'static + Sync + Send,
2816 {
2817 unsafe {
2818 ffi::init();
2819 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2820 Ok(Index::from_raw(idx))
2821 }
2822 }
2823
2824 fn cached_ex_index<T>() -> Index<Ssl, T>
2826 where
2827 T: 'static + Sync + Send,
2828 {
2829 unsafe {
2830 let idx = *SSL_INDEXES
2831 .lock()
2832 .unwrap_or_else(|e| e.into_inner())
2833 .entry(TypeId::of::<T>())
2834 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2835 Index::from_raw(idx)
2836 }
2837 }
2838
2839 #[corresponds(SSL_new)]
2841 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2842 unsafe {
2843 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2844 let mut ssl = Ssl::from_ptr(ptr);
2845 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx.to_owned());
2846
2847 Ok(ssl)
2848 }
2849 }
2850
2851 pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2863 where
2864 S: Read + Write,
2865 {
2866 SslStreamBuilder::new(self, stream).setup_connect()
2867 }
2868
2869 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2879 where
2880 S: Read + Write,
2881 {
2882 self.setup_connect(stream).handshake()
2883 }
2884
2885 pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
2897 where
2898 S: Read + Write,
2899 {
2900 SslStreamBuilder::new(self, stream).setup_accept()
2916 }
2917
2918 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2930 where
2931 S: Read + Write,
2932 {
2933 self.setup_accept(stream).handshake()
2934 }
2935}
2936
2937impl fmt::Debug for SslRef {
2938 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2939 let mut builder = fmt.debug_struct("Ssl");
2940
2941 builder.field("state", &self.state_string_long());
2942
2943 if self.ssl_context().has_x509_support() {
2944 builder.field("verify_result", &self.verify_result());
2945 }
2946
2947 #[cfg(not(feature = "rpk"))]
2948 builder.field("verify_result", &self.verify_result());
2949
2950 builder.finish()
2951 }
2952}
2953
2954impl SslRef {
2955 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2956 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2957 }
2958
2959 #[corresponds(SSL_set_options)]
2966 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
2967 let bits = unsafe { ffi::SSL_set_options(self.as_ptr(), option.bits()) };
2968 SslOptions::from_bits_retain(bits)
2969 }
2970
2971 #[corresponds(SSL_clear_options)]
2973 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
2974 let bits = unsafe { ffi::SSL_clear_options(self.as_ptr(), option.bits()) };
2975 SslOptions::from_bits_retain(bits)
2976 }
2977
2978 #[corresponds(SSL_set1_curves_list)]
2979 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2980 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2981 unsafe { cvt_0i(ffi::SSL_set1_curves_list(self.as_ptr(), curves.as_ptr())).map(|_| ()) }
2982 }
2983
2984 #[corresponds(SSL_set_verify_algorithm_prefs)]
2985 pub fn set_verify_algorithm_prefs(
2986 &mut self,
2987 prefs: &[SslSignatureAlgorithm],
2988 ) -> Result<(), ErrorStack> {
2989 unsafe {
2990 cvt_0i(ffi::SSL_set_verify_algorithm_prefs(
2991 self.as_ptr(),
2992 prefs.as_ptr().cast(),
2993 prefs.len(),
2994 ))
2995 .map(|_| ())
2996 }
2997 }
2998
2999 #[corresponds(SSL_get_curve_id)]
3001 #[must_use]
3002 pub fn curve(&self) -> Option<u16> {
3003 let curve_id = unsafe { ffi::SSL_get_curve_id(self.as_ptr()) };
3004 if curve_id == 0 {
3005 return None;
3006 }
3007 Some(curve_id)
3008 }
3009
3010 #[corresponds(SSL_get_curve_name)]
3012 #[must_use]
3013 pub fn curve_name(&self) -> Option<&'static str> {
3014 let curve_id = self.curve()?;
3015
3016 unsafe {
3017 let ptr = ffi::SSL_get_curve_name(curve_id);
3018 if ptr.is_null() {
3019 return None;
3020 }
3021
3022 CStr::from_ptr(ptr).to_str().ok()
3023 }
3024 }
3025
3026 pub fn used_hello_retry_request(&self) -> bool {
3028 unsafe { ffi::SSL_used_hello_retry_request(self.as_ptr()) == 1 }
3029 }
3030
3031 #[corresponds(SSL_get_error)]
3033 #[must_use]
3034 pub fn error_code(&self, ret: c_int) -> ErrorCode {
3035 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
3036 }
3037
3038 #[corresponds(SSL_set_verify)]
3042 pub fn set_verify(&mut self, mode: SslVerifyMode) {
3043 self.ssl_context().check_x509();
3044
3045 unsafe { ffi::SSL_set_verify(self.as_ptr(), c_int::from(mode.bits()), None) }
3046 }
3047
3048 #[corresponds(SSL_set_verify_depth)]
3052 pub fn set_verify_depth(&mut self, depth: u32) {
3053 self.ssl_context().check_x509();
3054
3055 unsafe {
3056 ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
3057 }
3058 }
3059
3060 #[corresponds(SSL_get_verify_mode)]
3062 #[must_use]
3063 pub fn verify_mode(&self) -> SslVerifyMode {
3064 self.ssl_context().check_x509();
3065
3066 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
3067 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
3068 }
3069
3070 #[corresponds(SSL_set_verify)]
3087 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3088 where
3089 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
3090 {
3091 self.ssl_context().check_x509();
3092
3093 unsafe {
3094 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3096 ffi::SSL_set_verify(
3097 self.as_ptr(),
3098 c_int::from(mode.bits()),
3099 Some(ssl_raw_verify::<F>),
3100 );
3101 }
3102 }
3103
3104 #[corresponds(SSL_set0_verify_cert_store)]
3106 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3107 self.ssl_context().check_x509();
3108
3109 unsafe {
3110 cvt(ffi::SSL_set0_verify_cert_store(
3111 self.as_ptr(),
3112 cert_store.into_ptr(),
3113 ))
3114 }
3115 }
3116
3117 #[corresponds(SSL_set_custom_verify)]
3123 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3124 where
3125 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
3126 {
3127 self.ssl_context().check_x509();
3128
3129 unsafe {
3130 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3132 ffi::SSL_set_custom_verify(
3133 self.as_ptr(),
3134 c_int::from(mode.bits()),
3135 Some(ssl_raw_custom_verify::<F>),
3136 );
3137 }
3138 }
3139
3140 #[corresponds(SSL_set_tmp_dh)]
3144 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3145 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr())) }
3146 }
3147
3148 #[corresponds(SSL_set_tmp_ecdh)]
3152 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3153 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr())) }
3154 }
3155
3156 #[corresponds(SSL_set_permute_extensions)]
3158 pub fn set_permute_extensions(&mut self, enabled: bool) {
3159 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as _) }
3160 }
3161
3162 #[corresponds(SSL_set_alpn_protos)]
3166 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3167 unsafe {
3168 let r = ffi::SSL_set_alpn_protos(
3169 self.as_ptr(),
3170 protocols.as_ptr(),
3171 try_int(protocols.len())?,
3172 );
3173 if r == 0 {
3175 Ok(())
3176 } else {
3177 Err(ErrorStack::get())
3178 }
3179 }
3180 }
3181
3182 #[corresponds(SSL_get_ciphers)]
3184 #[must_use]
3185 pub fn ciphers(&self) -> &StackRef<SslCipher> {
3186 unsafe {
3187 let cipher_list = ffi::SSL_get_ciphers(self.as_ptr());
3188 StackRef::from_ptr(cipher_list)
3189 }
3190 }
3191
3192 #[corresponds(SSL_get_current_cipher)]
3194 #[must_use]
3195 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3196 unsafe {
3197 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3198
3199 if ptr.is_null() {
3200 None
3201 } else {
3202 Some(SslCipherRef::from_ptr(ptr.cast_mut()))
3203 }
3204 }
3205 }
3206
3207 #[corresponds(SSL_get_peer_signature_algorithm)]
3210 #[must_use]
3211 pub fn peer_signature_algorithm(&self) -> Option<SslSignatureAlgorithm> {
3212 let sigalg = unsafe { ffi::SSL_get_peer_signature_algorithm(self.as_ptr()) };
3213 if sigalg == 0 {
3214 None
3215 } else {
3216 Some(SslSignatureAlgorithm(sigalg))
3217 }
3218 }
3219
3220 #[corresponds(SSL_get_signature_algorithm_used)]
3227 #[must_use]
3228 pub fn signature_algorithm_used(&self) -> Option<SslSignatureAlgorithm> {
3229 let sigalg = unsafe { ffi::SSL_get_signature_algorithm_used(self.as_ptr()) };
3230 if sigalg == 0 {
3231 None
3232 } else {
3233 Some(SslSignatureAlgorithm(sigalg))
3234 }
3235 }
3236
3237 #[corresponds(SSL_state_string)]
3241 #[must_use]
3242 pub fn state_string(&self) -> &'static str {
3243 let state = unsafe {
3244 let ptr = ffi::SSL_state_string(self.as_ptr());
3245 CStr::from_ptr(ptr)
3246 };
3247
3248 state.to_str().unwrap_or_default()
3249 }
3250
3251 #[corresponds(SSL_state_string_long)]
3255 #[must_use]
3256 pub fn state_string_long(&self) -> &'static str {
3257 let state = unsafe {
3258 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3259 CStr::from_ptr(ptr)
3260 };
3261
3262 state.to_str().unwrap_or_default()
3263 }
3264
3265 #[corresponds(SSL_set_tlsext_host_name)]
3269 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3270 let cstr = CString::new(hostname).map_err(ErrorStack::internal_error)?;
3271 unsafe { cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr())) }
3272 }
3273
3274 #[corresponds(SSL_get_peer_certificate)]
3276 #[must_use]
3277 pub fn peer_certificate(&self) -> Option<X509> {
3278 self.ssl_context().check_x509();
3279
3280 unsafe {
3281 let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
3282 if ptr.is_null() {
3283 None
3284 } else {
3285 Some(X509::from_ptr(ptr))
3286 }
3287 }
3288 }
3289
3290 #[corresponds(SSL_get_peer_cert_chain)]
3295 #[must_use]
3296 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3297 self.ssl_context().check_x509();
3298
3299 unsafe {
3300 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3301 if ptr.is_null() {
3302 None
3303 } else {
3304 Some(StackRef::from_ptr(ptr))
3305 }
3306 }
3307 }
3308
3309 #[corresponds(SSL_get_certificate)]
3311 #[must_use]
3312 pub fn certificate(&self) -> Option<&X509Ref> {
3313 self.ssl_context().check_x509();
3314
3315 unsafe {
3316 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3317 if ptr.is_null() {
3318 None
3319 } else {
3320 Some(X509Ref::from_ptr(ptr))
3321 }
3322 }
3323 }
3324
3325 #[corresponds(SSL_get_privatekey)]
3327 #[must_use]
3328 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3329 unsafe {
3330 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3331 if ptr.is_null() {
3332 None
3333 } else {
3334 Some(PKeyRef::from_ptr(ptr))
3335 }
3336 }
3337 }
3338
3339 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
3340 #[must_use]
3341 pub fn version(&self) -> &str {
3342 self.version_str()
3343 }
3344
3345 #[corresponds(SSL_version)]
3347 pub fn version2(&self) -> Option<SslVersion> {
3348 unsafe {
3349 let r = ffi::SSL_version(self.as_ptr());
3350 if r == 0 {
3351 None
3352 } else {
3353 r.try_into().ok().map(SslVersion)
3354 }
3355 }
3356 }
3357
3358 #[corresponds(SSL_get_version)]
3362 #[must_use]
3363 pub fn version_str(&self) -> &'static str {
3364 let version = unsafe {
3365 let ptr = ffi::SSL_get_version(self.as_ptr());
3366 CStr::from_ptr(ptr)
3367 };
3368
3369 version.to_str().unwrap()
3370 }
3371
3372 #[corresponds(SSL_set_min_proto_version)]
3377 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3378 unsafe {
3379 cvt(ffi::SSL_set_min_proto_version(
3380 self.as_ptr(),
3381 version.map_or(0, |v| v.0 as _),
3382 ))
3383 }
3384 }
3385
3386 #[corresponds(SSL_set_max_proto_version)]
3390 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3391 unsafe {
3392 cvt(ffi::SSL_set_max_proto_version(
3393 self.as_ptr(),
3394 version.map_or(0, |v| v.0 as _),
3395 ))
3396 }
3397 }
3398
3399 #[corresponds(SSL_get_min_proto_version)]
3401 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
3402 unsafe {
3403 let r = ffi::SSL_get_min_proto_version(self.as_ptr());
3404 if r == 0 {
3405 None
3406 } else {
3407 Some(SslVersion(r))
3408 }
3409 }
3410 }
3411
3412 #[corresponds(SSL_get_max_proto_version)]
3414 #[must_use]
3415 pub fn max_proto_version(&self) -> Option<SslVersion> {
3416 let r = unsafe { ffi::SSL_get_max_proto_version(self.as_ptr()) };
3417 if r == 0 {
3418 None
3419 } else {
3420 Some(SslVersion(r))
3421 }
3422 }
3423
3424 #[corresponds(SSL_get0_alpn_selected)]
3429 #[must_use]
3430 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3431 unsafe {
3432 let mut data: *const c_uchar = ptr::null();
3433 let mut len: c_uint = 0;
3434 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3437
3438 if data.is_null() {
3439 None
3440 } else {
3441 Some(slice::from_raw_parts(data, len as usize))
3442 }
3443 }
3444 }
3445
3446 #[corresponds(SSL_set_tlsext_use_srtp)]
3448 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3449 unsafe {
3450 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
3451
3452 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3453 if r == 0 {
3455 Ok(())
3456 } else {
3457 Err(ErrorStack::get())
3458 }
3459 }
3460 }
3461
3462 #[corresponds(SSL_get_strp_profiles)]
3466 #[must_use]
3467 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3468 unsafe {
3469 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3470
3471 if chain.is_null() {
3472 None
3473 } else {
3474 Some(StackRef::from_ptr(chain.cast_mut()))
3475 }
3476 }
3477 }
3478
3479 #[corresponds(SSL_get_selected_srtp_profile)]
3483 #[must_use]
3484 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3485 unsafe {
3486 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3487
3488 if profile.is_null() {
3489 None
3490 } else {
3491 Some(SrtpProtectionProfileRef::from_ptr(profile.cast_mut()))
3492 }
3493 }
3494 }
3495
3496 #[corresponds(SSL_pending)]
3501 #[must_use]
3502 pub fn pending(&self) -> usize {
3503 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3504 }
3505
3506 #[corresponds(SSL_get_servername)]
3519 #[must_use]
3520 pub fn servername(&self, type_: NameType) -> Option<&str> {
3521 self.servername_raw(type_)
3522 .and_then(|b| str::from_utf8(b).ok())
3523 }
3524
3525 #[corresponds(SSL_get_servername)]
3533 #[must_use]
3534 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3535 unsafe {
3536 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3537 if name.is_null() {
3538 None
3539 } else {
3540 Some(CStr::from_ptr(name).to_bytes())
3541 }
3542 }
3543 }
3544
3545 #[corresponds(SSL_set_SSL_CTX)]
3549 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3550 assert_eq!(
3551 self.ssl_context().has_x509_support(),
3552 ctx.has_x509_support(),
3553 "X.509 certificate support in old and new contexts doesn't match",
3554 );
3555
3556 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3557 }
3558
3559 #[corresponds(SSL_get_SSL_CTX)]
3561 #[must_use]
3562 pub fn ssl_context(&self) -> &SslContextRef {
3563 unsafe {
3564 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3565 SslContextRef::from_ptr(ssl_ctx)
3566 }
3567 }
3568
3569 #[corresponds(SSL_get0_param)]
3571 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
3572 self.ssl_context().check_x509();
3573
3574 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3575 }
3576
3577 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3579 self.verify_param_mut()
3580 }
3581
3582 #[corresponds(SSL_get_verify_result)]
3584 pub fn verify_result(&self) -> X509VerifyResult {
3585 self.ssl_context().check_x509();
3586
3587 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3588 }
3589
3590 #[corresponds(SSL_get_session)]
3592 #[must_use]
3593 pub fn session(&self) -> Option<&SslSessionRef> {
3594 unsafe {
3595 let p = ffi::SSL_get_session(self.as_ptr());
3596 if p.is_null() {
3597 None
3598 } else {
3599 Some(SslSessionRef::from_ptr(p))
3600 }
3601 }
3602 }
3603
3604 #[corresponds(SSL_get_client_random)]
3609 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3610 unsafe { ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
3611 }
3612
3613 #[corresponds(SSL_get_server_random)]
3618 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3619 unsafe { ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
3620 }
3621
3622 #[corresponds(SSL_export_keying_material)]
3624 pub fn export_keying_material(
3625 &self,
3626 out: &mut [u8],
3627 label: &str,
3628 context: Option<&[u8]>,
3629 ) -> Result<(), ErrorStack> {
3630 unsafe {
3631 let (context, contextlen, use_context) = match context {
3632 Some(context) => (context.as_ptr(), context.len(), 1),
3633 None => (ptr::null(), 0, 0),
3634 };
3635 cvt(ffi::SSL_export_keying_material(
3636 self.as_ptr(),
3637 out.as_mut_ptr(),
3638 out.len(),
3639 label.as_ptr().cast::<c_char>(),
3640 label.len(),
3641 context,
3642 contextlen,
3643 use_context,
3644 ))
3645 }
3646 }
3647
3648 #[corresponds(SSL_set_session)]
3659 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3660 unsafe { cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())) }
3661 }
3662
3663 #[corresponds(SSL_session_reused)]
3665 #[must_use]
3666 pub fn session_reused(&self) -> bool {
3667 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3668 }
3669
3670 #[corresponds(SSL_set_tlsext_status_type)]
3672 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3673 unsafe {
3674 cvt(ffi::SSL_set_tlsext_status_type(
3675 self.as_ptr(),
3676 type_.as_raw(),
3677 ))
3678 }
3679 }
3680
3681 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3683 #[must_use]
3684 pub fn ocsp_status(&self) -> Option<&[u8]> {
3685 unsafe {
3686 let mut p = ptr::null();
3687 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3688
3689 if len == 0 {
3690 None
3691 } else {
3692 Some(slice::from_raw_parts(p, len))
3693 }
3694 }
3695 }
3696
3697 #[corresponds(SSL_set_ocsp_response)]
3699 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3700 unsafe {
3701 assert!(response.len() <= c_int::MAX as usize);
3702 cvt(ffi::SSL_set_ocsp_response(
3703 self.as_ptr(),
3704 response.as_ptr(),
3705 response.len(),
3706 ))
3707 }
3708 }
3709
3710 #[corresponds(SSL_is_server)]
3712 #[must_use]
3713 pub fn is_server(&self) -> bool {
3714 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3715 }
3716
3717 #[corresponds(SSL_set_ex_data)]
3725 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3726 if let Some(old) = self.ex_data_mut(index) {
3727 *old = data;
3728 return;
3729 }
3730
3731 unsafe {
3732 let data = Box::into_raw(Box::new(data));
3733 ffi::SSL_set_ex_data(self.as_ptr(), index.as_raw(), data.cast());
3734 }
3735 }
3736
3737 #[corresponds(SSL_set_ex_data)]
3744 pub fn replace_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) -> Option<T> {
3745 if let Some(old) = self.ex_data_mut(index) {
3746 return Some(mem::replace(old, data));
3747 }
3748
3749 self.set_ex_data(index, data);
3750
3751 None
3752 }
3753
3754 #[corresponds(SSL_get_ex_data)]
3756 #[must_use]
3757 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3758 unsafe {
3759 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3760 if data.is_null() {
3761 None
3762 } else {
3763 Some(&*(data as *const T))
3764 }
3765 }
3766 }
3767
3768 #[corresponds(SSL_get_ex_data)]
3770 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3771 unsafe {
3772 ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw())
3773 .cast::<T>()
3774 .as_mut()
3775 }
3776 }
3777
3778 #[corresponds(SSL_get_finished)]
3783 pub fn finished(&self, buf: &mut [u8]) -> usize {
3784 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) }
3785 }
3786
3787 #[corresponds(SSL_get_peer_finished)]
3793 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3794 unsafe { ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) }
3795 }
3796
3797 #[corresponds(SSL_is_init_finished)]
3799 #[must_use]
3800 pub fn is_init_finished(&self) -> bool {
3801 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3802 }
3803
3804 #[corresponds(SSL_set_mtu)]
3806 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3807 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_uint)) }
3808 }
3809
3810 #[corresponds(SSL_use_certificate)]
3812 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3813 unsafe {
3814 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3815 }
3816
3817 Ok(())
3818 }
3819
3820 #[corresponds(SSL_set_client_CA_list)]
3825 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3826 self.ssl_context().check_x509();
3827
3828 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3829 mem::forget(list);
3830 }
3831
3832 #[corresponds(SSL_use_PrivateKey)]
3834 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
3835 where
3836 T: HasPrivate,
3837 {
3838 unsafe { cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), key.as_ptr())) }
3839 }
3840
3841 #[corresponds(SSL_set_mode)]
3844 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
3845 let bits = unsafe { ffi::SSL_set_mode(self.as_ptr(), mode.bits()) };
3846 SslMode::from_bits_retain(bits)
3847 }
3848
3849 #[corresponds(SSL_clear_mode)]
3852 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
3853 let bits = unsafe { ffi::SSL_clear_mode(self.as_ptr(), mode.bits()) };
3854 SslMode::from_bits_retain(bits)
3855 }
3856
3857 #[corresponds(SSL_add1_chain_cert)]
3859 pub fn add_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3860 unsafe { cvt(ffi::SSL_add1_chain_cert(self.as_ptr(), cert.as_ptr())) }
3861 }
3862
3863 #[corresponds(SSL_set1_ech_config_list)]
3871 pub fn set_ech_config_list(&mut self, ech_config_list: &[u8]) -> Result<(), ErrorStack> {
3872 unsafe {
3873 cvt_0i(ffi::SSL_set1_ech_config_list(
3874 self.as_ptr(),
3875 ech_config_list.as_ptr(),
3876 ech_config_list.len(),
3877 ))
3878 .map(|_| ())
3879 }
3880 }
3881
3882 #[corresponds(SSL_get0_ech_retry_configs)]
3889 #[must_use]
3890 pub fn get_ech_retry_configs(&self) -> Option<&[u8]> {
3891 unsafe {
3892 let mut data = ptr::null();
3893 let mut len: usize = 0;
3894 ffi::SSL_get0_ech_retry_configs(self.as_ptr(), &mut data, &mut len);
3895
3896 if data.is_null() {
3897 None
3898 } else {
3899 Some(slice::from_raw_parts(data, len))
3900 }
3901 }
3902 }
3903
3904 #[corresponds(SSL_get0_ech_name_override)]
3911 #[must_use]
3912 pub fn get_ech_name_override(&self) -> Option<&[u8]> {
3913 unsafe {
3914 let mut data: *const c_char = ptr::null();
3915 let mut len: usize = 0;
3916 ffi::SSL_get0_ech_name_override(self.as_ptr(), &mut data, &mut len);
3917
3918 if data.is_null() {
3919 None
3920 } else {
3921 Some(slice::from_raw_parts(data.cast::<u8>(), len))
3922 }
3923 }
3924 }
3925
3926 #[corresponds(SSL_ech_accepted)]
3928 #[must_use]
3929 pub fn ech_accepted(&self) -> bool {
3930 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
3931 }
3932
3933 #[corresponds(SSL_set_enable_ech_grease)]
3935 pub fn set_enable_ech_grease(&self, enable: bool) {
3936 let enable = if enable { 1 } else { 0 };
3937
3938 unsafe {
3939 ffi::SSL_set_enable_ech_grease(self.as_ptr(), enable);
3940 }
3941 }
3942
3943 #[corresponds(SSL_set_compliance_policy)]
3945 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
3946 unsafe { cvt_0i(ffi::SSL_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
3947 }
3948
3949 #[corresponds(SSL_add1_credential)]
3951 #[cfg(feature = "credential")]
3952 pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> {
3953 unsafe { cvt_0i(ffi::SSL_add1_credential(self.as_ptr(), credential.as_ptr())).map(|_| ()) }
3954 }
3955
3956 #[corresponds(SSL_get0_peer_pubkey)]
3958 #[cfg(feature = "rpk")]
3959 pub fn peer_pubkey(&self) -> Option<&PKeyRef<Public>> {
3960 unsafe {
3961 let pubkey = ffi::SSL_get0_peer_pubkey(self.as_ptr());
3962
3963 if pubkey.is_null() {
3964 return None;
3965 }
3966
3967 Some(PKeyRef::from_ptr(pubkey as *mut _))
3968 }
3969 }
3970
3971 #[corresponds(SSL_set1_accepted_peer_cert_types)]
3976 #[cfg(feature = "rpk")]
3977 pub fn set_server_certificate_types(
3978 &mut self,
3979 types: &[CertificateType],
3980 ) -> Result<(), ErrorStack> {
3981 if self.is_server() {
3982 return Err(ErrorStack::internal_error_str(
3983 "called set_server_certificate_types as server",
3984 ));
3985 }
3986
3987 unsafe {
3988 cvt_0i(ffi::SSL_set1_accepted_peer_cert_types(
3989 self.as_ptr(),
3990 types.as_ptr() as *const u8,
3991 types.len(),
3992 ))
3993 .map(|_| ())
3994 }
3995 }
3996
3997 #[corresponds(SSL_get0_accepted_peer_cert_types)]
4002 #[must_use]
4003 #[cfg(feature = "rpk")]
4004 pub fn server_certificate_types(&self) -> Option<&[CertificateType]> {
4005 if self.is_server() {
4006 return None;
4007 }
4008
4009 let mut types = ptr::null();
4010 let mut types_len = 0;
4011 unsafe {
4012 ffi::SSL_get0_accepted_peer_cert_types(self.as_ptr(), &mut types, &mut types_len);
4013
4014 if types_len == 0 {
4015 return None;
4016 }
4017
4018 Some(slice::from_raw_parts(
4019 types as *const CertificateType,
4020 types_len,
4021 ))
4022 }
4023 }
4024
4025 #[corresponds(SSL_get_peer_cert_type)]
4031 #[must_use]
4032 #[cfg(feature = "rpk")]
4033 pub fn selected_server_certificate_type(&self) -> Option<CertificateType> {
4034 if self.is_server() {
4035 return None;
4036 }
4037
4038 unsafe {
4039 Some(CertificateType(
4040 ffi::SSL_get_peer_cert_type(self.as_ptr()) as u8
4041 ))
4042 }
4043 }
4044}
4045
4046#[derive(Debug)]
4048pub struct MidHandshakeSslStream<S> {
4049 stream: SslStream<S>,
4050 error: Error,
4051}
4052
4053impl<S> MidHandshakeSslStream<S> {
4054 #[must_use]
4056 pub fn get_ref(&self) -> &S {
4057 self.stream.get_ref()
4058 }
4059
4060 pub fn get_mut(&mut self) -> &mut S {
4062 self.stream.get_mut()
4063 }
4064
4065 #[must_use]
4067 pub fn ssl(&self) -> &SslRef {
4068 self.stream.ssl()
4069 }
4070
4071 pub fn ssl_mut(&mut self) -> &mut SslRef {
4073 self.stream.ssl_mut()
4074 }
4075
4076 #[must_use]
4078 pub fn error(&self) -> &Error {
4079 &self.error
4080 }
4081
4082 #[must_use]
4084 pub fn into_error(self) -> Error {
4085 self.error
4086 }
4087
4088 #[must_use]
4090 pub fn into_source_stream(self) -> S {
4091 self.stream.into_inner()
4092 }
4093
4094 #[must_use]
4096 pub fn into_parts(self) -> (Error, S) {
4097 (self.error, self.stream.into_inner())
4098 }
4099
4100 #[corresponds(SSL_do_handshake)]
4102 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4103 let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) };
4104 if ret > 0 {
4105 Ok(self.stream)
4106 } else {
4107 self.error = self.stream.make_error(ret);
4108 Err(if self.error.would_block() {
4109 HandshakeError::WouldBlock(self)
4110 } else {
4111 HandshakeError::Failure(self)
4112 })
4113 }
4114 }
4115}
4116
4117pub struct SslStream<S> {
4119 ssl: ManuallyDrop<Ssl>,
4120 method: ManuallyDrop<BioMethod>,
4121 _p: PhantomData<S>,
4122}
4123
4124impl<S> Drop for SslStream<S> {
4125 fn drop(&mut self) {
4126 unsafe {
4128 ManuallyDrop::drop(&mut self.ssl);
4129 ManuallyDrop::drop(&mut self.method);
4130 }
4131 }
4132}
4133
4134impl<S> fmt::Debug for SslStream<S>
4135where
4136 S: fmt::Debug,
4137{
4138 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
4139 fmt.debug_struct("SslStream")
4140 .field("stream", &self.get_ref())
4141 .field("ssl", &self.ssl())
4142 .finish()
4143 }
4144}
4145
4146impl<S: Read + Write> SslStream<S> {
4147 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4153 let (bio, method) = bio::new(stream)?;
4154
4155 unsafe {
4156 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4157 }
4158
4159 Ok(SslStream {
4160 ssl: ManuallyDrop::new(ssl),
4161 method: ManuallyDrop::new(method),
4162 _p: PhantomData,
4163 })
4164 }
4165
4166 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
4174 let ssl = unsafe { Ssl::from_ptr(ssl) };
4175 Self::new(ssl, stream).unwrap()
4176 }
4177
4178 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4185 loop {
4186 match self.ssl_read_uninit(buf) {
4187 Ok(n) => return Ok(n),
4188 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4189 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4190 return Ok(0);
4191 }
4192 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4193 Err(e) => {
4194 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4195 }
4196 }
4197 }
4198 }
4199
4200 #[corresponds(SSL_read)]
4205 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4206 unsafe {
4208 self.ssl_read_uninit(slice::from_raw_parts_mut(
4209 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4210 buf.len(),
4211 ))
4212 }
4213 }
4214
4215 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4222 if buf.is_empty() {
4223 return Ok(0);
4224 }
4225
4226 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4227 let ret = unsafe { ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) };
4228 if ret > 0 {
4229 Ok(ret as usize)
4230 } else {
4231 Err(self.make_error(ret))
4232 }
4233 }
4234
4235 #[corresponds(SSL_write)]
4240 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4241 if buf.is_empty() {
4242 return Ok(0);
4243 }
4244
4245 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4246 let ret = unsafe { ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) };
4247 if ret > 0 {
4248 Ok(ret as usize)
4249 } else {
4250 Err(self.make_error(ret))
4251 }
4252 }
4253
4254 #[corresponds(SSL_shutdown)]
4264 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4265 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4266 0 => Ok(ShutdownResult::Sent),
4267 1 => Ok(ShutdownResult::Received),
4268 n => Err(self.make_error(n)),
4269 }
4270 }
4271
4272 #[corresponds(SSL_get_shutdown)]
4274 pub fn get_shutdown(&mut self) -> ShutdownState {
4275 unsafe {
4276 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4277 ShutdownState::from_bits_retain(bits)
4278 }
4279 }
4280
4281 #[corresponds(SSL_set_shutdown)]
4286 pub fn set_shutdown(&mut self, state: ShutdownState) {
4287 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4288 }
4289
4290 #[corresponds(SSL_connect)]
4292 pub fn connect(&mut self) -> Result<(), Error> {
4293 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4294 if ret > 0 {
4295 Ok(())
4296 } else {
4297 Err(self.make_error(ret))
4298 }
4299 }
4300
4301 #[corresponds(SSL_accept)]
4303 pub fn accept(&mut self) -> Result<(), Error> {
4304 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4305 if ret > 0 {
4306 Ok(())
4307 } else {
4308 Err(self.make_error(ret))
4309 }
4310 }
4311
4312 #[corresponds(SSL_do_handshake)]
4314 pub fn do_handshake(&mut self) -> Result<(), Error> {
4315 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4316 if ret > 0 {
4317 Ok(())
4318 } else {
4319 Err(self.make_error(ret))
4320 }
4321 }
4322}
4323
4324impl<S> SslStream<S> {
4325 fn make_error(&mut self, ret: c_int) -> Error {
4326 self.check_panic();
4327
4328 let code = self.ssl.error_code(ret);
4329
4330 let cause = match code {
4331 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4332 ErrorCode::SYSCALL => {
4333 let errs = ErrorStack::get();
4334 if errs.errors().is_empty() {
4335 self.get_bio_error().map(InnerError::Io)
4336 } else {
4337 Some(InnerError::Ssl(errs))
4338 }
4339 }
4340 ErrorCode::ZERO_RETURN => None,
4341 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4342 self.get_bio_error().map(InnerError::Io)
4343 }
4344 _ => None,
4345 };
4346
4347 Error { code, cause }
4348 }
4349
4350 fn check_panic(&mut self) {
4351 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4352 resume_unwind(err)
4353 }
4354 }
4355
4356 fn get_bio_error(&mut self) -> Option<io::Error> {
4357 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4358 }
4359
4360 #[must_use]
4362 pub fn into_inner(self) -> S {
4363 unsafe { bio::take_stream::<S>(self.ssl.get_raw_rbio()) }
4364 }
4365
4366 #[must_use]
4368 pub fn get_ref(&self) -> &S {
4369 unsafe {
4370 let bio = self.ssl.get_raw_rbio();
4371 bio::get_ref(bio)
4372 }
4373 }
4374
4375 pub fn get_mut(&mut self) -> &mut S {
4382 unsafe {
4383 let bio = self.ssl.get_raw_rbio();
4384 bio::get_mut(bio)
4385 }
4386 }
4387
4388 #[must_use]
4390 pub fn ssl(&self) -> &SslRef {
4391 &self.ssl
4392 }
4393
4394 pub fn ssl_mut(&mut self) -> &mut SslRef {
4396 &mut self.ssl
4397 }
4398}
4399
4400impl<S: Read + Write> Read for SslStream<S> {
4401 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4402 unsafe {
4404 self.read_uninit(slice::from_raw_parts_mut(
4405 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4406 buf.len(),
4407 ))
4408 }
4409 }
4410}
4411
4412impl<S: Read + Write> Write for SslStream<S> {
4413 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4414 loop {
4415 match self.ssl_write(buf) {
4416 Ok(n) => return Ok(n),
4417 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4418 Err(e) => {
4419 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4420 }
4421 }
4422 }
4423 }
4424
4425 fn flush(&mut self) -> io::Result<()> {
4426 self.get_mut().flush()
4427 }
4428}
4429
4430pub struct SslStreamBuilder<S> {
4432 inner: SslStream<S>,
4433}
4434
4435impl<S> SslStreamBuilder<S>
4436where
4437 S: Read + Write,
4438{
4439 pub fn new(ssl: Ssl, stream: S) -> Self {
4441 Self {
4442 inner: SslStream::new(ssl, stream).unwrap(),
4443 }
4444 }
4445
4446 #[corresponds(SSL_set_connect_state)]
4448 pub fn set_connect_state(&mut self) {
4449 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4450 }
4451
4452 #[corresponds(SSL_set_accept_state)]
4454 pub fn set_accept_state(&mut self) {
4455 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4456 }
4457
4458 #[must_use]
4464 pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
4465 self.set_connect_state();
4466
4467 MidHandshakeSslStream {
4468 stream: self.inner,
4469 error: Error {
4470 code: ErrorCode::WANT_WRITE,
4471 cause: Some(InnerError::Io(io::Error::new(
4472 io::ErrorKind::WouldBlock,
4473 "connect handshake has not started yet",
4474 ))),
4475 },
4476 }
4477 }
4478
4479 pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
4484 self.setup_connect().handshake()
4485 }
4486
4487 #[must_use]
4493 pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
4494 self.set_accept_state();
4495
4496 MidHandshakeSslStream {
4497 stream: self.inner,
4498 error: Error {
4499 code: ErrorCode::WANT_READ,
4500 cause: Some(InnerError::Io(io::Error::new(
4501 io::ErrorKind::WouldBlock,
4502 "accept handshake has not started yet",
4503 ))),
4504 },
4505 }
4506 }
4507
4508 pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
4513 self.setup_accept().handshake()
4514 }
4515
4516 #[corresponds(SSL_do_handshake)]
4520 pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
4521 let mut stream = self.inner;
4522 let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
4523 if ret > 0 {
4524 Ok(stream)
4525 } else {
4526 let error = stream.make_error(ret);
4527 Err(if error.would_block() {
4528 HandshakeError::WouldBlock(MidHandshakeSslStream { stream, error })
4529 } else {
4530 HandshakeError::Failure(MidHandshakeSslStream { stream, error })
4531 })
4532 }
4533 }
4534}
4535
4536impl<S> SslStreamBuilder<S> {
4537 #[must_use]
4539 pub fn get_ref(&self) -> &S {
4540 unsafe {
4541 let bio = self.inner.ssl.get_raw_rbio();
4542 bio::get_ref(bio)
4543 }
4544 }
4545
4546 pub fn get_mut(&mut self) -> &mut S {
4553 unsafe {
4554 let bio = self.inner.ssl.get_raw_rbio();
4555 bio::get_mut(bio)
4556 }
4557 }
4558
4559 #[must_use]
4561 pub fn ssl(&self) -> &SslRef {
4562 &self.inner.ssl
4563 }
4564
4565 pub fn ssl_mut(&mut self) -> &mut SslRef {
4567 &mut self.inner.ssl
4568 }
4569
4570 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4578 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4579 unsafe {
4580 let bio = self.inner.ssl.get_raw_rbio();
4581 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4582 }
4583 }
4584}
4585
4586#[cfg(feature = "rpk")]
4588#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4589#[repr(transparent)]
4590pub struct CertificateType(u8);
4591
4592#[cfg(feature = "rpk")]
4593impl CertificateType {
4594 pub const X509: Self = Self(ffi::TLSEXT_cert_type_x509 as u8);
4596
4597 pub const RAW_PUBLIC_KEY: Self = Self(ffi::TLSEXT_cert_type_rpk as u8);
4599}
4600
4601#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4603pub enum ShutdownResult {
4604 Sent,
4606
4607 Received,
4609}
4610
4611bitflags! {
4612 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
4614 pub struct ShutdownState: c_int {
4615 const SENT = ffi::SSL_SENT_SHUTDOWN;
4617 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4619 }
4620}
4621
4622pub trait PrivateKeyMethod: Send + Sync + 'static {
4630 fn sign(
4641 &self,
4642 ssl: &mut SslRef,
4643 input: &[u8],
4644 signature_algorithm: SslSignatureAlgorithm,
4645 output: &mut [u8],
4646 ) -> Result<usize, PrivateKeyMethodError>;
4647
4648 fn decrypt(
4663 &self,
4664 ssl: &mut SslRef,
4665 input: &[u8],
4666 output: &mut [u8],
4667 ) -> Result<usize, PrivateKeyMethodError>;
4668
4669 fn complete(&self, ssl: &mut SslRef, output: &mut [u8])
4678 -> Result<usize, PrivateKeyMethodError>;
4679}
4680
4681#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4683pub struct PrivateKeyMethodError(ffi::ssl_private_key_result_t);
4684
4685impl PrivateKeyMethodError {
4686 pub const FAILURE: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_failure);
4688
4689 pub const RETRY: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_retry);
4691}
4692
4693pub trait CertificateCompressor: Send + Sync + 'static {
4695 const ALGORITHM: CertificateCompressionAlgorithm;
4697
4698 const CAN_COMPRESS: bool;
4700
4701 const CAN_DECOMPRESS: bool;
4703
4704 #[allow(unused_variables)]
4706 fn compress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4707 where
4708 W: std::io::Write,
4709 {
4710 Err(std::io::Error::other("not implemented"))
4711 }
4712
4713 #[allow(unused_variables)]
4715 fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4716 where
4717 W: std::io::Write,
4718 {
4719 Err(std::io::Error::other("not implemented"))
4720 }
4721}
4722
4723use crate::ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4724
4725unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4726 unsafe { ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f) }
4727}
4728
4729unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4730 unsafe { ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f) }
4731}
4732
4733fn path_to_cstring(path: &Path) -> Result<CString, ErrorStack> {
4734 CString::new(path.as_os_str().as_encoded_bytes()).map_err(ErrorStack::internal_error)
4735}