192f3ab15Sopenharmony_ci//! SSL/TLS support. 292f3ab15Sopenharmony_ci//! 392f3ab15Sopenharmony_ci//! `SslConnector` and `SslAcceptor` should be used in most cases - they handle 492f3ab15Sopenharmony_ci//! configuration of the OpenSSL primitives for you. 592f3ab15Sopenharmony_ci//! 692f3ab15Sopenharmony_ci//! # Examples 792f3ab15Sopenharmony_ci//! 892f3ab15Sopenharmony_ci//! To connect as a client to a remote server: 992f3ab15Sopenharmony_ci//! 1092f3ab15Sopenharmony_ci//! ```no_run 1192f3ab15Sopenharmony_ci//! use openssl::ssl::{SslMethod, SslConnector}; 1292f3ab15Sopenharmony_ci//! use std::io::{Read, Write}; 1392f3ab15Sopenharmony_ci//! use std::net::TcpStream; 1492f3ab15Sopenharmony_ci//! 1592f3ab15Sopenharmony_ci//! let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); 1692f3ab15Sopenharmony_ci//! 1792f3ab15Sopenharmony_ci//! let stream = TcpStream::connect("google.com:443").unwrap(); 1892f3ab15Sopenharmony_ci//! let mut stream = connector.connect("google.com", stream).unwrap(); 1992f3ab15Sopenharmony_ci//! 2092f3ab15Sopenharmony_ci//! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); 2192f3ab15Sopenharmony_ci//! let mut res = vec![]; 2292f3ab15Sopenharmony_ci//! stream.read_to_end(&mut res).unwrap(); 2392f3ab15Sopenharmony_ci//! println!("{}", String::from_utf8_lossy(&res)); 2492f3ab15Sopenharmony_ci//! ``` 2592f3ab15Sopenharmony_ci//! 2692f3ab15Sopenharmony_ci//! To accept connections as a server from remote clients: 2792f3ab15Sopenharmony_ci//! 2892f3ab15Sopenharmony_ci//! ```no_run 2992f3ab15Sopenharmony_ci//! use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype}; 3092f3ab15Sopenharmony_ci//! use std::net::{TcpListener, TcpStream}; 3192f3ab15Sopenharmony_ci//! use std::sync::Arc; 3292f3ab15Sopenharmony_ci//! use std::thread; 3392f3ab15Sopenharmony_ci//! 3492f3ab15Sopenharmony_ci//! 3592f3ab15Sopenharmony_ci//! let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); 3692f3ab15Sopenharmony_ci//! acceptor.set_private_key_file("key.pem", SslFiletype::PEM).unwrap(); 3792f3ab15Sopenharmony_ci//! acceptor.set_certificate_chain_file("certs.pem").unwrap(); 3892f3ab15Sopenharmony_ci//! acceptor.check_private_key().unwrap(); 3992f3ab15Sopenharmony_ci//! let acceptor = Arc::new(acceptor.build()); 4092f3ab15Sopenharmony_ci//! 4192f3ab15Sopenharmony_ci//! let listener = TcpListener::bind("0.0.0.0:8443").unwrap(); 4292f3ab15Sopenharmony_ci//! 4392f3ab15Sopenharmony_ci//! fn handle_client(stream: SslStream<TcpStream>) { 4492f3ab15Sopenharmony_ci//! // ... 4592f3ab15Sopenharmony_ci//! } 4692f3ab15Sopenharmony_ci//! 4792f3ab15Sopenharmony_ci//! for stream in listener.incoming() { 4892f3ab15Sopenharmony_ci//! match stream { 4992f3ab15Sopenharmony_ci//! Ok(stream) => { 5092f3ab15Sopenharmony_ci//! let acceptor = acceptor.clone(); 5192f3ab15Sopenharmony_ci//! thread::spawn(move || { 5292f3ab15Sopenharmony_ci//! let stream = acceptor.accept(stream).unwrap(); 5392f3ab15Sopenharmony_ci//! handle_client(stream); 5492f3ab15Sopenharmony_ci//! }); 5592f3ab15Sopenharmony_ci//! } 5692f3ab15Sopenharmony_ci//! Err(e) => { /* connection failed */ } 5792f3ab15Sopenharmony_ci//! } 5892f3ab15Sopenharmony_ci//! } 5992f3ab15Sopenharmony_ci//! ``` 6092f3ab15Sopenharmony_ciuse crate::dh::{Dh, DhRef}; 6192f3ab15Sopenharmony_ci#[cfg(all(ossl101, not(ossl110)))] 6292f3ab15Sopenharmony_ciuse crate::ec::EcKey; 6392f3ab15Sopenharmony_ciuse crate::ec::EcKeyRef; 6492f3ab15Sopenharmony_ciuse crate::error::ErrorStack; 6592f3ab15Sopenharmony_ciuse crate::ex_data::Index; 6692f3ab15Sopenharmony_ci#[cfg(ossl111)] 6792f3ab15Sopenharmony_ciuse crate::hash::MessageDigest; 6892f3ab15Sopenharmony_ci#[cfg(any(ossl110, libressl270))] 6992f3ab15Sopenharmony_ciuse crate::nid::Nid; 7092f3ab15Sopenharmony_ciuse crate::pkey::{HasPrivate, PKeyRef, Params, Private}; 7192f3ab15Sopenharmony_ciuse crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef}; 7292f3ab15Sopenharmony_ciuse crate::ssl::bio::BioMethod; 7392f3ab15Sopenharmony_ciuse crate::ssl::callbacks::*; 7492f3ab15Sopenharmony_ciuse crate::ssl::error::InnerError; 7592f3ab15Sopenharmony_ciuse crate::stack::{Stack, StackRef, Stackable}; 7692f3ab15Sopenharmony_ciuse crate::util::{ForeignTypeExt, ForeignTypeRefExt}; 7792f3ab15Sopenharmony_ciuse crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef}; 7892f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl261))] 7992f3ab15Sopenharmony_ciuse crate::x509::verify::X509VerifyParamRef; 8092f3ab15Sopenharmony_ciuse crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509}; 8192f3ab15Sopenharmony_ciuse crate::{cvt, cvt_n, cvt_p, init}; 8292f3ab15Sopenharmony_ciuse bitflags::bitflags; 8392f3ab15Sopenharmony_ciuse cfg_if::cfg_if; 8492f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef, Opaque}; 8592f3ab15Sopenharmony_ciuse libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void}; 8692f3ab15Sopenharmony_ciuse once_cell::sync::{Lazy, OnceCell}; 8792f3ab15Sopenharmony_ciuse openssl_macros::corresponds; 8892f3ab15Sopenharmony_ciuse std::any::TypeId; 8992f3ab15Sopenharmony_ciuse std::cmp; 9092f3ab15Sopenharmony_ciuse std::collections::HashMap; 9192f3ab15Sopenharmony_ciuse std::ffi::{CStr, CString}; 9292f3ab15Sopenharmony_ciuse std::fmt; 9392f3ab15Sopenharmony_ciuse std::io; 9492f3ab15Sopenharmony_ciuse std::io::prelude::*; 9592f3ab15Sopenharmony_ciuse std::marker::PhantomData; 9692f3ab15Sopenharmony_ciuse std::mem::{self, ManuallyDrop}; 9792f3ab15Sopenharmony_ciuse std::ops::{Deref, DerefMut}; 9892f3ab15Sopenharmony_ciuse std::panic::resume_unwind; 9992f3ab15Sopenharmony_ciuse std::path::Path; 10092f3ab15Sopenharmony_ciuse std::ptr; 10192f3ab15Sopenharmony_ciuse std::slice; 10292f3ab15Sopenharmony_ciuse std::str; 10392f3ab15Sopenharmony_ciuse std::sync::{Arc, Mutex}; 10492f3ab15Sopenharmony_ci 10592f3ab15Sopenharmony_cipub use crate::ssl::connector::{ 10692f3ab15Sopenharmony_ci ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder, 10792f3ab15Sopenharmony_ci}; 10892f3ab15Sopenharmony_cipub use crate::ssl::error::{Error, ErrorCode, HandshakeError}; 10992f3ab15Sopenharmony_ci 11092f3ab15Sopenharmony_cimod bio; 11192f3ab15Sopenharmony_cimod callbacks; 11292f3ab15Sopenharmony_cimod connector; 11392f3ab15Sopenharmony_cimod error; 11492f3ab15Sopenharmony_ci#[cfg(test)] 11592f3ab15Sopenharmony_cimod test; 11692f3ab15Sopenharmony_ci 11792f3ab15Sopenharmony_ci/// Returns the OpenSSL name of a cipher corresponding to an RFC-standard cipher name. 11892f3ab15Sopenharmony_ci/// 11992f3ab15Sopenharmony_ci/// If the cipher has no corresponding OpenSSL name, the string `(NONE)` is returned. 12092f3ab15Sopenharmony_ci/// 12192f3ab15Sopenharmony_ci/// Requires OpenSSL 1.1.1 or newer. 12292f3ab15Sopenharmony_ci#[corresponds(OPENSSL_cipher_name)] 12392f3ab15Sopenharmony_ci#[cfg(ossl111)] 12492f3ab15Sopenharmony_cipub fn cipher_name(std_name: &str) -> &'static str { 12592f3ab15Sopenharmony_ci unsafe { 12692f3ab15Sopenharmony_ci ffi::init(); 12792f3ab15Sopenharmony_ci 12892f3ab15Sopenharmony_ci let s = CString::new(std_name).unwrap(); 12992f3ab15Sopenharmony_ci let ptr = ffi::OPENSSL_cipher_name(s.as_ptr()); 13092f3ab15Sopenharmony_ci CStr::from_ptr(ptr).to_str().unwrap() 13192f3ab15Sopenharmony_ci } 13292f3ab15Sopenharmony_ci} 13392f3ab15Sopenharmony_ci 13492f3ab15Sopenharmony_cicfg_if! { 13592f3ab15Sopenharmony_ci if #[cfg(ossl300)] { 13692f3ab15Sopenharmony_ci type SslOptionsRepr = u64; 13792f3ab15Sopenharmony_ci } else if #[cfg(boringssl)] { 13892f3ab15Sopenharmony_ci type SslOptionsRepr = u32; 13992f3ab15Sopenharmony_ci } else { 14092f3ab15Sopenharmony_ci type SslOptionsRepr = libc::c_ulong; 14192f3ab15Sopenharmony_ci } 14292f3ab15Sopenharmony_ci} 14392f3ab15Sopenharmony_ci 14492f3ab15Sopenharmony_cibitflags! { 14592f3ab15Sopenharmony_ci /// Options controlling the behavior of an `SslContext`. 14692f3ab15Sopenharmony_ci pub struct SslOptions: SslOptionsRepr { 14792f3ab15Sopenharmony_ci /// Disables a countermeasure against an SSLv3/TLSv1.0 vulnerability affecting CBC ciphers. 14892f3ab15Sopenharmony_ci const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr; 14992f3ab15Sopenharmony_ci 15092f3ab15Sopenharmony_ci /// A "reasonable default" set of options which enables compatibility flags. 15192f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 15292f3ab15Sopenharmony_ci const ALL = ffi::SSL_OP_ALL as SslOptionsRepr; 15392f3ab15Sopenharmony_ci 15492f3ab15Sopenharmony_ci /// Do not query the MTU. 15592f3ab15Sopenharmony_ci /// 15692f3ab15Sopenharmony_ci /// Only affects DTLS connections. 15792f3ab15Sopenharmony_ci const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr; 15892f3ab15Sopenharmony_ci 15992f3ab15Sopenharmony_ci /// Enables Cookie Exchange as described in [RFC 4347 Section 4.2.1]. 16092f3ab15Sopenharmony_ci /// 16192f3ab15Sopenharmony_ci /// Only affects DTLS connections. 16292f3ab15Sopenharmony_ci /// 16392f3ab15Sopenharmony_ci /// [RFC 4347 Section 4.2.1]: https://tools.ietf.org/html/rfc4347#section-4.2.1 16492f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 16592f3ab15Sopenharmony_ci const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr; 16692f3ab15Sopenharmony_ci 16792f3ab15Sopenharmony_ci /// Disables the use of session tickets for session resumption. 16892f3ab15Sopenharmony_ci const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr; 16992f3ab15Sopenharmony_ci 17092f3ab15Sopenharmony_ci /// Always start a new session when performing a renegotiation on the server side. 17192f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 17292f3ab15Sopenharmony_ci const NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 17392f3ab15Sopenharmony_ci ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr; 17492f3ab15Sopenharmony_ci 17592f3ab15Sopenharmony_ci /// Disables the use of TLS compression. 17692f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 17792f3ab15Sopenharmony_ci const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr; 17892f3ab15Sopenharmony_ci 17992f3ab15Sopenharmony_ci /// Allow legacy insecure renegotiation with servers or clients that do not support secure 18092f3ab15Sopenharmony_ci /// renegotiation. 18192f3ab15Sopenharmony_ci const ALLOW_UNSAFE_LEGACY_RENEGOTIATION = 18292f3ab15Sopenharmony_ci ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr; 18392f3ab15Sopenharmony_ci 18492f3ab15Sopenharmony_ci /// Creates a new key for each session when using ECDHE. 18592f3ab15Sopenharmony_ci /// 18692f3ab15Sopenharmony_ci /// This is always enabled in OpenSSL 1.1.0. 18792f3ab15Sopenharmony_ci const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr; 18892f3ab15Sopenharmony_ci 18992f3ab15Sopenharmony_ci /// Creates a new key for each session when using DHE. 19092f3ab15Sopenharmony_ci /// 19192f3ab15Sopenharmony_ci /// This is always enabled in OpenSSL 1.1.0. 19292f3ab15Sopenharmony_ci const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr; 19392f3ab15Sopenharmony_ci 19492f3ab15Sopenharmony_ci /// Use the server's preferences rather than the client's when selecting a cipher. 19592f3ab15Sopenharmony_ci /// 19692f3ab15Sopenharmony_ci /// This has no effect on the client side. 19792f3ab15Sopenharmony_ci const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr; 19892f3ab15Sopenharmony_ci 19992f3ab15Sopenharmony_ci /// Disables version rollback attach detection. 20092f3ab15Sopenharmony_ci const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr; 20192f3ab15Sopenharmony_ci 20292f3ab15Sopenharmony_ci /// Disables the use of SSLv2. 20392f3ab15Sopenharmony_ci const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr; 20492f3ab15Sopenharmony_ci 20592f3ab15Sopenharmony_ci /// Disables the use of SSLv3. 20692f3ab15Sopenharmony_ci const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr; 20792f3ab15Sopenharmony_ci 20892f3ab15Sopenharmony_ci /// Disables the use of TLSv1.0. 20992f3ab15Sopenharmony_ci const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr; 21092f3ab15Sopenharmony_ci 21192f3ab15Sopenharmony_ci /// Disables the use of TLSv1.1. 21292f3ab15Sopenharmony_ci const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr; 21392f3ab15Sopenharmony_ci 21492f3ab15Sopenharmony_ci /// Disables the use of TLSv1.2. 21592f3ab15Sopenharmony_ci const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr; 21692f3ab15Sopenharmony_ci 21792f3ab15Sopenharmony_ci /// Disables the use of TLSv1.3. 21892f3ab15Sopenharmony_ci /// 21992f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 22092f3ab15Sopenharmony_ci #[cfg(any(boringssl, ossl111, libressl340))] 22192f3ab15Sopenharmony_ci const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr; 22292f3ab15Sopenharmony_ci 22392f3ab15Sopenharmony_ci /// Disables the use of DTLSv1.0 22492f3ab15Sopenharmony_ci /// 22592f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL 3.3.2 or newer. 22692f3ab15Sopenharmony_ci #[cfg(any(boringssl, ossl102, ossl110, libressl332))] 22792f3ab15Sopenharmony_ci const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr; 22892f3ab15Sopenharmony_ci 22992f3ab15Sopenharmony_ci /// Disables the use of DTLSv1.2. 23092f3ab15Sopenharmony_ci /// 23192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL 3.3.2 or newer. 23292f3ab15Sopenharmony_ci #[cfg(any(boringssl, ossl102, ossl110, libressl332))] 23392f3ab15Sopenharmony_ci const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr; 23492f3ab15Sopenharmony_ci 23592f3ab15Sopenharmony_ci /// Disables the use of all (D)TLS protocol versions. 23692f3ab15Sopenharmony_ci /// 23792f3ab15Sopenharmony_ci /// This can be used as a mask when whitelisting protocol versions. 23892f3ab15Sopenharmony_ci /// 23992f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 24092f3ab15Sopenharmony_ci /// 24192f3ab15Sopenharmony_ci /// # Examples 24292f3ab15Sopenharmony_ci /// 24392f3ab15Sopenharmony_ci /// Only support TLSv1.2: 24492f3ab15Sopenharmony_ci /// 24592f3ab15Sopenharmony_ci /// ```rust 24692f3ab15Sopenharmony_ci /// use openssl::ssl::SslOptions; 24792f3ab15Sopenharmony_ci /// 24892f3ab15Sopenharmony_ci /// let options = SslOptions::NO_SSL_MASK & !SslOptions::NO_TLSV1_2; 24992f3ab15Sopenharmony_ci /// ``` 25092f3ab15Sopenharmony_ci #[cfg(any(ossl102, ossl110))] 25192f3ab15Sopenharmony_ci const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr; 25292f3ab15Sopenharmony_ci 25392f3ab15Sopenharmony_ci /// Disallow all renegotiation in TLSv1.2 and earlier. 25492f3ab15Sopenharmony_ci /// 25592f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0h or newer. 25692f3ab15Sopenharmony_ci #[cfg(any(boringssl, ossl110h))] 25792f3ab15Sopenharmony_ci const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr; 25892f3ab15Sopenharmony_ci 25992f3ab15Sopenharmony_ci /// Enable TLSv1.3 Compatibility mode. 26092f3ab15Sopenharmony_ci /// 26192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. This is on by default in 1.1.1, but a future version 26292f3ab15Sopenharmony_ci /// may have this disabled by default. 26392f3ab15Sopenharmony_ci #[cfg(ossl111)] 26492f3ab15Sopenharmony_ci const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr; 26592f3ab15Sopenharmony_ci 26692f3ab15Sopenharmony_ci /// Prioritize ChaCha ciphers when preferred by clients. 26792f3ab15Sopenharmony_ci /// 26892f3ab15Sopenharmony_ci /// Temporarily reprioritize ChaCha20-Poly1305 ciphers to the top of the server cipher list 26992f3ab15Sopenharmony_ci /// if a ChaCha20-Poly1305 cipher is at the top of the client cipher list. This helps those 27092f3ab15Sopenharmony_ci /// clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere in the server 27192f3ab15Sopenharmony_ci /// cipher list; but still allows other clients to use AES and other ciphers. 27292f3ab15Sopenharmony_ci /// 27392f3ab15Sopenharmony_ci /// Requires enable [`SslOptions::CIPHER_SERVER_PREFERENCE`]. 27492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 27592f3ab15Sopenharmony_ci /// 27692f3ab15Sopenharmony_ci /// [`SslOptions::CIPHER_SERVER_PREFERENCE`]: struct.SslOptions.html#associatedconstant.CIPHER_SERVER_PREFERENCE 27792f3ab15Sopenharmony_ci #[cfg(ossl111)] 27892f3ab15Sopenharmony_ci const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr; 27992f3ab15Sopenharmony_ci } 28092f3ab15Sopenharmony_ci} 28192f3ab15Sopenharmony_ci 28292f3ab15Sopenharmony_cibitflags! { 28392f3ab15Sopenharmony_ci /// Options controlling the behavior of an `SslContext`. 28492f3ab15Sopenharmony_ci pub struct SslMode: SslBitType { 28592f3ab15Sopenharmony_ci /// Enables "short writes". 28692f3ab15Sopenharmony_ci /// 28792f3ab15Sopenharmony_ci /// Normally, a write in OpenSSL will always write out all of the requested data, even if it 28892f3ab15Sopenharmony_ci /// requires more than one TLS record or write to the underlying stream. This option will 28992f3ab15Sopenharmony_ci /// cause a write to return after writing a single TLS record instead. 29092f3ab15Sopenharmony_ci const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE; 29192f3ab15Sopenharmony_ci 29292f3ab15Sopenharmony_ci /// Disables a check that the data buffer has not moved between calls when operating in a 29392f3ab15Sopenharmony_ci /// non-blocking context. 29492f3ab15Sopenharmony_ci const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; 29592f3ab15Sopenharmony_ci 29692f3ab15Sopenharmony_ci /// Enables automatic retries after TLS session events such as renegotiations or heartbeats. 29792f3ab15Sopenharmony_ci /// 29892f3ab15Sopenharmony_ci /// By default, OpenSSL will return a `WantRead` error after a renegotiation or heartbeat. 29992f3ab15Sopenharmony_ci /// This option will cause OpenSSL to automatically continue processing the requested 30092f3ab15Sopenharmony_ci /// operation instead. 30192f3ab15Sopenharmony_ci /// 30292f3ab15Sopenharmony_ci /// Note that `SslStream::read` and `SslStream::write` will automatically retry regardless 30392f3ab15Sopenharmony_ci /// of the state of this option. It only affects `SslStream::ssl_read` and 30492f3ab15Sopenharmony_ci /// `SslStream::ssl_write`. 30592f3ab15Sopenharmony_ci const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY; 30692f3ab15Sopenharmony_ci 30792f3ab15Sopenharmony_ci /// Disables automatic chain building when verifying a peer's certificate. 30892f3ab15Sopenharmony_ci /// 30992f3ab15Sopenharmony_ci /// TLS peers are responsible for sending the entire certificate chain from the leaf to a 31092f3ab15Sopenharmony_ci /// trusted root, but some will incorrectly not do so. OpenSSL will try to build the chain 31192f3ab15Sopenharmony_ci /// out of certificates it knows of, and this option will disable that behavior. 31292f3ab15Sopenharmony_ci const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN; 31392f3ab15Sopenharmony_ci 31492f3ab15Sopenharmony_ci /// Release memory buffers when the session does not need them. 31592f3ab15Sopenharmony_ci /// 31692f3ab15Sopenharmony_ci /// This saves ~34 KiB of memory for idle streams. 31792f3ab15Sopenharmony_ci const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS; 31892f3ab15Sopenharmony_ci 31992f3ab15Sopenharmony_ci /// Sends the fake `TLS_FALLBACK_SCSV` cipher suite in the ClientHello message of a 32092f3ab15Sopenharmony_ci /// handshake. 32192f3ab15Sopenharmony_ci /// 32292f3ab15Sopenharmony_ci /// This should only be enabled if a client has failed to connect to a server which 32392f3ab15Sopenharmony_ci /// attempted to downgrade the protocol version of the session. 32492f3ab15Sopenharmony_ci /// 32592f3ab15Sopenharmony_ci /// Do not use this unless you know what you're doing! 32692f3ab15Sopenharmony_ci #[cfg(not(libressl))] 32792f3ab15Sopenharmony_ci const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV; 32892f3ab15Sopenharmony_ci } 32992f3ab15Sopenharmony_ci} 33092f3ab15Sopenharmony_ci 33192f3ab15Sopenharmony_ci/// A type specifying the kind of protocol an `SslContext` will speak. 33292f3ab15Sopenharmony_ci#[derive(Copy, Clone)] 33392f3ab15Sopenharmony_cipub struct SslMethod(*const ffi::SSL_METHOD); 33492f3ab15Sopenharmony_ci 33592f3ab15Sopenharmony_ciimpl SslMethod { 33692f3ab15Sopenharmony_ci /// Support all versions of the TLS protocol. 33792f3ab15Sopenharmony_ci #[corresponds(TLS_method)] 33892f3ab15Sopenharmony_ci pub fn tls() -> SslMethod { 33992f3ab15Sopenharmony_ci unsafe { SslMethod(TLS_method()) } 34092f3ab15Sopenharmony_ci } 34192f3ab15Sopenharmony_ci 34292f3ab15Sopenharmony_ci /// Support all versions of the DTLS protocol. 34392f3ab15Sopenharmony_ci #[corresponds(DTLS_method)] 34492f3ab15Sopenharmony_ci pub fn dtls() -> SslMethod { 34592f3ab15Sopenharmony_ci unsafe { SslMethod(DTLS_method()) } 34692f3ab15Sopenharmony_ci } 34792f3ab15Sopenharmony_ci 34892f3ab15Sopenharmony_ci /// Support all versions of the TLS protocol, explicitly as a client. 34992f3ab15Sopenharmony_ci #[corresponds(TLS_client_method)] 35092f3ab15Sopenharmony_ci pub fn tls_client() -> SslMethod { 35192f3ab15Sopenharmony_ci unsafe { SslMethod(TLS_client_method()) } 35292f3ab15Sopenharmony_ci } 35392f3ab15Sopenharmony_ci 35492f3ab15Sopenharmony_ci /// Support all versions of the TLS protocol, explicitly as a server. 35592f3ab15Sopenharmony_ci #[corresponds(TLS_server_method)] 35692f3ab15Sopenharmony_ci pub fn tls_server() -> SslMethod { 35792f3ab15Sopenharmony_ci unsafe { SslMethod(TLS_server_method()) } 35892f3ab15Sopenharmony_ci } 35992f3ab15Sopenharmony_ci 36092f3ab15Sopenharmony_ci /// Constructs an `SslMethod` from a pointer to the underlying OpenSSL value. 36192f3ab15Sopenharmony_ci /// 36292f3ab15Sopenharmony_ci /// # Safety 36392f3ab15Sopenharmony_ci /// 36492f3ab15Sopenharmony_ci /// The caller must ensure the pointer is valid. 36592f3ab15Sopenharmony_ci pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod { 36692f3ab15Sopenharmony_ci SslMethod(ptr) 36792f3ab15Sopenharmony_ci } 36892f3ab15Sopenharmony_ci 36992f3ab15Sopenharmony_ci /// Returns a pointer to the underlying OpenSSL value. 37092f3ab15Sopenharmony_ci #[allow(clippy::trivially_copy_pass_by_ref)] 37192f3ab15Sopenharmony_ci pub fn as_ptr(&self) -> *const ffi::SSL_METHOD { 37292f3ab15Sopenharmony_ci self.0 37392f3ab15Sopenharmony_ci } 37492f3ab15Sopenharmony_ci} 37592f3ab15Sopenharmony_ci 37692f3ab15Sopenharmony_ciunsafe impl Sync for SslMethod {} 37792f3ab15Sopenharmony_ciunsafe impl Send for SslMethod {} 37892f3ab15Sopenharmony_ci 37992f3ab15Sopenharmony_cibitflags! { 38092f3ab15Sopenharmony_ci /// Options controlling the behavior of certificate verification. 38192f3ab15Sopenharmony_ci pub struct SslVerifyMode: i32 { 38292f3ab15Sopenharmony_ci /// Verifies that the peer's certificate is trusted. 38392f3ab15Sopenharmony_ci /// 38492f3ab15Sopenharmony_ci /// On the server side, this will cause OpenSSL to request a certificate from the client. 38592f3ab15Sopenharmony_ci const PEER = ffi::SSL_VERIFY_PEER; 38692f3ab15Sopenharmony_ci 38792f3ab15Sopenharmony_ci /// Disables verification of the peer's certificate. 38892f3ab15Sopenharmony_ci /// 38992f3ab15Sopenharmony_ci /// On the server side, this will cause OpenSSL to not request a certificate from the 39092f3ab15Sopenharmony_ci /// client. On the client side, the certificate will be checked for validity, but the 39192f3ab15Sopenharmony_ci /// negotiation will continue regardless of the result of that check. 39292f3ab15Sopenharmony_ci const NONE = ffi::SSL_VERIFY_NONE; 39392f3ab15Sopenharmony_ci 39492f3ab15Sopenharmony_ci /// On the server side, abort the handshake if the client did not send a certificate. 39592f3ab15Sopenharmony_ci /// 39692f3ab15Sopenharmony_ci /// This should be paired with `SSL_VERIFY_PEER`. It has no effect on the client side. 39792f3ab15Sopenharmony_ci const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 39892f3ab15Sopenharmony_ci } 39992f3ab15Sopenharmony_ci} 40092f3ab15Sopenharmony_ci 40192f3ab15Sopenharmony_ci#[cfg(boringssl)] 40292f3ab15Sopenharmony_citype SslBitType = c_int; 40392f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 40492f3ab15Sopenharmony_citype SslBitType = c_long; 40592f3ab15Sopenharmony_ci 40692f3ab15Sopenharmony_ci#[cfg(boringssl)] 40792f3ab15Sopenharmony_citype SslTimeTy = u64; 40892f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 40992f3ab15Sopenharmony_citype SslTimeTy = c_long; 41092f3ab15Sopenharmony_ci 41192f3ab15Sopenharmony_cibitflags! { 41292f3ab15Sopenharmony_ci /// Options controlling the behavior of session caching. 41392f3ab15Sopenharmony_ci pub struct SslSessionCacheMode: SslBitType { 41492f3ab15Sopenharmony_ci /// No session caching for the client or server takes place. 41592f3ab15Sopenharmony_ci const OFF = ffi::SSL_SESS_CACHE_OFF; 41692f3ab15Sopenharmony_ci 41792f3ab15Sopenharmony_ci /// Enable session caching on the client side. 41892f3ab15Sopenharmony_ci /// 41992f3ab15Sopenharmony_ci /// OpenSSL has no way of identifying the proper session to reuse automatically, so the 42092f3ab15Sopenharmony_ci /// application is responsible for setting it explicitly via [`SslRef::set_session`]. 42192f3ab15Sopenharmony_ci /// 42292f3ab15Sopenharmony_ci /// [`SslRef::set_session`]: struct.SslRef.html#method.set_session 42392f3ab15Sopenharmony_ci const CLIENT = ffi::SSL_SESS_CACHE_CLIENT; 42492f3ab15Sopenharmony_ci 42592f3ab15Sopenharmony_ci /// Enable session caching on the server side. 42692f3ab15Sopenharmony_ci /// 42792f3ab15Sopenharmony_ci /// This is the default mode. 42892f3ab15Sopenharmony_ci const SERVER = ffi::SSL_SESS_CACHE_SERVER; 42992f3ab15Sopenharmony_ci 43092f3ab15Sopenharmony_ci /// Enable session caching on both the client and server side. 43192f3ab15Sopenharmony_ci const BOTH = ffi::SSL_SESS_CACHE_BOTH; 43292f3ab15Sopenharmony_ci 43392f3ab15Sopenharmony_ci /// Disable automatic removal of expired sessions from the session cache. 43492f3ab15Sopenharmony_ci const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR; 43592f3ab15Sopenharmony_ci 43692f3ab15Sopenharmony_ci /// Disable use of the internal session cache for session lookups. 43792f3ab15Sopenharmony_ci const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; 43892f3ab15Sopenharmony_ci 43992f3ab15Sopenharmony_ci /// Disable use of the internal session cache for session storage. 44092f3ab15Sopenharmony_ci const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE; 44192f3ab15Sopenharmony_ci 44292f3ab15Sopenharmony_ci /// Disable use of the internal session cache for storage and lookup. 44392f3ab15Sopenharmony_ci const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL; 44492f3ab15Sopenharmony_ci } 44592f3ab15Sopenharmony_ci} 44692f3ab15Sopenharmony_ci 44792f3ab15Sopenharmony_ci#[cfg(ossl111)] 44892f3ab15Sopenharmony_cibitflags! { 44992f3ab15Sopenharmony_ci /// Which messages and under which conditions an extension should be added or expected. 45092f3ab15Sopenharmony_ci pub struct ExtensionContext: c_uint { 45192f3ab15Sopenharmony_ci /// This extension is only allowed in TLS 45292f3ab15Sopenharmony_ci const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY; 45392f3ab15Sopenharmony_ci /// This extension is only allowed in DTLS 45492f3ab15Sopenharmony_ci const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY; 45592f3ab15Sopenharmony_ci /// Some extensions may be allowed in DTLS but we don't implement them for it 45692f3ab15Sopenharmony_ci const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY; 45792f3ab15Sopenharmony_ci /// Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is 45892f3ab15Sopenharmony_ci const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED; 45992f3ab15Sopenharmony_ci /// Extension is only defined for TLS1.2 and below 46092f3ab15Sopenharmony_ci const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY; 46192f3ab15Sopenharmony_ci /// Extension is only defined for TLS1.3 and above 46292f3ab15Sopenharmony_ci const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY; 46392f3ab15Sopenharmony_ci /// Ignore this extension during parsing if we are resuming 46492f3ab15Sopenharmony_ci const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION; 46592f3ab15Sopenharmony_ci const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO; 46692f3ab15Sopenharmony_ci /// Really means TLS1.2 or below 46792f3ab15Sopenharmony_ci const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO; 46892f3ab15Sopenharmony_ci const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO; 46992f3ab15Sopenharmony_ci const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS; 47092f3ab15Sopenharmony_ci const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST; 47192f3ab15Sopenharmony_ci const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE; 47292f3ab15Sopenharmony_ci const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET; 47392f3ab15Sopenharmony_ci const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST; 47492f3ab15Sopenharmony_ci } 47592f3ab15Sopenharmony_ci} 47692f3ab15Sopenharmony_ci 47792f3ab15Sopenharmony_ci/// An identifier of the format of a certificate or key file. 47892f3ab15Sopenharmony_ci#[derive(Copy, Clone)] 47992f3ab15Sopenharmony_cipub struct SslFiletype(c_int); 48092f3ab15Sopenharmony_ci 48192f3ab15Sopenharmony_ciimpl SslFiletype { 48292f3ab15Sopenharmony_ci /// The PEM format. 48392f3ab15Sopenharmony_ci /// 48492f3ab15Sopenharmony_ci /// This corresponds to `SSL_FILETYPE_PEM`. 48592f3ab15Sopenharmony_ci pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM); 48692f3ab15Sopenharmony_ci 48792f3ab15Sopenharmony_ci /// The ASN1 format. 48892f3ab15Sopenharmony_ci /// 48992f3ab15Sopenharmony_ci /// This corresponds to `SSL_FILETYPE_ASN1`. 49092f3ab15Sopenharmony_ci pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1); 49192f3ab15Sopenharmony_ci 49292f3ab15Sopenharmony_ci /// Constructs an `SslFiletype` from a raw OpenSSL value. 49392f3ab15Sopenharmony_ci pub fn from_raw(raw: c_int) -> SslFiletype { 49492f3ab15Sopenharmony_ci SslFiletype(raw) 49592f3ab15Sopenharmony_ci } 49692f3ab15Sopenharmony_ci 49792f3ab15Sopenharmony_ci /// Returns the raw OpenSSL value represented by this type. 49892f3ab15Sopenharmony_ci #[allow(clippy::trivially_copy_pass_by_ref)] 49992f3ab15Sopenharmony_ci pub fn as_raw(&self) -> c_int { 50092f3ab15Sopenharmony_ci self.0 50192f3ab15Sopenharmony_ci } 50292f3ab15Sopenharmony_ci} 50392f3ab15Sopenharmony_ci 50492f3ab15Sopenharmony_ci/// An identifier of a certificate status type. 50592f3ab15Sopenharmony_ci#[derive(Copy, Clone)] 50692f3ab15Sopenharmony_cipub struct StatusType(c_int); 50792f3ab15Sopenharmony_ci 50892f3ab15Sopenharmony_ciimpl StatusType { 50992f3ab15Sopenharmony_ci /// An OSCP status. 51092f3ab15Sopenharmony_ci pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp); 51192f3ab15Sopenharmony_ci 51292f3ab15Sopenharmony_ci /// Constructs a `StatusType` from a raw OpenSSL value. 51392f3ab15Sopenharmony_ci pub fn from_raw(raw: c_int) -> StatusType { 51492f3ab15Sopenharmony_ci StatusType(raw) 51592f3ab15Sopenharmony_ci } 51692f3ab15Sopenharmony_ci 51792f3ab15Sopenharmony_ci /// Returns the raw OpenSSL value represented by this type. 51892f3ab15Sopenharmony_ci #[allow(clippy::trivially_copy_pass_by_ref)] 51992f3ab15Sopenharmony_ci pub fn as_raw(&self) -> c_int { 52092f3ab15Sopenharmony_ci self.0 52192f3ab15Sopenharmony_ci } 52292f3ab15Sopenharmony_ci} 52392f3ab15Sopenharmony_ci 52492f3ab15Sopenharmony_ci/// An identifier of a session name type. 52592f3ab15Sopenharmony_ci#[derive(Copy, Clone)] 52692f3ab15Sopenharmony_cipub struct NameType(c_int); 52792f3ab15Sopenharmony_ci 52892f3ab15Sopenharmony_ciimpl NameType { 52992f3ab15Sopenharmony_ci /// A host name. 53092f3ab15Sopenharmony_ci pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name); 53192f3ab15Sopenharmony_ci 53292f3ab15Sopenharmony_ci /// Constructs a `StatusType` from a raw OpenSSL value. 53392f3ab15Sopenharmony_ci pub fn from_raw(raw: c_int) -> StatusType { 53492f3ab15Sopenharmony_ci StatusType(raw) 53592f3ab15Sopenharmony_ci } 53692f3ab15Sopenharmony_ci 53792f3ab15Sopenharmony_ci /// Returns the raw OpenSSL value represented by this type. 53892f3ab15Sopenharmony_ci #[allow(clippy::trivially_copy_pass_by_ref)] 53992f3ab15Sopenharmony_ci pub fn as_raw(&self) -> c_int { 54092f3ab15Sopenharmony_ci self.0 54192f3ab15Sopenharmony_ci } 54292f3ab15Sopenharmony_ci} 54392f3ab15Sopenharmony_ci 54492f3ab15Sopenharmony_cistatic INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new())); 54592f3ab15Sopenharmony_cistatic SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new())); 54692f3ab15Sopenharmony_cistatic SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new(); 54792f3ab15Sopenharmony_ci 54892f3ab15Sopenharmony_cifn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> { 54992f3ab15Sopenharmony_ci SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index) 55092f3ab15Sopenharmony_ci} 55192f3ab15Sopenharmony_ci 55292f3ab15Sopenharmony_ciunsafe extern "C" fn free_data_box<T>( 55392f3ab15Sopenharmony_ci _parent: *mut c_void, 55492f3ab15Sopenharmony_ci ptr: *mut c_void, 55592f3ab15Sopenharmony_ci _ad: *mut ffi::CRYPTO_EX_DATA, 55692f3ab15Sopenharmony_ci _idx: c_int, 55792f3ab15Sopenharmony_ci _argl: c_long, 55892f3ab15Sopenharmony_ci _argp: *mut c_void, 55992f3ab15Sopenharmony_ci) { 56092f3ab15Sopenharmony_ci if !ptr.is_null() { 56192f3ab15Sopenharmony_ci let _ = Box::<T>::from_raw(ptr as *mut T); 56292f3ab15Sopenharmony_ci } 56392f3ab15Sopenharmony_ci} 56492f3ab15Sopenharmony_ci 56592f3ab15Sopenharmony_ci/// An error returned from the SNI callback. 56692f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)] 56792f3ab15Sopenharmony_cipub struct SniError(c_int); 56892f3ab15Sopenharmony_ci 56992f3ab15Sopenharmony_ciimpl SniError { 57092f3ab15Sopenharmony_ci /// Abort the handshake with a fatal alert. 57192f3ab15Sopenharmony_ci pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL); 57292f3ab15Sopenharmony_ci 57392f3ab15Sopenharmony_ci /// Send a warning alert to the client and continue the handshake. 57492f3ab15Sopenharmony_ci pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING); 57592f3ab15Sopenharmony_ci 57692f3ab15Sopenharmony_ci pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK); 57792f3ab15Sopenharmony_ci} 57892f3ab15Sopenharmony_ci 57992f3ab15Sopenharmony_ci/// An SSL/TLS alert. 58092f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)] 58192f3ab15Sopenharmony_cipub struct SslAlert(c_int); 58292f3ab15Sopenharmony_ci 58392f3ab15Sopenharmony_ciimpl SslAlert { 58492f3ab15Sopenharmony_ci /// Alert 112 - `unrecognized_name`. 58592f3ab15Sopenharmony_ci pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME); 58692f3ab15Sopenharmony_ci pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER); 58792f3ab15Sopenharmony_ci pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR); 58892f3ab15Sopenharmony_ci} 58992f3ab15Sopenharmony_ci 59092f3ab15Sopenharmony_ci/// An error returned from an ALPN selection callback. 59192f3ab15Sopenharmony_ci/// 59292f3ab15Sopenharmony_ci/// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 59392f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl261))] 59492f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)] 59592f3ab15Sopenharmony_cipub struct AlpnError(c_int); 59692f3ab15Sopenharmony_ci 59792f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl261))] 59892f3ab15Sopenharmony_ciimpl AlpnError { 59992f3ab15Sopenharmony_ci /// Terminate the handshake with a fatal alert. 60092f3ab15Sopenharmony_ci /// 60192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or newer. 60292f3ab15Sopenharmony_ci #[cfg(ossl110)] 60392f3ab15Sopenharmony_ci pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL); 60492f3ab15Sopenharmony_ci 60592f3ab15Sopenharmony_ci /// Do not select a protocol, but continue the handshake. 60692f3ab15Sopenharmony_ci pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK); 60792f3ab15Sopenharmony_ci} 60892f3ab15Sopenharmony_ci 60992f3ab15Sopenharmony_ci/// The result of a client hello callback. 61092f3ab15Sopenharmony_ci/// 61192f3ab15Sopenharmony_ci/// Requires OpenSSL 1.1.1 or newer. 61292f3ab15Sopenharmony_ci#[cfg(ossl111)] 61392f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)] 61492f3ab15Sopenharmony_cipub struct ClientHelloResponse(c_int); 61592f3ab15Sopenharmony_ci 61692f3ab15Sopenharmony_ci#[cfg(ossl111)] 61792f3ab15Sopenharmony_ciimpl ClientHelloResponse { 61892f3ab15Sopenharmony_ci /// Continue the handshake. 61992f3ab15Sopenharmony_ci pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS); 62092f3ab15Sopenharmony_ci 62192f3ab15Sopenharmony_ci /// Return from the handshake with an `ErrorCode::WANT_CLIENT_HELLO_CB` error. 62292f3ab15Sopenharmony_ci pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY); 62392f3ab15Sopenharmony_ci} 62492f3ab15Sopenharmony_ci 62592f3ab15Sopenharmony_ci/// An SSL/TLS protocol version. 62692f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)] 62792f3ab15Sopenharmony_cipub struct SslVersion(c_int); 62892f3ab15Sopenharmony_ci 62992f3ab15Sopenharmony_ciimpl SslVersion { 63092f3ab15Sopenharmony_ci /// SSLv3 63192f3ab15Sopenharmony_ci pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION); 63292f3ab15Sopenharmony_ci 63392f3ab15Sopenharmony_ci /// TLSv1.0 63492f3ab15Sopenharmony_ci pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION); 63592f3ab15Sopenharmony_ci 63692f3ab15Sopenharmony_ci /// TLSv1.1 63792f3ab15Sopenharmony_ci pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION); 63892f3ab15Sopenharmony_ci 63992f3ab15Sopenharmony_ci /// TLSv1.2 64092f3ab15Sopenharmony_ci pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION); 64192f3ab15Sopenharmony_ci 64292f3ab15Sopenharmony_ci /// TLSv1.3 64392f3ab15Sopenharmony_ci /// 64492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 64592f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 64692f3ab15Sopenharmony_ci pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION); 64792f3ab15Sopenharmony_ci 64892f3ab15Sopenharmony_ci /// DTLSv1.0 64992f3ab15Sopenharmony_ci /// 65092f3ab15Sopenharmony_ci /// DTLS 1.0 corresponds to TLS 1.1. 65192f3ab15Sopenharmony_ci pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION); 65292f3ab15Sopenharmony_ci 65392f3ab15Sopenharmony_ci /// DTLSv1.2 65492f3ab15Sopenharmony_ci /// 65592f3ab15Sopenharmony_ci /// DTLS 1.2 corresponds to TLS 1.2 to harmonize versions. There was never a DTLS 1.1. 65692f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl332))] 65792f3ab15Sopenharmony_ci pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION); 65892f3ab15Sopenharmony_ci} 65992f3ab15Sopenharmony_ci 66092f3ab15Sopenharmony_cicfg_if! { 66192f3ab15Sopenharmony_ci if #[cfg(boringssl)] { 66292f3ab15Sopenharmony_ci type SslCacheTy = i64; 66392f3ab15Sopenharmony_ci type SslCacheSize = libc::c_ulong; 66492f3ab15Sopenharmony_ci type MtuTy = u32; 66592f3ab15Sopenharmony_ci type SizeTy = usize; 66692f3ab15Sopenharmony_ci } else { 66792f3ab15Sopenharmony_ci type SslCacheTy = i64; 66892f3ab15Sopenharmony_ci type SslCacheSize = c_long; 66992f3ab15Sopenharmony_ci type MtuTy = c_long; 67092f3ab15Sopenharmony_ci type SizeTy = u32; 67192f3ab15Sopenharmony_ci } 67292f3ab15Sopenharmony_ci} 67392f3ab15Sopenharmony_ci 67492f3ab15Sopenharmony_ci/// A standard implementation of protocol selection for Application Layer Protocol Negotiation 67592f3ab15Sopenharmony_ci/// (ALPN). 67692f3ab15Sopenharmony_ci/// 67792f3ab15Sopenharmony_ci/// `server` should contain the server's list of supported protocols and `client` the client's. They 67892f3ab15Sopenharmony_ci/// must both be in the ALPN wire format. See the documentation for 67992f3ab15Sopenharmony_ci/// [`SslContextBuilder::set_alpn_protos`] for details. 68092f3ab15Sopenharmony_ci/// 68192f3ab15Sopenharmony_ci/// It will select the first protocol supported by the server which is also supported by the client. 68292f3ab15Sopenharmony_ci/// 68392f3ab15Sopenharmony_ci/// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos 68492f3ab15Sopenharmony_ci#[corresponds(SSL_select_next_proto)] 68592f3ab15Sopenharmony_cipub fn select_next_proto<'a>(server: &[u8], client: &'a [u8]) -> Option<&'a [u8]> { 68692f3ab15Sopenharmony_ci unsafe { 68792f3ab15Sopenharmony_ci let mut out = ptr::null_mut(); 68892f3ab15Sopenharmony_ci let mut outlen = 0; 68992f3ab15Sopenharmony_ci let r = ffi::SSL_select_next_proto( 69092f3ab15Sopenharmony_ci &mut out, 69192f3ab15Sopenharmony_ci &mut outlen, 69292f3ab15Sopenharmony_ci server.as_ptr(), 69392f3ab15Sopenharmony_ci server.len() as c_uint, 69492f3ab15Sopenharmony_ci client.as_ptr(), 69592f3ab15Sopenharmony_ci client.len() as c_uint, 69692f3ab15Sopenharmony_ci ); 69792f3ab15Sopenharmony_ci if r == ffi::OPENSSL_NPN_NEGOTIATED { 69892f3ab15Sopenharmony_ci Some(slice::from_raw_parts(out as *const u8, outlen as usize)) 69992f3ab15Sopenharmony_ci } else { 70092f3ab15Sopenharmony_ci None 70192f3ab15Sopenharmony_ci } 70292f3ab15Sopenharmony_ci } 70392f3ab15Sopenharmony_ci} 70492f3ab15Sopenharmony_ci 70592f3ab15Sopenharmony_ci/// A builder for `SslContext`s. 70692f3ab15Sopenharmony_cipub struct SslContextBuilder(SslContext); 70792f3ab15Sopenharmony_ci 70892f3ab15Sopenharmony_ciimpl SslContextBuilder { 70992f3ab15Sopenharmony_ci /// Creates a new `SslContextBuilder`. 71092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_new)] 71192f3ab15Sopenharmony_ci pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> { 71292f3ab15Sopenharmony_ci unsafe { 71392f3ab15Sopenharmony_ci init(); 71492f3ab15Sopenharmony_ci let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?; 71592f3ab15Sopenharmony_ci 71692f3ab15Sopenharmony_ci Ok(SslContextBuilder::from_ptr(ctx)) 71792f3ab15Sopenharmony_ci } 71892f3ab15Sopenharmony_ci } 71992f3ab15Sopenharmony_ci 72092f3ab15Sopenharmony_ci /// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value. 72192f3ab15Sopenharmony_ci /// 72292f3ab15Sopenharmony_ci /// # Safety 72392f3ab15Sopenharmony_ci /// 72492f3ab15Sopenharmony_ci /// The caller must ensure that the pointer is valid and uniquely owned by the builder. 72592f3ab15Sopenharmony_ci pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder { 72692f3ab15Sopenharmony_ci SslContextBuilder(SslContext::from_ptr(ctx)) 72792f3ab15Sopenharmony_ci } 72892f3ab15Sopenharmony_ci 72992f3ab15Sopenharmony_ci /// Returns a pointer to the raw OpenSSL value. 73092f3ab15Sopenharmony_ci pub fn as_ptr(&self) -> *mut ffi::SSL_CTX { 73192f3ab15Sopenharmony_ci self.0.as_ptr() 73292f3ab15Sopenharmony_ci } 73392f3ab15Sopenharmony_ci 73492f3ab15Sopenharmony_ci /// Configures the certificate verification method for new connections. 73592f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_verify)] 73692f3ab15Sopenharmony_ci pub fn set_verify(&mut self, mode: SslVerifyMode) { 73792f3ab15Sopenharmony_ci unsafe { 73892f3ab15Sopenharmony_ci ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, None); 73992f3ab15Sopenharmony_ci } 74092f3ab15Sopenharmony_ci } 74192f3ab15Sopenharmony_ci 74292f3ab15Sopenharmony_ci /// Configures the certificate verification method for new connections and 74392f3ab15Sopenharmony_ci /// registers a verification callback. 74492f3ab15Sopenharmony_ci /// 74592f3ab15Sopenharmony_ci /// The callback is passed a boolean indicating if OpenSSL's internal verification succeeded as 74692f3ab15Sopenharmony_ci /// well as a reference to the `X509StoreContext` which can be used to examine the certificate 74792f3ab15Sopenharmony_ci /// chain. It should return a boolean indicating if verification succeeded. 74892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_verify)] 74992f3ab15Sopenharmony_ci pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F) 75092f3ab15Sopenharmony_ci where 75192f3ab15Sopenharmony_ci F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, 75292f3ab15Sopenharmony_ci { 75392f3ab15Sopenharmony_ci unsafe { 75492f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), verify); 75592f3ab15Sopenharmony_ci ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::<F>)); 75692f3ab15Sopenharmony_ci } 75792f3ab15Sopenharmony_ci } 75892f3ab15Sopenharmony_ci 75992f3ab15Sopenharmony_ci /// Configures the server name indication (SNI) callback for new connections. 76092f3ab15Sopenharmony_ci /// 76192f3ab15Sopenharmony_ci /// SNI is used to allow a single server to handle requests for multiple domains, each of which 76292f3ab15Sopenharmony_ci /// has its own certificate chain and configuration. 76392f3ab15Sopenharmony_ci /// 76492f3ab15Sopenharmony_ci /// Obtain the server name with the `servername` method and then set the corresponding context 76592f3ab15Sopenharmony_ci /// with `set_ssl_context` 76692f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_tlsext_servername_callback)] 76792f3ab15Sopenharmony_ci // FIXME tlsext prefix? 76892f3ab15Sopenharmony_ci pub fn set_servername_callback<F>(&mut self, callback: F) 76992f3ab15Sopenharmony_ci where 77092f3ab15Sopenharmony_ci F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send, 77192f3ab15Sopenharmony_ci { 77292f3ab15Sopenharmony_ci unsafe { 77392f3ab15Sopenharmony_ci // The SNI callback is somewhat unique in that the callback associated with the original 77492f3ab15Sopenharmony_ci // context associated with an SSL can be used even if the SSL's context has been swapped 77592f3ab15Sopenharmony_ci // out. When that happens, we wouldn't be able to look up the callback's state in the 77692f3ab15Sopenharmony_ci // context's ex data. Instead, pass the pointer directly as the servername arg. It's 77792f3ab15Sopenharmony_ci // still stored in ex data to manage the lifetime. 77892f3ab15Sopenharmony_ci let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback); 77992f3ab15Sopenharmony_ci ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg); 78092f3ab15Sopenharmony_ci #[cfg(boringssl)] 78192f3ab15Sopenharmony_ci ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>)); 78292f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 78392f3ab15Sopenharmony_ci ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust( 78492f3ab15Sopenharmony_ci self.as_ptr(), 78592f3ab15Sopenharmony_ci Some(raw_sni::<F>), 78692f3ab15Sopenharmony_ci ); 78792f3ab15Sopenharmony_ci } 78892f3ab15Sopenharmony_ci } 78992f3ab15Sopenharmony_ci 79092f3ab15Sopenharmony_ci /// Sets the certificate verification depth. 79192f3ab15Sopenharmony_ci /// 79292f3ab15Sopenharmony_ci /// If the peer's certificate chain is longer than this value, verification will fail. 79392f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_verify_depth)] 79492f3ab15Sopenharmony_ci pub fn set_verify_depth(&mut self, depth: u32) { 79592f3ab15Sopenharmony_ci unsafe { 79692f3ab15Sopenharmony_ci ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int); 79792f3ab15Sopenharmony_ci } 79892f3ab15Sopenharmony_ci } 79992f3ab15Sopenharmony_ci 80092f3ab15Sopenharmony_ci /// Sets a custom certificate store for verifying peer certificates. 80192f3ab15Sopenharmony_ci /// 80292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 80392f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set0_verify_cert_store)] 80492f3ab15Sopenharmony_ci #[cfg(ossl102)] 80592f3ab15Sopenharmony_ci pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { 80692f3ab15Sopenharmony_ci unsafe { 80792f3ab15Sopenharmony_ci let ptr = cert_store.as_ptr(); 80892f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?; 80992f3ab15Sopenharmony_ci mem::forget(cert_store); 81092f3ab15Sopenharmony_ci 81192f3ab15Sopenharmony_ci Ok(()) 81292f3ab15Sopenharmony_ci } 81392f3ab15Sopenharmony_ci } 81492f3ab15Sopenharmony_ci 81592f3ab15Sopenharmony_ci /// Replaces the context's certificate store. 81692f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_cert_store)] 81792f3ab15Sopenharmony_ci pub fn set_cert_store(&mut self, cert_store: X509Store) { 81892f3ab15Sopenharmony_ci unsafe { 81992f3ab15Sopenharmony_ci ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr()); 82092f3ab15Sopenharmony_ci mem::forget(cert_store); 82192f3ab15Sopenharmony_ci } 82292f3ab15Sopenharmony_ci } 82392f3ab15Sopenharmony_ci 82492f3ab15Sopenharmony_ci /// Controls read ahead behavior. 82592f3ab15Sopenharmony_ci /// 82692f3ab15Sopenharmony_ci /// If enabled, OpenSSL will read as much data as is available from the underlying stream, 82792f3ab15Sopenharmony_ci /// instead of a single record at a time. 82892f3ab15Sopenharmony_ci /// 82992f3ab15Sopenharmony_ci /// It has no effect when used with DTLS. 83092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_read_ahead)] 83192f3ab15Sopenharmony_ci pub fn set_read_ahead(&mut self, read_ahead: bool) { 83292f3ab15Sopenharmony_ci unsafe { 83392f3ab15Sopenharmony_ci ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType); 83492f3ab15Sopenharmony_ci } 83592f3ab15Sopenharmony_ci } 83692f3ab15Sopenharmony_ci 83792f3ab15Sopenharmony_ci /// Sets the mode used by the context, returning the previous mode. 83892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_mode)] 83992f3ab15Sopenharmony_ci pub fn set_mode(&mut self, mode: SslMode) -> SslMode { 84092f3ab15Sopenharmony_ci unsafe { 84192f3ab15Sopenharmony_ci let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType; 84292f3ab15Sopenharmony_ci SslMode { bits } 84392f3ab15Sopenharmony_ci } 84492f3ab15Sopenharmony_ci } 84592f3ab15Sopenharmony_ci 84692f3ab15Sopenharmony_ci /// Sets the parameters to be used during ephemeral Diffie-Hellman key exchange. 84792f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_tmp_dh)] 84892f3ab15Sopenharmony_ci pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> { 84992f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } 85092f3ab15Sopenharmony_ci } 85192f3ab15Sopenharmony_ci 85292f3ab15Sopenharmony_ci /// Sets the callback which will generate parameters to be used during ephemeral Diffie-Hellman 85392f3ab15Sopenharmony_ci /// key exchange. 85492f3ab15Sopenharmony_ci /// 85592f3ab15Sopenharmony_ci /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean 85692f3ab15Sopenharmony_ci /// indicating if the selected cipher is export-grade, and the key length. The export and key 85792f3ab15Sopenharmony_ci /// length options are archaic and should be ignored in almost all cases. 85892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_tmp_dh_callback)] 85992f3ab15Sopenharmony_ci pub fn set_tmp_dh_callback<F>(&mut self, callback: F) 86092f3ab15Sopenharmony_ci where 86192f3ab15Sopenharmony_ci F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, 86292f3ab15Sopenharmony_ci { 86392f3ab15Sopenharmony_ci unsafe { 86492f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 86592f3ab15Sopenharmony_ci 86692f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 86792f3ab15Sopenharmony_ci ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>)); 86892f3ab15Sopenharmony_ci #[cfg(boringssl)] 86992f3ab15Sopenharmony_ci ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>)); 87092f3ab15Sopenharmony_ci } 87192f3ab15Sopenharmony_ci } 87292f3ab15Sopenharmony_ci 87392f3ab15Sopenharmony_ci /// Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange. 87492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_tmp_ecdh)] 87592f3ab15Sopenharmony_ci pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> { 87692f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } 87792f3ab15Sopenharmony_ci } 87892f3ab15Sopenharmony_ci 87992f3ab15Sopenharmony_ci /// Sets the callback which will generate parameters to be used during ephemeral elliptic curve 88092f3ab15Sopenharmony_ci /// Diffie-Hellman key exchange. 88192f3ab15Sopenharmony_ci /// 88292f3ab15Sopenharmony_ci /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean 88392f3ab15Sopenharmony_ci /// indicating if the selected cipher is export-grade, and the key length. The export and key 88492f3ab15Sopenharmony_ci /// length options are archaic and should be ignored in almost all cases. 88592f3ab15Sopenharmony_ci /// 88692f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.1 or 1.0.2. 88792f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_tmp_ecdh_callback)] 88892f3ab15Sopenharmony_ci #[cfg(all(ossl101, not(ossl110)))] 88992f3ab15Sopenharmony_ci #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")] 89092f3ab15Sopenharmony_ci pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) 89192f3ab15Sopenharmony_ci where 89292f3ab15Sopenharmony_ci F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, 89392f3ab15Sopenharmony_ci { 89492f3ab15Sopenharmony_ci unsafe { 89592f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 89692f3ab15Sopenharmony_ci ffi::SSL_CTX_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh::<F>)); 89792f3ab15Sopenharmony_ci } 89892f3ab15Sopenharmony_ci } 89992f3ab15Sopenharmony_ci 90092f3ab15Sopenharmony_ci /// Use the default locations of trusted certificates for verification. 90192f3ab15Sopenharmony_ci /// 90292f3ab15Sopenharmony_ci /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` environment variables 90392f3ab15Sopenharmony_ci /// if present, or defaults specified at OpenSSL build time otherwise. 90492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_default_verify_paths)] 90592f3ab15Sopenharmony_ci pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { 90692f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) } 90792f3ab15Sopenharmony_ci } 90892f3ab15Sopenharmony_ci 90992f3ab15Sopenharmony_ci /// Loads trusted root certificates from a file. 91092f3ab15Sopenharmony_ci /// 91192f3ab15Sopenharmony_ci /// The file should contain a sequence of PEM-formatted CA certificates. 91292f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_load_verify_locations)] 91392f3ab15Sopenharmony_ci pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> { 91492f3ab15Sopenharmony_ci let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 91592f3ab15Sopenharmony_ci unsafe { 91692f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_load_verify_locations( 91792f3ab15Sopenharmony_ci self.as_ptr(), 91892f3ab15Sopenharmony_ci file.as_ptr() as *const _, 91992f3ab15Sopenharmony_ci ptr::null(), 92092f3ab15Sopenharmony_ci )) 92192f3ab15Sopenharmony_ci .map(|_| ()) 92292f3ab15Sopenharmony_ci } 92392f3ab15Sopenharmony_ci } 92492f3ab15Sopenharmony_ci 92592f3ab15Sopenharmony_ci /// Sets the list of CA names sent to the client. 92692f3ab15Sopenharmony_ci /// 92792f3ab15Sopenharmony_ci /// The CA certificates must still be added to the trust root - they are not automatically set 92892f3ab15Sopenharmony_ci /// as trusted by this method. 92992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_client_CA_list)] 93092f3ab15Sopenharmony_ci pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) { 93192f3ab15Sopenharmony_ci unsafe { 93292f3ab15Sopenharmony_ci ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr()); 93392f3ab15Sopenharmony_ci mem::forget(list); 93492f3ab15Sopenharmony_ci } 93592f3ab15Sopenharmony_ci } 93692f3ab15Sopenharmony_ci 93792f3ab15Sopenharmony_ci /// Add the provided CA certificate to the list sent by the server to the client when 93892f3ab15Sopenharmony_ci /// requesting client-side TLS authentication. 93992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_add_client_CA)] 94092f3ab15Sopenharmony_ci pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> { 94192f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) } 94292f3ab15Sopenharmony_ci } 94392f3ab15Sopenharmony_ci 94492f3ab15Sopenharmony_ci /// Set the context identifier for sessions. 94592f3ab15Sopenharmony_ci /// 94692f3ab15Sopenharmony_ci /// This value identifies the server's session cache to clients, telling them when they're 94792f3ab15Sopenharmony_ci /// able to reuse sessions. It should be set to a unique value per server, unless multiple 94892f3ab15Sopenharmony_ci /// servers share a session cache. 94992f3ab15Sopenharmony_ci /// 95092f3ab15Sopenharmony_ci /// This value should be set when using client certificates, or each request will fail its 95192f3ab15Sopenharmony_ci /// handshake and need to be restarted. 95292f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_session_id_context)] 95392f3ab15Sopenharmony_ci pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> { 95492f3ab15Sopenharmony_ci unsafe { 95592f3ab15Sopenharmony_ci assert!(sid_ctx.len() <= c_uint::max_value() as usize); 95692f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_set_session_id_context( 95792f3ab15Sopenharmony_ci self.as_ptr(), 95892f3ab15Sopenharmony_ci sid_ctx.as_ptr(), 95992f3ab15Sopenharmony_ci sid_ctx.len() as SizeTy, 96092f3ab15Sopenharmony_ci )) 96192f3ab15Sopenharmony_ci .map(|_| ()) 96292f3ab15Sopenharmony_ci } 96392f3ab15Sopenharmony_ci } 96492f3ab15Sopenharmony_ci 96592f3ab15Sopenharmony_ci /// Loads a leaf certificate from a file. 96692f3ab15Sopenharmony_ci /// 96792f3ab15Sopenharmony_ci /// Only a single certificate will be loaded - use `add_extra_chain_cert` to add the remainder 96892f3ab15Sopenharmony_ci /// of the certificate chain, or `set_certificate_chain_file` to load the entire chain from a 96992f3ab15Sopenharmony_ci /// single file. 97092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_use_certificate_file)] 97192f3ab15Sopenharmony_ci pub fn set_certificate_file<P: AsRef<Path>>( 97292f3ab15Sopenharmony_ci &mut self, 97392f3ab15Sopenharmony_ci file: P, 97492f3ab15Sopenharmony_ci file_type: SslFiletype, 97592f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 97692f3ab15Sopenharmony_ci let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 97792f3ab15Sopenharmony_ci unsafe { 97892f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_use_certificate_file( 97992f3ab15Sopenharmony_ci self.as_ptr(), 98092f3ab15Sopenharmony_ci file.as_ptr() as *const _, 98192f3ab15Sopenharmony_ci file_type.as_raw(), 98292f3ab15Sopenharmony_ci )) 98392f3ab15Sopenharmony_ci .map(|_| ()) 98492f3ab15Sopenharmony_ci } 98592f3ab15Sopenharmony_ci } 98692f3ab15Sopenharmony_ci 98792f3ab15Sopenharmony_ci /// Loads a certificate chain from a file. 98892f3ab15Sopenharmony_ci /// 98992f3ab15Sopenharmony_ci /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf 99092f3ab15Sopenharmony_ci /// certificate, and the remainder forming the chain of certificates up to and including the 99192f3ab15Sopenharmony_ci /// trusted root certificate. 99292f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_use_certificate_chain_file)] 99392f3ab15Sopenharmony_ci pub fn set_certificate_chain_file<P: AsRef<Path>>( 99492f3ab15Sopenharmony_ci &mut self, 99592f3ab15Sopenharmony_ci file: P, 99692f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 99792f3ab15Sopenharmony_ci let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 99892f3ab15Sopenharmony_ci unsafe { 99992f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_use_certificate_chain_file( 100092f3ab15Sopenharmony_ci self.as_ptr(), 100192f3ab15Sopenharmony_ci file.as_ptr() as *const _, 100292f3ab15Sopenharmony_ci )) 100392f3ab15Sopenharmony_ci .map(|_| ()) 100492f3ab15Sopenharmony_ci } 100592f3ab15Sopenharmony_ci } 100692f3ab15Sopenharmony_ci 100792f3ab15Sopenharmony_ci /// Sets the leaf certificate. 100892f3ab15Sopenharmony_ci /// 100992f3ab15Sopenharmony_ci /// Use `add_extra_chain_cert` to add the remainder of the certificate chain. 101092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_use_certificate)] 101192f3ab15Sopenharmony_ci pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { 101292f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) } 101392f3ab15Sopenharmony_ci } 101492f3ab15Sopenharmony_ci 101592f3ab15Sopenharmony_ci /// Appends a certificate to the certificate chain. 101692f3ab15Sopenharmony_ci /// 101792f3ab15Sopenharmony_ci /// This chain should contain all certificates necessary to go from the certificate specified by 101892f3ab15Sopenharmony_ci /// `set_certificate` to a trusted root. 101992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_add_extra_chain_cert)] 102092f3ab15Sopenharmony_ci pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { 102192f3ab15Sopenharmony_ci unsafe { 102292f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?; 102392f3ab15Sopenharmony_ci mem::forget(cert); 102492f3ab15Sopenharmony_ci Ok(()) 102592f3ab15Sopenharmony_ci } 102692f3ab15Sopenharmony_ci } 102792f3ab15Sopenharmony_ci 102892f3ab15Sopenharmony_ci /// Loads the private key from a file. 102992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_use_PrivateKey_file)] 103092f3ab15Sopenharmony_ci pub fn set_private_key_file<P: AsRef<Path>>( 103192f3ab15Sopenharmony_ci &mut self, 103292f3ab15Sopenharmony_ci file: P, 103392f3ab15Sopenharmony_ci file_type: SslFiletype, 103492f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 103592f3ab15Sopenharmony_ci let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 103692f3ab15Sopenharmony_ci unsafe { 103792f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_use_PrivateKey_file( 103892f3ab15Sopenharmony_ci self.as_ptr(), 103992f3ab15Sopenharmony_ci file.as_ptr() as *const _, 104092f3ab15Sopenharmony_ci file_type.as_raw(), 104192f3ab15Sopenharmony_ci )) 104292f3ab15Sopenharmony_ci .map(|_| ()) 104392f3ab15Sopenharmony_ci } 104492f3ab15Sopenharmony_ci } 104592f3ab15Sopenharmony_ci 104692f3ab15Sopenharmony_ci /// Sets the private key. 104792f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_use_PrivateKey)] 104892f3ab15Sopenharmony_ci pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> 104992f3ab15Sopenharmony_ci where 105092f3ab15Sopenharmony_ci T: HasPrivate, 105192f3ab15Sopenharmony_ci { 105292f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) } 105392f3ab15Sopenharmony_ci } 105492f3ab15Sopenharmony_ci 105592f3ab15Sopenharmony_ci /// Sets the list of supported ciphers for protocols before TLSv1.3. 105692f3ab15Sopenharmony_ci /// 105792f3ab15Sopenharmony_ci /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3. 105892f3ab15Sopenharmony_ci /// 105992f3ab15Sopenharmony_ci /// See [`ciphers`] for details on the format. 106092f3ab15Sopenharmony_ci /// 106192f3ab15Sopenharmony_ci /// [`ciphers`]: https://www.openssl.org/docs/manmaster/apps/ciphers.html 106292f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_cipher_list)] 106392f3ab15Sopenharmony_ci pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { 106492f3ab15Sopenharmony_ci let cipher_list = CString::new(cipher_list).unwrap(); 106592f3ab15Sopenharmony_ci unsafe { 106692f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_set_cipher_list( 106792f3ab15Sopenharmony_ci self.as_ptr(), 106892f3ab15Sopenharmony_ci cipher_list.as_ptr() as *const _, 106992f3ab15Sopenharmony_ci )) 107092f3ab15Sopenharmony_ci .map(|_| ()) 107192f3ab15Sopenharmony_ci } 107292f3ab15Sopenharmony_ci } 107392f3ab15Sopenharmony_ci 107492f3ab15Sopenharmony_ci /// Sets the list of supported ciphers for the TLSv1.3 protocol. 107592f3ab15Sopenharmony_ci /// 107692f3ab15Sopenharmony_ci /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3. 107792f3ab15Sopenharmony_ci /// 107892f3ab15Sopenharmony_ci /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of 107992f3ab15Sopenharmony_ci /// preference. 108092f3ab15Sopenharmony_ci /// 108192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 108292f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_ciphersuites)] 108392f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 108492f3ab15Sopenharmony_ci pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { 108592f3ab15Sopenharmony_ci let cipher_list = CString::new(cipher_list).unwrap(); 108692f3ab15Sopenharmony_ci unsafe { 108792f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_set_ciphersuites( 108892f3ab15Sopenharmony_ci self.as_ptr(), 108992f3ab15Sopenharmony_ci cipher_list.as_ptr() as *const _, 109092f3ab15Sopenharmony_ci )) 109192f3ab15Sopenharmony_ci .map(|_| ()) 109292f3ab15Sopenharmony_ci } 109392f3ab15Sopenharmony_ci } 109492f3ab15Sopenharmony_ci 109592f3ab15Sopenharmony_ci /// Enables ECDHE key exchange with an automatically chosen curve list. 109692f3ab15Sopenharmony_ci /// 109792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2. 109892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_ecdh_auto)] 109992f3ab15Sopenharmony_ci #[cfg(any(libressl, all(ossl102, not(ossl110))))] 110092f3ab15Sopenharmony_ci pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { 110192f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } 110292f3ab15Sopenharmony_ci } 110392f3ab15Sopenharmony_ci 110492f3ab15Sopenharmony_ci /// Sets the options used by the context, returning the old set. 110592f3ab15Sopenharmony_ci /// 110692f3ab15Sopenharmony_ci /// # Note 110792f3ab15Sopenharmony_ci /// 110892f3ab15Sopenharmony_ci /// This *enables* the specified options, but does not disable unspecified options. Use 110992f3ab15Sopenharmony_ci /// `clear_options` for that. 111092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_options)] 111192f3ab15Sopenharmony_ci pub fn set_options(&mut self, option: SslOptions) -> SslOptions { 111292f3ab15Sopenharmony_ci let bits = 111392f3ab15Sopenharmony_ci unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr; 111492f3ab15Sopenharmony_ci SslOptions { bits } 111592f3ab15Sopenharmony_ci } 111692f3ab15Sopenharmony_ci 111792f3ab15Sopenharmony_ci /// Returns the options used by the context. 111892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_options)] 111992f3ab15Sopenharmony_ci pub fn options(&self) -> SslOptions { 112092f3ab15Sopenharmony_ci let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr; 112192f3ab15Sopenharmony_ci SslOptions { bits } 112292f3ab15Sopenharmony_ci } 112392f3ab15Sopenharmony_ci 112492f3ab15Sopenharmony_ci /// Clears the options used by the context, returning the old set. 112592f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_clear_options)] 112692f3ab15Sopenharmony_ci pub fn clear_options(&mut self, option: SslOptions) -> SslOptions { 112792f3ab15Sopenharmony_ci let bits = 112892f3ab15Sopenharmony_ci unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr; 112992f3ab15Sopenharmony_ci SslOptions { bits } 113092f3ab15Sopenharmony_ci } 113192f3ab15Sopenharmony_ci 113292f3ab15Sopenharmony_ci /// Sets the minimum supported protocol version. 113392f3ab15Sopenharmony_ci /// 113492f3ab15Sopenharmony_ci /// A value of `None` will enable protocol versions down to the lowest version supported by 113592f3ab15Sopenharmony_ci /// OpenSSL. 113692f3ab15Sopenharmony_ci /// 113792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer. 113892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_min_proto_version)] 113992f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl261))] 114092f3ab15Sopenharmony_ci pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { 114192f3ab15Sopenharmony_ci unsafe { 114292f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_set_min_proto_version( 114392f3ab15Sopenharmony_ci self.as_ptr(), 114492f3ab15Sopenharmony_ci version.map_or(0, |v| v.0 as _), 114592f3ab15Sopenharmony_ci )) 114692f3ab15Sopenharmony_ci .map(|_| ()) 114792f3ab15Sopenharmony_ci } 114892f3ab15Sopenharmony_ci } 114992f3ab15Sopenharmony_ci 115092f3ab15Sopenharmony_ci /// Sets the maximum supported protocol version. 115192f3ab15Sopenharmony_ci /// 115292f3ab15Sopenharmony_ci /// A value of `None` will enable protocol versions up to the highest version supported by 115392f3ab15Sopenharmony_ci /// OpenSSL. 115492f3ab15Sopenharmony_ci /// 115592f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer. 115692f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_max_proto_version)] 115792f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl261))] 115892f3ab15Sopenharmony_ci pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { 115992f3ab15Sopenharmony_ci unsafe { 116092f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_set_max_proto_version( 116192f3ab15Sopenharmony_ci self.as_ptr(), 116292f3ab15Sopenharmony_ci version.map_or(0, |v| v.0 as _), 116392f3ab15Sopenharmony_ci )) 116492f3ab15Sopenharmony_ci .map(|_| ()) 116592f3ab15Sopenharmony_ci } 116692f3ab15Sopenharmony_ci } 116792f3ab15Sopenharmony_ci 116892f3ab15Sopenharmony_ci /// Gets the minimum supported protocol version. 116992f3ab15Sopenharmony_ci /// 117092f3ab15Sopenharmony_ci /// A value of `None` indicates that all versions down to the lowest version supported by 117192f3ab15Sopenharmony_ci /// OpenSSL are enabled. 117292f3ab15Sopenharmony_ci /// 117392f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer. 117492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_min_proto_version)] 117592f3ab15Sopenharmony_ci #[cfg(any(ossl110g, libressl270))] 117692f3ab15Sopenharmony_ci pub fn min_proto_version(&mut self) -> Option<SslVersion> { 117792f3ab15Sopenharmony_ci unsafe { 117892f3ab15Sopenharmony_ci let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr()); 117992f3ab15Sopenharmony_ci if r == 0 { 118092f3ab15Sopenharmony_ci None 118192f3ab15Sopenharmony_ci } else { 118292f3ab15Sopenharmony_ci Some(SslVersion(r)) 118392f3ab15Sopenharmony_ci } 118492f3ab15Sopenharmony_ci } 118592f3ab15Sopenharmony_ci } 118692f3ab15Sopenharmony_ci 118792f3ab15Sopenharmony_ci /// Gets the maximum supported protocol version. 118892f3ab15Sopenharmony_ci /// 118992f3ab15Sopenharmony_ci /// A value of `None` indicates that all versions up to the highest version supported by 119092f3ab15Sopenharmony_ci /// OpenSSL are enabled. 119192f3ab15Sopenharmony_ci /// 119292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer. 119392f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_max_proto_version)] 119492f3ab15Sopenharmony_ci #[cfg(any(ossl110g, libressl270))] 119592f3ab15Sopenharmony_ci pub fn max_proto_version(&mut self) -> Option<SslVersion> { 119692f3ab15Sopenharmony_ci unsafe { 119792f3ab15Sopenharmony_ci let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr()); 119892f3ab15Sopenharmony_ci if r == 0 { 119992f3ab15Sopenharmony_ci None 120092f3ab15Sopenharmony_ci } else { 120192f3ab15Sopenharmony_ci Some(SslVersion(r)) 120292f3ab15Sopenharmony_ci } 120392f3ab15Sopenharmony_ci } 120492f3ab15Sopenharmony_ci } 120592f3ab15Sopenharmony_ci 120692f3ab15Sopenharmony_ci /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN). 120792f3ab15Sopenharmony_ci /// 120892f3ab15Sopenharmony_ci /// The input must be in ALPN "wire format". It consists of a sequence of supported protocol 120992f3ab15Sopenharmony_ci /// names prefixed by their byte length. For example, the protocol list consisting of `spdy/1` 121092f3ab15Sopenharmony_ci /// and `http/1.1` is encoded as `b"\x06spdy/1\x08http/1.1"`. The protocols are ordered by 121192f3ab15Sopenharmony_ci /// preference. 121292f3ab15Sopenharmony_ci /// 121392f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 121492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_alpn_protos)] 121592f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 121692f3ab15Sopenharmony_ci pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> { 121792f3ab15Sopenharmony_ci unsafe { 121892f3ab15Sopenharmony_ci assert!(protocols.len() <= c_uint::max_value() as usize); 121992f3ab15Sopenharmony_ci let r = ffi::SSL_CTX_set_alpn_protos( 122092f3ab15Sopenharmony_ci self.as_ptr(), 122192f3ab15Sopenharmony_ci protocols.as_ptr(), 122292f3ab15Sopenharmony_ci protocols.len() as c_uint, 122392f3ab15Sopenharmony_ci ); 122492f3ab15Sopenharmony_ci // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D: 122592f3ab15Sopenharmony_ci if r == 0 { 122692f3ab15Sopenharmony_ci Ok(()) 122792f3ab15Sopenharmony_ci } else { 122892f3ab15Sopenharmony_ci Err(ErrorStack::get()) 122992f3ab15Sopenharmony_ci } 123092f3ab15Sopenharmony_ci } 123192f3ab15Sopenharmony_ci } 123292f3ab15Sopenharmony_ci 123392f3ab15Sopenharmony_ci /// Enables the DTLS extension "use_srtp" as defined in RFC5764. 123492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_tlsext_use_srtp)] 123592f3ab15Sopenharmony_ci pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> { 123692f3ab15Sopenharmony_ci unsafe { 123792f3ab15Sopenharmony_ci let cstr = CString::new(protocols).unwrap(); 123892f3ab15Sopenharmony_ci 123992f3ab15Sopenharmony_ci let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr()); 124092f3ab15Sopenharmony_ci // fun fact, set_tlsext_use_srtp has a reversed return code D: 124192f3ab15Sopenharmony_ci if r == 0 { 124292f3ab15Sopenharmony_ci Ok(()) 124392f3ab15Sopenharmony_ci } else { 124492f3ab15Sopenharmony_ci Err(ErrorStack::get()) 124592f3ab15Sopenharmony_ci } 124692f3ab15Sopenharmony_ci } 124792f3ab15Sopenharmony_ci } 124892f3ab15Sopenharmony_ci 124992f3ab15Sopenharmony_ci /// Sets the callback used by a server to select a protocol for Application Layer Protocol 125092f3ab15Sopenharmony_ci /// Negotiation (ALPN). 125192f3ab15Sopenharmony_ci /// 125292f3ab15Sopenharmony_ci /// The callback is provided with the client's protocol list in ALPN wire format. See the 125392f3ab15Sopenharmony_ci /// documentation for [`SslContextBuilder::set_alpn_protos`] for details. It should return one 125492f3ab15Sopenharmony_ci /// of those protocols on success. The [`select_next_proto`] function implements the standard 125592f3ab15Sopenharmony_ci /// protocol selection algorithm. 125692f3ab15Sopenharmony_ci /// 125792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 125892f3ab15Sopenharmony_ci /// 125992f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos 126092f3ab15Sopenharmony_ci /// [`select_next_proto`]: fn.select_next_proto.html 126192f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_alpn_select_cb)] 126292f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 126392f3ab15Sopenharmony_ci pub fn set_alpn_select_callback<F>(&mut self, callback: F) 126492f3ab15Sopenharmony_ci where 126592f3ab15Sopenharmony_ci F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send, 126692f3ab15Sopenharmony_ci { 126792f3ab15Sopenharmony_ci unsafe { 126892f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 126992f3ab15Sopenharmony_ci ffi::SSL_CTX_set_alpn_select_cb__fixed_rust( 127092f3ab15Sopenharmony_ci self.as_ptr(), 127192f3ab15Sopenharmony_ci Some(callbacks::raw_alpn_select::<F>), 127292f3ab15Sopenharmony_ci ptr::null_mut(), 127392f3ab15Sopenharmony_ci ); 127492f3ab15Sopenharmony_ci } 127592f3ab15Sopenharmony_ci } 127692f3ab15Sopenharmony_ci 127792f3ab15Sopenharmony_ci /// Checks for consistency between the private key and certificate. 127892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_check_private_key)] 127992f3ab15Sopenharmony_ci pub fn check_private_key(&self) -> Result<(), ErrorStack> { 128092f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) } 128192f3ab15Sopenharmony_ci } 128292f3ab15Sopenharmony_ci 128392f3ab15Sopenharmony_ci /// Returns a shared reference to the context's certificate store. 128492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_cert_store)] 128592f3ab15Sopenharmony_ci pub fn cert_store(&self) -> &X509StoreBuilderRef { 128692f3ab15Sopenharmony_ci unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } 128792f3ab15Sopenharmony_ci } 128892f3ab15Sopenharmony_ci 128992f3ab15Sopenharmony_ci /// Returns a mutable reference to the context's certificate store. 129092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_cert_store)] 129192f3ab15Sopenharmony_ci pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef { 129292f3ab15Sopenharmony_ci unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } 129392f3ab15Sopenharmony_ci } 129492f3ab15Sopenharmony_ci 129592f3ab15Sopenharmony_ci /// Returns a reference to the X509 verification configuration. 129692f3ab15Sopenharmony_ci /// 129792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 129892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get0_param)] 129992f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 130092f3ab15Sopenharmony_ci pub fn verify_param(&self) -> &X509VerifyParamRef { 130192f3ab15Sopenharmony_ci unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) } 130292f3ab15Sopenharmony_ci } 130392f3ab15Sopenharmony_ci 130492f3ab15Sopenharmony_ci /// Returns a mutable reference to the X509 verification configuration. 130592f3ab15Sopenharmony_ci /// 130692f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 130792f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get0_param)] 130892f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 130992f3ab15Sopenharmony_ci pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef { 131092f3ab15Sopenharmony_ci unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) } 131192f3ab15Sopenharmony_ci } 131292f3ab15Sopenharmony_ci 131392f3ab15Sopenharmony_ci /// Sets the callback dealing with OCSP stapling. 131492f3ab15Sopenharmony_ci /// 131592f3ab15Sopenharmony_ci /// On the client side, this callback is responsible for validating the OCSP status response 131692f3ab15Sopenharmony_ci /// returned by the server. The status may be retrieved with the `SslRef::ocsp_status` method. 131792f3ab15Sopenharmony_ci /// A response of `Ok(true)` indicates that the OCSP status is valid, and a response of 131892f3ab15Sopenharmony_ci /// `Ok(false)` indicates that the OCSP status is invalid and the handshake should be 131992f3ab15Sopenharmony_ci /// terminated. 132092f3ab15Sopenharmony_ci /// 132192f3ab15Sopenharmony_ci /// On the server side, this callback is responsible for setting the OCSP status response to be 132292f3ab15Sopenharmony_ci /// returned to clients. The status may be set with the `SslRef::set_ocsp_status` method. A 132392f3ab15Sopenharmony_ci /// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and 132492f3ab15Sopenharmony_ci /// `Ok(false)` indicates that the status should not be returned to the client. 132592f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_tlsext_status_cb)] 132692f3ab15Sopenharmony_ci pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack> 132792f3ab15Sopenharmony_ci where 132892f3ab15Sopenharmony_ci F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send, 132992f3ab15Sopenharmony_ci { 133092f3ab15Sopenharmony_ci unsafe { 133192f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 133292f3ab15Sopenharmony_ci cvt( 133392f3ab15Sopenharmony_ci ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>)) 133492f3ab15Sopenharmony_ci as c_int, 133592f3ab15Sopenharmony_ci ) 133692f3ab15Sopenharmony_ci .map(|_| ()) 133792f3ab15Sopenharmony_ci } 133892f3ab15Sopenharmony_ci } 133992f3ab15Sopenharmony_ci 134092f3ab15Sopenharmony_ci /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK client. 134192f3ab15Sopenharmony_ci /// 134292f3ab15Sopenharmony_ci /// The callback will be called with the SSL context, an identity hint if one was provided 134392f3ab15Sopenharmony_ci /// by the server, a mutable slice for each of the identity and pre-shared key bytes. The 134492f3ab15Sopenharmony_ci /// identity must be written as a null-terminated C string. 134592f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_psk_client_callback)] 134692f3ab15Sopenharmony_ci #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 134792f3ab15Sopenharmony_ci pub fn set_psk_client_callback<F>(&mut self, callback: F) 134892f3ab15Sopenharmony_ci where 134992f3ab15Sopenharmony_ci F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> 135092f3ab15Sopenharmony_ci + 'static 135192f3ab15Sopenharmony_ci + Sync 135292f3ab15Sopenharmony_ci + Send, 135392f3ab15Sopenharmony_ci { 135492f3ab15Sopenharmony_ci unsafe { 135592f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 135692f3ab15Sopenharmony_ci ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>)); 135792f3ab15Sopenharmony_ci } 135892f3ab15Sopenharmony_ci } 135992f3ab15Sopenharmony_ci 136092f3ab15Sopenharmony_ci #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")] 136192f3ab15Sopenharmony_ci #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 136292f3ab15Sopenharmony_ci pub fn set_psk_callback<F>(&mut self, callback: F) 136392f3ab15Sopenharmony_ci where 136492f3ab15Sopenharmony_ci F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> 136592f3ab15Sopenharmony_ci + 'static 136692f3ab15Sopenharmony_ci + Sync 136792f3ab15Sopenharmony_ci + Send, 136892f3ab15Sopenharmony_ci { 136992f3ab15Sopenharmony_ci self.set_psk_client_callback(callback) 137092f3ab15Sopenharmony_ci } 137192f3ab15Sopenharmony_ci 137292f3ab15Sopenharmony_ci /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK server. 137392f3ab15Sopenharmony_ci /// 137492f3ab15Sopenharmony_ci /// The callback will be called with the SSL context, an identity provided by the client, 137592f3ab15Sopenharmony_ci /// and, a mutable slice for the pre-shared key bytes. The callback returns the number of 137692f3ab15Sopenharmony_ci /// bytes in the pre-shared key. 137792f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_psk_server_callback)] 137892f3ab15Sopenharmony_ci #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 137992f3ab15Sopenharmony_ci pub fn set_psk_server_callback<F>(&mut self, callback: F) 138092f3ab15Sopenharmony_ci where 138192f3ab15Sopenharmony_ci F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack> 138292f3ab15Sopenharmony_ci + 'static 138392f3ab15Sopenharmony_ci + Sync 138492f3ab15Sopenharmony_ci + Send, 138592f3ab15Sopenharmony_ci { 138692f3ab15Sopenharmony_ci unsafe { 138792f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 138892f3ab15Sopenharmony_ci ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>)); 138992f3ab15Sopenharmony_ci } 139092f3ab15Sopenharmony_ci } 139192f3ab15Sopenharmony_ci 139292f3ab15Sopenharmony_ci /// Sets the callback which is called when new sessions are negotiated. 139392f3ab15Sopenharmony_ci /// 139492f3ab15Sopenharmony_ci /// This can be used by clients to implement session caching. While in TLSv1.2 the session is 139592f3ab15Sopenharmony_ci /// available to access via [`SslRef::session`] immediately after the handshake completes, this 139692f3ab15Sopenharmony_ci /// is not the case for TLSv1.3. There, a session is not generally available immediately, and 139792f3ab15Sopenharmony_ci /// the server may provide multiple session tokens to the client over a single session. The new 139892f3ab15Sopenharmony_ci /// session callback is a portable way to deal with both cases. 139992f3ab15Sopenharmony_ci /// 140092f3ab15Sopenharmony_ci /// Note that session caching must be enabled for the callback to be invoked, and it defaults 140192f3ab15Sopenharmony_ci /// off for clients. [`set_session_cache_mode`] controls that behavior. 140292f3ab15Sopenharmony_ci /// 140392f3ab15Sopenharmony_ci /// [`SslRef::session`]: struct.SslRef.html#method.session 140492f3ab15Sopenharmony_ci /// [`set_session_cache_mode`]: #method.set_session_cache_mode 140592f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_sess_set_new_cb)] 140692f3ab15Sopenharmony_ci pub fn set_new_session_callback<F>(&mut self, callback: F) 140792f3ab15Sopenharmony_ci where 140892f3ab15Sopenharmony_ci F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send, 140992f3ab15Sopenharmony_ci { 141092f3ab15Sopenharmony_ci unsafe { 141192f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 141292f3ab15Sopenharmony_ci ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>)); 141392f3ab15Sopenharmony_ci } 141492f3ab15Sopenharmony_ci } 141592f3ab15Sopenharmony_ci 141692f3ab15Sopenharmony_ci /// Sets the callback which is called when sessions are removed from the context. 141792f3ab15Sopenharmony_ci /// 141892f3ab15Sopenharmony_ci /// Sessions can be removed because they have timed out or because they are considered faulty. 141992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_sess_set_remove_cb)] 142092f3ab15Sopenharmony_ci pub fn set_remove_session_callback<F>(&mut self, callback: F) 142192f3ab15Sopenharmony_ci where 142292f3ab15Sopenharmony_ci F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send, 142392f3ab15Sopenharmony_ci { 142492f3ab15Sopenharmony_ci unsafe { 142592f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 142692f3ab15Sopenharmony_ci ffi::SSL_CTX_sess_set_remove_cb( 142792f3ab15Sopenharmony_ci self.as_ptr(), 142892f3ab15Sopenharmony_ci Some(callbacks::raw_remove_session::<F>), 142992f3ab15Sopenharmony_ci ); 143092f3ab15Sopenharmony_ci } 143192f3ab15Sopenharmony_ci } 143292f3ab15Sopenharmony_ci 143392f3ab15Sopenharmony_ci /// Sets the callback which is called when a client proposed to resume a session but it was not 143492f3ab15Sopenharmony_ci /// found in the internal cache. 143592f3ab15Sopenharmony_ci /// 143692f3ab15Sopenharmony_ci /// The callback is passed a reference to the session ID provided by the client. It should 143792f3ab15Sopenharmony_ci /// return the session corresponding to that ID if available. This is only used for servers, not 143892f3ab15Sopenharmony_ci /// clients. 143992f3ab15Sopenharmony_ci /// 144092f3ab15Sopenharmony_ci /// # Safety 144192f3ab15Sopenharmony_ci /// 144292f3ab15Sopenharmony_ci /// The returned `SslSession` must not be associated with a different `SslContext`. 144392f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_sess_set_get_cb)] 144492f3ab15Sopenharmony_ci pub unsafe fn set_get_session_callback<F>(&mut self, callback: F) 144592f3ab15Sopenharmony_ci where 144692f3ab15Sopenharmony_ci F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send, 144792f3ab15Sopenharmony_ci { 144892f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 144992f3ab15Sopenharmony_ci ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>)); 145092f3ab15Sopenharmony_ci } 145192f3ab15Sopenharmony_ci 145292f3ab15Sopenharmony_ci /// Sets the TLS key logging callback. 145392f3ab15Sopenharmony_ci /// 145492f3ab15Sopenharmony_ci /// The callback is invoked whenever TLS key material is generated, and is passed a line of NSS 145592f3ab15Sopenharmony_ci /// SSLKEYLOGFILE-formatted text. This can be used by tools like Wireshark to decrypt message 145692f3ab15Sopenharmony_ci /// traffic. The line does not contain a trailing newline. 145792f3ab15Sopenharmony_ci /// 145892f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 145992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_keylog_callback)] 146092f3ab15Sopenharmony_ci #[cfg(ossl111)] 146192f3ab15Sopenharmony_ci pub fn set_keylog_callback<F>(&mut self, callback: F) 146292f3ab15Sopenharmony_ci where 146392f3ab15Sopenharmony_ci F: Fn(&SslRef, &str) + 'static + Sync + Send, 146492f3ab15Sopenharmony_ci { 146592f3ab15Sopenharmony_ci unsafe { 146692f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 146792f3ab15Sopenharmony_ci ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>)); 146892f3ab15Sopenharmony_ci } 146992f3ab15Sopenharmony_ci } 147092f3ab15Sopenharmony_ci 147192f3ab15Sopenharmony_ci /// Sets the session caching mode use for connections made with the context. 147292f3ab15Sopenharmony_ci /// 147392f3ab15Sopenharmony_ci /// Returns the previous session caching mode. 147492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_session_cache_mode)] 147592f3ab15Sopenharmony_ci pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode { 147692f3ab15Sopenharmony_ci unsafe { 147792f3ab15Sopenharmony_ci let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits()); 147892f3ab15Sopenharmony_ci SslSessionCacheMode { bits } 147992f3ab15Sopenharmony_ci } 148092f3ab15Sopenharmony_ci } 148192f3ab15Sopenharmony_ci 148292f3ab15Sopenharmony_ci /// Sets the callback for generating an application cookie for TLS1.3 148392f3ab15Sopenharmony_ci /// stateless handshakes. 148492f3ab15Sopenharmony_ci /// 148592f3ab15Sopenharmony_ci /// The callback will be called with the SSL context and a slice into which the cookie 148692f3ab15Sopenharmony_ci /// should be written. The callback should return the number of bytes written. 148792f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)] 148892f3ab15Sopenharmony_ci #[cfg(ossl111)] 148992f3ab15Sopenharmony_ci pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F) 149092f3ab15Sopenharmony_ci where 149192f3ab15Sopenharmony_ci F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, 149292f3ab15Sopenharmony_ci { 149392f3ab15Sopenharmony_ci unsafe { 149492f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 149592f3ab15Sopenharmony_ci ffi::SSL_CTX_set_stateless_cookie_generate_cb( 149692f3ab15Sopenharmony_ci self.as_ptr(), 149792f3ab15Sopenharmony_ci Some(raw_stateless_cookie_generate::<F>), 149892f3ab15Sopenharmony_ci ); 149992f3ab15Sopenharmony_ci } 150092f3ab15Sopenharmony_ci } 150192f3ab15Sopenharmony_ci 150292f3ab15Sopenharmony_ci /// Sets the callback for verifying an application cookie for TLS1.3 150392f3ab15Sopenharmony_ci /// stateless handshakes. 150492f3ab15Sopenharmony_ci /// 150592f3ab15Sopenharmony_ci /// The callback will be called with the SSL context and the cookie supplied by the 150692f3ab15Sopenharmony_ci /// client. It should return true if and only if the cookie is valid. 150792f3ab15Sopenharmony_ci /// 150892f3ab15Sopenharmony_ci /// Note that the OpenSSL implementation independently verifies the integrity of 150992f3ab15Sopenharmony_ci /// application cookies using an HMAC before invoking the supplied callback. 151092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)] 151192f3ab15Sopenharmony_ci #[cfg(ossl111)] 151292f3ab15Sopenharmony_ci pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F) 151392f3ab15Sopenharmony_ci where 151492f3ab15Sopenharmony_ci F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, 151592f3ab15Sopenharmony_ci { 151692f3ab15Sopenharmony_ci unsafe { 151792f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 151892f3ab15Sopenharmony_ci ffi::SSL_CTX_set_stateless_cookie_verify_cb( 151992f3ab15Sopenharmony_ci self.as_ptr(), 152092f3ab15Sopenharmony_ci Some(raw_stateless_cookie_verify::<F>), 152192f3ab15Sopenharmony_ci ) 152292f3ab15Sopenharmony_ci } 152392f3ab15Sopenharmony_ci } 152492f3ab15Sopenharmony_ci 152592f3ab15Sopenharmony_ci /// Sets the callback for generating a DTLSv1 cookie 152692f3ab15Sopenharmony_ci /// 152792f3ab15Sopenharmony_ci /// The callback will be called with the SSL context and a slice into which the cookie 152892f3ab15Sopenharmony_ci /// should be written. The callback should return the number of bytes written. 152992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_cookie_generate_cb)] 153092f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 153192f3ab15Sopenharmony_ci pub fn set_cookie_generate_cb<F>(&mut self, callback: F) 153292f3ab15Sopenharmony_ci where 153392f3ab15Sopenharmony_ci F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, 153492f3ab15Sopenharmony_ci { 153592f3ab15Sopenharmony_ci unsafe { 153692f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 153792f3ab15Sopenharmony_ci ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>)); 153892f3ab15Sopenharmony_ci } 153992f3ab15Sopenharmony_ci } 154092f3ab15Sopenharmony_ci 154192f3ab15Sopenharmony_ci /// Sets the callback for verifying a DTLSv1 cookie 154292f3ab15Sopenharmony_ci /// 154392f3ab15Sopenharmony_ci /// The callback will be called with the SSL context and the cookie supplied by the 154492f3ab15Sopenharmony_ci /// client. It should return true if and only if the cookie is valid. 154592f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_cookie_verify_cb)] 154692f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 154792f3ab15Sopenharmony_ci pub fn set_cookie_verify_cb<F>(&mut self, callback: F) 154892f3ab15Sopenharmony_ci where 154992f3ab15Sopenharmony_ci F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, 155092f3ab15Sopenharmony_ci { 155192f3ab15Sopenharmony_ci unsafe { 155292f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 155392f3ab15Sopenharmony_ci ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>)); 155492f3ab15Sopenharmony_ci } 155592f3ab15Sopenharmony_ci } 155692f3ab15Sopenharmony_ci 155792f3ab15Sopenharmony_ci /// Sets the extra data at the specified index. 155892f3ab15Sopenharmony_ci /// 155992f3ab15Sopenharmony_ci /// This can be used to provide data to callbacks registered with the context. Use the 156092f3ab15Sopenharmony_ci /// `SslContext::new_ex_index` method to create an `Index`. 156192f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_ex_data)] 156292f3ab15Sopenharmony_ci pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) { 156392f3ab15Sopenharmony_ci self.set_ex_data_inner(index, data); 156492f3ab15Sopenharmony_ci } 156592f3ab15Sopenharmony_ci 156692f3ab15Sopenharmony_ci fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void { 156792f3ab15Sopenharmony_ci unsafe { 156892f3ab15Sopenharmony_ci let data = Box::into_raw(Box::new(data)) as *mut c_void; 156992f3ab15Sopenharmony_ci ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data); 157092f3ab15Sopenharmony_ci data 157192f3ab15Sopenharmony_ci } 157292f3ab15Sopenharmony_ci } 157392f3ab15Sopenharmony_ci 157492f3ab15Sopenharmony_ci /// Adds a custom extension for a TLS/DTLS client or server for all supported protocol versions. 157592f3ab15Sopenharmony_ci /// 157692f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 157792f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_add_custom_ext)] 157892f3ab15Sopenharmony_ci #[cfg(ossl111)] 157992f3ab15Sopenharmony_ci pub fn add_custom_ext<AddFn, ParseFn, T>( 158092f3ab15Sopenharmony_ci &mut self, 158192f3ab15Sopenharmony_ci ext_type: u16, 158292f3ab15Sopenharmony_ci context: ExtensionContext, 158392f3ab15Sopenharmony_ci add_cb: AddFn, 158492f3ab15Sopenharmony_ci parse_cb: ParseFn, 158592f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> 158692f3ab15Sopenharmony_ci where 158792f3ab15Sopenharmony_ci AddFn: Fn( 158892f3ab15Sopenharmony_ci &mut SslRef, 158992f3ab15Sopenharmony_ci ExtensionContext, 159092f3ab15Sopenharmony_ci Option<(usize, &X509Ref)>, 159192f3ab15Sopenharmony_ci ) -> Result<Option<T>, SslAlert> 159292f3ab15Sopenharmony_ci + 'static 159392f3ab15Sopenharmony_ci + Sync 159492f3ab15Sopenharmony_ci + Send, 159592f3ab15Sopenharmony_ci T: AsRef<[u8]> + 'static + Sync + Send, 159692f3ab15Sopenharmony_ci ParseFn: Fn( 159792f3ab15Sopenharmony_ci &mut SslRef, 159892f3ab15Sopenharmony_ci ExtensionContext, 159992f3ab15Sopenharmony_ci &[u8], 160092f3ab15Sopenharmony_ci Option<(usize, &X509Ref)>, 160192f3ab15Sopenharmony_ci ) -> Result<(), SslAlert> 160292f3ab15Sopenharmony_ci + 'static 160392f3ab15Sopenharmony_ci + Sync 160492f3ab15Sopenharmony_ci + Send, 160592f3ab15Sopenharmony_ci { 160692f3ab15Sopenharmony_ci let ret = unsafe { 160792f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb); 160892f3ab15Sopenharmony_ci self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb); 160992f3ab15Sopenharmony_ci 161092f3ab15Sopenharmony_ci ffi::SSL_CTX_add_custom_ext( 161192f3ab15Sopenharmony_ci self.as_ptr(), 161292f3ab15Sopenharmony_ci ext_type as c_uint, 161392f3ab15Sopenharmony_ci context.bits(), 161492f3ab15Sopenharmony_ci Some(raw_custom_ext_add::<AddFn, T>), 161592f3ab15Sopenharmony_ci Some(raw_custom_ext_free::<T>), 161692f3ab15Sopenharmony_ci ptr::null_mut(), 161792f3ab15Sopenharmony_ci Some(raw_custom_ext_parse::<ParseFn>), 161892f3ab15Sopenharmony_ci ptr::null_mut(), 161992f3ab15Sopenharmony_ci ) 162092f3ab15Sopenharmony_ci }; 162192f3ab15Sopenharmony_ci if ret == 1 { 162292f3ab15Sopenharmony_ci Ok(()) 162392f3ab15Sopenharmony_ci } else { 162492f3ab15Sopenharmony_ci Err(ErrorStack::get()) 162592f3ab15Sopenharmony_ci } 162692f3ab15Sopenharmony_ci } 162792f3ab15Sopenharmony_ci 162892f3ab15Sopenharmony_ci /// Sets the maximum amount of early data that will be accepted on incoming connections. 162992f3ab15Sopenharmony_ci /// 163092f3ab15Sopenharmony_ci /// Defaults to 0. 163192f3ab15Sopenharmony_ci /// 163292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 163392f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_max_early_data)] 163492f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 163592f3ab15Sopenharmony_ci pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> { 163692f3ab15Sopenharmony_ci if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 { 163792f3ab15Sopenharmony_ci Ok(()) 163892f3ab15Sopenharmony_ci } else { 163992f3ab15Sopenharmony_ci Err(ErrorStack::get()) 164092f3ab15Sopenharmony_ci } 164192f3ab15Sopenharmony_ci } 164292f3ab15Sopenharmony_ci 164392f3ab15Sopenharmony_ci /// Sets a callback which will be invoked just after the client's hello message is received. 164492f3ab15Sopenharmony_ci /// 164592f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 164692f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_client_hello_cb)] 164792f3ab15Sopenharmony_ci #[cfg(ossl111)] 164892f3ab15Sopenharmony_ci pub fn set_client_hello_callback<F>(&mut self, callback: F) 164992f3ab15Sopenharmony_ci where 165092f3ab15Sopenharmony_ci F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack> 165192f3ab15Sopenharmony_ci + 'static 165292f3ab15Sopenharmony_ci + Sync 165392f3ab15Sopenharmony_ci + Send, 165492f3ab15Sopenharmony_ci { 165592f3ab15Sopenharmony_ci unsafe { 165692f3ab15Sopenharmony_ci let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback); 165792f3ab15Sopenharmony_ci ffi::SSL_CTX_set_client_hello_cb( 165892f3ab15Sopenharmony_ci self.as_ptr(), 165992f3ab15Sopenharmony_ci Some(callbacks::raw_client_hello::<F>), 166092f3ab15Sopenharmony_ci ptr, 166192f3ab15Sopenharmony_ci ); 166292f3ab15Sopenharmony_ci } 166392f3ab15Sopenharmony_ci } 166492f3ab15Sopenharmony_ci 166592f3ab15Sopenharmony_ci /// Sets the context's session cache size limit, returning the previous limit. 166692f3ab15Sopenharmony_ci /// 166792f3ab15Sopenharmony_ci /// A value of 0 means that the cache size is unbounded. 166892f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_sess_set_cache_size)] 166992f3ab15Sopenharmony_ci #[allow(clippy::useless_conversion)] 167092f3ab15Sopenharmony_ci pub fn set_session_cache_size(&mut self, size: i32) -> i64 { 167192f3ab15Sopenharmony_ci unsafe { 167292f3ab15Sopenharmony_ci ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy 167392f3ab15Sopenharmony_ci } 167492f3ab15Sopenharmony_ci } 167592f3ab15Sopenharmony_ci 167692f3ab15Sopenharmony_ci /// Sets the context's supported signature algorithms. 167792f3ab15Sopenharmony_ci /// 167892f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 167992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set1_sigalgs_list)] 168092f3ab15Sopenharmony_ci #[cfg(ossl102)] 168192f3ab15Sopenharmony_ci pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> { 168292f3ab15Sopenharmony_ci let sigalgs = CString::new(sigalgs).unwrap(); 168392f3ab15Sopenharmony_ci unsafe { 168492f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int) 168592f3ab15Sopenharmony_ci .map(|_| ()) 168692f3ab15Sopenharmony_ci } 168792f3ab15Sopenharmony_ci } 168892f3ab15Sopenharmony_ci 168992f3ab15Sopenharmony_ci /// Sets the context's supported elliptic curve groups. 169092f3ab15Sopenharmony_ci /// 169192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 2.5.1 or newer. 169292f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set1_groups_list)] 169392f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl251))] 169492f3ab15Sopenharmony_ci pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> { 169592f3ab15Sopenharmony_ci let groups = CString::new(groups).unwrap(); 169692f3ab15Sopenharmony_ci unsafe { 169792f3ab15Sopenharmony_ci cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ()) 169892f3ab15Sopenharmony_ci } 169992f3ab15Sopenharmony_ci } 170092f3ab15Sopenharmony_ci 170192f3ab15Sopenharmony_ci /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full 170292f3ab15Sopenharmony_ci /// handshake. 170392f3ab15Sopenharmony_ci /// 170492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 170592f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_set_num_tickets)] 170692f3ab15Sopenharmony_ci #[cfg(ossl111)] 170792f3ab15Sopenharmony_ci pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> { 170892f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) } 170992f3ab15Sopenharmony_ci } 171092f3ab15Sopenharmony_ci 171192f3ab15Sopenharmony_ci /// Consumes the builder, returning a new `SslContext`. 171292f3ab15Sopenharmony_ci pub fn build(self) -> SslContext { 171392f3ab15Sopenharmony_ci self.0 171492f3ab15Sopenharmony_ci } 171592f3ab15Sopenharmony_ci} 171692f3ab15Sopenharmony_ci 171792f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 171892f3ab15Sopenharmony_ci type CType = ffi::SSL_CTX; 171992f3ab15Sopenharmony_ci fn drop = ffi::SSL_CTX_free; 172092f3ab15Sopenharmony_ci 172192f3ab15Sopenharmony_ci /// A context object for TLS streams. 172292f3ab15Sopenharmony_ci /// 172392f3ab15Sopenharmony_ci /// Applications commonly configure a single `SslContext` that is shared by all of its 172492f3ab15Sopenharmony_ci /// `SslStreams`. 172592f3ab15Sopenharmony_ci pub struct SslContext; 172692f3ab15Sopenharmony_ci 172792f3ab15Sopenharmony_ci /// Reference to [`SslContext`] 172892f3ab15Sopenharmony_ci /// 172992f3ab15Sopenharmony_ci /// [`SslContext`]: struct.SslContext.html 173092f3ab15Sopenharmony_ci pub struct SslContextRef; 173192f3ab15Sopenharmony_ci} 173292f3ab15Sopenharmony_ci 173392f3ab15Sopenharmony_ciimpl Clone for SslContext { 173492f3ab15Sopenharmony_ci fn clone(&self) -> Self { 173592f3ab15Sopenharmony_ci (**self).to_owned() 173692f3ab15Sopenharmony_ci } 173792f3ab15Sopenharmony_ci} 173892f3ab15Sopenharmony_ci 173992f3ab15Sopenharmony_ciimpl ToOwned for SslContextRef { 174092f3ab15Sopenharmony_ci type Owned = SslContext; 174192f3ab15Sopenharmony_ci 174292f3ab15Sopenharmony_ci fn to_owned(&self) -> Self::Owned { 174392f3ab15Sopenharmony_ci unsafe { 174492f3ab15Sopenharmony_ci SSL_CTX_up_ref(self.as_ptr()); 174592f3ab15Sopenharmony_ci SslContext::from_ptr(self.as_ptr()) 174692f3ab15Sopenharmony_ci } 174792f3ab15Sopenharmony_ci } 174892f3ab15Sopenharmony_ci} 174992f3ab15Sopenharmony_ci 175092f3ab15Sopenharmony_ci// TODO: add useful info here 175192f3ab15Sopenharmony_ciimpl fmt::Debug for SslContext { 175292f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 175392f3ab15Sopenharmony_ci write!(fmt, "SslContext") 175492f3ab15Sopenharmony_ci } 175592f3ab15Sopenharmony_ci} 175692f3ab15Sopenharmony_ci 175792f3ab15Sopenharmony_ciimpl SslContext { 175892f3ab15Sopenharmony_ci /// Creates a new builder object for an `SslContext`. 175992f3ab15Sopenharmony_ci pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> { 176092f3ab15Sopenharmony_ci SslContextBuilder::new(method) 176192f3ab15Sopenharmony_ci } 176292f3ab15Sopenharmony_ci 176392f3ab15Sopenharmony_ci /// Returns a new extra data index. 176492f3ab15Sopenharmony_ci /// 176592f3ab15Sopenharmony_ci /// Each invocation of this function is guaranteed to return a distinct index. These can be used 176692f3ab15Sopenharmony_ci /// to store data in the context that can be retrieved later by callbacks, for example. 176792f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_ex_new_index)] 176892f3ab15Sopenharmony_ci pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack> 176992f3ab15Sopenharmony_ci where 177092f3ab15Sopenharmony_ci T: 'static + Sync + Send, 177192f3ab15Sopenharmony_ci { 177292f3ab15Sopenharmony_ci unsafe { 177392f3ab15Sopenharmony_ci ffi::init(); 177492f3ab15Sopenharmony_ci #[cfg(boringssl)] 177592f3ab15Sopenharmony_ci let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?; 177692f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 177792f3ab15Sopenharmony_ci let idx = cvt_n(get_new_idx(free_data_box::<T>))?; 177892f3ab15Sopenharmony_ci Ok(Index::from_raw(idx)) 177992f3ab15Sopenharmony_ci } 178092f3ab15Sopenharmony_ci } 178192f3ab15Sopenharmony_ci 178292f3ab15Sopenharmony_ci // FIXME should return a result? 178392f3ab15Sopenharmony_ci fn cached_ex_index<T>() -> Index<SslContext, T> 178492f3ab15Sopenharmony_ci where 178592f3ab15Sopenharmony_ci T: 'static + Sync + Send, 178692f3ab15Sopenharmony_ci { 178792f3ab15Sopenharmony_ci unsafe { 178892f3ab15Sopenharmony_ci let idx = *INDEXES 178992f3ab15Sopenharmony_ci .lock() 179092f3ab15Sopenharmony_ci .unwrap_or_else(|e| e.into_inner()) 179192f3ab15Sopenharmony_ci .entry(TypeId::of::<T>()) 179292f3ab15Sopenharmony_ci .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw()); 179392f3ab15Sopenharmony_ci Index::from_raw(idx) 179492f3ab15Sopenharmony_ci } 179592f3ab15Sopenharmony_ci } 179692f3ab15Sopenharmony_ci} 179792f3ab15Sopenharmony_ci 179892f3ab15Sopenharmony_ciimpl SslContextRef { 179992f3ab15Sopenharmony_ci /// Returns the certificate associated with this `SslContext`, if present. 180092f3ab15Sopenharmony_ci /// 180192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL 2.7.0 or newer. 180292f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get0_certificate)] 180392f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl270))] 180492f3ab15Sopenharmony_ci pub fn certificate(&self) -> Option<&X509Ref> { 180592f3ab15Sopenharmony_ci unsafe { 180692f3ab15Sopenharmony_ci let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr()); 180792f3ab15Sopenharmony_ci X509Ref::from_const_ptr_opt(ptr) 180892f3ab15Sopenharmony_ci } 180992f3ab15Sopenharmony_ci } 181092f3ab15Sopenharmony_ci 181192f3ab15Sopenharmony_ci /// Returns the private key associated with this `SslContext`, if present. 181292f3ab15Sopenharmony_ci /// 181392f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL 3.4.0 or newer. 181492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get0_privatekey)] 181592f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl340))] 181692f3ab15Sopenharmony_ci pub fn private_key(&self) -> Option<&PKeyRef<Private>> { 181792f3ab15Sopenharmony_ci unsafe { 181892f3ab15Sopenharmony_ci let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr()); 181992f3ab15Sopenharmony_ci PKeyRef::from_const_ptr_opt(ptr) 182092f3ab15Sopenharmony_ci } 182192f3ab15Sopenharmony_ci } 182292f3ab15Sopenharmony_ci 182392f3ab15Sopenharmony_ci /// Returns a shared reference to the certificate store used for verification. 182492f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_cert_store)] 182592f3ab15Sopenharmony_ci pub fn cert_store(&self) -> &X509StoreRef { 182692f3ab15Sopenharmony_ci unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } 182792f3ab15Sopenharmony_ci } 182892f3ab15Sopenharmony_ci 182992f3ab15Sopenharmony_ci /// Returns a shared reference to the stack of certificates making up the chain from the leaf. 183092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_extra_chain_certs)] 183192f3ab15Sopenharmony_ci pub fn extra_chain_certs(&self) -> &StackRef<X509> { 183292f3ab15Sopenharmony_ci unsafe { 183392f3ab15Sopenharmony_ci let mut chain = ptr::null_mut(); 183492f3ab15Sopenharmony_ci ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain); 183592f3ab15Sopenharmony_ci StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null") 183692f3ab15Sopenharmony_ci } 183792f3ab15Sopenharmony_ci } 183892f3ab15Sopenharmony_ci 183992f3ab15Sopenharmony_ci /// Returns a reference to the extra data at the specified index. 184092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_ex_data)] 184192f3ab15Sopenharmony_ci pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> { 184292f3ab15Sopenharmony_ci unsafe { 184392f3ab15Sopenharmony_ci let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw()); 184492f3ab15Sopenharmony_ci if data.is_null() { 184592f3ab15Sopenharmony_ci None 184692f3ab15Sopenharmony_ci } else { 184792f3ab15Sopenharmony_ci Some(&*(data as *const T)) 184892f3ab15Sopenharmony_ci } 184992f3ab15Sopenharmony_ci } 185092f3ab15Sopenharmony_ci } 185192f3ab15Sopenharmony_ci 185292f3ab15Sopenharmony_ci /// Gets the maximum amount of early data that will be accepted on incoming connections. 185392f3ab15Sopenharmony_ci /// 185492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 185592f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_max_early_data)] 185692f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 185792f3ab15Sopenharmony_ci pub fn max_early_data(&self) -> u32 { 185892f3ab15Sopenharmony_ci unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) } 185992f3ab15Sopenharmony_ci } 186092f3ab15Sopenharmony_ci 186192f3ab15Sopenharmony_ci /// Adds a session to the context's cache. 186292f3ab15Sopenharmony_ci /// 186392f3ab15Sopenharmony_ci /// Returns `true` if the session was successfully added to the cache, and `false` if it was already present. 186492f3ab15Sopenharmony_ci /// 186592f3ab15Sopenharmony_ci /// # Safety 186692f3ab15Sopenharmony_ci /// 186792f3ab15Sopenharmony_ci /// The caller of this method is responsible for ensuring that the session has never been used with another 186892f3ab15Sopenharmony_ci /// `SslContext` than this one. 186992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_add_session)] 187092f3ab15Sopenharmony_ci pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool { 187192f3ab15Sopenharmony_ci ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0 187292f3ab15Sopenharmony_ci } 187392f3ab15Sopenharmony_ci 187492f3ab15Sopenharmony_ci /// Removes a session from the context's cache and marks it as non-resumable. 187592f3ab15Sopenharmony_ci /// 187692f3ab15Sopenharmony_ci /// Returns `true` if the session was successfully found and removed, and `false` otherwise. 187792f3ab15Sopenharmony_ci /// 187892f3ab15Sopenharmony_ci /// # Safety 187992f3ab15Sopenharmony_ci /// 188092f3ab15Sopenharmony_ci /// The caller of this method is responsible for ensuring that the session has never been used with another 188192f3ab15Sopenharmony_ci /// `SslContext` than this one. 188292f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_remove_session)] 188392f3ab15Sopenharmony_ci pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool { 188492f3ab15Sopenharmony_ci ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0 188592f3ab15Sopenharmony_ci } 188692f3ab15Sopenharmony_ci 188792f3ab15Sopenharmony_ci /// Returns the context's session cache size limit. 188892f3ab15Sopenharmony_ci /// 188992f3ab15Sopenharmony_ci /// A value of 0 means that the cache size is unbounded. 189092f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_sess_get_cache_size)] 189192f3ab15Sopenharmony_ci #[allow(clippy::unnecessary_cast)] 189292f3ab15Sopenharmony_ci pub fn session_cache_size(&self) -> i64 { 189392f3ab15Sopenharmony_ci unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 } 189492f3ab15Sopenharmony_ci } 189592f3ab15Sopenharmony_ci 189692f3ab15Sopenharmony_ci /// Returns the verify mode that was set on this context from [`SslContextBuilder::set_verify`]. 189792f3ab15Sopenharmony_ci /// 189892f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify 189992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_verify_mode)] 190092f3ab15Sopenharmony_ci pub fn verify_mode(&self) -> SslVerifyMode { 190192f3ab15Sopenharmony_ci let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) }; 190292f3ab15Sopenharmony_ci SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode") 190392f3ab15Sopenharmony_ci } 190492f3ab15Sopenharmony_ci 190592f3ab15Sopenharmony_ci /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full 190692f3ab15Sopenharmony_ci /// handshake. 190792f3ab15Sopenharmony_ci /// 190892f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 190992f3ab15Sopenharmony_ci #[corresponds(SSL_CTX_get_num_tickets)] 191092f3ab15Sopenharmony_ci #[cfg(ossl111)] 191192f3ab15Sopenharmony_ci pub fn num_tickets(&self) -> usize { 191292f3ab15Sopenharmony_ci unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) } 191392f3ab15Sopenharmony_ci } 191492f3ab15Sopenharmony_ci} 191592f3ab15Sopenharmony_ci 191692f3ab15Sopenharmony_ci/// Information about the state of a cipher. 191792f3ab15Sopenharmony_cipub struct CipherBits { 191892f3ab15Sopenharmony_ci /// The number of secret bits used for the cipher. 191992f3ab15Sopenharmony_ci pub secret: i32, 192092f3ab15Sopenharmony_ci 192192f3ab15Sopenharmony_ci /// The number of bits processed by the chosen algorithm. 192292f3ab15Sopenharmony_ci pub algorithm: i32, 192392f3ab15Sopenharmony_ci} 192492f3ab15Sopenharmony_ci 192592f3ab15Sopenharmony_ci/// Information about a cipher. 192692f3ab15Sopenharmony_cipub struct SslCipher(*mut ffi::SSL_CIPHER); 192792f3ab15Sopenharmony_ci 192892f3ab15Sopenharmony_ciimpl ForeignType for SslCipher { 192992f3ab15Sopenharmony_ci type CType = ffi::SSL_CIPHER; 193092f3ab15Sopenharmony_ci type Ref = SslCipherRef; 193192f3ab15Sopenharmony_ci 193292f3ab15Sopenharmony_ci #[inline] 193392f3ab15Sopenharmony_ci unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher { 193492f3ab15Sopenharmony_ci SslCipher(ptr) 193592f3ab15Sopenharmony_ci } 193692f3ab15Sopenharmony_ci 193792f3ab15Sopenharmony_ci #[inline] 193892f3ab15Sopenharmony_ci fn as_ptr(&self) -> *mut ffi::SSL_CIPHER { 193992f3ab15Sopenharmony_ci self.0 194092f3ab15Sopenharmony_ci } 194192f3ab15Sopenharmony_ci} 194292f3ab15Sopenharmony_ci 194392f3ab15Sopenharmony_ciimpl Stackable for SslCipher { 194492f3ab15Sopenharmony_ci type StackType = ffi::stack_st_SSL_CIPHER; 194592f3ab15Sopenharmony_ci} 194692f3ab15Sopenharmony_ci 194792f3ab15Sopenharmony_ciimpl Deref for SslCipher { 194892f3ab15Sopenharmony_ci type Target = SslCipherRef; 194992f3ab15Sopenharmony_ci 195092f3ab15Sopenharmony_ci fn deref(&self) -> &SslCipherRef { 195192f3ab15Sopenharmony_ci unsafe { SslCipherRef::from_ptr(self.0) } 195292f3ab15Sopenharmony_ci } 195392f3ab15Sopenharmony_ci} 195492f3ab15Sopenharmony_ci 195592f3ab15Sopenharmony_ciimpl DerefMut for SslCipher { 195692f3ab15Sopenharmony_ci fn deref_mut(&mut self) -> &mut SslCipherRef { 195792f3ab15Sopenharmony_ci unsafe { SslCipherRef::from_ptr_mut(self.0) } 195892f3ab15Sopenharmony_ci } 195992f3ab15Sopenharmony_ci} 196092f3ab15Sopenharmony_ci 196192f3ab15Sopenharmony_ci/// Reference to an [`SslCipher`]. 196292f3ab15Sopenharmony_ci/// 196392f3ab15Sopenharmony_ci/// [`SslCipher`]: struct.SslCipher.html 196492f3ab15Sopenharmony_cipub struct SslCipherRef(Opaque); 196592f3ab15Sopenharmony_ci 196692f3ab15Sopenharmony_ciimpl ForeignTypeRef for SslCipherRef { 196792f3ab15Sopenharmony_ci type CType = ffi::SSL_CIPHER; 196892f3ab15Sopenharmony_ci} 196992f3ab15Sopenharmony_ci 197092f3ab15Sopenharmony_ciimpl SslCipherRef { 197192f3ab15Sopenharmony_ci /// Returns the name of the cipher. 197292f3ab15Sopenharmony_ci #[corresponds(SSL_CIPHER_get_name)] 197392f3ab15Sopenharmony_ci pub fn name(&self) -> &'static str { 197492f3ab15Sopenharmony_ci unsafe { 197592f3ab15Sopenharmony_ci let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr()); 197692f3ab15Sopenharmony_ci CStr::from_ptr(ptr).to_str().unwrap() 197792f3ab15Sopenharmony_ci } 197892f3ab15Sopenharmony_ci } 197992f3ab15Sopenharmony_ci 198092f3ab15Sopenharmony_ci /// Returns the RFC-standard name of the cipher, if one exists. 198192f3ab15Sopenharmony_ci /// 198292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 198392f3ab15Sopenharmony_ci #[corresponds(SSL_CIPHER_standard_name)] 198492f3ab15Sopenharmony_ci #[cfg(ossl111)] 198592f3ab15Sopenharmony_ci pub fn standard_name(&self) -> Option<&'static str> { 198692f3ab15Sopenharmony_ci unsafe { 198792f3ab15Sopenharmony_ci let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr()); 198892f3ab15Sopenharmony_ci if ptr.is_null() { 198992f3ab15Sopenharmony_ci None 199092f3ab15Sopenharmony_ci } else { 199192f3ab15Sopenharmony_ci Some(CStr::from_ptr(ptr).to_str().unwrap()) 199292f3ab15Sopenharmony_ci } 199392f3ab15Sopenharmony_ci } 199492f3ab15Sopenharmony_ci } 199592f3ab15Sopenharmony_ci 199692f3ab15Sopenharmony_ci /// Returns the SSL/TLS protocol version that first defined the cipher. 199792f3ab15Sopenharmony_ci #[corresponds(SSL_CIPHER_get_version)] 199892f3ab15Sopenharmony_ci pub fn version(&self) -> &'static str { 199992f3ab15Sopenharmony_ci let version = unsafe { 200092f3ab15Sopenharmony_ci let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr()); 200192f3ab15Sopenharmony_ci CStr::from_ptr(ptr as *const _) 200292f3ab15Sopenharmony_ci }; 200392f3ab15Sopenharmony_ci 200492f3ab15Sopenharmony_ci str::from_utf8(version.to_bytes()).unwrap() 200592f3ab15Sopenharmony_ci } 200692f3ab15Sopenharmony_ci 200792f3ab15Sopenharmony_ci /// Returns the number of bits used for the cipher. 200892f3ab15Sopenharmony_ci #[corresponds(SSL_CIPHER_get_bits)] 200992f3ab15Sopenharmony_ci #[allow(clippy::useless_conversion)] 201092f3ab15Sopenharmony_ci pub fn bits(&self) -> CipherBits { 201192f3ab15Sopenharmony_ci unsafe { 201292f3ab15Sopenharmony_ci let mut algo_bits = 0; 201392f3ab15Sopenharmony_ci let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits); 201492f3ab15Sopenharmony_ci CipherBits { 201592f3ab15Sopenharmony_ci secret: secret_bits.into(), 201692f3ab15Sopenharmony_ci algorithm: algo_bits.into(), 201792f3ab15Sopenharmony_ci } 201892f3ab15Sopenharmony_ci } 201992f3ab15Sopenharmony_ci } 202092f3ab15Sopenharmony_ci 202192f3ab15Sopenharmony_ci /// Returns a textual description of the cipher. 202292f3ab15Sopenharmony_ci #[corresponds(SSL_CIPHER_description)] 202392f3ab15Sopenharmony_ci pub fn description(&self) -> String { 202492f3ab15Sopenharmony_ci unsafe { 202592f3ab15Sopenharmony_ci // SSL_CIPHER_description requires a buffer of at least 128 bytes. 202692f3ab15Sopenharmony_ci let mut buf = [0; 128]; 202792f3ab15Sopenharmony_ci let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128); 202892f3ab15Sopenharmony_ci String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap() 202992f3ab15Sopenharmony_ci } 203092f3ab15Sopenharmony_ci } 203192f3ab15Sopenharmony_ci 203292f3ab15Sopenharmony_ci /// Returns the handshake digest of the cipher. 203392f3ab15Sopenharmony_ci /// 203492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 203592f3ab15Sopenharmony_ci #[corresponds(SSL_CIPHER_get_handshake_digest)] 203692f3ab15Sopenharmony_ci #[cfg(ossl111)] 203792f3ab15Sopenharmony_ci pub fn handshake_digest(&self) -> Option<MessageDigest> { 203892f3ab15Sopenharmony_ci unsafe { 203992f3ab15Sopenharmony_ci let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr()); 204092f3ab15Sopenharmony_ci if ptr.is_null() { 204192f3ab15Sopenharmony_ci None 204292f3ab15Sopenharmony_ci } else { 204392f3ab15Sopenharmony_ci Some(MessageDigest::from_ptr(ptr)) 204492f3ab15Sopenharmony_ci } 204592f3ab15Sopenharmony_ci } 204692f3ab15Sopenharmony_ci } 204792f3ab15Sopenharmony_ci 204892f3ab15Sopenharmony_ci /// Returns the NID corresponding to the cipher. 204992f3ab15Sopenharmony_ci /// 205092f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer. 205192f3ab15Sopenharmony_ci #[corresponds(SSL_CIPHER_get_cipher_nid)] 205292f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl270))] 205392f3ab15Sopenharmony_ci pub fn cipher_nid(&self) -> Option<Nid> { 205492f3ab15Sopenharmony_ci let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) }; 205592f3ab15Sopenharmony_ci if n == 0 { 205692f3ab15Sopenharmony_ci None 205792f3ab15Sopenharmony_ci } else { 205892f3ab15Sopenharmony_ci Some(Nid::from_raw(n)) 205992f3ab15Sopenharmony_ci } 206092f3ab15Sopenharmony_ci } 206192f3ab15Sopenharmony_ci} 206292f3ab15Sopenharmony_ci 206392f3ab15Sopenharmony_ciimpl fmt::Debug for SslCipherRef { 206492f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 206592f3ab15Sopenharmony_ci write!(fmt, "{}", self.name()) 206692f3ab15Sopenharmony_ci } 206792f3ab15Sopenharmony_ci} 206892f3ab15Sopenharmony_ci 206992f3ab15Sopenharmony_ci/// A stack of selected ciphers, and a stack of selected signalling cipher suites 207092f3ab15Sopenharmony_ci#[derive(Debug)] 207192f3ab15Sopenharmony_cipub struct CipherLists { 207292f3ab15Sopenharmony_ci pub suites: Stack<SslCipher>, 207392f3ab15Sopenharmony_ci pub signalling_suites: Stack<SslCipher>, 207492f3ab15Sopenharmony_ci} 207592f3ab15Sopenharmony_ci 207692f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 207792f3ab15Sopenharmony_ci type CType = ffi::SSL_SESSION; 207892f3ab15Sopenharmony_ci fn drop = ffi::SSL_SESSION_free; 207992f3ab15Sopenharmony_ci 208092f3ab15Sopenharmony_ci /// An encoded SSL session. 208192f3ab15Sopenharmony_ci /// 208292f3ab15Sopenharmony_ci /// These can be cached to share sessions across connections. 208392f3ab15Sopenharmony_ci pub struct SslSession; 208492f3ab15Sopenharmony_ci 208592f3ab15Sopenharmony_ci /// Reference to [`SslSession`]. 208692f3ab15Sopenharmony_ci /// 208792f3ab15Sopenharmony_ci /// [`SslSession`]: struct.SslSession.html 208892f3ab15Sopenharmony_ci pub struct SslSessionRef; 208992f3ab15Sopenharmony_ci} 209092f3ab15Sopenharmony_ci 209192f3ab15Sopenharmony_ciimpl Clone for SslSession { 209292f3ab15Sopenharmony_ci fn clone(&self) -> SslSession { 209392f3ab15Sopenharmony_ci SslSessionRef::to_owned(self) 209492f3ab15Sopenharmony_ci } 209592f3ab15Sopenharmony_ci} 209692f3ab15Sopenharmony_ci 209792f3ab15Sopenharmony_ciimpl SslSession { 209892f3ab15Sopenharmony_ci from_der! { 209992f3ab15Sopenharmony_ci /// Deserializes a DER-encoded session structure. 210092f3ab15Sopenharmony_ci #[corresponds(d2i_SSL_SESSION)] 210192f3ab15Sopenharmony_ci from_der, 210292f3ab15Sopenharmony_ci SslSession, 210392f3ab15Sopenharmony_ci ffi::d2i_SSL_SESSION 210492f3ab15Sopenharmony_ci } 210592f3ab15Sopenharmony_ci} 210692f3ab15Sopenharmony_ci 210792f3ab15Sopenharmony_ciimpl ToOwned for SslSessionRef { 210892f3ab15Sopenharmony_ci type Owned = SslSession; 210992f3ab15Sopenharmony_ci 211092f3ab15Sopenharmony_ci fn to_owned(&self) -> SslSession { 211192f3ab15Sopenharmony_ci unsafe { 211292f3ab15Sopenharmony_ci SSL_SESSION_up_ref(self.as_ptr()); 211392f3ab15Sopenharmony_ci SslSession(self.as_ptr()) 211492f3ab15Sopenharmony_ci } 211592f3ab15Sopenharmony_ci } 211692f3ab15Sopenharmony_ci} 211792f3ab15Sopenharmony_ci 211892f3ab15Sopenharmony_ciimpl SslSessionRef { 211992f3ab15Sopenharmony_ci /// Returns the SSL session ID. 212092f3ab15Sopenharmony_ci #[corresponds(SSL_SESSION_get_id)] 212192f3ab15Sopenharmony_ci pub fn id(&self) -> &[u8] { 212292f3ab15Sopenharmony_ci unsafe { 212392f3ab15Sopenharmony_ci let mut len = 0; 212492f3ab15Sopenharmony_ci let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len); 212592f3ab15Sopenharmony_ci slice::from_raw_parts(p as *const u8, len as usize) 212692f3ab15Sopenharmony_ci } 212792f3ab15Sopenharmony_ci } 212892f3ab15Sopenharmony_ci 212992f3ab15Sopenharmony_ci /// Returns the length of the master key. 213092f3ab15Sopenharmony_ci #[corresponds(SSL_SESSION_get_master_key)] 213192f3ab15Sopenharmony_ci pub fn master_key_len(&self) -> usize { 213292f3ab15Sopenharmony_ci unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) } 213392f3ab15Sopenharmony_ci } 213492f3ab15Sopenharmony_ci 213592f3ab15Sopenharmony_ci /// Copies the master key into the provided buffer. 213692f3ab15Sopenharmony_ci /// 213792f3ab15Sopenharmony_ci /// Returns the number of bytes written, or the size of the master key if the buffer is empty. 213892f3ab15Sopenharmony_ci #[corresponds(SSL_SESSION_get_master_key)] 213992f3ab15Sopenharmony_ci pub fn master_key(&self, buf: &mut [u8]) -> usize { 214092f3ab15Sopenharmony_ci unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) } 214192f3ab15Sopenharmony_ci } 214292f3ab15Sopenharmony_ci 214392f3ab15Sopenharmony_ci /// Gets the maximum amount of early data that can be sent on this session. 214492f3ab15Sopenharmony_ci /// 214592f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 214692f3ab15Sopenharmony_ci #[corresponds(SSL_SESSION_get_max_early_data)] 214792f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 214892f3ab15Sopenharmony_ci pub fn max_early_data(&self) -> u32 { 214992f3ab15Sopenharmony_ci unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) } 215092f3ab15Sopenharmony_ci } 215192f3ab15Sopenharmony_ci 215292f3ab15Sopenharmony_ci /// Returns the time at which the session was established, in seconds since the Unix epoch. 215392f3ab15Sopenharmony_ci #[corresponds(SSL_SESSION_get_time)] 215492f3ab15Sopenharmony_ci #[allow(clippy::useless_conversion)] 215592f3ab15Sopenharmony_ci pub fn time(&self) -> SslTimeTy { 215692f3ab15Sopenharmony_ci unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) } 215792f3ab15Sopenharmony_ci } 215892f3ab15Sopenharmony_ci 215992f3ab15Sopenharmony_ci /// Returns the sessions timeout, in seconds. 216092f3ab15Sopenharmony_ci /// 216192f3ab15Sopenharmony_ci /// A session older than this time should not be used for session resumption. 216292f3ab15Sopenharmony_ci #[corresponds(SSL_SESSION_get_timeout)] 216392f3ab15Sopenharmony_ci #[allow(clippy::useless_conversion)] 216492f3ab15Sopenharmony_ci pub fn timeout(&self) -> i64 { 216592f3ab15Sopenharmony_ci unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() } 216692f3ab15Sopenharmony_ci } 216792f3ab15Sopenharmony_ci 216892f3ab15Sopenharmony_ci /// Returns the session's TLS protocol version. 216992f3ab15Sopenharmony_ci /// 217092f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer. 217192f3ab15Sopenharmony_ci #[corresponds(SSL_SESSION_get_protocol_version)] 217292f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl270))] 217392f3ab15Sopenharmony_ci pub fn protocol_version(&self) -> SslVersion { 217492f3ab15Sopenharmony_ci unsafe { 217592f3ab15Sopenharmony_ci let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr()); 217692f3ab15Sopenharmony_ci SslVersion(version) 217792f3ab15Sopenharmony_ci } 217892f3ab15Sopenharmony_ci } 217992f3ab15Sopenharmony_ci 218092f3ab15Sopenharmony_ci to_der! { 218192f3ab15Sopenharmony_ci /// Serializes the session into a DER-encoded structure. 218292f3ab15Sopenharmony_ci #[corresponds(i2d_SSL_SESSION)] 218392f3ab15Sopenharmony_ci to_der, 218492f3ab15Sopenharmony_ci ffi::i2d_SSL_SESSION 218592f3ab15Sopenharmony_ci } 218692f3ab15Sopenharmony_ci} 218792f3ab15Sopenharmony_ci 218892f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 218992f3ab15Sopenharmony_ci type CType = ffi::SSL; 219092f3ab15Sopenharmony_ci fn drop = ffi::SSL_free; 219192f3ab15Sopenharmony_ci 219292f3ab15Sopenharmony_ci /// The state of an SSL/TLS session. 219392f3ab15Sopenharmony_ci /// 219492f3ab15Sopenharmony_ci /// `Ssl` objects are created from an [`SslContext`], which provides configuration defaults. 219592f3ab15Sopenharmony_ci /// These defaults can be overridden on a per-`Ssl` basis, however. 219692f3ab15Sopenharmony_ci /// 219792f3ab15Sopenharmony_ci /// [`SslContext`]: struct.SslContext.html 219892f3ab15Sopenharmony_ci pub struct Ssl; 219992f3ab15Sopenharmony_ci 220092f3ab15Sopenharmony_ci /// Reference to an [`Ssl`]. 220192f3ab15Sopenharmony_ci /// 220292f3ab15Sopenharmony_ci /// [`Ssl`]: struct.Ssl.html 220392f3ab15Sopenharmony_ci pub struct SslRef; 220492f3ab15Sopenharmony_ci} 220592f3ab15Sopenharmony_ci 220692f3ab15Sopenharmony_ciimpl fmt::Debug for Ssl { 220792f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 220892f3ab15Sopenharmony_ci fmt::Debug::fmt(&**self, fmt) 220992f3ab15Sopenharmony_ci } 221092f3ab15Sopenharmony_ci} 221192f3ab15Sopenharmony_ci 221292f3ab15Sopenharmony_ciimpl Ssl { 221392f3ab15Sopenharmony_ci /// Returns a new extra data index. 221492f3ab15Sopenharmony_ci /// 221592f3ab15Sopenharmony_ci /// Each invocation of this function is guaranteed to return a distinct index. These can be used 221692f3ab15Sopenharmony_ci /// to store data in the context that can be retrieved later by callbacks, for example. 221792f3ab15Sopenharmony_ci #[corresponds(SSL_get_ex_new_index)] 221892f3ab15Sopenharmony_ci pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack> 221992f3ab15Sopenharmony_ci where 222092f3ab15Sopenharmony_ci T: 'static + Sync + Send, 222192f3ab15Sopenharmony_ci { 222292f3ab15Sopenharmony_ci unsafe { 222392f3ab15Sopenharmony_ci ffi::init(); 222492f3ab15Sopenharmony_ci #[cfg(boringssl)] 222592f3ab15Sopenharmony_ci let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?; 222692f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 222792f3ab15Sopenharmony_ci let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?; 222892f3ab15Sopenharmony_ci Ok(Index::from_raw(idx)) 222992f3ab15Sopenharmony_ci } 223092f3ab15Sopenharmony_ci } 223192f3ab15Sopenharmony_ci 223292f3ab15Sopenharmony_ci // FIXME should return a result? 223392f3ab15Sopenharmony_ci fn cached_ex_index<T>() -> Index<Ssl, T> 223492f3ab15Sopenharmony_ci where 223592f3ab15Sopenharmony_ci T: 'static + Sync + Send, 223692f3ab15Sopenharmony_ci { 223792f3ab15Sopenharmony_ci unsafe { 223892f3ab15Sopenharmony_ci let idx = *SSL_INDEXES 223992f3ab15Sopenharmony_ci .lock() 224092f3ab15Sopenharmony_ci .unwrap_or_else(|e| e.into_inner()) 224192f3ab15Sopenharmony_ci .entry(TypeId::of::<T>()) 224292f3ab15Sopenharmony_ci .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw()); 224392f3ab15Sopenharmony_ci Index::from_raw(idx) 224492f3ab15Sopenharmony_ci } 224592f3ab15Sopenharmony_ci } 224692f3ab15Sopenharmony_ci 224792f3ab15Sopenharmony_ci /// Creates a new `Ssl`. 224892f3ab15Sopenharmony_ci /// 224992f3ab15Sopenharmony_ci /// This corresponds to [`SSL_new`]. 225092f3ab15Sopenharmony_ci /// 225192f3ab15Sopenharmony_ci /// [`SSL_new`]: https://www.openssl.org/docs/manmaster/ssl/SSL_new.html 225292f3ab15Sopenharmony_ci #[corresponds(SSL_new)] 225392f3ab15Sopenharmony_ci pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> { 225492f3ab15Sopenharmony_ci let session_ctx_index = try_get_session_ctx_index()?; 225592f3ab15Sopenharmony_ci unsafe { 225692f3ab15Sopenharmony_ci let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?; 225792f3ab15Sopenharmony_ci let mut ssl = Ssl::from_ptr(ptr); 225892f3ab15Sopenharmony_ci ssl.set_ex_data(*session_ctx_index, ctx.to_owned()); 225992f3ab15Sopenharmony_ci 226092f3ab15Sopenharmony_ci Ok(ssl) 226192f3ab15Sopenharmony_ci } 226292f3ab15Sopenharmony_ci } 226392f3ab15Sopenharmony_ci 226492f3ab15Sopenharmony_ci /// Initiates a client-side TLS handshake. 226592f3ab15Sopenharmony_ci /// 226692f3ab15Sopenharmony_ci /// This corresponds to [`SSL_connect`]. 226792f3ab15Sopenharmony_ci /// 226892f3ab15Sopenharmony_ci /// # Warning 226992f3ab15Sopenharmony_ci /// 227092f3ab15Sopenharmony_ci /// OpenSSL's default configuration is insecure. It is highly recommended to use 227192f3ab15Sopenharmony_ci /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. 227292f3ab15Sopenharmony_ci /// 227392f3ab15Sopenharmony_ci /// [`SSL_connect`]: https://www.openssl.org/docs/manmaster/man3/SSL_connect.html 227492f3ab15Sopenharmony_ci #[corresponds(SSL_connect)] 227592f3ab15Sopenharmony_ci #[allow(deprecated)] 227692f3ab15Sopenharmony_ci pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> 227792f3ab15Sopenharmony_ci where 227892f3ab15Sopenharmony_ci S: Read + Write, 227992f3ab15Sopenharmony_ci { 228092f3ab15Sopenharmony_ci SslStreamBuilder::new(self, stream).connect() 228192f3ab15Sopenharmony_ci } 228292f3ab15Sopenharmony_ci 228392f3ab15Sopenharmony_ci /// Initiates a server-side TLS handshake. 228492f3ab15Sopenharmony_ci /// 228592f3ab15Sopenharmony_ci /// This corresponds to [`SSL_accept`]. 228692f3ab15Sopenharmony_ci /// 228792f3ab15Sopenharmony_ci /// # Warning 228892f3ab15Sopenharmony_ci /// 228992f3ab15Sopenharmony_ci /// OpenSSL's default configuration is insecure. It is highly recommended to use 229092f3ab15Sopenharmony_ci /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. 229192f3ab15Sopenharmony_ci /// 229292f3ab15Sopenharmony_ci /// [`SSL_accept`]: https://www.openssl.org/docs/manmaster/man3/SSL_accept.html 229392f3ab15Sopenharmony_ci #[corresponds(SSL_accept)] 229492f3ab15Sopenharmony_ci #[allow(deprecated)] 229592f3ab15Sopenharmony_ci pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> 229692f3ab15Sopenharmony_ci where 229792f3ab15Sopenharmony_ci S: Read + Write, 229892f3ab15Sopenharmony_ci { 229992f3ab15Sopenharmony_ci SslStreamBuilder::new(self, stream).accept() 230092f3ab15Sopenharmony_ci } 230192f3ab15Sopenharmony_ci} 230292f3ab15Sopenharmony_ci 230392f3ab15Sopenharmony_ciimpl fmt::Debug for SslRef { 230492f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 230592f3ab15Sopenharmony_ci fmt.debug_struct("Ssl") 230692f3ab15Sopenharmony_ci .field("state", &self.state_string_long()) 230792f3ab15Sopenharmony_ci .field("verify_result", &self.verify_result()) 230892f3ab15Sopenharmony_ci .finish() 230992f3ab15Sopenharmony_ci } 231092f3ab15Sopenharmony_ci} 231192f3ab15Sopenharmony_ci 231292f3ab15Sopenharmony_ciimpl SslRef { 231392f3ab15Sopenharmony_ci fn get_raw_rbio(&self) -> *mut ffi::BIO { 231492f3ab15Sopenharmony_ci unsafe { ffi::SSL_get_rbio(self.as_ptr()) } 231592f3ab15Sopenharmony_ci } 231692f3ab15Sopenharmony_ci 231792f3ab15Sopenharmony_ci fn read(&mut self, buf: &mut [u8]) -> c_int { 231892f3ab15Sopenharmony_ci let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; 231992f3ab15Sopenharmony_ci unsafe { ffi::SSL_read(self.as_ptr(), buf.as_ptr() as *mut c_void, len) } 232092f3ab15Sopenharmony_ci } 232192f3ab15Sopenharmony_ci 232292f3ab15Sopenharmony_ci fn peek(&mut self, buf: &mut [u8]) -> c_int { 232392f3ab15Sopenharmony_ci let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; 232492f3ab15Sopenharmony_ci unsafe { ffi::SSL_peek(self.as_ptr(), buf.as_ptr() as *mut c_void, len) } 232592f3ab15Sopenharmony_ci } 232692f3ab15Sopenharmony_ci 232792f3ab15Sopenharmony_ci fn write(&mut self, buf: &[u8]) -> c_int { 232892f3ab15Sopenharmony_ci let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; 232992f3ab15Sopenharmony_ci unsafe { ffi::SSL_write(self.as_ptr(), buf.as_ptr() as *const c_void, len) } 233092f3ab15Sopenharmony_ci } 233192f3ab15Sopenharmony_ci 233292f3ab15Sopenharmony_ci fn get_error(&self, ret: c_int) -> ErrorCode { 233392f3ab15Sopenharmony_ci unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) } 233492f3ab15Sopenharmony_ci } 233592f3ab15Sopenharmony_ci 233692f3ab15Sopenharmony_ci /// Configure as an outgoing stream from a client. 233792f3ab15Sopenharmony_ci #[corresponds(SSL_set_connect_state)] 233892f3ab15Sopenharmony_ci pub fn set_connect_state(&mut self) { 233992f3ab15Sopenharmony_ci unsafe { ffi::SSL_set_connect_state(self.as_ptr()) } 234092f3ab15Sopenharmony_ci } 234192f3ab15Sopenharmony_ci 234292f3ab15Sopenharmony_ci /// Configure as an incoming stream to a server. 234392f3ab15Sopenharmony_ci #[corresponds(SSL_set_accept_state)] 234492f3ab15Sopenharmony_ci pub fn set_accept_state(&mut self) { 234592f3ab15Sopenharmony_ci unsafe { ffi::SSL_set_accept_state(self.as_ptr()) } 234692f3ab15Sopenharmony_ci } 234792f3ab15Sopenharmony_ci 234892f3ab15Sopenharmony_ci /// Like [`SslContextBuilder::set_verify`]. 234992f3ab15Sopenharmony_ci /// 235092f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify 235192f3ab15Sopenharmony_ci #[corresponds(SSL_set_verify)] 235292f3ab15Sopenharmony_ci pub fn set_verify(&mut self, mode: SslVerifyMode) { 235392f3ab15Sopenharmony_ci unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, None) } 235492f3ab15Sopenharmony_ci } 235592f3ab15Sopenharmony_ci 235692f3ab15Sopenharmony_ci /// Returns the verify mode that was set using `set_verify`. 235792f3ab15Sopenharmony_ci #[corresponds(SSL_set_verify_mode)] 235892f3ab15Sopenharmony_ci pub fn verify_mode(&self) -> SslVerifyMode { 235992f3ab15Sopenharmony_ci let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) }; 236092f3ab15Sopenharmony_ci SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode") 236192f3ab15Sopenharmony_ci } 236292f3ab15Sopenharmony_ci 236392f3ab15Sopenharmony_ci /// Like [`SslContextBuilder::set_verify_callback`]. 236492f3ab15Sopenharmony_ci /// 236592f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_verify_callback`]: struct.SslContextBuilder.html#method.set_verify_callback 236692f3ab15Sopenharmony_ci #[corresponds(SSL_set_verify)] 236792f3ab15Sopenharmony_ci pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F) 236892f3ab15Sopenharmony_ci where 236992f3ab15Sopenharmony_ci F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, 237092f3ab15Sopenharmony_ci { 237192f3ab15Sopenharmony_ci unsafe { 237292f3ab15Sopenharmony_ci // this needs to be in an Arc since the callback can register a new callback! 237392f3ab15Sopenharmony_ci self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify)); 237492f3ab15Sopenharmony_ci ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, Some(ssl_raw_verify::<F>)); 237592f3ab15Sopenharmony_ci } 237692f3ab15Sopenharmony_ci } 237792f3ab15Sopenharmony_ci 237892f3ab15Sopenharmony_ci /// Like [`SslContextBuilder::set_tmp_dh`]. 237992f3ab15Sopenharmony_ci /// 238092f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_tmp_dh`]: struct.SslContextBuilder.html#method.set_tmp_dh 238192f3ab15Sopenharmony_ci #[corresponds(SSL_set_tmp_dh)] 238292f3ab15Sopenharmony_ci pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> { 238392f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } 238492f3ab15Sopenharmony_ci } 238592f3ab15Sopenharmony_ci 238692f3ab15Sopenharmony_ci /// Like [`SslContextBuilder::set_tmp_dh_callback`]. 238792f3ab15Sopenharmony_ci /// 238892f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_tmp_dh_callback`]: struct.SslContextBuilder.html#method.set_tmp_dh_callback 238992f3ab15Sopenharmony_ci #[corresponds(SSL_set_tmp_dh_callback)] 239092f3ab15Sopenharmony_ci pub fn set_tmp_dh_callback<F>(&mut self, callback: F) 239192f3ab15Sopenharmony_ci where 239292f3ab15Sopenharmony_ci F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, 239392f3ab15Sopenharmony_ci { 239492f3ab15Sopenharmony_ci unsafe { 239592f3ab15Sopenharmony_ci // this needs to be in an Arc since the callback can register a new callback! 239692f3ab15Sopenharmony_ci self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); 239792f3ab15Sopenharmony_ci #[cfg(boringssl)] 239892f3ab15Sopenharmony_ci ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>)); 239992f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 240092f3ab15Sopenharmony_ci ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>)); 240192f3ab15Sopenharmony_ci } 240292f3ab15Sopenharmony_ci } 240392f3ab15Sopenharmony_ci 240492f3ab15Sopenharmony_ci /// Like [`SslContextBuilder::set_tmp_ecdh`]. 240592f3ab15Sopenharmony_ci /// 240692f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh 240792f3ab15Sopenharmony_ci #[corresponds(SSL_set_tmp_ecdh)] 240892f3ab15Sopenharmony_ci pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> { 240992f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } 241092f3ab15Sopenharmony_ci } 241192f3ab15Sopenharmony_ci 241292f3ab15Sopenharmony_ci /// Like [`SslContextBuilder::set_tmp_ecdh_callback`]. 241392f3ab15Sopenharmony_ci /// 241492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.1 or 1.0.2. 241592f3ab15Sopenharmony_ci #[corresponds(SSL_set_tmp_ecdh_callback)] 241692f3ab15Sopenharmony_ci #[cfg(all(ossl101, not(ossl110)))] 241792f3ab15Sopenharmony_ci #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")] 241892f3ab15Sopenharmony_ci pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) 241992f3ab15Sopenharmony_ci where 242092f3ab15Sopenharmony_ci F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, 242192f3ab15Sopenharmony_ci { 242292f3ab15Sopenharmony_ci unsafe { 242392f3ab15Sopenharmony_ci // this needs to be in an Arc since the callback can register a new callback! 242492f3ab15Sopenharmony_ci self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); 242592f3ab15Sopenharmony_ci ffi::SSL_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh_ssl::<F>)); 242692f3ab15Sopenharmony_ci } 242792f3ab15Sopenharmony_ci } 242892f3ab15Sopenharmony_ci 242992f3ab15Sopenharmony_ci /// Like [`SslContextBuilder::set_ecdh_auto`]. 243092f3ab15Sopenharmony_ci /// 243192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL. 243292f3ab15Sopenharmony_ci /// 243392f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh 243492f3ab15Sopenharmony_ci #[corresponds(SSL_set_ecdh_auto)] 243592f3ab15Sopenharmony_ci #[cfg(any(all(ossl102, not(ossl110)), libressl))] 243692f3ab15Sopenharmony_ci pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { 243792f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } 243892f3ab15Sopenharmony_ci } 243992f3ab15Sopenharmony_ci 244092f3ab15Sopenharmony_ci /// Like [`SslContextBuilder::set_alpn_protos`]. 244192f3ab15Sopenharmony_ci /// 244292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 244392f3ab15Sopenharmony_ci /// 244492f3ab15Sopenharmony_ci /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos 244592f3ab15Sopenharmony_ci #[corresponds(SSL_set_alpn_protos)] 244692f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 244792f3ab15Sopenharmony_ci pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> { 244892f3ab15Sopenharmony_ci unsafe { 244992f3ab15Sopenharmony_ci assert!(protocols.len() <= c_uint::max_value() as usize); 245092f3ab15Sopenharmony_ci let r = ffi::SSL_set_alpn_protos( 245192f3ab15Sopenharmony_ci self.as_ptr(), 245292f3ab15Sopenharmony_ci protocols.as_ptr(), 245392f3ab15Sopenharmony_ci protocols.len() as c_uint, 245492f3ab15Sopenharmony_ci ); 245592f3ab15Sopenharmony_ci // fun fact, SSL_set_alpn_protos has a reversed return code D: 245692f3ab15Sopenharmony_ci if r == 0 { 245792f3ab15Sopenharmony_ci Ok(()) 245892f3ab15Sopenharmony_ci } else { 245992f3ab15Sopenharmony_ci Err(ErrorStack::get()) 246092f3ab15Sopenharmony_ci } 246192f3ab15Sopenharmony_ci } 246292f3ab15Sopenharmony_ci } 246392f3ab15Sopenharmony_ci 246492f3ab15Sopenharmony_ci /// Returns the current cipher if the session is active. 246592f3ab15Sopenharmony_ci #[corresponds(SSL_get_current_cipher)] 246692f3ab15Sopenharmony_ci pub fn current_cipher(&self) -> Option<&SslCipherRef> { 246792f3ab15Sopenharmony_ci unsafe { 246892f3ab15Sopenharmony_ci let ptr = ffi::SSL_get_current_cipher(self.as_ptr()); 246992f3ab15Sopenharmony_ci 247092f3ab15Sopenharmony_ci SslCipherRef::from_const_ptr_opt(ptr) 247192f3ab15Sopenharmony_ci } 247292f3ab15Sopenharmony_ci } 247392f3ab15Sopenharmony_ci 247492f3ab15Sopenharmony_ci /// Returns a short string describing the state of the session. 247592f3ab15Sopenharmony_ci #[corresponds(SSL_state_string)] 247692f3ab15Sopenharmony_ci pub fn state_string(&self) -> &'static str { 247792f3ab15Sopenharmony_ci let state = unsafe { 247892f3ab15Sopenharmony_ci let ptr = ffi::SSL_state_string(self.as_ptr()); 247992f3ab15Sopenharmony_ci CStr::from_ptr(ptr as *const _) 248092f3ab15Sopenharmony_ci }; 248192f3ab15Sopenharmony_ci 248292f3ab15Sopenharmony_ci str::from_utf8(state.to_bytes()).unwrap() 248392f3ab15Sopenharmony_ci } 248492f3ab15Sopenharmony_ci 248592f3ab15Sopenharmony_ci /// Returns a longer string describing the state of the session. 248692f3ab15Sopenharmony_ci #[corresponds(SSL_state_string_long)] 248792f3ab15Sopenharmony_ci pub fn state_string_long(&self) -> &'static str { 248892f3ab15Sopenharmony_ci let state = unsafe { 248992f3ab15Sopenharmony_ci let ptr = ffi::SSL_state_string_long(self.as_ptr()); 249092f3ab15Sopenharmony_ci CStr::from_ptr(ptr as *const _) 249192f3ab15Sopenharmony_ci }; 249292f3ab15Sopenharmony_ci 249392f3ab15Sopenharmony_ci str::from_utf8(state.to_bytes()).unwrap() 249492f3ab15Sopenharmony_ci } 249592f3ab15Sopenharmony_ci 249692f3ab15Sopenharmony_ci /// Sets the host name to be sent to the server for Server Name Indication (SNI). 249792f3ab15Sopenharmony_ci /// 249892f3ab15Sopenharmony_ci /// It has no effect for a server-side connection. 249992f3ab15Sopenharmony_ci #[corresponds(SSL_set_tlsext_host_name)] 250092f3ab15Sopenharmony_ci pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> { 250192f3ab15Sopenharmony_ci let cstr = CString::new(hostname).unwrap(); 250292f3ab15Sopenharmony_ci unsafe { 250392f3ab15Sopenharmony_ci cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int) 250492f3ab15Sopenharmony_ci .map(|_| ()) 250592f3ab15Sopenharmony_ci } 250692f3ab15Sopenharmony_ci } 250792f3ab15Sopenharmony_ci 250892f3ab15Sopenharmony_ci /// Returns the peer's certificate, if present. 250992f3ab15Sopenharmony_ci #[corresponds(SSL_get_peer_certificate)] 251092f3ab15Sopenharmony_ci pub fn peer_certificate(&self) -> Option<X509> { 251192f3ab15Sopenharmony_ci unsafe { 251292f3ab15Sopenharmony_ci let ptr = SSL_get1_peer_certificate(self.as_ptr()); 251392f3ab15Sopenharmony_ci X509::from_ptr_opt(ptr) 251492f3ab15Sopenharmony_ci } 251592f3ab15Sopenharmony_ci } 251692f3ab15Sopenharmony_ci 251792f3ab15Sopenharmony_ci /// Returns the certificate chain of the peer, if present. 251892f3ab15Sopenharmony_ci /// 251992f3ab15Sopenharmony_ci /// On the client side, the chain includes the leaf certificate, but on the server side it does 252092f3ab15Sopenharmony_ci /// not. Fun! 252192f3ab15Sopenharmony_ci #[corresponds(SSL_get_peer_cert_chain)] 252292f3ab15Sopenharmony_ci pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> { 252392f3ab15Sopenharmony_ci unsafe { 252492f3ab15Sopenharmony_ci let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr()); 252592f3ab15Sopenharmony_ci StackRef::from_const_ptr_opt(ptr) 252692f3ab15Sopenharmony_ci } 252792f3ab15Sopenharmony_ci } 252892f3ab15Sopenharmony_ci 252992f3ab15Sopenharmony_ci /// Returns the verified certificate chain of the peer, including the leaf certificate. 253092f3ab15Sopenharmony_ci /// 253192f3ab15Sopenharmony_ci /// If verification was not successful (i.e. [`verify_result`] does not return 253292f3ab15Sopenharmony_ci /// [`X509VerifyResult::OK`]), this chain may be incomplete or invalid. 253392f3ab15Sopenharmony_ci /// 253492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or newer. 253592f3ab15Sopenharmony_ci /// 253692f3ab15Sopenharmony_ci /// [`verify_result`]: #method.verify_result 253792f3ab15Sopenharmony_ci /// [`X509VerifyResult::OK`]: ../x509/struct.X509VerifyResult.html#associatedconstant.OK 253892f3ab15Sopenharmony_ci #[corresponds(SSL_get0_verified_chain)] 253992f3ab15Sopenharmony_ci #[cfg(ossl110)] 254092f3ab15Sopenharmony_ci pub fn verified_chain(&self) -> Option<&StackRef<X509>> { 254192f3ab15Sopenharmony_ci unsafe { 254292f3ab15Sopenharmony_ci let ptr = ffi::SSL_get0_verified_chain(self.as_ptr()); 254392f3ab15Sopenharmony_ci StackRef::from_const_ptr_opt(ptr) 254492f3ab15Sopenharmony_ci } 254592f3ab15Sopenharmony_ci } 254692f3ab15Sopenharmony_ci 254792f3ab15Sopenharmony_ci /// Like [`SslContext::certificate`]. 254892f3ab15Sopenharmony_ci #[corresponds(SSL_get_certificate)] 254992f3ab15Sopenharmony_ci pub fn certificate(&self) -> Option<&X509Ref> { 255092f3ab15Sopenharmony_ci unsafe { 255192f3ab15Sopenharmony_ci let ptr = ffi::SSL_get_certificate(self.as_ptr()); 255292f3ab15Sopenharmony_ci X509Ref::from_const_ptr_opt(ptr) 255392f3ab15Sopenharmony_ci } 255492f3ab15Sopenharmony_ci } 255592f3ab15Sopenharmony_ci 255692f3ab15Sopenharmony_ci /// Like [`SslContext::private_key`]. 255792f3ab15Sopenharmony_ci /// 255892f3ab15Sopenharmony_ci /// [`SslContext::private_key`]: struct.SslContext.html#method.private_key 255992f3ab15Sopenharmony_ci #[corresponds(SSL_get_privatekey)] 256092f3ab15Sopenharmony_ci pub fn private_key(&self) -> Option<&PKeyRef<Private>> { 256192f3ab15Sopenharmony_ci unsafe { 256292f3ab15Sopenharmony_ci let ptr = ffi::SSL_get_privatekey(self.as_ptr()); 256392f3ab15Sopenharmony_ci PKeyRef::from_const_ptr_opt(ptr) 256492f3ab15Sopenharmony_ci } 256592f3ab15Sopenharmony_ci } 256692f3ab15Sopenharmony_ci 256792f3ab15Sopenharmony_ci #[deprecated(since = "0.10.5", note = "renamed to `version_str`")] 256892f3ab15Sopenharmony_ci pub fn version(&self) -> &str { 256992f3ab15Sopenharmony_ci self.version_str() 257092f3ab15Sopenharmony_ci } 257192f3ab15Sopenharmony_ci 257292f3ab15Sopenharmony_ci /// Returns the protocol version of the session. 257392f3ab15Sopenharmony_ci #[corresponds(SSL_version)] 257492f3ab15Sopenharmony_ci pub fn version2(&self) -> Option<SslVersion> { 257592f3ab15Sopenharmony_ci unsafe { 257692f3ab15Sopenharmony_ci let r = ffi::SSL_version(self.as_ptr()); 257792f3ab15Sopenharmony_ci if r == 0 { 257892f3ab15Sopenharmony_ci None 257992f3ab15Sopenharmony_ci } else { 258092f3ab15Sopenharmony_ci Some(SslVersion(r)) 258192f3ab15Sopenharmony_ci } 258292f3ab15Sopenharmony_ci } 258392f3ab15Sopenharmony_ci } 258492f3ab15Sopenharmony_ci 258592f3ab15Sopenharmony_ci /// Returns a string describing the protocol version of the session. 258692f3ab15Sopenharmony_ci #[corresponds(SSL_get_version)] 258792f3ab15Sopenharmony_ci pub fn version_str(&self) -> &'static str { 258892f3ab15Sopenharmony_ci let version = unsafe { 258992f3ab15Sopenharmony_ci let ptr = ffi::SSL_get_version(self.as_ptr()); 259092f3ab15Sopenharmony_ci CStr::from_ptr(ptr as *const _) 259192f3ab15Sopenharmony_ci }; 259292f3ab15Sopenharmony_ci 259392f3ab15Sopenharmony_ci str::from_utf8(version.to_bytes()).unwrap() 259492f3ab15Sopenharmony_ci } 259592f3ab15Sopenharmony_ci 259692f3ab15Sopenharmony_ci /// Returns the protocol selected via Application Layer Protocol Negotiation (ALPN). 259792f3ab15Sopenharmony_ci /// 259892f3ab15Sopenharmony_ci /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client 259992f3ab15Sopenharmony_ci /// to interpret it. 260092f3ab15Sopenharmony_ci /// 260192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 260292f3ab15Sopenharmony_ci #[corresponds(SSL_get0_alpn_selected)] 260392f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 260492f3ab15Sopenharmony_ci pub fn selected_alpn_protocol(&self) -> Option<&[u8]> { 260592f3ab15Sopenharmony_ci unsafe { 260692f3ab15Sopenharmony_ci let mut data: *const c_uchar = ptr::null(); 260792f3ab15Sopenharmony_ci let mut len: c_uint = 0; 260892f3ab15Sopenharmony_ci // Get the negotiated protocol from the SSL instance. 260992f3ab15Sopenharmony_ci // `data` will point at a `c_uchar` array; `len` will contain the length of this array. 261092f3ab15Sopenharmony_ci ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len); 261192f3ab15Sopenharmony_ci 261292f3ab15Sopenharmony_ci if data.is_null() { 261392f3ab15Sopenharmony_ci None 261492f3ab15Sopenharmony_ci } else { 261592f3ab15Sopenharmony_ci Some(slice::from_raw_parts(data, len as usize)) 261692f3ab15Sopenharmony_ci } 261792f3ab15Sopenharmony_ci } 261892f3ab15Sopenharmony_ci } 261992f3ab15Sopenharmony_ci 262092f3ab15Sopenharmony_ci /// Enables the DTLS extension "use_srtp" as defined in RFC5764. 262192f3ab15Sopenharmony_ci /// 262292f3ab15Sopenharmony_ci /// This corresponds to [`SSL_set_tlsext_use_srtp`]. 262392f3ab15Sopenharmony_ci /// 262492f3ab15Sopenharmony_ci /// [`SSL_set_tlsext_use_srtp`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html 262592f3ab15Sopenharmony_ci #[corresponds(SSL_set_tlsext_use_srtp)] 262692f3ab15Sopenharmony_ci pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> { 262792f3ab15Sopenharmony_ci unsafe { 262892f3ab15Sopenharmony_ci let cstr = CString::new(protocols).unwrap(); 262992f3ab15Sopenharmony_ci 263092f3ab15Sopenharmony_ci let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr()); 263192f3ab15Sopenharmony_ci // fun fact, set_tlsext_use_srtp has a reversed return code D: 263292f3ab15Sopenharmony_ci if r == 0 { 263392f3ab15Sopenharmony_ci Ok(()) 263492f3ab15Sopenharmony_ci } else { 263592f3ab15Sopenharmony_ci Err(ErrorStack::get()) 263692f3ab15Sopenharmony_ci } 263792f3ab15Sopenharmony_ci } 263892f3ab15Sopenharmony_ci } 263992f3ab15Sopenharmony_ci 264092f3ab15Sopenharmony_ci /// Gets all SRTP profiles that are enabled for handshake via set_tlsext_use_srtp 264192f3ab15Sopenharmony_ci /// 264292f3ab15Sopenharmony_ci /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled. 264392f3ab15Sopenharmony_ci /// 264492f3ab15Sopenharmony_ci /// This corresponds to [`SSL_get_srtp_profiles`]. 264592f3ab15Sopenharmony_ci /// 264692f3ab15Sopenharmony_ci /// [`SSL_get_srtp_profiles`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html 264792f3ab15Sopenharmony_ci #[corresponds(SSL_get_srtp_profiles)] 264892f3ab15Sopenharmony_ci pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> { 264992f3ab15Sopenharmony_ci unsafe { 265092f3ab15Sopenharmony_ci let chain = ffi::SSL_get_srtp_profiles(self.as_ptr()); 265192f3ab15Sopenharmony_ci 265292f3ab15Sopenharmony_ci StackRef::from_const_ptr_opt(chain) 265392f3ab15Sopenharmony_ci } 265492f3ab15Sopenharmony_ci } 265592f3ab15Sopenharmony_ci 265692f3ab15Sopenharmony_ci /// Gets the SRTP profile selected by handshake. 265792f3ab15Sopenharmony_ci /// 265892f3ab15Sopenharmony_ci /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled. 265992f3ab15Sopenharmony_ci #[corresponds(SSL_get_selected_srtp_profile)] 266092f3ab15Sopenharmony_ci pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> { 266192f3ab15Sopenharmony_ci unsafe { 266292f3ab15Sopenharmony_ci let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr()); 266392f3ab15Sopenharmony_ci 266492f3ab15Sopenharmony_ci SrtpProtectionProfileRef::from_const_ptr_opt(profile) 266592f3ab15Sopenharmony_ci } 266692f3ab15Sopenharmony_ci } 266792f3ab15Sopenharmony_ci 266892f3ab15Sopenharmony_ci /// Returns the number of bytes remaining in the currently processed TLS record. 266992f3ab15Sopenharmony_ci /// 267092f3ab15Sopenharmony_ci /// If this is greater than 0, the next call to `read` will not call down to the underlying 267192f3ab15Sopenharmony_ci /// stream. 267292f3ab15Sopenharmony_ci #[corresponds(SSL_pending)] 267392f3ab15Sopenharmony_ci pub fn pending(&self) -> usize { 267492f3ab15Sopenharmony_ci unsafe { ffi::SSL_pending(self.as_ptr()) as usize } 267592f3ab15Sopenharmony_ci } 267692f3ab15Sopenharmony_ci 267792f3ab15Sopenharmony_ci /// Returns the servername sent by the client via Server Name Indication (SNI). 267892f3ab15Sopenharmony_ci /// 267992f3ab15Sopenharmony_ci /// It is only useful on the server side. 268092f3ab15Sopenharmony_ci /// 268192f3ab15Sopenharmony_ci /// # Note 268292f3ab15Sopenharmony_ci /// 268392f3ab15Sopenharmony_ci /// While the SNI specification requires that servernames be valid domain names (and therefore 268492f3ab15Sopenharmony_ci /// ASCII), OpenSSL does not enforce this restriction. If the servername provided by the client 268592f3ab15Sopenharmony_ci /// is not valid UTF-8, this function will return `None`. The `servername_raw` method returns 268692f3ab15Sopenharmony_ci /// the raw bytes and does not have this restriction. 268792f3ab15Sopenharmony_ci /// 268892f3ab15Sopenharmony_ci /// [`SSL_get_servername`]: https://www.openssl.org/docs/manmaster/man3/SSL_get_servername.html 268992f3ab15Sopenharmony_ci #[corresponds(SSL_get_servername)] 269092f3ab15Sopenharmony_ci // FIXME maybe rethink in 0.11? 269192f3ab15Sopenharmony_ci pub fn servername(&self, type_: NameType) -> Option<&str> { 269292f3ab15Sopenharmony_ci self.servername_raw(type_) 269392f3ab15Sopenharmony_ci .and_then(|b| str::from_utf8(b).ok()) 269492f3ab15Sopenharmony_ci } 269592f3ab15Sopenharmony_ci 269692f3ab15Sopenharmony_ci /// Returns the servername sent by the client via Server Name Indication (SNI). 269792f3ab15Sopenharmony_ci /// 269892f3ab15Sopenharmony_ci /// It is only useful on the server side. 269992f3ab15Sopenharmony_ci /// 270092f3ab15Sopenharmony_ci /// # Note 270192f3ab15Sopenharmony_ci /// 270292f3ab15Sopenharmony_ci /// Unlike `servername`, this method does not require the name be valid UTF-8. 270392f3ab15Sopenharmony_ci #[corresponds(SSL_get_servername)] 270492f3ab15Sopenharmony_ci pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> { 270592f3ab15Sopenharmony_ci unsafe { 270692f3ab15Sopenharmony_ci let name = ffi::SSL_get_servername(self.as_ptr(), type_.0); 270792f3ab15Sopenharmony_ci if name.is_null() { 270892f3ab15Sopenharmony_ci None 270992f3ab15Sopenharmony_ci } else { 271092f3ab15Sopenharmony_ci Some(CStr::from_ptr(name as *const _).to_bytes()) 271192f3ab15Sopenharmony_ci } 271292f3ab15Sopenharmony_ci } 271392f3ab15Sopenharmony_ci } 271492f3ab15Sopenharmony_ci 271592f3ab15Sopenharmony_ci /// Changes the context corresponding to the current connection. 271692f3ab15Sopenharmony_ci /// 271792f3ab15Sopenharmony_ci /// It is most commonly used in the Server Name Indication (SNI) callback. 271892f3ab15Sopenharmony_ci #[corresponds(SSL_set_SSL_CTX)] 271992f3ab15Sopenharmony_ci pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> { 272092f3ab15Sopenharmony_ci unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) } 272192f3ab15Sopenharmony_ci } 272292f3ab15Sopenharmony_ci 272392f3ab15Sopenharmony_ci /// Returns the context corresponding to the current connection. 272492f3ab15Sopenharmony_ci #[corresponds(SSL_get_SSL_CTX)] 272592f3ab15Sopenharmony_ci pub fn ssl_context(&self) -> &SslContextRef { 272692f3ab15Sopenharmony_ci unsafe { 272792f3ab15Sopenharmony_ci let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr()); 272892f3ab15Sopenharmony_ci SslContextRef::from_ptr(ssl_ctx) 272992f3ab15Sopenharmony_ci } 273092f3ab15Sopenharmony_ci } 273192f3ab15Sopenharmony_ci 273292f3ab15Sopenharmony_ci /// Returns a mutable reference to the X509 verification configuration. 273392f3ab15Sopenharmony_ci /// 273492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.0.2 or newer. 273592f3ab15Sopenharmony_ci #[corresponds(SSL_get0_param)] 273692f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 273792f3ab15Sopenharmony_ci pub fn param_mut(&mut self) -> &mut X509VerifyParamRef { 273892f3ab15Sopenharmony_ci unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) } 273992f3ab15Sopenharmony_ci } 274092f3ab15Sopenharmony_ci 274192f3ab15Sopenharmony_ci /// Returns the certificate verification result. 274292f3ab15Sopenharmony_ci #[corresponds(SSL_get_verify_result)] 274392f3ab15Sopenharmony_ci pub fn verify_result(&self) -> X509VerifyResult { 274492f3ab15Sopenharmony_ci unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) } 274592f3ab15Sopenharmony_ci } 274692f3ab15Sopenharmony_ci 274792f3ab15Sopenharmony_ci /// Returns a shared reference to the SSL session. 274892f3ab15Sopenharmony_ci #[corresponds(SSL_get_session)] 274992f3ab15Sopenharmony_ci pub fn session(&self) -> Option<&SslSessionRef> { 275092f3ab15Sopenharmony_ci unsafe { 275192f3ab15Sopenharmony_ci let p = ffi::SSL_get_session(self.as_ptr()); 275292f3ab15Sopenharmony_ci SslSessionRef::from_const_ptr_opt(p) 275392f3ab15Sopenharmony_ci } 275492f3ab15Sopenharmony_ci } 275592f3ab15Sopenharmony_ci 275692f3ab15Sopenharmony_ci /// Copies the `client_random` value sent by the client in the TLS handshake into a buffer. 275792f3ab15Sopenharmony_ci /// 275892f3ab15Sopenharmony_ci /// Returns the number of bytes copied, or if the buffer is empty, the size of the `client_random` 275992f3ab15Sopenharmony_ci /// value. 276092f3ab15Sopenharmony_ci /// 276192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer. 276292f3ab15Sopenharmony_ci #[corresponds(SSL_get_client_random)] 276392f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl270))] 276492f3ab15Sopenharmony_ci pub fn client_random(&self, buf: &mut [u8]) -> usize { 276592f3ab15Sopenharmony_ci unsafe { 276692f3ab15Sopenharmony_ci ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len()) 276792f3ab15Sopenharmony_ci } 276892f3ab15Sopenharmony_ci } 276992f3ab15Sopenharmony_ci 277092f3ab15Sopenharmony_ci /// Copies the `server_random` value sent by the server in the TLS handshake into a buffer. 277192f3ab15Sopenharmony_ci /// 277292f3ab15Sopenharmony_ci /// Returns the number of bytes copied, or if the buffer is empty, the size of the `server_random` 277392f3ab15Sopenharmony_ci /// value. 277492f3ab15Sopenharmony_ci /// 277592f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer. 277692f3ab15Sopenharmony_ci #[corresponds(SSL_get_server_random)] 277792f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl270))] 277892f3ab15Sopenharmony_ci pub fn server_random(&self, buf: &mut [u8]) -> usize { 277992f3ab15Sopenharmony_ci unsafe { 278092f3ab15Sopenharmony_ci ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len()) 278192f3ab15Sopenharmony_ci } 278292f3ab15Sopenharmony_ci } 278392f3ab15Sopenharmony_ci 278492f3ab15Sopenharmony_ci /// Derives keying material for application use in accordance to RFC 5705. 278592f3ab15Sopenharmony_ci #[corresponds(SSL_export_keying_material)] 278692f3ab15Sopenharmony_ci pub fn export_keying_material( 278792f3ab15Sopenharmony_ci &self, 278892f3ab15Sopenharmony_ci out: &mut [u8], 278992f3ab15Sopenharmony_ci label: &str, 279092f3ab15Sopenharmony_ci context: Option<&[u8]>, 279192f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 279292f3ab15Sopenharmony_ci unsafe { 279392f3ab15Sopenharmony_ci let (context, contextlen, use_context) = match context { 279492f3ab15Sopenharmony_ci Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1), 279592f3ab15Sopenharmony_ci None => (ptr::null(), 0, 0), 279692f3ab15Sopenharmony_ci }; 279792f3ab15Sopenharmony_ci cvt(ffi::SSL_export_keying_material( 279892f3ab15Sopenharmony_ci self.as_ptr(), 279992f3ab15Sopenharmony_ci out.as_mut_ptr() as *mut c_uchar, 280092f3ab15Sopenharmony_ci out.len(), 280192f3ab15Sopenharmony_ci label.as_ptr() as *const c_char, 280292f3ab15Sopenharmony_ci label.len(), 280392f3ab15Sopenharmony_ci context, 280492f3ab15Sopenharmony_ci contextlen, 280592f3ab15Sopenharmony_ci use_context, 280692f3ab15Sopenharmony_ci )) 280792f3ab15Sopenharmony_ci .map(|_| ()) 280892f3ab15Sopenharmony_ci } 280992f3ab15Sopenharmony_ci } 281092f3ab15Sopenharmony_ci 281192f3ab15Sopenharmony_ci /// Derives keying material for application use in accordance to RFC 5705. 281292f3ab15Sopenharmony_ci /// 281392f3ab15Sopenharmony_ci /// This function is only usable with TLSv1.3, wherein there is no distinction between an empty context and no 281492f3ab15Sopenharmony_ci /// context. Therefore, unlike `export_keying_material`, `context` must always be supplied. 281592f3ab15Sopenharmony_ci /// 281692f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 281792f3ab15Sopenharmony_ci #[corresponds(SSL_export_keying_material_early)] 281892f3ab15Sopenharmony_ci #[cfg(ossl111)] 281992f3ab15Sopenharmony_ci pub fn export_keying_material_early( 282092f3ab15Sopenharmony_ci &self, 282192f3ab15Sopenharmony_ci out: &mut [u8], 282292f3ab15Sopenharmony_ci label: &str, 282392f3ab15Sopenharmony_ci context: &[u8], 282492f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 282592f3ab15Sopenharmony_ci unsafe { 282692f3ab15Sopenharmony_ci cvt(ffi::SSL_export_keying_material_early( 282792f3ab15Sopenharmony_ci self.as_ptr(), 282892f3ab15Sopenharmony_ci out.as_mut_ptr() as *mut c_uchar, 282992f3ab15Sopenharmony_ci out.len(), 283092f3ab15Sopenharmony_ci label.as_ptr() as *const c_char, 283192f3ab15Sopenharmony_ci label.len(), 283292f3ab15Sopenharmony_ci context.as_ptr() as *const c_uchar, 283392f3ab15Sopenharmony_ci context.len(), 283492f3ab15Sopenharmony_ci )) 283592f3ab15Sopenharmony_ci .map(|_| ()) 283692f3ab15Sopenharmony_ci } 283792f3ab15Sopenharmony_ci } 283892f3ab15Sopenharmony_ci 283992f3ab15Sopenharmony_ci /// Sets the session to be used. 284092f3ab15Sopenharmony_ci /// 284192f3ab15Sopenharmony_ci /// This should be called before the handshake to attempt to reuse a previously established 284292f3ab15Sopenharmony_ci /// session. If the server is not willing to reuse the session, a new one will be transparently 284392f3ab15Sopenharmony_ci /// negotiated. 284492f3ab15Sopenharmony_ci /// 284592f3ab15Sopenharmony_ci /// # Safety 284692f3ab15Sopenharmony_ci /// 284792f3ab15Sopenharmony_ci /// The caller of this method is responsible for ensuring that the session is associated 284892f3ab15Sopenharmony_ci /// with the same `SslContext` as this `Ssl`. 284992f3ab15Sopenharmony_ci #[corresponds(SSL_set_session)] 285092f3ab15Sopenharmony_ci pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> { 285192f3ab15Sopenharmony_ci cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ()) 285292f3ab15Sopenharmony_ci } 285392f3ab15Sopenharmony_ci 285492f3ab15Sopenharmony_ci /// Determines if the session provided to `set_session` was successfully reused. 285592f3ab15Sopenharmony_ci #[corresponds(SSL_session_reused)] 285692f3ab15Sopenharmony_ci pub fn session_reused(&self) -> bool { 285792f3ab15Sopenharmony_ci unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 } 285892f3ab15Sopenharmony_ci } 285992f3ab15Sopenharmony_ci 286092f3ab15Sopenharmony_ci /// Sets the status response a client wishes the server to reply with. 286192f3ab15Sopenharmony_ci #[corresponds(SSL_set_tlsext_status_type)] 286292f3ab15Sopenharmony_ci pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> { 286392f3ab15Sopenharmony_ci unsafe { 286492f3ab15Sopenharmony_ci cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ()) 286592f3ab15Sopenharmony_ci } 286692f3ab15Sopenharmony_ci } 286792f3ab15Sopenharmony_ci 286892f3ab15Sopenharmony_ci /// Determines if current session used Extended Master Secret 286992f3ab15Sopenharmony_ci /// 287092f3ab15Sopenharmony_ci /// Returns `None` if the handshake is still in-progress. 287192f3ab15Sopenharmony_ci #[corresponds(SSL_get_extms_support)] 287292f3ab15Sopenharmony_ci #[cfg(ossl110)] 287392f3ab15Sopenharmony_ci pub fn extms_support(&self) -> Option<bool> { 287492f3ab15Sopenharmony_ci unsafe { 287592f3ab15Sopenharmony_ci match ffi::SSL_get_extms_support(self.as_ptr()) { 287692f3ab15Sopenharmony_ci -1 => None, 287792f3ab15Sopenharmony_ci ret => Some(ret != 0), 287892f3ab15Sopenharmony_ci } 287992f3ab15Sopenharmony_ci } 288092f3ab15Sopenharmony_ci } 288192f3ab15Sopenharmony_ci 288292f3ab15Sopenharmony_ci /// Returns the server's OCSP response, if present. 288392f3ab15Sopenharmony_ci #[corresponds(SSL_get_tlsext_status_ocsp_resp)] 288492f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 288592f3ab15Sopenharmony_ci pub fn ocsp_status(&self) -> Option<&[u8]> { 288692f3ab15Sopenharmony_ci unsafe { 288792f3ab15Sopenharmony_ci let mut p = ptr::null_mut(); 288892f3ab15Sopenharmony_ci let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p); 288992f3ab15Sopenharmony_ci 289092f3ab15Sopenharmony_ci if len < 0 { 289192f3ab15Sopenharmony_ci None 289292f3ab15Sopenharmony_ci } else { 289392f3ab15Sopenharmony_ci Some(slice::from_raw_parts(p as *const u8, len as usize)) 289492f3ab15Sopenharmony_ci } 289592f3ab15Sopenharmony_ci } 289692f3ab15Sopenharmony_ci } 289792f3ab15Sopenharmony_ci 289892f3ab15Sopenharmony_ci /// Sets the OCSP response to be returned to the client. 289992f3ab15Sopenharmony_ci #[corresponds(SSL_set_tlsext_status_oscp_resp)] 290092f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 290192f3ab15Sopenharmony_ci pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> { 290292f3ab15Sopenharmony_ci unsafe { 290392f3ab15Sopenharmony_ci assert!(response.len() <= c_int::max_value() as usize); 290492f3ab15Sopenharmony_ci let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?; 290592f3ab15Sopenharmony_ci ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len()); 290692f3ab15Sopenharmony_ci cvt(ffi::SSL_set_tlsext_status_ocsp_resp( 290792f3ab15Sopenharmony_ci self.as_ptr(), 290892f3ab15Sopenharmony_ci p as *mut c_uchar, 290992f3ab15Sopenharmony_ci response.len() as c_long, 291092f3ab15Sopenharmony_ci ) as c_int) 291192f3ab15Sopenharmony_ci .map(|_| ()) 291292f3ab15Sopenharmony_ci .map_err(|e| { 291392f3ab15Sopenharmony_ci ffi::OPENSSL_free(p); 291492f3ab15Sopenharmony_ci e 291592f3ab15Sopenharmony_ci }) 291692f3ab15Sopenharmony_ci } 291792f3ab15Sopenharmony_ci } 291892f3ab15Sopenharmony_ci 291992f3ab15Sopenharmony_ci /// Determines if this `Ssl` is configured for server-side or client-side use. 292092f3ab15Sopenharmony_ci #[corresponds(SSL_is_server)] 292192f3ab15Sopenharmony_ci pub fn is_server(&self) -> bool { 292292f3ab15Sopenharmony_ci unsafe { SSL_is_server(self.as_ptr()) != 0 } 292392f3ab15Sopenharmony_ci } 292492f3ab15Sopenharmony_ci 292592f3ab15Sopenharmony_ci /// Sets the extra data at the specified index. 292692f3ab15Sopenharmony_ci /// 292792f3ab15Sopenharmony_ci /// This can be used to provide data to callbacks registered with the context. Use the 292892f3ab15Sopenharmony_ci /// `Ssl::new_ex_index` method to create an `Index`. 292992f3ab15Sopenharmony_ci #[corresponds(SSL_set_ex_data)] 293092f3ab15Sopenharmony_ci pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) { 293192f3ab15Sopenharmony_ci unsafe { 293292f3ab15Sopenharmony_ci let data = Box::new(data); 293392f3ab15Sopenharmony_ci ffi::SSL_set_ex_data( 293492f3ab15Sopenharmony_ci self.as_ptr(), 293592f3ab15Sopenharmony_ci index.as_raw(), 293692f3ab15Sopenharmony_ci Box::into_raw(data) as *mut c_void, 293792f3ab15Sopenharmony_ci ); 293892f3ab15Sopenharmony_ci } 293992f3ab15Sopenharmony_ci } 294092f3ab15Sopenharmony_ci 294192f3ab15Sopenharmony_ci /// Returns a reference to the extra data at the specified index. 294292f3ab15Sopenharmony_ci #[corresponds(SSL_get_ex_data)] 294392f3ab15Sopenharmony_ci pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> { 294492f3ab15Sopenharmony_ci unsafe { 294592f3ab15Sopenharmony_ci let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw()); 294692f3ab15Sopenharmony_ci if data.is_null() { 294792f3ab15Sopenharmony_ci None 294892f3ab15Sopenharmony_ci } else { 294992f3ab15Sopenharmony_ci Some(&*(data as *const T)) 295092f3ab15Sopenharmony_ci } 295192f3ab15Sopenharmony_ci } 295292f3ab15Sopenharmony_ci } 295392f3ab15Sopenharmony_ci 295492f3ab15Sopenharmony_ci /// Returns a mutable reference to the extra data at the specified index. 295592f3ab15Sopenharmony_ci #[corresponds(SSL_get_ex_data)] 295692f3ab15Sopenharmony_ci pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> { 295792f3ab15Sopenharmony_ci unsafe { 295892f3ab15Sopenharmony_ci let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw()); 295992f3ab15Sopenharmony_ci if data.is_null() { 296092f3ab15Sopenharmony_ci None 296192f3ab15Sopenharmony_ci } else { 296292f3ab15Sopenharmony_ci Some(&mut *(data as *mut T)) 296392f3ab15Sopenharmony_ci } 296492f3ab15Sopenharmony_ci } 296592f3ab15Sopenharmony_ci } 296692f3ab15Sopenharmony_ci 296792f3ab15Sopenharmony_ci /// Sets the maximum amount of early data that will be accepted on this connection. 296892f3ab15Sopenharmony_ci /// 296992f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 297092f3ab15Sopenharmony_ci #[corresponds(SSL_set_max_early_data)] 297192f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 297292f3ab15Sopenharmony_ci pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> { 297392f3ab15Sopenharmony_ci if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 { 297492f3ab15Sopenharmony_ci Ok(()) 297592f3ab15Sopenharmony_ci } else { 297692f3ab15Sopenharmony_ci Err(ErrorStack::get()) 297792f3ab15Sopenharmony_ci } 297892f3ab15Sopenharmony_ci } 297992f3ab15Sopenharmony_ci 298092f3ab15Sopenharmony_ci /// Gets the maximum amount of early data that can be sent on this connection. 298192f3ab15Sopenharmony_ci /// 298292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 298392f3ab15Sopenharmony_ci #[corresponds(SSL_get_max_early_data)] 298492f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 298592f3ab15Sopenharmony_ci pub fn max_early_data(&self) -> u32 { 298692f3ab15Sopenharmony_ci unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) } 298792f3ab15Sopenharmony_ci } 298892f3ab15Sopenharmony_ci 298992f3ab15Sopenharmony_ci /// Copies the contents of the last Finished message sent to the peer into the provided buffer. 299092f3ab15Sopenharmony_ci /// 299192f3ab15Sopenharmony_ci /// The total size of the message is returned, so this can be used to determine the size of the 299292f3ab15Sopenharmony_ci /// buffer required. 299392f3ab15Sopenharmony_ci #[corresponds(SSL_get_finished)] 299492f3ab15Sopenharmony_ci pub fn finished(&self, buf: &mut [u8]) -> usize { 299592f3ab15Sopenharmony_ci unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) } 299692f3ab15Sopenharmony_ci } 299792f3ab15Sopenharmony_ci 299892f3ab15Sopenharmony_ci /// Copies the contents of the last Finished message received from the peer into the provided 299992f3ab15Sopenharmony_ci /// buffer. 300092f3ab15Sopenharmony_ci /// 300192f3ab15Sopenharmony_ci /// The total size of the message is returned, so this can be used to determine the size of the 300292f3ab15Sopenharmony_ci /// buffer required. 300392f3ab15Sopenharmony_ci #[corresponds(SSL_get_peer_finished)] 300492f3ab15Sopenharmony_ci pub fn peer_finished(&self, buf: &mut [u8]) -> usize { 300592f3ab15Sopenharmony_ci unsafe { 300692f3ab15Sopenharmony_ci ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) 300792f3ab15Sopenharmony_ci } 300892f3ab15Sopenharmony_ci } 300992f3ab15Sopenharmony_ci 301092f3ab15Sopenharmony_ci /// Determines if the initial handshake has been completed. 301192f3ab15Sopenharmony_ci #[corresponds(SSL_is_init_finished)] 301292f3ab15Sopenharmony_ci #[cfg(ossl110)] 301392f3ab15Sopenharmony_ci pub fn is_init_finished(&self) -> bool { 301492f3ab15Sopenharmony_ci unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 } 301592f3ab15Sopenharmony_ci } 301692f3ab15Sopenharmony_ci 301792f3ab15Sopenharmony_ci /// Determines if the client's hello message is in the SSLv2 format. 301892f3ab15Sopenharmony_ci /// 301992f3ab15Sopenharmony_ci /// This can only be used inside of the client hello callback. Otherwise, `false` is returned. 302092f3ab15Sopenharmony_ci /// 302192f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 302292f3ab15Sopenharmony_ci #[corresponds(SSL_client_hello_isv2)] 302392f3ab15Sopenharmony_ci #[cfg(ossl111)] 302492f3ab15Sopenharmony_ci pub fn client_hello_isv2(&self) -> bool { 302592f3ab15Sopenharmony_ci unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 } 302692f3ab15Sopenharmony_ci } 302792f3ab15Sopenharmony_ci 302892f3ab15Sopenharmony_ci /// Returns the legacy version field of the client's hello message. 302992f3ab15Sopenharmony_ci /// 303092f3ab15Sopenharmony_ci /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 303192f3ab15Sopenharmony_ci /// 303292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 303392f3ab15Sopenharmony_ci #[corresponds(SSL_client_hello_get0_legacy_version)] 303492f3ab15Sopenharmony_ci #[cfg(ossl111)] 303592f3ab15Sopenharmony_ci pub fn client_hello_legacy_version(&self) -> Option<SslVersion> { 303692f3ab15Sopenharmony_ci unsafe { 303792f3ab15Sopenharmony_ci let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr()); 303892f3ab15Sopenharmony_ci if version == 0 { 303992f3ab15Sopenharmony_ci None 304092f3ab15Sopenharmony_ci } else { 304192f3ab15Sopenharmony_ci Some(SslVersion(version as c_int)) 304292f3ab15Sopenharmony_ci } 304392f3ab15Sopenharmony_ci } 304492f3ab15Sopenharmony_ci } 304592f3ab15Sopenharmony_ci 304692f3ab15Sopenharmony_ci /// Returns the random field of the client's hello message. 304792f3ab15Sopenharmony_ci /// 304892f3ab15Sopenharmony_ci /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 304992f3ab15Sopenharmony_ci /// 305092f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 305192f3ab15Sopenharmony_ci #[corresponds(SSL_client_hello_get0_random)] 305292f3ab15Sopenharmony_ci #[cfg(ossl111)] 305392f3ab15Sopenharmony_ci pub fn client_hello_random(&self) -> Option<&[u8]> { 305492f3ab15Sopenharmony_ci unsafe { 305592f3ab15Sopenharmony_ci let mut ptr = ptr::null(); 305692f3ab15Sopenharmony_ci let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr); 305792f3ab15Sopenharmony_ci if len == 0 { 305892f3ab15Sopenharmony_ci None 305992f3ab15Sopenharmony_ci } else { 306092f3ab15Sopenharmony_ci Some(slice::from_raw_parts(ptr, len)) 306192f3ab15Sopenharmony_ci } 306292f3ab15Sopenharmony_ci } 306392f3ab15Sopenharmony_ci } 306492f3ab15Sopenharmony_ci 306592f3ab15Sopenharmony_ci /// Returns the session ID field of the client's hello message. 306692f3ab15Sopenharmony_ci /// 306792f3ab15Sopenharmony_ci /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 306892f3ab15Sopenharmony_ci /// 306992f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 307092f3ab15Sopenharmony_ci #[corresponds(SSL_client_hello_get0_session_id)] 307192f3ab15Sopenharmony_ci #[cfg(ossl111)] 307292f3ab15Sopenharmony_ci pub fn client_hello_session_id(&self) -> Option<&[u8]> { 307392f3ab15Sopenharmony_ci unsafe { 307492f3ab15Sopenharmony_ci let mut ptr = ptr::null(); 307592f3ab15Sopenharmony_ci let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr); 307692f3ab15Sopenharmony_ci if len == 0 { 307792f3ab15Sopenharmony_ci None 307892f3ab15Sopenharmony_ci } else { 307992f3ab15Sopenharmony_ci Some(slice::from_raw_parts(ptr, len)) 308092f3ab15Sopenharmony_ci } 308192f3ab15Sopenharmony_ci } 308292f3ab15Sopenharmony_ci } 308392f3ab15Sopenharmony_ci 308492f3ab15Sopenharmony_ci /// Returns the ciphers field of the client's hello message. 308592f3ab15Sopenharmony_ci /// 308692f3ab15Sopenharmony_ci /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 308792f3ab15Sopenharmony_ci /// 308892f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 308992f3ab15Sopenharmony_ci #[corresponds(SSL_client_hello_get0_ciphers)] 309092f3ab15Sopenharmony_ci #[cfg(ossl111)] 309192f3ab15Sopenharmony_ci pub fn client_hello_ciphers(&self) -> Option<&[u8]> { 309292f3ab15Sopenharmony_ci unsafe { 309392f3ab15Sopenharmony_ci let mut ptr = ptr::null(); 309492f3ab15Sopenharmony_ci let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr); 309592f3ab15Sopenharmony_ci if len == 0 { 309692f3ab15Sopenharmony_ci None 309792f3ab15Sopenharmony_ci } else { 309892f3ab15Sopenharmony_ci Some(slice::from_raw_parts(ptr, len)) 309992f3ab15Sopenharmony_ci } 310092f3ab15Sopenharmony_ci } 310192f3ab15Sopenharmony_ci } 310292f3ab15Sopenharmony_ci 310392f3ab15Sopenharmony_ci /// Decodes a slice of wire-format cipher suite specification bytes. Unsupported cipher suites 310492f3ab15Sopenharmony_ci /// are ignored. 310592f3ab15Sopenharmony_ci /// 310692f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 310792f3ab15Sopenharmony_ci #[corresponds(SSL_bytes_to_cipher_list)] 310892f3ab15Sopenharmony_ci #[cfg(ossl111)] 310992f3ab15Sopenharmony_ci pub fn bytes_to_cipher_list( 311092f3ab15Sopenharmony_ci &self, 311192f3ab15Sopenharmony_ci bytes: &[u8], 311292f3ab15Sopenharmony_ci isv2format: bool, 311392f3ab15Sopenharmony_ci ) -> Result<CipherLists, ErrorStack> { 311492f3ab15Sopenharmony_ci unsafe { 311592f3ab15Sopenharmony_ci let ptr = bytes.as_ptr(); 311692f3ab15Sopenharmony_ci let len = bytes.len(); 311792f3ab15Sopenharmony_ci let mut sk = ptr::null_mut(); 311892f3ab15Sopenharmony_ci let mut scsvs = ptr::null_mut(); 311992f3ab15Sopenharmony_ci let res = ffi::SSL_bytes_to_cipher_list( 312092f3ab15Sopenharmony_ci self.as_ptr(), 312192f3ab15Sopenharmony_ci ptr, 312292f3ab15Sopenharmony_ci len, 312392f3ab15Sopenharmony_ci isv2format as c_int, 312492f3ab15Sopenharmony_ci &mut sk, 312592f3ab15Sopenharmony_ci &mut scsvs, 312692f3ab15Sopenharmony_ci ); 312792f3ab15Sopenharmony_ci if res == 1 { 312892f3ab15Sopenharmony_ci Ok(CipherLists { 312992f3ab15Sopenharmony_ci suites: Stack::from_ptr(sk), 313092f3ab15Sopenharmony_ci signalling_suites: Stack::from_ptr(scsvs), 313192f3ab15Sopenharmony_ci }) 313292f3ab15Sopenharmony_ci } else { 313392f3ab15Sopenharmony_ci Err(ErrorStack::get()) 313492f3ab15Sopenharmony_ci } 313592f3ab15Sopenharmony_ci } 313692f3ab15Sopenharmony_ci } 313792f3ab15Sopenharmony_ci 313892f3ab15Sopenharmony_ci /// Returns the compression methods field of the client's hello message. 313992f3ab15Sopenharmony_ci /// 314092f3ab15Sopenharmony_ci /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 314192f3ab15Sopenharmony_ci /// 314292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 314392f3ab15Sopenharmony_ci #[corresponds(SSL_client_hello_get0_compression_methods)] 314492f3ab15Sopenharmony_ci #[cfg(ossl111)] 314592f3ab15Sopenharmony_ci pub fn client_hello_compression_methods(&self) -> Option<&[u8]> { 314692f3ab15Sopenharmony_ci unsafe { 314792f3ab15Sopenharmony_ci let mut ptr = ptr::null(); 314892f3ab15Sopenharmony_ci let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr); 314992f3ab15Sopenharmony_ci if len == 0 { 315092f3ab15Sopenharmony_ci None 315192f3ab15Sopenharmony_ci } else { 315292f3ab15Sopenharmony_ci Some(slice::from_raw_parts(ptr, len)) 315392f3ab15Sopenharmony_ci } 315492f3ab15Sopenharmony_ci } 315592f3ab15Sopenharmony_ci } 315692f3ab15Sopenharmony_ci 315792f3ab15Sopenharmony_ci /// Sets the MTU used for DTLS connections. 315892f3ab15Sopenharmony_ci #[corresponds(SSL_set_mtu)] 315992f3ab15Sopenharmony_ci pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> { 316092f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) } 316192f3ab15Sopenharmony_ci } 316292f3ab15Sopenharmony_ci 316392f3ab15Sopenharmony_ci /// Returns the PSK identity hint used during connection setup. 316492f3ab15Sopenharmony_ci /// 316592f3ab15Sopenharmony_ci /// May return `None` if no PSK identity hint was used during the connection setup. 316692f3ab15Sopenharmony_ci #[corresponds(SSL_get_psk_identity_hint)] 316792f3ab15Sopenharmony_ci #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 316892f3ab15Sopenharmony_ci pub fn psk_identity_hint(&self) -> Option<&[u8]> { 316992f3ab15Sopenharmony_ci unsafe { 317092f3ab15Sopenharmony_ci let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr()); 317192f3ab15Sopenharmony_ci if ptr.is_null() { 317292f3ab15Sopenharmony_ci None 317392f3ab15Sopenharmony_ci } else { 317492f3ab15Sopenharmony_ci Some(CStr::from_ptr(ptr).to_bytes()) 317592f3ab15Sopenharmony_ci } 317692f3ab15Sopenharmony_ci } 317792f3ab15Sopenharmony_ci } 317892f3ab15Sopenharmony_ci 317992f3ab15Sopenharmony_ci /// Returns the PSK identity used during connection setup. 318092f3ab15Sopenharmony_ci #[corresponds(SSL_get_psk_identity)] 318192f3ab15Sopenharmony_ci #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 318292f3ab15Sopenharmony_ci pub fn psk_identity(&self) -> Option<&[u8]> { 318392f3ab15Sopenharmony_ci unsafe { 318492f3ab15Sopenharmony_ci let ptr = ffi::SSL_get_psk_identity(self.as_ptr()); 318592f3ab15Sopenharmony_ci if ptr.is_null() { 318692f3ab15Sopenharmony_ci None 318792f3ab15Sopenharmony_ci } else { 318892f3ab15Sopenharmony_ci Some(CStr::from_ptr(ptr).to_bytes()) 318992f3ab15Sopenharmony_ci } 319092f3ab15Sopenharmony_ci } 319192f3ab15Sopenharmony_ci } 319292f3ab15Sopenharmony_ci 319392f3ab15Sopenharmony_ci #[corresponds(SSL_add0_chain_cert)] 319492f3ab15Sopenharmony_ci #[cfg(ossl102)] 319592f3ab15Sopenharmony_ci pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> { 319692f3ab15Sopenharmony_ci unsafe { 319792f3ab15Sopenharmony_ci cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?; 319892f3ab15Sopenharmony_ci mem::forget(chain); 319992f3ab15Sopenharmony_ci } 320092f3ab15Sopenharmony_ci Ok(()) 320192f3ab15Sopenharmony_ci } 320292f3ab15Sopenharmony_ci 320392f3ab15Sopenharmony_ci /// Sets a new default TLS/SSL method for SSL objects 320492f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 320592f3ab15Sopenharmony_ci pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> { 320692f3ab15Sopenharmony_ci unsafe { 320792f3ab15Sopenharmony_ci cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?; 320892f3ab15Sopenharmony_ci }; 320992f3ab15Sopenharmony_ci Ok(()) 321092f3ab15Sopenharmony_ci } 321192f3ab15Sopenharmony_ci 321292f3ab15Sopenharmony_ci /// Loads the private key from a file. 321392f3ab15Sopenharmony_ci #[corresponds(SSL_use_Private_Key_file)] 321492f3ab15Sopenharmony_ci pub fn set_private_key_file<P: AsRef<Path>>( 321592f3ab15Sopenharmony_ci &mut self, 321692f3ab15Sopenharmony_ci path: P, 321792f3ab15Sopenharmony_ci ssl_file_type: SslFiletype, 321892f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 321992f3ab15Sopenharmony_ci let p = path.as_ref().as_os_str().to_str().unwrap(); 322092f3ab15Sopenharmony_ci let key_file = CString::new(p).unwrap(); 322192f3ab15Sopenharmony_ci unsafe { 322292f3ab15Sopenharmony_ci cvt(ffi::SSL_use_PrivateKey_file( 322392f3ab15Sopenharmony_ci self.as_ptr(), 322492f3ab15Sopenharmony_ci key_file.as_ptr(), 322592f3ab15Sopenharmony_ci ssl_file_type.as_raw(), 322692f3ab15Sopenharmony_ci ))?; 322792f3ab15Sopenharmony_ci }; 322892f3ab15Sopenharmony_ci Ok(()) 322992f3ab15Sopenharmony_ci } 323092f3ab15Sopenharmony_ci 323192f3ab15Sopenharmony_ci /// Sets the private key. 323292f3ab15Sopenharmony_ci #[corresponds(SSL_use_PrivateKey)] 323392f3ab15Sopenharmony_ci pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> { 323492f3ab15Sopenharmony_ci unsafe { 323592f3ab15Sopenharmony_ci cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?; 323692f3ab15Sopenharmony_ci }; 323792f3ab15Sopenharmony_ci Ok(()) 323892f3ab15Sopenharmony_ci } 323992f3ab15Sopenharmony_ci 324092f3ab15Sopenharmony_ci /// Sets the certificate 324192f3ab15Sopenharmony_ci #[corresponds(SSL_use_certificate)] 324292f3ab15Sopenharmony_ci pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { 324392f3ab15Sopenharmony_ci unsafe { 324492f3ab15Sopenharmony_ci cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?; 324592f3ab15Sopenharmony_ci }; 324692f3ab15Sopenharmony_ci Ok(()) 324792f3ab15Sopenharmony_ci } 324892f3ab15Sopenharmony_ci 324992f3ab15Sopenharmony_ci /// Loads a certificate chain from a file. 325092f3ab15Sopenharmony_ci /// 325192f3ab15Sopenharmony_ci /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf 325292f3ab15Sopenharmony_ci /// certificate, and the remainder forming the chain of certificates up to and including the 325392f3ab15Sopenharmony_ci /// trusted root certificate. 325492f3ab15Sopenharmony_ci #[corresponds(SSL_use_certificate_chain_file)] 325592f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl332))] 325692f3ab15Sopenharmony_ci pub fn set_certificate_chain_file<P: AsRef<Path>>( 325792f3ab15Sopenharmony_ci &mut self, 325892f3ab15Sopenharmony_ci path: P, 325992f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 326092f3ab15Sopenharmony_ci let p = path.as_ref().as_os_str().to_str().unwrap(); 326192f3ab15Sopenharmony_ci let cert_file = CString::new(p).unwrap(); 326292f3ab15Sopenharmony_ci unsafe { 326392f3ab15Sopenharmony_ci cvt(ffi::SSL_use_certificate_chain_file( 326492f3ab15Sopenharmony_ci self.as_ptr(), 326592f3ab15Sopenharmony_ci cert_file.as_ptr(), 326692f3ab15Sopenharmony_ci ))?; 326792f3ab15Sopenharmony_ci }; 326892f3ab15Sopenharmony_ci Ok(()) 326992f3ab15Sopenharmony_ci } 327092f3ab15Sopenharmony_ci 327192f3ab15Sopenharmony_ci /// Sets ca certificate that client trusted 327292f3ab15Sopenharmony_ci #[corresponds(SSL_add_client_CA)] 327392f3ab15Sopenharmony_ci pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> { 327492f3ab15Sopenharmony_ci unsafe { 327592f3ab15Sopenharmony_ci cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?; 327692f3ab15Sopenharmony_ci }; 327792f3ab15Sopenharmony_ci Ok(()) 327892f3ab15Sopenharmony_ci } 327992f3ab15Sopenharmony_ci 328092f3ab15Sopenharmony_ci // Sets the list of CAs sent to the client when requesting a client certificate for the chosen ssl 328192f3ab15Sopenharmony_ci #[corresponds(SSL_set_client_CA_list)] 328292f3ab15Sopenharmony_ci pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) { 328392f3ab15Sopenharmony_ci unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) } 328492f3ab15Sopenharmony_ci mem::forget(list); 328592f3ab15Sopenharmony_ci } 328692f3ab15Sopenharmony_ci 328792f3ab15Sopenharmony_ci /// Sets the minimum supported protocol version. 328892f3ab15Sopenharmony_ci /// 328992f3ab15Sopenharmony_ci /// A value of `None` will enable protocol versions down to the lowest version supported by 329092f3ab15Sopenharmony_ci /// OpenSSL. 329192f3ab15Sopenharmony_ci /// 329292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer. 329392f3ab15Sopenharmony_ci #[corresponds(SSL_set_min_proto_version)] 329492f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl261))] 329592f3ab15Sopenharmony_ci pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { 329692f3ab15Sopenharmony_ci unsafe { 329792f3ab15Sopenharmony_ci cvt(ffi::SSL_set_min_proto_version( 329892f3ab15Sopenharmony_ci self.as_ptr(), 329992f3ab15Sopenharmony_ci version.map_or(0, |v| v.0 as _), 330092f3ab15Sopenharmony_ci )) 330192f3ab15Sopenharmony_ci .map(|_| ()) 330292f3ab15Sopenharmony_ci } 330392f3ab15Sopenharmony_ci } 330492f3ab15Sopenharmony_ci 330592f3ab15Sopenharmony_ci /// Sets the maximum supported protocol version. 330692f3ab15Sopenharmony_ci /// 330792f3ab15Sopenharmony_ci /// A value of `None` will enable protocol versions up to the highest version supported by 330892f3ab15Sopenharmony_ci /// OpenSSL. 330992f3ab15Sopenharmony_ci /// 331092f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer. 331192f3ab15Sopenharmony_ci #[corresponds(SSL_set_max_proto_version)] 331292f3ab15Sopenharmony_ci #[cfg(any(ossl110, libressl261))] 331392f3ab15Sopenharmony_ci pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { 331492f3ab15Sopenharmony_ci unsafe { 331592f3ab15Sopenharmony_ci cvt(ffi::SSL_set_max_proto_version( 331692f3ab15Sopenharmony_ci self.as_ptr(), 331792f3ab15Sopenharmony_ci version.map_or(0, |v| v.0 as _), 331892f3ab15Sopenharmony_ci )) 331992f3ab15Sopenharmony_ci .map(|_| ()) 332092f3ab15Sopenharmony_ci } 332192f3ab15Sopenharmony_ci } 332292f3ab15Sopenharmony_ci 332392f3ab15Sopenharmony_ci /// Sets the list of supported ciphers for the TLSv1.3 protocol. 332492f3ab15Sopenharmony_ci /// 332592f3ab15Sopenharmony_ci /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3. 332692f3ab15Sopenharmony_ci /// 332792f3ab15Sopenharmony_ci /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of 332892f3ab15Sopenharmony_ci /// preference. 332992f3ab15Sopenharmony_ci /// 333092f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 333192f3ab15Sopenharmony_ci #[corresponds(SSL_set_ciphersuites)] 333292f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 333392f3ab15Sopenharmony_ci pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { 333492f3ab15Sopenharmony_ci let cipher_list = CString::new(cipher_list).unwrap(); 333592f3ab15Sopenharmony_ci unsafe { 333692f3ab15Sopenharmony_ci cvt(ffi::SSL_set_ciphersuites( 333792f3ab15Sopenharmony_ci self.as_ptr(), 333892f3ab15Sopenharmony_ci cipher_list.as_ptr() as *const _, 333992f3ab15Sopenharmony_ci )) 334092f3ab15Sopenharmony_ci .map(|_| ()) 334192f3ab15Sopenharmony_ci } 334292f3ab15Sopenharmony_ci } 334392f3ab15Sopenharmony_ci 334492f3ab15Sopenharmony_ci /// Sets the list of supported ciphers for protocols before TLSv1.3. 334592f3ab15Sopenharmony_ci /// 334692f3ab15Sopenharmony_ci /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3. 334792f3ab15Sopenharmony_ci /// 334892f3ab15Sopenharmony_ci /// See [`ciphers`] for details on the format. 334992f3ab15Sopenharmony_ci /// 335092f3ab15Sopenharmony_ci /// [`ciphers`]: https://www.openssl.org/docs/manmaster/apps/ciphers.html 335192f3ab15Sopenharmony_ci #[corresponds(SSL_set_cipher_list)] 335292f3ab15Sopenharmony_ci pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { 335392f3ab15Sopenharmony_ci let cipher_list = CString::new(cipher_list).unwrap(); 335492f3ab15Sopenharmony_ci unsafe { 335592f3ab15Sopenharmony_ci cvt(ffi::SSL_set_cipher_list( 335692f3ab15Sopenharmony_ci self.as_ptr(), 335792f3ab15Sopenharmony_ci cipher_list.as_ptr() as *const _, 335892f3ab15Sopenharmony_ci )) 335992f3ab15Sopenharmony_ci .map(|_| ()) 336092f3ab15Sopenharmony_ci } 336192f3ab15Sopenharmony_ci } 336292f3ab15Sopenharmony_ci 336392f3ab15Sopenharmony_ci /// Set the certificate store used for certificate verification 336492f3ab15Sopenharmony_ci #[corresponds(SSL_set_cert_store)] 336592f3ab15Sopenharmony_ci #[cfg(ossl102)] 336692f3ab15Sopenharmony_ci pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { 336792f3ab15Sopenharmony_ci unsafe { 336892f3ab15Sopenharmony_ci cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?; 336992f3ab15Sopenharmony_ci mem::forget(cert_store); 337092f3ab15Sopenharmony_ci Ok(()) 337192f3ab15Sopenharmony_ci } 337292f3ab15Sopenharmony_ci } 337392f3ab15Sopenharmony_ci 337492f3ab15Sopenharmony_ci /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full 337592f3ab15Sopenharmony_ci /// handshake. 337692f3ab15Sopenharmony_ci /// 337792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 337892f3ab15Sopenharmony_ci #[corresponds(SSL_set_num_tickets)] 337992f3ab15Sopenharmony_ci #[cfg(ossl111)] 338092f3ab15Sopenharmony_ci pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> { 338192f3ab15Sopenharmony_ci unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) } 338292f3ab15Sopenharmony_ci } 338392f3ab15Sopenharmony_ci 338492f3ab15Sopenharmony_ci /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full 338592f3ab15Sopenharmony_ci /// handshake. 338692f3ab15Sopenharmony_ci /// 338792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 338892f3ab15Sopenharmony_ci #[corresponds(SSL_get_num_tickets)] 338992f3ab15Sopenharmony_ci #[cfg(ossl111)] 339092f3ab15Sopenharmony_ci pub fn num_tickets(&self) -> usize { 339192f3ab15Sopenharmony_ci unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) } 339292f3ab15Sopenharmony_ci } 339392f3ab15Sopenharmony_ci} 339492f3ab15Sopenharmony_ci 339592f3ab15Sopenharmony_ci/// An SSL stream midway through the handshake process. 339692f3ab15Sopenharmony_ci#[derive(Debug)] 339792f3ab15Sopenharmony_cipub struct MidHandshakeSslStream<S> { 339892f3ab15Sopenharmony_ci stream: SslStream<S>, 339992f3ab15Sopenharmony_ci error: Error, 340092f3ab15Sopenharmony_ci} 340192f3ab15Sopenharmony_ci 340292f3ab15Sopenharmony_ciimpl<S> MidHandshakeSslStream<S> { 340392f3ab15Sopenharmony_ci /// Returns a shared reference to the inner stream. 340492f3ab15Sopenharmony_ci pub fn get_ref(&self) -> &S { 340592f3ab15Sopenharmony_ci self.stream.get_ref() 340692f3ab15Sopenharmony_ci } 340792f3ab15Sopenharmony_ci 340892f3ab15Sopenharmony_ci /// Returns a mutable reference to the inner stream. 340992f3ab15Sopenharmony_ci pub fn get_mut(&mut self) -> &mut S { 341092f3ab15Sopenharmony_ci self.stream.get_mut() 341192f3ab15Sopenharmony_ci } 341292f3ab15Sopenharmony_ci 341392f3ab15Sopenharmony_ci /// Returns a shared reference to the `Ssl` of the stream. 341492f3ab15Sopenharmony_ci pub fn ssl(&self) -> &SslRef { 341592f3ab15Sopenharmony_ci self.stream.ssl() 341692f3ab15Sopenharmony_ci } 341792f3ab15Sopenharmony_ci 341892f3ab15Sopenharmony_ci /// Returns the underlying error which interrupted this handshake. 341992f3ab15Sopenharmony_ci pub fn error(&self) -> &Error { 342092f3ab15Sopenharmony_ci &self.error 342192f3ab15Sopenharmony_ci } 342292f3ab15Sopenharmony_ci 342392f3ab15Sopenharmony_ci /// Consumes `self`, returning its error. 342492f3ab15Sopenharmony_ci pub fn into_error(self) -> Error { 342592f3ab15Sopenharmony_ci self.error 342692f3ab15Sopenharmony_ci } 342792f3ab15Sopenharmony_ci} 342892f3ab15Sopenharmony_ci 342992f3ab15Sopenharmony_ciimpl<S> MidHandshakeSslStream<S> 343092f3ab15Sopenharmony_ciwhere 343192f3ab15Sopenharmony_ci S: Read + Write, 343292f3ab15Sopenharmony_ci{ 343392f3ab15Sopenharmony_ci /// Restarts the handshake process. 343492f3ab15Sopenharmony_ci /// 343592f3ab15Sopenharmony_ci /// This corresponds to [`SSL_do_handshake`]. 343692f3ab15Sopenharmony_ci /// 343792f3ab15Sopenharmony_ci /// [`SSL_do_handshake`]: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html 343892f3ab15Sopenharmony_ci pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> { 343992f3ab15Sopenharmony_ci match self.stream.do_handshake() { 344092f3ab15Sopenharmony_ci Ok(()) => Ok(self.stream), 344192f3ab15Sopenharmony_ci Err(error) => { 344292f3ab15Sopenharmony_ci self.error = error; 344392f3ab15Sopenharmony_ci match self.error.code() { 344492f3ab15Sopenharmony_ci ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 344592f3ab15Sopenharmony_ci Err(HandshakeError::WouldBlock(self)) 344692f3ab15Sopenharmony_ci } 344792f3ab15Sopenharmony_ci _ => Err(HandshakeError::Failure(self)), 344892f3ab15Sopenharmony_ci } 344992f3ab15Sopenharmony_ci } 345092f3ab15Sopenharmony_ci } 345192f3ab15Sopenharmony_ci } 345292f3ab15Sopenharmony_ci} 345392f3ab15Sopenharmony_ci 345492f3ab15Sopenharmony_ci/// A TLS session over a stream. 345592f3ab15Sopenharmony_cipub struct SslStream<S> { 345692f3ab15Sopenharmony_ci ssl: ManuallyDrop<Ssl>, 345792f3ab15Sopenharmony_ci method: ManuallyDrop<BioMethod>, 345892f3ab15Sopenharmony_ci _p: PhantomData<S>, 345992f3ab15Sopenharmony_ci} 346092f3ab15Sopenharmony_ci 346192f3ab15Sopenharmony_ciimpl<S> Drop for SslStream<S> { 346292f3ab15Sopenharmony_ci fn drop(&mut self) { 346392f3ab15Sopenharmony_ci // ssl holds a reference to method internally so it has to drop first 346492f3ab15Sopenharmony_ci unsafe { 346592f3ab15Sopenharmony_ci ManuallyDrop::drop(&mut self.ssl); 346692f3ab15Sopenharmony_ci ManuallyDrop::drop(&mut self.method); 346792f3ab15Sopenharmony_ci } 346892f3ab15Sopenharmony_ci } 346992f3ab15Sopenharmony_ci} 347092f3ab15Sopenharmony_ci 347192f3ab15Sopenharmony_ciimpl<S> fmt::Debug for SslStream<S> 347292f3ab15Sopenharmony_ciwhere 347392f3ab15Sopenharmony_ci S: fmt::Debug, 347492f3ab15Sopenharmony_ci{ 347592f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 347692f3ab15Sopenharmony_ci fmt.debug_struct("SslStream") 347792f3ab15Sopenharmony_ci .field("stream", &self.get_ref()) 347892f3ab15Sopenharmony_ci .field("ssl", &self.ssl()) 347992f3ab15Sopenharmony_ci .finish() 348092f3ab15Sopenharmony_ci } 348192f3ab15Sopenharmony_ci} 348292f3ab15Sopenharmony_ci 348392f3ab15Sopenharmony_ciimpl<S: Read + Write> SslStream<S> { 348492f3ab15Sopenharmony_ci /// Creates a new `SslStream`. 348592f3ab15Sopenharmony_ci /// 348692f3ab15Sopenharmony_ci /// This function performs no IO; the stream will not have performed any part of the handshake 348792f3ab15Sopenharmony_ci /// with the peer. If the `Ssl` was configured with [`SslRef::set_connect_state`] or 348892f3ab15Sopenharmony_ci /// [`SslRef::set_accept_state`], the handshake can be performed automatically during the first 348992f3ab15Sopenharmony_ci /// call to read or write. Otherwise the `connect` and `accept` methods can be used to 349092f3ab15Sopenharmony_ci /// explicitly perform the handshake. 349192f3ab15Sopenharmony_ci #[corresponds(SSL_set_bio)] 349292f3ab15Sopenharmony_ci pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> { 349392f3ab15Sopenharmony_ci let (bio, method) = bio::new(stream)?; 349492f3ab15Sopenharmony_ci unsafe { 349592f3ab15Sopenharmony_ci ffi::SSL_set_bio(ssl.as_ptr(), bio, bio); 349692f3ab15Sopenharmony_ci } 349792f3ab15Sopenharmony_ci 349892f3ab15Sopenharmony_ci Ok(SslStream { 349992f3ab15Sopenharmony_ci ssl: ManuallyDrop::new(ssl), 350092f3ab15Sopenharmony_ci method: ManuallyDrop::new(method), 350192f3ab15Sopenharmony_ci _p: PhantomData, 350292f3ab15Sopenharmony_ci }) 350392f3ab15Sopenharmony_ci } 350492f3ab15Sopenharmony_ci 350592f3ab15Sopenharmony_ci /// Constructs an `SslStream` from a pointer to the underlying OpenSSL `SSL` struct. 350692f3ab15Sopenharmony_ci /// 350792f3ab15Sopenharmony_ci /// This is useful if the handshake has already been completed elsewhere. 350892f3ab15Sopenharmony_ci /// 350992f3ab15Sopenharmony_ci /// # Safety 351092f3ab15Sopenharmony_ci /// 351192f3ab15Sopenharmony_ci /// The caller must ensure the pointer is valid. 351292f3ab15Sopenharmony_ci #[deprecated( 351392f3ab15Sopenharmony_ci since = "0.10.32", 351492f3ab15Sopenharmony_ci note = "use Ssl::from_ptr and SslStream::new instead" 351592f3ab15Sopenharmony_ci )] 351692f3ab15Sopenharmony_ci pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self { 351792f3ab15Sopenharmony_ci let ssl = Ssl::from_ptr(ssl); 351892f3ab15Sopenharmony_ci Self::new(ssl, stream).unwrap() 351992f3ab15Sopenharmony_ci } 352092f3ab15Sopenharmony_ci 352192f3ab15Sopenharmony_ci /// Read application data transmitted by a client before handshake completion. 352292f3ab15Sopenharmony_ci /// 352392f3ab15Sopenharmony_ci /// Useful for reducing latency, but vulnerable to replay attacks. Call 352492f3ab15Sopenharmony_ci /// [`SslRef::set_accept_state`] first. 352592f3ab15Sopenharmony_ci /// 352692f3ab15Sopenharmony_ci /// Returns `Ok(0)` if all early data has been read. 352792f3ab15Sopenharmony_ci /// 352892f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 352992f3ab15Sopenharmony_ci #[corresponds(SSL_read_early_data)] 353092f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 353192f3ab15Sopenharmony_ci pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 353292f3ab15Sopenharmony_ci let mut read = 0; 353392f3ab15Sopenharmony_ci let ret = unsafe { 353492f3ab15Sopenharmony_ci ffi::SSL_read_early_data( 353592f3ab15Sopenharmony_ci self.ssl.as_ptr(), 353692f3ab15Sopenharmony_ci buf.as_ptr() as *mut c_void, 353792f3ab15Sopenharmony_ci buf.len(), 353892f3ab15Sopenharmony_ci &mut read, 353992f3ab15Sopenharmony_ci ) 354092f3ab15Sopenharmony_ci }; 354192f3ab15Sopenharmony_ci match ret { 354292f3ab15Sopenharmony_ci ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)), 354392f3ab15Sopenharmony_ci ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read), 354492f3ab15Sopenharmony_ci ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0), 354592f3ab15Sopenharmony_ci _ => unreachable!(), 354692f3ab15Sopenharmony_ci } 354792f3ab15Sopenharmony_ci } 354892f3ab15Sopenharmony_ci 354992f3ab15Sopenharmony_ci /// Send data to the server without blocking on handshake completion. 355092f3ab15Sopenharmony_ci /// 355192f3ab15Sopenharmony_ci /// Useful for reducing latency, but vulnerable to replay attacks. Call 355292f3ab15Sopenharmony_ci /// [`SslRef::set_connect_state`] first. 355392f3ab15Sopenharmony_ci /// 355492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 355592f3ab15Sopenharmony_ci #[corresponds(SSL_write_early_data)] 355692f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 355792f3ab15Sopenharmony_ci pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> { 355892f3ab15Sopenharmony_ci let mut written = 0; 355992f3ab15Sopenharmony_ci let ret = unsafe { 356092f3ab15Sopenharmony_ci ffi::SSL_write_early_data( 356192f3ab15Sopenharmony_ci self.ssl.as_ptr(), 356292f3ab15Sopenharmony_ci buf.as_ptr() as *const c_void, 356392f3ab15Sopenharmony_ci buf.len(), 356492f3ab15Sopenharmony_ci &mut written, 356592f3ab15Sopenharmony_ci ) 356692f3ab15Sopenharmony_ci }; 356792f3ab15Sopenharmony_ci if ret > 0 { 356892f3ab15Sopenharmony_ci Ok(written) 356992f3ab15Sopenharmony_ci } else { 357092f3ab15Sopenharmony_ci Err(self.make_error(ret)) 357192f3ab15Sopenharmony_ci } 357292f3ab15Sopenharmony_ci } 357392f3ab15Sopenharmony_ci 357492f3ab15Sopenharmony_ci /// Initiates a client-side TLS handshake. 357592f3ab15Sopenharmony_ci /// 357692f3ab15Sopenharmony_ci /// # Warning 357792f3ab15Sopenharmony_ci /// 357892f3ab15Sopenharmony_ci /// OpenSSL's default configuration is insecure. It is highly recommended to use 357992f3ab15Sopenharmony_ci /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. 358092f3ab15Sopenharmony_ci #[corresponds(SSL_connect)] 358192f3ab15Sopenharmony_ci pub fn connect(&mut self) -> Result<(), Error> { 358292f3ab15Sopenharmony_ci let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) }; 358392f3ab15Sopenharmony_ci if ret > 0 { 358492f3ab15Sopenharmony_ci Ok(()) 358592f3ab15Sopenharmony_ci } else { 358692f3ab15Sopenharmony_ci Err(self.make_error(ret)) 358792f3ab15Sopenharmony_ci } 358892f3ab15Sopenharmony_ci } 358992f3ab15Sopenharmony_ci 359092f3ab15Sopenharmony_ci /// Initiates a server-side TLS handshake. 359192f3ab15Sopenharmony_ci /// 359292f3ab15Sopenharmony_ci /// # Warning 359392f3ab15Sopenharmony_ci /// 359492f3ab15Sopenharmony_ci /// OpenSSL's default configuration is insecure. It is highly recommended to use 359592f3ab15Sopenharmony_ci /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. 359692f3ab15Sopenharmony_ci #[corresponds(SSL_accept)] 359792f3ab15Sopenharmony_ci pub fn accept(&mut self) -> Result<(), Error> { 359892f3ab15Sopenharmony_ci let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) }; 359992f3ab15Sopenharmony_ci if ret > 0 { 360092f3ab15Sopenharmony_ci Ok(()) 360192f3ab15Sopenharmony_ci } else { 360292f3ab15Sopenharmony_ci Err(self.make_error(ret)) 360392f3ab15Sopenharmony_ci } 360492f3ab15Sopenharmony_ci } 360592f3ab15Sopenharmony_ci 360692f3ab15Sopenharmony_ci /// Initiates the handshake. 360792f3ab15Sopenharmony_ci /// 360892f3ab15Sopenharmony_ci /// This will fail if `set_accept_state` or `set_connect_state` was not called first. 360992f3ab15Sopenharmony_ci #[corresponds(SSL_do_handshake)] 361092f3ab15Sopenharmony_ci pub fn do_handshake(&mut self) -> Result<(), Error> { 361192f3ab15Sopenharmony_ci let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) }; 361292f3ab15Sopenharmony_ci if ret > 0 { 361392f3ab15Sopenharmony_ci Ok(()) 361492f3ab15Sopenharmony_ci } else { 361592f3ab15Sopenharmony_ci Err(self.make_error(ret)) 361692f3ab15Sopenharmony_ci } 361792f3ab15Sopenharmony_ci } 361892f3ab15Sopenharmony_ci 361992f3ab15Sopenharmony_ci /// Perform a stateless server-side handshake. 362092f3ab15Sopenharmony_ci /// 362192f3ab15Sopenharmony_ci /// Requires that cookie generation and verification callbacks were 362292f3ab15Sopenharmony_ci /// set on the SSL context. 362392f3ab15Sopenharmony_ci /// 362492f3ab15Sopenharmony_ci /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie 362592f3ab15Sopenharmony_ci /// was read, in which case the handshake should be continued via 362692f3ab15Sopenharmony_ci /// `accept`. If a HelloRetryRequest containing a fresh cookie was 362792f3ab15Sopenharmony_ci /// transmitted, `Ok(false)` is returned instead. If the handshake cannot 362892f3ab15Sopenharmony_ci /// proceed at all, `Err` is returned. 362992f3ab15Sopenharmony_ci #[corresponds(SSL_stateless)] 363092f3ab15Sopenharmony_ci #[cfg(ossl111)] 363192f3ab15Sopenharmony_ci pub fn stateless(&mut self) -> Result<bool, ErrorStack> { 363292f3ab15Sopenharmony_ci match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } { 363392f3ab15Sopenharmony_ci 1 => Ok(true), 363492f3ab15Sopenharmony_ci 0 => Ok(false), 363592f3ab15Sopenharmony_ci -1 => Err(ErrorStack::get()), 363692f3ab15Sopenharmony_ci _ => unreachable!(), 363792f3ab15Sopenharmony_ci } 363892f3ab15Sopenharmony_ci } 363992f3ab15Sopenharmony_ci 364092f3ab15Sopenharmony_ci /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`. 364192f3ab15Sopenharmony_ci /// 364292f3ab15Sopenharmony_ci /// It is particularly useful with a non-blocking socket, where the error value will identify if 364392f3ab15Sopenharmony_ci /// OpenSSL is waiting on read or write readiness. 364492f3ab15Sopenharmony_ci #[corresponds(SSL_read)] 364592f3ab15Sopenharmony_ci pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 364692f3ab15Sopenharmony_ci // The interpretation of the return code here is a little odd with a 364792f3ab15Sopenharmony_ci // zero-length write. OpenSSL will likely correctly report back to us 364892f3ab15Sopenharmony_ci // that it read zero bytes, but zero is also the sentinel for "error". 364992f3ab15Sopenharmony_ci // To avoid that confusion short-circuit that logic and return quickly 365092f3ab15Sopenharmony_ci // if `buf` has a length of zero. 365192f3ab15Sopenharmony_ci if buf.is_empty() { 365292f3ab15Sopenharmony_ci return Ok(0); 365392f3ab15Sopenharmony_ci } 365492f3ab15Sopenharmony_ci 365592f3ab15Sopenharmony_ci let ret = self.ssl.read(buf); 365692f3ab15Sopenharmony_ci if ret > 0 { 365792f3ab15Sopenharmony_ci Ok(ret as usize) 365892f3ab15Sopenharmony_ci } else { 365992f3ab15Sopenharmony_ci Err(self.make_error(ret)) 366092f3ab15Sopenharmony_ci } 366192f3ab15Sopenharmony_ci } 366292f3ab15Sopenharmony_ci 366392f3ab15Sopenharmony_ci /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`. 366492f3ab15Sopenharmony_ci /// 366592f3ab15Sopenharmony_ci /// It is particularly useful with a non-blocking socket, where the error value will identify if 366692f3ab15Sopenharmony_ci /// OpenSSL is waiting on read or write readiness. 366792f3ab15Sopenharmony_ci #[corresponds(SSL_write)] 366892f3ab15Sopenharmony_ci pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> { 366992f3ab15Sopenharmony_ci // See above for why we short-circuit on zero-length buffers 367092f3ab15Sopenharmony_ci if buf.is_empty() { 367192f3ab15Sopenharmony_ci return Ok(0); 367292f3ab15Sopenharmony_ci } 367392f3ab15Sopenharmony_ci 367492f3ab15Sopenharmony_ci let ret = self.ssl.write(buf); 367592f3ab15Sopenharmony_ci if ret > 0 { 367692f3ab15Sopenharmony_ci Ok(ret as usize) 367792f3ab15Sopenharmony_ci } else { 367892f3ab15Sopenharmony_ci Err(self.make_error(ret)) 367992f3ab15Sopenharmony_ci } 368092f3ab15Sopenharmony_ci } 368192f3ab15Sopenharmony_ci 368292f3ab15Sopenharmony_ci /// Reads data from the stream, without removing it from the queue. 368392f3ab15Sopenharmony_ci #[corresponds(SSL_peek)] 368492f3ab15Sopenharmony_ci pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 368592f3ab15Sopenharmony_ci // See above for why we short-circuit on zero-length buffers 368692f3ab15Sopenharmony_ci if buf.is_empty() { 368792f3ab15Sopenharmony_ci return Ok(0); 368892f3ab15Sopenharmony_ci } 368992f3ab15Sopenharmony_ci 369092f3ab15Sopenharmony_ci let ret = self.ssl.peek(buf); 369192f3ab15Sopenharmony_ci if ret > 0 { 369292f3ab15Sopenharmony_ci Ok(ret as usize) 369392f3ab15Sopenharmony_ci } else { 369492f3ab15Sopenharmony_ci Err(self.make_error(ret)) 369592f3ab15Sopenharmony_ci } 369692f3ab15Sopenharmony_ci } 369792f3ab15Sopenharmony_ci 369892f3ab15Sopenharmony_ci /// Shuts down the session. 369992f3ab15Sopenharmony_ci /// 370092f3ab15Sopenharmony_ci /// The shutdown process consists of two steps. The first step sends a close notify message to 370192f3ab15Sopenharmony_ci /// the peer, after which `ShutdownResult::Sent` is returned. The second step awaits the receipt 370292f3ab15Sopenharmony_ci /// of a close notify message from the peer, after which `ShutdownResult::Received` is returned. 370392f3ab15Sopenharmony_ci /// 370492f3ab15Sopenharmony_ci /// While the connection may be closed after the first step, it is recommended to fully shut the 370592f3ab15Sopenharmony_ci /// session down. In particular, it must be fully shut down if the connection is to be used for 370692f3ab15Sopenharmony_ci /// further communication in the future. 370792f3ab15Sopenharmony_ci #[corresponds(SSL_shutdown)] 370892f3ab15Sopenharmony_ci pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> { 370992f3ab15Sopenharmony_ci match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } { 371092f3ab15Sopenharmony_ci 0 => Ok(ShutdownResult::Sent), 371192f3ab15Sopenharmony_ci 1 => Ok(ShutdownResult::Received), 371292f3ab15Sopenharmony_ci n => Err(self.make_error(n)), 371392f3ab15Sopenharmony_ci } 371492f3ab15Sopenharmony_ci } 371592f3ab15Sopenharmony_ci 371692f3ab15Sopenharmony_ci /// Returns the session's shutdown state. 371792f3ab15Sopenharmony_ci #[corresponds(SSL_get_shutdown)] 371892f3ab15Sopenharmony_ci pub fn get_shutdown(&mut self) -> ShutdownState { 371992f3ab15Sopenharmony_ci unsafe { 372092f3ab15Sopenharmony_ci let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr()); 372192f3ab15Sopenharmony_ci ShutdownState { bits } 372292f3ab15Sopenharmony_ci } 372392f3ab15Sopenharmony_ci } 372492f3ab15Sopenharmony_ci 372592f3ab15Sopenharmony_ci /// Sets the session's shutdown state. 372692f3ab15Sopenharmony_ci /// 372792f3ab15Sopenharmony_ci /// This can be used to tell OpenSSL that the session should be cached even if a full two-way 372892f3ab15Sopenharmony_ci /// shutdown was not completed. 372992f3ab15Sopenharmony_ci #[corresponds(SSL_set_shutdown)] 373092f3ab15Sopenharmony_ci pub fn set_shutdown(&mut self, state: ShutdownState) { 373192f3ab15Sopenharmony_ci unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) } 373292f3ab15Sopenharmony_ci } 373392f3ab15Sopenharmony_ci} 373492f3ab15Sopenharmony_ci 373592f3ab15Sopenharmony_ciimpl<S> SslStream<S> { 373692f3ab15Sopenharmony_ci fn make_error(&mut self, ret: c_int) -> Error { 373792f3ab15Sopenharmony_ci self.check_panic(); 373892f3ab15Sopenharmony_ci 373992f3ab15Sopenharmony_ci let code = self.ssl.get_error(ret); 374092f3ab15Sopenharmony_ci 374192f3ab15Sopenharmony_ci let cause = match code { 374292f3ab15Sopenharmony_ci ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())), 374392f3ab15Sopenharmony_ci ErrorCode::SYSCALL => { 374492f3ab15Sopenharmony_ci let errs = ErrorStack::get(); 374592f3ab15Sopenharmony_ci if errs.errors().is_empty() { 374692f3ab15Sopenharmony_ci self.get_bio_error().map(InnerError::Io) 374792f3ab15Sopenharmony_ci } else { 374892f3ab15Sopenharmony_ci Some(InnerError::Ssl(errs)) 374992f3ab15Sopenharmony_ci } 375092f3ab15Sopenharmony_ci } 375192f3ab15Sopenharmony_ci ErrorCode::ZERO_RETURN => None, 375292f3ab15Sopenharmony_ci ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 375392f3ab15Sopenharmony_ci self.get_bio_error().map(InnerError::Io) 375492f3ab15Sopenharmony_ci } 375592f3ab15Sopenharmony_ci _ => None, 375692f3ab15Sopenharmony_ci }; 375792f3ab15Sopenharmony_ci 375892f3ab15Sopenharmony_ci Error { code, cause } 375992f3ab15Sopenharmony_ci } 376092f3ab15Sopenharmony_ci 376192f3ab15Sopenharmony_ci fn check_panic(&mut self) { 376292f3ab15Sopenharmony_ci if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } { 376392f3ab15Sopenharmony_ci resume_unwind(err) 376492f3ab15Sopenharmony_ci } 376592f3ab15Sopenharmony_ci } 376692f3ab15Sopenharmony_ci 376792f3ab15Sopenharmony_ci fn get_bio_error(&mut self) -> Option<io::Error> { 376892f3ab15Sopenharmony_ci unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) } 376992f3ab15Sopenharmony_ci } 377092f3ab15Sopenharmony_ci 377192f3ab15Sopenharmony_ci /// Returns a shared reference to the underlying stream. 377292f3ab15Sopenharmony_ci pub fn get_ref(&self) -> &S { 377392f3ab15Sopenharmony_ci unsafe { 377492f3ab15Sopenharmony_ci let bio = self.ssl.get_raw_rbio(); 377592f3ab15Sopenharmony_ci bio::get_ref(bio) 377692f3ab15Sopenharmony_ci } 377792f3ab15Sopenharmony_ci } 377892f3ab15Sopenharmony_ci 377992f3ab15Sopenharmony_ci /// Returns a mutable reference to the underlying stream. 378092f3ab15Sopenharmony_ci /// 378192f3ab15Sopenharmony_ci /// # Warning 378292f3ab15Sopenharmony_ci /// 378392f3ab15Sopenharmony_ci /// It is inadvisable to read from or write to the underlying stream as it 378492f3ab15Sopenharmony_ci /// will most likely corrupt the SSL session. 378592f3ab15Sopenharmony_ci pub fn get_mut(&mut self) -> &mut S { 378692f3ab15Sopenharmony_ci unsafe { 378792f3ab15Sopenharmony_ci let bio = self.ssl.get_raw_rbio(); 378892f3ab15Sopenharmony_ci bio::get_mut(bio) 378992f3ab15Sopenharmony_ci } 379092f3ab15Sopenharmony_ci } 379192f3ab15Sopenharmony_ci 379292f3ab15Sopenharmony_ci /// Returns a shared reference to the `Ssl` object associated with this stream. 379392f3ab15Sopenharmony_ci pub fn ssl(&self) -> &SslRef { 379492f3ab15Sopenharmony_ci &self.ssl 379592f3ab15Sopenharmony_ci } 379692f3ab15Sopenharmony_ci} 379792f3ab15Sopenharmony_ci 379892f3ab15Sopenharmony_ciimpl<S: Read + Write> Read for SslStream<S> { 379992f3ab15Sopenharmony_ci fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { 380092f3ab15Sopenharmony_ci loop { 380192f3ab15Sopenharmony_ci match self.ssl_read(buf) { 380292f3ab15Sopenharmony_ci Ok(n) => return Ok(n), 380392f3ab15Sopenharmony_ci Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0), 380492f3ab15Sopenharmony_ci Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => { 380592f3ab15Sopenharmony_ci return Ok(0); 380692f3ab15Sopenharmony_ci } 380792f3ab15Sopenharmony_ci Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} 380892f3ab15Sopenharmony_ci Err(e) => { 380992f3ab15Sopenharmony_ci return Err(e 381092f3ab15Sopenharmony_ci .into_io_error() 381192f3ab15Sopenharmony_ci .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))); 381292f3ab15Sopenharmony_ci } 381392f3ab15Sopenharmony_ci } 381492f3ab15Sopenharmony_ci } 381592f3ab15Sopenharmony_ci } 381692f3ab15Sopenharmony_ci} 381792f3ab15Sopenharmony_ci 381892f3ab15Sopenharmony_ciimpl<S: Read + Write> Write for SslStream<S> { 381992f3ab15Sopenharmony_ci fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 382092f3ab15Sopenharmony_ci loop { 382192f3ab15Sopenharmony_ci match self.ssl_write(buf) { 382292f3ab15Sopenharmony_ci Ok(n) => return Ok(n), 382392f3ab15Sopenharmony_ci Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} 382492f3ab15Sopenharmony_ci Err(e) => { 382592f3ab15Sopenharmony_ci return Err(e 382692f3ab15Sopenharmony_ci .into_io_error() 382792f3ab15Sopenharmony_ci .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))); 382892f3ab15Sopenharmony_ci } 382992f3ab15Sopenharmony_ci } 383092f3ab15Sopenharmony_ci } 383192f3ab15Sopenharmony_ci } 383292f3ab15Sopenharmony_ci 383392f3ab15Sopenharmony_ci fn flush(&mut self) -> io::Result<()> { 383492f3ab15Sopenharmony_ci self.get_mut().flush() 383592f3ab15Sopenharmony_ci } 383692f3ab15Sopenharmony_ci} 383792f3ab15Sopenharmony_ci 383892f3ab15Sopenharmony_ci/// A partially constructed `SslStream`, useful for unusual handshakes. 383992f3ab15Sopenharmony_ci#[deprecated( 384092f3ab15Sopenharmony_ci since = "0.10.32", 384192f3ab15Sopenharmony_ci note = "use the methods directly on Ssl/SslStream instead" 384292f3ab15Sopenharmony_ci)] 384392f3ab15Sopenharmony_cipub struct SslStreamBuilder<S> { 384492f3ab15Sopenharmony_ci inner: SslStream<S>, 384592f3ab15Sopenharmony_ci} 384692f3ab15Sopenharmony_ci 384792f3ab15Sopenharmony_ci#[allow(deprecated)] 384892f3ab15Sopenharmony_ciimpl<S> SslStreamBuilder<S> 384992f3ab15Sopenharmony_ciwhere 385092f3ab15Sopenharmony_ci S: Read + Write, 385192f3ab15Sopenharmony_ci{ 385292f3ab15Sopenharmony_ci /// Begin creating an `SslStream` atop `stream` 385392f3ab15Sopenharmony_ci pub fn new(ssl: Ssl, stream: S) -> Self { 385492f3ab15Sopenharmony_ci Self { 385592f3ab15Sopenharmony_ci inner: SslStream::new(ssl, stream).unwrap(), 385692f3ab15Sopenharmony_ci } 385792f3ab15Sopenharmony_ci } 385892f3ab15Sopenharmony_ci 385992f3ab15Sopenharmony_ci /// Perform a stateless server-side handshake 386092f3ab15Sopenharmony_ci /// 386192f3ab15Sopenharmony_ci /// Requires that cookie generation and verification callbacks were 386292f3ab15Sopenharmony_ci /// set on the SSL context. 386392f3ab15Sopenharmony_ci /// 386492f3ab15Sopenharmony_ci /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie 386592f3ab15Sopenharmony_ci /// was read, in which case the handshake should be continued via 386692f3ab15Sopenharmony_ci /// `accept`. If a HelloRetryRequest containing a fresh cookie was 386792f3ab15Sopenharmony_ci /// transmitted, `Ok(false)` is returned instead. If the handshake cannot 386892f3ab15Sopenharmony_ci /// proceed at all, `Err` is returned. 386992f3ab15Sopenharmony_ci /// 387092f3ab15Sopenharmony_ci /// This corresponds to [`SSL_stateless`] 387192f3ab15Sopenharmony_ci /// 387292f3ab15Sopenharmony_ci /// [`SSL_stateless`]: https://www.openssl.org/docs/manmaster/man3/SSL_stateless.html 387392f3ab15Sopenharmony_ci #[cfg(ossl111)] 387492f3ab15Sopenharmony_ci pub fn stateless(&mut self) -> Result<bool, ErrorStack> { 387592f3ab15Sopenharmony_ci match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } { 387692f3ab15Sopenharmony_ci 1 => Ok(true), 387792f3ab15Sopenharmony_ci 0 => Ok(false), 387892f3ab15Sopenharmony_ci -1 => Err(ErrorStack::get()), 387992f3ab15Sopenharmony_ci _ => unreachable!(), 388092f3ab15Sopenharmony_ci } 388192f3ab15Sopenharmony_ci } 388292f3ab15Sopenharmony_ci 388392f3ab15Sopenharmony_ci /// Configure as an outgoing stream from a client. 388492f3ab15Sopenharmony_ci /// 388592f3ab15Sopenharmony_ci /// This corresponds to [`SSL_set_connect_state`]. 388692f3ab15Sopenharmony_ci /// 388792f3ab15Sopenharmony_ci /// [`SSL_set_connect_state`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_connect_state.html 388892f3ab15Sopenharmony_ci pub fn set_connect_state(&mut self) { 388992f3ab15Sopenharmony_ci unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) } 389092f3ab15Sopenharmony_ci } 389192f3ab15Sopenharmony_ci 389292f3ab15Sopenharmony_ci /// Configure as an incoming stream to a server. 389392f3ab15Sopenharmony_ci /// 389492f3ab15Sopenharmony_ci /// This corresponds to [`SSL_set_accept_state`]. 389592f3ab15Sopenharmony_ci /// 389692f3ab15Sopenharmony_ci /// [`SSL_set_accept_state`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_accept_state.html 389792f3ab15Sopenharmony_ci pub fn set_accept_state(&mut self) { 389892f3ab15Sopenharmony_ci unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) } 389992f3ab15Sopenharmony_ci } 390092f3ab15Sopenharmony_ci 390192f3ab15Sopenharmony_ci /// See `Ssl::connect` 390292f3ab15Sopenharmony_ci pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> { 390392f3ab15Sopenharmony_ci match self.inner.connect() { 390492f3ab15Sopenharmony_ci Ok(()) => Ok(self.inner), 390592f3ab15Sopenharmony_ci Err(error) => match error.code() { 390692f3ab15Sopenharmony_ci ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 390792f3ab15Sopenharmony_ci Err(HandshakeError::WouldBlock(MidHandshakeSslStream { 390892f3ab15Sopenharmony_ci stream: self.inner, 390992f3ab15Sopenharmony_ci error, 391092f3ab15Sopenharmony_ci })) 391192f3ab15Sopenharmony_ci } 391292f3ab15Sopenharmony_ci _ => Err(HandshakeError::Failure(MidHandshakeSslStream { 391392f3ab15Sopenharmony_ci stream: self.inner, 391492f3ab15Sopenharmony_ci error, 391592f3ab15Sopenharmony_ci })), 391692f3ab15Sopenharmony_ci }, 391792f3ab15Sopenharmony_ci } 391892f3ab15Sopenharmony_ci } 391992f3ab15Sopenharmony_ci 392092f3ab15Sopenharmony_ci /// See `Ssl::accept` 392192f3ab15Sopenharmony_ci pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> { 392292f3ab15Sopenharmony_ci match self.inner.accept() { 392392f3ab15Sopenharmony_ci Ok(()) => Ok(self.inner), 392492f3ab15Sopenharmony_ci Err(error) => match error.code() { 392592f3ab15Sopenharmony_ci ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 392692f3ab15Sopenharmony_ci Err(HandshakeError::WouldBlock(MidHandshakeSslStream { 392792f3ab15Sopenharmony_ci stream: self.inner, 392892f3ab15Sopenharmony_ci error, 392992f3ab15Sopenharmony_ci })) 393092f3ab15Sopenharmony_ci } 393192f3ab15Sopenharmony_ci _ => Err(HandshakeError::Failure(MidHandshakeSslStream { 393292f3ab15Sopenharmony_ci stream: self.inner, 393392f3ab15Sopenharmony_ci error, 393492f3ab15Sopenharmony_ci })), 393592f3ab15Sopenharmony_ci }, 393692f3ab15Sopenharmony_ci } 393792f3ab15Sopenharmony_ci } 393892f3ab15Sopenharmony_ci 393992f3ab15Sopenharmony_ci /// Initiates the handshake. 394092f3ab15Sopenharmony_ci /// 394192f3ab15Sopenharmony_ci /// This will fail if `set_accept_state` or `set_connect_state` was not called first. 394292f3ab15Sopenharmony_ci /// 394392f3ab15Sopenharmony_ci /// This corresponds to [`SSL_do_handshake`]. 394492f3ab15Sopenharmony_ci /// 394592f3ab15Sopenharmony_ci /// [`SSL_do_handshake`]: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html 394692f3ab15Sopenharmony_ci pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> { 394792f3ab15Sopenharmony_ci match self.inner.do_handshake() { 394892f3ab15Sopenharmony_ci Ok(()) => Ok(self.inner), 394992f3ab15Sopenharmony_ci Err(error) => match error.code() { 395092f3ab15Sopenharmony_ci ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 395192f3ab15Sopenharmony_ci Err(HandshakeError::WouldBlock(MidHandshakeSslStream { 395292f3ab15Sopenharmony_ci stream: self.inner, 395392f3ab15Sopenharmony_ci error, 395492f3ab15Sopenharmony_ci })) 395592f3ab15Sopenharmony_ci } 395692f3ab15Sopenharmony_ci _ => Err(HandshakeError::Failure(MidHandshakeSslStream { 395792f3ab15Sopenharmony_ci stream: self.inner, 395892f3ab15Sopenharmony_ci error, 395992f3ab15Sopenharmony_ci })), 396092f3ab15Sopenharmony_ci }, 396192f3ab15Sopenharmony_ci } 396292f3ab15Sopenharmony_ci } 396392f3ab15Sopenharmony_ci 396492f3ab15Sopenharmony_ci /// Read application data transmitted by a client before handshake 396592f3ab15Sopenharmony_ci /// completion. 396692f3ab15Sopenharmony_ci /// 396792f3ab15Sopenharmony_ci /// Useful for reducing latency, but vulnerable to replay attacks. Call 396892f3ab15Sopenharmony_ci /// `set_accept_state` first. 396992f3ab15Sopenharmony_ci /// 397092f3ab15Sopenharmony_ci /// Returns `Ok(0)` if all early data has been read. 397192f3ab15Sopenharmony_ci /// 397292f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 397392f3ab15Sopenharmony_ci /// 397492f3ab15Sopenharmony_ci /// This corresponds to [`SSL_read_early_data`]. 397592f3ab15Sopenharmony_ci /// 397692f3ab15Sopenharmony_ci /// [`SSL_read_early_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_read_early_data.html 397792f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 397892f3ab15Sopenharmony_ci pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 397992f3ab15Sopenharmony_ci self.inner.read_early_data(buf) 398092f3ab15Sopenharmony_ci } 398192f3ab15Sopenharmony_ci 398292f3ab15Sopenharmony_ci /// Send data to the server without blocking on handshake completion. 398392f3ab15Sopenharmony_ci /// 398492f3ab15Sopenharmony_ci /// Useful for reducing latency, but vulnerable to replay attacks. Call 398592f3ab15Sopenharmony_ci /// `set_connect_state` first. 398692f3ab15Sopenharmony_ci /// 398792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 398892f3ab15Sopenharmony_ci /// 398992f3ab15Sopenharmony_ci /// This corresponds to [`SSL_write_early_data`]. 399092f3ab15Sopenharmony_ci /// 399192f3ab15Sopenharmony_ci /// [`SSL_write_early_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_write_early_data.html 399292f3ab15Sopenharmony_ci #[cfg(any(ossl111, libressl340))] 399392f3ab15Sopenharmony_ci pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> { 399492f3ab15Sopenharmony_ci self.inner.write_early_data(buf) 399592f3ab15Sopenharmony_ci } 399692f3ab15Sopenharmony_ci} 399792f3ab15Sopenharmony_ci 399892f3ab15Sopenharmony_ci#[allow(deprecated)] 399992f3ab15Sopenharmony_ciimpl<S> SslStreamBuilder<S> { 400092f3ab15Sopenharmony_ci /// Returns a shared reference to the underlying stream. 400192f3ab15Sopenharmony_ci pub fn get_ref(&self) -> &S { 400292f3ab15Sopenharmony_ci unsafe { 400392f3ab15Sopenharmony_ci let bio = self.inner.ssl.get_raw_rbio(); 400492f3ab15Sopenharmony_ci bio::get_ref(bio) 400592f3ab15Sopenharmony_ci } 400692f3ab15Sopenharmony_ci } 400792f3ab15Sopenharmony_ci 400892f3ab15Sopenharmony_ci /// Returns a mutable reference to the underlying stream. 400992f3ab15Sopenharmony_ci /// 401092f3ab15Sopenharmony_ci /// # Warning 401192f3ab15Sopenharmony_ci /// 401292f3ab15Sopenharmony_ci /// It is inadvisable to read from or write to the underlying stream as it 401392f3ab15Sopenharmony_ci /// will most likely corrupt the SSL session. 401492f3ab15Sopenharmony_ci pub fn get_mut(&mut self) -> &mut S { 401592f3ab15Sopenharmony_ci unsafe { 401692f3ab15Sopenharmony_ci let bio = self.inner.ssl.get_raw_rbio(); 401792f3ab15Sopenharmony_ci bio::get_mut(bio) 401892f3ab15Sopenharmony_ci } 401992f3ab15Sopenharmony_ci } 402092f3ab15Sopenharmony_ci 402192f3ab15Sopenharmony_ci /// Returns a shared reference to the `Ssl` object associated with this builder. 402292f3ab15Sopenharmony_ci pub fn ssl(&self) -> &SslRef { 402392f3ab15Sopenharmony_ci &self.inner.ssl 402492f3ab15Sopenharmony_ci } 402592f3ab15Sopenharmony_ci 402692f3ab15Sopenharmony_ci /// Set the DTLS MTU size. 402792f3ab15Sopenharmony_ci /// 402892f3ab15Sopenharmony_ci /// It will be ignored if the value is smaller than the minimum packet size 402992f3ab15Sopenharmony_ci /// the DTLS protocol requires. 403092f3ab15Sopenharmony_ci /// 403192f3ab15Sopenharmony_ci /// # Panics 403292f3ab15Sopenharmony_ci /// This function panics if the given mtu size can't be represented in a positive `c_long` range 403392f3ab15Sopenharmony_ci #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")] 403492f3ab15Sopenharmony_ci pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) { 403592f3ab15Sopenharmony_ci unsafe { 403692f3ab15Sopenharmony_ci let bio = self.inner.ssl.get_raw_rbio(); 403792f3ab15Sopenharmony_ci bio::set_dtls_mtu_size::<S>(bio, mtu_size); 403892f3ab15Sopenharmony_ci } 403992f3ab15Sopenharmony_ci } 404092f3ab15Sopenharmony_ci} 404192f3ab15Sopenharmony_ci 404292f3ab15Sopenharmony_ci/// The result of a shutdown request. 404392f3ab15Sopenharmony_ci#[derive(Copy, Clone, Debug, PartialEq, Eq)] 404492f3ab15Sopenharmony_cipub enum ShutdownResult { 404592f3ab15Sopenharmony_ci /// A close notify message has been sent to the peer. 404692f3ab15Sopenharmony_ci Sent, 404792f3ab15Sopenharmony_ci 404892f3ab15Sopenharmony_ci /// A close notify response message has been received from the peer. 404992f3ab15Sopenharmony_ci Received, 405092f3ab15Sopenharmony_ci} 405192f3ab15Sopenharmony_ci 405292f3ab15Sopenharmony_cibitflags! { 405392f3ab15Sopenharmony_ci /// The shutdown state of a session. 405492f3ab15Sopenharmony_ci pub struct ShutdownState: c_int { 405592f3ab15Sopenharmony_ci /// A close notify message has been sent to the peer. 405692f3ab15Sopenharmony_ci const SENT = ffi::SSL_SENT_SHUTDOWN; 405792f3ab15Sopenharmony_ci /// A close notify message has been received from the peer. 405892f3ab15Sopenharmony_ci const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN; 405992f3ab15Sopenharmony_ci } 406092f3ab15Sopenharmony_ci} 406192f3ab15Sopenharmony_ci 406292f3ab15Sopenharmony_cicfg_if! { 406392f3ab15Sopenharmony_ci if #[cfg(any(boringssl, ossl110, libressl273))] { 406492f3ab15Sopenharmony_ci use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server}; 406592f3ab15Sopenharmony_ci } else { 406692f3ab15Sopenharmony_ci #[allow(bad_style)] 406792f3ab15Sopenharmony_ci pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int { 406892f3ab15Sopenharmony_ci ffi::CRYPTO_add_lock( 406992f3ab15Sopenharmony_ci &mut (*ssl).references, 407092f3ab15Sopenharmony_ci 1, 407192f3ab15Sopenharmony_ci ffi::CRYPTO_LOCK_SSL_CTX, 407292f3ab15Sopenharmony_ci "mod.rs\0".as_ptr() as *const _, 407392f3ab15Sopenharmony_ci line!() as c_int, 407492f3ab15Sopenharmony_ci ); 407592f3ab15Sopenharmony_ci 0 407692f3ab15Sopenharmony_ci } 407792f3ab15Sopenharmony_ci 407892f3ab15Sopenharmony_ci #[allow(bad_style)] 407992f3ab15Sopenharmony_ci pub unsafe fn SSL_SESSION_get_master_key( 408092f3ab15Sopenharmony_ci session: *const ffi::SSL_SESSION, 408192f3ab15Sopenharmony_ci out: *mut c_uchar, 408292f3ab15Sopenharmony_ci mut outlen: usize, 408392f3ab15Sopenharmony_ci ) -> usize { 408492f3ab15Sopenharmony_ci if outlen == 0 { 408592f3ab15Sopenharmony_ci return (*session).master_key_length as usize; 408692f3ab15Sopenharmony_ci } 408792f3ab15Sopenharmony_ci if outlen > (*session).master_key_length as usize { 408892f3ab15Sopenharmony_ci outlen = (*session).master_key_length as usize; 408992f3ab15Sopenharmony_ci } 409092f3ab15Sopenharmony_ci ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen); 409192f3ab15Sopenharmony_ci outlen 409292f3ab15Sopenharmony_ci } 409392f3ab15Sopenharmony_ci 409492f3ab15Sopenharmony_ci #[allow(bad_style)] 409592f3ab15Sopenharmony_ci pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int { 409692f3ab15Sopenharmony_ci (*s).server 409792f3ab15Sopenharmony_ci } 409892f3ab15Sopenharmony_ci 409992f3ab15Sopenharmony_ci #[allow(bad_style)] 410092f3ab15Sopenharmony_ci pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int { 410192f3ab15Sopenharmony_ci ffi::CRYPTO_add_lock( 410292f3ab15Sopenharmony_ci &mut (*ses).references, 410392f3ab15Sopenharmony_ci 1, 410492f3ab15Sopenharmony_ci ffi::CRYPTO_LOCK_SSL_CTX, 410592f3ab15Sopenharmony_ci "mod.rs\0".as_ptr() as *const _, 410692f3ab15Sopenharmony_ci line!() as c_int, 410792f3ab15Sopenharmony_ci ); 410892f3ab15Sopenharmony_ci 0 410992f3ab15Sopenharmony_ci } 411092f3ab15Sopenharmony_ci } 411192f3ab15Sopenharmony_ci} 411292f3ab15Sopenharmony_ci 411392f3ab15Sopenharmony_cicfg_if! { 411492f3ab15Sopenharmony_ci if #[cfg(ossl300)] { 411592f3ab15Sopenharmony_ci use ffi::SSL_get1_peer_certificate; 411692f3ab15Sopenharmony_ci } else { 411792f3ab15Sopenharmony_ci use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate; 411892f3ab15Sopenharmony_ci } 411992f3ab15Sopenharmony_ci} 412092f3ab15Sopenharmony_cicfg_if! { 412192f3ab15Sopenharmony_ci if #[cfg(any(boringssl, ossl110, libressl291))] { 412292f3ab15Sopenharmony_ci use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method}; 412392f3ab15Sopenharmony_ci } else { 412492f3ab15Sopenharmony_ci use ffi::{ 412592f3ab15Sopenharmony_ci SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method, 412692f3ab15Sopenharmony_ci SSLv23_server_method as TLS_server_method, 412792f3ab15Sopenharmony_ci }; 412892f3ab15Sopenharmony_ci } 412992f3ab15Sopenharmony_ci} 413092f3ab15Sopenharmony_cicfg_if! { 413192f3ab15Sopenharmony_ci if #[cfg(ossl110)] { 413292f3ab15Sopenharmony_ci unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { 413392f3ab15Sopenharmony_ci ffi::CRYPTO_get_ex_new_index( 413492f3ab15Sopenharmony_ci ffi::CRYPTO_EX_INDEX_SSL_CTX, 413592f3ab15Sopenharmony_ci 0, 413692f3ab15Sopenharmony_ci ptr::null_mut(), 413792f3ab15Sopenharmony_ci None, 413892f3ab15Sopenharmony_ci None, 413992f3ab15Sopenharmony_ci Some(f), 414092f3ab15Sopenharmony_ci ) 414192f3ab15Sopenharmony_ci } 414292f3ab15Sopenharmony_ci 414392f3ab15Sopenharmony_ci unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { 414492f3ab15Sopenharmony_ci ffi::CRYPTO_get_ex_new_index( 414592f3ab15Sopenharmony_ci ffi::CRYPTO_EX_INDEX_SSL, 414692f3ab15Sopenharmony_ci 0, 414792f3ab15Sopenharmony_ci ptr::null_mut(), 414892f3ab15Sopenharmony_ci None, 414992f3ab15Sopenharmony_ci None, 415092f3ab15Sopenharmony_ci Some(f), 415192f3ab15Sopenharmony_ci ) 415292f3ab15Sopenharmony_ci } 415392f3ab15Sopenharmony_ci } else { 415492f3ab15Sopenharmony_ci use std::sync::Once; 415592f3ab15Sopenharmony_ci 415692f3ab15Sopenharmony_ci unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { 415792f3ab15Sopenharmony_ci // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest 415892f3ab15Sopenharmony_ci static ONCE: Once = Once::new(); 415992f3ab15Sopenharmony_ci ONCE.call_once(|| { 416092f3ab15Sopenharmony_ci cfg_if! { 416192f3ab15Sopenharmony_ci if #[cfg(not(boringssl))] { 416292f3ab15Sopenharmony_ci ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None); 416392f3ab15Sopenharmony_ci } else { 416492f3ab15Sopenharmony_ci ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None); 416592f3ab15Sopenharmony_ci } 416692f3ab15Sopenharmony_ci } 416792f3ab15Sopenharmony_ci }); 416892f3ab15Sopenharmony_ci 416992f3ab15Sopenharmony_ci cfg_if! { 417092f3ab15Sopenharmony_ci if #[cfg(not(boringssl))] { 417192f3ab15Sopenharmony_ci ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)) 417292f3ab15Sopenharmony_ci } else { 417392f3ab15Sopenharmony_ci ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f) 417492f3ab15Sopenharmony_ci } 417592f3ab15Sopenharmony_ci } 417692f3ab15Sopenharmony_ci } 417792f3ab15Sopenharmony_ci 417892f3ab15Sopenharmony_ci unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { 417992f3ab15Sopenharmony_ci // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest 418092f3ab15Sopenharmony_ci static ONCE: Once = Once::new(); 418192f3ab15Sopenharmony_ci ONCE.call_once(|| { 418292f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 418392f3ab15Sopenharmony_ci ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None); 418492f3ab15Sopenharmony_ci #[cfg(boringssl)] 418592f3ab15Sopenharmony_ci ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None); 418692f3ab15Sopenharmony_ci }); 418792f3ab15Sopenharmony_ci 418892f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 418992f3ab15Sopenharmony_ci return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)); 419092f3ab15Sopenharmony_ci #[cfg(boringssl)] 419192f3ab15Sopenharmony_ci return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f); 419292f3ab15Sopenharmony_ci } 419392f3ab15Sopenharmony_ci } 419492f3ab15Sopenharmony_ci} 4195