src: Enable HTTP/3 with boringssl
This commit is contained in:
parent
c790ee64a4
commit
7055501efd
50
configure.ac
50
configure.ac
|
@ -474,6 +474,7 @@ if test "x${request_openssl}" != "xno"; then
|
||||||
CFLAGS="$OPENSSL_CFLAGS $CFLAGS"
|
CFLAGS="$OPENSSL_CFLAGS $CFLAGS"
|
||||||
LIBS="$OPENSSL_LIBS $LIBS"
|
LIBS="$OPENSSL_LIBS $LIBS"
|
||||||
|
|
||||||
|
# quictls/openssl has SSL_is_quic.
|
||||||
have_ssl_is_quic=no
|
have_ssl_is_quic=no
|
||||||
AC_MSG_CHECKING([for SSL_is_quic])
|
AC_MSG_CHECKING([for SSL_is_quic])
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
@ -485,6 +486,17 @@ if test "x${request_openssl}" != "xno"; then
|
||||||
[AC_MSG_RESULT([yes]); have_ssl_is_quic=yes],
|
[AC_MSG_RESULT([yes]); have_ssl_is_quic=yes],
|
||||||
[AC_MSG_RESULT([no]); have_ssl_is_quic=no])
|
[AC_MSG_RESULT([no]); have_ssl_is_quic=no])
|
||||||
|
|
||||||
|
# boringssl has SSL_set_quic_early_data_context.
|
||||||
|
AC_MSG_CHECKING([for SSL_set_quic_early_data_context])
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
]], [[
|
||||||
|
SSL *ssl = NULL;
|
||||||
|
SSL_set_quic_early_data_context(ssl, NULL, 0);
|
||||||
|
]])],
|
||||||
|
[AC_MSG_RESULT([yes]); have_boringssl_quic=yes],
|
||||||
|
[AC_MSG_RESULT([no]); have_boringssl_quic=no])
|
||||||
|
|
||||||
CFLAGS="$save_CFLAGS"
|
CFLAGS="$save_CFLAGS"
|
||||||
LIBS="$save_LIBS"
|
LIBS="$save_LIBS"
|
||||||
fi
|
fi
|
||||||
|
@ -527,21 +539,48 @@ fi
|
||||||
|
|
||||||
# ngtcp2_crypto_openssl (for src)
|
# ngtcp2_crypto_openssl (for src)
|
||||||
have_libngtcp2_crypto_openssl=no
|
have_libngtcp2_crypto_openssl=no
|
||||||
if test "x${request_libngtcp2}" != "xno"; then
|
if test "x${have_ssl_is_quic}" = "xyes" &&
|
||||||
|
test "x${request_libngtcp2}" != "xno"; then
|
||||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_OPENSSL],
|
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_OPENSSL],
|
||||||
[libngtcp2_crypto_openssl >= 0.0.0],
|
[libngtcp2_crypto_openssl >= 0.0.0],
|
||||||
[have_libngtcp2_crypto_openssl=yes],
|
[have_libngtcp2_crypto_openssl=yes],
|
||||||
[have_libngtcp2_crypto_openssl=no])
|
[have_libngtcp2_crypto_openssl=no])
|
||||||
if test "x${have_libngtcp2_crypto_openssl}" = "xno"; then
|
if test "x${have_libngtcp2_crypto_openssl}" = "xno"; then
|
||||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_OPENSSL_PKG_ERRORS)
|
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_OPENSSL_PKG_ERRORS)
|
||||||
|
else
|
||||||
|
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_OPENSSL], [1],
|
||||||
|
[Define to 1 if you have `libngtcp2_crypto_openssl` library.])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x${request_libngtcp2}" = "xyes" &&
|
if test "x${have_ssl_is_quic}" = "xyes" &&
|
||||||
|
test "x${request_libngtcp2}" = "xyes" &&
|
||||||
test "x${have_libngtcp2_crypto_openssl}" != "xyes"; then
|
test "x${have_libngtcp2_crypto_openssl}" != "xyes"; then
|
||||||
AC_MSG_ERROR([libngtcp2_crypto_openssl was requested (--with-libngtcp2) but not found])
|
AC_MSG_ERROR([libngtcp2_crypto_openssl was requested (--with-libngtcp2) but not found])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ngtcp2_crypto_boringssl (for src)
|
||||||
|
have_libngtcp2_crypto_boringssl=no
|
||||||
|
if test "x${have_boringssl_quic}" = "xyes" &&
|
||||||
|
test "x${request_libngtcp2}" != "xno"; then
|
||||||
|
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_BORINGSSL],
|
||||||
|
[libngtcp2_crypto_boringssl >= 0.0.0],
|
||||||
|
[have_libngtcp2_crypto_boringssl=yes],
|
||||||
|
[have_libngtcp2_crypto_boringssl=no])
|
||||||
|
if test "x${have_libngtcp2_crypto_boringssl}" = "xno"; then
|
||||||
|
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_BORINGSSL_PKG_ERRORS)
|
||||||
|
else
|
||||||
|
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_BORINGSSL], [1],
|
||||||
|
[Define to 1 if you have `libngtcp2_crypto_boringssl` library.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x${have_boringssl_quic}" = "xyes" &&
|
||||||
|
test "x${request_libngtcp2}" = "xyes" &&
|
||||||
|
test "x${have_libngtcp2_crypto_boringssl}" != "xyes"; then
|
||||||
|
AC_MSG_ERROR([libngtcp2_crypto_boringssl was requested (--with-libngtcp2) but not found])
|
||||||
|
fi
|
||||||
|
|
||||||
# nghttp3 (for src)
|
# nghttp3 (for src)
|
||||||
have_libnghttp3=no
|
have_libnghttp3=no
|
||||||
if test "x${request_libnghttp3}" != "xno"; then
|
if test "x${request_libnghttp3}" != "xno"; then
|
||||||
|
@ -749,9 +788,11 @@ AM_CONDITIONAL([ENABLE_APP], [ test "x${enable_app}" = "xyes" ])
|
||||||
# Check HTTP/3 support
|
# Check HTTP/3 support
|
||||||
enable_http3=no
|
enable_http3=no
|
||||||
if test "x${request_http3}" != "xno" &&
|
if test "x${request_http3}" != "xno" &&
|
||||||
test "x${have_ssl_is_quic}" = "xyes" &&
|
(test "x${have_ssl_is_quic}" = "xyes" ||
|
||||||
|
test "x${have_boringssl_quic}" = "xyes") &&
|
||||||
test "x${have_libngtcp2}" = "xyes" &&
|
test "x${have_libngtcp2}" = "xyes" &&
|
||||||
test "x${have_libngtcp2_crypto_openssl}" = "xyes" &&
|
(test "x${have_libngtcp2_crypto_openssl}" = "xyes" ||
|
||||||
|
test "x${have_libngtcp2_crypto_boringssl}" = "xyes") &&
|
||||||
test "x${have_libnghttp3}" = "xyes"; then
|
test "x${have_libnghttp3}" = "xyes"; then
|
||||||
enable_http3=yes
|
enable_http3=yes
|
||||||
AC_DEFINE([ENABLE_HTTP3], [1], [Define to 1 if HTTP/3 is enabled.])
|
AC_DEFINE([ENABLE_HTTP3], [1], [Define to 1 if HTTP/3 is enabled.])
|
||||||
|
@ -1184,6 +1225,7 @@ AC_MSG_NOTICE([summary of build options:
|
||||||
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||||
libngtcp2: ${have_libngtcp2} (CFLAGS='${LIBNGTCP2_CFLAGS}' LIBS='${LIBNGTCP2_LIBS}')
|
libngtcp2: ${have_libngtcp2} (CFLAGS='${LIBNGTCP2_CFLAGS}' LIBS='${LIBNGTCP2_LIBS}')
|
||||||
libngtcp2_crypto_openssl: ${have_libngtcp2_crypto_openssl} (CFLAGS='${LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_OPENSSL_LIBS}')
|
libngtcp2_crypto_openssl: ${have_libngtcp2_crypto_openssl} (CFLAGS='${LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_OPENSSL_LIBS}')
|
||||||
|
libngtcp2_crypto_boringssl: ${have_libngtcp2_crypto_boringssl} (CFLAGS='${LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_BORINGSSL_LIBS}')
|
||||||
libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}')
|
libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}')
|
||||||
libbpf: ${have_libbpf} (CFLAGS='${LIBBPF_CFLAGS}' LIBS='${LIBBPF_LIBS}')
|
libbpf: ${have_libbpf} (CFLAGS='${LIBBPF_CFLAGS}' LIBS='${LIBBPF_LIBS}')
|
||||||
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
||||||
|
|
|
@ -47,6 +47,7 @@ AM_CPPFLAGS = \
|
||||||
@LIBEV_CFLAGS@ \
|
@LIBEV_CFLAGS@ \
|
||||||
@LIBNGHTTP3_CFLAGS@ \
|
@LIBNGHTTP3_CFLAGS@ \
|
||||||
@LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@ \
|
@LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@ \
|
||||||
|
@LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ \
|
||||||
@LIBNGTCP2_CFLAGS@ \
|
@LIBNGTCP2_CFLAGS@ \
|
||||||
@OPENSSL_CFLAGS@ \
|
@OPENSSL_CFLAGS@ \
|
||||||
@LIBCARES_CFLAGS@ \
|
@LIBCARES_CFLAGS@ \
|
||||||
|
@ -65,6 +66,7 @@ LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||||
@LIBEV_LIBS@ \
|
@LIBEV_LIBS@ \
|
||||||
@LIBNGHTTP3_LIBS@ \
|
@LIBNGHTTP3_LIBS@ \
|
||||||
@LIBNGTCP2_CRYPTO_OPENSSL_LIBS@ \
|
@LIBNGTCP2_CRYPTO_OPENSSL_LIBS@ \
|
||||||
|
@LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ \
|
||||||
@LIBNGTCP2_LIBS@ \
|
@LIBNGTCP2_LIBS@ \
|
||||||
@OPENSSL_LIBS@ \
|
@OPENSSL_LIBS@ \
|
||||||
@LIBCARES_LIBS@ \
|
@LIBCARES_LIBS@ \
|
||||||
|
|
|
@ -474,8 +474,10 @@ struct Client {
|
||||||
int quic_stream_stop_sending(int64_t stream_id, uint64_t app_error_code);
|
int quic_stream_stop_sending(int64_t stream_id, uint64_t app_error_code);
|
||||||
int quic_extend_max_local_streams();
|
int quic_extend_max_local_streams();
|
||||||
|
|
||||||
int quic_on_key(ngtcp2_crypto_level level, const uint8_t *rx_secret,
|
int quic_on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||||
const uint8_t *tx_secret, size_t secretlen);
|
size_t secretlen);
|
||||||
|
int quic_on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||||
|
size_t secretlen);
|
||||||
void quic_set_tls_alert(uint8_t alert);
|
void quic_set_tls_alert(uint8_t alert);
|
||||||
|
|
||||||
void quic_write_client_handshake(ngtcp2_crypto_level level,
|
void quic_write_client_handshake(ngtcp2_crypto_level level,
|
||||||
|
|
|
@ -28,7 +28,12 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <ngtcp2/ngtcp2_crypto_openssl.h>
|
#ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||||
|
# include <ngtcp2/ngtcp2_crypto_openssl.h>
|
||||||
|
#endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||||
|
#ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||||
|
# include <ngtcp2/ngtcp2_crypto_boringssl.h>
|
||||||
|
#endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||||
|
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
@ -236,15 +241,19 @@ ngtcp2_tstamp timestamp(struct ev_loop *loop) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||||
namespace {
|
namespace {
|
||||||
int set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
|
int set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
|
||||||
const uint8_t *rx_secret, const uint8_t *tx_secret,
|
const uint8_t *rx_secret, const uint8_t *tx_secret,
|
||||||
size_t secret_len) {
|
size_t secret_len) {
|
||||||
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||||
|
auto level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
|
||||||
|
|
||||||
if (c->quic_on_key(
|
if (c->quic_on_rx_secret(level, rx_secret, secret_len) != 0) {
|
||||||
ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level),
|
return 0;
|
||||||
rx_secret, tx_secret, secret_len) != 0) {
|
}
|
||||||
|
|
||||||
|
if (c->quic_on_tx_secret(level, tx_secret, secret_len) != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,6 +291,70 @@ auto quic_method = SSL_QUIC_METHOD{
|
||||||
send_alert,
|
send_alert,
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
#endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||||
|
namespace {
|
||||||
|
int set_read_secret(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||||
|
const SSL_CIPHER *cipher, const uint8_t *secret,
|
||||||
|
size_t secretlen) {
|
||||||
|
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||||
|
|
||||||
|
if (c->quic_on_rx_secret(
|
||||||
|
ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), secret,
|
||||||
|
secretlen) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int set_write_secret(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||||
|
const SSL_CIPHER *cipher, const uint8_t *secret,
|
||||||
|
size_t secretlen) {
|
||||||
|
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||||
|
|
||||||
|
if (c->quic_on_tx_secret(
|
||||||
|
ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), secret,
|
||||||
|
secretlen) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int add_handshake_data(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||||
|
const uint8_t *data, size_t len) {
|
||||||
|
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||||
|
c->quic_write_client_handshake(
|
||||||
|
ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level), data, len);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int flush_flight(SSL *ssl) { return 1; }
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int send_alert(SSL *ssl, ssl_encryption_level_t level, uint8_t alert) {
|
||||||
|
auto c = static_cast<Client *>(SSL_get_app_data(ssl));
|
||||||
|
c->quic_set_tls_alert(alert);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
auto quic_method = SSL_QUIC_METHOD{
|
||||||
|
set_read_secret, set_write_secret, add_handshake_data,
|
||||||
|
flush_flight, send_alert,
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
#endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||||
|
|
||||||
// qlog write callback -- excerpted from ngtcp2/examples/client_base.cc
|
// qlog write callback -- excerpted from ngtcp2/examples/client_base.cc
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -462,24 +535,16 @@ void Client::quic_close_connection() {
|
||||||
ps.path.remote.addrlen, buf.data(), nwrite, 0);
|
ps.path.remote.addrlen, buf.data(), nwrite, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Client::quic_on_key(ngtcp2_crypto_level level, const uint8_t *rx_secret,
|
int Client::quic_on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||||
const uint8_t *tx_secret, size_t secretlen) {
|
size_t secretlen) {
|
||||||
if (ngtcp2_crypto_derive_and_install_rx_key(quic.conn, nullptr, nullptr,
|
if (ngtcp2_crypto_derive_and_install_rx_key(quic.conn, nullptr, nullptr,
|
||||||
nullptr, level, rx_secret,
|
nullptr, level, secret,
|
||||||
secretlen) != 0) {
|
secretlen) != 0) {
|
||||||
std::cerr << "ngtcp2_crypto_derive_and_install_rx_key() failed"
|
std::cerr << "ngtcp2_crypto_derive_and_install_rx_key() failed"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngtcp2_crypto_derive_and_install_tx_key(quic.conn, nullptr, nullptr,
|
|
||||||
nullptr, level, tx_secret,
|
|
||||||
secretlen) != 0) {
|
|
||||||
std::cerr << "ngtcp2_crypto_derive_and_install_tx_key() failed"
|
|
||||||
<< std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
|
if (level == NGTCP2_CRYPTO_LEVEL_APPLICATION) {
|
||||||
auto s = std::make_unique<Http3Session>(this);
|
auto s = std::make_unique<Http3Session>(this);
|
||||||
if (s->init_conn() == -1) {
|
if (s->init_conn() == -1) {
|
||||||
|
@ -491,6 +556,19 @@ int Client::quic_on_key(ngtcp2_crypto_level level, const uint8_t *rx_secret,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Client::quic_on_tx_secret(ngtcp2_crypto_level level, const uint8_t *secret,
|
||||||
|
size_t secretlen) {
|
||||||
|
if (ngtcp2_crypto_derive_and_install_tx_key(quic.conn, nullptr, nullptr,
|
||||||
|
nullptr, level, secret,
|
||||||
|
secretlen) != 0) {
|
||||||
|
std::cerr << "ngtcp2_crypto_derive_and_install_tx_key() failed"
|
||||||
|
<< std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Client::quic_set_tls_alert(uint8_t alert) {
|
void Client::quic_set_tls_alert(uint8_t alert) {
|
||||||
quic.last_error = quic::err_transport_tls(alert);
|
quic.last_error = quic::err_transport_tls(alert);
|
||||||
}
|
}
|
||||||
|
|
|
@ -740,9 +740,9 @@ void ConnectionHandler::handle_ocsp_complete() {
|
||||||
// that case we get nullptr.
|
// that case we get nullptr.
|
||||||
auto quic_ssl_ctx = quic_all_ssl_ctx_[ocsp_.next];
|
auto quic_ssl_ctx = quic_all_ssl_ctx_[ocsp_.next];
|
||||||
if (quic_ssl_ctx) {
|
if (quic_ssl_ctx) {
|
||||||
|
# ifndef OPENSSL_IS_BORINGSSL
|
||||||
auto quic_tls_ctx_data = static_cast<tls::TLSContextData *>(
|
auto quic_tls_ctx_data = static_cast<tls::TLSContextData *>(
|
||||||
SSL_CTX_get_app_data(quic_ssl_ctx));
|
SSL_CTX_get_app_data(quic_ssl_ctx));
|
||||||
# ifndef OPENSSL_IS_BORINGSSL
|
|
||||||
# ifdef HAVE_ATOMIC_STD_SHARED_PTR
|
# ifdef HAVE_ATOMIC_STD_SHARED_PTR
|
||||||
std::atomic_store_explicit(
|
std::atomic_store_explicit(
|
||||||
&quic_tls_ctx_data->ocsp_data,
|
&quic_tls_ctx_data->ocsp_data,
|
||||||
|
|
|
@ -613,6 +613,40 @@ int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr,
|
||||||
params.max_idle_timeout = static_cast<ngtcp2_tstamp>(
|
params.max_idle_timeout = static_cast<ngtcp2_tstamp>(
|
||||||
quicconf.upstream.timeout.idle * NGTCP2_SECONDS);
|
quicconf.upstream.timeout.idle * NGTCP2_SECONDS);
|
||||||
|
|
||||||
|
#ifdef OPENSSL_IS_BORINGSSL
|
||||||
|
if (quicconf.upstream.early_data) {
|
||||||
|
ngtcp2_transport_params early_data_params{
|
||||||
|
.initial_max_stream_data_bidi_local =
|
||||||
|
params.initial_max_stream_data_bidi_local,
|
||||||
|
.initial_max_stream_data_bidi_remote =
|
||||||
|
params.initial_max_stream_data_bidi_remote,
|
||||||
|
.initial_max_stream_data_uni = params.initial_max_stream_data_uni,
|
||||||
|
.initial_max_data = params.initial_max_data,
|
||||||
|
.initial_max_streams_bidi = params.initial_max_streams_bidi,
|
||||||
|
.initial_max_streams_uni = params.initial_max_streams_uni,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO include HTTP/3 SETTINGS
|
||||||
|
|
||||||
|
std::array<uint8_t, 128> quic_early_data_ctx;
|
||||||
|
|
||||||
|
auto quic_early_data_ctxlen = ngtcp2_encode_transport_params(
|
||||||
|
quic_early_data_ctx.data(), quic_early_data_ctx.size(),
|
||||||
|
NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS, &early_data_params);
|
||||||
|
|
||||||
|
assert(quic_early_data_ctxlen > 0);
|
||||||
|
assert(static_cast<size_t>(quic_early_data_ctxlen) <=
|
||||||
|
quic_early_data_ctx.size());
|
||||||
|
|
||||||
|
if (SSL_set_quic_early_data_context(handler_->get_ssl(),
|
||||||
|
quic_early_data_ctx.data(),
|
||||||
|
quic_early_data_ctxlen) != 1) {
|
||||||
|
ULOG(ERROR, this) << "SSL_set_quic_early_data_context failed";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // OPENSSL_IS_BORINGSSL
|
||||||
|
|
||||||
if (odcid) {
|
if (odcid) {
|
||||||
params.original_dcid = *odcid;
|
params.original_dcid = *odcid;
|
||||||
params.retry_scid = initial_hd.dcid;
|
params.retry_scid = initial_hd.dcid;
|
||||||
|
|
|
@ -369,7 +369,9 @@ ClientHandler *QUICConnectionHandler::handle_new_connection(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
assert(SSL_is_quic(ssl));
|
assert(SSL_is_quic(ssl));
|
||||||
|
#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
|
|
||||||
SSL_set_accept_state(ssl);
|
SSL_set_accept_state(ssl);
|
||||||
|
|
||||||
|
@ -377,7 +379,11 @@ ClientHandler *QUICConnectionHandler::handle_new_connection(
|
||||||
auto &quicconf = config->quic;
|
auto &quicconf = config->quic;
|
||||||
|
|
||||||
if (quicconf.upstream.early_data) {
|
if (quicconf.upstream.early_data) {
|
||||||
|
#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
SSL_set_quic_early_data_enabled(ssl, 1);
|
SSL_set_quic_early_data_enabled(ssl, 1);
|
||||||
|
#else // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL))
|
||||||
|
SSL_set_early_data_enabled(ssl, 1);
|
||||||
|
#endif // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable TLS session ticket if we don't have working ticket
|
// Disable TLS session ticket if we don't have working ticket
|
||||||
|
|
107
src/shrpx_tls.cc
107
src/shrpx_tls.cc
|
@ -61,8 +61,13 @@
|
||||||
#ifdef ENABLE_HTTP3
|
#ifdef ENABLE_HTTP3
|
||||||
# include <ngtcp2/ngtcp2.h>
|
# include <ngtcp2/ngtcp2.h>
|
||||||
# include <ngtcp2/ngtcp2_crypto.h>
|
# include <ngtcp2/ngtcp2_crypto.h>
|
||||||
# include <ngtcp2/ngtcp2_crypto_openssl.h>
|
# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||||
#endif // ENABLE_HTTP3
|
# include <ngtcp2/ngtcp2_crypto_openssl.h>
|
||||||
|
# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||||
|
# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||||
|
# include <ngtcp2/ngtcp2_crypto_boringssl.h>
|
||||||
|
# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||||
|
#endif // ENABLE_HTTP3
|
||||||
|
|
||||||
#include "shrpx_log.h"
|
#include "shrpx_log.h"
|
||||||
#include "shrpx_client_handler.h"
|
#include "shrpx_client_handler.h"
|
||||||
|
@ -196,8 +201,9 @@ int servername_callback(SSL *ssl, int *al, void *arg) {
|
||||||
auto hostname = StringRef{std::begin(buf), end_buf};
|
auto hostname = StringRef{std::begin(buf), end_buf};
|
||||||
|
|
||||||
#ifdef ENABLE_HTTP3
|
#ifdef ENABLE_HTTP3
|
||||||
auto cert_tree = SSL_is_quic(ssl) ? worker->get_quic_cert_lookup_tree()
|
auto cert_tree = conn->proto == Proto::HTTP3
|
||||||
: worker->get_cert_lookup_tree();
|
? worker->get_quic_cert_lookup_tree()
|
||||||
|
: worker->get_cert_lookup_tree();
|
||||||
#else // !ENABLE_HTTP3
|
#else // !ENABLE_HTTP3
|
||||||
auto cert_tree = worker->get_cert_lookup_tree();
|
auto cert_tree = worker->get_cert_lookup_tree();
|
||||||
#endif // !ENABLE_HTTP3
|
#endif // !ENABLE_HTTP3
|
||||||
|
@ -212,7 +218,7 @@ int servername_callback(SSL *ssl, int *al, void *arg) {
|
||||||
auto conn_handler = worker->get_connection_handler();
|
auto conn_handler = worker->get_connection_handler();
|
||||||
|
|
||||||
#ifdef ENABLE_HTTP3
|
#ifdef ENABLE_HTTP3
|
||||||
const auto &ssl_ctx_list = SSL_is_quic(ssl)
|
const auto &ssl_ctx_list = conn->proto == Proto::HTTP3
|
||||||
? conn_handler->get_quic_indexed_ssl_ctx(idx)
|
? conn_handler->get_quic_indexed_ssl_ctx(idx)
|
||||||
: conn_handler->get_indexed_ssl_ctx(idx);
|
: conn_handler->get_indexed_ssl_ctx(idx);
|
||||||
#else // !ENABLE_HTTP3
|
#else // !ENABLE_HTTP3
|
||||||
|
@ -1196,6 +1202,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_HTTP3
|
#ifdef ENABLE_HTTP3
|
||||||
|
# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||||
namespace {
|
namespace {
|
||||||
int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
|
int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
|
||||||
const uint8_t *rx_secret,
|
const uint8_t *rx_secret,
|
||||||
|
@ -1259,6 +1266,84 @@ auto quic_method = SSL_QUIC_METHOD{
|
||||||
quic_send_alert,
|
quic_send_alert,
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||||
|
|
||||||
|
# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||||
|
namespace {
|
||||||
|
int quic_set_read_secret(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||||
|
const SSL_CIPHER *cipher, const uint8_t *secret,
|
||||||
|
size_t secretlen) {
|
||||||
|
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||||
|
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||||
|
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||||
|
auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level);
|
||||||
|
|
||||||
|
if (upstream->on_rx_secret(level, secret, secretlen) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int quic_set_write_secret(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||||
|
const SSL_CIPHER *cipher, const uint8_t *secret,
|
||||||
|
size_t secretlen) {
|
||||||
|
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||||
|
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||||
|
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||||
|
auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level);
|
||||||
|
|
||||||
|
if (upstream->on_tx_secret(level, secret, secretlen) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int quic_add_handshake_data(SSL *ssl, ssl_encryption_level_t ssl_level,
|
||||||
|
const uint8_t *data, size_t len) {
|
||||||
|
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||||
|
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||||
|
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||||
|
auto level = ngtcp2_crypto_boringssl_from_ssl_encryption_level(ssl_level);
|
||||||
|
|
||||||
|
upstream->add_crypto_data(level, data, len);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int quic_flush_flight(SSL *ssl) { return 1; }
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int quic_send_alert(SSL *ssl, ssl_encryption_level_t level, uint8_t alert) {
|
||||||
|
auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
|
||||||
|
auto handler = static_cast<ClientHandler *>(conn->data);
|
||||||
|
auto upstream = static_cast<Http3Upstream *>(handler->get_upstream());
|
||||||
|
|
||||||
|
if (!upstream) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream->set_tls_alert(alert);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
auto quic_method = SSL_QUIC_METHOD{
|
||||||
|
quic_set_read_secret, quic_set_write_secret, quic_add_handshake_data,
|
||||||
|
quic_flush_flight, quic_send_alert,
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
|
||||||
|
|
||||||
SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
||||||
const char *cert_file,
|
const char *cert_file,
|
||||||
|
@ -1279,14 +1364,14 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE |
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE |
|
||||||
SSL_OP_SINGLE_DH_USE |
|
SSL_OP_SINGLE_DH_USE |
|
||||||
SSL_OP_CIPHER_SERVER_PREFERENCE
|
SSL_OP_CIPHER_SERVER_PREFERENCE
|
||||||
# if OPENSSL_1_1_1_API
|
# if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
// The reason for disabling built-in anti-replay in OpenSSL is
|
// The reason for disabling built-in anti-replay in OpenSSL is
|
||||||
// that it only works if client gets back to the same server.
|
// that it only works if client gets back to the same server.
|
||||||
// The freshness check described in
|
// The freshness check described in
|
||||||
// https://tools.ietf.org/html/rfc8446#section-8.3 is still
|
// https://tools.ietf.org/html/rfc8446#section-8.3 is still
|
||||||
// performed.
|
// performed.
|
||||||
| SSL_OP_NO_ANTI_REPLAY
|
| SSL_OP_NO_ANTI_REPLAY
|
||||||
# endif // OPENSSL_1_1_1_API
|
# endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
;
|
;
|
||||||
|
|
||||||
auto config = mod_config();
|
auto config = mod_config();
|
||||||
|
@ -1309,13 +1394,13 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
|
||||||
# if OPENSSL_1_1_1_API
|
# if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.c_str()) == 0) {
|
if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.c_str()) == 0) {
|
||||||
LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers
|
LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers
|
||||||
<< " failed: " << ERR_error_string(ERR_get_error(), nullptr);
|
<< " failed: " << ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
# endif // OPENSSL_1_1_1_API
|
# endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_EC
|
# ifndef OPENSSL_NO_EC
|
||||||
# if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
# if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
@ -1503,7 +1588,7 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
||||||
# endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&
|
# endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&
|
||||||
// !defined(OPENSSL_IS_BORINGSSL)
|
// !defined(OPENSSL_IS_BORINGSSL)
|
||||||
|
|
||||||
# if OPENSSL_1_1_1_API
|
# if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
auto &quicconf = config->quic;
|
auto &quicconf = config->quic;
|
||||||
|
|
||||||
if (quicconf.upstream.early_data &&
|
if (quicconf.upstream.early_data &&
|
||||||
|
@ -1513,7 +1598,7 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file,
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
# endif // OPENSSL_1_1_1_API
|
# endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_PSK
|
# ifndef OPENSSL_NO_PSK
|
||||||
SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb);
|
SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb);
|
||||||
|
|
Loading…
Reference in New Issue