BIO *net_rbio, *net_wbio;
} QUIC_TSERVER_ARGS;
-QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args);
+QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
+ const char *certfile, const char *keyfile);
void ossl_quic_tserver_free(QUIC_TSERVER *srv);
goto err;
}
- qc->tls = ossl_ssl_connection_new_int(ctx, TLS_client_method());
+ qc->tls = ossl_ssl_connection_new_int(ctx, TLS_method());
if (qc->tls == NULL || (sc = SSL_CONNECTION_FROM_SSL(qc->tls)) == NULL)
goto err;
/* override the user_ssl of the inner connection */
if (!qtls->configured) {
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(qtls->args.s);
+ SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(sc);
BIO *nullbio;
/*
*/
/* ALPN is a requirement for QUIC and must be set */
- if (sc->ext.alpn == NULL || sc->ext.alpn_len == 0) {
- qtls->inerror = 1;
- return 0;
+ if (qtls->args.is_server) {
+ if (sctx->ext.alpn_select_cb == NULL) {
+ qtls->inerror = 1;
+ return 0;
+ }
+ } else {
+ if (sc->ext.alpn == NULL || sc->ext.alpn_len == 0) {
+ qtls->inerror = 1;
+ return 0;
+ }
}
if (!SSL_set_min_proto_version(qtls->args.s, TLS1_3_VERSION)) {
qtls->inerror = 1;
ossl_ssl_set_custom_record_layer(sc, &quic_tls_record_method, qtls);
if (!ossl_tls_add_custom_ext_intern(NULL, &sc->cert->custext,
- ENDPOINT_CLIENT,
+ qtls->args.is_server ? ENDPOINT_SERVER
+ : ENDPOINT_CLIENT,
TLSEXT_TYPE_quic_transport_parameters,
SSL_EXT_TLS1_3_ONLY
| SSL_EXT_CLIENT_HELLO
*/
SSL_set_bio(qtls->args.s, nullbio, nullbio);
+ if (qtls->args.is_server)
+ SSL_set_accept_state(qtls->args.s);
+ else
+ SSL_set_connect_state(qtls->args.s);
+
qtls->configured = 1;
}
- ret = SSL_connect(qtls->args.s);
+ ret = SSL_do_handshake(qtls->args.s);
if (ret <= 0) {
switch (SSL_get_error(qtls->args.s, ret)) {
case SSL_ERROR_WANT_READ:
const unsigned char *transport_params,
size_t transport_params_len)
{
- if (!ossl_assert(!qtls->args.is_server)) {
- ERR_raise(ERR_LIB_SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- qtls->inerror = 1;
- return 0;
- }
-
qtls->local_transport_params = transport_params;
qtls->local_transport_params_len = transport_params_len;
return 1;
*/
QUIC_CHANNEL *ch;
+ /* SSL_CTX for creating the underlying TLS connection */
+ SSL_CTX *ctx;
+
+ /* SSL for the underlying TLS connection */
+ SSL *tls;
+
/* Our single bidirectional application data stream. */
QUIC_STREAM *stream0;
unsigned int connected : 1;
};
-QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args)
+static int alpn_select_cb(SSL *ssl, const unsigned char **out,
+ unsigned char *outlen, const unsigned char *in,
+ unsigned int inlen, void *arg)
+{
+ unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
+
+ if (SSL_select_next_proto((unsigned char **)out, outlen, alpn, sizeof(alpn),
+ in, inlen) != OPENSSL_NPN_NEGOTIATED)
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
+
+ return SSL_TLSEXT_ERR_OK;
+}
+
+QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
+ const char *certfile, const char *keyfile)
{
QUIC_TSERVER *srv = NULL;
QUIC_CHANNEL_ARGS ch_args = {0};
srv->args = *args;
+ srv->ctx = SSL_CTX_new_ex(srv->args.libctx, srv->args.propq, TLS_method());
+ if (srv->ctx == NULL)
+ goto err;
+
+ if (SSL_CTX_use_certificate_file(srv->ctx, certfile, SSL_FILETYPE_PEM) <= 0)
+ goto err;
+
+ if (SSL_CTX_use_PrivateKey_file(srv->ctx, keyfile, SSL_FILETYPE_PEM) <= 0)
+ goto err;
+
+ SSL_CTX_set_alpn_select_cb(srv->ctx, alpn_select_cb, srv);
+
+ srv->tls = SSL_new(srv->ctx);
+ if (srv->tls == NULL)
+ goto err;
+
ch_args.libctx = srv->args.libctx;
ch_args.propq = srv->args.propq;
+ ch_args.tls = srv->tls;
ch_args.is_server = 1;
if ((srv->ch = ossl_quic_channel_new(&ch_args)) == NULL)
ossl_quic_channel_free(srv->ch);
BIO_free(srv->args.net_rbio);
BIO_free(srv->args.net_wbio);
+ SSL_free(srv->tls);
+ SSL_CTX_free(srv->ctx);
OPENSSL_free(srv);
}
static const char msg1[] = "The quick brown fox jumped over the lazy dogs.";
static char msg2[1024], msg3[1024];
+static const char *certfile, *keyfile;
+
static int is_want(SSL *s, int ret)
{
int ec = SSL_get_error(s, ret);
size_t l = 0, s_total_read = 0, s_total_written = 0, c_total_read = 0;
int s_begin_write = 0;
OSSL_TIME start_time;
+ unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
ina.s_addr = htonl(0x7f000001UL);
tserver_args.net_rbio = s_net_bio;
tserver_args.net_wbio = s_net_bio;
- if (!TEST_ptr(tserver = ossl_quic_tserver_new(&tserver_args))) {
+ if (!TEST_ptr(tserver = ossl_quic_tserver_new(&tserver_args, certfile,
+ keyfile))) {
BIO_free(s_net_bio);
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);
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;
+ }
+
+ if (!TEST_ptr(certfile = test_get_argument(0))
+ || !TEST_ptr(keyfile = test_get_argument(1)))
+ return 0;
+
ADD_TEST(test_tserver);
return 1;
}
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
-use OpenSSL::Test;
+use OpenSSL::Test qw/:DEFAULT srctop_file/;
use OpenSSL::Test::Utils;
-setup("test_quic_txp");
+setup("test_quic_tserver");
plan skip_all => "QUIC protocol is not supported by this OpenSSL build"
if disabled('quic');
plan tests => 1;
-ok(run(test(["quic_tserver_test"])));
+ok(run(test(["quic_tserver_test",
+ srctop_file("test", "certs", "servercert.pem"),
+ srctop_file("test", "certs", "serverkey.pem")])));