Compare commits

..

3 Commits

Author SHA1 Message Date
Jordan Rose
7d000369f3 boring-sys: Support static MSVC runtime 2026-02-12 10:51:36 -08:00
Jordan Rose
43c8c279f3 Revert "Support TARGET_CC and CC_{target}"
This reverts commit a50a39fde7,
which interferes with CMake's own support for these variables,
at least how Signal has been using them.
2026-02-11 11:38:49 -08:00
Jordan Rose
ed051f3b63 Merge tag 'v5.0.0' 2026-02-10 18:03:19 -08:00
21 changed files with 140 additions and 198 deletions

View File

@ -4,6 +4,7 @@ on:
pull_request:
branches:
- main
- v4.x
push:
branches:
- main
@ -57,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 --features rpk,mlkem
run: cargo clippy --all --all-targets
- name: Check docs
run: cargo doc --no-deps -p boring -p boring-sys -p hyper-boring -p tokio-boring --features rpk,underscore-wildcards
env:
@ -225,15 +226,6 @@ jobs:
RUSTC_BOOTSTRAP: 1 # for -Z checksum-freshness
# CI's Windows doesn't have required root certs
extra_test_args: --workspace --exclude tokio-boring --exclude hyper-boring -Z checksum-freshness
- thing: x86_64-msvc-static
target: x86_64-pc-windows-msvc
rust: stable-x86_64-msvc
os: windows-latest
custom_env:
RUSTC_BOOTSTRAP: 1 # for -Z checksum-freshness
RUSTFLAGS: -Dwarnings -C target-feature=+crt-static
# CI's Windows doesn't have required root certs
extra_test_args: --workspace --exclude tokio-boring --exclude hyper-boring -Z checksum-freshness
env:
CARGO_HOME: ${{ github.workspace }}/.cache/cargo
CARGO_BUILD_BUILD_DIR: ${{ github.workspace }}/.cache/build-dir
@ -423,15 +415,9 @@ 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

View File

@ -8,7 +8,7 @@ members = [
resolver = "2"
[workspace.package]
version = "5.0.2"
version = "5.0.0"
rust-version = "1.85"
repository = "https://github.com/cloudflare/boring"
edition = "2021"
@ -20,9 +20,9 @@ tag-prefix = ""
publish = false
[workspace.dependencies]
boring-sys = { version = "5.0.2", path = "./boring-sys", default-features = false }
boring = { version = "5.0.2", path = "./boring", default-features = false }
tokio-boring = { version = "5.0.2", path = "./tokio-boring", default-features = false }
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" }
bindgen = { version = "0.72.0", default-features = false, features = ["runtime"] }
bitflags = "2.9"

View File

@ -7,10 +7,6 @@
This crate provides safe bindings for the Rust programming language and TLS adapters for [tokio](https://github.com/tokio-rs/tokio)
and [hyper](https://github.com/hyperium/hyper) built on top of it.
It supports [FIPS-compatible builds of BoringSSL](https://boringssl.googlesource.com/boringssl/+/master/crypto/fipsmodule/FIPS.md),
as well as [Post-Quantum crypto](https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/)
and [Raw Public Key](https://docs.rs/boring/latest/boring/ssl/struct.SslRef.html#method.peer_pubkey) extensions.
## Documentation
- Boring API: <https://docs.rs/boring>
- tokio TLS adapters: <https://docs.rs/tokio-boring>

View File

@ -43,7 +43,7 @@ include = [
]
[package.metadata.docs.rs]
features = ["rpk", "underscore-wildcards", "mlkem"]
features = ["rpk", "underscore-wildcards"]
rustdoc-args = ["--cfg", "docsrs"]
[features]
@ -58,9 +58,6 @@ 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

View File

@ -3,9 +3,7 @@
[BoringSSL](https://boringssl.googlesource.com/boringssl) is Google's fork of OpenSSL for Chrome/Chromium and Android.
This crate builds the BoringSSL library (or optionally links a pre-built version) and generates FFI bindings for it.
It supports [FIPS-compatible builds of BoringSSL](https://boringssl.googlesource.com/boringssl/+/master/crypto/fipsmodule/FIPS.md),
as well as [Post-Quantum crypto](https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/)
and [Raw Public Key](https://docs.rs/boring/latest/boring/ssl/struct.SslRef.html#method.peer_pubkey) extensions.
It supports FIPS-compatible builds of BoringSSL, as well as Post-Quantum crypto and Raw Public Key features.
To use BoringSSL from Rust, prefer the [higher-level safe API](https://docs.rs/boring).

View File

@ -50,7 +50,7 @@ impl Config {
let unix = env::var("CARGO_CFG_UNIX").is_ok();
let target_features = env::var("CARGO_CFG_TARGET_FEATURE")
.unwrap_or_default()
.unwrap()
.split(',')
.map(|s| s.to_owned())
.collect();

View File

@ -161,7 +161,7 @@ fn get_boringssl_source_path(config: &Config) -> &Path {
/// MSVC generator on Windows place static libs in a target sub-folder,
/// so adjust library location based on platform and build target.
/// See issue: <https://github.com/alexcrichton/cmake-rs/issues/18>
fn msvc_lib_subdir(config: &Config) -> Option<&'static str> {
fn get_boringssl_platform_output_path(config: &Config) -> String {
if config.target.ends_with("-msvc") {
// Code under this branch should match the logic in cmake-rs
let debug_env_var = config
@ -195,9 +195,9 @@ fn msvc_lib_subdir(config: &Config) -> Option<&'static str> {
_ => panic!("Unknown OPT_LEVEL={opt_env_var:?} env var."),
};
Some(subdir)
subdir.to_string()
} else {
None
String::new()
}
}
@ -527,7 +527,7 @@ fn run_command(command: &mut Command) -> io::Result<Output> {
Ok(out)
}
fn build_boringssl_or_get_prebuilt(config: &Config) -> &Path {
fn built_boring_source_path(config: &Config) -> &PathBuf {
static BUILD_SOURCE_PATH: OnceLock<PathBuf> = OnceLock::new();
BUILD_SOURCE_PATH.get_or_init(|| {
@ -557,13 +557,7 @@ fn build_boringssl_or_get_prebuilt(config: &Config) -> &Path {
}
cfg.build_target("ssl").build();
let path = cfg.build_target("crypto").build();
let build_dir = path.join("build");
if build_dir.exists() {
build_dir
} else {
path
}
cfg.build_target("crypto").build()
})
}
@ -590,23 +584,36 @@ fn main() {
}
fn emit_link_directives(config: &Config) {
let bssl_dir = build_boringssl_or_get_prebuilt(config);
let msvc_lib_subdir = msvc_lib_subdir(config);
let bssl_dir = built_boring_source_path(config);
let build_path = get_boringssl_platform_output_path(config);
let subdirs =
if config.is_bazel || (config.features.is_fips_like() && config.env.path.is_some()) {
&["lib"][..]
} else {
&["lib", "crypto", "ssl", ""][..]
};
for subdir in subdirs {
let dir = bssl_dir.join(subdir);
let dir = msvc_lib_subdir
.map(|s| dir.join(s))
.filter(|d| d.exists())
.unwrap_or(dir);
println!("cargo:rustc-link-search=native={}", dir.display());
if config.is_bazel || (config.features.is_fips_like() && config.env.path.is_some()) {
println!(
"cargo:rustc-link-search=native={}/lib/{}",
bssl_dir.display(),
build_path
);
} else {
// todo(rmehra): clean this up, I think these are pretty redundant
println!(
"cargo:rustc-link-search=native={}/build/crypto/{}",
bssl_dir.display(),
build_path
);
println!(
"cargo:rustc-link-search=native={}/build/ssl/{}",
bssl_dir.display(),
build_path
);
println!(
"cargo:rustc-link-search=native={}/build/{}",
bssl_dir.display(),
build_path
);
println!(
"cargo:rustc-link-search=native={}/build",
bssl_dir.display(),
);
}
if let Some(cpp_lib) = get_cpp_runtime_lib(config) {
@ -692,7 +699,7 @@ fn generate_bindings(config: &Config) {
}
}
let must_have_headers = [
let headers = [
"aes.h",
"asn1_mac.h",
"asn1t.h",
@ -708,12 +715,6 @@ 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",
@ -722,25 +723,26 @@ 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 (i, header) in must_have_headers.into_iter().chain(headers).enumerate() {
for header in &headers {
let header_path = include_path.join("openssl").join(header);
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" }
);
}
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());
}
let bindings = builder.generate().expect("Unable to generate bindings");

View File

@ -30,8 +30,6 @@ 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

View File

@ -17,7 +17,7 @@ features = ["rpk", "underscore-wildcards"]
rustdoc-args = ["--cfg", "docsrs"]
[features]
default = []
# Controlling the build
# Use a FIPS-validated version of BoringSSL.
fips = ["boring-sys/fips"]
@ -29,18 +29,12 @@ 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 = ["credential", "boring-sys/rpk"]
rpk = ["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
@ -49,10 +43,6 @@ rpk = ["credential", "boring-sys/rpk"]
# `BORING_BSSL{,_FIPS}_ASSUME_PATCHED`.
underscore-wildcards = ["boring-sys/underscore-wildcards"]
# **DO NOT USE** This will be removed without warning in future releases.
# Alias for 'fips', only for backwards compatibility.
fips-precompiled = ["fips"]
[dependencies]
bitflags = { workspace = true }
foreign-types = { workspace = true }

View File

@ -137,7 +137,6 @@ pub mod hash;
pub mod hmac;
pub mod hpke;
pub mod memcmp;
#[cfg(feature = "mlkem")]
pub mod mlkem;
pub mod nid;
pub mod pkcs12;

View File

@ -91,14 +91,14 @@ impl MlKemPrivateKey {
pub fn generate(algorithm: Algorithm) -> Result<(MlKemPublicKey, MlKemPrivateKey), ErrorStack> {
match algorithm {
Algorithm::MlKem768 => {
let (pk, sk) = MlKem768PrivateKey::generate()?;
let (pk, sk) = MlKem768PrivateKey::generate();
Ok((
MlKemPublicKey(Either::MlKem768(pk)),
MlKemPrivateKey(Either::MlKem768(sk)),
))
}
Algorithm::MlKem1024 => {
let (pk, sk) = MlKem1024PrivateKey::generate()?;
let (pk, sk) = MlKem1024PrivateKey::generate();
Ok((
MlKemPublicKey(Either::MlKem1024(pk)),
MlKemPrivateKey(Either::MlKem1024(sk)),
@ -222,27 +222,39 @@ impl MlKem768PrivateKey {
pub const CIPHERTEXT_BYTES: usize = ffi::MLKEM768_CIPHERTEXT_BYTES as usize;
/// Generate a new key pair.
fn generate() -> Result<(Box<MlKem768PublicKey>, Box<MlKem768PrivateKey>), ErrorStack> {
#[must_use]
fn generate() -> (Box<MlKem768PublicKey>, Box<MlKem768PrivateKey>) {
// SAFETY: all buffers are out parameters, correctly sized
unsafe {
ffi::init();
let mut bytes = [0; MlKem768PublicKey::PUBLIC_KEY_BYTES];
let mut seed = [0; PRIVATE_KEY_SEED_BYTES];
let mut public_key_bytes: MaybeUninit<[u8; MlKem768PublicKey::PUBLIC_KEY_BYTES]> =
MaybeUninit::uninit();
let mut seed: MaybeUninit<MlKemPrivateKeySeed> = MaybeUninit::uninit();
let mut expanded: MaybeUninit<ffi::MLKEM768_private_key> = MaybeUninit::uninit();
ffi::MLKEM768_generate_key(
bytes.as_mut_ptr().cast(),
seed.as_mut_ptr(),
public_key_bytes.as_mut_ptr().cast(),
seed.as_mut_ptr().cast(),
expanded.as_mut_ptr(),
);
Ok((
Box::new(MlKem768PublicKey::from_slice(&bytes)?),
let bytes = public_key_bytes.assume_init();
// Parse the public key bytes to get the parsed struct
let mut cbs = cbs_init(&bytes);
let mut parsed: MaybeUninit<ffi::MLKEM768_public_key> = MaybeUninit::uninit();
ffi::MLKEM768_parse_public_key(parsed.as_mut_ptr(), &mut cbs);
(
Box::new(MlKem768PublicKey {
bytes,
parsed: parsed.assume_init(),
}),
Box::new(MlKem768PrivateKey {
seed,
seed: seed.assume_init(),
expanded: expanded.assume_init(),
}),
))
)
}
}
@ -427,27 +439,39 @@ impl MlKem1024PrivateKey {
pub const CIPHERTEXT_BYTES: usize = ffi::MLKEM1024_CIPHERTEXT_BYTES as usize;
/// Generate a new key pair.
fn generate() -> Result<(Box<MlKem1024PublicKey>, Box<MlKem1024PrivateKey>), ErrorStack> {
#[must_use]
fn generate() -> (Box<MlKem1024PublicKey>, Box<MlKem1024PrivateKey>) {
// SAFETY: all buffers are out parameters, correctly sized
unsafe {
ffi::init();
let mut bytes = [0; MlKem1024PublicKey::PUBLIC_KEY_BYTES];
let mut seed = [0; PRIVATE_KEY_SEED_BYTES];
let mut public_key_bytes: MaybeUninit<[u8; MlKem1024PublicKey::PUBLIC_KEY_BYTES]> =
MaybeUninit::uninit();
let mut seed: MaybeUninit<MlKemPrivateKeySeed> = MaybeUninit::uninit();
let mut expanded: MaybeUninit<ffi::MLKEM1024_private_key> = MaybeUninit::uninit();
ffi::MLKEM1024_generate_key(
bytes.as_mut_ptr().cast(),
seed.as_mut_ptr(),
public_key_bytes.as_mut_ptr().cast(),
seed.as_mut_ptr().cast(),
expanded.as_mut_ptr(),
);
Ok((
Box::new(MlKem1024PublicKey::from_slice(&bytes)?),
let bytes = public_key_bytes.assume_init();
// Parse the public key bytes to get the parsed struct
let mut cbs = cbs_init(&bytes);
let mut parsed: MaybeUninit<ffi::MLKEM1024_public_key> = MaybeUninit::uninit();
ffi::MLKEM1024_parse_public_key(parsed.as_mut_ptr(), &mut cbs);
(
Box::new(MlKem1024PublicKey {
bytes,
parsed: parsed.assume_init(),
}),
Box::new(MlKem1024PrivateKey {
seed,
seed: seed.assume_init(),
expanded: expanded.assume_init(),
}),
))
)
}
}
@ -625,7 +649,7 @@ mod tests {
#[test]
fn roundtrip() {
let (pk, sk) = <$priv>::generate().unwrap();
let (pk, sk) = <$priv>::generate();
let (ct, ss1) = pk.encapsulate();
let ss2 = sk.decapsulate(&ct);
assert_eq!(ss1, ss2);
@ -633,7 +657,7 @@ mod tests {
#[test]
fn seed_roundtrip() {
let (pk, sk) = <$priv>::generate().unwrap();
let (pk, sk) = <$priv>::generate();
let sk2 = <$priv>::from_seed(&sk.seed).unwrap();
let (ct, ss1) = pk.encapsulate();
let ss2 = sk2.decapsulate(&ct);
@ -642,7 +666,7 @@ mod tests {
#[test]
fn derive_pubkey() {
let (pk, sk) = <$priv>::generate().unwrap();
let (pk, sk) = <$priv>::generate();
assert_eq!(pk.bytes, sk.public_key().unwrap().bytes);
}
@ -654,14 +678,14 @@ mod tests {
#[test]
fn from_slice_roundtrip() {
let (pk, _) = <$priv>::generate().unwrap();
let (pk, _) = <$priv>::generate();
let pk2 = <$pub>::from_slice(&pk.bytes).unwrap();
assert_eq!(pk.bytes, pk2.bytes);
}
#[test]
fn implicit_rejection() {
let (_, sk) = <$priv>::generate().unwrap();
let (_, sk) = <$priv>::generate();
let bad_ct = [0x42u8; $ct_len];
// bad ciphertext still "works", just returns deterministic garbage
let ss1 = sk.decapsulate(&bad_ct);
@ -671,7 +695,7 @@ mod tests {
#[test]
fn debug_redacts_seed() {
let (_, sk) = <$priv>::generate().unwrap();
let (_, sk) = <$priv>::generate();
let dbg = format!("{:?}", sk);
assert!(dbg.contains("redacted"));
}

View File

@ -10,7 +10,7 @@ use std::ptr;
use crate::error::ErrorStack;
use crate::nid::Nid;
use crate::pkey::{HasPrivate, PKey, PKeyRef, Private};
use crate::stack::{Stack, StackRef};
use crate::stack::Stack;
use crate::x509::{X509Ref, X509};
use crate::{cvt_0i, cvt_p};
@ -31,43 +31,33 @@ impl Pkcs12Ref {
ffi::i2d_PKCS12
}
/// Extracts the contents of the `Pkcs12` with `pkey` and `cert` required.
/// Extracts the contents of the `Pkcs12`.
pub fn parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack> {
let p2 = self.parse2(pass)?;
Ok(ParsedPkcs12 {
pkey: p2
.pkey
.ok_or_else(|| ErrorStack::internal_error_str("missing pkey"))?,
cert: p2
.cert
.ok_or_else(|| ErrorStack::internal_error_str("missing cert"))?,
chain: p2.ca,
})
}
/// Extracts the contents of the `Pkcs12` with `pkey` and `cert` optional.
#[corresponds(PKCS12_parse)]
pub fn parse2(&self, pass: &str) -> Result<ParsedPkcs12_2, ErrorStack> {
unsafe {
let pass = CString::new(pass.as_bytes()).map_err(ErrorStack::internal_error)?;
let mut pkey = ptr::null_mut();
let mut cert = ptr::null_mut();
let mut ca = ptr::null_mut();
let mut chain = ptr::null_mut();
cvt_0i(ffi::PKCS12_parse(
self.as_ptr(),
pass.as_ptr(),
&mut pkey,
&mut cert,
&mut ca,
&mut chain,
))?;
let pkey = (!pkey.is_null()).then(|| PKey::from_ptr(pkey));
let cert = (!cert.is_null()).then(|| X509::from_ptr(cert));
let ca = (!ca.is_null()).then(|| Stack::from_ptr(ca));
let pkey = PKey::from_ptr(pkey);
let cert = X509::from_ptr(cert);
Ok(ParsedPkcs12_2 { pkey, cert, ca })
let chain = if chain.is_null() {
None
} else {
Some(Stack::from_ptr(chain))
};
Ok(ParsedPkcs12 { pkey, cert, chain })
}
}
}
@ -110,19 +100,6 @@ pub struct ParsedPkcs12 {
pub chain: Option<Stack<X509>>,
}
/// [`ParsedPkcs12`] with optional fields
pub struct ParsedPkcs12_2 {
pub pkey: Option<PKey<Private>>,
pub cert: Option<X509>,
pub ca: Option<Stack<X509>>,
}
impl ParsedPkcs12_2 {
pub fn chain(&self) -> Option<&StackRef<X509>> {
self.ca.as_deref()
}
}
pub struct Pkcs12Builder {
nid_key: Nid,
nid_cert: Nid,

View File

@ -4,10 +4,8 @@ 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;
@ -175,7 +173,6 @@ impl SslContextBuilder {
}
}
#[cfg(feature = "credential")]
impl SslCredentialBuilder {
/// Configures a custom private key method on the context.
///

View File

@ -109,7 +109,6 @@ 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};
@ -118,7 +117,6 @@ mod async_callbacks;
mod bio;
mod callbacks;
mod connector;
#[cfg(feature = "credential")]
mod credential;
mod ech;
mod error;
@ -1272,26 +1270,15 @@ impl SslContextBuilder {
/// The file should contain a sequence of PEM-formatted CA certificates.
#[corresponds(SSL_CTX_load_verify_locations)]
pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
self.load_verify_locations(Some(file.as_ref()), None)
}
/// Loads trusted root certificates from a file and/or a directory.
#[corresponds(SSL_CTX_load_verify_locations)]
pub fn load_verify_locations(
&mut self,
ca_file: Option<&Path>,
ca_path: Option<&Path>,
) -> Result<(), ErrorStack> {
self.ctx.check_x509();
let ca_file = ca_file.map(path_to_cstring).transpose()?;
let ca_path = ca_path.map(path_to_cstring).transpose()?;
let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
.map_err(ErrorStack::internal_error)?;
unsafe {
cvt(ffi::SSL_CTX_load_verify_locations(
self.as_ptr(),
ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
file.as_ptr(),
ptr::null(),
))
}
}
@ -1352,7 +1339,8 @@ impl SslContextBuilder {
) -> Result<(), ErrorStack> {
self.ctx.check_x509();
let file = path_to_cstring(file.as_ref())?;
let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
.map_err(ErrorStack::internal_error)?;
unsafe {
cvt(ffi::SSL_CTX_use_certificate_file(
self.as_ptr(),
@ -1372,7 +1360,8 @@ impl SslContextBuilder {
&mut self,
file: P,
) -> Result<(), ErrorStack> {
let file = path_to_cstring(file.as_ref())?;
let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
.map_err(ErrorStack::internal_error)?;
unsafe {
cvt(ffi::SSL_CTX_use_certificate_chain_file(
self.as_ptr(),
@ -1412,7 +1401,8 @@ impl SslContextBuilder {
file: P,
file_type: SslFiletype,
) -> Result<(), ErrorStack> {
let file = path_to_cstring(file.as_ref())?;
let file = CString::new(file.as_ref().as_os_str().as_encoded_bytes())
.map_err(ErrorStack::internal_error)?;
unsafe {
cvt(ffi::SSL_CTX_use_PrivateKey_file(
self.as_ptr(),
@ -2039,7 +2029,6 @@ 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(
@ -3827,7 +3816,6 @@ 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(|_| ()) }
}
@ -4582,7 +4570,3 @@ unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
}
fn path_to_cstring(path: &Path) -> Result<CString, ErrorStack> {
CString::new(path.as_os_str().as_encoded_bytes()).map_err(ErrorStack::internal_error)
}

View File

@ -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();

View File

@ -31,7 +31,7 @@
//! builder.sign(&pkey, MessageDigest::sha256())?;
//!
//! let mut store_builder = X509StoreBuilder::new()?;
//! store_builder.add_cert(issuer)?;
//! store_builder.add_cert(&issuer)?;
//! store_builder.add_crl(builder.build())?;
//! store_builder
//! .param_mut()

View File

@ -129,7 +129,6 @@ impl X509StoreContextRef {
/// This can be used to provide data to callbacks registered with the context. Use the
/// `Ssl::new_ex_index` method to create an `Index`.
#[corresponds(X509_STORE_CTX_set_ex_data)]
#[doc(alias = "replace_ex_data")]
pub fn set_ex_data<T>(&mut self, index: Index<X509StoreContext, T>, data: T) {
if let Some(old) = self.ex_data_mut(index) {
*old = data;

View File

@ -81,8 +81,7 @@ impl X509StoreBuilder {
impl X509StoreBuilderRef {
/// Adds a certificate to the certificate store.
#[corresponds(X509_STORE_add_cert)]
pub fn add_cert(&mut self, cert: impl AsRef<X509Ref>) -> Result<(), ErrorStack> {
let cert = cert.as_ref();
pub fn add_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())) }
}

View File

@ -24,7 +24,7 @@ bitflags! {
}
bitflags! {
/// Flags used to check an `X509` certificate.
/// Flags used to configure verification of an `X509` certificate
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
#[repr(transparent)]
#[doc(alias = "X509Flags")]

View File

@ -16,8 +16,6 @@ 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"]
@ -27,9 +25,9 @@ http = { workspace = true }
hyper = { workspace = true }
hyper-util = { workspace = true, features = ["client", "client-legacy"] }
linked_hash_set = { workspace = true }
boring = { workspace = true, default-features = false }
boring = { workspace = true }
tokio = { workspace = true }
tokio-boring = { workspace = true, default-features = false }
tokio-boring = { workspace = true }
tower-layer = { workspace = true }
tower-service = { workspace = true }

View File

@ -17,8 +17,6 @@ features = ["rpk"]
rustdoc-args = ["--cfg", "docsrs"]
[features]
default = ["boring/default"]
# Use a FIPS-validated version of boringssl.
fips = ["boring/fips", "boring-sys/fips"]
@ -26,8 +24,8 @@ fips = ["boring/fips", "boring-sys/fips"]
rpk = ["boring/rpk"]
[dependencies]
boring = { workspace = true, default-features = false }
boring-sys = { workspace = true, default-features = false }
boring = { workspace = true }
boring-sys = { workspace = true }
tokio = { workspace = true }
[dev-dependencies]