diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c0057b7..9dc1367c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -187,7 +187,13 @@ jobs: - 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 + - name: Install Clang-12 + uses: KyleMayes/install-llvm-action@v1 + with: + version: "12.0.0" + directory: ${{ runner.temp }}/llvm + - name: Add clang++-12 link + working-directory: ${{ runner.temp }}/llvm/bin + run: ln -s clang clang++-12 - run: cargo test --features fips name: Run tests diff --git a/README.md b/README.md index da844210..d023c509 100644 --- a/README.md +++ b/README.md @@ -24,12 +24,12 @@ _Warning_: When providing a different version of BoringSSL make sure to use a co ## 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) +Only BoringCrypto module version 853ca1ea1168dff08011e5d42d94609cc0ca2e27, as certified with +[FIPS 140-2 certificate 4407](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4407) 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 ``` diff --git a/boring-sys/build.rs b/boring-sys/build.rs index c6e1de7e..1d3a7e2a 100644 --- a/boring-sys/build.rs +++ b/boring-sys/build.rs @@ -241,14 +241,16 @@ fn verify_fips_clang_version() -> (&'static str, &'static str) { return String::new(); } }; - assert!(output.status.success()); + if !output.status.success() { + return String::new(); + } let output = std::str::from_utf8(&output.stdout).expect("invalid utf8 output"); output.lines().next().expect("empty output").to_string() } - const REQUIRED_CLANG_VERSION: &str = "7.0.1"; + const REQUIRED_CLANG_VERSION: &str = "12.0.0"; for (cc, cxx) in [ - ("clang-7", "clang++-7"), + ("clang-12", "clang++-12"), ("clang", "clang++"), ("cc", "c++"), ] { @@ -434,7 +436,6 @@ fn main() { "aes.h", "asn1_mac.h", "asn1t.h", - #[cfg(not(feature = "fips"))] "blake2.h", "blowfish.h", "cast.h", @@ -459,7 +460,6 @@ fn main() { "ripemd.h", "siphash.h", "srtp.h", - #[cfg(not(feature = "fips"))] "trust_token.h", "x509v3.h", ]; diff --git a/boring-sys/deps/boringssl-fips b/boring-sys/deps/boringssl-fips index ae223d61..853ca1ea 160000 --- a/boring-sys/deps/boringssl-fips +++ b/boring-sys/deps/boringssl-fips @@ -1 +1 @@ -Subproject commit ae223d6138807a13006342edfeef32e813246b39 +Subproject commit 853ca1ea1168dff08011e5d42d94609cc0ca2e27 diff --git a/boring/examples/mk_certs.rs b/boring/examples/mk_certs.rs index b27b3974..217786e2 100644 --- a/boring/examples/mk_certs.rs +++ b/boring/examples/mk_certs.rs @@ -81,7 +81,6 @@ fn mk_request(privkey: &PKey) -> Result { } /// 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( ca_cert: &X509Ref, ca_privkey: &PKeyRef, @@ -99,15 +98,7 @@ fn mk_ca_signed_cert( serial.to_asn1_integer()? }; cert_builder.set_serial_number(&serial_number)?; - - #[cfg(not(feature = "fips"))] 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_pubkey(&privkey)?; let not_before = Asn1Time::days_from_now(0)?; diff --git a/boring/src/pkey.rs b/boring/src/pkey.rs index 4054abd1..c62ee341 100644 --- a/boring/src/pkey.rs +++ b/boring/src/pkey.rs @@ -76,10 +76,8 @@ impl Id { pub const DH: Id = Id(ffi::EVP_PKEY_DH); pub const EC: Id = Id(ffi::EVP_PKEY_EC); pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519); - #[cfg(not(feature = "fips"))] pub const ED448: Id = Id(ffi::EVP_PKEY_ED448); pub const X25519: Id = Id(ffi::EVP_PKEY_X25519); - #[cfg(not(feature = "fips"))] pub const X448: Id = Id(ffi::EVP_PKEY_X448); /// Creates a `Id` from an integer representation. @@ -291,7 +289,6 @@ impl fmt::Debug for PKey { Id::DH => "DH", Id::EC => "EC", Id::ED25519 => "Ed25519", - #[cfg(not(feature = "fips"))] Id::ED448 => "Ed448", _ => "unknown", }; diff --git a/boring/src/ssl/mod.rs b/boring/src/ssl/mod.rs index 8ccc1d15..b0460c79 100644 --- a/boring/src/ssl/mod.rs +++ b/boring/src/ssl/mod.rs @@ -486,10 +486,8 @@ impl ExtensionType { Self(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation 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); - #[cfg(not(feature = "fips"))] pub const QUIC_TRANSPORT_PARAMETERS_LEGACY: Self = Self(ffi::TLSEXT_TYPE_quic_transport_parameters_legacy as u16); - #[cfg(not(feature = "fips"))] pub const QUIC_TRANSPORT_PARAMETERS_STANDARD: Self = Self(ffi::TLSEXT_TYPE_quic_transport_parameters_standard as u16); pub const CERT_COMPRESSION: Self = Self(ffi::TLSEXT_TYPE_cert_compression as u16); @@ -506,9 +504,7 @@ impl ExtensionType { 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 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); - #[cfg(not(feature = "fips"))] pub const ENCRYPTED_CLIENT_HELLO: Self = Self(ffi::TLSEXT_TYPE_encrypted_client_hello 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); diff --git a/boring/src/ssl/test/mod.rs b/boring/src/ssl/test/mod.rs index 200ced24..0b83f6cb 100644 --- a/boring/src/ssl/test/mod.rs +++ b/boring/src/ssl/test/mod.rs @@ -448,19 +448,12 @@ fn test_alpn_server_select_none_fatal() { ssl::select_next_proto(b"\x08http/1.1\x08spdy/3.1", client) .ok_or(ssl::AlpnError::ALERT_FATAL) }); - #[cfg(not(feature = "fips"))] server.should_error(); let server = server.build(); let mut client = server.client(); client.ctx().set_alpn_protos(b"\x06http/2").unwrap(); - - if cfg!(feature = "fips") { - let s = client.connect(); - assert_eq!(None, s.ssl().selected_alpn_protocol()); - } else { - client.connect_err(); - } + client.connect_err(); } #[test] diff --git a/boring/src/x509/mod.rs b/boring/src/x509/mod.rs index 08f10208..a02403f4 100644 --- a/boring/src/x509/mod.rs +++ b/boring/src/x509/mod.rs @@ -197,7 +197,6 @@ impl X509StoreContextRef { 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. /// /// This corresponds to [`X509_STORE_CTX_get0_chain`]. @@ -230,14 +229,12 @@ impl X509Builder { /// Sets the notAfter constraint on the certificate. pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> { - // TODO: once FIPS supports `set1_notAfter`, use that instead - unsafe { cvt(X509_set_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) } + unsafe { cvt(X509_set1_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) } } /// Sets the notBefore constraint on the certificate. pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> { - // TODO: once FIPS supports `set1_notBefore`, use that instead - unsafe { cvt(X509_set_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) } + unsafe { cvt(X509_set1_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) } } /// Sets the version of the certificate. @@ -496,18 +493,18 @@ impl X509Ref { /// Returns the certificate's Not After validity period. pub fn not_after(&self) -> &Asn1TimeRef { unsafe { - let date = X509_get0_notAfter(self.as_ptr()); + let date = X509_getm_notAfter(self.as_ptr()); assert!(!date.is_null()); - Asn1TimeRef::from_ptr(date as *mut _) + Asn1TimeRef::from_ptr(date) } } /// Returns the certificate's Not Before validity period. pub fn not_before(&self) -> &Asn1TimeRef { unsafe { - let date = X509_get0_notBefore(self.as_ptr()); + let date = X509_getm_notBefore(self.as_ptr()); assert!(!date.is_null()); - Asn1TimeRef::from_ptr(date as *mut _) + Asn1TimeRef::from_ptr(date) } } @@ -1163,7 +1160,6 @@ impl X509ReqRef { ffi::i2d_X509_REQ } - #[cfg(not(feature = "fips"))] /// Returns the numerical value of the version field of the certificate request. /// /// This corresponds to [`X509_REQ_get_version`] @@ -1173,7 +1169,6 @@ impl X509ReqRef { unsafe { X509_REQ_get_version(self.as_ptr()) as i32 } } - #[cfg(not(feature = "fips"))] /// Returns the subject name of the certificate request. /// /// This corresponds to [`X509_REQ_get_subject_name`] @@ -1406,12 +1401,14 @@ impl Stackable for X509Object { type StackType = ffi::stack_st_X509_OBJECT; } -use crate::ffi::{X509_get0_notAfter, X509_get0_notBefore, X509_get0_signature, X509_up_ref}; +use crate::ffi::{X509_get0_signature, X509_getm_notAfter, X509_getm_notBefore, 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::{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)] unsafe fn X509_OBJECT_free(x: *mut ffi::X509_OBJECT) {