diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7f03cb5c..1c104a3dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,7 @@ jobs: path: target key: clippy-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - name: Run clippy - run: cargo clippy --all --all-targets + run: cargo clippy --all --all-targets --features rpk,mlkem - name: Check docs run: cargo doc --no-deps -p boring -p boring-sys -p hyper-boring -p tokio-boring --features rpk,underscore-wildcards env: @@ -415,9 +415,15 @@ jobs: - name: Install Rust (rustup) run: rustup update stable --no-self-update && rustup default stable shell: bash + - run: cargo check --no-default-features + name: Check `--no-default-features` + - run: cargo check --features mlkem,credential + name: Check `mlkem,credential` - run: cargo test --features rpk name: Run `rpk` tests - run: cargo test --features underscore-wildcards name: Run `underscore-wildcards` tests - run: cargo test --features rpk,underscore-wildcards name: Run `rpk,underscore-wildcards` tests + - run: cargo test --features rpk,underscore-wildcards,mlkem + name: Run `rpk,underscore-wildcards` tests diff --git a/Cargo.toml b/Cargo.toml index 80b803228..784bd44a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,9 +20,9 @@ tag-prefix = "" publish = false [workspace.dependencies] -boring-sys = { version = "5.0.0", path = "./boring-sys" } -boring = { version = "5.0.0", path = "./boring" } -tokio-boring = { version = "5.0.0", path = "./tokio-boring" } +boring-sys = { version = "5.0.0", path = "./boring-sys", default-features = false } +boring = { version = "5.0.0", path = "./boring", default-features = false } +tokio-boring = { version = "5.0.0", path = "./tokio-boring", default-features = false } bindgen = { version = "0.72.0", default-features = false, features = ["runtime"] } bitflags = "2.9" diff --git a/boring-sys/Cargo.toml b/boring-sys/Cargo.toml index 72845c85e..675a02f34 100644 --- a/boring-sys/Cargo.toml +++ b/boring-sys/Cargo.toml @@ -43,7 +43,7 @@ include = [ ] [package.metadata.docs.rs] -features = ["rpk", "underscore-wildcards"] +features = ["rpk", "underscore-wildcards", "mlkem"] rustdoc-args = ["--cfg", "docsrs"] [features] @@ -58,6 +58,9 @@ fips = [] # Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250) rpk = [] +# Require mlkem.h +mlkem = [] + # Applies a patch (`patches/underscore-wildcards.patch`) to enable # `ffi::X509_CHECK_FLAG_UNDERSCORE_WILDCARDS`. This feature is necessary in # order to compile the bindings for the default branch of boringSSL diff --git a/boring-sys/build/main.rs b/boring-sys/build/main.rs index abb733bed..0fe124157 100644 --- a/boring-sys/build/main.rs +++ b/boring-sys/build/main.rs @@ -704,7 +704,7 @@ fn generate_bindings(config: &Config) { } } - let headers = [ + let must_have_headers = [ "aes.h", "asn1_mac.h", "asn1t.h", @@ -720,6 +720,12 @@ fn generate_bindings(config: &Config) { "err.h", "hkdf.h", "hpke.h", + "ossl_typ.h", + "pkcs12.h", + "poly1305.h", + "x509v3.h", + ]; + let headers = [ "hmac.h", "hrss.h", "md4.h", @@ -728,26 +734,25 @@ fn generate_bindings(config: &Config) { "obj_mac.h", "objects.h", "opensslv.h", - "ossl_typ.h", - "pkcs12.h", - "poly1305.h", "rand.h", "rc4.h", "ripemd.h", "siphash.h", "srtp.h", "trust_token.h", - "x509v3.h", ]; - for header in &headers { + for (i, header) in must_have_headers.into_iter().chain(headers).enumerate() { let header_path = include_path.join("openssl").join(header); - assert!( - header_path.exists(), - "{} is missing. Is {} correct? run `cargo clean`", - header_path.display(), - include_path.display() - ); - builder = builder.header(header_path.to_str().unwrap()); + if header_path.exists() { + builder = builder.header(header_path.to_str().unwrap()); + } else { + let err = format!("'openssl/{header}' is missing from '{}'. The include path may be incorrect or contain an outdated version of OpenSSL/BoringSSL", include_path.display()); + let required = i < must_have_headers.len(); + println!( + "cargo::{}={err}", + if required { "error" } else { "warning" } + ); + } } let bindings = builder.generate().expect("Unable to generate bindings"); diff --git a/boring-sys/src/lib.rs b/boring-sys/src/lib.rs index 57ceffc76..e29b51257 100644 --- a/boring-sys/src/lib.rs +++ b/boring-sys/src/lib.rs @@ -30,6 +30,8 @@ pub use generated::{ssl_compliance_policy_t, ERR_add_error_data, SSL_set1_groups pub use generated::{BIO_new, OPENSSL_free, SSL_ERROR_NONE}; // if these are missing, your include path is incorrect #[cfg(feature = "fips")] pub use generated::{FIPS_mode, SSL_CTX_set_compliance_policy}; // your include path is incorrect or has a version of boringssl without FIPS support +#[cfg(feature = "mlkem")] +pub use generated::{MLKEM768_encap, MLKEM768_private_key_from_seed}; // your include path is incorrect or has a version of boringssl without mlkem support #[cfg(feature = "rpk")] pub use generated::{SSL_CREDENTIAL_new_raw_public_key, SSL_CREDENTIAL_set1_spki}; // your include path is incorrect or has a version of boringssl without rpk support diff --git a/boring/Cargo.toml b/boring/Cargo.toml index b9605ff13..71fe3230f 100644 --- a/boring/Cargo.toml +++ b/boring/Cargo.toml @@ -17,7 +17,7 @@ features = ["rpk", "underscore-wildcards"] rustdoc-args = ["--cfg", "docsrs"] [features] -# Controlling the build +default = [] # Use a FIPS-validated version of BoringSSL. fips = ["boring-sys/fips"] @@ -29,12 +29,18 @@ legacy-compat-deprecated = [] # PQ is always enabled. This feature is a no-op, only for backwards compatibility. pq-experimental = [] +# Interface for ML-KEM (FIPS 203) post-quantum key encapsulation. Does not affect ciphers used in TLS. +mlkem = [] + +# SslCredential API +credential = [] + # 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"] +rpk = ["credential", "boring-sys/rpk"] # Applies a patch to enable `ffi::X509_CHECK_FLAG_UNDERSCORE_WILDCARDS`. This # feature is necessary in order to compile the bindings for the default branch diff --git a/boring/src/lib.rs b/boring/src/lib.rs index d1d87e595..98c4f34e2 100644 --- a/boring/src/lib.rs +++ b/boring/src/lib.rs @@ -137,6 +137,7 @@ pub mod hash; pub mod hmac; pub mod hpke; pub mod memcmp; +#[cfg(feature = "mlkem")] pub mod mlkem; pub mod nid; pub mod pkcs12; diff --git a/boring/src/ssl/async_callbacks.rs b/boring/src/ssl/async_callbacks.rs index ad9683a08..23464030d 100644 --- a/boring/src/ssl/async_callbacks.rs +++ b/boring/src/ssl/async_callbacks.rs @@ -4,8 +4,10 @@ use super::{ Ssl, SslAlert, SslContextBuilder, SslRef, SslSession, SslSignatureAlgorithm, SslVerifyError, SslVerifyMode, }; +#[cfg(feature = "credential")] use crate::error::ErrorStack; use crate::ex_data::Index; +#[cfg(feature = "credential")] use crate::ssl::SslCredentialBuilder; use std::convert::identity; use std::future::Future; @@ -173,6 +175,7 @@ impl SslContextBuilder { } } +#[cfg(feature = "credential")] impl SslCredentialBuilder { /// Configures a custom private key method on the context. /// diff --git a/boring/src/ssl/mod.rs b/boring/src/ssl/mod.rs index 802e09390..b330ce976 100644 --- a/boring/src/ssl/mod.rs +++ b/boring/src/ssl/mod.rs @@ -109,6 +109,7 @@ pub use self::async_callbacks::{ pub use self::connector::{ ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder, }; +#[cfg(feature = "credential")] pub use self::credential::{SslCredential, SslCredentialBuilder, SslCredentialRef}; pub use self::ech::{SslEchKeys, SslEchKeysRef}; pub use self::error::{Error, ErrorCode, HandshakeError}; @@ -117,6 +118,7 @@ mod async_callbacks; mod bio; mod callbacks; mod connector; +#[cfg(feature = "credential")] mod credential; mod ech; mod error; @@ -2029,6 +2031,7 @@ impl SslContextBuilder { /// Adds a credential. #[corresponds(SSL_CTX_add1_credential)] + #[cfg(feature = "credential")] pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> { unsafe { cvt_0i(ffi::SSL_CTX_add1_credential( @@ -3816,6 +3819,7 @@ impl SslRef { /// Adds a credential. #[corresponds(SSL_add1_credential)] + #[cfg(feature = "credential")] pub fn add_credential(&mut self, credential: &SslCredentialRef) -> Result<(), ErrorStack> { unsafe { cvt_0i(ffi::SSL_add1_credential(self.as_ptr(), credential.as_ptr())).map(|_| ()) } } diff --git a/boring/src/ssl/test/mod.rs b/boring/src/ssl/test/mod.rs index 9317a7bae..3cdc5ed27 100644 --- a/boring/src/ssl/test/mod.rs +++ b/boring/src/ssl/test/mod.rs @@ -317,13 +317,13 @@ fn test_mutable_store() { let cert2 = X509::from_pem(cert2).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); - ctx.cert_store_mut().add_cert(&cert.clone()).unwrap(); + ctx.cert_store_mut().add_cert(cert.clone()).unwrap(); assert_eq!(1, ctx.cert_store().objects_len()); ctx.set_cert_store_builder(X509StoreBuilder::new().unwrap()); assert_eq!(0, ctx.cert_store().objects_len()); - ctx.cert_store_mut().add_cert(&cert.clone()).unwrap(); + ctx.cert_store_mut().add_cert(cert.clone()).unwrap(); assert_eq!(1, ctx.cert_store().objects_len()); let mut new_store = X509StoreBuilder::new().unwrap(); diff --git a/boring/src/x509/store.rs b/boring/src/x509/store.rs index 7b9a2317b..95aedda4d 100644 --- a/boring/src/x509/store.rs +++ b/boring/src/x509/store.rs @@ -80,7 +80,8 @@ impl X509StoreBuilder { impl X509StoreBuilderRef { /// Adds a certificate to the certificate store. #[corresponds(X509_STORE_add_cert)] - pub fn add_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { + pub fn add_cert(&mut self, cert: impl AsRef) -> Result<(), ErrorStack> { + let cert = cert.as_ref(); unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())) } } diff --git a/hyper-boring/Cargo.toml b/hyper-boring/Cargo.toml index 9963e6ee6..e8c833fd4 100644 --- a/hyper-boring/Cargo.toml +++ b/hyper-boring/Cargo.toml @@ -16,6 +16,8 @@ features = [] rustdoc-args = ["--cfg", "docsrs"] [features] +default = ["boring/default", "tokio-boring/default"] + # Use a FIPS-validated version of boringssl. fips = ["boring/fips", "tokio-boring/fips"] @@ -25,9 +27,9 @@ http = { workspace = true } hyper = { workspace = true } hyper-util = { workspace = true, features = ["client", "client-legacy"] } linked_hash_set = { workspace = true } -boring = { workspace = true } +boring = { workspace = true, default-features = false } tokio = { workspace = true } -tokio-boring = { workspace = true } +tokio-boring = { workspace = true, default-features = false } tower-layer = { workspace = true } tower-service = { workspace = true } diff --git a/tokio-boring/Cargo.toml b/tokio-boring/Cargo.toml index 18d2f2b20..1830cc175 100644 --- a/tokio-boring/Cargo.toml +++ b/tokio-boring/Cargo.toml @@ -17,6 +17,8 @@ features = ["rpk"] rustdoc-args = ["--cfg", "docsrs"] [features] +default = ["boring/default"] + # Use a FIPS-validated version of boringssl. fips = ["boring/fips", "boring-sys/fips"] @@ -24,8 +26,8 @@ fips = ["boring/fips", "boring-sys/fips"] rpk = ["boring/rpk"] [dependencies] -boring = { workspace = true } -boring-sys = { workspace = true } +boring = { workspace = true, default-features = false } +boring-sys = { workspace = true, default-features = false } tokio = { workspace = true } [dev-dependencies]