Skip to content

Commit

Permalink
feat(bench): add mTLS to benchmarks (#4079)
Browse files Browse the repository at this point in the history
  • Loading branch information
tinzh authored Jul 10, 2023
1 parent dce91ac commit e0fd532
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 91 deletions.
2 changes: 1 addition & 1 deletion bindings/rust/bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ All certs are stored in `certs/` and can be regenerated using `certs/generate_ce

### Negotiation parameters

The cipher suites benchmarked are `TLS_AES_128_GCM_SHA256` and `TLS_AES_256_GCM_SHA384`, and the key exchange methods benchmarked are ECDHE with `secp256r1` and with `x25519`.
The cipher suites benchmarked are `TLS_AES_128_GCM_SHA256` and `TLS_AES_256_GCM_SHA384`, and the key exchange methods benchmarked are ECDHE with `secp256r1` and with `x25519`. We also test connections with and without client authentication (mTLS).
41 changes: 28 additions & 13 deletions bindings/rust/bench/benches/handshake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,31 @@
use std::any::type_name;

use bench::{
CipherSuite::*,
CryptoConfig,
ECGroup::{self, *},
HandshakeType::{self, *},
OpenSslHarness, RustlsHarness, S2NHarness, TlsBenchHarness,
};
use criterion::{
criterion_group, criterion_main, measurement::WallTime, BatchSize, BenchmarkGroup, Criterion,
};

pub fn bench_handshake_key_exchange(c: &mut Criterion) {
pub fn bench_handshake_params(c: &mut Criterion) {
fn bench_handshake_for_library<T: TlsBenchHarness>(
bench_group: &mut BenchmarkGroup<WallTime>,
ec_group: &ECGroup,
handshake_type: HandshakeType,
ec_group: ECGroup,
) {
bench_group.bench_function(type_name::<T>(), |b| {
b.iter_batched_ref(
|| {
T::new(&CryptoConfig {
cipher_suite: AES_128_GCM_SHA256,
ec_group: *ec_group,
})
T::new(
CryptoConfig {
cipher_suite: Default::default(),
ec_group,
},
handshake_type,
)
.unwrap()
},
|harness| {
Expand All @@ -35,13 +39,24 @@ pub fn bench_handshake_key_exchange(c: &mut Criterion) {
});
}

for ec_group in [SECP256R1, X25519] {
let mut bench_group = c.benchmark_group(format!("handshake-{:?}", ec_group));
bench_handshake_for_library::<S2NHarness>(&mut bench_group, &ec_group);
bench_handshake_for_library::<RustlsHarness>(&mut bench_group, &ec_group);
bench_handshake_for_library::<OpenSslHarness>(&mut bench_group, &ec_group);
for handshake_type in [ServerAuth, MutualAuth] {
for ec_group in [SECP256R1, X25519] {
let mut bench_group =
c.benchmark_group(format!("handshake-{:?}-{:?}", handshake_type, ec_group));
bench_handshake_for_library::<S2NHarness>(&mut bench_group, handshake_type, ec_group);
bench_handshake_for_library::<RustlsHarness>(
&mut bench_group,
handshake_type,
ec_group,
);
bench_handshake_for_library::<OpenSslHarness>(
&mut bench_group,
handshake_type,
ec_group,
);
}
}
}

criterion_group!(benches, bench_handshake_key_exchange);
criterion_group!(benches, bench_handshake_params);
criterion_main!(benches);
44 changes: 44 additions & 0 deletions bindings/rust/bench/certs/client-fullchain.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
-----BEGIN CERTIFICATE-----
MIIDuzCCAqOgAwIBAgIUNCurbgaG3FFx/oedAfC+QM7PJI4wDQYJKoZIhvcNAQEL
BQAwgYkxCzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVDaGliYTETMBEGA1UEBwwKQ2hp
YmEgQ2l0eTEYMBYGA1UECgwPVGVzc2llci1Bc2hwb29sMRgwFgYDVQQDDA9kZXZl
bG9wLmxvY2FsY2ExITAfBgkqhkiG9w0BCQEWEmNhQGRldmVsb3AubG9jYWxjYTAg
Fw0yMzA2MDkxNzI1MDJaGA8yMjAyMTExNDE3MjUwMlowYDELMAkGA1UEBhMCVVMx
EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxDzANBgNVBAoM
BmNsaWVudDEZMBcGA1UEAwwQY2xpZW50LmxvY2FsaG9zdDB2MBAGByqGSM49AgEG
BSuBBAAiA2IABPCBEz2mGh83HkcxVHCZeKnQnl4RcJI4kznhAMSGRrFl9yEkbypf
wrOCTwytVQDn9ZLFR8BRWAlOQvaC7lYN0nVtA0dHpLJEATilvRzf3a4QUznh8Rbp
svRRUvOXoXWTM6OB7jCB6zAUBgNVHREEDTALgglsb2NhbGhvc3QwHQYDVR0OBBYE
FAEG/BipFATRiCJUrQTLvrrsxwHMMIGzBgNVHSMEgaswgaihgY+kgYwwgYkxCzAJ
BgNVBAYTAkpQMQ4wDAYDVQQIDAVDaGliYTETMBEGA1UEBwwKQ2hpYmEgQ2l0eTEY
MBYGA1UECgwPVGVzc2llci1Bc2hwb29sMRgwFgYDVQQDDA9kZXZlbG9wLmxvY2Fs
Y2ExITAfBgkqhkiG9w0BCQEWEmNhQGRldmVsb3AubG9jYWxjYYIUd3XGeEtpUSwl
UMjPQ8cfWZyVs+4wDQYJKoZIhvcNAQELBQADggEBAKsuZKK0mBcop0ZakO5tS8pm
5BLqymrC3yhEoEKTS6Tf6ek+Fr/++3bIiFeU1+X84Pd6/cfHRZp1RHykDPiLZy5S
xNZr+wsg1Dkx3GT521c/wievUTrqZ0G5/CK5On2jC5ytFHuARF9XNqYM/WhvSHN0
q/ZLUBqyOOGUsQ5BHatgPuEKXp3n7Qp0yW4Wy/s16f3jRi4KCbGAQC+Q64OXzBzr
rFMNGrLHJrusv4TIKQ/UR5A4JLuRChk1UdxlErowyID4UOOyzHroK73dFmwg/jGu
65miqd2SX8KcKC2Jiq+YCAnzIpuigiyz0EgFAV/pdUZB1qP3hEwb4hJItz3vyAo=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDnTCCAoUCFHd1xnhLaVEsJVDIz0PHH1mclbPuMA0GCSqGSIb3DQEBCwUAMIGJ
MQswCQYDVQQGEwJKUDEOMAwGA1UECAwFQ2hpYmExEzARBgNVBAcMCkNoaWJhIENp
dHkxGDAWBgNVBAoMD1Rlc3NpZXItQXNocG9vbDEYMBYGA1UEAwwPZGV2ZWxvcC5s
b2NhbGNhMSEwHwYJKoZIhvcNAQkBFhJjYUBkZXZlbG9wLmxvY2FsY2EwIBcNMjMw
NjA5MTcyNTAyWhgPMjIwMjExMTQxNzI1MDJaMIGJMQswCQYDVQQGEwJKUDEOMAwG
A1UECAwFQ2hpYmExEzARBgNVBAcMCkNoaWJhIENpdHkxGDAWBgNVBAoMD1Rlc3Np
ZXItQXNocG9vbDEYMBYGA1UEAwwPZGV2ZWxvcC5sb2NhbGNhMSEwHwYJKoZIhvcN
AQkBFhJjYUBkZXZlbG9wLmxvY2FsY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQDII4MvapIuBLmDoIn/jeu9xeHqw8vUiPZecg4azweLv6B/QKKQSAXF
bQA2JVCSHF7gxjHDvOFG3+Kx/RV74hKjHlp2yVMskW1r4e6WCC+duIBgR2y7xfaM
7C5XKt6DuSexHECmUiU9cG2ZRP8lx8Wclvet9Ob+iP+sx3xQJ8Y0NtLjeo5UCV5X
CAAVBUHLTypRNSsU6LFxkRjs2JxdjGLG98+ih4VNfc5lUXBJzcrCSLErnaIhvxcz
X6myHd57eCYsWEsukuGcY+59rgPkxDofK+G/PwMOMVjYeQ1HoR/Ms9+mgN88Udcm
d9IXCKZh1dmqbBZMOXZi5fjaViO8xhe1AgMBAAEwDQYJKoZIhvcNAQELBQADggEB
AKA3FgjF97cFyT0EfZfJag3g5sSq1NLqGuAvmtgaUhdqRT2vo5Uuaj+ZqxmFvEll
tb9zeQgaPksyW+wZ+Lg46qYHhwuInycqke6Sa4FKlQrydThoF9tM1zQtnJqzdX1s
gcm731nR2O3lYsrfNRasOeB11rk4a14cJRwWk57d8qt/nLwmPMt9dc4IsCmqQw6l
s0f49lX/PmEenAaO5hfVI7XcasT260L4/NlFA2HzrbGdO+o2aCrSfA5+Qt0PMsjZ
H2P+1/JefgRyMDG8hk0ev2aoqkGBvZrSJyCI/+EZoJRuS1qPI3S+kHGXkJ3tF4i+
IeTBeNaFh9ayc/UoUPyved0=
-----END CERTIFICATE-----
8 changes: 7 additions & 1 deletion bindings/rust/bench/certs/generate_certs.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#!/bin/bash

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

# immediately bail if any command fails
set -e

Expand Down Expand Up @@ -25,7 +30,8 @@ echo "verifying generated certificates"
openssl verify -CAfile ca-cert.pem server-cert.pem
openssl verify -CAfile ca-cert.pem client-cert.pem

cat server-cert.pem ca-cert.pem > fullchain.pem
cat server-cert.pem ca-cert.pem > server-fullchain.pem
cat client-cert.pem ca-cert.pem > client-fullchain.pem

echo "cleaning up temporary files"
rm server.csr
Expand Down
File renamed without changes.
63 changes: 35 additions & 28 deletions bindings/rust/bench/src/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,37 @@ pub fn read_to_bytes(path: &str) -> Vec<u8> {
read_to_string(path).unwrap().into_bytes()
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {
Client,
Server,
}

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum HandshakeType {
#[default]
ServerAuth,
MutualAuth,
}

// these parameters were the only ones readily usable for all three libaries:
// s2n-tls, rustls, and openssl
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum CipherSuite {
#[default]
AES_128_GCM_SHA256,
AES_256_GCM_SHA384,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum ECGroup {
SECP256R1,
#[default]
X25519,
}

#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct CryptoConfig {
pub cipher_suite: CipherSuite,
pub ec_group: ECGroup,
Expand All @@ -43,14 +53,14 @@ pub struct CryptoConfig {
pub trait TlsBenchHarness: Sized {
/// Default harness
fn default() -> Result<Self, Box<dyn Error>> {
Self::new(&CryptoConfig {
cipher_suite: CipherSuite::AES_128_GCM_SHA256,
ec_group: ECGroup::X25519,
})
Self::new(Default::default(), Default::default())
}

/// Initialize buffers, configs, and connections (pre-handshake)
fn new(crypto_config: &CryptoConfig) -> Result<Self, Box<dyn Error>>;
fn new(
crypto_config: CryptoConfig,
handshake_type: HandshakeType,
) -> Result<Self, Box<dyn Error>>;

/// Run handshake on initialized connection
/// Returns error if handshake has already completed
Expand Down Expand Up @@ -118,28 +128,25 @@ macro_rules! test_tls_bench_harnesses {
$(
mod $lib_name {
use super::*;
use CipherSuite::*;
use ECGroup::*;
use HandshakeType::*;

#[test]
fn test_handshake() {
let mut harness = <$harness_type>::default().unwrap();
assert!(!harness.handshake_completed());
harness.handshake().unwrap();
assert!(harness.handshake_completed());
assert!(harness.negotiated_tls13());
}

#[test]
fn test_different_crypto_config() {
use CipherSuite::*;
use ECGroup::*;

let (mut harness, mut crypto_config);
for cipher_suite in [AES_128_GCM_SHA256, AES_256_GCM_SHA384].iter() {
for ec_group in [SECP256R1, X25519].iter() {
crypto_config = CryptoConfig { cipher_suite: cipher_suite.clone(), ec_group: ec_group.clone() };
harness = <$harness_type>::new(&crypto_config).unwrap();
harness.handshake().unwrap();
assert_eq!(cipher_suite, &harness.get_negotiated_cipher_suite());
fn test_handshake_config() {
for handshake_type in [ServerAuth, MutualAuth] {
for cipher_suite in [AES_128_GCM_SHA256, AES_256_GCM_SHA384] {
for ec_group in [SECP256R1, X25519] {
let crypto_config = CryptoConfig { cipher_suite: cipher_suite.clone(), ec_group: ec_group.clone() };
let mut harness = <$harness_type>::new(crypto_config, handshake_type).unwrap();

assert!(!harness.handshake_completed());
harness.handshake().unwrap();
assert!(harness.handshake_completed());

assert!(harness.negotiated_tls13());
assert_eq!(cipher_suite, harness.get_negotiated_cipher_suite());
}
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions bindings/rust/bench/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ pub mod openssl;
pub mod rustls;
pub mod s2n_tls;
pub use crate::{
harness::{CipherSuite, CryptoConfig, ECGroup, TlsBenchHarness},
harness::{CipherSuite, CryptoConfig, ECGroup, HandshakeType, TlsBenchHarness},
openssl::OpenSslHarness,
rustls::RustlsHarness,
s2n_tls::S2NHarness,
};

const SERVER_KEY_PATH: &str = "certs/server-key.pem";
const SERVER_CERT_CHAIN_PATH: &str = "certs/fullchain.pem";
const SERVER_CERT_CHAIN_PATH: &str = "certs/server-fullchain.pem";
const CLIENT_KEY_PATH: &str = "certs/client-key.pem";
const CLIENT_CERT_CHAIN_PATH: &str = "certs/client-fullchain.pem";
const CA_CERT_PATH: &str = "certs/ca-cert.pem";

#[cfg(test)]
Expand All @@ -24,6 +26,8 @@ mod tests {
fn cert_paths_valid() {
assert!(Path::new(crate::SERVER_KEY_PATH).exists());
assert!(Path::new(crate::SERVER_CERT_CHAIN_PATH).exists());
assert!(Path::new(crate::CLIENT_KEY_PATH).exists());
assert!(Path::new(crate::CLIENT_CERT_CHAIN_PATH).exists());
assert!(Path::new(crate::CA_CERT_PATH).exists());
}
}
21 changes: 17 additions & 4 deletions bindings/rust/bench/src/openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
harness::{CipherSuite, ConnectedBuffer, CryptoConfig, ECGroup, Mode, TlsBenchHarness},
CA_CERT_PATH, SERVER_CERT_CHAIN_PATH, SERVER_KEY_PATH,
harness::{
CipherSuite, ConnectedBuffer, CryptoConfig, ECGroup, HandshakeType, Mode, TlsBenchHarness,
},
CA_CERT_PATH, CLIENT_CERT_CHAIN_PATH, CLIENT_KEY_PATH, SERVER_CERT_CHAIN_PATH, SERVER_KEY_PATH,
};
use openssl::ssl::{
ErrorCode, Ssl, SslContext, SslContextBuilder, SslFiletype, SslMethod, SslStream, SslVersion,
ErrorCode, Ssl, SslContext, SslContextBuilder, SslFiletype, SslMethod, SslStream,
SslVerifyMode, SslVersion,
};
use std::error::Error;

Expand Down Expand Up @@ -46,7 +49,10 @@ impl OpenSslHarness {
}

impl TlsBenchHarness for OpenSslHarness {
fn new(crypto_config: &CryptoConfig) -> Result<Self, Box<dyn Error>> {
fn new(
crypto_config: CryptoConfig,
handshake_type: HandshakeType,
) -> Result<Self, Box<dyn Error>> {
let client_buf = ConnectedBuffer::new();
let server_buf = client_buf.clone_inverse();

Expand All @@ -69,6 +75,13 @@ impl TlsBenchHarness for OpenSslHarness {
server_builder.set_private_key_file(SERVER_KEY_PATH, SslFiletype::PEM)?;
Self::common_config(&mut server_builder, cipher_suite, ec_key)?;

if handshake_type == HandshakeType::MutualAuth {
client_builder.set_certificate_chain_file(CLIENT_CERT_CHAIN_PATH)?;
client_builder.set_private_key_file(CLIENT_KEY_PATH, SslFiletype::PEM)?;
server_builder.set_ca_file(CA_CERT_PATH)?;
server_builder.set_verify(SslVerifyMode::FAIL_IF_NO_PEER_CERT | SslVerifyMode::PEER);
}

let client_config = client_builder.build();
let server_config = server_builder.build();

Expand Down
Loading

0 comments on commit e0fd532

Please sign in to comment.