diff --git a/configure.ac b/configure.ac index 5e19e1ce..671a9484 100644 --- a/configure.ac +++ b/configure.ac @@ -474,6 +474,7 @@ if test "x${request_openssl}" != "xno"; then CFLAGS="$OPENSSL_CFLAGS $CFLAGS" LIBS="$OPENSSL_LIBS $LIBS" + # quictls/openssl has SSL_is_quic. have_ssl_is_quic=no AC_MSG_CHECKING([for SSL_is_quic]) 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([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 + ]], [[ + 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" LIBS="$save_LIBS" fi @@ -527,21 +539,48 @@ fi # ngtcp2_crypto_openssl (for src) 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], [libngtcp2_crypto_openssl >= 0.0.0], [have_libngtcp2_crypto_openssl=yes], [have_libngtcp2_crypto_openssl=no]) if test "x${have_libngtcp2_crypto_openssl}" = "xno"; then 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 -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 AC_MSG_ERROR([libngtcp2_crypto_openssl was requested (--with-libngtcp2) but not found]) 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) have_libnghttp3=no if test "x${request_libnghttp3}" != "xno"; then @@ -749,9 +788,11 @@ AM_CONDITIONAL([ENABLE_APP], [ test "x${enable_app}" = "xyes" ]) # Check HTTP/3 support enable_http3=no 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_crypto_openssl}" = "xyes" && + (test "x${have_libngtcp2_crypto_openssl}" = "xyes" || + test "x${have_libngtcp2_crypto_boringssl}" = "xyes") && test "x${have_libnghttp3}" = "xyes"; then enable_http3=yes 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}') 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_boringssl: ${have_libngtcp2_crypto_boringssl} (CFLAGS='${LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_BORINGSSL_LIBS}') libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}') libbpf: ${have_libbpf} (CFLAGS='${LIBBPF_CFLAGS}' LIBS='${LIBBPF_LIBS}') Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}') diff --git a/src/Makefile.am b/src/Makefile.am index a0545b4f..2fd6eadd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,6 +47,7 @@ AM_CPPFLAGS = \ @LIBEV_CFLAGS@ \ @LIBNGHTTP3_CFLAGS@ \ @LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@ \ + @LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ \ @LIBNGTCP2_CFLAGS@ \ @OPENSSL_CFLAGS@ \ @LIBCARES_CFLAGS@ \ @@ -65,6 +66,7 @@ LDADD = $(top_builddir)/lib/libnghttp2.la \ @LIBEV_LIBS@ \ @LIBNGHTTP3_LIBS@ \ @LIBNGTCP2_CRYPTO_OPENSSL_LIBS@ \ + @LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ \ @LIBNGTCP2_LIBS@ \ @OPENSSL_LIBS@ \ @LIBCARES_LIBS@ \ diff --git a/src/h2load.h b/src/h2load.h index 895fb8eb..67da2b50 100644 --- a/src/h2load.h +++ b/src/h2load.h @@ -474,8 +474,10 @@ struct Client { int quic_stream_stop_sending(int64_t stream_id, uint64_t app_error_code); int quic_extend_max_local_streams(); - int quic_on_key(ngtcp2_crypto_level level, const uint8_t *rx_secret, - const uint8_t *tx_secret, size_t secretlen); + int quic_on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret, + 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_write_client_handshake(ngtcp2_crypto_level level, diff --git a/src/h2load_quic.cc b/src/h2load_quic.cc index b77bf6ce..74680043 100644 --- a/src/h2load_quic.cc +++ b/src/h2load_quic.cc @@ -28,7 +28,12 @@ #include -#include +#ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL +# include +#endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL +#ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL +# include +#endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL #include @@ -236,15 +241,19 @@ ngtcp2_tstamp timestamp(struct ev_loop *loop) { } } // namespace +#ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL namespace { int set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, const uint8_t *rx_secret, const uint8_t *tx_secret, size_t secret_len) { auto c = static_cast(SSL_get_app_data(ssl)); + auto level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level); - if (c->quic_on_key( - ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level), - rx_secret, tx_secret, secret_len) != 0) { + if (c->quic_on_rx_secret(level, rx_secret, secret_len) != 0) { + return 0; + } + + if (c->quic_on_tx_secret(level, tx_secret, secret_len) != 0) { return 0; } @@ -282,6 +291,70 @@ auto quic_method = SSL_QUIC_METHOD{ send_alert, }; } // 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(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(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(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(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 namespace { @@ -462,24 +535,16 @@ void Client::quic_close_connection() { ps.path.remote.addrlen, buf.data(), nwrite, 0); } -int Client::quic_on_key(ngtcp2_crypto_level level, const uint8_t *rx_secret, - const uint8_t *tx_secret, size_t secretlen) { +int Client::quic_on_rx_secret(ngtcp2_crypto_level level, const uint8_t *secret, + size_t secretlen) { if (ngtcp2_crypto_derive_and_install_rx_key(quic.conn, nullptr, nullptr, - nullptr, level, rx_secret, + nullptr, level, secret, secretlen) != 0) { std::cerr << "ngtcp2_crypto_derive_and_install_rx_key() failed" << std::endl; 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) { auto s = std::make_unique(this); 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; } +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) { quic.last_error = quic::err_transport_tls(alert); } diff --git a/src/shrpx_connection_handler.cc b/src/shrpx_connection_handler.cc index 99800ca4..cf45f508 100644 --- a/src/shrpx_connection_handler.cc +++ b/src/shrpx_connection_handler.cc @@ -740,9 +740,9 @@ void ConnectionHandler::handle_ocsp_complete() { // that case we get nullptr. auto quic_ssl_ctx = quic_all_ssl_ctx_[ocsp_.next]; if (quic_ssl_ctx) { +# ifndef OPENSSL_IS_BORINGSSL auto quic_tls_ctx_data = static_cast( SSL_CTX_get_app_data(quic_ssl_ctx)); -# ifndef OPENSSL_IS_BORINGSSL # ifdef HAVE_ATOMIC_STD_SHARED_PTR std::atomic_store_explicit( &quic_tls_ctx_data->ocsp_data, diff --git a/src/shrpx_http3_upstream.cc b/src/shrpx_http3_upstream.cc index 662c19ae..1208e3a3 100644 --- a/src/shrpx_http3_upstream.cc +++ b/src/shrpx_http3_upstream.cc @@ -613,6 +613,40 @@ int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr, params.max_idle_timeout = static_cast( 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 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(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) { params.original_dcid = *odcid; params.retry_scid = initial_hd.dcid; diff --git a/src/shrpx_quic_connection_handler.cc b/src/shrpx_quic_connection_handler.cc index 37116645..730c649f 100644 --- a/src/shrpx_quic_connection_handler.cc +++ b/src/shrpx_quic_connection_handler.cc @@ -369,7 +369,9 @@ ClientHandler *QUICConnectionHandler::handle_new_connection( return nullptr; } +#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) assert(SSL_is_quic(ssl)); +#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) SSL_set_accept_state(ssl); @@ -377,7 +379,11 @@ ClientHandler *QUICConnectionHandler::handle_new_connection( auto &quicconf = config->quic; if (quicconf.upstream.early_data) { +#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) 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 diff --git a/src/shrpx_tls.cc b/src/shrpx_tls.cc index bb0017e6..cff06ddc 100644 --- a/src/shrpx_tls.cc +++ b/src/shrpx_tls.cc @@ -61,8 +61,13 @@ #ifdef ENABLE_HTTP3 # include # include -# include -#endif // ENABLE_HTTP3 +# ifdef HAVE_LIBNGTCP2_CRYPTO_OPENSSL +# include +# endif // HAVE_LIBNGTCP2_CRYPTO_OPENSSL +# ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL +# include +# endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL +#endif // ENABLE_HTTP3 #include "shrpx_log.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}; #ifdef ENABLE_HTTP3 - auto cert_tree = SSL_is_quic(ssl) ? worker->get_quic_cert_lookup_tree() - : worker->get_cert_lookup_tree(); + auto cert_tree = conn->proto == Proto::HTTP3 + ? worker->get_quic_cert_lookup_tree() + : worker->get_cert_lookup_tree(); #else // !ENABLE_HTTP3 auto cert_tree = worker->get_cert_lookup_tree(); #endif // !ENABLE_HTTP3 @@ -212,7 +218,7 @@ int servername_callback(SSL *ssl, int *al, void *arg) { auto conn_handler = worker->get_connection_handler(); #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_indexed_ssl_ctx(idx); #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 HAVE_LIBNGTCP2_CRYPTO_OPENSSL namespace { int quic_set_encryption_secrets(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level, const uint8_t *rx_secret, @@ -1259,6 +1266,84 @@ auto quic_method = SSL_QUIC_METHOD{ quic_send_alert, }; } // 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(SSL_get_app_data(ssl)); + auto handler = static_cast(conn->data); + auto upstream = static_cast(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(SSL_get_app_data(ssl)); + auto handler = static_cast(conn->data); + auto upstream = static_cast(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(SSL_get_app_data(ssl)); + auto handler = static_cast(conn->data); + auto upstream = static_cast(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(SSL_get_app_data(ssl)); + auto handler = static_cast(conn->data); + auto upstream = static_cast(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, 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_SINGLE_DH_USE | 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 // that it only works if client gets back to the same server. // The freshness check described in // https://tools.ietf.org/html/rfc8446#section-8.3 is still // performed. | 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(); @@ -1309,13 +1394,13 @@ SSL_CTX *create_quic_ssl_context(const char *private_key_file, 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) { LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers << " failed: " << ERR_error_string(ERR_get_error(), nullptr); DIE(); } -# endif // OPENSSL_1_1_1_API +# endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) # ifndef OPENSSL_NO_EC # 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 && // !defined(OPENSSL_IS_BORINGSSL) -# if OPENSSL_1_1_1_API +# if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) auto &quicconf = config->quic; 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); DIE(); } -# endif // OPENSSL_1_1_1_API +# endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL) # ifndef OPENSSL_NO_PSK SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb);