Expose a safe Rust interface for the session resumption callback
This commit is contained in:
parent
ac1d71cb54
commit
ab8513ef8f
|
|
@ -0,0 +1,38 @@
|
|||
use crate::cvt;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use std::ffi::c_void;
|
||||
|
||||
use foreign_types::ForeignType;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::HMAC_CTX;
|
||||
fn drop = ffi::HMAC_CTX_free;
|
||||
|
||||
pub struct HmacCtx;
|
||||
}
|
||||
|
||||
impl HmacCtx {
|
||||
/// Configures HmacCtx to use `md` as the hash function and `key` as the key.
|
||||
///
|
||||
/// https://commondatastorage.googleapis.com/chromium-boringssl-docs/hmac.h.html#HMAC_Init_ex
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure HMAC_CTX has been initalized.
|
||||
pub unsafe fn init(&mut self, key: &[u8], md: &MessageDigest) -> Result<(), ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::HMAC_Init_ex(
|
||||
self.as_ptr(),
|
||||
key.as_ptr() as *const c_void,
|
||||
key.len(),
|
||||
md.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
core::ptr::null_mut(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -137,6 +137,7 @@ pub mod error;
|
|||
pub mod ex_data;
|
||||
pub mod fips;
|
||||
pub mod hash;
|
||||
pub mod hmac;
|
||||
pub mod hpke;
|
||||
pub mod memcmp;
|
||||
pub mod nid;
|
||||
|
|
|
|||
|
|
@ -8,13 +8,15 @@ use super::{
|
|||
};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::ffi;
|
||||
use crate::hmac::HmacCtx;
|
||||
use crate::ssl::TicketKeyCallbackResult;
|
||||
use crate::symm::CipherCtx;
|
||||
use crate::x509::{X509StoreContext, X509StoreContextRef};
|
||||
use foreign_types::ForeignType;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::{c_char, c_int, c_uchar, c_uint, c_void};
|
||||
use std::ffi::CStr;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::mem::{ManuallyDrop, MaybeUninit};
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
|
|
@ -288,8 +290,8 @@ where
|
|||
&SslRef,
|
||||
&mut [u8; 16],
|
||||
&mut [u8; ffi::EVP_MAX_IV_LENGTH as usize],
|
||||
*mut ffi::EVP_CIPHER_CTX,
|
||||
*mut ffi::HMAC_CTX,
|
||||
&mut CipherCtx,
|
||||
&mut HmacCtx,
|
||||
bool,
|
||||
) -> TicketKeyCallbackResult
|
||||
+ 'static
|
||||
|
|
@ -325,7 +327,11 @@ where
|
|||
let key_name = unsafe { key_name.assume_init_mut() };
|
||||
let iv = unsafe { iv.assume_init_mut() };
|
||||
|
||||
callback(ssl, key_name, iv, evp_ctx, hmac_ctx, encrypt).into()
|
||||
// The EVP_CIPHER_CTX and HMAC_CTX are owned by boringSSL.
|
||||
let mut evp_ctx = ManuallyDrop::new(unsafe { CipherCtx::from_ptr(evp_ctx) });
|
||||
let mut hmac_ctx = ManuallyDrop::new(unsafe { HmacCtx::from_ptr(hmac_ctx) });
|
||||
|
||||
callback(ssl, key_name, iv, &mut evp_ctx, &mut hmac_ctx, encrypt).into()
|
||||
}
|
||||
|
||||
pub(super) unsafe extern "C" fn raw_alpn_select<F>(
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ use crate::dh::DhRef;
|
|||
use crate::ec::EcKeyRef;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::ex_data::Index;
|
||||
use crate::hmac::HmacCtx;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
|
||||
use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
|
||||
|
|
@ -88,6 +89,7 @@ use crate::ssl::bio::BioMethod;
|
|||
use crate::ssl::callbacks::*;
|
||||
use crate::ssl::error::InnerError;
|
||||
use crate::stack::{Stack, StackRef, Stackable};
|
||||
use crate::symm::CipherCtx;
|
||||
use crate::x509::store::{X509Store, X509StoreBuilder, X509StoreBuilderRef, X509StoreRef};
|
||||
use crate::x509::verify::X509VerifyParamRef;
|
||||
use crate::x509::{
|
||||
|
|
@ -1137,6 +1139,8 @@ impl SslContextBuilder {
|
|||
/// prior to TLS 1.3, retroactively decrypt all application traffic from sessions using that
|
||||
/// ticket key. Thus ticket keys must be regularly rotated for forward secrecy.
|
||||
///
|
||||
/// CipherCtx and HmacCtx are guaranteed to be initialized.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This method panics if this `Ssl` is associated with a RPK context.
|
||||
|
|
@ -1148,14 +1152,14 @@ impl SslContextBuilder {
|
|||
///
|
||||
/// [`SSL_CTX_set_tlsext_ticket_key_cb`]: https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_tlsext_ticket_key_cb
|
||||
#[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
|
||||
pub unsafe fn set_ticket_key_callback_unsafe<F>(&mut self, callback: F)
|
||||
pub unsafe fn set_ticket_key_callback<F>(&mut self, callback: F)
|
||||
where
|
||||
F: Fn(
|
||||
&SslRef,
|
||||
&mut [u8; 16],
|
||||
&mut [u8; ffi::EVP_MAX_IV_LENGTH as usize],
|
||||
*mut ffi::EVP_CIPHER_CTX,
|
||||
*mut ffi::HMAC_CTX,
|
||||
&mut CipherCtx,
|
||||
&mut HmacCtx,
|
||||
bool,
|
||||
) -> TicketKeyCallbackResult
|
||||
+ 'static
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use super::server::Server;
|
||||
use crate::ssl::test::MessageDigest;
|
||||
use crate::ssl::HmacCtx;
|
||||
use crate::ssl::SslRef;
|
||||
use crate::ssl::SslSession;
|
||||
use crate::ssl::SslSessionCacheMode;
|
||||
use crate::ssl::TicketKeyCallbackResult;
|
||||
use crate::symm::Cipher;
|
||||
use std::ffi::c_void;
|
||||
use crate::symm::CipherCtx;
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
|
|
@ -60,7 +61,7 @@ fn custom_callback_success() {
|
|||
unsafe {
|
||||
server
|
||||
.ctx()
|
||||
.set_ticket_key_callback_unsafe(test_success_tickey_key_callback)
|
||||
.set_ticket_key_callback(test_success_tickey_key_callback)
|
||||
};
|
||||
let server = server.build();
|
||||
|
||||
|
|
@ -105,7 +106,7 @@ fn custom_callback_unrecognized_decryption_ticket() {
|
|||
unsafe {
|
||||
server
|
||||
.ctx()
|
||||
.set_ticket_key_callback_unsafe(test_noop_tickey_key_callback)
|
||||
.set_ticket_key_callback(test_noop_tickey_key_callback)
|
||||
};
|
||||
let server = server.build();
|
||||
|
||||
|
|
@ -147,8 +148,8 @@ fn test_noop_tickey_key_callback(
|
|||
_ssl: &SslRef,
|
||||
key_name: &mut [u8; 16],
|
||||
iv: &mut [u8; ffi::EVP_MAX_IV_LENGTH as usize],
|
||||
evp_ctx: *mut ffi::EVP_CIPHER_CTX,
|
||||
hmac_ctx: *mut ffi::HMAC_CTX,
|
||||
evp_ctx: &mut CipherCtx,
|
||||
hmac_ctx: &mut HmacCtx,
|
||||
encrypt: bool,
|
||||
) -> TicketKeyCallbackResult {
|
||||
// These should only be used for testing purposes.
|
||||
|
|
@ -164,31 +165,16 @@ fn test_noop_tickey_key_callback(
|
|||
assert_eq!(iv, &[0; 16]);
|
||||
|
||||
NOOP_ENCRYPTION_CALLED_BACK.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
// Set the encryption context.
|
||||
let ret = unsafe {
|
||||
ffi::EVP_EncryptInit_ex(
|
||||
evp_ctx,
|
||||
cipher.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
core::ptr::null_mut(),
|
||||
TEST_AES_128_CBC_KEY.as_ptr(),
|
||||
TEST_CBC_IV.as_ptr(),
|
||||
)
|
||||
unsafe {
|
||||
evp_ctx
|
||||
.init_encrypt(&cipher, &TEST_AES_128_CBC_KEY, &TEST_CBC_IV)
|
||||
.unwrap()
|
||||
};
|
||||
assert!(ret == 1);
|
||||
|
||||
// Set the hmac context.
|
||||
let ret = unsafe {
|
||||
ffi::HMAC_Init_ex(
|
||||
hmac_ctx,
|
||||
TEST_HMAC_KEY.as_ptr() as *const c_void,
|
||||
TEST_HMAC_KEY.len(),
|
||||
digest.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
core::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
assert!(ret == 1);
|
||||
unsafe { hmac_ctx.init(&TEST_HMAC_KEY, &digest).unwrap() };
|
||||
|
||||
TicketKeyCallbackResult::Success
|
||||
} else {
|
||||
|
|
@ -202,8 +188,8 @@ fn test_success_tickey_key_callback(
|
|||
_ssl: &SslRef,
|
||||
key_name: &mut [u8; 16],
|
||||
iv: &mut [u8; ffi::EVP_MAX_IV_LENGTH as usize],
|
||||
evp_ctx: *mut ffi::EVP_CIPHER_CTX,
|
||||
hmac_ctx: *mut ffi::HMAC_CTX,
|
||||
evp_ctx: &mut CipherCtx,
|
||||
hmac_ctx: &mut HmacCtx,
|
||||
encrypt: bool,
|
||||
) -> TicketKeyCallbackResult {
|
||||
// These should only be used for testing purposes.
|
||||
|
|
@ -219,58 +205,27 @@ fn test_success_tickey_key_callback(
|
|||
assert_eq!(iv, &[0; 16]);
|
||||
|
||||
SUCCESS_ENCRYPTION_CALLED_BACK.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
// Set the encryption context.
|
||||
let ret = unsafe {
|
||||
ffi::EVP_EncryptInit_ex(
|
||||
evp_ctx,
|
||||
cipher.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
core::ptr::null_mut(),
|
||||
TEST_AES_128_CBC_KEY.as_ptr(),
|
||||
TEST_CBC_IV.as_ptr(),
|
||||
)
|
||||
unsafe {
|
||||
evp_ctx
|
||||
.init_encrypt(&cipher, &TEST_AES_128_CBC_KEY, &TEST_CBC_IV)
|
||||
.unwrap()
|
||||
};
|
||||
assert!(ret == 1);
|
||||
|
||||
// Set the hmac context.
|
||||
let ret = unsafe {
|
||||
ffi::HMAC_Init_ex(
|
||||
hmac_ctx,
|
||||
TEST_HMAC_KEY.as_ptr() as *const c_void,
|
||||
TEST_HMAC_KEY.len(),
|
||||
digest.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
core::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
assert!(ret == 1);
|
||||
unsafe { hmac_ctx.init(&TEST_HMAC_KEY, &digest).unwrap() };
|
||||
} else {
|
||||
SUCCESS_DECRYPTION_CALLED_BACK.fetch_add(1, Ordering::SeqCst);
|
||||
// Set the decryption context.
|
||||
let ret = unsafe {
|
||||
ffi::EVP_DecryptInit_ex(
|
||||
evp_ctx,
|
||||
cipher.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
core::ptr::null_mut(),
|
||||
TEST_AES_128_CBC_KEY.as_ptr(),
|
||||
TEST_CBC_IV.as_ptr(),
|
||||
)
|
||||
unsafe {
|
||||
evp_ctx
|
||||
.init_decrypt(&cipher, &TEST_AES_128_CBC_KEY, &TEST_CBC_IV)
|
||||
.unwrap()
|
||||
};
|
||||
assert!(ret == 1);
|
||||
|
||||
// Set the hmac context.
|
||||
let ret = unsafe {
|
||||
ffi::HMAC_Init_ex(
|
||||
hmac_ctx,
|
||||
TEST_HMAC_KEY.as_ptr() as *const c_void,
|
||||
TEST_HMAC_KEY.len(),
|
||||
digest.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
core::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
assert!(ret == 1);
|
||||
unsafe { hmac_ctx.init(&TEST_HMAC_KEY, &digest).unwrap() };
|
||||
}
|
||||
|
||||
TicketKeyCallbackResult::Success
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
//! ```
|
||||
|
||||
use crate::ffi;
|
||||
use foreign_types::ForeignType;
|
||||
use libc::{c_int, c_uint};
|
||||
use openssl_macros::corresponds;
|
||||
use std::cmp;
|
||||
|
|
@ -68,6 +69,77 @@ pub enum Mode {
|
|||
Decrypt,
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::EVP_CIPHER_CTX;
|
||||
fn drop = ffi::EVP_CIPHER_CTX_free;
|
||||
|
||||
pub struct CipherCtx;
|
||||
}
|
||||
|
||||
impl CipherCtx {
|
||||
/// Configures CipherCtx for a fresh encryption operation using `cipher`.
|
||||
///
|
||||
/// https://commondatastorage.googleapis.com/chromium-boringssl-docs/cipher.h.html#EVP_EncryptInit_ex
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure EVP_CIPHER_CTX has been initalized.
|
||||
///
|
||||
/// The caller is responsible for ensuring the length of `key` and `iv` are appropriate for the
|
||||
/// chosen Cipher.
|
||||
pub unsafe fn init_encrypt(
|
||||
&mut self,
|
||||
cipher: &Cipher,
|
||||
key: &[u8],
|
||||
iv: &[u8; ffi::EVP_MAX_IV_LENGTH as usize],
|
||||
) -> Result<(), ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_EncryptInit_ex(
|
||||
self.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
ptr::null_mut(),
|
||||
key.as_ptr(),
|
||||
iv.as_ptr(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Configures CipherCtx for a fresh decryption operation using `cipher`.
|
||||
///
|
||||
/// https://commondatastorage.googleapis.com/chromium-boringssl-docs/cipher.h.html#EVP_DecryptInit_ex
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure EVP_CIPHER_CTX has been initalized.
|
||||
///
|
||||
/// The caller is responsible for ensuring the length of `key` and `iv` are appropriate for the
|
||||
/// chosen Cipher.
|
||||
pub unsafe fn init_decrypt(
|
||||
&mut self,
|
||||
cipher: &Cipher,
|
||||
key: &[u8],
|
||||
iv: &[u8; ffi::EVP_MAX_IV_LENGTH as usize],
|
||||
) -> Result<(), ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DecryptInit_ex(
|
||||
self.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
// ENGINE api is deprecated
|
||||
ptr::null_mut(),
|
||||
key.as_ptr(),
|
||||
iv.as_ptr(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a particular cipher algorithm.
|
||||
///
|
||||
/// See OpenSSL doc at [`EVP_EncryptInit`] for more information on each algorithms.
|
||||
|
|
|
|||
Loading…
Reference in New Issue