Loading openssl-sys/src/ssl.rs +15 −0 Original line number Diff line number Diff line Loading @@ -349,6 +349,8 @@ pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94; pub const SSL_CTRL_SET_SIGALGS_LIST: c_int = 98; #[cfg(ossl102)] pub const SSL_CTRL_SET_VERIFY_CERT_STORE: c_int = 106; #[cfg(ossl300)] pub const SSL_CTRL_GET_PEER_TMP_KEY: c_int = 109; #[cfg(ossl110)] pub const SSL_CTRL_GET_EXTMS_SUPPORT: c_int = 122; #[cfg(any(ossl110, libressl261))] Loading @@ -359,6 +361,8 @@ pub const SSL_CTRL_SET_MAX_PROTO_VERSION: c_int = 124; pub const SSL_CTRL_GET_MIN_PROTO_VERSION: c_int = 130; #[cfg(any(ossl110g, libressl270))] pub const SSL_CTRL_GET_MAX_PROTO_VERSION: c_int = 131; #[cfg(ossl300)] pub const SSL_CTRL_GET_TMP_KEY: c_int = 133; pub unsafe fn SSL_CTX_set_tmp_dh(ctx: *mut SSL_CTX, dh: *mut DH) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, dh as *mut c_void) Loading Loading @@ -506,6 +510,17 @@ cfg_if! { } } } cfg_if! { if #[cfg(ossl300)] { pub unsafe fn SSL_get_peer_tmp_key(ssl: *mut SSL, key: *mut *mut EVP_PKEY) -> c_long { SSL_ctrl(ssl, SSL_CTRL_GET_PEER_TMP_KEY, 0, key as *mut c_void) } pub unsafe fn SSL_get_tmp_key(ssl: *mut SSL, key: *mut *mut EVP_PKEY) -> c_long { SSL_ctrl(ssl, SSL_CTRL_GET_TMP_KEY, 0, key as *mut c_void) } } } #[cfg(ossl111)] pub const SSL_CLIENT_HELLO_SUCCESS: c_int = 1; Loading openssl/src/lib.rs +15 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,8 @@ pub use ffi::init; use libc::c_int; #[cfg(ossl300)] use libc::c_long; use crate::error::ErrorStack; Loading Loading @@ -212,6 +214,19 @@ fn cvt(r: c_int) -> Result<c_int, ErrorStack> { } } // cvt_long is currently only used in functions that require openssl >= 3.0.0, // so this cfg statement is used to avoid "unused function" errors when // compiling with openssl < 3.0.0 #[inline] #[cfg(ossl300)] fn cvt_long(r: c_long) -> Result<c_long, ErrorStack> { if r <= 0 { Err(ErrorStack::get()) } else { Ok(r) } } #[inline] fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> { if r < 0 { Loading openssl/src/ssl/mod.rs +36 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ //! } //! } //! ``` #[cfg(ossl300)] use crate::cvt_long; use crate::dh::{Dh, DhRef}; #[cfg(all(ossl101, not(ossl110)))] use crate::ec::EcKey; Loading @@ -68,6 +70,8 @@ use crate::hash::MessageDigest; #[cfg(any(ossl110, libressl270))] use crate::nid::Nid; use crate::pkey::{HasPrivate, PKeyRef, Params, Private}; #[cfg(ossl300)] use crate::pkey::{PKey, Public}; use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef}; use crate::ssl::bio::BioMethod; use crate::ssl::callbacks::*; Loading Loading @@ -3445,6 +3449,38 @@ impl SslRef { pub fn security_level(&self) -> u32 { unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 } } /// Get the temporary key provided by the peer that is used during key /// exchange. // We use an owned value because EVP_KEY free need to be called when it is // dropped #[corresponds(SSL_get_peer_tmp_key)] #[cfg(ossl300)] pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> { unsafe { let mut key = ptr::null_mut(); match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) { Ok(_) => Ok(PKey::<Public>::from_ptr(key)), Err(e) => Err(e), } } } /// Returns the temporary key from the local end of the connection that is /// used during key exchange. // We use an owned value because EVP_KEY free need to be called when it is // dropped #[corresponds(SSL_get_tmp_key)] #[cfg(ossl300)] pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> { unsafe { let mut key = ptr::null_mut(); match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) { Ok(_) => Ok(PKey::<Private>::from_ptr(key)), Err(e) => Err(e), } } } } /// An SSL stream midway through the handshake process. Loading openssl/src/ssl/test/mod.rs +51 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ use crate::error::ErrorStack; use crate::hash::MessageDigest; #[cfg(not(boringssl))] use crate::ocsp::{OcspResponse, OcspResponseStatus}; use crate::pkey::PKey; use crate::pkey::{Id, PKey}; use crate::srtp::SrtpProfileId; use crate::ssl::test::server::Server; #[cfg(any(ossl110, ossl111, libressl261))] Loading Loading @@ -322,6 +322,56 @@ fn state() { ); } // when a connection uses ECDHE P-384 key exchange, then the temp key APIs // return P-384 keys, and the peer and local keys are different. #[test] #[cfg(ossl300)] fn peer_tmp_key_p384() { let mut server = Server::builder(); server.ctx().set_groups_list("P-384").unwrap(); let server = server.build(); let s = server.client().connect(); let peer_temp = s.ssl().peer_tmp_key().unwrap(); assert_eq!(peer_temp.id(), Id::EC); assert_eq!(peer_temp.bits(), 384); let local_temp = s.ssl().tmp_key().unwrap(); assert_eq!(local_temp.id(), Id::EC); assert_eq!(local_temp.bits(), 384); assert_ne!( peer_temp.ec_key().unwrap().public_key_to_der().unwrap(), local_temp.ec_key().unwrap().public_key_to_der().unwrap(), ); } // when a connection uses RSA key exchange, then the peer (server) temp key is // an Error because there is no temp key, and the local (client) temp key is the // temp key sent in the initial key share. #[test] #[cfg(ossl300)] fn peer_tmp_key_rsa() { let mut server = Server::builder(); server.ctx().set_cipher_list("RSA").unwrap(); // RSA key exchange is not allowed in TLS 1.3, so force the connection // to negotiate TLS 1.2 server .ctx() .set_max_proto_version(Some(SslVersion::TLS1_2)) .unwrap(); let server = server.build(); let mut client = server.client(); client.ctx().set_groups_list("P-521").unwrap(); let s = client.connect(); let peer_temp = s.ssl().peer_tmp_key(); assert!(peer_temp.is_err()); // this is the temp key that the client sent in the initial key share let local_temp = s.ssl().tmp_key().unwrap(); assert_eq!(local_temp.id(), Id::EC); assert_eq!(local_temp.bits(), 521); } /// Tests that when both the client as well as the server use SRTP and their /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. Loading Loading
openssl-sys/src/ssl.rs +15 −0 Original line number Diff line number Diff line Loading @@ -349,6 +349,8 @@ pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94; pub const SSL_CTRL_SET_SIGALGS_LIST: c_int = 98; #[cfg(ossl102)] pub const SSL_CTRL_SET_VERIFY_CERT_STORE: c_int = 106; #[cfg(ossl300)] pub const SSL_CTRL_GET_PEER_TMP_KEY: c_int = 109; #[cfg(ossl110)] pub const SSL_CTRL_GET_EXTMS_SUPPORT: c_int = 122; #[cfg(any(ossl110, libressl261))] Loading @@ -359,6 +361,8 @@ pub const SSL_CTRL_SET_MAX_PROTO_VERSION: c_int = 124; pub const SSL_CTRL_GET_MIN_PROTO_VERSION: c_int = 130; #[cfg(any(ossl110g, libressl270))] pub const SSL_CTRL_GET_MAX_PROTO_VERSION: c_int = 131; #[cfg(ossl300)] pub const SSL_CTRL_GET_TMP_KEY: c_int = 133; pub unsafe fn SSL_CTX_set_tmp_dh(ctx: *mut SSL_CTX, dh: *mut DH) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, dh as *mut c_void) Loading Loading @@ -506,6 +510,17 @@ cfg_if! { } } } cfg_if! { if #[cfg(ossl300)] { pub unsafe fn SSL_get_peer_tmp_key(ssl: *mut SSL, key: *mut *mut EVP_PKEY) -> c_long { SSL_ctrl(ssl, SSL_CTRL_GET_PEER_TMP_KEY, 0, key as *mut c_void) } pub unsafe fn SSL_get_tmp_key(ssl: *mut SSL, key: *mut *mut EVP_PKEY) -> c_long { SSL_ctrl(ssl, SSL_CTRL_GET_TMP_KEY, 0, key as *mut c_void) } } } #[cfg(ossl111)] pub const SSL_CLIENT_HELLO_SUCCESS: c_int = 1; Loading
openssl/src/lib.rs +15 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,8 @@ pub use ffi::init; use libc::c_int; #[cfg(ossl300)] use libc::c_long; use crate::error::ErrorStack; Loading Loading @@ -212,6 +214,19 @@ fn cvt(r: c_int) -> Result<c_int, ErrorStack> { } } // cvt_long is currently only used in functions that require openssl >= 3.0.0, // so this cfg statement is used to avoid "unused function" errors when // compiling with openssl < 3.0.0 #[inline] #[cfg(ossl300)] fn cvt_long(r: c_long) -> Result<c_long, ErrorStack> { if r <= 0 { Err(ErrorStack::get()) } else { Ok(r) } } #[inline] fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> { if r < 0 { Loading
openssl/src/ssl/mod.rs +36 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ //! } //! } //! ``` #[cfg(ossl300)] use crate::cvt_long; use crate::dh::{Dh, DhRef}; #[cfg(all(ossl101, not(ossl110)))] use crate::ec::EcKey; Loading @@ -68,6 +70,8 @@ use crate::hash::MessageDigest; #[cfg(any(ossl110, libressl270))] use crate::nid::Nid; use crate::pkey::{HasPrivate, PKeyRef, Params, Private}; #[cfg(ossl300)] use crate::pkey::{PKey, Public}; use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef}; use crate::ssl::bio::BioMethod; use crate::ssl::callbacks::*; Loading Loading @@ -3445,6 +3449,38 @@ impl SslRef { pub fn security_level(&self) -> u32 { unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 } } /// Get the temporary key provided by the peer that is used during key /// exchange. // We use an owned value because EVP_KEY free need to be called when it is // dropped #[corresponds(SSL_get_peer_tmp_key)] #[cfg(ossl300)] pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> { unsafe { let mut key = ptr::null_mut(); match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) { Ok(_) => Ok(PKey::<Public>::from_ptr(key)), Err(e) => Err(e), } } } /// Returns the temporary key from the local end of the connection that is /// used during key exchange. // We use an owned value because EVP_KEY free need to be called when it is // dropped #[corresponds(SSL_get_tmp_key)] #[cfg(ossl300)] pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> { unsafe { let mut key = ptr::null_mut(); match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) { Ok(_) => Ok(PKey::<Private>::from_ptr(key)), Err(e) => Err(e), } } } } /// An SSL stream midway through the handshake process. Loading
openssl/src/ssl/test/mod.rs +51 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ use crate::error::ErrorStack; use crate::hash::MessageDigest; #[cfg(not(boringssl))] use crate::ocsp::{OcspResponse, OcspResponseStatus}; use crate::pkey::PKey; use crate::pkey::{Id, PKey}; use crate::srtp::SrtpProfileId; use crate::ssl::test::server::Server; #[cfg(any(ossl110, ossl111, libressl261))] Loading Loading @@ -322,6 +322,56 @@ fn state() { ); } // when a connection uses ECDHE P-384 key exchange, then the temp key APIs // return P-384 keys, and the peer and local keys are different. #[test] #[cfg(ossl300)] fn peer_tmp_key_p384() { let mut server = Server::builder(); server.ctx().set_groups_list("P-384").unwrap(); let server = server.build(); let s = server.client().connect(); let peer_temp = s.ssl().peer_tmp_key().unwrap(); assert_eq!(peer_temp.id(), Id::EC); assert_eq!(peer_temp.bits(), 384); let local_temp = s.ssl().tmp_key().unwrap(); assert_eq!(local_temp.id(), Id::EC); assert_eq!(local_temp.bits(), 384); assert_ne!( peer_temp.ec_key().unwrap().public_key_to_der().unwrap(), local_temp.ec_key().unwrap().public_key_to_der().unwrap(), ); } // when a connection uses RSA key exchange, then the peer (server) temp key is // an Error because there is no temp key, and the local (client) temp key is the // temp key sent in the initial key share. #[test] #[cfg(ossl300)] fn peer_tmp_key_rsa() { let mut server = Server::builder(); server.ctx().set_cipher_list("RSA").unwrap(); // RSA key exchange is not allowed in TLS 1.3, so force the connection // to negotiate TLS 1.2 server .ctx() .set_max_proto_version(Some(SslVersion::TLS1_2)) .unwrap(); let server = server.build(); let mut client = server.client(); client.ctx().set_groups_list("P-521").unwrap(); let s = client.connect(); let peer_temp = s.ssl().peer_tmp_key(); assert!(peer_temp.is_err()); // this is the temp key that the client sent in the initial key share let local_temp = s.ssl().tmp_key().unwrap(); assert_eq!(local_temp.id(), Id::EC); assert_eq!(local_temp.bits(), 521); } /// Tests that when both the client as well as the server use SRTP and their /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. Loading