Skip to content

Commit

Permalink
add integration test examples
Browse files Browse the repository at this point in the history
  • Loading branch information
jmayclin committed Oct 16, 2024
1 parent 471e9a7 commit 43c5fc5
Show file tree
Hide file tree
Showing 12 changed files with 383 additions and 25 deletions.
4 changes: 3 additions & 1 deletion bindings/rust/bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
[features]
default = ["rustls", "openssl"]
rustls = ["dep:rustls", "rustls-pemfile"]
openssl = ["dep:openssl"]
openssl = ["dep:openssl", "dep:openssl-sys"]
memory = ["plotters", "crabgrind", "structopt"]
historical-perf = ["plotters", "serde_json", "semver"]

Expand All @@ -18,10 +18,12 @@ strum = { version = "0.25", features = ["derive"] }
rustls = { version = "0.23", optional = true }
rustls-pemfile = { version = "2", optional = true }
openssl = { version = "0.10", features = ["vendored"], optional = true }
openssl-sys = { version = "0.9", features = ["vendored"], optional = true }
crabgrind = { version = "0.1", optional = true }
structopt = { version = "0.3", optional = true }
serde_json = { version = "1.0", optional = true }
semver = { version = "1.0", optional = true }
foreign-types-shared = "0.1.1"

[dependencies.plotters]
version = "0.3"
Expand Down
2 changes: 1 addition & 1 deletion bindings/rust/bench/benches/handshake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn bench_handshake_for_library<T>(
kx_group: KXGroup,
sig_type: SigType,
) where
T: TlsConnection,
T: TlsConnection + 'static,
T::Config: TlsBenchConfig,
{
// make configs before benching to reuse
Expand Down
4 changes: 2 additions & 2 deletions bindings/rust/bench/benches/resumption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use criterion::{

fn bench_handshake_pair<T>(bench_group: &mut BenchmarkGroup<WallTime>, sig_type: SigType)
where
T: TlsConnection,
T: TlsConnection + 'static,
T::Config: TlsBenchConfig,
{
// generate all harnesses (TlsConnPair structs) beforehand so that benchmarks
Expand All @@ -38,7 +38,7 @@ where

fn bench_handshake_server_1rtt<T>(bench_group: &mut BenchmarkGroup<WallTime>, sig_type: SigType)
where
T: TlsConnection,
T: TlsConnection + 'static,
T::Config: TlsBenchConfig,
{
for handshake in [HandshakeType::Resumption, HandshakeType::ServerAuth] {
Expand Down
Empty file.
106 changes: 88 additions & 18 deletions bindings/rust/bench/src/harness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ mod io;
pub use io::{LocalDataBuffer, ViewIO};

use io::TestPairIO;
use std::{
error::Error,
fmt::Debug,
fs::read_to_string,
rc::Rc,
};
use std::{error::Error, fmt::Debug, fs::read_to_string, rc::Rc};
use strum::EnumIter;

#[derive(Clone, Copy, EnumIter)]
Expand Down Expand Up @@ -184,8 +179,57 @@ pub trait TlsConnection: Sized {
fn recv(&mut self, data: &mut [u8]) -> Result<(), Box<dyn Error>>;
}

pub trait TlsConnIo {
/// Run one handshake step: receive msgs from other connection, process, and send new msgs
fn handshake(&mut self) -> Result<(), Box<dyn Error>>;

fn handshake_completed(&self) -> bool;

/// Send application data to ConnectedBuffer
fn send(&mut self, data: &[u8]) -> Result<(), Box<dyn Error>>;

/// Read application data from ConnectedBuffer
fn recv(&mut self, data: &mut [u8]) -> Result<(), Box<dyn Error>>;
}

impl TlsConnIo for Box<dyn TlsConnIo + 'static> {
fn handshake(&mut self) -> Result<(), Box<dyn Error>> {
self.handshake()
}

fn handshake_completed(&self) -> bool {
self.handshake_completed()
}

fn send(&mut self, data: &[u8]) -> Result<(), Box<dyn Error>> {
self.send(data)
}

fn recv(&mut self, data: &mut [u8]) -> Result<(), Box<dyn Error>> {
self.recv(data)
}
}

impl<T: TlsConnection> TlsConnIo for T {
fn handshake(&mut self) -> Result<(), Box<dyn Error>> {
self.handshake()
}

fn handshake_completed(&self) -> bool {
self.handshake_completed()
}

fn send(&mut self, data: &[u8]) -> Result<(), Box<dyn Error>> {
self.send(data)
}

fn recv(&mut self, data: &mut [u8]) -> Result<(), Box<dyn Error>> {
self.recv(data)
}
}

/// A TlsConnPair owns the client and server tls connections along with the IO buffers.
pub struct TlsConnPair<C: TlsConnection, S: TlsConnection> {
pub struct TlsConnPair<C, S> {
pub client: C,
pub server: S,
pub io: TestPairIO,
Expand Down Expand Up @@ -270,6 +314,42 @@ where
(self.client, self.server)
}

pub fn get_negotiated_cipher_suite(&self) -> CipherSuite {
assert!(self.handshake_completed());
assert!(
self.client.get_negotiated_cipher_suite() == self.server.get_negotiated_cipher_suite()
);
self.client.get_negotiated_cipher_suite()
}

pub fn negotiated_tls13(&self) -> bool {
self.client.negotiated_tls13() && self.server.negotiated_tls13()
}
}

impl<C, S> TlsConnPair<C, S>
where
C: TlsConnIo + 'static,
S: TlsConnIo + 'static,
{
pub fn type_erase(self) -> TlsConnPair<Box<dyn TlsConnIo + 'static>, Box<dyn TlsConnIo + 'static>> {
let TlsConnPair { client, server, io } = self;
let boxed_client = Box::new(client);
let boxed_server = Box::new(server);
TlsConnPair { client: boxed_client, server: boxed_server, io: io }
}
}

impl<C, S> TlsConnPair<C, S>
where
C: TlsConnIo,
S: TlsConnIo,
{

// pub fn type_erase(self) -> TlsConnPair<Box<dyn TlsConnection>, Box<dyn TlsConnection>> {

// }

/// Run handshake on connections
/// Two round trips are needed for the server to receive the Finished message
/// from the client and be ready to send data
Expand All @@ -287,17 +367,6 @@ where
self.client.handshake_completed() && self.server.handshake_completed()
}

pub fn get_negotiated_cipher_suite(&self) -> CipherSuite {
assert!(self.handshake_completed());
assert!(
self.client.get_negotiated_cipher_suite() == self.server.get_negotiated_cipher_suite()
);
self.client.get_negotiated_cipher_suite()
}

pub fn negotiated_tls13(&self) -> bool {
self.client.negotiated_tls13() && self.server.negotiated_tls13()
}

/// Send data from client to server, and then from server to client
pub fn round_trip_transfer(&mut self, data: &mut [u8]) -> Result<(), Box<dyn Error>> {
Expand All @@ -313,6 +382,7 @@ where
}
}


#[cfg(test)]
mod tests {
use super::*;
Expand Down
8 changes: 8 additions & 0 deletions bindings/rust/bench/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@
pub mod harness;
#[cfg(feature = "openssl")]
pub mod openssl;
#[cfg(feature = "openssl")]
pub mod openssl_extension;
#[cfg(feature = "rustls")]
pub mod rustls;
pub mod s2n_tls;
// Although these are integration tests, we deliberately avoid the "integration"
// provided in the default repo setup, because it will run tests in serial rather
// than parallel/
// https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html
#[cfg(test)]
mod tests;

#[cfg(feature = "openssl")]
pub use crate::openssl::OpenSslConnection;
Expand Down
2 changes: 1 addition & 1 deletion bindings/rust/bench/src/openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl Drop for OpenSslConnection {
}

pub struct OpenSslConfig {
config: SslContext,
pub config: SslContext,
session_ticket_storage: SessionTicketStorage,
}

Expand Down
48 changes: 48 additions & 0 deletions bindings/rust/bench/src/openssl_extension.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! This module defines "extension" trait to add our own bindings to the openssl
//! crate. Ideally all of this logic would live _in_ the openssl crate, but they
//! don't really accept PRs
//! - add signature type retrieval functions: https://github.com/sfackler/rust-openssl/pull/2164
//! - Add helper to return &mut SslRef from stream: https://github.com/sfackler/rust-openssl/pull/2223

// # define SSL_CTX_set_max_send_fragment(ctx,m) \
// SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)

use std::ffi::c_long;

use openssl::ssl::SslContext;
use openssl_sys::SSL_CTX;

// very tediously, we need to import exactly the same verion of ForeignType as
// ossl because we need this trait impl to access the raw pointers on all of the
// openssl types.
use foreign_types_shared::ForeignType;

// expose the macro as a function
fn SSL_CTX_set_max_send_fragment(ctx: *mut SSL_CTX, m: c_long) -> c_long {
// # define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52
const SSL_CTRL_SET_MAX_SEND_FRAGMENT: std::ffi::c_int = 52;

// TODO: assert on the return value
unsafe {openssl_sys::SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_SEND_FRAGMENT, m, std::ptr::null_mut())}
}

extern "C" {
// int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);
pub fn SSL_CTX_set_block_padding(ctx: *mut SSL_CTX, block_size: usize) -> std::ffi::c_int;
}

pub trait SslContextExtension {
fn set_max_send_fragment(&mut self, max_send_fragment: usize);

fn set_block_padding(&mut self, block_size: usize);
}

impl SslContextExtension for SslContext {
fn set_max_send_fragment(&mut self, max_send_fragment: usize) {
SSL_CTX_set_max_send_fragment(self.as_ptr(), max_send_fragment as _);
}

fn set_block_padding(&mut self, block_size: usize) {
unsafe {SSL_CTX_set_block_padding(self.as_ptr(), block_size as _);}
}
}
4 changes: 2 additions & 2 deletions bindings/rust/bench/src/s2n_tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const KEY_VALUE: [u8; 16] = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3];
/// s2n-tls has mode-independent configs, so this struct wraps the config with the mode
pub struct S2NConfig {
mode: Mode,
config: s2n_tls::config::Config,
pub config: s2n_tls::config::Config,
ticket_storage: SessionTicketStorage,
}

Expand Down Expand Up @@ -152,7 +152,7 @@ impl crate::harness::TlsBenchConfig for S2NConfig {
}

pub struct S2NConnection {
connection: Connection,
pub connection: Connection,
handshake_completed: bool,
}

Expand Down
Loading

0 comments on commit 43c5fc5

Please sign in to comment.