Skip to content

Commit

Permalink
Use features to set default key exchange preferences
Browse files Browse the repository at this point in the history
Overwrite boringSSL's default key exchange preferences with safe
defaults using feature flags:

* "kx-pq-supported" enables support for PQ key exchange algorithms by
  default. Classical key exchange is still preferred, but will be
  upgraded to PQ if requested.

* "kx-pq-preferred"  enables preference for PQ key exchange by default,
  with fallback to classical key exchange if requested.

* "kx-fips-required" disables non-FIPS-compliant algorithms by default.
  • Loading branch information
cjpatton committed Aug 15, 2023
1 parent a6e35a4 commit d70dbb9
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 14 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ boring = { version = "3", path = "./boring" }
tokio-boring = { version = "3", path = "./tokio-boring" }

bindgen = { version = "0.66.1", default-features = false, features = ["runtime"] }
cfg-if = "1.0.0"
cmake = "0.1"
fs_extra = "1.3.0"
fslock = "0.2"
Expand Down
6 changes: 5 additions & 1 deletion boring-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ fips-link-precompiled = ["fips"]
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
rpk = []

# Enables experimental post-quantum crypto (https://blog.cloudflare.com/post-quantum-for-all/)
# Applies a patch (`patches/boring-pq.patch`) to the boringSSL source code that
# enables support for PQ key exchange. This feature is necessary in order to
# compile the bindings for the default branch of boringSSL (`deps/boringssl`).
# Alternatively, a version of boringSSL that implements the same feature set
# can be provided by setting `BORING_BSSL_SOURCE_PATH`.
pq-experimental = []

[build-dependencies]
Expand Down
21 changes: 20 additions & 1 deletion boring/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,30 @@ fips-link-precompiled = ["fips", "boring-sys/fips-link-precompiled"]
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
rpk = ["boring-sys/rpk"]

# Enables experimental post-quantum crypto (https://blog.cloudflare.com/post-quantum-for-all/)
# Applies a patch to the boringSSL source code that enables support for PQ key
# exchange. 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_SOURCE_PATH`.
pq-experimental = ["boring-sys/pq-experimental"]

# Support PQ key exchange by default. The client will prefer classical key
# exchange, but will upgrade to PQ key exchange if requested by the server.
# This is the safest option if you don't know if the peer supports PQ key
# exchange.
kx-pq-supported = []

# Prefer PQ key exchange by default. The client will prefer PQ exchange, but
# fallback to classical key exchange if requested by the server. This is the
# best option if you know the peer supports PQ key exchange.
kx-pq-preferred = ["kx-pq-supported"]

# Disable non-FIPS key exchange algorithms by default.
kx-fips-required = []

[dependencies]
bitflags = { workspace = true }
cfg-if = { workspace = true }
foreign-types = { workspace = true }
once_cell = { workspace = true }
libc = { workspace = true }
Expand Down
61 changes: 49 additions & 12 deletions boring/src/ssl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,13 +633,13 @@ impl SslCurve {
#[cfg(not(feature = "fips"))]
pub const X25519_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::NID_X25519Kyber768Draft00);

#[cfg(feature = "pq-experimental")]
#[cfg(feature = "kx-pq-supported")]
pub const X25519_KYBER768_DRAFT00_OLD: SslCurve = SslCurve(ffi::NID_X25519Kyber768Draft00Old);

#[cfg(feature = "pq-experimental")]
#[cfg(feature = "kx-pq-supported")]
pub const X25519_KYBER512_DRAFT00: SslCurve = SslCurve(ffi::NID_X25519Kyber512Draft00);

#[cfg(feature = "pq-experimental")]
#[cfg(feature = "kx-pq-supported")]
pub const P256_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::NID_P256Kyber768Draft00);
}

Expand Down Expand Up @@ -696,16 +696,20 @@ pub struct SslContextBuilder {
impl SslContextBuilder {
/// Creates a new `SslContextBuilder` to be used with Raw Public Key.
///
/// This corresponds to [`SSL_CTX_new`].
/// This corresponds to calling [`SSL_CTX_new`] then overwriting the default key exchange and
/// cipher preferences. The defaults are only overwritten if certain feature flags are set.
///
/// [`SSL_CTX_new`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_new.html
pub fn new_rpk() -> Result<SslContextBuilder, ErrorStack> {
unsafe {
let mut ctx = unsafe {
init();
let ctx = cvt_p(ffi::SSL_CTX_new(SslMethod::tls_with_buffer().as_ptr()))?;

Ok(SslContextBuilder::from_ptr(ctx, true))
}
SslContextBuilder::from_ptr(ctx, true)
};

ctx.set_safe_defaults()?;
Ok(ctx)
}

/// Sets raw public key certificate in DER format.
Expand Down Expand Up @@ -739,24 +743,28 @@ impl SslContextBuilder {
impl SslContextBuilder {
/// Creates a new `SslContextBuilder`.
///
/// This corresponds to [`SSL_CTX_new`].
/// This corresponds to calling [`SSL_CTX_new`] then overwriting the default key exchange and
/// cipher preferences. The defaults are only overwritten if certain feature flags are set.
///
/// [`SSL_CTX_new`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_new.html
pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
unsafe {
let mut ctx = unsafe {
init();
let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;

#[cfg(feature = "rpk")]
{
Ok(SslContextBuilder::from_ptr(ctx, false))
SslContextBuilder::from_ptr(ctx, false)
}

#[cfg(not(feature = "rpk"))]
{
Ok(SslContextBuilder::from_ptr(ctx))
SslContextBuilder::from_ptr(ctx)
}
}
};

ctx.set_safe_defaults()?;
Ok(ctx)
}

/// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value.
Expand Down Expand Up @@ -1707,6 +1715,35 @@ impl SslContextBuilder {
}
}

fn set_safe_defaults(&mut self) -> Result<(), ErrorStack> {
// Set default key exchange preferences.
cfg_if::cfg_if! {
if #[cfg(feature = "kx-pq-preferred")] {
self.set_curves(&[
#[cfg(not(feature = "kx-fips-required"))]
SslCurve::X25519_KYBER512_DRAFT00,
SslCurve::P256_KYBER768_DRAFT00,
#[cfg(not(feature = "kx-fips-required"))]
SslCurve::X25519,
SslCurve::SECP256R1,
SslCurve::SECP384R1,
])?;
} else if #[cfg(feature = "kx-pq-supported")] {
self.set_curves(&[
#[cfg(not(feature = "kx-fips-required"))]
SslCurve::X25519,
SslCurve::SECP256R1,
SslCurve::SECP384R1,
#[cfg(not(feature = "kx-fips-required"))]
SslCurve::X25519_KYBER512_DRAFT00,
SslCurve::P256_KYBER768_DRAFT00,
])?;
}
}

Ok(())
}

/// Consumes the builder, returning a new `SslContext`.
pub fn build(self) -> SslContext {
self.ctx
Expand Down

0 comments on commit d70dbb9

Please sign in to comment.