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 let r = ffi::SSL_CTX_set_alpn_protos(
1616 self.as_ptr(),
1617 protocols.as_ptr(),
1618 #[allow(clippy::useless_conversion)]
1619 protocols
1620 .len()
1621 .try_into()
1622 .map_err(ErrorStack::internal_error)?,
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
2404pub struct CipherBits {
2406 pub secret: i32,
2408
2409 pub algorithm: i32,
2411}
2412
2413#[repr(transparent)]
2414pub struct ClientHello<'ssl>(&'ssl ffi::SSL_CLIENT_HELLO);
2415
2416impl ClientHello<'_> {
2417 #[corresponds(SSL_early_callback_ctx_extension_get)]
2419 #[must_use]
2420 pub fn get_extension(&self, ext_type: ExtensionType) -> Option<&[u8]> {
2421 unsafe {
2422 let mut ptr = ptr::null();
2423 let mut len = 0;
2424 let result =
2425 ffi::SSL_early_callback_ctx_extension_get(self.0, ext_type.0, &mut ptr, &mut len);
2426 if result == 0 {
2427 return None;
2428 }
2429 Some(slice::from_raw_parts(ptr, len))
2430 }
2431 }
2432
2433 pub fn ssl_mut(&mut self) -> &mut SslRef {
2434 unsafe { SslRef::from_ptr_mut(self.0.ssl) }
2435 }
2436
2437 #[must_use]
2438 pub fn ssl(&self) -> &SslRef {
2439 unsafe { SslRef::from_ptr(self.0.ssl) }
2440 }
2441
2442 #[must_use]
2444 pub fn servername(&self, type_: NameType) -> Option<&str> {
2445 self.ssl().servername(type_)
2446 }
2447
2448 #[must_use]
2450 pub fn client_version(&self) -> SslVersion {
2451 SslVersion(self.0.version)
2452 }
2453
2454 #[must_use]
2456 pub fn version_str(&self) -> &'static str {
2457 self.ssl().version_str()
2458 }
2459
2460 #[must_use]
2462 pub fn as_bytes(&self) -> &[u8] {
2463 unsafe { slice::from_raw_parts(self.0.client_hello, self.0.client_hello_len) }
2464 }
2465
2466 #[must_use]
2468 pub fn random(&self) -> &[u8] {
2469 unsafe { slice::from_raw_parts(self.0.random, self.0.random_len) }
2470 }
2471
2472 #[must_use]
2474 pub fn ciphers(&self) -> &[u8] {
2475 unsafe { slice::from_raw_parts(self.0.cipher_suites, self.0.cipher_suites_len) }
2476 }
2477}
2478
2479pub struct SslCipher(*mut ffi::SSL_CIPHER);
2481
2482impl SslCipher {
2483 #[corresponds(SSL_get_cipher_by_value)]
2484 #[must_use]
2485 pub fn from_value(value: u16) -> Option<Self> {
2486 unsafe {
2487 let ptr = ffi::SSL_get_cipher_by_value(value);
2488 if ptr.is_null() {
2489 None
2490 } else {
2491 Some(Self::from_ptr(ptr as *mut ffi::SSL_CIPHER))
2492 }
2493 }
2494 }
2495}
2496
2497impl Stackable for SslCipher {
2498 type StackType = ffi::stack_st_SSL_CIPHER;
2499}
2500
2501unsafe impl ForeignType for SslCipher {
2502 type CType = ffi::SSL_CIPHER;
2503 type Ref = SslCipherRef;
2504
2505 #[inline]
2506 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2507 SslCipher(ptr)
2508 }
2509
2510 #[inline]
2511 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2512 self.0
2513 }
2514}
2515
2516impl Deref for SslCipher {
2517 type Target = SslCipherRef;
2518
2519 fn deref(&self) -> &SslCipherRef {
2520 unsafe { SslCipherRef::from_ptr(self.0) }
2521 }
2522}
2523
2524impl DerefMut for SslCipher {
2525 fn deref_mut(&mut self) -> &mut SslCipherRef {
2526 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2527 }
2528}
2529
2530pub struct SslCipherRef(Opaque);
2534
2535unsafe impl ForeignTypeRef for SslCipherRef {
2536 type CType = ffi::SSL_CIPHER;
2537}
2538
2539impl SslCipherRef {
2540 #[corresponds(SSL_CIPHER_get_name)]
2542 #[must_use]
2543 pub fn name(&self) -> &'static str {
2544 unsafe {
2545 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2546 CStr::from_ptr(ptr).to_str().unwrap()
2547 }
2548 }
2549
2550 #[corresponds(SSL_CIPHER_standard_name)]
2552 #[must_use]
2553 pub fn standard_name(&self) -> Option<&'static str> {
2554 unsafe {
2555 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2556 if ptr.is_null() {
2557 None
2558 } else {
2559 Some(CStr::from_ptr(ptr).to_str().unwrap())
2560 }
2561 }
2562 }
2563
2564 #[corresponds(SSL_CIPHER_get_version)]
2566 #[must_use]
2567 pub fn version(&self) -> &'static str {
2568 let version = unsafe {
2569 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2570 CStr::from_ptr(ptr as *const _)
2571 };
2572
2573 version.to_str().unwrap()
2574 }
2575
2576 #[corresponds(SSL_CIPHER_get_bits)]
2578 #[allow(clippy::useless_conversion)]
2579 #[must_use]
2580 pub fn bits(&self) -> CipherBits {
2581 unsafe {
2582 let mut algo_bits = 0;
2583 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2584 CipherBits {
2585 secret: secret_bits.into(),
2586 algorithm: algo_bits.into(),
2587 }
2588 }
2589 }
2590
2591 #[corresponds(SSL_CIPHER_description)]
2593 #[must_use]
2594 pub fn description(&self) -> String {
2595 unsafe {
2596 let mut buf = [0; 128];
2598 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2599 CStr::from_ptr(ptr.cast()).to_string_lossy().into_owned()
2600 }
2601 }
2602
2603 #[corresponds(SSL_CIPHER_is_aead)]
2605 #[must_use]
2606 pub fn cipher_is_aead(&self) -> bool {
2607 unsafe { ffi::SSL_CIPHER_is_aead(self.as_ptr()) != 0 }
2608 }
2609
2610 #[corresponds(SSL_CIPHER_get_auth_nid)]
2612 #[must_use]
2613 pub fn cipher_auth_nid(&self) -> Option<Nid> {
2614 let n = unsafe { ffi::SSL_CIPHER_get_auth_nid(self.as_ptr()) };
2615 if n == 0 {
2616 None
2617 } else {
2618 Some(Nid::from_raw(n))
2619 }
2620 }
2621
2622 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2624 #[must_use]
2625 pub fn cipher_nid(&self) -> Option<Nid> {
2626 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2627 if n == 0 {
2628 None
2629 } else {
2630 Some(Nid::from_raw(n))
2631 }
2632 }
2633}
2634
2635foreign_type_and_impl_send_sync! {
2636 type CType = ffi::SSL_SESSION;
2637 fn drop = ffi::SSL_SESSION_free;
2638
2639 pub struct SslSession;
2643}
2644
2645impl Clone for SslSession {
2646 fn clone(&self) -> SslSession {
2647 SslSessionRef::to_owned(self)
2648 }
2649}
2650
2651impl SslSession {
2652 from_der! {
2653 #[corresponds(d2i_SSL_SESSION)]
2655 from_der,
2656 SslSession,
2657 ffi::d2i_SSL_SESSION,
2658 ::libc::c_long
2659 }
2660}
2661
2662impl ToOwned for SslSessionRef {
2663 type Owned = SslSession;
2664
2665 fn to_owned(&self) -> SslSession {
2666 unsafe {
2667 SSL_SESSION_up_ref(self.as_ptr());
2668 SslSession(NonNull::new_unchecked(self.as_ptr()))
2669 }
2670 }
2671}
2672
2673impl SslSessionRef {
2674 #[corresponds(SSL_SESSION_get_id)]
2676 #[must_use]
2677 pub fn id(&self) -> &[u8] {
2678 unsafe {
2679 let mut len = 0;
2680 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2681 slice::from_raw_parts(p, len as usize)
2682 }
2683 }
2684
2685 #[corresponds(SSL_SESSION_get_master_key)]
2687 #[must_use]
2688 pub fn master_key_len(&self) -> usize {
2689 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2690 }
2691
2692 #[corresponds(SSL_SESSION_get_master_key)]
2696 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2697 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2698 }
2699
2700 #[corresponds(SSL_SESSION_get_time)]
2702 #[allow(clippy::useless_conversion)]
2703 #[must_use]
2704 pub fn time(&self) -> u64 {
2705 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2706 }
2707
2708 #[corresponds(SSL_SESSION_get_timeout)]
2712 #[allow(clippy::useless_conversion)]
2713 #[must_use]
2714 pub fn timeout(&self) -> u32 {
2715 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()) }
2716 }
2717
2718 #[corresponds(SSL_SESSION_get_protocol_version)]
2720 #[must_use]
2721 pub fn protocol_version(&self) -> SslVersion {
2722 unsafe {
2723 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2724 SslVersion(version)
2725 }
2726 }
2727
2728 to_der! {
2729 #[corresponds(i2d_SSL_SESSION)]
2731 to_der,
2732 ffi::i2d_SSL_SESSION
2733 }
2734}
2735
2736foreign_type_and_impl_send_sync! {
2737 type CType = ffi::SSL;
2738 fn drop = ffi::SSL_free;
2739
2740 pub struct Ssl;
2747}
2748
2749impl fmt::Debug for Ssl {
2750 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2751 fmt::Debug::fmt(&**self, fmt)
2752 }
2753}
2754
2755impl Ssl {
2756 #[corresponds(SSL_get_ex_new_index)]
2761 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2762 where
2763 T: 'static + Sync + Send,
2764 {
2765 unsafe {
2766 ffi::init();
2767 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2768 Ok(Index::from_raw(idx))
2769 }
2770 }
2771
2772 fn cached_ex_index<T>() -> Index<Ssl, T>
2774 where
2775 T: 'static + Sync + Send,
2776 {
2777 unsafe {
2778 let idx = *SSL_INDEXES
2779 .lock()
2780 .unwrap_or_else(|e| e.into_inner())
2781 .entry(TypeId::of::<T>())
2782 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2783 Index::from_raw(idx)
2784 }
2785 }
2786
2787 #[corresponds(SSL_new)]
2791 pub fn new(ctx: &SslContext) -> Result<Ssl, ErrorStack> {
2792 unsafe {
2793 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2794 let mut ssl = Ssl::from_ptr(ptr);
2795 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx.clone());
2796
2797 Ok(ssl)
2798 }
2799 }
2800
2801 #[corresponds(SSL_new)]
2806 pub fn new_from_ref(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2807 unsafe {
2808 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2809 let mut ssl = Ssl::from_ptr(ptr);
2810 SSL_CTX_up_ref(ctx.as_ptr());
2811 let ctx_owned = SslContext::from_ptr(ctx.as_ptr());
2812 ssl.set_ex_data(*SESSION_CTX_INDEX, ctx_owned);
2813
2814 Ok(ssl)
2815 }
2816 }
2817
2818 pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2830 where
2831 S: Read + Write,
2832 {
2833 SslStreamBuilder::new(self, stream).setup_connect()
2834 }
2835
2836 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2846 where
2847 S: Read + Write,
2848 {
2849 self.setup_connect(stream).handshake()
2850 }
2851
2852 pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
2864 where
2865 S: Read + Write,
2866 {
2867 #[cfg(feature = "rpk")]
2868 {
2869 let ctx = self.ssl_context();
2870
2871 if ctx.is_rpk() {
2872 unsafe {
2873 ffi::SSL_CTX_set_custom_verify(
2874 ctx.as_ptr(),
2875 SslVerifyMode::PEER.bits(),
2876 Some(rpk_verify_failure_callback),
2877 );
2878 }
2879 }
2880 }
2881
2882 SslStreamBuilder::new(self, stream).setup_accept()
2883 }
2884
2885 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2897 where
2898 S: Read + Write,
2899 {
2900 self.setup_accept(stream).handshake()
2901 }
2902}
2903
2904impl fmt::Debug for SslRef {
2905 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2906 let mut builder = fmt.debug_struct("Ssl");
2907
2908 builder.field("state", &self.state_string_long());
2909
2910 #[cfg(feature = "rpk")]
2911 if !self.ssl_context().is_rpk() {
2912 builder.field("verify_result", &self.verify_result());
2913 }
2914
2915 #[cfg(not(feature = "rpk"))]
2916 builder.field("verify_result", &self.verify_result());
2917
2918 builder.finish()
2919 }
2920}
2921
2922impl SslRef {
2923 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2924 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2925 }
2926
2927 #[corresponds(SSL_set_options)]
2934 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
2935 let bits = unsafe { ffi::SSL_set_options(self.as_ptr(), option.bits()) };
2936 SslOptions::from_bits_retain(bits)
2937 }
2938
2939 #[corresponds(SSL_clear_options)]
2941 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
2942 let bits = unsafe { ffi::SSL_clear_options(self.as_ptr(), option.bits()) };
2943 SslOptions::from_bits_retain(bits)
2944 }
2945
2946 #[corresponds(SSL_set1_curves_list)]
2947 pub fn set_curves_list(&mut self, curves: &str) -> Result<(), ErrorStack> {
2948 let curves = CString::new(curves).map_err(ErrorStack::internal_error)?;
2949 unsafe {
2950 cvt_0i(ffi::SSL_set1_curves_list(
2951 self.as_ptr(),
2952 curves.as_ptr() as *const _,
2953 ))
2954 .map(|_| ())
2955 }
2956 }
2957
2958 #[corresponds(SSL_set1_groups)]
2961 #[deprecated(note = "SslCurveNid will be removed in the next release. Use set_curves_list")]
2962 #[allow(deprecated)]
2963 pub fn set_group_nids(&mut self, group_nids: &[SslCurveNid]) -> Result<(), ErrorStack> {
2964 unsafe {
2965 cvt_0i(ffi::SSL_set1_curves(
2966 self.as_ptr(),
2967 group_nids.as_ptr() as *const _,
2968 group_nids.len(),
2969 ))
2970 .map(|_| ())
2971 }
2972 }
2973
2974 #[cfg(feature = "kx-safe-default")]
2975 fn client_set_default_curves_list(&mut self) {
2976 let curves = if cfg!(feature = "kx-client-pq-preferred") {
2977 if cfg!(feature = "kx-client-nist-required") {
2978 "P256Kyber768Draft00:P-256:P-384:P-521"
2979 } else {
2980 "X25519MLKEM768:X25519Kyber768Draft00:X25519:P256Kyber768Draft00:P-256:P-384:P-521"
2981 }
2982 } else if cfg!(feature = "kx-client-pq-supported") {
2983 if cfg!(feature = "kx-client-nist-required") {
2984 "P-256:P-384:P-521:P256Kyber768Draft00"
2985 } else {
2986 "X25519:P-256:P-384:P-521:X25519MLKEM768:X25519Kyber768Draft00:P256Kyber768Draft00"
2987 }
2988 } else {
2989 if cfg!(feature = "kx-client-nist-required") {
2990 "P-256:P-384:P-521"
2991 } else {
2992 "X25519:P-256:P-384:P-521"
2993 }
2994 };
2995
2996 self.set_curves_list(curves)
2997 .expect("invalid default client curves list");
2998 }
2999
3000 #[cfg(feature = "kx-safe-default")]
3001 fn server_set_default_curves_list(&mut self) {
3002 self.set_curves_list(
3003 "X25519MLKEM768:X25519Kyber768Draft00:P256Kyber768Draft00:X25519:P-256:P-384",
3004 )
3005 .expect("invalid default server curves list");
3006 }
3007
3008 #[corresponds(SSL_get_curve_id)]
3010 #[must_use]
3011 #[deprecated(note = "SslCurve will be removed in the next release")]
3012 #[allow(deprecated)]
3013 pub fn curve(&self) -> Option<SslCurve> {
3014 let curve_id = unsafe { ffi::SSL_get_curve_id(self.as_ptr()) };
3015 if curve_id == 0 {
3016 return None;
3017 }
3018 Some(SslCurve(curve_id.into()))
3019 }
3020
3021 #[corresponds(SSL_get_error)]
3023 #[must_use]
3024 pub fn error_code(&self, ret: c_int) -> ErrorCode {
3025 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
3026 }
3027
3028 #[corresponds(SSL_set_verify)]
3032 pub fn set_verify(&mut self, mode: SslVerifyMode) {
3033 #[cfg(feature = "rpk")]
3034 assert!(
3035 !self.ssl_context().is_rpk(),
3036 "This API is not supported for RPK"
3037 );
3038
3039 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
3040 }
3041
3042 #[corresponds(SSL_set_verify_depth)]
3046 pub fn set_verify_depth(&mut self, depth: u32) {
3047 #[cfg(feature = "rpk")]
3048 assert!(
3049 !self.ssl_context().is_rpk(),
3050 "This API is not supported for RPK"
3051 );
3052
3053 unsafe {
3054 ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
3055 }
3056 }
3057
3058 #[corresponds(SSL_get_verify_mode)]
3060 #[must_use]
3061 pub fn verify_mode(&self) -> SslVerifyMode {
3062 #[cfg(feature = "rpk")]
3063 assert!(
3064 !self.ssl_context().is_rpk(),
3065 "This API is not supported for RPK"
3066 );
3067
3068 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
3069 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
3070 }
3071
3072 #[corresponds(SSL_set_verify)]
3089 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3090 where
3091 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
3092 {
3093 #[cfg(feature = "rpk")]
3094 assert!(
3095 !self.ssl_context().is_rpk(),
3096 "This API is not supported for RPK"
3097 );
3098
3099 unsafe {
3100 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3102 ffi::SSL_set_verify(
3103 self.as_ptr(),
3104 mode.bits() as c_int,
3105 Some(ssl_raw_verify::<F>),
3106 );
3107 }
3108 }
3109
3110 #[corresponds(SSL_set0_verify_cert_store)]
3112 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3113 #[cfg(feature = "rpk")]
3114 assert!(
3115 !self.ssl_context().is_rpk(),
3116 "This API is not supported for RPK"
3117 );
3118
3119 unsafe {
3120 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int)?;
3121 Ok(())
3122 }
3123 }
3124
3125 #[corresponds(SSL_set_custom_verify)]
3131 pub fn set_custom_verify_callback<F>(&mut self, mode: SslVerifyMode, callback: F)
3132 where
3133 F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
3134 {
3135 #[cfg(feature = "rpk")]
3136 assert!(
3137 !self.ssl_context().is_rpk(),
3138 "This API is not supported for RPK"
3139 );
3140
3141 unsafe {
3142 self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3144 ffi::SSL_set_custom_verify(
3145 self.as_ptr(),
3146 mode.bits() as c_int,
3147 Some(ssl_raw_custom_verify::<F>),
3148 );
3149 }
3150 }
3151
3152 #[corresponds(SSL_set_tmp_dh)]
3156 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3157 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3158 }
3159
3160 #[corresponds(SSL_set_tmp_ecdh)]
3164 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3165 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3166 }
3167
3168 #[corresponds(SSL_set_permute_extensions)]
3170 #[cfg(not(feature = "fips-compat"))]
3175 pub fn set_permute_extensions(&mut self, enabled: bool) {
3176 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as _) }
3177 }
3178
3179 #[corresponds(SSL_set_alpn_protos)]
3183 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3184 unsafe {
3185 let r = ffi::SSL_set_alpn_protos(
3186 self.as_ptr(),
3187 protocols.as_ptr(),
3188 #[allow(clippy::useless_conversion)]
3189 protocols
3190 .len()
3191 .try_into()
3192 .map_err(ErrorStack::internal_error)?,
3193 );
3194 if r == 0 {
3196 Ok(())
3197 } else {
3198 Err(ErrorStack::get())
3199 }
3200 }
3201 }
3202
3203 #[corresponds(SSL_get_ciphers)]
3205 #[must_use]
3206 pub fn ciphers(&self) -> &StackRef<SslCipher> {
3207 unsafe {
3208 let cipher_list = ffi::SSL_get_ciphers(self.as_ptr());
3209 StackRef::from_ptr(cipher_list)
3210 }
3211 }
3212
3213 #[corresponds(SSL_get_current_cipher)]
3215 #[must_use]
3216 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3217 unsafe {
3218 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3219
3220 if ptr.is_null() {
3221 None
3222 } else {
3223 Some(SslCipherRef::from_ptr(ptr as *mut _))
3224 }
3225 }
3226 }
3227
3228 #[corresponds(SSL_state_string)]
3232 #[must_use]
3233 pub fn state_string(&self) -> &'static str {
3234 let state = unsafe {
3235 let ptr = ffi::SSL_state_string(self.as_ptr());
3236 CStr::from_ptr(ptr as *const _)
3237 };
3238
3239 state.to_str().unwrap_or_default()
3240 }
3241
3242 #[corresponds(SSL_state_string_long)]
3246 #[must_use]
3247 pub fn state_string_long(&self) -> &'static str {
3248 let state = unsafe {
3249 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3250 CStr::from_ptr(ptr as *const _)
3251 };
3252
3253 state.to_str().unwrap_or_default()
3254 }
3255
3256 #[corresponds(SSL_set_tlsext_host_name)]
3260 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3261 let cstr = CString::new(hostname).map_err(ErrorStack::internal_error)?;
3262 unsafe {
3263 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3264 .map(|_| ())
3265 }
3266 }
3267
3268 #[corresponds(SSL_get_peer_certificate)]
3270 #[must_use]
3271 pub fn peer_certificate(&self) -> Option<X509> {
3272 #[cfg(feature = "rpk")]
3273 assert!(
3274 !self.ssl_context().is_rpk(),
3275 "This API is not supported for RPK"
3276 );
3277
3278 unsafe {
3279 let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
3280 if ptr.is_null() {
3281 None
3282 } else {
3283 Some(X509::from_ptr(ptr))
3284 }
3285 }
3286 }
3287
3288 #[corresponds(SSL_get_peer_certificate)]
3293 #[must_use]
3294 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3295 #[cfg(feature = "rpk")]
3296 assert!(
3297 !self.ssl_context().is_rpk(),
3298 "This API is not supported for RPK"
3299 );
3300
3301 unsafe {
3302 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3303 if ptr.is_null() {
3304 None
3305 } else {
3306 Some(StackRef::from_ptr(ptr))
3307 }
3308 }
3309 }
3310
3311 #[corresponds(SSL_get_certificate)]
3313 #[must_use]
3314 pub fn certificate(&self) -> Option<&X509Ref> {
3315 #[cfg(feature = "rpk")]
3316 assert!(
3317 !self.ssl_context().is_rpk(),
3318 "This API is not supported for RPK"
3319 );
3320
3321 unsafe {
3322 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3323 if ptr.is_null() {
3324 None
3325 } else {
3326 Some(X509Ref::from_ptr(ptr))
3327 }
3328 }
3329 }
3330
3331 #[corresponds(SSL_get_privatekey)]
3333 #[must_use]
3334 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3335 unsafe {
3336 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3337 if ptr.is_null() {
3338 None
3339 } else {
3340 Some(PKeyRef::from_ptr(ptr))
3341 }
3342 }
3343 }
3344
3345 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
3346 #[must_use]
3347 pub fn version(&self) -> &str {
3348 self.version_str()
3349 }
3350
3351 #[corresponds(SSL_version)]
3353 pub fn version2(&self) -> Option<SslVersion> {
3354 unsafe {
3355 let r = ffi::SSL_version(self.as_ptr());
3356 if r == 0 {
3357 None
3358 } else {
3359 r.try_into().ok().map(SslVersion)
3360 }
3361 }
3362 }
3363
3364 #[corresponds(SSL_get_version)]
3368 #[must_use]
3369 pub fn version_str(&self) -> &'static str {
3370 let version = unsafe {
3371 let ptr = ffi::SSL_get_version(self.as_ptr());
3372 CStr::from_ptr(ptr as *const _)
3373 };
3374
3375 version.to_str().unwrap()
3376 }
3377
3378 #[corresponds(SSL_set_min_proto_version)]
3383 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3384 unsafe {
3385 cvt(ffi::SSL_set_min_proto_version(
3386 self.as_ptr(),
3387 version.map_or(0, |v| v.0 as _),
3388 ))
3389 .map(|_| ())
3390 }
3391 }
3392
3393 #[corresponds(SSL_set_max_proto_version)]
3397 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3398 unsafe {
3399 cvt(ffi::SSL_set_max_proto_version(
3400 self.as_ptr(),
3401 version.map_or(0, |v| v.0 as _),
3402 ))
3403 .map(|_| ())
3404 }
3405 }
3406
3407 #[corresponds(SSL_get_min_proto_version)]
3409 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
3410 unsafe {
3411 let r = ffi::SSL_get_min_proto_version(self.as_ptr());
3412 if r == 0 {
3413 None
3414 } else {
3415 Some(SslVersion(r))
3416 }
3417 }
3418 }
3419
3420 #[corresponds(SSL_get_max_proto_version)]
3422 #[must_use]
3423 pub fn max_proto_version(&self) -> Option<SslVersion> {
3424 let r = unsafe { ffi::SSL_get_max_proto_version(self.as_ptr()) };
3425 if r == 0 {
3426 None
3427 } else {
3428 Some(SslVersion(r))
3429 }
3430 }
3431
3432 #[corresponds(SSL_get0_alpn_selected)]
3437 #[must_use]
3438 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3439 unsafe {
3440 let mut data: *const c_uchar = ptr::null();
3441 let mut len: c_uint = 0;
3442 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3445
3446 if data.is_null() {
3447 None
3448 } else {
3449 Some(slice::from_raw_parts(data, len as usize))
3450 }
3451 }
3452 }
3453
3454 #[corresponds(SSL_set_tlsext_use_srtp)]
3456 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3457 unsafe {
3458 let cstr = CString::new(protocols).map_err(ErrorStack::internal_error)?;
3459
3460 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3461 if r == 0 {
3463 Ok(())
3464 } else {
3465 Err(ErrorStack::get())
3466 }
3467 }
3468 }
3469
3470 #[corresponds(SSL_get_strp_profiles)]
3474 #[must_use]
3475 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3476 unsafe {
3477 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3478
3479 if chain.is_null() {
3480 None
3481 } else {
3482 Some(StackRef::from_ptr(chain as *mut _))
3483 }
3484 }
3485 }
3486
3487 #[corresponds(SSL_get_selected_srtp_profile)]
3491 #[must_use]
3492 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3493 unsafe {
3494 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3495
3496 if profile.is_null() {
3497 None
3498 } else {
3499 Some(SrtpProtectionProfileRef::from_ptr(profile as *mut _))
3500 }
3501 }
3502 }
3503
3504 #[corresponds(SSL_pending)]
3509 #[must_use]
3510 pub fn pending(&self) -> usize {
3511 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3512 }
3513
3514 #[corresponds(SSL_get_servername)]
3527 #[must_use]
3528 pub fn servername(&self, type_: NameType) -> Option<&str> {
3529 self.servername_raw(type_)
3530 .and_then(|b| str::from_utf8(b).ok())
3531 }
3532
3533 #[corresponds(SSL_get_servername)]
3541 #[must_use]
3542 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3543 unsafe {
3544 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3545 if name.is_null() {
3546 None
3547 } else {
3548 Some(CStr::from_ptr(name as *const _).to_bytes())
3549 }
3550 }
3551 }
3552
3553 #[corresponds(SSL_set_SSL_CTX)]
3557 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3558 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3559 }
3560
3561 #[corresponds(SSL_get_SSL_CTX)]
3563 #[must_use]
3564 pub fn ssl_context(&self) -> &SslContextRef {
3565 unsafe {
3566 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3567 SslContextRef::from_ptr(ssl_ctx)
3568 }
3569 }
3570
3571 #[corresponds(SSL_get0_param)]
3573 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
3574 #[cfg(feature = "rpk")]
3575 assert!(
3576 !self.ssl_context().is_rpk(),
3577 "This API is not supported for RPK"
3578 );
3579
3580 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3581 }
3582
3583 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3585 self.verify_param_mut()
3586 }
3587
3588 #[corresponds(SSL_get_verify_result)]
3590 pub fn verify_result(&self) -> X509VerifyResult {
3591 #[cfg(feature = "rpk")]
3592 assert!(
3593 !self.ssl_context().is_rpk(),
3594 "This API is not supported for RPK"
3595 );
3596
3597 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3598 }
3599
3600 #[corresponds(SSL_get_session)]
3602 #[must_use]
3603 pub fn session(&self) -> Option<&SslSessionRef> {
3604 unsafe {
3605 let p = ffi::SSL_get_session(self.as_ptr());
3606 if p.is_null() {
3607 None
3608 } else {
3609 Some(SslSessionRef::from_ptr(p))
3610 }
3611 }
3612 }
3613
3614 #[corresponds(SSL_get_client_random)]
3619 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3620 unsafe {
3621 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3622 }
3623 }
3624
3625 #[corresponds(SSL_get_server_random)]
3630 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3631 unsafe {
3632 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3633 }
3634 }
3635
3636 #[corresponds(SSL_export_keying_material)]
3638 pub fn export_keying_material(
3639 &self,
3640 out: &mut [u8],
3641 label: &str,
3642 context: Option<&[u8]>,
3643 ) -> Result<(), ErrorStack> {
3644 unsafe {
3645 let (context, contextlen, use_context) = match context {
3646 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3647 None => (ptr::null(), 0, 0),
3648 };
3649 cvt(ffi::SSL_export_keying_material(
3650 self.as_ptr(),
3651 out.as_mut_ptr() as *mut c_uchar,
3652 out.len(),
3653 label.as_ptr() as *const c_char,
3654 label.len(),
3655 context,
3656 contextlen,
3657 use_context,
3658 ))
3659 .map(|_| ())
3660 }
3661 }
3662
3663 #[corresponds(SSL_set_session)]
3674 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3675 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3676 }
3677
3678 #[corresponds(SSL_session_reused)]
3680 #[must_use]
3681 pub fn session_reused(&self) -> bool {
3682 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3683 }
3684
3685 #[corresponds(SSL_set_tlsext_status_type)]
3687 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3688 unsafe {
3689 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3690 }
3691 }
3692
3693 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3695 #[must_use]
3696 pub fn ocsp_status(&self) -> Option<&[u8]> {
3697 unsafe {
3698 let mut p = ptr::null();
3699 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3700
3701 if len == 0 {
3702 None
3703 } else {
3704 Some(slice::from_raw_parts(p, len))
3705 }
3706 }
3707 }
3708
3709 #[corresponds(SSL_set_tlsext_status_ocsp_resp)]
3711 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3712 unsafe {
3713 assert!(response.len() <= c_int::MAX as usize);
3714 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3715 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3716 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3717 self.as_ptr(),
3718 p as *mut c_uchar,
3719 response.len(),
3720 ) as c_int)
3721 .map(|_| ())
3722 }
3723 }
3724
3725 #[corresponds(SSL_is_server)]
3727 #[must_use]
3728 pub fn is_server(&self) -> bool {
3729 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3730 }
3731
3732 #[corresponds(SSL_set_ex_data)]
3740 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3741 if let Some(old) = self.ex_data_mut(index) {
3742 *old = data;
3743
3744 return;
3745 }
3746
3747 unsafe {
3748 let data = Box::new(data);
3749 ffi::SSL_set_ex_data(
3750 self.as_ptr(),
3751 index.as_raw(),
3752 Box::into_raw(data) as *mut c_void,
3753 );
3754 }
3755 }
3756
3757 #[corresponds(SSL_set_ex_data)]
3764 pub fn replace_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) -> Option<T> {
3765 if let Some(old) = self.ex_data_mut(index) {
3766 return Some(mem::replace(old, data));
3767 }
3768
3769 self.set_ex_data(index, data);
3770
3771 None
3772 }
3773
3774 #[corresponds(SSL_get_ex_data)]
3776 #[must_use]
3777 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3778 unsafe {
3779 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3780 if data.is_null() {
3781 None
3782 } else {
3783 Some(&*(data as *const T))
3784 }
3785 }
3786 }
3787
3788 #[corresponds(SSL_get_ex_data)]
3790 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3791 unsafe {
3792 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3793 if data.is_null() {
3794 None
3795 } else {
3796 Some(&mut *(data as *mut T))
3797 }
3798 }
3799 }
3800
3801 #[corresponds(SSL_get_finished)]
3806 pub fn finished(&self, buf: &mut [u8]) -> usize {
3807 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3808 }
3809
3810 #[corresponds(SSL_get_peer_finished)]
3816 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3817 unsafe {
3818 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3819 }
3820 }
3821
3822 #[corresponds(SSL_is_init_finished)]
3824 #[must_use]
3825 pub fn is_init_finished(&self) -> bool {
3826 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3827 }
3828
3829 #[corresponds(SSL_set_mtu)]
3831 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3832 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_uint) as c_int).map(|_| ()) }
3833 }
3834
3835 #[corresponds(SSL_use_certificate)]
3837 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3838 unsafe {
3839 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3840 }
3841
3842 Ok(())
3843 }
3844
3845 #[corresponds(SSL_set_client_CA_list)]
3850 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3851 #[cfg(feature = "rpk")]
3852 assert!(
3853 !self.ssl_context().is_rpk(),
3854 "This API is not supported for RPK"
3855 );
3856
3857 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3858 mem::forget(list);
3859 }
3860
3861 #[corresponds(SSL_use_PrivateKey)]
3863 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
3864 where
3865 T: HasPrivate,
3866 {
3867 unsafe { cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
3868 }
3869
3870 #[corresponds(SSL_set_mode)]
3873 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
3874 let bits = unsafe { ffi::SSL_set_mode(self.as_ptr(), mode.bits()) };
3875 SslMode::from_bits_retain(bits)
3876 }
3877
3878 #[corresponds(SSL_clear_mode)]
3881 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
3882 let bits = unsafe { ffi::SSL_clear_mode(self.as_ptr(), mode.bits()) };
3883 SslMode::from_bits_retain(bits)
3884 }
3885
3886 #[corresponds(SSL_add1_chain_cert)]
3888 pub fn add_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3889 unsafe { cvt(ffi::SSL_add1_chain_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
3890 }
3891
3892 #[cfg(not(feature = "fips"))]
3900 #[corresponds(SSL_set1_ech_config_list)]
3901 pub fn set_ech_config_list(&mut self, ech_config_list: &[u8]) -> Result<(), ErrorStack> {
3902 unsafe {
3903 cvt_0i(ffi::SSL_set1_ech_config_list(
3904 self.as_ptr(),
3905 ech_config_list.as_ptr(),
3906 ech_config_list.len(),
3907 ))
3908 .map(|_| ())
3909 }
3910 }
3911
3912 #[cfg(not(feature = "fips"))]
3919 #[corresponds(SSL_get0_ech_retry_configs)]
3920 #[must_use]
3921 pub fn get_ech_retry_configs(&self) -> Option<&[u8]> {
3922 unsafe {
3923 let mut data = ptr::null();
3924 let mut len: usize = 0;
3925 ffi::SSL_get0_ech_retry_configs(self.as_ptr(), &mut data, &mut len);
3926
3927 if data.is_null() {
3928 None
3929 } else {
3930 Some(slice::from_raw_parts(data, len))
3931 }
3932 }
3933 }
3934
3935 #[cfg(not(feature = "fips"))]
3942 #[corresponds(SSL_get0_ech_name_override)]
3943 #[must_use]
3944 pub fn get_ech_name_override(&self) -> Option<&[u8]> {
3945 unsafe {
3946 let mut data: *const c_char = ptr::null();
3947 let mut len: usize = 0;
3948 ffi::SSL_get0_ech_name_override(self.as_ptr(), &mut data, &mut len);
3949
3950 if data.is_null() {
3951 None
3952 } else {
3953 Some(slice::from_raw_parts(data as *const u8, len))
3954 }
3955 }
3956 }
3957
3958 #[cfg(not(feature = "fips"))]
3960 #[corresponds(SSL_ech_accepted)]
3961 #[must_use]
3962 pub fn ech_accepted(&self) -> bool {
3963 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
3964 }
3965
3966 #[cfg(not(feature = "fips"))]
3968 #[corresponds(SSL_set_enable_ech_grease)]
3969 pub fn set_enable_ech_grease(&self, enable: bool) {
3970 let enable = if enable { 1 } else { 0 };
3971
3972 unsafe {
3973 ffi::SSL_set_enable_ech_grease(self.as_ptr(), enable);
3974 }
3975 }
3976
3977 #[cfg(not(feature = "fips-compat"))]
3979 #[corresponds(SSL_set_compliance_policy)]
3980 pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
3981 unsafe { cvt_0i(ffi::SSL_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
3982 }
3983}
3984
3985#[derive(Debug)]
3987pub struct MidHandshakeSslStream<S> {
3988 stream: SslStream<S>,
3989 error: Error,
3990}
3991
3992impl<S> MidHandshakeSslStream<S> {
3993 #[must_use]
3995 pub fn get_ref(&self) -> &S {
3996 self.stream.get_ref()
3997 }
3998
3999 pub fn get_mut(&mut self) -> &mut S {
4001 self.stream.get_mut()
4002 }
4003
4004 #[must_use]
4006 pub fn ssl(&self) -> &SslRef {
4007 self.stream.ssl()
4008 }
4009
4010 pub fn ssl_mut(&mut self) -> &mut SslRef {
4012 self.stream.ssl_mut()
4013 }
4014
4015 #[must_use]
4017 pub fn error(&self) -> &Error {
4018 &self.error
4019 }
4020
4021 #[must_use]
4023 pub fn into_error(self) -> Error {
4024 self.error
4025 }
4026
4027 #[must_use]
4029 pub fn into_source_stream(self) -> S {
4030 self.stream.into_inner()
4031 }
4032
4033 #[must_use]
4035 pub fn into_parts(self) -> (Error, S) {
4036 (self.error, self.stream.into_inner())
4037 }
4038
4039 #[corresponds(SSL_do_handshake)]
4041 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4042 let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) };
4043 if ret > 0 {
4044 Ok(self.stream)
4045 } else {
4046 self.error = self.stream.make_error(ret);
4047 Err(if self.error.would_block() {
4048 HandshakeError::WouldBlock(self)
4049 } else {
4050 HandshakeError::Failure(self)
4051 })
4052 }
4053 }
4054}
4055
4056pub struct SslStream<S> {
4058 ssl: ManuallyDrop<Ssl>,
4059 method: ManuallyDrop<BioMethod>,
4060 _p: PhantomData<S>,
4061}
4062
4063impl<S> Drop for SslStream<S> {
4064 fn drop(&mut self) {
4065 unsafe {
4067 ManuallyDrop::drop(&mut self.ssl);
4068 ManuallyDrop::drop(&mut self.method);
4069 }
4070 }
4071}
4072
4073impl<S> fmt::Debug for SslStream<S>
4074where
4075 S: fmt::Debug,
4076{
4077 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
4078 fmt.debug_struct("SslStream")
4079 .field("stream", &self.get_ref())
4080 .field("ssl", &self.ssl())
4081 .finish()
4082 }
4083}
4084
4085impl<S: Read + Write> SslStream<S> {
4086 fn new_base(ssl: Ssl, stream: S) -> Self {
4087 unsafe {
4088 let (bio, method) = bio::new(stream).unwrap();
4089 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4090
4091 SslStream {
4092 ssl: ManuallyDrop::new(ssl),
4093 method: ManuallyDrop::new(method),
4094 _p: PhantomData,
4095 }
4096 }
4097 }
4098
4099 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4105 Ok(Self::new_base(ssl, stream))
4106 }
4107
4108 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
4116 let ssl = Ssl::from_ptr(ssl);
4117 Self::new_base(ssl, stream)
4118 }
4119
4120 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4127 loop {
4128 match self.ssl_read_uninit(buf) {
4129 Ok(n) => return Ok(n),
4130 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4131 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4132 return Ok(0);
4133 }
4134 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4135 Err(e) => {
4136 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4137 }
4138 }
4139 }
4140 }
4141
4142 #[corresponds(SSL_read)]
4147 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4148 unsafe {
4150 self.ssl_read_uninit(slice::from_raw_parts_mut(
4151 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4152 buf.len(),
4153 ))
4154 }
4155 }
4156
4157 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4164 if buf.is_empty() {
4165 return Ok(0);
4166 }
4167
4168 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4169 let ret = unsafe { ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len) };
4170 if ret > 0 {
4171 Ok(ret as usize)
4172 } else {
4173 Err(self.make_error(ret))
4174 }
4175 }
4176
4177 #[corresponds(SSL_write)]
4182 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4183 if buf.is_empty() {
4184 return Ok(0);
4185 }
4186
4187 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4188 let ret = unsafe { ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len) };
4189 if ret > 0 {
4190 Ok(ret as usize)
4191 } else {
4192 Err(self.make_error(ret))
4193 }
4194 }
4195
4196 #[corresponds(SSL_shutdown)]
4206 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4207 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4208 0 => Ok(ShutdownResult::Sent),
4209 1 => Ok(ShutdownResult::Received),
4210 n => Err(self.make_error(n)),
4211 }
4212 }
4213
4214 #[corresponds(SSL_get_shutdown)]
4216 pub fn get_shutdown(&mut self) -> ShutdownState {
4217 unsafe {
4218 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4219 ShutdownState::from_bits_retain(bits)
4220 }
4221 }
4222
4223 #[corresponds(SSL_set_shutdown)]
4228 pub fn set_shutdown(&mut self, state: ShutdownState) {
4229 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4230 }
4231
4232 #[corresponds(SSL_connect)]
4234 pub fn connect(&mut self) -> Result<(), Error> {
4235 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4236 if ret > 0 {
4237 Ok(())
4238 } else {
4239 Err(self.make_error(ret))
4240 }
4241 }
4242
4243 #[corresponds(SSL_accept)]
4245 pub fn accept(&mut self) -> Result<(), Error> {
4246 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4247 if ret > 0 {
4248 Ok(())
4249 } else {
4250 Err(self.make_error(ret))
4251 }
4252 }
4253
4254 #[corresponds(SSL_do_handshake)]
4256 pub fn do_handshake(&mut self) -> Result<(), Error> {
4257 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4258 if ret > 0 {
4259 Ok(())
4260 } else {
4261 Err(self.make_error(ret))
4262 }
4263 }
4264}
4265
4266impl<S> SslStream<S> {
4267 fn make_error(&mut self, ret: c_int) -> Error {
4268 self.check_panic();
4269
4270 let code = self.ssl.error_code(ret);
4271
4272 let cause = match code {
4273 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4274 ErrorCode::SYSCALL => {
4275 let errs = ErrorStack::get();
4276 if errs.errors().is_empty() {
4277 self.get_bio_error().map(InnerError::Io)
4278 } else {
4279 Some(InnerError::Ssl(errs))
4280 }
4281 }
4282 ErrorCode::ZERO_RETURN => None,
4283 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4284 self.get_bio_error().map(InnerError::Io)
4285 }
4286 _ => None,
4287 };
4288
4289 Error { code, cause }
4290 }
4291
4292 fn check_panic(&mut self) {
4293 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4294 resume_unwind(err)
4295 }
4296 }
4297
4298 fn get_bio_error(&mut self) -> Option<io::Error> {
4299 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4300 }
4301
4302 #[must_use]
4304 pub fn into_inner(self) -> S {
4305 unsafe { bio::take_stream::<S>(self.ssl.get_raw_rbio()) }
4306 }
4307
4308 #[must_use]
4310 pub fn get_ref(&self) -> &S {
4311 unsafe {
4312 let bio = self.ssl.get_raw_rbio();
4313 bio::get_ref(bio)
4314 }
4315 }
4316
4317 pub fn get_mut(&mut self) -> &mut S {
4324 unsafe {
4325 let bio = self.ssl.get_raw_rbio();
4326 bio::get_mut(bio)
4327 }
4328 }
4329
4330 #[must_use]
4332 pub fn ssl(&self) -> &SslRef {
4333 &self.ssl
4334 }
4335
4336 pub fn ssl_mut(&mut self) -> &mut SslRef {
4338 &mut self.ssl
4339 }
4340}
4341
4342impl<S: Read + Write> Read for SslStream<S> {
4343 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4344 unsafe {
4346 self.read_uninit(slice::from_raw_parts_mut(
4347 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4348 buf.len(),
4349 ))
4350 }
4351 }
4352}
4353
4354impl<S: Read + Write> Write for SslStream<S> {
4355 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4356 loop {
4357 match self.ssl_write(buf) {
4358 Ok(n) => return Ok(n),
4359 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4360 Err(e) => {
4361 return Err(e.into_io_error().unwrap_or_else(io::Error::other));
4362 }
4363 }
4364 }
4365 }
4366
4367 fn flush(&mut self) -> io::Result<()> {
4368 self.get_mut().flush()
4369 }
4370}
4371
4372pub struct SslStreamBuilder<S> {
4374 inner: SslStream<S>,
4375}
4376
4377impl<S> SslStreamBuilder<S>
4378where
4379 S: Read + Write,
4380{
4381 pub fn new(ssl: Ssl, stream: S) -> Self {
4383 Self {
4384 inner: SslStream::new_base(ssl, stream),
4385 }
4386 }
4387
4388 #[corresponds(SSL_set_connect_state)]
4390 pub fn set_connect_state(&mut self) {
4391 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4392 }
4393
4394 #[corresponds(SSL_set_accept_state)]
4396 pub fn set_accept_state(&mut self) {
4397 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4398 }
4399
4400 #[must_use]
4406 pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
4407 self.set_connect_state();
4408
4409 #[cfg(feature = "kx-safe-default")]
4410 self.inner.ssl.client_set_default_curves_list();
4411
4412 MidHandshakeSslStream {
4413 stream: self.inner,
4414 error: Error {
4415 code: ErrorCode::WANT_WRITE,
4416 cause: Some(InnerError::Io(io::Error::new(
4417 io::ErrorKind::WouldBlock,
4418 "connect handshake has not started yet",
4419 ))),
4420 },
4421 }
4422 }
4423
4424 pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
4429 self.setup_connect().handshake()
4430 }
4431
4432 #[must_use]
4438 pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
4439 self.set_accept_state();
4440
4441 #[cfg(feature = "kx-safe-default")]
4442 self.inner.ssl.server_set_default_curves_list();
4443
4444 MidHandshakeSslStream {
4445 stream: self.inner,
4446 error: Error {
4447 code: ErrorCode::WANT_READ,
4448 cause: Some(InnerError::Io(io::Error::new(
4449 io::ErrorKind::WouldBlock,
4450 "accept handshake has not started yet",
4451 ))),
4452 },
4453 }
4454 }
4455
4456 pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
4461 self.setup_accept().handshake()
4462 }
4463
4464 #[corresponds(SSL_do_handshake)]
4468 pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
4469 let mut stream = self.inner;
4470 let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
4471 if ret > 0 {
4472 Ok(stream)
4473 } else {
4474 let error = stream.make_error(ret);
4475 Err(if error.would_block() {
4476 HandshakeError::WouldBlock(MidHandshakeSslStream { stream, error })
4477 } else {
4478 HandshakeError::Failure(MidHandshakeSslStream { stream, error })
4479 })
4480 }
4481 }
4482}
4483
4484impl<S> SslStreamBuilder<S> {
4485 #[must_use]
4487 pub fn get_ref(&self) -> &S {
4488 unsafe {
4489 let bio = self.inner.ssl.get_raw_rbio();
4490 bio::get_ref(bio)
4491 }
4492 }
4493
4494 pub fn get_mut(&mut self) -> &mut S {
4501 unsafe {
4502 let bio = self.inner.ssl.get_raw_rbio();
4503 bio::get_mut(bio)
4504 }
4505 }
4506
4507 #[must_use]
4509 pub fn ssl(&self) -> &SslRef {
4510 &self.inner.ssl
4511 }
4512
4513 pub fn ssl_mut(&mut self) -> &mut SslRef {
4515 &mut self.inner.ssl
4516 }
4517
4518 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4526 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4527 unsafe {
4528 let bio = self.inner.ssl.get_raw_rbio();
4529 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4530 }
4531 }
4532}
4533
4534#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4536pub enum ShutdownResult {
4537 Sent,
4539
4540 Received,
4542}
4543
4544bitflags! {
4545 #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
4547 pub struct ShutdownState: c_int {
4548 const SENT = ffi::SSL_SENT_SHUTDOWN;
4550 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4552 }
4553}
4554
4555pub trait PrivateKeyMethod: Send + Sync + 'static {
4563 fn sign(
4574 &self,
4575 ssl: &mut SslRef,
4576 input: &[u8],
4577 signature_algorithm: SslSignatureAlgorithm,
4578 output: &mut [u8],
4579 ) -> Result<usize, PrivateKeyMethodError>;
4580
4581 fn decrypt(
4596 &self,
4597 ssl: &mut SslRef,
4598 input: &[u8],
4599 output: &mut [u8],
4600 ) -> Result<usize, PrivateKeyMethodError>;
4601
4602 fn complete(&self, ssl: &mut SslRef, output: &mut [u8])
4611 -> Result<usize, PrivateKeyMethodError>;
4612}
4613
4614#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4616pub struct PrivateKeyMethodError(ffi::ssl_private_key_result_t);
4617
4618impl PrivateKeyMethodError {
4619 pub const FAILURE: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_failure);
4621
4622 pub const RETRY: Self = Self(ffi::ssl_private_key_result_t::ssl_private_key_retry);
4624}
4625
4626pub trait CertificateCompressor: Send + Sync + 'static {
4628 const ALGORITHM: CertificateCompressionAlgorithm;
4630
4631 const CAN_COMPRESS: bool;
4633
4634 const CAN_DECOMPRESS: bool;
4636
4637 #[allow(unused_variables)]
4639 fn compress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4640 where
4641 W: std::io::Write,
4642 {
4643 Err(std::io::Error::other("not implemented"))
4644 }
4645
4646 #[allow(unused_variables)]
4648 fn decompress<W>(&self, input: &[u8], output: &mut W) -> std::io::Result<()>
4649 where
4650 W: std::io::Write,
4651 {
4652 Err(std::io::Error::other("not implemented"))
4653 }
4654}
4655
4656use crate::ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4657
4658use crate::ffi::{DTLS_method, TLS_client_method, TLS_method, TLS_server_method};
4659
4660use std::sync::Once;
4661
4662unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4663 static ONCE: Once = Once::new();
4665 ONCE.call_once(|| {
4666 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4667 });
4668
4669 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4670}
4671
4672unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4673 static ONCE: Once = Once::new();
4675 ONCE.call_once(|| {
4676 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4677 });
4678
4679 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4680}