feat: Removal of `rpk` support

This commit is contained in:
0x676e67 2025-02-07 11:50:05 +08:00
parent 5d33987600
commit ed56d2c06a
8 changed files with 5 additions and 412 deletions

View File

@ -61,9 +61,6 @@ fips = []
# Link with precompiled FIPS-validated `bcm.o` module. # Link with precompiled FIPS-validated `bcm.o` module.
fips-link-precompiled = [] fips-link-precompiled = []
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
rpk = []
# Applies a patch (`patches/boring-pq.patch`) to the boringSSL source code that # Applies a patch (`patches/boring-pq.patch`) to the boringSSL source code that
# enables support for PQ key exchange. This feature is necessary in order to # enables support for PQ key exchange. This feature is necessary in order to
# compile the bindings for the default branch of boringSSL (`deps/boringssl`). # compile the bindings for the default branch of boringSSL (`deps/boringssl`).

View File

@ -30,13 +30,6 @@ fips-compat = []
# Link with precompiled FIPS-validated `bcm.o` module. # Link with precompiled FIPS-validated `bcm.o` module.
fips-link-precompiled = ["boring-sys/fips-link-precompiled"] fips-link-precompiled = ["boring-sys/fips-link-precompiled"]
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
# This feature is necessary in order to compile the bindings for the
# default branch of boringSSL. Alternatively, a version of boringSSL that
# implements the same feature set can be provided by setting
# `BORING_BSSL{,_FIPS}_SOURCE_PATH` and `BORING_BSSL{,_FIPS}_ASSUME_PATCHED`.
rpk = ["boring-sys/rpk"]
# Applies a patch to the boringSSL source code that enables support for PQ key # Applies a patch to the boringSSL source code that enables support for PQ key
# exchange. This feature is necessary in order to compile the bindings for the # exchange. This feature is necessary in order to compile the bindings for the
# default branch of boringSSL. Alternatively, a version of boringSSL that # default branch of boringSSL. Alternatively, a version of boringSSL that

View File

@ -63,11 +63,6 @@
//! //!
//! # Optional patches //! # Optional patches
//! //!
//! ## Raw Public Key
//!
//! The crate can be compiled with [RawPublicKey](https://datatracker.ietf.org/doc/html/rfc7250)
//! support by turning on `rpk` compilation feature.
//!
//! ## Experimental post-quantum cryptography //! ## Experimental post-quantum cryptography
//! //!
//! The crate can be compiled with [post-quantum cryptography](https://blog.cloudflare.com/post-quantum-for-all/) //! The crate can be compiled with [post-quantum cryptography](https://blog.cloudflare.com/post-quantum-for-all/)

View File

@ -24,17 +24,13 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
"; ";
enum ContextType { enum ContextType {
WithMethod(SslMethod), WithMethod(SslMethod)
#[cfg(feature = "rpk")]
Rpk,
} }
#[allow(clippy::inconsistent_digit_grouping)] #[allow(clippy::inconsistent_digit_grouping)]
fn ctx(ty: ContextType) -> Result<SslContextBuilder, ErrorStack> { fn ctx(ty: ContextType) -> Result<SslContextBuilder, ErrorStack> {
let mut ctx = match ty { let mut ctx = match ty {
ContextType::WithMethod(method) => SslContextBuilder::new(method), ContextType::WithMethod(method) => SslContextBuilder::new(method)
#[cfg(feature = "rpk")]
ContextType::Rpk => SslContextBuilder::new_rpk(),
}?; }?;
let mut opts = SslOptions::ALL let mut opts = SslOptions::ALL
@ -99,17 +95,6 @@ impl SslConnector {
Ok(SslConnectorBuilder(ctx)) Ok(SslConnectorBuilder(ctx))
} }
/// Creates a new builder for TLS connections with raw public key.
#[cfg(feature = "rpk")]
pub fn rpk_builder() -> Result<SslConnectorBuilder, ErrorStack> {
let mut ctx = ctx(ContextType::Rpk)?;
ctx.set_cipher_list(
"DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK",
)?;
Ok(SslConnectorBuilder(ctx))
}
/// Initiates a client-side TLS session on a stream. /// Initiates a client-side TLS session on a stream.
/// ///
/// The domain is used for SNI and hostname verification. /// The domain is used for SNI and hostname verification.
@ -231,13 +216,7 @@ impl ConnectConfiguration {
self.ssl.set_hostname(domain)?; self.ssl.set_hostname(domain)?;
} }
#[cfg(feature = "rpk")] if self.verify_hostname {
let verify_hostname = !self.ssl.ssl_context().is_rpk() && self.verify_hostname;
#[cfg(not(feature = "rpk"))]
let verify_hostname = self.verify_hostname;
if verify_hostname {
setup_verify_hostname(&mut self.ssl, domain)?; setup_verify_hostname(&mut self.ssl, domain)?;
} }
@ -299,21 +278,6 @@ impl DerefMut for ConnectConfiguration {
pub struct SslAcceptor(SslContext); pub struct SslAcceptor(SslContext);
impl SslAcceptor { impl SslAcceptor {
/// Creates a new builder configured to connect to clients that support Raw Public Keys.
#[cfg(feature = "rpk")]
pub fn rpk() -> Result<SslAcceptorBuilder, ErrorStack> {
let mut ctx = ctx(ContextType::Rpk)?;
ctx.set_options(SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1);
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
ctx.set_tmp_dh(&dh)?;
ctx.set_cipher_list(
"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:\
ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
)?;
Ok(SslAcceptorBuilder(ctx))
}
/// Creates a new builder configured to connect to non-legacy clients. This should generally be /// Creates a new builder configured to connect to non-legacy clients. This should generally be
/// considered a reasonable default choice. /// considered a reasonable default choice.
/// ///

View File

@ -200,12 +200,6 @@ fn fmt_mid_handshake_error(
f: &mut fmt::Formatter, f: &mut fmt::Formatter,
prefix: &str, prefix: &str,
) -> fmt::Result { ) -> fmt::Result {
#[cfg(feature = "rpk")]
if s.ssl().ssl_context().is_rpk() {
write!(f, "{}", prefix)?;
return write!(f, " {}", s.error());
}
match s.ssl().verify_result() { match s.ssl().verify_result() {
// INVALID_CALL is returned if no verification took place, // INVALID_CALL is returned if no verification took place,
// such as before a cert is sent. // such as before a cert is sent.

View File

@ -251,12 +251,6 @@ impl SslMethod {
unsafe { SslMethod(TLS_method()) } unsafe { SslMethod(TLS_method()) }
} }
/// Same as `tls`, but doesn't create X509 for certificates.
#[cfg(feature = "rpk")]
pub fn tls_with_buffer() -> SslMethod {
unsafe { SslMethod(ffi::TLS_with_buffers_method()) }
}
/// Support all versions of the DTLS protocol. /// Support all versions of the DTLS protocol.
#[corresponds(DTLS_method)] #[corresponds(DTLS_method)]
pub fn dtls() -> SslMethod { pub fn dtls() -> SslMethod {
@ -434,9 +428,6 @@ static SSL_INDEXES: LazyLock<Mutex<HashMap<TypeId, c_int>>> =
LazyLock::new(|| Mutex::new(HashMap::new())); LazyLock::new(|| Mutex::new(HashMap::new()));
static SESSION_CTX_INDEX: LazyLock<Index<Ssl, SslContext>> = static SESSION_CTX_INDEX: LazyLock<Index<Ssl, SslContext>> =
LazyLock::new(|| Ssl::new_ex_index().unwrap()); LazyLock::new(|| Ssl::new_ex_index().unwrap());
#[cfg(feature = "rpk")]
static RPK_FLAG_INDEX: LazyLock<Index<SslContext, bool>> =
LazyLock::new(|| SslContext::new_ex_index().unwrap());
unsafe extern "C" fn free_data_box<T>( unsafe extern "C" fn free_data_box<T>(
_parent: *mut c_void, _parent: *mut c_void,
@ -977,61 +968,9 @@ impl Ssl3AlertLevel {
pub const FATAL: Ssl3AlertLevel = Self(ffi::SSL3_AL_FATAL); pub const FATAL: Ssl3AlertLevel = Self(ffi::SSL3_AL_FATAL);
} }
#[cfg(feature = "rpk")]
extern "C" fn rpk_verify_failure_callback(
_ssl: *mut ffi::SSL,
_out_alert: *mut u8,
) -> ffi::ssl_verify_result_t {
// Always verify the peer.
ffi::ssl_verify_result_t::ssl_verify_invalid
}
/// A builder for `SslContext`s. /// A builder for `SslContext`s.
pub struct SslContextBuilder { pub struct SslContextBuilder {
ctx: SslContext, ctx: SslContext
#[cfg(feature = "rpk")]
is_rpk: bool,
}
#[cfg(feature = "rpk")]
impl SslContextBuilder {
/// Creates a new `SslContextBuilder` to be used with Raw Public Key.
#[corresponds(SSL_CTX_new)]
pub fn new_rpk() -> Result<SslContextBuilder, ErrorStack> {
unsafe {
init();
let ctx = cvt_p(ffi::SSL_CTX_new(SslMethod::tls_with_buffer().as_ptr()))?;
Ok(SslContextBuilder::from_ptr(ctx, true))
}
}
/// Sets raw public key certificate in DER format.
pub fn set_rpk_certificate(&mut self, cert: &[u8]) -> Result<(), ErrorStack> {
unsafe {
cvt(ffi::SSL_CTX_set_server_raw_public_key_certificate(
self.as_ptr(),
cert.as_ptr(),
cert.len() as u32,
))
.map(|_| ())
}
}
/// Sets RPK null chain private key.
pub fn set_null_chain_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
where
T: HasPrivate,
{
unsafe {
cvt(ffi::SSL_CTX_set_nullchain_and_key(
self.as_ptr(),
key.as_ptr(),
ptr::null_mut(),
))
.map(|_| ())
}
}
} }
impl SslContextBuilder { impl SslContextBuilder {
@ -1042,39 +981,15 @@ impl SslContextBuilder {
init(); init();
let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?; let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
#[cfg(feature = "rpk")]
{
Ok(SslContextBuilder::from_ptr(ctx, false))
}
#[cfg(not(feature = "rpk"))]
{
Ok(SslContextBuilder::from_ptr(ctx)) Ok(SslContextBuilder::from_ptr(ctx))
} }
} }
}
/// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value. /// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value.
/// ///
/// # Safety /// # Safety
/// ///
/// The caller must ensure that the pointer is valid and uniquely owned by the builder. /// The caller must ensure that the pointer is valid and uniquely owned by the builder.
#[cfg(feature = "rpk")]
pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX, is_rpk: bool) -> SslContextBuilder {
let ctx = SslContext::from_ptr(ctx);
let mut builder = SslContextBuilder { ctx, is_rpk };
builder.set_ex_data(*RPK_FLAG_INDEX, is_rpk);
builder
}
/// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value.
///
/// # Safety
///
/// The caller must ensure that the pointer is valid and uniquely owned by the builder.
#[cfg(not(feature = "rpk"))]
pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder { pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
SslContextBuilder { SslContextBuilder {
ctx: SslContext::from_ptr(ctx), ctx: SslContext::from_ptr(ctx),
@ -1110,9 +1025,6 @@ impl SslContextBuilder {
where where
F: Fn(&mut X509StoreContextRef) -> bool + 'static + Sync + Send, F: Fn(&mut X509StoreContextRef) -> bool + 'static + Sync + Send,
{ {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
// NOTE(jlarisch): Q: Why don't we wrap the callback in an Arc, since // NOTE(jlarisch): Q: Why don't we wrap the callback in an Arc, since
// `set_verify_callback` does? // `set_verify_callback` does?
// A: I don't think that Arc is necessary, and I don't think one is necessary here. // A: I don't think that Arc is necessary, and I don't think one is necessary here.
@ -1132,9 +1044,6 @@ impl SslContextBuilder {
/// Configures the certificate verification method for new connections. /// Configures the certificate verification method for new connections.
#[corresponds(SSL_CTX_set_verify)] #[corresponds(SSL_CTX_set_verify)]
pub fn set_verify(&mut self, mode: SslVerifyMode) { pub fn set_verify(&mut self, mode: SslVerifyMode) {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { unsafe {
ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None); ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
} }
@ -1161,9 +1070,6 @@ impl SslContextBuilder {
where where
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
{ {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { unsafe {
self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback); self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>)); ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
@ -1189,9 +1095,6 @@ impl SslContextBuilder {
where where
F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send, F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
{ {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { unsafe {
self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback); self.replace_ex_data(SslContext::cached_ex_index::<F>(), callback);
ffi::SSL_CTX_set_custom_verify( ffi::SSL_CTX_set_custom_verify(
@ -1239,9 +1142,6 @@ impl SslContextBuilder {
/// If the peer's certificate chain is longer than this value, verification will fail. /// If the peer's certificate chain is longer than this value, verification will fail.
#[corresponds(SSL_CTX_set_verify_depth)] #[corresponds(SSL_CTX_set_verify_depth)]
pub fn set_verify_depth(&mut self, depth: u32) { pub fn set_verify_depth(&mut self, depth: u32) {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { unsafe {
ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int); ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
} }
@ -1250,9 +1150,6 @@ impl SslContextBuilder {
/// Sets a custom certificate store for verifying peer certificates. /// Sets a custom certificate store for verifying peer certificates.
#[corresponds(SSL_CTX_set0_verify_cert_store)] #[corresponds(SSL_CTX_set0_verify_cert_store)]
pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { unsafe {
cvt( cvt(
ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int, ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int,
@ -1265,9 +1162,6 @@ impl SslContextBuilder {
/// Replaces the context's certificate store. /// Replaces the context's certificate store.
#[corresponds(SSL_CTX_set_cert_store)] #[corresponds(SSL_CTX_set_cert_store)]
pub fn set_cert_store(&mut self, cert_store: X509Store) { pub fn set_cert_store(&mut self, cert_store: X509Store) {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { unsafe {
ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr()); ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.into_ptr());
} }
@ -1311,9 +1205,6 @@ impl SslContextBuilder {
/// if present, or defaults specified at OpenSSL build time otherwise. /// if present, or defaults specified at OpenSSL build time otherwise.
#[corresponds(SSL_CTX_set_default_verify_paths)] #[corresponds(SSL_CTX_set_default_verify_paths)]
pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) } unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
} }
@ -1322,9 +1213,6 @@ impl SslContextBuilder {
/// The file should contain a sequence of PEM-formatted CA certificates. /// The file should contain a sequence of PEM-formatted CA certificates.
#[corresponds(SSL_CTX_load_verify_locations)] #[corresponds(SSL_CTX_load_verify_locations)]
pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> { pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
unsafe { unsafe {
cvt(ffi::SSL_CTX_load_verify_locations( cvt(ffi::SSL_CTX_load_verify_locations(
@ -1342,9 +1230,6 @@ impl SslContextBuilder {
/// as trusted by this method. /// as trusted by this method.
#[corresponds(SSL_CTX_set_client_CA_list)] #[corresponds(SSL_CTX_set_client_CA_list)]
pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) { pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { unsafe {
ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr()); ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
mem::forget(list); mem::forget(list);
@ -1355,9 +1240,6 @@ impl SslContextBuilder {
/// requesting client-side TLS authentication. /// requesting client-side TLS authentication.
#[corresponds(SSL_CTX_add_client_CA)] #[corresponds(SSL_CTX_add_client_CA)]
pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> { pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) } unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
} }
@ -1393,9 +1275,6 @@ impl SslContextBuilder {
file: P, file: P,
file_type: SslFiletype, file_type: SslFiletype,
) -> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
unsafe { unsafe {
cvt(ffi::SSL_CTX_use_certificate_file( cvt(ffi::SSL_CTX_use_certificate_file(
@ -1441,9 +1320,6 @@ impl SslContextBuilder {
/// `set_certificate` to a trusted root. /// `set_certificate` to a trusted root.
#[corresponds(SSL_CTX_add_extra_chain_cert)] #[corresponds(SSL_CTX_add_extra_chain_cert)]
pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { unsafe {
cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.into_ptr()) as c_int)?; cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.into_ptr()) as c_int)?;
Ok(()) Ok(())
@ -1705,18 +1581,12 @@ impl SslContextBuilder {
/// Returns a shared reference to the context's certificate store. /// Returns a shared reference to the context's certificate store.
#[corresponds(SSL_CTX_get_cert_store)] #[corresponds(SSL_CTX_get_cert_store)]
pub fn cert_store(&self) -> &X509StoreBuilderRef { pub fn cert_store(&self) -> &X509StoreBuilderRef {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
} }
/// Returns a mutable reference to the context's certificate store. /// Returns a mutable reference to the context's certificate store.
#[corresponds(SSL_CTX_get_cert_store)] #[corresponds(SSL_CTX_get_cert_store)]
pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef { pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk, "This API is not supported for RPK");
unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
} }
@ -2209,9 +2079,6 @@ impl SslContextRef {
/// Returns the certificate associated with this `SslContext`, if present. /// Returns the certificate associated with this `SslContext`, if present.
#[corresponds(SSL_CTX_get0_certificate)] #[corresponds(SSL_CTX_get0_certificate)]
pub fn certificate(&self) -> Option<&X509Ref> { pub fn certificate(&self) -> Option<&X509Ref> {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk(), "This API is not supported for RPK");
unsafe { unsafe {
let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr()); let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
@ -2238,9 +2105,6 @@ impl SslContextRef {
/// Returns a shared reference to the certificate store used for verification. /// Returns a shared reference to the certificate store used for verification.
#[corresponds(SSL_CTX_get_cert_store)] #[corresponds(SSL_CTX_get_cert_store)]
pub fn cert_store(&self) -> &X509StoreRef { pub fn cert_store(&self) -> &X509StoreRef {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk(), "This API is not supported for RPK");
unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
} }
@ -2343,18 +2207,9 @@ impl SslContextRef {
/// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
#[corresponds(SSL_CTX_get_verify_mode)] #[corresponds(SSL_CTX_get_verify_mode)]
pub fn verify_mode(&self) -> SslVerifyMode { pub fn verify_mode(&self) -> SslVerifyMode {
#[cfg(feature = "rpk")]
assert!(!self.is_rpk(), "This API is not supported for RPK");
let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) }; let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode") SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
} }
/// Returns `true` if context was created for Raw Public Key verification
#[cfg(feature = "rpk")]
pub fn is_rpk(&self) -> bool {
self.ex_data(*RPK_FLAG_INDEX).copied().unwrap_or_default()
}
} }
/// Error returned by the callback to get a session when operation /// Error returned by the callback to get a session when operation
@ -2819,21 +2674,6 @@ impl Ssl {
where where
S: Read + Write, S: Read + Write,
{ {
#[cfg(feature = "rpk")]
{
let ctx = self.ssl_context();
if ctx.is_rpk() {
unsafe {
ffi::SSL_CTX_set_custom_verify(
ctx.as_ptr(),
SslVerifyMode::PEER.bits(),
Some(rpk_verify_failure_callback),
);
}
}
}
SslStreamBuilder::new(self, stream).setup_accept() SslStreamBuilder::new(self, stream).setup_accept()
} }
@ -2862,12 +2702,6 @@ impl fmt::Debug for SslRef {
builder.field("state", &self.state_string_long()); builder.field("state", &self.state_string_long());
#[cfg(feature = "rpk")]
if !self.ssl_context().is_rpk() {
builder.field("verify_result", &self.verify_result());
}
#[cfg(not(feature = "rpk"))]
builder.field("verify_result", &self.verify_result()); builder.field("verify_result", &self.verify_result());
builder.finish() builder.finish()
@ -2946,12 +2780,6 @@ impl SslRef {
/// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
#[corresponds(SSL_set_verify)] #[corresponds(SSL_set_verify)]
pub fn set_verify(&mut self, mode: SslVerifyMode) { pub fn set_verify(&mut self, mode: SslVerifyMode) {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) } unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
} }
@ -2960,12 +2788,6 @@ impl SslRef {
/// If the peer's certificate chain is longer than this value, verification will fail. /// If the peer's certificate chain is longer than this value, verification will fail.
#[corresponds(SSL_set_verify_depth)] #[corresponds(SSL_set_verify_depth)]
pub fn set_verify_depth(&mut self, depth: u32) { pub fn set_verify_depth(&mut self, depth: u32) {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { unsafe {
ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int); ffi::SSL_set_verify_depth(self.as_ptr(), depth as c_int);
} }
@ -2974,12 +2796,6 @@ impl SslRef {
/// Returns the verify mode that was set using `set_verify`. /// Returns the verify mode that was set using `set_verify`.
#[corresponds(SSL_get_verify_mode)] #[corresponds(SSL_get_verify_mode)]
pub fn verify_mode(&self) -> SslVerifyMode { pub fn verify_mode(&self) -> SslVerifyMode {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) }; let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode") SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
} }
@ -3005,12 +2821,6 @@ impl SslRef {
where where
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
{ {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { unsafe {
// this needs to be in an Arc since the callback can register a new callback! // this needs to be in an Arc since the callback can register a new callback!
self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
@ -3025,12 +2835,6 @@ impl SslRef {
/// Sets a custom certificate store for verifying peer certificates. /// Sets a custom certificate store for verifying peer certificates.
#[corresponds(SSL_set0_verify_cert_store)] #[corresponds(SSL_set0_verify_cert_store)]
pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { unsafe {
cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int)?; cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.into_ptr()) as c_int)?;
Ok(()) Ok(())
@ -3047,12 +2851,6 @@ impl SslRef {
where where
F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send, F: Fn(&mut SslRef) -> Result<(), SslVerifyError> + 'static + Sync + Send,
{ {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { unsafe {
// this needs to be in an Arc since the callback can register a new callback! // this needs to be in an Arc since the callback can register a new callback!
self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); self.replace_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
@ -3178,12 +2976,6 @@ impl SslRef {
/// Returns the peer's certificate, if present. /// Returns the peer's certificate, if present.
#[corresponds(SSL_get_peer_certificate)] #[corresponds(SSL_get_peer_certificate)]
pub fn peer_certificate(&self) -> Option<X509> { pub fn peer_certificate(&self) -> Option<X509> {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { unsafe {
let ptr = ffi::SSL_get_peer_certificate(self.as_ptr()); let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
@ -3200,12 +2992,6 @@ impl SslRef {
/// not. Fun! /// not. Fun!
#[corresponds(SSL_get_peer_certificate)] #[corresponds(SSL_get_peer_certificate)]
pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> { pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { unsafe {
let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr()); let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
@ -3219,12 +3005,6 @@ impl SslRef {
/// Like [`SslContext::certificate`]. /// Like [`SslContext::certificate`].
#[corresponds(SSL_get_certificate)] #[corresponds(SSL_get_certificate)]
pub fn certificate(&self) -> Option<&X509Ref> { pub fn certificate(&self) -> Option<&X509Ref> {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { unsafe {
let ptr = ffi::SSL_get_certificate(self.as_ptr()); let ptr = ffi::SSL_get_certificate(self.as_ptr());
if ptr.is_null() { if ptr.is_null() {
@ -3465,12 +3245,6 @@ impl SslRef {
/// Returns a mutable reference to the X509 verification configuration. /// Returns a mutable reference to the X509 verification configuration.
#[corresponds(SSL_get0_param)] #[corresponds(SSL_get0_param)]
pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef { pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) } unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
} }
@ -3482,12 +3256,6 @@ impl SslRef {
/// Returns the certificate verification result. /// Returns the certificate verification result.
#[corresponds(SSL_get_verify_result)] #[corresponds(SSL_get_verify_result)]
pub fn verify_result(&self) -> X509VerifyResult { pub fn verify_result(&self) -> X509VerifyResult {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) } unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
} }
@ -3736,12 +3504,6 @@ impl SslRef {
/// as trusted by this method. /// as trusted by this method.
#[corresponds(SSL_set_client_CA_list)] #[corresponds(SSL_set_client_CA_list)]
pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) { pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
#[cfg(feature = "rpk")]
assert!(
!self.ssl_context().is_rpk(),
"This API is not supported for RPK"
);
unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) } unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
mem::forget(list); mem::forget(list);
} }

View File

@ -25,9 +25,6 @@ fips-link-precompiled = ["boring/fips-link-precompiled", "boring-sys/fips-link-p
# Enables experimental post-quantum crypto (https://blog.cloudflare.com/post-quantum-for-all/) # Enables experimental post-quantum crypto (https://blog.cloudflare.com/post-quantum-for-all/)
pq-experimental = ["boring/pq-experimental"] pq-experimental = ["boring/pq-experimental"]
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
rpk = ["boring/rpk"]
[dependencies] [dependencies]
boring = { workspace = true } boring = { workspace = true }
boring-sys = { workspace = true } boring-sys = { workspace = true }

View File

@ -1,109 +0,0 @@
#[cfg(feature = "rpk")]
mod test_rpk {
use boring::pkey::PKey;
use boring::ssl::{SslAcceptor, SslConnector};
use futures::future;
use std::future::Future;
use std::net::SocketAddr;
use std::pin::Pin;
use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::net::{TcpListener, TcpStream};
use tokio_boring::{HandshakeError, SslStream};
fn create_server() -> (
impl Future<Output = Result<SslStream<TcpStream>, HandshakeError<TcpStream>>>,
SocketAddr,
) {
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
listener.set_nonblocking(true).unwrap();
let listener = TcpListener::from_std(listener).unwrap();
let addr = listener.local_addr().unwrap();
let server = async move {
let mut acceptor = SslAcceptor::rpk().unwrap();
let pkey = std::fs::read("tests/key.pem").unwrap();
let pkey = PKey::private_key_from_pem(&pkey).unwrap();
let cert = std::fs::read("tests/pubkey.der").unwrap();
acceptor.set_rpk_certificate(&cert).unwrap();
acceptor.set_null_chain_private_key(&pkey).unwrap();
let acceptor = acceptor.build();
let stream = listener.accept().await.unwrap().0;
tokio_boring::accept(&acceptor, stream).await
};
(server, addr)
}
#[tokio::test]
async fn server_rpk() {
let (stream, addr) = create_server();
let server = async {
let mut stream = stream.await.unwrap();
let mut buf = [0; 4];
stream.read_exact(&mut buf).await.unwrap();
assert_eq!(&buf, b"asdf");
stream.write_all(b"jkl;").await.unwrap();
future::poll_fn(|ctx| Pin::new(&mut stream).poll_shutdown(ctx))
.await
.unwrap();
};
let client = async {
let mut connector = SslConnector::rpk_builder().unwrap();
let cert = std::fs::read("tests/pubkey.der").unwrap();
connector.set_rpk_certificate(&cert).unwrap();
let config = connector.build().configure().unwrap();
let stream = TcpStream::connect(&addr).await.unwrap();
let mut stream = tokio_boring::connect(config, "localhost", stream)
.await
.unwrap();
stream.write_all(b"asdf").await.unwrap();
let mut buf = vec![];
stream.read_to_end(&mut buf).await.unwrap();
assert_eq!(buf, b"jkl;");
};
future::join(server, client).await;
}
#[tokio::test]
async fn client_rpk_unknown_cert() {
let (stream, addr) = create_server();
let server = async {
assert!(stream.await.is_err());
};
let client = async {
let mut connector = SslConnector::rpk_builder().unwrap();
let cert = std::fs::read("tests/pubkey2.der").unwrap();
connector.set_rpk_certificate(&cert).unwrap();
let config = connector.build().configure().unwrap();
let stream = TcpStream::connect(&addr).await.unwrap();
let err = tokio_boring::connect(config, "localhost", stream)
.await
.unwrap_err();
// NOTE: smoke test for https://github.com/cloudflare/boring/issues/140
let _ = err.to_string();
};
future::join(server, client).await;
}
}