Add fips-3678 feature (#52)
* Add rerun-if-env-changed instructions for BORING_* variables * Use X509_get0_notBefore() and X509_get0_notAfter() instead of X509_getm_notBefore() and X509_getm_notAfter(). According to https://www.openssl.org/docs/man1.1.0/man3/X509_getm_notBefore.html, "X509_getm_notBefore() and X509_getm_notAfter() are similar to X509_get0_notBefore() and X509_get0_notAfter() except they return non-constant mutable references to the associated date field of the certificate". * Only update boringssl submodule if BORING_BSSL_PATH not provided * Allow BORING_BSSL_LIB_PATH to control link search * Add fips feature * Use X509_set_notAfter unconditionally for FIPS compatibility This is equivalent according to https://boringssl.googlesource.com/boringssl/+/c947efabcbc38dcf93e8ad0e6a76206cf0ec8072 The version of boringssl that's FIPS-certified doesn't have `X509_set1_notAfter`. The only difference between that and `X509_set_notAfter` is whether they're const-correct, which doesn't seem worth having two different code-paths. * Check out fips commit automatically * Verify the version of the compiler used for building boringssl NIST specifies that it needs to be 7.0.1; I originally tried building with clang 10 and it failed. Theoretically this should check the versions of Go and Ninja too, but they haven't given me trouble in practice. Example error: ``` Compiling boring-sys v1.1.1 (/home/jnelson/work/boring/boring-sys) error: failed to run custom build command for `boring-sys v1.1.1 (/home/jnelson/work/boring/boring-sys)` Caused by: process didn't exit successfully: `/home/jnelson/work/boring/target/debug/build/boring-sys-31b8ce53031cfd83/build-script-build` (exit status: 101) --- stdout cargo:rerun-if-env-changed=BORING_BSSL_PATH --- stderr warning: missing clang-7, trying other compilers: Permission denied (os error 13) warning: FIPS requires clang version 7.0.1, skipping incompatible version "clang version 10.0.0-4ubuntu1 " thread 'main' panicked at 'unsupported clang version "cc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0": FIPS requires clang 7.0.1', boring-sys/build.rs:216:13 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ``` * Add Github actions workflow testing FIPS Co-authored-by: Joshua Nelson <jnelson@cloudflare.com>
This commit is contained in:
parent
5f327aba86
commit
1507689c5b
|
|
@ -159,3 +159,18 @@ jobs:
|
||||||
- if: "!startsWith(matrix.os, 'windows')"
|
- if: "!startsWith(matrix.os, 'windows')"
|
||||||
run: cargo test
|
run: cargo test
|
||||||
name: Run tests (not Windows)
|
name: Run tests (not Windows)
|
||||||
|
|
||||||
|
test-fips:
|
||||||
|
name: Test FIPS integration
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
- name: Install Rust (rustup)
|
||||||
|
run: rustup update stable --no-self-update && rustup default stable
|
||||||
|
shell: bash
|
||||||
|
- name: Install Clang-7
|
||||||
|
run: sudo apt-get install -y clang-7
|
||||||
|
- run: cargo test --features fips
|
||||||
|
name: Run tests
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,6 @@
|
||||||
path = boring-sys/deps/boringssl
|
path = boring-sys/deps/boringssl
|
||||||
url = https://github.com/google/boringssl.git
|
url = https://github.com/google/boringssl.git
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
|
[submodule "boring-sys/deps/boringssl-fips"]
|
||||||
|
path = boring-sys/deps/boringssl-fips
|
||||||
|
url = https://github.com/google/boringssl.git
|
||||||
|
|
|
||||||
12
README.md
12
README.md
|
|
@ -22,6 +22,18 @@ _Notes_: The crate will look for headers in the `$BORING_BSSL_INCLUDE_PATH/opens
|
||||||
|
|
||||||
_Warning_: When providing a different version of BoringSSL make sure to use a compatible one, the crate relies on the presence of certain functions.
|
_Warning_: When providing a different version of BoringSSL make sure to use a compatible one, the crate relies on the presence of certain functions.
|
||||||
|
|
||||||
|
## Building with a FIPS-validated module
|
||||||
|
|
||||||
|
Only BoringCrypto module version ae223d6138807a13006342edfeef32e813246b39, as
|
||||||
|
certified with [certificate
|
||||||
|
3678](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3678)
|
||||||
|
is supported by this crate. Support is enabled by this crate's `fips` feature.
|
||||||
|
|
||||||
|
`boring-sys` comes with a test that FIPS is enabled/disabled depending on the feature flag. You can run it as follows:
|
||||||
|
```bash
|
||||||
|
$ cargo test --features fips fips::is_enabled
|
||||||
|
```
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
|
|
||||||
Unless you explicitly state otherwise, any contribution intentionally
|
Unless you explicitly state otherwise, any contribution intentionally
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,7 @@ include = [
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = { version = "0.59", default-features = false, features = ["runtime"] }
|
bindgen = { version = "0.59", default-features = false, features = ["runtime"] }
|
||||||
cmake = "0.1"
|
cmake = "0.1"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# Use a FIPS-validated version of boringssl.
|
||||||
|
fips = []
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
// NOTE: this build script is adopted from quiche (https://github.com/cloudflare/quiche)
|
// NOTE: this build script is adopted from quiche (https://github.com/cloudflare/quiche)
|
||||||
|
|
||||||
// Additional parameters for Android build of BoringSSL.
|
// Additional parameters for Android build of BoringSSL.
|
||||||
|
|
@ -85,6 +88,11 @@ fn get_boringssl_platform_output_path() -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "fips")]
|
||||||
|
const BORING_SSL_PATH: &str = "deps/boringssl-fips";
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
|
const BORING_SSL_PATH: &str = "deps/boringssl";
|
||||||
|
|
||||||
/// Returns a new cmake::Config for building BoringSSL.
|
/// Returns a new cmake::Config for building BoringSSL.
|
||||||
///
|
///
|
||||||
/// It will add platform-specific parameters if needed.
|
/// It will add platform-specific parameters if needed.
|
||||||
|
|
@ -93,7 +101,7 @@ fn get_boringssl_cmake_config() -> cmake::Config {
|
||||||
let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
|
let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||||
let pwd = std::env::current_dir().unwrap();
|
let pwd = std::env::current_dir().unwrap();
|
||||||
|
|
||||||
let mut boringssl_cmake = cmake::Config::new("deps/boringssl");
|
let mut boringssl_cmake = cmake::Config::new(BORING_SSL_PATH);
|
||||||
|
|
||||||
// Add platform-specific parameters.
|
// Add platform-specific parameters.
|
||||||
match os.as_ref() {
|
match os.as_ref() {
|
||||||
|
|
@ -105,6 +113,7 @@ fn get_boringssl_cmake_config() -> cmake::Config {
|
||||||
};
|
};
|
||||||
|
|
||||||
// We need ANDROID_NDK_HOME to be set properly.
|
// We need ANDROID_NDK_HOME to be set properly.
|
||||||
|
println!("cargo:rerun-if-env-changed=ANDROID_NDK_HOME");
|
||||||
let android_ndk_home = std::env::var("ANDROID_NDK_HOME")
|
let android_ndk_home = std::env::var("ANDROID_NDK_HOME")
|
||||||
.expect("Please set ANDROID_NDK_HOME for Android build");
|
.expect("Please set ANDROID_NDK_HOME for Android build");
|
||||||
let android_ndk_home = std::path::Path::new(&android_ndk_home);
|
let android_ndk_home = std::path::Path::new(&android_ndk_home);
|
||||||
|
|
@ -161,7 +170,8 @@ fn get_boringssl_cmake_config() -> cmake::Config {
|
||||||
if arch == "x86" && os != "windows" {
|
if arch == "x86" && os != "windows" {
|
||||||
boringssl_cmake.define(
|
boringssl_cmake.define(
|
||||||
"CMAKE_TOOLCHAIN_FILE",
|
"CMAKE_TOOLCHAIN_FILE",
|
||||||
pwd.join("deps/boringssl/src/util/32-bit-toolchain.cmake")
|
pwd.join(BORING_SSL_PATH)
|
||||||
|
.join("src/util/32-bit-toolchain.cmake")
|
||||||
.as_os_str(),
|
.as_os_str(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -171,42 +181,107 @@ fn get_boringssl_cmake_config() -> cmake::Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
/// Verify that the toolchains match https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf
|
||||||
use std::env;
|
/// See "Installation Instructions" under section 12.1.
|
||||||
use std::path::{Path, PathBuf};
|
// TODO: maybe this should also verify the Go and Ninja versions? But those haven't been an issue in practice ...
|
||||||
use std::process::Command;
|
fn verify_fips_clang_version() -> (&'static str, &'static str) {
|
||||||
|
fn version(tool: &str) -> String {
|
||||||
if !Path::new("deps/boringssl/CMakeLists.txt").exists() {
|
let output = match Command::new(tool).arg("--version").output() {
|
||||||
println!("cargo:warning=fetching boringssl git submodule");
|
Ok(o) => o,
|
||||||
// fetch the boringssl submodule
|
Err(e) => {
|
||||||
let status = Command::new("git")
|
eprintln!("warning: missing {}, trying other compilers: {}", tool, e);
|
||||||
.args(&[
|
// NOTE: hard-codes that the loop below checks the version
|
||||||
"submodule",
|
return String::new();
|
||||||
"update",
|
}
|
||||||
"--init",
|
};
|
||||||
"--recursive",
|
assert!(output.status.success());
|
||||||
"deps/boringssl",
|
let output = std::str::from_utf8(&output.stdout).expect("invalid utf8 output");
|
||||||
])
|
output.lines().next().expect("empty output").to_string()
|
||||||
.status();
|
|
||||||
if !status.map_or(false, |status| status.success()) {
|
|
||||||
panic!("failed to fetch submodule - consider running `git submodule update --init --recursive deps/boringssl` yourself");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const REQUIRED_CLANG_VERSION: &str = "7.0.1";
|
||||||
|
for (cc, cxx) in [
|
||||||
|
("clang-7", "clang++-7"),
|
||||||
|
("clang", "clang++"),
|
||||||
|
("cc", "c++"),
|
||||||
|
] {
|
||||||
|
let cc_version = version(cc);
|
||||||
|
if cc_version.contains(REQUIRED_CLANG_VERSION) {
|
||||||
|
assert!(
|
||||||
|
version(cxx).contains(REQUIRED_CLANG_VERSION),
|
||||||
|
"mismatched versions of cc and c++"
|
||||||
|
);
|
||||||
|
return (cc, cxx);
|
||||||
|
} else if cc == "cc" {
|
||||||
|
panic!(
|
||||||
|
"unsupported clang version \"{}\": FIPS requires clang {}",
|
||||||
|
cc_version, REQUIRED_CLANG_VERSION
|
||||||
|
);
|
||||||
|
} else if !cc_version.is_empty() {
|
||||||
|
eprintln!(
|
||||||
|
"warning: FIPS requires clang version {}, skipping incompatible version \"{}\"",
|
||||||
|
REQUIRED_CLANG_VERSION, cc_version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-env-changed=BORING_BSSL_PATH");
|
||||||
let bssl_dir = std::env::var("BORING_BSSL_PATH").unwrap_or_else(|_| {
|
let bssl_dir = std::env::var("BORING_BSSL_PATH").unwrap_or_else(|_| {
|
||||||
|
if !Path::new(BORING_SSL_PATH).join("CMakeLists.txt").exists() {
|
||||||
|
println!("cargo:warning=fetching boringssl git submodule");
|
||||||
|
// fetch the boringssl submodule
|
||||||
|
let status = Command::new("git")
|
||||||
|
.args(&[
|
||||||
|
"submodule",
|
||||||
|
"update",
|
||||||
|
"--init",
|
||||||
|
"--recursive",
|
||||||
|
BORING_SSL_PATH,
|
||||||
|
])
|
||||||
|
.status();
|
||||||
|
if !status.map_or(false, |status| status.success()) {
|
||||||
|
panic!("failed to fetch submodule - consider running `git submodule update --init --recursive deps/boringssl` yourself");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut cfg = get_boringssl_cmake_config();
|
let mut cfg = get_boringssl_cmake_config();
|
||||||
|
|
||||||
if cfg!(feature = "fuzzing") {
|
if cfg!(feature = "fuzzing") {
|
||||||
cfg.cxxflag("-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE")
|
cfg.cxxflag("-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE")
|
||||||
.cxxflag("-DBORINGSSL_UNSAFE_FUZZER_MODE");
|
.cxxflag("-DBORINGSSL_UNSAFE_FUZZER_MODE");
|
||||||
}
|
}
|
||||||
|
if cfg!(feature = "fips") {
|
||||||
|
let (clang, clangxx) = verify_fips_clang_version();
|
||||||
|
cfg.define("CMAKE_C_COMPILER", clang);
|
||||||
|
cfg.define("CMAKE_CXX_COMPILER", clangxx);
|
||||||
|
cfg.define("CMAKE_ASM_COMPILER", clang);
|
||||||
|
cfg.define("FIPS", "1");
|
||||||
|
}
|
||||||
|
|
||||||
cfg.build_target("bssl").build().display().to_string()
|
cfg.build_target("bssl").build().display().to_string()
|
||||||
});
|
});
|
||||||
|
|
||||||
let build_path = get_boringssl_platform_output_path();
|
let build_path = get_boringssl_platform_output_path();
|
||||||
let build_dir = format!("{}/build/{}", bssl_dir, build_path);
|
if cfg!(feature = "fips") {
|
||||||
println!("cargo:rustc-link-search=native={}", build_dir);
|
println!(
|
||||||
|
"cargo:rustc-link-search=native={}/build/crypto/{}",
|
||||||
|
bssl_dir, build_path
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"cargo:rustc-link-search=native={}/build/ssl/{}",
|
||||||
|
bssl_dir, build_path
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!(
|
||||||
|
"cargo:rustc-link-search=native={}/build/{}",
|
||||||
|
bssl_dir, build_path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
println!("cargo:rustc-link-lib=static=crypto");
|
println!("cargo:rustc-link-lib=static=crypto");
|
||||||
println!("cargo:rustc-link-lib=static=ssl");
|
println!("cargo:rustc-link-lib=static=ssl");
|
||||||
|
|
@ -216,10 +291,14 @@ fn main() {
|
||||||
println!("cargo:rustc-cdylib-link-arg=-Wl,-undefined,dynamic_lookup");
|
println!("cargo:rustc-cdylib-link-arg=-Wl,-undefined,dynamic_lookup");
|
||||||
}
|
}
|
||||||
|
|
||||||
let include_path = PathBuf::from(
|
println!("cargo:rerun-if-env-changed=BORING_BSSL_INCLUDE_PATH");
|
||||||
std::env::var("BORING_BSSL_INCLUDE_PATH")
|
let include_path = std::env::var("BORING_BSSL_INCLUDE_PATH").unwrap_or_else(|_| {
|
||||||
.unwrap_or_else(|_| String::from("deps/boringssl/src/include")),
|
if cfg!(feature = "fips") {
|
||||||
);
|
format!("{}/include", BORING_SSL_PATH)
|
||||||
|
} else {
|
||||||
|
format!("{}/src/include", BORING_SSL_PATH)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let mut builder = bindgen::Builder::default()
|
let mut builder = bindgen::Builder::default()
|
||||||
.derive_copy(true)
|
.derive_copy(true)
|
||||||
|
|
@ -234,12 +313,13 @@ fn main() {
|
||||||
.layout_tests(true)
|
.layout_tests(true)
|
||||||
.prepend_enum_name(true)
|
.prepend_enum_name(true)
|
||||||
.rustfmt_bindings(true)
|
.rustfmt_bindings(true)
|
||||||
.clang_args(&["-I", include_path.to_str().unwrap()]);
|
.clang_args(&["-I", &include_path]);
|
||||||
|
|
||||||
let headers = [
|
let headers = [
|
||||||
"aes.h",
|
"aes.h",
|
||||||
"asn1_mac.h",
|
"asn1_mac.h",
|
||||||
"asn1t.h",
|
"asn1t.h",
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
"blake2.h",
|
"blake2.h",
|
||||||
"blowfish.h",
|
"blowfish.h",
|
||||||
"cast.h",
|
"cast.h",
|
||||||
|
|
@ -264,11 +344,18 @@ fn main() {
|
||||||
"ripemd.h",
|
"ripemd.h",
|
||||||
"siphash.h",
|
"siphash.h",
|
||||||
"srtp.h",
|
"srtp.h",
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
"trust_token.h",
|
"trust_token.h",
|
||||||
"x509v3.h",
|
"x509v3.h",
|
||||||
];
|
];
|
||||||
for header in &headers {
|
for header in &headers {
|
||||||
builder = builder.header(include_path.join("openssl").join(header).to_str().unwrap());
|
builder = builder.header(
|
||||||
|
Path::new(&include_path)
|
||||||
|
.join("openssl")
|
||||||
|
.join(header)
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let bindings = builder.generate().expect("Unable to generate bindings");
|
let bindings = builder.generate().expect("Unable to generate bindings");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit ae223d6138807a13006342edfeef32e813246b39
|
||||||
|
|
@ -21,3 +21,7 @@ boring-sys = { version = ">=1.1.0,<3.0.0", path = "../boring-sys" }
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
rusty-hook = "^0.11"
|
rusty-hook = "^0.11"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# Use a FIPS-validated version of boringssl.
|
||||||
|
fips = ["boring-sys/fips"]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println!("boring::fips::enabled(): {}", boring::fips::enabled());
|
||||||
|
}
|
||||||
|
|
@ -81,6 +81,7 @@ fn mk_request(privkey: &PKey<Private>) -> Result<X509Req, ErrorStack> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Make a certificate and private key signed by the given CA cert and private key
|
/// Make a certificate and private key signed by the given CA cert and private key
|
||||||
|
#[cfg_attr(feature = "fips", allow(unreachable_code, unused_variables))]
|
||||||
fn mk_ca_signed_cert(
|
fn mk_ca_signed_cert(
|
||||||
ca_cert: &X509Ref,
|
ca_cert: &X509Ref,
|
||||||
ca_privkey: &PKeyRef<Private>,
|
ca_privkey: &PKeyRef<Private>,
|
||||||
|
|
@ -98,7 +99,15 @@ fn mk_ca_signed_cert(
|
||||||
serial.to_asn1_integer()?
|
serial.to_asn1_integer()?
|
||||||
};
|
};
|
||||||
cert_builder.set_serial_number(&serial_number)?;
|
cert_builder.set_serial_number(&serial_number)?;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
cert_builder.set_subject_name(req.subject_name())?;
|
cert_builder.set_subject_name(req.subject_name())?;
|
||||||
|
#[cfg(feature = "fips")]
|
||||||
|
{
|
||||||
|
eprintln!("mk_certs not supported with FIPS module");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
cert_builder.set_issuer_name(ca_cert.subject_name())?;
|
cert_builder.set_issuer_name(ca_cert.subject_name())?;
|
||||||
cert_builder.set_pubkey(&privkey)?;
|
cert_builder.set_pubkey(&privkey)?;
|
||||||
let not_before = Asn1Time::days_from_now(0)?;
|
let not_before = Asn1Time::days_from_now(0)?;
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,11 @@ pub fn enable(enabled: bool) -> Result<(), ErrorStack> {
|
||||||
pub fn enabled() -> bool {
|
pub fn enabled() -> bool {
|
||||||
unsafe { ffi::FIPS_mode() != 0 }
|
unsafe { ffi::FIPS_mode() != 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn is_enabled() {
|
||||||
|
#[cfg(feature = "fips")]
|
||||||
|
assert!(enabled());
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
|
assert!(!enabled());
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,10 @@ impl Id {
|
||||||
pub const DH: Id = Id(ffi::EVP_PKEY_DH);
|
pub const DH: Id = Id(ffi::EVP_PKEY_DH);
|
||||||
pub const EC: Id = Id(ffi::EVP_PKEY_EC);
|
pub const EC: Id = Id(ffi::EVP_PKEY_EC);
|
||||||
pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519);
|
pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519);
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
pub const ED448: Id = Id(ffi::EVP_PKEY_ED448);
|
pub const ED448: Id = Id(ffi::EVP_PKEY_ED448);
|
||||||
pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
|
pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
pub const X448: Id = Id(ffi::EVP_PKEY_X448);
|
pub const X448: Id = Id(ffi::EVP_PKEY_X448);
|
||||||
|
|
||||||
/// Creates a `Id` from an integer representation.
|
/// Creates a `Id` from an integer representation.
|
||||||
|
|
@ -289,6 +291,7 @@ impl<T> fmt::Debug for PKey<T> {
|
||||||
Id::DH => "DH",
|
Id::DH => "DH",
|
||||||
Id::EC => "EC",
|
Id::EC => "EC",
|
||||||
Id::ED25519 => "Ed25519",
|
Id::ED25519 => "Ed25519",
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
Id::ED448 => "Ed448",
|
Id::ED448 => "Ed448",
|
||||||
_ => "unknown",
|
_ => "unknown",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -487,8 +487,10 @@ impl ExtensionType {
|
||||||
pub const PADDING: Self = Self(ffi::TLSEXT_TYPE_padding as u16);
|
pub const PADDING: Self = Self(ffi::TLSEXT_TYPE_padding as u16);
|
||||||
pub const EXTENDED_MASTER_SECRET: Self = Self(ffi::TLSEXT_TYPE_extended_master_secret as u16);
|
pub const EXTENDED_MASTER_SECRET: Self = Self(ffi::TLSEXT_TYPE_extended_master_secret as u16);
|
||||||
pub const TOKEN_BINDING: Self = Self(ffi::TLSEXT_TYPE_token_binding as u16);
|
pub const TOKEN_BINDING: Self = Self(ffi::TLSEXT_TYPE_token_binding as u16);
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
pub const QUIC_TRANSPORT_PARAMETERS_LEGACY: Self =
|
pub const QUIC_TRANSPORT_PARAMETERS_LEGACY: Self =
|
||||||
Self(ffi::TLSEXT_TYPE_quic_transport_parameters_legacy as u16);
|
Self(ffi::TLSEXT_TYPE_quic_transport_parameters_legacy as u16);
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
pub const QUIC_TRANSPORT_PARAMETERS_STANDARD: Self =
|
pub const QUIC_TRANSPORT_PARAMETERS_STANDARD: Self =
|
||||||
Self(ffi::TLSEXT_TYPE_quic_transport_parameters_standard as u16);
|
Self(ffi::TLSEXT_TYPE_quic_transport_parameters_standard as u16);
|
||||||
pub const CERT_COMPRESSION: Self = Self(ffi::TLSEXT_TYPE_cert_compression as u16);
|
pub const CERT_COMPRESSION: Self = Self(ffi::TLSEXT_TYPE_cert_compression as u16);
|
||||||
|
|
@ -505,8 +507,11 @@ impl ExtensionType {
|
||||||
pub const KEY_SHARE: Self = Self(ffi::TLSEXT_TYPE_key_share as u16);
|
pub const KEY_SHARE: Self = Self(ffi::TLSEXT_TYPE_key_share as u16);
|
||||||
pub const RENEGOTIATE: Self = Self(ffi::TLSEXT_TYPE_renegotiate as u16);
|
pub const RENEGOTIATE: Self = Self(ffi::TLSEXT_TYPE_renegotiate as u16);
|
||||||
pub const DELEGATED_CREDENTIAL: Self = Self(ffi::TLSEXT_TYPE_delegated_credential as u16);
|
pub const DELEGATED_CREDENTIAL: Self = Self(ffi::TLSEXT_TYPE_delegated_credential as u16);
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
pub const APPLICATION_SETTINGS: Self = Self(ffi::TLSEXT_TYPE_application_settings as u16);
|
pub const APPLICATION_SETTINGS: Self = Self(ffi::TLSEXT_TYPE_application_settings as u16);
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
pub const ENCRYPTED_CLIENT_HELLO: Self = Self(ffi::TLSEXT_TYPE_encrypted_client_hello as u16);
|
pub const ENCRYPTED_CLIENT_HELLO: Self = Self(ffi::TLSEXT_TYPE_encrypted_client_hello as u16);
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
pub const ECH_IS_INNER: Self = Self(ffi::TLSEXT_TYPE_ech_is_inner as u16);
|
pub const ECH_IS_INNER: Self = Self(ffi::TLSEXT_TYPE_ech_is_inner as u16);
|
||||||
pub const CERTIFICATE_TIMESTAMP: Self = Self(ffi::TLSEXT_TYPE_certificate_timestamp as u16);
|
pub const CERTIFICATE_TIMESTAMP: Self = Self(ffi::TLSEXT_TYPE_certificate_timestamp as u16);
|
||||||
pub const NEXT_PROTO_NEG: Self = Self(ffi::TLSEXT_TYPE_next_proto_neg as u16);
|
pub const NEXT_PROTO_NEG: Self = Self(ffi::TLSEXT_TYPE_next_proto_neg as u16);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
use hex;
|
use hex;
|
||||||
|
use std::cell::Cell;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
@ -508,14 +509,16 @@ fn test_select_cert_error() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_select_cert_unknown_extension() {
|
fn test_select_cert_unknown_extension() {
|
||||||
let mut server = Server::builder();
|
let mut server = Server::builder();
|
||||||
let unknown_extension = std::sync::Arc::new(std::sync::Mutex::new(None));
|
let unknown_extension = std::sync::Arc::new(std::sync::Mutex::new(Some(vec![])));
|
||||||
|
|
||||||
server.ctx().set_select_certificate_callback({
|
server.ctx().set_select_certificate_callback({
|
||||||
let unknown = unknown_extension.clone();
|
let unknown = unknown_extension.clone();
|
||||||
move |client_hello| {
|
move |client_hello| {
|
||||||
*unknown.lock().unwrap() = client_hello
|
let ext = client_hello
|
||||||
.get_extension(ExtensionType::QUIC_TRANSPORT_PARAMETERS_LEGACY)
|
.get_extension(ExtensionType::SERVER_NAME)
|
||||||
.map(ToOwned::to_owned);
|
.map(ToOwned::to_owned);
|
||||||
|
assert!(ext.is_none());
|
||||||
|
*unknown.lock().unwrap() = ext;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,7 @@ impl X509StoreContextRef {
|
||||||
unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 }
|
unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
/// Returns a reference to a complete valid `X509` certificate chain.
|
/// Returns a reference to a complete valid `X509` certificate chain.
|
||||||
///
|
///
|
||||||
/// This corresponds to [`X509_STORE_CTX_get0_chain`].
|
/// This corresponds to [`X509_STORE_CTX_get0_chain`].
|
||||||
|
|
@ -229,12 +230,14 @@ impl X509Builder {
|
||||||
|
|
||||||
/// Sets the notAfter constraint on the certificate.
|
/// Sets the notAfter constraint on the certificate.
|
||||||
pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> {
|
pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> {
|
||||||
unsafe { cvt(X509_set1_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) }
|
// TODO: once FIPS supports `set1_notAfter`, use that instead
|
||||||
|
unsafe { cvt(X509_set_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the notBefore constraint on the certificate.
|
/// Sets the notBefore constraint on the certificate.
|
||||||
pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> {
|
pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> {
|
||||||
unsafe { cvt(X509_set1_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) }
|
// TODO: once FIPS supports `set1_notBefore`, use that instead
|
||||||
|
unsafe { cvt(X509_set_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the version of the certificate.
|
/// Sets the version of the certificate.
|
||||||
|
|
@ -493,18 +496,18 @@ impl X509Ref {
|
||||||
/// Returns the certificate's Not After validity period.
|
/// Returns the certificate's Not After validity period.
|
||||||
pub fn not_after(&self) -> &Asn1TimeRef {
|
pub fn not_after(&self) -> &Asn1TimeRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
let date = X509_getm_notAfter(self.as_ptr());
|
let date = X509_get0_notAfter(self.as_ptr());
|
||||||
assert!(!date.is_null());
|
assert!(!date.is_null());
|
||||||
Asn1TimeRef::from_ptr(date)
|
Asn1TimeRef::from_ptr(date as *mut _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the certificate's Not Before validity period.
|
/// Returns the certificate's Not Before validity period.
|
||||||
pub fn not_before(&self) -> &Asn1TimeRef {
|
pub fn not_before(&self) -> &Asn1TimeRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
let date = X509_getm_notBefore(self.as_ptr());
|
let date = X509_get0_notBefore(self.as_ptr());
|
||||||
assert!(!date.is_null());
|
assert!(!date.is_null());
|
||||||
Asn1TimeRef::from_ptr(date)
|
Asn1TimeRef::from_ptr(date as *mut _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1160,6 +1163,7 @@ impl X509ReqRef {
|
||||||
ffi::i2d_X509_REQ
|
ffi::i2d_X509_REQ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
/// Returns the numerical value of the version field of the certificate request.
|
/// Returns the numerical value of the version field of the certificate request.
|
||||||
///
|
///
|
||||||
/// This corresponds to [`X509_REQ_get_version`]
|
/// This corresponds to [`X509_REQ_get_version`]
|
||||||
|
|
@ -1169,6 +1173,7 @@ impl X509ReqRef {
|
||||||
unsafe { X509_REQ_get_version(self.as_ptr()) as i32 }
|
unsafe { X509_REQ_get_version(self.as_ptr()) as i32 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
/// Returns the subject name of the certificate request.
|
/// Returns the subject name of the certificate request.
|
||||||
///
|
///
|
||||||
/// This corresponds to [`X509_REQ_get_subject_name`]
|
/// This corresponds to [`X509_REQ_get_subject_name`]
|
||||||
|
|
@ -1401,14 +1406,12 @@ impl Stackable for X509Object {
|
||||||
type StackType = ffi::stack_st_X509_OBJECT;
|
type StackType = ffi::stack_st_X509_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::ffi::{X509_get0_signature, X509_getm_notAfter, X509_getm_notBefore, X509_up_ref};
|
use crate::ffi::{X509_get0_notAfter, X509_get0_notBefore, X509_get0_signature, X509_up_ref};
|
||||||
|
|
||||||
use crate::ffi::{
|
|
||||||
ASN1_STRING_get0_data, X509_ALGOR_get0, X509_REQ_get_subject_name, X509_REQ_get_version,
|
|
||||||
X509_STORE_CTX_get0_chain, X509_set1_notAfter, X509_set1_notBefore,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::ffi::X509_OBJECT_get0_X509;
|
use crate::ffi::X509_OBJECT_get0_X509;
|
||||||
|
use crate::ffi::{ASN1_STRING_get0_data, X509_ALGOR_get0, X509_set_notAfter, X509_set_notBefore};
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
|
use crate::ffi::{X509_REQ_get_subject_name, X509_REQ_get_version, X509_STORE_CTX_get0_chain};
|
||||||
|
|
||||||
#[allow(bad_style)]
|
#[allow(bad_style)]
|
||||||
unsafe fn X509_OBJECT_free(x: *mut ffi::X509_OBJECT) {
|
unsafe fn X509_OBJECT_free(x: *mut ffi::X509_OBJECT) {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ exclude = ["test/*"]
|
||||||
default = ["runtime"]
|
default = ["runtime"]
|
||||||
|
|
||||||
runtime = ["hyper/runtime"]
|
runtime = ["hyper/runtime"]
|
||||||
|
fips = ["tokio-boring/fips"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
antidote = "1.0.0"
|
antidote = "1.0.0"
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,6 @@ tokio = "1"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
fips = ["boring/fips"]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue