Add support for OpenSSL (#1436)

Signed-off-by: Ted Poole <tpoole@redhat.com>
This commit is contained in:
Ted Poole 2025-02-27 19:36:31 +00:00 committed by GitHub
parent 5532e0dcc9
commit e52cc43c88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 146 additions and 10 deletions

78
Cargo.lock generated
View File

@ -348,7 +348,7 @@ checksum = "3e10058cf3b10c9eca798177ac6ee3c895c7312d094618de60a2bb6f2698f25f"
dependencies = [
"bitflags 2.8.0",
"boring-sys",
"foreign-types",
"foreign-types 0.5.0",
"libc",
"openssl-macros",
]
@ -361,7 +361,7 @@ dependencies = [
"aead",
"boring",
"boring-sys",
"foreign-types",
"foreign-types 0.5.0",
]
[[package]]
@ -374,7 +374,7 @@ dependencies = [
"boring-additions",
"boring-sys",
"boring-sys-additions",
"foreign-types",
"foreign-types 0.5.0",
"lazy_static",
"once_cell",
"rustls",
@ -975,6 +975,15 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared 0.1.1",
]
[[package]]
name = "foreign-types"
version = "0.5.0"
@ -982,7 +991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [
"foreign-types-macros",
"foreign-types-shared",
"foreign-types-shared 0.3.1",
]
[[package]]
@ -996,6 +1005,12 @@ dependencies = [
"syn 2.0.98",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "foreign-types-shared"
version = "0.3.1"
@ -2171,6 +2186,21 @@ version = "11.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
[[package]]
name = "openssl"
version = "0.10.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
dependencies = [
"bitflags 2.8.0",
"cfg-if",
"foreign-types 0.3.2",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
@ -2188,6 +2218,18 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
version = "0.9.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "overload"
version = "0.1.1"
@ -2309,6 +2351,12 @@ dependencies = [
"tokio",
]
[[package]]
name = "pkg-config"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "plotters"
version = "0.3.7"
@ -2849,6 +2897,20 @@ dependencies = [
"security-framework",
]
[[package]]
name = "rustls-openssl"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad6baac2596417ed1ac329842cc9ab22d90fbbc3c59612ecd74d783b1df26523"
dependencies = [
"foreign-types-shared 0.1.1",
"once_cell",
"openssl",
"openssl-sys",
"rustls",
"rustls-webpki",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
@ -3637,6 +3699,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.5"
@ -4205,6 +4273,7 @@ dependencies = [
"nix 0.29.0",
"oid-registry 0.8.1",
"once_cell",
"openssl",
"pin-project-lite",
"pingora-pool",
"ppp",
@ -4220,6 +4289,7 @@ dependencies = [
"rustc_version",
"rustls",
"rustls-native-certs",
"rustls-openssl",
"rustls-pemfile",
"serde",
"serde_json",

View File

@ -10,6 +10,7 @@ jemalloc = ["dep:tikv-jemallocator", "dep:jemalloc_pprof"]
tls-boring = ["dep:boring", "dep:boring-sys", "boring-rustls-provider/fips-only"]
tls-ring = ["dep:ring", "rustls/ring", "tokio-rustls/ring", "hyper-rustls/ring", "dep:rcgen"]
tls-aws-lc = ["dep:ring", "rustls/aws_lc_rs", "tokio-rustls/aws_lc_rs", "hyper-rustls/aws-lc-rs", "dep:rcgen", "rcgen/aws_lc_rs"]
tls-openssl = ["dep:rustls-openssl", "dep:openssl" ]
testing = ["dep:rcgen", "rcgen/x509-parser"] # Enables utilities supporting tests.
[lib]
@ -38,6 +39,10 @@ boring-sys = { version = "4", optional = true }
# Enabled with 'tls-ring'
ring = { version = "0.17", optional = true }
# Enabled with 'tls-openssl'
rustls-openssl = { version = "0.2", optional = true }
openssl = { version = "0.10", optional = true }
anyhow = "1.0"
async-stream = "0.3"
async-trait = "0.1"

View File

@ -5,6 +5,8 @@ ifeq ($(TLS_MODE), boring)
FEATURES:=--no-default-features -F tls-boring
else ifeq ($(TLS_MODE), aws-lc)
FEATURES:=--no-default-features -F tls-aws-lc
else ifeq ($(TLS_MODE), openssl)
FEATURES:=--no-default-features -F tls-openssl
endif
test:
@ -24,6 +26,7 @@ inpodserver:
check-features:
cargo check --no-default-features -F tls-boring
cargo check --no-default-features -F tls-aws-lc
cargo check --no-default-features -F tls-openssl
cargo check -F jemalloc
(cd fuzz; RUSTFLAGS="--cfg fuzzing" cargo check)

View File

@ -34,11 +34,12 @@ Ztunnel's TLS is built on [rustls](https://github.com/rustls/rustls).
Rustls has support for plugging in various crypto providers to meet various needs (compliance, performance, etc).
| Name | How To Enable |
|------------------------------------------------|-----------------------------------------------|
| [ring](https://github.com/briansmith/ring/) | Default (or `--features tls-ring`) |
| [boring](https://github.com/cloudflare/boring) | `--features tls-boring --no-default-features` |
| [aws-lc]https://github.com/aws/aws-lc-rs) | `--features tls-aws-lc --no-default-features` |
| Name | How To Enable |
|----------------------------------------------------|------------------------------------------------|
| [ring](https://github.com/briansmith/ring/) | Default (or `--features tls-ring`) |
| [boring](https://github.com/cloudflare/boring) | `--features tls-boring --no-default-features` |
| [aws-lc]https://github.com/aws/aws-lc-rs) | `--features tls-aws-lc --no-default-features` |
| [openssl](https://github.com/tofay/rustls-openssl) | `--features tls-openssl --no-default-features` |
In all options, only TLS 1.3 with cipher suites `TLS13_AES_256_GCM_SHA384` and `TLS13_AES_128_GCM_SHA256` is used.

View File

@ -4,7 +4,7 @@ targets = [
{ triple = "x86_64-unknown-linux-gnu" },
{ triple = "aarch64-unknown-linux-gnu" },
]
features = ["tls-boring", "tls-ring", "tls-aws-lc"]
features = ["tls-boring", "tls-ring", "tls-aws-lc", "tls-openssl" ]
[advisories]
version = 2

View File

@ -33,6 +33,8 @@ if [[ "$TLS_MODE" == "boring" ]]; then
cargo build --release --no-default-features -F tls-boring
elif [[ "$TLS_MODE" == "aws-lc" ]]; then
cargo build --release --no-default-features -F tls-aws-lc
elif [[ "$TLS_MODE" == "openssl" ]]; then
cargo build --release --no-default-features -F tls-openssl
else
cargo build --release
fi

View File

@ -53,6 +53,10 @@ pub enum Error {
#[cfg(feature = "tls-boring")]
SslError(#[from] boring::error::ErrorStack),
#[error("invalid operation: {0:?}")]
#[cfg(feature = "tls-openssl")]
SslError(#[from] openssl::error::ErrorStack),
#[error("invalid certificate generation: {0:?}")]
#[cfg(any(feature = "tls-ring", feature = "tls-aws-lc"))]
RcgenError(Arc<rcgen::Error>),

View File

@ -80,6 +80,45 @@ impl CsrOptions {
private_key: private_key.into(),
})
}
#[cfg(feature = "tls-openssl")]
pub fn generate(&self) -> Result<CertSign, Error> {
use openssl::ec::{EcGroup, EcKey};
use openssl::hash::MessageDigest;
use openssl::nid::Nid;
use openssl::pkey::PKey;
use openssl::stack::Stack;
use openssl::x509::extension::SubjectAlternativeName;
use openssl::x509::{self};
// TODO: https://github.com/rustls/rcgen/issues/228 can we always use rcgen?
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
let ec_key = EcKey::generate(&group)?;
let pkey = PKey::from_ec_key(ec_key)?;
let mut csr = x509::X509ReqBuilder::new()?;
csr.set_pubkey(&pkey)?;
let mut extensions = Stack::new()?;
let subject_alternative_name = SubjectAlternativeName::new()
.uri(&self.san)
.critical()
.build(&csr.x509v3_context(None))?;
extensions.push(subject_alternative_name)?;
csr.add_extensions(&extensions)?;
csr.sign(&pkey, MessageDigest::sha256())?;
let csr = csr.build();
let pkey_pem = pkey.private_key_to_pem_pkcs8()?;
let csr_pem = csr.to_pem()?;
let csr_pem = std::str::from_utf8(&csr_pem)
.expect("CSR is valid string")
.to_string();
Ok(CertSign {
csr: csr_pem,
private_key: pkey_pem,
})
}
}
#[cfg(test)]

View File

@ -78,6 +78,18 @@ pub(super) fn provider() -> Arc<CryptoProvider> {
})
}
#[cfg(feature = "tls-openssl")]
pub(super) fn provider() -> Arc<CryptoProvider> {
Arc::new(CryptoProvider {
// Limit to only the subset of ciphers that are FIPS compatible
cipher_suites: vec![
rustls_openssl::cipher_suite::TLS13_AES_256_GCM_SHA384,
rustls_openssl::cipher_suite::TLS13_AES_128_GCM_SHA256,
],
..rustls_openssl::default_provider()
})
}
#[derive(thiserror::Error, Debug)]
pub enum TlsError {
#[error("tls handshake error: {0:?}")]