1use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
61use libc::{c_char, c_int, c_uchar, c_uint, c_void};
62use openssl_macros::corresponds;
63use std::any::TypeId;
64use std::collections::HashMap;
65use std::convert::TryInto;
66use std::ffi::{CStr, CString};
67use std::fmt;
68use std::io;
69use std::io::prelude::*;
70use std::marker::PhantomData;
71use std::mem::{self, ManuallyDrop, MaybeUninit};
72use std::ops::{Deref, DerefMut};
73use std::panic::resume_unwind;
74use std::path::Path;
75use std::ptr::{self, NonNull};
76use std::slice;
77use std::str;
78use std::sync::{Arc, LazyLock, Mutex};
79
80use crate::dh::DhRef;
81use crate::ec::EcKeyRef;
82use crate::error::ErrorStack;
83use crate::ex_data::Index;
84use crate::nid::Nid;
85use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
86use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
87use crate::ssl::bio::BioMethod;
88use crate::ssl::callbacks::*;
89use crate::ssl::error::InnerError;
90use crate::stack::{Stack, StackRef, Stackable};
91use crate::x509::store::{X509Store, X509StoreBuilder, X509StoreBuilderRef, X509StoreRef};
92use crate::x509::verify::X509VerifyParamRef;
93use crate::x509::{
94 X509Name, X509Ref, X509StoreContextRef, X509VerifyError, X509VerifyResult, X509,
95};
96use crate::{cvt, cvt_0i, cvt_n, cvt_p, init};
97use crate::{ffi, free_data_box};
98
99pub use self::async_callbacks::{
100 AsyncPrivateKeyMethod, AsyncPrivateKeyMethodError, AsyncSelectCertError, BoxCustomVerifyFinish,
101 BoxCustomVerifyFuture, BoxGetSessionFinish, BoxGetSessionFuture, BoxPrivateKeyMethodFinish,
102 BoxPrivateKeyMethodFuture, BoxSelectCertFinish, BoxSelectCertFuture, ExDataFuture,
103};
104pub use self::connector::{
105 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
106};
107#[cfg(not(feature = "fips"))]
108pub use self::ech::{SslEchKeys, SslEchKeysRef};
109pub use self::error::{Error, ErrorCode, HandshakeError};
110
111mod async_callbacks;
112mod bio;
113mod callbacks;
114mod connector;
115#[cfg(not(feature = "fips"))]
116mod ech;
117mod error;
118mod mut_only;
119#[cfg(test)]
120mod test;
121
122bitflags! {
123 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
125 pub struct SslOptions: c_uint {
126 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as _;
128
129 const ALL = ffi::SSL_OP_ALL as _;
131
132 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as _;
136
137 const NO_TICKET = ffi::SSL_OP_NO_TICKET as _;
139
140 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
142 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as _;
143
144 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as _;
146
147 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
150 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as _;
151
152 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as _;
154
155 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as _;
157
158 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as _;
162
163 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as _;
165
166 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as _;
168
169 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as _;
171
172 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as _;
174
175 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as _;
177
178 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as _;
180
181 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as _;
183
184 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as _;
186
187 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as _;
189
190 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as _;
192 }
193}
194
195bitflags! {
196 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
198 pub struct SslMode: c_uint {
199 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE as _;
205
206 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER as _;
209
210 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY as _;
220
221 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN as _;
227
228 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS as _;
232
233 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV as _;
241 }
242}
243
244#[derive(Copy, Clone)]
246pub struct SslMethod(*const ffi::SSL_METHOD);
247
248impl SslMethod {
249 #[corresponds(TLS_method)]
251 #[must_use]
252 pub fn tls() -> SslMethod {
253 unsafe { SslMethod(TLS_method()) }
254 }
255
256 #[cfg(feature = "rpk")]
258 pub fn tls_with_buffer() -> SslMethod {
259 unsafe { SslMethod(ffi::TLS_with_buffers_method()) }
260 }
261
262 #[corresponds(DTLS_method)]
264 #[must_use]
265 pub fn dtls() -> SslMethod {
266 unsafe { SslMethod(DTLS_method()) }
267 }
268
269 #[corresponds(TLS_client_method)]
271 #[must_use]
272 pub fn tls_client() -> SslMethod {
273 unsafe { SslMethod(TLS_client_method()) }
274 }
275
276 #[corresponds(TLS_server_method)]
278 #[must_use]
279 pub fn tls_server() -> SslMethod {
280 unsafe { SslMethod(TLS_server_method()) }
281 }
282
283 #[corresponds(TLS_server_method)]
289 #[must_use]
290 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
291 SslMethod(ptr)
292 }
293
294 #[allow(clippy::trivially_copy_pass_by_ref)]
296 #[must_use]
297 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
298 self.0
299 }
300}
301
302unsafe impl Sync for SslMethod {}
303unsafe impl Send for SslMethod {}
304
305bitflags! {
306 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
308 pub struct SslVerifyMode: i32 {
309 const PEER = ffi::SSL_VERIFY_PEER;
313
314 const NONE = ffi::SSL_VERIFY_NONE;
320
321 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
325 }
326}
327
328#[derive(Clone, Copy, Debug, Eq, PartialEq)]
329pub enum SslVerifyError {
330 Invalid(SslAlert),
331 Retry,
332}
333
334bitflags! {
335 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
337 pub struct SslSessionCacheMode: c_int {
338 const OFF = ffi::SSL_SESS_CACHE_OFF;
340
341 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
348
349 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
353
354 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
356
357 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
359
360 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
362
363 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
365
366 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
368 }
369}
370
371#[derive(Copy, Clone)]
373pub struct SslFiletype(c_int);
374
375impl SslFiletype {
376 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
380
381 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
385
386 #[must_use]
388 pub fn from_raw(raw: c_int) -> SslFiletype {
389 SslFiletype(raw)
390 }
391
392 #[allow(clippy::trivially_copy_pass_by_ref)]
394 #[must_use]
395 pub fn as_raw(&self) -> c_int {
396 self.0
397 }
398}
399
400#[derive(Copy, Clone)]
402pub struct StatusType(c_int);
403
404impl StatusType {
405 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
407
408 #[must_use]
410 pub fn from_raw(raw: c_int) -> StatusType {
411 StatusType(raw)
412 }
413
414 #[allow(clippy::trivially_copy_pass_by_ref)]
416 #[must_use]
417 pub fn as_raw(&self) -> c_int {
418 self.0
419 }
420}
421
422#[derive(Copy, Clone)]
424pub struct NameType(c_int);
425
426impl NameType {
427 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
429
430 #[must_use]
432 pub fn from_raw(raw: c_int) -> StatusType {
433 StatusType(raw)
434 }
435
436 #[allow(clippy::trivially_copy_pass_by_ref)]
438 #[must_use]
439 pub fn as_raw(&self) -> c_int {
440 self.0
441 }
442}
443
444static INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
445 LazyLock::new(|| Mutex::new(HashMap::new()));
446static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
447 LazyLock::new(|| Mutex::new(HashMap::new()));
448static SESSION_CTX_INDEX: LazyLock<Index<Ssl, SslContext>> =
449 LazyLock::new(|| Ssl::new_ex_index().unwrap());
450#[cfg(feature = "rpk")]
451static RPK_FLAG_INDEX: LazyLock<Index<SslContext, bool>> =
452 LazyLock::new(|| SslContext::new_ex_index().unwrap());
453
454#[derive(Debug, Copy, Clone, PartialEq, Eq)]
456pub struct SniError(c_int);
457
458impl SniError {
459 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
461
462 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
464
465 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
466}
467
468#[derive(Debug, Copy, Clone, PartialEq, Eq)]
470pub struct SslAlert(c_int);
471
472impl SslAlert {
473 pub const CLOSE_NOTIFY: Self = Self(ffi::SSL_AD_CLOSE_NOTIFY);
474 pub const UNEXPECTED_MESSAGE: Self = Self(ffi::SSL_AD_UNEXPECTED_MESSAGE);
475 pub const BAD_RECORD_MAC: Self = Self(ffi::SSL_AD_BAD_RECORD_MAC);
476 pub const DECRYPTION_FAILED: Self = Self(ffi::SSL_AD_DECRYPTION_FAILED);
477 pub const RECORD_OVERFLOW: Self = Self(ffi::SSL_AD_RECORD_OVERFLOW);
478 pub const DECOMPRESSION_FAILURE: Self = Self(ffi::SSL_AD_DECOMPRESSION_FAILURE);
479 pub const HANDSHAKE_FAILURE: Self = Self(ffi::SSL_AD_HANDSHAKE_FAILURE);
480 pub const NO_CERTIFICATE: Self = Self(ffi::SSL_AD_NO_CERTIFICATE);
481 pub const BAD_CERTIFICATE: Self = Self(ffi::SSL_AD_BAD_CERTIFICATE);
482 pub const UNSUPPORTED_CERTIFICATE: Self = Self(ffi::SSL_AD_UNSUPPORTED_CERTIFICATE);
483 pub const CERTIFICATE_REVOKED: Self = Self(ffi::SSL_AD_CERTIFICATE_REVOKED);
484 pub const CERTIFICATE_EXPIRED: Self = Self(ffi::SSL_AD_CERTIFICATE_EXPIRED);
485 pub const CERTIFICATE_UNKNOWN: Self = Self(ffi::SSL_AD_CERTIFICATE_UNKNOWN);
486 pub const ILLEGAL_PARAMETER: Self = Self(ffi::SSL_AD_ILLEGAL_PARAMETER);
487 pub const UNKNOWN_CA: Self = Self(ffi::SSL_AD_UNKNOWN_CA);
488 pub const ACCESS_DENIED: Self = Self(ffi::SSL_AD_ACCESS_DENIED);
489 pub const DECODE_ERROR: Self = Self(ffi::SSL_AD_DECODE_ERROR);
490 pub const DECRYPT_ERROR: Self = Self(ffi::SSL_AD_DECRYPT_ERROR);
491 pub const EXPORT_RESTRICTION: Self = Self(ffi::SSL_AD_EXPORT_RESTRICTION);
492 pub const PROTOCOL_VERSION: Self = Self(ffi::SSL_AD_PROTOCOL_VERSION);
493 pub const INSUFFICIENT_SECURITY: Self = Self(ffi::SSL_AD_INSUFFICIENT_SECURITY);
494 pub const INTERNAL_ERROR: Self = Self(ffi::SSL_AD_INTERNAL_ERROR);
495 pub const INAPPROPRIATE_FALLBACK: Self = Self(ffi::SSL_AD_INAPPROPRIATE_FALLBACK);
496 pub const USER_CANCELLED: Self = Self(ffi::SSL_AD_USER_CANCELLED);
497 pub const NO_RENEGOTIATION: Self = Self(ffi::SSL_AD_NO_RENEGOTIATION);
498 pub const MISSING_EXTENSION: Self = Self(ffi::SSL_AD_MISSING_EXTENSION);
499 pub const UNSUPPORTED_EXTENSION: Self = Self(ffi::SSL_AD_UNSUPPORTED_EXTENSION);
500 pub const CERTIFICATE_UNOBTAINABLE: Self = Self(ffi::SSL_AD_CERTIFICATE_UNOBTAINABLE);
501 pub const UNRECOGNIZED_NAME: Self = Self(ffi::SSL_AD_UNRECOGNIZED_NAME);
502 pub const BAD_CERTIFICATE_STATUS_RESPONSE: Self =
503 Self(ffi::SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
504 pub const BAD_CERTIFICATE_HASH_VALUE: Self = Self(ffi::SSL_AD_BAD_CERTIFICATE_HASH_VALUE);
505 pub const UNKNOWN_PSK_IDENTITY: Self = Self(ffi::SSL_AD_UNKNOWN_PSK_IDENTITY);
506 pub const CERTIFICATE_REQUIRED: Self = Self(ffi::SSL_AD_CERTIFICATE_REQUIRED);
507 pub const NO_APPLICATION_PROTOCOL: Self = Self(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
508}
509
510#[derive(Debug, Copy, Clone, PartialEq, Eq)]
512pub struct AlpnError(c_int);
513
514impl AlpnError {
515 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
517
518 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
520}
521
522#[derive(Debug, Copy, Clone, PartialEq, Eq)]
524pub struct SelectCertError(ffi::ssl_select_cert_result_t);
525
526impl SelectCertError {
527 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_error);
529
530 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t::ssl_select_cert_retry);
532}
533
534#[derive(Debug, Copy, Clone, PartialEq, Eq)]
540pub struct ExtensionType(u16);
541
542impl ExtensionType {
543 pub const SERVER_NAME: Self = Self(ffi::TLSEXT_TYPE_server_name as u16);
544 pub const STATUS_REQUEST: Self = Self(ffi::TLSEXT_TYPE_status_request as u16);
545 pub const EC_POINT_FORMATS: Self = Self(ffi::TLSEXT_TYPE_ec_point_formats as u16);
546 pub const SIGNATURE_ALGORITHMS: Self = Self(ffi::TLSEXT_TYPE_signature_algorithms as u16);
547 pub const SRTP: Self = Self(ffi::TLSEXT_TYPE_srtp as u16);
548 pub const APPLICATION_LAYER_PROTOCOL_NEGOTIATION: Self =
549 Self(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as u16);
550 pub const PADDING: Self = Self(ffi::TLSEXT_TYPE_padding as u16);
551 pub const EXTENDED_MASTER_SECRET: Self = Self(ffi::TLSEXT_TYPE_extended_master_secret as u16);
552 pub const QUIC_TRANSPORT_PARAMETERS_LEGACY: Self =
553 Self(ffi::TLSEXT_TYPE_quic_transport_parameters_legacy as u16);
554 pub const QUIC_TRANSPORT_PARAMETERS_STANDARD: Self =
555 Self(ffi::TLSEXT_TYPE_quic_transport_parameters_standard as u16);
556 pub const CERT_COMPRESSION: Self = Self(ffi::TLSEXT_TYPE_cert_compression as u16);
557 pub const SESSION_TICKET: Self = Self(ffi::TLSEXT_TYPE_session_ticket as u16);
558 pub const SUPPORTED_GROUPS: Self = Self(ffi::TLSEXT_TYPE_supported_groups as u16);
559 pub const PRE_SHARED_KEY: Self = Self(ffi::TLSEXT_TYPE_pre_shared_key as u16);
560 pub const EARLY_DATA: Self = Self(ffi::TLSEXT_TYPE_early_data as u16);
561 pub const SUPPORTED_VERSIONS: Self = Self(ffi::TLSEXT_TYPE_supported_versions as u16);
562 pub const COOKIE: Self = Self(ffi::TLSEXT_TYPE_cookie as u16);
563 pub const PSK_KEY_EXCHANGE_MODES: Self = Self(ffi::TLSEXT_TYPE_psk_key_exchange_modes as u16);
564 pub const CERTIFICATE_AUTHORITIES: Self = Self(ffi::TLSEXT_TYPE_certificate_authorities as u16);
565 pub const SIGNATURE_ALGORITHMS_CERT: Self =
566 Self(ffi::TLSEXT_TYPE_signature_algorithms_cert as u16);
567 pub const KEY_SHARE: Self = Self(ffi::TLSEXT_TYPE_key_share as u16);
568 pub const RENEGOTIATE: Self = Self(ffi::TLSEXT_TYPE_renegotiate as u16);
569 pub const DELEGATED_CREDENTIAL: Self = Self(ffi::TLSEXT_TYPE_delegated_credential as u16);
570 pub const APPLICATION_SETTINGS: Self = Self(ffi::TLSEXT_TYPE_application_settings as u16);
571 pub const ENCRYPTED_CLIENT_HELLO: Self = Self(ffi::TLSEXT_TYPE_encrypted_client_hello as u16);
572 pub const CERTIFICATE_TIMESTAMP: Self = Self(ffi::TLSEXT_TYPE_certificate_timestamp as u16);
573 pub const NEXT_PROTO_NEG: Self = Self(ffi::TLSEXT_TYPE_next_proto_neg as u16);
574 pub const CHANNEL_ID: Self = Self(ffi::TLSEXT_TYPE_channel_id as u16);
575}
576
577impl From<u16> for ExtensionType {
578 fn from(value: u16) -> Self {
579 Self(value)
580 }
581}
582
583#[derive(Copy, Clone, PartialEq, Eq)]
585pub struct SslVersion(u16);
586
587impl SslVersion {
588 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION as _);
590
591 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION as _);
593
594 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION as _);
596
597 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION as _);
599
600 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION as _);
602}
603
604impl TryFrom<u16> for SslVersion {
605 type Error = &'static str;
606
607 fn try_from(value: u16) -> Result<Self, Self::Error> {
608 match i32::from(value) {
609 ffi::SSL3_VERSION
610 | ffi::TLS1_VERSION
611 | ffi::TLS1_1_VERSION
612 | ffi::TLS1_2_VERSION
613 | ffi::TLS1_3_VERSION => Ok(Self(value)),
614 _ => Err("Unknown SslVersion"),
615 }
616 }
617}
618
619impl fmt::Debug for SslVersion {
620 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
621 f.write_str(match *self {
622 Self::SSL3 => "SSL3",
623 Self::TLS1 => "TLS1",
624 Self::TLS1_1 => "TLS1_1",
625 Self::TLS1_2 => "TLS1_2",
626 Self::TLS1_3 => "TLS1_3",
627 _ => return write!(f, "{:#06x}", self.0),
628 })
629 }
630}
631
632impl fmt::Display for SslVersion {
633 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
634 f.write_str(match *self {
635 Self::SSL3 => "SSLv3",
636 Self::TLS1 => "TLSv1",
637 Self::TLS1_1 => "TLSv1.1",
638 Self::TLS1_2 => "TLSv1.2",
639 Self::TLS1_3 => "TLSv1.3",
640 _ => return write!(f, "unknown ({:#06x})", self.0),
641 })
642 }
643}
644
645#[repr(transparent)]
651#[derive(Debug, Copy, Clone, PartialEq, Eq)]
652pub struct SslSignatureAlgorithm(u16);
653
654impl SslSignatureAlgorithm {
655 pub const RSA_PKCS1_SHA1: SslSignatureAlgorithm =
656 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA1 as _);
657
658 pub const RSA_PKCS1_SHA256: SslSignatureAlgorithm =
659 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA256 as _);
660
661 pub const RSA_PKCS1_SHA384: SslSignatureAlgorithm =
662 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA384 as _);
663
664 pub const RSA_PKCS1_SHA512: SslSignatureAlgorithm =
665 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_SHA512 as _);
666
667 pub const RSA_PKCS1_MD5_SHA1: SslSignatureAlgorithm =
668 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PKCS1_MD5_SHA1 as _);
669
670 pub const ECDSA_SHA1: SslSignatureAlgorithm =
671 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SHA1 as _);
672
673 pub const ECDSA_SECP256R1_SHA256: SslSignatureAlgorithm =
674 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP256R1_SHA256 as _);
675
676 pub const ECDSA_SECP384R1_SHA384: SslSignatureAlgorithm =
677 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP384R1_SHA384 as _);
678
679 pub const ECDSA_SECP521R1_SHA512: SslSignatureAlgorithm =
680 SslSignatureAlgorithm(ffi::SSL_SIGN_ECDSA_SECP521R1_SHA512 as _);
681
682 pub const RSA_PSS_RSAE_SHA256: SslSignatureAlgorithm =
683 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA256 as _);
684
685 pub const RSA_PSS_RSAE_SHA384: SslSignatureAlgorithm =
686 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA384 as _);
687
688 pub const RSA_PSS_RSAE_SHA512: SslSignatureAlgorithm =
689 SslSignatureAlgorithm(ffi::SSL_SIGN_RSA_PSS_RSAE_SHA512 as _);
690
691 pub const ED25519: SslSignatureAlgorithm = SslSignatureAlgorithm(ffi::SSL_SIGN_ED25519 as _);
692}
693
694impl From<u16> for SslSignatureAlgorithm {
695 fn from(value: u16) -> Self {
696 Self(value)
697 }
698}
699
700#[repr(transparent)]
702#[derive(Debug, Copy, Clone, PartialEq, Eq)]
703pub struct SslCurveNid(c_int);
704
705#[repr(transparent)]
707#[derive(Debug, Copy, Clone, PartialEq, Eq)]
708pub struct SslCurve(c_int);
709
710impl SslCurve {
711 pub const SECP224R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP224R1 as _);
712
713 pub const SECP256R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP256R1 as _);
714
715 pub const SECP384R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP384R1 as _);
716
717 pub const SECP521R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP521R1 as _);
718
719 pub const X25519: SslCurve = SslCurve(ffi::SSL_CURVE_X25519 as _);
720
721 #[cfg(not(any(feature = "fips", feature = "fips-precompiled")))]
722 pub const X25519_KYBER768_DRAFT00: SslCurve =
723 SslCurve(ffi::SSL_CURVE_X25519_KYBER768_DRAFT00 as _);
724
725 #[cfg(all(
726 not(any(feature = "fips", feature = "fips-precompiled")),
727 feature = "pq-experimental"
728 ))]
729 pub const X25519_KYBER768_DRAFT00_OLD: SslCurve =
730 SslCurve(ffi::SSL_CURVE_X25519_KYBER768_DRAFT00_OLD as _);
731
732 #[cfg(all(
733 not(any(feature = "fips", feature = "fips-precompiled")),
734 feature = "pq-experimental"
735 ))]
736 pub const X25519_KYBER512_DRAFT00: SslCurve =
737 SslCurve(ffi::SSL_CURVE_X25519_KYBER512_DRAFT00 as _);
738
739 #[cfg(all(
740 not(any(feature = "fips", feature = "fips-precompiled")),
741 feature = "pq-experimental"
742 ))]
743 pub const P256_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::SSL_CURVE_P256_KYBER768_DRAFT00 as _);
744
745 #[cfg(all(
746 not(any(feature = "fips", feature = "fips-precompiled")),
747 feature = "pq-experimental"
748 ))]
749 pub const X25519_MLKEM768: SslCurve = SslCurve(ffi::SSL_CURVE_X25519_MLKEM768 as _);
750
751 #[corresponds(SSL_get_curve_name)]
753 #[must_use]
754 pub fn name(&self) -> Option<&'static str> {
755 unsafe {
756 let ptr = ffi::SSL_get_curve_name(self.0 as u16);
757 if ptr.is_null() {
758 return None;
759 }
760
761 CStr::from_ptr(ptr).to_str().ok()
762 }
763 }
764
765 #[allow(dead_code)]
775 pub fn nid(&self) -> Option<SslCurveNid> {
776 match self.0 {
777 ffi::SSL_CURVE_SECP224R1 => Some(ffi::NID_secp224r1),
778 ffi::SSL_CURVE_SECP256R1 => Some(ffi::NID_X9_62_prime256v1),
779 ffi::SSL_CURVE_SECP384R1 => Some(ffi::NID_secp384r1),
780 ffi::SSL_CURVE_SECP521R1 => Some(ffi::NID_secp521r1),
781 ffi::SSL_CURVE_X25519 => Some(ffi::NID_X25519),
782 #[cfg(not(any(feature = "fips", feature = "fips-precompiled")))]
783 ffi::SSL_CURVE_X25519_KYBER768_DRAFT00 => Some(ffi::NID_X25519Kyber768Draft00),
784 #[cfg(all(
785 not(any(feature = "fips", feature = "fips-precompiled")),
786 feature = "pq-experimental"
787 ))]
788 ffi::SSL_CURVE_X25519_KYBER768_DRAFT00_OLD => Some(ffi::NID_X25519Kyber768Draft00Old),
789 #[cfg(all(
790 not(any(feature = "fips", feature = "fips-precompiled")),
791 feature = "pq-experimental"
792 ))]
793 ffi::SSL_CURVE_X25519_KYBER512_DRAFT00 => Some(ffi::NID_X25519Kyber512Draft00),
794 #[cfg(all(
795 not(any(feature = "fips", feature = "fips-precompiled")),
796 feature = "pq-experimental"
797 ))]
798 ffi::SSL_CURVE_P256_KYBER768_DRAFT00 => Some(ffi::NID_P256Kyber768Draft00),
799 #[cfg(all(
800 not(any(feature = "fips", feature = "fips-precompiled")),
801 feature = "pq-experimental"
802 ))]
803 ffi::SSL_CURVE_X25519_MLKEM768 => Some(ffi::NID_X25519MLKEM768),
804 _ => None,
805 }
806 .map(SslCurveNid)
807 }
808}
809
810#[derive(Debug, Copy, Clone, PartialEq, Eq)]
812#[cfg(not(feature = "fips-compat"))]
813pub struct CompliancePolicy(ffi::ssl_compliance_policy_t);
814
815#[cfg(not(feature = "fips-compat"))]
816impl CompliancePolicy {
817 pub const NONE: Self = Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_none);
819
820 pub const FIPS_202205: Self =
823 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_fips_202205);
824
825 pub const WPA3_192_202304: Self =
828 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_wpa3_192_202304);
829}
830
831#[derive(Debug, Copy, Clone, PartialEq, Eq)]
833pub struct CertificateCompressionAlgorithm(u16);
834
835impl CertificateCompressionAlgorithm {
836 pub const ZLIB: Self = Self(ffi::TLSEXT_cert_compression_zlib as u16);
837
838 pub const BROTLI: Self = Self(ffi::TLSEXT_cert_compression_brotli as u16);
839}
840
841#[corresponds(SSL_select_next_proto)]
852#[must_use]
853pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
854 if server.is_empty() || client.is_empty() {
855 return None;
856 }
857
858 unsafe {
859 let mut out = ptr::null_mut();
860 let mut outlen = 0;
861 let r = ffi::SSL_select_next_proto(
862 &mut out,
863 &mut outlen,
864 server.as_ptr(),
865 server.len() as c_uint,
866 client.as_ptr(),
867 client.len() as c_uint,
868 );
869
870 if r == ffi::OPENSSL_NPN_NEGOTIATED {
871 Some(slice::from_raw_parts(out as *const u8, outlen as usize))
872 } else {
873 None
874 }
875 }
876}
877
878#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
880pub struct SslInfoCallbackMode(i32);
881
882impl SslInfoCallbackMode {
883 pub const READ_ALERT: Self = Self(ffi::SSL_CB_READ_ALERT);
885
886 pub const WRITE_ALERT: Self = Self(ffi::SSL_CB_WRITE_ALERT);
888
889 pub const HANDSHAKE_START: Self = Self(ffi::SSL_CB_HANDSHAKE_START);
891
892 pub const HANDSHAKE_DONE: Self = Self(ffi::SSL_CB_HANDSHAKE_DONE);
894
895 pub const ACCEPT_LOOP: Self = Self(ffi::SSL_CB_ACCEPT_LOOP);
897
898 pub const ACCEPT_EXIT: Self = Self(ffi::SSL_CB_ACCEPT_EXIT);
900
901 pub const CONNECT_EXIT: Self = Self(ffi::SSL_CB_CONNECT_EXIT);
903}
904
905#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
908pub enum SslInfoCallbackValue {
909 Unit,
913 Alert(SslInfoCallbackAlert),
917}
918
919#[derive(Hash, Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
920pub struct SslInfoCallbackAlert(c_int);
921
922impl SslInfoCallbackAlert {
923 #[must_use]
925 pub fn alert_level(&self) -> Ssl3AlertLevel {
926 let value = self.0 >> 8;
927 Ssl3AlertLevel(value)
928 }
929
930 #[must_use]
932 pub fn alert(&self) -> SslAlert {
933 let value = self.0 & i32::from(u8::MAX);
934 SslAlert(value)
935 }
936}
937
938#[derive(Debug, Copy, Clone, PartialEq, Eq)]
939pub struct Ssl3AlertLevel(c_int);
940
941impl Ssl3AlertLevel {
942 pub const WARNING: Ssl3AlertLevel = Self(ffi::SSL3_AL_WARNING);
943 pub const FATAL: Ssl3AlertLevel = Self(ffi::SSL3_AL_FATAL);
944}
945
946#[cfg(feature = "rpk")]
947extern "C" fn rpk_verify_failure_callback(
948 _ssl: *mut ffi::SSL,
949 _out_alert: *mut u8,
950) -> ffi::ssl_verify_result_t {
951 ffi::ssl_verify_result_t::ssl_verify_invalid
953}
954
955pub struct SslContextBuilder {
957 ctx: SslContext,
958 has_shared_cert_store: bool,
960 #[cfg(feature = "rpk")]
961 is_rpk: bool,
962}
963
964#[cfg(feature = "rpk")]
965impl SslContextBuilder {
966 #[corresponds(SSL_CTX_new)]
968 pub fn new_rpk() -> Result<SslContextBuilder, ErrorStack> {
969 unsafe {
970 init();
971 let ctx = cvt_p(ffi::SSL_CTX_new(SslMethod::tls_with_buffer().as_ptr()))?;
972
973 Ok(SslContextBuilder::from_ptr(ctx, true))
974 }
975 }
976
977 pub fn set_rpk_certificate(&mut self, cert: &[u8]) -> Result<(), ErrorStack> {
979 unsafe {
980 cvt(ffi::SSL_CTX_set_server_raw_public_key_certificate(
981 self.as_ptr(),
982 cert.as_ptr(),
983 cert.len() as u32,
984 ))
985 .map(|_| ())
986 }
987 }
988
989 pub fn set_null_chain_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
991 where
992 T: HasPrivate,
993 {
994 unsafe {
995 cvt(ffi::SSL_CTX_set_nullchain_and_key(
996 self.as_ptr(),
997 key.as_ptr(),
998 ptr::null_mut(),
999 ))
1000 .map(|_| ())
1001 }
1002 }
1003}
1004
1005impl SslContextBuilder {
1006 #[corresponds(SSL_CTX_new)]
1008 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1009 unsafe {
1010 init();
1011 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
1012
1013 #[cfg(feature = "rpk")]
1014 {
1015 Ok(SslContextBuilder::from_ptr(ctx, false))
1016 }
1017
1018 #[cfg(not(feature = "rpk"))]
1019 {
1020 Ok(SslContextBuilder::from_ptr(ctx))
1021 }
1022 }
1023 }
1024
1025 #[cfg(feature = "rpk")]
1031 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX, is_rpk: bool) -> SslContextBuilder {
1032 let ctx = SslContext::from_ptr(ctx);
1033 let mut builder = SslContextBuilder {
1034 ctx,
1035 is_rpk,
1036 has_shared_cert_store: false,
1037 };
1038
1039 builder.set_ex_data(*RPK_FLAG_INDEX, is_rpk);
1040
1041 builder
1042 }
1043
1044 #[cfg(not(feature = "rpk"))]
1050 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
1051 SslContextBuilder {
1052 ctx: SslContext::from_ptr(ctx),
1053 has_shared_cert_store: false,
1054 }
1055 }
1056
1057 #[must_use]
1059 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
1060 self.ctx.as_ptr()
1061 }
1062
1063 #[corresponds(SSL_CTX_set_cert_verify_callback)]
1083 pub fn set_cert_verify_callback<F>(&mut self, callback: F)
1084 where
1085 F: Fn(&mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1086 {
1087 #[cfg(feature = "rpk")]
1088 assert!(!self.is_rpk, "This API is not supported for RPK");
1089
1090 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1097 unsafe {
1098 ffi::SSL_CTX_set_cert_verify_callback(
1099 self.as_ptr(),
1100 Some(raw_cert_verify::<F>),
1101 ptr::null_mut(),
1102 );
1103 }
1104 }
1105
1106 #[corresponds(SSL_CTX_set_verify)]
1108 pub fn set_verify(&mut self, mode: SslVerifyMode) {
1109 #[cfg(feature = "rpk")]
1110 assert!(!self.is_rpk, "This API is not supported for RPK");
1111
1112 unsafe {
1113 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
1114 }
1115 }
1116
1117 #[corresponds(SSL_CTX_set_verify)]
1134 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1135 where
1136 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1137 {
1138 #[cfg(feature = "rpk")]
1139 assert!(!self.is_rpk, "This API is not supported for RPK");
1140
1141 unsafe {
1142 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1143 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
1144 }
1145 }
1146
1147 #[corresponds(SSL_CTX_set_custom_verify)]
1162 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1163 where
1164 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
1165 {
1166 #[cfg(feature = "rpk")]
1167 assert!(!self.is_rpk, "This API is not supported for RPK");
1168
1169 unsafe {
1170 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1171 ffi::SSL_CTX_set_custom_verify(
1172 self.as_ptr(),
1173 mode.bits() as c_int,
1174 Some(raw_custom_verify::<F>),
1175 );
1176 }
1177 }
1178
1179 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
1189 pub fn set_servername_callback<F>(&mut self, callback: F)
1190 where
1191 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
1192 {
1193 unsafe {
1194 let callback_index = SslContext::cached_ex_index::<F>();
1201
1202 self.ctx.replace_ex_data(callback_index, callback);
1203
1204 let arg = self.ctx.ex_data(callback_index).unwrap() as *const F as *mut c_void;
1205
1206 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
1207 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
1208 }
1209 }
1210
1211 #[corresponds(SSL_CTX_set_verify_depth)]
1215 pub fn set_verify_depth(&mut self, depth: u32) {
1216 #[cfg(feature = "rpk")]
1217 assert!(!self.is_rpk, "This API is not supported for RPK");
1218
1219 unsafe {
1220 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
1221 }
1222 }
1223
1224 #[corresponds(SSL_CTX_set0_verify_cert_store)]
1226 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
1227 #[cfg(feature = "rpk")]
1228 assert!(!self.is_rpk, "This API is not supported for RPK");
1229
1230 unsafe {
1231 cvt(
1232 ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int,
1233 )?;
1234
1235 Ok(())
1236 }
1237 }
1238
1239 #[corresponds(SSL_CTX_set_cert_store)]
1243 #[deprecated(note = "Use set_cert_store_builder or set_cert_store_ref instead")]
1244 pub fn set_cert_store(&mut self, cert_store: X509Store) {
1245 #[cfg(feature = "rpk")]
1246 assert!(!self.is_rpk, "This API is not supported for RPK");
1247
1248 self.has_shared_cert_store = false;
1249 unsafe {
1250 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1251 }
1252 }
1253
1254 #[corresponds(SSL_CTX_set_cert_store)]
1256 pub fn set_cert_store_builder(&mut self, cert_store: X509StoreBuilder) {
1257 #[cfg(feature = "rpk")]
1258 assert!(!self.is_rpk, "This API is not supported for RPK");
1259
1260 self.has_shared_cert_store = false;
1261 unsafe {
1262 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1263 }
1264 }
1265
1266 #[corresponds(SSL_CTX_set_cert_store)]
1270 pub fn set_cert_store_ref(&mut self, cert_store: &X509Store) {
1271 #[cfg(feature = "rpk")]
1272 assert!(!self.is_rpk, "This API is not supported for RPK");
1273
1274 self.has_shared_cert_store = true;
1275 unsafe {
1276 ffi::X509_STORE_up_ref(cert_store.as_ptr());
1277 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
1278 }
1279 }
1280
1281 #[corresponds(SSL_CTX_set_read_ahead)]
1288 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1289 unsafe {
1290 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), c_int::from(read_ahead));
1291 }
1292 }
1293
1294 #[corresponds(SSL_CTX_set_mode)]
1296 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1297 let bits = unsafe { ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits()) };
1298 SslMode::from_bits_retain(bits)
1299 }
1300
1301 #[corresponds(SSL_CTX_set_tmp_dh)]
1303 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1304 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1305 }
1306
1307 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1309 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1310 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1311 }
1312
1313 #[corresponds(SSL_CTX_set_default_verify_paths)]
1318 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1319 #[cfg(feature = "rpk")]
1320 assert!(!self.is_rpk, "This API is not supported for RPK");
1321
1322 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1323 }
1324
1325 #[corresponds(SSL_CTX_load_verify_locations)]
1329 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1330 #[cfg(feature = "rpk")]
1331 assert!(!self.is_rpk, "This API is not supported for RPK");
1332
1333 let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
1334 .map_err(ErrorStack::internal_error)?;
1335 unsafe {
1336 cvt(ffi::SSL_CTX_load_verify_locations(
1337 self.as_ptr(),
1338 file.as_ptr() as *const _,
1339 ptr::null(),
1340 ))
1341 .map(|_| ())
1342 }
1343 }
1344
1345 #[corresponds(SSL_CTX_set_client_CA_list)]
1350 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1351 #[cfg(feature = "rpk")]
1352 assert!(!self.is_rpk, "This API is not supported for RPK");
1353
1354 unsafe {
1355 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1356 mem::forget(list);
1357 }
1358 }
1359
1360 #[corresponds(SSL_CTX_add_client_CA)]
1363 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1364 #[cfg(feature = "rpk")]
1365 assert!(!self.is_rpk, "This API is not supported for RPK");
1366
1367 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1368 }
1369
1370 #[corresponds(SSL_CTX_set_session_id_context)]
1379 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1380 unsafe {
1381 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1382 cvt(ffi::SSL_CTX_set_session_id_context(
1383 self.as_ptr(),
1384 sid_ctx.as_ptr(),
1385 sid_ctx.len(),
1386 ))
1387 .map(|_| ())
1388 }
1389 }
1390
1391 #[corresponds(SSL_CTX_use_certificate_file)]
1397 pub fn set_certificate_file<P: AsRef<Path>>(
1398 &mut self,
1399 file: P,
1400 file_type: SslFiletype,
1401 ) -> Result<(), ErrorStack> {
1402 #[cfg(feature = "rpk")]
1403 assert!(!self.is_rpk, "This API is not supported for RPK");
1404
1405 let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
1406 .map_err(ErrorStack::internal_error)?;
1407 unsafe {
1408 cvt(ffi::SSL_CTX_use_certificate_file(
1409 self.as_ptr(),
1410 file.as_ptr() as *const _,
1411 file_type.as_raw(),
1412 ))
1413 .map(|_| ())
1414 }
1415 }
1416
1417 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1423 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1424 &mut self,
1425 file: P,
1426 ) -> Result<(), ErrorStack> {
1427 let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
1428 .map_err(ErrorStack::internal_error)?;
1429 unsafe {
1430 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1431 self.as_ptr(),
1432 file.as_ptr() as *const _,
1433 ))
1434 .map(|_| ())
1435 }
1436 }
1437
1438 #[corresponds(SSL_CTX_use_certificate)]
1442 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1443 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1444 }
1445
1446 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1451 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1452 #[cfg(feature = "rpk")]
1453 assert!(!self.is_rpk, "This API is not supported for RPK");
1454
1455 unsafe {
1456 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.into_ptr()) as c_int)?;
1457 Ok(())
1458 }
1459 }
1460
1461 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1463 pub fn set_private_key_file<P: AsRef<Path>>(
1464 &mut self,
1465 file: P,
1466 file_type: SslFiletype,
1467 ) -> Result<(), ErrorStack> {
1468 let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
1469 .map_err(ErrorStack::internal_error)?;
1470 unsafe {
1471 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1472 self.as_ptr(),
1473 file.as_ptr() as *const _,
1474 file_type.as_raw(),
1475 ))
1476 .map(|_| ())
1477 }
1478 }
1479
1480 #[corresponds(SSL_CTX_use_PrivateKey)]
1482 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1483 where
1484 T: HasPrivate,
1485 {
1486 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1487 }
1488
1489 #[corresponds(SSL_CTX_set_cipher_list)]
1499 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1500 let cipher_list = CString::new(cipher_list).unwrap();
1501 unsafe {
1502 cvt(ffi::SSL_CTX_set_cipher_list(
1503 self.as_ptr(),
1504 cipher_list.as_ptr() as *const _,
1505 ))
1506 .map(|_| ())
1507 }
1508 }
1509
1510 #[corresponds(SSL_CTX_get_ciphers)]
1516 #[must_use]
1517 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
1518 self.ctx.ciphers()
1519 }
1520
1521 #[corresponds(SSL_CTX_set_options)]
1528 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1529 let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
1530 SslOptions::from_bits_retain(bits)
1531 }
1532
1533 #[corresponds(SSL_CTX_get_options)]
1535 #[must_use]
1536 pub fn options(&self) -> SslOptions {
1537 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
1538 SslOptions::from_bits_retain(bits)
1539 }
1540
1541 #[corresponds(SSL_CTX_clear_options)]
1543 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1544 let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
1545 SslOptions::from_bits_retain(bits)
1546 }
1547
1548 #[corresponds(SSL_CTX_set_min_proto_version)]
1553 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1554 unsafe {
1555 cvt(ffi::SSL_CTX_set_min_proto_version(
1556 self.as_ptr(),
1557 version.map_or(0, |v| v.0 as _),
1558 ))
1559 .map(|_| ())
1560 }
1561 }
1562
1563 #[corresponds(SSL_CTX_set_max_proto_version)]
1567 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1568 unsafe {
1569 cvt(ffi::SSL_CTX_set_max_proto_version(
1570 self.as_ptr(),
1571 version.map_or(0, |v| v.0 as _),
1572 ))
1573 .map(|_| ())
1574 }
1575 }
1576
1577 #[corresponds(SSL_CTX_get_min_proto_version)]
1579 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1580 unsafe {
1581 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1582 if r == 0 {
1583 None
1584 } else {
1585 Some(SslVersion(r))
1586 }
1587 }
1588 }
1589
1590 #[corresponds(SSL_CTX_get_max_proto_version)]
1592 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1593 unsafe {
1594 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1595 if r == 0 {
1596 None
1597 } else {
1598 Some(SslVersion(r))
1599 }
1600 }
1601 }
1602
1603 #[corresponds(SSL_CTX_set_alpn_protos)]
1610 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1611 unsafe {
1612 #[cfg_attr(not(feature = "fips-compat"), allow(clippy::unnecessary_cast))]
1613 {
1614 assert!(protocols.len() <= ProtosLen::MAX as usize);
1615 }
1616 let r = ffi::SSL_CTX_set_alpn_protos(
1617 self.as_ptr(),
1618 protocols.as_ptr(),
1619 protocols.len() as ProtosLen,
1620 );
1621 if r == 0 {
1623 Ok(())
1624 } else {
1625 Err(ErrorStack::get())
1626 }
1627 }
1628 }
1629
1630 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1632 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1633 unsafe {
1634 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
1635
1636 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1637 if r == 0 {
1639 Ok(())
1640 } else {
1641 Err(ErrorStack::get())
1642 }
1643 }
1644 }
1645
1646 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1657 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1658 where
1659 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1660 {
1661 unsafe {
1662 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1663 ffi::SSL_CTX_set_alpn_select_cb(
1664 self.as_ptr(),
1665 Some(callbacks::raw_alpn_select::<F>),
1666 ptr::null_mut(),
1667 );
1668 }
1669 }
1670
1671 #[corresponds(SSL_CTX_set_select_certificate_cb)]
1675 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
1676 where
1677 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
1678 {
1679 unsafe {
1680 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1681 ffi::SSL_CTX_set_select_certificate_cb(
1682 self.as_ptr(),
1683 Some(callbacks::raw_select_cert::<F>),
1684 );
1685 }
1686 }
1687
1688 #[corresponds(SSL_CTX_add_cert_compression_alg)]
1692 pub fn add_certificate_compression_algorithm<C>(
1693 &mut self,
1694 compressor: C,
1695 ) -> Result<(), ErrorStack>
1696 where
1697 C: CertificateCompressor,
1698 {
1699 const {
1700 assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered")
1701 };
1702 let success = unsafe {
1703 ffi::SSL_CTX_add_cert_compression_alg(
1704 self.as_ptr(),
1705 C::ALGORITHM.0,
1706 const {
1707 if C::CAN_COMPRESS {
1708 Some(callbacks::raw_ssl_cert_compress::<C>)
1709 } else {
1710 None
1711 }
1712 },
1713 const {
1714 if C::CAN_DECOMPRESS {
1715 Some(callbacks::raw_ssl_cert_decompress::<C>)
1716 } else {
1717 None
1718 }
1719 },
1720 ) == 1
1721 };
1722 if !success {
1723 return Err(ErrorStack::get());
1724 }
1725 self.replace_ex_data(SslContext::cached_ex_index::<C>(), compressor);
1726 Ok(())
1727 }
1728
1729 #[corresponds(SSL_CTX_set_private_key_method)]
1733 pub fn set_private_key_method<M>(&mut self, method: M)
1734 where
1735 M: PrivateKeyMethod,
1736 {
1737 unsafe {
1738 self.replace_ex_data(SslContext::cached_ex_index::<M>(), method);
1739
1740 ffi::SSL_CTX_set_private_key_method(
1741 self.as_ptr(),
1742 &ffi::SSL_PRIVATE_KEY_METHOD {
1743 sign: Some(callbacks::raw_sign::<M>),
1744 decrypt: Some(callbacks::raw_decrypt::<M>),
1745 complete: Some(callbacks::raw_complete::<M>),
1746 },
1747 )
1748 }
1749 }
1750
1751 #[corresponds(SSL_CTX_check_private_key)]
1753 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1754 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1755 }
1756
1757 #[corresponds(SSL_CTX_get_cert_store)]
1759 #[must_use]
1760 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1761 #[cfg(feature = "rpk")]
1762 assert!(!self.is_rpk, "This API is not supported for RPK");
1763
1764 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1765 }
1766
1767 #[corresponds(SSL_CTX_get_cert_store)]
1777 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1778 #[cfg(feature = "rpk")]
1779 assert!(!self.is_rpk, "This API is not supported for RPK");
1780
1781 assert!(
1782 !self.has_shared_cert_store,
1783 "Shared X509Store can't be mutated. Make a new store"
1784 );
1785 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1788 }
1789
1790 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1803 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1804 where
1805 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1806 {
1807 unsafe {
1808 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1809 cvt(
1810 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1811 as c_int,
1812 )
1813 .map(|_| ())
1814 }
1815 }
1816
1817 #[corresponds(SSL_CTX_set_psk_client_callback)]
1823 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1824 where
1825 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1826 + 'static
1827 + Sync
1828 + Send,
1829 {
1830 unsafe {
1831 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1832 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1833 }
1834 }
1835
1836 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1837 pub fn set_psk_callback<F>(&mut self, callback: F)
1838 where
1839 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1840 + 'static
1841 + Sync
1842 + Send,
1843 {
1844 self.set_psk_client_callback(callback)
1845 }
1846
1847 #[corresponds(SSL_CTX_set_psk_server_callback)]
1853 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1854 where
1855 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1856 + 'static
1857 + Sync
1858 + Send,
1859 {
1860 unsafe {
1861 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1862 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1863 }
1864 }
1865
1866 #[corresponds(SSL_CTX_sess_set_new_cb)]
1880 pub fn set_new_session_callback<F>(&mut self, callback: F)
1881 where
1882 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1883 {
1884 unsafe {
1885 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1886 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1887 }
1888 }
1889
1890 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1894 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1895 where
1896 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1897 {
1898 unsafe {
1899 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1900 ffi::SSL_CTX_sess_set_remove_cb(
1901 self.as_ptr(),
1902 Some(callbacks::raw_remove_session::<F>),
1903 );
1904 }
1905 }
1906
1907 #[corresponds(SSL_CTX_sess_set_get_cb)]
1918 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1919 where
1920 F: Fn(&mut SslRef, &[u8]) -> Result<Option<SslSession>, GetSessionPendingError>
1921 + 'static
1922 + Sync
1923 + Send,
1924 {
1925 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1926 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1927 }
1928
1929 #[corresponds(SSL_CTX_set_keylog_callback)]
1935 pub fn set_keylog_callback<F>(&mut self, callback: F)
1936 where
1937 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1938 {
1939 unsafe {
1940 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1941 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1942 }
1943 }
1944
1945 #[corresponds(SSL_CTX_set_session_cache_mode)]
1949 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1950 unsafe {
1951 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1952 SslSessionCacheMode::from_bits_retain(bits)
1953 }
1954 }
1955
1956 #[corresponds(SSL_CTX_set_ex_data)]
1964 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1965 unsafe {
1966 self.ctx.set_ex_data(index, data);
1967 }
1968 }
1969
1970 #[corresponds(SSL_CTX_set_ex_data)]
1977 pub fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
1978 unsafe { self.ctx.replace_ex_data(index, data) }
1979 }
1980
1981 #[corresponds(SSL_CTX_sess_set_cache_size)]
1985 #[allow(clippy::useless_conversion)]
1986 pub fn set_session_cache_size(&mut self, size: u32) -> u64 {
1987 unsafe { ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size.into()).into() }
1988 }
1989
1990 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1992 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1993 let sigalgs = CString::new(sigalgs).map_err(ErrorStack::internal_error)?;
1994 unsafe {
1995 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1996 .map(|_| ())
1997 }
1998 }
1999
2000 #[corresponds(SSL_CTX_set_grease_enabled)]
2002 pub fn set_grease_enabled(&mut self, enabled: bool) {
2003 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as _) }
2004 }
2005
2006 #[corresponds(SSL_CTX_set_permute_extensions)]
2012 #[cfg(not(feature = "fips-compat"))]
2013 pub fn set_permute_extensions(&mut self, enabled: bool) {
2014 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as _) }
2015 }
2016
2017 #[corresponds(SSL_CTX_set_verify_algorithm_prefs)]
2019 pub fn set_verify_algorithm_prefs(
2020 &mut self,
2021 prefs: &[SslSignatureAlgorithm],
2022 ) -> Result<(), ErrorStack> {
2023 unsafe {
2024 cvt_0i(ffi::SSL_CTX_set_verify_algorithm_prefs(
2025 self.as_ptr(),
2026 prefs.as_ptr() as *const _,
2027 prefs.len(),
2028 ))
2029 .map(|_| ())
2030 }
2031 }
2032
2033 #[corresponds(SSL_CTX_enable_signed_cert_timestamps)]
2035 pub fn enable_signed_cert_timestamps(&mut self) {
2036 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
2037 }
2038
2039 #[corresponds(SSL_CTX_enable_ocsp_stapling)]
2041 pub fn enable_ocsp_stapling(&mut self) {
2042 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
2043 }
2044
2045 #[cfg(not(feature = "kx-safe-default"))]
2051 #[corresponds(SSL_CTX_set1_curves_list)]
2052 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2053 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2054 unsafe {
2055 cvt_0i(ffi::SSL_CTX_set1_curves_list(
2056 self.as_ptr(),
2057 curves.as_ptr() as *const _,
2058 ))
2059 .map(|_| ())
2060 }
2061 }
2062
2063 #[corresponds(SSL_CTX_set1_curves)]
2069 #[cfg(not(feature = "kx-safe-default"))]
2070 pub fn set_curves(&mut self, curves: &[SslCurve]) -> Result<(), ErrorStack> {
2071 let curves: Vec<i32> = curves
2072 .iter()
2073 .filter_map(|curve| curve.nid().map(|nid| nid.0))
2074 .collect();
2075
2076 unsafe {
2077 cvt_0i(ffi::SSL_CTX_set1_curves(
2078 self.as_ptr(),
2079 curves.as_ptr() as *const _,
2080 curves.len(),
2081 ))
2082 .map(|_| ())
2083 }
2084 }
2085
2086 #[corresponds(SSL_CTX_set_compliance_policy)]
2090 #[cfg(not(feature = "fips-compat"))]
2091 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
2092 unsafe { cvt_0i(ffi::SSL_CTX_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
2093 }
2094
2095 #[corresponds(SSL_CTX_set_info_callback)]
2097 pub fn set_info_callback<F>(&mut self, callback: F)
2098 where
2099 F: Fn(&SslRef, SslInfoCallbackMode, SslInfoCallbackValue) + Send + Sync + 'static,
2100 {
2101 unsafe {
2102 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
2103 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info_callback::<F>));
2104 }
2105 }
2106
2107 #[cfg(not(feature = "fips"))]
2112 #[corresponds(SSL_CTX_set1_ech_keys)]
2113 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2114 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())).map(|_| ()) }
2115 }
2116
2117 #[must_use]
2119 pub fn build(self) -> SslContext {
2120 self.ctx
2121 }
2122}
2123
2124foreign_type_and_impl_send_sync! {
2125 type CType = ffi::SSL_CTX;
2126 fn drop = ffi::SSL_CTX_free;
2127
2128 pub struct SslContext;
2133}
2134
2135impl Clone for SslContext {
2136 fn clone(&self) -> Self {
2137 (**self).to_owned()
2138 }
2139}
2140
2141impl ToOwned for SslContextRef {
2142 type Owned = SslContext;
2143
2144 fn to_owned(&self) -> Self::Owned {
2145 unsafe {
2146 SSL_CTX_up_ref(self.as_ptr());
2147 SslContext::from_ptr(self.as_ptr())
2148 }
2149 }
2150}
2151
2152impl fmt::Debug for SslContext {
2154 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2155 write!(fmt, "SslContext")
2156 }
2157}
2158
2159impl SslContext {
2160 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2162 SslContextBuilder::new(method)
2163 }
2164
2165 #[corresponds(SSL_CTX_get_ex_new_index)]
2170 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2171 where
2172 T: 'static + Sync + Send,
2173 {
2174 unsafe {
2175 ffi::init();
2176 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2177 Ok(Index::from_raw(idx))
2178 }
2179 }
2180
2181 fn cached_ex_index<T>() -> Index<SslContext, T>
2183 where
2184 T: 'static + Sync + Send,
2185 {
2186 unsafe {
2187 let idx = *INDEXES
2188 .lock()
2189 .unwrap_or_else(|e| e.into_inner())
2190 .entry(TypeId::of::<T>())
2191 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2192 Index::from_raw(idx)
2193 }
2194 }
2195
2196 #[corresponds(SSL_CTX_get_ciphers)]
2202 #[must_use]
2203 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
2204 unsafe {
2205 let ciphers = ffi::SSL_CTX_get_ciphers(self.as_ptr());
2206 if ciphers.is_null() {
2207 None
2208 } else {
2209 Some(StackRef::from_ptr(ciphers))
2210 }
2211 }
2212 }
2213}
2214
2215impl SslContextRef {
2216 #[corresponds(SSL_CTX_get0_certificate)]
2218 #[must_use]
2219 pub fn certificate(&self) -> Option<&X509Ref> {
2220 #[cfg(feature = "rpk")]
2221 assert!(!self.is_rpk(), "This API is not supported for RPK");
2222
2223 unsafe {
2224 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2225 if ptr.is_null() {
2226 None
2227 } else {
2228 Some(X509Ref::from_ptr(ptr))
2229 }
2230 }
2231 }
2232
2233 #[corresponds(SSL_CTX_get0_privatekey)]
2235 #[must_use]
2236 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2237 unsafe {
2238 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2239 if ptr.is_null() {
2240 None
2241 } else {
2242 Some(PKeyRef::from_ptr(ptr))
2243 }
2244 }
2245 }
2246
2247 #[corresponds(SSL_CTX_get_cert_store)]
2249 #[must_use]
2250 pub fn cert_store(&self) -> &X509StoreRef {
2251 #[cfg(feature = "rpk")]
2252 assert!(!self.is_rpk(), "This API is not supported for RPK");
2253
2254 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2255 }
2256
2257 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2259 #[must_use]
2260 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2261 unsafe {
2262 let mut chain = ptr::null_mut();
2263 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2264 assert!(!chain.is_null());
2265 StackRef::from_ptr(chain)
2266 }
2267 }
2268
2269 #[corresponds(SSL_CTX_get_ex_data)]
2271 #[must_use]
2272 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2273 unsafe {
2274 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2275 if data.is_null() {
2276 None
2277 } else {
2278 Some(&*(data as *const T))
2279 }
2280 }
2281 }
2282
2283 #[corresponds(SSL_CTX_get_ex_data)]
2286 unsafe fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2287 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2288 if data.is_null() {
2289 None
2290 } else {
2291 Some(&mut *(data as *mut T))
2292 }
2293 }
2294
2295 #[corresponds(SSL_CTX_set_ex_data)]
2298 unsafe fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2299 unsafe {
2300 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2301 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2302 }
2303 }
2304
2305 #[corresponds(SSL_CTX_set_ex_data)]
2308 unsafe fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2309 if let Some(old) = self.ex_data_mut(index) {
2310 return Some(mem::replace(old, data));
2311 }
2312
2313 self.set_ex_data(index, data);
2314
2315 None
2316 }
2317
2318 #[corresponds(SSL_CTX_add_session)]
2327 #[must_use]
2328 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2329 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2330 }
2331
2332 #[corresponds(SSL_CTX_remove_session)]
2341 #[must_use]
2342 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2343 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2344 }
2345
2346 #[corresponds(SSL_CTX_sess_get_cache_size)]
2350 #[allow(clippy::useless_conversion)]
2351 #[must_use]
2352 pub fn session_cache_size(&self) -> u64 {
2353 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()).into() }
2354 }
2355
2356 #[corresponds(SSL_CTX_get_verify_mode)]
2360 #[must_use]
2361 pub fn verify_mode(&self) -> SslVerifyMode {
2362 #[cfg(feature = "rpk")]
2363 assert!(!self.is_rpk(), "This API is not supported for RPK");
2364
2365 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2366 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2367 }
2368
2369 #[cfg(feature = "rpk")]
2371 pub fn is_rpk(&self) -> bool {
2372 self.ex_data(*RPK_FLAG_INDEX).copied().unwrap_or_default()
2373 }
2374
2375 #[cfg(not(feature = "fips"))]
2380 #[corresponds(SSL_CTX_set1_ech_keys)]
2381 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2382 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())).map(|_| ()) }
2383 }
2384}
2385
2386#[derive(Debug)]
2391pub struct GetSessionPendingError;
2392
2393#[cfg(not(feature = "fips-compat"))]
2394type ProtosLen = usize;
2395#[cfg(feature = "fips-compat")]
2396type ProtosLen = libc::c_uint;
2397
2398pub struct CipherBits {
2400 pub secret: i32,
2402
2403 pub algorithm: i32,
2405}
2406
2407#[repr(transparent)]
2408pub struct ClientHello<'ssl>(&'ssl ffi::SSL_CLIENT_HELLO);
2409
2410impl ClientHello<'_> {
2411 #[corresponds(SSL_early_callback_ctx_extension_get)]
2413 #[must_use]
2414 pub fn get_extension(&self, ext_type: ExtensionType) -> Option<&[u8]> {
2415 unsafe {
2416 let mut ptr = ptr::null();
2417 let mut len = 0;
2418 let result =
2419 ffi::SSL_early_callback_ctx_extension_get(self.0, ext_type.0, &mut ptr, &mut len);
2420 if result == 0 {
2421 return None;
2422 }
2423 Some(slice::from_raw_parts(ptr, len))
2424 }
2425 }
2426
2427 pub fn ssl_mut(&mut self) -> &mut SslRef {
2428 unsafe { SslRef::from_ptr_mut(self.0.ssl) }
2429 }
2430
2431 #[must_use]
2432 pub fn ssl(&self) -> &SslRef {
2433 unsafe { SslRef::from_ptr(self.0.ssl) }
2434 }
2435
2436 #[must_use]
2438 pub fn servername(&self, type_: NameType) -> Option<&str> {
2439 self.ssl().servername(type_)
2440 }
2441
2442 #[must_use]
2444 pub fn client_version(&self) -> SslVersion {
2445 SslVersion(self.0.version)
2446 }
2447
2448 #[must_use]
2450 pub fn version_str(&self) -> &'static str {
2451 self.ssl().version_str()
2452 }
2453
2454 #[must_use]
2456 pub fn as_bytes(&self) -> &[u8] {
2457 unsafe { slice::from_raw_parts(self.0.client_hello, self.0.client_hello_len) }
2458 }
2459
2460 #[must_use]
2462 pub fn random(&self) -> &[u8] {
2463 unsafe { slice::from_raw_parts(self.0.random, self.0.random_len) }
2464 }
2465
2466 #[must_use]
2468 pub fn ciphers(&self) -> &[u8] {
2469 unsafe { slice::from_raw_parts(self.0.cipher_suites, self.0.cipher_suites_len) }
2470 }
2471}
2472
2473pub struct SslCipher(*mut ffi::SSL_CIPHER);
2475
2476impl SslCipher {
2477 #[corresponds(SSL_get_cipher_by_value)]
2478 #[must_use]
2479 pub fn from_value(value: u16) -> Option<Self> {
2480 unsafe {
2481 let ptr = ffi::SSL_get_cipher_by_value(value);
2482 if ptr.is_null() {
2483 None
2484 } else {
2485 Some(Self::from_ptr(ptr as *mut ffi::SSL_CIPHER))
2486 }
2487 }
2488 }
2489}
2490
2491impl Stackable for SslCipher {
2492 type StackType = ffi::stack_st_SSL_CIPHER;
2493}
2494
2495unsafe impl ForeignType for SslCipher {
2496 type CType = ffi::SSL_CIPHER;
2497 type Ref = SslCipherRef;
2498
2499 #[inline]
2500 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2501 SslCipher(ptr)
2502 }
2503
2504 #[inline]
2505 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2506 self.0
2507 }
2508}
2509
2510impl Deref for SslCipher {
2511 type Target = SslCipherRef;
2512
2513 fn deref(&self) -> &SslCipherRef {
2514 unsafe { SslCipherRef::from_ptr(self.0) }
2515 }
2516}
2517
2518impl DerefMut for SslCipher {
2519 fn deref_mut(&mut self) -> &mut SslCipherRef {
2520 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2521 }
2522}
2523
2524pub struct SslCipherRef(Opaque);
2528
2529unsafe impl ForeignTypeRef for SslCipherRef {
2530 type CType = ffi::SSL_CIPHER;
2531}
2532
2533impl SslCipherRef {
2534 #[corresponds(SSL_CIPHER_get_name)]
2536 #[must_use]
2537 pub fn name(&self) -> &'static str {
2538 unsafe {
2539 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2540 CStr::from_ptr(ptr).to_str().unwrap()
2541 }
2542 }
2543
2544 #[corresponds(SSL_CIPHER_standard_name)]
2546 #[must_use]
2547 pub fn standard_name(&self) -> Option<&'static str> {
2548 unsafe {
2549 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2550 if ptr.is_null() {
2551 None
2552 } else {
2553 Some(CStr::from_ptr(ptr).to_str().unwrap())
2554 }
2555 }
2556 }
2557
2558 #[corresponds(SSL_CIPHER_get_version)]
2560 #[must_use]
2561 pub fn version(&self) -> &'static str {
2562 let version = unsafe {
2563 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2564 CStr::from_ptr(ptr as *const _)
2565 };
2566
2567 str::from_utf8(version.to_bytes()).unwrap()
2568 }
2569
2570 #[corresponds(SSL_CIPHER_get_bits)]
2572 #[allow(clippy::useless_conversion)]
2573 #[must_use]
2574 pub fn bits(&self) -> CipherBits {
2575 unsafe {
2576 let mut algo_bits = 0;
2577 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2578 CipherBits {
2579 secret: secret_bits.into(),
2580 algorithm: algo_bits.into(),
2581 }
2582 }
2583 }
2584
2585 #[corresponds(SSL_CIPHER_description)]
2587 #[must_use]
2588 pub fn description(&self) -> String {
2589 unsafe {
2590 let mut buf = [0; 128];
2592 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2593 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2594 }
2595 }
2596
2597 #[corresponds(SSL_CIPHER_is_aead)]
2599 #[must_use]
2600 pub fn cipher_is_aead(&self) -> bool {
2601 unsafe { ffi::SSL_CIPHER_is_aead(self.as_ptr()) != 0 }
2602 }
2603
2604 #[corresponds(SSL_CIPHER_get_auth_nid)]
2606 #[must_use]
2607 pub fn cipher_auth_nid(&self) -> Option<Nid> {
2608 let n = unsafe { ffi::SSL_CIPHER_get_auth_nid(self.as_ptr()) };
2609 if n == 0 {
2610 None
2611 } else {
2612 Some(Nid::from_raw(n))
2613 }
2614 }
2615
2616 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2618 #[must_use]
2619 pub fn cipher_nid(&self) -> Option<Nid> {
2620 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2621 if n == 0 {
2622 None
2623 } else {
2624 Some(Nid::from_raw(n))
2625 }
2626 }
2627}
2628
2629foreign_type_and_impl_send_sync! {
2630 type CType = ffi::SSL_SESSION;
2631 fn drop = ffi::SSL_SESSION_free;
2632
2633 pub struct SslSession;
2637}
2638
2639impl Clone for SslSession {
2640 fn clone(&self) -> SslSession {
2641 SslSessionRef::to_owned(self)
2642 }
2643}
2644
2645impl SslSession {
2646 from_der! {
2647 #[corresponds(d2i_SSL_SESSION)]
2649 from_der,
2650 SslSession,
2651 ffi::d2i_SSL_SESSION,
2652 ::libc::c_long
2653 }
2654}
2655
2656impl ToOwned for SslSessionRef {
2657 type Owned = SslSession;
2658
2659 fn to_owned(&self) -> SslSession {
2660 unsafe {
2661 SSL_SESSION_up_ref(self.as_ptr());
2662 SslSession(NonNull::new_unchecked(self.as_ptr()))
2663 }
2664 }
2665}
2666
2667impl SslSessionRef {
2668 #[corresponds(SSL_SESSION_get_id)]
2670 #[must_use]
2671 pub fn id(&self) -> &[u8] {
2672 unsafe {
2673 let mut len = 0;
2674 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2675 slice::from_raw_parts(p, len as usize)
2676 }
2677 }
2678
2679 #[corresponds(SSL_SESSION_get_master_key)]
2681 #[must_use]
2682 pub fn master_key_len(&self) -> usize {
2683 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2684 }
2685
2686 #[corresponds(SSL_SESSION_get_master_key)]
2690 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2691 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2692 }
2693
2694 #[corresponds(SSL_SESSION_get_time)]
2696 #[allow(clippy::useless_conversion)]
2697 #[must_use]
2698 pub fn time(&self) -> u64 {
2699 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2700 }
2701
2702 #[corresponds(SSL_SESSION_get_timeout)]
2706 #[allow(clippy::useless_conversion)]
2707 #[must_use]
2708 pub fn timeout(&self) -> u32 {
2709 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()) }
2710 }
2711
2712 #[corresponds(SSL_SESSION_get_protocol_version)]
2714 #[must_use]
2715 pub fn protocol_version(&self) -> SslVersion {
2716 unsafe {
2717 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2718 SslVersion(version)
2719 }
2720 }
2721
2722 to_der! {
2723 #[corresponds(i2d_SSL_SESSION)]
2725 to_der,
2726 ffi::i2d_SSL_SESSION
2727 }
2728}
2729
2730foreign_type_and_impl_send_sync! {
2731 type CType = ffi::SSL;
2732 fn drop = ffi::SSL_free;
2733
2734 pub struct Ssl;
2741}
2742
2743impl fmt::Debug for Ssl {
2744 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2745 fmt::Debug::fmt(&**self, fmt)
2746 }
2747}
2748
2749impl Ssl {
2750 #[corresponds(SSL_get_ex_new_index)]
2755 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2756 where
2757 T: 'static + Sync + Send,
2758 {
2759 unsafe {
2760 ffi::init();
2761 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2762 Ok(Index::from_raw(idx))
2763 }
2764 }
2765
2766 fn cached_ex_index<T>() -> Index<Ssl, T>
2768 where
2769 T: 'static + Sync + Send,
2770 {
2771 unsafe {
2772 let idx = *SSL_INDEXES
2773 .lock()
2774 .unwrap_or_else(|e| e.into_inner())
2775 .entry(TypeId::of::<T>())
2776 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2777 Index::from_raw(idx)
2778 }
2779 }
2780
2781 #[corresponds(SSL_new)]
2785 pub fn new(ctx: &SslContext) -> Result<Ssl, ErrorStack> {
2786 unsafe {
2787 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2788 let mut ssl = Ssl::from_ptr(ptr);
2789 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx.clone());
2790
2791 Ok(ssl)
2792 }
2793 }
2794
2795 #[corresponds(SSL_new)]
2800 pub fn new_from_ref(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2801 unsafe {
2802 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2803 let mut ssl = Ssl::from_ptr(ptr);
2804 SSL_CTX_up_ref(ctx.as_ptr());
2805 let ctx_owned = SslContext::from_ptr(ctx.as_ptr());
2806 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx_owned);
2807
2808 Ok(ssl)
2809 }
2810 }
2811
2812 pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2824 where
2825 S: Read + Write,
2826 {
2827 SslStreamBuilder::new(self, stream).setup_connect()
2828 }
2829
2830 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2840 where
2841 S: Read + Write,
2842 {
2843 self.setup_connect(stream).handshake()
2844 }
2845
2846 pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
2858 where
2859 S: Read + Write,
2860 {
2861 #[cfg(feature = "rpk")]
2862 {
2863 let ctx = self.ssl_context();
2864
2865 if ctx.is_rpk() {
2866 unsafe {
2867 ffi::SSL_CTX_set_custom_verify(
2868 ctx.as_ptr(),
2869 SslVerifyMode::PEER.bits(),
2870 Some(rpk_verify_failure_callback),
2871 );
2872 }
2873 }
2874 }
2875
2876 SslStreamBuilder::new(self, stream).setup_accept()
2877 }
2878
2879 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2891 where
2892 S: Read + Write,
2893 {
2894 self.setup_accept(stream).handshake()
2895 }
2896}
2897
2898impl fmt::Debug for SslRef {
2899 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2900 let mut builder = fmt.debug_struct("Ssl");
2901
2902 builder.field("state", &self.state_string_long());
2903
2904 #[cfg(feature = "rpk")]
2905 if !self.ssl_context().is_rpk() {
2906 builder.field("verify_result", &self.verify_result());
2907 }
2908
2909 #[cfg(not(feature = "rpk"))]
2910 builder.field("verify_result", &self.verify_result());
2911
2912 builder.finish()
2913 }
2914}
2915
2916impl SslRef {
2917 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2918 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2919 }
2920
2921 #[corresponds(SSL_set_options)]
2928 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
2929 let bits = unsafe { ffi::SSL_set_options(self.as_ptr(), option.bits()) };
2930 SslOptions::from_bits_retain(bits)
2931 }
2932
2933 #[corresponds(SSL_clear_options)]
2935 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
2936 let bits = unsafe { ffi::SSL_clear_options(self.as_ptr(), option.bits()) };
2937 SslOptions::from_bits_retain(bits)
2938 }
2939
2940 #[corresponds(SSL_set1_curves_list)]
2941 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2942 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2943 unsafe {
2944 cvt_0i(ffi::SSL_set1_curves_list(
2945 self.as_ptr(),
2946 curves.as_ptr() as *const _,
2947 ))
2948 .map(|_| ())
2949 }
2950 }
2951
2952 #[corresponds(SSL_set1_groups)]
2955 pub fn set_group_nids(&mut self, group_nids: &[SslCurveNid]) -> Result<(), ErrorStack> {
2956 unsafe {
2957 cvt_0i(ffi::SSL_set1_curves(
2958 self.as_ptr(),
2959 group_nids.as_ptr() as *const _,
2960 group_nids.len(),
2961 ))
2962 .map(|_| ())
2963 }
2964 }
2965
2966 #[cfg(feature = "kx-safe-default")]
2967 fn client_set_default_curves_list(&mut self) {
2968 let curves = if cfg!(feature = "kx-client-pq-preferred") {
2969 if cfg!(feature = "kx-client-nist-required") {
2970 "P256Kyber768Draft00:P-256:P-384:P-521"
2971 } else {
2972 "X25519MLKEM768:X25519Kyber768Draft00:X25519:P256Kyber768Draft00:P-256:P-384:P-521"
2973 }
2974 } else if cfg!(feature = "kx-client-pq-supported") {
2975 if cfg!(feature = "kx-client-nist-required") {
2976 "P-256:P-384:P-521:P256Kyber768Draft00"
2977 } else {
2978 "X25519:P-256:P-384:P-521:X25519MLKEM768:X25519Kyber768Draft00:P256Kyber768Draft00"
2979 }
2980 } else {
2981 if cfg!(feature = "kx-client-nist-required") {
2982 "P-256:P-384:P-521"
2983 } else {
2984 "X25519:P-256:P-384:P-521"
2985 }
2986 };
2987
2988 self.set_curves_list(curves)
2989 .expect("invalid default client curves list");
2990 }
2991
2992 #[cfg(feature = "kx-safe-default")]
2993 fn server_set_default_curves_list(&mut self) {
2994 self.set_curves_list(
2995 "X25519MLKEM768:X25519Kyber768Draft00:P256Kyber768Draft00:X25519:P-256:P-384",
2996 )
2997 .expect("invalid default server curves list");
2998 }
2999
3000 #[corresponds(SSL_get_curve_id)]
3002 #[must_use]
3003 pub fn curve(&self) -> Option<SslCurve> {
3004 let curve_id = unsafe { ffi::SSL_get_curve_id(self.as_ptr()) };
3005 if curve_id == 0 {
3006 return None;
3007 }
3008 Some(SslCurve(curve_id.into()))
3009 }
3010
3011 #[corresponds(SSL_get_error)]
3013 #[must_use]
3014 pub fn error_code(&self, ret: c_int) -> ErrorCode {
3015 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
3016 }
3017
3018 #[corresponds(SSL_set_verify)]
3022 pub fn set_verify(&mut self, mode: SslVerifyMode) {
3023 #[cfg(feature = "rpk")]
3024 assert!(
3025 !self.ssl_context().is_rpk(),
3026 "This API is not supported for RPK"
3027 );
3028
3029 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
3030 }
3031
3032 #[corresponds(SSL_set_verify_depth)]
3036 pub fn set_verify_depth(&mut self, depth: u32) {
3037 #[cfg(feature = "rpk")]
3038 assert!(
3039 !self.ssl_context().is_rpk(),
3040 "This API is not supported for RPK"
3041 );
3042
3043 unsafe {
3044 ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
3045 }
3046 }
3047
3048 #[corresponds(SSL_get_verify_mode)]
3050 #[must_use]
3051 pub fn verify_mode(&self) -> SslVerifyMode {
3052 #[cfg(feature = "rpk")]
3053 assert!(
3054 !self.ssl_context().is_rpk(),
3055 "This API is not supported for RPK"
3056 );
3057
3058 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
3059 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
3060 }
3061
3062 #[corresponds(SSL_set_verify)]
3079 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3080 where
3081 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
3082 {
3083 #[cfg(feature = "rpk")]
3084 assert!(
3085 !self.ssl_context().is_rpk(),
3086 "This API is not supported for RPK"
3087 );
3088
3089 unsafe {
3090 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3092 ffi::SSL_set_verify(
3093 self.as_ptr(),
3094 mode.bits() as c_int,
3095 Some(ssl_raw_verify::<F>),
3096 );
3097 }
3098 }
3099
3100 #[corresponds(SSL_set0_verify_cert_store)]
3102 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3103 #[cfg(feature = "rpk")]
3104 assert!(
3105 !self.ssl_context().is_rpk(),
3106 "This API is not supported for RPK"
3107 );
3108
3109 unsafe {
3110 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int)?;
3111 Ok(())
3112 }
3113 }
3114
3115 #[corresponds(SSL_set_custom_verify)]
3121 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3122 where
3123 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
3124 {
3125 #[cfg(feature = "rpk")]
3126 assert!(
3127 !self.ssl_context().is_rpk(),
3128 "This API is not supported for RPK"
3129 );
3130
3131 unsafe {
3132 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3134 ffi::SSL_set_custom_verify(
3135 self.as_ptr(),
3136 mode.bits() as c_int,
3137 Some(ssl_raw_custom_verify::<F>),
3138 );
3139 }
3140 }
3141
3142 #[corresponds(SSL_set_tmp_dh)]
3146 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3147 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3148 }
3149
3150 #[corresponds(SSL_set_tmp_ecdh)]
3154 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3155 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3156 }
3157
3158 #[corresponds(SSL_set_permute_extensions)]
3160 #[cfg(not(feature = "fips-compat"))]
3165 pub fn set_permute_extensions(&mut self, enabled: bool) {
3166 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as _) }
3167 }
3168
3169 #[corresponds(SSL_set_alpn_protos)]
3173 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3174 unsafe {
3175 #[cfg_attr(not(feature = "fips-compat"), allow(clippy::unnecessary_cast))]
3176 {
3177 assert!(protocols.len() <= ProtosLen::MAX as usize);
3178 }
3179 let r = ffi::SSL_set_alpn_protos(
3180 self.as_ptr(),
3181 protocols.as_ptr(),
3182 protocols.len() as ProtosLen,
3183 );
3184 if r == 0 {
3186 Ok(())
3187 } else {
3188 Err(ErrorStack::get())
3189 }
3190 }
3191 }
3192
3193 #[corresponds(SSL_get_ciphers)]
3195 #[must_use]
3196 pub fn ciphers(&self) -> &StackRef<SslCipher> {
3197 unsafe {
3198 let cipher_list = ffi::SSL_get_ciphers(self.as_ptr());
3199 StackRef::from_ptr(cipher_list)
3200 }
3201 }
3202
3203 #[corresponds(SSL_get_current_cipher)]
3205 #[must_use]
3206 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3207 unsafe {
3208 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3209
3210 if ptr.is_null() {
3211 None
3212 } else {
3213 Some(SslCipherRef::from_ptr(ptr as *mut _))
3214 }
3215 }
3216 }
3217
3218 #[corresponds(SSL_state_string)]
3220 #[must_use]
3221 pub fn state_string(&self) -> &'static str {
3222 let state = unsafe {
3223 let ptr = ffi::SSL_state_string(self.as_ptr());
3224 CStr::from_ptr(ptr as *const _)
3225 };
3226
3227 str::from_utf8(state.to_bytes()).unwrap()
3228 }
3229
3230 #[corresponds(SSL_state_string_long)]
3232 #[must_use]
3233 pub fn state_string_long(&self) -> &'static str {
3234 let state = unsafe {
3235 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3236 CStr::from_ptr(ptr as *const _)
3237 };
3238
3239 str::from_utf8(state.to_bytes()).unwrap()
3240 }
3241
3242 #[corresponds(SSL_set_tlsext_host_name)]
3246 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3247 let cstr = CString::new(hostname).map_err(ErrorStack::internal_error)?;
3248 unsafe {
3249 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3250 .map(|_| ())
3251 }
3252 }
3253
3254 #[corresponds(SSL_get_peer_certificate)]
3256 #[must_use]
3257 pub fn peer_certificate(&self) -> Option<X509> {
3258 #[cfg(feature = "rpk")]
3259 assert!(
3260 !self.ssl_context().is_rpk(),
3261 "This API is not supported for RPK"
3262 );
3263
3264 unsafe {
3265 let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
3266 if ptr.is_null() {
3267 None
3268 } else {
3269 Some(X509::from_ptr(ptr))
3270 }
3271 }
3272 }
3273
3274 #[corresponds(SSL_get_peer_certificate)]
3279 #[must_use]
3280 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3281 #[cfg(feature = "rpk")]
3282 assert!(
3283 !self.ssl_context().is_rpk(),
3284 "This API is not supported for RPK"
3285 );
3286
3287 unsafe {
3288 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3289 if ptr.is_null() {
3290 None
3291 } else {
3292 Some(StackRef::from_ptr(ptr))
3293 }
3294 }
3295 }
3296
3297 #[corresponds(SSL_get_certificate)]
3299 #[must_use]
3300 pub fn certificate(&self) -> Option<&X509Ref> {
3301 #[cfg(feature = "rpk")]
3302 assert!(
3303 !self.ssl_context().is_rpk(),
3304 "This API is not supported for RPK"
3305 );
3306
3307 unsafe {
3308 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3309 if ptr.is_null() {
3310 None
3311 } else {
3312 Some(X509Ref::from_ptr(ptr))
3313 }
3314 }
3315 }
3316
3317 #[corresponds(SSL_get_privatekey)]
3319 #[must_use]
3320 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3321 unsafe {
3322 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3323 if ptr.is_null() {
3324 None
3325 } else {
3326 Some(PKeyRef::from_ptr(ptr))
3327 }
3328 }
3329 }
3330
3331 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
3332 #[must_use]
3333 pub fn version(&self) -> &str {
3334 self.version_str()
3335 }
3336
3337 #[corresponds(SSL_version)]
3339 pub fn version2(&self) -> Option<SslVersion> {
3340 unsafe {
3341 let r = ffi::SSL_version(self.as_ptr());
3342 if r == 0 {
3343 None
3344 } else {
3345 r.try_into().ok().map(SslVersion)
3346 }
3347 }
3348 }
3349
3350 #[corresponds(SSL_get_version)]
3352 #[must_use]
3353 pub fn version_str(&self) -> &'static str {
3354 let version = unsafe {
3355 let ptr = ffi::SSL_get_version(self.as_ptr());
3356 CStr::from_ptr(ptr as *const _)
3357 };
3358
3359 str::from_utf8(version.to_bytes()).unwrap()
3360 }
3361
3362 #[corresponds(SSL_set_min_proto_version)]
3367 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3368 unsafe {
3369 cvt(ffi::SSL_set_min_proto_version(
3370 self.as_ptr(),
3371 version.map_or(0, |v| v.0 as _),
3372 ))
3373 .map(|_| ())
3374 }
3375 }
3376
3377 #[corresponds(SSL_set_max_proto_version)]
3381 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3382 unsafe {
3383 cvt(ffi::SSL_set_max_proto_version(
3384 self.as_ptr(),
3385 version.map_or(0, |v| v.0 as _),
3386 ))
3387 .map(|_| ())
3388 }
3389 }
3390
3391 #[corresponds(SSL_get_min_proto_version)]
3393 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
3394 unsafe {
3395 let r = ffi::SSL_get_min_proto_version(self.as_ptr());
3396 if r == 0 {
3397 None
3398 } else {
3399 Some(SslVersion(r))
3400 }
3401 }
3402 }
3403
3404 #[corresponds(SSL_get_max_proto_version)]
3406 #[must_use]
3407 pub fn max_proto_version(&self) -> Option<SslVersion> {
3408 let r = unsafe { ffi::SSL_get_max_proto_version(self.as_ptr()) };
3409 if r == 0 {
3410 None
3411 } else {
3412 Some(SslVersion(r))
3413 }
3414 }
3415
3416 #[corresponds(SSL_get0_alpn_selected)]
3421 #[must_use]
3422 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3423 unsafe {
3424 let mut data: *const c_uchar = ptr::null();
3425 let mut len: c_uint = 0;
3426 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3429
3430 if data.is_null() {
3431 None
3432 } else {
3433 Some(slice::from_raw_parts(data, len as usize))
3434 }
3435 }
3436 }
3437
3438 #[corresponds(SSL_set_tlsext_use_srtp)]
3440 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3441 unsafe {
3442 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
3443
3444 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3445 if r == 0 {
3447 Ok(())
3448 } else {
3449 Err(ErrorStack::get())
3450 }
3451 }
3452 }
3453
3454 #[corresponds(SSL_get_strp_profiles)]
3458 #[must_use]
3459 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3460 unsafe {
3461 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3462
3463 if chain.is_null() {
3464 None
3465 } else {
3466 Some(StackRef::from_ptr(chain as *mut _))
3467 }
3468 }
3469 }
3470
3471 #[corresponds(SSL_get_selected_srtp_profile)]
3475 #[must_use]
3476 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3477 unsafe {
3478 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3479
3480 if profile.is_null() {
3481 None
3482 } else {
3483 Some(SrtpProtectionProfileRef::from_ptr(profile as *mut _))
3484 }
3485 }
3486 }
3487
3488 #[corresponds(SSL_pending)]
3493 #[must_use]
3494 pub fn pending(&self) -> usize {
3495 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3496 }
3497
3498 #[corresponds(SSL_get_servername)]
3511 #[must_use]
3512 pub fn servername(&self, type_: NameType) -> Option<&str> {
3513 self.servername_raw(type_)
3514 .and_then(|b| str::from_utf8(b).ok())
3515 }
3516
3517 #[corresponds(SSL_get_servername)]
3525 #[must_use]
3526 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3527 unsafe {
3528 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3529 if name.is_null() {
3530 None
3531 } else {
3532 Some(CStr::from_ptr(name as *const _).to_bytes())
3533 }
3534 }
3535 }
3536
3537 #[corresponds(SSL_set_SSL_CTX)]
3541 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3542 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3543 }
3544
3545 #[corresponds(SSL_get_SSL_CTX)]
3547 #[must_use]
3548 pub fn ssl_context(&self) -> &SslContextRef {
3549 unsafe {
3550 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3551 SslContextRef::from_ptr(ssl_ctx)
3552 }
3553 }
3554
3555 #[corresponds(SSL_get0_param)]
3557 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
3558 #[cfg(feature = "rpk")]
3559 assert!(
3560 !self.ssl_context().is_rpk(),
3561 "This API is not supported for RPK"
3562 );
3563
3564 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3565 }
3566
3567 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3569 self.verify_param_mut()
3570 }
3571
3572 #[corresponds(SSL_get_verify_result)]
3574 pub fn verify_result(&self) -> X509VerifyResult {
3575 #[cfg(feature = "rpk")]
3576 assert!(
3577 !self.ssl_context().is_rpk(),
3578 "This API is not supported for RPK"
3579 );
3580
3581 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3582 }
3583
3584 #[corresponds(SSL_get_session)]
3586 #[must_use]
3587 pub fn session(&self) -> Option<&SslSessionRef> {
3588 unsafe {
3589 let p = ffi::SSL_get_session(self.as_ptr());
3590 if p.is_null() {
3591 None
3592 } else {
3593 Some(SslSessionRef::from_ptr(p))
3594 }
3595 }
3596 }
3597
3598 #[corresponds(SSL_get_client_random)]
3603 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3604 unsafe {
3605 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3606 }
3607 }
3608
3609 #[corresponds(SSL_get_server_random)]
3614 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3615 unsafe {
3616 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3617 }
3618 }
3619
3620 #[corresponds(SSL_export_keying_material)]
3622 pub fn export_keying_material(
3623 &self,
3624 out: &mut [u8],
3625 label: &str,
3626 context: Option<&[u8]>,
3627 ) -> Result<(), ErrorStack> {
3628 unsafe {
3629 let (context, contextlen, use_context) = match context {
3630 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3631 None => (ptr::null(), 0, 0),
3632 };
3633 cvt(ffi::SSL_export_keying_material(
3634 self.as_ptr(),
3635 out.as_mut_ptr() as *mut c_uchar,
3636 out.len(),
3637 label.as_ptr() as *const c_char,
3638 label.len(),
3639 context,
3640 contextlen,
3641 use_context,
3642 ))
3643 .map(|_| ())
3644 }
3645 }
3646
3647 #[corresponds(SSL_set_session)]
3658 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3659 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3660 }
3661
3662 #[corresponds(SSL_session_reused)]
3664 #[must_use]
3665 pub fn session_reused(&self) -> bool {
3666 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3667 }
3668
3669 #[corresponds(SSL_set_tlsext_status_type)]
3671 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3672 unsafe {
3673 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3674 }
3675 }
3676
3677 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3679 #[must_use]
3680 pub fn ocsp_status(&self) -> Option<&[u8]> {
3681 unsafe {
3682 let mut p = ptr::null();
3683 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3684
3685 if len == 0 {
3686 None
3687 } else {
3688 Some(slice::from_raw_parts(p, len))
3689 }
3690 }
3691 }
3692
3693 #[corresponds(SSL_set_tlsext_status_ocsp_resp)]
3695 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3696 unsafe {
3697 assert!(response.len() <= c_int::MAX as usize);
3698 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3699 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3700 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3701 self.as_ptr(),
3702 p as *mut c_uchar,
3703 response.len(),
3704 ) as c_int)
3705 .map(|_| ())
3706 }
3707 }
3708
3709 #[corresponds(SSL_is_server)]
3711 #[must_use]
3712 pub fn is_server(&self) -> bool {
3713 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3714 }
3715
3716 #[corresponds(SSL_set_ex_data)]
3724 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3725 if let Some(old) = self.ex_data_mut(index) {
3726 *old = data;
3727
3728 return;
3729 }
3730
3731 unsafe {
3732 let data = Box::new(data);
3733 ffi::SSL_set_ex_data(
3734 self.as_ptr(),
3735 index.as_raw(),
3736 Box::into_raw(data) as *mut c_void,
3737 );
3738 }
3739 }
3740
3741 #[corresponds(SSL_set_ex_data)]
3748 pub fn replace_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) -> Option<T> {
3749 if let Some(old) = self.ex_data_mut(index) {
3750 return Some(mem::replace(old, data));
3751 }
3752
3753 self.set_ex_data(index, data);
3754
3755 None
3756 }
3757
3758 #[corresponds(SSL_get_ex_data)]
3760 #[must_use]
3761 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3762 unsafe {
3763 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3764 if data.is_null() {
3765 None
3766 } else {
3767 Some(&*(data as *const T))
3768 }
3769 }
3770 }
3771
3772 #[corresponds(SSL_get_ex_data)]
3774 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3775 unsafe {
3776 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3777 if data.is_null() {
3778 None
3779 } else {
3780 Some(&mut *(data as *mut T))
3781 }
3782 }
3783 }
3784
3785 #[corresponds(SSL_get_finished)]
3790 pub fn finished(&self, buf: &mut [u8]) -> usize {
3791 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3792 }
3793
3794 #[corresponds(SSL_get_peer_finished)]
3800 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3801 unsafe {
3802 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3803 }
3804 }
3805
3806 #[corresponds(SSL_is_init_finished)]
3808 #[must_use]
3809 pub fn is_init_finished(&self) -> bool {
3810 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3811 }
3812
3813 #[corresponds(SSL_set_mtu)]
3815 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3816 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_uint) as c_int).map(|_| ()) }
3817 }
3818
3819 #[corresponds(SSL_use_certificate)]
3821 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3822 unsafe {
3823 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3824 }
3825
3826 Ok(())
3827 }
3828
3829 #[corresponds(SSL_set_client_CA_list)]
3834 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3835 #[cfg(feature = "rpk")]
3836 assert!(
3837 !self.ssl_context().is_rpk(),
3838 "This API is not supported for RPK"
3839 );
3840
3841 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3842 mem::forget(list);
3843 }
3844
3845 #[corresponds(SSL_use_PrivateKey)]
3847 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
3848 where
3849 T: HasPrivate,
3850 {
3851 unsafe { cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
3852 }
3853
3854 #[corresponds(SSL_set_mode)]
3857 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
3858 let bits = unsafe { ffi::SSL_set_mode(self.as_ptr(), mode.bits()) };
3859 SslMode::from_bits_retain(bits)
3860 }
3861
3862 #[corresponds(SSL_clear_mode)]
3865 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
3866 let bits = unsafe { ffi::SSL_clear_mode(self.as_ptr(), mode.bits()) };
3867 SslMode::from_bits_retain(bits)
3868 }
3869
3870 #[corresponds(SSL_add1_chain_cert)]
3872 pub fn add_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3873 unsafe { cvt(ffi::SSL_add1_chain_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
3874 }
3875
3876 #[cfg(not(feature = "fips"))]
3884 #[corresponds(SSL_set1_ech_config_list)]
3885 pub fn set_ech_config_list(&mut self, ech_config_list: &[u8]) -> Result<(), ErrorStack> {
3886 unsafe {
3887 cvt_0i(ffi::SSL_set1_ech_config_list(
3888 self.as_ptr(),
3889 ech_config_list.as_ptr(),
3890 ech_config_list.len(),
3891 ))
3892 .map(|_| ())
3893 }
3894 }
3895
3896 #[cfg(not(feature = "fips"))]
3903 #[corresponds(SSL_get0_ech_retry_configs)]
3904 #[must_use]
3905 pub fn get_ech_retry_configs(&self) -> Option<&[u8]> {
3906 unsafe {
3907 let mut data = ptr::null();
3908 let mut len: usize = 0;
3909 ffi::SSL_get0_ech_retry_configs(self.as_ptr(), &mut data, &mut len);
3910
3911 if data.is_null() {
3912 None
3913 } else {
3914 Some(slice::from_raw_parts(data, len))
3915 }
3916 }
3917 }
3918
3919 #[cfg(not(feature = "fips"))]
3926 #[corresponds(SSL_get0_ech_name_override)]
3927 #[must_use]
3928 pub fn get_ech_name_override(&self) -> Option<&[u8]> {
3929 unsafe {
3930 let mut data: *const c_char = ptr::null();
3931 let mut len: usize = 0;
3932 ffi::SSL_get0_ech_name_override(self.as_ptr(), &mut data, &mut len);
3933
3934 if data.is_null() {
3935 None
3936 } else {
3937 Some(slice::from_raw_parts(data as *const u8, len))
3938 }
3939 }
3940 }
3941
3942 #[cfg(not(feature = "fips"))]
3944 #[corresponds(SSL_ech_accepted)]
3945 #[must_use]
3946 pub fn ech_accepted(&self) -> bool {
3947 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
3948 }
3949
3950 #[cfg(not(feature = "fips"))]
3952 #[corresponds(SSL_set_enable_ech_grease)]
3953 pub fn set_enable_ech_grease(&self, enable: bool) {
3954 let enable = if enable { 1 } else { 0 };
3955
3956 unsafe {
3957 ffi::SSL_set_enable_ech_grease(self.as_ptr(), enable);
3958 }
3959 }
3960
3961 #[cfg(not(feature = "fips-compat"))]
3963 #[corresponds(SSL_set_compliance_policy)]
3964 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
3965 unsafe { cvt_0i(ffi::SSL_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
3966 }
3967}
3968
3969#[derive(Debug)]
3971pub struct MidHandshakeSslStream<S> {
3972 stream: SslStream<S>,
3973 error: Error,
3974}
3975
3976impl<S> MidHandshakeSslStream<S> {
3977 #[must_use]
3979 pub fn get_ref(&self) -> &S {
3980 self.stream.get_ref()
3981 }
3982
3983 pub fn get_mut(&mut self) -> &mut S {
3985 self.stream.get_mut()
3986 }
3987
3988 #[must_use]
3990 pub fn ssl(&self) -> &SslRef {
3991 self.stream.ssl()
3992 }
3993
3994 pub fn ssl_mut(&mut self) -> &mut SslRef {
3996 self.stream.ssl_mut()
3997 }
3998
3999 #[must_use]
4001 pub fn error(&self) -> &Error {
4002 &self.error
4003 }
4004
4005 #[must_use]
4007 pub fn into_error(self) -> Error {
4008 self.error
4009 }
4010
4011 #[must_use]
4013 pub fn into_source_stream(self) -> S {
4014 self.stream.into_inner()
4015 }
4016
4017 #[must_use]
4019 pub fn into_parts(self) -> (Error, S) {
4020 (self.error, self.stream.into_inner())
4021 }
4022
4023 #[corresponds(SSL_do_handshake)]
4025 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4026 let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) };
4027 if ret > 0 {
4028 Ok(self.stream)
4029 } else {
4030 self.error = self.stream.make_error(ret);
4031 match self.error.would_block() {
4032 true => Err(HandshakeError::WouldBlock(self)),
4033 false => Err(HandshakeError::Failure(self)),
4034 }
4035 }
4036 }
4037}
4038
4039pub struct SslStream<S> {
4041 ssl: ManuallyDrop<Ssl>,
4042 method: ManuallyDrop<BioMethod>,
4043 _p: PhantomData<S>,
4044}
4045
4046impl<S> Drop for SslStream<S> {
4047 fn drop(&mut self) {
4048 unsafe {
4050 ManuallyDrop::drop(&mut self.ssl);
4051 ManuallyDrop::drop(&mut self.method);
4052 }
4053 }
4054}
4055
4056impl<S> fmt::Debug for SslStream<S>
4057where
4058 S: fmt::Debug,
4059{
4060 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
4061 fmt.debug_struct("SslStream")
4062 .field("stream", &self.get_ref())
4063 .field("ssl", &self.ssl())
4064 .finish()
4065 }
4066}
4067
4068impl<S: Read + Write> SslStream<S> {
4069 fn new_base(ssl: Ssl, stream: S) -> Self {
4070 unsafe {
4071 let (bio, method) = bio::new(stream).unwrap();
4072 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4073
4074 SslStream {
4075 ssl: ManuallyDrop::new(ssl),
4076 method: ManuallyDrop::new(method),
4077 _p: PhantomData,
4078 }
4079 }
4080 }
4081
4082 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4088 Ok(Self::new_base(ssl, stream))
4089 }
4090
4091 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
4099 let ssl = Ssl::from_ptr(ssl);
4100 Self::new_base(ssl, stream)
4101 }
4102
4103 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4110 loop {
4111 match self.ssl_read_uninit(buf) {
4112 Ok(n) => return Ok(n),
4113 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4114 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4115 return Ok(0);
4116 }
4117 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4118 Err(e) => {
4119 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4120 }
4121 }
4122 }
4123 }
4124
4125 #[corresponds(SSL_read)]
4130 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4131 unsafe {
4133 self.ssl_read_uninit(slice::from_raw_parts_mut(
4134 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4135 buf.len(),
4136 ))
4137 }
4138 }
4139
4140 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4147 if buf.is_empty() {
4148 return Ok(0);
4149 }
4150
4151 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4152 let ret = unsafe { ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) };
4153 if ret > 0 {
4154 Ok(ret as usize)
4155 } else {
4156 Err(self.make_error(ret))
4157 }
4158 }
4159
4160 #[corresponds(SSL_write)]
4165 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4166 if buf.is_empty() {
4167 return Ok(0);
4168 }
4169
4170 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4171 let ret = unsafe { ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) };
4172 if ret > 0 {
4173 Ok(ret as usize)
4174 } else {
4175 Err(self.make_error(ret))
4176 }
4177 }
4178
4179 #[corresponds(SSL_shutdown)]
4189 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4190 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4191 0 => Ok(ShutdownResult::Sent),
4192 1 => Ok(ShutdownResult::Received),
4193 n => Err(self.make_error(n)),
4194 }
4195 }
4196
4197 #[corresponds(SSL_get_shutdown)]
4199 pub fn get_shutdown(&mut self) -> ShutdownState {
4200 unsafe {
4201 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4202 ShutdownState::from_bits_retain(bits)
4203 }
4204 }
4205
4206 #[corresponds(SSL_set_shutdown)]
4211 pub fn set_shutdown(&mut self, state: ShutdownState) {
4212 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4213 }
4214
4215 #[corresponds(SSL_connect)]
4217 pub fn connect(&mut self) -> Result<(), Error> {
4218 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4219 if ret > 0 {
4220 Ok(())
4221 } else {
4222 Err(self.make_error(ret))
4223 }
4224 }
4225
4226 #[corresponds(SSL_accept)]
4228 pub fn accept(&mut self) -> Result<(), Error> {
4229 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4230 if ret > 0 {
4231 Ok(())
4232 } else {
4233 Err(self.make_error(ret))
4234 }
4235 }
4236
4237 #[corresponds(SSL_do_handshake)]
4239 pub fn do_handshake(&mut self) -> Result<(), Error> {
4240 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4241 if ret > 0 {
4242 Ok(())
4243 } else {
4244 Err(self.make_error(ret))
4245 }
4246 }
4247}
4248
4249impl<S> SslStream<S> {
4250 fn make_error(&mut self, ret: c_int) -> Error {
4251 self.check_panic();
4252
4253 let code = self.ssl.error_code(ret);
4254
4255 let cause = match code {
4256 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4257 ErrorCode::SYSCALL => {
4258 let errs = ErrorStack::get();
4259 if errs.errors().is_empty() {
4260 self.get_bio_error().map(InnerError::Io)
4261 } else {
4262 Some(InnerError::Ssl(errs))
4263 }
4264 }
4265 ErrorCode::ZERO_RETURN => None,
4266 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4267 self.get_bio_error().map(InnerError::Io)
4268 }
4269 _ => None,
4270 };
4271
4272 Error { code, cause }
4273 }
4274
4275 fn check_panic(&mut self) {
4276 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4277 resume_unwind(err)
4278 }
4279 }
4280
4281 fn get_bio_error(&mut self) -> Option<io::Error> {
4282 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4283 }
4284
4285 #[must_use]
4287 pub fn into_inner(self) -> S {
4288 unsafe { bio::take_stream::<S>(self.ssl.get_raw_rbio()) }
4289 }
4290
4291 #[must_use]
4293 pub fn get_ref(&self) -> &S {
4294 unsafe {
4295 let bio = self.ssl.get_raw_rbio();
4296 bio::get_ref(bio)
4297 }
4298 }
4299
4300 pub fn get_mut(&mut self) -> &mut S {
4307 unsafe {
4308 let bio = self.ssl.get_raw_rbio();
4309 bio::get_mut(bio)
4310 }
4311 }
4312
4313 #[must_use]
4315 pub fn ssl(&self) -> &SslRef {
4316 &self.ssl
4317 }
4318
4319 pub fn ssl_mut(&mut self) -> &mut SslRef {
4321 &mut self.ssl
4322 }
4323}
4324
4325impl<S: Read + Write> Read for SslStream<S> {
4326 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4327 unsafe {
4329 self.read_uninit(slice::from_raw_parts_mut(
4330 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4331 buf.len(),
4332 ))
4333 }
4334 }
4335}
4336
4337impl<S: Read + Write> Write for SslStream<S> {
4338 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4339 loop {
4340 match self.ssl_write(buf) {
4341 Ok(n) => return Ok(n),
4342 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4343 Err(e) => {
4344 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4345 }
4346 }
4347 }
4348 }
4349
4350 fn flush(&mut self) -> io::Result<()> {
4351 self.get_mut().flush()
4352 }
4353}
4354
4355pub struct SslStreamBuilder<S> {
4357 inner: SslStream<S>,
4358}
4359
4360impl<S> SslStreamBuilder<S>
4361where
4362 S: Read + Write,
4363{
4364 pub fn new(ssl: Ssl, stream: S) -> Self {
4366 Self {
4367 inner: SslStream::new_base(ssl, stream),
4368 }
4369 }
4370
4371 #[corresponds(SSL_set_connect_state)]
4373 pub fn set_connect_state(&mut self) {
4374 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4375 }
4376
4377 #[corresponds(SSL_set_accept_state)]
4379 pub fn set_accept_state(&mut self) {
4380 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4381 }
4382
4383 #[must_use]
4389 pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
4390 self.set_connect_state();
4391
4392 #[cfg(feature = "kx-safe-default")]
4393 self.inner.ssl.client_set_default_curves_list();
4394
4395 MidHandshakeSslStream {
4396 stream: self.inner,
4397 error: Error {
4398 code: ErrorCode::WANT_WRITE,
4399 cause: Some(InnerError::Io(io::Error::new(
4400 io::ErrorKind::WouldBlock,
4401 "connect handshake has not started yet",
4402 ))),
4403 },
4404 }
4405 }
4406
4407 pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
4412 self.setup_connect().handshake()
4413 }
4414
4415 #[must_use]
4421 pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
4422 self.set_accept_state();
4423
4424 #[cfg(feature = "kx-safe-default")]
4425 self.inner.ssl.server_set_default_curves_list();
4426
4427 MidHandshakeSslStream {
4428 stream: self.inner,
4429 error: Error {
4430 code: ErrorCode::WANT_READ,
4431 cause: Some(InnerError::Io(io::Error::new(
4432 io::ErrorKind::WouldBlock,
4433 "accept handshake has not started yet",
4434 ))),
4435 },
4436 }
4437 }
4438
4439 pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
4444 self.setup_accept().handshake()
4445 }
4446
4447 #[corresponds(SSL_do_handshake)]
4451 pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
4452 let mut stream = self.inner;
4453 let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
4454 if ret > 0 {
4455 Ok(stream)
4456 } else {
4457 let error = stream.make_error(ret);
4458 match error.would_block() {
4459 true => Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4460 stream,
4461 error,
4462 })),
4463 false => Err(HandshakeError::Failure(MidHandshakeSslStream {
4464 stream,
4465 error,
4466 })),
4467 }
4468 }
4469 }
4470}
4471
4472impl<S> SslStreamBuilder<S> {
4473 #[must_use]
4475 pub fn get_ref(&self) -> &S {
4476 unsafe {
4477 let bio = self.inner.ssl.get_raw_rbio();
4478 bio::get_ref(bio)
4479 }
4480 }
4481
4482 pub fn get_mut(&mut self) -> &mut S {
4489 unsafe {
4490 let bio = self.inner.ssl.get_raw_rbio();
4491 bio::get_mut(bio)
4492 }
4493 }
4494
4495 #[must_use]
4497 pub fn ssl(&self) -> &SslRef {
4498 &self.inner.ssl
4499 }
4500
4501 pub fn ssl_mut(&mut self) -> &mut SslRef {
4503 &mut self.inner.ssl
4504 }
4505
4506 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4514 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4515 unsafe {
4516 let bio = self.inner.ssl.get_raw_rbio();
4517 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4518 }
4519 }
4520}
4521
4522#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4524pub enum ShutdownResult {
4525 Sent,
4527
4528 Received,
4530}
4531
4532bitflags! {
4533 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
4535 pub struct ShutdownState: c_int {
4536 const SENT = ffi::SSL_SENT_SHUTDOWN;
4538 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4540 }
4541}
4542
4543pub trait PrivateKeyMethod: Send + Sync + 'static {
4551 fn sign(
4562 &self,
4563 ssl: &mut SslRef,
4564 input: &[u8],
4565 signature_algorithm: SslSignatureAlgorithm,
4566 output: &mut [u8],
4567 ) -> Result<usize, PrivateKeyMethodError>;
4568
4569 fn decrypt(
4584 &self,
4585 ssl: &mut SslRef,
4586 input: &[u8],
4587 output: &mut [u8],
4588 ) -> Result<usize, PrivateKeyMethodError>;
4589
4590 fn complete(&self, ssl: &mut SslRef, output: &mut [u8])
4599 -> Result<usize, PrivateKeyMethodError>;
4600}
4601
4602#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4604pub struct PrivateKeyMethodError(ffi::ssl_private_key_result_t);
4605
4606impl PrivateKeyMethodError {
4607 pub const FAILURE: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_failure);
4609
4610 pub const RETRY: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_retry);
4612}
4613
4614pub trait CertificateCompressor: Send + Sync + 'static {
4616 const ALGORITHM: CertificateCompressionAlgorithm;
4618
4619 const CAN_COMPRESS: bool;
4621
4622 const CAN_DECOMPRESS: bool;
4624
4625 #[allow(unused_variables)]
4627 fn compress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4628 where
4629 W: std::io::Write,
4630 {
4631 Err(std::io::Error::other("not implemented"))
4632 }
4633
4634 #[allow(unused_variables)]
4636 fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4637 where
4638 W: std::io::Write,
4639 {
4640 Err(std::io::Error::other("not implemented"))
4641 }
4642}
4643
4644use crate::ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4645
4646use crate::ffi::{DTLS_method, TLS_client_method, TLS_method, TLS_server_method};
4647
4648use std::sync::Once;
4649
4650unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4651 static ONCE: Once = Once::new();
4653 ONCE.call_once(|| {
4654 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4655 });
4656
4657 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4658}
4659
4660unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4661 static ONCE: Once = Once::new();
4663 ONCE.call_once(|| {
4664 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4665 });
4666
4667 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4668}