From 6dc9974547427261db25758612b6a570083d52e6 Mon Sep 17 00:00:00 2001 From: Emilia Kasper Date: Tue, 16 Aug 2016 15:11:08 +0200 Subject: [PATCH] Port multi-buffer tests Make maximum fragment length configurable and add various fragmentation tests, in addition to the existing multi-buffer tests. Reviewed-by: Rich Salz --- test/README.ssltest.md | 13 + test/handshake_helper.c | 35 ++- test/recipes/80-test_ssl_new.t | 7 +- test/recipes/80-test_ssl_old.t | 24 +- test/ssl-tests/13-fragmentation.conf | 397 ++++++++++++++++++++++++ test/ssl-tests/13-fragmentation.conf.in | 181 +++++++++++ test/ssl_test_ctx.c | 12 +- test/ssl_test_ctx.h | 2 + test/ssl_test_ctx_test.c | 7 + test/ssl_test_ctx_test.conf | 1 + 10 files changed, 648 insertions(+), 31 deletions(-) create mode 100644 test/ssl-tests/13-fragmentation.conf create mode 100644 test/ssl-tests/13-fragmentation.conf.in diff --git a/test/README.ssltest.md b/test/README.ssltest.md index d6b020d01a..9c27da089b 100644 --- a/test/README.ssltest.md +++ b/test/README.ssltest.md @@ -60,6 +60,19 @@ When HandshakeMode is Resume or Renegotiate, the original handshake is expected to succeed. All configured test expectations are verified against the second handshake. +* ApplicationData - amount of application data bytes to send (integer, defaults + to 256 bytes). Applies to both client and server. Application data is sent in + 64kB chunks (but limited by MaxFragmentSize and available parallelization, see + below). + +* MaxFragmentSize - maximum send fragment size (integer, defaults to 512 in + tests - see `SSL_CTX_set_max_send_fragment` for documentation). Applies to + both client and server. Lowering the fragment size will split handshake and + application data up between more `SSL_write` calls, thus allowing to exercise + different code paths. In particular, if the buffer size (64kB) is at least + four times as large as the maximum fragment, interleaved multi-buffer crypto + implementations may be used on some platforms. + ### Test expectations * ExpectedResult - expected handshake outcome. One of diff --git a/test/handshake_helper.c b/test/handshake_helper.c index c4b14e7c31..6b5f834f86 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -270,6 +270,7 @@ static int server_alpn_cb(SSL *s, const unsigned char **out, */ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx, + const SSL_TEST_CTX *test, const SSL_TEST_EXTRA_CONF *extra, CTX_DATA *server_ctx_data, CTX_DATA *server2_ctx_data, @@ -278,6 +279,15 @@ static void configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx, unsigned char *ticket_keys; size_t ticket_key_len; + TEST_check(SSL_CTX_set_max_send_fragment(server_ctx, + test->max_fragment_size) == 1); + if (server2_ctx != NULL) { + TEST_check(SSL_CTX_set_max_send_fragment(server2_ctx, + test->max_fragment_size) == 1); + } + TEST_check(SSL_CTX_set_max_send_fragment(client_ctx, + test->max_fragment_size) == 1); + switch (extra->client.verify_callback) { case SSL_TEST_VERIFY_ACCEPT_ALL: SSL_CTX_set_cert_verify_callback(client_ctx, &verify_accept_cb, @@ -686,9 +696,22 @@ static char *dup_str(const unsigned char *in, size_t len) return ret; } +/* + * Note that |extra| points to the correct client/server configuration + * within |test_ctx|. When configuring the handshake, general mode settings + * are taken from |test_ctx|, and client/server-specific settings should be + * taken from |extra|. + * + * The configuration code should never reach into |test_ctx->extra| or + * |test_ctx->resume_extra| directly. + * + * (We could refactor test mode settings into a substructure. This would result + * in cleaner argument passing but would complicate the test configuration + * parsing.) + */ static HANDSHAKE_RESULT *do_handshake_internal( SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_CTX *client_ctx, - const SSL_TEST_EXTRA_CONF *extra, int app_data_size, + const SSL_TEST_CTX *test_ctx, const SSL_TEST_EXTRA_CONF *extra, SSL_SESSION *session_in, SSL_SESSION **session_out) { PEER server, client; @@ -712,15 +735,15 @@ static HANDSHAKE_RESULT *do_handshake_internal( memset(&server, 0, sizeof(server)); memset(&client, 0, sizeof(client)); - configure_handshake_ctx(server_ctx, server2_ctx, client_ctx, extra, + configure_handshake_ctx(server_ctx, server2_ctx, client_ctx, test_ctx, extra, &server_ctx_data, &server2_ctx_data, &client_ctx_data); /* Setup SSL and buffers; additional configuration happens below. */ create_peer(&server, server_ctx); create_peer(&client, client_ctx); - server.bytes_to_write = client.bytes_to_read = app_data_size; - client.bytes_to_write = server.bytes_to_read = app_data_size; + server.bytes_to_write = client.bytes_to_read = test_ctx->app_data_size; + client.bytes_to_write = server.bytes_to_read = test_ctx->app_data_size; configure_handshake_ssl(server.ssl, client.ssl, extra); if (session_in != NULL) { @@ -869,7 +892,7 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx, SSL_SESSION *session = NULL; result = do_handshake_internal(server_ctx, server2_ctx, client_ctx, - &test_ctx->extra, test_ctx->app_data_size, + test_ctx, &test_ctx->extra, NULL, &session); if (test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_SIMPLE) goto end; @@ -884,7 +907,7 @@ HANDSHAKE_RESULT *do_handshake(SSL_CTX *server_ctx, SSL_CTX *server2_ctx, HANDSHAKE_RESULT_free(result); /* We don't support SNI on second handshake yet, so server2_ctx is NULL. */ result = do_handshake_internal(resume_server_ctx, NULL, resume_client_ctx, - &test_ctx->resume_extra, test_ctx->app_data_size, + test_ctx, &test_ctx->resume_extra, session, NULL); end: SSL_SESSION_free(session); diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index 06ddbdcca4..7cd38565ea 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -29,7 +29,7 @@ map { s/\.in// } @conf_files; # We hard-code the number of tests to double-check that the globbing above # finds all files as expected. -plan tests => 12; # = scalar @conf_srcs +plan tests => 13; # = scalar @conf_srcs # Some test results depend on the configuration of enabled protocols. We only # verify generated sources in the default configuration. @@ -59,6 +59,11 @@ my %skip = ( "10-resumption.conf" => disabled("tls1_1") || disabled("tls1_2"), "11-dtls_resumption.conf" => disabled("dtls1") || disabled("dtls1_2"), "12-ct.conf" => $no_tls || $no_ct || $no_ec, + # We could run some of these tests without TLS 1.2 if we had a per-test + # disable instruction but that's a bizarre configuration not worth + # special-casing for. + # We should review this once we have TLS 1.3. + "13-fragmentation.conf" => disabled("tls1_2") ); foreach my $conf (@conf_files) { diff --git a/test/recipes/80-test_ssl_old.t b/test/recipes/80-test_ssl_old.t index 9347c9605b..ff1a50ab8f 100644 --- a/test/recipes/80-test_ssl_old.t +++ b/test/recipes/80-test_ssl_old.t @@ -79,7 +79,7 @@ my $client_sess="client.ss"; # new format in ssl_test.c and add recipes to 80-test_ssl_new.t instead. plan tests => 1 # For testss - +7 # For the first testssl + +6 # For the first testssl ; subtest 'test_ss' => sub { @@ -579,28 +579,6 @@ sub testssl { 'test tls1 with SRP auth via BIO pair'); } }; - - subtest 'Multi-buffer tests' => sub { - ###################################################################### - - plan tests => 2; - - SKIP: { - skip "Neither SSLv3 nor any TLS version are supported by this OpenSSL build", 2 - if $no_anytls; - - skip "skipping multi-buffer tests", 2 - if (POSIX::uname())[4] ne "x86_64"; - - ok(run(test([@ssltest, "-cipher", "AES128-SHA", "-bytes", "8m"]))); - - # We happen to know that AES128-SHA256 is TLSv1.2 only... for now. - skip "TLSv1.2 is not supported by this OpenSSL configuration", 1 - if $no_tls1_2; - - ok(run(test([@ssltest, "-cipher", "AES128-SHA256", "-bytes", "8m"]))); - } - }; } unlink $CAkey; diff --git a/test/ssl-tests/13-fragmentation.conf b/test/ssl-tests/13-fragmentation.conf new file mode 100644 index 0000000000..4c1e9e2b33 --- /dev/null +++ b/test/ssl-tests/13-fragmentation.conf @@ -0,0 +1,397 @@ +# Generated with generate_ssl_tests.pl + +num_tests = 16 + +test-0 = 0-one-fragment-minus-app-data +test-1 = 1-one-fragment-app-data +test-2 = 2-one-fragment-plus-app-data +test-3 = 3-small-app-data +test-4 = 4-small-app-data-large-fragment-size +test-5 = 5-medium-app-data +test-6 = 6-medium-plus-app-data +test-7 = 7-large-app-data +test-8 = 8-large-app-data-large-fragment-size +test-9 = 9-large-app-data-odd-fragment-size +test-10 = 10-large-app-data-aes-sha1-multibuffer +test-11 = 11-large-app-data-aes-sha2-multibuffer +test-12 = 12-large-app-data-aes-sha1-multibuffer-odd-fragment +test-13 = 13-large-app-data-aes-sha2-multibuffer-odd-fragment +test-14 = 14-small-app-data-aes-sha1-multibuffer +test-15 = 15-small-app-data-aes-sha2-multibuffer +# =========================================================== + +[0-one-fragment-minus-app-data] +ssl_conf = 0-one-fragment-minus-app-data-ssl + +[0-one-fragment-minus-app-data-ssl] +server = 0-one-fragment-minus-app-data-server +client = 0-one-fragment-minus-app-data-client + +[0-one-fragment-minus-app-data-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[0-one-fragment-minus-app-data-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-0] +ApplicationData = 511 + + +# =========================================================== + +[1-one-fragment-app-data] +ssl_conf = 1-one-fragment-app-data-ssl + +[1-one-fragment-app-data-ssl] +server = 1-one-fragment-app-data-server +client = 1-one-fragment-app-data-client + +[1-one-fragment-app-data-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[1-one-fragment-app-data-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-1] +ApplicationData = 512 + + +# =========================================================== + +[2-one-fragment-plus-app-data] +ssl_conf = 2-one-fragment-plus-app-data-ssl + +[2-one-fragment-plus-app-data-ssl] +server = 2-one-fragment-plus-app-data-server +client = 2-one-fragment-plus-app-data-client + +[2-one-fragment-plus-app-data-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[2-one-fragment-plus-app-data-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-2] +ApplicationData = 513 + + +# =========================================================== + +[3-small-app-data] +ssl_conf = 3-small-app-data-ssl + +[3-small-app-data-ssl] +server = 3-small-app-data-server +client = 3-small-app-data-client + +[3-small-app-data-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[3-small-app-data-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-3] +ApplicationData = 4097 + + +# =========================================================== + +[4-small-app-data-large-fragment-size] +ssl_conf = 4-small-app-data-large-fragment-size-ssl + +[4-small-app-data-large-fragment-size-ssl] +server = 4-small-app-data-large-fragment-size-server +client = 4-small-app-data-large-fragment-size-client + +[4-small-app-data-large-fragment-size-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[4-small-app-data-large-fragment-size-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-4] +ApplicationData = 4097 +MaxFragmentSize = 16384 + + +# =========================================================== + +[5-medium-app-data] +ssl_conf = 5-medium-app-data-ssl + +[5-medium-app-data-ssl] +server = 5-medium-app-data-server +client = 5-medium-app-data-client + +[5-medium-app-data-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[5-medium-app-data-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-5] +ApplicationData = 32775 + + +# =========================================================== + +[6-medium-plus-app-data] +ssl_conf = 6-medium-plus-app-data-ssl + +[6-medium-plus-app-data-ssl] +server = 6-medium-plus-app-data-server +client = 6-medium-plus-app-data-client + +[6-medium-plus-app-data-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[6-medium-plus-app-data-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-6] +ApplicationData = 131069 + + +# =========================================================== + +[7-large-app-data] +ssl_conf = 7-large-app-data-ssl + +[7-large-app-data-ssl] +server = 7-large-app-data-server +client = 7-large-app-data-client + +[7-large-app-data-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[7-large-app-data-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-7] +ApplicationData = 1048576 + + +# =========================================================== + +[8-large-app-data-large-fragment-size] +ssl_conf = 8-large-app-data-large-fragment-size-ssl + +[8-large-app-data-large-fragment-size-ssl] +server = 8-large-app-data-large-fragment-size-server +client = 8-large-app-data-large-fragment-size-client + +[8-large-app-data-large-fragment-size-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[8-large-app-data-large-fragment-size-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-8] +ApplicationData = 1048576 +MaxFragmentSize = 16384 + + +# =========================================================== + +[9-large-app-data-odd-fragment-size] +ssl_conf = 9-large-app-data-odd-fragment-size-ssl + +[9-large-app-data-odd-fragment-size-ssl] +server = 9-large-app-data-odd-fragment-size-server +client = 9-large-app-data-odd-fragment-size-client + +[9-large-app-data-odd-fragment-size-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[9-large-app-data-odd-fragment-size-client] +CipherString = DEFAULT +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-9] +ApplicationData = 1048576 +MaxFragmentSize = 5115 + + +# =========================================================== + +[10-large-app-data-aes-sha1-multibuffer] +ssl_conf = 10-large-app-data-aes-sha1-multibuffer-ssl + +[10-large-app-data-aes-sha1-multibuffer-ssl] +server = 10-large-app-data-aes-sha1-multibuffer-server +client = 10-large-app-data-aes-sha1-multibuffer-client + +[10-large-app-data-aes-sha1-multibuffer-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[10-large-app-data-aes-sha1-multibuffer-client] +CipherString = AES128-SHA +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-10] +ApplicationData = 1048576 +MaxFragmentSize = 4096 + + +# =========================================================== + +[11-large-app-data-aes-sha2-multibuffer] +ssl_conf = 11-large-app-data-aes-sha2-multibuffer-ssl + +[11-large-app-data-aes-sha2-multibuffer-ssl] +server = 11-large-app-data-aes-sha2-multibuffer-server +client = 11-large-app-data-aes-sha2-multibuffer-client + +[11-large-app-data-aes-sha2-multibuffer-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[11-large-app-data-aes-sha2-multibuffer-client] +CipherString = AES128-SHA256 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-11] +ApplicationData = 1048576 +MaxFragmentSize = 4096 + + +# =========================================================== + +[12-large-app-data-aes-sha1-multibuffer-odd-fragment] +ssl_conf = 12-large-app-data-aes-sha1-multibuffer-odd-fragment-ssl + +[12-large-app-data-aes-sha1-multibuffer-odd-fragment-ssl] +server = 12-large-app-data-aes-sha1-multibuffer-odd-fragment-server +client = 12-large-app-data-aes-sha1-multibuffer-odd-fragment-client + +[12-large-app-data-aes-sha1-multibuffer-odd-fragment-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[12-large-app-data-aes-sha1-multibuffer-odd-fragment-client] +CipherString = AES128-SHA +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-12] +ApplicationData = 1048579 +MaxFragmentSize = 5115 + + +# =========================================================== + +[13-large-app-data-aes-sha2-multibuffer-odd-fragment] +ssl_conf = 13-large-app-data-aes-sha2-multibuffer-odd-fragment-ssl + +[13-large-app-data-aes-sha2-multibuffer-odd-fragment-ssl] +server = 13-large-app-data-aes-sha2-multibuffer-odd-fragment-server +client = 13-large-app-data-aes-sha2-multibuffer-odd-fragment-client + +[13-large-app-data-aes-sha2-multibuffer-odd-fragment-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[13-large-app-data-aes-sha2-multibuffer-odd-fragment-client] +CipherString = AES128-SHA256 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-13] +ApplicationData = 1048573 +MaxFragmentSize = 5125 + + +# =========================================================== + +[14-small-app-data-aes-sha1-multibuffer] +ssl_conf = 14-small-app-data-aes-sha1-multibuffer-ssl + +[14-small-app-data-aes-sha1-multibuffer-ssl] +server = 14-small-app-data-aes-sha1-multibuffer-server +client = 14-small-app-data-aes-sha1-multibuffer-client + +[14-small-app-data-aes-sha1-multibuffer-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[14-small-app-data-aes-sha1-multibuffer-client] +CipherString = AES128-SHA +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-14] +ApplicationData = 4096 +MaxFragmentSize = 4096 + + +# =========================================================== + +[15-small-app-data-aes-sha2-multibuffer] +ssl_conf = 15-small-app-data-aes-sha2-multibuffer-ssl + +[15-small-app-data-aes-sha2-multibuffer-ssl] +server = 15-small-app-data-aes-sha2-multibuffer-server +client = 15-small-app-data-aes-sha2-multibuffer-client + +[15-small-app-data-aes-sha2-multibuffer-server] +Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem +CipherString = DEFAULT +PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem + +[15-small-app-data-aes-sha2-multibuffer-client] +CipherString = AES128-SHA256 +VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem +VerifyMode = Peer + +[test-15] +ApplicationData = 4096 +MaxFragmentSize = 4096 + + diff --git a/test/ssl-tests/13-fragmentation.conf.in b/test/ssl-tests/13-fragmentation.conf.in new file mode 100644 index 0000000000..645163ca89 --- /dev/null +++ b/test/ssl-tests/13-fragmentation.conf.in @@ -0,0 +1,181 @@ +# -*- mode: perl; -*- +# Copyright 2016-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +## Test version negotiation + +use strict; +use warnings; + +package ssltests; + + +our @tests = ( + # Default fragment size is 512. + { + name => "one-fragment-minus-app-data", + server => { }, + client => { }, + test => { + ApplicationData => 511, + } + }, + { + name => "one-fragment-app-data", + server => { }, + client => { }, + test => { + ApplicationData => 512, + } + }, + { + name => "one-fragment-plus-app-data", + server => { }, + client => { }, + test => { + ApplicationData => 513, + } + }, + { + name => "small-app-data", + server => { }, + client => { }, + test => { + ApplicationData => 4 * 1024 + 1, + } + }, + { + name => "small-app-data-large-fragment-size", + server => { }, + client => { }, + test => { + ApplicationData => 4 * 1024 + 1, + MaxFragmentSize => 16384, + } + }, + { + name => "medium-app-data", + server => { }, + client => { }, + test => { + ApplicationData => 32 * 1024 + 7, + } + }, + # Exceeds the 64kB write buffer size. + { + name => "medium-plus-app-data", + server => { }, + client => { }, + test => { + ApplicationData => 128 * 1024 - 3, + } + }, + { + name => "large-app-data", + server => { }, + client => { }, + test => { + ApplicationData => 1024 * 1024, + } + }, + { + name => "large-app-data-large-fragment-size", + server => { }, + client => { }, + test => { + ApplicationData => 1024 * 1024, + MaxFragmentSize => 16384, + } + }, + { + name => "large-app-data-odd-fragment-size", + server => { }, + client => { }, + test => { + ApplicationData => 1024 * 1024, + MaxFragmentSize => 5 * 1024 - 5, + } + }, + # When the buffer / fragment size ratio is sufficiently large, + # multi-buffer code kicks in on some platforms for AES-SHA. The + # exact minimum ratio depends on the platform, and is usually + # around 4. Since the the test buffer is 64kB, a 4kB fragment is + # easily sufficient. + # + # (We run this test on all platforms though it's only true multibuffer + # on some of them.) + { + name => "large-app-data-aes-sha1-multibuffer", + server => { }, + client => { + CipherString => "AES128-SHA", + }, + test => { + ApplicationData => 1024 * 1024, + MaxFragmentSize => 4 * 1024, + } + }, + { + name => "large-app-data-aes-sha2-multibuffer", + server => { }, + client => { + CipherString => "AES128-SHA256", + }, + test => { + ApplicationData => 1024 * 1024, + MaxFragmentSize => 4 * 1024, + } + }, + { + name => "large-app-data-aes-sha1-multibuffer-odd-fragment", + server => { }, + client => { + CipherString => "AES128-SHA", + }, + test => { + ApplicationData => 1024 * 1024 + 3, + MaxFragmentSize => 5 * 1024 - 5, + } + }, + { + name => "large-app-data-aes-sha2-multibuffer-odd-fragment", + server => { }, + client => { + CipherString => "AES128-SHA256", + }, + test => { + ApplicationData => 1024 * 1024 - 3, + MaxFragmentSize => 5 * 1024 + 5, + } + }, + # Test that multibuffer-capable code also handles small data correctly. + # Here fragment size == app data size < buffer size, + # so no multibuffering should happen. + { + name => "small-app-data-aes-sha1-multibuffer", + server => { }, + client => { + CipherString => "AES128-SHA", + }, + test => { + ApplicationData => 4 * 1024, + MaxFragmentSize => 4 * 1024, + } + }, + { + name => "small-app-data-aes-sha2-multibuffer", + server => { }, + client => { + CipherString => "AES128-SHA256", + }, + test => { + ApplicationData => 4 * 1024, + MaxFragmentSize => 4 * 1024, + } + }, +); diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c index 8c953a3add..ac90f199b2 100644 --- a/test/ssl_test_ctx.c +++ b/test/ssl_test_ctx.c @@ -17,6 +17,8 @@ #include "testutil.h" static const int default_app_data_size = 256; +/* Default set to be as small as possible to exercise fragmentation. */ +static const int default_max_fragment_size = 512; static int parse_boolean(const char *value, int *result) { @@ -389,11 +391,17 @@ IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, resumption_expected) IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, broken_session_ticket) /***********************/ -/* Applicationdata */ +/* ApplicationData */ /***********************/ IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, app_data_size) +/***********************/ +/* MaxFragmentSize */ +/***********************/ + +IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, max_fragment_size) + /*************************************************************/ /* Known test options and their corresponding parse methods. */ /*************************************************************/ @@ -417,6 +425,7 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = { { "HandshakeMode", &parse_handshake_mode }, { "ResumptionExpected", &parse_test_resumption_expected }, { "ApplicationData", &parse_test_app_data_size }, + { "MaxFragmentSize", &parse_test_max_fragment_size }, }; /* Nested client options. */ @@ -456,6 +465,7 @@ SSL_TEST_CTX *SSL_TEST_CTX_new() ret = OPENSSL_zalloc(sizeof(*ret)); TEST_check(ret != NULL); ret->app_data_size = default_app_data_size; + ret->max_fragment_size = default_max_fragment_size; return ret; } diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h index 1074f8ee72..11b6c33321 100644 --- a/test/ssl_test_ctx.h +++ b/test/ssl_test_ctx.h @@ -109,6 +109,8 @@ typedef struct { * Both peers will send |app_data_size| bytes interleaved. */ int app_data_size; + /* Maximum send fragment size. */ + int max_fragment_size; /* * Extra server/client configurations. Per-handshake. diff --git a/test/ssl_test_ctx_test.c b/test/ssl_test_ctx_test.c index f110bd1ec6..b54d7eab36 100644 --- a/test/ssl_test_ctx_test.c +++ b/test/ssl_test_ctx_test.c @@ -115,6 +115,12 @@ static int SSL_TEST_CTX_equal(SSL_TEST_CTX *ctx, SSL_TEST_CTX *ctx2) return 0; } + if (ctx->max_fragment_size != ctx2->max_fragment_size) { + fprintf(stderr, "MaxFragmentSize mismatch: %d vs %d.\n", + ctx->max_fragment_size, ctx2->max_fragment_size); + return 0; + } + if (!SSL_TEST_EXTRA_CONF_equal(&ctx->extra, &ctx2->extra)) { fprintf(stderr, "Extra conf mismatch.\n"); return 0; @@ -246,6 +252,7 @@ static int test_good_configuration() fixture.expected_ctx->method = SSL_TEST_METHOD_DTLS; fixture.expected_ctx->handshake_mode = SSL_TEST_HANDSHAKE_RESUME; fixture.expected_ctx->app_data_size = 1024; + fixture.expected_ctx->max_fragment_size = 2048; fixture.expected_ctx->expected_result = SSL_TEST_SERVER_FAIL; fixture.expected_ctx->expected_client_alert = SSL_AD_UNKNOWN_CA; diff --git a/test/ssl_test_ctx_test.conf b/test/ssl_test_ctx_test.conf index d1dbd22677..a062d75a10 100644 --- a/test/ssl_test_ctx_test.conf +++ b/test/ssl_test_ctx_test.conf @@ -9,6 +9,7 @@ resume-client = ssltest_good_resume_client_extra Method = DTLS HandshakeMode = Resume ApplicationData = 1024 +MaxFragmentSize = 2048 ExpectedResult = ServerFail ExpectedClientAlert = UnknownCA -- 2.25.1