Skip to content

Commit

Permalink
Expose set_compliance_policy and get_ciphers
Browse files Browse the repository at this point in the history
  • Loading branch information
jhoyla committed Jan 16, 2024
1 parent 0f5731b commit 576967c
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 2 deletions.
57 changes: 55 additions & 2 deletions boring/src/ssl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
use crate::ssl::bio::BioMethod;
use crate::ssl::callbacks::*;
use crate::ssl::error::InnerError;
use crate::stack::{Stack, StackRef};
use crate::stack::{Stack, StackRef, Stackable};
use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
use crate::x509::verify::X509VerifyParamRef;
use crate::x509::{
Expand Down Expand Up @@ -701,6 +701,27 @@ impl SslCurve {
pub const P256_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::NID_P256Kyber768Draft00);
}

/// A compliance policy
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg(feature = "fips-link-precompiled")]
pub struct CompliancePolicy(ffi::ssl_compliance_policy_t);

#[cfg(feature = "fips-link-precompiled")]
impl CompliancePolicy {
/// Does nothing, however setting this does not undo other policies, so trying to set this is an error.
pub const NONE: Self = Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_none);

/// Configures a TLS connection to try and be compliant with NIST requirements, but does not guarantee success.
/// This policy can be called even if Boring is not built with FIPS.
pub const FIPS_202205: Self =
Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_fips_202205);

/// Partially configures a TLS connection to be compliant with WPA3. Callers must enforce certificate chain requirements themselves.
/// Use of this policy is less secure than the default and not recommended.
pub const WPA3_192_202304: Self =
Self(ffi::ssl_compliance_policy_t::ssl_compliance_policy_wpa3_192_202304);
}

/// A standard implementation of protocol selection for Application Layer Protocol Negotiation
/// (ALPN).
///
Expand Down Expand Up @@ -1262,7 +1283,9 @@ impl SslContextBuilder {

/// Sets the list of supported ciphers for protocols before TLSv1.3.
///
/// The `set_ciphersuites` method controls the cipher suites for TLSv1.3.
/// The `set_ciphersuites` method controls the cipher suites for TLSv1.3 in OpenSSL.
/// BoringSSL doesn't implement `set_ciphersuites`.
/// See https://github.com/google/boringssl/blob/master/include/openssl/ssl.h#L1542-L1544
///
/// See [`ciphers`] for details on the format.
///
Expand All @@ -1281,6 +1304,21 @@ impl SslContextBuilder {
}
}

/// Gets the list of supported ciphers for protocols before TLSv1.3.
///
/// See [`ciphers`] for details on the format
///
/// This corresponds to [`SSL_CTX_get_ciphers`].
///
/// [`ciphers`]: https://www.openssl.org/docs/manmaster/man1/ciphers.html
/// [`SSL_CTX_set_cipher_list`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_get_ciphers.html
pub fn get_ciphers(&mut self) -> Result<&StackRef<SslCipher>, ErrorStack> {
unsafe {
let ciphers = cvt_p(ffi::SSL_CTX_get_ciphers(self.as_ptr()))?;
Ok(StackRef::from_ptr(ciphers))
}
}

/// Sets the options used by the context, returning the old set.
///
/// This corresponds to [`SSL_CTX_set_options`].
Expand Down Expand Up @@ -1856,6 +1894,17 @@ impl SslContextBuilder {
}
}

/// Sets the context's compliance policy.
///
/// This corresponds to [`SSL_CTX_set_compliance_policy`]
///
/// [`SSL_CTX_set_compliance_policy`] https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_compliance_policy
/// This feature isn't available in the certified version of BoringSSL.
#[cfg(feature = "fips-link-precompiled")]
pub fn set_compliance_policy(&mut self, policy: CompliancePolicy) -> Result<(), ErrorStack> {
unsafe { cvt_0i(ffi::SSL_CTX_set_compliance_policy(self.as_ptr(), policy.0)).map(|_| ()) }
}

/// Consumes the builder, returning a new `SslContext`.
pub fn build(self) -> SslContext {
self.ctx
Expand Down Expand Up @@ -2181,6 +2230,10 @@ impl ClientHello<'_> {
/// Information about a cipher.
pub struct SslCipher(*mut ffi::SSL_CIPHER);

impl Stackable for SslCipher {
type StackType = ffi::stack_st_SSL_CIPHER;
}

unsafe impl ForeignType for SslCipher {
type CType = ffi::SSL_CIPHER;
type Ref = SslCipherRef;
Expand Down
50 changes: 50 additions & 0 deletions boring/src/ssl/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ use crate::ssl::{
use crate::x509::verify::X509CheckFlags;
use crate::x509::{X509Name, X509};

#[cfg(feature = "fips-link-precompiled")]
use super::CompliancePolicy;

mod custom_verify;
mod private_key_method;
mod server;
Expand Down Expand Up @@ -917,6 +920,53 @@ fn server_set_default_curves_list() {
ssl.server_set_default_curves_list();
}

#[test]
#[cfg(feature = "fips-link-precompiled")]
fn test_set_compliance() {
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_compliance_policy(CompliancePolicy::FIPS_202205)
.unwrap();

assert_eq!(ctx.max_proto_version().unwrap(), SslVersion::TLS1_3);
assert_eq!(ctx.min_proto_version().unwrap(), SslVersion::TLS1_2);

const FIPS_CIPHERS: [&str; 4] = [
"ECDHE-ECDSA-AES128-GCM-SHA256",
"ECDHE-RSA-AES128-GCM-SHA256",
"ECDHE-ECDSA-AES256-GCM-SHA384",
"ECDHE-RSA-AES256-GCM-SHA384",
];

let ciphers = ctx.get_ciphers().unwrap();
assert_eq!(ciphers.len(), FIPS_CIPHERS.len());

for cipher in ciphers.into_iter().zip(FIPS_CIPHERS) {
assert_eq!(cipher.0.name(), cipher.1)
}

let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_compliance_policy(CompliancePolicy::WPA3_192_202304)
.unwrap();

assert_eq!(ctx.max_proto_version().unwrap(), SslVersion::TLS1_3);
assert_eq!(ctx.min_proto_version().unwrap(), SslVersion::TLS1_2);

const WPA3_192_CIPHERS: [&str; 2] = [
"ECDHE-ECDSA-AES256-GCM-SHA384",
"ECDHE-RSA-AES256-GCM-SHA384",
];

let ciphers = ctx.get_ciphers().unwrap();
assert_eq!(ciphers.len(), WPA3_192_CIPHERS.len());

for cipher in ciphers.into_iter().zip(WPA3_192_CIPHERS) {
assert_eq!(cipher.0.name(), cipher.1)
}

ctx.set_compliance_policy(CompliancePolicy::NONE)
.expect_err("Testing expect err if set compliance policy to NONE");
}

#[test]
fn drop_ex_data_in_context() {
let index = SslContext::new_ex_index::<&'static str>().unwrap();
Expand Down

0 comments on commit 576967c

Please sign in to comment.