diff --git a/doc/admin-guide/files/sni.yaml.en.rst b/doc/admin-guide/files/sni.yaml.en.rst index 8478c5099ab..f1771f239b8 100644 --- a/doc/admin-guide/files/sni.yaml.en.rst +++ b/doc/admin-guide/files/sni.yaml.en.rst @@ -96,8 +96,8 @@ valid_tls_versions_in This specifies the list of TLS protocols that will be :ts:cv:`proxy.config.ssl.TLSv1`, :ts:cv:`proxy.config.ssl.TLSv1_1`, :ts:cv:`proxy.config.ssl.TLSv1_2`, and :ts:cv:`proxy.config.ssl.TLSv1_3`. The potential values are TLSv1, TLSv1_1, TLSv1_2, and TLSv1_3. You must list all protocols that |TS| - should offer to the client when using this key. This key is only valid for openssl - 1.1.0 and later. Older versions of openssl do not provide a hook early enough to update + should offer to the client when using this key. This key is only valid for OpenSSL + 1.1.0 and later and BoringSSL. Older versions of OpenSSL do not provide a hook early enough to update the SSL object. It is a syntax error for |TS| built against earlier versions. client_cert The file containing the client certificate to use for the outbound connection. diff --git a/iocore/net/BoringSSLUtils.cc b/iocore/net/BoringSSLUtils.cc new file mode 100644 index 00000000000..a5a63499ac6 --- /dev/null +++ b/iocore/net/BoringSSLUtils.cc @@ -0,0 +1,138 @@ +/** @file + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +// Borrowed from Envoy +// https://github.com/envoyproxy/envoy/blob/329b2491949fc52f4dc5c4a778ea158bfe6fe979/source/extensions/transport_sockets/tls/context_impl.cc#L962 + +#include "BoringSSLUtils.h" + +#ifdef OPENSSL_IS_BORINGSSL +namespace BoringSSLUtils +{ +bool +cbsContainsU16(CBS &cbs, uint16_t n) +{ + while (CBS_len(&cbs) > 0) { + uint16_t v; + if (!CBS_get_u16(&cbs, &v)) { + return false; + } + if (v == n) { + return true; + } + } + + return false; +} + +bool +isCipherEnabled(SSL_CTX *ctx, uint16_t cipher_id, uint16_t client_version) +{ + const SSL_CIPHER *c = SSL_get_cipher_by_value(cipher_id); + if (c == nullptr) { + return false; + } + // Skip TLS 1.2 only ciphersuites unless the client supports it. + if (SSL_CIPHER_get_min_version(c) > client_version) { + return false; + } + if (SSL_CIPHER_get_auth_nid(c) != NID_auth_ecdsa) { + return false; + } + for (const SSL_CIPHER *our_c : SSL_CTX_get_ciphers(ctx)) { + if (SSL_CIPHER_get_id(our_c) == SSL_CIPHER_get_id(c)) { + return true; + } + } + return false; +} + +bool +isClientEcdsaCapable(const SSL_CLIENT_HELLO *ssl_client_hello) +{ + CBS client_hello; + CBS_init(&client_hello, ssl_client_hello->client_hello, ssl_client_hello->client_hello_len); + + // This is the TLSv1.3 case (TLSv1.2 on the wire and the supported_versions extensions present). + // We just need to look at signature algorithms. + const uint16_t client_version = ssl_client_hello->version; + if (client_version == TLS1_2_VERSION && true) { + // If the supported_versions extension is found then we assume that the client is competent + // enough that just checking the signature_algorithms is sufficient. + const uint8_t *supported_versions_data; + size_t supported_versions_len; + if (SSL_early_callback_ctx_extension_get(ssl_client_hello, TLSEXT_TYPE_supported_versions, &supported_versions_data, + &supported_versions_len)) { + const uint8_t *signature_algorithms_data; + size_t signature_algorithms_len; + if (SSL_early_callback_ctx_extension_get(ssl_client_hello, TLSEXT_TYPE_signature_algorithms, &signature_algorithms_data, + &signature_algorithms_len)) { + CBS signature_algorithms_ext, signature_algorithms; + CBS_init(&signature_algorithms_ext, signature_algorithms_data, signature_algorithms_len); + if (!CBS_get_u16_length_prefixed(&signature_algorithms_ext, &signature_algorithms) || + CBS_len(&signature_algorithms_ext) != 0) { + return false; + } + if (cbsContainsU16(signature_algorithms, SSL_SIGN_ECDSA_SECP256R1_SHA256)) { + return true; + } + } + + return false; + } + } + + // Otherwise we are < TLSv1.3 and need to look at both the curves in the supported_groups for + // ECDSA and also for a compatible cipher suite. https://tools.ietf.org/html/rfc4492#section-5.1.1 + const uint8_t *curvelist_data; + size_t curvelist_len; + if (!SSL_early_callback_ctx_extension_get(ssl_client_hello, TLSEXT_TYPE_supported_groups, &curvelist_data, &curvelist_len)) { + return false; + } + + CBS curvelist; + CBS_init(&curvelist, curvelist_data, curvelist_len); + + // We only support P256 ECDSA curves today. + if (!cbsContainsU16(curvelist, SSL_CURVE_SECP256R1)) { + return false; + } + + // The client must have offered an ECDSA ciphersuite that we like. + CBS cipher_suites; + CBS_init(&cipher_suites, ssl_client_hello->cipher_suites, ssl_client_hello->cipher_suites_len); + + while (CBS_len(&cipher_suites) > 0) { + uint16_t cipher_id; + if (!CBS_get_u16(&cipher_suites, &cipher_id)) { + return false; + } + + SSL_CTX *ctx = SSL_get_SSL_CTX(ssl_client_hello->ssl); + if (isCipherEnabled(ctx, cipher_id, client_version)) { + return true; + } + } + return false; +} + +} // namespace BoringSSLUtils +#endif diff --git a/iocore/net/BoringSSLUtils.h b/iocore/net/BoringSSLUtils.h new file mode 100644 index 00000000000..dcd1760f9d4 --- /dev/null +++ b/iocore/net/BoringSSLUtils.h @@ -0,0 +1,30 @@ +/** @file + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include + +#ifdef OPENSSL_IS_BORINGSSL +namespace BoringSSLUtils +{ +bool isClientEcdsaCapable(const SSL_CLIENT_HELLO *ssl_client_hello); + +} // namespace BoringSSLUtils +#endif diff --git a/iocore/net/Makefile.am b/iocore/net/Makefile.am index 1b97bb87d6b..e94e6e18c5a 100644 --- a/iocore/net/Makefile.am +++ b/iocore/net/Makefile.am @@ -119,6 +119,8 @@ libinknet_a_SOURCES = \ ALPNSupport.cc \ BIO_fastopen.cc \ BIO_fastopen.h \ + BoringSSLUtils.cc \ + BoringSSLUtils.h \ Connection.cc \ I_Net.h \ I_NetProcessor.h \ @@ -143,7 +145,7 @@ libinknet_a_SOURCES = \ P_Socks.h \ P_SSLCertLookup.h \ P_SSLConfig.h \ - P_SSLSecret.h \ + P_SSLSecret.h \ P_SSLNetAccept.h \ P_SSLNetProcessor.h \ P_SSLNetVConnection.h \ @@ -172,7 +174,7 @@ libinknet_a_SOURCES = \ SSLClientCoordinator.cc \ SSLClientUtils.cc \ SSLConfig.cc \ - SSLSecret.cc \ + SSLSecret.cc \ SSLDiags.cc \ SSLInternal.cc \ SSLNetAccept.cc \ diff --git a/iocore/net/P_SSLCertLookup.h b/iocore/net/P_SSLCertLookup.h index 6d03f70134f..a36aba9dba7 100644 --- a/iocore/net/P_SSLCertLookup.h +++ b/iocore/net/P_SSLCertLookup.h @@ -40,6 +40,14 @@ enum class SSLCertContextOption { OPT_TUNNEL ///< Just tunnel, don't terminate. }; +/** Used to discern the context type when BoringSSL is used for the SSL implementation. + */ +enum class SSLCertContextType { + GENERIC, ///< Generic Context (can be either EC or RSA) + RSA, ///< RSA-based Context + EC ///< EC-based Context +}; + /** @brief Gather user provided settings from ssl_multicert.config in to this single struct */ @@ -100,14 +108,17 @@ struct SSLCertContext { : ctx_mutex(), ctx(c, SSL_CTX_free), opt(SSLCertContextOption::OPT_NONE), userconfig(nullptr), keyblock(nullptr) { } - SSLCertContext(shared_SSL_CTX sc, shared_SSLMultiCertConfigParams u) - : ctx_mutex(), ctx(sc), opt(u->opt), userconfig(u), keyblock(nullptr) + + SSLCertContext(shared_SSL_CTX sc, SSLCertContextType ctx_type, shared_SSLMultiCertConfigParams u) + : ctx_mutex(), ctx(sc), ctx_type(ctx_type), opt(u->opt), userconfig(u), keyblock(nullptr) { } - SSLCertContext(shared_SSL_CTX sc, shared_SSLMultiCertConfigParams u, shared_ssl_ticket_key_block kb) - : ctx_mutex(), ctx(sc), opt(u->opt), userconfig(u), keyblock(kb) + + SSLCertContext(shared_SSL_CTX sc, SSLCertContextType ctx_type, shared_SSLMultiCertConfigParams u, shared_ssl_ticket_key_block kb) + : ctx_mutex(), ctx(sc), ctx_type(ctx_type), opt(u->opt), userconfig(u), keyblock(kb) { } + SSLCertContext(SSLCertContext const &other); SSLCertContext &operator=(SSLCertContext const &other); ~SSLCertContext() {} @@ -117,6 +128,7 @@ struct SSLCertContext { void setCtx(shared_SSL_CTX sc); void release(); + SSLCertContextType ctx_type = SSLCertContextType::GENERIC; SSLCertContextOption opt = SSLCertContextOption::OPT_NONE; ///< Special handling option. shared_SSLMultiCertConfigParams userconfig = nullptr; ///< User provided settings shared_ssl_ticket_key_block keyblock = nullptr; ///< session keys associated with this address @@ -124,6 +136,8 @@ struct SSLCertContext { struct SSLCertLookup : public ConfigInfo { SSLContextStorage *ssl_storage; + SSLContextStorage *ec_storage; + shared_SSL_CTX ssl_default; bool is_valid = true; @@ -141,7 +155,7 @@ struct SSLCertLookup : public ConfigInfo { Exact matches have priority, then wildcards. Only destination based matches are checked. @return @c A pointer to the matched context, @c nullptr if no match is found. */ - SSLCertContext *find(const std::string &name) const; + SSLCertContext *find(const std::string &name, SSLCertContextType ctxType = SSLCertContextType::GENERIC) const; // Return the last-resort default TLS context if there is no name or address match. SSL_CTX * diff --git a/iocore/net/P_SSLUtils.h b/iocore/net/P_SSLUtils.h index 6c0d7d72d18..37221b7d42c 100644 --- a/iocore/net/P_SSLUtils.h +++ b/iocore/net/P_SSLUtils.h @@ -42,7 +42,7 @@ class SSLNetVConnection; typedef int ssl_error_t; -#ifndef OPENSSL_IS_BORING +#ifndef OPENSSL_IS_BORINGSSL typedef int ssl_curve_id; #else typedef uint16_t ssl_curve_id; @@ -51,6 +51,15 @@ typedef uint16_t ssl_curve_id; // Return the SSL Curve ID associated to the specified SSL connection ssl_curve_id SSLGetCurveNID(SSL *ssl); +enum class SSLCertContextType; + +struct SSLLoadingContext { + SSL_CTX *ctx; + SSLCertContextType ctx_type; + + explicit SSLLoadingContext(SSL_CTX *c, SSLCertContextType ctx_type) : ctx(c), ctx_type(ctx_type) {} +}; + /** @brief Load SSL certificates from ssl_multicert.config and setup SSLCertLookup for SSLCertificateConfig */ @@ -59,6 +68,7 @@ class SSLMultiCertConfigLoader public: struct CertLoadData { std::vector cert_names_list, key_list, ca_list, ocsp_list; + std::vector cert_type_list; }; SSLMultiCertConfigLoader(const SSLConfigParams *p) : _params(p) {} virtual ~SSLMultiCertConfigLoader(){}; @@ -66,15 +76,21 @@ class SSLMultiCertConfigLoader bool load(SSLCertLookup *lookup); virtual SSL_CTX *default_server_ssl_ctx(); - virtual SSL_CTX *init_server_ssl_ctx(CertLoadData const &data, const SSLMultiCertConfigParams *sslMultCertSettings, - std::set &names); - static bool load_certs(SSL_CTX *ctx, CertLoadData const &data, const SSLConfigParams *params, + virtual std::vector init_server_ssl_ctx(CertLoadData const &data, + const SSLMultiCertConfigParams *sslMultCertSettings, + std::set &names); + + static bool load_certs(SSL_CTX *ctx, const std::vector &cert_names_list, + const std::vector &key_names_list, CertLoadData const &data, const SSLConfigParams *params, const SSLMultiCertConfigParams *sslMultCertSettings); + bool load_certs_and_cross_reference_names(std::vector &cert_list, CertLoadData &data, const SSLConfigParams *params, const SSLMultiCertConfigParams *sslMultCertSettings, std::set &common_names, - std::unordered_map> &unique_names); + std::unordered_map> &unique_names, + SSLCertContextType *certType); + static bool set_session_id_context(SSL_CTX *ctx, const SSLConfigParams *params, const SSLMultiCertConfigParams *sslMultCertSettings); @@ -87,7 +103,7 @@ class SSLMultiCertConfigLoader const SSLConfigParams *_params; bool _store_single_ssl_ctx(SSLCertLookup *lookup, const shared_SSLMultiCertConfigParams &sslMultCertSettings, shared_SSL_CTX ctx, - std::set &names); + SSLCertContextType ctx_type, std::set &names); private: virtual const char *_debug_tag() const; diff --git a/iocore/net/SSLCertLookup.cc b/iocore/net/SSLCertLookup.cc index 69c668005e4..06d5c4d7d57 100644 --- a/iocore/net/SSLCertLookup.cc +++ b/iocore/net/SSLCertLookup.cc @@ -253,6 +253,7 @@ SSLCertContext::SSLCertContext(SSLCertContext const &other) opt = other.opt; userconfig = other.userconfig; keyblock = other.keyblock; + ctx_type = other.ctx_type; std::lock_guard lock(other.ctx_mutex); ctx = other.ctx; } @@ -264,6 +265,7 @@ SSLCertContext::operator=(SSLCertContext const &other) this->opt = other.opt; this->userconfig = other.userconfig; this->keyblock = other.keyblock; + this->ctx_type = other.ctx_type; std::lock_guard lock(other.ctx_mutex); this->ctx = other.ctx; } @@ -284,16 +286,30 @@ SSLCertContext::setCtx(shared_SSL_CTX sc) ctx = std::move(sc); } -SSLCertLookup::SSLCertLookup() : ssl_storage(new SSLContextStorage()), ssl_default(nullptr), is_valid(true) {} +SSLCertLookup::SSLCertLookup() + : ssl_storage(new SSLContextStorage()), ec_storage(new SSLContextStorage()), ssl_default(nullptr), is_valid(true) +{ +} SSLCertLookup::~SSLCertLookup() { delete this->ssl_storage; + delete this->ec_storage; } SSLCertContext * -SSLCertLookup::find(const std::string &address) const +SSLCertLookup::find(const std::string &address, SSLCertContextType ctxType) const { +#ifdef OPENSSL_IS_BORINGSSL + // If the context is EC supportable, try finding that first. + if (ctxType == SSLCertContextType::EC) { + auto ctx = this->ec_storage->lookup(address); + if (ctx != nullptr) { + return ctx; + } + } +#endif + // non-EC last resort return this->ssl_storage->lookup(address); } @@ -303,6 +319,24 @@ SSLCertLookup::find(const IpEndpoint &address) const SSLCertContext *cc; SSLAddressLookupKey key(address); +#ifdef OPENSSL_IS_BORINGSSL + // If the context is EC supportable, try finding that first. + if ((cc = this->ec_storage->lookup(key.get()))) { + return cc; + } + + // If that failed, try the address without the port. + if (address.port()) { + key.split(); + if ((cc = this->ec_storage->lookup(key.get()))) { + return cc; + } + } + + // reset for search across RSA + key = SSLAddressLookupKey(address); +#endif + // First try the full address. if ((cc = this->ssl_storage->lookup(key.get()))) { return cc; @@ -320,14 +354,39 @@ SSLCertLookup::find(const IpEndpoint &address) const int SSLCertLookup::insert(const char *name, SSLCertContext const &cc) { +#ifdef OPENSSL_IS_BORINGSSL + switch (cc.ctx_type) { + case SSLCertContextType::GENERIC: + case SSLCertContextType::RSA: + return this->ssl_storage->insert(name, cc); + case SSLCertContextType::EC: + return this->ec_storage->insert(name, cc); + default: + ink_assert(false); + } +#else return this->ssl_storage->insert(name, cc); +#endif } int SSLCertLookup::insert(const IpEndpoint &address, SSLCertContext const &cc) { SSLAddressLookupKey key(address); + +#ifdef OPENSSL_IS_BORINGSSL + switch (cc.ctx_type) { + case SSLCertContextType::GENERIC: + case SSLCertContextType::RSA: + return this->ssl_storage->insert(key.get(), cc); + case SSLCertContextType::EC: + return this->ec_storage->insert(key.get(), cc); + default: + ink_assert(false); + } +#else return this->ssl_storage->insert(key.get(), cc); +#endif } unsigned diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc index 912f6ba03d0..b81506e2e97 100644 --- a/iocore/net/SSLConfig.cc +++ b/iocore/net/SSLConfig.cc @@ -710,7 +710,7 @@ cleanup_bio(BIO *&biop) void SSLConfigParams::updateCTX(const std::string &cert_secret_name) const { - // Clear the corresponding client CTX's. They will be lazy loaded later + // Clear the corresponding client CTXs. They will be lazy loaded later Debug("ssl", "Update cert %s", cert_secret_name.c_str()); this->clearCTX(cert_secret_name); diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc index c1060177aec..aa3a1c79d5c 100644 --- a/iocore/net/SSLUtils.cc +++ b/iocore/net/SSLUtils.cc @@ -38,6 +38,7 @@ #include "P_OCSPStapling.h" #include "P_SSLSNI.h" #include "P_SSLConfig.h" +#include "BoringSSLUtils.h" #include "ProxyProtocol.h" #include "SSLSessionCache.h" #include "SSLSessionTicket.h" @@ -253,16 +254,18 @@ ssl_rm_cached_session(SSL_CTX *ctx, SSL_SESSION *sess) } static int -set_context_cert(SSL *ssl) +set_context_cert(SSL *ssl, void *arg) { shared_SSL_CTX ctx = nullptr; SSL_CTX *verify_ctx = nullptr; SSLCertContext *cc = nullptr; SSLCertificateConfig::scoped_config lookup; - const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); - SSLNetVConnection *netvc = SSLNetVCAccess(ssl); - bool found = true; - int retval = 1; + + const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + SSLNetVConnection *netvc = SSLNetVCAccess(ssl); + bool found = true; + int retval = 1; + SSLCertContextType ctxType = SSLCertContextType::GENERIC; if (!netvc || netvc->ssl != ssl) { Debug("ssl.error", "set_context_cert call back on stale netvc"); @@ -279,11 +282,19 @@ set_context_cert(SSL *ssl) goto done; } +#ifdef OPENSSL_IS_BORINGSSL + if (arg != nullptr) { + const SSL_CLIENT_HELLO *client_hello = (const SSL_CLIENT_HELLO *)arg; + const bool client_ecdsa_capable = BoringSSLUtils::isClientEcdsaCapable(client_hello); + ctxType = client_ecdsa_capable ? SSLCertContextType::EC : SSLCertContextType::RSA; + } +#endif + // The incoming SSL_CTX is either the one mapped from the inbound IP address or the default one. If we // don't find a name-based match at this point, we *do not* want to mess with the context because we've // already made a best effort to find the best match. if (likely(servername)) { - cc = lookup->find(const_cast(servername)); + cc = lookup->find(servername, ctxType); if (cc) { ctx = cc->getCtx(); } @@ -342,6 +353,7 @@ set_context_cert(SSL *ssl) } verify_ctx = SSL_get_SSL_CTX(ssl); + // set_context_cert found SSL context for ... Debug("ssl", "ssl_cert_callback %s SSL context %p for requested name '%s'", found ? "found" : "using", verify_ctx, servername); if (verify_ctx == nullptr) { @@ -410,14 +422,48 @@ ssl_client_hello_callback(SSL *s, int *al, void *arg) } return SSL_CLIENT_HELLO_SUCCESS; } +#elif defined(OPENSSL_IS_BORINGSSL) +static ssl_select_cert_result_t +ssl_client_hello_callback(const SSL_CLIENT_HELLO *client_hello) +{ + SSL *s = client_hello->ssl; + TLSSNISupport *snis = TLSSNISupport::getInstance(s); + + if (snis) { + snis->on_client_hello(client_hello); + int ret = snis->perform_sni_action(); + if (ret != SSL_TLSEXT_ERR_OK) { + return ssl_select_cert_error; + } + } else { + // This error suggests either of these: + // 1) Call back on unsupported netvc -- Don't register callback unnecessarily + // 2) Call back on stale netvc + Debug("ssl.error", "ssl_client_hello_callback was called unexpectedly"); + return ssl_select_cert_error; + } + + SSLNetVConnection *netvc = SSLNetVCAccess(s); + if (!netvc || netvc->ssl != s) { + Debug("ssl.error", "ssl_client_hello_callback call back on stale netvc"); + return ssl_select_cert_error; + } + + bool reenabled = netvc->callHooks(TS_EVENT_SSL_CLIENT_HELLO); + + if (!reenabled) { + return ssl_select_cert_retry; + } + return ssl_select_cert_success; +} #endif /** * Called before either the server or the client certificate is used - * Return 1 on success, 0 on error, or -1 to pause + * Return 1 on success, 0 on error, or -1 to pause, -2 to retry */ static int -ssl_cert_callback(SSL *ssl, void * /*arg*/) +ssl_cert_callback(SSL *ssl, void *arg) { SSLNetVConnection *netvc = SSLNetVCAccess(ssl); bool reenabled; @@ -430,13 +476,17 @@ ssl_cert_callback(SSL *ssl, void * /*arg*/) // If we are in tunnel mode, don't select a cert. Pause! if (HttpProxyPort::TRANSPORT_BLIND_TUNNEL == netvc->attributes) { +#ifdef OPENSSL_IS_BORINGSSL + return -2; // Retry +#else return -1; // Pause +#endif } // Do the common certificate lookup only once. If we pause // and restart processing, do not execute the common logic again if (!netvc->calledHooks(TS_EVENT_SSL_CERT)) { - retval = set_context_cert(ssl); + retval = set_context_cert(ssl, arg); if (retval != 1) { return retval; } @@ -463,7 +513,7 @@ ssl_servername_callback(SSL *ssl, int *al, void *arg) TLSSNISupport *snis = TLSSNISupport::getInstance(ssl); if (snis) { snis->on_servername(ssl, al, arg); -#if !TS_USE_HELLO_CB +#if !TS_USE_HELLO_CB && !defined(OPENSSL_IS_BORINGSSL) // Only call the SNI actions here if not already performed in the HELLO_CB int ret = snis->perform_sni_action(); if (ret != SSL_TLSEXT_ERR_OK) { @@ -1099,12 +1149,48 @@ void SSLMultiCertConfigLoader::_set_handshake_callbacks(SSL_CTX *ctx) { // Make sure the callbacks are set +#ifndef OPENSSL_IS_BORINGSSL SSL_CTX_set_cert_cb(ctx, ssl_cert_callback, nullptr); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_callback); #if TS_USE_HELLO_CB SSL_CTX_set_client_hello_cb(ctx, ssl_client_hello_callback, nullptr); #endif +#else + SSL_CTX_set_select_certificate_cb(ctx, [](const SSL_CLIENT_HELLO *client_hello) -> ssl_select_cert_result_t { + ssl_select_cert_result_t res; + res = ssl_client_hello_callback(client_hello); + if (res == ssl_select_cert_error) { + return res; + } + + res = (ssl_servername_callback(client_hello->ssl, nullptr, nullptr) == SSL_TLSEXT_ERR_OK) ? ssl_select_cert_success : + ssl_select_cert_error; + if (res == ssl_select_cert_error) { + return res; + } + + int cbres = ssl_cert_callback(client_hello->ssl, (void *)client_hello); + switch (cbres) { + case -2: + res = ssl_select_cert_retry; + break; + case -1: + res = ssl_select_cert_success; + break; + case 0: + res = ssl_select_cert_error; + break; + case 1: + res = ssl_select_cert_success; + break; + default: + ink_assert(!"unhandled cert result"); + } + + return res; + }); +#endif } void @@ -1154,99 +1240,147 @@ setClientCertCACerts(SSL *ssl, const char *file, const char *dir) Initialize SSL_CTX for server This is public function because of used by SSLCreateServerContext. */ -SSL_CTX * +std::vector SSLMultiCertConfigLoader::init_server_ssl_ctx(CertLoadData const &data, const SSLMultiCertConfigParams *sslMultCertSettings, std::set &names) { - const SSLConfigParams *params = this->_params; + std::vector> cert_names; + std::vector> key_names; + std::vector key_names_list; + + bool generate_default_ctx = data.cert_names_list.empty(); + if (!generate_default_ctx) { +#ifdef OPENSSL_IS_BORINGSSL + for (auto const &name : data.cert_names_list) { + cert_names.emplace_back(std::vector({name})); + } + for (auto const &name : data.key_list) { + key_names.emplace_back(std::vector({name})); + } +#else + if (!data.cert_names_list.empty()) { + cert_names.emplace_back(data.cert_names_list); + key_names.emplace_back(data.key_list); + } +#endif + } else { + // In the case of no cert_names, we still want to create a + // ctx with all the bells and whistles (as much as possible) + cert_names.emplace_back(std::vector({std::string("default")})); + key_names.emplace_back(std::vector({std::string("default")})); + } + + SSLCertContextType ctx_type = SSLCertContextType::GENERIC; + std::vector ret; + unsigned int i = 0; + SSL_CTX *ctx = nullptr; + for (auto const &cert_names_list : cert_names) { + if (i < key_names.size()) { + key_names_list = key_names[i]; + } else { + key_names_list.clear(); + } - SSL_CTX *ctx = this->default_server_ssl_ctx(); + ctx = this->default_server_ssl_ctx(); - // disable selected protocols - SSL_CTX_set_options(ctx, params->ssl_ctx_options); + ctx_type = (!generate_default_ctx && i < data.cert_type_list.size()) ? data.cert_type_list[i] : SSLCertContextType::GENERIC; - if (!this->_setup_session_cache(ctx)) { - goto fail; - } + Debug("ssl", "Creating new context %p cert_count=%ld initial: %s", ctx, cert_names_list.size(), cert_names_list[0].c_str()); + + // disable selected protocols + SSL_CTX_set_options(ctx, _params->ssl_ctx_options); + + if (!this->_setup_session_cache(ctx)) { + goto fail; + } #ifdef SSL_MODE_RELEASE_BUFFERS - Debug("ssl", "enabling SSL_MODE_RELEASE_BUFFERS"); - SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); + Debug("ssl", "enabling SSL_MODE_RELEASE_BUFFERS"); + SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG - SSL_CTX_set_options(ctx, SSL_OP_SAFARI_ECDHE_ECDSA_BUG); + SSL_CTX_set_options(ctx, SSL_OP_SAFARI_ECDHE_ECDSA_BUG); #endif - if (sslMultCertSettings) { - if (!this->_setup_dialog(ctx, sslMultCertSettings)) { - goto fail; - } + if (sslMultCertSettings) { + if (!this->_setup_dialog(ctx, sslMultCertSettings)) { + goto fail; + } + + if (sslMultCertSettings->cert && !generate_default_ctx) { + if (!SSLMultiCertConfigLoader::load_certs(ctx, cert_names_list, key_names_list, data, _params, sslMultCertSettings)) { + goto fail; + } + } - if (sslMultCertSettings->cert) { - if (!SSLMultiCertConfigLoader::load_certs(ctx, data, params, sslMultCertSettings)) { + if (!this->_set_verify_path(ctx, sslMultCertSettings)) { + goto fail; + } + + if (!this->_setup_session_ticket(ctx, sslMultCertSettings)) { goto fail; } } - if (!this->_set_verify_path(ctx, sslMultCertSettings)) { + if (!this->_setup_client_cert_verification(ctx)) { goto fail; } - if (!this->_setup_session_ticket(ctx, sslMultCertSettings)) { + if (!SSLMultiCertConfigLoader::set_session_id_context(ctx, _params, sslMultCertSettings)) { goto fail; } - } - if (!this->_setup_client_cert_verification(ctx)) { - goto fail; - } + if (!this->_set_cipher_suites_for_legacy_versions(ctx)) { + goto fail; + } - if (!SSLMultiCertConfigLoader::set_session_id_context(ctx, params, sslMultCertSettings)) { - goto fail; - } + if (!this->_set_cipher_suites(ctx)) { + goto fail; + } - if (!this->_set_cipher_suites_for_legacy_versions(ctx)) { - goto fail; - ; - } - if (!this->_set_cipher_suites(ctx)) { - goto fail; - } - if (!this->_set_curves(ctx)) { - goto fail; - } + if (!this->_set_curves(ctx)) { + goto fail; + } - if (!ssl_context_enable_dhe(params->dhparamsFile, ctx)) { - goto fail; - } + if (!ssl_context_enable_dhe(_params->dhparamsFile, ctx)) { + goto fail; + } - ssl_context_enable_ecdh(ctx); + ssl_context_enable_ecdh(ctx); - if (sslMultCertSettings && sslMultCertSettings->dialog) { - SSLMultiCertConfigLoader::clear_pw_references(ctx); - } + if (sslMultCertSettings && sslMultCertSettings->dialog) { + SSLMultiCertConfigLoader::clear_pw_references(ctx); + } - if (!this->_set_info_callback(ctx)) { - goto fail; - }; - if (!this->_set_npn_callback(ctx)) { - goto fail; - } - if (!this->_set_alpn_callback(ctx)) { - goto fail; - } + if (!this->_set_info_callback(ctx)) { + goto fail; + } - if (SSLConfigParams::init_ssl_ctx_cb) { - SSLConfigParams::init_ssl_ctx_cb(ctx, true); - } + if (!this->_set_npn_callback(ctx)) { + goto fail; + } - return ctx; + if (!this->_set_alpn_callback(ctx)) { + goto fail; + } + + if (SSLConfigParams::init_ssl_ctx_cb) { + SSLConfigParams::init_ssl_ctx_cb(ctx, true); + } + + ret.emplace_back(SSLLoadingContext(ctx, ctx_type)); + i++; + } + return ret; fail: + ink_assert(ctx != nullptr); SSLMultiCertConfigLoader::clear_pw_references(ctx); - SSLReleaseContext(ctx); - return nullptr; + SSL_CTX_free(ctx); + ret.emplace_back(SSLLoadingContext(ctx, ctx_type)); + + return ret; } bool @@ -1470,31 +1604,40 @@ SSLCreateServerContext(const SSLConfigParams *params, const SSLMultiCertConfigPa const char *key_path) { SSLMultiCertConfigLoader loader(params); - std::unique_ptr ctx(nullptr, &SSL_CTX_free); std::vector cert_list; std::set common_names; std::unordered_map> unique_names; SSLMultiCertConfigLoader::CertLoadData data; - if (loader.load_certs_and_cross_reference_names(cert_list, data, params, sslMultiCertSettings, common_names, unique_names)) { - ctx.reset(loader.init_server_ssl_ctx(data, sslMultiCertSettings, common_names)); + SSLCertContextType cert_type; + if (!loader.load_certs_and_cross_reference_names(cert_list, data, params, sslMultiCertSettings, common_names, unique_names, + &cert_type)) { + return nullptr; } for (auto &i : cert_list) { X509_free(i); } - if (ctx && cert_path) { - if (!SSL_CTX_use_certificate_file(ctx.get(), cert_path, SSL_FILETYPE_PEM)) { - SSLError("SSLCreateServerContext(): failed to load server certificate."); - ctx = nullptr; - } else if (!key_path || key_path[0] == '\0') { - key_path = cert_path; - } - if (ctx) { - if (!SSL_CTX_use_PrivateKey_file(ctx.get(), key_path, SSL_FILETYPE_PEM)) { - SSLError("SSLCreateServerContext(): failed to load server private key."); - ctx = nullptr; - } else if (!SSL_CTX_check_private_key(ctx.get())) { - SSLError("SSLCreateServerContext(): server private key does not match server certificate."); + + std::unique_ptr ctx(nullptr, &SSL_CTX_free); + + std::vector ctxs = loader.init_server_ssl_ctx(data, sslMultiCertSettings, common_names); + for (auto const &loaderctx : ctxs) { + ctx.reset(loaderctx.ctx); + + if (ctx && cert_path) { + if (!SSL_CTX_use_certificate_file(ctx.get(), cert_path, SSL_FILETYPE_PEM)) { + SSLError("SSLCreateServerContext(): failed to load server certificate."); ctx = nullptr; + } else if (!key_path || key_path[0] == '\0') { + key_path = cert_path; + } + if (ctx) { + if (!SSL_CTX_use_PrivateKey_file(ctx.get(), key_path, SSL_FILETYPE_PEM)) { + SSLError("SSLCreateServerContext(): failed to load server private key."); + ctx = nullptr; + } else if (!SSL_CTX_check_private_key(ctx.get())) { + SSLError("SSLCreateServerContext(): server private key does not match server certificate."); + ctx = nullptr; + } } } } @@ -1512,11 +1655,15 @@ SSLMultiCertConfigLoader::_prep_ssl_ctx(const shared_SSLMultiCertConfigParams ss std::vector cert_list; const SSLConfigParams *params = this->_params; - this->load_certs_and_cross_reference_names(cert_list, data, params, sslMultCertSettings.get(), common_names, unique_names); + SSLCertContextType cert_type; + if (!this->load_certs_and_cross_reference_names(cert_list, data, params, sslMultCertSettings.get(), common_names, unique_names, + &cert_type)) { + return false; + } int i = 0; bool good_certs = true; - for (auto cert : cert_list) { + for (auto const &cert : cert_list) { const char *current_cert_name = data.cert_names_list[i].c_str(); if (0 > SSLMultiCertConfigLoader::check_server_cert_now(cert, current_cert_name)) { /* At this point, we know cert is bad, and we've already printed a @@ -1550,13 +1697,13 @@ SSLMultiCertConfigLoader::_store_ssl_ctx(SSLCertLookup *lookup, const shared_SSL return false; } - if (!common_names.empty()) { - shared_SSL_CTX ctx(this->init_server_ssl_ctx(data, sslMultCertSettings.get(), common_names), SSL_CTX_free); - - if (!ctx || !sslMultCertSettings || !this->_store_single_ssl_ctx(lookup, sslMultCertSettings, ctx, common_names)) { + std::vector ctxs = this->init_server_ssl_ctx(data, sslMultCertSettings.get(), common_names); + for (const auto &loadingctx : ctxs) { + shared_SSL_CTX ctx(loadingctx.ctx, SSL_CTX_free); + if (!sslMultCertSettings || !this->_store_single_ssl_ctx(lookup, sslMultCertSettings, ctx, loadingctx.ctx_type, common_names)) { retval = false; std::string names; - for (auto name : data.cert_names_list) { + for (auto const &name : data.cert_names_list) { names.append(name); names.append(" "); } @@ -1577,11 +1724,14 @@ SSLMultiCertConfigLoader::_store_ssl_ctx(SSLCertLookup *lookup, const shared_SSL single_data.ca_list.push_back(i < data.ca_list.size() ? data.ca_list[i] : ""); single_data.ocsp_list.push_back(i < data.ocsp_list.size() ? data.ocsp_list[i] : ""); - shared_SSL_CTX unique_ctx(this->init_server_ssl_ctx(single_data, sslMultCertSettings.get(), iter->second), SSL_CTX_free); - if (!unique_ctx || !this->_store_single_ssl_ctx(lookup, sslMultCertSettings, unique_ctx, iter->second)) { - retval = false; - } else { - lookup->register_cert_secrets(data.cert_names_list, iter->second); + std::vector ctxs = this->init_server_ssl_ctx(single_data, sslMultCertSettings.get(), iter->second); + for (const auto &loadingctx : ctxs) { + shared_SSL_CTX unique_ctx(loadingctx.ctx, SSL_CTX_free); + if (!this->_store_single_ssl_ctx(lookup, sslMultCertSettings, unique_ctx, loadingctx.ctx_type, iter->second)) { + retval = false; + } else { + lookup->register_cert_secrets(data.cert_names_list, iter->second); + } } } return retval; @@ -1611,15 +1761,18 @@ SSLMultiCertConfigLoader::update_ssl_ctx(const std::string &secret_name) } if (!common_names.empty()) { - shared_SSL_CTX ctx(this->init_server_ssl_ctx(data, policy_iter->get(), common_names), SSL_CTX_free); + std::vector ctxs = this->init_server_ssl_ctx(data, policy_iter->get(), common_names); + for (const auto &loadingctx : ctxs) { + shared_SSL_CTX ctx(loadingctx.ctx, SSL_CTX_free); - if (!ctx) { - retval = false; - } else { - for (auto name : common_names) { - SSLCertContext *cc = lookup->find(name); - if (cc && cc->userconfig.get() == policy_iter->get()) { - cc->setCtx(ctx); + if (!ctx) { + retval = false; + } else { + for (auto const &name : common_names) { + SSLCertContext *cc = lookup->find(name, loadingctx.ctx_type); + if (cc && cc->userconfig.get() == policy_iter->get()) { + cc->setCtx(ctx); + } } } } @@ -1634,15 +1787,18 @@ SSLMultiCertConfigLoader::update_ssl_ctx(const std::string &secret_name) single_data.ca_list.push_back(i < data.ca_list.size() ? data.ca_list[i] : ""); single_data.ocsp_list.push_back(i < data.ocsp_list.size() ? data.ocsp_list[i] : ""); - shared_SSL_CTX unique_ctx(this->init_server_ssl_ctx(single_data, policy_iter->get(), iter->second), SSL_CTX_free); + std::vector ctxs = this->init_server_ssl_ctx(single_data, policy_iter->get(), iter->second); + for (auto const &loadingctx : ctxs) { + shared_SSL_CTX unique_ctx(loadingctx.ctx, SSL_CTX_free); - if (!unique_ctx) { - retval = false; - } else { - for (auto name : iter->second) { - SSLCertContext *cc = lookup->find(name); - if (cc && cc->userconfig.get() == policy_iter->get()) { - cc->setCtx(unique_ctx); + if (!unique_ctx) { + retval = false; + } else { + for (auto const &name : iter->second) { + SSLCertContext *cc = lookup->find(name, loadingctx.ctx_type); + if (cc && cc->userconfig.get() == policy_iter->get()) { + cc->setCtx(unique_ctx); + } } } } @@ -1653,7 +1809,7 @@ SSLMultiCertConfigLoader::update_ssl_ctx(const std::string &secret_name) bool SSLMultiCertConfigLoader::_store_single_ssl_ctx(SSLCertLookup *lookup, const shared_SSLMultiCertConfigParams &sslMultCertSettings, - shared_SSL_CTX ctx, std::set &names) + shared_SSL_CTX ctx, SSLCertContextType ctx_type, std::set &names) { bool inserted = false; shared_ssl_ticket_key_block keyblock = nullptr; @@ -1665,7 +1821,8 @@ SSLMultiCertConfigLoader::_store_single_ssl_ctx(SSLCertLookup *lookup, const sha // Index this certificate by the specified IP(v6) address. If the address is "*", make it the default context. if (sslMultCertSettings->addr) { if (strcmp(sslMultCertSettings->addr, "*") == 0) { - if (lookup->insert(sslMultCertSettings->addr, SSLCertContext(ctx, sslMultCertSettings, keyblock)) >= 0) { + Debug("ssl", "Addr is '*'; setting %p to default", ctx.get()); + if (lookup->insert(sslMultCertSettings->addr, SSLCertContext(ctx, ctx_type, sslMultCertSettings, keyblock)) >= 0) { inserted = true; lookup->ssl_default = ctx; this->_set_handshake_callbacks(ctx.get()); @@ -1674,7 +1831,7 @@ SSLMultiCertConfigLoader::_store_single_ssl_ctx(SSLCertLookup *lookup, const sha IpEndpoint ep; if (ats_ip_pton(sslMultCertSettings->addr, &ep) == 0) { - if (lookup->insert(ep, SSLCertContext(ctx, sslMultCertSettings, keyblock)) >= 0) { + if (lookup->insert(ep, SSLCertContext(ctx, ctx_type, sslMultCertSettings, keyblock)) >= 0) { inserted = true; } } else { @@ -1687,8 +1844,8 @@ SSLMultiCertConfigLoader::_store_single_ssl_ctx(SSLCertLookup *lookup, const sha // Insert additional mappings. Note that this maps multiple keys to the same value, so when // this code is updated to reconfigure the SSL certificates, it will need some sort of // refcounting or alternate way of avoiding double frees. - for (auto sni_name : names) { - if (lookup->insert(sni_name.c_str(), SSLCertContext(ctx, sslMultCertSettings, keyblock)) >= 0) { + for (auto const &sni_name : names) { + if (lookup->insert(sni_name.c_str(), SSLCertContext(ctx, ctx_type, sslMultCertSettings, keyblock)) >= 0) { inserted = true; } } @@ -1797,7 +1954,7 @@ SSLMultiCertConfigLoader::load(SSLCertLookup *lookup) switch (ec.value()) { case ENOENT: Warning("Cannot open SSL certificate configuration from %s - %s", params->configFilePath, strerror(ec.value())); - break; + return false; default: Error("Failed to read SSL certificate configuration from %s - %s", params->configFilePath, strerror(ec.value())); return false; @@ -1971,12 +2128,10 @@ get_verify_str(SSL *ssl) * of the including certificate */ bool -SSLMultiCertConfigLoader::load_certs_and_cross_reference_names(std::vector &cert_list, - SSLMultiCertConfigLoader::CertLoadData &data, - const SSLConfigParams *params, - const SSLMultiCertConfigParams *sslMultCertSettings, - std::set &common_names, - std::unordered_map> &unique_names) +SSLMultiCertConfigLoader::load_certs_and_cross_reference_names( + std::vector &cert_list, SSLMultiCertConfigLoader::CertLoadData &data, const SSLConfigParams *params, + const SSLMultiCertConfigParams *sslMultCertSettings, std::set &common_names, + std::unordered_map> &unique_names, SSLCertContextType *certType) { SimpleTokenizer cert_tok(sslMultCertSettings && sslMultCertSettings->cert ? (const char *)sslMultCertSettings->cert : "", SSL_CERT_SEPARATE_DELIM); @@ -2050,6 +2205,27 @@ SSLMultiCertConfigLoader::load_certs_and_cross_reference_names(std::vector public_key(X509_get_pubkey(cert), &EVP_PKEY_free); + int pkey_id = EVP_PKEY_id(public_key.get()); + + switch (pkey_id) { + case EVP_PKEY_EC: + *certType = SSLCertContextType::EC; + break; + case EVP_PKEY_RSA: + *certType = SSLCertContextType::RSA; + break; + default: + ink_assert(false); + } +#else + *certType = SSLCertContextType::GENERIC; +#endif + data.cert_type_list.push_back(*certType); + } + cert_list.push_back(cert); std::set name_set; @@ -2120,7 +2296,7 @@ SSLMultiCertConfigLoader::load_certs_and_cross_reference_names(std::vector new_set; @@ -2141,7 +2317,8 @@ SSLMultiCertConfigLoader::load_certs_and_cross_reference_names(std::vector &cert_names_list, + const std::vector &key_list, CertLoadData const &data, const SSLConfigParams *params, const SSLMultiCertConfigParams *sslMultCertSettings) { #if TS_USE_TLS_OCSP @@ -2157,13 +2334,15 @@ SSLMultiCertConfigLoader::load_certs(SSL_CTX *ctx, SSLMultiCertConfigLoader::Cer } #endif /* TS_USE_TLS_OCSP */ - for (size_t i = 0; i < data.cert_names_list.size(); i++) { - std::string keyPath = (i < data.key_list.size()) ? data.key_list[i] : ""; + ink_assert(!cert_names_list.empty()); + + for (size_t i = 0; i < cert_names_list.size(); i++) { + std::string keyPath = (i < key_list.size()) ? key_list[i] : ""; std::string_view secret_data; std::string_view secret_key_data; - params->secrets.getOrLoadSecret(data.cert_names_list[i], keyPath, secret_data, secret_key_data); + params->secrets.getOrLoadSecret(cert_names_list[i], keyPath, secret_data, secret_key_data); if (secret_data.empty()) { - SSLError("failed to load certificate secret for %s", data.cert_names_list[i].c_str()); + SSLError("failed to load certificate secret for %s", cert_names_list[i].c_str()); return false; } scoped_BIO bio(BIO_new_mem_buf(secret_data.data(), secret_data.size())); @@ -2171,18 +2350,23 @@ SSLMultiCertConfigLoader::load_certs(SSL_CTX *ctx, SSLMultiCertConfigLoader::Cer if (bio) { cert = PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr); } + if (!bio || !cert) { - SSLError("failed to load certificate chain from %s", data.cert_names_list[i].c_str()); + SSLError("failed to load certificate chain from %s", cert_names_list[i].c_str()); return false; } + + Debug("ssl", "for ctx=%p, using certificate %s", ctx, cert_names_list[i].c_str()); if (!SSL_CTX_use_certificate(ctx, cert)) { - SSLError("Failed to assign cert from %s to SSL_CTX", data.cert_names_list[i].c_str()); + SSLError("Failed to assign cert from %s to SSL_CTX", cert_names_list[i].c_str()); X509_free(cert); return false; } // Load up any additional chain certificates - SSL_CTX_add_extra_chain_cert_bio(ctx, bio); + if (!SSL_CTX_add_extra_chain_cert_bio(ctx, bio)) { + Debug("ssl", "couldn't add chain to %p", ctx); + } if (secret_key_data.empty()) { secret_key_data = secret_data; diff --git a/iocore/net/TLSSNISupport.cc b/iocore/net/TLSSNISupport.cc index 52cd4720541..b3dd1aa87e1 100644 --- a/iocore/net/TLSSNISupport.cc +++ b/iocore/net/TLSSNISupport.cc @@ -72,15 +72,24 @@ TLSSNISupport::perform_sni_action() return SSL_TLSEXT_ERR_OK; } -#if TS_USE_HELLO_CB +#if TS_USE_HELLO_CB || defined(OPENSSL_IS_BORINGSSL) void +#ifdef OPENSSL_IS_BORINGSSL +TLSSNISupport::on_client_hello(const SSL_CLIENT_HELLO *client_hello) +#else TLSSNISupport::on_client_hello(SSL *ssl, int *al, void *arg) +#endif { const char *servername = nullptr; const unsigned char *p; size_t remaining, len; // Parse the server name if the get extension call succeeds and there are more than 2 bytes to parse - if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &p, &remaining) && remaining > 2) { +#ifdef OPENSSL_IS_BORINGSSL + if (SSL_early_callback_ctx_extension_get(client_hello, TLSEXT_TYPE_server_name, &p, &remaining) && remaining > 2) +#else + if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &p, &remaining) && remaining > 2) +#endif + { // Parse to get to the name, originally from test/handshake_helper.c in openssl tree /* Extract the length of the supplied list of names. */ len = *(p++) << 8; diff --git a/iocore/net/TLSSNISupport.h b/iocore/net/TLSSNISupport.h index 82572028d9f..0470b6c281a 100644 --- a/iocore/net/TLSSNISupport.h +++ b/iocore/net/TLSSNISupport.h @@ -40,8 +40,12 @@ class TLSSNISupport int perform_sni_action(); // Callback functions for OpenSSL libraries -#if TS_USE_HELLO_CB +#if TS_USE_HELLO_CB || defined(OPENSSL_IS_BORINGSSL) +#ifdef OPENSSL_IS_BORINGSSL + void on_client_hello(const SSL_CLIENT_HELLO *client_hello); +#else void on_client_hello(SSL *ssl, int *al, void *arg); +#endif #endif void on_servername(SSL *ssl, int *al, void *arg); diff --git a/iocore/net/YamlSNIConfig.cc b/iocore/net/YamlSNIConfig.cc index 9b9b0d31be2..e38231f36e3 100644 --- a/iocore/net/YamlSNIConfig.cc +++ b/iocore/net/YamlSNIConfig.cc @@ -136,7 +136,7 @@ std::set valid_sni_config_keys = {TS_fqdn, TS_client_sni_policy, TS_http2, TS_ip_allow, -#if TS_USE_HELLO_CB +#if TS_USE_HELLO_CB || defined(OPENSSL_IS_BORINGSSL) TS_valid_tls_versions_in, #endif TS_host_sni_policy}; diff --git a/tests/gold_tests/tls_hooks/tls_hooks14.test.py b/tests/gold_tests/tls_hooks/tls_hooks14.test.py index cb5370e533a..e6c9ca06670 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks14.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks14.test.py @@ -23,10 +23,6 @@ Test different combinations of TLS handshake hooks to ensure they are applied consistently. ''' -Test.SkipUnless( - Condition.IsOpenSSL() -) - ts = Test.MakeATSProcess("ts", select_ports=True, enable_tls=True) server = Test.MakeOriginServer("server", ssl=True) request_header = {"headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} diff --git a/tests/gold_tests/tls_hooks/tls_hooks16.test.py b/tests/gold_tests/tls_hooks/tls_hooks16.test.py index 9e3029ea99a..844330f20a8 100644 --- a/tests/gold_tests/tls_hooks/tls_hooks16.test.py +++ b/tests/gold_tests/tls_hooks/tls_hooks16.test.py @@ -25,8 +25,7 @@ ''' Test.SkipUnless( - Condition.HasOpenSSLVersion("1.1.1"), - Condition.IsOpenSSL() + Condition.HasOpenSSLVersion("1.1.1") ) ts = Test.MakeATSProcess("ts", select_ports=True, enable_tls=True)