Skip to main content

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