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
638impl TryFrom<u16> for SslVersion {
639 type Error = &'static str;
640
641 fn try_from(value: u16) -> Result<Self, Self::Error> {
642 match i32::from(value) {
643 ffi::SSL3_VERSION
644 | ffi::TLS1_VERSION
645 | ffi::TLS1_1_VERSION
646 | ffi::TLS1_2_VERSION
647 | ffi::TLS1_3_VERSION => Ok(Self(value)),
648 _ => Err("Unknown SslVersion"),
649 }
650 }
651}
652
653impl fmt::Debug for SslVersion {
654 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
655 f.write_str(match *self {
656 Self::SSL3 => "SSL3",
657 Self::TLS1 => "TLS1",
658 Self::TLS1_1 => "TLS1_1",
659 Self::TLS1_2 => "TLS1_2",
660 Self::TLS1_3 => "TLS1_3",
661 _ => return write!(f, "{:#06x}", self.0),
662 })
663 }
664}
665
666impl fmt::Display for SslVersion {
667 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
668 f.write_str(match *self {
669 Self::SSL3 => "SSLv3",
670 Self::TLS1 => "TLSv1",
671 Self::TLS1_1 => "TLSv1.1",
672 Self::TLS1_2 => "TLSv1.2",
673 Self::TLS1_3 => "TLSv1.3",
674 _ => return write!(f, "unknown ({:#06x})", self.0),
675 })
676 }
677}
678
679#[repr(transparent)]
685#[derive(Debug, Copy, Clone, PartialEq, Eq)]
686pub struct SslSignatureAlgorithm(u16);
687
688impl SslSignatureAlgorithm {
689 pub const RSA_PKCS1_SHA1: SslSignatureAlgorithm =
690 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA1 as _);
691
692 pub const RSA_PKCS1_SHA256: SslSignatureAlgorithm =
693 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA256 as _);
694
695 pub const RSA_PKCS1_SHA384: SslSignatureAlgorithm =
696 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA384 as _);
697
698 pub const RSA_PKCS1_SHA512: SslSignatureAlgorithm =
699 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA512 as _);
700
701 pub const RSA_PKCS1_MD5_SHA1: SslSignatureAlgorithm =
702 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_MD5_SHA1 as _);
703
704 pub const ECDSA_SHA1: SslSignatureAlgorithm =
705 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SHA1 as _);
706
707 pub const ECDSA_SECP256R1_SHA256: SslSignatureAlgorithm =
708 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP256R1_SHA256 as _);
709
710 pub const ECDSA_SECP384R1_SHA384: SslSignatureAlgorithm =
711 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP384R1_SHA384 as _);
712
713 pub const ECDSA_SECP521R1_SHA512: SslSignatureAlgorithm =
714 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP521R1_SHA512 as _);
715
716 pub const RSA_PSS_RSAE_SHA256: SslSignatureAlgorithm =
717 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA256 as _);
718
719 pub const RSA_PSS_RSAE_SHA384: SslSignatureAlgorithm =
720 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA384 as _);
721
722 pub const RSA_PSS_RSAE_SHA512: SslSignatureAlgorithm =
723 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA512 as _);
724
725 pub const ED25519: SslSignatureAlgorithm = SslSignatureAlgorithm(ffi::SSL_SIGN_ED25519 as _);
726}
727
728impl From<u16> for SslSignatureAlgorithm {
729 fn from(value: u16) -> Self {
730 Self(value)
731 }
732}
733
734#[derive(Debug, Copy, Clone, PartialEq, Eq)]
736pub struct CompliancePolicy(ffi::ssl_compliance_policy_t);
737
738impl CompliancePolicy {
739 #[cfg(not(feature = "legacy-compat-deprecated"))]
741 pub const NONE: Self = Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_none);
742
743 pub const FIPS_202205: Self =
746 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_fips_202205);
747
748 #[cfg(not(feature = "legacy-compat-deprecated"))]
751 pub const WPA3_192_202304: Self =
752 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_wpa3_192_202304);
753}
754
755#[derive(Debug, Copy, Clone, PartialEq, Eq)]
757pub struct CertificateCompressionAlgorithm(u16);
758
759impl CertificateCompressionAlgorithm {
760 pub const ZLIB: Self = Self(ffi::TLSEXT_cert_compression_zlib as u16);
761
762 pub const BROTLI: Self = Self(ffi::TLSEXT_cert_compression_brotli as u16);
763}
764
765#[corresponds(SSL_select_next_proto)]
776#[must_use]
777pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
778 if server.is_empty() || client.is_empty() {
779 return None;
780 }
781
782 unsafe {
783 let mut out = ptr::null_mut();
784 let mut outlen = 0;
785 let r = ffi::SSL_select_next_proto(
786 &mut out,
787 &mut outlen,
788 server.as_ptr(),
789 try_int(server.len()).ok()?,
790 client.as_ptr(),
791 try_int(client.len()).ok()?,
792 );
793
794 if r == ffi::OPENSSL_NPN_NEGOTIATED {
795 Some(slice::from_raw_parts(out.cast_const(), outlen as usize))
796 } else {
797 None
798 }
799 }
800}
801
802#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
804pub struct SslInfoCallbackMode(i32);
805
806impl SslInfoCallbackMode {
807 pub const READ_ALERT: Self = Self(ffi::SSL_CB_READ_ALERT);
809
810 pub const WRITE_ALERT: Self = Self(ffi::SSL_CB_WRITE_ALERT);
812
813 pub const HANDSHAKE_START: Self = Self(ffi::SSL_CB_HANDSHAKE_START);
815
816 pub const HANDSHAKE_DONE: Self = Self(ffi::SSL_CB_HANDSHAKE_DONE);
818
819 pub const ACCEPT_LOOP: Self = Self(ffi::SSL_CB_ACCEPT_LOOP);
821
822 pub const ACCEPT_EXIT: Self = Self(ffi::SSL_CB_ACCEPT_EXIT);
824
825 pub const CONNECT_EXIT: Self = Self(ffi::SSL_CB_CONNECT_EXIT);
827}
828
829#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
832pub enum SslInfoCallbackValue {
833 Unit,
837 Alert(SslInfoCallbackAlert),
841}
842
843#[derive(Debug, Copy, Clone, PartialEq, Eq)]
845pub enum TicketKeyCallbackResult {
846 Error,
848
849 Noop,
858
859 Success,
864
865 DecryptSuccessRenew,
877}
878
879impl From<TicketKeyCallbackResult> for c_int {
880 fn from(value: TicketKeyCallbackResult) -> Self {
881 match value {
882 TicketKeyCallbackResult::Error => -1,
883 TicketKeyCallbackResult::Noop => 0,
884 TicketKeyCallbackResult::Success => 1,
885 TicketKeyCallbackResult::DecryptSuccessRenew => 2,
886 }
887 }
888}
889
890#[derive(Hash, Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
891pub struct SslInfoCallbackAlert(c_int);
892
893impl SslInfoCallbackAlert {
894 #[must_use]
896 pub fn alert_level(&self) -> Ssl3AlertLevel {
897 let value = self.0 >> 8;
898 Ssl3AlertLevel(value)
899 }
900
901 #[must_use]
903 pub fn alert(&self) -> SslAlert {
904 let value = self.0 & i32::from(u8::MAX);
905 SslAlert(value)
906 }
907}
908
909#[derive(Debug, Copy, Clone, PartialEq, Eq)]
910pub struct Ssl3AlertLevel(c_int);
911
912impl Ssl3AlertLevel {
913 pub const WARNING: Ssl3AlertLevel = Self(ffi::SSL3_AL_WARNING);
914 pub const FATAL: Ssl3AlertLevel = Self(ffi::SSL3_AL_FATAL);
915}
916
917pub struct SslContextBuilder {
919 ctx: SslContext,
920 has_shared_cert_store: bool,
922}
923
924impl SslContextBuilder {
925 #[corresponds(SSL_CTX_new)]
927 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
928 unsafe {
929 init();
930 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
931 let mut builder = SslContextBuilder::from_ptr(ctx);
932
933 if method.is_x509_method {
934 builder.ctx.assume_x509();
935 }
936
937 Ok(builder)
938 }
939 }
940
941 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> Self {
953 Self {
954 ctx: SslContext::from_ptr(ctx),
955 has_shared_cert_store: false,
956 }
957 }
958
959 pub unsafe fn assume_x509(&mut self) {
967 self.ctx.assume_x509();
968 }
969
970 #[must_use]
972 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
973 self.ctx.as_ptr()
974 }
975
976 #[corresponds(SSL_CTX_set_cert_verify_callback)]
996 pub fn set_cert_verify_callback<F>(&mut self, callback: F)
997 where
998 F: Fn(&mut X509StoreContextRef) -> bool + 'static + Sync + Send,
999 {
1000 self.ctx.check_x509();
1001
1002 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1009 unsafe {
1010 ffi::SSL_CTX_set_cert_verify_callback(
1011 self.as_ptr(),
1012 Some(raw_cert_verify::<F>),
1013 ptr::null_mut(),
1014 );
1015 }
1016 }
1017
1018 #[corresponds(SSL_CTX_set_verify)]
1020 pub fn set_verify(&mut self, mode: SslVerifyMode) {
1021 self.ctx.check_x509();
1022
1023 unsafe {
1024 ffi::SSL_CTX_set_verify(self.as_ptr(), c_int::from(mode.bits()), None);
1025 }
1026 }
1027
1028 #[corresponds(SSL_CTX_set_verify)]
1045 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1046 where
1047 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1048 {
1049 self.ctx.check_x509();
1050
1051 unsafe {
1052 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1053 ffi::SSL_CTX_set_verify(
1054 self.as_ptr(),
1055 c_int::from(mode.bits()),
1056 Some(raw_verify::<F>),
1057 );
1058 }
1059 }
1060
1061 #[corresponds(SSL_CTX_set_custom_verify)]
1076 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1077 where
1078 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
1079 {
1080 unsafe {
1081 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1082 ffi::SSL_CTX_set_custom_verify(
1083 self.as_ptr(),
1084 c_int::from(mode.bits()),
1085 Some(raw_custom_verify::<F>),
1086 );
1087 }
1088 }
1089
1090 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
1100 pub fn set_servername_callback<F>(&mut self, callback: F)
1101 where
1102 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
1103 {
1104 unsafe {
1105 let callback_index = SslContext::cached_ex_index::<F>();
1112
1113 self.ctx.replace_ex_data(callback_index, callback);
1114 let callback = self.ctx.ex_data(callback_index).unwrap();
1115
1116 let arg = std::ptr::from_ref(callback).cast_mut().cast();
1117 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
1118 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
1119 }
1120 }
1121
1122 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1145 pub unsafe fn set_ticket_key_callback<F>(&mut self, callback: F)
1146 where
1147 F: Fn(
1148 &SslRef,
1149 &mut [u8; 16],
1150 &mut [u8; ffi::EVP_MAX_IV_LENGTH as usize],
1151 &mut CipherCtxRef,
1152 &mut HmacCtxRef,
1153 bool,
1154 ) -> TicketKeyCallbackResult
1155 + 'static
1156 + Sync
1157 + Send,
1158 {
1159 self.ctx.check_x509();
1160
1161 unsafe {
1162 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1163 ffi::SSL_CTX_set_tlsext_ticket_key_cb(self.as_ptr(), Some(raw_ticket_key::<F>))
1164 };
1165 }
1166
1167 #[corresponds(SSL_CTX_set_verify_depth)]
1171 pub fn set_verify_depth(&mut self, depth: u32) {
1172 self.ctx.check_x509();
1173
1174 unsafe {
1175 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
1176 }
1177 }
1178
1179 #[corresponds(SSL_CTX_set0_verify_cert_store)]
1181 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
1182 self.ctx.check_x509();
1183
1184 unsafe {
1185 cvt(ffi::SSL_CTX_set0_verify_cert_store(
1186 self.as_ptr(),
1187 cert_store.into_ptr(),
1188 ))
1189 }
1190 }
1191
1192 #[corresponds(SSL_CTX_set_cert_store)]
1199 pub fn set_cert_store(&mut self, cert_store: X509Store) {
1200 self.ctx.check_x509();
1201
1202 self.has_shared_cert_store = true;
1203 unsafe {
1204 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1205 }
1206 }
1207
1208 #[corresponds(SSL_CTX_set_cert_store)]
1210 pub fn set_cert_store_builder(&mut self, cert_store: X509StoreBuilder) {
1211 self.ctx.check_x509();
1212
1213 self.has_shared_cert_store = false;
1214 unsafe {
1215 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1216 }
1217 }
1218
1219 #[corresponds(SSL_CTX_set_cert_store)]
1223 pub fn set_cert_store_ref(&mut self, cert_store: &X509Store) {
1224 self.set_cert_store(cert_store.to_owned());
1225 }
1226
1227 #[corresponds(SSL_CTX_set_read_ahead)]
1234 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1235 unsafe {
1236 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), c_int::from(read_ahead));
1237 }
1238 }
1239
1240 #[corresponds(SSL_CTX_set_mode)]
1242 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1243 let bits = unsafe { ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits()) };
1244 SslMode::from_bits_retain(bits)
1245 }
1246
1247 #[corresponds(SSL_CTX_set_tmp_dh)]
1249 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1250 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr())) }
1251 }
1252
1253 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1255 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1256 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr())) }
1257 }
1258
1259 #[corresponds(SSL_CTX_set_default_verify_paths)]
1264 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1265 self.ctx.check_x509();
1266
1267 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())) }
1268 }
1269
1270 #[corresponds(SSL_CTX_load_verify_locations)]
1274 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1275 self.load_verify_locations(Some(file.as_ref()), None)
1276 }
1277
1278 #[corresponds(SSL_CTX_load_verify_locations)]
1280 pub fn load_verify_locations(
1281 &mut self,
1282 ca_file: Option<&Path>,
1283 ca_path: Option<&Path>,
1284 ) -> Result<(), ErrorStack> {
1285 self.ctx.check_x509();
1286
1287 let ca_file = ca_file.map(path_to_cstring).transpose()?;
1288 let ca_path = ca_path.map(path_to_cstring).transpose()?;
1289
1290 unsafe {
1291 cvt(ffi::SSL_CTX_load_verify_locations(
1292 self.as_ptr(),
1293 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1294 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1295 ))
1296 }
1297 }
1298
1299 #[corresponds(SSL_CTX_set_client_CA_list)]
1304 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1305 self.ctx.check_x509();
1306
1307 unsafe {
1308 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1309 mem::forget(list);
1310 }
1311 }
1312
1313 #[corresponds(SSL_CTX_add_client_CA)]
1316 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1317 self.ctx.check_x509();
1318
1319 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())) }
1320 }
1321
1322 #[corresponds(SSL_CTX_set_session_id_context)]
1331 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1332 unsafe {
1333 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1334 cvt(ffi::SSL_CTX_set_session_id_context(
1335 self.as_ptr(),
1336 sid_ctx.as_ptr(),
1337 sid_ctx.len(),
1338 ))
1339 }
1340 }
1341
1342 #[corresponds(SSL_CTX_use_certificate_file)]
1348 pub fn set_certificate_file<P: AsRef<Path>>(
1349 &mut self,
1350 file: P,
1351 file_type: SslFiletype,
1352 ) -> Result<(), ErrorStack> {
1353 self.ctx.check_x509();
1354
1355 let file = path_to_cstring(file.as_ref())?;
1356 unsafe {
1357 cvt(ffi::SSL_CTX_use_certificate_file(
1358 self.as_ptr(),
1359 file.as_ptr(),
1360 file_type.as_raw(),
1361 ))
1362 }
1363 }
1364
1365 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1371 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1372 &mut self,
1373 file: P,
1374 ) -> Result<(), ErrorStack> {
1375 let file = path_to_cstring(file.as_ref())?;
1376 unsafe {
1377 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1378 self.as_ptr(),
1379 file.as_ptr(),
1380 ))
1381 }
1382 }
1383
1384 #[corresponds(SSL_CTX_use_certificate)]
1388 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1389 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())) }
1390 }
1391
1392 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1397 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1398 self.ctx.check_x509();
1399
1400 unsafe {
1401 cvt(ffi::SSL_CTX_add_extra_chain_cert(
1402 self.as_ptr(),
1403 cert.into_ptr(),
1404 ))
1405 }
1406 }
1407
1408 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1410 pub fn set_private_key_file<P: AsRef<Path>>(
1411 &mut self,
1412 file: P,
1413 file_type: SslFiletype,
1414 ) -> Result<(), ErrorStack> {
1415 let file = path_to_cstring(file.as_ref())?;
1416 unsafe {
1417 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1418 self.as_ptr(),
1419 file.as_ptr(),
1420 file_type.as_raw(),
1421 ))
1422 }
1423 }
1424
1425 #[corresponds(SSL_CTX_use_PrivateKey)]
1427 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1428 where
1429 T: HasPrivate,
1430 {
1431 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())) }
1432 }
1433
1434 #[corresponds(SSL_CTX_set_cipher_list)]
1446 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1447 let cipher_list = CString::new(cipher_list).map_err(ErrorStack::internal_error)?;
1448 unsafe {
1449 cvt(ffi::SSL_CTX_set_cipher_list(
1450 self.as_ptr(),
1451 cipher_list.as_ptr(),
1452 ))
1453 }
1454 }
1455
1456 #[corresponds(SSL_CTX_set_strict_cipher_list)]
1467 pub fn set_strict_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1468 let cipher_list = CString::new(cipher_list).map_err(ErrorStack::internal_error)?;
1469 unsafe {
1470 cvt(ffi::SSL_CTX_set_strict_cipher_list(
1471 self.as_ptr(),
1472 cipher_list.as_ptr(),
1473 ))
1474 }
1475 }
1476
1477 #[corresponds(SSL_CTX_get_ciphers)]
1483 #[must_use]
1484 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
1485 self.ctx.ciphers()
1486 }
1487
1488 #[corresponds(SSL_CTX_set_options)]
1495 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1496 let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
1497 SslOptions::from_bits_retain(bits)
1498 }
1499
1500 #[corresponds(SSL_CTX_get_options)]
1502 #[must_use]
1503 pub fn options(&self) -> SslOptions {
1504 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
1505 SslOptions::from_bits_retain(bits)
1506 }
1507
1508 #[corresponds(SSL_CTX_clear_options)]
1510 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1511 let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
1512 SslOptions::from_bits_retain(bits)
1513 }
1514
1515 #[corresponds(SSL_CTX_set_min_proto_version)]
1520 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1521 unsafe {
1522 cvt(ffi::SSL_CTX_set_min_proto_version(
1523 self.as_ptr(),
1524 version.map_or(0, |v| v.0 as _),
1525 ))
1526 }
1527 }
1528
1529 #[corresponds(SSL_CTX_set_max_proto_version)]
1533 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1534 unsafe {
1535 cvt(ffi::SSL_CTX_set_max_proto_version(
1536 self.as_ptr(),
1537 version.map_or(0, |v| v.0 as _),
1538 ))
1539 }
1540 }
1541
1542 #[corresponds(SSL_CTX_get_min_proto_version)]
1544 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1545 unsafe {
1546 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1547 if r == 0 {
1548 None
1549 } else {
1550 Some(SslVersion(r))
1551 }
1552 }
1553 }
1554
1555 #[corresponds(SSL_CTX_get_max_proto_version)]
1557 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1558 unsafe {
1559 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1560 if r == 0 {
1561 None
1562 } else {
1563 Some(SslVersion(r))
1564 }
1565 }
1566 }
1567
1568 #[corresponds(SSL_CTX_set_alpn_protos)]
1575 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1576 unsafe {
1577 let r = ffi::SSL_CTX_set_alpn_protos(
1578 self.as_ptr(),
1579 protocols.as_ptr(),
1580 try_int(protocols.len())?,
1581 );
1582 if r == 0 {
1584 Ok(())
1585 } else {
1586 Err(ErrorStack::get())
1587 }
1588 }
1589 }
1590
1591 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1593 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1594 unsafe {
1595 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
1596
1597 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1598 if r == 0 {
1600 Ok(())
1601 } else {
1602 Err(ErrorStack::get())
1603 }
1604 }
1605 }
1606
1607 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1618 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1619 where
1620 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1621 {
1622 unsafe {
1623 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1624 ffi::SSL_CTX_set_alpn_select_cb(
1625 self.as_ptr(),
1626 Some(callbacks::raw_alpn_select::<F>),
1627 ptr::null_mut(),
1628 );
1629 }
1630 }
1631
1632 #[corresponds(SSL_CTX_set_select_certificate_cb)]
1636 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
1637 where
1638 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
1639 {
1640 unsafe {
1641 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1642 ffi::SSL_CTX_set_select_certificate_cb(
1643 self.as_ptr(),
1644 Some(callbacks::raw_select_cert::<F>),
1645 );
1646 }
1647 }
1648
1649 #[corresponds(SSL_CTX_add_cert_compression_alg)]
1653 pub fn add_certificate_compression_algorithm<C>(
1654 &mut self,
1655 compressor: C,
1656 ) -> Result<(), ErrorStack>
1657 where
1658 C: CertificateCompressor,
1659 {
1660 const {
1661 assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered");
1662 };
1663 let success = unsafe {
1664 ffi::SSL_CTX_add_cert_compression_alg(
1665 self.as_ptr(),
1666 C::ALGORITHM.0,
1667 const {
1668 if C::CAN_COMPRESS {
1669 Some(callbacks::raw_ssl_cert_compress::<C>)
1670 } else {
1671 None
1672 }
1673 },
1674 const {
1675 if C::CAN_DECOMPRESS {
1676 Some(callbacks::raw_ssl_cert_decompress::<C>)
1677 } else {
1678 None
1679 }
1680 },
1681 ) == 1
1682 };
1683 if !success {
1684 return Err(ErrorStack::get());
1685 }
1686 self.replace_ex_data(SslContext::cached_ex_index::<C>(), compressor);
1687 Ok(())
1688 }
1689
1690 #[corresponds(SSL_CTX_set_private_key_method)]
1694 pub fn set_private_key_method<M>(&mut self, method: M)
1695 where
1696 M: PrivateKeyMethod,
1697 {
1698 unsafe {
1699 self.replace_ex_data(SslContext::cached_ex_index::<M>(), method);
1700
1701 ffi::SSL_CTX_set_private_key_method(
1702 self.as_ptr(),
1703 &ffi::SSL_PRIVATE_KEY_METHOD {
1704 sign: Some(callbacks::raw_sign::<M>),
1705 decrypt: Some(callbacks::raw_decrypt::<M>),
1706 complete: Some(callbacks::raw_complete::<M>),
1707 },
1708 );
1709 }
1710 }
1711
1712 #[corresponds(SSL_CTX_check_private_key)]
1714 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1715 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())) }
1716 }
1717
1718 #[corresponds(SSL_CTX_get_cert_store)]
1720 #[must_use]
1721 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1722 self.ctx.check_x509();
1723
1724 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1725 }
1726
1727 #[corresponds(SSL_CTX_get_cert_store)]
1737 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1738 self.ctx.check_x509();
1739
1740 assert!(
1741 !self.has_shared_cert_store,
1742 "Shared X509Store can't be mutated. Use set_cert_store_builder() instead of set_cert_store()
1743 or completely finish building the cert store setting it."
1744 );
1745 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1748 }
1749
1750 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1763 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1764 where
1765 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1766 {
1767 unsafe {
1768 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1769 cvt(ffi::SSL_CTX_set_tlsext_status_cb(
1770 self.as_ptr(),
1771 Some(raw_tlsext_status::<F>),
1772 ))
1773 }
1774 }
1775
1776 #[corresponds(SSL_CTX_set_psk_client_callback)]
1782 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1783 where
1784 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1785 + 'static
1786 + Sync
1787 + Send,
1788 {
1789 unsafe {
1790 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1791 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1792 }
1793 }
1794
1795 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1796 pub fn set_psk_callback<F>(&mut self, callback: F)
1797 where
1798 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1799 + 'static
1800 + Sync
1801 + Send,
1802 {
1803 self.set_psk_client_callback(callback);
1804 }
1805
1806 #[corresponds(SSL_CTX_set_psk_server_callback)]
1812 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1813 where
1814 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1815 + 'static
1816 + Sync
1817 + Send,
1818 {
1819 unsafe {
1820 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1821 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1822 }
1823 }
1824
1825 #[corresponds(SSL_CTX_sess_set_new_cb)]
1839 pub fn set_new_session_callback<F>(&mut self, callback: F)
1840 where
1841 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1842 {
1843 unsafe {
1844 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1845 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1846 }
1847 }
1848
1849 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1853 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1854 where
1855 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1856 {
1857 unsafe {
1858 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1859 ffi::SSL_CTX_sess_set_remove_cb(
1860 self.as_ptr(),
1861 Some(callbacks::raw_remove_session::<F>),
1862 );
1863 }
1864 }
1865
1866 #[corresponds(SSL_CTX_sess_set_get_cb)]
1877 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1878 where
1879 F: Fn(&mut SslRef, &[u8]) -> Result<Option<SslSession>, GetSessionPendingError>
1880 + 'static
1881 + Sync
1882 + Send,
1883 {
1884 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1885 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1886 }
1887
1888 #[corresponds(SSL_CTX_set_keylog_callback)]
1894 pub fn set_keylog_callback<F>(&mut self, callback: F)
1895 where
1896 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1897 {
1898 unsafe {
1899 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1900 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1901 }
1902 }
1903
1904 #[corresponds(SSL_CTX_set_session_cache_mode)]
1908 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1909 unsafe {
1910 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1911 SslSessionCacheMode::from_bits_retain(bits)
1912 }
1913 }
1914
1915 #[corresponds(SSL_CTX_set_ex_data)]
1920 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1921 unsafe {
1922 self.ctx.replace_ex_data(index, data);
1923 }
1924 }
1925
1926 #[corresponds(SSL_CTX_set_ex_data)]
1933 pub fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
1934 unsafe { self.ctx.replace_ex_data(index, data) }
1935 }
1936
1937 #[corresponds(SSL_CTX_sess_set_cache_size)]
1941 #[allow(clippy::useless_conversion)]
1942 pub fn set_session_cache_size(&mut self, size: u32) -> u64 {
1943 unsafe { ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size.into()).into() }
1944 }
1945
1946 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1948 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1949 let sigalgs = CString::new(sigalgs).map_err(ErrorStack::internal_error)?;
1950 unsafe {
1951 cvt(ffi::SSL_CTX_set1_sigalgs_list(
1952 self.as_ptr(),
1953 sigalgs.as_ptr(),
1954 ))
1955 }
1956 }
1957
1958 #[corresponds(SSL_CTX_set_grease_enabled)]
1960 pub fn set_grease_enabled(&mut self, enabled: bool) {
1961 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as _) }
1962 }
1963
1964 #[corresponds(SSL_CTX_set_permute_extensions)]
1966 pub fn set_permute_extensions(&mut self, enabled: bool) {
1967 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as _) }
1968 }
1969
1970 #[corresponds(SSL_CTX_set_verify_algorithm_prefs)]
1972 pub fn set_verify_algorithm_prefs(
1973 &mut self,
1974 prefs: &[SslSignatureAlgorithm],
1975 ) -> Result<(), ErrorStack> {
1976 unsafe {
1977 cvt_0i(ffi::SSL_CTX_set_verify_algorithm_prefs(
1978 self.as_ptr(),
1979 prefs.as_ptr().cast(),
1980 prefs.len(),
1981 ))
1982 .map(|_| ())
1983 }
1984 }
1985
1986 #[corresponds(SSL_CTX_enable_signed_cert_timestamps)]
1988 pub fn enable_signed_cert_timestamps(&mut self) {
1989 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1990 }
1991
1992 #[corresponds(SSL_CTX_enable_ocsp_stapling)]
1994 pub fn enable_ocsp_stapling(&mut self) {
1995 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1996 }
1997
1998 #[corresponds(SSL_CTX_set1_curves_list)]
2000 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2001 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2002 unsafe {
2003 cvt_0i(ffi::SSL_CTX_set1_curves_list(
2004 self.as_ptr(),
2005 curves.as_ptr(),
2006 ))
2007 .map(|_| ())
2008 }
2009 }
2010
2011 #[corresponds(SSL_CTX_set_compliance_policy)]
2015 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
2016 unsafe { cvt_0i(ffi::SSL_CTX_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
2017 }
2018
2019 #[corresponds(SSL_CTX_set_info_callback)]
2021 pub fn set_info_callback<F>(&mut self, callback: F)
2022 where
2023 F: Fn(&SslRef, SslInfoCallbackMode, SslInfoCallbackValue) + Send + Sync + 'static,
2024 {
2025 unsafe {
2026 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
2027 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info_callback::<F>));
2028 }
2029 }
2030
2031 #[corresponds(SSL_CTX_set1_ech_keys)]
2036 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2037 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())) }
2038 }
2039
2040 #[corresponds(SSL_CTX_add1_credential)]
2042 #[cfg(feature = "credential")]
2043 pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> {
2044 unsafe {
2045 cvt_0i(ffi::SSL_CTX_add1_credential(
2046 self.as_ptr(),
2047 credential.as_ptr(),
2048 ))
2049 .map(|_| ())
2050 }
2051 }
2052
2053 #[corresponds(SSL_CTX_set_server_certificate_types)]
2056 #[cfg(feature = "rpk")]
2057 pub fn set_server_certificate_types(
2058 &mut self,
2059 types: &[CertificateType],
2060 ) -> Result<(), ErrorStack> {
2061 unsafe {
2062 cvt_0i(ffi::SSL_CTX_set_server_certificate_types(
2063 self.as_ptr(),
2064 types.as_ptr() as *const u8,
2065 types.len(),
2066 ))
2067 .map(|_| ())
2068 }
2069 }
2070
2071 #[must_use]
2073 pub fn build(self) -> SslContext {
2074 self.ctx
2075 }
2076}
2077
2078foreign_type_and_impl_send_sync! {
2079 type CType = ffi::SSL_CTX;
2080 fn drop = ffi::SSL_CTX_free;
2081
2082 pub struct SslContext;
2087}
2088
2089impl Clone for SslContext {
2090 fn clone(&self) -> Self {
2091 (**self).to_owned()
2092 }
2093}
2094
2095impl ToOwned for SslContextRef {
2096 type Owned = SslContext;
2097
2098 fn to_owned(&self) -> Self::Owned {
2099 unsafe {
2100 SSL_CTX_up_ref(self.as_ptr());
2101 SslContext::from_ptr(self.as_ptr())
2102 }
2103 }
2104}
2105
2106impl fmt::Debug for SslContext {
2108 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2109 write!(fmt, "SslContext")
2110 }
2111}
2112
2113impl SslContext {
2114 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2116 SslContextBuilder::new(method)
2117 }
2118
2119 #[corresponds(SSL_CTX_get_ex_new_index)]
2124 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2125 where
2126 T: 'static + Sync + Send,
2127 {
2128 unsafe {
2129 ffi::init();
2130 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2131 Ok(Index::from_raw(idx))
2132 }
2133 }
2134
2135 fn cached_ex_index<T>() -> Index<SslContext, T>
2137 where
2138 T: 'static + Sync + Send,
2139 {
2140 unsafe {
2141 let idx = *INDEXES
2142 .lock()
2143 .unwrap_or_else(|e| e.into_inner())
2144 .entry(TypeId::of::<T>())
2145 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2146 Index::from_raw(idx)
2147 }
2148 }
2149
2150 #[corresponds(SSL_CTX_get_ciphers)]
2156 #[must_use]
2157 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
2158 unsafe {
2159 let ciphers = ffi::SSL_CTX_get_ciphers(self.as_ptr());
2160 if ciphers.is_null() {
2161 None
2162 } else {
2163 Some(StackRef::from_ptr(ciphers))
2164 }
2165 }
2166 }
2167}
2168
2169impl SslContextRef {
2170 #[corresponds(SSL_CTX_get0_certificate)]
2172 #[must_use]
2173 pub fn certificate(&self) -> Option<&X509Ref> {
2174 self.check_x509();
2175
2176 unsafe {
2177 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2178 if ptr.is_null() {
2179 None
2180 } else {
2181 Some(X509Ref::from_ptr(ptr))
2182 }
2183 }
2184 }
2185
2186 #[corresponds(SSL_CTX_get0_privatekey)]
2188 #[must_use]
2189 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2190 unsafe {
2191 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2192 if ptr.is_null() {
2193 None
2194 } else {
2195 Some(PKeyRef::from_ptr(ptr))
2196 }
2197 }
2198 }
2199
2200 #[corresponds(SSL_CTX_get_cert_store)]
2202 #[must_use]
2203 pub fn cert_store(&self) -> &X509StoreRef {
2204 self.check_x509();
2205
2206 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2207 }
2208
2209 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2211 #[must_use]
2212 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2213 unsafe {
2214 let mut chain = ptr::null_mut();
2215 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2216 assert!(!chain.is_null());
2217 StackRef::from_ptr(chain)
2218 }
2219 }
2220
2221 #[corresponds(SSL_CTX_get_ex_data)]
2223 #[must_use]
2224 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2225 unsafe {
2226 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2227 if data.is_null() {
2228 None
2229 } else {
2230 Some(&*(data as *const T))
2231 }
2232 }
2233 }
2234
2235 #[corresponds(SSL_CTX_get_ex_data)]
2238 unsafe fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2239 ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw())
2240 .cast::<T>()
2241 .as_mut()
2242 }
2243
2244 #[corresponds(SSL_CTX_set_ex_data)]
2247 unsafe fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2248 unsafe {
2249 let data = Box::into_raw(Box::new(data));
2250 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data.cast());
2251 }
2252 }
2253
2254 #[corresponds(SSL_CTX_set_ex_data)]
2257 unsafe fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2258 if let Some(old) = self.ex_data_mut(index) {
2259 return Some(mem::replace(old, data));
2260 }
2261
2262 self.set_ex_data(index, data);
2263
2264 None
2265 }
2266
2267 #[corresponds(SSL_CTX_add_session)]
2276 #[must_use]
2277 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2278 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2279 }
2280
2281 #[corresponds(SSL_CTX_remove_session)]
2290 #[must_use]
2291 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2292 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2293 }
2294
2295 #[corresponds(SSL_CTX_sess_get_cache_size)]
2299 #[allow(clippy::useless_conversion)]
2300 #[must_use]
2301 pub fn session_cache_size(&self) -> u64 {
2302 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()).into() }
2303 }
2304
2305 #[corresponds(SSL_CTX_get_verify_mode)]
2309 #[must_use]
2310 pub fn verify_mode(&self) -> SslVerifyMode {
2311 self.check_x509();
2312
2313 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2314 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2315 }
2316
2317 pub unsafe fn assume_x509(&mut self) {
2325 self.replace_ex_data(*X509_FLAG_INDEX, true);
2326 }
2327
2328 #[must_use]
2330 pub fn has_x509_support(&self) -> bool {
2331 self.ex_data(*X509_FLAG_INDEX).copied().unwrap_or_default()
2332 }
2333
2334 #[track_caller]
2335 fn check_x509(&self) {
2336 assert!(
2337 self.has_x509_support(),
2338 "This context is not configured for X.509 certificates"
2339 );
2340 }
2341
2342 #[corresponds(SSL_CTX_set1_ech_keys)]
2347 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2348 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())) }
2349 }
2350
2351 #[corresponds(SSL_CTX_get0_server_certificate_types)]
2353 #[cfg(feature = "rpk")]
2354 #[must_use]
2355 pub fn server_certificate_types(&self) -> Option<&[CertificateType]> {
2356 let mut types = ptr::null();
2357 let mut types_len = 0;
2358 unsafe {
2359 ffi::SSL_CTX_get0_server_certificate_types(self.as_ptr(), &mut types, &mut types_len);
2360
2361 if types_len == 0 {
2362 return None;
2363 }
2364
2365 Some(slice::from_raw_parts(
2366 types as *const CertificateType,
2367 types_len,
2368 ))
2369 }
2370 }
2371}
2372
2373#[derive(Debug)]
2378pub struct GetSessionPendingError;
2379
2380pub struct CipherBits {
2382 pub secret: i32,
2384
2385 pub algorithm: i32,
2387}
2388
2389#[repr(transparent)]
2390pub struct ClientHello<'ssl>(&'ssl ffi::SSL_CLIENT_HELLO);
2391
2392impl ClientHello<'_> {
2393 #[corresponds(SSL_early_callback_ctx_extension_get)]
2395 #[must_use]
2396 pub fn get_extension(&self, ext_type: ExtensionType) -> Option<&[u8]> {
2397 unsafe {
2398 let mut ptr = ptr::null();
2399 let mut len = 0;
2400 let result =
2401 ffi::SSL_early_callback_ctx_extension_get(self.0, ext_type.0, &mut ptr, &mut len);
2402 if result == 0 {
2403 return None;
2404 }
2405 Some(slice::from_raw_parts(ptr, len))
2406 }
2407 }
2408
2409 pub fn ssl_mut(&mut self) -> &mut SslRef {
2410 unsafe { SslRef::from_ptr_mut(self.0.ssl) }
2411 }
2412
2413 #[must_use]
2414 pub fn ssl(&self) -> &SslRef {
2415 unsafe { SslRef::from_ptr(self.0.ssl) }
2416 }
2417
2418 #[must_use]
2420 pub fn servername(&self, type_: NameType) -> Option<&str> {
2421 self.ssl().servername(type_)
2422 }
2423
2424 #[must_use]
2426 pub fn client_version(&self) -> SslVersion {
2427 SslVersion(self.0.version)
2428 }
2429
2430 #[must_use]
2432 pub fn version_str(&self) -> &'static str {
2433 self.ssl().version_str()
2434 }
2435
2436 #[must_use]
2438 pub fn as_bytes(&self) -> &[u8] {
2439 unsafe { slice::from_raw_parts(self.0.client_hello, self.0.client_hello_len) }
2440 }
2441
2442 #[must_use]
2444 pub fn random(&self) -> &[u8] {
2445 unsafe { slice::from_raw_parts(self.0.random, self.0.random_len) }
2446 }
2447
2448 #[must_use]
2450 pub fn ciphers(&self) -> &[u8] {
2451 unsafe { slice::from_raw_parts(self.0.cipher_suites, self.0.cipher_suites_len) }
2452 }
2453}
2454
2455#[derive(Clone, Copy)]
2457pub struct SslCipher(&'static SslCipherRef);
2458
2459impl SslCipher {
2460 #[corresponds(SSL_get_cipher_by_value)]
2461 #[must_use]
2462 pub fn from_value(value: u16) -> Option<Self> {
2463 unsafe {
2464 let ptr = ffi::SSL_get_cipher_by_value(value);
2465 if ptr.is_null() {
2466 None
2467 } else {
2468 Some(Self::from_ptr(ptr.cast_mut()))
2469 }
2470 }
2471 }
2472}
2473
2474impl Stackable for SslCipher {
2475 type StackType = ffi::stack_st_SSL_CIPHER;
2476}
2477
2478unsafe impl ForeignType for SslCipher {
2479 type CType = ffi::SSL_CIPHER;
2480 type Ref = SslCipherRef;
2481
2482 #[inline]
2483 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2484 SslCipher(SslCipherRef::from_ptr(ptr))
2485 }
2486
2487 #[inline]
2488 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2489 self.0.as_ptr()
2490 }
2491}
2492
2493impl Deref for SslCipher {
2494 type Target = SslCipherRef;
2495
2496 fn deref(&self) -> &SslCipherRef {
2497 self.0
2498 }
2499}
2500
2501pub struct SslCipherRef(Opaque);
2505
2506unsafe impl Send for SslCipherRef {}
2507unsafe impl Sync for SslCipherRef {}
2508
2509unsafe impl ForeignTypeRef for SslCipherRef {
2510 type CType = ffi::SSL_CIPHER;
2511}
2512
2513impl SslCipherRef {
2514 #[corresponds(SSL_CIPHER_get_protocol_id)]
2516 #[must_use]
2517 pub fn protocol_id(&self) -> u16 {
2518 unsafe { ffi::SSL_CIPHER_get_protocol_id(self.as_ptr()) }
2519 }
2520
2521 #[corresponds(SSL_CIPHER_get_name)]
2523 #[must_use]
2524 pub fn name(&self) -> &'static str {
2525 unsafe {
2526 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2527 CStr::from_ptr(ptr).to_str().unwrap()
2528 }
2529 }
2530
2531 #[corresponds(SSL_CIPHER_standard_name)]
2533 #[must_use]
2534 pub fn standard_name(&self) -> Option<&'static str> {
2535 unsafe {
2536 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2537 if ptr.is_null() {
2538 None
2539 } else {
2540 Some(CStr::from_ptr(ptr).to_str().unwrap())
2541 }
2542 }
2543 }
2544
2545 #[corresponds(SSL_CIPHER_get_version)]
2547 #[must_use]
2548 pub fn version(&self) -> &'static str {
2549 let version = unsafe {
2550 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2551 CStr::from_ptr(ptr)
2552 };
2553
2554 version.to_str().unwrap()
2555 }
2556
2557 #[corresponds(SSL_CIPHER_get_bits)]
2559 #[allow(clippy::useless_conversion)]
2560 #[must_use]
2561 pub fn bits(&self) -> CipherBits {
2562 unsafe {
2563 let mut algo_bits = 0;
2564 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2565 CipherBits {
2566 secret: secret_bits.into(),
2567 algorithm: algo_bits.into(),
2568 }
2569 }
2570 }
2571
2572 #[corresponds(SSL_CIPHER_description)]
2574 #[must_use]
2575 pub fn description(&self) -> String {
2576 unsafe {
2577 let mut buf = [0; 128];
2579 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2580 CStr::from_ptr(ptr).to_string_lossy().into_owned()
2581 }
2582 }
2583
2584 #[corresponds(SSL_CIPHER_is_aead)]
2586 #[must_use]
2587 pub fn cipher_is_aead(&self) -> bool {
2588 unsafe { ffi::SSL_CIPHER_is_aead(self.as_ptr()) != 0 }
2589 }
2590
2591 #[corresponds(SSL_CIPHER_get_auth_nid)]
2593 #[must_use]
2594 pub fn cipher_auth_nid(&self) -> Option<Nid> {
2595 let n = unsafe { ffi::SSL_CIPHER_get_auth_nid(self.as_ptr()) };
2596 if n == 0 {
2597 None
2598 } else {
2599 Some(Nid::from_raw(n))
2600 }
2601 }
2602
2603 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2605 #[must_use]
2606 pub fn cipher_nid(&self) -> Option<Nid> {
2607 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2608 if n == 0 {
2609 None
2610 } else {
2611 Some(Nid::from_raw(n))
2612 }
2613 }
2614}
2615
2616foreign_type_and_impl_send_sync! {
2617 type CType = ffi::SSL_SESSION;
2618 fn drop = ffi::SSL_SESSION_free;
2619
2620 pub struct SslSession;
2624}
2625
2626impl Clone for SslSession {
2627 fn clone(&self) -> SslSession {
2628 SslSessionRef::to_owned(self)
2629 }
2630}
2631
2632impl SslSession {
2633 from_der! {
2634 #[corresponds(d2i_SSL_SESSION)]
2636 from_der,
2637 SslSession,
2638 ffi::d2i_SSL_SESSION,
2639 ::libc::c_long
2640 }
2641}
2642
2643impl ToOwned for SslSessionRef {
2644 type Owned = SslSession;
2645
2646 fn to_owned(&self) -> SslSession {
2647 unsafe {
2648 SSL_SESSION_up_ref(self.as_ptr());
2649 SslSession(NonNull::new_unchecked(self.as_ptr()))
2650 }
2651 }
2652}
2653
2654impl SslSessionRef {
2655 #[corresponds(SSL_SESSION_get_id)]
2657 #[must_use]
2658 pub fn id(&self) -> &[u8] {
2659 unsafe {
2660 let mut len = 0;
2661 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2662 slice::from_raw_parts(p, len as usize)
2663 }
2664 }
2665
2666 #[corresponds(SSL_SESSION_get_master_key)]
2668 #[must_use]
2669 pub fn master_key_len(&self) -> usize {
2670 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2671 }
2672
2673 #[corresponds(SSL_SESSION_get_master_key)]
2677 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2678 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2679 }
2680
2681 #[corresponds(SSL_SESSION_get_time)]
2683 #[allow(clippy::useless_conversion)]
2684 #[must_use]
2685 pub fn time(&self) -> u64 {
2686 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2687 }
2688
2689 #[corresponds(SSL_SESSION_get_timeout)]
2693 #[allow(clippy::useless_conversion)]
2694 #[must_use]
2695 pub fn timeout(&self) -> u32 {
2696 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()) }
2697 }
2698
2699 #[corresponds(SSL_SESSION_get_protocol_version)]
2701 #[must_use]
2702 pub fn protocol_version(&self) -> SslVersion {
2703 unsafe {
2704 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2705 SslVersion(version)
2706 }
2707 }
2708
2709 to_der! {
2710 #[corresponds(i2d_SSL_SESSION)]
2712 to_der,
2713 ffi::i2d_SSL_SESSION
2714 }
2715}
2716
2717foreign_type_and_impl_send_sync! {
2718 type CType = ffi::SSL;
2719 fn drop = ffi::SSL_free;
2720
2721 pub struct Ssl;
2728}
2729
2730impl fmt::Debug for Ssl {
2731 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2732 fmt::Debug::fmt(&**self, fmt)
2733 }
2734}
2735
2736impl Ssl {
2737 #[corresponds(SSL_get_ex_new_index)]
2742 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2743 where
2744 T: 'static + Sync + Send,
2745 {
2746 unsafe {
2747 ffi::init();
2748 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2749 Ok(Index::from_raw(idx))
2750 }
2751 }
2752
2753 fn cached_ex_index<T>() -> Index<Ssl, T>
2755 where
2756 T: 'static + Sync + Send,
2757 {
2758 unsafe {
2759 let idx = *SSL_INDEXES
2760 .lock()
2761 .unwrap_or_else(|e| e.into_inner())
2762 .entry(TypeId::of::<T>())
2763 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2764 Index::from_raw(idx)
2765 }
2766 }
2767
2768 #[corresponds(SSL_new)]
2770 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2771 unsafe {
2772 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2773 let mut ssl = Ssl::from_ptr(ptr);
2774 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx.to_owned());
2775
2776 Ok(ssl)
2777 }
2778 }
2779
2780 pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2792 where
2793 S: Read + Write,
2794 {
2795 SslStreamBuilder::new(self, stream).setup_connect()
2796 }
2797
2798 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2808 where
2809 S: Read + Write,
2810 {
2811 self.setup_connect(stream).handshake()
2812 }
2813
2814 pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
2826 where
2827 S: Read + Write,
2828 {
2829 SslStreamBuilder::new(self, stream).setup_accept()
2845 }
2846
2847 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2859 where
2860 S: Read + Write,
2861 {
2862 self.setup_accept(stream).handshake()
2863 }
2864}
2865
2866impl fmt::Debug for SslRef {
2867 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2868 let mut builder = fmt.debug_struct("Ssl");
2869
2870 builder.field("state", &self.state_string_long());
2871
2872 if self.ssl_context().has_x509_support() {
2873 builder.field("verify_result", &self.verify_result());
2874 }
2875
2876 #[cfg(not(feature = "rpk"))]
2877 builder.field("verify_result", &self.verify_result());
2878
2879 builder.finish()
2880 }
2881}
2882
2883impl SslRef {
2884 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2885 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2886 }
2887
2888 #[corresponds(SSL_set_options)]
2895 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
2896 let bits = unsafe { ffi::SSL_set_options(self.as_ptr(), option.bits()) };
2897 SslOptions::from_bits_retain(bits)
2898 }
2899
2900 #[corresponds(SSL_clear_options)]
2902 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
2903 let bits = unsafe { ffi::SSL_clear_options(self.as_ptr(), option.bits()) };
2904 SslOptions::from_bits_retain(bits)
2905 }
2906
2907 #[corresponds(SSL_set1_curves_list)]
2908 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2909 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2910 unsafe { cvt_0i(ffi::SSL_set1_curves_list(self.as_ptr(), curves.as_ptr())).map(|_| ()) }
2911 }
2912
2913 #[corresponds(SSL_get_curve_id)]
2915 #[must_use]
2916 pub fn curve(&self) -> Option<u16> {
2917 let curve_id = unsafe { ffi::SSL_get_curve_id(self.as_ptr()) };
2918 if curve_id == 0 {
2919 return None;
2920 }
2921 Some(curve_id)
2922 }
2923
2924 #[corresponds(SSL_get_curve_name)]
2926 #[must_use]
2927 pub fn curve_name(&self) -> Option<&'static str> {
2928 let curve_id = self.curve()?;
2929
2930 unsafe {
2931 let ptr = ffi::SSL_get_curve_name(curve_id);
2932 if ptr.is_null() {
2933 return None;
2934 }
2935
2936 CStr::from_ptr(ptr).to_str().ok()
2937 }
2938 }
2939
2940 pub fn used_hello_retry_request(&self) -> bool {
2942 unsafe { ffi::SSL_used_hello_retry_request(self.as_ptr()) == 1 }
2943 }
2944
2945 #[corresponds(SSL_get_error)]
2947 #[must_use]
2948 pub fn error_code(&self, ret: c_int) -> ErrorCode {
2949 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2950 }
2951
2952 #[corresponds(SSL_set_verify)]
2956 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2957 self.ssl_context().check_x509();
2958
2959 unsafe { ffi::SSL_set_verify(self.as_ptr(), c_int::from(mode.bits()), None) }
2960 }
2961
2962 #[corresponds(SSL_set_verify_depth)]
2966 pub fn set_verify_depth(&mut self, depth: u32) {
2967 self.ssl_context().check_x509();
2968
2969 unsafe {
2970 ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
2971 }
2972 }
2973
2974 #[corresponds(SSL_get_verify_mode)]
2976 #[must_use]
2977 pub fn verify_mode(&self) -> SslVerifyMode {
2978 self.ssl_context().check_x509();
2979
2980 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2981 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2982 }
2983
2984 #[corresponds(SSL_set_verify)]
3001 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3002 where
3003 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
3004 {
3005 self.ssl_context().check_x509();
3006
3007 unsafe {
3008 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3010 ffi::SSL_set_verify(
3011 self.as_ptr(),
3012 c_int::from(mode.bits()),
3013 Some(ssl_raw_verify::<F>),
3014 );
3015 }
3016 }
3017
3018 #[corresponds(SSL_set0_verify_cert_store)]
3020 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3021 self.ssl_context().check_x509();
3022
3023 unsafe {
3024 cvt(ffi::SSL_set0_verify_cert_store(
3025 self.as_ptr(),
3026 cert_store.into_ptr(),
3027 ))
3028 }
3029 }
3030
3031 #[corresponds(SSL_set_custom_verify)]
3037 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3038 where
3039 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
3040 {
3041 self.ssl_context().check_x509();
3042
3043 unsafe {
3044 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3046 ffi::SSL_set_custom_verify(
3047 self.as_ptr(),
3048 c_int::from(mode.bits()),
3049 Some(ssl_raw_custom_verify::<F>),
3050 );
3051 }
3052 }
3053
3054 #[corresponds(SSL_set_tmp_dh)]
3058 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3059 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr())) }
3060 }
3061
3062 #[corresponds(SSL_set_tmp_ecdh)]
3066 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3067 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr())) }
3068 }
3069
3070 #[corresponds(SSL_set_permute_extensions)]
3072 pub fn set_permute_extensions(&mut self, enabled: bool) {
3073 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as _) }
3074 }
3075
3076 #[corresponds(SSL_set_alpn_protos)]
3080 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3081 unsafe {
3082 let r = ffi::SSL_set_alpn_protos(
3083 self.as_ptr(),
3084 protocols.as_ptr(),
3085 try_int(protocols.len())?,
3086 );
3087 if r == 0 {
3089 Ok(())
3090 } else {
3091 Err(ErrorStack::get())
3092 }
3093 }
3094 }
3095
3096 #[corresponds(SSL_get_ciphers)]
3098 #[must_use]
3099 pub fn ciphers(&self) -> &StackRef<SslCipher> {
3100 unsafe {
3101 let cipher_list = ffi::SSL_get_ciphers(self.as_ptr());
3102 StackRef::from_ptr(cipher_list)
3103 }
3104 }
3105
3106 #[corresponds(SSL_get_current_cipher)]
3108 #[must_use]
3109 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3110 unsafe {
3111 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3112
3113 if ptr.is_null() {
3114 None
3115 } else {
3116 Some(SslCipherRef::from_ptr(ptr.cast_mut()))
3117 }
3118 }
3119 }
3120
3121 #[corresponds(SSL_state_string)]
3125 #[must_use]
3126 pub fn state_string(&self) -> &'static str {
3127 let state = unsafe {
3128 let ptr = ffi::SSL_state_string(self.as_ptr());
3129 CStr::from_ptr(ptr)
3130 };
3131
3132 state.to_str().unwrap_or_default()
3133 }
3134
3135 #[corresponds(SSL_state_string_long)]
3139 #[must_use]
3140 pub fn state_string_long(&self) -> &'static str {
3141 let state = unsafe {
3142 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3143 CStr::from_ptr(ptr)
3144 };
3145
3146 state.to_str().unwrap_or_default()
3147 }
3148
3149 #[corresponds(SSL_set_tlsext_host_name)]
3153 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3154 let cstr = CString::new(hostname).map_err(ErrorStack::internal_error)?;
3155 unsafe { cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr())) }
3156 }
3157
3158 #[corresponds(SSL_get_peer_certificate)]
3160 #[must_use]
3161 pub fn peer_certificate(&self) -> Option<X509> {
3162 self.ssl_context().check_x509();
3163
3164 unsafe {
3165 let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
3166 if ptr.is_null() {
3167 None
3168 } else {
3169 Some(X509::from_ptr(ptr))
3170 }
3171 }
3172 }
3173
3174 #[corresponds(SSL_get_peer_cert_chain)]
3179 #[must_use]
3180 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3181 self.ssl_context().check_x509();
3182
3183 unsafe {
3184 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3185 if ptr.is_null() {
3186 None
3187 } else {
3188 Some(StackRef::from_ptr(ptr))
3189 }
3190 }
3191 }
3192
3193 #[corresponds(SSL_get_certificate)]
3195 #[must_use]
3196 pub fn certificate(&self) -> Option<&X509Ref> {
3197 self.ssl_context().check_x509();
3198
3199 unsafe {
3200 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3201 if ptr.is_null() {
3202 None
3203 } else {
3204 Some(X509Ref::from_ptr(ptr))
3205 }
3206 }
3207 }
3208
3209 #[corresponds(SSL_get_privatekey)]
3211 #[must_use]
3212 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3213 unsafe {
3214 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3215 if ptr.is_null() {
3216 None
3217 } else {
3218 Some(PKeyRef::from_ptr(ptr))
3219 }
3220 }
3221 }
3222
3223 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
3224 #[must_use]
3225 pub fn version(&self) -> &str {
3226 self.version_str()
3227 }
3228
3229 #[corresponds(SSL_version)]
3231 pub fn version2(&self) -> Option<SslVersion> {
3232 unsafe {
3233 let r = ffi::SSL_version(self.as_ptr());
3234 if r == 0 {
3235 None
3236 } else {
3237 r.try_into().ok().map(SslVersion)
3238 }
3239 }
3240 }
3241
3242 #[corresponds(SSL_get_version)]
3246 #[must_use]
3247 pub fn version_str(&self) -> &'static str {
3248 let version = unsafe {
3249 let ptr = ffi::SSL_get_version(self.as_ptr());
3250 CStr::from_ptr(ptr)
3251 };
3252
3253 version.to_str().unwrap()
3254 }
3255
3256 #[corresponds(SSL_set_min_proto_version)]
3261 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3262 unsafe {
3263 cvt(ffi::SSL_set_min_proto_version(
3264 self.as_ptr(),
3265 version.map_or(0, |v| v.0 as _),
3266 ))
3267 }
3268 }
3269
3270 #[corresponds(SSL_set_max_proto_version)]
3274 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3275 unsafe {
3276 cvt(ffi::SSL_set_max_proto_version(
3277 self.as_ptr(),
3278 version.map_or(0, |v| v.0 as _),
3279 ))
3280 }
3281 }
3282
3283 #[corresponds(SSL_get_min_proto_version)]
3285 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
3286 unsafe {
3287 let r = ffi::SSL_get_min_proto_version(self.as_ptr());
3288 if r == 0 {
3289 None
3290 } else {
3291 Some(SslVersion(r))
3292 }
3293 }
3294 }
3295
3296 #[corresponds(SSL_get_max_proto_version)]
3298 #[must_use]
3299 pub fn max_proto_version(&self) -> Option<SslVersion> {
3300 let r = unsafe { ffi::SSL_get_max_proto_version(self.as_ptr()) };
3301 if r == 0 {
3302 None
3303 } else {
3304 Some(SslVersion(r))
3305 }
3306 }
3307
3308 #[corresponds(SSL_get0_alpn_selected)]
3313 #[must_use]
3314 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3315 unsafe {
3316 let mut data: *const c_uchar = ptr::null();
3317 let mut len: c_uint = 0;
3318 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3321
3322 if data.is_null() {
3323 None
3324 } else {
3325 Some(slice::from_raw_parts(data, len as usize))
3326 }
3327 }
3328 }
3329
3330 #[corresponds(SSL_set_tlsext_use_srtp)]
3332 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3333 unsafe {
3334 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
3335
3336 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3337 if r == 0 {
3339 Ok(())
3340 } else {
3341 Err(ErrorStack::get())
3342 }
3343 }
3344 }
3345
3346 #[corresponds(SSL_get_strp_profiles)]
3350 #[must_use]
3351 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3352 unsafe {
3353 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3354
3355 if chain.is_null() {
3356 None
3357 } else {
3358 Some(StackRef::from_ptr(chain.cast_mut()))
3359 }
3360 }
3361 }
3362
3363 #[corresponds(SSL_get_selected_srtp_profile)]
3367 #[must_use]
3368 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3369 unsafe {
3370 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3371
3372 if profile.is_null() {
3373 None
3374 } else {
3375 Some(SrtpProtectionProfileRef::from_ptr(profile.cast_mut()))
3376 }
3377 }
3378 }
3379
3380 #[corresponds(SSL_pending)]
3385 #[must_use]
3386 pub fn pending(&self) -> usize {
3387 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3388 }
3389
3390 #[corresponds(SSL_get_servername)]
3403 #[must_use]
3404 pub fn servername(&self, type_: NameType) -> Option<&str> {
3405 self.servername_raw(type_)
3406 .and_then(|b| str::from_utf8(b).ok())
3407 }
3408
3409 #[corresponds(SSL_get_servername)]
3417 #[must_use]
3418 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3419 unsafe {
3420 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3421 if name.is_null() {
3422 None
3423 } else {
3424 Some(CStr::from_ptr(name).to_bytes())
3425 }
3426 }
3427 }
3428
3429 #[corresponds(SSL_set_SSL_CTX)]
3433 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3434 assert_eq!(
3435 self.ssl_context().has_x509_support(),
3436 ctx.has_x509_support(),
3437 "X.509 certificate support in old and new contexts doesn't match",
3438 );
3439
3440 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3441 }
3442
3443 #[corresponds(SSL_get_SSL_CTX)]
3445 #[must_use]
3446 pub fn ssl_context(&self) -> &SslContextRef {
3447 unsafe {
3448 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3449 SslContextRef::from_ptr(ssl_ctx)
3450 }
3451 }
3452
3453 #[corresponds(SSL_get0_param)]
3455 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
3456 self.ssl_context().check_x509();
3457
3458 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3459 }
3460
3461 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3463 self.verify_param_mut()
3464 }
3465
3466 #[corresponds(SSL_get_verify_result)]
3468 pub fn verify_result(&self) -> X509VerifyResult {
3469 self.ssl_context().check_x509();
3470
3471 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3472 }
3473
3474 #[corresponds(SSL_get_session)]
3476 #[must_use]
3477 pub fn session(&self) -> Option<&SslSessionRef> {
3478 unsafe {
3479 let p = ffi::SSL_get_session(self.as_ptr());
3480 if p.is_null() {
3481 None
3482 } else {
3483 Some(SslSessionRef::from_ptr(p))
3484 }
3485 }
3486 }
3487
3488 #[corresponds(SSL_get_client_random)]
3493 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3494 unsafe { ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
3495 }
3496
3497 #[corresponds(SSL_get_server_random)]
3502 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3503 unsafe { ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
3504 }
3505
3506 #[corresponds(SSL_export_keying_material)]
3508 pub fn export_keying_material(
3509 &self,
3510 out: &mut [u8],
3511 label: &str,
3512 context: Option<&[u8]>,
3513 ) -> Result<(), ErrorStack> {
3514 unsafe {
3515 let (context, contextlen, use_context) = match context {
3516 Some(context) => (context.as_ptr(), context.len(), 1),
3517 None => (ptr::null(), 0, 0),
3518 };
3519 cvt(ffi::SSL_export_keying_material(
3520 self.as_ptr(),
3521 out.as_mut_ptr(),
3522 out.len(),
3523 label.as_ptr().cast::<c_char>(),
3524 label.len(),
3525 context,
3526 contextlen,
3527 use_context,
3528 ))
3529 }
3530 }
3531
3532 #[corresponds(SSL_set_session)]
3543 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3544 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr()))
3545 }
3546
3547 #[corresponds(SSL_session_reused)]
3549 #[must_use]
3550 pub fn session_reused(&self) -> bool {
3551 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3552 }
3553
3554 #[corresponds(SSL_set_tlsext_status_type)]
3556 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3557 unsafe {
3558 cvt(ffi::SSL_set_tlsext_status_type(
3559 self.as_ptr(),
3560 type_.as_raw(),
3561 ))
3562 }
3563 }
3564
3565 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3567 #[must_use]
3568 pub fn ocsp_status(&self) -> Option<&[u8]> {
3569 unsafe {
3570 let mut p = ptr::null();
3571 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3572
3573 if len == 0 {
3574 None
3575 } else {
3576 Some(slice::from_raw_parts(p, len))
3577 }
3578 }
3579 }
3580
3581 #[corresponds(SSL_set_ocsp_response)]
3583 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3584 unsafe {
3585 assert!(response.len() <= c_int::MAX as usize);
3586 cvt(ffi::SSL_set_ocsp_response(
3587 self.as_ptr(),
3588 response.as_ptr(),
3589 response.len(),
3590 ))
3591 }
3592 }
3593
3594 #[corresponds(SSL_is_server)]
3596 #[must_use]
3597 pub fn is_server(&self) -> bool {
3598 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3599 }
3600
3601 #[corresponds(SSL_set_ex_data)]
3609 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3610 if let Some(old) = self.ex_data_mut(index) {
3611 *old = data;
3612 return;
3613 }
3614
3615 unsafe {
3616 let data = Box::into_raw(Box::new(data));
3617 ffi::SSL_set_ex_data(self.as_ptr(), index.as_raw(), data.cast());
3618 }
3619 }
3620
3621 #[corresponds(SSL_set_ex_data)]
3628 pub fn replace_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) -> Option<T> {
3629 if let Some(old) = self.ex_data_mut(index) {
3630 return Some(mem::replace(old, data));
3631 }
3632
3633 self.set_ex_data(index, data);
3634
3635 None
3636 }
3637
3638 #[corresponds(SSL_get_ex_data)]
3640 #[must_use]
3641 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3642 unsafe {
3643 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3644 if data.is_null() {
3645 None
3646 } else {
3647 Some(&*(data as *const T))
3648 }
3649 }
3650 }
3651
3652 #[corresponds(SSL_get_ex_data)]
3654 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3655 unsafe {
3656 ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw())
3657 .cast::<T>()
3658 .as_mut()
3659 }
3660 }
3661
3662 #[corresponds(SSL_get_finished)]
3667 pub fn finished(&self, buf: &mut [u8]) -> usize {
3668 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) }
3669 }
3670
3671 #[corresponds(SSL_get_peer_finished)]
3677 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3678 unsafe { ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) }
3679 }
3680
3681 #[corresponds(SSL_is_init_finished)]
3683 #[must_use]
3684 pub fn is_init_finished(&self) -> bool {
3685 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3686 }
3687
3688 #[corresponds(SSL_set_mtu)]
3690 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3691 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_uint)) }
3692 }
3693
3694 #[corresponds(SSL_use_certificate)]
3696 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3697 unsafe {
3698 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3699 }
3700
3701 Ok(())
3702 }
3703
3704 #[corresponds(SSL_set_client_CA_list)]
3709 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3710 self.ssl_context().check_x509();
3711
3712 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3713 mem::forget(list);
3714 }
3715
3716 #[corresponds(SSL_use_PrivateKey)]
3718 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
3719 where
3720 T: HasPrivate,
3721 {
3722 unsafe { cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), key.as_ptr())) }
3723 }
3724
3725 #[corresponds(SSL_set_mode)]
3728 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
3729 let bits = unsafe { ffi::SSL_set_mode(self.as_ptr(), mode.bits()) };
3730 SslMode::from_bits_retain(bits)
3731 }
3732
3733 #[corresponds(SSL_clear_mode)]
3736 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
3737 let bits = unsafe { ffi::SSL_clear_mode(self.as_ptr(), mode.bits()) };
3738 SslMode::from_bits_retain(bits)
3739 }
3740
3741 #[corresponds(SSL_add1_chain_cert)]
3743 pub fn add_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3744 unsafe { cvt(ffi::SSL_add1_chain_cert(self.as_ptr(), cert.as_ptr())) }
3745 }
3746
3747 #[corresponds(SSL_set1_ech_config_list)]
3755 pub fn set_ech_config_list(&mut self, ech_config_list: &[u8]) -> Result<(), ErrorStack> {
3756 unsafe {
3757 cvt_0i(ffi::SSL_set1_ech_config_list(
3758 self.as_ptr(),
3759 ech_config_list.as_ptr(),
3760 ech_config_list.len(),
3761 ))
3762 .map(|_| ())
3763 }
3764 }
3765
3766 #[corresponds(SSL_get0_ech_retry_configs)]
3773 #[must_use]
3774 pub fn get_ech_retry_configs(&self) -> Option<&[u8]> {
3775 unsafe {
3776 let mut data = ptr::null();
3777 let mut len: usize = 0;
3778 ffi::SSL_get0_ech_retry_configs(self.as_ptr(), &mut data, &mut len);
3779
3780 if data.is_null() {
3781 None
3782 } else {
3783 Some(slice::from_raw_parts(data, len))
3784 }
3785 }
3786 }
3787
3788 #[corresponds(SSL_get0_ech_name_override)]
3795 #[must_use]
3796 pub fn get_ech_name_override(&self) -> Option<&[u8]> {
3797 unsafe {
3798 let mut data: *const c_char = ptr::null();
3799 let mut len: usize = 0;
3800 ffi::SSL_get0_ech_name_override(self.as_ptr(), &mut data, &mut len);
3801
3802 if data.is_null() {
3803 None
3804 } else {
3805 Some(slice::from_raw_parts(data.cast::<u8>(), len))
3806 }
3807 }
3808 }
3809
3810 #[corresponds(SSL_ech_accepted)]
3812 #[must_use]
3813 pub fn ech_accepted(&self) -> bool {
3814 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
3815 }
3816
3817 #[corresponds(SSL_set_enable_ech_grease)]
3819 pub fn set_enable_ech_grease(&self, enable: bool) {
3820 let enable = if enable { 1 } else { 0 };
3821
3822 unsafe {
3823 ffi::SSL_set_enable_ech_grease(self.as_ptr(), enable);
3824 }
3825 }
3826
3827 #[corresponds(SSL_set_compliance_policy)]
3829 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
3830 unsafe { cvt_0i(ffi::SSL_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
3831 }
3832
3833 #[corresponds(SSL_add1_credential)]
3835 #[cfg(feature = "credential")]
3836 pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> {
3837 unsafe { cvt_0i(ffi::SSL_add1_credential(self.as_ptr(), credential.as_ptr())).map(|_| ()) }
3838 }
3839
3840 #[corresponds(SSL_get0_peer_pubkey)]
3842 #[cfg(feature = "rpk")]
3843 pub fn peer_pubkey(&self) -> Option<&PKeyRef<Public>> {
3844 unsafe {
3845 let pubkey = ffi::SSL_get0_peer_pubkey(self.as_ptr());
3846
3847 if pubkey.is_null() {
3848 return None;
3849 }
3850
3851 Some(PKeyRef::from_ptr(pubkey as *mut _))
3852 }
3853 }
3854
3855 #[corresponds(SSL_set_server_certificate_types)]
3858 #[cfg(feature = "rpk")]
3859 pub fn set_server_certificate_types(
3860 &mut self,
3861 types: &[CertificateType],
3862 ) -> Result<(), ErrorStack> {
3863 unsafe {
3864 cvt_0i(ffi::SSL_set_server_certificate_types(
3865 self.as_ptr(),
3866 types.as_ptr() as *const u8,
3867 types.len(),
3868 ))
3869 .map(|_| ())
3870 }
3871 }
3872
3873 #[corresponds(SSL_get0_server_certificate_types)]
3875 #[must_use]
3876 #[cfg(feature = "rpk")]
3877 pub fn server_certificate_types(&self) -> Option<&[CertificateType]> {
3878 let mut types = ptr::null();
3879 let mut types_len = 0;
3880 unsafe {
3881 ffi::SSL_get0_server_certificate_types(self.as_ptr(), &mut types, &mut types_len);
3882
3883 if types_len == 0 {
3884 return None;
3885 }
3886
3887 Some(slice::from_raw_parts(
3888 types as *const CertificateType,
3889 types_len,
3890 ))
3891 }
3892 }
3893
3894 #[corresponds(SSL_get_server_certificate_type_selected)]
3897 #[must_use]
3898 #[cfg(feature = "rpk")]
3899 pub fn selected_server_certificate_type(&self) -> CertificateType {
3900 unsafe { CertificateType(ffi::SSL_get_server_certificate_type_selected(self.as_ptr())) }
3901 }
3902}
3903
3904#[derive(Debug)]
3906pub struct MidHandshakeSslStream<S> {
3907 stream: SslStream<S>,
3908 error: Error,
3909}
3910
3911impl<S> MidHandshakeSslStream<S> {
3912 #[must_use]
3914 pub fn get_ref(&self) -> &S {
3915 self.stream.get_ref()
3916 }
3917
3918 pub fn get_mut(&mut self) -> &mut S {
3920 self.stream.get_mut()
3921 }
3922
3923 #[must_use]
3925 pub fn ssl(&self) -> &SslRef {
3926 self.stream.ssl()
3927 }
3928
3929 pub fn ssl_mut(&mut self) -> &mut SslRef {
3931 self.stream.ssl_mut()
3932 }
3933
3934 #[must_use]
3936 pub fn error(&self) -> &Error {
3937 &self.error
3938 }
3939
3940 #[must_use]
3942 pub fn into_error(self) -> Error {
3943 self.error
3944 }
3945
3946 #[must_use]
3948 pub fn into_source_stream(self) -> S {
3949 self.stream.into_inner()
3950 }
3951
3952 #[must_use]
3954 pub fn into_parts(self) -> (Error, S) {
3955 (self.error, self.stream.into_inner())
3956 }
3957
3958 #[corresponds(SSL_do_handshake)]
3960 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3961 let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) };
3962 if ret > 0 {
3963 Ok(self.stream)
3964 } else {
3965 self.error = self.stream.make_error(ret);
3966 Err(if self.error.would_block() {
3967 HandshakeError::WouldBlock(self)
3968 } else {
3969 HandshakeError::Failure(self)
3970 })
3971 }
3972 }
3973}
3974
3975pub struct SslStream<S> {
3977 ssl: ManuallyDrop<Ssl>,
3978 method: ManuallyDrop<BioMethod>,
3979 _p: PhantomData<S>,
3980}
3981
3982impl<S> Drop for SslStream<S> {
3983 fn drop(&mut self) {
3984 unsafe {
3986 ManuallyDrop::drop(&mut self.ssl);
3987 ManuallyDrop::drop(&mut self.method);
3988 }
3989 }
3990}
3991
3992impl<S> fmt::Debug for SslStream<S>
3993where
3994 S: fmt::Debug,
3995{
3996 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
3997 fmt.debug_struct("SslStream")
3998 .field("stream", &self.get_ref())
3999 .field("ssl", &self.ssl())
4000 .finish()
4001 }
4002}
4003
4004impl<S: Read + Write> SslStream<S> {
4005 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4011 let (bio, method) = bio::new(stream)?;
4012
4013 unsafe {
4014 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4015 }
4016
4017 Ok(SslStream {
4018 ssl: ManuallyDrop::new(ssl),
4019 method: ManuallyDrop::new(method),
4020 _p: PhantomData,
4021 })
4022 }
4023
4024 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
4032 let ssl = Ssl::from_ptr(ssl);
4033 Self::new(ssl, stream).unwrap()
4034 }
4035
4036 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4043 loop {
4044 match self.ssl_read_uninit(buf) {
4045 Ok(n) => return Ok(n),
4046 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4047 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4048 return Ok(0);
4049 }
4050 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4051 Err(e) => {
4052 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4053 }
4054 }
4055 }
4056 }
4057
4058 #[corresponds(SSL_read)]
4063 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4064 unsafe {
4066 self.ssl_read_uninit(slice::from_raw_parts_mut(
4067 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4068 buf.len(),
4069 ))
4070 }
4071 }
4072
4073 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4080 if buf.is_empty() {
4081 return Ok(0);
4082 }
4083
4084 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4085 let ret = unsafe { ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) };
4086 if ret > 0 {
4087 Ok(ret as usize)
4088 } else {
4089 Err(self.make_error(ret))
4090 }
4091 }
4092
4093 #[corresponds(SSL_write)]
4098 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4099 if buf.is_empty() {
4100 return Ok(0);
4101 }
4102
4103 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4104 let ret = unsafe { ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) };
4105 if ret > 0 {
4106 Ok(ret as usize)
4107 } else {
4108 Err(self.make_error(ret))
4109 }
4110 }
4111
4112 #[corresponds(SSL_shutdown)]
4122 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4123 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4124 0 => Ok(ShutdownResult::Sent),
4125 1 => Ok(ShutdownResult::Received),
4126 n => Err(self.make_error(n)),
4127 }
4128 }
4129
4130 #[corresponds(SSL_get_shutdown)]
4132 pub fn get_shutdown(&mut self) -> ShutdownState {
4133 unsafe {
4134 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4135 ShutdownState::from_bits_retain(bits)
4136 }
4137 }
4138
4139 #[corresponds(SSL_set_shutdown)]
4144 pub fn set_shutdown(&mut self, state: ShutdownState) {
4145 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4146 }
4147
4148 #[corresponds(SSL_connect)]
4150 pub fn connect(&mut self) -> Result<(), Error> {
4151 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4152 if ret > 0 {
4153 Ok(())
4154 } else {
4155 Err(self.make_error(ret))
4156 }
4157 }
4158
4159 #[corresponds(SSL_accept)]
4161 pub fn accept(&mut self) -> Result<(), Error> {
4162 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4163 if ret > 0 {
4164 Ok(())
4165 } else {
4166 Err(self.make_error(ret))
4167 }
4168 }
4169
4170 #[corresponds(SSL_do_handshake)]
4172 pub fn do_handshake(&mut self) -> Result<(), Error> {
4173 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4174 if ret > 0 {
4175 Ok(())
4176 } else {
4177 Err(self.make_error(ret))
4178 }
4179 }
4180}
4181
4182impl<S> SslStream<S> {
4183 fn make_error(&mut self, ret: c_int) -> Error {
4184 self.check_panic();
4185
4186 let code = self.ssl.error_code(ret);
4187
4188 let cause = match code {
4189 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4190 ErrorCode::SYSCALL => {
4191 let errs = ErrorStack::get();
4192 if errs.errors().is_empty() {
4193 self.get_bio_error().map(InnerError::Io)
4194 } else {
4195 Some(InnerError::Ssl(errs))
4196 }
4197 }
4198 ErrorCode::ZERO_RETURN => None,
4199 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4200 self.get_bio_error().map(InnerError::Io)
4201 }
4202 _ => None,
4203 };
4204
4205 Error { code, cause }
4206 }
4207
4208 fn check_panic(&mut self) {
4209 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4210 resume_unwind(err)
4211 }
4212 }
4213
4214 fn get_bio_error(&mut self) -> Option<io::Error> {
4215 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4216 }
4217
4218 #[must_use]
4220 pub fn into_inner(self) -> S {
4221 unsafe { bio::take_stream::<S>(self.ssl.get_raw_rbio()) }
4222 }
4223
4224 #[must_use]
4226 pub fn get_ref(&self) -> &S {
4227 unsafe {
4228 let bio = self.ssl.get_raw_rbio();
4229 bio::get_ref(bio)
4230 }
4231 }
4232
4233 pub fn get_mut(&mut self) -> &mut S {
4240 unsafe {
4241 let bio = self.ssl.get_raw_rbio();
4242 bio::get_mut(bio)
4243 }
4244 }
4245
4246 #[must_use]
4248 pub fn ssl(&self) -> &SslRef {
4249 &self.ssl
4250 }
4251
4252 pub fn ssl_mut(&mut self) -> &mut SslRef {
4254 &mut self.ssl
4255 }
4256}
4257
4258impl<S: Read + Write> Read for SslStream<S> {
4259 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4260 unsafe {
4262 self.read_uninit(slice::from_raw_parts_mut(
4263 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4264 buf.len(),
4265 ))
4266 }
4267 }
4268}
4269
4270impl<S: Read + Write> Write for SslStream<S> {
4271 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4272 loop {
4273 match self.ssl_write(buf) {
4274 Ok(n) => return Ok(n),
4275 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4276 Err(e) => {
4277 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4278 }
4279 }
4280 }
4281 }
4282
4283 fn flush(&mut self) -> io::Result<()> {
4284 self.get_mut().flush()
4285 }
4286}
4287
4288pub struct SslStreamBuilder<S> {
4290 inner: SslStream<S>,
4291}
4292
4293impl<S> SslStreamBuilder<S>
4294where
4295 S: Read + Write,
4296{
4297 pub fn new(ssl: Ssl, stream: S) -> Self {
4299 Self {
4300 inner: SslStream::new(ssl, stream).unwrap(),
4301 }
4302 }
4303
4304 #[corresponds(SSL_set_connect_state)]
4306 pub fn set_connect_state(&mut self) {
4307 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4308 }
4309
4310 #[corresponds(SSL_set_accept_state)]
4312 pub fn set_accept_state(&mut self) {
4313 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4314 }
4315
4316 #[must_use]
4322 pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
4323 self.set_connect_state();
4324
4325 MidHandshakeSslStream {
4326 stream: self.inner,
4327 error: Error {
4328 code: ErrorCode::WANT_WRITE,
4329 cause: Some(InnerError::Io(io::Error::new(
4330 io::ErrorKind::WouldBlock,
4331 "connect handshake has not started yet",
4332 ))),
4333 },
4334 }
4335 }
4336
4337 pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
4342 self.setup_connect().handshake()
4343 }
4344
4345 #[must_use]
4351 pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
4352 self.set_accept_state();
4353
4354 MidHandshakeSslStream {
4355 stream: self.inner,
4356 error: Error {
4357 code: ErrorCode::WANT_READ,
4358 cause: Some(InnerError::Io(io::Error::new(
4359 io::ErrorKind::WouldBlock,
4360 "accept handshake has not started yet",
4361 ))),
4362 },
4363 }
4364 }
4365
4366 pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
4371 self.setup_accept().handshake()
4372 }
4373
4374 #[corresponds(SSL_do_handshake)]
4378 pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
4379 let mut stream = self.inner;
4380 let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
4381 if ret > 0 {
4382 Ok(stream)
4383 } else {
4384 let error = stream.make_error(ret);
4385 Err(if error.would_block() {
4386 HandshakeError::WouldBlock(MidHandshakeSslStream { stream, error })
4387 } else {
4388 HandshakeError::Failure(MidHandshakeSslStream { stream, error })
4389 })
4390 }
4391 }
4392}
4393
4394impl<S> SslStreamBuilder<S> {
4395 #[must_use]
4397 pub fn get_ref(&self) -> &S {
4398 unsafe {
4399 let bio = self.inner.ssl.get_raw_rbio();
4400 bio::get_ref(bio)
4401 }
4402 }
4403
4404 pub fn get_mut(&mut self) -> &mut S {
4411 unsafe {
4412 let bio = self.inner.ssl.get_raw_rbio();
4413 bio::get_mut(bio)
4414 }
4415 }
4416
4417 #[must_use]
4419 pub fn ssl(&self) -> &SslRef {
4420 &self.inner.ssl
4421 }
4422
4423 pub fn ssl_mut(&mut self) -> &mut SslRef {
4425 &mut self.inner.ssl
4426 }
4427
4428 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4436 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4437 unsafe {
4438 let bio = self.inner.ssl.get_raw_rbio();
4439 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4440 }
4441 }
4442}
4443
4444#[cfg(feature = "rpk")]
4446#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4447#[repr(transparent)]
4448pub struct CertificateType(u8);
4449
4450#[cfg(feature = "rpk")]
4451impl CertificateType {
4452 pub const X509: Self = Self(ffi::TLS_CERTIFICATE_TYPE_X509 as u8);
4454
4455 pub const RAW_PUBLIC_KEY: Self = Self(ffi::TLS_CERTIFICATE_TYPE_RAW_PUBLIC_KEY as u8);
4457}
4458
4459#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4461pub enum ShutdownResult {
4462 Sent,
4464
4465 Received,
4467}
4468
4469bitflags! {
4470 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
4472 pub struct ShutdownState: c_int {
4473 const SENT = ffi::SSL_SENT_SHUTDOWN;
4475 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4477 }
4478}
4479
4480pub trait PrivateKeyMethod: Send + Sync + 'static {
4488 fn sign(
4499 &self,
4500 ssl: &mut SslRef,
4501 input: &[u8],
4502 signature_algorithm: SslSignatureAlgorithm,
4503 output: &mut [u8],
4504 ) -> Result<usize, PrivateKeyMethodError>;
4505
4506 fn decrypt(
4521 &self,
4522 ssl: &mut SslRef,
4523 input: &[u8],
4524 output: &mut [u8],
4525 ) -> Result<usize, PrivateKeyMethodError>;
4526
4527 fn complete(&self, ssl: &mut SslRef, output: &mut [u8])
4536 -> Result<usize, PrivateKeyMethodError>;
4537}
4538
4539#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4541pub struct PrivateKeyMethodError(ffi::ssl_private_key_result_t);
4542
4543impl PrivateKeyMethodError {
4544 pub const FAILURE: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_failure);
4546
4547 pub const RETRY: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_retry);
4549}
4550
4551pub trait CertificateCompressor: Send + Sync + 'static {
4553 const ALGORITHM: CertificateCompressionAlgorithm;
4555
4556 const CAN_COMPRESS: bool;
4558
4559 const CAN_DECOMPRESS: bool;
4561
4562 #[allow(unused_variables)]
4564 fn compress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4565 where
4566 W: std::io::Write,
4567 {
4568 Err(std::io::Error::other("not implemented"))
4569 }
4570
4571 #[allow(unused_variables)]
4573 fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4574 where
4575 W: std::io::Write,
4576 {
4577 Err(std::io::Error::other("not implemented"))
4578 }
4579}
4580
4581use crate::ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4582
4583unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4584 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4585}
4586
4587unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4588 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4589}
4590
4591fn path_to_cstring(path: &Path) -> Result<CString, ErrorStack> {
4592 CString::new(path.as_os_str().as_encoded_bytes()).map_err(ErrorStack::internal_error)
4593}