summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2023-03-16 18:25:37 +0100
committerPauli <pauli@openssl.org>2023-03-22 00:13:30 +0100
commitfc11028089c374bb24655895c90eaf069c3cee6f (patch)
tree9c23b28c127a4b83de99bf9eb98a3f1a641f42b6
parentAdded `CERTIFICATE_VERIFY_MAX_LENGTH` constant (diff)
downloadopenssl-fc11028089c374bb24655895c90eaf069c3cee6f.tar.xz
openssl-fc11028089c374bb24655895c90eaf069c3cee6f.zip
Add simple interoperability test with Cloudflare quiche
This is an external test which requires recursive checkout of the cloudflare-quiche submodule. We simply run a client against the example quiche-server serving HTTP/0.9 requests. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20527)
-rw-r--r--.github/workflows/ci.yml18
-rw-r--r--.gitmodules3
m---------cloudflare-quiche0
-rw-r--r--test/build.info5
-rw-r--r--test/quic_client_test.c176
-rw-r--r--test/recipes/95-test_external_cf_quiche.t44
-rwxr-xr-xtest/recipes/95-test_external_cf_quiche_data/quiche-build.sh26
-rwxr-xr-xtest/recipes/95-test_external_cf_quiche_data/quiche-server.sh29
8 files changed, 301 insertions, 0 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index eb4384f926..17a87cd1e1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -410,3 +410,21 @@ jobs:
default: true
- name: test external pyca
run: make test TESTS="test_external_pyca" VERBOSE=1
+
+ external-test-cf-quiche:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ - name: Configure OpenSSL
+ run: ./config --banner=Configured --strict-warnings enable-external-tests enable-quic && perl configdata.pm --dump
+ - name: make
+ run: make -s -j4
+ - uses: actions-rs/toolchain@v1
+ with:
+ profile: default
+ toolchain: stable
+ default: true
+ - name: test external Cloudflare quiche
+ run: make test TESTS="test_external_cf_quiche" VERBOSE=1
diff --git a/.gitmodules b/.gitmodules
index 6531705b2a..ee878a96ed 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -25,3 +25,6 @@
[submodule "oqs-provider"]
path = oqs-provider
url = https://github.com/open-quantum-safe/oqs-provider.git
+[submodule "cloudflare-quiche"]
+ path = cloudflare-quiche
+ url = https://github.com/cloudflare/quiche
diff --git a/cloudflare-quiche b/cloudflare-quiche
new file mode 160000
+Subproject 24a959abf115923910ce18985aa199d85fb602d
diff --git a/test/build.info b/test/build.info
index dc3e4518ac..56d53445dc 100644
--- a/test/build.info
+++ b/test/build.info
@@ -332,6 +332,10 @@ IF[{- !$disabled{tests} -}]
INCLUDE[quic_tserver_test]=../include ../apps/include
DEPEND[quic_tserver_test]=../libcrypto.a ../libssl.a libtestutil.a
+ SOURCE[quic_client_test]=quic_client_test.c
+ INCLUDE[quic_client_test]=../include ../apps/include
+ DEPEND[quic_client_test]=../libcrypto.a ../libssl.a libtestutil.a
+
SOURCE[asynctest]=asynctest.c
INCLUDE[asynctest]=../include ../apps/include
DEPEND[asynctest]=../libcrypto
@@ -1076,6 +1080,7 @@ ENDIF
PROGRAMS{noinst}=quic_wire_test quic_ackm_test quic_record_test
PROGRAMS{noinst}=quic_fc_test quic_stream_test quic_cfq_test quic_txpim_test
PROGRAMS{noinst}=quic_fifd_test quic_txp_test quic_tserver_test
+ PROGRAMS{noinst}=quic_client_test
ENDIF
SOURCE[quic_ackm_test]=quic_ackm_test.c
diff --git a/test/quic_client_test.c b/test/quic_client_test.c
new file mode 100644
index 0000000000..81b21fda3a
--- /dev/null
+++ b/test/quic_client_test.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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
+ */
+#include <stdio.h>
+#include <openssl/ssl.h>
+#include <openssl/quic.h>
+#include <openssl/bio.h>
+#include "internal/common.h"
+#include "internal/sockets.h"
+#include "internal/time.h"
+#include "testutil.h"
+
+static const char msg1[] = "GET LICENSE.txt\r\n";
+static char msg2[16000];
+
+static int is_want(SSL *s, int ret)
+{
+ int ec = SSL_get_error(s, ret);
+
+ return ec == SSL_ERROR_WANT_READ || ec == SSL_ERROR_WANT_WRITE;
+}
+
+static int test_quic_client(void)
+{
+ int testresult = 0, ret;
+ int c_fd = INVALID_SOCKET;
+ BIO *c_net_bio = NULL, *c_net_bio_own = NULL;
+ BIO_ADDR *s_addr_ = NULL;
+ struct in_addr ina = {0};
+ SSL_CTX *c_ctx = NULL;
+ SSL *c_ssl = NULL;
+ short port = 4433;
+ int c_connected = 0, c_write_done = 0, c_shutdown = 0;
+ size_t l = 0, c_total_read = 0;
+ OSSL_TIME start_time;
+ unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '0', '.', '9' };
+
+ ina.s_addr = htonl(0x7f000001UL);
+
+ /* Setup test client. */
+ c_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0);
+ if (!TEST_int_ne(c_fd, INVALID_SOCKET))
+ goto err;
+
+ if (!TEST_true(BIO_socket_nbio(c_fd, 1)))
+ goto err;
+
+ if (!TEST_ptr(s_addr_ = BIO_ADDR_new()))
+ goto err;
+
+ if (!TEST_true(BIO_ADDR_rawmake(s_addr_, AF_INET, &ina, sizeof(ina),
+ htons(port))))
+ goto err;
+
+ if (!TEST_ptr(c_net_bio = c_net_bio_own = BIO_new_dgram(c_fd, 0)))
+ goto err;
+
+ if (!BIO_dgram_set_peer(c_net_bio, s_addr_))
+ goto err;
+
+ if (!TEST_ptr(c_ctx = SSL_CTX_new(OSSL_QUIC_client_method())))
+ goto err;
+
+ if (!TEST_ptr(c_ssl = SSL_new(c_ctx)))
+ goto err;
+
+ /* 0 is a success for SSL_set_alpn_protos() */
+ if (!TEST_false(SSL_set_alpn_protos(c_ssl, alpn, sizeof(alpn))))
+ goto err;
+
+ /* Takes ownership of our reference to the BIO. */
+ SSL_set0_rbio(c_ssl, c_net_bio);
+
+ /* Get another reference to be transferred in the SSL_set0_wbio call. */
+ if (!TEST_true(BIO_up_ref(c_net_bio))) {
+ c_net_bio_own = NULL; /* SSL_free will free the first reference. */
+ goto err;
+ }
+
+ SSL_set0_wbio(c_ssl, c_net_bio);
+ c_net_bio_own = NULL;
+
+ if (!TEST_true(SSL_set_blocking_mode(c_ssl, 0)))
+ goto err;
+
+ start_time = ossl_time_now();
+
+ for (;;) {
+ if (ossl_time_compare(ossl_time_subtract(ossl_time_now(), start_time),
+ ossl_ms2time(3000)) >= 0) {
+ TEST_error("timeout while attempting QUIC client test");
+ goto err;
+ }
+
+ if (!c_connected) {
+ ret = SSL_connect(c_ssl);
+ if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
+ goto err;
+
+ if (ret == 1) {
+ c_connected = 1;
+ TEST_info("Connected!");
+ }
+ }
+
+ if (c_connected && !c_write_done) {
+ if (!TEST_int_eq(SSL_write(c_ssl, msg1, sizeof(msg1) - 1),
+ (int)sizeof(msg1) - 1))
+ goto err;
+
+ if (!TEST_true(SSL_stream_conclude(c_ssl, 0)))
+ goto err;
+
+ c_write_done = 1;
+ }
+
+ if (c_write_done && !c_shutdown && c_total_read < sizeof(msg2) - 1) {
+ ret = SSL_read_ex(c_ssl, msg2 + c_total_read,
+ sizeof(msg2) - 1 - c_total_read, &l);
+ if (ret != 1) {
+ if (SSL_get_error(c_ssl, ret) == SSL_ERROR_ZERO_RETURN) {
+ c_shutdown = 1;
+ TEST_info("Message: \n%s\n", msg2);
+ } else if (!TEST_true(is_want(c_ssl, ret))) {
+ goto err;
+ }
+ } else {
+ c_total_read += l;
+
+ if (!TEST_size_t_lt(c_total_read, sizeof(msg2) - 1))
+ goto err;
+ }
+ }
+
+ if (c_shutdown) {
+ ret = SSL_shutdown(c_ssl);
+ if (ret == 1)
+ break;
+ }
+
+ /*
+ * This is inefficient because we spin until things work without
+ * blocking but this is just a test.
+ */
+ OSSL_sleep(0);
+ SSL_tick(c_ssl);
+ }
+
+ testresult = 1;
+err:
+ SSL_free(c_ssl);
+ SSL_CTX_free(c_ctx);
+ BIO_ADDR_free(s_addr_);
+ BIO_free(c_net_bio_own);
+ if (c_fd != INVALID_SOCKET)
+ BIO_closesocket(c_fd);
+ return testresult;
+}
+
+OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
+
+int setup_tests(void)
+{
+ if (!test_skip_common_options()) {
+ TEST_error("Error parsing test options\n");
+ return 0;
+ }
+
+ ADD_TEST(test_quic_client);
+ return 1;
+}
diff --git a/test/recipes/95-test_external_cf_quiche.t b/test/recipes/95-test_external_cf_quiche.t
new file mode 100644
index 0000000000..133038fd19
--- /dev/null
+++ b/test/recipes/95-test_external_cf_quiche.t
@@ -0,0 +1,44 @@
+#! /usr/bin/env perl
+# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (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
+
+
+use OpenSSL::Test;
+use OpenSSL::Test::Utils;
+use OpenSSL::Test qw/:DEFAULT data_file bldtop_dir srctop_dir srctop_file/;
+
+setup("test_external_cf_quiche");
+
+plan skip_all => "No external tests in this configuration"
+ if disabled("external-tests");
+plan skip_all => "Cloudflare quiche tests not available on Windows or VMS"
+ if $^O =~ /^(VMS|MSWin32)$/;
+plan skip_all => "Cloudflare quiche tests only available with QUIC support"
+ if disabled("quic");
+plan skip_all => "Cloudflare & Boringssl not checked out"
+ if ! -f srctop_file("cloudflare-quiche", "quiche", "deps", "boringssl", "LICENSE");
+
+plan tests => 3;
+
+ok(run(cmd(["sh", data_file("quiche-build.sh")])),
+ "running Cloudflare quiche build");
+
+ok(run(cmd(["sh", data_file("quiche-server.sh")])),
+ "running Cloudflare quiche server");
+
+ok(run(test(["quic_client_test"])),
+ "running quic_client_test");
+
+open my $fh, '<', "server.pid"
+ or die "Error opening server.pid - $!\n";
+$serverpid = <$fh>;
+close($fh);
+
+kill('TERM', $serverpid);
+sleep(1);
+kill('KILL', $serverpid);
+waitpid($serverpid, 0);
diff --git a/test/recipes/95-test_external_cf_quiche_data/quiche-build.sh b/test/recipes/95-test_external_cf_quiche_data/quiche-build.sh
new file mode 100755
index 0000000000..5444d4e060
--- /dev/null
+++ b/test/recipes/95-test_external_cf_quiche_data/quiche-build.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (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
+
+#
+# Build the Cloudflare quiche
+#
+set -e
+
+SRCTOP="$(cd $SRCTOP; pwd)"
+BLDTOP="$(cd $BLDTOP; pwd)"
+
+echo "------------------------------------------------------------------"
+echo "Building Cloudflare quiche"
+echo "------------------------------------------------------------------"
+
+QUICHE_TARGET_PATH="$BLDTOP/quiche"
+test -d "$QUICHE_TARGET_PATH" || mkdir "$QUICHE_TARGET_PATH"
+echo " QUICHE_TARGET_PATH: $QUICHE_TARGET_PATH"
+
+(cd "$SRCTOP/cloudflare-quiche" && cargo build --verbose --target-dir "$QUICHE_TARGET_PATH")
diff --git a/test/recipes/95-test_external_cf_quiche_data/quiche-server.sh b/test/recipes/95-test_external_cf_quiche_data/quiche-server.sh
new file mode 100755
index 0000000000..4ed566a575
--- /dev/null
+++ b/test/recipes/95-test_external_cf_quiche_data/quiche-server.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (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
+
+#
+# Run the quiche server
+#
+set -e
+
+SRCTOP="$(cd $SRCTOP; pwd)"
+BLDTOP="$(cd $BLDTOP; pwd)"
+
+echo "------------------------------------------------------------------"
+echo "Running Cloudflare quiche-server"
+echo "------------------------------------------------------------------"
+
+QUICHE_TARGET_PATH="$BLDTOP/quiche"
+test -d "$QUICHE_TARGET_PATH" || exit 1
+
+"$QUICHE_TARGET_PATH/debug/quiche-server" --cert "$SRCTOP/test/certs/servercert.pem" \
+ --key "$SRCTOP/test/certs/serverkey.pem" --disable-gso \
+ --http-version HTTP/0.9 --root "$SRCTOP" --no-grease --disable-hystart &
+
+echo $! >server.pid