From 6d2428946510cdc8690f3338ac22361ab48fe861 Mon Sep 17 00:00:00 2001 From: Doug Chapman <54039637+dougch@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:46:14 -0800 Subject: [PATCH 1/5] chore: fix GHA for merge-queue (#4973) --- .github/workflows/codeql.yml | 29 +++++++++++++++++++++++------ .github/workflows/regression_ci.yml | 7 ++++++- .github/workflows/usage_guide.yml | 3 +++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index babcab6dac7..7858994b8be 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -2,13 +2,9 @@ name: "CodeQL - Python" on: push: - branches: [ "main" ] - paths-ignore: - - '**/tests/integration/*' + branches: [main] pull_request: - branches: [ "main" ] - paths-ignore: - - '**/tests/integration/*' + branches: [main] schedule: - cron: "1 18 * * 0" merge_group: @@ -49,3 +45,24 @@ jobs: uses: github/codeql-action/analyze@v3 with: category: "/language:${{ matrix.language }}" + + # This is a very simple Action that will act as a substitute required status + # check for Code Scanning once you have merge-queue enabled. It will force + # Code Scanning to pass at the Pull Request and allow you to skip it in your + # repo's merge group. https://github.com/Eldrick19/code-scanning-status-checker + check_codeql_status: + name: Check CodeQL Status + needs: analyze + permissions: + contents: read + checks: read + pull-requests: read + runs-on: ubuntu-latest + if: ${{ github.event_name == 'pull_request' }} + steps: + - name: Check CodeQL Status + uses: eldrick19/code-scanning-status-checker@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + pr_number: ${{ github.event.pull_request.number }} + repo: ${{ github.repository }} \ No newline at end of file diff --git a/.github/workflows/regression_ci.yml b/.github/workflows/regression_ci.yml index d39b3aa3a6a..0ba35de94c8 100644 --- a/.github/workflows/regression_ci.yml +++ b/.github/workflows/regression_ci.yml @@ -3,16 +3,21 @@ name: Performance Regression Test on: + push: + branches: [main] pull_request: branches: - main paths-ignore: - tests/regression/** + merge_group: + types: [checks_requested] + branches: [main] jobs: regression-test: runs-on: ubuntu-latest - + if: ${{ github.event_name == 'pull_request' }} steps: # Checkout the code from the pull request branch - name: Checkout code diff --git a/.github/workflows/usage_guide.yml b/.github/workflows/usage_guide.yml index 23ed742dba1..ffe7d3ba39b 100644 --- a/.github/workflows/usage_guide.yml +++ b/.github/workflows/usage_guide.yml @@ -6,6 +6,9 @@ on: pull_request: branches: - main + merge_group: + types: [checks_requested] + branches: [main] env: CDN: https://d3fqnyekunr9xg.cloudfront.net From 142ef882de3cecbfc2246b787a38b5b40edc71d1 Mon Sep 17 00:00:00 2001 From: James Mayclin Date: Wed, 11 Dec 2024 18:14:04 -0800 Subject: [PATCH 2/5] chore(bindings): move tokio examples to dedicated folder (#4954) --- bindings/rust-examples/Cargo.toml | 2 +- .../certs/ca-cert.pem | 0 .../certs/generate.sh | 0 .../certs/kangaroo-chain.pem | 0 .../certs/kangaroo-key.pem | 0 .../certs/wombat-chain.pem | 0 .../certs/wombat-key.pem | 0 .../src/bin/client.rs | 3 ++- .../src/bin/server.rs | 8 ++++++-- .../rust-examples/tokio-server-client/Cargo.toml | 13 +++++++++++++ .../tokio-server-client/src/bin}/client.rs | 8 ++++---- .../tokio-server-client/src/bin}/server.rs | 4 ++-- bindings/rust/s2n-tls-tokio/Cargo.toml | 1 - 13 files changed, 28 insertions(+), 11 deletions(-) rename bindings/rust-examples/{client-hello-config-resolution => }/certs/ca-cert.pem (100%) rename bindings/rust-examples/{client-hello-config-resolution => }/certs/generate.sh (100%) rename bindings/rust-examples/{client-hello-config-resolution => }/certs/kangaroo-chain.pem (100%) rename bindings/rust-examples/{client-hello-config-resolution => }/certs/kangaroo-key.pem (100%) rename bindings/rust-examples/{client-hello-config-resolution => }/certs/wombat-chain.pem (100%) rename bindings/rust-examples/{client-hello-config-resolution => }/certs/wombat-key.pem (100%) create mode 100644 bindings/rust-examples/tokio-server-client/Cargo.toml rename bindings/{rust/s2n-tls-tokio/examples => rust-examples/tokio-server-client/src/bin}/client.rs (88%) rename bindings/{rust/s2n-tls-tokio/examples => rust-examples/tokio-server-client/src/bin}/server.rs (97%) diff --git a/bindings/rust-examples/Cargo.toml b/bindings/rust-examples/Cargo.toml index 0b4ca8be1aa..a718b4ff287 100644 --- a/bindings/rust-examples/Cargo.toml +++ b/bindings/rust-examples/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = [ - "client-hello-config-resolution", + "client-hello-config-resolution", "tokio-server-client", ] resolver = "2" diff --git a/bindings/rust-examples/client-hello-config-resolution/certs/ca-cert.pem b/bindings/rust-examples/certs/ca-cert.pem similarity index 100% rename from bindings/rust-examples/client-hello-config-resolution/certs/ca-cert.pem rename to bindings/rust-examples/certs/ca-cert.pem diff --git a/bindings/rust-examples/client-hello-config-resolution/certs/generate.sh b/bindings/rust-examples/certs/generate.sh similarity index 100% rename from bindings/rust-examples/client-hello-config-resolution/certs/generate.sh rename to bindings/rust-examples/certs/generate.sh diff --git a/bindings/rust-examples/client-hello-config-resolution/certs/kangaroo-chain.pem b/bindings/rust-examples/certs/kangaroo-chain.pem similarity index 100% rename from bindings/rust-examples/client-hello-config-resolution/certs/kangaroo-chain.pem rename to bindings/rust-examples/certs/kangaroo-chain.pem diff --git a/bindings/rust-examples/client-hello-config-resolution/certs/kangaroo-key.pem b/bindings/rust-examples/certs/kangaroo-key.pem similarity index 100% rename from bindings/rust-examples/client-hello-config-resolution/certs/kangaroo-key.pem rename to bindings/rust-examples/certs/kangaroo-key.pem diff --git a/bindings/rust-examples/client-hello-config-resolution/certs/wombat-chain.pem b/bindings/rust-examples/certs/wombat-chain.pem similarity index 100% rename from bindings/rust-examples/client-hello-config-resolution/certs/wombat-chain.pem rename to bindings/rust-examples/certs/wombat-chain.pem diff --git a/bindings/rust-examples/client-hello-config-resolution/certs/wombat-key.pem b/bindings/rust-examples/certs/wombat-key.pem similarity index 100% rename from bindings/rust-examples/client-hello-config-resolution/certs/wombat-key.pem rename to bindings/rust-examples/certs/wombat-key.pem diff --git a/bindings/rust-examples/client-hello-config-resolution/src/bin/client.rs b/bindings/rust-examples/client-hello-config-resolution/src/bin/client.rs index a9c9518cf8a..e79da70b888 100644 --- a/bindings/rust-examples/client-hello-config-resolution/src/bin/client.rs +++ b/bindings/rust-examples/client-hello-config-resolution/src/bin/client.rs @@ -22,7 +22,8 @@ struct Cli { async fn main() -> Result<(), Box> { let args = Cli::parse(); let mut config = s2n_tls::config::Config::builder(); - let ca: Vec = std::fs::read(env!("CARGO_MANIFEST_DIR").to_owned() + "/certs/ca-cert.pem")?; + let ca: Vec = + std::fs::read(env!("CARGO_MANIFEST_DIR").to_owned() + "/../certs/ca-cert.pem")?; config.set_security_policy(&DEFAULT_TLS13)?; config.trust_pem(&ca)?; diff --git a/bindings/rust-examples/client-hello-config-resolution/src/bin/server.rs b/bindings/rust-examples/client-hello-config-resolution/src/bin/server.rs index 958fdb51633..064d274d2af 100644 --- a/bindings/rust-examples/client-hello-config-resolution/src/bin/server.rs +++ b/bindings/rust-examples/client-hello-config-resolution/src/bin/server.rs @@ -72,8 +72,12 @@ impl ClientHelloCallback for AnimalConfigResolver { } fn server_config(animal: &str) -> s2n_tls::config::Config { - let cert_path = format!("{}/certs/{}-chain.pem", env!("CARGO_MANIFEST_DIR"), animal); - let key_path = format!("{}/certs/{}-key.pem", env!("CARGO_MANIFEST_DIR"), animal); + let cert_path = format!( + "{}/../certs/{}-chain.pem", + env!("CARGO_MANIFEST_DIR"), + animal + ); + let key_path = format!("{}/../certs/{}-key.pem", env!("CARGO_MANIFEST_DIR"), animal); let cert = std::fs::read(cert_path).unwrap(); let key = std::fs::read(key_path).unwrap(); let mut config = s2n_tls::config::Builder::new(); diff --git a/bindings/rust-examples/tokio-server-client/Cargo.toml b/bindings/rust-examples/tokio-server-client/Cargo.toml new file mode 100644 index 00000000000..b2fc2d0f397 --- /dev/null +++ b/bindings/rust-examples/tokio-server-client/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "tokio-server-client" +version.workspace = true +authors.workspace = true +publish.workspace = true +license.workspace = true +edition.workspace = true + +[dependencies] +s2n-tls = { path = "../../rust/s2n-tls" } +s2n-tls-tokio = { path = "../../rust/s2n-tls-tokio" } +tokio = { version = "1", features = ["full"] } +clap = { version = "4", features = ["derive"] } diff --git a/bindings/rust/s2n-tls-tokio/examples/client.rs b/bindings/rust-examples/tokio-server-client/src/bin/client.rs similarity index 88% rename from bindings/rust/s2n-tls-tokio/examples/client.rs rename to bindings/rust-examples/tokio-server-client/src/bin/client.rs index eebc3e115ac..9f108f77350 100644 --- a/bindings/rust/s2n-tls-tokio/examples/client.rs +++ b/bindings/rust-examples/tokio-server-client/src/bin/client.rs @@ -7,12 +7,12 @@ use s2n_tls_tokio::TlsConnector; use std::{error::Error, fs}; use tokio::{io::AsyncWriteExt, net::TcpStream}; -/// NOTE: this certificate is to be used for demonstration purposes only! -const DEFAULT_CERT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../certs/cert.pem"); +/// NOTE: this ca is to be used for demonstration purposes only! +const DEFAULT_CA: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../certs/ca-cert.pem"); #[derive(Parser, Debug)] struct Args { - #[clap(short, long, default_value_t = String::from(DEFAULT_CERT))] + #[clap(short, long, default_value_t = String::from(DEFAULT_CA))] trust: String, addr: String, } @@ -29,7 +29,7 @@ async fn run_client(trust_pem: &[u8], addr: &str) -> Result<(), Box> // Connect to the server. let stream = TcpStream::connect(addr).await?; - let tls = client.connect("localhost", stream).await?; + let tls = client.connect("www.kangaroo.com", stream).await?; println!("{:#?}", tls); // Split the stream. diff --git a/bindings/rust/s2n-tls-tokio/examples/server.rs b/bindings/rust-examples/tokio-server-client/src/bin/server.rs similarity index 97% rename from bindings/rust/s2n-tls-tokio/examples/server.rs rename to bindings/rust-examples/tokio-server-client/src/bin/server.rs index 3e549ef10e9..4ca86ead206 100644 --- a/bindings/rust/s2n-tls-tokio/examples/server.rs +++ b/bindings/rust-examples/tokio-server-client/src/bin/server.rs @@ -8,8 +8,8 @@ use std::{error::Error, fs}; use tokio::{io::AsyncWriteExt, net::TcpListener}; /// NOTE: this certificate and key are to be used for demonstration purposes only! -const DEFAULT_CERT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../certs/cert.pem"); -const DEFAULT_KEY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../certs/key.pem"); +const DEFAULT_CERT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../certs/kangaroo-chain.pem"); +const DEFAULT_KEY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../certs/kangaroo-key.pem"); #[derive(Parser, Debug)] struct Args { diff --git a/bindings/rust/s2n-tls-tokio/Cargo.toml b/bindings/rust/s2n-tls-tokio/Cargo.toml index 038ee9176d2..07e2afa7b81 100644 --- a/bindings/rust/s2n-tls-tokio/Cargo.toml +++ b/bindings/rust/s2n-tls-tokio/Cargo.toml @@ -20,7 +20,6 @@ tokio = { version = "1", features = ["net", "time"] } [dev-dependencies] s2n-tls = { path = "../s2n-tls", features = ["unstable-testing"] } -clap = { version = "3", features = ["derive"] } rand = { version = "0.8" } tokio = { version = "1", features = [ "io-std", "io-util", "macros", "net", "rt-multi-thread", "test-util", "time"] } tokio-macros = "=2.3.0" From 20cbaac9384290096d3b86249888a85682ce3035 Mon Sep 17 00:00:00 2001 From: James Mayclin Date: Wed, 11 Dec 2024 18:26:57 -0800 Subject: [PATCH 3/5] docs: specify s2n_blob growable conditions (#4943) Co-authored-by: maddeleine <59030281+maddeleine@users.noreply.github.com> --- stuffer/s2n_stuffer.h | 6 +++++- utils/s2n_blob.c | 1 + utils/s2n_blob.h | 14 ++++++++++++-- utils/s2n_ensure.h | 3 +++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/stuffer/s2n_stuffer.h b/stuffer/s2n_stuffer.h index abf294cce80..05e46d49006 100644 --- a/stuffer/s2n_stuffer.h +++ b/stuffer/s2n_stuffer.h @@ -45,7 +45,11 @@ struct s2n_stuffer { uint32_t write_cursor; uint32_t high_water_mark; - /* Was this stuffer alloc()'d ? */ + /* Was this stuffer alloc()'d? + * This field controls whether the stuffer "owns" the blob. If the stuffer + * was allocated, then `blob` must be freed when the stuffer is freed. If the + * stuffer was not allocated, then the blob must not be freed by the stuffer, even if the + * blob itself is allocated. */ unsigned int alloced : 1; /* Is this stuffer growable? */ diff --git a/utils/s2n_blob.c b/utils/s2n_blob.c index 58cd7b0a72b..ecf0e81709d 100644 --- a/utils/s2n_blob.c +++ b/utils/s2n_blob.c @@ -29,6 +29,7 @@ S2N_RESULT s2n_blob_validate(const struct s2n_blob *b) RESULT_DEBUG_ENSURE(S2N_IMPLIES(b->data == NULL, b->size == 0), S2N_ERR_SAFETY); RESULT_DEBUG_ENSURE(S2N_IMPLIES(b->data == NULL, b->allocated == 0), S2N_ERR_SAFETY); RESULT_DEBUG_ENSURE(S2N_IMPLIES(b->growable == 0, b->allocated == 0), S2N_ERR_SAFETY); + RESULT_DEBUG_ENSURE(S2N_IMPLIES(b->growable == 1, b->allocated > 0 || b->size == 0), S2N_ERR_SAFETY); RESULT_DEBUG_ENSURE(S2N_IMPLIES(b->growable != 0, b->size <= b->allocated), S2N_ERR_SAFETY); RESULT_DEBUG_ENSURE(S2N_MEM_IS_READABLE(b->data, b->allocated), S2N_ERR_SAFETY); RESULT_DEBUG_ENSURE(S2N_MEM_IS_READABLE(b->data, b->size), S2N_ERR_SAFETY); diff --git a/utils/s2n_blob.h b/utils/s2n_blob.h index 25e6b7a7646..8e40bb600fa 100644 --- a/utils/s2n_blob.h +++ b/utils/s2n_blob.h @@ -30,11 +30,21 @@ struct s2n_blob { /* The amount of memory allocated for this blob (i.e. the amount of memory * which needs to be freed when the blob is cleaned up). If this blob was * created with s2n_blob_init(), this value is 0. If s2n_alloc() was called, - * this value will be greater than 0. + * this value will be greater than or equal to size. + * + * size < allocated implies that an allocated blob is being reused to store + * a smaller amount of data. */ uint32_t allocated; - /* Can this blob be resized */ + /* An allocated blob (e.g.`s2n_alloc`) is always growable. A "reference" + * blob (from `s2n_blob_init`) is never growable. + * + * This field is necessary to distinguish zero-sized allocated blobs from + * zero-sized "reference" blobs. Zero-sized allocated blobs can not be + * constructed with s2n_alloc or s2n_realloc, but they are directly initialized + * in s2n_free_object. + */ unsigned growable : 1; }; diff --git a/utils/s2n_ensure.h b/utils/s2n_ensure.h index 866db937db0..b7247eadf78 100644 --- a/utils/s2n_ensure.h +++ b/utils/s2n_ensure.h @@ -120,6 +120,9 @@ void *s2n_ensure_memmove_trace(void *to, const void *from, size_t size); #define S2N_OBJECT_PTR_IS_READABLE(ptr) ((ptr) != NULL) #define S2N_OBJECT_PTR_IS_WRITABLE(ptr) ((ptr) != NULL) +/** + * If `a` is true, then `b` must be true. + */ #define S2N_IMPLIES(a, b) (!(a) || (b)) /** * If and only if (iff) is a biconditional logical connective between statements a and b. From b16dd82dbd8fba3ef4ab33378d0f29d51b956d47 Mon Sep 17 00:00:00 2001 From: Lindsay Stewart Date: Wed, 11 Dec 2024 21:20:28 -0800 Subject: [PATCH 4/5] fix: pem parsing detection of last cert errors (#4908) --- crypto/s2n_certificate.c | 37 ++----- stuffer/s2n_stuffer.h | 3 +- stuffer/s2n_stuffer_pem.c | 38 +++++-- tests/unit/s2n_certificate_parsing_test.c | 123 ++++++++++++++++++++++ 4 files changed, 167 insertions(+), 34 deletions(-) diff --git a/crypto/s2n_certificate.c b/crypto/s2n_certificate.c index 77629baf9b4..0961e309837 100644 --- a/crypto/s2n_certificate.c +++ b/crypto/s2n_certificate.c @@ -47,45 +47,30 @@ int s2n_create_cert_chain_from_stuffer(struct s2n_cert_chain *cert_chain_out, st struct s2n_cert **insert = &cert_chain_out->head; uint32_t chain_size = 0; - do { - struct s2n_cert *new_node = NULL; + while (s2n_stuffer_pem_has_certificate(chain_in_stuffer)) { + int result = s2n_stuffer_certificate_from_pem(chain_in_stuffer, &cert_out_stuffer); + POSIX_ENSURE(result == S2N_SUCCESS, S2N_ERR_INVALID_PEM); - if (s2n_stuffer_certificate_from_pem(chain_in_stuffer, &cert_out_stuffer) < 0) { - if (chain_size == 0) { - POSIX_BAIL(S2N_ERR_NO_CERTIFICATE_IN_PEM); - } - break; - } - struct s2n_blob mem = { 0 }; + DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free); POSIX_GUARD(s2n_alloc(&mem, sizeof(struct s2n_cert))); POSIX_GUARD(s2n_blob_zero(&mem)); - new_node = (struct s2n_cert *) (void *) mem.data; - if (s2n_alloc(&new_node->raw, s2n_stuffer_data_available(&cert_out_stuffer)) != S2N_SUCCESS) { - POSIX_GUARD(s2n_free(&mem)); - S2N_ERROR_PRESERVE_ERRNO(); - } - if (s2n_stuffer_read(&cert_out_stuffer, &new_node->raw) != S2N_SUCCESS) { - POSIX_GUARD(s2n_free(&mem)); - S2N_ERROR_PRESERVE_ERRNO(); - } + struct s2n_cert *new_node = (struct s2n_cert *) (void *) mem.data; + POSIX_GUARD(s2n_alloc(&new_node->raw, s2n_stuffer_data_available(&cert_out_stuffer))); + POSIX_GUARD(s2n_stuffer_read(&cert_out_stuffer, &new_node->raw)); + ZERO_TO_DISABLE_DEFER_CLEANUP(mem); /* Additional 3 bytes for the length field in the protocol */ chain_size += new_node->raw.size + 3; new_node->next = NULL; *insert = new_node; insert = &new_node->next; - } while (s2n_stuffer_data_available(chain_in_stuffer)); - - /* Leftover data at this point means one of two things: - * A bug in s2n's PEM parsing OR a malformed PEM in the user's chain. - * Be conservative and fail instead of using a partial chain. - */ - S2N_ERROR_IF(s2n_stuffer_data_available(chain_in_stuffer) > 0, S2N_ERR_INVALID_PEM); + }; + POSIX_ENSURE(chain_size > 0, S2N_ERR_NO_CERTIFICATE_IN_PEM); cert_chain_out->chain_size = chain_size; - return 0; + return S2N_SUCCESS; } int s2n_cert_chain_and_key_set_cert_chain_from_stuffer(struct s2n_cert_chain_and_key *cert_and_key, struct s2n_stuffer *chain_in_stuffer) diff --git a/stuffer/s2n_stuffer.h b/stuffer/s2n_stuffer.h index 05e46d49006..f3d8f29cb3c 100644 --- a/stuffer/s2n_stuffer.h +++ b/stuffer/s2n_stuffer.h @@ -212,8 +212,9 @@ int S2N_RESULT_MUST_USE s2n_stuffer_vprintf(struct s2n_stuffer *stuffer, const c /* Read a private key from a PEM encoded stuffer to an ASN1/DER encoded one */ int S2N_RESULT_MUST_USE s2n_stuffer_private_key_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1, int *type); -/* Read a certificate from a PEM encoded stuffer to an ASN1/DER encoded one */ +/* Read a certificate from a PEM encoded stuffer to an ASN1/DER encoded one */ int S2N_RESULT_MUST_USE s2n_stuffer_certificate_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1); +bool s2n_stuffer_pem_has_certificate(struct s2n_stuffer *pem); /* Read a CRL from a PEM encoded stuffer to an ASN1/DER encoded one */ int S2N_RESULT_MUST_USE s2n_stuffer_crl_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1); diff --git a/stuffer/s2n_stuffer_pem.c b/stuffer/s2n_stuffer_pem.c index cf5d2ecb205..38448e0e37c 100644 --- a/stuffer/s2n_stuffer_pem.c +++ b/stuffer/s2n_stuffer_pem.c @@ -34,19 +34,30 @@ #define S2N_PEM_CERTIFICATE "CERTIFICATE" #define S2N_PEM_CRL "X509 CRL" -static int s2n_stuffer_pem_read_encapsulation_line(struct s2n_stuffer *pem, const char *encap_marker, - const char *keyword) +static S2N_RESULT s2n_stuffer_pem_read_delimiter_chars(struct s2n_stuffer *pem) { - /* Skip any number of Chars until a "--" is reached. + RESULT_ENSURE_REF(pem); + RESULT_ENSURE(s2n_stuffer_data_available(pem) >= S2N_PEM_DELIMITER_MIN_COUNT, + S2N_ERR_INVALID_PEM); + + /* Skip any number of chars until a "--" is reached. * We use "--" instead of "-" to account for dashes that appear in comments. * We do not accept comments that contain "--". */ - POSIX_GUARD(s2n_stuffer_skip_read_until(pem, S2N_PEM_DELIMITER_TOKEN)); - POSIX_GUARD(s2n_stuffer_rewind_read(pem, strlen(S2N_PEM_DELIMITER_TOKEN))); + RESULT_GUARD_POSIX(s2n_stuffer_skip_read_until(pem, S2N_PEM_DELIMITER_TOKEN)); + RESULT_GUARD_POSIX(s2n_stuffer_rewind_read(pem, strlen(S2N_PEM_DELIMITER_TOKEN))); /* Ensure between 2 and 64 '-' chars at start of line. */ - POSIX_GUARD(s2n_stuffer_skip_expected_char(pem, S2N_PEM_DELIMITER_CHAR, S2N_PEM_DELIMITER_MIN_COUNT, - S2N_PEM_DELIMITER_MAX_COUNT, NULL)); + RESULT_GUARD_POSIX(s2n_stuffer_skip_expected_char(pem, S2N_PEM_DELIMITER_CHAR, + S2N_PEM_DELIMITER_MIN_COUNT, S2N_PEM_DELIMITER_MAX_COUNT, NULL)); + + return S2N_RESULT_OK; +} + +static int s2n_stuffer_pem_read_encapsulation_line(struct s2n_stuffer *pem, const char *encap_marker, + const char *keyword) +{ + POSIX_GUARD_RESULT(s2n_stuffer_pem_read_delimiter_chars(pem)); /* Ensure next string in stuffer is "BEGIN " or "END " */ POSIX_GUARD(s2n_stuffer_read_expected_str(pem, encap_marker)); @@ -173,6 +184,19 @@ int s2n_stuffer_private_key_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer POSIX_BAIL(S2N_ERR_INVALID_PEM); } +/* We define a pem containing a certificate as a pem containing the delimiter chars. + * If the delimiter chars exist but the certificate keyword doesn't, that is a parsing error. + * That ensures that we don't ignore unexpected keywords like "END CERTIFICATE" + * instead of "BEGIN CERTIFICATE" or malformed keywords like "BEGAN CERTIFICATE" + * instead of "BEGIN CERTIFICATE". + */ +bool s2n_stuffer_pem_has_certificate(struct s2n_stuffer *pem) +{ + /* Operate on a copy of pem to avoid modifying pem */ + struct s2n_stuffer pem_copy = *pem; + return s2n_result_is_ok(s2n_stuffer_pem_read_delimiter_chars(&pem_copy)); +} + int s2n_stuffer_certificate_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1) { return s2n_stuffer_data_from_pem(pem, asn1, S2N_PEM_CERTIFICATE); diff --git a/tests/unit/s2n_certificate_parsing_test.c b/tests/unit/s2n_certificate_parsing_test.c index 260f763fc5f..d14d3fb7a18 100644 --- a/tests/unit/s2n_certificate_parsing_test.c +++ b/tests/unit/s2n_certificate_parsing_test.c @@ -250,6 +250,23 @@ int main(int argc, char **argv) "--" BEGIN_CERT "--" CERTIFICATE_2 "--" END_CERT "--" BEGIN_CERT "--" CERTIFICATE_3 "--" END_CERT "--" , }, + { + .name = "non-certificate data", + .input = + "this is not a certificate\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_1 "\n" + END_CERT_LINE "\n" + "\n" + "this is not a certificate either\n" + "\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_2 "\n" + END_CERT_LINE "not a certificate\n" + "not a certificate" BEGIN_CERT_LINE "\n" + CERTIFICATE_3 "\n" + END_CERT_LINE "\n", + }, { .name = "comments", .input = @@ -304,6 +321,50 @@ int main(int argc, char **argv) CERTIFICATE_3 "\n" END_CERT_LINE "\n", }, + { + .name = "trailing comment", + .input = + BEGIN_CERT_LINE "\n" + CERTIFICATE_1 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_2 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_3 "\n" + END_CERT_LINE "\n" + "# trailing comment \n" + }, + { + .name = "trailing whitespace", + .input = + BEGIN_CERT_LINE "\n" + CERTIFICATE_1 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_2 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_3 "\n" + END_CERT_LINE "\n" + "\n" + "\n", + }, + { + .name = "trailing non-certificate data", + .input = + BEGIN_CERT_LINE "\n" + CERTIFICATE_1 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_2 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_3 "\n" + END_CERT_LINE "\n" + "this is not a certificate\n" + "neither is this", + }, }; /* clang-format on */ @@ -420,6 +481,32 @@ int main(int argc, char **argv) CERTIFICATE_1 "\n" END_CERT_LINE "\n" }, + { + .name = "multiple certs: trailing marker", + .input = + BEGIN_CERT_LINE "\n" + CERTIFICATE_1 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + }, + { + .name = "multiple certs: trailing partial certificate", + .input = + BEGIN_CERT_LINE "\n" + CERTIFICATE_1 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + "MIIBljCCATygAwIBAg\n" + }, + { + .name = "multiple certs: missing end marker", + .input = + BEGIN_CERT_LINE "\n" + CERTIFICATE_1 "\n" + END_CERT_LINE "\n" + BEGIN_CERT_LINE "\n" + CERTIFICATE_1 "\n" + }, }; /* clang-format on */ @@ -439,6 +526,42 @@ int main(int argc, char **argv) }; } + /* Any case that is invalid for a single certificate should also be invalid + * for a certificate chain. + * We do not want to rely solely on our test for 0-length chains. + */ + const char *valid_cert_chain = test_cases[0].input; + for (size_t i = 0; i < s2n_array_len(bad_test_cases); i++) { + const struct s2n_test_case *test_case = &bad_test_cases[i]; + + /* The extra character is for an extra newline */ + size_t test_input_size = strlen(test_case->input) + strlen(valid_cert_chain) + 1; + + DEFER_CLEANUP(struct s2n_stuffer test_input = { 0 }, s2n_stuffer_free); + EXPECT_SUCCESS(s2n_stuffer_alloc(&test_input, test_input_size)); + EXPECT_SUCCESS(s2n_stuffer_write_str(&test_input, valid_cert_chain)); + + /* Sanity check: valid chain is valid */ + DEFER_CLEANUP(struct s2n_cert_chain_and_key *good_chain_and_key = s2n_cert_chain_and_key_new(), + s2n_cert_chain_and_key_ptr_free); + struct s2n_cert_chain *good_chain = good_chain_and_key->cert_chain; + EXPECT_SUCCESS(s2n_create_cert_chain_from_stuffer(good_chain, &test_input)); + + /* Add the invalid input to the end of the proven valid chain */ + EXPECT_SUCCESS(s2n_stuffer_write_char(&test_input, '\n')); + EXPECT_SUCCESS(s2n_stuffer_write_str(&test_input, test_case->input)); + EXPECT_SUCCESS(s2n_stuffer_reread(&test_input)); + + /* Test: valid chain + invalid test case is sill invalid */ + DEFER_CLEANUP(struct s2n_cert_chain_and_key *bad_chain_and_key = s2n_cert_chain_and_key_new(), + s2n_cert_chain_and_key_ptr_free); + struct s2n_cert_chain *bad_chain = bad_chain_and_key->cert_chain; + if (s2n_create_cert_chain_from_stuffer(bad_chain, &test_input) == S2N_SUCCESS) { + fprintf(stderr, "Successfully parsed invalid cert chain \"%s\"\n", test_case->name); + FAIL_MSG("Successfully parsed invalid cert chain"); + }; + } + for (size_t i = 0; i < s2n_array_len(expected_certs); i++) { EXPECT_SUCCESS(s2n_free(&expected_certs[i])); } From 2e79e7efeb26f06eb59a1d4f3444ea63fc3e20c3 Mon Sep 17 00:00:00 2001 From: James Mayclin Date: Thu, 12 Dec 2024 10:00:24 -0800 Subject: [PATCH 5/5] refactor(bench): remove historical benchmarks (#4940) --- bindings/rust/bench/Cargo.toml | 35 +- bindings/rust/bench/README.md | 48 +- bindings/rust/bench/benches/handshake.rs | 30 +- bindings/rust/bench/benches/throughput.rs | 29 +- .../images/historical-perf-handshake.svg | 947 ------------------ .../images/historical-perf-throughput.svg | 383 ------- bindings/rust/bench/scripts/bench-memory.sh | 30 - bindings/rust/bench/scripts/bench-past.sh | 80 -- bindings/rust/bench/src/bin/graph_memory.rs | 134 --- bindings/rust/bench/src/bin/graph_perf.rs | 306 ------ bindings/rust/bench/src/bin/memory.rs | 191 ---- bindings/rust/bench/src/harness.rs | 8 +- bindings/rust/bench/src/lib.rs | 8 +- bindings/rust/bench/src/openssl.rs | 5 +- 14 files changed, 29 insertions(+), 2205 deletions(-) delete mode 100644 bindings/rust/bench/images/historical-perf-handshake.svg delete mode 100644 bindings/rust/bench/images/historical-perf-throughput.svg delete mode 100755 bindings/rust/bench/scripts/bench-memory.sh delete mode 100755 bindings/rust/bench/scripts/bench-past.sh delete mode 100644 bindings/rust/bench/src/bin/graph_memory.rs delete mode 100644 bindings/rust/bench/src/bin/graph_perf.rs delete mode 100644 bindings/rust/bench/src/bin/memory.rs diff --git a/bindings/rust/bench/Cargo.toml b/bindings/rust/bench/Cargo.toml index c061bedbeef..ab4da6cb9d4 100644 --- a/bindings/rust/bench/Cargo.toml +++ b/bindings/rust/bench/Cargo.toml @@ -3,31 +3,14 @@ name = "bench" version = "0.1.0" edition = "2021" -[features] -default = ["rustls", "openssl"] -rustls = ["dep:rustls", "rustls-pemfile"] -openssl = ["dep:openssl"] -memory = ["plotters", "crabgrind", "structopt"] -historical-perf = ["plotters", "serde_json", "semver"] - [dependencies] s2n-tls = { path = "../s2n-tls" } errno = "0.3" libc = "0.2" 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 } -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 } - -[dependencies.plotters] -version = "0.3" -optional = true -default-features = false -features = ["all_series", "all_elements", "full_palette", "svg_backend"] +rustls = { version = "0.23" } +rustls-pemfile = { version = "2" } +openssl = { version = "0.10", features = ["vendored"] } [dev-dependencies] criterion = "0.5" @@ -37,18 +20,6 @@ pprof = { version = "0.12", features = ["criterion", "flamegraph"] } env_logger = "0.10" log = "0.4" -[[bin]] -name = "memory" -required-features = ["memory"] - -[[bin]] -name = "graph_memory" -required-features = ["memory"] - -[[bin]] -name = "graph_perf" -required-features = ["historical-perf"] - [[bench]] name = "handshake" harness = false diff --git a/bindings/rust/bench/README.md b/bindings/rust/bench/README.md index e444f1e765b..b0cdb34cd3d 100644 --- a/bindings/rust/bench/README.md +++ b/bindings/rust/bench/README.md @@ -8,7 +8,7 @@ All benchmarks are run in an idealized environment, using only a single thread a ``` # generate rust bindings -../generate.sh +../generate.sh --skip-tests # run all benchmarks cargo bench @@ -36,37 +36,6 @@ Throughput benchmarks measure round-trip throughput with the client and server c To generate flamegraphs, run `cargo bench --bench handshake --bench throughput -- --profile-time 5`, which profiles each benchmark for 5 seconds and stores the resulting flamegraph in `target/criterion/[bench-name]/[lib-name]/profile/flamegraph.svg`. -## Memory benchmarks - -To run all memory benchmarks, run `scripts/bench-memory.sh`. Graphs of memory usage will be generated in `images/`. - -Memory benchmark data is generated using the `memory` binary. Command line arguments can be given to `cargo run` or to the built executable located at `target/release/memory`. The usage is as follows: - -``` -memory [(pair|client|server)] [(s2n-tls|rustls|openssl)] [--reuse-config (true|false)] [--shrink-buffers (true|false)] -``` - -- `(pair|client|server)`: target to memory bench, defaults to `server` -- `(s2n-tls|rustls|openssl)`: library to be benched, if unset benches all libraries -- `--reuse-config`: if `true` (default), reuse configs between connections -- `--shrink-buffers`: if `true` (default), shrink buffers owned by connections - -To view a callgraph of memory usage, use [KCachegrind](https://github.com/KDE/kcachegrind) on `xtree.out` generated from memory benching: - -``` -kcachegrind target/memory////xtree.out -``` - -To view a flamegraph of memory usage, use [heaptrack](https://github.com/KDE/heaptrack) with `heaptrack_gui` also installed. Run heaptrack with the `memory` executable and target/library options: - -``` -heaptrack target/release/memory (pair|client|server) (s2n-tls|rustls|openssl) -``` - -## Historical benchmarks - -To do historical benchmarks, run `scripts/bench-past.sh`. This will checkout old versions of s2n-tls back to v1.3.16 in `target/` and run benchmarks on those with the `historical-perf` feature, disabling Rustls and OpenSSL benches. - ## PKI Structure ``` ┌────root──────┐ @@ -88,21 +57,6 @@ The last version benched is v1.3.16, since before that, the s2n-tls Rust binding v1.3.30-1.3.37 are not benched because of dependency issues when generating the Rust bindings. However, versions before and after are benched, so the overall trend in performance can still be seen without the data from these versions. -### Sample output - -Because these benches take a longer time to generate (>30 min), we include the results from historical benching (as of v1.3.47) here. - -Notes: -- Two sets of parameters for the handshake couldn't be benched before 1.3.40, since security policies that negotiated those policies as their top choice did not exist before then. -- There is no data from 1.3.30 to 1.3.37 because those versions have a dependency issue that cause the Rust bindings not to build. However, there is data before and after that period, so the performance for those versions can be inferred via interpolation. -- The improvement in throughput in 1.3.28 was most likely caused by the addition of LTO to the default Rust bindings build. -- Since the benches are run over a long time, noise on the machine can cause variability, and background processes can cause spikes. -- The variability can be seen with throughput especially because it is calculated as the inverse of time taken. - -![historical-perf-handshake](images/historical-perf-handshake.svg) - -![historical-perf-throughput](images/historical-perf-throughput.svg) - ## Implementation details We use Rust bindings for s2n-tls and OpenSSL. All of our benchmarks are run in Rust on a single thread for consistency. diff --git a/bindings/rust/bench/benches/handshake.rs b/bindings/rust/bench/benches/handshake.rs index 6fc7c5b2a20..b86d0a81b0d 100644 --- a/bindings/rust/bench/benches/handshake.rs +++ b/bindings/rust/bench/benches/handshake.rs @@ -1,13 +1,10 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#[cfg(feature = "openssl")] -use bench::OpenSslConnection; -#[cfg(feature = "rustls")] -use bench::RustlsConnection; use bench::{ harness::TlsBenchConfig, CipherSuite, ConnectedBuffer, CryptoConfig, HandshakeType, KXGroup, - Mode, S2NConnection, SigType, TlsConnPair, TlsConnection, PROFILER_FREQUENCY, + Mode, OpenSslConnection, RustlsConnection, S2NConnection, SigType, TlsConnPair, TlsConnection, + PROFILER_FREQUENCY, }; use criterion::{ criterion_group, criterion_main, measurement::WallTime, BatchSize, BenchmarkGroup, Criterion, @@ -27,25 +24,20 @@ fn bench_handshake_for_library( { // make configs before benching to reuse let crypto_config = CryptoConfig::new(CipherSuite::default(), kx_group, sig_type); - let client_config = T::Config::make_config(Mode::Client, crypto_config, handshake_type); - let server_config = T::Config::make_config(Mode::Server, crypto_config, handshake_type); + let client_config = + T::Config::make_config(Mode::Client, crypto_config, handshake_type).unwrap(); + let server_config = + T::Config::make_config(Mode::Server, crypto_config, handshake_type).unwrap(); // generate all harnesses (TlsConnPair structs) beforehand so that benchmarks // only include negotiation and not config/connection initialization bench_group.bench_function(T::name(), |b| { b.iter_batched_ref( || -> Result, Box> { - if let (Ok(client_config), Ok(server_config)) = - (client_config.as_ref(), server_config.as_ref()) - { - let connected_buffer = ConnectedBuffer::default(); - let client = - T::new_from_config(client_config, connected_buffer.clone_inverse())?; - let server = T::new_from_config(server_config, connected_buffer)?; - Ok(TlsConnPair::wrap(client, server)) - } else { - Err("invalid configs".into()) - } + let connected_buffer = ConnectedBuffer::default(); + let client = T::new_from_config(&client_config, connected_buffer.clone_inverse())?; + let server = T::new_from_config(&server_config, connected_buffer)?; + Ok(TlsConnPair::wrap(client, server)) }, |conn_pair| { // harnesses with certain parameters fail to initialize for @@ -67,14 +59,12 @@ fn bench_handshake_with_params( sig_type: SigType, ) { bench_handshake_for_library::(bench_group, handshake_type, kx_group, sig_type); - #[cfg(feature = "rustls")] bench_handshake_for_library::( bench_group, handshake_type, kx_group, sig_type, ); - #[cfg(feature = "openssl")] bench_handshake_for_library::( bench_group, handshake_type, diff --git a/bindings/rust/bench/benches/throughput.rs b/bindings/rust/bench/benches/throughput.rs index 7ad675202f4..b6785552320 100644 --- a/bindings/rust/bench/benches/throughput.rs +++ b/bindings/rust/bench/benches/throughput.rs @@ -1,9 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#[cfg(feature = "openssl")] use bench::OpenSslConnection; -#[cfg(feature = "rustls")] use bench::RustlsConnection; use bench::{ harness::TlsBenchConfig, CipherSuite, ConnectedBuffer, CryptoConfig, HandshakeType, KXGroup, @@ -26,25 +24,20 @@ fn bench_throughput_for_library( T::Config: TlsBenchConfig, { let crypto_config = CryptoConfig::new(cipher_suite, KXGroup::default(), SigType::default()); - let client_config = T::Config::make_config(Mode::Client, crypto_config, HandshakeType::default()); - let server_config = T::Config::make_config(Mode::Server, crypto_config, HandshakeType::default()); + let client_config = + T::Config::make_config(Mode::Client, crypto_config, HandshakeType::default()).unwrap(); + let server_config = + T::Config::make_config(Mode::Server, crypto_config, HandshakeType::default()).unwrap(); bench_group.bench_function(T::name(), |b| { b.iter_batched_ref( || -> Result, Box> { - if let (Ok(client_config), Ok(server_config)) = - (client_config.as_ref(), server_config.as_ref()) - { - let connected_buffer = ConnectedBuffer::default(); - let client = - T::new_from_config(client_config, connected_buffer.clone_inverse())?; - let server = T::new_from_config(server_config, connected_buffer)?; - let mut conn_pair = TlsConnPair::wrap(client, server); - conn_pair.handshake()?; - Ok(conn_pair) - } else { - Err("invalid configs".into()) - } + let connected_buffer = ConnectedBuffer::default(); + let client = T::new_from_config(&client_config, connected_buffer.clone_inverse())?; + let server = T::new_from_config(&server_config, connected_buffer)?; + let mut conn_pair = TlsConnPair::wrap(client, server); + conn_pair.handshake()?; + Ok(conn_pair) }, |conn_pair| { if let Ok(conn_pair) = conn_pair { @@ -68,13 +61,11 @@ pub fn bench_throughput_cipher_suites(c: &mut Criterion) { &mut shared_buf, cipher_suite, ); - #[cfg(feature = "rustls")] bench_throughput_for_library::( &mut bench_group, &mut shared_buf, cipher_suite, ); - #[cfg(feature = "openssl")] bench_throughput_for_library::( &mut bench_group, &mut shared_buf, diff --git a/bindings/rust/bench/images/historical-perf-handshake.svg b/bindings/rust/bench/images/historical-perf-handshake.svg deleted file mode 100644 index 06f65b30056..00000000000 --- a/bindings/rust/bench/images/historical-perf-handshake.svg +++ /dev/null @@ -1,947 +0,0 @@ - - - -Performance of handshake by version since Jun 2022 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Time - - -Version - - - - - - - - - - - - - - - - - - - - - - - - - -0 ms - - - -2 ms - - - -4 ms - - - -6 ms - - - -8 ms - - - - -1.3.16 - - - -1.3.18 - - - -1.3.20 - - - -1.3.22 - - - -1.3.24 - - - -1.3.26 - - - -1.3.28 - - - -1.3.30 - - - -1.3.32 - - - -1.3.34 - - - -1.3.36 - - - -1.3.38 - - - -1.3.40 - - - -1.3.42 - - - -1.3.44 - - - -1.3.46 - - - -1.3.48 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -handshake-x25519 - - -handshake-no-mTLS - - -handshake-rsa2048 - - -handshake-rsa4096 - - -handshake-rsa3072 - - -handshake-secp256r1 - - -handshake-mTLS - - -handshake-ecdsa384 - - - - - - - - - - diff --git a/bindings/rust/bench/images/historical-perf-throughput.svg b/bindings/rust/bench/images/historical-perf-throughput.svg deleted file mode 100644 index a27ad4e054c..00000000000 --- a/bindings/rust/bench/images/historical-perf-throughput.svg +++ /dev/null @@ -1,383 +0,0 @@ - - - -Performance of round trip throughput by version since Jun 2022 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Throughput - - -Version - - - - - - - - - - - - - - - - - - - - - - - - - -0 GB/s - - - -0.2 GB/s - - - -0.4 GB/s - - - -0.6 GB/s - - - -0.8 GB/s - - - - -1.3.16 - - - -1.3.18 - - - -1.3.20 - - - -1.3.22 - - - -1.3.24 - - - -1.3.26 - - - -1.3.28 - - - -1.3.30 - - - -1.3.32 - - - -1.3.34 - - - -1.3.36 - - - -1.3.38 - - - -1.3.40 - - - -1.3.42 - - - -1.3.44 - - - -1.3.46 - - - -1.3.48 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -throughput-AES_128_GCM_SHA256 - - -throughput-AES_256_GCM_SHA384 - - - - diff --git a/bindings/rust/bench/scripts/bench-memory.sh b/bindings/rust/bench/scripts/bench-memory.sh deleted file mode 100755 index fcc7e4e3840..00000000000 --- a/bindings/rust/bench/scripts/bench-memory.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 - -# Benches memory usage for all possible configurations and generate plots in images/ -# All given arguments (ex. `--config aws-lc-config/s2n.toml` to use AWS-LC) are passed to Cargo - -set -e - -pushd "$(dirname "$0")"/.. > /dev/null - -cargo build --release --features memory --bin memory --bin graph_memory "$@" - -# iterate through all possible options -for reuse_config in false true -do - for shrink_buffers in false true - do - for bench_target in client server pair - do - valgrind --tool=massif --depth=1 --massif-out-file="target/memory/massif.out" --time-unit=ms target/release/memory $bench_target --reuse-config $reuse_config --shrink-buffers $shrink_buffers - rm target/memory/massif.out - done - done -done - -cargo run --release --features memory --bin graph_memory "$@" - -popd > /dev/null diff --git a/bindings/rust/bench/scripts/bench-past.sh b/bindings/rust/bench/scripts/bench-past.sh deleted file mode 100755 index 57eaf04b738..00000000000 --- a/bindings/rust/bench/scripts/bench-past.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env bash - -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 - -# Run historical benchmarking by checking out old version of s2n-tls into target/ -# Criterion JSON results get cached to target/historical-perf/[bench-group-name]/[version].json -# Results are then plotted, saved to images/historical-perf-[bench-name].svg -# All given arguments (ex. `--config aws-lc-config/s2n.toml` to use AWS-LC) are passed to Cargo - -# immediately bail if any command fails -set -e - -# suppress stdout and most cargo warnings -exec >/dev/null -export CARGO_TERM_QUIET=true -export RUSTFLAGS=-Awarnings - -# go to bench directory -pushd "$(dirname "$0")"/../ -bench_path="$(pwd)" - -# delete past runs -rm -rf target/historical-perf - -# make Cargo.toml point s2n-tls to the cloned old version -sed -i "s|s2n-tls = .*|s2n-tls = { path = \"target/s2n-tls/bindings/rust/s2n-tls\" }|" Cargo.toml - -# ensure Cargo.toml gets changed back on exit; retains original exit status -trap "{ status=$?; sed -i 's|s2n-tls = .*|s2n-tls = { path = \"../s2n-tls\" }|' $bench_path/Cargo.toml; exit $status; }" EXIT - -# clone copy of repo to target/s2n-tls -echo "cloning repo" >&2 -mkdir -p target -cd target -rm -rf s2n-tls -git clone --quiet https://github.com/aws/s2n-tls -cd s2n-tls/bindings/rust/ -copied_bindings_path="$(pwd)" - -# get list of tags sorted newest to oldest -sorted_tags="$(git tag -l | sort -rV)" - -# last tag we want is v1.3.16, get line number of v1.3.16 in sorted_tags -line_num_last_tag=$(echo "$sorted_tags" | grep "v1.3.16" --line-number | head -n 1 | cut -d":" -f1) - -# loop through all tags in order up to v1.3.16 -for tag in $(echo "$sorted_tags" | head -$line_num_last_tag) -do - ( - # go to s2n-tls/bindings/rust/ inside copied repo - cd $copied_bindings_path - - echo "checkout tag $tag" >&2 - git checkout $tag --quiet - - echo "generating rust bindings" >&2 - # if generate.sh fails, exit out of block - ./generate.sh || exit 1 - - echo "running cargo bench and saving results" >&2 - cd $bench_path - rm -rf target/criterion - cargo bench --no-default-features --no-fail-fast - - # cache criterion outputs from this bench into target/historical-perf - for bench_group in $(ls target/criterion | grep -v "report") - do - mkdir -p target/historical-perf/$bench_group/ - cp target/criterion/$bench_group/s2n-tls/new/estimates.json target/historical-perf/$bench_group/$tag.json - done - ) || echo "failed, trying next tag" - echo -done - -# graph results -cd $bench_path -cargo run --release --no-default-features --features historical-perf --bin graph_perf - -popd diff --git a/bindings/rust/bench/src/bin/graph_memory.rs b/bindings/rust/bench/src/bin/graph_memory.rs deleted file mode 100644 index c633e69d7b9..00000000000 --- a/bindings/rust/bench/src/bin/graph_memory.rs +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -use plotters::{ - prelude::{ - ChartBuilder, IntoDrawingArea, IntoSegmentedCoord, LabelAreaPosition, Rectangle, - SVGBackend, SegmentValue, - }, - style::{AsRelative, Color, IntoFont, Palette, Palette99, RGBAColor, WHITE}, -}; -use std::{ - collections::BTreeMap, - error::Error, - fs::{read_dir, read_to_string}, - path::Path, -}; - -struct Stats { - mean: f64, - stderr: f64, -} - -fn get_bytes_from_snapshot(path: &Path, i: i32) -> i32 { - // number of bytes in snapshot starts on 8th line, 12th character - read_to_string(format!("{}/{i}.snapshot", path.display())) - .unwrap() - .lines() - .nth(7) - .unwrap()[11..] - .parse() - .unwrap() -} - -/// Get the difference in bytes between two snapshots, which is memory of the -/// `i`th TlsConnPair (client and server) -fn get_bytes_diff(path: &Path, i: i32) -> i32 { - get_bytes_from_snapshot(path, i + 1) - get_bytes_from_snapshot(path, i) -} - -fn get_memory_data(path: &Path) -> Stats { - let data: Vec = (0..100).map(|i| get_bytes_diff(path, i) as f64).collect(); - let mean = data.iter().sum::() / (data.len() as f64); - let variance: f64 = - data.iter().map(|x| (x - mean) * (x - mean)).sum::() / ((data.len() - 1) as f64); - let stdev = variance.sqrt(); - let stderr = stdev / (data.len() as f64).sqrt(); - - Stats { mean, stderr } -} - -/// Gets data from memory benching and plots it -fn plot_memory_data(param_name: &str, target_name: &str) -> Result<(), Box> { - // go through each library name directory (ex. "s2n-tls") and calculate stats - let mut stats: BTreeMap = Default::default(); // btree to sort by name - for dir_entry in read_dir(format!("target/memory/{param_name}/{target_name}"))? { - let dir_path = dir_entry?.path(); - let dir_name = dir_path.file_name().unwrap().to_str().unwrap().to_string(); - stats.insert(dir_name.clone(), get_memory_data(&dir_path)); - } - - // calculate things for plotting - let num_bars = stats.len(); - let x_labels: Vec = stats.iter().map(|kv| kv.0.clone()).collect(); - let max_mem = 120_000.0; // constant to keep scale same for all graphs - - // setup plotting - let chart_path = format!("images/memory-{target_name}-{param_name}.svg"); - let drawing_area = SVGBackend::new(&chart_path, (600, 500)).into_drawing_area(); - drawing_area.fill(&WHITE)?; - - let mut ctx = ChartBuilder::on(&drawing_area) - .caption( - format!("Memory of {target_name} with {param_name}"), - ("sans-serif", 30).into_font(), - ) - .set_label_area_size(LabelAreaPosition::Left, (15).percent()) // axes padding - .set_label_area_size(LabelAreaPosition::Bottom, (6).percent()) - .build_cartesian_2d( - (0..num_bars - 1).into_segmented(), - 0.0..(1.1 * max_mem), // upper y bound on plot is 1.1 * y_max - )?; - - let axis_label_style = ("sans-serif", 18).into_font(); - - ctx.configure_mesh() - .light_line_style(RGBAColor(235, 235, 235, 1.0)) // change gridline color - .bold_line_style(RGBAColor(225, 225, 225, 1.0)) - .x_labels(num_bars) - .x_label_formatter(&|x| { - // change axis labels to name of bar - let x = match *x { - SegmentValue::CenterOf(x) => x, - _ => 0, - }; - x_labels.get(x).unwrap().to_string() - }) - .x_label_style(axis_label_style.clone()) - .y_desc("Memory (kB)") - .y_labels(10) // max number of labels on y axis - .y_label_formatter(&|y| format!("{} kB", y / 1000.0)) - .y_label_style(axis_label_style) - .draw()?; - - // draw bars - // x coord is index of bench name in x_labels - ctx.draw_series(stats.iter().enumerate().map(|(i, (_name, stats))| { - // define each bar as a Rectangle - let x0 = SegmentValue::Exact(i); - let x1 = SegmentValue::Exact(i + 1); - let color = Palette99::pick(i).filled(); - let mut bar = Rectangle::new([(x0, 0.0), (x1, stats.mean)], color); - bar.set_margin(0, 0, 30, 30); // spacing between bars - bar - }))?; - - Ok(()) -} - -/// Plots all available data in target/memory and stores graphs in images -fn main() -> Result<(), Box> { - // iterate through param options ex. shrink-buffers or reuse-config - for param_dir_entry in read_dir("target/memory")? { - let param_dir_path = param_dir_entry?.path(); - let param_name = param_dir_path.file_name().unwrap().to_str().unwrap(); - - // iterate through targets, ex. client or server - for target_dir_entry in read_dir(¶m_dir_path)? { - let target_name = target_dir_entry?.file_name().to_string_lossy().to_string(); - plot_memory_data(param_name, &target_name)?; - } - } - - Ok(()) -} diff --git a/bindings/rust/bench/src/bin/graph_perf.rs b/bindings/rust/bench/src/bin/graph_perf.rs deleted file mode 100644 index f3a238e01ba..00000000000 --- a/bindings/rust/bench/src/bin/graph_perf.rs +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -use plotters::{ - prelude::{ - BindKeyPoints, ChartBuilder, ErrorBar, IntoDrawingArea, LabelAreaPosition, Rectangle, - SVGBackend, SeriesLabelPosition, - }, - series::LineSeries, - style::{AsRelative, Color, IntoFont, Palette, Palette99, RGBAColor, BLACK, WHITE}, -}; -use semver::Version; -use serde_json::Value; -use std::{ - collections::{BTreeSet, HashMap}, - fs::{read_dir, read_to_string}, - path::Path, -}; - -struct Stats { - mean: f64, - stderr: f64, -} - -struct VersionDataPoint { - version: Version, // x coordinate - mean: f64, // y coordinate - stderr: f64, // y error bar -} - -struct VersionDataSeries { - name: String, // ex. throughput-AES_128_GCM_SHA256 - data: Vec, -} - -struct DataPoint { - x: i32, - y: f64, - y_bar: f64, -} - -struct DataSeries { - name: String, - data: Vec, -} - -/// Get the relevant stats in a given JSON bench output -fn process_single_json(path: &Path) -> Stats { - let json_str = read_to_string(path).unwrap(); - let json_value: Value = serde_json::from_str(json_str.as_str()).unwrap(); - let stats = json_value.get("mean").unwrap(); - Stats { - mean: stats.get("point_estimate").unwrap().as_f64().unwrap(), - stderr: stats.get("standard_error").unwrap().as_f64().unwrap(), - } -} - -/// Get data from directory of Criterion json outputs, given directory path -/// Outputs a Vec of (version, mean, stderr) sorted by version -fn parse_bench_group_data(path: &Path) -> Vec { - let mut data: Vec = read_dir(path) - .unwrap() - .map(|dir_entry| { - let path = dir_entry.unwrap().path(); - let stats = process_single_json(&path); - let tag = path.file_stem().unwrap().to_str().unwrap(); - let version = Version::parse(&tag[1..]).unwrap(); - VersionDataPoint { - version, - mean: stats.mean, - stderr: stats.stderr, - } - }) - .collect(); - data.sort_by(|data_point_1, data_point_2| data_point_1.version.cmp(&data_point_2.version)); - data -} - -/// Gets data from all bench groups given a prefix (ex. "handshake") for the bench group names -fn get_all_data(prefix: &str) -> Vec { - read_dir("target/historical-perf") - .unwrap() - .map(|dir_entry| dir_entry.unwrap().path()) - .filter(|path| { - // get all paths starting with prefix - path.file_name() - .unwrap() - .to_str() - .unwrap() - .starts_with(prefix) - }) - .map(|path| { - // get data in each directory - VersionDataSeries { - name: path.file_name().unwrap().to_string_lossy().into_owned(), - data: parse_bench_group_data(&path), - } - }) - .collect() -} - -fn get_unique_versions(data: &[VersionDataSeries]) -> BTreeSet { - data.iter() - .flat_map(|data_series| { - data_series - .data - .iter() - .map(|version_data_point| version_data_point.version.clone()) - }) - .collect() -} - -/// Converts all VersionDataSeries in version_data to DataSeries -fn convert_to_data_series( - version_data: Vec, - version_to_x: &HashMap<&Version, i32>, -) -> Vec { - version_data - .into_iter() - .map(|version_data_series| DataSeries { - name: version_data_series.name, - data: version_data_series - .data - .into_iter() - .map(|version_data_point| DataPoint { - // map VersionDataPoints to DataPoints - x: version_to_x[&&version_data_point.version], - y: version_data_point.mean, - y_bar: version_data_point.stderr * 1.96, // 95% confidence interval - }) - .collect(), - }) - .collect() -} - -/// Plots given DataSeries with given chart parameters -fn plot_data String, G: Fn(&f64) -> String>( - data: &[DataSeries], - image_name: &str, - bench_name: &str, - x_label_formatter: &F, - y_label: &str, - y_label_formatter: &G, -) { - // get x_max and y_max for plotting range - let x_max = data - .iter() - .flat_map(|data_series| data_series.data.iter().map(|data_point| data_point.x)) - .max_by(|a, b| a.partial_cmp(b).unwrap()) - .unwrap(); - let y_max = data - .iter() - .flat_map(|data_series| data_series.data.iter().map(|data_point| data_point.y)) - .max_by(|a, b| a.partial_cmp(b).unwrap()) - .unwrap(); - - // setup plotting - let path = format!("images/historical-perf-{image_name}.svg"); - let drawing_area = SVGBackend::new(&path, (1000, 500)).into_drawing_area(); - drawing_area.fill(&WHITE).unwrap(); - - let mut ctx = ChartBuilder::on(&drawing_area) - .caption( - format!("Performance of {bench_name} by version since Jun 2022"), - ("sans-serif", 30).into_font(), - ) - .set_label_area_size(LabelAreaPosition::Left, (17).percent()) // axes padding - .set_label_area_size(LabelAreaPosition::Bottom, (11).percent()) - .build_cartesian_2d( - // bounds for plot - // plot every other x coord starting from 1 (not 0 which is default) - (0..(x_max + 1)).with_key_points((1..(x_max + 1)).step_by(2).collect()), - 0.0..(1.2 * y_max), - ) - .unwrap(); - - let axis_label_style = ("sans-serif", 18).into_font(); - - ctx.configure_mesh() - .light_line_style(RGBAColor(235, 235, 235, 1.0)) // gridline color - .bold_line_style(RGBAColor(225, 225, 225, 1.0)) - .x_desc("Version") // axis labels - .x_labels(20) // max number of labels - .x_label_style(axis_label_style.clone()) - .x_label_formatter(x_label_formatter) - .y_desc(y_label) - .y_labels(5) - .y_label_formatter(y_label_formatter) - .y_label_style(axis_label_style) - .draw() - .unwrap(); - - // go through each DataSeries and plot them - for (i, data_series) in data.iter().enumerate() { - // remove data that returned error while benching - // heuristic: times < 1% of y_max are invalid/had error - let filtered_data = data_series - .data - .iter() - .filter(|data_point| data_point.y > 0.01 * y_max) - .collect::>(); - - let color = Palette99::pick(i); - - // draw error bars - ctx.draw_series(filtered_data.iter().map(|data_point| { - ErrorBar::new_vertical( - data_point.x, - data_point.y - data_point.y_bar, - data_point.y, - data_point.y + data_point.y_bar, - &color, - 3, - ) - })) - .unwrap(); - - // draw lines with legend entry - ctx.draw_series(LineSeries::new( - filtered_data - .iter() - .map(|data_point| (data_point.x, data_point.y)), - color.stroke_width(2), - )) - .unwrap() - .label(&data_series.name) - .legend(move |(x, y)| Rectangle::new([(x, y - 5), (x + 10, y + 5)], color.filled())); - } - - // enable legend - ctx.configure_series_labels() - .position(SeriesLabelPosition::LowerRight) - .margin(10) - .border_style(BLACK) - .background_style(WHITE) - .draw() - .unwrap(); -} - -fn main() { - let handshake_data = get_all_data("handshake"); - let throughput_data = get_all_data("throughput"); - - // combine all versions present in handshake and throughput data - // also fill in missing version v1.3.15 and v1.3.30-v1.3.37 - let mut versions = get_unique_versions(&handshake_data); - versions.extend(get_unique_versions(&throughput_data).into_iter()); - versions.extend((15..16).chain(30..38).map(|p| Version::new(1, 3, p))); - let versions = versions.into_iter().collect::>(); - - // map versions to x coordinates - let version_to_x = versions - .iter() - .enumerate() - .map(|(i, version)| (version, i as i32)) - .collect::>(); - - // convert from Vec to Vec for plotting - let handshake_data: Vec = convert_to_data_series(handshake_data, &version_to_x); - let mut throughput_data = convert_to_data_series(throughput_data, &version_to_x); - - // convert data from ns to transfer of 100KB of data -> bytes/s throughput - throughput_data = throughput_data - .into_iter() - .map(|data_series| { - const TRANSFER_SIZE: f64 = 1e5; - const NANO_SIZE: f64 = 1e-9; - DataSeries { - name: data_series.name, - data: data_series - .data - .into_iter() - .map(|data_point| { - let mean_throughput = TRANSFER_SIZE / (data_point.y * NANO_SIZE); - let stderr_throughput = mean_throughput - - TRANSFER_SIZE / ((data_point.y + data_point.y_bar) * NANO_SIZE); - DataPoint { - x: data_point.x, - y: mean_throughput, - y_bar: stderr_throughput, - } - }) - .collect(), - } - }) - .collect(); - - let x_label_formatter = |x: &i32| format!("{}", versions[*x as usize]); - - plot_data( - &handshake_data, - "handshake", - "handshake", - &x_label_formatter, - "Time", - &|y| format!("{} ms", y / 1e6), - ); - plot_data( - &throughput_data, - "throughput", - "round trip throughput", - &x_label_formatter, - "Throughput", - &|y| format!("{} GB/s", y / 1e9), - ); -} diff --git a/bindings/rust/bench/src/bin/memory.rs b/bindings/rust/bench/src/bin/memory.rs deleted file mode 100644 index aeee51338fd..00000000000 --- a/bindings/rust/bench/src/bin/memory.rs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#[cfg(feature = "openssl")] -use bench::OpenSslConnection; -#[cfg(feature = "rustls")] -use bench::RustlsConnection; -use bench::{ - ConnectedBuffer, CryptoConfig, HandshakeType, Mode, S2NConnection, TlsConnPair, TlsConnection, -}; -use std::{error::Error, fs::create_dir_all}; -use structopt::{clap::arg_enum, StructOpt}; - -arg_enum! { - enum MemoryBenchTarget { - Client, - Server, - Pair, - } -} - -impl std::fmt::Debug for MemoryBenchTarget { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - MemoryBenchTarget::Client => "client", - MemoryBenchTarget::Server => "server", - MemoryBenchTarget::Pair => "pair", - } - ) - } -} - -/// Bench the memory taken by either a client, server, or pair of connections -fn memory_bench(opt: &Opt) -> Result<(), Box> { - let reuse_config: bool = opt.reuse_config.parse()?; - let shrink_buffers: bool = opt.shrink_buffers.parse()?; - - // store data in directory based on params, target, and library name - let params_string = match (reuse_config, shrink_buffers) { - (false, false) => "no-optimizations", - (true, false) => "reuse-config", - (false, true) => "shrink-buffers", - (true, true) => "reuse-config-shrink-buffers", - }; - let dir_name = &format!( - "target/memory/{params_string}/{:?}/{}", - opt.target, - T::name() - ); - - println!("benching {:?} {} {}", opt.target, T::name(), params_string); - - // create the directory that will hold memory snapshots and xtree - create_dir_all(dir_name).unwrap(); - - // create space to store TlsConnections - const BENCH_SIZE: usize = 100; - let mut connections = Vec::new(); - match opt.target { - MemoryBenchTarget::Client | MemoryBenchTarget::Server => { - connections.reserve_exact(BENCH_SIZE) - } - // for each connection pair, need to save two connections - MemoryBenchTarget::Pair => connections.reserve_exact(BENCH_SIZE * 2), - }; - - // reserve space for buffers before benching - // shrink buffers before and after handshake to keep memory net zero - let mut buffers: Vec = (0..BENCH_SIZE) - .map(|_| { - let mut buffer = ConnectedBuffer::new(); - buffer.shrink(); - buffer - }) - .collect(); - - // handshake one harness to initalize libraries - let mut conn_pair = TlsConnPair::::default(); - conn_pair.handshake().unwrap(); - - // make configs - let client_config = T::make_config( - Mode::Client, - CryptoConfig::default(), - HandshakeType::default(), - )?; - let server_config = T::make_config( - Mode::Server, - CryptoConfig::default(), - HandshakeType::default(), - )?; - - // tell valgrind/massif to take initial memory snapshot - crabgrind::monitor_command(format!("snapshot {dir_name}/0.snapshot")).unwrap(); - - // make and handshake conn pairs - for i in 1..BENCH_SIZE + 1 { - // make conn pair - let mut conn_pair; - if reuse_config { - let client_conn = T::new_from_config(&client_config, buffers.pop().unwrap())?; - let server_conn = T::new_from_config( - &server_config, - client_conn.connected_buffer().clone_inverse(), - )?; - conn_pair = TlsConnPair::wrap(client_conn, server_conn); - } else { - conn_pair = TlsConnPair::::new( - CryptoConfig::default(), - HandshakeType::default(), - buffers.pop().unwrap(), - )?; - } - - // handshake conn pair - conn_pair.handshake()?; - if shrink_buffers { - conn_pair.shrink_connection_buffers(); - } - conn_pair.shrink_connected_buffers(); - - // store bench target(s) - let (client, server) = conn_pair.split(); - match opt.target { - MemoryBenchTarget::Client => connections.push(client), - MemoryBenchTarget::Server => connections.push(server), - MemoryBenchTarget::Pair => { - connections.push(client); - connections.push(server); - } - }; - - // take memory snapshot - crabgrind::monitor_command(format!("snapshot {dir_name}/{i}.snapshot"))?; - } - - // take xtree snapshot - crabgrind::monitor_command(format!("xtmemory {dir_name}/xtree.out"))?; - - Ok(()) -} - -#[derive(StructOpt)] -/// Generate TLS connections and record memory used after each connection. -/// Snapshots are stored in target/memory/[params]/[target] -struct Opt { - /// Which connection(s) to memory bench - #[structopt(possible_values = &MemoryBenchTarget::variants(), case_insensitive = true, default_value = "pair")] - target: MemoryBenchTarget, - - /// If set, run benches with only a specific library - #[structopt()] - lib_name: Option, - - /// Reuse configs when making connections - #[structopt(long, default_value = "true")] - reuse_config: String, - - /// Shrink connection buffers after handshake to simulate idle connection - #[structopt(long, default_value = "true")] - shrink_buffers: String, -} - -fn main() -> Result<(), Box> { - assert!(!cfg!(debug_assertions), "need to run in release mode"); - - let opt = Opt::from_args(); - - match &opt.lib_name { - Some(lib_name) => match lib_name.as_str() { - "s2n-tls" => memory_bench::(&opt)?, - #[cfg(feature = "rustls")] - "rustls" => memory_bench::(&opt)?, - #[cfg(feature = "openssl")] - "openssl" => memory_bench::(&opt)?, - _ => panic!("invalid library"), - }, - None => { - memory_bench::(&opt)?; - #[cfg(feature = "rustls")] - memory_bench::(&opt)?; - #[cfg(feature = "openssl")] - memory_bench::(&opt)?; - } - } - - Ok(()) -} diff --git a/bindings/rust/bench/src/harness.rs b/bindings/rust/bench/src/harness.rs index c535afaf528..eff9bc629e3 100644 --- a/bindings/rust/bench/src/harness.rs +++ b/bindings/rust/bench/src/harness.rs @@ -417,11 +417,7 @@ impl Default for ConnectedBuffer { #[cfg(test)] mod tests { use super::*; - #[cfg(feature = "openssl")] - use crate::OpenSslConnection; - #[cfg(feature = "rustls")] - use crate::RustlsConnection; - use crate::{S2NConnection, TlsConnPair}; + use crate::{OpenSslConnection, RustlsConnection, S2NConnection, TlsConnPair}; use std::path::Path; use strum::IntoEnumIterator; @@ -440,9 +436,7 @@ mod tests { #[test] fn test_all() { test_type::(); - #[cfg(feature = "rustls")] test_type::(); - #[cfg(feature = "openssl")] test_type::(); } diff --git a/bindings/rust/bench/src/lib.rs b/bindings/rust/bench/src/lib.rs index e6ef9ec4333..95d92b42ab4 100644 --- a/bindings/rust/bench/src/lib.rs +++ b/bindings/rust/bench/src/lib.rs @@ -2,21 +2,17 @@ // SPDX-License-Identifier: Apache-2.0 pub mod harness; -#[cfg(feature = "openssl")] pub mod openssl; -#[cfg(feature = "rustls")] pub mod rustls; pub mod s2n_tls; -#[cfg(feature = "openssl")] -pub use crate::openssl::OpenSslConnection; -#[cfg(feature = "rustls")] -pub use crate::rustls::RustlsConnection; pub use crate::{ harness::{ get_cert_path, CipherSuite, ConnectedBuffer, CryptoConfig, HandshakeType, KXGroup, Mode, PemType, SigType, TlsConnPair, TlsConnection, }, + openssl::OpenSslConnection, + rustls::RustlsConnection, s2n_tls::S2NConnection, }; diff --git a/bindings/rust/bench/src/openssl.rs b/bindings/rust/bench/src/openssl.rs index 012f2aac0b1..24ec9e9e125 100644 --- a/bindings/rust/bench/src/openssl.rs +++ b/bindings/rust/bench/src/openssl.rs @@ -4,7 +4,8 @@ use crate::{ get_cert_path, harness::{ - CipherSuite, ConnectedBuffer, CryptoConfig, HandshakeType, KXGroup, Mode, TlsConnection, TlsBenchConfig, + CipherSuite, ConnectedBuffer, CryptoConfig, HandshakeType, KXGroup, Mode, TlsBenchConfig, + TlsConnection, }, PemType::*, }; @@ -43,7 +44,6 @@ pub struct OpenSslConfig { } impl TlsBenchConfig for OpenSslConfig { - fn make_config( mode: Mode, crypto_config: CryptoConfig, @@ -148,7 +148,6 @@ impl TlsConnection for OpenSslConnection { ) } - fn new_from_config( config: &Self::Config, connected_buffer: ConnectedBuffer,