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)]
1568 pub fn set_raw_cipher_list(&mut self, cipher_list: &[u16]) -> Result<(), ErrorStack> {
1569 unsafe {
1570 cvt(ffi::RAMA_SSL_CTX_set_raw_cipher_list(
1571 self.as_ptr(),
1572 cipher_list.as_ptr() as *const _,
1573 cipher_list.len() as i32,
1574 ))
1575 }
1576 }
1577
1578 #[corresponds(SSL_CTX_get_ciphers)]
1584 #[must_use]
1585 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
1586 self.ctx.ciphers()
1587 }
1588
1589 #[corresponds(SSL_CTX_set_options)]
1596 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1597 let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
1598 SslOptions::from_bits_retain(bits)
1599 }
1600
1601 #[corresponds(SSL_CTX_get_options)]
1603 #[must_use]
1604 pub fn options(&self) -> SslOptions {
1605 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
1606 SslOptions::from_bits_retain(bits)
1607 }
1608
1609 #[corresponds(SSL_CTX_clear_options)]
1611 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1612 let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
1613 SslOptions::from_bits_retain(bits)
1614 }
1615
1616 #[corresponds(SSL_CTX_set_min_proto_version)]
1621 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1622 unsafe {
1623 cvt(ffi::SSL_CTX_set_min_proto_version(
1624 self.as_ptr(),
1625 version.map_or(0, |v| v.0 as _),
1626 ))
1627 }
1628 }
1629
1630 #[corresponds(SSL_CTX_set_max_proto_version)]
1634 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1635 unsafe {
1636 cvt(ffi::SSL_CTX_set_max_proto_version(
1637 self.as_ptr(),
1638 version.map_or(0, |v| v.0 as _),
1639 ))
1640 .map(|_| ())
1641 }
1642 }
1643
1644 #[corresponds(SSL_CTX_get_min_proto_version)]
1646 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1647 unsafe {
1648 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1649 if r == 0 {
1650 None
1651 } else {
1652 Some(SslVersion(r))
1653 }
1654 }
1655 }
1656
1657 #[corresponds(SSL_CTX_get_max_proto_version)]
1659 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1660 unsafe {
1661 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1662 if r == 0 {
1663 None
1664 } else {
1665 Some(SslVersion(r))
1666 }
1667 }
1668 }
1669
1670 #[corresponds(SSL_CTX_set_alpn_protos)]
1677 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1678 unsafe {
1679 let r = ffi::SSL_CTX_set_alpn_protos(
1680 self.as_ptr(),
1681 protocols.as_ptr(),
1682 try_int(protocols.len())?,
1683 );
1684 if r == 0 {
1686 Ok(())
1687 } else {
1688 Err(ErrorStack::get())
1689 }
1690 }
1691 }
1692
1693 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1695 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1696 unsafe {
1697 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
1698
1699 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1700 if r == 0 {
1702 Ok(())
1703 } else {
1704 Err(ErrorStack::get())
1705 }
1706 }
1707 }
1708
1709 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1720 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1721 where
1722 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1723 {
1724 unsafe {
1725 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1726 ffi::SSL_CTX_set_alpn_select_cb(
1727 self.as_ptr(),
1728 Some(callbacks::raw_alpn_select::<F>),
1729 ptr::null_mut(),
1730 );
1731 }
1732 }
1733
1734 #[corresponds(SSL_CTX_set_select_certificate_cb)]
1738 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
1739 where
1740 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
1741 {
1742 unsafe {
1743 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1744 ffi::SSL_CTX_set_select_certificate_cb(
1745 self.as_ptr(),
1746 Some(callbacks::raw_select_cert::<F>),
1747 );
1748 }
1749 }
1750
1751 #[corresponds(SSL_CTX_add_cert_compression_alg)]
1755 pub fn add_certificate_compression_algorithm<C>(
1756 &mut self,
1757 compressor: C,
1758 ) -> Result<(), ErrorStack>
1759 where
1760 C: CertificateCompressor,
1761 {
1762 const {
1763 assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered");
1764 };
1765 let success = unsafe {
1766 ffi::SSL_CTX_add_cert_compression_alg(
1767 self.as_ptr(),
1768 C::ALGORITHM.0,
1769 const {
1770 if C::CAN_COMPRESS {
1771 Some(callbacks::raw_ssl_cert_compress::<C>)
1772 } else {
1773 None
1774 }
1775 },
1776 const {
1777 if C::CAN_DECOMPRESS {
1778 Some(callbacks::raw_ssl_cert_decompress::<C>)
1779 } else {
1780 None
1781 }
1782 },
1783 ) == 1
1784 };
1785 if !success {
1786 return Err(ErrorStack::get());
1787 }
1788 self.replace_ex_data(SslContext::cached_ex_index::<C>(), compressor);
1789 Ok(())
1790 }
1791
1792 #[corresponds(SSL_CTX_set_private_key_method)]
1796 pub fn set_private_key_method<M>(&mut self, method: M)
1797 where
1798 M: PrivateKeyMethod,
1799 {
1800 unsafe {
1801 self.replace_ex_data(SslContext::cached_ex_index::<M>(), method);
1802
1803 ffi::SSL_CTX_set_private_key_method(
1804 self.as_ptr(),
1805 &ffi::SSL_PRIVATE_KEY_METHOD {
1806 sign: Some(callbacks::raw_sign::<M>),
1807 decrypt: Some(callbacks::raw_decrypt::<M>),
1808 complete: Some(callbacks::raw_complete::<M>),
1809 },
1810 );
1811 }
1812 }
1813
1814 #[corresponds(SSL_CTX_check_private_key)]
1816 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1817 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())) }
1818 }
1819
1820 #[corresponds(SSL_CTX_get_cert_store)]
1822 #[must_use]
1823 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1824 self.ctx.check_x509();
1825 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1826 }
1827
1828 #[corresponds(SSL_CTX_get_cert_store)]
1836 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1837 self.ctx.check_x509();
1838 assert!(
1839 !self.has_shared_cert_store,
1840 "Shared X509Store can't be mutated. Use set_cert_store_builder() instead of set_cert_store()
1841 or completely finish building the cert store setting it."
1842 );
1843 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1846 }
1847
1848 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1861 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1862 where
1863 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1864 {
1865 unsafe {
1866 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1867 cvt(ffi::SSL_CTX_set_tlsext_status_cb(
1868 self.as_ptr(),
1869 Some(raw_tlsext_status::<F>),
1870 ))
1871 }
1872 }
1873
1874 #[corresponds(SSL_CTX_set_psk_client_callback)]
1880 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1881 where
1882 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1883 + 'static
1884 + Sync
1885 + Send,
1886 {
1887 unsafe {
1888 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1889 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1890 }
1891 }
1892
1893 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1894 pub fn set_psk_callback<F>(&mut self, callback: F)
1895 where
1896 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1897 + 'static
1898 + Sync
1899 + Send,
1900 {
1901 self.set_psk_client_callback(callback);
1902 }
1903
1904 #[corresponds(SSL_CTX_set_psk_server_callback)]
1910 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1911 where
1912 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1913 + 'static
1914 + Sync
1915 + Send,
1916 {
1917 unsafe {
1918 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1919 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1920 }
1921 }
1922
1923 #[corresponds(SSL_CTX_sess_set_new_cb)]
1937 pub fn set_new_session_callback<F>(&mut self, callback: F)
1938 where
1939 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1940 {
1941 unsafe {
1942 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1943 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1944 }
1945 }
1946
1947 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1951 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1952 where
1953 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1954 {
1955 unsafe {
1956 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1957 ffi::SSL_CTX_sess_set_remove_cb(
1958 self.as_ptr(),
1959 Some(callbacks::raw_remove_session::<F>),
1960 );
1961 }
1962 }
1963
1964 #[corresponds(SSL_CTX_sess_set_get_cb)]
1975 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1976 where
1977 F: Fn(&mut SslRef, &[u8]) -> Result<Option<SslSession>, GetSessionPendingError>
1978 + 'static
1979 + Sync
1980 + Send,
1981 {
1982 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1983 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1984 }
1985
1986 #[corresponds(SSL_CTX_set_keylog_callback)]
1992 pub fn set_keylog_callback<F>(&mut self, callback: F)
1993 where
1994 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1995 {
1996 unsafe {
1997 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1998 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1999 }
2000 }
2001
2002 #[corresponds(SSL_CTX_set_session_cache_mode)]
2006 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
2007 unsafe {
2008 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
2009 SslSessionCacheMode::from_bits_retain(bits)
2010 }
2011 }
2012
2013 #[corresponds(SSL_CTX_set_ex_data)]
2018 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2019 unsafe {
2020 self.ctx.replace_ex_data(index, data);
2021 }
2022 }
2023
2024 #[corresponds(SSL_CTX_set_ex_data)]
2031 pub fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2032 unsafe { self.ctx.replace_ex_data(index, data) }
2033 }
2034
2035 #[corresponds(SSL_CTX_sess_set_cache_size)]
2039 #[allow(clippy::useless_conversion)]
2040 pub fn set_session_cache_size(&mut self, size: u32) -> u64 {
2041 unsafe { ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size.into()).into() }
2042 }
2043
2044 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2046 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2047 let sigalgs = CString::new(sigalgs).map_err(ErrorStack::internal_error)?;
2048 unsafe {
2049 cvt(ffi::SSL_CTX_set1_sigalgs_list(
2050 self.as_ptr(),
2051 sigalgs.as_ptr(),
2052 ))
2053 }
2054 }
2055
2056 #[corresponds(SSL_CTX_set_grease_enabled)]
2058 pub fn set_grease_enabled(&mut self, enabled: bool) {
2059 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as _) }
2060 }
2061
2062 #[corresponds(SSL_CTX_set_permute_extensions)]
2064 pub fn set_permute_extensions(&mut self, enabled: bool) {
2065 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as _) }
2066 }
2067
2068 #[corresponds(RAMA_SSL_CTX_set_extension_order)]
2070 pub fn set_extension_order(&mut self, ids: &[u16]) -> Result<(), ErrorStack> {
2071 unsafe {
2072 cvt(ffi::RAMA_SSL_CTX_set_extension_order(
2073 self.as_ptr(),
2074 ids.as_ptr() as *const _,
2075 ids.len() as i32,
2076 ))
2077 .map(|_| ())
2078 }
2079 }
2080
2081 #[corresponds(SSL_CTX_set_verify_algorithm_prefs)]
2083 pub fn set_verify_algorithm_prefs(
2084 &mut self,
2085 prefs: &[SslSignatureAlgorithm],
2086 ) -> Result<(), ErrorStack> {
2087 unsafe {
2088 cvt_0i(ffi::SSL_CTX_set_verify_algorithm_prefs(
2089 self.as_ptr(),
2090 prefs.as_ptr().cast(),
2091 prefs.len(),
2092 ))
2093 .map(|_| ())
2094 }
2095 }
2096
2097 #[corresponds(SSL_CTX_enable_signed_cert_timestamps)]
2099 pub fn enable_signed_cert_timestamps(&mut self) {
2100 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
2101 }
2102
2103 #[corresponds(SSL_CTX_enable_ocsp_stapling)]
2105 pub fn enable_ocsp_stapling(&mut self) {
2106 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
2107 }
2108
2109 #[corresponds(SSL_CTX_set1_curves_list)]
2115 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2116 let curves = CString::new(curves).unwrap();
2117 unsafe {
2118 cvt_0i(ffi::SSL_CTX_set1_curves_list(
2119 self.as_ptr(),
2120 curves.as_ptr(),
2121 ))
2122 .map(|_| ())
2123 }
2124 }
2125
2126 #[corresponds(SSL_CTX_set1_curves)]
2132 pub fn set_curves(&mut self, curves: &[SslCurve]) -> Result<(), ErrorStack> {
2133 let curves: Vec<i32> = curves.iter().filter_map(|curve| curve.nid()).collect();
2134
2135 unsafe {
2136 cvt_0i(ffi::SSL_CTX_set1_curves(
2137 self.as_ptr(),
2138 curves.as_ptr() as *const _,
2139 curves.len(),
2140 ))
2141 .map(|_| ())
2142 }
2143 }
2144
2145 #[corresponds(SSL_CTX_set_compliance_policy)]
2149 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
2150 unsafe { cvt_0i(ffi::SSL_CTX_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
2151 }
2152
2153 #[corresponds(SSL_CTX_set_info_callback)]
2155 pub fn set_info_callback<F>(&mut self, callback: F)
2156 where
2157 F: Fn(&SslRef, SslInfoCallbackMode, SslInfoCallbackValue) + Send + Sync + 'static,
2158 {
2159 unsafe {
2160 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
2161 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info_callback::<F>));
2162 }
2163 }
2164
2165 #[corresponds(SSL_CTX_set1_ech_keys)]
2170 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2171 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())) }
2172 }
2173
2174 #[corresponds(SSL_CTX_add1_credential)]
2176 pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> {
2177 unsafe {
2178 cvt_0i(ffi::SSL_CTX_add1_credential(
2179 self.as_ptr(),
2180 credential.as_ptr(),
2181 ))
2182 .map(|_| ())
2183 }
2184 }
2185
2186 #[must_use]
2188 pub fn build(self) -> SslContext {
2189 self.ctx
2190 }
2191}
2192
2193foreign_type_and_impl_send_sync! {
2194 type CType = ffi::SSL_CTX;
2195 fn drop = ffi::SSL_CTX_free;
2196
2197 pub struct SslContext;
2202}
2203
2204impl Clone for SslContext {
2205 fn clone(&self) -> Self {
2206 (**self).to_owned()
2207 }
2208}
2209
2210impl ToOwned for SslContextRef {
2211 type Owned = SslContext;
2212
2213 fn to_owned(&self) -> Self::Owned {
2214 unsafe {
2215 SSL_CTX_up_ref(self.as_ptr());
2216 SslContext::from_ptr(self.as_ptr())
2217 }
2218 }
2219}
2220
2221impl fmt::Debug for SslContext {
2223 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2224 write!(fmt, "SslContext")
2225 }
2226}
2227
2228impl SslContext {
2229 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2231 SslContextBuilder::new(method)
2232 }
2233
2234 #[corresponds(SSL_CTX_get_ex_new_index)]
2239 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2240 where
2241 T: 'static + Sync + Send,
2242 {
2243 unsafe {
2244 ffi::init();
2245 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2246 Ok(Index::from_raw(idx))
2247 }
2248 }
2249
2250 fn cached_ex_index<T>() -> Index<SslContext, T>
2252 where
2253 T: 'static + Sync + Send,
2254 {
2255 unsafe {
2256 let idx = *INDEXES
2257 .lock()
2258 .unwrap_or_else(|e| e.into_inner())
2259 .entry(TypeId::of::<T>())
2260 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2261 Index::from_raw(idx)
2262 }
2263 }
2264
2265 #[corresponds(SSL_CTX_get_ciphers)]
2271 #[must_use]
2272 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
2273 unsafe {
2274 let ciphers = ffi::SSL_CTX_get_ciphers(self.as_ptr());
2275 if ciphers.is_null() {
2276 None
2277 } else {
2278 Some(StackRef::from_ptr(ciphers))
2279 }
2280 }
2281 }
2282}
2283
2284impl SslContextRef {
2285 #[corresponds(SSL_CTX_get0_certificate)]
2287 #[must_use]
2288 pub fn certificate(&self) -> Option<&X509Ref> {
2289 self.check_x509();
2290 unsafe {
2291 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2292 if ptr.is_null() {
2293 None
2294 } else {
2295 Some(X509Ref::from_ptr(ptr))
2296 }
2297 }
2298 }
2299
2300 #[corresponds(SSL_CTX_get0_privatekey)]
2302 #[must_use]
2303 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2304 unsafe {
2305 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2306 if ptr.is_null() {
2307 None
2308 } else {
2309 Some(PKeyRef::from_ptr(ptr))
2310 }
2311 }
2312 }
2313
2314 #[corresponds(SSL_CTX_get_cert_store)]
2316 #[must_use]
2317 pub fn cert_store(&self) -> &X509StoreRef {
2318 self.check_x509();
2319 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2320 }
2321
2322 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2324 #[must_use]
2325 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2326 unsafe {
2327 let mut chain = ptr::null_mut();
2328 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2329 assert!(!chain.is_null());
2330 StackRef::from_ptr(chain)
2331 }
2332 }
2333
2334 #[corresponds(SSL_CTX_get_ex_data)]
2336 #[must_use]
2337 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2338 unsafe {
2339 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2340 if data.is_null() {
2341 None
2342 } else {
2343 Some(&*(data as *const T))
2344 }
2345 }
2346 }
2347
2348 #[corresponds(SSL_CTX_get_ex_data)]
2351 unsafe fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2352 ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw())
2353 .cast::<T>()
2354 .as_mut()
2355 }
2356
2357 #[corresponds(SSL_CTX_set_ex_data)]
2360 unsafe fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2361 unsafe {
2362 let data = Box::into_raw(Box::new(data));
2363 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data.cast());
2364 }
2365 }
2366
2367 #[corresponds(SSL_CTX_set_ex_data)]
2370 unsafe fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2371 if let Some(old) = self.ex_data_mut(index) {
2372 return Some(mem::replace(old, data));
2373 }
2374
2375 self.set_ex_data(index, data);
2376
2377 None
2378 }
2379
2380 #[corresponds(SSL_CTX_add_session)]
2389 #[must_use]
2390 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2391 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2392 }
2393
2394 #[corresponds(SSL_CTX_remove_session)]
2403 #[must_use]
2404 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2405 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2406 }
2407
2408 #[corresponds(SSL_CTX_sess_get_cache_size)]
2412 #[allow(clippy::useless_conversion)]
2413 #[must_use]
2414 pub fn session_cache_size(&self) -> u64 {
2415 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()).into() }
2416 }
2417
2418 #[corresponds(SSL_CTX_get_verify_mode)]
2422 #[must_use]
2423 pub fn verify_mode(&self) -> SslVerifyMode {
2424 self.check_x509();
2425 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2426 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2427 }
2428
2429 pub unsafe fn assume_x509(&mut self) {
2437 self.replace_ex_data(*X509_FLAG_INDEX, true);
2438 }
2439
2440 #[must_use]
2442 pub fn has_x509_support(&self) -> bool {
2443 self.ex_data(*X509_FLAG_INDEX).copied().unwrap_or_default()
2444 }
2445
2446 #[track_caller]
2447 fn check_x509(&self) {
2448 assert!(
2449 self.has_x509_support(),
2450 "This context is not configured for X.509 certificates"
2451 );
2452 }
2453
2454 #[corresponds(SSL_CTX_set1_ech_keys)]
2459 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2460 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())) }
2461 }
2462}
2463
2464#[derive(Debug)]
2469pub struct GetSessionPendingError;
2470
2471pub struct CipherBits {
2473 pub secret: i32,
2475
2476 pub algorithm: i32,
2478}
2479
2480#[repr(transparent)]
2481pub struct ClientHello<'ssl>(&'ssl ffi::SSL_CLIENT_HELLO);
2482
2483impl ClientHello<'_> {
2484 #[corresponds(SSL_early_callback_ctx_extension_get)]
2486 #[must_use]
2487 pub fn get_extension(&self, ext_type: ExtensionType) -> Option<&[u8]> {
2488 unsafe {
2489 let mut ptr = ptr::null();
2490 let mut len = 0;
2491 let result =
2492 ffi::SSL_early_callback_ctx_extension_get(self.0, ext_type.0, &mut ptr, &mut len);
2493 if result == 0 {
2494 return None;
2495 }
2496 Some(slice::from_raw_parts(ptr, len))
2497 }
2498 }
2499
2500 #[must_use]
2501 pub fn ssl_mut(&mut self) -> &mut SslRef {
2502 unsafe { SslRef::from_ptr_mut(self.0.ssl) }
2503 }
2504
2505 #[must_use]
2506 pub fn ssl(&self) -> &SslRef {
2507 unsafe { SslRef::from_ptr(self.0.ssl) }
2508 }
2509
2510 pub fn servername(&self, type_: NameType) -> Option<&str> {
2512 self.ssl().servername(type_)
2513 }
2514
2515 #[must_use]
2517 pub fn client_version(&self) -> SslVersion {
2518 SslVersion(self.0.version)
2519 }
2520
2521 #[must_use]
2523 pub fn version_str(&self) -> &'static str {
2524 self.ssl().version_str()
2525 }
2526
2527 pub fn as_bytes(&self) -> &[u8] {
2529 unsafe { slice::from_raw_parts(self.0.client_hello, self.0.client_hello_len) }
2530 }
2531
2532 #[must_use]
2534 pub fn random(&self) -> &[u8] {
2535 unsafe { slice::from_raw_parts(self.0.random, self.0.random_len) }
2536 }
2537
2538 #[must_use]
2540 pub fn ciphers(&self) -> &[u8] {
2541 unsafe { slice::from_raw_parts(self.0.cipher_suites, self.0.cipher_suites_len) }
2542 }
2543}
2544
2545#[derive(Clone, Copy)]
2547pub struct SslCipher(&'static SslCipherRef);
2548
2549impl SslCipher {
2550 #[corresponds(SSL_get_cipher_by_value)]
2551 #[must_use]
2552 pub fn from_value(value: u16) -> Option<Self> {
2553 unsafe {
2554 let ptr = ffi::SSL_get_cipher_by_value(value);
2555 if ptr.is_null() {
2556 None
2557 } else {
2558 Some(Self::from_ptr(ptr.cast_mut()))
2559 }
2560 }
2561 }
2562}
2563
2564impl Stackable for SslCipher {
2565 type StackType = ffi::stack_st_SSL_CIPHER;
2566}
2567
2568unsafe impl ForeignType for SslCipher {
2569 type CType = ffi::SSL_CIPHER;
2570 type Ref = SslCipherRef;
2571
2572 #[inline]
2573 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2574 SslCipher(SslCipherRef::from_ptr(ptr))
2575 }
2576
2577 #[inline]
2578 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2579 self.0.as_ptr()
2580 }
2581}
2582
2583impl Deref for SslCipher {
2584 type Target = SslCipherRef;
2585
2586 fn deref(&self) -> &SslCipherRef {
2587 self.0
2588 }
2589}
2590
2591pub struct SslCipherRef(Opaque);
2595
2596unsafe impl Send for SslCipherRef {}
2597unsafe impl Sync for SslCipherRef {}
2598
2599unsafe impl ForeignTypeRef for SslCipherRef {
2600 type CType = ffi::SSL_CIPHER;
2601}
2602
2603impl SslCipherRef {
2604 #[corresponds(SSL_CIPHER_get_protocol_id)]
2606 #[must_use]
2607 pub fn protocol_id(&self) -> u16 {
2608 unsafe { ffi::SSL_CIPHER_get_protocol_id(self.as_ptr()) }
2609 }
2610
2611 #[corresponds(SSL_CIPHER_get_name)]
2613 #[must_use]
2614 pub fn name(&self) -> &'static str {
2615 unsafe {
2616 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2617 CStr::from_ptr(ptr).to_str().unwrap()
2618 }
2619 }
2620
2621 #[corresponds(SSL_CIPHER_standard_name)]
2623 #[must_use]
2624 pub fn standard_name(&self) -> Option<&'static str> {
2625 unsafe {
2626 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2627 if ptr.is_null() {
2628 None
2629 } else {
2630 Some(CStr::from_ptr(ptr).to_str().unwrap())
2631 }
2632 }
2633 }
2634
2635 #[corresponds(SSL_CIPHER_get_version)]
2637 #[must_use]
2638 pub fn version(&self) -> &'static str {
2639 let version = unsafe {
2640 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2641 CStr::from_ptr(ptr)
2642 };
2643
2644 str::from_utf8(version.to_bytes()).unwrap()
2645 }
2646
2647 #[corresponds(SSL_CIPHER_get_bits)]
2649 #[allow(clippy::useless_conversion)]
2650 #[must_use]
2651 pub fn bits(&self) -> CipherBits {
2652 unsafe {
2653 let mut algo_bits = 0;
2654 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2655 CipherBits {
2656 secret: secret_bits.into(),
2657 algorithm: algo_bits.into(),
2658 }
2659 }
2660 }
2661
2662 #[corresponds(SSL_CIPHER_description)]
2664 #[must_use]
2665 pub fn description(&self) -> String {
2666 unsafe {
2667 let mut buf = [0; 128];
2669 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2670 CStr::from_ptr(ptr).to_string_lossy().into_owned()
2671 }
2672 }
2673
2674 #[corresponds(SSL_CIPHER_is_aead)]
2676 #[must_use]
2677 pub fn cipher_is_aead(&self) -> bool {
2678 unsafe { ffi::SSL_CIPHER_is_aead(self.as_ptr()) != 0 }
2679 }
2680
2681 #[corresponds(SSL_CIPHER_get_auth_nid)]
2683 #[must_use]
2684 pub fn cipher_auth_nid(&self) -> Option<Nid> {
2685 let n = unsafe { ffi::SSL_CIPHER_get_auth_nid(self.as_ptr()) };
2686 if n == 0 {
2687 None
2688 } else {
2689 Some(Nid::from_raw(n))
2690 }
2691 }
2692
2693 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2695 #[must_use]
2696 pub fn cipher_nid(&self) -> Option<Nid> {
2697 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2698 if n == 0 {
2699 None
2700 } else {
2701 Some(Nid::from_raw(n))
2702 }
2703 }
2704}
2705
2706foreign_type_and_impl_send_sync! {
2707 type CType = ffi::SSL_SESSION;
2708 fn drop = ffi::SSL_SESSION_free;
2709
2710 pub struct SslSession;
2714}
2715
2716impl Clone for SslSession {
2717 fn clone(&self) -> SslSession {
2718 SslSessionRef::to_owned(self)
2719 }
2720}
2721
2722impl SslSession {
2723 from_der! {
2724 #[corresponds(d2i_SSL_SESSION)]
2726 from_der,
2727 SslSession,
2728 ffi::d2i_SSL_SESSION,
2729 crate::libc_types::c_long
2730 }
2731}
2732
2733impl ToOwned for SslSessionRef {
2734 type Owned = SslSession;
2735
2736 fn to_owned(&self) -> SslSession {
2737 unsafe {
2738 SSL_SESSION_up_ref(self.as_ptr());
2739 SslSession(NonNull::new_unchecked(self.as_ptr()))
2740 }
2741 }
2742}
2743
2744impl SslSessionRef {
2745 #[corresponds(SSL_SESSION_get_id)]
2747 #[must_use]
2748 pub fn id(&self) -> &[u8] {
2749 unsafe {
2750 let mut len = 0;
2751 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2752 slice::from_raw_parts(p, len as usize)
2753 }
2754 }
2755
2756 #[corresponds(SSL_SESSION_get_master_key)]
2758 #[must_use]
2759 pub fn master_key_len(&self) -> usize {
2760 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2761 }
2762
2763 #[corresponds(SSL_SESSION_get_master_key)]
2767 #[must_use]
2768 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2769 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2770 }
2771
2772 #[corresponds(SSL_SESSION_get_time)]
2774 #[allow(clippy::useless_conversion)]
2775 #[must_use]
2776 pub fn time(&self) -> u64 {
2777 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2778 }
2779
2780 #[corresponds(SSL_SESSION_get_timeout)]
2784 #[allow(clippy::useless_conversion)]
2785 #[must_use]
2786 pub fn timeout(&self) -> u32 {
2787 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()) }
2788 }
2789
2790 #[corresponds(SSL_SESSION_get_protocol_version)]
2792 #[must_use]
2793 pub fn protocol_version(&self) -> SslVersion {
2794 unsafe {
2795 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2796 SslVersion(version)
2797 }
2798 }
2799
2800 to_der! {
2801 #[corresponds(i2d_SSL_SESSION)]
2803 to_der,
2804 ffi::i2d_SSL_SESSION
2805 }
2806}
2807
2808foreign_type_and_impl_send_sync! {
2809 type CType = ffi::SSL;
2810 fn drop = ffi::SSL_free;
2811
2812 pub struct Ssl;
2819}
2820
2821impl fmt::Debug for Ssl {
2822 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2823 fmt::Debug::fmt(&**self, fmt)
2824 }
2825}
2826
2827impl Ssl {
2828 #[corresponds(SSL_get_ex_new_index)]
2833 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2834 where
2835 T: 'static + Sync + Send,
2836 {
2837 unsafe {
2838 ffi::init();
2839 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2840 Ok(Index::from_raw(idx))
2841 }
2842 }
2843
2844 fn cached_ex_index<T>() -> Index<Ssl, T>
2846 where
2847 T: 'static + Sync + Send,
2848 {
2849 unsafe {
2850 let idx = *SSL_INDEXES
2851 .lock()
2852 .unwrap_or_else(|e| e.into_inner())
2853 .entry(TypeId::of::<T>())
2854 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2855 Index::from_raw(idx)
2856 }
2857 }
2858
2859 #[corresponds(SSL_new)]
2861 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2862 unsafe {
2863 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2864 let mut ssl = Ssl::from_ptr(ptr);
2865 SSL_CTX_up_ref(ctx.as_ptr());
2866 let ctx_owned = SslContext::from_ptr(ctx.as_ptr());
2867 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx_owned);
2868
2869 Ok(ssl)
2870 }
2871 }
2872
2873 pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2885 where
2886 S: Read + Write,
2887 {
2888 SslStreamBuilder::new(self, stream).setup_connect()
2889 }
2890
2891 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2901 where
2902 S: Read + Write,
2903 {
2904 self.setup_connect(stream).handshake()
2905 }
2906
2907 pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
2919 where
2920 S: Read + Write,
2921 {
2922 SslStreamBuilder::new(self, stream).setup_accept()
2923 }
2924
2925 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2937 where
2938 S: Read + Write,
2939 {
2940 self.setup_accept(stream).handshake()
2941 }
2942}
2943
2944impl fmt::Debug for SslRef {
2945 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2946 let mut builder = fmt.debug_struct("Ssl");
2947 builder.field("state", &self.state_string_long());
2948 if self.ssl_context().has_x509_support() {
2949 builder.field("verify_result", &self.verify_result());
2950 }
2951 builder.finish()
2952 }
2953}
2954
2955impl SslRef {
2956 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2957 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2958 }
2959
2960 #[corresponds(SSL_set_options)]
2967 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
2968 let bits = unsafe { ffi::SSL_set_options(self.as_ptr(), option.bits()) };
2969 SslOptions::from_bits_retain(bits)
2970 }
2971
2972 #[corresponds(SSL_clear_options)]
2974 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
2975 let bits = unsafe { ffi::SSL_clear_options(self.as_ptr(), option.bits()) };
2976 SslOptions::from_bits_retain(bits)
2977 }
2978
2979 #[corresponds(SSL_set1_curves_list)]
2980 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2981 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2982 unsafe {
2983 cvt_0i(ffi::SSL_set1_curves_list(
2984 self.as_ptr(),
2985 curves.as_ptr() as *const _,
2986 ))
2987 .map(|_| ())
2988 }
2989 }
2990
2991 #[corresponds(SSL_get_curve_id)]
2993 pub fn curve(&self) -> Option<SslCurve> {
2994 let curve_id = unsafe { ffi::SSL_get_curve_id(self.as_ptr()) };
2995 if curve_id == 0 {
2996 return None;
2997 }
2998 Some(SslCurve(curve_id.into()))
2999 }
3000
3001 #[corresponds(SSL_get_curve_name)]
3003 #[must_use]
3004 pub fn curve_name(&self) -> Option<&'static str> {
3005 let curve_id = self.curve()?.0;
3006
3007 unsafe {
3008 let ptr = ffi::SSL_get_curve_name(curve_id as u16);
3009 if ptr.is_null() {
3010 return None;
3011 }
3012
3013 CStr::from_ptr(ptr).to_str().ok()
3014 }
3015 }
3016
3017 #[corresponds(SSL_get_error)]
3019 #[must_use]
3020 pub fn error_code(&self, ret: c_int) -> ErrorCode {
3021 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
3022 }
3023
3024 #[corresponds(SSL_set_verify)]
3028 pub fn set_verify(&mut self, mode: SslVerifyMode) {
3029 self.ssl_context().check_x509();
3030 unsafe { ffi::SSL_set_verify(self.as_ptr(), c_int::from(mode.bits()), None) }
3031 }
3032
3033 #[corresponds(SSL_set_verify_depth)]
3037 pub fn set_verify_depth(&mut self, depth: u32) {
3038 self.ssl_context().check_x509();
3039 unsafe {
3040 ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
3041 }
3042 }
3043
3044 #[corresponds(SSL_get_verify_mode)]
3046 #[must_use]
3047 pub fn verify_mode(&self) -> SslVerifyMode {
3048 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
3049 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
3050 }
3051
3052 #[corresponds(SSL_set_verify)]
3069 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3070 where
3071 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
3072 {
3073 self.ssl_context().check_x509();
3074 unsafe {
3075 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3077 ffi::SSL_set_verify(
3078 self.as_ptr(),
3079 c_int::from(mode.bits()),
3080 Some(ssl_raw_verify::<F>),
3081 );
3082 }
3083 }
3084
3085 #[corresponds(SSL_set0_verify_cert_store)]
3087 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3088 self.ssl_context().check_x509();
3089 unsafe {
3090 cvt(ffi::SSL_set0_verify_cert_store(
3091 self.as_ptr(),
3092 cert_store.into_ptr(),
3093 ))
3094 }
3095 }
3096
3097 #[corresponds(SSL_set_custom_verify)]
3103 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3104 where
3105 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
3106 {
3107 self.ssl_context().check_x509();
3108 unsafe {
3109 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3111 ffi::SSL_set_custom_verify(
3112 self.as_ptr(),
3113 c_int::from(mode.bits()),
3114 Some(ssl_raw_custom_verify::<F>),
3115 );
3116 }
3117 }
3118
3119 #[corresponds(SSL_set_tmp_dh)]
3123 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3124 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr())) }
3125 }
3126
3127 #[corresponds(SSL_set_tmp_ecdh)]
3131 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3132 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr())) }
3133 }
3134
3135 #[corresponds(SSL_set_permute_extensions)]
3137 pub fn set_permute_extensions(&mut self, enabled: bool) {
3138 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as _) }
3139 }
3140
3141 #[corresponds(SSL_set_alpn_protos)]
3145 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3146 unsafe {
3147 let r = ffi::SSL_set_alpn_protos(
3148 self.as_ptr(),
3149 protocols.as_ptr(),
3150 try_int(protocols.len())?,
3151 );
3152 if r == 0 {
3154 Ok(())
3155 } else {
3156 Err(ErrorStack::get())
3157 }
3158 }
3159 }
3160
3161 #[corresponds(SSL_set_record_size_limit)]
3162 pub fn set_record_size_limit(&mut self, value: u16) -> Result<(), ErrorStack> {
3163 unsafe { cvt(ffi::SSL_set_record_size_limit(self.as_ptr(), value) as c_int).map(|_| ()) }
3164 }
3165
3166 #[corresponds(SSL_set_delegated_credential_schemes)]
3167 pub fn set_delegated_credential_schemes(
3168 &mut self,
3169 schemes: &[SslSignatureAlgorithm],
3170 ) -> Result<(), ErrorStack> {
3171 unsafe {
3172 cvt_0i(ffi::SSL_set_delegated_credential_schemes(
3173 self.as_ptr(),
3174 schemes.as_ptr() as *const _,
3175 schemes.len(),
3176 ))
3177 .map(|_| ())
3178 }
3179 }
3180
3181 #[corresponds(SSL_get_ciphers)]
3183 #[must_use]
3184 pub fn ciphers(&self) -> &StackRef<SslCipher> {
3185 unsafe {
3186 let cipher_list = ffi::SSL_get_ciphers(self.as_ptr());
3187 StackRef::from_ptr(cipher_list)
3188 }
3189 }
3190
3191 #[corresponds(SSL_get_current_cipher)]
3193 #[must_use]
3194 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3195 unsafe {
3196 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3197
3198 if ptr.is_null() {
3199 None
3200 } else {
3201 Some(SslCipherRef::from_ptr(ptr.cast_mut()))
3202 }
3203 }
3204 }
3205
3206 #[corresponds(SSL_state_string)]
3208 #[must_use]
3209 pub fn state_string(&self) -> &'static str {
3210 let state = unsafe {
3211 let ptr = ffi::SSL_state_string(self.as_ptr());
3212 CStr::from_ptr(ptr)
3213 };
3214
3215 state.to_str().unwrap_or_default()
3216 }
3217
3218 #[corresponds(SSL_state_string_long)]
3222 #[must_use]
3223 pub fn state_string_long(&self) -> &'static str {
3224 let state = unsafe {
3225 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3226 CStr::from_ptr(ptr)
3227 };
3228
3229 state.to_str().unwrap_or_default()
3230 }
3231
3232 #[corresponds(SSL_set_tlsext_host_name)]
3236 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3237 let cstr = CString::new(hostname).map_err(ErrorStack::internal_error)?;
3238 unsafe { cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr())) }
3239 }
3240
3241 #[corresponds(SSL_get_peer_certificate)]
3243 #[must_use]
3244 pub fn peer_certificate(&self) -> Option<X509> {
3245 self.ssl_context().check_x509();
3246 unsafe {
3247 let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
3248 if ptr.is_null() {
3249 None
3250 } else {
3251 Some(X509::from_ptr(ptr))
3252 }
3253 }
3254 }
3255
3256 #[corresponds(SSL_get_peer_certificate)]
3261 #[must_use]
3262 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3263 unsafe {
3264 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3265 if ptr.is_null() {
3266 None
3267 } else {
3268 Some(StackRef::from_ptr(ptr))
3269 }
3270 }
3271 }
3272
3273 #[corresponds(SSL_get_certificate)]
3275 #[must_use]
3276 pub fn certificate(&self) -> Option<&X509Ref> {
3277 self.ssl_context().check_x509();
3278 unsafe {
3279 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3280 if ptr.is_null() {
3281 None
3282 } else {
3283 Some(X509Ref::from_ptr(ptr))
3284 }
3285 }
3286 }
3287
3288 #[corresponds(SSL_get_privatekey)]
3290 #[must_use]
3291 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3292 unsafe {
3293 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3294 if ptr.is_null() {
3295 None
3296 } else {
3297 Some(PKeyRef::from_ptr(ptr))
3298 }
3299 }
3300 }
3301
3302 #[corresponds(SSL_version)]
3304 #[must_use]
3305 pub fn version(&self) -> Option<SslVersion> {
3306 unsafe {
3307 let r = ffi::SSL_version(self.as_ptr());
3308 if r == 0 {
3309 None
3310 } else {
3311 r.try_into().ok().map(SslVersion)
3312 }
3313 }
3314 }
3315
3316 #[corresponds(SSL_get_version)]
3320 #[must_use]
3321 pub fn version_str(&self) -> &'static str {
3322 let version = unsafe {
3323 let ptr = ffi::SSL_get_version(self.as_ptr());
3324 CStr::from_ptr(ptr)
3325 };
3326
3327 version.to_str().unwrap()
3328 }
3329
3330 #[corresponds(SSL_set_min_proto_version)]
3335 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3336 unsafe {
3337 cvt(ffi::SSL_set_min_proto_version(
3338 self.as_ptr(),
3339 version.map_or(0, |v| v.0 as _),
3340 ))
3341 }
3342 }
3343
3344 #[corresponds(SSL_set_max_proto_version)]
3348 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3349 unsafe {
3350 cvt(ffi::SSL_set_max_proto_version(
3351 self.as_ptr(),
3352 version.map_or(0, |v| v.0 as _),
3353 ))
3354 }
3355 }
3356
3357 #[corresponds(SSL_get_min_proto_version)]
3359 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
3360 unsafe {
3361 let r = ffi::SSL_get_min_proto_version(self.as_ptr());
3362 if r == 0 {
3363 None
3364 } else {
3365 Some(SslVersion(r))
3366 }
3367 }
3368 }
3369
3370 #[corresponds(SSL_get_max_proto_version)]
3372 #[must_use]
3373 pub fn max_proto_version(&self) -> Option<SslVersion> {
3374 let r = unsafe { ffi::SSL_get_max_proto_version(self.as_ptr()) };
3375 if r == 0 {
3376 None
3377 } else {
3378 Some(SslVersion(r))
3379 }
3380 }
3381
3382 #[corresponds(SSL_get0_alpn_selected)]
3387 #[must_use]
3388 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3389 unsafe {
3390 let mut data: *const c_uchar = ptr::null();
3391 let mut len: c_uint = 0;
3392 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3395
3396 if data.is_null() {
3397 None
3398 } else {
3399 Some(slice::from_raw_parts(data, len as usize))
3400 }
3401 }
3402 }
3403
3404 #[corresponds(SSL_set_tlsext_use_srtp)]
3406 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3407 unsafe {
3408 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
3409
3410 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3411 if r == 0 {
3413 Ok(())
3414 } else {
3415 Err(ErrorStack::get())
3416 }
3417 }
3418 }
3419
3420 #[corresponds(SSL_get_strp_profiles)]
3424 #[must_use]
3425 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3426 unsafe {
3427 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3428
3429 if chain.is_null() {
3430 None
3431 } else {
3432 Some(StackRef::from_ptr(chain.cast_mut()))
3433 }
3434 }
3435 }
3436
3437 #[corresponds(SSL_get_selected_srtp_profile)]
3441 #[must_use]
3442 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3443 unsafe {
3444 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3445
3446 if profile.is_null() {
3447 None
3448 } else {
3449 Some(SrtpProtectionProfileRef::from_ptr(profile.cast_mut()))
3450 }
3451 }
3452 }
3453
3454 #[corresponds(SSL_pending)]
3459 #[must_use]
3460 pub fn pending(&self) -> usize {
3461 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3462 }
3463
3464 #[corresponds(SSL_get_servername)]
3477 #[must_use]
3478 pub fn servername(&self, type_: NameType) -> Option<&str> {
3479 self.servername_raw(type_)
3480 .and_then(|b| str::from_utf8(b).ok())
3481 }
3482
3483 #[corresponds(SSL_get_servername)]
3491 #[must_use]
3492 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3493 unsafe {
3494 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3495 if name.is_null() {
3496 None
3497 } else {
3498 Some(CStr::from_ptr(name).to_bytes())
3499 }
3500 }
3501 }
3502
3503 #[corresponds(SSL_set_SSL_CTX)]
3507 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3508 assert_eq!(
3509 self.ssl_context().has_x509_support(),
3510 ctx.has_x509_support(),
3511 "X.509 certificate support in old and new contexts doesn't match",
3512 );
3513 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3514 }
3515
3516 #[corresponds(SSL_get_SSL_CTX)]
3518 #[must_use]
3519 pub fn ssl_context(&self) -> &SslContextRef {
3520 unsafe {
3521 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3522 SslContextRef::from_ptr(ssl_ctx)
3523 }
3524 }
3525
3526 #[corresponds(SSL_get0_param)]
3528 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
3529 self.ssl_context().check_x509();
3530 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3531 }
3532
3533 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3535 self.verify_param_mut()
3536 }
3537
3538 #[corresponds(SSL_get_verify_result)]
3540 pub fn verify_result(&self) -> X509VerifyResult {
3541 self.ssl_context().check_x509();
3542 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3543 }
3544
3545 #[corresponds(SSL_get_session)]
3547 #[must_use]
3548 pub fn session(&self) -> Option<&SslSessionRef> {
3549 unsafe {
3550 let p = ffi::SSL_get_session(self.as_ptr());
3551 if p.is_null() {
3552 None
3553 } else {
3554 Some(SslSessionRef::from_ptr(p))
3555 }
3556 }
3557 }
3558
3559 #[corresponds(SSL_get_client_random)]
3564 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3565 unsafe { ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
3566 }
3567
3568 #[corresponds(SSL_get_server_random)]
3573 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3574 unsafe { ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
3575 }
3576
3577 #[corresponds(SSL_export_keying_material)]
3579 pub fn export_keying_material(
3580 &self,
3581 out: &mut [u8],
3582 label: &str,
3583 context: Option<&[u8]>,
3584 ) -> Result<(), ErrorStack> {
3585 unsafe {
3586 let (context, contextlen, use_context) = match context {
3587 Some(context) => (context.as_ptr(), context.len(), 1),
3588 None => (ptr::null(), 0, 0),
3589 };
3590 cvt(ffi::SSL_export_keying_material(
3591 self.as_ptr(),
3592 out.as_mut_ptr(),
3593 out.len(),
3594 label.as_ptr().cast::<c_char>(),
3595 label.len(),
3596 context,
3597 contextlen,
3598 use_context,
3599 ))
3600 .map(|_| ())
3601 }
3602 }
3603
3604 #[corresponds(SSL_set_session)]
3615 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3616 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr()))
3617 }
3618
3619 #[corresponds(SSL_session_reused)]
3621 #[must_use]
3622 pub fn session_reused(&self) -> bool {
3623 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3624 }
3625
3626 #[corresponds(SSL_set_tlsext_status_type)]
3628 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3629 unsafe {
3630 cvt(ffi::SSL_set_tlsext_status_type(
3631 self.as_ptr(),
3632 type_.as_raw(),
3633 ))
3634 }
3635 }
3636
3637 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3639 #[must_use]
3640 pub fn ocsp_status(&self) -> Option<&[u8]> {
3641 unsafe {
3642 let mut p = ptr::null();
3643 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3644
3645 if len == 0 {
3646 None
3647 } else {
3648 Some(slice::from_raw_parts(p, len))
3649 }
3650 }
3651 }
3652
3653 #[corresponds(SSL_set_ocsp_response)]
3655 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3656 unsafe {
3657 assert!(response.len() <= c_int::MAX as usize);
3658 cvt(ffi::SSL_set_ocsp_response(
3659 self.as_ptr(),
3660 response.as_ptr(),
3661 response.len(),
3662 ))
3663 }
3664 }
3665
3666 #[corresponds(SSL_is_server)]
3668 #[must_use]
3669 pub fn is_server(&self) -> bool {
3670 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3671 }
3672
3673 #[corresponds(SSL_set_ex_data)]
3681 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3682 if let Some(old) = self.ex_data_mut(index) {
3683 *old = data;
3684 return;
3685 }
3686
3687 unsafe {
3688 let data = Box::into_raw(Box::new(data));
3689 ffi::SSL_set_ex_data(self.as_ptr(), index.as_raw(), data.cast());
3690 }
3691 }
3692
3693 #[corresponds(SSL_set_ex_data)]
3700 pub fn replace_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) -> Option<T> {
3701 if let Some(old) = self.ex_data_mut(index) {
3702 return Some(mem::replace(old, data));
3703 }
3704
3705 self.set_ex_data(index, data);
3706
3707 None
3708 }
3709
3710 #[corresponds(SSL_get_ex_data)]
3712 #[must_use]
3713 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3714 unsafe {
3715 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3716 if data.is_null() {
3717 None
3718 } else {
3719 Some(&*(data as *const T))
3720 }
3721 }
3722 }
3723
3724 #[corresponds(SSL_get_ex_data)]
3726 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3727 unsafe {
3728 ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw())
3729 .cast::<T>()
3730 .as_mut()
3731 }
3732 }
3733
3734 #[corresponds(SSL_get_finished)]
3739 pub fn finished(&self, buf: &mut [u8]) -> usize {
3740 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) }
3741 }
3742
3743 #[corresponds(SSL_get_peer_finished)]
3749 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3750 unsafe { ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr().cast(), buf.len()) }
3751 }
3752
3753 #[corresponds(SSL_is_init_finished)]
3755 #[must_use]
3756 pub fn is_init_finished(&self) -> bool {
3757 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3758 }
3759
3760 #[corresponds(SSL_set_mtu)]
3762 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3763 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_uint)) }
3764 }
3765
3766 #[corresponds(SSL_use_certificate)]
3768 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3769 unsafe {
3770 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3771 }
3772
3773 Ok(())
3774 }
3775
3776 #[corresponds(SSL_set_client_CA_list)]
3781 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3782 self.ssl_context().check_x509();
3783 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3784 mem::forget(list);
3785 }
3786
3787 #[corresponds(SSL_use_PrivateKey)]
3789 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
3790 where
3791 T: HasPrivate,
3792 {
3793 unsafe { cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), key.as_ptr())) }
3794 }
3795
3796 #[corresponds(SSL_set_mode)]
3799 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
3800 let bits = unsafe { ffi::SSL_set_mode(self.as_ptr(), mode.bits()) };
3801 SslMode::from_bits_retain(bits)
3802 }
3803
3804 #[corresponds(SSL_clear_mode)]
3807 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
3808 let bits = unsafe { ffi::SSL_clear_mode(self.as_ptr(), mode.bits()) };
3809 SslMode::from_bits_retain(bits)
3810 }
3811
3812 #[corresponds(SSL_add1_chain_cert)]
3814 pub fn add_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3815 unsafe { cvt(ffi::SSL_add1_chain_cert(self.as_ptr(), cert.as_ptr())) }
3816 }
3817
3818 #[corresponds(SSL_set1_ech_config_list)]
3826 pub fn set_ech_config_list(&mut self, ech_config_list: &[u8]) -> Result<(), ErrorStack> {
3827 unsafe {
3828 cvt_0i(ffi::SSL_set1_ech_config_list(
3829 self.as_ptr(),
3830 ech_config_list.as_ptr(),
3831 ech_config_list.len(),
3832 ))
3833 .map(|_| ())
3834 }
3835 }
3836
3837 #[corresponds(SSL_get0_ech_retry_configs)]
3844 #[must_use]
3845 pub fn get_ech_retry_configs(&self) -> Option<&[u8]> {
3846 unsafe {
3847 let mut data = ptr::null();
3848 let mut len: usize = 0;
3849 ffi::SSL_get0_ech_retry_configs(self.as_ptr(), &mut data, &mut len);
3850
3851 if data.is_null() {
3852 None
3853 } else {
3854 Some(slice::from_raw_parts(data, len))
3855 }
3856 }
3857 }
3858
3859 #[corresponds(SSL_get0_ech_name_override)]
3866 #[must_use]
3867 pub fn get_ech_name_override(&self) -> Option<&[u8]> {
3868 unsafe {
3869 let mut data: *const c_char = ptr::null();
3870 let mut len: usize = 0;
3871 ffi::SSL_get0_ech_name_override(self.as_ptr(), &mut data, &mut len);
3872
3873 if data.is_null() {
3874 None
3875 } else {
3876 Some(slice::from_raw_parts(data.cast::<u8>(), len))
3877 }
3878 }
3879 }
3880
3881 #[corresponds(SSL_ech_accepted)]
3883 pub fn ech_accepted(&self) -> bool {
3884 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
3885 }
3886
3887 #[corresponds(SSL_set_enable_ech_grease)]
3889 pub fn set_enable_ech_grease(&self, enable: bool) {
3890 let enable = if enable { 1 } else { 0 };
3891
3892 unsafe {
3893 ffi::SSL_set_enable_ech_grease(self.as_ptr(), enable);
3894 }
3895 }
3896
3897 #[corresponds(SSL_set_compliance_policy)]
3899 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
3900 unsafe { cvt_0i(ffi::SSL_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
3901 }
3902
3903 #[corresponds(SSL_add1_credential)]
3905 pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> {
3906 unsafe { cvt_0i(ffi::SSL_add1_credential(self.as_ptr(), credential.as_ptr())).map(|_| ()) }
3907 }
3908
3909 #[corresponds(SSL_set_alps_use_new_codepoint)]
3911 pub fn set_alps_use_new_codepoint(&mut self, use_new_codepoint: bool) {
3912 let use_new_codepoint = if use_new_codepoint { 1 } else { 0 };
3913 unsafe {
3914 ffi::SSL_set_alps_use_new_codepoint(self.as_ptr(), use_new_codepoint);
3915 }
3916 }
3917
3918 #[corresponds(SSL_add_application_settings)]
3920 pub fn add_application_settings(&mut self, alps: &[u8]) -> Result<(), ErrorStack> {
3921 unsafe {
3922 cvt_0i(ffi::SSL_add_application_settings(
3923 self.as_ptr(),
3924 alps.as_ptr(),
3925 alps.len(),
3926 ptr::null(),
3927 0,
3928 ))
3929 .map(|_| ())
3930 }
3931 }
3932}
3933
3934#[derive(Debug)]
3936pub struct MidHandshakeSslStream<S> {
3937 stream: SslStream<S>,
3938 error: Error,
3939}
3940
3941impl<S> MidHandshakeSslStream<S> {
3942 #[must_use]
3944 pub fn get_ref(&self) -> &S {
3945 self.stream.get_ref()
3946 }
3947
3948 pub fn get_mut(&mut self) -> &mut S {
3950 self.stream.get_mut()
3951 }
3952
3953 #[must_use]
3955 pub fn ssl(&self) -> &SslRef {
3956 self.stream.ssl()
3957 }
3958
3959 pub fn ssl_mut(&mut self) -> &mut SslRef {
3961 self.stream.ssl_mut()
3962 }
3963
3964 #[must_use]
3966 pub fn error(&self) -> &Error {
3967 &self.error
3968 }
3969
3970 #[must_use]
3972 pub fn into_error(self) -> Error {
3973 self.error
3974 }
3975
3976 #[must_use]
3978 pub fn into_source_stream(self) -> S {
3979 self.stream.into_inner()
3980 }
3981
3982 pub fn into_parts(self) -> (Error, S) {
3984 (self.error, self.stream.into_inner())
3985 }
3986
3987 #[corresponds(SSL_do_handshake)]
3989 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3990 let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) };
3991 if ret > 0 {
3992 Ok(self.stream)
3993 } else {
3994 self.error = self.stream.make_error(ret);
3995 Err(if self.error.would_block() {
3996 HandshakeError::WouldBlock(self)
3997 } else {
3998 HandshakeError::Failure(self)
3999 })
4000 }
4001 }
4002}
4003
4004pub struct SslStream<S> {
4006 ssl: ManuallyDrop<Ssl>,
4007 method: ManuallyDrop<BioMethod>,
4008 _p: PhantomData<S>,
4009}
4010
4011impl<S> Drop for SslStream<S> {
4012 fn drop(&mut self) {
4013 unsafe {
4015 ManuallyDrop::drop(&mut self.ssl);
4016 ManuallyDrop::drop(&mut self.method);
4017 }
4018 }
4019}
4020
4021impl<S> fmt::Debug for SslStream<S>
4022where
4023 S: fmt::Debug,
4024{
4025 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
4026 fmt.debug_struct("SslStream")
4027 .field("stream", &self.get_ref())
4028 .field("ssl", &self.ssl())
4029 .finish()
4030 }
4031}
4032
4033impl<S: Read + Write> SslStream<S> {
4034 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4040 let (bio, method) = bio::new(stream)?;
4041
4042 unsafe {
4043 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4044 }
4045
4046 Ok(SslStream {
4047 ssl: ManuallyDrop::new(ssl),
4048 method: ManuallyDrop::new(method),
4049 _p: PhantomData,
4050 })
4051 }
4052
4053 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
4061 let ssl = Ssl::from_ptr(ssl);
4062 Self::new(ssl, stream).unwrap()
4063 }
4064
4065 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4072 loop {
4073 match self.ssl_read_uninit(buf) {
4074 Ok(n) => return Ok(n),
4075 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4076 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4077 return Ok(0);
4078 }
4079 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4080 Err(e) => {
4081 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4082 }
4083 }
4084 }
4085 }
4086
4087 #[corresponds(SSL_read)]
4092 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4093 unsafe {
4095 self.ssl_read_uninit(slice::from_raw_parts_mut(
4096 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4097 buf.len(),
4098 ))
4099 }
4100 }
4101
4102 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4109 if buf.is_empty() {
4110 return Ok(0);
4111 }
4112
4113 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4114 let ret = unsafe { ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) };
4115 if ret > 0 {
4116 Ok(ret as usize)
4117 } else {
4118 Err(self.make_error(ret))
4119 }
4120 }
4121
4122 #[corresponds(SSL_write)]
4127 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4128 if buf.is_empty() {
4129 return Ok(0);
4130 }
4131
4132 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4133 let ret = unsafe { ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) };
4134 if ret > 0 {
4135 Ok(ret as usize)
4136 } else {
4137 Err(self.make_error(ret))
4138 }
4139 }
4140
4141 #[corresponds(SSL_shutdown)]
4151 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4152 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4153 0 => Ok(ShutdownResult::Sent),
4154 1 => Ok(ShutdownResult::Received),
4155 n => Err(self.make_error(n)),
4156 }
4157 }
4158
4159 #[corresponds(SSL_get_shutdown)]
4161 pub fn get_shutdown(&mut self) -> ShutdownState {
4162 unsafe {
4163 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4164 ShutdownState::from_bits_retain(bits)
4165 }
4166 }
4167
4168 #[corresponds(SSL_set_shutdown)]
4173 pub fn set_shutdown(&mut self, state: ShutdownState) {
4174 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4175 }
4176
4177 #[corresponds(SSL_connect)]
4179 pub fn connect(&mut self) -> Result<(), Error> {
4180 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4181 if ret > 0 {
4182 Ok(())
4183 } else {
4184 Err(self.make_error(ret))
4185 }
4186 }
4187
4188 #[corresponds(SSL_accept)]
4190 pub fn accept(&mut self) -> Result<(), Error> {
4191 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4192 if ret > 0 {
4193 Ok(())
4194 } else {
4195 Err(self.make_error(ret))
4196 }
4197 }
4198
4199 #[corresponds(SSL_do_handshake)]
4201 pub fn do_handshake(&mut self) -> Result<(), Error> {
4202 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4203 if ret > 0 {
4204 Ok(())
4205 } else {
4206 Err(self.make_error(ret))
4207 }
4208 }
4209}
4210
4211impl<S> SslStream<S> {
4212 fn make_error(&mut self, ret: c_int) -> Error {
4213 self.check_panic();
4214
4215 let code = self.ssl.error_code(ret);
4216
4217 let cause = match code {
4218 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4219 ErrorCode::SYSCALL => {
4220 let errs = ErrorStack::get();
4221 if errs.errors().is_empty() {
4222 self.get_bio_error().map(InnerError::Io)
4223 } else {
4224 Some(InnerError::Ssl(errs))
4225 }
4226 }
4227 ErrorCode::ZERO_RETURN => None,
4228 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4229 self.get_bio_error().map(InnerError::Io)
4230 }
4231 _ => None,
4232 };
4233
4234 Error { code, cause }
4235 }
4236
4237 fn check_panic(&mut self) {
4238 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4239 resume_unwind(err)
4240 }
4241 }
4242
4243 fn get_bio_error(&mut self) -> Option<io::Error> {
4244 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4245 }
4246
4247 #[must_use]
4249 pub fn into_inner(self) -> S {
4250 unsafe { bio::take_stream::<S>(self.ssl.get_raw_rbio()) }
4251 }
4252
4253 #[must_use]
4255 pub fn get_ref(&self) -> &S {
4256 unsafe {
4257 let bio = self.ssl.get_raw_rbio();
4258 bio::get_ref(bio)
4259 }
4260 }
4261
4262 pub fn get_mut(&mut self) -> &mut S {
4269 unsafe {
4270 let bio = self.ssl.get_raw_rbio();
4271 bio::get_mut(bio)
4272 }
4273 }
4274
4275 #[must_use]
4277 pub fn ssl(&self) -> &SslRef {
4278 &self.ssl
4279 }
4280
4281 pub fn ssl_mut(&mut self) -> &mut SslRef {
4283 &mut self.ssl
4284 }
4285}
4286
4287impl<S: Read + Write> Read for SslStream<S> {
4288 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4289 unsafe {
4291 self.read_uninit(slice::from_raw_parts_mut(
4292 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4293 buf.len(),
4294 ))
4295 }
4296 }
4297}
4298
4299impl<S: Read + Write> Write for SslStream<S> {
4300 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4301 loop {
4302 match self.ssl_write(buf) {
4303 Ok(n) => return Ok(n),
4304 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4305 Err(e) => {
4306 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4307 }
4308 }
4309 }
4310 }
4311
4312 fn flush(&mut self) -> io::Result<()> {
4313 self.get_mut().flush()
4314 }
4315}
4316
4317pub struct SslStreamBuilder<S> {
4319 inner: SslStream<S>,
4320}
4321
4322impl<S> SslStreamBuilder<S>
4323where
4324 S: Read + Write,
4325{
4326 pub fn new(ssl: Ssl, stream: S) -> Self {
4328 Self {
4329 inner: SslStream::new(ssl, stream).unwrap(),
4330 }
4331 }
4332
4333 #[corresponds(SSL_set_connect_state)]
4335 pub fn set_connect_state(&mut self) {
4336 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4337 }
4338
4339 #[corresponds(SSL_set_accept_state)]
4341 pub fn set_accept_state(&mut self) {
4342 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4343 }
4344
4345 #[must_use]
4351 pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
4352 self.set_connect_state();
4353
4354 MidHandshakeSslStream {
4355 stream: self.inner,
4356 error: Error {
4357 code: ErrorCode::WANT_WRITE,
4358 cause: Some(InnerError::Io(io::Error::new(
4359 io::ErrorKind::WouldBlock,
4360 "connect handshake has not started yet",
4361 ))),
4362 },
4363 }
4364 }
4365
4366 pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
4371 self.setup_connect().handshake()
4372 }
4373
4374 #[must_use]
4380 pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
4381 self.set_accept_state();
4382
4383 MidHandshakeSslStream {
4384 stream: self.inner,
4385 error: Error {
4386 code: ErrorCode::WANT_READ,
4387 cause: Some(InnerError::Io(io::Error::new(
4388 io::ErrorKind::WouldBlock,
4389 "accept handshake has not started yet",
4390 ))),
4391 },
4392 }
4393 }
4394
4395 pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
4400 self.setup_accept().handshake()
4401 }
4402
4403 #[corresponds(SSL_do_handshake)]
4407 pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
4408 let mut stream = self.inner;
4409 let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
4410 if ret > 0 {
4411 Ok(stream)
4412 } else {
4413 let error = stream.make_error(ret);
4414 Err(if error.would_block() {
4415 HandshakeError::WouldBlock(MidHandshakeSslStream { stream, error })
4416 } else {
4417 HandshakeError::Failure(MidHandshakeSslStream { stream, error })
4418 })
4419 }
4420 }
4421}
4422
4423impl<S> SslStreamBuilder<S> {
4424 #[must_use]
4426 pub fn get_ref(&self) -> &S {
4427 unsafe {
4428 let bio = self.inner.ssl.get_raw_rbio();
4429 bio::get_ref(bio)
4430 }
4431 }
4432
4433 pub fn get_mut(&mut self) -> &mut S {
4440 unsafe {
4441 let bio = self.inner.ssl.get_raw_rbio();
4442 bio::get_mut(bio)
4443 }
4444 }
4445
4446 #[must_use]
4448 pub fn ssl(&self) -> &SslRef {
4449 &self.inner.ssl
4450 }
4451
4452 pub fn ssl_mut(&mut self) -> &mut SslRef {
4454 &mut self.inner.ssl
4455 }
4456
4457 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4465 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4466 unsafe {
4467 let bio = self.inner.ssl.get_raw_rbio();
4468 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4469 }
4470 }
4471}
4472
4473#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4475pub enum ShutdownResult {
4476 Sent,
4478
4479 Received,
4481}
4482
4483bitflags! {
4484 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
4486 pub struct ShutdownState: c_int {
4487 const SENT = ffi::SSL_SENT_SHUTDOWN;
4489 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4491 }
4492}
4493
4494pub trait PrivateKeyMethod: Send + Sync + 'static {
4502 fn sign(
4513 &self,
4514 ssl: &mut SslRef,
4515 input: &[u8],
4516 signature_algorithm: SslSignatureAlgorithm,
4517 output: &mut [u8],
4518 ) -> Result<usize, PrivateKeyMethodError>;
4519
4520 fn decrypt(
4535 &self,
4536 ssl: &mut SslRef,
4537 input: &[u8],
4538 output: &mut [u8],
4539 ) -> Result<usize, PrivateKeyMethodError>;
4540
4541 fn complete(&self, ssl: &mut SslRef, output: &mut [u8])
4550 -> Result<usize, PrivateKeyMethodError>;
4551}
4552
4553#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4555pub struct PrivateKeyMethodError(ffi::ssl_private_key_result_t);
4556
4557impl PrivateKeyMethodError {
4558 pub const FAILURE: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_failure);
4560
4561 pub const RETRY: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_retry);
4563}
4564
4565pub trait CertificateCompressor: Send + Sync + 'static {
4567 const ALGORITHM: CertificateCompressionAlgorithm;
4569
4570 const CAN_COMPRESS: bool;
4572
4573 const CAN_DECOMPRESS: bool;
4575
4576 #[allow(unused_variables)]
4578 fn compress<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 #[allow(unused_variables)]
4587 fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4588 where
4589 W: std::io::Write,
4590 {
4591 Err(std::io::Error::other("not implemented"))
4592 }
4593}
4594
4595use crate::ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4596
4597unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4598 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4599}
4600
4601unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4602 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4603}
4604
4605fn path_to_cstring(path: &Path) -> Result<CString, ErrorStack> {
4606 CString::new(path.as_os_str().as_encoded_bytes()).map_err(ErrorStack::internal_error)
4607}