variant_ssl/ssl/
mod.rs

1//! SSL/TLS support.
2//!
3//! `SslConnector` and `SslAcceptor` should be used in most cases - they handle
4//! configuration of the OpenSSL primitives for you.
5//!
6//! # Examples
7//!
8//! To connect as a client to a remote server:
9//!
10//! ```no_run
11//! use openssl::ssl::{SslMethod, SslConnector};
12//! use std::io::{Read, Write};
13//! use std::net::TcpStream;
14//!
15//! let connector = SslConnector::builder(SslMethod::tls()).unwrap().build();
16//!
17//! let stream = TcpStream::connect("google.com:443").unwrap();
18//! let mut stream = connector.connect("google.com", stream).unwrap();
19//!
20//! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
21//! let mut res = vec![];
22//! stream.read_to_end(&mut res).unwrap();
23//! println!("{}", String::from_utf8_lossy(&res));
24//! ```
25//!
26//! To accept connections as a server from remote clients:
27//!
28//! ```no_run
29//! use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype};
30//! use std::net::{TcpListener, TcpStream};
31//! use std::sync::Arc;
32//! use std::thread;
33//!
34//!
35//! let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
36//! acceptor.set_private_key_file("key.pem", SslFiletype::PEM).unwrap();
37//! acceptor.set_certificate_chain_file("certs.pem").unwrap();
38//! acceptor.check_private_key().unwrap();
39//! let acceptor = Arc::new(acceptor.build());
40//!
41//! let listener = TcpListener::bind("0.0.0.0:8443").unwrap();
42//!
43//! fn handle_client(stream: SslStream<TcpStream>) {
44//!     // ...
45//! }
46//!
47//! for stream in listener.incoming() {
48//!     match stream {
49//!         Ok(stream) => {
50//!             let acceptor = acceptor.clone();
51//!             thread::spawn(move || {
52//!                 let stream = acceptor.accept(stream).unwrap();
53//!                 handle_client(stream);
54//!             });
55//!         }
56//!         Err(e) => { /* connection failed */ }
57//!     }
58//! }
59//! ```
60use crate::cipher_ctx::CipherCtxRef;
61#[cfg(ossl300)]
62use crate::cvt_long;
63use crate::dh::{Dh, DhRef};
64use crate::ec::EcKeyRef;
65use crate::error::ErrorStack;
66use crate::ex_data::Index;
67#[cfg(ossl111)]
68use crate::hash::MessageDigest;
69use crate::hmac::HMacCtxRef;
70#[cfg(ossl300)]
71use crate::mac_ctx::MacCtxRef;
72#[cfg(any(ossl110, libressl270))]
73use crate::nid::Nid;
74use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
75#[cfg(ossl300)]
76use crate::pkey::{PKey, Public};
77use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
78use crate::ssl::bio::BioMethod;
79use crate::ssl::callbacks::*;
80use crate::ssl::error::InnerError;
81use crate::stack::{Stack, StackRef, Stackable};
82use crate::util;
83use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
84use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
85#[cfg(any(ossl102, boringssl, libressl261, awslc))]
86use crate::x509::verify::X509VerifyParamRef;
87use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
88use crate::{cvt, cvt_n, cvt_p, init};
89use bitflags::bitflags;
90use cfg_if::cfg_if;
91use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
92use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
93use once_cell::sync::{Lazy, OnceCell};
94use openssl_macros::corresponds;
95use std::any::TypeId;
96use std::collections::HashMap;
97use std::ffi::{CStr, CString};
98use std::fmt;
99use std::io;
100use std::io::prelude::*;
101use std::marker::PhantomData;
102use std::mem::{self, ManuallyDrop, MaybeUninit};
103use std::ops::{Deref, DerefMut};
104use std::panic::resume_unwind;
105use std::path::Path;
106use std::ptr;
107use std::str;
108use std::sync::{Arc, Mutex};
109
110pub use crate::ssl::connector::{
111    ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
112};
113pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
114
115mod bio;
116mod callbacks;
117#[cfg(any(boringssl, awslc))]
118mod client_hello;
119mod connector;
120mod error;
121#[cfg(test)]
122mod test;
123
124#[cfg(any(boringssl, awslc))]
125pub use client_hello::ClientHello;
126
127/// Returns the OpenSSL name of a cipher corresponding to an RFC-standard cipher name.
128///
129/// If the cipher has no corresponding OpenSSL name, the string `(NONE)` is returned.
130///
131/// Requires OpenSSL 1.1.1 or newer.
132#[corresponds(OPENSSL_cipher_name)]
133#[cfg(ossl111)]
134pub fn cipher_name(std_name: &str) -> &'static str {
135    unsafe {
136        ffi::init();
137
138        let s = CString::new(std_name).unwrap();
139        let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
140        CStr::from_ptr(ptr).to_str().unwrap()
141    }
142}
143
144cfg_if! {
145    if #[cfg(ossl300)] {
146        type SslOptionsRepr = u64;
147    } else if #[cfg(any(boringssl, awslc))] {
148        type SslOptionsRepr = u32;
149    } else {
150        type SslOptionsRepr = libc::c_ulong;
151    }
152}
153
154bitflags! {
155    /// Options controlling the behavior of an `SslContext`.
156    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
157    #[repr(transparent)]
158    pub struct SslOptions: SslOptionsRepr {
159        /// Disables a countermeasure against an SSLv3/TLSv1.0 vulnerability affecting CBC ciphers.
160        const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
161
162        /// A "reasonable default" set of options which enables compatibility flags.
163        #[cfg(not(any(boringssl, awslc)))]
164        const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
165
166        /// Do not query the MTU.
167        ///
168        /// Only affects DTLS connections.
169        const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
170
171        /// Enables Cookie Exchange as described in [RFC 4347 Section 4.2.1].
172        ///
173        /// Only affects DTLS connections.
174        ///
175        /// [RFC 4347 Section 4.2.1]: https://tools.ietf.org/html/rfc4347#section-4.2.1
176        #[cfg(not(any(boringssl, awslc)))]
177        const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
178
179        /// Disables the use of session tickets for session resumption.
180        const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
181
182        /// Always start a new session when performing a renegotiation on the server side.
183        #[cfg(not(any(boringssl, awslc)))]
184        const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
185            ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
186
187        /// Disables the use of TLS compression.
188        #[cfg(not(any(boringssl, awslc)))]
189        const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
190
191        /// Allow legacy insecure renegotiation with servers or clients that do not support secure
192        /// renegotiation.
193        const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
194            ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
195
196        /// Creates a new key for each session when using ECDHE.
197        ///
198        /// This is always enabled in OpenSSL 1.1.0.
199        const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
200
201        /// Creates a new key for each session when using DHE.
202        ///
203        /// This is always enabled in OpenSSL 1.1.0.
204        const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
205
206        /// Use the server's preferences rather than the client's when selecting a cipher.
207        ///
208        /// This has no effect on the client side.
209        const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
210
211        /// Disables version rollback attach detection.
212        const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
213
214        /// Disables the use of SSLv2.
215        const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
216
217        /// Disables the use of SSLv3.
218        const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
219
220        /// Disables the use of TLSv1.0.
221        const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
222
223        /// Disables the use of TLSv1.1.
224        const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
225
226        /// Disables the use of TLSv1.2.
227        const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
228
229        /// Disables the use of TLSv1.3.
230        ///
231        /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
232        #[cfg(any(boringssl, ossl111, libressl340, awslc))]
233        const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
234
235        /// Disables the use of DTLSv1.0
236        ///
237        /// Requires OpenSSL 1.0.2 or LibreSSL 3.3.2 or newer.
238        #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
239        const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
240
241        /// Disables the use of DTLSv1.2.
242        ///
243        /// Requires OpenSSL 1.0.2 or LibreSSL 3.3.2 or newer.
244        #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
245        const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
246
247        /// Disables the use of all (D)TLS protocol versions.
248        ///
249        /// This can be used as a mask when whitelisting protocol versions.
250        ///
251        /// Requires OpenSSL 1.0.2 or newer.
252        ///
253        /// # Examples
254        ///
255        /// Only support TLSv1.2:
256        ///
257        /// ```rust
258        /// use openssl::ssl::SslOptions;
259        ///
260        /// let options = SslOptions::NO_SSL_MASK & !SslOptions::NO_TLSV1_2;
261        /// ```
262        #[cfg(any(ossl102, ossl110))]
263        const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
264
265        /// Disallow all renegotiation in TLSv1.2 and earlier.
266        ///
267        /// Requires OpenSSL 1.1.0h or newer.
268        #[cfg(any(boringssl, ossl110h, awslc))]
269        const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
270
271        /// Enable TLSv1.3 Compatibility mode.
272        ///
273        /// Requires OpenSSL 1.1.1 or newer. This is on by default in 1.1.1, but a future version
274        /// may have this disabled by default.
275        #[cfg(ossl111)]
276        const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
277
278        /// Prioritize ChaCha ciphers when preferred by clients.
279        ///
280        /// Temporarily reprioritize ChaCha20-Poly1305 ciphers to the top of the server cipher list
281        /// if a ChaCha20-Poly1305 cipher is at the top of the client cipher list. This helps those
282        /// clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere in the server
283        /// cipher list; but still allows other clients to use AES and other ciphers.
284        ///
285        /// Requires enable [`SslOptions::CIPHER_SERVER_PREFERENCE`].
286        /// Requires OpenSSL 1.1.1 or newer.
287        ///
288        /// [`SslOptions::CIPHER_SERVER_PREFERENCE`]: struct.SslOptions.html#associatedconstant.CIPHER_SERVER_PREFERENCE
289        #[cfg(ossl111)]
290        const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
291    }
292}
293
294bitflags! {
295    /// Options controlling the behavior of an `SslContext`.
296    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
297    #[repr(transparent)]
298    pub struct SslMode: SslBitType {
299        /// Enables "short writes".
300        ///
301        /// Normally, a write in OpenSSL will always write out all of the requested data, even if it
302        /// requires more than one TLS record or write to the underlying stream. This option will
303        /// cause a write to return after writing a single TLS record instead.
304        const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
305
306        /// Disables a check that the data buffer has not moved between calls when operating in a
307        /// non-blocking context.
308        const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
309
310        /// Enables automatic retries after TLS session events such as renegotiations or heartbeats.
311        ///
312        /// By default, OpenSSL will return a `WantRead` error after a renegotiation or heartbeat.
313        /// This option will cause OpenSSL to automatically continue processing the requested
314        /// operation instead.
315        ///
316        /// Note that `SslStream::read` and `SslStream::write` will automatically retry regardless
317        /// of the state of this option. It only affects `SslStream::ssl_read` and
318        /// `SslStream::ssl_write`.
319        const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
320
321        /// Disables automatic chain building when verifying a peer's certificate.
322        ///
323        /// TLS peers are responsible for sending the entire certificate chain from the leaf to a
324        /// trusted root, but some will incorrectly not do so. OpenSSL will try to build the chain
325        /// out of certificates it knows of, and this option will disable that behavior.
326        const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
327
328        /// Release memory buffers when the session does not need them.
329        ///
330        /// This saves ~34 KiB of memory for idle streams.
331        const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
332
333        /// Sends the fake `TLS_FALLBACK_SCSV` cipher suite in the ClientHello message of a
334        /// handshake.
335        ///
336        /// This should only be enabled if a client has failed to connect to a server which
337        /// attempted to downgrade the protocol version of the session.
338        ///
339        /// Do not use this unless you know what you're doing!
340        #[cfg(not(libressl))]
341        const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
342
343        /// Enable asynchronous processing.
344        ///
345        /// TLS I/O operations may indicate a retry with SSL_ERROR_WANT_ASYNC with this mode set
346        /// if an asynchronous capable engine is used to perform cryptographic operations.
347        ///
348        /// Do not use this unless you know what you're doing!
349        #[cfg(ossl110)]
350        const ASYNC = ffi::SSL_MODE_ASYNC;
351    }
352}
353
354/// A type specifying the kind of protocol an `SslContext` will speak.
355#[derive(Copy, Clone)]
356pub struct SslMethod(*const ffi::SSL_METHOD);
357
358impl SslMethod {
359    /// Support all versions of the TLS protocol.
360    #[corresponds(TLS_method)]
361    pub fn tls() -> SslMethod {
362        unsafe { SslMethod(TLS_method()) }
363    }
364
365    /// Support all versions of the DTLS protocol.
366    #[corresponds(DTLS_method)]
367    pub fn dtls() -> SslMethod {
368        unsafe { SslMethod(DTLS_method()) }
369    }
370
371    /// Support all versions of the TLS protocol, explicitly as a client.
372    #[corresponds(TLS_client_method)]
373    pub fn tls_client() -> SslMethod {
374        unsafe { SslMethod(TLS_client_method()) }
375    }
376
377    /// Support all versions of the TLS protocol, explicitly as a server.
378    #[corresponds(TLS_server_method)]
379    pub fn tls_server() -> SslMethod {
380        unsafe { SslMethod(TLS_server_method()) }
381    }
382
383    #[cfg(tongsuo)]
384    #[corresponds(NTLS_client_method)]
385    pub fn ntls_client() -> SslMethod {
386        unsafe { SslMethod(ffi::NTLS_client_method()) }
387    }
388
389    #[cfg(tongsuo)]
390    #[corresponds(NTLS_server_method)]
391    pub fn ntls_server() -> SslMethod {
392        unsafe { SslMethod(ffi::NTLS_server_method()) }
393    }
394
395    /// Support all versions of the DTLS protocol, explicitly as a client.
396    #[corresponds(DTLS_client_method)]
397    #[cfg(any(boringssl, ossl110, libressl291, awslc))]
398    pub fn dtls_client() -> SslMethod {
399        unsafe { SslMethod(DTLS_client_method()) }
400    }
401
402    /// Support all versions of the DTLS protocol, explicitly as a server.
403    #[corresponds(DTLS_server_method)]
404    #[cfg(any(boringssl, ossl110, libressl291, awslc))]
405    pub fn dtls_server() -> SslMethod {
406        unsafe { SslMethod(DTLS_server_method()) }
407    }
408
409    /// Constructs an `SslMethod` from a pointer to the underlying OpenSSL value.
410    ///
411    /// # Safety
412    ///
413    /// The caller must ensure the pointer is valid.
414    pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
415        SslMethod(ptr)
416    }
417
418    /// Returns a pointer to the underlying OpenSSL value.
419    #[allow(clippy::trivially_copy_pass_by_ref)]
420    pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
421        self.0
422    }
423}
424
425unsafe impl Sync for SslMethod {}
426unsafe impl Send for SslMethod {}
427
428bitflags! {
429    /// Options controlling the behavior of certificate verification.
430    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
431    #[repr(transparent)]
432    pub struct SslVerifyMode: i32 {
433        /// Verifies that the peer's certificate is trusted.
434        ///
435        /// On the server side, this will cause OpenSSL to request a certificate from the client.
436        const PEER = ffi::SSL_VERIFY_PEER;
437
438        /// Disables verification of the peer's certificate.
439        ///
440        /// On the server side, this will cause OpenSSL to not request a certificate from the
441        /// client. On the client side, the certificate will be checked for validity, but the
442        /// negotiation will continue regardless of the result of that check.
443        const NONE = ffi::SSL_VERIFY_NONE;
444
445        /// On the server side, abort the handshake if the client did not send a certificate.
446        ///
447        /// This should be paired with `SSL_VERIFY_PEER`. It has no effect on the client side.
448        const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
449    }
450}
451
452#[cfg(any(boringssl, awslc))]
453type SslBitType = c_int;
454#[cfg(not(any(boringssl, awslc)))]
455type SslBitType = c_long;
456
457#[cfg(any(boringssl, awslc))]
458type SslTimeTy = u64;
459#[cfg(not(any(boringssl, awslc)))]
460type SslTimeTy = c_long;
461
462bitflags! {
463    /// Options controlling the behavior of session caching.
464    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
465    #[repr(transparent)]
466    pub struct SslSessionCacheMode: SslBitType {
467        /// No session caching for the client or server takes place.
468        const OFF = ffi::SSL_SESS_CACHE_OFF;
469
470        /// Enable session caching on the client side.
471        ///
472        /// OpenSSL has no way of identifying the proper session to reuse automatically, so the
473        /// application is responsible for setting it explicitly via [`SslRef::set_session`].
474        ///
475        /// [`SslRef::set_session`]: struct.SslRef.html#method.set_session
476        const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
477
478        /// Enable session caching on the server side.
479        ///
480        /// This is the default mode.
481        const SERVER = ffi::SSL_SESS_CACHE_SERVER;
482
483        /// Enable session caching on both the client and server side.
484        const BOTH = ffi::SSL_SESS_CACHE_BOTH;
485
486        /// Disable automatic removal of expired sessions from the session cache.
487        const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
488
489        /// Disable use of the internal session cache for session lookups.
490        const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
491
492        /// Disable use of the internal session cache for session storage.
493        const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
494
495        /// Disable use of the internal session cache for storage and lookup.
496        const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
497    }
498}
499
500#[cfg(ossl111)]
501bitflags! {
502    /// Which messages and under which conditions an extension should be added or expected.
503    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
504    #[repr(transparent)]
505    pub struct ExtensionContext: c_uint {
506        /// This extension is only allowed in TLS
507        const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
508        /// This extension is only allowed in DTLS
509        const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
510        /// Some extensions may be allowed in DTLS but we don't implement them for it
511        const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
512        /// Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is
513        const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
514        /// Extension is only defined for TLS1.2 and below
515        const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
516        /// Extension is only defined for TLS1.3 and above
517        const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
518        /// Ignore this extension during parsing if we are resuming
519        const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
520        const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
521        /// Really means TLS1.2 or below
522        const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
523        const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
524        const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
525        const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
526        const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
527        const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
528        const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
529    }
530}
531
532/// TLS Extension Type
533#[derive(Copy, Clone)]
534pub struct TlsExtType(c_uint);
535
536impl TlsExtType {
537    /// server name.
538    ///
539    /// This corresponds to `TLSEXT_TYPE_server_name`.
540    pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
541
542    /// application layer protocol negotiation.
543    ///
544    /// This corresponds to `TLSEXT_TYPE_application_layer_protocol_negotiation`.
545    pub const ALPN: TlsExtType =
546        TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
547
548    /// Constructs an `TlsExtType` from a raw value.
549    pub fn from_raw(raw: c_uint) -> TlsExtType {
550        TlsExtType(raw)
551    }
552
553    /// Returns the raw value represented by this type.
554    #[allow(clippy::trivially_copy_pass_by_ref)]
555    pub fn as_raw(&self) -> c_uint {
556        self.0
557    }
558}
559
560/// An identifier of the format of a certificate or key file.
561#[derive(Copy, Clone)]
562pub struct SslFiletype(c_int);
563
564impl SslFiletype {
565    /// The PEM format.
566    ///
567    /// This corresponds to `SSL_FILETYPE_PEM`.
568    pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
569
570    /// The ASN1 format.
571    ///
572    /// This corresponds to `SSL_FILETYPE_ASN1`.
573    pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
574
575    /// Constructs an `SslFiletype` from a raw OpenSSL value.
576    pub fn from_raw(raw: c_int) -> SslFiletype {
577        SslFiletype(raw)
578    }
579
580    /// Returns the raw OpenSSL value represented by this type.
581    #[allow(clippy::trivially_copy_pass_by_ref)]
582    pub fn as_raw(&self) -> c_int {
583        self.0
584    }
585}
586
587/// An identifier of a certificate status type.
588#[derive(Copy, Clone)]
589pub struct StatusType(c_int);
590
591impl StatusType {
592    /// An OSCP status.
593    pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
594
595    /// Constructs a `StatusType` from a raw OpenSSL value.
596    pub fn from_raw(raw: c_int) -> StatusType {
597        StatusType(raw)
598    }
599
600    /// Returns the raw OpenSSL value represented by this type.
601    #[allow(clippy::trivially_copy_pass_by_ref)]
602    pub fn as_raw(&self) -> c_int {
603        self.0
604    }
605}
606
607/// An identifier of a session name type.
608#[derive(Copy, Clone)]
609pub struct NameType(c_int);
610
611impl NameType {
612    /// A host name.
613    pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
614
615    /// Constructs a `StatusType` from a raw OpenSSL value.
616    pub fn from_raw(raw: c_int) -> StatusType {
617        StatusType(raw)
618    }
619
620    /// Returns the raw OpenSSL value represented by this type.
621    #[allow(clippy::trivially_copy_pass_by_ref)]
622    pub fn as_raw(&self) -> c_int {
623        self.0
624    }
625}
626
627static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
628static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
629static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
630
631fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
632    SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
633}
634
635unsafe extern "C" fn free_data_box<T>(
636    _parent: *mut c_void,
637    ptr: *mut c_void,
638    _ad: *mut ffi::CRYPTO_EX_DATA,
639    _idx: c_int,
640    _argl: c_long,
641    _argp: *mut c_void,
642) {
643    if !ptr.is_null() {
644        let _ = Box::<T>::from_raw(ptr as *mut T);
645    }
646}
647
648/// An error returned from the SNI callback.
649#[derive(Debug, Copy, Clone, PartialEq, Eq)]
650pub struct SniError(c_int);
651
652impl SniError {
653    /// Abort the handshake with a fatal alert.
654    pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
655
656    /// Send a warning alert to the client and continue the handshake.
657    pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
658
659    pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
660}
661
662/// An SSL/TLS alert.
663#[derive(Debug, Copy, Clone, PartialEq, Eq)]
664pub struct SslAlert(c_int);
665
666impl SslAlert {
667    /// Alert 112 - `unrecognized_name`.
668    pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
669    pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
670    pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
671    pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
672}
673
674/// An error returned from an ALPN selection callback.
675#[derive(Debug, Copy, Clone, PartialEq, Eq)]
676pub struct AlpnError(c_int);
677
678impl AlpnError {
679    /// Terminate the handshake with a fatal alert.
680    pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
681
682    /// Do not select a protocol, but continue the handshake.
683    pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
684}
685
686/// An error returned from a client hello callback.
687///
688/// Requires OpenSSL 1.1.1 or newer.
689#[cfg(ossl111)]
690#[derive(Debug, Copy, Clone, PartialEq, Eq)]
691pub struct ClientHelloError(c_int);
692
693#[cfg(ossl111)]
694impl ClientHelloError {
695    /// Terminate the connection.
696    pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
697
698    /// Return from the handshake with an `ErrorCode::WANT_CLIENT_HELLO_CB` error.
699    pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
700}
701
702/// Session Ticket Key CB result type
703#[derive(Debug, Copy, Clone, PartialEq, Eq)]
704pub struct TicketKeyStatus(c_int);
705
706impl TicketKeyStatus {
707    /// Session Ticket Key is not set/retrieved for current session
708    pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
709    /// Session Ticket Key is set, and no renew is needed
710    pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
711    /// Session Ticket Key is set, and a new ticket will be needed
712    pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
713}
714
715/// An error returned from a certificate selection callback.
716#[derive(Debug, Copy, Clone, PartialEq, Eq)]
717#[cfg(any(boringssl, awslc))]
718pub struct SelectCertError(ffi::ssl_select_cert_result_t);
719
720#[cfg(any(boringssl, awslc))]
721impl SelectCertError {
722    /// A fatal error occurred and the handshake should be terminated.
723    pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
724
725    /// The operation could not be completed and should be retried later.
726    pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
727
728    /// Although an encrypted ClientHelloInner was decrypted, it should be discarded.
729    /// The certificate selection callback will then be called again, passing in the
730    /// ClientHelloOuter instead. From there, the handshake will proceed
731    /// without retry_configs, to signal to the client to disable ECH.
732    /// This value may only be returned when |SSL_ech_accepted| returnes one.
733    #[cfg(boringssl)]
734    pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
735}
736
737/// SSL CT validation mode.
738#[cfg(ossl111)]
739#[derive(Debug, Copy, Clone, PartialEq, Eq)]
740pub struct SslCtValidationMode(c_int);
741
742#[cfg(ossl111)]
743impl SslCtValidationMode {
744    pub const PERMISSIVE: SslCtValidationMode =
745        SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
746    pub const STRICT: SslCtValidationMode =
747        SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
748}
749
750/// TLS Certificate Compression Algorithm IDs, defined by IANA
751#[derive(Debug, Copy, Clone, PartialEq, Eq)]
752pub struct CertCompressionAlgorithm(c_int);
753
754impl CertCompressionAlgorithm {
755    pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
756    pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
757    pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
758}
759
760/// An SSL/TLS protocol version.
761#[derive(Debug, Copy, Clone, PartialEq, Eq)]
762pub struct SslVersion(c_int);
763
764impl SslVersion {
765    /// SSLv3
766    pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
767
768    /// TLSv1.0
769    pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
770
771    /// TLSv1.1
772    pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
773
774    /// TLSv1.2
775    pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
776
777    /// TLSv1.3
778    ///
779    /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
780    #[cfg(any(ossl111, libressl340, boringssl, awslc))]
781    pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
782
783    #[cfg(tongsuo)]
784    pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
785
786    /// DTLSv1.0
787    ///
788    /// DTLS 1.0 corresponds to TLS 1.1.
789    pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
790
791    /// DTLSv1.2
792    ///
793    /// DTLS 1.2 corresponds to TLS 1.2 to harmonize versions. There was never a DTLS 1.1.
794    #[cfg(any(ossl102, libressl332, boringssl, awslc))]
795    pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
796}
797
798cfg_if! {
799    if #[cfg(any(boringssl, awslc))] {
800        type SslCacheTy = i64;
801        type SslCacheSize = libc::c_ulong;
802        type MtuTy = u32;
803        type ModeTy = u32;
804        type SizeTy = usize;
805    } else {
806        type SslCacheTy = i64;
807        type SslCacheSize = c_long;
808        type MtuTy = c_long;
809        type ModeTy = c_long;
810        type SizeTy = u32;
811    }
812}
813
814/// A standard implementation of protocol selection for Application Layer Protocol Negotiation
815/// (ALPN).
816///
817/// `server` should contain the server's list of supported protocols and `client` the client's. They
818/// must both be in the ALPN wire format. See the documentation for
819/// [`SslContextBuilder::set_alpn_protos`] for details.
820///
821/// It will select the first protocol supported by the server which is also supported by the client.
822///
823/// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
824#[corresponds(SSL_select_next_proto)]
825pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
826    unsafe {
827        let mut out = ptr::null_mut();
828        let mut outlen = 0;
829        let r = ffi::SSL_select_next_proto(
830            &mut out,
831            &mut outlen,
832            server.as_ptr(),
833            server.len() as c_uint,
834            client.as_ptr(),
835            client.len() as c_uint,
836        );
837        if r == ffi::OPENSSL_NPN_NEGOTIATED {
838            Some(util::from_raw_parts(out as *const u8, outlen as usize))
839        } else {
840            None
841        }
842    }
843}
844
845/// A builder for `SslContext`s.
846pub struct SslContextBuilder(SslContext);
847
848impl SslContextBuilder {
849    /// Creates a new `SslContextBuilder`.
850    #[corresponds(SSL_CTX_new)]
851    pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
852        unsafe {
853            init();
854            let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
855
856            Ok(SslContextBuilder::from_ptr(ctx))
857        }
858    }
859
860    /// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value.
861    ///
862    /// # Safety
863    ///
864    /// The caller must ensure that the pointer is valid and uniquely owned by the builder.
865    pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
866        SslContextBuilder(SslContext::from_ptr(ctx))
867    }
868
869    /// Returns a pointer to the raw OpenSSL value.
870    pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
871        self.0.as_ptr()
872    }
873
874    #[cfg(tongsuo)]
875    #[corresponds(SSL_CTX_enable_ntls)]
876    pub fn enable_ntls(&mut self) {
877        unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
878    }
879
880    #[cfg(tongsuo)]
881    #[corresponds(SSL_CTX_disable_ntls)]
882    pub fn disable_ntls(&mut self) {
883        unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
884    }
885
886    #[cfg(all(tongsuo, ossl300))]
887    #[corresponds(SSL_CTX_enable_force_ntls)]
888    pub fn enable_force_ntls(&mut self) {
889        unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
890    }
891
892    #[cfg(all(tongsuo, ossl300))]
893    #[corresponds(SSL_CTX_disable_force_ntls)]
894    pub fn disable_force_ntls(&mut self) {
895        unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
896    }
897
898    #[cfg(tongsuo)]
899    #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
900    pub fn enable_sm_tls13_strict(&mut self) {
901        unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
902    }
903
904    #[cfg(tongsuo)]
905    #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
906    pub fn disable_sm_tls13_strict(&mut self) {
907        unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
908    }
909
910    /// Configures the certificate verification method for new connections.
911    #[corresponds(SSL_CTX_set_verify)]
912    pub fn set_verify(&mut self, mode: SslVerifyMode) {
913        unsafe {
914            ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
915        }
916    }
917
918    /// Configures the certificate verification method for new connections and
919    /// registers a verification callback.
920    ///
921    /// The callback is passed a boolean indicating if OpenSSL's internal verification succeeded as
922    /// well as a reference to the `X509StoreContext` which can be used to examine the certificate
923    /// chain. It should return a boolean indicating if verification succeeded.
924    #[corresponds(SSL_CTX_set_verify)]
925    pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
926    where
927        F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
928    {
929        unsafe {
930            self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
931            ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
932        }
933    }
934
935    /// Configures the server name indication (SNI) callback for new connections.
936    ///
937    /// SNI is used to allow a single server to handle requests for multiple domains, each of which
938    /// has its own certificate chain and configuration.
939    ///
940    /// Obtain the server name with the `servername` method and then set the corresponding context
941    /// with `set_ssl_context`
942    #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
943    // FIXME tlsext prefix?
944    pub fn set_servername_callback<F>(&mut self, callback: F)
945    where
946        F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
947    {
948        unsafe {
949            // The SNI callback is somewhat unique in that the callback associated with the original
950            // context associated with an SSL can be used even if the SSL's context has been swapped
951            // out. When that happens, we wouldn't be able to look up the callback's state in the
952            // context's ex data. Instead, pass the pointer directly as the servername arg. It's
953            // still stored in ex data to manage the lifetime.
954            let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
955            ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
956            ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
957        }
958    }
959
960    /// Sets the certificate verification depth.
961    ///
962    /// If the peer's certificate chain is longer than this value, verification will fail.
963    #[corresponds(SSL_CTX_set_verify_depth)]
964    pub fn set_verify_depth(&mut self, depth: u32) {
965        unsafe {
966            ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
967        }
968    }
969
970    /// Sets a custom certificate store for verifying peer certificates.
971    ///
972    /// Requires AWS-LC or OpenSSL 1.0.2 or newer.
973    #[corresponds(SSL_CTX_set0_verify_cert_store)]
974    #[cfg(any(ossl102, boringssl, awslc))]
975    pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
976        unsafe {
977            let ptr = cert_store.as_ptr();
978            cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
979            mem::forget(cert_store);
980
981            Ok(())
982        }
983    }
984
985    /// Replaces the context's certificate store.
986    #[corresponds(SSL_CTX_set_cert_store)]
987    pub fn set_cert_store(&mut self, cert_store: X509Store) {
988        unsafe {
989            ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
990            mem::forget(cert_store);
991        }
992    }
993
994    /// Controls read ahead behavior.
995    ///
996    /// If enabled, OpenSSL will read as much data as is available from the underlying stream,
997    /// instead of a single record at a time.
998    ///
999    /// It has no effect when used with DTLS.
1000    #[corresponds(SSL_CTX_set_read_ahead)]
1001    pub fn set_read_ahead(&mut self, read_ahead: bool) {
1002        unsafe {
1003            ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1004        }
1005    }
1006
1007    /// Sets the mode used by the context, returning the new mode bit mask.
1008    ///
1009    /// Options already set before are not cleared.
1010    #[corresponds(SSL_CTX_set_mode)]
1011    pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1012        unsafe {
1013            let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1014            SslMode::from_bits_retain(bits)
1015        }
1016    }
1017
1018    /// Clear the mode used by the context, returning the new mode bit mask.
1019    #[corresponds(SSL_CTX_clear_mode)]
1020    pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1021        unsafe {
1022            let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1023            SslMode::from_bits_retain(bits)
1024        }
1025    }
1026
1027    /// Returns the mode set for the context.
1028    #[corresponds(SSL_CTX_get_mode)]
1029    pub fn mode(&self) -> SslMode {
1030        unsafe {
1031            let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1032            SslMode::from_bits_retain(bits)
1033        }
1034    }
1035
1036    /// Configure OpenSSL to use the default built-in DH parameters.
1037    ///
1038    /// If “auto” DH parameters are switched on then the parameters will be selected to be
1039    /// consistent with the size of the key associated with the server's certificate.
1040    /// If there is no certificate (e.g. for PSK ciphersuites), then it it will be consistent
1041    /// with the size of the negotiated symmetric cipher key.
1042    ///
1043    /// Requires OpenSSL 3.0.0.
1044    #[corresponds(SSL_CTX_set_dh_auto)]
1045    #[cfg(ossl300)]
1046    pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1047        unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1048    }
1049
1050    /// Sets the parameters to be used during ephemeral Diffie-Hellman key exchange.
1051    #[corresponds(SSL_CTX_set_tmp_dh)]
1052    pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1053        unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1054    }
1055
1056    /// Sets the callback which will generate parameters to be used during ephemeral Diffie-Hellman
1057    /// key exchange.
1058    ///
1059    /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean
1060    /// indicating if the selected cipher is export-grade, and the key length. The export and key
1061    /// length options are archaic and should be ignored in almost all cases.
1062    #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1063    pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1064    where
1065        F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1066    {
1067        unsafe {
1068            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1069
1070            ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1071        }
1072    }
1073
1074    /// Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange.
1075    #[corresponds(SSL_CTX_set_tmp_ecdh)]
1076    pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1077        unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1078    }
1079
1080    /// Use the default locations of trusted certificates for verification.
1081    ///
1082    /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` environment variables
1083    /// if present, or defaults specified at OpenSSL build time otherwise.
1084    #[corresponds(SSL_CTX_set_default_verify_paths)]
1085    pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1086        unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1087    }
1088
1089    /// Loads trusted root certificates from a file.
1090    ///
1091    /// The file should contain a sequence of PEM-formatted CA certificates.
1092    #[corresponds(SSL_CTX_load_verify_locations)]
1093    pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1094        self.load_verify_locations(Some(file.as_ref()), None)
1095    }
1096
1097    /// Loads trusted root certificates from a file and/or a directory.
1098    #[corresponds(SSL_CTX_load_verify_locations)]
1099    pub fn load_verify_locations(
1100        &mut self,
1101        ca_file: Option<&Path>,
1102        ca_path: Option<&Path>,
1103    ) -> Result<(), ErrorStack> {
1104        let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1105        let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1106        unsafe {
1107            cvt(ffi::SSL_CTX_load_verify_locations(
1108                self.as_ptr(),
1109                ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1110                ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1111            ))
1112            .map(|_| ())
1113        }
1114    }
1115
1116    /// Sets the list of CA names sent to the client.
1117    ///
1118    /// The CA certificates must still be added to the trust root - they are not automatically set
1119    /// as trusted by this method.
1120    #[corresponds(SSL_CTX_set_client_CA_list)]
1121    pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1122        unsafe {
1123            ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1124            mem::forget(list);
1125        }
1126    }
1127
1128    /// Add the provided CA certificate to the list sent by the server to the client when
1129    /// requesting client-side TLS authentication.
1130    #[corresponds(SSL_CTX_add_client_CA)]
1131    pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1132        unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1133    }
1134
1135    /// Set the context identifier for sessions.
1136    ///
1137    /// This value identifies the server's session cache to clients, telling them when they're
1138    /// able to reuse sessions. It should be set to a unique value per server, unless multiple
1139    /// servers share a session cache.
1140    ///
1141    /// This value should be set when using client certificates, or each request will fail its
1142    /// handshake and need to be restarted.
1143    #[corresponds(SSL_CTX_set_session_id_context)]
1144    pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1145        unsafe {
1146            assert!(sid_ctx.len() <= c_uint::MAX as usize);
1147            cvt(ffi::SSL_CTX_set_session_id_context(
1148                self.as_ptr(),
1149                sid_ctx.as_ptr(),
1150                sid_ctx.len() as SizeTy,
1151            ))
1152            .map(|_| ())
1153        }
1154    }
1155
1156    /// Loads a leaf certificate from a file.
1157    ///
1158    /// Only a single certificate will be loaded - use `add_extra_chain_cert` to add the remainder
1159    /// of the certificate chain, or `set_certificate_chain_file` to load the entire chain from a
1160    /// single file.
1161    #[corresponds(SSL_CTX_use_certificate_file)]
1162    pub fn set_certificate_file<P: AsRef<Path>>(
1163        &mut self,
1164        file: P,
1165        file_type: SslFiletype,
1166    ) -> Result<(), ErrorStack> {
1167        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1168        unsafe {
1169            cvt(ffi::SSL_CTX_use_certificate_file(
1170                self.as_ptr(),
1171                file.as_ptr() as *const _,
1172                file_type.as_raw(),
1173            ))
1174            .map(|_| ())
1175        }
1176    }
1177
1178    /// Loads a certificate chain from a file.
1179    ///
1180    /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf
1181    /// certificate, and the remainder forming the chain of certificates up to and including the
1182    /// trusted root certificate.
1183    #[corresponds(SSL_CTX_use_certificate_chain_file)]
1184    pub fn set_certificate_chain_file<P: AsRef<Path>>(
1185        &mut self,
1186        file: P,
1187    ) -> Result<(), ErrorStack> {
1188        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1189        unsafe {
1190            cvt(ffi::SSL_CTX_use_certificate_chain_file(
1191                self.as_ptr(),
1192                file.as_ptr() as *const _,
1193            ))
1194            .map(|_| ())
1195        }
1196    }
1197
1198    /// Sets the leaf certificate.
1199    ///
1200    /// Use `add_extra_chain_cert` to add the remainder of the certificate chain.
1201    #[corresponds(SSL_CTX_use_certificate)]
1202    pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1203        unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1204    }
1205
1206    /// Appends a certificate to the certificate chain.
1207    ///
1208    /// This chain should contain all certificates necessary to go from the certificate specified by
1209    /// `set_certificate` to a trusted root.
1210    #[corresponds(SSL_CTX_add_extra_chain_cert)]
1211    pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1212        unsafe {
1213            cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1214            mem::forget(cert);
1215            Ok(())
1216        }
1217    }
1218
1219    #[cfg(tongsuo)]
1220    #[corresponds(SSL_CTX_use_enc_certificate_file)]
1221    pub fn set_enc_certificate_file<P: AsRef<Path>>(
1222        &mut self,
1223        file: P,
1224        file_type: SslFiletype,
1225    ) -> Result<(), ErrorStack> {
1226        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1227        unsafe {
1228            cvt(ffi::SSL_CTX_use_enc_certificate_file(
1229                self.as_ptr(),
1230                file.as_ptr() as *const _,
1231                file_type.as_raw(),
1232            ))
1233            .map(|_| ())
1234        }
1235    }
1236
1237    #[cfg(tongsuo)]
1238    #[corresponds(SSL_CTX_use_enc_certificate)]
1239    pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1240        unsafe {
1241            cvt(ffi::SSL_CTX_use_enc_certificate(
1242                self.as_ptr(),
1243                cert.as_ptr(),
1244            ))
1245            .map(|_| ())
1246        }
1247    }
1248
1249    #[cfg(tongsuo)]
1250    #[corresponds(SSL_CTX_use_sign_certificate_file)]
1251    pub fn set_sign_certificate_file<P: AsRef<Path>>(
1252        &mut self,
1253        file: P,
1254        file_type: SslFiletype,
1255    ) -> Result<(), ErrorStack> {
1256        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1257        unsafe {
1258            cvt(ffi::SSL_CTX_use_sign_certificate_file(
1259                self.as_ptr(),
1260                file.as_ptr() as *const _,
1261                file_type.as_raw(),
1262            ))
1263            .map(|_| ())
1264        }
1265    }
1266
1267    #[cfg(tongsuo)]
1268    #[corresponds(SSL_CTX_use_sign_certificate)]
1269    pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1270        unsafe {
1271            cvt(ffi::SSL_CTX_use_sign_certificate(
1272                self.as_ptr(),
1273                cert.as_ptr(),
1274            ))
1275            .map(|_| ())
1276        }
1277    }
1278
1279    /// Loads the private key from a file.
1280    #[corresponds(SSL_CTX_use_PrivateKey_file)]
1281    pub fn set_private_key_file<P: AsRef<Path>>(
1282        &mut self,
1283        file: P,
1284        file_type: SslFiletype,
1285    ) -> Result<(), ErrorStack> {
1286        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1287        unsafe {
1288            cvt(ffi::SSL_CTX_use_PrivateKey_file(
1289                self.as_ptr(),
1290                file.as_ptr() as *const _,
1291                file_type.as_raw(),
1292            ))
1293            .map(|_| ())
1294        }
1295    }
1296
1297    /// Sets the private key.
1298    #[corresponds(SSL_CTX_use_PrivateKey)]
1299    pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1300    where
1301        T: HasPrivate,
1302    {
1303        unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1304    }
1305
1306    #[cfg(tongsuo)]
1307    #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1308    pub fn set_enc_private_key_file<P: AsRef<Path>>(
1309        &mut self,
1310        file: P,
1311        file_type: SslFiletype,
1312    ) -> Result<(), ErrorStack> {
1313        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1314        unsafe {
1315            cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1316                self.as_ptr(),
1317                file.as_ptr() as *const _,
1318                file_type.as_raw(),
1319            ))
1320            .map(|_| ())
1321        }
1322    }
1323
1324    #[cfg(tongsuo)]
1325    #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1326    pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1327    where
1328        T: HasPrivate,
1329    {
1330        unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1331    }
1332
1333    #[cfg(tongsuo)]
1334    #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1335    pub fn set_sign_private_key_file<P: AsRef<Path>>(
1336        &mut self,
1337        file: P,
1338        file_type: SslFiletype,
1339    ) -> Result<(), ErrorStack> {
1340        let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1341        unsafe {
1342            cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1343                self.as_ptr(),
1344                file.as_ptr() as *const _,
1345                file_type.as_raw(),
1346            ))
1347            .map(|_| ())
1348        }
1349    }
1350
1351    #[cfg(tongsuo)]
1352    #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1353    pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1354    where
1355        T: HasPrivate,
1356    {
1357        unsafe {
1358            cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1359                self.as_ptr(),
1360                key.as_ptr(),
1361            ))
1362            .map(|_| ())
1363        }
1364    }
1365
1366    /// Sets the list of supported ciphers for protocols before TLSv1.3.
1367    ///
1368    /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3.
1369    ///
1370    /// See [`ciphers`] for details on the format.
1371    ///
1372    /// [`ciphers`]: https://www.openssl.org/docs/manmaster/apps/ciphers.html
1373    #[corresponds(SSL_CTX_set_cipher_list)]
1374    pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1375        let cipher_list = CString::new(cipher_list).unwrap();
1376        unsafe {
1377            cvt(ffi::SSL_CTX_set_cipher_list(
1378                self.as_ptr(),
1379                cipher_list.as_ptr() as *const _,
1380            ))
1381            .map(|_| ())
1382        }
1383    }
1384
1385    /// Sets the list of supported ciphers for the TLSv1.3 protocol.
1386    ///
1387    /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3.
1388    ///
1389    /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of
1390    /// preference.
1391    ///
1392    /// Requires AWS-LC or OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
1393    #[corresponds(SSL_CTX_set_ciphersuites)]
1394    #[cfg(any(ossl111, libressl340, awslc))]
1395    pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1396        let cipher_list = CString::new(cipher_list).unwrap();
1397        unsafe {
1398            cvt(ffi::SSL_CTX_set_ciphersuites(
1399                self.as_ptr(),
1400                cipher_list.as_ptr() as *const _,
1401            ))
1402            .map(|_| ())
1403        }
1404    }
1405
1406    /// Enables ECDHE key exchange with an automatically chosen curve list.
1407    ///
1408    /// Requires OpenSSL 1.0.2.
1409    #[corresponds(SSL_CTX_set_ecdh_auto)]
1410    #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1411    pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1412        unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1413    }
1414
1415    /// Sets the options used by the context, returning the old set.
1416    ///
1417    /// # Note
1418    ///
1419    /// This *enables* the specified options, but does not disable unspecified options. Use
1420    /// `clear_options` for that.
1421    #[corresponds(SSL_CTX_set_options)]
1422    pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1423        let bits =
1424            unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1425        SslOptions::from_bits_retain(bits)
1426    }
1427
1428    /// Returns the options used by the context.
1429    #[corresponds(SSL_CTX_get_options)]
1430    pub fn options(&self) -> SslOptions {
1431        let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1432        SslOptions::from_bits_retain(bits)
1433    }
1434
1435    /// Clears the options used by the context, returning the old set.
1436    #[corresponds(SSL_CTX_clear_options)]
1437    pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1438        let bits =
1439            unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1440        SslOptions::from_bits_retain(bits)
1441    }
1442
1443    /// Sets the minimum supported protocol version.
1444    ///
1445    /// A value of `None` will enable protocol versions down to the lowest version supported by
1446    /// OpenSSL.
1447    ///
1448    /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.
1449    #[corresponds(SSL_CTX_set_min_proto_version)]
1450    #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1451    pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1452        unsafe {
1453            cvt(ffi::SSL_CTX_set_min_proto_version(
1454                self.as_ptr(),
1455                version.map_or(0, |v| v.0 as _),
1456            ))
1457            .map(|_| ())
1458        }
1459    }
1460
1461    /// Sets the maximum supported protocol version.
1462    ///
1463    /// A value of `None` will enable protocol versions up to the highest version supported by
1464    /// OpenSSL.
1465    ///
1466    /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.
1467    #[corresponds(SSL_CTX_set_max_proto_version)]
1468    #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1469    pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1470        unsafe {
1471            cvt(ffi::SSL_CTX_set_max_proto_version(
1472                self.as_ptr(),
1473                version.map_or(0, |v| v.0 as _),
1474            ))
1475            .map(|_| ())
1476        }
1477    }
1478
1479    /// Gets the minimum supported protocol version.
1480    ///
1481    /// A value of `None` indicates that all versions down to the lowest version supported by
1482    /// OpenSSL are enabled.
1483    ///
1484    /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.
1485    #[corresponds(SSL_CTX_get_min_proto_version)]
1486    #[cfg(any(ossl110g, libressl270))]
1487    pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1488        unsafe {
1489            let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1490            if r == 0 {
1491                None
1492            } else {
1493                Some(SslVersion(r))
1494            }
1495        }
1496    }
1497
1498    /// Gets the maximum supported protocol version.
1499    ///
1500    /// A value of `None` indicates that all versions up to the highest version supported by
1501    /// OpenSSL are enabled.
1502    ///
1503    /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.
1504    #[corresponds(SSL_CTX_get_max_proto_version)]
1505    #[cfg(any(ossl110g, libressl270))]
1506    pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1507        unsafe {
1508            let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1509            if r == 0 {
1510                None
1511            } else {
1512                Some(SslVersion(r))
1513            }
1514        }
1515    }
1516
1517    /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN).
1518    ///
1519    /// The input must be in ALPN "wire format". It consists of a sequence of supported protocol
1520    /// names prefixed by their byte length. For example, the protocol list consisting of `spdy/1`
1521    /// and `http/1.1` is encoded as `b"\x06spdy/1\x08http/1.1"`. The protocols are ordered by
1522    /// preference.
1523    ///
1524    /// Requires AWS-LC or BoringSSL or OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
1525    #[corresponds(SSL_CTX_set_alpn_protos)]
1526    #[cfg(any(ossl102, libressl261, boringssl, awslc))]
1527    pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1528        unsafe {
1529            assert!(protocols.len() <= c_uint::MAX as usize);
1530            let r = ffi::SSL_CTX_set_alpn_protos(
1531                self.as_ptr(),
1532                protocols.as_ptr(),
1533                protocols.len() as _,
1534            );
1535            // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D:
1536            if r == 0 {
1537                Ok(())
1538            } else {
1539                Err(ErrorStack::get())
1540            }
1541        }
1542    }
1543
1544    /// Enables the DTLS extension "use_srtp" as defined in RFC5764.
1545    #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1546    pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1547        unsafe {
1548            let cstr = CString::new(protocols).unwrap();
1549
1550            let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1551            // fun fact, set_tlsext_use_srtp has a reversed return code D:
1552            if r == 0 {
1553                Ok(())
1554            } else {
1555                Err(ErrorStack::get())
1556            }
1557        }
1558    }
1559
1560    /// Sets the callback used by a server to select a protocol for Application Layer Protocol
1561    /// Negotiation (ALPN).
1562    ///
1563    /// The callback is provided with the client's protocol list in ALPN wire format. See the
1564    /// documentation for [`SslContextBuilder::set_alpn_protos`] for details. It should return one
1565    /// of those protocols on success. The [`select_next_proto`] function implements the standard
1566    /// protocol selection algorithm.
1567    ///
1568    /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
1569    /// [`select_next_proto`]: fn.select_next_proto.html
1570    #[corresponds(SSL_CTX_set_alpn_select_cb)]
1571    pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1572    where
1573        F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1574    {
1575        unsafe {
1576            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1577            ffi::SSL_CTX_set_alpn_select_cb(
1578                self.as_ptr(),
1579                Some(callbacks::raw_alpn_select::<F>),
1580                ptr::null_mut(),
1581            );
1582        }
1583    }
1584
1585    /// Checks for consistency between the private key and certificate.
1586    #[corresponds(SSL_CTX_check_private_key)]
1587    pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1588        unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1589    }
1590
1591    /// Returns a shared reference to the context's certificate store.
1592    #[corresponds(SSL_CTX_get_cert_store)]
1593    pub fn cert_store(&self) -> &X509StoreBuilderRef {
1594        unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1595    }
1596
1597    /// Returns a mutable reference to the context's certificate store.
1598    #[corresponds(SSL_CTX_get_cert_store)]
1599    pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1600        unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1601    }
1602
1603    /// Returns a reference to the X509 verification configuration.
1604    ///
1605    /// Requires AWS-LC or BoringSSL or OpenSSL 1.0.2 or newer.
1606    #[corresponds(SSL_CTX_get0_param)]
1607    #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1608    pub fn verify_param(&self) -> &X509VerifyParamRef {
1609        unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1610    }
1611
1612    /// Returns a mutable reference to the X509 verification configuration.
1613    ///
1614    /// Requires AWS-LC or BoringSSL or OpenSSL 1.0.2 or newer.
1615    #[corresponds(SSL_CTX_get0_param)]
1616    #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1617    pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1618        unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1619    }
1620
1621    /// Registers a certificate decompression algorithm on ctx with ID alg_id.
1622    ///
1623    /// This corresponds to [`SSL_CTX_add_cert_compression_alg`].
1624    ///
1625    /// [`SSL_CTX_add_cert_compression_alg`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_add_cert_compression_alg
1626    ///
1627    /// Requires BoringSSL or Tongsuo.
1628    #[cfg(any(boringssl, tongsuo, awslc))]
1629    pub fn add_cert_decompression_alg<F>(
1630        &mut self,
1631        alg_id: CertCompressionAlgorithm,
1632        decompress: F,
1633    ) -> Result<(), ErrorStack>
1634    where
1635        F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1636    {
1637        unsafe {
1638            self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1639            cvt(ffi::SSL_CTX_add_cert_compression_alg(
1640                self.as_ptr(),
1641                alg_id.0 as _,
1642                None,
1643                Some(raw_cert_decompression::<F>),
1644            ))
1645            .map(|_| ())
1646        }
1647    }
1648
1649    /// Specify the preferred cert compression algorithms
1650    #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1651    #[cfg(ossl320)]
1652    pub fn set_cert_comp_preference(
1653        &mut self,
1654        algs: &[CertCompressionAlgorithm],
1655    ) -> Result<(), ErrorStack> {
1656        let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1657        unsafe {
1658            cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1659                self.as_ptr(),
1660                algs.as_mut_ptr(),
1661                algs.len(),
1662            ))
1663            .map(|_| ())
1664        }
1665    }
1666
1667    /// Enables OCSP stapling on all client SSL objects created from ctx
1668    ///
1669    /// This corresponds to [`SSL_CTX_enable_ocsp_stapling`].
1670    ///
1671    /// [`SSL_CTX_enable_ocsp_stapling`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_enable_ocsp_stapling
1672    ///
1673    /// Requires BoringSSL.
1674    #[cfg(any(boringssl, awslc))]
1675    pub fn enable_ocsp_stapling(&mut self) {
1676        unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1677    }
1678
1679    /// Enables SCT requests on all client SSL objects created from ctx
1680    ///
1681    /// This corresponds to [`SSL_CTX_enable_signed_cert_timestamps`].
1682    ///
1683    /// [`SSL_CTX_enable_signed_cert_timestamps`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_enable_signed_cert_timestamps
1684    ///
1685    /// Requires BoringSSL.
1686    #[cfg(any(boringssl, awslc))]
1687    pub fn enable_signed_cert_timestamps(&mut self) {
1688        unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1689    }
1690
1691    /// Set whether to enable GREASE on all client SSL objects created from ctx
1692    ///
1693    /// This corresponds to [`SSL_CTX_set_grease_enabled`].
1694    ///
1695    /// [`SSL_CTX_set_grease_enabled`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_grease_enabled
1696    ///
1697    /// Requires BoringSSL.
1698    #[cfg(any(boringssl, awslc))]
1699    pub fn set_grease_enabled(&mut self, enabled: bool) {
1700        unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1701    }
1702
1703    /// Configures whether sockets on ctx should permute extensions.
1704    ///
1705    /// This corresponds to [`SSL_CTX_set_permute_extensions`].
1706    ///
1707    /// [`SSL_CTX_set_permute_extensions`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_permute_extensions
1708    ///
1709    /// Requires BoringSSL.
1710    #[cfg(any(boringssl, awslc))]
1711    pub fn set_permute_extensions(&mut self, enabled: bool) {
1712        unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1713    }
1714
1715    /// Enable the processing of signed certificate timestamps (SCTs) for all connections that share the given SSL context.
1716    #[corresponds(SSL_CTX_enable_ct)]
1717    #[cfg(ossl111)]
1718    pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1719        unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1720    }
1721
1722    /// Check whether CT processing is enabled.
1723    #[corresponds(SSL_CTX_ct_is_enabled)]
1724    #[cfg(ossl111)]
1725    pub fn ct_is_enabled(&self) -> bool {
1726        unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1727    }
1728
1729    /// Sets the status response a client wishes the server to reply with.
1730    #[corresponds(SSL_CTX_set_tlsext_status_type)]
1731    #[cfg(not(any(boringssl, awslc)))]
1732    pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1733        unsafe {
1734            cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1735                .map(|_| ())
1736        }
1737    }
1738
1739    /// Sets the callback dealing with OCSP stapling.
1740    ///
1741    /// On the client side, this callback is responsible for validating the OCSP status response
1742    /// returned by the server. The status may be retrieved with the `SslRef::ocsp_status` method.
1743    /// A response of `Ok(true)` indicates that the OCSP status is valid, and a response of
1744    /// `Ok(false)` indicates that the OCSP status is invalid and the handshake should be
1745    /// terminated.
1746    ///
1747    /// On the server side, this callback is responsible for setting the OCSP status response to be
1748    /// returned to clients. The status may be set with the `SslRef::set_ocsp_status` method. A
1749    /// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and
1750    /// `Ok(false)` indicates that the status should not be returned to the client.
1751    #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1752    pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1753    where
1754        F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1755    {
1756        unsafe {
1757            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1758            cvt(
1759                ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1760                    as c_int,
1761            )
1762            .map(|_| ())
1763        }
1764    }
1765
1766    #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1767    #[cfg(ossl300)]
1768    pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1769    where
1770        F: Fn(
1771                &mut SslRef,
1772                &mut [u8],
1773                &mut [u8],
1774                &mut CipherCtxRef,
1775                &mut MacCtxRef,
1776                bool,
1777            ) -> Result<TicketKeyStatus, ErrorStack>
1778            + 'static
1779            + Sync
1780            + Send,
1781    {
1782        unsafe {
1783            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1784            cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1785                self.as_ptr(),
1786                Some(raw_tlsext_ticket_key_evp::<F>),
1787            ) as c_int)
1788            .map(|_| ())
1789        }
1790    }
1791
1792    #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1793    pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1794    where
1795        F: Fn(
1796                &mut SslRef,
1797                &mut [u8],
1798                &mut [u8],
1799                &mut CipherCtxRef,
1800                &mut HMacCtxRef,
1801                bool,
1802            ) -> Result<TicketKeyStatus, ErrorStack>
1803            + 'static
1804            + Sync
1805            + Send,
1806    {
1807        unsafe {
1808            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1809            cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1810                self.as_ptr(),
1811                Some(raw_tlsext_ticket_key::<F>),
1812            ) as c_int)
1813            .map(|_| ())
1814        }
1815    }
1816
1817    /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK client.
1818    ///
1819    /// The callback will be called with the SSL context, an identity hint if one was provided
1820    /// by the server, a mutable slice for each of the identity and pre-shared key bytes. The
1821    /// identity must be written as a null-terminated C string.
1822    #[corresponds(SSL_CTX_set_psk_client_callback)]
1823    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1824    pub fn set_psk_client_callback<F>(&mut self, callback: F)
1825    where
1826        F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1827            + 'static
1828            + Sync
1829            + Send,
1830    {
1831        unsafe {
1832            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1833            ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1834        }
1835    }
1836
1837    /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK server.
1838    ///
1839    /// The callback will be called with the SSL context, an identity provided by the client,
1840    /// and, a mutable slice for the pre-shared key bytes. The callback returns the number of
1841    /// bytes in the pre-shared key.
1842    #[corresponds(SSL_CTX_set_psk_server_callback)]
1843    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1844    pub fn set_psk_server_callback<F>(&mut self, callback: F)
1845    where
1846        F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1847            + 'static
1848            + Sync
1849            + Send,
1850    {
1851        unsafe {
1852            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1853            ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1854        }
1855    }
1856
1857    /// Sets the callback which is called when new sessions are negotiated.
1858    ///
1859    /// This can be used by clients to implement session caching. While in TLSv1.2 the session is
1860    /// available to access via [`SslRef::session`] immediately after the handshake completes, this
1861    /// is not the case for TLSv1.3. There, a session is not generally available immediately, and
1862    /// the server may provide multiple session tokens to the client over a single session. The new
1863    /// session callback is a portable way to deal with both cases.
1864    ///
1865    /// Note that session caching must be enabled for the callback to be invoked, and it defaults
1866    /// off for clients. [`set_session_cache_mode`] controls that behavior.
1867    ///
1868    /// [`SslRef::session`]: struct.SslRef.html#method.session
1869    /// [`set_session_cache_mode`]: #method.set_session_cache_mode
1870    #[corresponds(SSL_CTX_sess_set_new_cb)]
1871    pub fn set_new_session_callback<F>(&mut self, callback: F)
1872    where
1873        F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1874    {
1875        unsafe {
1876            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1877            ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1878        }
1879    }
1880
1881    /// Sets the callback which is called when sessions are removed from the context.
1882    ///
1883    /// Sessions can be removed because they have timed out or because they are considered faulty.
1884    #[corresponds(SSL_CTX_sess_set_remove_cb)]
1885    pub fn set_remove_session_callback<F>(&mut self, callback: F)
1886    where
1887        F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1888    {
1889        unsafe {
1890            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1891            ffi::SSL_CTX_sess_set_remove_cb(
1892                self.as_ptr(),
1893                Some(callbacks::raw_remove_session::<F>),
1894            );
1895        }
1896    }
1897
1898    /// Sets the callback which is called when a client proposed to resume a session but it was not
1899    /// found in the internal cache.
1900    ///
1901    /// The callback is passed a reference to the session ID provided by the client. It should
1902    /// return the session corresponding to that ID if available. This is only used for servers, not
1903    /// clients.
1904    ///
1905    /// # Safety
1906    ///
1907    /// The returned `SslSession` must not be associated with a different `SslContext`.
1908    #[corresponds(SSL_CTX_sess_set_get_cb)]
1909    pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1910    where
1911        F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1912    {
1913        self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1914        ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1915    }
1916
1917    /// Sets the TLS key logging callback.
1918    ///
1919    /// The callback is invoked whenever TLS key material is generated, and is passed a line of NSS
1920    /// SSLKEYLOGFILE-formatted text. This can be used by tools like Wireshark to decrypt message
1921    /// traffic. The line does not contain a trailing newline.
1922    ///
1923    /// Requires OpenSSL 1.1.1 or newer.
1924    #[corresponds(SSL_CTX_set_keylog_callback)]
1925    #[cfg(any(ossl111, boringssl, awslc))]
1926    pub fn set_keylog_callback<F>(&mut self, callback: F)
1927    where
1928        F: Fn(&SslRef, &str) + 'static + Sync + Send,
1929    {
1930        unsafe {
1931            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1932            ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1933        }
1934    }
1935
1936    /// Sets the session caching mode use for connections made with the context.
1937    ///
1938    /// Returns the previous session caching mode.
1939    #[corresponds(SSL_CTX_set_session_cache_mode)]
1940    pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1941        unsafe {
1942            let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1943            SslSessionCacheMode::from_bits_retain(bits)
1944        }
1945    }
1946
1947    /// Sets the callback for generating an application cookie for TLS1.3
1948    /// stateless handshakes.
1949    ///
1950    /// The callback will be called with the SSL context and a slice into which the cookie
1951    /// should be written. The callback should return the number of bytes written.
1952    #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1953    #[cfg(ossl111)]
1954    pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1955    where
1956        F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1957    {
1958        unsafe {
1959            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1960            ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1961                self.as_ptr(),
1962                Some(raw_stateless_cookie_generate::<F>),
1963            );
1964        }
1965    }
1966
1967    /// Sets the callback for verifying an application cookie for TLS1.3
1968    /// stateless handshakes.
1969    ///
1970    /// The callback will be called with the SSL context and the cookie supplied by the
1971    /// client. It should return true if and only if the cookie is valid.
1972    ///
1973    /// Note that the OpenSSL implementation independently verifies the integrity of
1974    /// application cookies using an HMAC before invoking the supplied callback.
1975    #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1976    #[cfg(ossl111)]
1977    pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1978    where
1979        F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1980    {
1981        unsafe {
1982            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1983            ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1984                self.as_ptr(),
1985                Some(raw_stateless_cookie_verify::<F>),
1986            )
1987        }
1988    }
1989
1990    /// Sets the callback for generating a DTLSv1 cookie
1991    ///
1992    /// The callback will be called with the SSL context and a slice into which the cookie
1993    /// should be written. The callback should return the number of bytes written.
1994    #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1995    #[cfg(not(any(boringssl, awslc)))]
1996    pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1997    where
1998        F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1999    {
2000        unsafe {
2001            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2002            ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2003        }
2004    }
2005
2006    /// Sets the callback for verifying a DTLSv1 cookie
2007    ///
2008    /// The callback will be called with the SSL context and the cookie supplied by the
2009    /// client. It should return true if and only if the cookie is valid.
2010    #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2011    #[cfg(not(any(boringssl, awslc)))]
2012    pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2013    where
2014        F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2015    {
2016        unsafe {
2017            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2018            ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2019        }
2020    }
2021
2022    /// Sets the extra data at the specified index.
2023    ///
2024    /// This can be used to provide data to callbacks registered with the context. Use the
2025    /// `SslContext::new_ex_index` method to create an `Index`.
2026    // FIXME should return a result
2027    #[corresponds(SSL_CTX_set_ex_data)]
2028    pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2029        self.set_ex_data_inner(index, data);
2030    }
2031
2032    fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2033        match self.ex_data_mut(index) {
2034            Some(v) => {
2035                *v = data;
2036                (v as *mut T).cast()
2037            }
2038            _ => unsafe {
2039                let data = Box::into_raw(Box::new(data)) as *mut c_void;
2040                ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2041                data
2042            },
2043        }
2044    }
2045
2046    fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2047        unsafe {
2048            let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2049            if data.is_null() {
2050                None
2051            } else {
2052                Some(&mut *data.cast())
2053            }
2054        }
2055    }
2056
2057    /// Adds a custom extension for a TLS/DTLS client or server for all supported protocol versions.
2058    ///
2059    /// Requires OpenSSL 1.1.1 or newer.
2060    #[corresponds(SSL_CTX_add_custom_ext)]
2061    #[cfg(ossl111)]
2062    pub fn add_custom_ext<AddFn, ParseFn, T>(
2063        &mut self,
2064        ext_type: u16,
2065        context: ExtensionContext,
2066        add_cb: AddFn,
2067        parse_cb: ParseFn,
2068    ) -> Result<(), ErrorStack>
2069    where
2070        AddFn: Fn(
2071                &mut SslRef,
2072                ExtensionContext,
2073                Option<(usize, &X509Ref)>,
2074            ) -> Result<Option<T>, SslAlert>
2075            + 'static
2076            + Sync
2077            + Send,
2078        T: AsRef<[u8]> + 'static + Sync + Send,
2079        ParseFn: Fn(
2080                &mut SslRef,
2081                ExtensionContext,
2082                &[u8],
2083                Option<(usize, &X509Ref)>,
2084            ) -> Result<(), SslAlert>
2085            + 'static
2086            + Sync
2087            + Send,
2088    {
2089        let ret = unsafe {
2090            self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2091            self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2092
2093            ffi::SSL_CTX_add_custom_ext(
2094                self.as_ptr(),
2095                ext_type as c_uint,
2096                context.bits(),
2097                Some(raw_custom_ext_add::<AddFn, T>),
2098                Some(raw_custom_ext_free::<T>),
2099                ptr::null_mut(),
2100                Some(raw_custom_ext_parse::<ParseFn>),
2101                ptr::null_mut(),
2102            )
2103        };
2104        if ret == 1 {
2105            Ok(())
2106        } else {
2107            Err(ErrorStack::get())
2108        }
2109    }
2110
2111    /// Sets the maximum amount of early data that will be accepted on incoming connections.
2112    ///
2113    /// Defaults to 0.
2114    ///
2115    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
2116    #[corresponds(SSL_CTX_set_max_early_data)]
2117    #[cfg(any(ossl111, libressl340))]
2118    pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2119        if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2120            Ok(())
2121        } else {
2122            Err(ErrorStack::get())
2123        }
2124    }
2125
2126    /// Sets a callback that is called before most ClientHello processing and before the decision whether
2127    /// to resume a session is made. The callback may inspect the ClientHello and configure the
2128    /// connection.
2129    ///
2130    /// This corresponds to [`SSL_CTX_set_select_certificate_cb`].
2131    ///
2132    /// [`SSL_CTX_set_select_certificate_cb`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_select_certificate_cb
2133    ///
2134    /// Requires BoringSSL.
2135    #[cfg(any(boringssl, awslc))]
2136    pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2137    where
2138        F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2139    {
2140        unsafe {
2141            self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2142            ffi::SSL_CTX_set_select_certificate_cb(
2143                self.as_ptr(),
2144                Some(callbacks::raw_select_cert::<F>),
2145            );
2146        }
2147    }
2148
2149    /// Sets a callback which will be invoked just after the client's hello message is received.
2150    ///
2151    /// Requires OpenSSL 1.1.1 or newer.
2152    #[corresponds(SSL_CTX_set_client_hello_cb)]
2153    #[cfg(ossl111)]
2154    pub fn set_client_hello_callback<F>(&mut self, callback: F)
2155    where
2156        F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2157    {
2158        unsafe {
2159            let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2160            ffi::SSL_CTX_set_client_hello_cb(
2161                self.as_ptr(),
2162                Some(callbacks::raw_client_hello::<F>),
2163                ptr,
2164            );
2165        }
2166    }
2167
2168    /// Sets the callback function that can be used to obtain state information for SSL objects
2169    /// created from ctx during connection setup and use.
2170    #[corresponds(SSL_CTX_set_info_callback)]
2171    pub fn set_info_callback<F>(&mut self, callback: F)
2172    where
2173        F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2174    {
2175        unsafe {
2176            self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2177            ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2178        }
2179    }
2180
2181    /// Sets the context's session cache size limit, returning the previous limit.
2182    ///
2183    /// A value of 0 means that the cache size is unbounded.
2184    #[corresponds(SSL_CTX_sess_set_cache_size)]
2185    #[allow(clippy::useless_conversion)]
2186    pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2187        unsafe {
2188            ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2189        }
2190    }
2191
2192    /// Sets the context's supported signature algorithms.
2193    ///
2194    /// Requires OpenSSL 1.0.2 or newer.
2195    #[corresponds(SSL_CTX_set1_sigalgs_list)]
2196    #[cfg(ossl102)]
2197    pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2198        let sigalgs = CString::new(sigalgs).unwrap();
2199        unsafe {
2200            cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2201                .map(|_| ())
2202        }
2203    }
2204
2205    /// Sets the context's supported elliptic curve groups.
2206    ///
2207    /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.1 or LibreSSL 2.5.1 or newer.
2208    #[corresponds(SSL_CTX_set1_groups_list)]
2209    #[cfg(any(ossl111, boringssl, libressl251, awslc))]
2210    pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2211        let groups = CString::new(groups).unwrap();
2212        unsafe {
2213            cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2214        }
2215    }
2216
2217    /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full
2218    /// handshake.
2219    ///
2220    /// Requires OpenSSL 1.1.1 or newer.
2221    #[corresponds(SSL_CTX_set_num_tickets)]
2222    #[cfg(any(ossl111, boringssl, awslc))]
2223    pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2224        unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2225    }
2226
2227    /// Set the context's security level to a value between 0 and 5, inclusive.
2228    /// A security value of 0 allows allows all parameters and algorithms.
2229    ///
2230    /// Requires OpenSSL 1.1.0 or newer.
2231    #[corresponds(SSL_CTX_set_security_level)]
2232    #[cfg(any(ossl110, libressl360))]
2233    pub fn set_security_level(&mut self, level: u32) {
2234        unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2235    }
2236
2237    /// Consumes the builder, returning a new `SslContext`.
2238    pub fn build(self) -> SslContext {
2239        self.0
2240    }
2241}
2242
2243foreign_type_and_impl_send_sync! {
2244    type CType = ffi::SSL_CTX;
2245    fn drop = ffi::SSL_CTX_free;
2246
2247    /// A context object for TLS streams.
2248    ///
2249    /// Applications commonly configure a single `SslContext` that is shared by all of its
2250    /// `SslStreams`.
2251    pub struct SslContext;
2252
2253    /// Reference to [`SslContext`]
2254    ///
2255    /// [`SslContext`]: struct.SslContext.html
2256    pub struct SslContextRef;
2257}
2258
2259impl Clone for SslContext {
2260    fn clone(&self) -> Self {
2261        (**self).to_owned()
2262    }
2263}
2264
2265impl ToOwned for SslContextRef {
2266    type Owned = SslContext;
2267
2268    fn to_owned(&self) -> Self::Owned {
2269        unsafe {
2270            SSL_CTX_up_ref(self.as_ptr());
2271            SslContext::from_ptr(self.as_ptr())
2272        }
2273    }
2274}
2275
2276// TODO: add useful info here
2277impl fmt::Debug for SslContext {
2278    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2279        write!(fmt, "SslContext")
2280    }
2281}
2282
2283impl SslContext {
2284    /// Creates a new builder object for an `SslContext`.
2285    pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2286        SslContextBuilder::new(method)
2287    }
2288
2289    /// Returns a new extra data index.
2290    ///
2291    /// Each invocation of this function is guaranteed to return a distinct index. These can be used
2292    /// to store data in the context that can be retrieved later by callbacks, for example.
2293    #[corresponds(SSL_CTX_get_ex_new_index)]
2294    pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2295    where
2296        T: 'static + Sync + Send,
2297    {
2298        unsafe {
2299            ffi::init();
2300            let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2301            Ok(Index::from_raw(idx))
2302        }
2303    }
2304
2305    // FIXME should return a result?
2306    fn cached_ex_index<T>() -> Index<SslContext, T>
2307    where
2308        T: 'static + Sync + Send,
2309    {
2310        unsafe {
2311            let idx = *INDEXES
2312                .lock()
2313                .unwrap_or_else(|e| e.into_inner())
2314                .entry(TypeId::of::<T>())
2315                .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2316            Index::from_raw(idx)
2317        }
2318    }
2319}
2320
2321impl SslContextRef {
2322    /// Returns the certificate associated with this `SslContext`, if present.
2323    ///
2324    /// Requires OpenSSL 1.0.2 or LibreSSL 2.7.0 or newer.
2325    #[corresponds(SSL_CTX_get0_certificate)]
2326    #[cfg(any(ossl102, libressl270))]
2327    pub fn certificate(&self) -> Option<&X509Ref> {
2328        unsafe {
2329            let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2330            X509Ref::from_const_ptr_opt(ptr)
2331        }
2332    }
2333
2334    /// Returns the private key associated with this `SslContext`, if present.
2335    ///
2336    /// Requires OpenSSL 1.0.2 or LibreSSL 3.4.0 or newer.
2337    #[corresponds(SSL_CTX_get0_privatekey)]
2338    #[cfg(any(ossl102, libressl340))]
2339    pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2340        unsafe {
2341            let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2342            PKeyRef::from_const_ptr_opt(ptr)
2343        }
2344    }
2345
2346    /// Returns a shared reference to the certificate store used for verification.
2347    #[corresponds(SSL_CTX_get_cert_store)]
2348    pub fn cert_store(&self) -> &X509StoreRef {
2349        unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2350    }
2351
2352    /// Returns a shared reference to the stack of certificates making up the chain from the leaf.
2353    #[corresponds(SSL_CTX_get_extra_chain_certs)]
2354    pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2355        unsafe {
2356            let mut chain = ptr::null_mut();
2357            ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2358            StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2359        }
2360    }
2361
2362    /// Returns a reference to the extra data at the specified index.
2363    #[corresponds(SSL_CTX_get_ex_data)]
2364    pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2365        unsafe {
2366            let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2367            if data.is_null() {
2368                None
2369            } else {
2370                Some(&*(data as *const T))
2371            }
2372        }
2373    }
2374
2375    /// Gets the maximum amount of early data that will be accepted on incoming connections.
2376    ///
2377    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
2378    #[corresponds(SSL_CTX_get_max_early_data)]
2379    #[cfg(any(ossl111, libressl340))]
2380    pub fn max_early_data(&self) -> u32 {
2381        unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2382    }
2383
2384    /// Adds a session to the context's cache.
2385    ///
2386    /// Returns `true` if the session was successfully added to the cache, and `false` if it was already present.
2387    ///
2388    /// # Safety
2389    ///
2390    /// The caller of this method is responsible for ensuring that the session has never been used with another
2391    /// `SslContext` than this one.
2392    #[corresponds(SSL_CTX_add_session)]
2393    pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2394        ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2395    }
2396
2397    /// Removes a session from the context's cache and marks it as non-resumable.
2398    ///
2399    /// Returns `true` if the session was successfully found and removed, and `false` otherwise.
2400    ///
2401    /// # Safety
2402    ///
2403    /// The caller of this method is responsible for ensuring that the session has never been used with another
2404    /// `SslContext` than this one.
2405    #[corresponds(SSL_CTX_remove_session)]
2406    pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2407        ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2408    }
2409
2410    /// Returns the context's session cache size limit.
2411    ///
2412    /// A value of 0 means that the cache size is unbounded.
2413    #[corresponds(SSL_CTX_sess_get_cache_size)]
2414    #[allow(clippy::unnecessary_cast)]
2415    pub fn session_cache_size(&self) -> i64 {
2416        unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2417    }
2418
2419    /// Returns the verify mode that was set on this context from [`SslContextBuilder::set_verify`].
2420    ///
2421    /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
2422    #[corresponds(SSL_CTX_get_verify_mode)]
2423    pub fn verify_mode(&self) -> SslVerifyMode {
2424        let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2425        SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2426    }
2427
2428    /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full
2429    /// handshake.
2430    ///
2431    /// Requires OpenSSL 1.1.1 or newer.
2432    #[corresponds(SSL_CTX_get_num_tickets)]
2433    #[cfg(ossl111)]
2434    pub fn num_tickets(&self) -> usize {
2435        unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2436    }
2437
2438    /// Get the context's security level, which controls the allowed parameters
2439    /// and algorithms.
2440    ///
2441    /// Requires OpenSSL 1.1.0 or newer.
2442    #[corresponds(SSL_CTX_get_security_level)]
2443    #[cfg(any(ossl110, libressl360))]
2444    pub fn security_level(&self) -> u32 {
2445        unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2446    }
2447}
2448
2449/// Information about the state of a cipher.
2450pub struct CipherBits {
2451    /// The number of secret bits used for the cipher.
2452    pub secret: i32,
2453
2454    /// The number of bits processed by the chosen algorithm.
2455    pub algorithm: i32,
2456}
2457
2458/// Information about a cipher.
2459pub struct SslCipher(*mut ffi::SSL_CIPHER);
2460
2461impl ForeignType for SslCipher {
2462    type CType = ffi::SSL_CIPHER;
2463    type Ref = SslCipherRef;
2464
2465    #[inline]
2466    unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2467        SslCipher(ptr)
2468    }
2469
2470    #[inline]
2471    fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2472        self.0
2473    }
2474}
2475
2476impl Stackable for SslCipher {
2477    type StackType = ffi::stack_st_SSL_CIPHER;
2478}
2479
2480impl Deref for SslCipher {
2481    type Target = SslCipherRef;
2482
2483    fn deref(&self) -> &SslCipherRef {
2484        unsafe { SslCipherRef::from_ptr(self.0) }
2485    }
2486}
2487
2488impl DerefMut for SslCipher {
2489    fn deref_mut(&mut self) -> &mut SslCipherRef {
2490        unsafe { SslCipherRef::from_ptr_mut(self.0) }
2491    }
2492}
2493
2494/// Reference to an [`SslCipher`].
2495///
2496/// [`SslCipher`]: struct.SslCipher.html
2497pub struct SslCipherRef(Opaque);
2498
2499impl ForeignTypeRef for SslCipherRef {
2500    type CType = ffi::SSL_CIPHER;
2501}
2502
2503impl SslCipherRef {
2504    /// Returns the name of the cipher.
2505    #[corresponds(SSL_CIPHER_get_name)]
2506    pub fn name(&self) -> &'static str {
2507        unsafe {
2508            let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2509            CStr::from_ptr(ptr).to_str().unwrap()
2510        }
2511    }
2512
2513    /// Returns the RFC-standard name of the cipher, if one exists.
2514    ///
2515    /// Requires OpenSSL 1.1.1 or newer.
2516    #[corresponds(SSL_CIPHER_standard_name)]
2517    #[cfg(ossl111)]
2518    pub fn standard_name(&self) -> Option<&'static str> {
2519        unsafe {
2520            let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2521            if ptr.is_null() {
2522                None
2523            } else {
2524                Some(CStr::from_ptr(ptr).to_str().unwrap())
2525            }
2526        }
2527    }
2528
2529    /// Returns the SSL/TLS protocol version that first defined the cipher.
2530    #[corresponds(SSL_CIPHER_get_version)]
2531    pub fn version(&self) -> &'static str {
2532        let version = unsafe {
2533            let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2534            CStr::from_ptr(ptr as *const _)
2535        };
2536
2537        str::from_utf8(version.to_bytes()).unwrap()
2538    }
2539
2540    /// Returns the number of bits used for the cipher.
2541    #[corresponds(SSL_CIPHER_get_bits)]
2542    #[allow(clippy::useless_conversion)]
2543    pub fn bits(&self) -> CipherBits {
2544        unsafe {
2545            let mut algo_bits = 0;
2546            let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2547            CipherBits {
2548                secret: secret_bits.into(),
2549                algorithm: algo_bits.into(),
2550            }
2551        }
2552    }
2553
2554    /// Returns a textual description of the cipher.
2555    #[corresponds(SSL_CIPHER_description)]
2556    pub fn description(&self) -> String {
2557        unsafe {
2558            // SSL_CIPHER_description requires a buffer of at least 128 bytes.
2559            let mut buf = [0; 128];
2560            let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2561            String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2562        }
2563    }
2564
2565    /// Returns the handshake digest of the cipher.
2566    ///
2567    /// Requires OpenSSL 1.1.1 or newer.
2568    #[corresponds(SSL_CIPHER_get_handshake_digest)]
2569    #[cfg(ossl111)]
2570    pub fn handshake_digest(&self) -> Option<MessageDigest> {
2571        unsafe {
2572            let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2573            if ptr.is_null() {
2574                None
2575            } else {
2576                Some(MessageDigest::from_ptr(ptr))
2577            }
2578        }
2579    }
2580
2581    /// Returns the NID corresponding to the cipher.
2582    ///
2583    /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.
2584    #[corresponds(SSL_CIPHER_get_cipher_nid)]
2585    #[cfg(any(ossl110, libressl270))]
2586    pub fn cipher_nid(&self) -> Option<Nid> {
2587        let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2588        if n == 0 {
2589            None
2590        } else {
2591            Some(Nid::from_raw(n))
2592        }
2593    }
2594}
2595
2596impl fmt::Debug for SslCipherRef {
2597    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2598        write!(fmt, "{}", self.name())
2599    }
2600}
2601
2602/// A stack of selected ciphers, and a stack of selected signalling cipher suites
2603#[derive(Debug)]
2604pub struct CipherLists {
2605    pub suites: Stack<SslCipher>,
2606    pub signalling_suites: Stack<SslCipher>,
2607}
2608
2609foreign_type_and_impl_send_sync! {
2610    type CType = ffi::SSL_SESSION;
2611    fn drop = ffi::SSL_SESSION_free;
2612
2613    /// An encoded SSL session.
2614    ///
2615    /// These can be cached to share sessions across connections.
2616    pub struct SslSession;
2617
2618    /// Reference to [`SslSession`].
2619    ///
2620    /// [`SslSession`]: struct.SslSession.html
2621    pub struct SslSessionRef;
2622}
2623
2624impl Clone for SslSession {
2625    fn clone(&self) -> SslSession {
2626        SslSessionRef::to_owned(self)
2627    }
2628}
2629
2630impl SslSession {
2631    from_der! {
2632        /// Deserializes a DER-encoded session structure.
2633        #[corresponds(d2i_SSL_SESSION)]
2634        from_der,
2635        SslSession,
2636        ffi::d2i_SSL_SESSION
2637    }
2638}
2639
2640impl ToOwned for SslSessionRef {
2641    type Owned = SslSession;
2642
2643    fn to_owned(&self) -> SslSession {
2644        unsafe {
2645            SSL_SESSION_up_ref(self.as_ptr());
2646            SslSession(self.as_ptr())
2647        }
2648    }
2649}
2650
2651impl SslSessionRef {
2652    /// Returns the SSL session ID.
2653    #[corresponds(SSL_SESSION_get_id)]
2654    pub fn id(&self) -> &[u8] {
2655        unsafe {
2656            let mut len = 0;
2657            let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2658            #[allow(clippy::unnecessary_cast)]
2659            util::from_raw_parts(p as *const u8, len as usize)
2660        }
2661    }
2662
2663    /// Returns the length of the master key.
2664    #[corresponds(SSL_SESSION_get_master_key)]
2665    pub fn master_key_len(&self) -> usize {
2666        unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2667    }
2668
2669    /// Copies the master key into the provided buffer.
2670    ///
2671    /// Returns the number of bytes written, or the size of the master key if the buffer is empty.
2672    #[corresponds(SSL_SESSION_get_master_key)]
2673    pub fn master_key(&self, buf: &mut [u8]) -> usize {
2674        unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2675    }
2676
2677    /// Gets the maximum amount of early data that can be sent on this session.
2678    ///
2679    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
2680    #[corresponds(SSL_SESSION_get_max_early_data)]
2681    #[cfg(any(ossl111, libressl340))]
2682    pub fn max_early_data(&self) -> u32 {
2683        unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2684    }
2685
2686    /// Returns the time at which the session was established, in seconds since the Unix epoch.
2687    #[corresponds(SSL_SESSION_get_time)]
2688    #[allow(clippy::useless_conversion)]
2689    pub fn time(&self) -> SslTimeTy {
2690        unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2691    }
2692
2693    /// Returns the sessions timeout, in seconds.
2694    ///
2695    /// A session older than this time should not be used for session resumption.
2696    #[corresponds(SSL_SESSION_get_timeout)]
2697    #[allow(clippy::useless_conversion)]
2698    pub fn timeout(&self) -> i64 {
2699        unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2700    }
2701
2702    /// Returns the session's TLS protocol version.
2703    ///
2704    /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.
2705    #[corresponds(SSL_SESSION_get_protocol_version)]
2706    #[cfg(any(ossl110, libressl270))]
2707    pub fn protocol_version(&self) -> SslVersion {
2708        unsafe {
2709            let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2710            SslVersion(version)
2711        }
2712    }
2713
2714    /// Returns the session's TLS protocol version.
2715    #[corresponds(SSL_SESSION_get_protocol_version)]
2716    #[cfg(any(boringssl, awslc))]
2717    pub fn protocol_version(&self) -> SslVersion {
2718        unsafe {
2719            let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2720            SslVersion(version as _)
2721        }
2722    }
2723
2724    to_der! {
2725        /// Serializes the session into a DER-encoded structure.
2726        #[corresponds(i2d_SSL_SESSION)]
2727        to_der,
2728        ffi::i2d_SSL_SESSION
2729    }
2730}
2731
2732foreign_type_and_impl_send_sync! {
2733    type CType = ffi::SSL;
2734    fn drop = ffi::SSL_free;
2735
2736    /// The state of an SSL/TLS session.
2737    ///
2738    /// `Ssl` objects are created from an [`SslContext`], which provides configuration defaults.
2739    /// These defaults can be overridden on a per-`Ssl` basis, however.
2740    ///
2741    /// [`SslContext`]: struct.SslContext.html
2742    pub struct Ssl;
2743
2744    /// Reference to an [`Ssl`].
2745    ///
2746    /// [`Ssl`]: struct.Ssl.html
2747    pub struct SslRef;
2748}
2749
2750impl fmt::Debug for Ssl {
2751    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2752        fmt::Debug::fmt(&**self, fmt)
2753    }
2754}
2755
2756impl Ssl {
2757    /// Returns a new extra data index.
2758    ///
2759    /// Each invocation of this function is guaranteed to return a distinct index. These can be used
2760    /// to store data in the context that can be retrieved later by callbacks, for example.
2761    #[corresponds(SSL_get_ex_new_index)]
2762    pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2763    where
2764        T: 'static + Sync + Send,
2765    {
2766        unsafe {
2767            ffi::init();
2768            let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2769            Ok(Index::from_raw(idx))
2770        }
2771    }
2772
2773    // FIXME should return a result?
2774    fn cached_ex_index<T>() -> Index<Ssl, T>
2775    where
2776        T: 'static + Sync + Send,
2777    {
2778        unsafe {
2779            let idx = *SSL_INDEXES
2780                .lock()
2781                .unwrap_or_else(|e| e.into_inner())
2782                .entry(TypeId::of::<T>())
2783                .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2784            Index::from_raw(idx)
2785        }
2786    }
2787
2788    /// Creates a new `Ssl`.
2789    #[corresponds(SSL_new)]
2790    pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2791        let session_ctx_index = try_get_session_ctx_index()?;
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.to_owned());
2796
2797            Ok(ssl)
2798        }
2799    }
2800
2801    /// Initiates a client-side TLS handshake.
2802    /// # Warning
2803    ///
2804    /// OpenSSL's default configuration is insecure. It is highly recommended to use
2805    /// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
2806    #[corresponds(SSL_connect)]
2807    #[allow(deprecated)]
2808    pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2809    where
2810        S: Read + Write,
2811    {
2812        SslStreamBuilder::new(self, stream).connect()
2813    }
2814
2815    /// Initiates a server-side TLS handshake.
2816    ///
2817    /// # Warning
2818    ///
2819    /// OpenSSL's default configuration is insecure. It is highly recommended to use
2820    /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
2821    #[corresponds(SSL_accept)]
2822    #[allow(deprecated)]
2823    pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2824    where
2825        S: Read + Write,
2826    {
2827        SslStreamBuilder::new(self, stream).accept()
2828    }
2829}
2830
2831impl fmt::Debug for SslRef {
2832    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2833        fmt.debug_struct("Ssl")
2834            .field("state", &self.state_string_long())
2835            .field("verify_result", &self.verify_result())
2836            .finish()
2837    }
2838}
2839
2840impl SslRef {
2841    #[cfg(not(feature = "tongsuo"))]
2842    fn get_raw_rbio(&self) -> *mut ffi::BIO {
2843        unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2844    }
2845
2846    #[cfg(feature = "tongsuo")]
2847    fn get_raw_rbio(&self) -> *mut ffi::BIO {
2848        unsafe {
2849            let bio = ffi::SSL_get_rbio(self.as_ptr());
2850            bio::find_correct_bio(bio)
2851        }
2852    }
2853
2854    fn get_error(&self, ret: c_int) -> ErrorCode {
2855        unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2856    }
2857
2858    /// Sets the mode used by the SSL, returning the new mode bit mask.
2859    ///
2860    /// Options already set before are not cleared.
2861    #[corresponds(SSL_set_mode)]
2862    pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2863        unsafe {
2864            let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2865            SslMode::from_bits_retain(bits)
2866        }
2867    }
2868
2869    /// Clear the mode used by the SSL, returning the new mode bit mask.
2870    #[corresponds(SSL_clear_mode)]
2871    pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2872        unsafe {
2873            let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2874            SslMode::from_bits_retain(bits)
2875        }
2876    }
2877
2878    /// Returns the mode set for the SSL.
2879    #[corresponds(SSL_get_mode)]
2880    pub fn mode(&self) -> SslMode {
2881        unsafe {
2882            let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2883            SslMode::from_bits_retain(bits)
2884        }
2885    }
2886
2887    /// Configure as an outgoing stream from a client.
2888    #[corresponds(SSL_set_connect_state)]
2889    pub fn set_connect_state(&mut self) {
2890        unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2891    }
2892
2893    /// Configure as an incoming stream to a server.
2894    #[corresponds(SSL_set_accept_state)]
2895    pub fn set_accept_state(&mut self) {
2896        unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2897    }
2898
2899    #[cfg(any(boringssl, awslc))]
2900    #[corresponds(SSL_ech_accepted)]
2901    pub fn ech_accepted(&self) -> bool {
2902        unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2903    }
2904
2905    #[cfg(tongsuo)]
2906    #[corresponds(SSL_is_ntls)]
2907    pub fn is_ntls(&mut self) -> bool {
2908        unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2909    }
2910
2911    #[cfg(tongsuo)]
2912    #[corresponds(SSL_enable_ntls)]
2913    pub fn enable_ntls(&mut self) {
2914        unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2915    }
2916
2917    #[cfg(tongsuo)]
2918    #[corresponds(SSL_disable_ntls)]
2919    pub fn disable_ntls(&mut self) {
2920        unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2921    }
2922
2923    #[cfg(all(tongsuo, ossl300))]
2924    #[corresponds(SSL_enable_force_ntls)]
2925    pub fn enable_force_ntls(&mut self) {
2926        unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2927    }
2928
2929    #[cfg(all(tongsuo, ossl300))]
2930    #[corresponds(SSL_disable_force_ntls)]
2931    pub fn disable_force_ntls(&mut self) {
2932        unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2933    }
2934
2935    #[cfg(tongsuo)]
2936    #[corresponds(SSL_enable_sm_tls13_strict)]
2937    pub fn enable_sm_tls13_strict(&mut self) {
2938        unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2939    }
2940
2941    #[cfg(tongsuo)]
2942    #[corresponds(SSL_disable_sm_tls13_strict)]
2943    pub fn disable_sm_tls13_strict(&mut self) {
2944        unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2945    }
2946
2947    /// Like [`SslContextBuilder::set_verify`].
2948    ///
2949    /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
2950    #[corresponds(SSL_set_verify)]
2951    pub fn set_verify(&mut self, mode: SslVerifyMode) {
2952        unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2953    }
2954
2955    /// Returns the verify mode that was set using `set_verify`.
2956    #[corresponds(SSL_set_verify_mode)]
2957    pub fn verify_mode(&self) -> SslVerifyMode {
2958        let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2959        SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2960    }
2961
2962    /// Like [`SslContextBuilder::set_verify_callback`].
2963    ///
2964    /// [`SslContextBuilder::set_verify_callback`]: struct.SslContextBuilder.html#method.set_verify_callback
2965    #[corresponds(SSL_set_verify)]
2966    pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2967    where
2968        F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2969    {
2970        unsafe {
2971            // this needs to be in an Arc since the callback can register a new callback!
2972            self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2973            ffi::SSL_set_verify(
2974                self.as_ptr(),
2975                mode.bits() as c_int,
2976                Some(ssl_raw_verify::<F>),
2977            );
2978        }
2979    }
2980
2981    // Sets the callback function, that can be used to obtain state information for ssl during
2982    // connection setup and use
2983    #[corresponds(SSL_set_info_callback)]
2984    pub fn set_info_callback<F>(&mut self, callback: F)
2985    where
2986        F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2987    {
2988        unsafe {
2989            // this needs to be in an Arc since the callback can register a new callback!
2990            self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2991            ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
2992        }
2993    }
2994
2995    /// Like [`SslContextBuilder::set_dh_auto`].
2996    ///
2997    /// [`SslContextBuilder::set_dh_auto`]: struct.SslContextBuilder.html#method.set_dh_auto
2998    #[corresponds(SSL_set_dh_auto)]
2999    #[cfg(ossl300)]
3000    pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3001        unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
3002    }
3003
3004    /// Like [`SslContextBuilder::set_tmp_dh`].
3005    ///
3006    /// [`SslContextBuilder::set_tmp_dh`]: struct.SslContextBuilder.html#method.set_tmp_dh
3007    #[corresponds(SSL_set_tmp_dh)]
3008    pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3009        unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3010    }
3011
3012    /// Like [`SslContextBuilder::set_tmp_dh_callback`].
3013    ///
3014    /// [`SslContextBuilder::set_tmp_dh_callback`]: struct.SslContextBuilder.html#method.set_tmp_dh_callback
3015    #[corresponds(SSL_set_tmp_dh_callback)]
3016    pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3017    where
3018        F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3019    {
3020        unsafe {
3021            // this needs to be in an Arc since the callback can register a new callback!
3022            self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3023            ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3024        }
3025    }
3026
3027    /// Like [`SslContextBuilder::set_tmp_ecdh`].
3028    ///
3029    /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh
3030    #[corresponds(SSL_set_tmp_ecdh)]
3031    pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3032        unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3033    }
3034
3035    /// Like [`SslContextBuilder::set_ecdh_auto`].
3036    ///
3037    /// Requires OpenSSL 1.0.2 or LibreSSL.
3038    ///
3039    /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh
3040    #[corresponds(SSL_set_ecdh_auto)]
3041    #[cfg(any(all(ossl102, not(ossl110)), libressl))]
3042    pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3043        unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
3044    }
3045
3046    /// Like [`SslContextBuilder::set_alpn_protos`].
3047    ///
3048    /// Requires AWS-LC or BoringSSL or OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
3049    ///
3050    /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
3051    #[corresponds(SSL_set_alpn_protos)]
3052    #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3053    pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3054        unsafe {
3055            assert!(protocols.len() <= c_uint::MAX as usize);
3056            let r =
3057                ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3058            // fun fact, SSL_set_alpn_protos has a reversed return code D:
3059            if r == 0 {
3060                Ok(())
3061            } else {
3062                Err(ErrorStack::get())
3063            }
3064        }
3065    }
3066
3067    /// Returns the current cipher if the session is active.
3068    #[corresponds(SSL_get_current_cipher)]
3069    pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3070        unsafe {
3071            let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3072
3073            SslCipherRef::from_const_ptr_opt(ptr)
3074        }
3075    }
3076
3077    /// Returns a short string describing the state of the session.
3078    #[corresponds(SSL_state_string)]
3079    pub fn state_string(&self) -> &'static str {
3080        let state = unsafe {
3081            let ptr = ffi::SSL_state_string(self.as_ptr());
3082            CStr::from_ptr(ptr as *const _)
3083        };
3084
3085        str::from_utf8(state.to_bytes()).unwrap()
3086    }
3087
3088    /// Returns a longer string describing the state of the session.
3089    #[corresponds(SSL_state_string_long)]
3090    pub fn state_string_long(&self) -> &'static str {
3091        let state = unsafe {
3092            let ptr = ffi::SSL_state_string_long(self.as_ptr());
3093            CStr::from_ptr(ptr as *const _)
3094        };
3095
3096        str::from_utf8(state.to_bytes()).unwrap()
3097    }
3098
3099    /// Sets the host name to be sent to the server for Server Name Indication (SNI).
3100    ///
3101    /// It has no effect for a server-side connection.
3102    #[corresponds(SSL_set_tlsext_host_name)]
3103    pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3104        let cstr = CString::new(hostname).unwrap();
3105        unsafe {
3106            cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3107                .map(|_| ())
3108        }
3109    }
3110
3111    /// Returns the peer's certificate, if present.
3112    #[corresponds(SSL_get_peer_certificate)]
3113    pub fn peer_certificate(&self) -> Option<X509> {
3114        unsafe {
3115            let ptr = SSL_get1_peer_certificate(self.as_ptr());
3116            X509::from_ptr_opt(ptr)
3117        }
3118    }
3119
3120    /// Returns the certificate chain of the peer, if present.
3121    ///
3122    /// On the client side, the chain includes the leaf certificate, but on the server side it does
3123    /// not. Fun!
3124    #[corresponds(SSL_get_peer_cert_chain)]
3125    pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3126        unsafe {
3127            let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3128            StackRef::from_const_ptr_opt(ptr)
3129        }
3130    }
3131
3132    /// Returns the verified certificate chain of the peer, including the leaf certificate.
3133    ///
3134    /// If verification was not successful (i.e. [`verify_result`] does not return
3135    /// [`X509VerifyResult::OK`]), this chain may be incomplete or invalid.
3136    ///
3137    /// Requires OpenSSL 1.1.0 or newer.
3138    ///
3139    /// [`verify_result`]: #method.verify_result
3140    /// [`X509VerifyResult::OK`]: ../x509/struct.X509VerifyResult.html#associatedconstant.OK
3141    #[corresponds(SSL_get0_verified_chain)]
3142    #[cfg(ossl110)]
3143    pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3144        unsafe {
3145            let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3146            StackRef::from_const_ptr_opt(ptr)
3147        }
3148    }
3149
3150    /// Like [`SslContext::certificate`].
3151    #[corresponds(SSL_get_certificate)]
3152    pub fn certificate(&self) -> Option<&X509Ref> {
3153        unsafe {
3154            let ptr = ffi::SSL_get_certificate(self.as_ptr());
3155            X509Ref::from_const_ptr_opt(ptr)
3156        }
3157    }
3158
3159    /// Like [`SslContext::private_key`].
3160    ///
3161    /// [`SslContext::private_key`]: struct.SslContext.html#method.private_key
3162    #[corresponds(SSL_get_privatekey)]
3163    pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3164        unsafe {
3165            let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3166            PKeyRef::from_const_ptr_opt(ptr)
3167        }
3168    }
3169
3170    /// Returns the protocol version of the session.
3171    #[corresponds(SSL_version)]
3172    pub fn version2(&self) -> Option<SslVersion> {
3173        unsafe {
3174            let r = ffi::SSL_version(self.as_ptr());
3175            if r == 0 {
3176                None
3177            } else {
3178                Some(SslVersion(r))
3179            }
3180        }
3181    }
3182
3183    /// Returns a string describing the protocol version of the session.
3184    #[corresponds(SSL_get_version)]
3185    pub fn version_str(&self) -> &'static str {
3186        let version = unsafe {
3187            let ptr = ffi::SSL_get_version(self.as_ptr());
3188            CStr::from_ptr(ptr as *const _)
3189        };
3190
3191        str::from_utf8(version.to_bytes()).unwrap()
3192    }
3193
3194    /// Returns the protocol selected via Application Layer Protocol Negotiation (ALPN).
3195    ///
3196    /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client
3197    /// to interpret it.
3198    ///
3199    /// Requires AWS-LC or BoringSSL or OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
3200    #[corresponds(SSL_get0_alpn_selected)]
3201    #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3202    pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3203        unsafe {
3204            let mut data: *const c_uchar = ptr::null();
3205            let mut len: c_uint = 0;
3206            // Get the negotiated protocol from the SSL instance.
3207            // `data` will point at a `c_uchar` array; `len` will contain the length of this array.
3208            ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3209
3210            if data.is_null() {
3211                None
3212            } else {
3213                Some(util::from_raw_parts(data, len as usize))
3214            }
3215        }
3216    }
3217
3218    /// Enables the DTLS extension "use_srtp" as defined in RFC5764.
3219    #[corresponds(SSL_set_tlsext_use_srtp)]
3220    pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3221        unsafe {
3222            let cstr = CString::new(protocols).unwrap();
3223
3224            let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3225            // fun fact, set_tlsext_use_srtp has a reversed return code D:
3226            if r == 0 {
3227                Ok(())
3228            } else {
3229                Err(ErrorStack::get())
3230            }
3231        }
3232    }
3233
3234    /// Gets all SRTP profiles that are enabled for handshake via set_tlsext_use_srtp
3235    ///
3236    /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled.
3237    #[corresponds(SSL_get_srtp_profiles)]
3238    pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3239        unsafe {
3240            let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3241
3242            StackRef::from_const_ptr_opt(chain)
3243        }
3244    }
3245
3246    /// Gets the SRTP profile selected by handshake.
3247    ///
3248    /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled.
3249    #[corresponds(SSL_get_selected_srtp_profile)]
3250    pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3251        unsafe {
3252            let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3253
3254            SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3255        }
3256    }
3257
3258    /// Returns the number of bytes remaining in the currently processed TLS record.
3259    ///
3260    /// If this is greater than 0, the next call to `read` will not call down to the underlying
3261    /// stream.
3262    #[corresponds(SSL_pending)]
3263    pub fn pending(&self) -> usize {
3264        unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3265    }
3266
3267    /// Returns the servername sent by the client via Server Name Indication (SNI).
3268    ///
3269    /// It is only useful on the server side.
3270    ///
3271    /// # Note
3272    ///
3273    /// While the SNI specification requires that servernames be valid domain names (and therefore
3274    /// ASCII), OpenSSL does not enforce this restriction. If the servername provided by the client
3275    /// is not valid UTF-8, this function will return `None`. The `servername_raw` method returns
3276    /// the raw bytes and does not have this restriction.
3277    ///
3278    /// [`SSL_get_servername`]: https://www.openssl.org/docs/manmaster/man3/SSL_get_servername.html
3279    #[corresponds(SSL_get_servername)]
3280    // FIXME maybe rethink in 0.11?
3281    pub fn servername(&self, type_: NameType) -> Option<&str> {
3282        self.servername_raw(type_)
3283            .and_then(|b| str::from_utf8(b).ok())
3284    }
3285
3286    /// Returns the servername sent by the client via Server Name Indication (SNI).
3287    ///
3288    /// It is only useful on the server side.
3289    ///
3290    /// # Note
3291    ///
3292    /// Unlike `servername`, this method does not require the name be valid UTF-8.
3293    #[corresponds(SSL_get_servername)]
3294    pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3295        unsafe {
3296            let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3297            if name.is_null() {
3298                None
3299            } else {
3300                Some(CStr::from_ptr(name as *const _).to_bytes())
3301            }
3302        }
3303    }
3304
3305    /// Changes the context corresponding to the current connection.
3306    ///
3307    /// It is most commonly used in the Server Name Indication (SNI) callback.
3308    #[corresponds(SSL_set_SSL_CTX)]
3309    pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3310        unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3311    }
3312
3313    /// Returns the context corresponding to the current connection.
3314    #[corresponds(SSL_get_SSL_CTX)]
3315    pub fn ssl_context(&self) -> &SslContextRef {
3316        unsafe {
3317            let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3318            SslContextRef::from_ptr(ssl_ctx)
3319        }
3320    }
3321
3322    /// Returns a mutable reference to the X509 verification configuration.
3323    ///
3324    /// Requires AWS-LC or BoringSSL or OpenSSL 1.0.2 or newer.
3325    #[corresponds(SSL_get0_param)]
3326    #[cfg(any(ossl102, boringssl, libressl261, awslc))]
3327    pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3328        unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3329    }
3330
3331    /// Returns the certificate verification result.
3332    #[corresponds(SSL_get_verify_result)]
3333    pub fn verify_result(&self) -> X509VerifyResult {
3334        unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3335    }
3336
3337    /// Returns a shared reference to the SSL session.
3338    #[corresponds(SSL_get_session)]
3339    pub fn session(&self) -> Option<&SslSessionRef> {
3340        unsafe {
3341            let p = ffi::SSL_get_session(self.as_ptr());
3342            SslSessionRef::from_const_ptr_opt(p)
3343        }
3344    }
3345
3346    /// Copies the `client_random` value sent by the client in the TLS handshake into a buffer.
3347    ///
3348    /// Returns the number of bytes copied, or if the buffer is empty, the size of the `client_random`
3349    /// value.
3350    ///
3351    /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.
3352    #[corresponds(SSL_get_client_random)]
3353    #[cfg(any(ossl110, libressl270))]
3354    pub fn client_random(&self, buf: &mut [u8]) -> usize {
3355        unsafe {
3356            ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3357        }
3358    }
3359
3360    /// Copies the `server_random` value sent by the server in the TLS handshake into a buffer.
3361    ///
3362    /// Returns the number of bytes copied, or if the buffer is empty, the size of the `server_random`
3363    /// value.
3364    ///
3365    /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer.
3366    #[corresponds(SSL_get_server_random)]
3367    #[cfg(any(ossl110, libressl270))]
3368    pub fn server_random(&self, buf: &mut [u8]) -> usize {
3369        unsafe {
3370            ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3371        }
3372    }
3373
3374    /// Derives keying material for application use in accordance to RFC 5705.
3375    #[corresponds(SSL_export_keying_material)]
3376    pub fn export_keying_material(
3377        &self,
3378        out: &mut [u8],
3379        label: &str,
3380        context: Option<&[u8]>,
3381    ) -> Result<(), ErrorStack> {
3382        unsafe {
3383            let (context, contextlen, use_context) = match context {
3384                Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3385                None => (ptr::null(), 0, 0),
3386            };
3387            cvt(ffi::SSL_export_keying_material(
3388                self.as_ptr(),
3389                out.as_mut_ptr() as *mut c_uchar,
3390                out.len(),
3391                label.as_ptr() as *const c_char,
3392                label.len(),
3393                context,
3394                contextlen,
3395                use_context,
3396            ))
3397            .map(|_| ())
3398        }
3399    }
3400
3401    /// Derives keying material for application use in accordance to RFC 5705.
3402    ///
3403    /// This function is only usable with TLSv1.3, wherein there is no distinction between an empty context and no
3404    /// context. Therefore, unlike `export_keying_material`, `context` must always be supplied.
3405    ///
3406    /// Requires OpenSSL 1.1.1 or newer.
3407    #[corresponds(SSL_export_keying_material_early)]
3408    #[cfg(ossl111)]
3409    pub fn export_keying_material_early(
3410        &self,
3411        out: &mut [u8],
3412        label: &str,
3413        context: &[u8],
3414    ) -> Result<(), ErrorStack> {
3415        unsafe {
3416            cvt(ffi::SSL_export_keying_material_early(
3417                self.as_ptr(),
3418                out.as_mut_ptr() as *mut c_uchar,
3419                out.len(),
3420                label.as_ptr() as *const c_char,
3421                label.len(),
3422                context.as_ptr() as *const c_uchar,
3423                context.len(),
3424            ))
3425            .map(|_| ())
3426        }
3427    }
3428
3429    /// Sets the session to be used.
3430    ///
3431    /// This should be called before the handshake to attempt to reuse a previously established
3432    /// session. If the server is not willing to reuse the session, a new one will be transparently
3433    /// negotiated.
3434    ///
3435    /// # Safety
3436    ///
3437    /// The caller of this method is responsible for ensuring that the session is associated
3438    /// with the same `SslContext` as this `Ssl`.
3439    #[corresponds(SSL_set_session)]
3440    pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3441        cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3442    }
3443
3444    /// Determines if the session provided to `set_session` was successfully reused.
3445    #[corresponds(SSL_session_reused)]
3446    pub fn session_reused(&self) -> bool {
3447        unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3448    }
3449
3450    /// Causes ssl (which must be the client end of a connection) to request a stapled OCSP response from the server
3451    ///
3452    /// This corresponds to [`SSL_enable_ocsp_stapling`].
3453    ///
3454    /// [`SSL_enable_ocsp_stapling`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_enable_ocsp_stapling
3455    ///
3456    /// Requires BoringSSL.
3457    #[cfg(any(boringssl, awslc))]
3458    pub fn enable_ocsp_stapling(&mut self) {
3459        unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3460    }
3461
3462    /// Causes ssl (which must be the client end of a connection) to request SCTs from the server
3463    ///
3464    /// This corresponds to [`SSL_enable_signed_cert_timestamps`].
3465    ///
3466    /// [`SSL_enable_signed_cert_timestamps`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_enable_signed_cert_timestamps
3467    ///
3468    /// Requires BoringSSL.
3469    #[cfg(any(boringssl, awslc))]
3470    pub fn enable_signed_cert_timestamps(&mut self) {
3471        unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3472    }
3473
3474    /// Configures whether sockets on ssl should permute extensions.
3475    ///
3476    /// This corresponds to [`SSL_set_permute_extensions`].
3477    ///
3478    /// [`SSL_set_permute_extensions`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_set_permute_extensions
3479    ///
3480    /// Requires BoringSSL.
3481    #[cfg(any(boringssl, awslc))]
3482    pub fn set_permute_extensions(&mut self, enabled: bool) {
3483        unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3484    }
3485
3486    /// Enable the processing of signed certificate timestamps (SCTs) for the given SSL connection.
3487    #[corresponds(SSL_enable_ct)]
3488    #[cfg(ossl111)]
3489    pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3490        unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3491    }
3492
3493    /// Check whether CT processing is enabled.
3494    #[corresponds(SSL_ct_is_enabled)]
3495    #[cfg(ossl111)]
3496    pub fn ct_is_enabled(&self) -> bool {
3497        unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3498    }
3499
3500    /// Sets the status response a client wishes the server to reply with.
3501    #[corresponds(SSL_set_tlsext_status_type)]
3502    pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3503        unsafe {
3504            cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3505        }
3506    }
3507
3508    /// Determines if current session used Extended Master Secret
3509    ///
3510    /// Returns `None` if the handshake is still in-progress.
3511    #[corresponds(SSL_get_extms_support)]
3512    #[cfg(ossl110)]
3513    pub fn extms_support(&self) -> Option<bool> {
3514        unsafe {
3515            match ffi::SSL_get_extms_support(self.as_ptr()) {
3516                -1 => None,
3517                ret => Some(ret != 0),
3518            }
3519        }
3520    }
3521
3522    /// Returns the server's OCSP response, if present.
3523    #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3524    #[cfg(not(any(boringssl, awslc)))]
3525    pub fn ocsp_status(&self) -> Option<&[u8]> {
3526        unsafe {
3527            let mut p = ptr::null_mut();
3528            let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3529
3530            if len < 0 {
3531                None
3532            } else {
3533                Some(util::from_raw_parts(p as *const u8, len as usize))
3534            }
3535        }
3536    }
3537
3538    /// Returns the server's OCSP response, if present.
3539    #[corresponds(SSL_get0_ocsp_response)]
3540    #[cfg(any(boringssl, awslc))]
3541    pub fn ocsp_status(&self) -> Option<&[u8]> {
3542        unsafe {
3543            let mut p = ptr::null();
3544            let mut len: usize = 0;
3545            ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3546
3547            if len == 0 {
3548                None
3549            } else {
3550                Some(util::from_raw_parts(p as *const u8, len))
3551            }
3552        }
3553    }
3554
3555    /// Sets the OCSP response to be returned to the client.
3556    #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3557    #[cfg(not(any(boringssl, awslc)))]
3558    pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3559        unsafe {
3560            assert!(response.len() <= c_int::MAX as usize);
3561            let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3562            ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3563            cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3564                self.as_ptr(),
3565                p as *mut c_uchar,
3566                response.len() as c_long,
3567            ) as c_int)
3568            .map(|_| ())
3569            .map_err(|e| {
3570                ffi::OPENSSL_free(p);
3571                e
3572            })
3573        }
3574    }
3575
3576    /// Sets the OCSP response to be returned to the client.
3577    #[corresponds(SSL_set_ocsp_response)]
3578    #[cfg(any(boringssl, awslc))]
3579    pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3580        unsafe {
3581            cvt(ffi::SSL_set_ocsp_response(
3582                self.as_ptr(),
3583                response.as_ptr(),
3584                response.len(),
3585            ))
3586            .map(|_| ())
3587        }
3588    }
3589
3590    /// Determines if this `Ssl` is configured for server-side or client-side use.
3591    #[corresponds(SSL_is_server)]
3592    pub fn is_server(&self) -> bool {
3593        unsafe { SSL_is_server(self.as_ptr()) != 0 }
3594    }
3595
3596    /// Sets the extra data at the specified index.
3597    ///
3598    /// This can be used to provide data to callbacks registered with the context. Use the
3599    /// `Ssl::new_ex_index` method to create an `Index`.
3600    // FIXME should return a result
3601    #[corresponds(SSL_set_ex_data)]
3602    pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3603        match self.ex_data_mut(index) {
3604            Some(v) => *v = data,
3605            None => unsafe {
3606                let data = Box::new(data);
3607                ffi::SSL_set_ex_data(
3608                    self.as_ptr(),
3609                    index.as_raw(),
3610                    Box::into_raw(data) as *mut c_void,
3611                );
3612            },
3613        }
3614    }
3615
3616    /// Returns a reference to the extra data at the specified index.
3617    #[corresponds(SSL_get_ex_data)]
3618    pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3619        unsafe {
3620            let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3621            if data.is_null() {
3622                None
3623            } else {
3624                Some(&*(data as *const T))
3625            }
3626        }
3627    }
3628
3629    /// Returns a mutable reference to the extra data at the specified index.
3630    #[corresponds(SSL_get_ex_data)]
3631    pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3632        unsafe {
3633            let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3634            if data.is_null() {
3635                None
3636            } else {
3637                Some(&mut *(data as *mut T))
3638            }
3639        }
3640    }
3641
3642    /// Sets the maximum amount of early data that will be accepted on this connection.
3643    ///
3644    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
3645    #[corresponds(SSL_set_max_early_data)]
3646    #[cfg(any(ossl111, libressl340))]
3647    pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3648        if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3649            Ok(())
3650        } else {
3651            Err(ErrorStack::get())
3652        }
3653    }
3654
3655    /// Gets the maximum amount of early data that can be sent on this connection.
3656    ///
3657    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
3658    #[corresponds(SSL_get_max_early_data)]
3659    #[cfg(any(ossl111, libressl340))]
3660    pub fn max_early_data(&self) -> u32 {
3661        unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3662    }
3663
3664    /// Copies the contents of the last Finished message sent to the peer into the provided buffer.
3665    ///
3666    /// The total size of the message is returned, so this can be used to determine the size of the
3667    /// buffer required.
3668    #[corresponds(SSL_get_finished)]
3669    pub fn finished(&self, buf: &mut [u8]) -> usize {
3670        unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3671    }
3672
3673    /// Copies the contents of the last Finished message received from the peer into the provided
3674    /// buffer.
3675    ///
3676    /// The total size of the message is returned, so this can be used to determine the size of the
3677    /// buffer required.
3678    #[corresponds(SSL_get_peer_finished)]
3679    pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3680        unsafe {
3681            ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3682        }
3683    }
3684
3685    /// Determines if the initial handshake has been completed.
3686    #[corresponds(SSL_is_init_finished)]
3687    #[cfg(ossl110)]
3688    pub fn is_init_finished(&self) -> bool {
3689        unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3690    }
3691
3692    /// Determines if the client's hello message is in the SSLv2 format.
3693    ///
3694    /// This can only be used inside of the client hello callback. Otherwise, `false` is returned.
3695    ///
3696    /// Requires OpenSSL 1.1.1 or newer.
3697    #[corresponds(SSL_client_hello_isv2)]
3698    #[cfg(ossl111)]
3699    pub fn client_hello_isv2(&self) -> bool {
3700        unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3701    }
3702
3703    /// Returns the legacy version field of the client's hello message.
3704    ///
3705    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3706    ///
3707    /// Requires OpenSSL 1.1.1 or newer.
3708    #[corresponds(SSL_client_hello_get0_legacy_version)]
3709    #[cfg(ossl111)]
3710    pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3711        unsafe {
3712            let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3713            if version == 0 {
3714                None
3715            } else {
3716                Some(SslVersion(version as c_int))
3717            }
3718        }
3719    }
3720
3721    /// Returns the random field of the client's hello message.
3722    ///
3723    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3724    ///
3725    /// Requires OpenSSL 1.1.1 or newer.
3726    #[corresponds(SSL_client_hello_get0_random)]
3727    #[cfg(ossl111)]
3728    pub fn client_hello_random(&self) -> Option<&[u8]> {
3729        unsafe {
3730            let mut ptr = ptr::null();
3731            let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3732            if len == 0 {
3733                None
3734            } else {
3735                Some(util::from_raw_parts(ptr, len))
3736            }
3737        }
3738    }
3739
3740    /// Returns the session ID field of the client's hello message.
3741    ///
3742    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3743    ///
3744    /// Requires OpenSSL 1.1.1 or newer.
3745    #[corresponds(SSL_client_hello_get0_session_id)]
3746    #[cfg(ossl111)]
3747    pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3748        unsafe {
3749            let mut ptr = ptr::null();
3750            let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3751            if len == 0 {
3752                None
3753            } else {
3754                Some(util::from_raw_parts(ptr, len))
3755            }
3756        }
3757    }
3758
3759    /// Returns the ciphers field of the client's hello message.
3760    ///
3761    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3762    ///
3763    /// Requires OpenSSL 1.1.1 or newer.
3764    #[corresponds(SSL_client_hello_get0_ciphers)]
3765    #[cfg(ossl111)]
3766    pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3767        unsafe {
3768            let mut ptr = ptr::null();
3769            let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3770            if len == 0 {
3771                None
3772            } else {
3773                Some(util::from_raw_parts(ptr, len))
3774            }
3775        }
3776    }
3777
3778    /// Provides access to individual extensions from the ClientHello on a per-extension basis.
3779    ///
3780    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3781    ///
3782    /// Requires OpenSSL 1.1.1 or newer.
3783    #[cfg(ossl111)]
3784    pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3785        unsafe {
3786            let mut ptr = ptr::null();
3787            let mut len = 0usize;
3788            let r = ffi::SSL_client_hello_get0_ext(
3789                self.as_ptr(),
3790                ext_type.as_raw() as _,
3791                &mut ptr,
3792                &mut len,
3793            );
3794            if r == 0 {
3795                None
3796            } else {
3797                Some(util::from_raw_parts(ptr, len))
3798            }
3799        }
3800    }
3801
3802    /// Decodes a slice of wire-format cipher suite specification bytes. Unsupported cipher suites
3803    /// are ignored.
3804    ///
3805    /// Requires OpenSSL 1.1.1 or newer.
3806    #[corresponds(SSL_bytes_to_cipher_list)]
3807    #[cfg(ossl111)]
3808    pub fn bytes_to_cipher_list(
3809        &self,
3810        bytes: &[u8],
3811        isv2format: bool,
3812    ) -> Result<CipherLists, ErrorStack> {
3813        unsafe {
3814            let ptr = bytes.as_ptr();
3815            let len = bytes.len();
3816            let mut sk = ptr::null_mut();
3817            let mut scsvs = ptr::null_mut();
3818            let res = ffi::SSL_bytes_to_cipher_list(
3819                self.as_ptr(),
3820                ptr,
3821                len,
3822                isv2format as c_int,
3823                &mut sk,
3824                &mut scsvs,
3825            );
3826            if res == 1 {
3827                Ok(CipherLists {
3828                    suites: Stack::from_ptr(sk),
3829                    signalling_suites: Stack::from_ptr(scsvs),
3830                })
3831            } else {
3832                Err(ErrorStack::get())
3833            }
3834        }
3835    }
3836
3837    /// Returns the compression methods field of the client's hello message.
3838    ///
3839    /// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
3840    ///
3841    /// Requires OpenSSL 1.1.1 or newer.
3842    #[corresponds(SSL_client_hello_get0_compression_methods)]
3843    #[cfg(ossl111)]
3844    pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3845        unsafe {
3846            let mut ptr = ptr::null();
3847            let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3848            if len == 0 {
3849                None
3850            } else {
3851                Some(util::from_raw_parts(ptr, len))
3852            }
3853        }
3854    }
3855
3856    /// Sets the MTU used for DTLS connections.
3857    #[corresponds(SSL_set_mtu)]
3858    pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3859        unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3860    }
3861
3862    /// Returns the PSK identity hint used during connection setup.
3863    ///
3864    /// May return `None` if no PSK identity hint was used during the connection setup.
3865    #[corresponds(SSL_get_psk_identity_hint)]
3866    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3867    pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3868        unsafe {
3869            let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3870            if ptr.is_null() {
3871                None
3872            } else {
3873                Some(CStr::from_ptr(ptr).to_bytes())
3874            }
3875        }
3876    }
3877
3878    /// Returns the PSK identity used during connection setup.
3879    #[corresponds(SSL_get_psk_identity)]
3880    #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3881    pub fn psk_identity(&self) -> Option<&[u8]> {
3882        unsafe {
3883            let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3884            if ptr.is_null() {
3885                None
3886            } else {
3887                Some(CStr::from_ptr(ptr).to_bytes())
3888            }
3889        }
3890    }
3891
3892    #[corresponds(SSL_add0_chain_cert)]
3893    #[cfg(any(ossl102, boringssl, awslc))]
3894    pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3895        unsafe {
3896            cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3897            mem::forget(chain);
3898        }
3899        Ok(())
3900    }
3901
3902    /// Sets a new default TLS/SSL method for SSL objects
3903    #[cfg(not(any(boringssl, awslc)))]
3904    pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3905        unsafe {
3906            cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3907        };
3908        Ok(())
3909    }
3910
3911    /// Loads the private key from a file.
3912    #[corresponds(SSL_use_Private_Key_file)]
3913    pub fn set_private_key_file<P: AsRef<Path>>(
3914        &mut self,
3915        path: P,
3916        ssl_file_type: SslFiletype,
3917    ) -> Result<(), ErrorStack> {
3918        let p = path.as_ref().as_os_str().to_str().unwrap();
3919        let key_file = CString::new(p).unwrap();
3920        unsafe {
3921            cvt(ffi::SSL_use_PrivateKey_file(
3922                self.as_ptr(),
3923                key_file.as_ptr(),
3924                ssl_file_type.as_raw(),
3925            ))?;
3926        };
3927        Ok(())
3928    }
3929
3930    /// Sets the private key.
3931    #[corresponds(SSL_use_PrivateKey)]
3932    pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3933        unsafe {
3934            cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3935        };
3936        Ok(())
3937    }
3938
3939    #[cfg(tongsuo)]
3940    #[corresponds(SSL_use_enc_Private_Key_file)]
3941    pub fn set_enc_private_key_file<P: AsRef<Path>>(
3942        &mut self,
3943        path: P,
3944        ssl_file_type: SslFiletype,
3945    ) -> Result<(), ErrorStack> {
3946        let p = path.as_ref().as_os_str().to_str().unwrap();
3947        let key_file = CString::new(p).unwrap();
3948        unsafe {
3949            cvt(ffi::SSL_use_enc_PrivateKey_file(
3950                self.as_ptr(),
3951                key_file.as_ptr(),
3952                ssl_file_type.as_raw(),
3953            ))?;
3954        };
3955        Ok(())
3956    }
3957
3958    #[cfg(tongsuo)]
3959    #[corresponds(SSL_use_enc_PrivateKey)]
3960    pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3961        unsafe {
3962            cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3963        };
3964        Ok(())
3965    }
3966
3967    #[cfg(tongsuo)]
3968    #[corresponds(SSL_use_sign_Private_Key_file)]
3969    pub fn set_sign_private_key_file<P: AsRef<Path>>(
3970        &mut self,
3971        path: P,
3972        ssl_file_type: SslFiletype,
3973    ) -> Result<(), ErrorStack> {
3974        let p = path.as_ref().as_os_str().to_str().unwrap();
3975        let key_file = CString::new(p).unwrap();
3976        unsafe {
3977            cvt(ffi::SSL_use_sign_PrivateKey_file(
3978                self.as_ptr(),
3979                key_file.as_ptr(),
3980                ssl_file_type.as_raw(),
3981            ))?;
3982        };
3983        Ok(())
3984    }
3985
3986    #[cfg(tongsuo)]
3987    #[corresponds(SSL_use_sign_PrivateKey)]
3988    pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3989        unsafe {
3990            cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3991        };
3992        Ok(())
3993    }
3994
3995    /// Sets the certificate
3996    #[corresponds(SSL_use_certificate)]
3997    pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3998        unsafe {
3999            cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4000        };
4001        Ok(())
4002    }
4003
4004    #[cfg(tongsuo)]
4005    #[corresponds(SSL_use_enc_certificate)]
4006    pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4007        unsafe {
4008            cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4009        };
4010        Ok(())
4011    }
4012
4013    #[cfg(tongsuo)]
4014    #[corresponds(SSL_use_sign_certificate)]
4015    pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4016        unsafe {
4017            cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4018        };
4019        Ok(())
4020    }
4021
4022    /// Loads a certificate chain from a file.
4023    ///
4024    /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf
4025    /// certificate, and the remainder forming the chain of certificates up to and including the
4026    /// trusted root certificate.
4027    #[corresponds(SSL_use_certificate_chain_file)]
4028    #[cfg(any(ossl110, libressl332))]
4029    pub fn set_certificate_chain_file<P: AsRef<Path>>(
4030        &mut self,
4031        path: P,
4032    ) -> Result<(), ErrorStack> {
4033        let p = path.as_ref().as_os_str().to_str().unwrap();
4034        let cert_file = CString::new(p).unwrap();
4035        unsafe {
4036            cvt(ffi::SSL_use_certificate_chain_file(
4037                self.as_ptr(),
4038                cert_file.as_ptr(),
4039            ))?;
4040        };
4041        Ok(())
4042    }
4043
4044    /// Sets ca certificate that client trusted
4045    #[corresponds(SSL_add_client_CA)]
4046    pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4047        unsafe {
4048            cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4049        };
4050        Ok(())
4051    }
4052
4053    // Sets the list of CAs sent to the client when requesting a client certificate for the chosen ssl
4054    #[corresponds(SSL_set_client_CA_list)]
4055    pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4056        unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4057        mem::forget(list);
4058    }
4059
4060    /// Sets the minimum supported protocol version.
4061    ///
4062    /// A value of `None` will enable protocol versions down to the lowest version supported by
4063    /// OpenSSL.
4064    ///
4065    /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.
4066    #[corresponds(SSL_set_min_proto_version)]
4067    #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4068    pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4069        unsafe {
4070            cvt(ffi::SSL_set_min_proto_version(
4071                self.as_ptr(),
4072                version.map_or(0, |v| v.0 as _),
4073            ))
4074            .map(|_| ())
4075        }
4076    }
4077
4078    /// Sets the maximum supported protocol version.
4079    ///
4080    /// A value of `None` will enable protocol versions up to the highest version supported by
4081    /// OpenSSL.
4082    ///
4083    /// Requires AWS-LC or BoringSSL or OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.
4084    #[corresponds(SSL_set_max_proto_version)]
4085    #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4086    pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4087        unsafe {
4088            cvt(ffi::SSL_set_max_proto_version(
4089                self.as_ptr(),
4090                version.map_or(0, |v| v.0 as _),
4091            ))
4092            .map(|_| ())
4093        }
4094    }
4095
4096    /// Sets the list of supported ciphers for the TLSv1.3 protocol.
4097    ///
4098    /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3.
4099    ///
4100    /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of
4101    /// preference.
4102    ///
4103    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
4104    #[corresponds(SSL_set_ciphersuites)]
4105    #[cfg(any(ossl111, libressl340))]
4106    pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4107        let cipher_list = CString::new(cipher_list).unwrap();
4108        unsafe {
4109            cvt(ffi::SSL_set_ciphersuites(
4110                self.as_ptr(),
4111                cipher_list.as_ptr() as *const _,
4112            ))
4113            .map(|_| ())
4114        }
4115    }
4116
4117    /// Sets the list of supported ciphers for protocols before TLSv1.3.
4118    ///
4119    /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3.
4120    ///
4121    /// See [`ciphers`] for details on the format.
4122    ///
4123    /// [`ciphers`]: https://www.openssl.org/docs/manmaster/apps/ciphers.html
4124    #[corresponds(SSL_set_cipher_list)]
4125    pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4126        let cipher_list = CString::new(cipher_list).unwrap();
4127        unsafe {
4128            cvt(ffi::SSL_set_cipher_list(
4129                self.as_ptr(),
4130                cipher_list.as_ptr() as *const _,
4131            ))
4132            .map(|_| ())
4133        }
4134    }
4135
4136    /// Set the certificate store used for certificate verification
4137    #[corresponds(SSL_set_cert_store)]
4138    #[cfg(any(ossl102, boringssl, awslc))]
4139    pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4140        unsafe {
4141            cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4142            mem::forget(cert_store);
4143            Ok(())
4144        }
4145    }
4146
4147    /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full
4148    /// handshake.
4149    ///
4150    /// Requires OpenSSL 1.1.1 or newer.
4151    #[corresponds(SSL_set_num_tickets)]
4152    #[cfg(ossl111)]
4153    pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4154        unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4155    }
4156
4157    /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full
4158    /// handshake.
4159    ///
4160    /// Requires OpenSSL 1.1.1 or newer.
4161    #[corresponds(SSL_get_num_tickets)]
4162    #[cfg(ossl111)]
4163    pub fn num_tickets(&self) -> usize {
4164        unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4165    }
4166
4167    /// Set the context's security level to a value between 0 and 5, inclusive.
4168    /// A security value of 0 allows allows all parameters and algorithms.
4169    ///
4170    /// Requires OpenSSL 1.1.0 or newer.
4171    #[corresponds(SSL_set_security_level)]
4172    #[cfg(any(ossl110, libressl360))]
4173    pub fn set_security_level(&mut self, level: u32) {
4174        unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4175    }
4176
4177    /// Get the connection's security level, which controls the allowed parameters
4178    /// and algorithms.
4179    ///
4180    /// Requires OpenSSL 1.1.0 or newer.
4181    #[corresponds(SSL_get_security_level)]
4182    #[cfg(any(ossl110, libressl360))]
4183    pub fn security_level(&self) -> u32 {
4184        unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4185    }
4186
4187    /// Get the temporary key provided by the peer that is used during key
4188    /// exchange.
4189    // We use an owned value because EVP_KEY free need to be called when it is
4190    // dropped
4191    #[corresponds(SSL_get_peer_tmp_key)]
4192    #[cfg(ossl300)]
4193    pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4194        unsafe {
4195            let mut key = ptr::null_mut();
4196            match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4197                Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4198                Err(e) => Err(e),
4199            }
4200        }
4201    }
4202
4203    /// Returns the temporary key from the local end of the connection that is
4204    /// used during key exchange.
4205    // We use an owned value because EVP_KEY free need to be called when it is
4206    // dropped
4207    #[corresponds(SSL_get_tmp_key)]
4208    #[cfg(ossl300)]
4209    pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4210        unsafe {
4211            let mut key = ptr::null_mut();
4212            match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4213                Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4214                Err(e) => Err(e),
4215            }
4216        }
4217    }
4218}
4219
4220/// An SSL stream midway through the handshake process.
4221#[derive(Debug)]
4222pub struct MidHandshakeSslStream<S> {
4223    stream: SslStream<S>,
4224    error: Error,
4225}
4226
4227impl<S> MidHandshakeSslStream<S> {
4228    /// Returns a shared reference to the inner stream.
4229    pub fn get_ref(&self) -> &S {
4230        self.stream.get_ref()
4231    }
4232
4233    /// Returns a mutable reference to the inner stream.
4234    pub fn get_mut(&mut self) -> &mut S {
4235        self.stream.get_mut()
4236    }
4237
4238    /// Returns a shared reference to the `Ssl` of the stream.
4239    pub fn ssl(&self) -> &SslRef {
4240        self.stream.ssl()
4241    }
4242
4243    /// Returns a mutable reference to the `Ssl` of the stream.
4244    pub fn ssl_mut(&mut self) -> &mut SslRef {
4245        self.stream.ssl_mut()
4246    }
4247
4248    /// Returns the underlying error which interrupted this handshake.
4249    pub fn error(&self) -> &Error {
4250        &self.error
4251    }
4252
4253    /// Consumes `self`, returning its error.
4254    pub fn into_error(self) -> Error {
4255        self.error
4256    }
4257}
4258
4259impl<S> MidHandshakeSslStream<S>
4260where
4261    S: Read + Write,
4262{
4263    /// Restarts the handshake process.
4264    ///
4265    #[corresponds(SSL_do_handshake)]
4266    pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4267        match self.stream.do_handshake() {
4268            Ok(()) => Ok(self.stream),
4269            Err(error) => {
4270                self.error = error;
4271                match self.error.code() {
4272                    ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4273                        Err(HandshakeError::WouldBlock(self))
4274                    }
4275                    _ => Err(HandshakeError::Failure(self)),
4276                }
4277            }
4278        }
4279    }
4280}
4281
4282/// A TLS session over a stream.
4283pub struct SslStream<S> {
4284    ssl: ManuallyDrop<Ssl>,
4285    method: ManuallyDrop<BioMethod>,
4286    _p: PhantomData<S>,
4287}
4288
4289impl<S> Drop for SslStream<S> {
4290    fn drop(&mut self) {
4291        // ssl holds a reference to method internally so it has to drop first
4292        unsafe {
4293            ManuallyDrop::drop(&mut self.ssl);
4294            ManuallyDrop::drop(&mut self.method);
4295        }
4296    }
4297}
4298
4299impl<S> fmt::Debug for SslStream<S>
4300where
4301    S: fmt::Debug,
4302{
4303    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4304        fmt.debug_struct("SslStream")
4305            .field("stream", &self.get_ref())
4306            .field("ssl", &self.ssl())
4307            .finish()
4308    }
4309}
4310
4311impl<S: Read + Write> SslStream<S> {
4312    /// Creates a new `SslStream`.
4313    ///
4314    /// This function performs no IO; the stream will not have performed any part of the handshake
4315    /// with the peer. If the `Ssl` was configured with [`SslRef::set_connect_state`] or
4316    /// [`SslRef::set_accept_state`], the handshake can be performed automatically during the first
4317    /// call to read or write. Otherwise the `connect` and `accept` methods can be used to
4318    /// explicitly perform the handshake.
4319    #[corresponds(SSL_set_bio)]
4320    pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4321        let (bio, method) = bio::new(stream)?;
4322        unsafe {
4323            ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4324        }
4325
4326        Ok(SslStream {
4327            ssl: ManuallyDrop::new(ssl),
4328            method: ManuallyDrop::new(method),
4329            _p: PhantomData,
4330        })
4331    }
4332
4333    /// Read application data transmitted by a client before handshake completion.
4334    ///
4335    /// Useful for reducing latency, but vulnerable to replay attacks. Call
4336    /// [`SslRef::set_accept_state`] first.
4337    ///
4338    /// Returns `Ok(0)` if all early data has been read.
4339    ///
4340    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
4341    #[corresponds(SSL_read_early_data)]
4342    #[cfg(any(ossl111, libressl340))]
4343    pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4344        let mut read = 0;
4345        let ret = unsafe {
4346            ffi::SSL_read_early_data(
4347                self.ssl.as_ptr(),
4348                buf.as_ptr() as *mut c_void,
4349                buf.len(),
4350                &mut read,
4351            )
4352        };
4353        match ret {
4354            ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4355            ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4356            ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4357            _ => unreachable!(),
4358        }
4359    }
4360
4361    /// Send data to the server without blocking on handshake completion.
4362    ///
4363    /// Useful for reducing latency, but vulnerable to replay attacks. Call
4364    /// [`SslRef::set_connect_state`] first.
4365    ///
4366    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
4367    #[corresponds(SSL_write_early_data)]
4368    #[cfg(any(ossl111, libressl340))]
4369    pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4370        let mut written = 0;
4371        let ret = unsafe {
4372            ffi::SSL_write_early_data(
4373                self.ssl.as_ptr(),
4374                buf.as_ptr() as *const c_void,
4375                buf.len(),
4376                &mut written,
4377            )
4378        };
4379        if ret > 0 {
4380            Ok(written)
4381        } else {
4382            Err(self.make_error(ret))
4383        }
4384    }
4385
4386    /// Initiates a client-side TLS handshake.
4387    ///
4388    /// # Warning
4389    ///
4390    /// OpenSSL's default configuration is insecure. It is highly recommended to use
4391    /// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
4392    #[corresponds(SSL_connect)]
4393    pub fn connect(&mut self) -> Result<(), Error> {
4394        let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4395        if ret > 0 {
4396            Ok(())
4397        } else {
4398            Err(self.make_error(ret))
4399        }
4400    }
4401
4402    /// Initiates a server-side TLS handshake.
4403    ///
4404    /// # Warning
4405    ///
4406    /// OpenSSL's default configuration is insecure. It is highly recommended to use
4407    /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
4408    #[corresponds(SSL_accept)]
4409    pub fn accept(&mut self) -> Result<(), Error> {
4410        let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4411        if ret > 0 {
4412            Ok(())
4413        } else {
4414            Err(self.make_error(ret))
4415        }
4416    }
4417
4418    /// Initiates the handshake.
4419    ///
4420    /// This will fail if `set_accept_state` or `set_connect_state` was not called first.
4421    #[corresponds(SSL_do_handshake)]
4422    pub fn do_handshake(&mut self) -> Result<(), Error> {
4423        let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4424        if ret > 0 {
4425            Ok(())
4426        } else {
4427            Err(self.make_error(ret))
4428        }
4429    }
4430
4431    /// Perform a stateless server-side handshake.
4432    ///
4433    /// Requires that cookie generation and verification callbacks were
4434    /// set on the SSL context.
4435    ///
4436    /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie
4437    /// was read, in which case the handshake should be continued via
4438    /// `accept`. If a HelloRetryRequest containing a fresh cookie was
4439    /// transmitted, `Ok(false)` is returned instead. If the handshake cannot
4440    /// proceed at all, `Err` is returned.
4441    #[corresponds(SSL_stateless)]
4442    #[cfg(ossl111)]
4443    pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4444        match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4445            1 => Ok(true),
4446            0 => Ok(false),
4447            -1 => Err(ErrorStack::get()),
4448            _ => unreachable!(),
4449        }
4450    }
4451
4452    /// Like `read`, but takes a possibly-uninitialized slice.
4453    ///
4454    /// # Safety
4455    ///
4456    /// No portion of `buf` will be de-initialized by this method. If the method returns `Ok(n)`,
4457    /// then the first `n` bytes of `buf` are guaranteed to be initialized.
4458    #[corresponds(SSL_read_ex)]
4459    pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4460        loop {
4461            match self.ssl_read_uninit(buf) {
4462                Ok(n) => return Ok(n),
4463                Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4464                Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4465                    return Ok(0);
4466                }
4467                Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4468                Err(e) => {
4469                    return Err(e
4470                        .into_io_error()
4471                        .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4472                }
4473            }
4474        }
4475    }
4476
4477    /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`.
4478    ///
4479    /// It is particularly useful with a non-blocking socket, where the error value will identify if
4480    /// OpenSSL is waiting on read or write readiness.
4481    #[corresponds(SSL_read_ex)]
4482    pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4483        // SAFETY: `ssl_read_uninit` does not de-initialize the buffer.
4484        unsafe {
4485            self.ssl_read_uninit(util::from_raw_parts_mut(
4486                buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4487                buf.len(),
4488            ))
4489        }
4490    }
4491
4492    /// Like `read_ssl`, but takes a possibly-uninitialized slice.
4493    ///
4494    /// # Safety
4495    ///
4496    /// No portion of `buf` will be de-initialized by this method. If the method returns `Ok(n)`,
4497    /// then the first `n` bytes of `buf` are guaranteed to be initialized.
4498    #[corresponds(SSL_read_ex)]
4499    pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4500        cfg_if! {
4501            if #[cfg(any(ossl111, libressl350))] {
4502                let mut readbytes = 0;
4503                let ret = unsafe {
4504                    ffi::SSL_read_ex(
4505                        self.ssl().as_ptr(),
4506                        buf.as_mut_ptr().cast(),
4507                        buf.len(),
4508                        &mut readbytes,
4509                    )
4510                };
4511
4512                if ret > 0 {
4513                    Ok(readbytes)
4514                } else {
4515                    Err(self.make_error(ret))
4516                }
4517            } else {
4518                if buf.is_empty() {
4519                    return Ok(0);
4520                }
4521
4522                let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4523                let ret = unsafe {
4524                    ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4525                };
4526                if ret > 0 {
4527                    Ok(ret as usize)
4528                } else {
4529                    Err(self.make_error(ret))
4530                }
4531            }
4532        }
4533    }
4534
4535    /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`.
4536    ///
4537    /// It is particularly useful with a non-blocking socket, where the error value will identify if
4538    /// OpenSSL is waiting on read or write readiness.
4539    #[corresponds(SSL_write_ex)]
4540    pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4541        cfg_if! {
4542            if #[cfg(any(ossl111, libressl350))] {
4543                let mut written = 0;
4544                let ret = unsafe {
4545                    ffi::SSL_write_ex(
4546                        self.ssl().as_ptr(),
4547                        buf.as_ptr().cast(),
4548                        buf.len(),
4549                        &mut written,
4550                    )
4551                };
4552
4553                if ret > 0 {
4554                    Ok(written)
4555                } else {
4556                    Err(self.make_error(ret))
4557                }
4558            } else {
4559                if buf.is_empty() {
4560                    return Ok(0);
4561                }
4562
4563                let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4564                let ret = unsafe {
4565                    ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4566                };
4567                if ret > 0 {
4568                    Ok(ret as usize)
4569                } else {
4570                    Err(self.make_error(ret))
4571                }
4572            }
4573        }
4574    }
4575
4576    /// Reads data from the stream, without removing it from the queue.
4577    #[corresponds(SSL_peek_ex)]
4578    pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4579        cfg_if! {
4580            if #[cfg(any(ossl111, libressl350))] {
4581                let mut readbytes = 0;
4582                let ret = unsafe {
4583                    ffi::SSL_peek_ex(
4584                        self.ssl().as_ptr(),
4585                        buf.as_mut_ptr().cast(),
4586                        buf.len(),
4587                        &mut readbytes,
4588                    )
4589                };
4590
4591                if ret > 0 {
4592                    Ok(readbytes)
4593                } else {
4594                    Err(self.make_error(ret))
4595                }
4596            } else {
4597                if buf.is_empty() {
4598                    return Ok(0);
4599                }
4600
4601                let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4602                let ret = unsafe {
4603                    ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4604                };
4605                if ret > 0 {
4606                    Ok(ret as usize)
4607                } else {
4608                    Err(self.make_error(ret))
4609                }
4610            }
4611        }
4612    }
4613
4614    /// Shuts down the session.
4615    ///
4616    /// The shutdown process consists of two steps. The first step sends a close notify message to
4617    /// the peer, after which `ShutdownResult::Sent` is returned. The second step awaits the receipt
4618    /// of a close notify message from the peer, after which `ShutdownResult::Received` is returned.
4619    ///
4620    /// While the connection may be closed after the first step, it is recommended to fully shut the
4621    /// session down. In particular, it must be fully shut down if the connection is to be used for
4622    /// further communication in the future.
4623    #[corresponds(SSL_shutdown)]
4624    pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4625        match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4626            0 => Ok(ShutdownResult::Sent),
4627            1 => Ok(ShutdownResult::Received),
4628            n => Err(self.make_error(n)),
4629        }
4630    }
4631
4632    /// Returns the session's shutdown state.
4633    #[corresponds(SSL_get_shutdown)]
4634    pub fn get_shutdown(&mut self) -> ShutdownState {
4635        unsafe {
4636            let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4637            ShutdownState::from_bits_retain(bits)
4638        }
4639    }
4640
4641    /// Sets the session's shutdown state.
4642    ///
4643    /// This can be used to tell OpenSSL that the session should be cached even if a full two-way
4644    /// shutdown was not completed.
4645    #[corresponds(SSL_set_shutdown)]
4646    pub fn set_shutdown(&mut self, state: ShutdownState) {
4647        unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4648    }
4649}
4650
4651impl<S> SslStream<S> {
4652    fn make_error(&mut self, ret: c_int) -> Error {
4653        self.check_panic();
4654
4655        let code = self.ssl.get_error(ret);
4656
4657        let cause = match code {
4658            ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4659            ErrorCode::SYSCALL => {
4660                let errs = ErrorStack::get();
4661                if errs.errors().is_empty() {
4662                    self.get_bio_error().map(InnerError::Io)
4663                } else {
4664                    Some(InnerError::Ssl(errs))
4665                }
4666            }
4667            ErrorCode::ZERO_RETURN => None,
4668            ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4669                self.get_bio_error().map(InnerError::Io)
4670            }
4671            _ => None,
4672        };
4673
4674        Error { code, cause }
4675    }
4676
4677    fn check_panic(&mut self) {
4678        if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4679            resume_unwind(err)
4680        }
4681    }
4682
4683    fn get_bio_error(&mut self) -> Option<io::Error> {
4684        unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4685    }
4686
4687    /// Returns a shared reference to the underlying stream.
4688    pub fn get_ref(&self) -> &S {
4689        unsafe {
4690            let bio = self.ssl.get_raw_rbio();
4691            bio::get_ref(bio)
4692        }
4693    }
4694
4695    /// Returns a mutable reference to the underlying stream.
4696    ///
4697    /// # Warning
4698    ///
4699    /// It is inadvisable to read from or write to the underlying stream as it
4700    /// will most likely corrupt the SSL session.
4701    pub fn get_mut(&mut self) -> &mut S {
4702        unsafe {
4703            let bio = self.ssl.get_raw_rbio();
4704            bio::get_mut(bio)
4705        }
4706    }
4707
4708    /// Returns a shared reference to the `Ssl` object associated with this stream.
4709    pub fn ssl(&self) -> &SslRef {
4710        &self.ssl
4711    }
4712
4713    /// Returns a mutable reference to the `Ssl` object associated with this stream.
4714    pub fn ssl_mut(&mut self) -> &mut SslRef {
4715        &mut self.ssl
4716    }
4717}
4718
4719impl<S: Read + Write> Read for SslStream<S> {
4720    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4721        // SAFETY: `read_uninit` does not de-initialize the buffer
4722        unsafe {
4723            self.read_uninit(util::from_raw_parts_mut(
4724                buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4725                buf.len(),
4726            ))
4727        }
4728    }
4729}
4730
4731impl<S: Read + Write> Write for SslStream<S> {
4732    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4733        loop {
4734            match self.ssl_write(buf) {
4735                Ok(n) => return Ok(n),
4736                Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4737                Err(e) => {
4738                    return Err(e
4739                        .into_io_error()
4740                        .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4741                }
4742            }
4743        }
4744    }
4745
4746    fn flush(&mut self) -> io::Result<()> {
4747        self.get_mut().flush()
4748    }
4749}
4750
4751/// A partially constructed `SslStream`, useful for unusual handshakes.
4752#[deprecated(
4753    since = "0.10.32",
4754    note = "use the methods directly on Ssl/SslStream instead"
4755)]
4756pub struct SslStreamBuilder<S> {
4757    inner: SslStream<S>,
4758}
4759
4760#[allow(deprecated)]
4761impl<S> SslStreamBuilder<S>
4762where
4763    S: Read + Write,
4764{
4765    /// Begin creating an `SslStream` atop `stream`
4766    pub fn new(ssl: Ssl, stream: S) -> Self {
4767        Self {
4768            inner: SslStream::new(ssl, stream).unwrap(),
4769        }
4770    }
4771
4772    /// Perform a stateless server-side handshake
4773    ///
4774    /// Requires that cookie generation and verification callbacks were
4775    /// set on the SSL context.
4776    ///
4777    /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie
4778    /// was read, in which case the handshake should be continued via
4779    /// `accept`. If a HelloRetryRequest containing a fresh cookie was
4780    /// transmitted, `Ok(false)` is returned instead. If the handshake cannot
4781    /// proceed at all, `Err` is returned.
4782    #[corresponds(SSL_stateless)]
4783    #[cfg(ossl111)]
4784    pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4785        match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4786            1 => Ok(true),
4787            0 => Ok(false),
4788            -1 => Err(ErrorStack::get()),
4789            _ => unreachable!(),
4790        }
4791    }
4792
4793    /// Configure as an outgoing stream from a client.
4794    #[corresponds(SSL_set_connect_state)]
4795    pub fn set_connect_state(&mut self) {
4796        unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4797    }
4798
4799    /// Configure as an incoming stream to a server.
4800    #[corresponds(SSL_set_accept_state)]
4801    pub fn set_accept_state(&mut self) {
4802        unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4803    }
4804
4805    /// See `Ssl::connect`
4806    pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4807        match self.inner.connect() {
4808            Ok(()) => Ok(self.inner),
4809            Err(error) => match error.code() {
4810                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4811                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4812                        stream: self.inner,
4813                        error,
4814                    }))
4815                }
4816                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4817                    stream: self.inner,
4818                    error,
4819                })),
4820            },
4821        }
4822    }
4823
4824    /// See `Ssl::accept`
4825    pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4826        match self.inner.accept() {
4827            Ok(()) => Ok(self.inner),
4828            Err(error) => match error.code() {
4829                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4830                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4831                        stream: self.inner,
4832                        error,
4833                    }))
4834                }
4835                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4836                    stream: self.inner,
4837                    error,
4838                })),
4839            },
4840        }
4841    }
4842
4843    /// Initiates the handshake.
4844    ///
4845    /// This will fail if `set_accept_state` or `set_connect_state` was not called first.
4846    #[corresponds(SSL_do_handshake)]
4847    pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4848        match self.inner.do_handshake() {
4849            Ok(()) => Ok(self.inner),
4850            Err(error) => match error.code() {
4851                ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4852                    Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4853                        stream: self.inner,
4854                        error,
4855                    }))
4856                }
4857                _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4858                    stream: self.inner,
4859                    error,
4860                })),
4861            },
4862        }
4863    }
4864
4865    /// Read application data transmitted by a client before handshake
4866    /// completion.
4867    ///
4868    /// Useful for reducing latency, but vulnerable to replay attacks. Call
4869    /// `set_accept_state` first.
4870    ///
4871    /// Returns `Ok(0)` if all early data has been read.
4872    ///
4873    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
4874    #[corresponds(SSL_read_early_data)]
4875    #[cfg(any(ossl111, libressl340))]
4876    pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4877        self.inner.read_early_data(buf)
4878    }
4879
4880    /// Send data to the server without blocking on handshake completion.
4881    ///
4882    /// Useful for reducing latency, but vulnerable to replay attacks. Call
4883    /// `set_connect_state` first.
4884    ///
4885    /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
4886    #[corresponds(SSL_write_early_data)]
4887    #[cfg(any(ossl111, libressl340))]
4888    pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4889        self.inner.write_early_data(buf)
4890    }
4891}
4892
4893#[allow(deprecated)]
4894impl<S> SslStreamBuilder<S> {
4895    /// Returns a shared reference to the underlying stream.
4896    pub fn get_ref(&self) -> &S {
4897        unsafe {
4898            let bio = self.inner.ssl.get_raw_rbio();
4899            bio::get_ref(bio)
4900        }
4901    }
4902
4903    /// Returns a mutable reference to the underlying stream.
4904    ///
4905    /// # Warning
4906    ///
4907    /// It is inadvisable to read from or write to the underlying stream as it
4908    /// will most likely corrupt the SSL session.
4909    pub fn get_mut(&mut self) -> &mut S {
4910        unsafe {
4911            let bio = self.inner.ssl.get_raw_rbio();
4912            bio::get_mut(bio)
4913        }
4914    }
4915
4916    /// Returns a shared reference to the `Ssl` object associated with this builder.
4917    pub fn ssl(&self) -> &SslRef {
4918        &self.inner.ssl
4919    }
4920
4921    /// Returns a mutable reference to the `Ssl` object associated with this builder.
4922    pub fn ssl_mut(&mut self) -> &mut SslRef {
4923        &mut self.inner.ssl
4924    }
4925}
4926
4927/// The result of a shutdown request.
4928#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4929pub enum ShutdownResult {
4930    /// A close notify message has been sent to the peer.
4931    Sent,
4932
4933    /// A close notify response message has been received from the peer.
4934    Received,
4935}
4936
4937bitflags! {
4938    /// The shutdown state of a session.
4939    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4940    #[repr(transparent)]
4941    pub struct ShutdownState: c_int {
4942        /// A close notify message has been sent to the peer.
4943        const SENT = ffi::SSL_SENT_SHUTDOWN;
4944        /// A close notify message has been received from the peer.
4945        const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4946    }
4947}
4948
4949cfg_if! {
4950    if #[cfg(any(boringssl, ossl110, libressl273, awslc))] {
4951        use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4952    } else {
4953        #[allow(bad_style)]
4954        pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4955            ffi::CRYPTO_add_lock(
4956                &mut (*ssl).references,
4957                1,
4958                ffi::CRYPTO_LOCK_SSL_CTX,
4959                "mod.rs\0".as_ptr() as *const _,
4960                line!() as c_int,
4961            );
4962            0
4963        }
4964
4965        #[allow(bad_style)]
4966        pub unsafe fn SSL_SESSION_get_master_key(
4967            session: *const ffi::SSL_SESSION,
4968            out: *mut c_uchar,
4969            mut outlen: usize,
4970        ) -> usize {
4971            if outlen == 0 {
4972                return (*session).master_key_length as usize;
4973            }
4974            if outlen > (*session).master_key_length as usize {
4975                outlen = (*session).master_key_length as usize;
4976            }
4977            ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
4978            outlen
4979        }
4980
4981        #[allow(bad_style)]
4982        pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
4983            (*s).server
4984        }
4985
4986        #[allow(bad_style)]
4987        pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
4988            ffi::CRYPTO_add_lock(
4989                &mut (*ses).references,
4990                1,
4991                ffi::CRYPTO_LOCK_SSL_CTX,
4992                "mod.rs\0".as_ptr() as *const _,
4993                line!() as c_int,
4994            );
4995            0
4996        }
4997    }
4998}
4999
5000cfg_if! {
5001    if #[cfg(ossl300)] {
5002        use ffi::SSL_get1_peer_certificate;
5003    } else {
5004        use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
5005    }
5006}
5007cfg_if! {
5008    if #[cfg(any(boringssl, ossl110, libressl291, awslc))] {
5009        use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
5010    } else {
5011        use ffi::{
5012            SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
5013            SSLv23_server_method as TLS_server_method,
5014        };
5015    }
5016}
5017cfg_if! {
5018    if #[cfg(ossl110)] {
5019        unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5020            ffi::CRYPTO_get_ex_new_index(
5021                ffi::CRYPTO_EX_INDEX_SSL_CTX,
5022                0,
5023                ptr::null_mut(),
5024                None,
5025                None,
5026                f,
5027            )
5028        }
5029
5030        unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5031            ffi::CRYPTO_get_ex_new_index(
5032                ffi::CRYPTO_EX_INDEX_SSL,
5033                0,
5034                ptr::null_mut(),
5035                None,
5036                None,
5037                f,
5038            )
5039        }
5040    } else {
5041        use std::sync::Once;
5042
5043        unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5044            // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest
5045            static ONCE: Once = Once::new();
5046            ONCE.call_once(|| {
5047                cfg_if! {
5048                    if #[cfg(not(any(boringssl, awslc)))] {
5049                        ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5050                    } else {
5051                        ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5052                    }
5053                }
5054            });
5055
5056            cfg_if! {
5057                if #[cfg(not(any(boringssl, awslc)))] {
5058                    ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5059                } else {
5060                    ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5061                }
5062            }
5063        }
5064
5065        unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5066            // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest
5067            static ONCE: Once = Once::new();
5068            ONCE.call_once(|| {
5069                #[cfg(not(any(boringssl, awslc)))]
5070                ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5071                #[cfg(any(boringssl, awslc))]
5072                ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5073            });
5074
5075            #[cfg(not(any(boringssl, awslc)))]
5076            return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5077            #[cfg(any(boringssl, awslc))]
5078            return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5079        }
5080    }
5081}