1use crate::libc_types::{c_char, c_int, c_uchar, c_uint};
61use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
62use openssl_macros::corresponds;
63use std::any::TypeId;
64use std::collections::HashMap;
65use std::convert::TryInto;
66use std::ffi::{CStr, CString};
67use std::fmt;
68use std::io;
69use std::io::prelude::*;
70use std::marker::PhantomData;
71use std::mem::{self, ManuallyDrop, MaybeUninit};
72use std::ops::Deref;
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;
86use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
87use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
88use crate::ssl::bio::BioMethod;
89use crate::ssl::callbacks::*;
90use crate::ssl::error::InnerError;
91use crate::stack::{Stack, StackRef, Stackable};
92use crate::symm::CipherCtxRef;
93use crate::x509::store::{X509Store, X509StoreBuilder, X509StoreBuilderRef, X509StoreRef};
94use crate::x509::verify::X509VerifyParamRef;
95use crate::x509::{
96 X509Name, X509Ref, X509StoreContextRef, X509VerifyError, X509VerifyResult, X509,
97};
98use crate::{cvt, cvt_0i, cvt_n, cvt_p, init, try_int};
99use crate::{ffi, free_data_box};
100
101pub use self::async_callbacks::{
102 AsyncPrivateKeyMethod, AsyncPrivateKeyMethodError, AsyncSelectCertError, BoxCustomVerifyFinish,
103 BoxCustomVerifyFuture, BoxGetSessionFinish, BoxGetSessionFuture, BoxPrivateKeyMethodFinish,
104 BoxPrivateKeyMethodFuture, BoxSelectCertFinish, BoxSelectCertFuture, ExDataFuture,
105};
106pub use self::connector::{
107 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
108};
109pub use self::credential::{SslCredential, SslCredentialBuilder, SslCredentialRef};
110pub use self::ech::{SslEchKeys, SslEchKeysRef};
111pub use self::error::{Error, ErrorCode, HandshakeError};
112
113mod async_callbacks;
114mod bio;
115mod callbacks;
116mod connector;
117mod credential;
118mod ech;
119mod error;
120mod mut_only;
121#[cfg(test)]
122mod test;
123
124bitflags! {
125 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
127 pub struct SslOptions: c_uint {
128 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as _;
130
131 const ALL = ffi::SSL_OP_ALL as _;
133
134 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as _;
138
139 const NO_TICKET = ffi::SSL_OP_NO_TICKET as _;
141
142 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
144 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as _;
145
146 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as _;
148
149 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
152 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as _;
153
154 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as _;
156
157 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as _;
159
160 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as _;
164
165 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as _;
167
168 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as _;
170
171 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as _;
173
174 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as _;
176
177 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as _;
179
180 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as _;
182
183 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as _;
185
186 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as _;
188
189 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as _;
191
192 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as _;
194 }
195}
196
197bitflags! {
198 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
200 pub struct SslMode: c_uint {
201 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE as _;
207
208 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as _;
211
212 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY as _;
222
223 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN as _;
229
230 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS as _;
234
235 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV as _;
243 }
244}
245
246#[derive(Copy, Clone)]
248pub struct SslMethod {
249 ptr: *const ffi::SSL_METHOD,
250 is_x509_method: bool,
251}
252
253impl SslMethod {
254 #[corresponds(TLS_method)]
256 #[must_use]
257 pub fn tls() -> SslMethod {
258 unsafe {
259 Self {
260 ptr: ffi::TLS_method(),
261 is_x509_method: true,
262 }
263 }
264 }
265
266 #[must_use]
274 pub unsafe fn tls_with_buffer() -> Self {
275 unsafe {
276 Self {
277 ptr: ffi::TLS_with_buffers_method(),
278 is_x509_method: false,
279 }
280 }
281 }
282
283 #[corresponds(DTLS_method)]
285 #[must_use]
286 pub fn dtls() -> Self {
287 unsafe {
288 Self {
289 ptr: ffi::DTLS_method(),
290 is_x509_method: true,
291 }
292 }
293 }
294
295 #[corresponds(TLS_client_method)]
297 #[must_use]
298 pub fn tls_client() -> SslMethod {
299 unsafe {
300 Self {
301 ptr: ffi::TLS_client_method(),
302 is_x509_method: true,
303 }
304 }
305 }
306
307 #[corresponds(TLS_server_method)]
309 #[must_use]
310 pub fn tls_server() -> SslMethod {
311 unsafe {
312 Self {
313 ptr: ffi::TLS_server_method(),
314 is_x509_method: true,
315 }
316 }
317 }
318
319 #[corresponds(TLS_server_method)]
329 #[must_use]
330 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
331 SslMethod {
332 ptr,
333 is_x509_method: false,
334 }
335 }
336
337 pub unsafe fn assume_x509(&mut self) {
345 self.is_x509_method = true;
346 }
347
348 #[allow(clippy::trivially_copy_pass_by_ref)]
350 #[must_use]
351 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
352 self.ptr
353 }
354}
355
356unsafe impl Sync for SslMethod {}
357unsafe impl Send for SslMethod {}
358
359bitflags! {
360 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
362 pub struct SslVerifyMode: i32 {
363 const PEER = ffi::SSL_VERIFY_PEER;
367
368 const NONE = ffi::SSL_VERIFY_NONE;
374
375 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
379 }
380}
381
382#[derive(Clone, Copy, Debug, Eq, PartialEq)]
383pub enum SslVerifyError {
384 Invalid(SslAlert),
385 Retry,
386}
387
388bitflags! {
389 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
391 pub struct SslSessionCacheMode: c_int {
392 const OFF = ffi::SSL_SESS_CACHE_OFF;
394
395 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
402
403 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
407
408 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
410
411 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
413
414 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
416
417 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
419
420 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
422 }
423}
424
425#[derive(Copy, Clone)]
427pub struct SslFiletype(c_int);
428
429impl SslFiletype {
430 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
434
435 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
439
440 #[must_use]
442 pub fn from_raw(raw: c_int) -> SslFiletype {
443 SslFiletype(raw)
444 }
445
446 #[allow(clippy::trivially_copy_pass_by_ref)]
448 #[must_use]
449 pub fn as_raw(&self) -> c_int {
450 self.0
451 }
452}
453
454#[derive(Copy, Clone)]
456pub struct StatusType(c_int);
457
458impl StatusType {
459 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
461
462 #[must_use]
464 pub fn from_raw(raw: c_int) -> StatusType {
465 StatusType(raw)
466 }
467
468 #[allow(clippy::trivially_copy_pass_by_ref)]
470 #[must_use]
471 pub fn as_raw(&self) -> c_int {
472 self.0
473 }
474}
475
476#[derive(Copy, Clone)]
478pub struct NameType(c_int);
479
480impl NameType {
481 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
483
484 #[must_use]
486 pub fn from_raw(raw: c_int) -> StatusType {
487 StatusType(raw)
488 }
489
490 #[allow(clippy::trivially_copy_pass_by_ref)]
492 #[must_use]
493 pub fn as_raw(&self) -> c_int {
494 self.0
495 }
496}
497
498static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
499 LazyLock::new(|| Mutex::new(HashMap::new()));
500static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
501 LazyLock::new(|| Mutex::new(HashMap::new()));
502static SESSION_CTX_INDEX: LazyLock<Index<Ssl, SslContext>> =
503 LazyLock::new(|| Ssl::new_ex_index().unwrap());
504static X509_FLAG_INDEX: LazyLock<Index<SslContext, bool>> =
505 LazyLock::new(|| SslContext::new_ex_index().unwrap());
506
507#[derive(Debug, Copy, Clone, PartialEq, Eq)]
509pub struct SniError(c_int);
510
511impl SniError {
512 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
514
515 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
517
518 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
519}
520
521#[derive(Debug, Copy, Clone, PartialEq, Eq)]
523pub struct SslAlert(c_int);
524
525impl SslAlert {
526 pub const CLOSE_NOTIFY: Self = Self(ffi::SSL_AD_CLOSE_NOTIFY);
527 pub const UNEXPECTED_MESSAGE: Self = Self(ffi::SSL_AD_UNEXPECTED_MESSAGE);
528 pub const BAD_RECORD_MAC: Self = Self(ffi::SSL_AD_BAD_RECORD_MAC);
529 pub const DECRYPTION_FAILED: Self = Self(ffi::SSL_AD_DECRYPTION_FAILED);
530 pub const RECORD_OVERFLOW: Self = Self(ffi::SSL_AD_RECORD_OVERFLOW);
531 pub const DECOMPRESSION_FAILURE: Self = Self(ffi::SSL_AD_DECOMPRESSION_FAILURE);
532 pub const HANDSHAKE_FAILURE: Self = Self(ffi::SSL_AD_HANDSHAKE_FAILURE);
533 pub const NO_CERTIFICATE: Self = Self(ffi::SSL_AD_NO_CERTIFICATE);
534 pub const BAD_CERTIFICATE: Self = Self(ffi::SSL_AD_BAD_CERTIFICATE);
535 pub const UNSUPPORTED_CERTIFICATE: Self = Self(ffi::SSL_AD_UNSUPPORTED_CERTIFICATE);
536 pub const CERTIFICATE_REVOKED: Self = Self(ffi::SSL_AD_CERTIFICATE_REVOKED);
537 pub const CERTIFICATE_EXPIRED: Self = Self(ffi::SSL_AD_CERTIFICATE_EXPIRED);
538 pub const CERTIFICATE_UNKNOWN: Self = Self(ffi::SSL_AD_CERTIFICATE_UNKNOWN);
539 pub const ILLEGAL_PARAMETER: Self = Self(ffi::SSL_AD_ILLEGAL_PARAMETER);
540 pub const UNKNOWN_CA: Self = Self(ffi::SSL_AD_UNKNOWN_CA);
541 pub const ACCESS_DENIED: Self = Self(ffi::SSL_AD_ACCESS_DENIED);
542 pub const DECODE_ERROR: Self = Self(ffi::SSL_AD_DECODE_ERROR);
543 pub const DECRYPT_ERROR: Self = Self(ffi::SSL_AD_DECRYPT_ERROR);
544 pub const EXPORT_RESTRICTION: Self = Self(ffi::SSL_AD_EXPORT_RESTRICTION);
545 pub const PROTOCOL_VERSION: Self = Self(ffi::SSL_AD_PROTOCOL_VERSION);
546 pub const INSUFFICIENT_SECURITY: Self = Self(ffi::SSL_AD_INSUFFICIENT_SECURITY);
547 pub const INTERNAL_ERROR: Self = Self(ffi::SSL_AD_INTERNAL_ERROR);
548 pub const INAPPROPRIATE_FALLBACK: Self = Self(ffi::SSL_AD_INAPPROPRIATE_FALLBACK);
549 pub const USER_CANCELLED: Self = Self(ffi::SSL_AD_USER_CANCELLED);
550 pub const NO_RENEGOTIATION: Self = Self(ffi::SSL_AD_NO_RENEGOTIATION);
551 pub const MISSING_EXTENSION: Self = Self(ffi::SSL_AD_MISSING_EXTENSION);
552 pub const UNSUPPORTED_EXTENSION: Self = Self(ffi::SSL_AD_UNSUPPORTED_EXTENSION);
553 pub const CERTIFICATE_UNOBTAINABLE: Self = Self(ffi::SSL_AD_CERTIFICATE_UNOBTAINABLE);
554 pub const UNRECOGNIZED_NAME: Self = Self(ffi::SSL_AD_UNRECOGNIZED_NAME);
555 pub const BAD_CERTIFICATE_STATUS_RESPONSE: Self =
556 Self(ffi::SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
557 pub const BAD_CERTIFICATE_HASH_VALUE: Self = Self(ffi::SSL_AD_BAD_CERTIFICATE_HASH_VALUE);
558 pub const UNKNOWN_PSK_IDENTITY: Self = Self(ffi::SSL_AD_UNKNOWN_PSK_IDENTITY);
559 pub const CERTIFICATE_REQUIRED: Self = Self(ffi::SSL_AD_CERTIFICATE_REQUIRED);
560 pub const NO_APPLICATION_PROTOCOL: Self = Self(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
561}
562
563#[derive(Debug, Copy, Clone, PartialEq, Eq)]
565pub struct AlpnError(c_int);
566
567impl AlpnError {
568 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
570
571 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
573}
574
575#[derive(Debug, Copy, Clone, PartialEq, Eq)]
577pub struct SelectCertError(ffi::ssl_select_cert_result_t);
578
579impl SelectCertError {
580 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_error);
582
583 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_retry);
585}
586
587#[derive(Debug, Copy, Clone, PartialEq, Eq)]
593pub struct ExtensionType(u16);
594
595impl ExtensionType {
596 pub const SERVER_NAME: Self = Self(ffi::TLSEXT_TYPE_server_name as u16);
597 pub const STATUS_REQUEST: Self = Self(ffi::TLSEXT_TYPE_status_request as u16);
598 pub const EC_POINT_FORMATS: Self = Self(ffi::TLSEXT_TYPE_ec_point_formats as u16);
599 pub const SIGNATURE_ALGORITHMS: Self = Self(ffi::TLSEXT_TYPE_signature_algorithms as u16);
600 pub const SRTP: Self = Self(ffi::TLSEXT_TYPE_srtp as u16);
601 pub const APPLICATION_LAYER_PROTOCOL_NEGOTIATION: Self =
602 Self(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as u16);
603 pub const PADDING: Self = Self(ffi::TLSEXT_TYPE_padding as u16);
604 pub const EXTENDED_MASTER_SECRET: Self = Self(ffi::TLSEXT_TYPE_extended_master_secret as u16);
605 pub const RECORD_SIZE_LIMIT: Self = Self(ffi::TLSEXT_TYPE_record_size_limit as u16);
606 pub const QUIC_TRANSPORT_PARAMETERS_LEGACY: Self =
607 Self(ffi::TLSEXT_TYPE_quic_transport_parameters_legacy as u16);
608 pub const QUIC_TRANSPORT_PARAMETERS_STANDARD: Self =
609 Self(ffi::TLSEXT_TYPE_quic_transport_parameters_standard as u16);
610 pub const CERT_COMPRESSION: Self = Self(ffi::TLSEXT_TYPE_cert_compression as u16);
611 pub const SESSION_TICKET: Self = Self(ffi::TLSEXT_TYPE_session_ticket as u16);
612 pub const SUPPORTED_GROUPS: Self = Self(ffi::TLSEXT_TYPE_supported_groups as u16);
613 pub const PRE_SHARED_KEY: Self = Self(ffi::TLSEXT_TYPE_pre_shared_key as u16);
614 pub const EARLY_DATA: Self = Self(ffi::TLSEXT_TYPE_early_data as u16);
615 pub const SUPPORTED_VERSIONS: Self = Self(ffi::TLSEXT_TYPE_supported_versions as u16);
616 pub const COOKIE: Self = Self(ffi::TLSEXT_TYPE_cookie as u16);
617 pub const PSK_KEY_EXCHANGE_MODES: Self = Self(ffi::TLSEXT_TYPE_psk_key_exchange_modes as u16);
618 pub const CERTIFICATE_AUTHORITIES: Self = Self(ffi::TLSEXT_TYPE_certificate_authorities as u16);
619 pub const SIGNATURE_ALGORITHMS_CERT: Self =
620 Self(ffi::TLSEXT_TYPE_signature_algorithms_cert as u16);
621 pub const KEY_SHARE: Self = Self(ffi::TLSEXT_TYPE_key_share as u16);
622 pub const RENEGOTIATE: Self = Self(ffi::TLSEXT_TYPE_renegotiate as u16);
623 pub const DELEGATED_CREDENTIAL: Self = Self(ffi::TLSEXT_TYPE_delegated_credential as u16);
624 pub const APPLICATION_SETTINGS: Self = Self(ffi::TLSEXT_TYPE_application_settings as u16);
625 pub const ENCRYPTED_CLIENT_HELLO: Self = Self(ffi::TLSEXT_TYPE_encrypted_client_hello as u16);
626 pub const CERTIFICATE_TIMESTAMP: Self = Self(ffi::TLSEXT_TYPE_certificate_timestamp as u16);
627 pub const NEXT_PROTO_NEG: Self = Self(ffi::TLSEXT_TYPE_next_proto_neg as u16);
628 pub const CHANNEL_ID: Self = Self(ffi::TLSEXT_TYPE_channel_id as u16);
629}
630
631impl From<u16> for ExtensionType {
632 fn from(value: u16) -> Self {
633 Self(value)
634 }
635}
636
637#[derive(Copy, Clone, PartialEq, Eq)]
639pub struct SslVersion(u16);
640
641impl SslVersion {
642 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION as _);
644
645 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION as _);
647
648 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION as _);
650
651 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION as _);
653
654 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION as _);
656}
657
658impl TryFrom<u16> for SslVersion {
659 type Error = &'static str;
660
661 fn try_from(value: u16) -> Result<Self, Self::Error> {
662 match i32::from(value) {
663 ffi::SSL3_VERSION
664 | ffi::TLS1_VERSION
665 | ffi::TLS1_1_VERSION
666 | ffi::TLS1_2_VERSION
667 | ffi::TLS1_3_VERSION => Ok(Self(value)),
668 _ => Err("Unknown SslVersion"),
669 }
670 }
671}
672
673impl fmt::Debug for SslVersion {
674 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
675 f.write_str(match *self {
676 Self::SSL3 => "SSL3",
677 Self::TLS1 => "TLS1",
678 Self::TLS1_1 => "TLS1_1",
679 Self::TLS1_2 => "TLS1_2",
680 Self::TLS1_3 => "TLS1_3",
681 _ => return write!(f, "{:#06x}", self.0),
682 })
683 }
684}
685
686impl fmt::Display for SslVersion {
687 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
688 f.write_str(match *self {
689 Self::SSL3 => "SSLv3",
690 Self::TLS1 => "TLSv1",
691 Self::TLS1_1 => "TLSv1.1",
692 Self::TLS1_2 => "TLSv1.2",
693 Self::TLS1_3 => "TLSv1.3",
694 _ => return write!(f, "unknown ({:#06x})", self.0),
695 })
696 }
697}
698
699#[repr(transparent)]
705#[derive(Debug, Copy, Clone, PartialEq, Eq)]
706pub struct SslSignatureAlgorithm(u16);
707
708impl SslSignatureAlgorithm {
709 pub const RSA_PKCS1_SHA1: SslSignatureAlgorithm =
710 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA1 as _);
711
712 pub const RSA_PKCS1_SHA256: SslSignatureAlgorithm =
713 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA256 as _);
714
715 pub const RSA_PKCS1_SHA384: SslSignatureAlgorithm =
716 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA384 as _);
717
718 pub const RSA_PKCS1_SHA512: SslSignatureAlgorithm =
719 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA512 as _);
720
721 pub const RSA_PKCS1_MD5_SHA1: SslSignatureAlgorithm =
722 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_MD5_SHA1 as _);
723
724 pub const ECDSA_SHA1: SslSignatureAlgorithm =
725 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SHA1 as _);
726
727 pub const ECDSA_SECP256R1_SHA256: SslSignatureAlgorithm =
728 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP256R1_SHA256 as _);
729
730 pub const ECDSA_SECP384R1_SHA384: SslSignatureAlgorithm =
731 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP384R1_SHA384 as _);
732
733 pub const ECDSA_SECP521R1_SHA512: SslSignatureAlgorithm =
734 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP521R1_SHA512 as _);
735
736 pub const RSA_PSS_RSAE_SHA256: SslSignatureAlgorithm =
737 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA256 as _);
738
739 pub const RSA_PSS_RSAE_SHA384: SslSignatureAlgorithm =
740 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA384 as _);
741
742 pub const RSA_PSS_RSAE_SHA512: SslSignatureAlgorithm =
743 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA512 as _);
744
745 pub const ED25519: SslSignatureAlgorithm = SslSignatureAlgorithm(ffi::SSL_SIGN_ED25519 as _);
746}
747
748impl From<u16> for SslSignatureAlgorithm {
749 fn from(value: u16) -> Self {
750 Self(value)
751 }
752}
753
754#[repr(transparent)]
756#[derive(Debug, Copy, Clone, PartialEq, Eq)]
757pub struct SslCurve(c_int);
758
759impl SslCurve {
760 pub const SECP256R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP256R1 as _);
761
762 pub const SECP384R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP384R1 as _);
763
764 pub const SECP521R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP521R1 as _);
765
766 pub const X25519: SslCurve = SslCurve(ffi::SSL_CURVE_X25519 as _);
767
768 pub const X25519_MLKEM768: SslCurve = SslCurve(ffi::SSL_GROUP_X25519_MLKEM768 as _);
769
770 pub const X25519_KYBER768_DRAFT00: SslCurve =
771 SslCurve(ffi::SSL_GROUP_X25519_KYBER768_DRAFT00 as _);
772
773 pub const X25519_KYBER512_DRAFT00: SslCurve =
774 SslCurve(ffi::SSL_GROUP_X25519_KYBER512_DRAFT00 as _);
775
776 pub const X25519_KYBER768_DRAFT00_OLD: SslCurve =
777 SslCurve(ffi::SSL_GROUP_X25519_KYBER768_DRAFT00_OLD as _);
778
779 pub const P256_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::SSL_GROUP_P256_KYBER768_DRAFT00 as _);
780
781 pub const MLKEM1024: SslCurve = SslCurve(ffi::SSL_GROUP_MLKEM1024 as _);
782
783 #[corresponds(SSL_get_curve_name)]
785 pub fn name(&self) -> Option<&'static str> {
786 unsafe {
787 let ptr = ffi::SSL_get_curve_name(self.0 as u16);
788 if ptr.is_null() {
789 return None;
790 }
791
792 CStr::from_ptr(ptr).to_str().ok()
793 }
794 }
795
796 #[allow(dead_code)]
809 fn nid(&self) -> Option<c_int> {
810 match self.0 {
811 ffi::SSL_CURVE_SECP256R1 => Some(ffi::NID_X9_62_prime256v1),
812 ffi::SSL_CURVE_SECP384R1 => Some(ffi::NID_secp384r1),
813 ffi::SSL_CURVE_SECP521R1 => Some(ffi::NID_secp521r1),
814 ffi::SSL_CURVE_X25519 => Some(ffi::NID_X25519),
815 ffi::SSL_GROUP_X25519_MLKEM768 => Some(ffi::NID_X25519MLKEM768),
816 ffi::SSL_GROUP_X25519_KYBER768_DRAFT00 => Some(ffi::NID_X25519Kyber768Draft00),
817 ffi::SSL_GROUP_X25519_KYBER512_DRAFT00 => Some(ffi::NID_X25519Kyber512Draft00),
818 ffi::SSL_GROUP_X25519_KYBER768_DRAFT00_OLD => Some(ffi::NID_X25519Kyber768Draft00Old),
819 ffi::SSL_GROUP_P256_KYBER768_DRAFT00 => Some(ffi::NID_P256Kyber768Draft00),
820 ffi::SSL_GROUP_MLKEM1024 => Some(ffi::NID_MLKEM1024),
821 _ => None,
822 }
823 }
824}
825
826#[derive(Debug, Copy, Clone, PartialEq, Eq)]
828pub struct CompliancePolicy(ffi::ssl_compliance_policy_t);
829
830impl CompliancePolicy {
831 pub const NONE: Self = Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_none);
833
834 pub const FIPS_202205: Self =
837 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_fips_202205);
838
839 pub const WPA3_192_202304: Self =
842 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_wpa3_192_202304);
843}
844
845#[derive(Debug, Copy, Clone, PartialEq, Eq)]
848pub struct CertificateCompressionAlgorithm(u16);
849
850impl CertificateCompressionAlgorithm {
851 pub const ZLIB: Self = Self(ffi::TLSEXT_cert_compression_zlib as u16);
852 pub const BROTLI: Self = Self(ffi::TLSEXT_cert_compression_brotli as u16);
853 pub const ZSTD: Self = Self(ffi::TLSEXT_cert_compression_zstd as u16);
854}
855
856#[corresponds(SSL_select_next_proto)]
867#[must_use]
868pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
869 if server.is_empty() || client.is_empty() {
870 return None;
871 }
872
873 unsafe {
874 let mut out = ptr::null_mut();
875 let mut outlen = 0;
876 let r = ffi::SSL_select_next_proto(
877 &mut out,
878 &mut outlen,
879 server.as_ptr(),
880 try_int(server.len()).ok()?,
881 client.as_ptr(),
882 try_int(client.len()).ok()?,
883 );
884
885 if r == ffi::OPENSSL_NPN_NEGOTIATED {
886 Some(slice::from_raw_parts(out.cast_const(), outlen as usize))
887 } else {
888 None
889 }
890 }
891}
892
893#[derive(Debug, Copy, Clone, PartialEq, Eq)]
895pub enum TicketKeyCallbackResult {
896 Error,
898
899 Noop,
908
909 Success,
914
915 DecryptSuccessRenew,
927}
928
929impl From<TicketKeyCallbackResult> for c_int {
930 fn from(value: TicketKeyCallbackResult) -> Self {
931 match value {
932 TicketKeyCallbackResult::Error => -1,
933 TicketKeyCallbackResult::Noop => 0,
934 TicketKeyCallbackResult::Success => 1,
935 TicketKeyCallbackResult::DecryptSuccessRenew => 2,
936 }
937 }
938}
939
940#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
942pub struct SslInfoCallbackMode(i32);
943
944impl SslInfoCallbackMode {
945 pub const READ_ALERT: Self = Self(ffi::SSL_CB_READ_ALERT);
947
948 pub const WRITE_ALERT: Self = Self(ffi::SSL_CB_WRITE_ALERT);
950
951 pub const HANDSHAKE_START: Self = Self(ffi::SSL_CB_HANDSHAKE_START);
953
954 pub const HANDSHAKE_DONE: Self = Self(ffi::SSL_CB_HANDSHAKE_DONE);
956
957 pub const ACCEPT_LOOP: Self = Self(ffi::SSL_CB_ACCEPT_LOOP);
959
960 pub const ACCEPT_EXIT: Self = Self(ffi::SSL_CB_ACCEPT_EXIT);
962
963 pub const CONNECT_EXIT: Self = Self(ffi::SSL_CB_CONNECT_EXIT);
965}
966
967#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
970pub enum SslInfoCallbackValue {
971 Unit,
975 Alert(SslInfoCallbackAlert),
979}
980
981#[derive(Hash, Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
982pub struct SslInfoCallbackAlert(c_int);
983
984impl SslInfoCallbackAlert {
985 #[must_use]
987 pub fn alert_level(&self) -> Ssl3AlertLevel {
988 let value = self.0 >> 8;
989 Ssl3AlertLevel(value)
990 }
991
992 #[must_use]
994 pub fn alert(&self) -> SslAlert {
995 let value = self.0 & i32::from(u8::MAX);
996 SslAlert(value)
997 }
998}
999
1000#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1001pub struct Ssl3AlertLevel(c_int);
1002
1003impl Ssl3AlertLevel {
1004 pub const WARNING: Ssl3AlertLevel = Self(ffi::SSL3_AL_WARNING);
1005 pub const FATAL: Ssl3AlertLevel = Self(ffi::SSL3_AL_FATAL);
1006}
1007
1008pub struct SslContextBuilder {
1010 ctx: SslContext,
1011 has_shared_cert_store: bool,
1013}
1014
1015impl SslContextBuilder {
1016 #[corresponds(SSL_CTX_new)]
1018 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1019 unsafe {
1020 init();
1021 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
1022 let mut builder = SslContextBuilder::from_ptr(ctx);
1023
1024 if method.is_x509_method {
1025 builder.ctx.assume_x509();
1026 }
1027
1028 Ok(builder)
1029 }
1030 }
1031
1032 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
1043 SslContextBuilder {
1044 ctx: SslContext::from_ptr(ctx),
1045 has_shared_cert_store: false,
1046 }
1047 }
1048
1049 pub unsafe fn assume_x509(&mut self) {
1057 self.ctx.assume_x509();
1058 }
1059
1060 #[must_use]
1062 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
1063 self.ctx.as_ptr()
1064 }
1065
1066 #[corresponds(SSL_CTX_set_cert_verify_callback)]
1082 pub fn set_cert_verify_callback<F>(&mut self, callback: F)
1083 where
1084 F: Fn(&mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1085 {
1086 self.ctx.check_x509();
1087
1088 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1095 unsafe {
1096 ffi::SSL_CTX_set_cert_verify_callback(
1097 self.as_ptr(),
1098 Some(raw_cert_verify::<F>),
1099 ptr::null_mut(),
1100 );
1101 }
1102 }
1103
1104 #[corresponds(SSL_CTX_set_verify)]
1106 pub fn set_verify(&mut self, mode: SslVerifyMode) {
1107 unsafe {
1108 ffi::SSL_CTX_set_verify(self.as_ptr(), c_int::from(mode.bits()), None);
1109 }
1110 }
1111
1112 #[corresponds(SSL_CTX_set_verify)]
1129 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1130 where
1131 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1132 {
1133 self.ctx.check_x509();
1134 unsafe {
1135 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1136 ffi::SSL_CTX_set_verify(
1137 self.as_ptr(),
1138 c_int::from(mode.bits()),
1139 Some(raw_verify::<F>),
1140 );
1141 }
1142 }
1143
1144 #[corresponds(SSL_CTX_set_custom_verify)]
1159 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1160 where
1161 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
1162 {
1163 unsafe {
1164 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1165 ffi::SSL_CTX_set_custom_verify(
1166 self.as_ptr(),
1167 c_int::from(mode.bits()),
1168 Some(raw_custom_verify::<F>),
1169 );
1170 }
1171 }
1172
1173 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
1183 pub fn set_servername_callback<F>(&mut self, callback: F)
1184 where
1185 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
1186 {
1187 unsafe {
1188 let callback_index = SslContext::cached_ex_index::<F>();
1195
1196 self.ctx.replace_ex_data(callback_index, callback);
1197 let callback = self.ctx.ex_data(callback_index).unwrap();
1198
1199 let arg = std::ptr::from_ref(callback).cast_mut().cast();
1200
1201 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
1202 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
1203 }
1204 }
1205
1206 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1229 pub unsafe fn set_ticket_key_callback<F>(&mut self, callback: F)
1230 where
1231 F: Fn(
1232 &SslRef,
1233 &mut [u8; 16],
1234 &mut [u8; ffi::EVP_MAX_IV_LENGTH as usize],
1235 &mut CipherCtxRef,
1236 &mut HmacCtxRef,
1237 bool,
1238 ) -> TicketKeyCallbackResult
1239 + 'static
1240 + Sync
1241 + Send,
1242 {
1243 self.ctx.check_x509();
1244 unsafe {
1245 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1246 ffi::SSL_CTX_set_tlsext_ticket_key_cb(self.as_ptr(), Some(raw_ticket_key::<F>))
1247 };
1248 }
1249
1250 #[corresponds(SSL_CTX_set_verify_depth)]
1254 pub fn set_verify_depth(&mut self, depth: u32) {
1255 self.ctx.check_x509();
1256 unsafe {
1257 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
1258 }
1259 }
1260
1261 #[corresponds(SSL_CTX_set0_verify_cert_store)]
1263 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
1264 self.ctx.check_x509();
1265 unsafe {
1266 cvt(ffi::SSL_CTX_set0_verify_cert_store(
1267 self.as_ptr(),
1268 cert_store.into_ptr(),
1269 ))
1270 }
1271 }
1272
1273 #[corresponds(SSL_CTX_set_cert_store)]
1280 pub fn set_cert_store(&mut self, cert_store: X509Store) {
1281 self.ctx.check_x509();
1282 self.has_shared_cert_store = true;
1283 unsafe {
1284 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1285 }
1286 }
1287
1288 #[corresponds(SSL_CTX_set_cert_store)]
1290 pub fn set_cert_store_builder(&mut self, cert_store: X509StoreBuilder) {
1291 self.ctx.check_x509();
1292 self.has_shared_cert_store = false;
1293 unsafe {
1294 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1295 }
1296 }
1297
1298 #[corresponds(SSL_CTX_set_cert_store)]
1302 pub fn set_cert_store_ref(&mut self, cert_store: &X509Store) {
1303 self.set_cert_store(cert_store.to_owned());
1304 }
1305
1306 #[corresponds(SSL_CTX_set_read_ahead)]
1313 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1314 unsafe {
1315 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), c_int::from(read_ahead));
1316 }
1317 }
1318
1319 #[corresponds(SSL_CTX_set_mode)]
1321 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1322 let bits = unsafe { ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits()) };
1323 SslMode::from_bits_retain(bits)
1324 }
1325
1326 #[corresponds(SSL_CTX_set_tmp_dh)]
1328 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1329 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr())) }
1330 }
1331
1332 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1334 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1335 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr())) }
1336 }
1337
1338 #[corresponds(SSL_CTX_set_default_verify_paths)]
1343 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1344 self.ctx.check_x509();
1345 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())) }
1346 }
1347
1348 #[corresponds(SSL_CTX_load_verify_locations)]
1352 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1353 self.load_verify_locations(Some(file.as_ref()), None)
1354 }
1355
1356 #[corresponds(SSL_CTX_load_verify_locations)]
1358 pub fn load_verify_locations(
1359 &mut self,
1360 ca_file: Option<&Path>,
1361 ca_path: Option<&Path>,
1362 ) -> Result<(), ErrorStack> {
1363 self.ctx.check_x509();
1364
1365 let ca_file = ca_file.map(path_to_cstring).transpose()?;
1366 let ca_path = ca_path.map(path_to_cstring).transpose()?;
1367
1368 unsafe {
1369 cvt(ffi::SSL_CTX_load_verify_locations(
1370 self.as_ptr(),
1371 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1372 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1373 ))
1374 .map(|_| ())
1375 }
1376 }
1377
1378 #[corresponds(SSL_CTX_set_client_CA_list)]
1383 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1384 self.ctx.check_x509();
1385 unsafe {
1386 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1387 mem::forget(list);
1388 }
1389 }
1390
1391 #[corresponds(SSL_CTX_add_client_CA)]
1394 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1395 self.ctx.check_x509();
1396 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())) }
1397 }
1398
1399 #[corresponds(SSL_CTX_set_session_id_context)]
1408 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1409 unsafe {
1410 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1411 cvt(ffi::SSL_CTX_set_session_id_context(
1412 self.as_ptr(),
1413 sid_ctx.as_ptr(),
1414 sid_ctx.len(),
1415 ))
1416 }
1417 }
1418
1419 #[corresponds(SSL_CTX_use_certificate_file)]
1425 pub fn set_certificate_file<P: AsRef<Path>>(
1426 &mut self,
1427 file: P,
1428 file_type: SslFiletype,
1429 ) -> Result<(), ErrorStack> {
1430 self.ctx.check_x509();
1431 let file = path_to_cstring(file.as_ref())?;
1432 unsafe {
1433 cvt(ffi::SSL_CTX_use_certificate_file(
1434 self.as_ptr(),
1435 file.as_ptr(),
1436 file_type.as_raw(),
1437 ))
1438 .map(|_| ())
1439 }
1440 }
1441
1442 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1448 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1449 &mut self,
1450 file: P,
1451 ) -> Result<(), ErrorStack> {
1452 let file = path_to_cstring(file.as_ref())?;
1453 unsafe {
1454 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1455 self.as_ptr(),
1456 file.as_ptr(),
1457 ))
1458 .map(|_| ())
1459 }
1460 }
1461
1462 #[corresponds(SSL_CTX_use_certificate)]
1466 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1467 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())) }
1468 }
1469
1470 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1475 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1476 self.ctx.check_x509();
1477 unsafe {
1478 cvt(ffi::SSL_CTX_add_extra_chain_cert(
1479 self.as_ptr(),
1480 cert.into_ptr(),
1481 ))
1482 }
1483 }
1484
1485 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1487 pub fn set_private_key_file<P: AsRef<Path>>(
1488 &mut self,
1489 file: P,
1490 file_type: SslFiletype,
1491 ) -> Result<(), ErrorStack> {
1492 let file = path_to_cstring(file.as_ref())?;
1493 unsafe {
1494 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1495 self.as_ptr(),
1496 file.as_ptr(),
1497 file_type.as_raw(),
1498 ))
1499 .map(|_| ())
1500 }
1501 }
1502
1503 #[corresponds(SSL_CTX_use_PrivateKey)]
1505 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1506 where
1507 T: HasPrivate,
1508 {
1509 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())) }
1510 }
1511
1512 #[corresponds(SSL_CTX_set_cipher_list)]
1524 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1525 let cipher_list = CString::new(cipher_list).map_err(ErrorStack::internal_error)?;
1526 unsafe {
1527 cvt(ffi::SSL_CTX_set_cipher_list(
1528 self.as_ptr(),
1529 cipher_list.as_ptr(),
1530 ))
1531 }
1532 }
1533
1534 #[corresponds(SSL_CTX_set_strict_cipher_list)]
1545 pub fn set_strict_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1546 let cipher_list = CString::new(cipher_list).map_err(ErrorStack::internal_error)?;
1547 unsafe {
1548 cvt(ffi::SSL_CTX_set_strict_cipher_list(
1549 self.as_ptr(),
1550 cipher_list.as_ptr(),
1551 ))
1552 }
1553 }
1554
1555 #[corresponds(RAMA_SSL_CTX_set_raw_cipher_list)]
1559 pub fn set_raw_cipher_list(&mut self, cipher_list: &[u16]) -> Result<(), ErrorStack> {
1560 unsafe {
1561 cvt(ffi::RAMA_SSL_CTX_set_raw_cipher_list(
1562 self.as_ptr(),
1563 cipher_list.as_ptr() as *const _,
1564 cipher_list.len() as i32,
1565 ))
1566 }
1567 }
1568
1569 #[corresponds(SSL_CTX_get_ciphers)]
1575 #[must_use]
1576 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
1577 self.ctx.ciphers()
1578 }
1579
1580 #[corresponds(SSL_CTX_set_options)]
1587 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1588 let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
1589 SslOptions::from_bits_retain(bits)
1590 }
1591
1592 #[corresponds(SSL_CTX_get_options)]
1594 #[must_use]
1595 pub fn options(&self) -> SslOptions {
1596 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
1597 SslOptions::from_bits_retain(bits)
1598 }
1599
1600 #[corresponds(SSL_CTX_clear_options)]
1602 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1603 let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
1604 SslOptions::from_bits_retain(bits)
1605 }
1606
1607 #[corresponds(SSL_CTX_set_min_proto_version)]
1612 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1613 unsafe {
1614 cvt(ffi::SSL_CTX_set_min_proto_version(
1615 self.as_ptr(),
1616 version.map_or(0, |v| v.0 as _),
1617 ))
1618 }
1619 }
1620
1621 #[corresponds(SSL_CTX_set_max_proto_version)]
1625 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1626 unsafe {
1627 cvt(ffi::SSL_CTX_set_max_proto_version(
1628 self.as_ptr(),
1629 version.map_or(0, |v| v.0 as _),
1630 ))
1631 .map(|_| ())
1632 }
1633 }
1634
1635 #[corresponds(SSL_CTX_get_min_proto_version)]
1637 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1638 unsafe {
1639 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1640 if r == 0 {
1641 None
1642 } else {
1643 Some(SslVersion(r))
1644 }
1645 }
1646 }
1647
1648 #[corresponds(SSL_CTX_get_max_proto_version)]
1650 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1651 unsafe {
1652 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1653 if r == 0 {
1654 None
1655 } else {
1656 Some(SslVersion(r))
1657 }
1658 }
1659 }
1660
1661 #[corresponds(SSL_CTX_set_alpn_protos)]
1668 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1669 unsafe {
1670 let r = ffi::SSL_CTX_set_alpn_protos(
1671 self.as_ptr(),
1672 protocols.as_ptr(),
1673 try_int(protocols.len())?,
1674 );
1675 if r == 0 {
1677 Ok(())
1678 } else {
1679 Err(ErrorStack::get())
1680 }
1681 }
1682 }
1683
1684 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1686 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1687 unsafe {
1688 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
1689
1690 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1691 if r == 0 {
1693 Ok(())
1694 } else {
1695 Err(ErrorStack::get())
1696 }
1697 }
1698 }
1699
1700 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1711 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1712 where
1713 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1714 {
1715 unsafe {
1716 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1717 ffi::SSL_CTX_set_alpn_select_cb(
1718 self.as_ptr(),
1719 Some(callbacks::raw_alpn_select::<F>),
1720 ptr::null_mut(),
1721 );
1722 }
1723 }
1724
1725 #[corresponds(SSL_CTX_set_select_certificate_cb)]
1729 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
1730 where
1731 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
1732 {
1733 unsafe {
1734 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1735 ffi::SSL_CTX_set_select_certificate_cb(
1736 self.as_ptr(),
1737 Some(callbacks::raw_select_cert::<F>),
1738 );
1739 }
1740 }
1741
1742 #[corresponds(SSL_CTX_add_cert_compression_alg)]
1746 pub fn add_certificate_compression_algorithm<C>(
1747 &mut self,
1748 compressor: C,
1749 ) -> Result<(), ErrorStack>
1750 where
1751 C: CertificateCompressor,
1752 {
1753 const {
1754 assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered");
1755 };
1756 let success = unsafe {
1757 ffi::SSL_CTX_add_cert_compression_alg(
1758 self.as_ptr(),
1759 C::ALGORITHM.0,
1760 const {
1761 if C::CAN_COMPRESS {
1762 Some(callbacks::raw_ssl_cert_compress::<C>)
1763 } else {
1764 None
1765 }
1766 },
1767 const {
1768 if C::CAN_DECOMPRESS {
1769 Some(callbacks::raw_ssl_cert_decompress::<C>)
1770 } else {
1771 None
1772 }
1773 },
1774 ) == 1
1775 };
1776 if !success {
1777 return Err(ErrorStack::get());
1778 }
1779 self.replace_ex_data(SslContext::cached_ex_index::<C>(), compressor);
1780 Ok(())
1781 }
1782
1783 #[corresponds(SSL_CTX_set_private_key_method)]
1787 pub fn set_private_key_method<M>(&mut self, method: M)
1788 where
1789 M: PrivateKeyMethod,
1790 {
1791 unsafe {
1792 self.replace_ex_data(SslContext::cached_ex_index::<M>(), method);
1793
1794 ffi::SSL_CTX_set_private_key_method(
1795 self.as_ptr(),
1796 &ffi::SSL_PRIVATE_KEY_METHOD {
1797 sign: Some(callbacks::raw_sign::<M>),
1798 decrypt: Some(callbacks::raw_decrypt::<M>),
1799 complete: Some(callbacks::raw_complete::<M>),
1800 },
1801 );
1802 }
1803 }
1804
1805 #[corresponds(SSL_CTX_check_private_key)]
1807 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1808 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())) }
1809 }
1810
1811 #[corresponds(SSL_CTX_get_cert_store)]
1813 #[must_use]
1814 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1815 self.ctx.check_x509();
1816 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1817 }
1818
1819 #[corresponds(SSL_CTX_get_cert_store)]
1827 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1828 self.ctx.check_x509();
1829 assert!(
1830 !self.has_shared_cert_store,
1831 "Shared X509Store can't be mutated. Use set_cert_store_builder() instead of set_cert_store()
1832 or completely finish building the cert store setting it."
1833 );
1834 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1837 }
1838
1839 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1852 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1853 where
1854 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1855 {
1856 unsafe {
1857 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1858 cvt(ffi::SSL_CTX_set_tlsext_status_cb(
1859 self.as_ptr(),
1860 Some(raw_tlsext_status::<F>),
1861 ))
1862 }
1863 }
1864
1865 #[corresponds(SSL_CTX_set_psk_client_callback)]
1871 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1872 where
1873 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1874 + 'static
1875 + Sync
1876 + Send,
1877 {
1878 unsafe {
1879 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1880 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1881 }
1882 }
1883
1884 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1885 pub fn set_psk_callback<F>(&mut self, callback: F)
1886 where
1887 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1888 + 'static
1889 + Sync
1890 + Send,
1891 {
1892 self.set_psk_client_callback(callback);
1893 }
1894
1895 #[corresponds(SSL_CTX_set_psk_server_callback)]
1901 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1902 where
1903 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1904 + 'static
1905 + Sync
1906 + Send,
1907 {
1908 unsafe {
1909 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1910 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1911 }
1912 }
1913
1914 #[corresponds(SSL_CTX_sess_set_new_cb)]
1928 pub fn set_new_session_callback<F>(&mut self, callback: F)
1929 where
1930 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1931 {
1932 unsafe {
1933 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1934 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1935 }
1936 }
1937
1938 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1942 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1943 where
1944 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1945 {
1946 unsafe {
1947 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1948 ffi::SSL_CTX_sess_set_remove_cb(
1949 self.as_ptr(),
1950 Some(callbacks::raw_remove_session::<F>),
1951 );
1952 }
1953 }
1954
1955 #[corresponds(SSL_CTX_sess_set_get_cb)]
1966 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1967 where
1968 F: Fn(&mut SslRef, &[u8]) -> Result<Option<SslSession>, GetSessionPendingError>
1969 + 'static
1970 + Sync
1971 + Send,
1972 {
1973 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1974 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1975 }
1976
1977 #[corresponds(SSL_CTX_set_keylog_callback)]
1983 pub fn set_keylog_callback<F>(&mut self, callback: F)
1984 where
1985 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1986 {
1987 unsafe {
1988 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1989 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1990 }
1991 }
1992
1993 #[corresponds(SSL_CTX_set_session_cache_mode)]
1997 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1998 unsafe {
1999 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
2000 SslSessionCacheMode::from_bits_retain(bits)
2001 }
2002 }
2003
2004 #[corresponds(SSL_CTX_set_ex_data)]
2009 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2010 unsafe {
2011 self.ctx.replace_ex_data(index, data);
2012 }
2013 }
2014
2015 #[corresponds(SSL_CTX_set_ex_data)]
2022 pub fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2023 unsafe { self.ctx.replace_ex_data(index, data) }
2024 }
2025
2026 #[corresponds(SSL_CTX_sess_set_cache_size)]
2030 #[allow(clippy::useless_conversion)]
2031 pub fn set_session_cache_size(&mut self, size: u32) -> u64 {
2032 unsafe { ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size.into()).into() }
2033 }
2034
2035 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2037 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2038 let sigalgs = CString::new(sigalgs).map_err(ErrorStack::internal_error)?;
2039 unsafe {
2040 cvt(ffi::SSL_CTX_set1_sigalgs_list(
2041 self.as_ptr(),
2042 sigalgs.as_ptr(),
2043 ))
2044 }
2045 }
2046
2047 #[corresponds(SSL_CTX_set_grease_enabled)]
2049 pub fn set_grease_enabled(&mut self, enabled: bool) {
2050 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as _) }
2051 }
2052
2053 #[corresponds(SSL_CTX_set_permute_extensions)]
2055 pub fn set_permute_extensions(&mut self, enabled: bool) {
2056 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as _) }
2057 }
2058
2059 #[corresponds(RAMA_SSL_CTX_set_extension_order)]
2061 pub fn set_extension_order(&mut self, ids: &[u16]) -> Result<(), ErrorStack> {
2062 unsafe {
2063 cvt(ffi::RAMA_SSL_CTX_set_extension_order(
2064 self.as_ptr(),
2065 ids.as_ptr() as *const _,
2066 ids.len() as i32,
2067 ))
2068 .map(|_| ())
2069 }
2070 }
2071
2072 #[corresponds(SSL_CTX_set_verify_algorithm_prefs)]
2074 pub fn set_verify_algorithm_prefs(
2075 &mut self,
2076 prefs: &[SslSignatureAlgorithm],
2077 ) -> Result<(), ErrorStack> {
2078 unsafe {
2079 cvt_0i(ffi::SSL_CTX_set_verify_algorithm_prefs(
2080 self.as_ptr(),
2081 prefs.as_ptr().cast(),
2082 prefs.len(),
2083 ))
2084 .map(|_| ())
2085 }
2086 }
2087
2088 #[corresponds(SSL_CTX_enable_signed_cert_timestamps)]
2090 pub fn enable_signed_cert_timestamps(&mut self) {
2091 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
2092 }
2093
2094 #[corresponds(SSL_CTX_enable_ocsp_stapling)]
2096 pub fn enable_ocsp_stapling(&mut self) {
2097 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
2098 }
2099
2100 #[corresponds(SSL_CTX_set1_curves_list)]
2106 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2107 let curves = CString::new(curves).unwrap();
2108 unsafe {
2109 cvt_0i(ffi::SSL_CTX_set1_curves_list(
2110 self.as_ptr(),
2111 curves.as_ptr(),
2112 ))
2113 .map(|_| ())
2114 }
2115 }
2116
2117 #[corresponds(SSL_CTX_set1_curves)]
2123 pub fn set_curves(&mut self, curves: &[SslCurve]) -> Result<(), ErrorStack> {
2124 let curves: Vec<i32> = curves.iter().filter_map(|curve| curve.nid()).collect();
2125
2126 unsafe {
2127 cvt_0i(ffi::SSL_CTX_set1_curves(
2128 self.as_ptr(),
2129 curves.as_ptr() as *const _,
2130 curves.len(),
2131 ))
2132 .map(|_| ())
2133 }
2134 }
2135
2136 #[corresponds(SSL_CTX_set_compliance_policy)]
2140 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
2141 unsafe { cvt_0i(ffi::SSL_CTX_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
2142 }
2143
2144 #[corresponds(SSL_CTX_set_info_callback)]
2146 pub fn set_info_callback<F>(&mut self, callback: F)
2147 where
2148 F: Fn(&SslRef, SslInfoCallbackMode, SslInfoCallbackValue) + Send + Sync + 'static,
2149 {
2150 unsafe {
2151 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
2152 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info_callback::<F>));
2153 }
2154 }
2155
2156 #[corresponds(SSL_CTX_set1_ech_keys)]
2161 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2162 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())) }
2163 }
2164
2165 #[corresponds(SSL_CTX_add1_credential)]
2167 pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> {
2168 unsafe {
2169 cvt_0i(ffi::SSL_CTX_add1_credential(
2170 self.as_ptr(),
2171 credential.as_ptr(),
2172 ))
2173 .map(|_| ())
2174 }
2175 }
2176
2177 #[must_use]
2179 pub fn build(self) -> SslContext {
2180 self.ctx
2181 }
2182}
2183
2184foreign_type_and_impl_send_sync! {
2185 type CType = ffi::SSL_CTX;
2186 fn drop = ffi::SSL_CTX_free;
2187
2188 pub struct SslContext;
2193}
2194
2195impl Clone for SslContext {
2196 fn clone(&self) -> Self {
2197 (**self).to_owned()
2198 }
2199}
2200
2201impl ToOwned for SslContextRef {
2202 type Owned = SslContext;
2203
2204 fn to_owned(&self) -> Self::Owned {
2205 unsafe {
2206 SSL_CTX_up_ref(self.as_ptr());
2207 SslContext::from_ptr(self.as_ptr())
2208 }
2209 }
2210}
2211
2212impl fmt::Debug for SslContext {
2214 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2215 write!(fmt, "SslContext")
2216 }
2217}
2218
2219impl SslContext {
2220 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2222 SslContextBuilder::new(method)
2223 }
2224
2225 #[corresponds(SSL_CTX_get_ex_new_index)]
2230 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2231 where
2232 T: 'static + Sync + Send,
2233 {
2234 unsafe {
2235 ffi::init();
2236 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2237 Ok(Index::from_raw(idx))
2238 }
2239 }
2240
2241 fn cached_ex_index<T>() -> Index<SslContext, T>
2243 where
2244 T: 'static + Sync + Send,
2245 {
2246 unsafe {
2247 let idx = *INDEXES
2248 .lock()
2249 .unwrap_or_else(|e| e.into_inner())
2250 .entry(TypeId::of::<T>())
2251 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2252 Index::from_raw(idx)
2253 }
2254 }
2255
2256 #[corresponds(SSL_CTX_get_ciphers)]
2262 #[must_use]
2263 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
2264 unsafe {
2265 let ciphers = ffi::SSL_CTX_get_ciphers(self.as_ptr());
2266 if ciphers.is_null() {
2267 None
2268 } else {
2269 Some(StackRef::from_ptr(ciphers))
2270 }
2271 }
2272 }
2273}
2274
2275impl SslContextRef {
2276 #[corresponds(SSL_CTX_get0_certificate)]
2278 #[must_use]
2279 pub fn certificate(&self) -> Option<&X509Ref> {
2280 self.check_x509();
2281 unsafe {
2282 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2283 if ptr.is_null() {
2284 None
2285 } else {
2286 Some(X509Ref::from_ptr(ptr))
2287 }
2288 }
2289 }
2290
2291 #[corresponds(SSL_CTX_get0_privatekey)]
2293 #[must_use]
2294 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2295 unsafe {
2296 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2297 if ptr.is_null() {
2298 None
2299 } else {
2300 Some(PKeyRef::from_ptr(ptr))
2301 }
2302 }
2303 }
2304
2305 #[corresponds(SSL_CTX_get_cert_store)]
2307 #[must_use]
2308 pub fn cert_store(&self) -> &X509StoreRef {
2309 self.check_x509();
2310 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2311 }
2312
2313 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2315 #[must_use]
2316 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2317 unsafe {
2318 let mut chain = ptr::null_mut();
2319 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2320 assert!(!chain.is_null());
2321 StackRef::from_ptr(chain)
2322 }
2323 }
2324
2325 #[corresponds(SSL_CTX_get_ex_data)]
2327 #[must_use]
2328 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2329 unsafe {
2330 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2331 if data.is_null() {
2332 None
2333 } else {
2334 Some(&*(data as *const T))
2335 }
2336 }
2337 }
2338
2339 #[corresponds(SSL_CTX_get_ex_data)]
2342 unsafe fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2343 ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw())
2344 .cast::<T>()
2345 .as_mut()
2346 }
2347
2348 #[corresponds(SSL_CTX_set_ex_data)]
2351 unsafe fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2352 unsafe {
2353 let data = Box::into_raw(Box::new(data));
2354 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data.cast());
2355 }
2356 }
2357
2358 #[corresponds(SSL_CTX_set_ex_data)]
2361 unsafe fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2362 if let Some(old) = self.ex_data_mut(index) {
2363 return Some(mem::replace(old, data));
2364 }
2365
2366 self.set_ex_data(index, data);
2367
2368 None
2369 }
2370
2371 #[corresponds(SSL_CTX_add_session)]
2380 #[must_use]
2381 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2382 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2383 }
2384
2385 #[corresponds(SSL_CTX_remove_session)]
2394 #[must_use]
2395 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2396 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2397 }
2398
2399 #[corresponds(SSL_CTX_sess_get_cache_size)]
2403 #[allow(clippy::useless_conversion)]
2404 #[must_use]
2405 pub fn session_cache_size(&self) -> u64 {
2406 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()).into() }
2407 }
2408
2409 #[corresponds(SSL_CTX_get_verify_mode)]
2413 #[must_use]
2414 pub fn verify_mode(&self) -> SslVerifyMode {
2415 self.check_x509();
2416 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2417 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2418 }
2419
2420 pub unsafe fn assume_x509(&mut self) {
2428 self.replace_ex_data(*X509_FLAG_INDEX, true);
2429 }
2430
2431 #[must_use]
2433 pub fn has_x509_support(&self) -> bool {
2434 self.ex_data(*X509_FLAG_INDEX).copied().unwrap_or_default()
2435 }
2436
2437 #[track_caller]
2438 fn check_x509(&self) {
2439 assert!(
2440 self.has_x509_support(),
2441 "This context is not configured for X.509 certificates"
2442 );
2443 }
2444
2445 #[corresponds(SSL_CTX_set1_ech_keys)]
2450 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2451 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())) }
2452 }
2453}
2454
2455#[derive(Debug)]
2460pub struct GetSessionPendingError;
2461
2462pub struct CipherBits {
2464 pub secret: i32,
2466
2467 pub algorithm: i32,
2469}
2470
2471#[repr(transparent)]
2472pub struct ClientHello<'ssl>(&'ssl ffi::SSL_CLIENT_HELLO);
2473
2474impl ClientHello<'_> {
2475 #[corresponds(SSL_early_callback_ctx_extension_get)]
2477 #[must_use]
2478 pub fn get_extension(&self, ext_type: ExtensionType) -> Option<&[u8]> {
2479 unsafe {
2480 let mut ptr = ptr::null();
2481 let mut len = 0;
2482 let result =
2483 ffi::SSL_early_callback_ctx_extension_get(self.0, ext_type.0, &mut ptr, &mut len);
2484 if result == 0 {
2485 return None;
2486 }
2487 Some(slice::from_raw_parts(ptr, len))
2488 }
2489 }
2490
2491 #[must_use]
2492 pub fn ssl_mut(&mut self) -> &mut SslRef {
2493 unsafe { SslRef::from_ptr_mut(self.0.ssl) }
2494 }
2495
2496 #[must_use]
2497 pub fn ssl(&self) -> &SslRef {
2498 unsafe { SslRef::from_ptr(self.0.ssl) }
2499 }
2500
2501 pub fn servername(&self, type_: NameType) -> Option<&str> {
2503 self.ssl().servername(type_)
2504 }
2505
2506 #[must_use]
2508 pub fn client_version(&self) -> SslVersion {
2509 SslVersion(self.0.version)
2510 }
2511
2512 #[must_use]
2514 pub fn version_str(&self) -> &'static str {
2515 self.ssl().version_str()
2516 }
2517
2518 pub fn as_bytes(&self) -> &[u8] {
2520 unsafe { slice::from_raw_parts(self.0.client_hello, self.0.client_hello_len) }
2521 }
2522
2523 #[must_use]
2525 pub fn random(&self) -> &[u8] {
2526 unsafe { slice::from_raw_parts(self.0.random, self.0.random_len) }
2527 }
2528
2529 #[must_use]
2531 pub fn ciphers(&self) -> &[u8] {
2532 unsafe { slice::from_raw_parts(self.0.cipher_suites, self.0.cipher_suites_len) }
2533 }
2534}
2535
2536#[derive(Clone, Copy)]
2538pub struct SslCipher(&'static SslCipherRef);
2539
2540impl SslCipher {
2541 #[corresponds(SSL_get_cipher_by_value)]
2542 #[must_use]
2543 pub fn from_value(value: u16) -> Option<Self> {
2544 unsafe {
2545 let ptr = ffi::SSL_get_cipher_by_value(value);
2546 if ptr.is_null() {
2547 None
2548 } else {
2549 Some(Self::from_ptr(ptr.cast_mut()))
2550 }
2551 }
2552 }
2553}
2554
2555impl Stackable for SslCipher {
2556 type StackType = ffi::stack_st_SSL_CIPHER;
2557}
2558
2559unsafe impl ForeignType for SslCipher {
2560 type CType = ffi::SSL_CIPHER;
2561 type Ref = SslCipherRef;
2562
2563 #[inline]
2564 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2565 SslCipher(SslCipherRef::from_ptr(ptr))
2566 }
2567
2568 #[inline]
2569 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2570 self.0.as_ptr()
2571 }
2572}
2573
2574impl Deref for SslCipher {
2575 type Target = SslCipherRef;
2576
2577 fn deref(&self) -> &SslCipherRef {
2578 self.0
2579 }
2580}
2581
2582pub struct SslCipherRef(Opaque);
2586
2587unsafe impl Send for SslCipherRef {}
2588unsafe impl Sync for SslCipherRef {}
2589
2590unsafe impl ForeignTypeRef for SslCipherRef {
2591 type CType = ffi::SSL_CIPHER;
2592}
2593
2594impl SslCipherRef {
2595 #[corresponds(SSL_CIPHER_get_protocol_id)]
2597 #[must_use]
2598 pub fn protocol_id(&self) -> u16 {
2599 unsafe { ffi::SSL_CIPHER_get_protocol_id(self.as_ptr()) }
2600 }
2601
2602 #[corresponds(SSL_CIPHER_get_name)]
2604 #[must_use]
2605 pub fn name(&self) -> &'static str {
2606 unsafe {
2607 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2608 CStr::from_ptr(ptr).to_str().unwrap()
2609 }
2610 }
2611
2612 #[corresponds(SSL_CIPHER_standard_name)]
2614 #[must_use]
2615 pub fn standard_name(&self) -> Option<&'static str> {
2616 unsafe {
2617 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2618 if ptr.is_null() {
2619 None
2620 } else {
2621 Some(CStr::from_ptr(ptr).to_str().unwrap())
2622 }
2623 }
2624 }
2625
2626 #[corresponds(SSL_CIPHER_get_version)]
2628 #[must_use]
2629 pub fn version(&self) -> &'static str {
2630 let version = unsafe {
2631 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2632 CStr::from_ptr(ptr)
2633 };
2634
2635 str::from_utf8(version.to_bytes()).unwrap()
2636 }
2637
2638 #[corresponds(SSL_CIPHER_get_bits)]
2640 #[allow(clippy::useless_conversion)]
2641 #[must_use]
2642 pub fn bits(&self) -> CipherBits {
2643 unsafe {
2644 let mut algo_bits = 0;
2645 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2646 CipherBits {
2647 secret: secret_bits.into(),
2648 algorithm: algo_bits.into(),
2649 }
2650 }
2651 }
2652
2653 #[corresponds(SSL_CIPHER_description)]
2655 #[must_use]
2656 pub fn description(&self) -> String {
2657 unsafe {
2658 let mut buf = [0; 128];
2660 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2661 CStr::from_ptr(ptr).to_string_lossy().into_owned()
2662 }
2663 }
2664
2665 #[corresponds(SSL_CIPHER_is_aead)]
2667 #[must_use]
2668 pub fn cipher_is_aead(&self) -> bool {
2669 unsafe { ffi::SSL_CIPHER_is_aead(self.as_ptr()) != 0 }
2670 }
2671
2672 #[corresponds(SSL_CIPHER_get_auth_nid)]
2674 #[must_use]
2675 pub fn cipher_auth_nid(&self) -> Option<Nid> {
2676 let n = unsafe { ffi::SSL_CIPHER_get_auth_nid(self.as_ptr()) };
2677 if n == 0 {
2678 None
2679 } else {
2680 Some(Nid::from_raw(n))
2681 }
2682 }
2683
2684 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2686 #[must_use]
2687 pub fn cipher_nid(&self) -> Option<Nid> {
2688 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2689 if n == 0 {
2690 None
2691 } else {
2692 Some(Nid::from_raw(n))
2693 }
2694 }
2695}
2696
2697foreign_type_and_impl_send_sync! {
2698 type CType = ffi::SSL_SESSION;
2699 fn drop = ffi::SSL_SESSION_free;
2700
2701 pub struct SslSession;
2705}
2706
2707impl Clone for SslSession {
2708 fn clone(&self) -> SslSession {
2709 SslSessionRef::to_owned(self)
2710 }
2711}
2712
2713impl SslSession {
2714 from_der! {
2715 #[corresponds(d2i_SSL_SESSION)]
2717 from_der,
2718 SslSession,
2719 ffi::d2i_SSL_SESSION,
2720 crate::libc_types::c_long
2721 }
2722}
2723
2724impl ToOwned for SslSessionRef {
2725 type Owned = SslSession;
2726
2727 fn to_owned(&self) -> SslSession {
2728 unsafe {
2729 SSL_SESSION_up_ref(self.as_ptr());
2730 SslSession(NonNull::new_unchecked(self.as_ptr()))
2731 }
2732 }
2733}
2734
2735impl SslSessionRef {
2736 #[corresponds(SSL_SESSION_get_id)]
2738 #[must_use]
2739 pub fn id(&self) -> &[u8] {
2740 unsafe {
2741 let mut len = 0;
2742 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2743 slice::from_raw_parts(p, len as usize)
2744 }
2745 }
2746
2747 #[corresponds(SSL_SESSION_get_master_key)]
2749 #[must_use]
2750 pub fn master_key_len(&self) -> usize {
2751 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2752 }
2753
2754 #[corresponds(SSL_SESSION_get_master_key)]
2758 #[must_use]
2759 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2760 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2761 }
2762
2763 #[corresponds(SSL_SESSION_get_time)]
2765 #[allow(clippy::useless_conversion)]
2766 #[must_use]
2767 pub fn time(&self) -> u64 {
2768 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2769 }
2770
2771 #[corresponds(SSL_SESSION_get_timeout)]
2775 #[allow(clippy::useless_conversion)]
2776 #[must_use]
2777 pub fn timeout(&self) -> u32 {
2778 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()) }
2779 }
2780
2781 #[corresponds(SSL_SESSION_get_protocol_version)]
2783 #[must_use]
2784 pub fn protocol_version(&self) -> SslVersion {
2785 unsafe {
2786 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2787 SslVersion(version)
2788 }
2789 }
2790
2791 to_der! {
2792 #[corresponds(i2d_SSL_SESSION)]
2794 to_der,
2795 ffi::i2d_SSL_SESSION
2796 }
2797}
2798
2799foreign_type_and_impl_send_sync! {
2800 type CType = ffi::SSL;
2801 fn drop = ffi::SSL_free;
2802
2803 pub struct Ssl;
2810}
2811
2812impl fmt::Debug for Ssl {
2813 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2814 fmt::Debug::fmt(&**self, fmt)
2815 }
2816}
2817
2818impl Ssl {
2819 #[corresponds(SSL_get_ex_new_index)]
2824 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2825 where
2826 T: 'static + Sync + Send,
2827 {
2828 unsafe {
2829 ffi::init();
2830 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2831 Ok(Index::from_raw(idx))
2832 }
2833 }
2834
2835 fn cached_ex_index<T>() -> Index<Ssl, T>
2837 where
2838 T: 'static + Sync + Send,
2839 {
2840 unsafe {
2841 let idx = *SSL_INDEXES
2842 .lock()
2843 .unwrap_or_else(|e| e.into_inner())
2844 .entry(TypeId::of::<T>())
2845 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2846 Index::from_raw(idx)
2847 }
2848 }
2849
2850 #[corresponds(SSL_new)]
2852 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2853 unsafe {
2854 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2855 let mut ssl = Ssl::from_ptr(ptr);
2856 SSL_CTX_up_ref(ctx.as_ptr());
2857 let ctx_owned = SslContext::from_ptr(ctx.as_ptr());
2858 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx_owned);
2859
2860 Ok(ssl)
2861 }
2862 }
2863
2864 pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2876 where
2877 S: Read + Write,
2878 {
2879 SslStreamBuilder::new(self, stream).setup_connect()
2880 }
2881
2882 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2892 where
2893 S: Read + Write,
2894 {
2895 self.setup_connect(stream).handshake()
2896 }
2897
2898 pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
2910 where
2911 S: Read + Write,
2912 {
2913 SslStreamBuilder::new(self, stream).setup_accept()
2914 }
2915
2916 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2928 where
2929 S: Read + Write,
2930 {
2931 self.setup_accept(stream).handshake()
2932 }
2933}
2934
2935impl fmt::Debug for SslRef {
2936 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2937 let mut builder = fmt.debug_struct("Ssl");
2938 builder.field("state", &self.state_string_long());
2939 if self.ssl_context().has_x509_support() {
2940 builder.field("verify_result", &self.verify_result());
2941 }
2942 builder.finish()
2943 }
2944}
2945
2946impl SslRef {
2947 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2948 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2949 }
2950
2951 #[corresponds(SSL_set_options)]
2958 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
2959 let bits = unsafe { ffi::SSL_set_options(self.as_ptr(), option.bits()) };
2960 SslOptions::from_bits_retain(bits)
2961 }
2962
2963 #[corresponds(SSL_clear_options)]
2965 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
2966 let bits = unsafe { ffi::SSL_clear_options(self.as_ptr(), option.bits()) };
2967 SslOptions::from_bits_retain(bits)
2968 }
2969
2970 #[corresponds(SSL_set1_curves_list)]
2971 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2972 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2973 unsafe {
2974 cvt_0i(ffi::SSL_set1_curves_list(
2975 self.as_ptr(),
2976 curves.as_ptr() as *const _,
2977 ))
2978 .map(|_| ())
2979 }
2980 }
2981
2982 #[corresponds(SSL_get_curve_id)]
2984 pub fn curve(&self) -> Option<SslCurve> {
2985 let curve_id = unsafe { ffi::SSL_get_curve_id(self.as_ptr()) };
2986 if curve_id == 0 {
2987 return None;
2988 }
2989 Some(SslCurve(curve_id.into()))
2990 }
2991
2992 #[corresponds(SSL_get_curve_name)]
2994 #[must_use]
2995 pub fn curve_name(&self) -> Option<&'static str> {
2996 let curve_id = self.curve()?.0;
2997
2998 unsafe {
2999 let ptr = ffi::SSL_get_curve_name(curve_id as u16);
3000 if ptr.is_null() {
3001 return None;
3002 }
3003
3004 CStr::from_ptr(ptr).to_str().ok()
3005 }
3006 }
3007
3008 #[corresponds(SSL_get_error)]
3010 #[must_use]
3011 pub fn error_code(&self, ret: c_int) -> ErrorCode {
3012 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
3013 }
3014
3015 #[corresponds(SSL_set_verify)]
3019 pub fn set_verify(&mut self, mode: SslVerifyMode) {
3020 self.ssl_context().check_x509();
3021 unsafe { ffi::SSL_set_verify(self.as_ptr(), c_int::from(mode.bits()), None) }
3022 }
3023
3024 #[corresponds(SSL_set_verify_depth)]
3028 pub fn set_verify_depth(&mut self, depth: u32) {
3029 self.ssl_context().check_x509();
3030 unsafe {
3031 ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
3032 }
3033 }
3034
3035 #[corresponds(SSL_get_verify_mode)]
3037 #[must_use]
3038 pub fn verify_mode(&self) -> SslVerifyMode {
3039 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
3040 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
3041 }
3042
3043 #[corresponds(SSL_set_verify)]
3060 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3061 where
3062 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
3063 {
3064 self.ssl_context().check_x509();
3065 unsafe {
3066 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3068 ffi::SSL_set_verify(
3069 self.as_ptr(),
3070 c_int::from(mode.bits()),
3071 Some(ssl_raw_verify::<F>),
3072 );
3073 }
3074 }
3075
3076 #[corresponds(SSL_set0_verify_cert_store)]
3078 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3079 self.ssl_context().check_x509();
3080 unsafe {
3081 cvt(ffi::SSL_set0_verify_cert_store(
3082 self.as_ptr(),
3083 cert_store.into_ptr(),
3084 ))
3085 }
3086 }
3087
3088 #[corresponds(SSL_set_custom_verify)]
3094 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3095 where
3096 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
3097 {
3098 self.ssl_context().check_x509();
3099 unsafe {
3100 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3102 ffi::SSL_set_custom_verify(
3103 self.as_ptr(),
3104 c_int::from(mode.bits()),
3105 Some(ssl_raw_custom_verify::<F>),
3106 );
3107 }
3108 }
3109
3110 #[corresponds(SSL_set_tmp_dh)]
3114 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3115 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr())) }
3116 }
3117
3118 #[corresponds(SSL_set_tmp_ecdh)]
3122 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3123 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr())) }
3124 }
3125
3126 #[corresponds(SSL_set_permute_extensions)]
3128 pub fn set_permute_extensions(&mut self, enabled: bool) {
3129 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as _) }
3130 }
3131
3132 #[corresponds(SSL_set_alpn_protos)]
3136 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3137 unsafe {
3138 let r = ffi::SSL_set_alpn_protos(
3139 self.as_ptr(),
3140 protocols.as_ptr(),
3141 try_int(protocols.len())?,
3142 );
3143 if r == 0 {
3145 Ok(())
3146 } else {
3147 Err(ErrorStack::get())
3148 }
3149 }
3150 }
3151
3152 #[corresponds(SSL_set_record_size_limit)]
3153 pub fn set_record_size_limit(&mut self, value: u16) -> Result<(), ErrorStack> {
3154 unsafe { cvt(ffi::SSL_set_record_size_limit(self.as_ptr(), value) as c_int).map(|_| ()) }
3155 }
3156
3157 #[corresponds(SSL_set_delegated_credential_schemes)]
3158 pub fn set_delegated_credential_schemes(
3159 &mut self,
3160 schemes: &[SslSignatureAlgorithm],
3161 ) -> Result<(), ErrorStack> {
3162 unsafe {
3163 cvt_0i(ffi::SSL_set_delegated_credential_schemes(
3164 self.as_ptr(),
3165 schemes.as_ptr() as *const _,
3166 schemes.len(),
3167 ))
3168 .map(|_| ())
3169 }
3170 }
3171
3172 #[corresponds(SSL_get_ciphers)]
3174 #[must_use]
3175 pub fn ciphers(&self) -> &StackRef<SslCipher> {
3176 unsafe {
3177 let cipher_list = ffi::SSL_get_ciphers(self.as_ptr());
3178 StackRef::from_ptr(cipher_list)
3179 }
3180 }
3181
3182 #[corresponds(SSL_get_current_cipher)]
3184 #[must_use]
3185 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3186 unsafe {
3187 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3188
3189 if ptr.is_null() {
3190 None
3191 } else {
3192 Some(SslCipherRef::from_ptr(ptr.cast_mut()))
3193 }
3194 }
3195 }
3196
3197 #[corresponds(SSL_state_string)]
3199 #[must_use]
3200 pub fn state_string(&self) -> &'static str {
3201 let state = unsafe {
3202 let ptr = ffi::SSL_state_string(self.as_ptr());
3203 CStr::from_ptr(ptr)
3204 };
3205
3206 state.to_str().unwrap_or_default()
3207 }
3208
3209 #[corresponds(SSL_state_string_long)]
3213 #[must_use]
3214 pub fn state_string_long(&self) -> &'static str {
3215 let state = unsafe {
3216 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3217 CStr::from_ptr(ptr)
3218 };
3219
3220 state.to_str().unwrap_or_default()
3221 }
3222
3223 #[corresponds(SSL_set_tlsext_host_name)]
3227 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3228 let cstr = CString::new(hostname).map_err(ErrorStack::internal_error)?;
3229 unsafe { cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr())) }
3230 }
3231
3232 #[corresponds(SSL_get_peer_certificate)]
3234 #[must_use]
3235 pub fn peer_certificate(&self) -> Option<X509> {
3236 self.ssl_context().check_x509();
3237 unsafe {
3238 let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
3239 if ptr.is_null() {
3240 None
3241 } else {
3242 Some(X509::from_ptr(ptr))
3243 }
3244 }
3245 }
3246
3247 #[corresponds(SSL_get_peer_certificate)]
3252 #[must_use]
3253 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3254 unsafe {
3255 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3256 if ptr.is_null() {
3257 None
3258 } else {
3259 Some(StackRef::from_ptr(ptr))
3260 }
3261 }
3262 }
3263
3264 #[corresponds(SSL_get_certificate)]
3266 #[must_use]
3267 pub fn certificate(&self) -> Option<&X509Ref> {
3268 self.ssl_context().check_x509();
3269 unsafe {
3270 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3271 if ptr.is_null() {
3272 None
3273 } else {
3274 Some(X509Ref::from_ptr(ptr))
3275 }
3276 }
3277 }
3278
3279 #[corresponds(SSL_get_privatekey)]
3281 #[must_use]
3282 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3283 unsafe {
3284 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3285 if ptr.is_null() {
3286 None
3287 } else {
3288 Some(PKeyRef::from_ptr(ptr))
3289 }
3290 }
3291 }
3292
3293 #[corresponds(SSL_version)]
3295 #[must_use]
3296 pub fn version(&self) -> Option<SslVersion> {
3297 unsafe {
3298 let r = ffi::SSL_version(self.as_ptr());
3299 if r == 0 {
3300 None
3301 } else {
3302 r.try_into().ok().map(SslVersion)
3303 }
3304 }
3305 }
3306
3307 #[corresponds(SSL_get_version)]
3311 #[must_use]
3312 pub fn version_str(&self) -> &'static str {
3313 let version = unsafe {
3314 let ptr = ffi::SSL_get_version(self.as_ptr());
3315 CStr::from_ptr(ptr)
3316 };
3317
3318 version.to_str().unwrap()
3319 }
3320
3321 #[corresponds(SSL_set_min_proto_version)]
3326 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3327 unsafe {
3328 cvt(ffi::SSL_set_min_proto_version(
3329 self.as_ptr(),
3330 version.map_or(0, |v| v.0 as _),
3331 ))
3332 }
3333 }
3334
3335 #[corresponds(SSL_set_max_proto_version)]
3339 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3340 unsafe {
3341 cvt(ffi::SSL_set_max_proto_version(
3342 self.as_ptr(),
3343 version.map_or(0, |v| v.0 as _),
3344 ))
3345 }
3346 }
3347
3348 #[corresponds(SSL_get_min_proto_version)]
3350 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
3351 unsafe {
3352 let r = ffi::SSL_get_min_proto_version(self.as_ptr());
3353 if r == 0 {
3354 None
3355 } else {
3356 Some(SslVersion(r))
3357 }
3358 }
3359 }
3360
3361 #[corresponds(SSL_get_max_proto_version)]
3363 #[must_use]
3364 pub fn max_proto_version(&self) -> Option<SslVersion> {
3365 let r = unsafe { ffi::SSL_get_max_proto_version(self.as_ptr()) };
3366 if r == 0 {
3367 None
3368 } else {
3369 Some(SslVersion(r))
3370 }
3371 }
3372
3373 #[corresponds(SSL_get0_alpn_selected)]
3378 #[must_use]
3379 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3380 unsafe {
3381 let mut data: *const c_uchar = ptr::null();
3382 let mut len: c_uint = 0;
3383 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3386
3387 if data.is_null() {
3388 None
3389 } else {
3390 Some(slice::from_raw_parts(data, len as usize))
3391 }
3392 }
3393 }
3394
3395 #[corresponds(SSL_set_tlsext_use_srtp)]
3397 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3398 unsafe {
3399 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
3400
3401 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3402 if r == 0 {
3404 Ok(())
3405 } else {
3406 Err(ErrorStack::get())
3407 }
3408 }
3409 }
3410
3411 #[corresponds(SSL_get_strp_profiles)]
3415 #[must_use]
3416 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3417 unsafe {
3418 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3419
3420 if chain.is_null() {
3421 None
3422 } else {
3423 Some(StackRef::from_ptr(chain.cast_mut()))
3424 }
3425 }
3426 }
3427
3428 #[corresponds(SSL_get_selected_srtp_profile)]
3432 #[must_use]
3433 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3434 unsafe {
3435 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3436
3437 if profile.is_null() {
3438 None
3439 } else {
3440 Some(SrtpProtectionProfileRef::from_ptr(profile.cast_mut()))
3441 }
3442 }
3443 }
3444
3445 #[corresponds(SSL_pending)]
3450 #[must_use]
3451 pub fn pending(&self) -> usize {
3452 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3453 }
3454
3455 #[corresponds(SSL_get_servername)]
3468 #[must_use]
3469 pub fn servername(&self, type_: NameType) -> Option<&str> {
3470 self.servername_raw(type_)
3471 .and_then(|b| str::from_utf8(b).ok())
3472 }
3473
3474 #[corresponds(SSL_get_servername)]
3482 #[must_use]
3483 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3484 unsafe {
3485 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3486 if name.is_null() {
3487 None
3488 } else {
3489 Some(CStr::from_ptr(name).to_bytes())
3490 }
3491 }
3492 }
3493
3494 #[corresponds(SSL_set_SSL_CTX)]
3498 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3499 assert_eq!(
3500 self.ssl_context().has_x509_support(),
3501 ctx.has_x509_support(),
3502 "X.509 certificate support in old and new contexts doesn't match",
3503 );
3504 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3505 }
3506
3507 #[corresponds(SSL_get_SSL_CTX)]
3509 #[must_use]
3510 pub fn ssl_context(&self) -> &SslContextRef {
3511 unsafe {
3512 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3513 SslContextRef::from_ptr(ssl_ctx)
3514 }
3515 }
3516
3517 #[corresponds(SSL_get0_param)]
3519 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
3520 self.ssl_context().check_x509();
3521 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3522 }
3523
3524 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3526 self.verify_param_mut()
3527 }
3528
3529 #[corresponds(SSL_get_verify_result)]
3531 pub fn verify_result(&self) -> X509VerifyResult {
3532 self.ssl_context().check_x509();
3533 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3534 }
3535
3536 #[corresponds(SSL_get_session)]
3538 #[must_use]
3539 pub fn session(&self) -> Option<&SslSessionRef> {
3540 unsafe {
3541 let p = ffi::SSL_get_session(self.as_ptr());
3542 if p.is_null() {
3543 None
3544 } else {
3545 Some(SslSessionRef::from_ptr(p))
3546 }
3547 }
3548 }
3549
3550 #[corresponds(SSL_get_client_random)]
3555 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3556 unsafe { ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
3557 }
3558
3559 #[corresponds(SSL_get_server_random)]
3564 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3565 unsafe { ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
3566 }
3567
3568 #[corresponds(SSL_export_keying_material)]
3570 pub fn export_keying_material(
3571 &self,
3572 out: &mut [u8],
3573 label: &str,
3574 context: Option<&[u8]>,
3575 ) -> Result<(), ErrorStack> {
3576 unsafe {
3577 let (context, contextlen, use_context) = match context {
3578 Some(context) => (context.as_ptr(), context.len(), 1),
3579 None => (ptr::null(), 0, 0),
3580 };
3581 cvt(ffi::SSL_export_keying_material(
3582 self.as_ptr(),
3583 out.as_mut_ptr(),
3584 out.len(),
3585 label.as_ptr().cast::<c_char>(),
3586 label.len(),
3587 context,
3588 contextlen,
3589 use_context,
3590 ))
3591 .map(|_| ())
3592 }
3593 }
3594
3595 #[corresponds(SSL_set_session)]
3606 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3607 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr()))
3608 }
3609
3610 #[corresponds(SSL_session_reused)]
3612 #[must_use]
3613 pub fn session_reused(&self) -> bool {
3614 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3615 }
3616
3617 #[corresponds(SSL_set_tlsext_status_type)]
3619 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3620 unsafe {
3621 cvt(ffi::SSL_set_tlsext_status_type(
3622 self.as_ptr(),
3623 type_.as_raw(),
3624 ))
3625 }
3626 }
3627
3628 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3630 #[must_use]
3631 pub fn ocsp_status(&self) -> Option<&[u8]> {
3632 unsafe {
3633 let mut p = ptr::null();
3634 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3635
3636 if len == 0 {
3637 None
3638 } else {
3639 Some(slice::from_raw_parts(p, len))
3640 }
3641 }
3642 }
3643
3644 #[corresponds(SSL_set_ocsp_response)]
3646 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3647 unsafe {
3648 assert!(response.len() <= c_int::MAX as usize);
3649 cvt(ffi::SSL_set_ocsp_response(
3650 self.as_ptr(),
3651 response.as_ptr(),
3652 response.len(),
3653 ))
3654 }
3655 }
3656
3657 #[corresponds(SSL_is_server)]
3659 #[must_use]
3660 pub fn is_server(&self) -> bool {
3661 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3662 }
3663
3664 #[corresponds(SSL_set_ex_data)]
3672 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3673 if let Some(old) = self.ex_data_mut(index) {
3674 *old = data;
3675 return;
3676 }
3677
3678 unsafe {
3679 let data = Box::into_raw(Box::new(data));
3680 ffi::SSL_set_ex_data(self.as_ptr(), index.as_raw(), data.cast());
3681 }
3682 }
3683
3684 #[corresponds(SSL_set_ex_data)]
3691 pub fn replace_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) -> Option<T> {
3692 if let Some(old) = self.ex_data_mut(index) {
3693 return Some(mem::replace(old, data));
3694 }
3695
3696 self.set_ex_data(index, data);
3697
3698 None
3699 }
3700
3701 #[corresponds(SSL_get_ex_data)]
3703 #[must_use]
3704 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3705 unsafe {
3706 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3707 if data.is_null() {
3708 None
3709 } else {
3710 Some(&*(data as *const T))
3711 }
3712 }
3713 }
3714
3715 #[corresponds(SSL_get_ex_data)]
3717 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3718 unsafe {
3719 ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw())
3720 .cast::<T>()
3721 .as_mut()
3722 }
3723 }
3724
3725 #[corresponds(SSL_get_finished)]
3730 pub fn finished(&self, buf: &mut [u8]) -> usize {
3731 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) }
3732 }
3733
3734 #[corresponds(SSL_get_peer_finished)]
3740 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3741 unsafe { ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) }
3742 }
3743
3744 #[corresponds(SSL_is_init_finished)]
3746 #[must_use]
3747 pub fn is_init_finished(&self) -> bool {
3748 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3749 }
3750
3751 #[corresponds(SSL_set_mtu)]
3753 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3754 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_uint)) }
3755 }
3756
3757 #[corresponds(SSL_use_certificate)]
3759 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3760 unsafe {
3761 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3762 }
3763
3764 Ok(())
3765 }
3766
3767 #[corresponds(SSL_set_client_CA_list)]
3772 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3773 self.ssl_context().check_x509();
3774 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3775 mem::forget(list);
3776 }
3777
3778 #[corresponds(SSL_use_PrivateKey)]
3780 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
3781 where
3782 T: HasPrivate,
3783 {
3784 unsafe { cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), key.as_ptr())) }
3785 }
3786
3787 #[corresponds(SSL_set_mode)]
3790 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
3791 let bits = unsafe { ffi::SSL_set_mode(self.as_ptr(), mode.bits()) };
3792 SslMode::from_bits_retain(bits)
3793 }
3794
3795 #[corresponds(SSL_clear_mode)]
3798 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
3799 let bits = unsafe { ffi::SSL_clear_mode(self.as_ptr(), mode.bits()) };
3800 SslMode::from_bits_retain(bits)
3801 }
3802
3803 #[corresponds(SSL_add1_chain_cert)]
3805 pub fn add_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3806 unsafe { cvt(ffi::SSL_add1_chain_cert(self.as_ptr(), cert.as_ptr())) }
3807 }
3808
3809 #[corresponds(SSL_set1_ech_config_list)]
3817 pub fn set_ech_config_list(&mut self, ech_config_list: &[u8]) -> Result<(), ErrorStack> {
3818 unsafe {
3819 cvt_0i(ffi::SSL_set1_ech_config_list(
3820 self.as_ptr(),
3821 ech_config_list.as_ptr(),
3822 ech_config_list.len(),
3823 ))
3824 .map(|_| ())
3825 }
3826 }
3827
3828 #[corresponds(SSL_get0_ech_retry_configs)]
3835 #[must_use]
3836 pub fn get_ech_retry_configs(&self) -> Option<&[u8]> {
3837 unsafe {
3838 let mut data = ptr::null();
3839 let mut len: usize = 0;
3840 ffi::SSL_get0_ech_retry_configs(self.as_ptr(), &mut data, &mut len);
3841
3842 if data.is_null() {
3843 None
3844 } else {
3845 Some(slice::from_raw_parts(data, len))
3846 }
3847 }
3848 }
3849
3850 #[corresponds(SSL_get0_ech_name_override)]
3857 #[must_use]
3858 pub fn get_ech_name_override(&self) -> Option<&[u8]> {
3859 unsafe {
3860 let mut data: *const c_char = ptr::null();
3861 let mut len: usize = 0;
3862 ffi::SSL_get0_ech_name_override(self.as_ptr(), &mut data, &mut len);
3863
3864 if data.is_null() {
3865 None
3866 } else {
3867 Some(slice::from_raw_parts(data.cast::<u8>(), len))
3868 }
3869 }
3870 }
3871
3872 #[corresponds(SSL_ech_accepted)]
3874 pub fn ech_accepted(&self) -> bool {
3875 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
3876 }
3877
3878 #[corresponds(SSL_set_enable_ech_grease)]
3880 pub fn set_enable_ech_grease(&self, enable: bool) {
3881 let enable = if enable { 1 } else { 0 };
3882
3883 unsafe {
3884 ffi::SSL_set_enable_ech_grease(self.as_ptr(), enable);
3885 }
3886 }
3887
3888 #[corresponds(SSL_set_compliance_policy)]
3890 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
3891 unsafe { cvt_0i(ffi::SSL_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
3892 }
3893
3894 #[corresponds(SSL_add1_credential)]
3896 pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> {
3897 unsafe { cvt_0i(ffi::SSL_add1_credential(self.as_ptr(), credential.as_ptr())).map(|_| ()) }
3898 }
3899
3900 #[corresponds(SSL_set_alps_use_new_codepoint)]
3902 pub fn set_alps_use_new_codepoint(&mut self, use_new_codepoint: bool) {
3903 let use_new_codepoint = if use_new_codepoint { 1 } else { 0 };
3904 unsafe {
3905 ffi::SSL_set_alps_use_new_codepoint(self.as_ptr(), use_new_codepoint);
3906 }
3907 }
3908
3909 #[corresponds(SSL_add_application_settings)]
3911 pub fn add_application_settings(&mut self, alps: &[u8]) -> Result<(), ErrorStack> {
3912 unsafe {
3913 cvt_0i(ffi::SSL_add_application_settings(
3914 self.as_ptr(),
3915 alps.as_ptr(),
3916 alps.len(),
3917 ptr::null(),
3918 0,
3919 ))
3920 .map(|_| ())
3921 }
3922 }
3923}
3924
3925#[derive(Debug)]
3927pub struct MidHandshakeSslStream<S> {
3928 stream: SslStream<S>,
3929 error: Error,
3930}
3931
3932impl<S> MidHandshakeSslStream<S> {
3933 #[must_use]
3935 pub fn get_ref(&self) -> &S {
3936 self.stream.get_ref()
3937 }
3938
3939 pub fn get_mut(&mut self) -> &mut S {
3941 self.stream.get_mut()
3942 }
3943
3944 #[must_use]
3946 pub fn ssl(&self) -> &SslRef {
3947 self.stream.ssl()
3948 }
3949
3950 pub fn ssl_mut(&mut self) -> &mut SslRef {
3952 self.stream.ssl_mut()
3953 }
3954
3955 #[must_use]
3957 pub fn error(&self) -> &Error {
3958 &self.error
3959 }
3960
3961 #[must_use]
3963 pub fn into_error(self) -> Error {
3964 self.error
3965 }
3966
3967 #[must_use]
3969 pub fn into_source_stream(self) -> S {
3970 self.stream.into_inner()
3971 }
3972
3973 pub fn into_parts(self) -> (Error, S) {
3975 (self.error, self.stream.into_inner())
3976 }
3977
3978 #[corresponds(SSL_do_handshake)]
3980 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3981 let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) };
3982 if ret > 0 {
3983 Ok(self.stream)
3984 } else {
3985 self.error = self.stream.make_error(ret);
3986 Err(if self.error.would_block() {
3987 HandshakeError::WouldBlock(self)
3988 } else {
3989 HandshakeError::Failure(self)
3990 })
3991 }
3992 }
3993}
3994
3995pub struct SslStream<S> {
3997 ssl: ManuallyDrop<Ssl>,
3998 method: ManuallyDrop<BioMethod>,
3999 _p: PhantomData<S>,
4000}
4001
4002impl<S> Drop for SslStream<S> {
4003 fn drop(&mut self) {
4004 unsafe {
4006 ManuallyDrop::drop(&mut self.ssl);
4007 ManuallyDrop::drop(&mut self.method);
4008 }
4009 }
4010}
4011
4012impl<S> fmt::Debug for SslStream<S>
4013where
4014 S: fmt::Debug,
4015{
4016 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
4017 fmt.debug_struct("SslStream")
4018 .field("stream", &self.get_ref())
4019 .field("ssl", &self.ssl())
4020 .finish()
4021 }
4022}
4023
4024impl<S: Read + Write> SslStream<S> {
4025 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4031 let (bio, method) = bio::new(stream)?;
4032
4033 unsafe {
4034 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4035 }
4036
4037 Ok(SslStream {
4038 ssl: ManuallyDrop::new(ssl),
4039 method: ManuallyDrop::new(method),
4040 _p: PhantomData,
4041 })
4042 }
4043
4044 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
4052 let ssl = Ssl::from_ptr(ssl);
4053 Self::new(ssl, stream).unwrap()
4054 }
4055
4056 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4063 loop {
4064 match self.ssl_read_uninit(buf) {
4065 Ok(n) => return Ok(n),
4066 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4067 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4068 return Ok(0);
4069 }
4070 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4071 Err(e) => {
4072 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4073 }
4074 }
4075 }
4076 }
4077
4078 #[corresponds(SSL_read)]
4083 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4084 unsafe {
4086 self.ssl_read_uninit(slice::from_raw_parts_mut(
4087 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4088 buf.len(),
4089 ))
4090 }
4091 }
4092
4093 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4100 if buf.is_empty() {
4101 return Ok(0);
4102 }
4103
4104 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4105 let ret = unsafe { ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) };
4106 if ret > 0 {
4107 Ok(ret as usize)
4108 } else {
4109 Err(self.make_error(ret))
4110 }
4111 }
4112
4113 #[corresponds(SSL_write)]
4118 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4119 if buf.is_empty() {
4120 return Ok(0);
4121 }
4122
4123 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4124 let ret = unsafe { ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) };
4125 if ret > 0 {
4126 Ok(ret as usize)
4127 } else {
4128 Err(self.make_error(ret))
4129 }
4130 }
4131
4132 #[corresponds(SSL_shutdown)]
4142 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4143 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4144 0 => Ok(ShutdownResult::Sent),
4145 1 => Ok(ShutdownResult::Received),
4146 n => Err(self.make_error(n)),
4147 }
4148 }
4149
4150 #[corresponds(SSL_get_shutdown)]
4152 pub fn get_shutdown(&mut self) -> ShutdownState {
4153 unsafe {
4154 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4155 ShutdownState::from_bits_retain(bits)
4156 }
4157 }
4158
4159 #[corresponds(SSL_set_shutdown)]
4164 pub fn set_shutdown(&mut self, state: ShutdownState) {
4165 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4166 }
4167
4168 #[corresponds(SSL_connect)]
4170 pub fn connect(&mut self) -> Result<(), Error> {
4171 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4172 if ret > 0 {
4173 Ok(())
4174 } else {
4175 Err(self.make_error(ret))
4176 }
4177 }
4178
4179 #[corresponds(SSL_accept)]
4181 pub fn accept(&mut self) -> Result<(), Error> {
4182 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4183 if ret > 0 {
4184 Ok(())
4185 } else {
4186 Err(self.make_error(ret))
4187 }
4188 }
4189
4190 #[corresponds(SSL_do_handshake)]
4192 pub fn do_handshake(&mut self) -> Result<(), Error> {
4193 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4194 if ret > 0 {
4195 Ok(())
4196 } else {
4197 Err(self.make_error(ret))
4198 }
4199 }
4200}
4201
4202impl<S> SslStream<S> {
4203 fn make_error(&mut self, ret: c_int) -> Error {
4204 self.check_panic();
4205
4206 let code = self.ssl.error_code(ret);
4207
4208 let cause = match code {
4209 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4210 ErrorCode::SYSCALL => {
4211 let errs = ErrorStack::get();
4212 if errs.errors().is_empty() {
4213 self.get_bio_error().map(InnerError::Io)
4214 } else {
4215 Some(InnerError::Ssl(errs))
4216 }
4217 }
4218 ErrorCode::ZERO_RETURN => None,
4219 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4220 self.get_bio_error().map(InnerError::Io)
4221 }
4222 _ => None,
4223 };
4224
4225 Error { code, cause }
4226 }
4227
4228 fn check_panic(&mut self) {
4229 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4230 resume_unwind(err)
4231 }
4232 }
4233
4234 fn get_bio_error(&mut self) -> Option<io::Error> {
4235 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4236 }
4237
4238 #[must_use]
4240 pub fn into_inner(self) -> S {
4241 unsafe { bio::take_stream::<S>(self.ssl.get_raw_rbio()) }
4242 }
4243
4244 #[must_use]
4246 pub fn get_ref(&self) -> &S {
4247 unsafe {
4248 let bio = self.ssl.get_raw_rbio();
4249 bio::get_ref(bio)
4250 }
4251 }
4252
4253 pub fn get_mut(&mut self) -> &mut S {
4260 unsafe {
4261 let bio = self.ssl.get_raw_rbio();
4262 bio::get_mut(bio)
4263 }
4264 }
4265
4266 #[must_use]
4268 pub fn ssl(&self) -> &SslRef {
4269 &self.ssl
4270 }
4271
4272 pub fn ssl_mut(&mut self) -> &mut SslRef {
4274 &mut self.ssl
4275 }
4276}
4277
4278impl<S: Read + Write> Read for SslStream<S> {
4279 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4280 unsafe {
4282 self.read_uninit(slice::from_raw_parts_mut(
4283 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4284 buf.len(),
4285 ))
4286 }
4287 }
4288}
4289
4290impl<S: Read + Write> Write for SslStream<S> {
4291 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4292 loop {
4293 match self.ssl_write(buf) {
4294 Ok(n) => return Ok(n),
4295 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4296 Err(e) => {
4297 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4298 }
4299 }
4300 }
4301 }
4302
4303 fn flush(&mut self) -> io::Result<()> {
4304 self.get_mut().flush()
4305 }
4306}
4307
4308pub struct SslStreamBuilder<S> {
4310 inner: SslStream<S>,
4311}
4312
4313impl<S> SslStreamBuilder<S>
4314where
4315 S: Read + Write,
4316{
4317 pub fn new(ssl: Ssl, stream: S) -> Self {
4319 Self {
4320 inner: SslStream::new(ssl, stream).unwrap(),
4321 }
4322 }
4323
4324 #[corresponds(SSL_set_connect_state)]
4326 pub fn set_connect_state(&mut self) {
4327 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4328 }
4329
4330 #[corresponds(SSL_set_accept_state)]
4332 pub fn set_accept_state(&mut self) {
4333 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4334 }
4335
4336 #[must_use]
4342 pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
4343 self.set_connect_state();
4344
4345 MidHandshakeSslStream {
4346 stream: self.inner,
4347 error: Error {
4348 code: ErrorCode::WANT_WRITE,
4349 cause: Some(InnerError::Io(io::Error::new(
4350 io::ErrorKind::WouldBlock,
4351 "connect handshake has not started yet",
4352 ))),
4353 },
4354 }
4355 }
4356
4357 pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
4362 self.setup_connect().handshake()
4363 }
4364
4365 #[must_use]
4371 pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
4372 self.set_accept_state();
4373
4374 MidHandshakeSslStream {
4375 stream: self.inner,
4376 error: Error {
4377 code: ErrorCode::WANT_READ,
4378 cause: Some(InnerError::Io(io::Error::new(
4379 io::ErrorKind::WouldBlock,
4380 "accept handshake has not started yet",
4381 ))),
4382 },
4383 }
4384 }
4385
4386 pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
4391 self.setup_accept().handshake()
4392 }
4393
4394 #[corresponds(SSL_do_handshake)]
4398 pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
4399 let mut stream = self.inner;
4400 let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
4401 if ret > 0 {
4402 Ok(stream)
4403 } else {
4404 let error = stream.make_error(ret);
4405 Err(if error.would_block() {
4406 HandshakeError::WouldBlock(MidHandshakeSslStream { stream, error })
4407 } else {
4408 HandshakeError::Failure(MidHandshakeSslStream { stream, error })
4409 })
4410 }
4411 }
4412}
4413
4414impl<S> SslStreamBuilder<S> {
4415 #[must_use]
4417 pub fn get_ref(&self) -> &S {
4418 unsafe {
4419 let bio = self.inner.ssl.get_raw_rbio();
4420 bio::get_ref(bio)
4421 }
4422 }
4423
4424 pub fn get_mut(&mut self) -> &mut S {
4431 unsafe {
4432 let bio = self.inner.ssl.get_raw_rbio();
4433 bio::get_mut(bio)
4434 }
4435 }
4436
4437 #[must_use]
4439 pub fn ssl(&self) -> &SslRef {
4440 &self.inner.ssl
4441 }
4442
4443 pub fn ssl_mut(&mut self) -> &mut SslRef {
4445 &mut self.inner.ssl
4446 }
4447
4448 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4456 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4457 unsafe {
4458 let bio = self.inner.ssl.get_raw_rbio();
4459 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4460 }
4461 }
4462}
4463
4464#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4466pub enum ShutdownResult {
4467 Sent,
4469
4470 Received,
4472}
4473
4474bitflags! {
4475 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
4477 pub struct ShutdownState: c_int {
4478 const SENT = ffi::SSL_SENT_SHUTDOWN;
4480 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4482 }
4483}
4484
4485pub trait PrivateKeyMethod: Send + Sync + 'static {
4493 fn sign(
4504 &self,
4505 ssl: &mut SslRef,
4506 input: &[u8],
4507 signature_algorithm: SslSignatureAlgorithm,
4508 output: &mut [u8],
4509 ) -> Result<usize, PrivateKeyMethodError>;
4510
4511 fn decrypt(
4526 &self,
4527 ssl: &mut SslRef,
4528 input: &[u8],
4529 output: &mut [u8],
4530 ) -> Result<usize, PrivateKeyMethodError>;
4531
4532 fn complete(&self, ssl: &mut SslRef, output: &mut [u8])
4541 -> Result<usize, PrivateKeyMethodError>;
4542}
4543
4544#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4546pub struct PrivateKeyMethodError(ffi::ssl_private_key_result_t);
4547
4548impl PrivateKeyMethodError {
4549 pub const FAILURE: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_failure);
4551
4552 pub const RETRY: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_retry);
4554}
4555
4556pub trait CertificateCompressor: Send + Sync + 'static {
4558 const ALGORITHM: CertificateCompressionAlgorithm;
4560
4561 const CAN_COMPRESS: bool;
4563
4564 const CAN_DECOMPRESS: bool;
4566
4567 #[allow(unused_variables)]
4569 fn compress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4570 where
4571 W: std::io::Write,
4572 {
4573 Err(std::io::Error::other("not implemented"))
4574 }
4575
4576 #[allow(unused_variables)]
4578 fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4579 where
4580 W: std::io::Write,
4581 {
4582 Err(std::io::Error::other("not implemented"))
4583 }
4584}
4585
4586use crate::ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4587
4588unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4589 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4590}
4591
4592unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4593 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4594}
4595
4596fn path_to_cstring(path: &Path) -> Result<CString, ErrorStack> {
4597 CString::new(path.as_os_str().as_encoded_bytes()).map_err(ErrorStack::internal_error)
4598}