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