Compare commits
3 Commits
main
...
jrose/bori
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d000369f3 | ||
|
|
43c8c279f3 | ||
|
|
ed051f3b63 |
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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).
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 }
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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"));
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
///
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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())) }
|
||||
}
|
||||
|
||||
|
||||
@ -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")]
|
||||
|
||||
@ -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 }
|
||||
|
||||
|
||||
@ -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]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user