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)]
703#[deprecated(note = "this is not ABI-stable and will be removed in the next release")]
704pub struct SslCurveNid(c_int);
705
706#[repr(transparent)]
708#[derive(Debug, Copy, Clone, PartialEq, Eq)]
709#[deprecated(note = "this is not ABI-stable and will be removed in the next release")]
710pub struct SslCurve(c_int);
711
712#[allow(deprecated)]
713impl SslCurve {
714 pub const SECP224R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP224R1 as _);
715
716 pub const SECP256R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP256R1 as _);
717
718 pub const SECP384R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP384R1 as _);
719
720 pub const SECP521R1: SslCurve = SslCurve(ffi::SSL_CURVE_SECP521R1 as _);
721
722 pub const X25519: SslCurve = SslCurve(ffi::SSL_CURVE_X25519 as _);
723
724 #[cfg(not(any(feature = "fips", feature = "fips-precompiled")))]
725 pub const X25519_KYBER768_DRAFT00: SslCurve =
726 SslCurve(ffi::SSL_CURVE_X25519_KYBER768_DRAFT00 as _);
727
728 #[cfg(all(
729 not(any(feature = "fips", feature = "fips-precompiled")),
730 feature = "pq-experimental"
731 ))]
732 pub const X25519_KYBER768_DRAFT00_OLD: SslCurve =
733 SslCurve(ffi::SSL_CURVE_X25519_KYBER768_DRAFT00_OLD as _);
734
735 #[cfg(all(
736 not(any(feature = "fips", feature = "fips-precompiled")),
737 feature = "pq-experimental"
738 ))]
739 pub const X25519_KYBER512_DRAFT00: SslCurve =
740 SslCurve(ffi::SSL_CURVE_X25519_KYBER512_DRAFT00 as _);
741
742 #[cfg(all(
743 not(any(feature = "fips", feature = "fips-precompiled")),
744 feature = "pq-experimental"
745 ))]
746 pub const P256_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::SSL_CURVE_P256_KYBER768_DRAFT00 as _);
747
748 #[cfg(all(
749 not(any(feature = "fips", feature = "fips-precompiled")),
750 feature = "pq-experimental"
751 ))]
752 pub const X25519_MLKEM768: SslCurve = SslCurve(ffi::SSL_CURVE_X25519_MLKEM768 as _);
753
754 #[corresponds(SSL_get_curve_name)]
756 #[must_use]
757 pub fn name(&self) -> Option<&'static str> {
758 unsafe {
759 let ptr = ffi::SSL_get_curve_name(self.0 as u16);
760 if ptr.is_null() {
761 return None;
762 }
763
764 CStr::from_ptr(ptr).to_str().ok()
765 }
766 }
767
768 #[allow(dead_code)]
778 pub fn nid(&self) -> Option<SslCurveNid> {
779 match self.0 {
780 ffi::SSL_CURVE_SECP224R1 => Some(ffi::NID_secp224r1),
781 ffi::SSL_CURVE_SECP256R1 => Some(ffi::NID_X9_62_prime256v1),
782 ffi::SSL_CURVE_SECP384R1 => Some(ffi::NID_secp384r1),
783 ffi::SSL_CURVE_SECP521R1 => Some(ffi::NID_secp521r1),
784 ffi::SSL_CURVE_X25519 => Some(ffi::NID_X25519),
785 #[cfg(not(any(feature = "fips", feature = "fips-precompiled")))]
786 ffi::SSL_CURVE_X25519_KYBER768_DRAFT00 => Some(ffi::NID_X25519Kyber768Draft00),
787 #[cfg(all(
788 not(any(feature = "fips", feature = "fips-precompiled")),
789 feature = "pq-experimental"
790 ))]
791 ffi::SSL_CURVE_X25519_KYBER768_DRAFT00_OLD => Some(ffi::NID_X25519Kyber768Draft00Old),
792 #[cfg(all(
793 not(any(feature = "fips", feature = "fips-precompiled")),
794 feature = "pq-experimental"
795 ))]
796 ffi::SSL_CURVE_X25519_KYBER512_DRAFT00 => Some(ffi::NID_X25519Kyber512Draft00),
797 #[cfg(all(
798 not(any(feature = "fips", feature = "fips-precompiled")),
799 feature = "pq-experimental"
800 ))]
801 ffi::SSL_CURVE_P256_KYBER768_DRAFT00 => Some(ffi::NID_P256Kyber768Draft00),
802 #[cfg(all(
803 not(any(feature = "fips", feature = "fips-precompiled")),
804 feature = "pq-experimental"
805 ))]
806 ffi::SSL_CURVE_X25519_MLKEM768 => Some(ffi::NID_X25519MLKEM768),
807 _ => None,
808 }
809 .map(SslCurveNid)
810 }
811}
812
813#[derive(Debug, Copy, Clone, PartialEq, Eq)]
815#[cfg(not(feature = "fips-compat"))]
816pub struct CompliancePolicy(ffi::ssl_compliance_policy_t);
817
818#[cfg(not(feature = "fips-compat"))]
819impl CompliancePolicy {
820 pub const NONE: Self = Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_none);
822
823 pub const FIPS_202205: Self =
826 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_fips_202205);
827
828 pub const WPA3_192_202304: Self =
831 Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_wpa3_192_202304);
832}
833
834#[derive(Debug, Copy, Clone, PartialEq, Eq)]
836pub struct CertificateCompressionAlgorithm(u16);
837
838impl CertificateCompressionAlgorithm {
839 pub const ZLIB: Self = Self(ffi::TLSEXT_cert_compression_zlib as u16);
840
841 pub const BROTLI: Self = Self(ffi::TLSEXT_cert_compression_brotli as u16);
842}
843
844#[corresponds(SSL_select_next_proto)]
855#[must_use]
856pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
857 if server.is_empty() || client.is_empty() {
858 return None;
859 }
860
861 unsafe {
862 let mut out = ptr::null_mut();
863 let mut outlen = 0;
864 let r = ffi::SSL_select_next_proto(
865 &mut out,
866 &mut outlen,
867 server.as_ptr(),
868 server.len() as c_uint,
869 client.as_ptr(),
870 client.len() as c_uint,
871 );
872
873 if r == ffi::OPENSSL_NPN_NEGOTIATED {
874 Some(slice::from_raw_parts(out as *const u8, outlen as usize))
875 } else {
876 None
877 }
878 }
879}
880
881#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
883pub struct SslInfoCallbackMode(i32);
884
885impl SslInfoCallbackMode {
886 pub const READ_ALERT: Self = Self(ffi::SSL_CB_READ_ALERT);
888
889 pub const WRITE_ALERT: Self = Self(ffi::SSL_CB_WRITE_ALERT);
891
892 pub const HANDSHAKE_START: Self = Self(ffi::SSL_CB_HANDSHAKE_START);
894
895 pub const HANDSHAKE_DONE: Self = Self(ffi::SSL_CB_HANDSHAKE_DONE);
897
898 pub const ACCEPT_LOOP: Self = Self(ffi::SSL_CB_ACCEPT_LOOP);
900
901 pub const ACCEPT_EXIT: Self = Self(ffi::SSL_CB_ACCEPT_EXIT);
903
904 pub const CONNECT_EXIT: Self = Self(ffi::SSL_CB_CONNECT_EXIT);
906}
907
908#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
911pub enum SslInfoCallbackValue {
912 Unit,
916 Alert(SslInfoCallbackAlert),
920}
921
922#[derive(Hash, Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
923pub struct SslInfoCallbackAlert(c_int);
924
925impl SslInfoCallbackAlert {
926 #[must_use]
928 pub fn alert_level(&self) -> Ssl3AlertLevel {
929 let value = self.0 >> 8;
930 Ssl3AlertLevel(value)
931 }
932
933 #[must_use]
935 pub fn alert(&self) -> SslAlert {
936 let value = self.0 & i32::from(u8::MAX);
937 SslAlert(value)
938 }
939}
940
941#[derive(Debug, Copy, Clone, PartialEq, Eq)]
942pub struct Ssl3AlertLevel(c_int);
943
944impl Ssl3AlertLevel {
945 pub const WARNING: Ssl3AlertLevel = Self(ffi::SSL3_AL_WARNING);
946 pub const FATAL: Ssl3AlertLevel = Self(ffi::SSL3_AL_FATAL);
947}
948
949#[cfg(feature = "rpk")]
950extern "C" fn rpk_verify_failure_callback(
951 _ssl: *mut ffi::SSL,
952 _out_alert: *mut u8,
953) -> ffi::ssl_verify_result_t {
954 ffi::ssl_verify_result_t::ssl_verify_invalid
956}
957
958pub struct SslContextBuilder {
960 ctx: SslContext,
961 has_shared_cert_store: bool,
963 #[cfg(feature = "rpk")]
964 is_rpk: bool,
965}
966
967#[cfg(feature = "rpk")]
968impl SslContextBuilder {
969 #[corresponds(SSL_CTX_new)]
971 pub fn new_rpk() -> Result<SslContextBuilder, ErrorStack> {
972 unsafe {
973 init();
974 let ctx = cvt_p(ffi::SSL_CTX_new(SslMethod::tls_with_buffer().as_ptr()))?;
975
976 Ok(SslContextBuilder::from_ptr(ctx, true))
977 }
978 }
979
980 pub fn set_rpk_certificate(&mut self, cert: &[u8]) -> Result<(), ErrorStack> {
982 unsafe {
983 cvt(ffi::SSL_CTX_set_server_raw_public_key_certificate(
984 self.as_ptr(),
985 cert.as_ptr(),
986 cert.len() as u32,
987 ))
988 .map(|_| ())
989 }
990 }
991
992 pub fn set_null_chain_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
994 where
995 T: HasPrivate,
996 {
997 unsafe {
998 cvt(ffi::SSL_CTX_set_nullchain_and_key(
999 self.as_ptr(),
1000 key.as_ptr(),
1001 ptr::null_mut(),
1002 ))
1003 .map(|_| ())
1004 }
1005 }
1006}
1007
1008impl SslContextBuilder {
1009 #[corresponds(SSL_CTX_new)]
1011 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1012 unsafe {
1013 init();
1014 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
1015
1016 #[cfg(feature = "rpk")]
1017 {
1018 Ok(SslContextBuilder::from_ptr(ctx, false))
1019 }
1020
1021 #[cfg(not(feature = "rpk"))]
1022 {
1023 Ok(SslContextBuilder::from_ptr(ctx))
1024 }
1025 }
1026 }
1027
1028 #[cfg(feature = "rpk")]
1034 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX, is_rpk: bool) -> SslContextBuilder {
1035 let ctx = SslContext::from_ptr(ctx);
1036 let mut builder = SslContextBuilder {
1037 ctx,
1038 is_rpk,
1039 has_shared_cert_store: false,
1040 };
1041
1042 builder.replace_ex_data(*RPK_FLAG_INDEX, is_rpk);
1043
1044 builder
1045 }
1046
1047 #[cfg(not(feature = "rpk"))]
1053 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
1054 SslContextBuilder {
1055 ctx: SslContext::from_ptr(ctx),
1056 has_shared_cert_store: false,
1057 }
1058 }
1059
1060 #[must_use]
1062 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
1063 self.ctx.as_ptr()
1064 }
1065
1066 #[corresponds(SSL_CTX_set_cert_verify_callback)]
1086 pub fn set_cert_verify_callback<F>(&mut self, callback: F)
1087 where
1088 F: Fn(&mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1089 {
1090 #[cfg(feature = "rpk")]
1091 assert!(!self.is_rpk, "This API is not supported for RPK");
1092
1093 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1100 unsafe {
1101 ffi::SSL_CTX_set_cert_verify_callback(
1102 self.as_ptr(),
1103 Some(raw_cert_verify::<F>),
1104 ptr::null_mut(),
1105 );
1106 }
1107 }
1108
1109 #[corresponds(SSL_CTX_set_verify)]
1111 pub fn set_verify(&mut self, mode: SslVerifyMode) {
1112 #[cfg(feature = "rpk")]
1113 assert!(!self.is_rpk, "This API is not supported for RPK");
1114
1115 unsafe {
1116 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
1117 }
1118 }
1119
1120 #[corresponds(SSL_CTX_set_verify)]
1137 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1138 where
1139 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
1140 {
1141 #[cfg(feature = "rpk")]
1142 assert!(!self.is_rpk, "This API is not supported for RPK");
1143
1144 unsafe {
1145 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1146 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
1147 }
1148 }
1149
1150 #[corresponds(SSL_CTX_set_custom_verify)]
1165 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
1166 where
1167 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
1168 {
1169 #[cfg(feature = "rpk")]
1170 assert!(!self.is_rpk, "This API is not supported for RPK");
1171
1172 unsafe {
1173 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1174 ffi::SSL_CTX_set_custom_verify(
1175 self.as_ptr(),
1176 mode.bits() as c_int,
1177 Some(raw_custom_verify::<F>),
1178 );
1179 }
1180 }
1181
1182 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
1192 pub fn set_servername_callback<F>(&mut self, callback: F)
1193 where
1194 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
1195 {
1196 unsafe {
1197 let callback_index = SslContext::cached_ex_index::<F>();
1204
1205 self.ctx.replace_ex_data(callback_index, callback);
1206
1207 let arg = self.ctx.ex_data(callback_index).unwrap() as *const F as *mut c_void;
1208
1209 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
1210 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
1211 }
1212 }
1213
1214 #[corresponds(SSL_CTX_set_verify_depth)]
1218 pub fn set_verify_depth(&mut self, depth: u32) {
1219 #[cfg(feature = "rpk")]
1220 assert!(!self.is_rpk, "This API is not supported for RPK");
1221
1222 unsafe {
1223 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
1224 }
1225 }
1226
1227 #[corresponds(SSL_CTX_set0_verify_cert_store)]
1229 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
1230 #[cfg(feature = "rpk")]
1231 assert!(!self.is_rpk, "This API is not supported for RPK");
1232
1233 unsafe {
1234 cvt(
1235 ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int,
1236 )?;
1237
1238 Ok(())
1239 }
1240 }
1241
1242 #[corresponds(SSL_CTX_set_cert_store)]
1246 #[deprecated(note = "Use set_cert_store_builder or set_cert_store_ref instead")]
1247 pub fn set_cert_store(&mut self, cert_store: X509Store) {
1248 #[cfg(feature = "rpk")]
1249 assert!(!self.is_rpk, "This API is not supported for RPK");
1250
1251 self.has_shared_cert_store = false;
1252 unsafe {
1253 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1254 }
1255 }
1256
1257 #[corresponds(SSL_CTX_set_cert_store)]
1259 pub fn set_cert_store_builder(&mut self, cert_store: X509StoreBuilder) {
1260 #[cfg(feature = "rpk")]
1261 assert!(!self.is_rpk, "This API is not supported for RPK");
1262
1263 self.has_shared_cert_store = false;
1264 unsafe {
1265 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
1266 }
1267 }
1268
1269 #[corresponds(SSL_CTX_set_cert_store)]
1273 pub fn set_cert_store_ref(&mut self, cert_store: &X509Store) {
1274 #[cfg(feature = "rpk")]
1275 assert!(!self.is_rpk, "This API is not supported for RPK");
1276
1277 self.has_shared_cert_store = true;
1278 unsafe {
1279 ffi::X509_STORE_up_ref(cert_store.as_ptr());
1280 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
1281 }
1282 }
1283
1284 #[corresponds(SSL_CTX_set_read_ahead)]
1291 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1292 unsafe {
1293 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), c_int::from(read_ahead));
1294 }
1295 }
1296
1297 #[corresponds(SSL_CTX_set_mode)]
1299 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1300 let bits = unsafe { ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits()) };
1301 SslMode::from_bits_retain(bits)
1302 }
1303
1304 #[corresponds(SSL_CTX_set_tmp_dh)]
1306 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1307 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1308 }
1309
1310 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1312 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1313 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1314 }
1315
1316 #[corresponds(SSL_CTX_set_default_verify_paths)]
1321 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1322 #[cfg(feature = "rpk")]
1323 assert!(!self.is_rpk, "This API is not supported for RPK");
1324
1325 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1326 }
1327
1328 #[corresponds(SSL_CTX_load_verify_locations)]
1332 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1333 #[cfg(feature = "rpk")]
1334 assert!(!self.is_rpk, "This API is not supported for RPK");
1335
1336 let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
1337 .map_err(ErrorStack::internal_error)?;
1338 unsafe {
1339 cvt(ffi::SSL_CTX_load_verify_locations(
1340 self.as_ptr(),
1341 file.as_ptr() as *const _,
1342 ptr::null(),
1343 ))
1344 .map(|_| ())
1345 }
1346 }
1347
1348 #[corresponds(SSL_CTX_set_client_CA_list)]
1353 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1354 #[cfg(feature = "rpk")]
1355 assert!(!self.is_rpk, "This API is not supported for RPK");
1356
1357 unsafe {
1358 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1359 mem::forget(list);
1360 }
1361 }
1362
1363 #[corresponds(SSL_CTX_add_client_CA)]
1366 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1367 #[cfg(feature = "rpk")]
1368 assert!(!self.is_rpk, "This API is not supported for RPK");
1369
1370 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1371 }
1372
1373 #[corresponds(SSL_CTX_set_session_id_context)]
1382 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1383 unsafe {
1384 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1385 cvt(ffi::SSL_CTX_set_session_id_context(
1386 self.as_ptr(),
1387 sid_ctx.as_ptr(),
1388 sid_ctx.len(),
1389 ))
1390 .map(|_| ())
1391 }
1392 }
1393
1394 #[corresponds(SSL_CTX_use_certificate_file)]
1400 pub fn set_certificate_file<P: AsRef<Path>>(
1401 &mut self,
1402 file: P,
1403 file_type: SslFiletype,
1404 ) -> Result<(), ErrorStack> {
1405 #[cfg(feature = "rpk")]
1406 assert!(!self.is_rpk, "This API is not supported for RPK");
1407
1408 let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
1409 .map_err(ErrorStack::internal_error)?;
1410 unsafe {
1411 cvt(ffi::SSL_CTX_use_certificate_file(
1412 self.as_ptr(),
1413 file.as_ptr() as *const _,
1414 file_type.as_raw(),
1415 ))
1416 .map(|_| ())
1417 }
1418 }
1419
1420 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1426 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1427 &mut self,
1428 file: P,
1429 ) -> Result<(), ErrorStack> {
1430 let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
1431 .map_err(ErrorStack::internal_error)?;
1432 unsafe {
1433 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1434 self.as_ptr(),
1435 file.as_ptr() as *const _,
1436 ))
1437 .map(|_| ())
1438 }
1439 }
1440
1441 #[corresponds(SSL_CTX_use_certificate)]
1445 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1446 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1447 }
1448
1449 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1454 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1455 #[cfg(feature = "rpk")]
1456 assert!(!self.is_rpk, "This API is not supported for RPK");
1457
1458 unsafe {
1459 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.into_ptr()) as c_int)?;
1460 Ok(())
1461 }
1462 }
1463
1464 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1466 pub fn set_private_key_file<P: AsRef<Path>>(
1467 &mut self,
1468 file: P,
1469 file_type: SslFiletype,
1470 ) -> Result<(), ErrorStack> {
1471 let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
1472 .map_err(ErrorStack::internal_error)?;
1473 unsafe {
1474 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1475 self.as_ptr(),
1476 file.as_ptr() as *const _,
1477 file_type.as_raw(),
1478 ))
1479 .map(|_| ())
1480 }
1481 }
1482
1483 #[corresponds(SSL_CTX_use_PrivateKey)]
1485 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1486 where
1487 T: HasPrivate,
1488 {
1489 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1490 }
1491
1492 #[corresponds(SSL_CTX_set_cipher_list)]
1502 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1503 let cipher_list = CString::new(cipher_list).unwrap();
1504 unsafe {
1505 cvt(ffi::SSL_CTX_set_cipher_list(
1506 self.as_ptr(),
1507 cipher_list.as_ptr() as *const _,
1508 ))
1509 .map(|_| ())
1510 }
1511 }
1512
1513 #[corresponds(SSL_CTX_get_ciphers)]
1519 #[must_use]
1520 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
1521 self.ctx.ciphers()
1522 }
1523
1524 #[corresponds(SSL_CTX_set_options)]
1531 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1532 let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
1533 SslOptions::from_bits_retain(bits)
1534 }
1535
1536 #[corresponds(SSL_CTX_get_options)]
1538 #[must_use]
1539 pub fn options(&self) -> SslOptions {
1540 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
1541 SslOptions::from_bits_retain(bits)
1542 }
1543
1544 #[corresponds(SSL_CTX_clear_options)]
1546 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1547 let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
1548 SslOptions::from_bits_retain(bits)
1549 }
1550
1551 #[corresponds(SSL_CTX_set_min_proto_version)]
1556 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1557 unsafe {
1558 cvt(ffi::SSL_CTX_set_min_proto_version(
1559 self.as_ptr(),
1560 version.map_or(0, |v| v.0 as _),
1561 ))
1562 .map(|_| ())
1563 }
1564 }
1565
1566 #[corresponds(SSL_CTX_set_max_proto_version)]
1570 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1571 unsafe {
1572 cvt(ffi::SSL_CTX_set_max_proto_version(
1573 self.as_ptr(),
1574 version.map_or(0, |v| v.0 as _),
1575 ))
1576 .map(|_| ())
1577 }
1578 }
1579
1580 #[corresponds(SSL_CTX_get_min_proto_version)]
1582 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1583 unsafe {
1584 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1585 if r == 0 {
1586 None
1587 } else {
1588 Some(SslVersion(r))
1589 }
1590 }
1591 }
1592
1593 #[corresponds(SSL_CTX_get_max_proto_version)]
1595 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1596 unsafe {
1597 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1598 if r == 0 {
1599 None
1600 } else {
1601 Some(SslVersion(r))
1602 }
1603 }
1604 }
1605
1606 #[corresponds(SSL_CTX_set_alpn_protos)]
1613 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1614 unsafe {
1615 #[cfg_attr(not(feature = "fips-compat"), allow(clippy::unnecessary_cast))]
1616 {
1617 assert!(protocols.len() <= ProtosLen::MAX as usize);
1618 }
1619 let r = ffi::SSL_CTX_set_alpn_protos(
1620 self.as_ptr(),
1621 protocols.as_ptr(),
1622 protocols.len() as ProtosLen,
1623 );
1624 if r == 0 {
1626 Ok(())
1627 } else {
1628 Err(ErrorStack::get())
1629 }
1630 }
1631 }
1632
1633 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1635 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1636 unsafe {
1637 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
1638
1639 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1640 if r == 0 {
1642 Ok(())
1643 } else {
1644 Err(ErrorStack::get())
1645 }
1646 }
1647 }
1648
1649 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1660 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1661 where
1662 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1663 {
1664 unsafe {
1665 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1666 ffi::SSL_CTX_set_alpn_select_cb(
1667 self.as_ptr(),
1668 Some(callbacks::raw_alpn_select::<F>),
1669 ptr::null_mut(),
1670 );
1671 }
1672 }
1673
1674 #[corresponds(SSL_CTX_set_select_certificate_cb)]
1678 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
1679 where
1680 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
1681 {
1682 unsafe {
1683 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1684 ffi::SSL_CTX_set_select_certificate_cb(
1685 self.as_ptr(),
1686 Some(callbacks::raw_select_cert::<F>),
1687 );
1688 }
1689 }
1690
1691 #[corresponds(SSL_CTX_add_cert_compression_alg)]
1695 pub fn add_certificate_compression_algorithm<C>(
1696 &mut self,
1697 compressor: C,
1698 ) -> Result<(), ErrorStack>
1699 where
1700 C: CertificateCompressor,
1701 {
1702 const {
1703 assert!(C::CAN_COMPRESS || C::CAN_DECOMPRESS, "Either compression or decompression must be supported for algorithm to be registered")
1704 };
1705 let success = unsafe {
1706 ffi::SSL_CTX_add_cert_compression_alg(
1707 self.as_ptr(),
1708 C::ALGORITHM.0,
1709 const {
1710 if C::CAN_COMPRESS {
1711 Some(callbacks::raw_ssl_cert_compress::<C>)
1712 } else {
1713 None
1714 }
1715 },
1716 const {
1717 if C::CAN_DECOMPRESS {
1718 Some(callbacks::raw_ssl_cert_decompress::<C>)
1719 } else {
1720 None
1721 }
1722 },
1723 ) == 1
1724 };
1725 if !success {
1726 return Err(ErrorStack::get());
1727 }
1728 self.replace_ex_data(SslContext::cached_ex_index::<C>(), compressor);
1729 Ok(())
1730 }
1731
1732 #[corresponds(SSL_CTX_set_private_key_method)]
1736 pub fn set_private_key_method<M>(&mut self, method: M)
1737 where
1738 M: PrivateKeyMethod,
1739 {
1740 unsafe {
1741 self.replace_ex_data(SslContext::cached_ex_index::<M>(), method);
1742
1743 ffi::SSL_CTX_set_private_key_method(
1744 self.as_ptr(),
1745 &ffi::SSL_PRIVATE_KEY_METHOD {
1746 sign: Some(callbacks::raw_sign::<M>),
1747 decrypt: Some(callbacks::raw_decrypt::<M>),
1748 complete: Some(callbacks::raw_complete::<M>),
1749 },
1750 )
1751 }
1752 }
1753
1754 #[corresponds(SSL_CTX_check_private_key)]
1756 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1757 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1758 }
1759
1760 #[corresponds(SSL_CTX_get_cert_store)]
1762 #[must_use]
1763 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1764 #[cfg(feature = "rpk")]
1765 assert!(!self.is_rpk, "This API is not supported for RPK");
1766
1767 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1768 }
1769
1770 #[corresponds(SSL_CTX_get_cert_store)]
1780 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1781 #[cfg(feature = "rpk")]
1782 assert!(!self.is_rpk, "This API is not supported for RPK");
1783
1784 assert!(
1785 !self.has_shared_cert_store,
1786 "Shared X509Store can't be mutated. Make a new store"
1787 );
1788 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1791 }
1792
1793 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1806 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1807 where
1808 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1809 {
1810 unsafe {
1811 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1812 cvt(
1813 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1814 as c_int,
1815 )
1816 .map(|_| ())
1817 }
1818 }
1819
1820 #[corresponds(SSL_CTX_set_psk_client_callback)]
1826 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1827 where
1828 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1829 + 'static
1830 + Sync
1831 + Send,
1832 {
1833 unsafe {
1834 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1835 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1836 }
1837 }
1838
1839 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1840 pub fn set_psk_callback<F>(&mut self, callback: F)
1841 where
1842 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1843 + 'static
1844 + Sync
1845 + Send,
1846 {
1847 self.set_psk_client_callback(callback);
1848 }
1849
1850 #[corresponds(SSL_CTX_set_psk_server_callback)]
1856 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1857 where
1858 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1859 + 'static
1860 + Sync
1861 + Send,
1862 {
1863 unsafe {
1864 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1865 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1866 }
1867 }
1868
1869 #[corresponds(SSL_CTX_sess_set_new_cb)]
1883 pub fn set_new_session_callback<F>(&mut self, callback: F)
1884 where
1885 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1886 {
1887 unsafe {
1888 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1889 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1890 }
1891 }
1892
1893 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1897 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1898 where
1899 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1900 {
1901 unsafe {
1902 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1903 ffi::SSL_CTX_sess_set_remove_cb(
1904 self.as_ptr(),
1905 Some(callbacks::raw_remove_session::<F>),
1906 );
1907 }
1908 }
1909
1910 #[corresponds(SSL_CTX_sess_set_get_cb)]
1921 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1922 where
1923 F: Fn(&mut SslRef, &[u8]) -> Result<Option<SslSession>, GetSessionPendingError>
1924 + 'static
1925 + Sync
1926 + Send,
1927 {
1928 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1929 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1930 }
1931
1932 #[corresponds(SSL_CTX_set_keylog_callback)]
1938 pub fn set_keylog_callback<F>(&mut self, callback: F)
1939 where
1940 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1941 {
1942 unsafe {
1943 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
1944 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1945 }
1946 }
1947
1948 #[corresponds(SSL_CTX_set_session_cache_mode)]
1952 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1953 unsafe {
1954 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1955 SslSessionCacheMode::from_bits_retain(bits)
1956 }
1957 }
1958
1959 #[corresponds(SSL_CTX_set_ex_data)]
1969 #[deprecated(
1970 note = "This may leak memory. Don't rely on leaking. Use `replace_ex_data()` instead."
1971 )]
1972 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1973 unsafe {
1974 self.ctx.write_ex_data(index, data);
1975 }
1976 }
1977
1978 #[corresponds(SSL_CTX_set_ex_data)]
1985 #[doc(alias = "set_ex_data")]
1986 pub fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
1987 unsafe { self.ctx.replace_ex_data(index, data) }
1988 }
1989
1990 #[corresponds(SSL_CTX_sess_set_cache_size)]
1994 #[allow(clippy::useless_conversion)]
1995 pub fn set_session_cache_size(&mut self, size: u32) -> u64 {
1996 unsafe { ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size.into()).into() }
1997 }
1998
1999 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2001 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2002 let sigalgs = CString::new(sigalgs).map_err(ErrorStack::internal_error)?;
2003 unsafe {
2004 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2005 .map(|_| ())
2006 }
2007 }
2008
2009 #[corresponds(SSL_CTX_set_grease_enabled)]
2011 pub fn set_grease_enabled(&mut self, enabled: bool) {
2012 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as _) }
2013 }
2014
2015 #[corresponds(SSL_CTX_set_permute_extensions)]
2021 #[cfg(not(feature = "fips-compat"))]
2022 pub fn set_permute_extensions(&mut self, enabled: bool) {
2023 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as _) }
2024 }
2025
2026 #[corresponds(SSL_CTX_set_verify_algorithm_prefs)]
2028 pub fn set_verify_algorithm_prefs(
2029 &mut self,
2030 prefs: &[SslSignatureAlgorithm],
2031 ) -> Result<(), ErrorStack> {
2032 unsafe {
2033 cvt_0i(ffi::SSL_CTX_set_verify_algorithm_prefs(
2034 self.as_ptr(),
2035 prefs.as_ptr() as *const _,
2036 prefs.len(),
2037 ))
2038 .map(|_| ())
2039 }
2040 }
2041
2042 #[corresponds(SSL_CTX_enable_signed_cert_timestamps)]
2044 pub fn enable_signed_cert_timestamps(&mut self) {
2045 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
2046 }
2047
2048 #[corresponds(SSL_CTX_enable_ocsp_stapling)]
2050 pub fn enable_ocsp_stapling(&mut self) {
2051 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
2052 }
2053
2054 #[corresponds(SSL_CTX_set1_curves_list)]
2056 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2057 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2058 unsafe {
2059 cvt_0i(ffi::SSL_CTX_set1_curves_list(
2060 self.as_ptr(),
2061 curves.as_ptr() as *const _,
2062 ))
2063 .map(|_| ())
2064 }
2065 }
2066
2067 #[corresponds(SSL_CTX_set1_curves)]
2075 #[cfg(not(feature = "kx-safe-default"))]
2076 #[deprecated(
2077 note = "Use set_curves_list(). set_curves() and SslCurve will be removed in the next release"
2078 )]
2079 #[allow(deprecated)]
2080 pub fn set_curves(&mut self, curves: &[SslCurve]) -> Result<(), ErrorStack> {
2081 let curves: Vec<i32> = curves
2082 .iter()
2083 .filter_map(|curve| curve.nid().map(|nid| nid.0))
2084 .collect();
2085
2086 unsafe {
2087 cvt_0i(ffi::SSL_CTX_set1_curves(
2088 self.as_ptr(),
2089 curves.as_ptr() as *const _,
2090 curves.len(),
2091 ))
2092 .map(|_| ())
2093 }
2094 }
2095
2096 #[corresponds(SSL_CTX_set_compliance_policy)]
2100 #[cfg(not(feature = "fips-compat"))]
2101 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
2102 unsafe { cvt_0i(ffi::SSL_CTX_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
2103 }
2104
2105 #[corresponds(SSL_CTX_set_info_callback)]
2107 pub fn set_info_callback<F>(&mut self, callback: F)
2108 where
2109 F: Fn(&SslRef, SslInfoCallbackMode, SslInfoCallbackValue) + Send + Sync + 'static,
2110 {
2111 unsafe {
2112 self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
2113 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info_callback::<F>));
2114 }
2115 }
2116
2117 #[cfg(not(feature = "fips"))]
2122 #[corresponds(SSL_CTX_set1_ech_keys)]
2123 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2124 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())).map(|_| ()) }
2125 }
2126
2127 #[must_use]
2129 pub fn build(self) -> SslContext {
2130 self.ctx
2131 }
2132}
2133
2134foreign_type_and_impl_send_sync! {
2135 type CType = ffi::SSL_CTX;
2136 fn drop = ffi::SSL_CTX_free;
2137
2138 pub struct SslContext;
2143}
2144
2145impl Clone for SslContext {
2146 fn clone(&self) -> Self {
2147 (**self).to_owned()
2148 }
2149}
2150
2151impl ToOwned for SslContextRef {
2152 type Owned = SslContext;
2153
2154 fn to_owned(&self) -> Self::Owned {
2155 unsafe {
2156 SSL_CTX_up_ref(self.as_ptr());
2157 SslContext::from_ptr(self.as_ptr())
2158 }
2159 }
2160}
2161
2162impl fmt::Debug for SslContext {
2164 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2165 write!(fmt, "SslContext")
2166 }
2167}
2168
2169impl SslContext {
2170 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2172 SslContextBuilder::new(method)
2173 }
2174
2175 #[corresponds(SSL_CTX_get_ex_new_index)]
2180 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2181 where
2182 T: 'static + Sync + Send,
2183 {
2184 unsafe {
2185 ffi::init();
2186 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2187 Ok(Index::from_raw(idx))
2188 }
2189 }
2190
2191 fn cached_ex_index<T>() -> Index<SslContext, T>
2193 where
2194 T: 'static + Sync + Send,
2195 {
2196 unsafe {
2197 let idx = *INDEXES
2198 .lock()
2199 .unwrap_or_else(|e| e.into_inner())
2200 .entry(TypeId::of::<T>())
2201 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2202 Index::from_raw(idx)
2203 }
2204 }
2205
2206 #[corresponds(SSL_CTX_get_ciphers)]
2212 #[must_use]
2213 pub fn ciphers(&self) -> Option<&StackRef<SslCipher>> {
2214 unsafe {
2215 let ciphers = ffi::SSL_CTX_get_ciphers(self.as_ptr());
2216 if ciphers.is_null() {
2217 None
2218 } else {
2219 Some(StackRef::from_ptr(ciphers))
2220 }
2221 }
2222 }
2223}
2224
2225impl SslContextRef {
2226 #[corresponds(SSL_CTX_get0_certificate)]
2228 #[must_use]
2229 pub fn certificate(&self) -> Option<&X509Ref> {
2230 #[cfg(feature = "rpk")]
2231 assert!(!self.is_rpk(), "This API is not supported for RPK");
2232
2233 unsafe {
2234 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2235 if ptr.is_null() {
2236 None
2237 } else {
2238 Some(X509Ref::from_ptr(ptr))
2239 }
2240 }
2241 }
2242
2243 #[corresponds(SSL_CTX_get0_privatekey)]
2245 #[must_use]
2246 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2247 unsafe {
2248 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2249 if ptr.is_null() {
2250 None
2251 } else {
2252 Some(PKeyRef::from_ptr(ptr))
2253 }
2254 }
2255 }
2256
2257 #[corresponds(SSL_CTX_get_cert_store)]
2259 #[must_use]
2260 pub fn cert_store(&self) -> &X509StoreRef {
2261 #[cfg(feature = "rpk")]
2262 assert!(!self.is_rpk(), "This API is not supported for RPK");
2263
2264 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2265 }
2266
2267 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2269 #[must_use]
2270 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2271 unsafe {
2272 let mut chain = ptr::null_mut();
2273 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2274 assert!(!chain.is_null());
2275 StackRef::from_ptr(chain)
2276 }
2277 }
2278
2279 #[corresponds(SSL_CTX_get_ex_data)]
2281 #[must_use]
2282 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2283 unsafe {
2284 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2285 if data.is_null() {
2286 None
2287 } else {
2288 Some(&*(data as *const T))
2289 }
2290 }
2291 }
2292
2293 #[corresponds(SSL_CTX_get_ex_data)]
2296 unsafe fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2297 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2298 if data.is_null() {
2299 None
2300 } else {
2301 Some(&mut *(data as *mut T))
2302 }
2303 }
2304
2305 #[corresponds(SSL_CTX_set_ex_data)]
2309 unsafe fn write_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2310 unsafe {
2311 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2312 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2313 }
2314 }
2315
2316 #[corresponds(SSL_CTX_set_ex_data)]
2319 unsafe fn replace_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) -> Option<T> {
2320 if let Some(old) = self.ex_data_mut(index) {
2321 return Some(mem::replace(old, data));
2322 }
2323
2324 self.write_ex_data(index, data);
2325
2326 None
2327 }
2328
2329 #[corresponds(SSL_CTX_add_session)]
2338 #[must_use]
2339 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2340 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2341 }
2342
2343 #[corresponds(SSL_CTX_remove_session)]
2352 #[must_use]
2353 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2354 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2355 }
2356
2357 #[corresponds(SSL_CTX_sess_get_cache_size)]
2361 #[allow(clippy::useless_conversion)]
2362 #[must_use]
2363 pub fn session_cache_size(&self) -> u64 {
2364 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()).into() }
2365 }
2366
2367 #[corresponds(SSL_CTX_get_verify_mode)]
2371 #[must_use]
2372 pub fn verify_mode(&self) -> SslVerifyMode {
2373 #[cfg(feature = "rpk")]
2374 assert!(!self.is_rpk(), "This API is not supported for RPK");
2375
2376 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2377 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2378 }
2379
2380 #[cfg(feature = "rpk")]
2382 pub fn is_rpk(&self) -> bool {
2383 self.ex_data(*RPK_FLAG_INDEX).copied().unwrap_or_default()
2384 }
2385
2386 #[cfg(not(feature = "fips"))]
2391 #[corresponds(SSL_CTX_set1_ech_keys)]
2392 pub fn set_ech_keys(&self, keys: &SslEchKeys) -> Result<(), ErrorStack> {
2393 unsafe { cvt(ffi::SSL_CTX_set1_ech_keys(self.as_ptr(), keys.as_ptr())).map(|_| ()) }
2394 }
2395}
2396
2397#[derive(Debug)]
2402pub struct GetSessionPendingError;
2403
2404#[cfg(not(feature = "fips-compat"))]
2405type ProtosLen = usize;
2406#[cfg(feature = "fips-compat")]
2407type ProtosLen = libc::c_uint;
2408
2409pub struct CipherBits {
2411 pub secret: i32,
2413
2414 pub algorithm: i32,
2416}
2417
2418#[repr(transparent)]
2419pub struct ClientHello<'ssl>(&'ssl ffi::SSL_CLIENT_HELLO);
2420
2421impl ClientHello<'_> {
2422 #[corresponds(SSL_early_callback_ctx_extension_get)]
2424 #[must_use]
2425 pub fn get_extension(&self, ext_type: ExtensionType) -> Option<&[u8]> {
2426 unsafe {
2427 let mut ptr = ptr::null();
2428 let mut len = 0;
2429 let result =
2430 ffi::SSL_early_callback_ctx_extension_get(self.0, ext_type.0, &mut ptr, &mut len);
2431 if result == 0 {
2432 return None;
2433 }
2434 Some(slice::from_raw_parts(ptr, len))
2435 }
2436 }
2437
2438 pub fn ssl_mut(&mut self) -> &mut SslRef {
2439 unsafe { SslRef::from_ptr_mut(self.0.ssl) }
2440 }
2441
2442 #[must_use]
2443 pub fn ssl(&self) -> &SslRef {
2444 unsafe { SslRef::from_ptr(self.0.ssl) }
2445 }
2446
2447 #[must_use]
2449 pub fn servername(&self, type_: NameType) -> Option<&str> {
2450 self.ssl().servername(type_)
2451 }
2452
2453 #[must_use]
2455 pub fn client_version(&self) -> SslVersion {
2456 SslVersion(self.0.version)
2457 }
2458
2459 #[must_use]
2461 pub fn version_str(&self) -> &'static str {
2462 self.ssl().version_str()
2463 }
2464
2465 #[must_use]
2467 pub fn as_bytes(&self) -> &[u8] {
2468 unsafe { slice::from_raw_parts(self.0.client_hello, self.0.client_hello_len) }
2469 }
2470
2471 #[must_use]
2473 pub fn random(&self) -> &[u8] {
2474 unsafe { slice::from_raw_parts(self.0.random, self.0.random_len) }
2475 }
2476
2477 #[must_use]
2479 pub fn ciphers(&self) -> &[u8] {
2480 unsafe { slice::from_raw_parts(self.0.cipher_suites, self.0.cipher_suites_len) }
2481 }
2482}
2483
2484pub struct SslCipher(*mut ffi::SSL_CIPHER);
2486
2487impl SslCipher {
2488 #[corresponds(SSL_get_cipher_by_value)]
2489 #[must_use]
2490 pub fn from_value(value: u16) -> Option<Self> {
2491 unsafe {
2492 let ptr = ffi::SSL_get_cipher_by_value(value);
2493 if ptr.is_null() {
2494 None
2495 } else {
2496 Some(Self::from_ptr(ptr as *mut ffi::SSL_CIPHER))
2497 }
2498 }
2499 }
2500}
2501
2502impl Stackable for SslCipher {
2503 type StackType = ffi::stack_st_SSL_CIPHER;
2504}
2505
2506unsafe impl ForeignType for SslCipher {
2507 type CType = ffi::SSL_CIPHER;
2508 type Ref = SslCipherRef;
2509
2510 #[inline]
2511 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2512 SslCipher(ptr)
2513 }
2514
2515 #[inline]
2516 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2517 self.0
2518 }
2519}
2520
2521impl Deref for SslCipher {
2522 type Target = SslCipherRef;
2523
2524 fn deref(&self) -> &SslCipherRef {
2525 unsafe { SslCipherRef::from_ptr(self.0) }
2526 }
2527}
2528
2529impl DerefMut for SslCipher {
2530 fn deref_mut(&mut self) -> &mut SslCipherRef {
2531 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2532 }
2533}
2534
2535pub struct SslCipherRef(Opaque);
2539
2540unsafe impl ForeignTypeRef for SslCipherRef {
2541 type CType = ffi::SSL_CIPHER;
2542}
2543
2544impl SslCipherRef {
2545 #[corresponds(SSL_CIPHER_get_name)]
2547 #[must_use]
2548 pub fn name(&self) -> &'static str {
2549 unsafe {
2550 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2551 CStr::from_ptr(ptr).to_str().unwrap()
2552 }
2553 }
2554
2555 #[corresponds(SSL_CIPHER_standard_name)]
2557 #[must_use]
2558 pub fn standard_name(&self) -> Option<&'static str> {
2559 unsafe {
2560 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2561 if ptr.is_null() {
2562 None
2563 } else {
2564 Some(CStr::from_ptr(ptr).to_str().unwrap())
2565 }
2566 }
2567 }
2568
2569 #[corresponds(SSL_CIPHER_get_version)]
2571 #[must_use]
2572 pub fn version(&self) -> &'static str {
2573 let version = unsafe {
2574 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2575 CStr::from_ptr(ptr as *const _)
2576 };
2577
2578 version.to_str().unwrap()
2579 }
2580
2581 #[corresponds(SSL_CIPHER_get_bits)]
2583 #[allow(clippy::useless_conversion)]
2584 #[must_use]
2585 pub fn bits(&self) -> CipherBits {
2586 unsafe {
2587 let mut algo_bits = 0;
2588 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2589 CipherBits {
2590 secret: secret_bits.into(),
2591 algorithm: algo_bits.into(),
2592 }
2593 }
2594 }
2595
2596 #[corresponds(SSL_CIPHER_description)]
2598 #[must_use]
2599 pub fn description(&self) -> String {
2600 unsafe {
2601 let mut buf = [0; 128];
2603 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2604 CStr::from_ptr(ptr.cast()).to_string_lossy().into_owned()
2605 }
2606 }
2607
2608 #[corresponds(SSL_CIPHER_is_aead)]
2610 #[must_use]
2611 pub fn cipher_is_aead(&self) -> bool {
2612 unsafe { ffi::SSL_CIPHER_is_aead(self.as_ptr()) != 0 }
2613 }
2614
2615 #[corresponds(SSL_CIPHER_get_auth_nid)]
2617 #[must_use]
2618 pub fn cipher_auth_nid(&self) -> Option<Nid> {
2619 let n = unsafe { ffi::SSL_CIPHER_get_auth_nid(self.as_ptr()) };
2620 if n == 0 {
2621 None
2622 } else {
2623 Some(Nid::from_raw(n))
2624 }
2625 }
2626
2627 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2629 #[must_use]
2630 pub fn cipher_nid(&self) -> Option<Nid> {
2631 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2632 if n == 0 {
2633 None
2634 } else {
2635 Some(Nid::from_raw(n))
2636 }
2637 }
2638}
2639
2640foreign_type_and_impl_send_sync! {
2641 type CType = ffi::SSL_SESSION;
2642 fn drop = ffi::SSL_SESSION_free;
2643
2644 pub struct SslSession;
2648}
2649
2650impl Clone for SslSession {
2651 fn clone(&self) -> SslSession {
2652 SslSessionRef::to_owned(self)
2653 }
2654}
2655
2656impl SslSession {
2657 from_der! {
2658 #[corresponds(d2i_SSL_SESSION)]
2660 from_der,
2661 SslSession,
2662 ffi::d2i_SSL_SESSION,
2663 ::libc::c_long
2664 }
2665}
2666
2667impl ToOwned for SslSessionRef {
2668 type Owned = SslSession;
2669
2670 fn to_owned(&self) -> SslSession {
2671 unsafe {
2672 SSL_SESSION_up_ref(self.as_ptr());
2673 SslSession(NonNull::new_unchecked(self.as_ptr()))
2674 }
2675 }
2676}
2677
2678impl SslSessionRef {
2679 #[corresponds(SSL_SESSION_get_id)]
2681 #[must_use]
2682 pub fn id(&self) -> &[u8] {
2683 unsafe {
2684 let mut len = 0;
2685 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2686 slice::from_raw_parts(p, len as usize)
2687 }
2688 }
2689
2690 #[corresponds(SSL_SESSION_get_master_key)]
2692 #[must_use]
2693 pub fn master_key_len(&self) -> usize {
2694 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2695 }
2696
2697 #[corresponds(SSL_SESSION_get_master_key)]
2701 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2702 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2703 }
2704
2705 #[corresponds(SSL_SESSION_get_time)]
2707 #[allow(clippy::useless_conversion)]
2708 #[must_use]
2709 pub fn time(&self) -> u64 {
2710 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2711 }
2712
2713 #[corresponds(SSL_SESSION_get_timeout)]
2717 #[allow(clippy::useless_conversion)]
2718 #[must_use]
2719 pub fn timeout(&self) -> u32 {
2720 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()) }
2721 }
2722
2723 #[corresponds(SSL_SESSION_get_protocol_version)]
2725 #[must_use]
2726 pub fn protocol_version(&self) -> SslVersion {
2727 unsafe {
2728 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2729 SslVersion(version)
2730 }
2731 }
2732
2733 to_der! {
2734 #[corresponds(i2d_SSL_SESSION)]
2736 to_der,
2737 ffi::i2d_SSL_SESSION
2738 }
2739}
2740
2741foreign_type_and_impl_send_sync! {
2742 type CType = ffi::SSL;
2743 fn drop = ffi::SSL_free;
2744
2745 pub struct Ssl;
2752}
2753
2754impl fmt::Debug for Ssl {
2755 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2756 fmt::Debug::fmt(&**self, fmt)
2757 }
2758}
2759
2760impl Ssl {
2761 #[corresponds(SSL_get_ex_new_index)]
2766 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2767 where
2768 T: 'static + Sync + Send,
2769 {
2770 unsafe {
2771 ffi::init();
2772 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2773 Ok(Index::from_raw(idx))
2774 }
2775 }
2776
2777 fn cached_ex_index<T>() -> Index<Ssl, T>
2779 where
2780 T: 'static + Sync + Send,
2781 {
2782 unsafe {
2783 let idx = *SSL_INDEXES
2784 .lock()
2785 .unwrap_or_else(|e| e.into_inner())
2786 .entry(TypeId::of::<T>())
2787 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2788 Index::from_raw(idx)
2789 }
2790 }
2791
2792 #[corresponds(SSL_new)]
2796 pub fn new(ctx: &SslContext) -> Result<Ssl, ErrorStack> {
2797 unsafe {
2798 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2799 let mut ssl = Ssl::from_ptr(ptr);
2800 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx.clone());
2801
2802 Ok(ssl)
2803 }
2804 }
2805
2806 #[corresponds(SSL_new)]
2811 pub fn new_from_ref(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2812 unsafe {
2813 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2814 let mut ssl = Ssl::from_ptr(ptr);
2815 SSL_CTX_up_ref(ctx.as_ptr());
2816 let ctx_owned = SslContext::from_ptr(ctx.as_ptr());
2817 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx_owned);
2818
2819 Ok(ssl)
2820 }
2821 }
2822
2823 pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2835 where
2836 S: Read + Write,
2837 {
2838 SslStreamBuilder::new(self, stream).setup_connect()
2839 }
2840
2841 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2851 where
2852 S: Read + Write,
2853 {
2854 self.setup_connect(stream).handshake()
2855 }
2856
2857 pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
2869 where
2870 S: Read + Write,
2871 {
2872 #[cfg(feature = "rpk")]
2873 {
2874 let ctx = self.ssl_context();
2875
2876 if ctx.is_rpk() {
2877 unsafe {
2878 ffi::SSL_CTX_set_custom_verify(
2879 ctx.as_ptr(),
2880 SslVerifyMode::PEER.bits(),
2881 Some(rpk_verify_failure_callback),
2882 );
2883 }
2884 }
2885 }
2886
2887 SslStreamBuilder::new(self, stream).setup_accept()
2888 }
2889
2890 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2902 where
2903 S: Read + Write,
2904 {
2905 self.setup_accept(stream).handshake()
2906 }
2907}
2908
2909impl fmt::Debug for SslRef {
2910 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2911 let mut builder = fmt.debug_struct("Ssl");
2912
2913 builder.field("state", &self.state_string_long());
2914
2915 #[cfg(feature = "rpk")]
2916 if !self.ssl_context().is_rpk() {
2917 builder.field("verify_result", &self.verify_result());
2918 }
2919
2920 #[cfg(not(feature = "rpk"))]
2921 builder.field("verify_result", &self.verify_result());
2922
2923 builder.finish()
2924 }
2925}
2926
2927impl SslRef {
2928 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2929 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2930 }
2931
2932 #[corresponds(SSL_set_options)]
2939 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
2940 let bits = unsafe { ffi::SSL_set_options(self.as_ptr(), option.bits()) };
2941 SslOptions::from_bits_retain(bits)
2942 }
2943
2944 #[corresponds(SSL_clear_options)]
2946 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
2947 let bits = unsafe { ffi::SSL_clear_options(self.as_ptr(), option.bits()) };
2948 SslOptions::from_bits_retain(bits)
2949 }
2950
2951 #[corresponds(SSL_set1_curves_list)]
2952 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2953 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2954 unsafe {
2955 cvt_0i(ffi::SSL_set1_curves_list(
2956 self.as_ptr(),
2957 curves.as_ptr() as *const _,
2958 ))
2959 .map(|_| ())
2960 }
2961 }
2962
2963 #[corresponds(SSL_set1_groups)]
2966 #[deprecated(note = "SslCurveNid will be removed in the next release. Use set_curves_list")]
2967 #[allow(deprecated)]
2968 pub fn set_group_nids(&mut self, group_nids: &[SslCurveNid]) -> Result<(), ErrorStack> {
2969 unsafe {
2970 cvt_0i(ffi::SSL_set1_curves(
2971 self.as_ptr(),
2972 group_nids.as_ptr() as *const _,
2973 group_nids.len(),
2974 ))
2975 .map(|_| ())
2976 }
2977 }
2978
2979 #[cfg(feature = "kx-safe-default")]
2980 fn client_set_default_curves_list(&mut self) {
2981 let curves = if cfg!(feature = "kx-client-pq-preferred") {
2982 if cfg!(feature = "kx-client-nist-required") {
2983 "P256Kyber768Draft00:P-256:P-384:P-521"
2984 } else {
2985 "X25519MLKEM768:X25519Kyber768Draft00:X25519:P256Kyber768Draft00:P-256:P-384:P-521"
2986 }
2987 } else if cfg!(feature = "kx-client-pq-supported") {
2988 if cfg!(feature = "kx-client-nist-required") {
2989 "P-256:P-384:P-521:P256Kyber768Draft00"
2990 } else {
2991 "X25519:P-256:P-384:P-521:X25519MLKEM768:X25519Kyber768Draft00:P256Kyber768Draft00"
2992 }
2993 } else {
2994 if cfg!(feature = "kx-client-nist-required") {
2995 "P-256:P-384:P-521"
2996 } else {
2997 "X25519:P-256:P-384:P-521"
2998 }
2999 };
3000
3001 self.set_curves_list(curves)
3002 .expect("invalid default client curves list");
3003 }
3004
3005 #[cfg(feature = "kx-safe-default")]
3006 fn server_set_default_curves_list(&mut self) {
3007 self.set_curves_list(
3008 "X25519MLKEM768:X25519Kyber768Draft00:P256Kyber768Draft00:X25519:P-256:P-384",
3009 )
3010 .expect("invalid default server curves list");
3011 }
3012
3013 #[corresponds(SSL_get_curve_id)]
3015 #[must_use]
3016 #[deprecated(note = "SslCurve will be removed in the next release")]
3017 #[allow(deprecated)]
3018 pub fn curve(&self) -> Option<SslCurve> {
3019 let curve_id = unsafe { ffi::SSL_get_curve_id(self.as_ptr()) };
3020 if curve_id == 0 {
3021 return None;
3022 }
3023 Some(SslCurve(curve_id.into()))
3024 }
3025
3026 #[corresponds(SSL_get_error)]
3028 #[must_use]
3029 pub fn error_code(&self, ret: c_int) -> ErrorCode {
3030 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
3031 }
3032
3033 #[corresponds(SSL_set_verify)]
3037 pub fn set_verify(&mut self, mode: SslVerifyMode) {
3038 #[cfg(feature = "rpk")]
3039 assert!(
3040 !self.ssl_context().is_rpk(),
3041 "This API is not supported for RPK"
3042 );
3043
3044 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
3045 }
3046
3047 #[corresponds(SSL_set_verify_depth)]
3051 pub fn set_verify_depth(&mut self, depth: u32) {
3052 #[cfg(feature = "rpk")]
3053 assert!(
3054 !self.ssl_context().is_rpk(),
3055 "This API is not supported for RPK"
3056 );
3057
3058 unsafe {
3059 ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
3060 }
3061 }
3062
3063 #[corresponds(SSL_get_verify_mode)]
3065 #[must_use]
3066 pub fn verify_mode(&self) -> SslVerifyMode {
3067 #[cfg(feature = "rpk")]
3068 assert!(
3069 !self.ssl_context().is_rpk(),
3070 "This API is not supported for RPK"
3071 );
3072
3073 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
3074 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
3075 }
3076
3077 #[corresponds(SSL_set_verify)]
3094 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3095 where
3096 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
3097 {
3098 #[cfg(feature = "rpk")]
3099 assert!(
3100 !self.ssl_context().is_rpk(),
3101 "This API is not supported for RPK"
3102 );
3103
3104 unsafe {
3105 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3107 ffi::SSL_set_verify(
3108 self.as_ptr(),
3109 mode.bits() as c_int,
3110 Some(ssl_raw_verify::<F>),
3111 );
3112 }
3113 }
3114
3115 #[corresponds(SSL_set0_verify_cert_store)]
3117 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3118 #[cfg(feature = "rpk")]
3119 assert!(
3120 !self.ssl_context().is_rpk(),
3121 "This API is not supported for RPK"
3122 );
3123
3124 unsafe {
3125 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int)?;
3126 Ok(())
3127 }
3128 }
3129
3130 #[corresponds(SSL_set_custom_verify)]
3136 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3137 where
3138 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
3139 {
3140 #[cfg(feature = "rpk")]
3141 assert!(
3142 !self.ssl_context().is_rpk(),
3143 "This API is not supported for RPK"
3144 );
3145
3146 unsafe {
3147 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3149 ffi::SSL_set_custom_verify(
3150 self.as_ptr(),
3151 mode.bits() as c_int,
3152 Some(ssl_raw_custom_verify::<F>),
3153 );
3154 }
3155 }
3156
3157 #[corresponds(SSL_set_tmp_dh)]
3161 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3162 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3163 }
3164
3165 #[corresponds(SSL_set_tmp_ecdh)]
3169 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3170 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3171 }
3172
3173 #[corresponds(SSL_set_permute_extensions)]
3175 #[cfg(not(feature = "fips-compat"))]
3180 pub fn set_permute_extensions(&mut self, enabled: bool) {
3181 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as _) }
3182 }
3183
3184 #[corresponds(SSL_set_alpn_protos)]
3188 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3189 unsafe {
3190 #[cfg_attr(not(feature = "fips-compat"), allow(clippy::unnecessary_cast))]
3191 {
3192 assert!(protocols.len() <= ProtosLen::MAX as usize);
3193 }
3194 let r = ffi::SSL_set_alpn_protos(
3195 self.as_ptr(),
3196 protocols.as_ptr(),
3197 protocols.len() as ProtosLen,
3198 );
3199 if r == 0 {
3201 Ok(())
3202 } else {
3203 Err(ErrorStack::get())
3204 }
3205 }
3206 }
3207
3208 #[corresponds(SSL_get_ciphers)]
3210 #[must_use]
3211 pub fn ciphers(&self) -> &StackRef<SslCipher> {
3212 unsafe {
3213 let cipher_list = ffi::SSL_get_ciphers(self.as_ptr());
3214 StackRef::from_ptr(cipher_list)
3215 }
3216 }
3217
3218 #[corresponds(SSL_get_current_cipher)]
3220 #[must_use]
3221 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3222 unsafe {
3223 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3224
3225 if ptr.is_null() {
3226 None
3227 } else {
3228 Some(SslCipherRef::from_ptr(ptr as *mut _))
3229 }
3230 }
3231 }
3232
3233 #[corresponds(SSL_state_string)]
3237 #[must_use]
3238 pub fn state_string(&self) -> &'static str {
3239 let state = unsafe {
3240 let ptr = ffi::SSL_state_string(self.as_ptr());
3241 CStr::from_ptr(ptr as *const _)
3242 };
3243
3244 state.to_str().unwrap_or_default()
3245 }
3246
3247 #[corresponds(SSL_state_string_long)]
3251 #[must_use]
3252 pub fn state_string_long(&self) -> &'static str {
3253 let state = unsafe {
3254 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3255 CStr::from_ptr(ptr as *const _)
3256 };
3257
3258 state.to_str().unwrap_or_default()
3259 }
3260
3261 #[corresponds(SSL_set_tlsext_host_name)]
3265 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3266 let cstr = CString::new(hostname).map_err(ErrorStack::internal_error)?;
3267 unsafe {
3268 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3269 .map(|_| ())
3270 }
3271 }
3272
3273 #[corresponds(SSL_get_peer_certificate)]
3275 #[must_use]
3276 pub fn peer_certificate(&self) -> Option<X509> {
3277 #[cfg(feature = "rpk")]
3278 assert!(
3279 !self.ssl_context().is_rpk(),
3280 "This API is not supported for RPK"
3281 );
3282
3283 unsafe {
3284 let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
3285 if ptr.is_null() {
3286 None
3287 } else {
3288 Some(X509::from_ptr(ptr))
3289 }
3290 }
3291 }
3292
3293 #[corresponds(SSL_get_peer_certificate)]
3298 #[must_use]
3299 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3300 #[cfg(feature = "rpk")]
3301 assert!(
3302 !self.ssl_context().is_rpk(),
3303 "This API is not supported for RPK"
3304 );
3305
3306 unsafe {
3307 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3308 if ptr.is_null() {
3309 None
3310 } else {
3311 Some(StackRef::from_ptr(ptr))
3312 }
3313 }
3314 }
3315
3316 #[corresponds(SSL_get_certificate)]
3318 #[must_use]
3319 pub fn certificate(&self) -> Option<&X509Ref> {
3320 #[cfg(feature = "rpk")]
3321 assert!(
3322 !self.ssl_context().is_rpk(),
3323 "This API is not supported for RPK"
3324 );
3325
3326 unsafe {
3327 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3328 if ptr.is_null() {
3329 None
3330 } else {
3331 Some(X509Ref::from_ptr(ptr))
3332 }
3333 }
3334 }
3335
3336 #[corresponds(SSL_get_privatekey)]
3338 #[must_use]
3339 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3340 unsafe {
3341 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3342 if ptr.is_null() {
3343 None
3344 } else {
3345 Some(PKeyRef::from_ptr(ptr))
3346 }
3347 }
3348 }
3349
3350 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
3351 #[must_use]
3352 pub fn version(&self) -> &str {
3353 self.version_str()
3354 }
3355
3356 #[corresponds(SSL_version)]
3358 pub fn version2(&self) -> Option<SslVersion> {
3359 unsafe {
3360 let r = ffi::SSL_version(self.as_ptr());
3361 if r == 0 {
3362 None
3363 } else {
3364 r.try_into().ok().map(SslVersion)
3365 }
3366 }
3367 }
3368
3369 #[corresponds(SSL_get_version)]
3373 #[must_use]
3374 pub fn version_str(&self) -> &'static str {
3375 let version = unsafe {
3376 let ptr = ffi::SSL_get_version(self.as_ptr());
3377 CStr::from_ptr(ptr as *const _)
3378 };
3379
3380 version.to_str().unwrap()
3381 }
3382
3383 #[corresponds(SSL_set_min_proto_version)]
3388 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3389 unsafe {
3390 cvt(ffi::SSL_set_min_proto_version(
3391 self.as_ptr(),
3392 version.map_or(0, |v| v.0 as _),
3393 ))
3394 .map(|_| ())
3395 }
3396 }
3397
3398 #[corresponds(SSL_set_max_proto_version)]
3402 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3403 unsafe {
3404 cvt(ffi::SSL_set_max_proto_version(
3405 self.as_ptr(),
3406 version.map_or(0, |v| v.0 as _),
3407 ))
3408 .map(|_| ())
3409 }
3410 }
3411
3412 #[corresponds(SSL_get_min_proto_version)]
3414 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
3415 unsafe {
3416 let r = ffi::SSL_get_min_proto_version(self.as_ptr());
3417 if r == 0 {
3418 None
3419 } else {
3420 Some(SslVersion(r))
3421 }
3422 }
3423 }
3424
3425 #[corresponds(SSL_get_max_proto_version)]
3427 #[must_use]
3428 pub fn max_proto_version(&self) -> Option<SslVersion> {
3429 let r = unsafe { ffi::SSL_get_max_proto_version(self.as_ptr()) };
3430 if r == 0 {
3431 None
3432 } else {
3433 Some(SslVersion(r))
3434 }
3435 }
3436
3437 #[corresponds(SSL_get0_alpn_selected)]
3442 #[must_use]
3443 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3444 unsafe {
3445 let mut data: *const c_uchar = ptr::null();
3446 let mut len: c_uint = 0;
3447 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3450
3451 if data.is_null() {
3452 None
3453 } else {
3454 Some(slice::from_raw_parts(data, len as usize))
3455 }
3456 }
3457 }
3458
3459 #[corresponds(SSL_set_tlsext_use_srtp)]
3461 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3462 unsafe {
3463 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
3464
3465 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3466 if r == 0 {
3468 Ok(())
3469 } else {
3470 Err(ErrorStack::get())
3471 }
3472 }
3473 }
3474
3475 #[corresponds(SSL_get_strp_profiles)]
3479 #[must_use]
3480 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3481 unsafe {
3482 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3483
3484 if chain.is_null() {
3485 None
3486 } else {
3487 Some(StackRef::from_ptr(chain as *mut _))
3488 }
3489 }
3490 }
3491
3492 #[corresponds(SSL_get_selected_srtp_profile)]
3496 #[must_use]
3497 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3498 unsafe {
3499 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3500
3501 if profile.is_null() {
3502 None
3503 } else {
3504 Some(SrtpProtectionProfileRef::from_ptr(profile as *mut _))
3505 }
3506 }
3507 }
3508
3509 #[corresponds(SSL_pending)]
3514 #[must_use]
3515 pub fn pending(&self) -> usize {
3516 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3517 }
3518
3519 #[corresponds(SSL_get_servername)]
3532 #[must_use]
3533 pub fn servername(&self, type_: NameType) -> Option<&str> {
3534 self.servername_raw(type_)
3535 .and_then(|b| str::from_utf8(b).ok())
3536 }
3537
3538 #[corresponds(SSL_get_servername)]
3546 #[must_use]
3547 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3548 unsafe {
3549 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3550 if name.is_null() {
3551 None
3552 } else {
3553 Some(CStr::from_ptr(name as *const _).to_bytes())
3554 }
3555 }
3556 }
3557
3558 #[corresponds(SSL_set_SSL_CTX)]
3562 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3563 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3564 }
3565
3566 #[corresponds(SSL_get_SSL_CTX)]
3568 #[must_use]
3569 pub fn ssl_context(&self) -> &SslContextRef {
3570 unsafe {
3571 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3572 SslContextRef::from_ptr(ssl_ctx)
3573 }
3574 }
3575
3576 #[corresponds(SSL_get0_param)]
3578 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
3579 #[cfg(feature = "rpk")]
3580 assert!(
3581 !self.ssl_context().is_rpk(),
3582 "This API is not supported for RPK"
3583 );
3584
3585 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3586 }
3587
3588 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3590 self.verify_param_mut()
3591 }
3592
3593 #[corresponds(SSL_get_verify_result)]
3595 pub fn verify_result(&self) -> X509VerifyResult {
3596 #[cfg(feature = "rpk")]
3597 assert!(
3598 !self.ssl_context().is_rpk(),
3599 "This API is not supported for RPK"
3600 );
3601
3602 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3603 }
3604
3605 #[corresponds(SSL_get_session)]
3607 #[must_use]
3608 pub fn session(&self) -> Option<&SslSessionRef> {
3609 unsafe {
3610 let p = ffi::SSL_get_session(self.as_ptr());
3611 if p.is_null() {
3612 None
3613 } else {
3614 Some(SslSessionRef::from_ptr(p))
3615 }
3616 }
3617 }
3618
3619 #[corresponds(SSL_get_client_random)]
3624 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3625 unsafe {
3626 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3627 }
3628 }
3629
3630 #[corresponds(SSL_get_server_random)]
3635 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3636 unsafe {
3637 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3638 }
3639 }
3640
3641 #[corresponds(SSL_export_keying_material)]
3643 pub fn export_keying_material(
3644 &self,
3645 out: &mut [u8],
3646 label: &str,
3647 context: Option<&[u8]>,
3648 ) -> Result<(), ErrorStack> {
3649 unsafe {
3650 let (context, contextlen, use_context) = match context {
3651 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3652 None => (ptr::null(), 0, 0),
3653 };
3654 cvt(ffi::SSL_export_keying_material(
3655 self.as_ptr(),
3656 out.as_mut_ptr() as *mut c_uchar,
3657 out.len(),
3658 label.as_ptr() as *const c_char,
3659 label.len(),
3660 context,
3661 contextlen,
3662 use_context,
3663 ))
3664 .map(|_| ())
3665 }
3666 }
3667
3668 #[corresponds(SSL_set_session)]
3679 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3680 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3681 }
3682
3683 #[corresponds(SSL_session_reused)]
3685 #[must_use]
3686 pub fn session_reused(&self) -> bool {
3687 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3688 }
3689
3690 #[corresponds(SSL_set_tlsext_status_type)]
3692 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3693 unsafe {
3694 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3695 }
3696 }
3697
3698 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3700 #[must_use]
3701 pub fn ocsp_status(&self) -> Option<&[u8]> {
3702 unsafe {
3703 let mut p = ptr::null();
3704 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3705
3706 if len == 0 {
3707 None
3708 } else {
3709 Some(slice::from_raw_parts(p, len))
3710 }
3711 }
3712 }
3713
3714 #[corresponds(SSL_set_tlsext_status_ocsp_resp)]
3716 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3717 unsafe {
3718 assert!(response.len() <= c_int::MAX as usize);
3719 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3720 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3721 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3722 self.as_ptr(),
3723 p as *mut c_uchar,
3724 response.len(),
3725 ) as c_int)
3726 .map(|_| ())
3727 }
3728 }
3729
3730 #[corresponds(SSL_is_server)]
3732 #[must_use]
3733 pub fn is_server(&self) -> bool {
3734 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3735 }
3736
3737 #[corresponds(SSL_set_ex_data)]
3745 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3746 if let Some(old) = self.ex_data_mut(index) {
3747 *old = data;
3748
3749 return;
3750 }
3751
3752 unsafe {
3753 let data = Box::new(data);
3754 ffi::SSL_set_ex_data(
3755 self.as_ptr(),
3756 index.as_raw(),
3757 Box::into_raw(data) as *mut c_void,
3758 );
3759 }
3760 }
3761
3762 #[corresponds(SSL_set_ex_data)]
3769 pub fn replace_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) -> Option<T> {
3770 if let Some(old) = self.ex_data_mut(index) {
3771 return Some(mem::replace(old, data));
3772 }
3773
3774 self.set_ex_data(index, data);
3775
3776 None
3777 }
3778
3779 #[corresponds(SSL_get_ex_data)]
3781 #[must_use]
3782 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3783 unsafe {
3784 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3785 if data.is_null() {
3786 None
3787 } else {
3788 Some(&*(data as *const T))
3789 }
3790 }
3791 }
3792
3793 #[corresponds(SSL_get_ex_data)]
3795 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3796 unsafe {
3797 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3798 if data.is_null() {
3799 None
3800 } else {
3801 Some(&mut *(data as *mut T))
3802 }
3803 }
3804 }
3805
3806 #[corresponds(SSL_get_finished)]
3811 pub fn finished(&self, buf: &mut [u8]) -> usize {
3812 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3813 }
3814
3815 #[corresponds(SSL_get_peer_finished)]
3821 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3822 unsafe {
3823 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3824 }
3825 }
3826
3827 #[corresponds(SSL_is_init_finished)]
3829 #[must_use]
3830 pub fn is_init_finished(&self) -> bool {
3831 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3832 }
3833
3834 #[corresponds(SSL_set_mtu)]
3836 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3837 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_uint) as c_int).map(|_| ()) }
3838 }
3839
3840 #[corresponds(SSL_use_certificate)]
3842 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3843 unsafe {
3844 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3845 }
3846
3847 Ok(())
3848 }
3849
3850 #[corresponds(SSL_set_client_CA_list)]
3855 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3856 #[cfg(feature = "rpk")]
3857 assert!(
3858 !self.ssl_context().is_rpk(),
3859 "This API is not supported for RPK"
3860 );
3861
3862 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3863 mem::forget(list);
3864 }
3865
3866 #[corresponds(SSL_use_PrivateKey)]
3868 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
3869 where
3870 T: HasPrivate,
3871 {
3872 unsafe { cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
3873 }
3874
3875 #[corresponds(SSL_set_mode)]
3878 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
3879 let bits = unsafe { ffi::SSL_set_mode(self.as_ptr(), mode.bits()) };
3880 SslMode::from_bits_retain(bits)
3881 }
3882
3883 #[corresponds(SSL_clear_mode)]
3886 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
3887 let bits = unsafe { ffi::SSL_clear_mode(self.as_ptr(), mode.bits()) };
3888 SslMode::from_bits_retain(bits)
3889 }
3890
3891 #[corresponds(SSL_add1_chain_cert)]
3893 pub fn add_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3894 unsafe { cvt(ffi::SSL_add1_chain_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
3895 }
3896
3897 #[cfg(not(feature = "fips"))]
3905 #[corresponds(SSL_set1_ech_config_list)]
3906 pub fn set_ech_config_list(&mut self, ech_config_list: &[u8]) -> Result<(), ErrorStack> {
3907 unsafe {
3908 cvt_0i(ffi::SSL_set1_ech_config_list(
3909 self.as_ptr(),
3910 ech_config_list.as_ptr(),
3911 ech_config_list.len(),
3912 ))
3913 .map(|_| ())
3914 }
3915 }
3916
3917 #[cfg(not(feature = "fips"))]
3924 #[corresponds(SSL_get0_ech_retry_configs)]
3925 #[must_use]
3926 pub fn get_ech_retry_configs(&self) -> Option<&[u8]> {
3927 unsafe {
3928 let mut data = ptr::null();
3929 let mut len: usize = 0;
3930 ffi::SSL_get0_ech_retry_configs(self.as_ptr(), &mut data, &mut len);
3931
3932 if data.is_null() {
3933 None
3934 } else {
3935 Some(slice::from_raw_parts(data, len))
3936 }
3937 }
3938 }
3939
3940 #[cfg(not(feature = "fips"))]
3947 #[corresponds(SSL_get0_ech_name_override)]
3948 #[must_use]
3949 pub fn get_ech_name_override(&self) -> Option<&[u8]> {
3950 unsafe {
3951 let mut data: *const c_char = ptr::null();
3952 let mut len: usize = 0;
3953 ffi::SSL_get0_ech_name_override(self.as_ptr(), &mut data, &mut len);
3954
3955 if data.is_null() {
3956 None
3957 } else {
3958 Some(slice::from_raw_parts(data as *const u8, len))
3959 }
3960 }
3961 }
3962
3963 #[cfg(not(feature = "fips"))]
3965 #[corresponds(SSL_ech_accepted)]
3966 #[must_use]
3967 pub fn ech_accepted(&self) -> bool {
3968 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
3969 }
3970
3971 #[cfg(not(feature = "fips"))]
3973 #[corresponds(SSL_set_enable_ech_grease)]
3974 pub fn set_enable_ech_grease(&self, enable: bool) {
3975 let enable = if enable { 1 } else { 0 };
3976
3977 unsafe {
3978 ffi::SSL_set_enable_ech_grease(self.as_ptr(), enable);
3979 }
3980 }
3981
3982 #[cfg(not(feature = "fips-compat"))]
3984 #[corresponds(SSL_set_compliance_policy)]
3985 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
3986 unsafe { cvt_0i(ffi::SSL_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
3987 }
3988}
3989
3990#[derive(Debug)]
3992pub struct MidHandshakeSslStream<S> {
3993 stream: SslStream<S>,
3994 error: Error,
3995}
3996
3997impl<S> MidHandshakeSslStream<S> {
3998 #[must_use]
4000 pub fn get_ref(&self) -> &S {
4001 self.stream.get_ref()
4002 }
4003
4004 pub fn get_mut(&mut self) -> &mut S {
4006 self.stream.get_mut()
4007 }
4008
4009 #[must_use]
4011 pub fn ssl(&self) -> &SslRef {
4012 self.stream.ssl()
4013 }
4014
4015 pub fn ssl_mut(&mut self) -> &mut SslRef {
4017 self.stream.ssl_mut()
4018 }
4019
4020 #[must_use]
4022 pub fn error(&self) -> &Error {
4023 &self.error
4024 }
4025
4026 #[must_use]
4028 pub fn into_error(self) -> Error {
4029 self.error
4030 }
4031
4032 #[must_use]
4034 pub fn into_source_stream(self) -> S {
4035 self.stream.into_inner()
4036 }
4037
4038 #[must_use]
4040 pub fn into_parts(self) -> (Error, S) {
4041 (self.error, self.stream.into_inner())
4042 }
4043
4044 #[corresponds(SSL_do_handshake)]
4046 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4047 let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) };
4048 if ret > 0 {
4049 Ok(self.stream)
4050 } else {
4051 self.error = self.stream.make_error(ret);
4052 Err(if self.error.would_block() {
4053 HandshakeError::WouldBlock(self)
4054 } else {
4055 HandshakeError::Failure(self)
4056 })
4057 }
4058 }
4059}
4060
4061pub struct SslStream<S> {
4063 ssl: ManuallyDrop<Ssl>,
4064 method: ManuallyDrop<BioMethod>,
4065 _p: PhantomData<S>,
4066}
4067
4068impl<S> Drop for SslStream<S> {
4069 fn drop(&mut self) {
4070 unsafe {
4072 ManuallyDrop::drop(&mut self.ssl);
4073 ManuallyDrop::drop(&mut self.method);
4074 }
4075 }
4076}
4077
4078impl<S> fmt::Debug for SslStream<S>
4079where
4080 S: fmt::Debug,
4081{
4082 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
4083 fmt.debug_struct("SslStream")
4084 .field("stream", &self.get_ref())
4085 .field("ssl", &self.ssl())
4086 .finish()
4087 }
4088}
4089
4090impl<S: Read + Write> SslStream<S> {
4091 fn new_base(ssl: Ssl, stream: S) -> Self {
4092 unsafe {
4093 let (bio, method) = bio::new(stream).unwrap();
4094 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4095
4096 SslStream {
4097 ssl: ManuallyDrop::new(ssl),
4098 method: ManuallyDrop::new(method),
4099 _p: PhantomData,
4100 }
4101 }
4102 }
4103
4104 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4110 Ok(Self::new_base(ssl, stream))
4111 }
4112
4113 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
4121 let ssl = Ssl::from_ptr(ssl);
4122 Self::new_base(ssl, stream)
4123 }
4124
4125 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4132 loop {
4133 match self.ssl_read_uninit(buf) {
4134 Ok(n) => return Ok(n),
4135 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4136 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4137 return Ok(0);
4138 }
4139 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4140 Err(e) => {
4141 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4142 }
4143 }
4144 }
4145 }
4146
4147 #[corresponds(SSL_read)]
4152 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4153 unsafe {
4155 self.ssl_read_uninit(slice::from_raw_parts_mut(
4156 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4157 buf.len(),
4158 ))
4159 }
4160 }
4161
4162 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4169 if buf.is_empty() {
4170 return Ok(0);
4171 }
4172
4173 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4174 let ret = unsafe { ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) };
4175 if ret > 0 {
4176 Ok(ret as usize)
4177 } else {
4178 Err(self.make_error(ret))
4179 }
4180 }
4181
4182 #[corresponds(SSL_write)]
4187 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4188 if buf.is_empty() {
4189 return Ok(0);
4190 }
4191
4192 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4193 let ret = unsafe { ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) };
4194 if ret > 0 {
4195 Ok(ret as usize)
4196 } else {
4197 Err(self.make_error(ret))
4198 }
4199 }
4200
4201 #[corresponds(SSL_shutdown)]
4211 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4212 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4213 0 => Ok(ShutdownResult::Sent),
4214 1 => Ok(ShutdownResult::Received),
4215 n => Err(self.make_error(n)),
4216 }
4217 }
4218
4219 #[corresponds(SSL_get_shutdown)]
4221 pub fn get_shutdown(&mut self) -> ShutdownState {
4222 unsafe {
4223 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4224 ShutdownState::from_bits_retain(bits)
4225 }
4226 }
4227
4228 #[corresponds(SSL_set_shutdown)]
4233 pub fn set_shutdown(&mut self, state: ShutdownState) {
4234 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4235 }
4236
4237 #[corresponds(SSL_connect)]
4239 pub fn connect(&mut self) -> Result<(), Error> {
4240 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4241 if ret > 0 {
4242 Ok(())
4243 } else {
4244 Err(self.make_error(ret))
4245 }
4246 }
4247
4248 #[corresponds(SSL_accept)]
4250 pub fn accept(&mut self) -> Result<(), Error> {
4251 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4252 if ret > 0 {
4253 Ok(())
4254 } else {
4255 Err(self.make_error(ret))
4256 }
4257 }
4258
4259 #[corresponds(SSL_do_handshake)]
4261 pub fn do_handshake(&mut self) -> Result<(), Error> {
4262 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4263 if ret > 0 {
4264 Ok(())
4265 } else {
4266 Err(self.make_error(ret))
4267 }
4268 }
4269}
4270
4271impl<S> SslStream<S> {
4272 fn make_error(&mut self, ret: c_int) -> Error {
4273 self.check_panic();
4274
4275 let code = self.ssl.error_code(ret);
4276
4277 let cause = match code {
4278 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4279 ErrorCode::SYSCALL => {
4280 let errs = ErrorStack::get();
4281 if errs.errors().is_empty() {
4282 self.get_bio_error().map(InnerError::Io)
4283 } else {
4284 Some(InnerError::Ssl(errs))
4285 }
4286 }
4287 ErrorCode::ZERO_RETURN => None,
4288 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4289 self.get_bio_error().map(InnerError::Io)
4290 }
4291 _ => None,
4292 };
4293
4294 Error { code, cause }
4295 }
4296
4297 fn check_panic(&mut self) {
4298 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4299 resume_unwind(err)
4300 }
4301 }
4302
4303 fn get_bio_error(&mut self) -> Option<io::Error> {
4304 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4305 }
4306
4307 #[must_use]
4309 pub fn into_inner(self) -> S {
4310 unsafe { bio::take_stream::<S>(self.ssl.get_raw_rbio()) }
4311 }
4312
4313 #[must_use]
4315 pub fn get_ref(&self) -> &S {
4316 unsafe {
4317 let bio = self.ssl.get_raw_rbio();
4318 bio::get_ref(bio)
4319 }
4320 }
4321
4322 pub fn get_mut(&mut self) -> &mut S {
4329 unsafe {
4330 let bio = self.ssl.get_raw_rbio();
4331 bio::get_mut(bio)
4332 }
4333 }
4334
4335 #[must_use]
4337 pub fn ssl(&self) -> &SslRef {
4338 &self.ssl
4339 }
4340
4341 pub fn ssl_mut(&mut self) -> &mut SslRef {
4343 &mut self.ssl
4344 }
4345}
4346
4347impl<S: Read + Write> Read for SslStream<S> {
4348 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4349 unsafe {
4351 self.read_uninit(slice::from_raw_parts_mut(
4352 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4353 buf.len(),
4354 ))
4355 }
4356 }
4357}
4358
4359impl<S: Read + Write> Write for SslStream<S> {
4360 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4361 loop {
4362 match self.ssl_write(buf) {
4363 Ok(n) => return Ok(n),
4364 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4365 Err(e) => {
4366 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4367 }
4368 }
4369 }
4370 }
4371
4372 fn flush(&mut self) -> io::Result<()> {
4373 self.get_mut().flush()
4374 }
4375}
4376
4377pub struct SslStreamBuilder<S> {
4379 inner: SslStream<S>,
4380}
4381
4382impl<S> SslStreamBuilder<S>
4383where
4384 S: Read + Write,
4385{
4386 pub fn new(ssl: Ssl, stream: S) -> Self {
4388 Self {
4389 inner: SslStream::new_base(ssl, stream),
4390 }
4391 }
4392
4393 #[corresponds(SSL_set_connect_state)]
4395 pub fn set_connect_state(&mut self) {
4396 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4397 }
4398
4399 #[corresponds(SSL_set_accept_state)]
4401 pub fn set_accept_state(&mut self) {
4402 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4403 }
4404
4405 #[must_use]
4411 pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
4412 self.set_connect_state();
4413
4414 #[cfg(feature = "kx-safe-default")]
4415 self.inner.ssl.client_set_default_curves_list();
4416
4417 MidHandshakeSslStream {
4418 stream: self.inner,
4419 error: Error {
4420 code: ErrorCode::WANT_WRITE,
4421 cause: Some(InnerError::Io(io::Error::new(
4422 io::ErrorKind::WouldBlock,
4423 "connect handshake has not started yet",
4424 ))),
4425 },
4426 }
4427 }
4428
4429 pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
4434 self.setup_connect().handshake()
4435 }
4436
4437 #[must_use]
4443 pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
4444 self.set_accept_state();
4445
4446 #[cfg(feature = "kx-safe-default")]
4447 self.inner.ssl.server_set_default_curves_list();
4448
4449 MidHandshakeSslStream {
4450 stream: self.inner,
4451 error: Error {
4452 code: ErrorCode::WANT_READ,
4453 cause: Some(InnerError::Io(io::Error::new(
4454 io::ErrorKind::WouldBlock,
4455 "accept handshake has not started yet",
4456 ))),
4457 },
4458 }
4459 }
4460
4461 pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
4466 self.setup_accept().handshake()
4467 }
4468
4469 #[corresponds(SSL_do_handshake)]
4473 pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
4474 let mut stream = self.inner;
4475 let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
4476 if ret > 0 {
4477 Ok(stream)
4478 } else {
4479 let error = stream.make_error(ret);
4480 Err(if error.would_block() {
4481 HandshakeError::WouldBlock(MidHandshakeSslStream { stream, error })
4482 } else {
4483 HandshakeError::Failure(MidHandshakeSslStream { stream, error })
4484 })
4485 }
4486 }
4487}
4488
4489impl<S> SslStreamBuilder<S> {
4490 #[must_use]
4492 pub fn get_ref(&self) -> &S {
4493 unsafe {
4494 let bio = self.inner.ssl.get_raw_rbio();
4495 bio::get_ref(bio)
4496 }
4497 }
4498
4499 pub fn get_mut(&mut self) -> &mut S {
4506 unsafe {
4507 let bio = self.inner.ssl.get_raw_rbio();
4508 bio::get_mut(bio)
4509 }
4510 }
4511
4512 #[must_use]
4514 pub fn ssl(&self) -> &SslRef {
4515 &self.inner.ssl
4516 }
4517
4518 pub fn ssl_mut(&mut self) -> &mut SslRef {
4520 &mut self.inner.ssl
4521 }
4522
4523 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4531 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4532 unsafe {
4533 let bio = self.inner.ssl.get_raw_rbio();
4534 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4535 }
4536 }
4537}
4538
4539#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4541pub enum ShutdownResult {
4542 Sent,
4544
4545 Received,
4547}
4548
4549bitflags! {
4550 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
4552 pub struct ShutdownState: c_int {
4553 const SENT = ffi::SSL_SENT_SHUTDOWN;
4555 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4557 }
4558}
4559
4560pub trait PrivateKeyMethod: Send + Sync + 'static {
4568 fn sign(
4579 &self,
4580 ssl: &mut SslRef,
4581 input: &[u8],
4582 signature_algorithm: SslSignatureAlgorithm,
4583 output: &mut [u8],
4584 ) -> Result<usize, PrivateKeyMethodError>;
4585
4586 fn decrypt(
4601 &self,
4602 ssl: &mut SslRef,
4603 input: &[u8],
4604 output: &mut [u8],
4605 ) -> Result<usize, PrivateKeyMethodError>;
4606
4607 fn complete(&self, ssl: &mut SslRef, output: &mut [u8])
4616 -> Result<usize, PrivateKeyMethodError>;
4617}
4618
4619#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4621pub struct PrivateKeyMethodError(ffi::ssl_private_key_result_t);
4622
4623impl PrivateKeyMethodError {
4624 pub const FAILURE: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_failure);
4626
4627 pub const RETRY: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_retry);
4629}
4630
4631pub trait CertificateCompressor: Send + Sync + 'static {
4633 const ALGORITHM: CertificateCompressionAlgorithm;
4635
4636 const CAN_COMPRESS: bool;
4638
4639 const CAN_DECOMPRESS: bool;
4641
4642 #[allow(unused_variables)]
4644 fn compress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4645 where
4646 W: std::io::Write,
4647 {
4648 Err(std::io::Error::other("not implemented"))
4649 }
4650
4651 #[allow(unused_variables)]
4653 fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4654 where
4655 W: std::io::Write,
4656 {
4657 Err(std::io::Error::other("not implemented"))
4658 }
4659}
4660
4661use crate::ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4662
4663use crate::ffi::{DTLS_method, TLS_client_method, TLS_method, TLS_server_method};
4664
4665use std::sync::Once;
4666
4667unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4668 static ONCE: Once = Once::new();
4670 ONCE.call_once(|| {
4671 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4672 });
4673
4674 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4675}
4676
4677unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4678 static ONCE: Once = Once::new();
4680 ONCE.call_once(|| {
4681 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4682 });
4683
4684 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4685}