12c593315Sopenharmony_ci/*
22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library
32c593315Sopenharmony_ci *
42c593315Sopenharmony_ci * Copyright (c) 2012 Tatsuhiro Tsujikawa
52c593315Sopenharmony_ci *
62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the
82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
122c593315Sopenharmony_ci * the following conditions:
132c593315Sopenharmony_ci *
142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be
152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software.
162c593315Sopenharmony_ci *
172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242c593315Sopenharmony_ci */
252c593315Sopenharmony_ci#include "shrpx_tls.h"
262c593315Sopenharmony_ci
272c593315Sopenharmony_ci#ifdef HAVE_SYS_SOCKET_H
282c593315Sopenharmony_ci#  include <sys/socket.h>
292c593315Sopenharmony_ci#endif // HAVE_SYS_SOCKET_H
302c593315Sopenharmony_ci#ifdef HAVE_NETDB_H
312c593315Sopenharmony_ci#  include <netdb.h>
322c593315Sopenharmony_ci#endif // HAVE_NETDB_H
332c593315Sopenharmony_ci#include <netinet/tcp.h>
342c593315Sopenharmony_ci#include <pthread.h>
352c593315Sopenharmony_ci#include <sys/types.h>
362c593315Sopenharmony_ci
372c593315Sopenharmony_ci#include <vector>
382c593315Sopenharmony_ci#include <string>
392c593315Sopenharmony_ci#include <iomanip>
402c593315Sopenharmony_ci
412c593315Sopenharmony_ci#include <iostream>
422c593315Sopenharmony_ci
432c593315Sopenharmony_ci#include "ssl_compat.h"
442c593315Sopenharmony_ci
452c593315Sopenharmony_ci#include <openssl/crypto.h>
462c593315Sopenharmony_ci#include <openssl/x509.h>
472c593315Sopenharmony_ci#include <openssl/x509v3.h>
482c593315Sopenharmony_ci#include <openssl/rand.h>
492c593315Sopenharmony_ci#include <openssl/dh.h>
502c593315Sopenharmony_ci#ifndef OPENSSL_NO_OCSP
512c593315Sopenharmony_ci#  include <openssl/ocsp.h>
522c593315Sopenharmony_ci#endif // OPENSSL_NO_OCSP
532c593315Sopenharmony_ci#if OPENSSL_3_0_0_API
542c593315Sopenharmony_ci#  include <openssl/params.h>
552c593315Sopenharmony_ci#  include <openssl/core_names.h>
562c593315Sopenharmony_ci#  include <openssl/decoder.h>
572c593315Sopenharmony_ci#endif // OPENSSL_3_0_0_API
582c593315Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
592c593315Sopenharmony_ci#  include <openssl/hmac.h>
602c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL
612c593315Sopenharmony_ci
622c593315Sopenharmony_ci#include <nghttp2/nghttp2.h>
632c593315Sopenharmony_ci
642c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
652c593315Sopenharmony_ci#  include <ngtcp2/ngtcp2.h>
662c593315Sopenharmony_ci#  include <ngtcp2/ngtcp2_crypto.h>
672c593315Sopenharmony_ci#  ifdef HAVE_LIBNGTCP2_CRYPTO_QUICTLS
682c593315Sopenharmony_ci#    include <ngtcp2/ngtcp2_crypto_quictls.h>
692c593315Sopenharmony_ci#  endif // HAVE_LIBNGTCP2_CRYPTO_QUICTLS
702c593315Sopenharmony_ci#  ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
712c593315Sopenharmony_ci#    include <ngtcp2/ngtcp2_crypto_boringssl.h>
722c593315Sopenharmony_ci#  endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
732c593315Sopenharmony_ci#endif   // ENABLE_HTTP3
742c593315Sopenharmony_ci
752c593315Sopenharmony_ci#include "shrpx_log.h"
762c593315Sopenharmony_ci#include "shrpx_client_handler.h"
772c593315Sopenharmony_ci#include "shrpx_config.h"
782c593315Sopenharmony_ci#include "shrpx_worker.h"
792c593315Sopenharmony_ci#include "shrpx_downstream_connection_pool.h"
802c593315Sopenharmony_ci#include "shrpx_http2_session.h"
812c593315Sopenharmony_ci#include "shrpx_memcached_request.h"
822c593315Sopenharmony_ci#include "shrpx_memcached_dispatcher.h"
832c593315Sopenharmony_ci#include "shrpx_connection_handler.h"
842c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
852c593315Sopenharmony_ci#  include "shrpx_http3_upstream.h"
862c593315Sopenharmony_ci#endif // ENABLE_HTTP3
872c593315Sopenharmony_ci#include "util.h"
882c593315Sopenharmony_ci#include "tls.h"
892c593315Sopenharmony_ci#include "template.h"
902c593315Sopenharmony_ci#include "timegm.h"
912c593315Sopenharmony_ci
922c593315Sopenharmony_ciusing namespace nghttp2;
932c593315Sopenharmony_ciusing namespace std::chrono_literals;
942c593315Sopenharmony_ci
952c593315Sopenharmony_cinamespace shrpx {
962c593315Sopenharmony_ci
972c593315Sopenharmony_cinamespace tls {
982c593315Sopenharmony_ci
992c593315Sopenharmony_ci#if !OPENSSL_1_1_API
1002c593315Sopenharmony_cinamespace {
1012c593315Sopenharmony_ciconst unsigned char *ASN1_STRING_get0_data(ASN1_STRING *x) {
1022c593315Sopenharmony_ci  return ASN1_STRING_data(x);
1032c593315Sopenharmony_ci}
1042c593315Sopenharmony_ci} // namespace
1052c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API
1062c593315Sopenharmony_ci
1072c593315Sopenharmony_ci#ifndef OPENSSL_NO_NEXTPROTONEG
1082c593315Sopenharmony_cinamespace {
1092c593315Sopenharmony_ciint next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
1102c593315Sopenharmony_ci                  void *arg) {
1112c593315Sopenharmony_ci  auto &prefs = get_config()->tls.alpn_prefs;
1122c593315Sopenharmony_ci  *data = prefs.data();
1132c593315Sopenharmony_ci  *len = prefs.size();
1142c593315Sopenharmony_ci  return SSL_TLSEXT_ERR_OK;
1152c593315Sopenharmony_ci}
1162c593315Sopenharmony_ci} // namespace
1172c593315Sopenharmony_ci#endif // !OPENSSL_NO_NEXTPROTONEG
1182c593315Sopenharmony_ci
1192c593315Sopenharmony_cinamespace {
1202c593315Sopenharmony_ciint verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
1212c593315Sopenharmony_ci  if (!preverify_ok) {
1222c593315Sopenharmony_ci    int err = X509_STORE_CTX_get_error(ctx);
1232c593315Sopenharmony_ci    int depth = X509_STORE_CTX_get_error_depth(ctx);
1242c593315Sopenharmony_ci    if (err == X509_V_ERR_CERT_HAS_EXPIRED && depth == 0 &&
1252c593315Sopenharmony_ci        get_config()->tls.client_verify.tolerate_expired) {
1262c593315Sopenharmony_ci      LOG(INFO) << "The client certificate has expired, but is accepted by "
1272c593315Sopenharmony_ci                   "configuration";
1282c593315Sopenharmony_ci      return 1;
1292c593315Sopenharmony_ci    }
1302c593315Sopenharmony_ci    LOG(ERROR) << "client certificate verify error:num=" << err << ":"
1312c593315Sopenharmony_ci               << X509_verify_cert_error_string(err) << ":depth=" << depth;
1322c593315Sopenharmony_ci  }
1332c593315Sopenharmony_ci  return preverify_ok;
1342c593315Sopenharmony_ci}
1352c593315Sopenharmony_ci} // namespace
1362c593315Sopenharmony_ci
1372c593315Sopenharmony_ciint set_alpn_prefs(std::vector<unsigned char> &out,
1382c593315Sopenharmony_ci                   const std::vector<StringRef> &protos) {
1392c593315Sopenharmony_ci  size_t len = 0;
1402c593315Sopenharmony_ci
1412c593315Sopenharmony_ci  for (const auto &proto : protos) {
1422c593315Sopenharmony_ci    if (proto.size() > 255) {
1432c593315Sopenharmony_ci      LOG(FATAL) << "Too long ALPN identifier: " << proto.size();
1442c593315Sopenharmony_ci      return -1;
1452c593315Sopenharmony_ci    }
1462c593315Sopenharmony_ci
1472c593315Sopenharmony_ci    len += 1 + proto.size();
1482c593315Sopenharmony_ci  }
1492c593315Sopenharmony_ci
1502c593315Sopenharmony_ci  if (len > (1 << 16) - 1) {
1512c593315Sopenharmony_ci    LOG(FATAL) << "Too long ALPN identifier list: " << len;
1522c593315Sopenharmony_ci    return -1;
1532c593315Sopenharmony_ci  }
1542c593315Sopenharmony_ci
1552c593315Sopenharmony_ci  out.resize(len);
1562c593315Sopenharmony_ci  auto ptr = out.data();
1572c593315Sopenharmony_ci
1582c593315Sopenharmony_ci  for (const auto &proto : protos) {
1592c593315Sopenharmony_ci    *ptr++ = proto.size();
1602c593315Sopenharmony_ci    ptr = std::copy(std::begin(proto), std::end(proto), ptr);
1612c593315Sopenharmony_ci  }
1622c593315Sopenharmony_ci
1632c593315Sopenharmony_ci  return 0;
1642c593315Sopenharmony_ci}
1652c593315Sopenharmony_ci
1662c593315Sopenharmony_cinamespace {
1672c593315Sopenharmony_ciint ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) {
1682c593315Sopenharmony_ci  auto config = static_cast<Config *>(user_data);
1692c593315Sopenharmony_ci  auto len = static_cast<int>(config->tls.private_key_passwd.size());
1702c593315Sopenharmony_ci  if (size < len + 1) {
1712c593315Sopenharmony_ci    LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size;
1722c593315Sopenharmony_ci    return 0;
1732c593315Sopenharmony_ci  }
1742c593315Sopenharmony_ci  // Copy string including last '\0'.
1752c593315Sopenharmony_ci  memcpy(buf, config->tls.private_key_passwd.c_str(), len + 1);
1762c593315Sopenharmony_ci  return len;
1772c593315Sopenharmony_ci}
1782c593315Sopenharmony_ci} // namespace
1792c593315Sopenharmony_ci
1802c593315Sopenharmony_cinamespace {
1812c593315Sopenharmony_ci// *al is set to SSL_AD_UNRECOGNIZED_NAME by openssl, so we don't have
1822c593315Sopenharmony_ci// to set it explicitly.
1832c593315Sopenharmony_ciint servername_callback(SSL *ssl, int *al, void *arg) {
1842c593315Sopenharmony_ci  auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
1852c593315Sopenharmony_ci  auto handler = static_cast<ClientHandler *>(conn->data);
1862c593315Sopenharmony_ci  auto worker = handler->get_worker();
1872c593315Sopenharmony_ci
1882c593315Sopenharmony_ci  auto rawhost = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
1892c593315Sopenharmony_ci  if (rawhost == nullptr) {
1902c593315Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
1912c593315Sopenharmony_ci  }
1922c593315Sopenharmony_ci
1932c593315Sopenharmony_ci  auto len = strlen(rawhost);
1942c593315Sopenharmony_ci  // NI_MAXHOST includes terminal NULL.
1952c593315Sopenharmony_ci  if (len == 0 || len + 1 > NI_MAXHOST) {
1962c593315Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
1972c593315Sopenharmony_ci  }
1982c593315Sopenharmony_ci
1992c593315Sopenharmony_ci  std::array<uint8_t, NI_MAXHOST> buf;
2002c593315Sopenharmony_ci
2012c593315Sopenharmony_ci  auto end_buf = std::copy_n(rawhost, len, std::begin(buf));
2022c593315Sopenharmony_ci
2032c593315Sopenharmony_ci  util::inp_strlower(std::begin(buf), end_buf);
2042c593315Sopenharmony_ci
2052c593315Sopenharmony_ci  auto hostname = StringRef{std::begin(buf), end_buf};
2062c593315Sopenharmony_ci
2072c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2082c593315Sopenharmony_ci  auto cert_tree = conn->proto == Proto::HTTP3
2092c593315Sopenharmony_ci                       ? worker->get_quic_cert_lookup_tree()
2102c593315Sopenharmony_ci                       : worker->get_cert_lookup_tree();
2112c593315Sopenharmony_ci#else  // !ENABLE_HTTP3
2122c593315Sopenharmony_ci  auto cert_tree = worker->get_cert_lookup_tree();
2132c593315Sopenharmony_ci#endif // !ENABLE_HTTP3
2142c593315Sopenharmony_ci
2152c593315Sopenharmony_ci  auto idx = cert_tree->lookup(hostname);
2162c593315Sopenharmony_ci  if (idx == -1) {
2172c593315Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
2182c593315Sopenharmony_ci  }
2192c593315Sopenharmony_ci
2202c593315Sopenharmony_ci  handler->set_tls_sni(hostname);
2212c593315Sopenharmony_ci
2222c593315Sopenharmony_ci  auto conn_handler = worker->get_connection_handler();
2232c593315Sopenharmony_ci
2242c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2252c593315Sopenharmony_ci  const auto &ssl_ctx_list = conn->proto == Proto::HTTP3
2262c593315Sopenharmony_ci                                 ? conn_handler->get_quic_indexed_ssl_ctx(idx)
2272c593315Sopenharmony_ci                                 : conn_handler->get_indexed_ssl_ctx(idx);
2282c593315Sopenharmony_ci#else  // !ENABLE_HTTP3
2292c593315Sopenharmony_ci  const auto &ssl_ctx_list = conn_handler->get_indexed_ssl_ctx(idx);
2302c593315Sopenharmony_ci#endif // !ENABLE_HTTP3
2312c593315Sopenharmony_ci
2322c593315Sopenharmony_ci  assert(!ssl_ctx_list.empty());
2332c593315Sopenharmony_ci
2342c593315Sopenharmony_ci#if !defined(OPENSSL_IS_BORINGSSL) && !LIBRESSL_IN_USE &&                      \
2352c593315Sopenharmony_ci    OPENSSL_VERSION_NUMBER >= 0x10002000L
2362c593315Sopenharmony_ci  auto num_sigalgs =
2372c593315Sopenharmony_ci      SSL_get_sigalgs(ssl, 0, nullptr, nullptr, nullptr, nullptr, nullptr);
2382c593315Sopenharmony_ci
2392c593315Sopenharmony_ci  for (idx = 0; idx < num_sigalgs; ++idx) {
2402c593315Sopenharmony_ci    int signhash;
2412c593315Sopenharmony_ci
2422c593315Sopenharmony_ci    SSL_get_sigalgs(ssl, idx, nullptr, nullptr, &signhash, nullptr, nullptr);
2432c593315Sopenharmony_ci    switch (signhash) {
2442c593315Sopenharmony_ci    case NID_ecdsa_with_SHA256:
2452c593315Sopenharmony_ci    case NID_ecdsa_with_SHA384:
2462c593315Sopenharmony_ci    case NID_ecdsa_with_SHA512:
2472c593315Sopenharmony_ci      break;
2482c593315Sopenharmony_ci    default:
2492c593315Sopenharmony_ci      continue;
2502c593315Sopenharmony_ci    }
2512c593315Sopenharmony_ci
2522c593315Sopenharmony_ci    break;
2532c593315Sopenharmony_ci  }
2542c593315Sopenharmony_ci
2552c593315Sopenharmony_ci  if (idx == num_sigalgs) {
2562c593315Sopenharmony_ci    SSL_set_SSL_CTX(ssl, ssl_ctx_list[0]);
2572c593315Sopenharmony_ci
2582c593315Sopenharmony_ci    return SSL_TLSEXT_ERR_OK;
2592c593315Sopenharmony_ci  }
2602c593315Sopenharmony_ci
2612c593315Sopenharmony_ci  auto num_shared_curves = SSL_get_shared_curve(ssl, -1);
2622c593315Sopenharmony_ci
2632c593315Sopenharmony_ci  for (auto i = 0; i < num_shared_curves; ++i) {
2642c593315Sopenharmony_ci    auto shared_curve = SSL_get_shared_curve(ssl, i);
2652c593315Sopenharmony_ci#  if OPENSSL_3_0_0_API
2662c593315Sopenharmony_ci    // It looks like only short name is defined in OpenSSL.  No idea
2672c593315Sopenharmony_ci    // which one to use because it is unknown that which one
2682c593315Sopenharmony_ci    // EVP_PKEY_get_utf8_string_param("group") returns.
2692c593315Sopenharmony_ci    auto shared_curve_name = OBJ_nid2sn(shared_curve);
2702c593315Sopenharmony_ci    if (shared_curve_name == nullptr) {
2712c593315Sopenharmony_ci      continue;
2722c593315Sopenharmony_ci    }
2732c593315Sopenharmony_ci#  endif // OPENSSL_3_0_0_API
2742c593315Sopenharmony_ci
2752c593315Sopenharmony_ci    for (auto ssl_ctx : ssl_ctx_list) {
2762c593315Sopenharmony_ci      auto cert = SSL_CTX_get0_certificate(ssl_ctx);
2772c593315Sopenharmony_ci
2782c593315Sopenharmony_ci#  if OPENSSL_1_1_API
2792c593315Sopenharmony_ci      auto pubkey = X509_get0_pubkey(cert);
2802c593315Sopenharmony_ci#  else  // !OPENSSL_1_1_API
2812c593315Sopenharmony_ci      auto pubkey = X509_get_pubkey(cert);
2822c593315Sopenharmony_ci#  endif // !OPENSSL_1_1_API
2832c593315Sopenharmony_ci
2842c593315Sopenharmony_ci      if (EVP_PKEY_base_id(pubkey) != EVP_PKEY_EC) {
2852c593315Sopenharmony_ci        continue;
2862c593315Sopenharmony_ci      }
2872c593315Sopenharmony_ci
2882c593315Sopenharmony_ci#  if OPENSSL_3_0_0_API
2892c593315Sopenharmony_ci      std::array<char, 64> curve_name;
2902c593315Sopenharmony_ci      if (!EVP_PKEY_get_utf8_string_param(pubkey, "group", curve_name.data(),
2912c593315Sopenharmony_ci                                          curve_name.size(), nullptr)) {
2922c593315Sopenharmony_ci        continue;
2932c593315Sopenharmony_ci      }
2942c593315Sopenharmony_ci
2952c593315Sopenharmony_ci      if (strcmp(shared_curve_name, curve_name.data()) == 0) {
2962c593315Sopenharmony_ci        SSL_set_SSL_CTX(ssl, ssl_ctx);
2972c593315Sopenharmony_ci        return SSL_TLSEXT_ERR_OK;
2982c593315Sopenharmony_ci      }
2992c593315Sopenharmony_ci#  else // !OPENSSL_3_0_0_API
3002c593315Sopenharmony_ci#    if OPENSSL_1_1_API
3012c593315Sopenharmony_ci      auto eckey = EVP_PKEY_get0_EC_KEY(pubkey);
3022c593315Sopenharmony_ci#    else  // !OPENSSL_1_1_API
3032c593315Sopenharmony_ci      auto eckey = EVP_PKEY_get1_EC_KEY(pubkey);
3042c593315Sopenharmony_ci#    endif // !OPENSSL_1_1_API
3052c593315Sopenharmony_ci
3062c593315Sopenharmony_ci      if (eckey == nullptr) {
3072c593315Sopenharmony_ci        continue;
3082c593315Sopenharmony_ci      }
3092c593315Sopenharmony_ci
3102c593315Sopenharmony_ci      auto ecgroup = EC_KEY_get0_group(eckey);
3112c593315Sopenharmony_ci      auto cert_curve = EC_GROUP_get_curve_name(ecgroup);
3122c593315Sopenharmony_ci
3132c593315Sopenharmony_ci#    if !OPENSSL_1_1_API
3142c593315Sopenharmony_ci      EC_KEY_free(eckey);
3152c593315Sopenharmony_ci      EVP_PKEY_free(pubkey);
3162c593315Sopenharmony_ci#    endif // !OPENSSL_1_1_API
3172c593315Sopenharmony_ci
3182c593315Sopenharmony_ci      if (shared_curve == cert_curve) {
3192c593315Sopenharmony_ci        SSL_set_SSL_CTX(ssl, ssl_ctx);
3202c593315Sopenharmony_ci        return SSL_TLSEXT_ERR_OK;
3212c593315Sopenharmony_ci      }
3222c593315Sopenharmony_ci#  endif   // !OPENSSL_3_0_0_API
3232c593315Sopenharmony_ci    }
3242c593315Sopenharmony_ci  }
3252c593315Sopenharmony_ci#endif // !defined(OPENSSL_IS_BORINGSSL) && !LIBRESSL_IN_USE &&
3262c593315Sopenharmony_ci       // OPENSSL_VERSION_NUMBER >= 0x10002000L
3272c593315Sopenharmony_ci
3282c593315Sopenharmony_ci  SSL_set_SSL_CTX(ssl, ssl_ctx_list[0]);
3292c593315Sopenharmony_ci
3302c593315Sopenharmony_ci  return SSL_TLSEXT_ERR_OK;
3312c593315Sopenharmony_ci}
3322c593315Sopenharmony_ci} // namespace
3332c593315Sopenharmony_ci
3342c593315Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL
3352c593315Sopenharmony_cinamespace {
3362c593315Sopenharmony_cistd::shared_ptr<std::vector<uint8_t>>
3372c593315Sopenharmony_ciget_ocsp_data(TLSContextData *tls_ctx_data) {
3382c593315Sopenharmony_ci#  ifdef HAVE_ATOMIC_STD_SHARED_PTR
3392c593315Sopenharmony_ci  return std::atomic_load_explicit(&tls_ctx_data->ocsp_data,
3402c593315Sopenharmony_ci                                   std::memory_order_acquire);
3412c593315Sopenharmony_ci#  else  // !HAVE_ATOMIC_STD_SHARED_PTR
3422c593315Sopenharmony_ci  std::lock_guard<std::mutex> g(tls_ctx_data->mu);
3432c593315Sopenharmony_ci  return tls_ctx_data->ocsp_data;
3442c593315Sopenharmony_ci#  endif // !HAVE_ATOMIC_STD_SHARED_PTR
3452c593315Sopenharmony_ci}
3462c593315Sopenharmony_ci} // namespace
3472c593315Sopenharmony_ci
3482c593315Sopenharmony_cinamespace {
3492c593315Sopenharmony_ciint ocsp_resp_cb(SSL *ssl, void *arg) {
3502c593315Sopenharmony_ci  auto ssl_ctx = SSL_get_SSL_CTX(ssl);
3512c593315Sopenharmony_ci  auto tls_ctx_data =
3522c593315Sopenharmony_ci      static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
3532c593315Sopenharmony_ci
3542c593315Sopenharmony_ci  auto data = get_ocsp_data(tls_ctx_data);
3552c593315Sopenharmony_ci
3562c593315Sopenharmony_ci  if (!data) {
3572c593315Sopenharmony_ci    return SSL_TLSEXT_ERR_OK;
3582c593315Sopenharmony_ci  }
3592c593315Sopenharmony_ci
3602c593315Sopenharmony_ci  auto buf =
3612c593315Sopenharmony_ci      static_cast<uint8_t *>(CRYPTO_malloc(data->size(), __FILE__, __LINE__));
3622c593315Sopenharmony_ci
3632c593315Sopenharmony_ci  if (!buf) {
3642c593315Sopenharmony_ci    return SSL_TLSEXT_ERR_OK;
3652c593315Sopenharmony_ci  }
3662c593315Sopenharmony_ci
3672c593315Sopenharmony_ci  std::copy(std::begin(*data), std::end(*data), buf);
3682c593315Sopenharmony_ci
3692c593315Sopenharmony_ci  SSL_set_tlsext_status_ocsp_resp(ssl, buf, data->size());
3702c593315Sopenharmony_ci
3712c593315Sopenharmony_ci  return SSL_TLSEXT_ERR_OK;
3722c593315Sopenharmony_ci}
3732c593315Sopenharmony_ci} // namespace
3742c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL
3752c593315Sopenharmony_ci
3762c593315Sopenharmony_ciconstexpr auto MEMCACHED_SESSION_CACHE_KEY_PREFIX =
3772c593315Sopenharmony_ci    StringRef::from_lit("nghttpx:tls-session-cache:");
3782c593315Sopenharmony_ci
3792c593315Sopenharmony_cinamespace {
3802c593315Sopenharmony_ciint tls_session_client_new_cb(SSL *ssl, SSL_SESSION *session) {
3812c593315Sopenharmony_ci  auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
3822c593315Sopenharmony_ci  if (conn->tls.client_session_cache == nullptr) {
3832c593315Sopenharmony_ci    return 0;
3842c593315Sopenharmony_ci  }
3852c593315Sopenharmony_ci
3862c593315Sopenharmony_ci  try_cache_tls_session(conn->tls.client_session_cache, session,
3872c593315Sopenharmony_ci                        std::chrono::steady_clock::now());
3882c593315Sopenharmony_ci
3892c593315Sopenharmony_ci  return 0;
3902c593315Sopenharmony_ci}
3912c593315Sopenharmony_ci} // namespace
3922c593315Sopenharmony_ci
3932c593315Sopenharmony_cinamespace {
3942c593315Sopenharmony_ciint tls_session_new_cb(SSL *ssl, SSL_SESSION *session) {
3952c593315Sopenharmony_ci  auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
3962c593315Sopenharmony_ci  auto handler = static_cast<ClientHandler *>(conn->data);
3972c593315Sopenharmony_ci  auto worker = handler->get_worker();
3982c593315Sopenharmony_ci  auto dispatcher = worker->get_session_cache_memcached_dispatcher();
3992c593315Sopenharmony_ci  auto &balloc = handler->get_block_allocator();
4002c593315Sopenharmony_ci
4012c593315Sopenharmony_ci#ifdef TLS1_3_VERSION
4022c593315Sopenharmony_ci  if (SSL_version(ssl) == TLS1_3_VERSION) {
4032c593315Sopenharmony_ci    return 0;
4042c593315Sopenharmony_ci  }
4052c593315Sopenharmony_ci#endif // TLS1_3_VERSION
4062c593315Sopenharmony_ci
4072c593315Sopenharmony_ci  const unsigned char *id;
4082c593315Sopenharmony_ci  unsigned int idlen;
4092c593315Sopenharmony_ci
4102c593315Sopenharmony_ci  id = SSL_SESSION_get_id(session, &idlen);
4112c593315Sopenharmony_ci
4122c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
4132c593315Sopenharmony_ci    LOG(INFO) << "Memcached: cache session, id=" << util::format_hex(id, idlen);
4142c593315Sopenharmony_ci  }
4152c593315Sopenharmony_ci
4162c593315Sopenharmony_ci  auto req = std::make_unique<MemcachedRequest>();
4172c593315Sopenharmony_ci  req->op = MemcachedOp::ADD;
4182c593315Sopenharmony_ci  req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX.str();
4192c593315Sopenharmony_ci  req->key +=
4202c593315Sopenharmony_ci      util::format_hex(balloc, StringRef{id, static_cast<size_t>(idlen)});
4212c593315Sopenharmony_ci
4222c593315Sopenharmony_ci  auto sessionlen = i2d_SSL_SESSION(session, nullptr);
4232c593315Sopenharmony_ci  req->value.resize(sessionlen);
4242c593315Sopenharmony_ci  auto buf = &req->value[0];
4252c593315Sopenharmony_ci  i2d_SSL_SESSION(session, &buf);
4262c593315Sopenharmony_ci  req->expiry = 12_h;
4272c593315Sopenharmony_ci  req->cb = [](MemcachedRequest *req, MemcachedResult res) {
4282c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
4292c593315Sopenharmony_ci      LOG(INFO) << "Memcached: session cache done.  key=" << req->key
4302c593315Sopenharmony_ci                << ", status_code=" << static_cast<uint16_t>(res.status_code)
4312c593315Sopenharmony_ci                << ", value="
4322c593315Sopenharmony_ci                << std::string(std::begin(res.value), std::end(res.value));
4332c593315Sopenharmony_ci    }
4342c593315Sopenharmony_ci    if (res.status_code != MemcachedStatusCode::NO_ERROR) {
4352c593315Sopenharmony_ci      LOG(WARN) << "Memcached: failed to cache session key=" << req->key
4362c593315Sopenharmony_ci                << ", status_code=" << static_cast<uint16_t>(res.status_code)
4372c593315Sopenharmony_ci                << ", value="
4382c593315Sopenharmony_ci                << std::string(std::begin(res.value), std::end(res.value));
4392c593315Sopenharmony_ci    }
4402c593315Sopenharmony_ci  };
4412c593315Sopenharmony_ci  assert(!req->canceled);
4422c593315Sopenharmony_ci
4432c593315Sopenharmony_ci  dispatcher->add_request(std::move(req));
4442c593315Sopenharmony_ci
4452c593315Sopenharmony_ci  return 0;
4462c593315Sopenharmony_ci}
4472c593315Sopenharmony_ci} // namespace
4482c593315Sopenharmony_ci
4492c593315Sopenharmony_cinamespace {
4502c593315Sopenharmony_ciSSL_SESSION *tls_session_get_cb(SSL *ssl,
4512c593315Sopenharmony_ci#if OPENSSL_1_1_API || LIBRESSL_2_7_API
4522c593315Sopenharmony_ci                                const unsigned char *id,
4532c593315Sopenharmony_ci#else  // !(OPENSSL_1_1_API || LIBRESSL_2_7_API)
4542c593315Sopenharmony_ci                                unsigned char *id,
4552c593315Sopenharmony_ci#endif // !(OPENSSL_1_1_API || LIBRESSL_2_7_API)
4562c593315Sopenharmony_ci                                int idlen, int *copy) {
4572c593315Sopenharmony_ci  auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
4582c593315Sopenharmony_ci  auto handler = static_cast<ClientHandler *>(conn->data);
4592c593315Sopenharmony_ci  auto worker = handler->get_worker();
4602c593315Sopenharmony_ci  auto dispatcher = worker->get_session_cache_memcached_dispatcher();
4612c593315Sopenharmony_ci  auto &balloc = handler->get_block_allocator();
4622c593315Sopenharmony_ci
4632c593315Sopenharmony_ci  if (idlen == 0) {
4642c593315Sopenharmony_ci    return nullptr;
4652c593315Sopenharmony_ci  }
4662c593315Sopenharmony_ci
4672c593315Sopenharmony_ci  if (conn->tls.cached_session) {
4682c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
4692c593315Sopenharmony_ci      LOG(INFO) << "Memcached: found cached session, id="
4702c593315Sopenharmony_ci                << util::format_hex(id, idlen);
4712c593315Sopenharmony_ci    }
4722c593315Sopenharmony_ci
4732c593315Sopenharmony_ci    // This is required, without this, memory leak occurs.
4742c593315Sopenharmony_ci    *copy = 0;
4752c593315Sopenharmony_ci
4762c593315Sopenharmony_ci    auto session = conn->tls.cached_session;
4772c593315Sopenharmony_ci    conn->tls.cached_session = nullptr;
4782c593315Sopenharmony_ci    return session;
4792c593315Sopenharmony_ci  }
4802c593315Sopenharmony_ci
4812c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
4822c593315Sopenharmony_ci    LOG(INFO) << "Memcached: get cached session, id="
4832c593315Sopenharmony_ci              << util::format_hex(id, idlen);
4842c593315Sopenharmony_ci  }
4852c593315Sopenharmony_ci
4862c593315Sopenharmony_ci  auto req = std::make_unique<MemcachedRequest>();
4872c593315Sopenharmony_ci  req->op = MemcachedOp::GET;
4882c593315Sopenharmony_ci  req->key = MEMCACHED_SESSION_CACHE_KEY_PREFIX.str();
4892c593315Sopenharmony_ci  req->key +=
4902c593315Sopenharmony_ci      util::format_hex(balloc, StringRef{id, static_cast<size_t>(idlen)});
4912c593315Sopenharmony_ci  req->cb = [conn](MemcachedRequest *, MemcachedResult res) {
4922c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
4932c593315Sopenharmony_ci      LOG(INFO) << "Memcached: returned status code "
4942c593315Sopenharmony_ci                << static_cast<uint16_t>(res.status_code);
4952c593315Sopenharmony_ci    }
4962c593315Sopenharmony_ci
4972c593315Sopenharmony_ci    // We might stop reading, so start it again
4982c593315Sopenharmony_ci    conn->rlimit.startw();
4992c593315Sopenharmony_ci    ev_timer_again(conn->loop, &conn->rt);
5002c593315Sopenharmony_ci
5012c593315Sopenharmony_ci    conn->wlimit.startw();
5022c593315Sopenharmony_ci    ev_timer_again(conn->loop, &conn->wt);
5032c593315Sopenharmony_ci
5042c593315Sopenharmony_ci    conn->tls.cached_session_lookup_req = nullptr;
5052c593315Sopenharmony_ci    if (res.status_code != MemcachedStatusCode::NO_ERROR) {
5062c593315Sopenharmony_ci      conn->tls.handshake_state = TLSHandshakeState::CANCEL_SESSION_CACHE;
5072c593315Sopenharmony_ci      return;
5082c593315Sopenharmony_ci    }
5092c593315Sopenharmony_ci
5102c593315Sopenharmony_ci    const uint8_t *p = res.value.data();
5112c593315Sopenharmony_ci
5122c593315Sopenharmony_ci    auto session = d2i_SSL_SESSION(nullptr, &p, res.value.size());
5132c593315Sopenharmony_ci    if (!session) {
5142c593315Sopenharmony_ci      if (LOG_ENABLED(INFO)) {
5152c593315Sopenharmony_ci        LOG(INFO) << "cannot materialize session";
5162c593315Sopenharmony_ci      }
5172c593315Sopenharmony_ci      conn->tls.handshake_state = TLSHandshakeState::CANCEL_SESSION_CACHE;
5182c593315Sopenharmony_ci      return;
5192c593315Sopenharmony_ci    }
5202c593315Sopenharmony_ci
5212c593315Sopenharmony_ci    conn->tls.cached_session = session;
5222c593315Sopenharmony_ci    conn->tls.handshake_state = TLSHandshakeState::GOT_SESSION_CACHE;
5232c593315Sopenharmony_ci  };
5242c593315Sopenharmony_ci
5252c593315Sopenharmony_ci  conn->tls.handshake_state = TLSHandshakeState::WAIT_FOR_SESSION_CACHE;
5262c593315Sopenharmony_ci  conn->tls.cached_session_lookup_req = req.get();
5272c593315Sopenharmony_ci
5282c593315Sopenharmony_ci  dispatcher->add_request(std::move(req));
5292c593315Sopenharmony_ci
5302c593315Sopenharmony_ci  return nullptr;
5312c593315Sopenharmony_ci}
5322c593315Sopenharmony_ci} // namespace
5332c593315Sopenharmony_ci
5342c593315Sopenharmony_cinamespace {
5352c593315Sopenharmony_ciint ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv,
5362c593315Sopenharmony_ci                  EVP_CIPHER_CTX *ctx,
5372c593315Sopenharmony_ci#if OPENSSL_3_0_0_API
5382c593315Sopenharmony_ci                  EVP_MAC_CTX *hctx,
5392c593315Sopenharmony_ci#else  // !OPENSSL_3_0_0_API
5402c593315Sopenharmony_ci                  HMAC_CTX *hctx,
5412c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API
5422c593315Sopenharmony_ci                  int enc) {
5432c593315Sopenharmony_ci  auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
5442c593315Sopenharmony_ci  auto handler = static_cast<ClientHandler *>(conn->data);
5452c593315Sopenharmony_ci  auto worker = handler->get_worker();
5462c593315Sopenharmony_ci  auto ticket_keys = worker->get_ticket_keys();
5472c593315Sopenharmony_ci
5482c593315Sopenharmony_ci  if (!ticket_keys) {
5492c593315Sopenharmony_ci    // No ticket keys available.
5502c593315Sopenharmony_ci    return -1;
5512c593315Sopenharmony_ci  }
5522c593315Sopenharmony_ci
5532c593315Sopenharmony_ci  auto &keys = ticket_keys->keys;
5542c593315Sopenharmony_ci  assert(!keys.empty());
5552c593315Sopenharmony_ci
5562c593315Sopenharmony_ci  if (enc) {
5572c593315Sopenharmony_ci    if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) == 0) {
5582c593315Sopenharmony_ci      if (LOG_ENABLED(INFO)) {
5592c593315Sopenharmony_ci        CLOG(INFO, handler) << "session ticket key: RAND_bytes failed";
5602c593315Sopenharmony_ci      }
5612c593315Sopenharmony_ci      return -1;
5622c593315Sopenharmony_ci    }
5632c593315Sopenharmony_ci
5642c593315Sopenharmony_ci    auto &key = keys[0];
5652c593315Sopenharmony_ci
5662c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
5672c593315Sopenharmony_ci      CLOG(INFO, handler) << "encrypt session ticket key: "
5682c593315Sopenharmony_ci                          << util::format_hex(key.data.name);
5692c593315Sopenharmony_ci    }
5702c593315Sopenharmony_ci
5712c593315Sopenharmony_ci    std::copy(std::begin(key.data.name), std::end(key.data.name), key_name);
5722c593315Sopenharmony_ci
5732c593315Sopenharmony_ci    EVP_EncryptInit_ex(ctx, get_config()->tls.ticket.cipher, nullptr,
5742c593315Sopenharmony_ci                       key.data.enc_key.data(), iv);
5752c593315Sopenharmony_ci#if OPENSSL_3_0_0_API
5762c593315Sopenharmony_ci    std::array<OSSL_PARAM, 3> params{
5772c593315Sopenharmony_ci        OSSL_PARAM_construct_octet_string(
5782c593315Sopenharmony_ci            OSSL_MAC_PARAM_KEY, key.data.hmac_key.data(), key.hmac_keylen),
5792c593315Sopenharmony_ci        OSSL_PARAM_construct_utf8_string(
5802c593315Sopenharmony_ci            OSSL_MAC_PARAM_DIGEST,
5812c593315Sopenharmony_ci            const_cast<char *>(EVP_MD_get0_name(key.hmac)), 0),
5822c593315Sopenharmony_ci        OSSL_PARAM_construct_end(),
5832c593315Sopenharmony_ci    };
5842c593315Sopenharmony_ci    if (!EVP_MAC_CTX_set_params(hctx, params.data())) {
5852c593315Sopenharmony_ci      if (LOG_ENABLED(INFO)) {
5862c593315Sopenharmony_ci        CLOG(INFO, handler) << "EVP_MAC_CTX_set_params failed";
5872c593315Sopenharmony_ci      }
5882c593315Sopenharmony_ci      return -1;
5892c593315Sopenharmony_ci    }
5902c593315Sopenharmony_ci#else  // !OPENSSL_3_0_0_API
5912c593315Sopenharmony_ci    HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac,
5922c593315Sopenharmony_ci                 nullptr);
5932c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API
5942c593315Sopenharmony_ci    return 1;
5952c593315Sopenharmony_ci  }
5962c593315Sopenharmony_ci
5972c593315Sopenharmony_ci  size_t i;
5982c593315Sopenharmony_ci  for (i = 0; i < keys.size(); ++i) {
5992c593315Sopenharmony_ci    auto &key = keys[i];
6002c593315Sopenharmony_ci    if (std::equal(std::begin(key.data.name), std::end(key.data.name),
6012c593315Sopenharmony_ci                   key_name)) {
6022c593315Sopenharmony_ci      break;
6032c593315Sopenharmony_ci    }
6042c593315Sopenharmony_ci  }
6052c593315Sopenharmony_ci
6062c593315Sopenharmony_ci  if (i == keys.size()) {
6072c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
6082c593315Sopenharmony_ci      CLOG(INFO, handler) << "session ticket key "
6092c593315Sopenharmony_ci                          << util::format_hex(key_name, 16) << " not found";
6102c593315Sopenharmony_ci    }
6112c593315Sopenharmony_ci    return 0;
6122c593315Sopenharmony_ci  }
6132c593315Sopenharmony_ci
6142c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
6152c593315Sopenharmony_ci    CLOG(INFO, handler) << "decrypt session ticket key: "
6162c593315Sopenharmony_ci                        << util::format_hex(key_name, 16);
6172c593315Sopenharmony_ci  }
6182c593315Sopenharmony_ci
6192c593315Sopenharmony_ci  auto &key = keys[i];
6202c593315Sopenharmony_ci#if OPENSSL_3_0_0_API
6212c593315Sopenharmony_ci  std::array<OSSL_PARAM, 3> params{
6222c593315Sopenharmony_ci      OSSL_PARAM_construct_octet_string(
6232c593315Sopenharmony_ci          OSSL_MAC_PARAM_KEY, key.data.hmac_key.data(), key.hmac_keylen),
6242c593315Sopenharmony_ci      OSSL_PARAM_construct_utf8_string(
6252c593315Sopenharmony_ci          OSSL_MAC_PARAM_DIGEST, const_cast<char *>(EVP_MD_get0_name(key.hmac)),
6262c593315Sopenharmony_ci          0),
6272c593315Sopenharmony_ci      OSSL_PARAM_construct_end(),
6282c593315Sopenharmony_ci  };
6292c593315Sopenharmony_ci  if (!EVP_MAC_CTX_set_params(hctx, params.data())) {
6302c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
6312c593315Sopenharmony_ci      CLOG(INFO, handler) << "EVP_MAC_CTX_set_params failed";
6322c593315Sopenharmony_ci    }
6332c593315Sopenharmony_ci    return -1;
6342c593315Sopenharmony_ci  }
6352c593315Sopenharmony_ci#else  // !OPENSSL_3_0_0_API
6362c593315Sopenharmony_ci  HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac,
6372c593315Sopenharmony_ci               nullptr);
6382c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API
6392c593315Sopenharmony_ci  EVP_DecryptInit_ex(ctx, key.cipher, nullptr, key.data.enc_key.data(), iv);
6402c593315Sopenharmony_ci
6412c593315Sopenharmony_ci#ifdef TLS1_3_VERSION
6422c593315Sopenharmony_ci  // If ticket_key_cb is not set, OpenSSL always renew ticket for
6432c593315Sopenharmony_ci  // TLSv1.3.
6442c593315Sopenharmony_ci  if (SSL_version(ssl) == TLS1_3_VERSION) {
6452c593315Sopenharmony_ci    return 2;
6462c593315Sopenharmony_ci  }
6472c593315Sopenharmony_ci#endif // TLS1_3_VERSION
6482c593315Sopenharmony_ci
6492c593315Sopenharmony_ci  return i == 0 ? 1 : 2;
6502c593315Sopenharmony_ci}
6512c593315Sopenharmony_ci} // namespace
6522c593315Sopenharmony_ci
6532c593315Sopenharmony_cinamespace {
6542c593315Sopenharmony_civoid info_callback(const SSL *ssl, int where, int ret) {
6552c593315Sopenharmony_ci#ifdef TLS1_3_VERSION
6562c593315Sopenharmony_ci  // TLSv1.3 has no renegotiation.
6572c593315Sopenharmony_ci  if (SSL_version(ssl) == TLS1_3_VERSION) {
6582c593315Sopenharmony_ci    return;
6592c593315Sopenharmony_ci  }
6602c593315Sopenharmony_ci#endif // TLS1_3_VERSION
6612c593315Sopenharmony_ci
6622c593315Sopenharmony_ci  // To mitigate possible DOS attack using lots of renegotiations, we
6632c593315Sopenharmony_ci  // disable renegotiation. Since OpenSSL does not provide an easy way
6642c593315Sopenharmony_ci  // to disable it, we check that renegotiation is started in this
6652c593315Sopenharmony_ci  // callback.
6662c593315Sopenharmony_ci  if (where & SSL_CB_HANDSHAKE_START) {
6672c593315Sopenharmony_ci    auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
6682c593315Sopenharmony_ci    if (conn && conn->tls.initial_handshake_done) {
6692c593315Sopenharmony_ci      auto handler = static_cast<ClientHandler *>(conn->data);
6702c593315Sopenharmony_ci      if (LOG_ENABLED(INFO)) {
6712c593315Sopenharmony_ci        CLOG(INFO, handler) << "TLS renegotiation started";
6722c593315Sopenharmony_ci      }
6732c593315Sopenharmony_ci      handler->start_immediate_shutdown();
6742c593315Sopenharmony_ci    }
6752c593315Sopenharmony_ci  }
6762c593315Sopenharmony_ci}
6772c593315Sopenharmony_ci} // namespace
6782c593315Sopenharmony_ci
6792c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L
6802c593315Sopenharmony_cinamespace {
6812c593315Sopenharmony_ciint alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
6822c593315Sopenharmony_ci                         unsigned char *outlen, const unsigned char *in,
6832c593315Sopenharmony_ci                         unsigned int inlen, void *arg) {
6842c593315Sopenharmony_ci  // We assume that get_config()->npn_list contains ALPN protocol
6852c593315Sopenharmony_ci  // identifier sorted by preference order.  So we just break when we
6862c593315Sopenharmony_ci  // found the first overlap.
6872c593315Sopenharmony_ci  for (const auto &target_proto_id : get_config()->tls.npn_list) {
6882c593315Sopenharmony_ci    for (auto p = in, end = in + inlen; p < end;) {
6892c593315Sopenharmony_ci      auto proto_id = p + 1;
6902c593315Sopenharmony_ci      auto proto_len = *p;
6912c593315Sopenharmony_ci
6922c593315Sopenharmony_ci      if (proto_id + proto_len <= end &&
6932c593315Sopenharmony_ci          util::streq(target_proto_id, StringRef{proto_id, proto_len})) {
6942c593315Sopenharmony_ci
6952c593315Sopenharmony_ci        *out = reinterpret_cast<const unsigned char *>(proto_id);
6962c593315Sopenharmony_ci        *outlen = proto_len;
6972c593315Sopenharmony_ci
6982c593315Sopenharmony_ci        return SSL_TLSEXT_ERR_OK;
6992c593315Sopenharmony_ci      }
7002c593315Sopenharmony_ci
7012c593315Sopenharmony_ci      p += 1 + proto_len;
7022c593315Sopenharmony_ci    }
7032c593315Sopenharmony_ci  }
7042c593315Sopenharmony_ci
7052c593315Sopenharmony_ci  return SSL_TLSEXT_ERR_NOACK;
7062c593315Sopenharmony_ci}
7072c593315Sopenharmony_ci} // namespace
7082c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
7092c593315Sopenharmony_ci
7102c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
7112c593315Sopenharmony_ci#  if OPENSSL_VERSION_NUMBER >= 0x10002000L
7122c593315Sopenharmony_cinamespace {
7132c593315Sopenharmony_ciint quic_alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
7142c593315Sopenharmony_ci                              unsigned char *outlen, const unsigned char *in,
7152c593315Sopenharmony_ci                              unsigned int inlen, void *arg) {
7162c593315Sopenharmony_ci  constexpr StringRef alpnlist[] = {
7172c593315Sopenharmony_ci      StringRef::from_lit("h3"),
7182c593315Sopenharmony_ci      StringRef::from_lit("h3-29"),
7192c593315Sopenharmony_ci  };
7202c593315Sopenharmony_ci
7212c593315Sopenharmony_ci  for (auto &alpn : alpnlist) {
7222c593315Sopenharmony_ci    for (auto p = in, end = in + inlen; p < end;) {
7232c593315Sopenharmony_ci      auto proto_id = p + 1;
7242c593315Sopenharmony_ci      auto proto_len = *p;
7252c593315Sopenharmony_ci
7262c593315Sopenharmony_ci      if (alpn.size() == proto_len &&
7272c593315Sopenharmony_ci          memcmp(alpn.byte(), proto_id, alpn.size()) == 0) {
7282c593315Sopenharmony_ci        *out = proto_id;
7292c593315Sopenharmony_ci        *outlen = proto_len;
7302c593315Sopenharmony_ci
7312c593315Sopenharmony_ci        return SSL_TLSEXT_ERR_OK;
7322c593315Sopenharmony_ci      }
7332c593315Sopenharmony_ci
7342c593315Sopenharmony_ci      p += 1 + proto_len;
7352c593315Sopenharmony_ci    }
7362c593315Sopenharmony_ci  }
7372c593315Sopenharmony_ci
7382c593315Sopenharmony_ci  return SSL_TLSEXT_ERR_ALERT_FATAL;
7392c593315Sopenharmony_ci}
7402c593315Sopenharmony_ci} // namespace
7412c593315Sopenharmony_ci#  endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
7422c593315Sopenharmony_ci#endif   // ENABLE_HTTP3
7432c593315Sopenharmony_ci
7442c593315Sopenharmony_ci#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&               \
7452c593315Sopenharmony_ci    !defined(OPENSSL_IS_BORINGSSL)
7462c593315Sopenharmony_ci
7472c593315Sopenharmony_ci#  ifndef TLSEXT_TYPE_signed_certificate_timestamp
7482c593315Sopenharmony_ci#    define TLSEXT_TYPE_signed_certificate_timestamp 18
7492c593315Sopenharmony_ci#  endif // !TLSEXT_TYPE_signed_certificate_timestamp
7502c593315Sopenharmony_ci
7512c593315Sopenharmony_cinamespace {
7522c593315Sopenharmony_ciint sct_add_cb(SSL *ssl, unsigned int ext_type, unsigned int context,
7532c593315Sopenharmony_ci               const unsigned char **out, size_t *outlen, X509 *x,
7542c593315Sopenharmony_ci               size_t chainidx, int *al, void *add_arg) {
7552c593315Sopenharmony_ci  assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp);
7562c593315Sopenharmony_ci
7572c593315Sopenharmony_ci  auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
7582c593315Sopenharmony_ci  if (!conn->tls.sct_requested) {
7592c593315Sopenharmony_ci    return 0;
7602c593315Sopenharmony_ci  }
7612c593315Sopenharmony_ci
7622c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
7632c593315Sopenharmony_ci    LOG(INFO) << "sct_add_cb is called, chainidx=" << chainidx << ", x=" << x
7642c593315Sopenharmony_ci              << ", context=" << log::hex << context;
7652c593315Sopenharmony_ci  }
7662c593315Sopenharmony_ci
7672c593315Sopenharmony_ci  // We only have SCTs for leaf certificate.
7682c593315Sopenharmony_ci  if (chainidx != 0) {
7692c593315Sopenharmony_ci    return 0;
7702c593315Sopenharmony_ci  }
7712c593315Sopenharmony_ci
7722c593315Sopenharmony_ci  auto ssl_ctx = SSL_get_SSL_CTX(ssl);
7732c593315Sopenharmony_ci  auto tls_ctx_data =
7742c593315Sopenharmony_ci      static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
7752c593315Sopenharmony_ci
7762c593315Sopenharmony_ci  *out = tls_ctx_data->sct_data.data();
7772c593315Sopenharmony_ci  *outlen = tls_ctx_data->sct_data.size();
7782c593315Sopenharmony_ci
7792c593315Sopenharmony_ci  return 1;
7802c593315Sopenharmony_ci}
7812c593315Sopenharmony_ci} // namespace
7822c593315Sopenharmony_ci
7832c593315Sopenharmony_cinamespace {
7842c593315Sopenharmony_civoid sct_free_cb(SSL *ssl, unsigned int ext_type, unsigned int context,
7852c593315Sopenharmony_ci                 const unsigned char *out, void *add_arg) {
7862c593315Sopenharmony_ci  assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp);
7872c593315Sopenharmony_ci}
7882c593315Sopenharmony_ci} // namespace
7892c593315Sopenharmony_ci
7902c593315Sopenharmony_cinamespace {
7912c593315Sopenharmony_ciint sct_parse_cb(SSL *ssl, unsigned int ext_type, unsigned int context,
7922c593315Sopenharmony_ci                 const unsigned char *in, size_t inlen, X509 *x,
7932c593315Sopenharmony_ci                 size_t chainidx, int *al, void *parse_arg) {
7942c593315Sopenharmony_ci  assert(ext_type == TLSEXT_TYPE_signed_certificate_timestamp);
7952c593315Sopenharmony_ci  // client SHOULD send 0 length extension_data, but it is still
7962c593315Sopenharmony_ci  // SHOULD, and not MUST.
7972c593315Sopenharmony_ci
7982c593315Sopenharmony_ci  // For TLSv1.3 Certificate message, sct_add_cb is called even if
7992c593315Sopenharmony_ci  // client has not sent signed_certificate_timestamp extension in its
8002c593315Sopenharmony_ci  // ClientHello.  Explicitly remember that client has included it
8012c593315Sopenharmony_ci  // here.
8022c593315Sopenharmony_ci  auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
8032c593315Sopenharmony_ci  conn->tls.sct_requested = true;
8042c593315Sopenharmony_ci
8052c593315Sopenharmony_ci  return 1;
8062c593315Sopenharmony_ci}
8072c593315Sopenharmony_ci} // namespace
8082c593315Sopenharmony_ci
8092c593315Sopenharmony_ci#  if !OPENSSL_1_1_1_API
8102c593315Sopenharmony_ci
8112c593315Sopenharmony_cinamespace {
8122c593315Sopenharmony_ciint legacy_sct_add_cb(SSL *ssl, unsigned int ext_type,
8132c593315Sopenharmony_ci                      const unsigned char **out, size_t *outlen, int *al,
8142c593315Sopenharmony_ci                      void *add_arg) {
8152c593315Sopenharmony_ci  return sct_add_cb(ssl, ext_type, 0, out, outlen, nullptr, 0, al, add_arg);
8162c593315Sopenharmony_ci}
8172c593315Sopenharmony_ci} // namespace
8182c593315Sopenharmony_ci
8192c593315Sopenharmony_cinamespace {
8202c593315Sopenharmony_civoid legacy_sct_free_cb(SSL *ssl, unsigned int ext_type,
8212c593315Sopenharmony_ci                        const unsigned char *out, void *add_arg) {
8222c593315Sopenharmony_ci  sct_free_cb(ssl, ext_type, 0, out, add_arg);
8232c593315Sopenharmony_ci}
8242c593315Sopenharmony_ci} // namespace
8252c593315Sopenharmony_ci
8262c593315Sopenharmony_cinamespace {
8272c593315Sopenharmony_ciint legacy_sct_parse_cb(SSL *ssl, unsigned int ext_type,
8282c593315Sopenharmony_ci                        const unsigned char *in, size_t inlen, int *al,
8292c593315Sopenharmony_ci                        void *parse_arg) {
8302c593315Sopenharmony_ci  return sct_parse_cb(ssl, ext_type, 0, in, inlen, nullptr, 0, al, parse_arg);
8312c593315Sopenharmony_ci}
8322c593315Sopenharmony_ci} // namespace
8332c593315Sopenharmony_ci
8342c593315Sopenharmony_ci#  endif // !OPENSSL_1_1_1_API
8352c593315Sopenharmony_ci#endif   // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&
8362c593315Sopenharmony_ci         // !defined(OPENSSL_IS_BORINGSSL)
8372c593315Sopenharmony_ci
8382c593315Sopenharmony_ci#ifndef OPENSSL_NO_PSK
8392c593315Sopenharmony_cinamespace {
8402c593315Sopenharmony_ciunsigned int psk_server_cb(SSL *ssl, const char *identity, unsigned char *psk,
8412c593315Sopenharmony_ci                           unsigned int max_psk_len) {
8422c593315Sopenharmony_ci  auto config = get_config();
8432c593315Sopenharmony_ci  auto &tlsconf = config->tls;
8442c593315Sopenharmony_ci
8452c593315Sopenharmony_ci  auto it = tlsconf.psk_secrets.find(StringRef{identity});
8462c593315Sopenharmony_ci  if (it == std::end(tlsconf.psk_secrets)) {
8472c593315Sopenharmony_ci    return 0;
8482c593315Sopenharmony_ci  }
8492c593315Sopenharmony_ci
8502c593315Sopenharmony_ci  auto &secret = (*it).second;
8512c593315Sopenharmony_ci  if (secret.size() > max_psk_len) {
8522c593315Sopenharmony_ci    LOG(ERROR) << "The size of PSK secret is " << secret.size()
8532c593315Sopenharmony_ci               << ", but the acceptable maximum size is" << max_psk_len;
8542c593315Sopenharmony_ci    return 0;
8552c593315Sopenharmony_ci  }
8562c593315Sopenharmony_ci
8572c593315Sopenharmony_ci  std::copy(std::begin(secret), std::end(secret), psk);
8582c593315Sopenharmony_ci
8592c593315Sopenharmony_ci  return static_cast<unsigned int>(secret.size());
8602c593315Sopenharmony_ci}
8612c593315Sopenharmony_ci} // namespace
8622c593315Sopenharmony_ci#endif // !OPENSSL_NO_PSK
8632c593315Sopenharmony_ci
8642c593315Sopenharmony_ci#ifndef OPENSSL_NO_PSK
8652c593315Sopenharmony_cinamespace {
8662c593315Sopenharmony_ciunsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity_out,
8672c593315Sopenharmony_ci                           unsigned int max_identity_len, unsigned char *psk,
8682c593315Sopenharmony_ci                           unsigned int max_psk_len) {
8692c593315Sopenharmony_ci  auto config = get_config();
8702c593315Sopenharmony_ci  auto &tlsconf = config->tls;
8712c593315Sopenharmony_ci
8722c593315Sopenharmony_ci  auto &identity = tlsconf.client.psk.identity;
8732c593315Sopenharmony_ci  auto &secret = tlsconf.client.psk.secret;
8742c593315Sopenharmony_ci
8752c593315Sopenharmony_ci  if (identity.empty()) {
8762c593315Sopenharmony_ci    return 0;
8772c593315Sopenharmony_ci  }
8782c593315Sopenharmony_ci
8792c593315Sopenharmony_ci  if (identity.size() + 1 > max_identity_len) {
8802c593315Sopenharmony_ci    LOG(ERROR) << "The size of PSK identity is " << identity.size()
8812c593315Sopenharmony_ci               << ", but the acceptable maximum size is " << max_identity_len;
8822c593315Sopenharmony_ci    return 0;
8832c593315Sopenharmony_ci  }
8842c593315Sopenharmony_ci
8852c593315Sopenharmony_ci  if (secret.size() > max_psk_len) {
8862c593315Sopenharmony_ci    LOG(ERROR) << "The size of PSK secret is " << secret.size()
8872c593315Sopenharmony_ci               << ", but the acceptable maximum size is " << max_psk_len;
8882c593315Sopenharmony_ci    return 0;
8892c593315Sopenharmony_ci  }
8902c593315Sopenharmony_ci
8912c593315Sopenharmony_ci  *std::copy(std::begin(identity), std::end(identity), identity_out) = '\0';
8922c593315Sopenharmony_ci  std::copy(std::begin(secret), std::end(secret), psk);
8932c593315Sopenharmony_ci
8942c593315Sopenharmony_ci  return static_cast<unsigned int>(secret.size());
8952c593315Sopenharmony_ci}
8962c593315Sopenharmony_ci} // namespace
8972c593315Sopenharmony_ci#endif // !OPENSSL_NO_PSK
8982c593315Sopenharmony_ci
8992c593315Sopenharmony_cistruct TLSProtocol {
9002c593315Sopenharmony_ci  StringRef name;
9012c593315Sopenharmony_ci  long int mask;
9022c593315Sopenharmony_ci};
9032c593315Sopenharmony_ci
9042c593315Sopenharmony_ciconstexpr TLSProtocol TLS_PROTOS[] = {
9052c593315Sopenharmony_ci    TLSProtocol{StringRef::from_lit("TLSv1.2"), SSL_OP_NO_TLSv1_2},
9062c593315Sopenharmony_ci    TLSProtocol{StringRef::from_lit("TLSv1.1"), SSL_OP_NO_TLSv1_1},
9072c593315Sopenharmony_ci    TLSProtocol{StringRef::from_lit("TLSv1.0"), SSL_OP_NO_TLSv1}};
9082c593315Sopenharmony_ci
9092c593315Sopenharmony_cilong int create_tls_proto_mask(const std::vector<StringRef> &tls_proto_list) {
9102c593315Sopenharmony_ci  long int res = 0;
9112c593315Sopenharmony_ci
9122c593315Sopenharmony_ci  for (auto &supported : TLS_PROTOS) {
9132c593315Sopenharmony_ci    auto ok = false;
9142c593315Sopenharmony_ci    for (auto &name : tls_proto_list) {
9152c593315Sopenharmony_ci      if (util::strieq(supported.name, name)) {
9162c593315Sopenharmony_ci        ok = true;
9172c593315Sopenharmony_ci        break;
9182c593315Sopenharmony_ci      }
9192c593315Sopenharmony_ci    }
9202c593315Sopenharmony_ci    if (!ok) {
9212c593315Sopenharmony_ci      res |= supported.mask;
9222c593315Sopenharmony_ci    }
9232c593315Sopenharmony_ci  }
9242c593315Sopenharmony_ci  return res;
9252c593315Sopenharmony_ci}
9262c593315Sopenharmony_ci
9272c593315Sopenharmony_ciSSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
9282c593315Sopenharmony_ci                            const std::vector<uint8_t> &sct_data
9292c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
9302c593315Sopenharmony_ci                            ,
9312c593315Sopenharmony_ci                            neverbleed_t *nb
9322c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
9332c593315Sopenharmony_ci) {
9342c593315Sopenharmony_ci  auto ssl_ctx = SSL_CTX_new(TLS_server_method());
9352c593315Sopenharmony_ci  if (!ssl_ctx) {
9362c593315Sopenharmony_ci    LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr);
9372c593315Sopenharmony_ci    DIE();
9382c593315Sopenharmony_ci  }
9392c593315Sopenharmony_ci
9402c593315Sopenharmony_ci  auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
9412c593315Sopenharmony_ci                  SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
9422c593315Sopenharmony_ci                  SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
9432c593315Sopenharmony_ci                  SSL_OP_SINGLE_ECDH_USE | SSL_OP_SINGLE_DH_USE |
9442c593315Sopenharmony_ci                  SSL_OP_CIPHER_SERVER_PREFERENCE
9452c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
9462c593315Sopenharmony_ci                  // The reason for disabling built-in anti-replay in
9472c593315Sopenharmony_ci                  // OpenSSL is that it only works if client gets back
9482c593315Sopenharmony_ci                  // to the same server.  The freshness check
9492c593315Sopenharmony_ci                  // described in
9502c593315Sopenharmony_ci                  // https://tools.ietf.org/html/rfc8446#section-8.3
9512c593315Sopenharmony_ci                  // is still performed.
9522c593315Sopenharmony_ci                  | SSL_OP_NO_ANTI_REPLAY
9532c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
9542c593315Sopenharmony_ci      ;
9552c593315Sopenharmony_ci
9562c593315Sopenharmony_ci  auto config = mod_config();
9572c593315Sopenharmony_ci  auto &tlsconf = config->tls;
9582c593315Sopenharmony_ci
9592c593315Sopenharmony_ci#ifdef SSL_OP_ENABLE_KTLS
9602c593315Sopenharmony_ci  if (tlsconf.ktls) {
9612c593315Sopenharmony_ci    ssl_opts |= SSL_OP_ENABLE_KTLS;
9622c593315Sopenharmony_ci  }
9632c593315Sopenharmony_ci#endif // SSL_OP_ENABLE_KTLS
9642c593315Sopenharmony_ci
9652c593315Sopenharmony_ci  SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
9662c593315Sopenharmony_ci
9672c593315Sopenharmony_ci  if (nghttp2::tls::ssl_ctx_set_proto_versions(
9682c593315Sopenharmony_ci          ssl_ctx, tlsconf.min_proto_version, tlsconf.max_proto_version) != 0) {
9692c593315Sopenharmony_ci    LOG(FATAL) << "Could not set TLS protocol version";
9702c593315Sopenharmony_ci    DIE();
9712c593315Sopenharmony_ci  }
9722c593315Sopenharmony_ci
9732c593315Sopenharmony_ci  const unsigned char sid_ctx[] = "shrpx";
9742c593315Sopenharmony_ci  SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
9752c593315Sopenharmony_ci  SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER);
9762c593315Sopenharmony_ci
9772c593315Sopenharmony_ci  if (!tlsconf.session_cache.memcached.host.empty()) {
9782c593315Sopenharmony_ci    SSL_CTX_sess_set_new_cb(ssl_ctx, tls_session_new_cb);
9792c593315Sopenharmony_ci    SSL_CTX_sess_set_get_cb(ssl_ctx, tls_session_get_cb);
9802c593315Sopenharmony_ci  }
9812c593315Sopenharmony_ci
9822c593315Sopenharmony_ci  SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count());
9832c593315Sopenharmony_ci
9842c593315Sopenharmony_ci  if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.ciphers.c_str()) == 0) {
9852c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.ciphers
9862c593315Sopenharmony_ci               << " failed: " << ERR_error_string(ERR_get_error(), nullptr);
9872c593315Sopenharmony_ci    DIE();
9882c593315Sopenharmony_ci  }
9892c593315Sopenharmony_ci
9902c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
9912c593315Sopenharmony_ci  if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.c_str()) == 0) {
9922c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers
9932c593315Sopenharmony_ci               << " failed: " << ERR_error_string(ERR_get_error(), nullptr);
9942c593315Sopenharmony_ci    DIE();
9952c593315Sopenharmony_ci  }
9962c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
9972c593315Sopenharmony_ci
9982c593315Sopenharmony_ci#ifndef OPENSSL_NO_EC
9992c593315Sopenharmony_ci#  if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
10002c593315Sopenharmony_ci  if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.c_str()) != 1) {
10012c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set1_curves_list " << tlsconf.ecdh_curves
10022c593315Sopenharmony_ci               << " failed";
10032c593315Sopenharmony_ci    DIE();
10042c593315Sopenharmony_ci  }
10052c593315Sopenharmony_ci#    if !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API
10062c593315Sopenharmony_ci  // It looks like we need this function call for OpenSSL 1.0.2.  This
10072c593315Sopenharmony_ci  // function was deprecated in OpenSSL 1.1.0 and BoringSSL.
10082c593315Sopenharmony_ci  SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
10092c593315Sopenharmony_ci#    endif // !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API
10102c593315Sopenharmony_ci#  else    // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L
10112c593315Sopenharmony_ci  // Use P-256, which is sufficiently secure at the time of this
10122c593315Sopenharmony_ci  // writing.
10132c593315Sopenharmony_ci  auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
10142c593315Sopenharmony_ci  if (ecdh == nullptr) {
10152c593315Sopenharmony_ci    LOG(FATAL) << "EC_KEY_new_by_curv_name failed: "
10162c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
10172c593315Sopenharmony_ci    DIE();
10182c593315Sopenharmony_ci  }
10192c593315Sopenharmony_ci  SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
10202c593315Sopenharmony_ci  EC_KEY_free(ecdh);
10212c593315Sopenharmony_ci#  endif   // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L
10222c593315Sopenharmony_ci#endif     // OPENSSL_NO_EC
10232c593315Sopenharmony_ci
10242c593315Sopenharmony_ci  if (!tlsconf.dh_param_file.empty()) {
10252c593315Sopenharmony_ci    // Read DH parameters from file
10262c593315Sopenharmony_ci    auto bio = BIO_new_file(tlsconf.dh_param_file.c_str(), "rb");
10272c593315Sopenharmony_ci    if (bio == nullptr) {
10282c593315Sopenharmony_ci      LOG(FATAL) << "BIO_new_file() failed: "
10292c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
10302c593315Sopenharmony_ci      DIE();
10312c593315Sopenharmony_ci    }
10322c593315Sopenharmony_ci#if OPENSSL_3_0_0_API
10332c593315Sopenharmony_ci    EVP_PKEY *dh = nullptr;
10342c593315Sopenharmony_ci    auto dctx = OSSL_DECODER_CTX_new_for_pkey(
10352c593315Sopenharmony_ci        &dh, "PEM", nullptr, "DH", OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
10362c593315Sopenharmony_ci        nullptr, nullptr);
10372c593315Sopenharmony_ci
10382c593315Sopenharmony_ci    if (!OSSL_DECODER_from_bio(dctx, bio)) {
10392c593315Sopenharmony_ci      LOG(FATAL) << "OSSL_DECODER_from_bio() failed: "
10402c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
10412c593315Sopenharmony_ci      DIE();
10422c593315Sopenharmony_ci    }
10432c593315Sopenharmony_ci
10442c593315Sopenharmony_ci    if (SSL_CTX_set0_tmp_dh_pkey(ssl_ctx, dh) != 1) {
10452c593315Sopenharmony_ci      LOG(FATAL) << "SSL_CTX_set0_tmp_dh_pkey failed: "
10462c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
10472c593315Sopenharmony_ci      DIE();
10482c593315Sopenharmony_ci    }
10492c593315Sopenharmony_ci#else  // !OPENSSL_3_0_0_API
10502c593315Sopenharmony_ci    auto dh = PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr);
10512c593315Sopenharmony_ci    if (dh == nullptr) {
10522c593315Sopenharmony_ci      LOG(FATAL) << "PEM_read_bio_DHparams() failed: "
10532c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
10542c593315Sopenharmony_ci      DIE();
10552c593315Sopenharmony_ci    }
10562c593315Sopenharmony_ci    SSL_CTX_set_tmp_dh(ssl_ctx, dh);
10572c593315Sopenharmony_ci    DH_free(dh);
10582c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API
10592c593315Sopenharmony_ci    BIO_free(bio);
10602c593315Sopenharmony_ci  }
10612c593315Sopenharmony_ci
10622c593315Sopenharmony_ci  SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
10632c593315Sopenharmony_ci
10642c593315Sopenharmony_ci  if (SSL_CTX_set_default_verify_paths(ssl_ctx) != 1) {
10652c593315Sopenharmony_ci    LOG(WARN) << "Could not load system trusted ca certificates: "
10662c593315Sopenharmony_ci              << ERR_error_string(ERR_get_error(), nullptr);
10672c593315Sopenharmony_ci  }
10682c593315Sopenharmony_ci
10692c593315Sopenharmony_ci  if (!tlsconf.cacert.empty()) {
10702c593315Sopenharmony_ci    if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.c_str(),
10712c593315Sopenharmony_ci                                      nullptr) != 1) {
10722c593315Sopenharmony_ci      LOG(FATAL) << "Could not load trusted ca certificates from "
10732c593315Sopenharmony_ci                 << tlsconf.cacert << ": "
10742c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
10752c593315Sopenharmony_ci      DIE();
10762c593315Sopenharmony_ci    }
10772c593315Sopenharmony_ci  }
10782c593315Sopenharmony_ci
10792c593315Sopenharmony_ci  if (!tlsconf.private_key_passwd.empty()) {
10802c593315Sopenharmony_ci    SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb);
10812c593315Sopenharmony_ci    SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, config);
10822c593315Sopenharmony_ci  }
10832c593315Sopenharmony_ci
10842c593315Sopenharmony_ci#ifndef HAVE_NEVERBLEED
10852c593315Sopenharmony_ci  if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file,
10862c593315Sopenharmony_ci                                  SSL_FILETYPE_PEM) != 1) {
10872c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_use_PrivateKey_file failed: "
10882c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
10892c593315Sopenharmony_ci    DIE();
10902c593315Sopenharmony_ci  }
10912c593315Sopenharmony_ci#else  // HAVE_NEVERBLEED
10922c593315Sopenharmony_ci  std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
10932c593315Sopenharmony_ci  if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file,
10942c593315Sopenharmony_ci                                       errbuf.data()) != 1) {
10952c593315Sopenharmony_ci    LOG(FATAL) << "neverbleed_load_private_key_file failed: " << errbuf.data();
10962c593315Sopenharmony_ci    DIE();
10972c593315Sopenharmony_ci  }
10982c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
10992c593315Sopenharmony_ci
11002c593315Sopenharmony_ci  if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) {
11012c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_use_certificate_file failed: "
11022c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
11032c593315Sopenharmony_ci    DIE();
11042c593315Sopenharmony_ci  }
11052c593315Sopenharmony_ci  if (SSL_CTX_check_private_key(ssl_ctx) != 1) {
11062c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_check_private_key failed: "
11072c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
11082c593315Sopenharmony_ci    DIE();
11092c593315Sopenharmony_ci  }
11102c593315Sopenharmony_ci  if (tlsconf.client_verify.enabled) {
11112c593315Sopenharmony_ci    if (!tlsconf.client_verify.cacert.empty()) {
11122c593315Sopenharmony_ci      if (SSL_CTX_load_verify_locations(
11132c593315Sopenharmony_ci              ssl_ctx, tlsconf.client_verify.cacert.c_str(), nullptr) != 1) {
11142c593315Sopenharmony_ci
11152c593315Sopenharmony_ci        LOG(FATAL) << "Could not load trusted ca certificates from "
11162c593315Sopenharmony_ci                   << tlsconf.client_verify.cacert << ": "
11172c593315Sopenharmony_ci                   << ERR_error_string(ERR_get_error(), nullptr);
11182c593315Sopenharmony_ci        DIE();
11192c593315Sopenharmony_ci      }
11202c593315Sopenharmony_ci      // It is heard that SSL_CTX_load_verify_locations() may leave
11212c593315Sopenharmony_ci      // error even though it returns success. See
11222c593315Sopenharmony_ci      // http://forum.nginx.org/read.php?29,242540
11232c593315Sopenharmony_ci      ERR_clear_error();
11242c593315Sopenharmony_ci      auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.c_str());
11252c593315Sopenharmony_ci      if (!list) {
11262c593315Sopenharmony_ci        LOG(FATAL) << "Could not load ca certificates from "
11272c593315Sopenharmony_ci                   << tlsconf.client_verify.cacert << ": "
11282c593315Sopenharmony_ci                   << ERR_error_string(ERR_get_error(), nullptr);
11292c593315Sopenharmony_ci        DIE();
11302c593315Sopenharmony_ci      }
11312c593315Sopenharmony_ci      SSL_CTX_set_client_CA_list(ssl_ctx, list);
11322c593315Sopenharmony_ci    }
11332c593315Sopenharmony_ci    SSL_CTX_set_verify(ssl_ctx,
11342c593315Sopenharmony_ci                       SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE |
11352c593315Sopenharmony_ci                           SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
11362c593315Sopenharmony_ci                       verify_callback);
11372c593315Sopenharmony_ci  }
11382c593315Sopenharmony_ci  SSL_CTX_set_tlsext_servername_callback(ssl_ctx, servername_callback);
11392c593315Sopenharmony_ci#if OPENSSL_3_0_0_API
11402c593315Sopenharmony_ci  SSL_CTX_set_tlsext_ticket_key_evp_cb(ssl_ctx, ticket_key_cb);
11412c593315Sopenharmony_ci#else  // !OPENSSL_3_0_0_API
11422c593315Sopenharmony_ci  SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx, ticket_key_cb);
11432c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API
11442c593315Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL
11452c593315Sopenharmony_ci  SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
11462c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL
11472c593315Sopenharmony_ci  SSL_CTX_set_info_callback(ssl_ctx, info_callback);
11482c593315Sopenharmony_ci
11492c593315Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
11502c593315Sopenharmony_ci  SSL_CTX_set_early_data_enabled(ssl_ctx, 1);
11512c593315Sopenharmony_ci#endif // OPENSSL_IS_BORINGSSL
11522c593315Sopenharmony_ci
11532c593315Sopenharmony_ci  // NPN advertisement
11542c593315Sopenharmony_ci#ifndef OPENSSL_NO_NEXTPROTONEG
11552c593315Sopenharmony_ci  SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, nullptr);
11562c593315Sopenharmony_ci#endif // !OPENSSL_NO_NEXTPROTONEG
11572c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L
11582c593315Sopenharmony_ci  // ALPN selection callback
11592c593315Sopenharmony_ci  SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, nullptr);
11602c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
11612c593315Sopenharmony_ci
11622c593315Sopenharmony_ci  auto tls_ctx_data = new TLSContextData();
11632c593315Sopenharmony_ci  tls_ctx_data->cert_file = cert_file;
11642c593315Sopenharmony_ci  tls_ctx_data->sct_data = sct_data;
11652c593315Sopenharmony_ci
11662c593315Sopenharmony_ci  SSL_CTX_set_app_data(ssl_ctx, tls_ctx_data);
11672c593315Sopenharmony_ci
11682c593315Sopenharmony_ci#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&               \
11692c593315Sopenharmony_ci    !defined(OPENSSL_IS_BORINGSSL)
11702c593315Sopenharmony_ci  // SSL_extension_supported(TLSEXT_TYPE_signed_certificate_timestamp)
11712c593315Sopenharmony_ci  // returns 1, which means OpenSSL internally handles it.  But
11722c593315Sopenharmony_ci  // OpenSSL handles signed_certificate_timestamp extension specially,
11732c593315Sopenharmony_ci  // and it lets custom handler to process the extension.
11742c593315Sopenharmony_ci  if (!sct_data.empty()) {
11752c593315Sopenharmony_ci#  if OPENSSL_1_1_1_API
11762c593315Sopenharmony_ci    // It is not entirely clear to me that SSL_EXT_CLIENT_HELLO is
11772c593315Sopenharmony_ci    // required here.  sct_parse_cb is called without
11782c593315Sopenharmony_ci    // SSL_EXT_CLIENT_HELLO being set.  But the passed context value
11792c593315Sopenharmony_ci    // is SSL_EXT_CLIENT_HELLO.
11802c593315Sopenharmony_ci    if (SSL_CTX_add_custom_ext(
11812c593315Sopenharmony_ci            ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp,
11822c593315Sopenharmony_ci            SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO |
11832c593315Sopenharmony_ci                SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_IGNORE_ON_RESUMPTION,
11842c593315Sopenharmony_ci            sct_add_cb, sct_free_cb, nullptr, sct_parse_cb, nullptr) != 1) {
11852c593315Sopenharmony_ci      LOG(FATAL) << "SSL_CTX_add_custom_ext failed: "
11862c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
11872c593315Sopenharmony_ci      DIE();
11882c593315Sopenharmony_ci    }
11892c593315Sopenharmony_ci#  else  // !OPENSSL_1_1_1_API
11902c593315Sopenharmony_ci    if (SSL_CTX_add_server_custom_ext(
11912c593315Sopenharmony_ci            ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp,
11922c593315Sopenharmony_ci            legacy_sct_add_cb, legacy_sct_free_cb, nullptr, legacy_sct_parse_cb,
11932c593315Sopenharmony_ci            nullptr) != 1) {
11942c593315Sopenharmony_ci      LOG(FATAL) << "SSL_CTX_add_server_custom_ext failed: "
11952c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
11962c593315Sopenharmony_ci      DIE();
11972c593315Sopenharmony_ci    }
11982c593315Sopenharmony_ci#  endif // !OPENSSL_1_1_1_API
11992c593315Sopenharmony_ci  }
12002c593315Sopenharmony_ci#elif defined(OPENSSL_IS_BORINGSSL)
12012c593315Sopenharmony_ci  if (!tls_ctx_data->sct_data.empty() &&
12022c593315Sopenharmony_ci      SSL_CTX_set_signed_cert_timestamp_list(
12032c593315Sopenharmony_ci          ssl_ctx, tls_ctx_data->sct_data.data(),
12042c593315Sopenharmony_ci          tls_ctx_data->sct_data.size()) != 1) {
12052c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_signed_cert_timestamp_list failed: "
12062c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
12072c593315Sopenharmony_ci    DIE();
12082c593315Sopenharmony_ci  }
12092c593315Sopenharmony_ci#endif // defined(OPENSSL_IS_BORINGSSL)
12102c593315Sopenharmony_ci
12112c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
12122c593315Sopenharmony_ci  if (SSL_CTX_set_max_early_data(ssl_ctx, tlsconf.max_early_data) != 1) {
12132c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_max_early_data failed: "
12142c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
12152c593315Sopenharmony_ci    DIE();
12162c593315Sopenharmony_ci  }
12172c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
12182c593315Sopenharmony_ci
12192c593315Sopenharmony_ci#ifndef OPENSSL_NO_PSK
12202c593315Sopenharmony_ci  SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb);
12212c593315Sopenharmony_ci#endif // !LIBRESSL_NO_PSK
12222c593315Sopenharmony_ci
12232c593315Sopenharmony_ci  return ssl_ctx;
12242c593315Sopenharmony_ci}
12252c593315Sopenharmony_ci
12262c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
12272c593315Sopenharmony_ciSSL_CTX *create_quic_ssl_context(const char *private_key_file,
12282c593315Sopenharmony_ci                                 const char *cert_file,
12292c593315Sopenharmony_ci                                 const std::vector<uint8_t> &sct_data
12302c593315Sopenharmony_ci#  ifdef HAVE_NEVERBLEED
12312c593315Sopenharmony_ci                                 ,
12322c593315Sopenharmony_ci                                 neverbleed_t *nb
12332c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
12342c593315Sopenharmony_ci) {
12352c593315Sopenharmony_ci  auto ssl_ctx = SSL_CTX_new(TLS_server_method());
12362c593315Sopenharmony_ci  if (!ssl_ctx) {
12372c593315Sopenharmony_ci    LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr);
12382c593315Sopenharmony_ci    DIE();
12392c593315Sopenharmony_ci  }
12402c593315Sopenharmony_ci
12412c593315Sopenharmony_ci  constexpr auto ssl_opts =
12422c593315Sopenharmony_ci      (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
12432c593315Sopenharmony_ci      SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE |
12442c593315Sopenharmony_ci      SSL_OP_SINGLE_DH_USE |
12452c593315Sopenharmony_ci      SSL_OP_CIPHER_SERVER_PREFERENCE
12462c593315Sopenharmony_ci#  if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
12472c593315Sopenharmony_ci      // The reason for disabling built-in anti-replay in OpenSSL is
12482c593315Sopenharmony_ci      // that it only works if client gets back to the same server.
12492c593315Sopenharmony_ci      // The freshness check described in
12502c593315Sopenharmony_ci      // https://tools.ietf.org/html/rfc8446#section-8.3 is still
12512c593315Sopenharmony_ci      // performed.
12522c593315Sopenharmony_ci      | SSL_OP_NO_ANTI_REPLAY
12532c593315Sopenharmony_ci#  endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
12542c593315Sopenharmony_ci      ;
12552c593315Sopenharmony_ci
12562c593315Sopenharmony_ci  auto config = mod_config();
12572c593315Sopenharmony_ci  auto &tlsconf = config->tls;
12582c593315Sopenharmony_ci
12592c593315Sopenharmony_ci  SSL_CTX_set_options(ssl_ctx, ssl_opts);
12602c593315Sopenharmony_ci
12612c593315Sopenharmony_ci#  ifdef HAVE_LIBNGTCP2_CRYPTO_QUICTLS
12622c593315Sopenharmony_ci  if (ngtcp2_crypto_quictls_configure_server_context(ssl_ctx) != 0) {
12632c593315Sopenharmony_ci    LOG(FATAL) << "ngtcp2_crypto_quictls_configure_server_context failed";
12642c593315Sopenharmony_ci    DIE();
12652c593315Sopenharmony_ci  }
12662c593315Sopenharmony_ci#  endif // HAVE_LIBNGTCP2_CRYPTO_QUICTLS
12672c593315Sopenharmony_ci#  ifdef HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
12682c593315Sopenharmony_ci  if (ngtcp2_crypto_boringssl_configure_server_context(ssl_ctx) != 0) {
12692c593315Sopenharmony_ci    LOG(FATAL) << "ngtcp2_crypto_boringssl_configure_server_context failed";
12702c593315Sopenharmony_ci    DIE();
12712c593315Sopenharmony_ci  }
12722c593315Sopenharmony_ci#  endif // HAVE_LIBNGTCP2_CRYPTO_BORINGSSL
12732c593315Sopenharmony_ci
12742c593315Sopenharmony_ci  const unsigned char sid_ctx[] = "shrpx";
12752c593315Sopenharmony_ci  SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
12762c593315Sopenharmony_ci  SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF);
12772c593315Sopenharmony_ci
12782c593315Sopenharmony_ci  SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count());
12792c593315Sopenharmony_ci
12802c593315Sopenharmony_ci  if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.ciphers.c_str()) == 0) {
12812c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.ciphers
12822c593315Sopenharmony_ci               << " failed: " << ERR_error_string(ERR_get_error(), nullptr);
12832c593315Sopenharmony_ci    DIE();
12842c593315Sopenharmony_ci  }
12852c593315Sopenharmony_ci
12862c593315Sopenharmony_ci#  if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
12872c593315Sopenharmony_ci  if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.tls13_ciphers.c_str()) == 0) {
12882c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.tls13_ciphers
12892c593315Sopenharmony_ci               << " failed: " << ERR_error_string(ERR_get_error(), nullptr);
12902c593315Sopenharmony_ci    DIE();
12912c593315Sopenharmony_ci  }
12922c593315Sopenharmony_ci#  endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
12932c593315Sopenharmony_ci
12942c593315Sopenharmony_ci#  ifndef OPENSSL_NO_EC
12952c593315Sopenharmony_ci#    if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
12962c593315Sopenharmony_ci  if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.c_str()) != 1) {
12972c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set1_curves_list " << tlsconf.ecdh_curves
12982c593315Sopenharmony_ci               << " failed";
12992c593315Sopenharmony_ci    DIE();
13002c593315Sopenharmony_ci  }
13012c593315Sopenharmony_ci#      if !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API
13022c593315Sopenharmony_ci  // It looks like we need this function call for OpenSSL 1.0.2.  This
13032c593315Sopenharmony_ci  // function was deprecated in OpenSSL 1.1.0 and BoringSSL.
13042c593315Sopenharmony_ci  SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
13052c593315Sopenharmony_ci#      endif // !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API
13062c593315Sopenharmony_ci#    else    // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L
13072c593315Sopenharmony_ci  // Use P-256, which is sufficiently secure at the time of this
13082c593315Sopenharmony_ci  // writing.
13092c593315Sopenharmony_ci  auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
13102c593315Sopenharmony_ci  if (ecdh == nullptr) {
13112c593315Sopenharmony_ci    LOG(FATAL) << "EC_KEY_new_by_curv_name failed: "
13122c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
13132c593315Sopenharmony_ci    DIE();
13142c593315Sopenharmony_ci  }
13152c593315Sopenharmony_ci  SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
13162c593315Sopenharmony_ci  EC_KEY_free(ecdh);
13172c593315Sopenharmony_ci#    endif   // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L
13182c593315Sopenharmony_ci#  endif     // OPENSSL_NO_EC
13192c593315Sopenharmony_ci
13202c593315Sopenharmony_ci  if (!tlsconf.dh_param_file.empty()) {
13212c593315Sopenharmony_ci    // Read DH parameters from file
13222c593315Sopenharmony_ci    auto bio = BIO_new_file(tlsconf.dh_param_file.c_str(), "rb");
13232c593315Sopenharmony_ci    if (bio == nullptr) {
13242c593315Sopenharmony_ci      LOG(FATAL) << "BIO_new_file() failed: "
13252c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
13262c593315Sopenharmony_ci      DIE();
13272c593315Sopenharmony_ci    }
13282c593315Sopenharmony_ci#  if OPENSSL_3_0_0_API
13292c593315Sopenharmony_ci    EVP_PKEY *dh = nullptr;
13302c593315Sopenharmony_ci    auto dctx = OSSL_DECODER_CTX_new_for_pkey(
13312c593315Sopenharmony_ci        &dh, "PEM", nullptr, "DH", OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
13322c593315Sopenharmony_ci        nullptr, nullptr);
13332c593315Sopenharmony_ci
13342c593315Sopenharmony_ci    if (!OSSL_DECODER_from_bio(dctx, bio)) {
13352c593315Sopenharmony_ci      LOG(FATAL) << "OSSL_DECODER_from_bio() failed: "
13362c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
13372c593315Sopenharmony_ci      DIE();
13382c593315Sopenharmony_ci    }
13392c593315Sopenharmony_ci
13402c593315Sopenharmony_ci    if (SSL_CTX_set0_tmp_dh_pkey(ssl_ctx, dh) != 1) {
13412c593315Sopenharmony_ci      LOG(FATAL) << "SSL_CTX_set0_tmp_dh_pkey failed: "
13422c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
13432c593315Sopenharmony_ci      DIE();
13442c593315Sopenharmony_ci    }
13452c593315Sopenharmony_ci#  else  // !OPENSSL_3_0_0_API
13462c593315Sopenharmony_ci    auto dh = PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr);
13472c593315Sopenharmony_ci    if (dh == nullptr) {
13482c593315Sopenharmony_ci      LOG(FATAL) << "PEM_read_bio_DHparams() failed: "
13492c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
13502c593315Sopenharmony_ci      DIE();
13512c593315Sopenharmony_ci    }
13522c593315Sopenharmony_ci    SSL_CTX_set_tmp_dh(ssl_ctx, dh);
13532c593315Sopenharmony_ci    DH_free(dh);
13542c593315Sopenharmony_ci#  endif // !OPENSSL_3_0_0_API
13552c593315Sopenharmony_ci    BIO_free(bio);
13562c593315Sopenharmony_ci  }
13572c593315Sopenharmony_ci
13582c593315Sopenharmony_ci  SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
13592c593315Sopenharmony_ci
13602c593315Sopenharmony_ci  if (SSL_CTX_set_default_verify_paths(ssl_ctx) != 1) {
13612c593315Sopenharmony_ci    LOG(WARN) << "Could not load system trusted ca certificates: "
13622c593315Sopenharmony_ci              << ERR_error_string(ERR_get_error(), nullptr);
13632c593315Sopenharmony_ci  }
13642c593315Sopenharmony_ci
13652c593315Sopenharmony_ci  if (!tlsconf.cacert.empty()) {
13662c593315Sopenharmony_ci    if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.c_str(),
13672c593315Sopenharmony_ci                                      nullptr) != 1) {
13682c593315Sopenharmony_ci      LOG(FATAL) << "Could not load trusted ca certificates from "
13692c593315Sopenharmony_ci                 << tlsconf.cacert << ": "
13702c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
13712c593315Sopenharmony_ci      DIE();
13722c593315Sopenharmony_ci    }
13732c593315Sopenharmony_ci  }
13742c593315Sopenharmony_ci
13752c593315Sopenharmony_ci  if (!tlsconf.private_key_passwd.empty()) {
13762c593315Sopenharmony_ci    SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb);
13772c593315Sopenharmony_ci    SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, config);
13782c593315Sopenharmony_ci  }
13792c593315Sopenharmony_ci
13802c593315Sopenharmony_ci#  ifndef HAVE_NEVERBLEED
13812c593315Sopenharmony_ci  if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file,
13822c593315Sopenharmony_ci                                  SSL_FILETYPE_PEM) != 1) {
13832c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_use_PrivateKey_file failed: "
13842c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
13852c593315Sopenharmony_ci    DIE();
13862c593315Sopenharmony_ci  }
13872c593315Sopenharmony_ci#  else  // HAVE_NEVERBLEED
13882c593315Sopenharmony_ci  std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
13892c593315Sopenharmony_ci  if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file,
13902c593315Sopenharmony_ci                                       errbuf.data()) != 1) {
13912c593315Sopenharmony_ci    LOG(FATAL) << "neverbleed_load_private_key_file failed: " << errbuf.data();
13922c593315Sopenharmony_ci    DIE();
13932c593315Sopenharmony_ci  }
13942c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
13952c593315Sopenharmony_ci
13962c593315Sopenharmony_ci  if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) {
13972c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_use_certificate_file failed: "
13982c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
13992c593315Sopenharmony_ci    DIE();
14002c593315Sopenharmony_ci  }
14012c593315Sopenharmony_ci  if (SSL_CTX_check_private_key(ssl_ctx) != 1) {
14022c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_check_private_key failed: "
14032c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
14042c593315Sopenharmony_ci    DIE();
14052c593315Sopenharmony_ci  }
14062c593315Sopenharmony_ci  if (tlsconf.client_verify.enabled) {
14072c593315Sopenharmony_ci    if (!tlsconf.client_verify.cacert.empty()) {
14082c593315Sopenharmony_ci      if (SSL_CTX_load_verify_locations(
14092c593315Sopenharmony_ci              ssl_ctx, tlsconf.client_verify.cacert.c_str(), nullptr) != 1) {
14102c593315Sopenharmony_ci
14112c593315Sopenharmony_ci        LOG(FATAL) << "Could not load trusted ca certificates from "
14122c593315Sopenharmony_ci                   << tlsconf.client_verify.cacert << ": "
14132c593315Sopenharmony_ci                   << ERR_error_string(ERR_get_error(), nullptr);
14142c593315Sopenharmony_ci        DIE();
14152c593315Sopenharmony_ci      }
14162c593315Sopenharmony_ci      // It is heard that SSL_CTX_load_verify_locations() may leave
14172c593315Sopenharmony_ci      // error even though it returns success. See
14182c593315Sopenharmony_ci      // http://forum.nginx.org/read.php?29,242540
14192c593315Sopenharmony_ci      ERR_clear_error();
14202c593315Sopenharmony_ci      auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.c_str());
14212c593315Sopenharmony_ci      if (!list) {
14222c593315Sopenharmony_ci        LOG(FATAL) << "Could not load ca certificates from "
14232c593315Sopenharmony_ci                   << tlsconf.client_verify.cacert << ": "
14242c593315Sopenharmony_ci                   << ERR_error_string(ERR_get_error(), nullptr);
14252c593315Sopenharmony_ci        DIE();
14262c593315Sopenharmony_ci      }
14272c593315Sopenharmony_ci      SSL_CTX_set_client_CA_list(ssl_ctx, list);
14282c593315Sopenharmony_ci    }
14292c593315Sopenharmony_ci    SSL_CTX_set_verify(ssl_ctx,
14302c593315Sopenharmony_ci                       SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE |
14312c593315Sopenharmony_ci                           SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
14322c593315Sopenharmony_ci                       verify_callback);
14332c593315Sopenharmony_ci  }
14342c593315Sopenharmony_ci  SSL_CTX_set_tlsext_servername_callback(ssl_ctx, servername_callback);
14352c593315Sopenharmony_ci#  if OPENSSL_3_0_0_API
14362c593315Sopenharmony_ci  SSL_CTX_set_tlsext_ticket_key_evp_cb(ssl_ctx, ticket_key_cb);
14372c593315Sopenharmony_ci#  else  // !OPENSSL_3_0_0_API
14382c593315Sopenharmony_ci  SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx, ticket_key_cb);
14392c593315Sopenharmony_ci#  endif // !OPENSSL_3_0_0_API
14402c593315Sopenharmony_ci#  ifndef OPENSSL_IS_BORINGSSL
14412c593315Sopenharmony_ci  SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
14422c593315Sopenharmony_ci#  endif // OPENSSL_IS_BORINGSSL
14432c593315Sopenharmony_ci
14442c593315Sopenharmony_ci#  if OPENSSL_VERSION_NUMBER >= 0x10002000L
14452c593315Sopenharmony_ci  // ALPN selection callback
14462c593315Sopenharmony_ci  SSL_CTX_set_alpn_select_cb(ssl_ctx, quic_alpn_select_proto_cb, nullptr);
14472c593315Sopenharmony_ci#  endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
14482c593315Sopenharmony_ci
14492c593315Sopenharmony_ci  auto tls_ctx_data = new TLSContextData();
14502c593315Sopenharmony_ci  tls_ctx_data->cert_file = cert_file;
14512c593315Sopenharmony_ci  tls_ctx_data->sct_data = sct_data;
14522c593315Sopenharmony_ci
14532c593315Sopenharmony_ci  SSL_CTX_set_app_data(ssl_ctx, tls_ctx_data);
14542c593315Sopenharmony_ci
14552c593315Sopenharmony_ci#  if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&             \
14562c593315Sopenharmony_ci      !defined(OPENSSL_IS_BORINGSSL)
14572c593315Sopenharmony_ci  // SSL_extension_supported(TLSEXT_TYPE_signed_certificate_timestamp)
14582c593315Sopenharmony_ci  // returns 1, which means OpenSSL internally handles it.  But
14592c593315Sopenharmony_ci  // OpenSSL handles signed_certificate_timestamp extension specially,
14602c593315Sopenharmony_ci  // and it lets custom handler to process the extension.
14612c593315Sopenharmony_ci  if (!sct_data.empty()) {
14622c593315Sopenharmony_ci#    if OPENSSL_1_1_1_API
14632c593315Sopenharmony_ci    // It is not entirely clear to me that SSL_EXT_CLIENT_HELLO is
14642c593315Sopenharmony_ci    // required here.  sct_parse_cb is called without
14652c593315Sopenharmony_ci    // SSL_EXT_CLIENT_HELLO being set.  But the passed context value
14662c593315Sopenharmony_ci    // is SSL_EXT_CLIENT_HELLO.
14672c593315Sopenharmony_ci    if (SSL_CTX_add_custom_ext(
14682c593315Sopenharmony_ci            ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp,
14692c593315Sopenharmony_ci            SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO |
14702c593315Sopenharmony_ci                SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_IGNORE_ON_RESUMPTION,
14712c593315Sopenharmony_ci            sct_add_cb, sct_free_cb, nullptr, sct_parse_cb, nullptr) != 1) {
14722c593315Sopenharmony_ci      LOG(FATAL) << "SSL_CTX_add_custom_ext failed: "
14732c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
14742c593315Sopenharmony_ci      DIE();
14752c593315Sopenharmony_ci    }
14762c593315Sopenharmony_ci#    else  // !OPENSSL_1_1_1_API
14772c593315Sopenharmony_ci    if (SSL_CTX_add_server_custom_ext(
14782c593315Sopenharmony_ci            ssl_ctx, TLSEXT_TYPE_signed_certificate_timestamp,
14792c593315Sopenharmony_ci            legacy_sct_add_cb, legacy_sct_free_cb, nullptr, legacy_sct_parse_cb,
14802c593315Sopenharmony_ci            nullptr) != 1) {
14812c593315Sopenharmony_ci      LOG(FATAL) << "SSL_CTX_add_server_custom_ext failed: "
14822c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
14832c593315Sopenharmony_ci      DIE();
14842c593315Sopenharmony_ci    }
14852c593315Sopenharmony_ci#    endif // !OPENSSL_1_1_1_API
14862c593315Sopenharmony_ci  }
14872c593315Sopenharmony_ci#  elif defined(OPENSSL_IS_BORINGSSL)
14882c593315Sopenharmony_ci  if (!tls_ctx_data->sct_data.empty() &&
14892c593315Sopenharmony_ci      SSL_CTX_set_signed_cert_timestamp_list(
14902c593315Sopenharmony_ci          ssl_ctx, tls_ctx_data->sct_data.data(),
14912c593315Sopenharmony_ci          tls_ctx_data->sct_data.size()) != 1) {
14922c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_signed_cert_timestamp_list failed: "
14932c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
14942c593315Sopenharmony_ci    DIE();
14952c593315Sopenharmony_ci  }
14962c593315Sopenharmony_ci#  endif // defined(OPENSSL_IS_BORINGSSL)
14972c593315Sopenharmony_ci
14982c593315Sopenharmony_ci#  if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
14992c593315Sopenharmony_ci  auto &quicconf = config->quic;
15002c593315Sopenharmony_ci
15012c593315Sopenharmony_ci  if (quicconf.upstream.early_data &&
15022c593315Sopenharmony_ci      SSL_CTX_set_max_early_data(ssl_ctx,
15032c593315Sopenharmony_ci                                 std::numeric_limits<uint32_t>::max()) != 1) {
15042c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_max_early_data failed: "
15052c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
15062c593315Sopenharmony_ci    DIE();
15072c593315Sopenharmony_ci  }
15082c593315Sopenharmony_ci#  endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
15092c593315Sopenharmony_ci
15102c593315Sopenharmony_ci#  ifndef OPENSSL_NO_PSK
15112c593315Sopenharmony_ci  SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb);
15122c593315Sopenharmony_ci#  endif // !LIBRESSL_NO_PSK
15132c593315Sopenharmony_ci
15142c593315Sopenharmony_ci  return ssl_ctx;
15152c593315Sopenharmony_ci}
15162c593315Sopenharmony_ci#endif // ENABLE_HTTP3
15172c593315Sopenharmony_ci
15182c593315Sopenharmony_cinamespace {
15192c593315Sopenharmony_ciint select_h2_next_proto_cb(SSL *ssl, unsigned char **out,
15202c593315Sopenharmony_ci                            unsigned char *outlen, const unsigned char *in,
15212c593315Sopenharmony_ci                            unsigned int inlen, void *arg) {
15222c593315Sopenharmony_ci  if (!util::select_h2(const_cast<const unsigned char **>(out), outlen, in,
15232c593315Sopenharmony_ci                       inlen)) {
15242c593315Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
15252c593315Sopenharmony_ci  }
15262c593315Sopenharmony_ci
15272c593315Sopenharmony_ci  return SSL_TLSEXT_ERR_OK;
15282c593315Sopenharmony_ci}
15292c593315Sopenharmony_ci} // namespace
15302c593315Sopenharmony_ci
15312c593315Sopenharmony_cinamespace {
15322c593315Sopenharmony_ciint select_h1_next_proto_cb(SSL *ssl, unsigned char **out,
15332c593315Sopenharmony_ci                            unsigned char *outlen, const unsigned char *in,
15342c593315Sopenharmony_ci                            unsigned int inlen, void *arg) {
15352c593315Sopenharmony_ci  auto end = in + inlen;
15362c593315Sopenharmony_ci  for (; in < end;) {
15372c593315Sopenharmony_ci    if (util::streq(NGHTTP2_H1_1_ALPN, StringRef{in, in + (in[0] + 1)})) {
15382c593315Sopenharmony_ci      *out = const_cast<unsigned char *>(in) + 1;
15392c593315Sopenharmony_ci      *outlen = in[0];
15402c593315Sopenharmony_ci      return SSL_TLSEXT_ERR_OK;
15412c593315Sopenharmony_ci    }
15422c593315Sopenharmony_ci    in += in[0] + 1;
15432c593315Sopenharmony_ci  }
15442c593315Sopenharmony_ci
15452c593315Sopenharmony_ci  return SSL_TLSEXT_ERR_NOACK;
15462c593315Sopenharmony_ci}
15472c593315Sopenharmony_ci} // namespace
15482c593315Sopenharmony_ci
15492c593315Sopenharmony_cinamespace {
15502c593315Sopenharmony_ciint select_next_proto_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
15512c593315Sopenharmony_ci                         const unsigned char *in, unsigned int inlen,
15522c593315Sopenharmony_ci                         void *arg) {
15532c593315Sopenharmony_ci  auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
15542c593315Sopenharmony_ci  switch (conn->proto) {
15552c593315Sopenharmony_ci  case Proto::HTTP1:
15562c593315Sopenharmony_ci    return select_h1_next_proto_cb(ssl, out, outlen, in, inlen, arg);
15572c593315Sopenharmony_ci  case Proto::HTTP2:
15582c593315Sopenharmony_ci    return select_h2_next_proto_cb(ssl, out, outlen, in, inlen, arg);
15592c593315Sopenharmony_ci  default:
15602c593315Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
15612c593315Sopenharmony_ci  }
15622c593315Sopenharmony_ci}
15632c593315Sopenharmony_ci} // namespace
15642c593315Sopenharmony_ci
15652c593315Sopenharmony_ciSSL_CTX *create_ssl_client_context(
15662c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
15672c593315Sopenharmony_ci    neverbleed_t *nb,
15682c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
15692c593315Sopenharmony_ci    const StringRef &cacert, const StringRef &cert_file,
15702c593315Sopenharmony_ci    const StringRef &private_key_file,
15712c593315Sopenharmony_ci    int (*next_proto_select_cb)(SSL *s, unsigned char **out,
15722c593315Sopenharmony_ci                                unsigned char *outlen, const unsigned char *in,
15732c593315Sopenharmony_ci                                unsigned int inlen, void *arg)) {
15742c593315Sopenharmony_ci  auto ssl_ctx = SSL_CTX_new(TLS_client_method());
15752c593315Sopenharmony_ci  if (!ssl_ctx) {
15762c593315Sopenharmony_ci    LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr);
15772c593315Sopenharmony_ci    DIE();
15782c593315Sopenharmony_ci  }
15792c593315Sopenharmony_ci
15802c593315Sopenharmony_ci  auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
15812c593315Sopenharmony_ci                  SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
15822c593315Sopenharmony_ci                  SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
15832c593315Sopenharmony_ci
15842c593315Sopenharmony_ci  auto &tlsconf = get_config()->tls;
15852c593315Sopenharmony_ci
15862c593315Sopenharmony_ci#ifdef SSL_OP_ENABLE_KTLS
15872c593315Sopenharmony_ci  if (tlsconf.ktls) {
15882c593315Sopenharmony_ci    ssl_opts |= SSL_OP_ENABLE_KTLS;
15892c593315Sopenharmony_ci  }
15902c593315Sopenharmony_ci#endif // SSL_OP_ENABLE_KTLS
15912c593315Sopenharmony_ci
15922c593315Sopenharmony_ci  SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
15932c593315Sopenharmony_ci
15942c593315Sopenharmony_ci  SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_CLIENT |
15952c593315Sopenharmony_ci                                              SSL_SESS_CACHE_NO_INTERNAL_STORE);
15962c593315Sopenharmony_ci  SSL_CTX_sess_set_new_cb(ssl_ctx, tls_session_client_new_cb);
15972c593315Sopenharmony_ci
15982c593315Sopenharmony_ci  if (nghttp2::tls::ssl_ctx_set_proto_versions(
15992c593315Sopenharmony_ci          ssl_ctx, tlsconf.min_proto_version, tlsconf.max_proto_version) != 0) {
16002c593315Sopenharmony_ci    LOG(FATAL) << "Could not set TLS protocol version";
16012c593315Sopenharmony_ci    DIE();
16022c593315Sopenharmony_ci  }
16032c593315Sopenharmony_ci
16042c593315Sopenharmony_ci  if (SSL_CTX_set_cipher_list(ssl_ctx, tlsconf.client.ciphers.c_str()) == 0) {
16052c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_cipher_list " << tlsconf.client.ciphers
16062c593315Sopenharmony_ci               << " failed: " << ERR_error_string(ERR_get_error(), nullptr);
16072c593315Sopenharmony_ci    DIE();
16082c593315Sopenharmony_ci  }
16092c593315Sopenharmony_ci
16102c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
16112c593315Sopenharmony_ci  if (SSL_CTX_set_ciphersuites(ssl_ctx, tlsconf.client.tls13_ciphers.c_str()) ==
16122c593315Sopenharmony_ci      0) {
16132c593315Sopenharmony_ci    LOG(FATAL) << "SSL_CTX_set_ciphersuites " << tlsconf.client.tls13_ciphers
16142c593315Sopenharmony_ci               << " failed: " << ERR_error_string(ERR_get_error(), nullptr);
16152c593315Sopenharmony_ci    DIE();
16162c593315Sopenharmony_ci  }
16172c593315Sopenharmony_ci#endif // OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
16182c593315Sopenharmony_ci
16192c593315Sopenharmony_ci  SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
16202c593315Sopenharmony_ci
16212c593315Sopenharmony_ci  if (SSL_CTX_set_default_verify_paths(ssl_ctx) != 1) {
16222c593315Sopenharmony_ci    LOG(WARN) << "Could not load system trusted ca certificates: "
16232c593315Sopenharmony_ci              << ERR_error_string(ERR_get_error(), nullptr);
16242c593315Sopenharmony_ci  }
16252c593315Sopenharmony_ci
16262c593315Sopenharmony_ci  if (!cacert.empty()) {
16272c593315Sopenharmony_ci    if (SSL_CTX_load_verify_locations(ssl_ctx, cacert.c_str(), nullptr) != 1) {
16282c593315Sopenharmony_ci
16292c593315Sopenharmony_ci      LOG(FATAL) << "Could not load trusted ca certificates from " << cacert
16302c593315Sopenharmony_ci                 << ": " << ERR_error_string(ERR_get_error(), nullptr);
16312c593315Sopenharmony_ci      DIE();
16322c593315Sopenharmony_ci    }
16332c593315Sopenharmony_ci  }
16342c593315Sopenharmony_ci
16352c593315Sopenharmony_ci  if (!tlsconf.insecure) {
16362c593315Sopenharmony_ci    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, nullptr);
16372c593315Sopenharmony_ci  }
16382c593315Sopenharmony_ci
16392c593315Sopenharmony_ci  if (!cert_file.empty()) {
16402c593315Sopenharmony_ci    if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file.c_str()) != 1) {
16412c593315Sopenharmony_ci
16422c593315Sopenharmony_ci      LOG(FATAL) << "Could not load client certificate from " << cert_file
16432c593315Sopenharmony_ci                 << ": " << ERR_error_string(ERR_get_error(), nullptr);
16442c593315Sopenharmony_ci      DIE();
16452c593315Sopenharmony_ci    }
16462c593315Sopenharmony_ci  }
16472c593315Sopenharmony_ci
16482c593315Sopenharmony_ci  if (!private_key_file.empty()) {
16492c593315Sopenharmony_ci#ifndef HAVE_NEVERBLEED
16502c593315Sopenharmony_ci    if (SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key_file.c_str(),
16512c593315Sopenharmony_ci                                    SSL_FILETYPE_PEM) != 1) {
16522c593315Sopenharmony_ci      LOG(FATAL) << "Could not load client private key from "
16532c593315Sopenharmony_ci                 << private_key_file << ": "
16542c593315Sopenharmony_ci                 << ERR_error_string(ERR_get_error(), nullptr);
16552c593315Sopenharmony_ci      DIE();
16562c593315Sopenharmony_ci    }
16572c593315Sopenharmony_ci#else  // HAVE_NEVERBLEED
16582c593315Sopenharmony_ci    std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
16592c593315Sopenharmony_ci    if (neverbleed_load_private_key_file(nb, ssl_ctx, private_key_file.c_str(),
16602c593315Sopenharmony_ci                                         errbuf.data()) != 1) {
16612c593315Sopenharmony_ci      LOG(FATAL) << "neverbleed_load_private_key_file: could not load client "
16622c593315Sopenharmony_ci                    "private key from "
16632c593315Sopenharmony_ci                 << private_key_file << ": " << errbuf.data();
16642c593315Sopenharmony_ci      DIE();
16652c593315Sopenharmony_ci    }
16662c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
16672c593315Sopenharmony_ci  }
16682c593315Sopenharmony_ci
16692c593315Sopenharmony_ci#ifndef OPENSSL_NO_PSK
16702c593315Sopenharmony_ci  SSL_CTX_set_psk_client_callback(ssl_ctx, psk_client_cb);
16712c593315Sopenharmony_ci#endif // !OPENSSL_NO_PSK
16722c593315Sopenharmony_ci
16732c593315Sopenharmony_ci  // NPN selection callback.  This is required to set SSL_CTX because
16742c593315Sopenharmony_ci  // OpenSSL does not offer SSL_set_next_proto_select_cb.
16752c593315Sopenharmony_ci#ifndef OPENSSL_NO_NEXTPROTONEG
16762c593315Sopenharmony_ci  SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_cb, nullptr);
16772c593315Sopenharmony_ci#endif // !OPENSSL_NO_NEXTPROTONEG
16782c593315Sopenharmony_ci
16792c593315Sopenharmony_ci  return ssl_ctx;
16802c593315Sopenharmony_ci}
16812c593315Sopenharmony_ci
16822c593315Sopenharmony_ciSSL *create_ssl(SSL_CTX *ssl_ctx) {
16832c593315Sopenharmony_ci  auto ssl = SSL_new(ssl_ctx);
16842c593315Sopenharmony_ci  if (!ssl) {
16852c593315Sopenharmony_ci    LOG(ERROR) << "SSL_new() failed: "
16862c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
16872c593315Sopenharmony_ci    return nullptr;
16882c593315Sopenharmony_ci  }
16892c593315Sopenharmony_ci
16902c593315Sopenharmony_ci  return ssl;
16912c593315Sopenharmony_ci}
16922c593315Sopenharmony_ci
16932c593315Sopenharmony_ciClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr,
16942c593315Sopenharmony_ci                                 int addrlen, const UpstreamAddr *faddr) {
16952c593315Sopenharmony_ci  std::array<char, NI_MAXHOST> host;
16962c593315Sopenharmony_ci  std::array<char, NI_MAXSERV> service;
16972c593315Sopenharmony_ci  int rv;
16982c593315Sopenharmony_ci
16992c593315Sopenharmony_ci  if (addr->sa_family == AF_UNIX) {
17002c593315Sopenharmony_ci    std::copy_n("localhost", sizeof("localhost"), std::begin(host));
17012c593315Sopenharmony_ci    service[0] = '\0';
17022c593315Sopenharmony_ci  } else {
17032c593315Sopenharmony_ci    rv = getnameinfo(addr, addrlen, host.data(), host.size(), service.data(),
17042c593315Sopenharmony_ci                     service.size(), NI_NUMERICHOST | NI_NUMERICSERV);
17052c593315Sopenharmony_ci    if (rv != 0) {
17062c593315Sopenharmony_ci      LOG(ERROR) << "getnameinfo() failed: " << gai_strerror(rv);
17072c593315Sopenharmony_ci
17082c593315Sopenharmony_ci      return nullptr;
17092c593315Sopenharmony_ci    }
17102c593315Sopenharmony_ci
17112c593315Sopenharmony_ci    rv = util::make_socket_nodelay(fd);
17122c593315Sopenharmony_ci    if (rv == -1) {
17132c593315Sopenharmony_ci      LOG(WARN) << "Setting option TCP_NODELAY failed: errno=" << errno;
17142c593315Sopenharmony_ci    }
17152c593315Sopenharmony_ci  }
17162c593315Sopenharmony_ci  SSL *ssl = nullptr;
17172c593315Sopenharmony_ci  if (faddr->tls) {
17182c593315Sopenharmony_ci    auto ssl_ctx = worker->get_sv_ssl_ctx();
17192c593315Sopenharmony_ci
17202c593315Sopenharmony_ci    assert(ssl_ctx);
17212c593315Sopenharmony_ci
17222c593315Sopenharmony_ci    ssl = create_ssl(ssl_ctx);
17232c593315Sopenharmony_ci    if (!ssl) {
17242c593315Sopenharmony_ci      return nullptr;
17252c593315Sopenharmony_ci    }
17262c593315Sopenharmony_ci    // Disable TLS session ticket if we don't have working ticket
17272c593315Sopenharmony_ci    // keys.
17282c593315Sopenharmony_ci    if (!worker->get_ticket_keys()) {
17292c593315Sopenharmony_ci      SSL_set_options(ssl, SSL_OP_NO_TICKET);
17302c593315Sopenharmony_ci    }
17312c593315Sopenharmony_ci  }
17322c593315Sopenharmony_ci
17332c593315Sopenharmony_ci  return new ClientHandler(worker, fd, ssl, StringRef{host.data()},
17342c593315Sopenharmony_ci                           StringRef{service.data()}, addr->sa_family, faddr);
17352c593315Sopenharmony_ci}
17362c593315Sopenharmony_ci
17372c593315Sopenharmony_cibool tls_hostname_match(const StringRef &pattern, const StringRef &hostname) {
17382c593315Sopenharmony_ci  auto ptWildcard = std::find(std::begin(pattern), std::end(pattern), '*');
17392c593315Sopenharmony_ci  if (ptWildcard == std::end(pattern)) {
17402c593315Sopenharmony_ci    return util::strieq(pattern, hostname);
17412c593315Sopenharmony_ci  }
17422c593315Sopenharmony_ci
17432c593315Sopenharmony_ci  auto ptLeftLabelEnd = std::find(std::begin(pattern), std::end(pattern), '.');
17442c593315Sopenharmony_ci  auto wildcardEnabled = true;
17452c593315Sopenharmony_ci  // Do case-insensitive match. At least 2 dots are required to enable
17462c593315Sopenharmony_ci  // wildcard match. Also wildcard must be in the left-most label.
17472c593315Sopenharmony_ci  // Don't attempt to match a presented identifier where the wildcard
17482c593315Sopenharmony_ci  // character is embedded within an A-label.
17492c593315Sopenharmony_ci  if (ptLeftLabelEnd == std::end(pattern) ||
17502c593315Sopenharmony_ci      std::find(ptLeftLabelEnd + 1, std::end(pattern), '.') ==
17512c593315Sopenharmony_ci          std::end(pattern) ||
17522c593315Sopenharmony_ci      ptLeftLabelEnd < ptWildcard || util::istarts_with_l(pattern, "xn--")) {
17532c593315Sopenharmony_ci    wildcardEnabled = false;
17542c593315Sopenharmony_ci  }
17552c593315Sopenharmony_ci
17562c593315Sopenharmony_ci  if (!wildcardEnabled) {
17572c593315Sopenharmony_ci    return util::strieq(pattern, hostname);
17582c593315Sopenharmony_ci  }
17592c593315Sopenharmony_ci
17602c593315Sopenharmony_ci  auto hnLeftLabelEnd =
17612c593315Sopenharmony_ci      std::find(std::begin(hostname), std::end(hostname), '.');
17622c593315Sopenharmony_ci  if (hnLeftLabelEnd == std::end(hostname) ||
17632c593315Sopenharmony_ci      !util::strieq(StringRef{ptLeftLabelEnd, std::end(pattern)},
17642c593315Sopenharmony_ci                    StringRef{hnLeftLabelEnd, std::end(hostname)})) {
17652c593315Sopenharmony_ci    return false;
17662c593315Sopenharmony_ci  }
17672c593315Sopenharmony_ci  // Perform wildcard match. Here '*' must match at least one
17682c593315Sopenharmony_ci  // character.
17692c593315Sopenharmony_ci  if (hnLeftLabelEnd - std::begin(hostname) <
17702c593315Sopenharmony_ci      ptLeftLabelEnd - std::begin(pattern)) {
17712c593315Sopenharmony_ci    return false;
17722c593315Sopenharmony_ci  }
17732c593315Sopenharmony_ci  return util::istarts_with(StringRef{std::begin(hostname), hnLeftLabelEnd},
17742c593315Sopenharmony_ci                            StringRef{std::begin(pattern), ptWildcard}) &&
17752c593315Sopenharmony_ci         util::iends_with(StringRef{std::begin(hostname), hnLeftLabelEnd},
17762c593315Sopenharmony_ci                          StringRef{ptWildcard + 1, ptLeftLabelEnd});
17772c593315Sopenharmony_ci}
17782c593315Sopenharmony_ci
17792c593315Sopenharmony_cinamespace {
17802c593315Sopenharmony_ci// if return value is not empty, StringRef.c_str() must be freed using
17812c593315Sopenharmony_ci// OPENSSL_free().
17822c593315Sopenharmony_ciStringRef get_common_name(X509 *cert) {
17832c593315Sopenharmony_ci  auto subjectname = X509_get_subject_name(cert);
17842c593315Sopenharmony_ci  if (!subjectname) {
17852c593315Sopenharmony_ci    LOG(WARN) << "Could not get X509 name object from the certificate.";
17862c593315Sopenharmony_ci    return StringRef{};
17872c593315Sopenharmony_ci  }
17882c593315Sopenharmony_ci  int lastpos = -1;
17892c593315Sopenharmony_ci  for (;;) {
17902c593315Sopenharmony_ci    lastpos = X509_NAME_get_index_by_NID(subjectname, NID_commonName, lastpos);
17912c593315Sopenharmony_ci    if (lastpos == -1) {
17922c593315Sopenharmony_ci      break;
17932c593315Sopenharmony_ci    }
17942c593315Sopenharmony_ci    auto entry = X509_NAME_get_entry(subjectname, lastpos);
17952c593315Sopenharmony_ci
17962c593315Sopenharmony_ci    unsigned char *p;
17972c593315Sopenharmony_ci    auto plen = ASN1_STRING_to_UTF8(&p, X509_NAME_ENTRY_get_data(entry));
17982c593315Sopenharmony_ci    if (plen < 0) {
17992c593315Sopenharmony_ci      continue;
18002c593315Sopenharmony_ci    }
18012c593315Sopenharmony_ci    if (std::find(p, p + plen, '\0') != p + plen) {
18022c593315Sopenharmony_ci      // Embedded NULL is not permitted.
18032c593315Sopenharmony_ci      continue;
18042c593315Sopenharmony_ci    }
18052c593315Sopenharmony_ci    if (plen == 0) {
18062c593315Sopenharmony_ci      LOG(WARN) << "X509 name is empty";
18072c593315Sopenharmony_ci      OPENSSL_free(p);
18082c593315Sopenharmony_ci      continue;
18092c593315Sopenharmony_ci    }
18102c593315Sopenharmony_ci
18112c593315Sopenharmony_ci    return StringRef{p, static_cast<size_t>(plen)};
18122c593315Sopenharmony_ci  }
18132c593315Sopenharmony_ci  return StringRef{};
18142c593315Sopenharmony_ci}
18152c593315Sopenharmony_ci} // namespace
18162c593315Sopenharmony_ci
18172c593315Sopenharmony_ciint verify_numeric_hostname(X509 *cert, const StringRef &hostname,
18182c593315Sopenharmony_ci                            const Address *addr) {
18192c593315Sopenharmony_ci  const void *saddr;
18202c593315Sopenharmony_ci  size_t saddrlen;
18212c593315Sopenharmony_ci  switch (addr->su.storage.ss_family) {
18222c593315Sopenharmony_ci  case AF_INET:
18232c593315Sopenharmony_ci    saddr = &addr->su.in.sin_addr;
18242c593315Sopenharmony_ci    saddrlen = sizeof(addr->su.in.sin_addr);
18252c593315Sopenharmony_ci    break;
18262c593315Sopenharmony_ci  case AF_INET6:
18272c593315Sopenharmony_ci    saddr = &addr->su.in6.sin6_addr;
18282c593315Sopenharmony_ci    saddrlen = sizeof(addr->su.in6.sin6_addr);
18292c593315Sopenharmony_ci    break;
18302c593315Sopenharmony_ci  default:
18312c593315Sopenharmony_ci    return -1;
18322c593315Sopenharmony_ci  }
18332c593315Sopenharmony_ci
18342c593315Sopenharmony_ci  auto altnames = static_cast<GENERAL_NAMES *>(
18352c593315Sopenharmony_ci      X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
18362c593315Sopenharmony_ci  if (altnames) {
18372c593315Sopenharmony_ci    auto altnames_deleter = defer(GENERAL_NAMES_free, altnames);
18382c593315Sopenharmony_ci    size_t n = sk_GENERAL_NAME_num(altnames);
18392c593315Sopenharmony_ci    auto ip_found = false;
18402c593315Sopenharmony_ci    for (size_t i = 0; i < n; ++i) {
18412c593315Sopenharmony_ci      auto altname = sk_GENERAL_NAME_value(altnames, i);
18422c593315Sopenharmony_ci      if (altname->type != GEN_IPADD) {
18432c593315Sopenharmony_ci        continue;
18442c593315Sopenharmony_ci      }
18452c593315Sopenharmony_ci
18462c593315Sopenharmony_ci      auto ip_addr = altname->d.iPAddress->data;
18472c593315Sopenharmony_ci      if (!ip_addr) {
18482c593315Sopenharmony_ci        continue;
18492c593315Sopenharmony_ci      }
18502c593315Sopenharmony_ci      size_t ip_addrlen = altname->d.iPAddress->length;
18512c593315Sopenharmony_ci
18522c593315Sopenharmony_ci      ip_found = true;
18532c593315Sopenharmony_ci      if (saddrlen == ip_addrlen && memcmp(saddr, ip_addr, ip_addrlen) == 0) {
18542c593315Sopenharmony_ci        return 0;
18552c593315Sopenharmony_ci      }
18562c593315Sopenharmony_ci    }
18572c593315Sopenharmony_ci
18582c593315Sopenharmony_ci    if (ip_found) {
18592c593315Sopenharmony_ci      return -1;
18602c593315Sopenharmony_ci    }
18612c593315Sopenharmony_ci  }
18622c593315Sopenharmony_ci
18632c593315Sopenharmony_ci  auto cn = get_common_name(cert);
18642c593315Sopenharmony_ci  if (cn.empty()) {
18652c593315Sopenharmony_ci    return -1;
18662c593315Sopenharmony_ci  }
18672c593315Sopenharmony_ci
18682c593315Sopenharmony_ci  // cn is not NULL terminated
18692c593315Sopenharmony_ci  auto rv = util::streq(hostname, cn);
18702c593315Sopenharmony_ci  OPENSSL_free(const_cast<char *>(cn.c_str()));
18712c593315Sopenharmony_ci
18722c593315Sopenharmony_ci  if (rv) {
18732c593315Sopenharmony_ci    return 0;
18742c593315Sopenharmony_ci  }
18752c593315Sopenharmony_ci
18762c593315Sopenharmony_ci  return -1;
18772c593315Sopenharmony_ci}
18782c593315Sopenharmony_ci
18792c593315Sopenharmony_ciint verify_dns_hostname(X509 *cert, const StringRef &hostname) {
18802c593315Sopenharmony_ci  auto altnames = static_cast<GENERAL_NAMES *>(
18812c593315Sopenharmony_ci      X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
18822c593315Sopenharmony_ci  if (altnames) {
18832c593315Sopenharmony_ci    auto dns_found = false;
18842c593315Sopenharmony_ci    auto altnames_deleter = defer(GENERAL_NAMES_free, altnames);
18852c593315Sopenharmony_ci    size_t n = sk_GENERAL_NAME_num(altnames);
18862c593315Sopenharmony_ci    for (size_t i = 0; i < n; ++i) {
18872c593315Sopenharmony_ci      auto altname = sk_GENERAL_NAME_value(altnames, i);
18882c593315Sopenharmony_ci      if (altname->type != GEN_DNS) {
18892c593315Sopenharmony_ci        continue;
18902c593315Sopenharmony_ci      }
18912c593315Sopenharmony_ci
18922c593315Sopenharmony_ci      auto name = ASN1_STRING_get0_data(altname->d.ia5);
18932c593315Sopenharmony_ci      if (!name) {
18942c593315Sopenharmony_ci        continue;
18952c593315Sopenharmony_ci      }
18962c593315Sopenharmony_ci
18972c593315Sopenharmony_ci      auto len = ASN1_STRING_length(altname->d.ia5);
18982c593315Sopenharmony_ci      if (len == 0) {
18992c593315Sopenharmony_ci        continue;
19002c593315Sopenharmony_ci      }
19012c593315Sopenharmony_ci      if (std::find(name, name + len, '\0') != name + len) {
19022c593315Sopenharmony_ci        // Embedded NULL is not permitted.
19032c593315Sopenharmony_ci        continue;
19042c593315Sopenharmony_ci      }
19052c593315Sopenharmony_ci
19062c593315Sopenharmony_ci      if (name[len - 1] == '.') {
19072c593315Sopenharmony_ci        --len;
19082c593315Sopenharmony_ci        if (len == 0) {
19092c593315Sopenharmony_ci          continue;
19102c593315Sopenharmony_ci        }
19112c593315Sopenharmony_ci      }
19122c593315Sopenharmony_ci
19132c593315Sopenharmony_ci      dns_found = true;
19142c593315Sopenharmony_ci
19152c593315Sopenharmony_ci      if (tls_hostname_match(StringRef{name, static_cast<size_t>(len)},
19162c593315Sopenharmony_ci                             hostname)) {
19172c593315Sopenharmony_ci        return 0;
19182c593315Sopenharmony_ci      }
19192c593315Sopenharmony_ci    }
19202c593315Sopenharmony_ci
19212c593315Sopenharmony_ci    // RFC 6125, section 6.4.4. says that client MUST not seek a match
19222c593315Sopenharmony_ci    // for CN if a dns dNSName is found.
19232c593315Sopenharmony_ci    if (dns_found) {
19242c593315Sopenharmony_ci      return -1;
19252c593315Sopenharmony_ci    }
19262c593315Sopenharmony_ci  }
19272c593315Sopenharmony_ci
19282c593315Sopenharmony_ci  auto cn = get_common_name(cert);
19292c593315Sopenharmony_ci  if (cn.empty()) {
19302c593315Sopenharmony_ci    return -1;
19312c593315Sopenharmony_ci  }
19322c593315Sopenharmony_ci
19332c593315Sopenharmony_ci  if (cn[cn.size() - 1] == '.') {
19342c593315Sopenharmony_ci    if (cn.size() == 1) {
19352c593315Sopenharmony_ci      OPENSSL_free(const_cast<char *>(cn.c_str()));
19362c593315Sopenharmony_ci
19372c593315Sopenharmony_ci      return -1;
19382c593315Sopenharmony_ci    }
19392c593315Sopenharmony_ci    cn = StringRef{cn.c_str(), cn.size() - 1};
19402c593315Sopenharmony_ci  }
19412c593315Sopenharmony_ci
19422c593315Sopenharmony_ci  auto rv = tls_hostname_match(cn, hostname);
19432c593315Sopenharmony_ci  OPENSSL_free(const_cast<char *>(cn.c_str()));
19442c593315Sopenharmony_ci
19452c593315Sopenharmony_ci  return rv ? 0 : -1;
19462c593315Sopenharmony_ci}
19472c593315Sopenharmony_ci
19482c593315Sopenharmony_cinamespace {
19492c593315Sopenharmony_ciint verify_hostname(X509 *cert, const StringRef &hostname,
19502c593315Sopenharmony_ci                    const Address *addr) {
19512c593315Sopenharmony_ci  if (util::numeric_host(hostname.c_str())) {
19522c593315Sopenharmony_ci    return verify_numeric_hostname(cert, hostname, addr);
19532c593315Sopenharmony_ci  }
19542c593315Sopenharmony_ci
19552c593315Sopenharmony_ci  return verify_dns_hostname(cert, hostname);
19562c593315Sopenharmony_ci}
19572c593315Sopenharmony_ci} // namespace
19582c593315Sopenharmony_ci
19592c593315Sopenharmony_ciint check_cert(SSL *ssl, const Address *addr, const StringRef &host) {
19602c593315Sopenharmony_ci#if OPENSSL_3_0_0_API
19612c593315Sopenharmony_ci  auto cert = SSL_get0_peer_certificate(ssl);
19622c593315Sopenharmony_ci#else  // !OPENSSL_3_0_0_API
19632c593315Sopenharmony_ci  auto cert = SSL_get_peer_certificate(ssl);
19642c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API
19652c593315Sopenharmony_ci  if (!cert) {
19662c593315Sopenharmony_ci    // By the protocol definition, TLS server always sends certificate
19672c593315Sopenharmony_ci    // if it has.  If certificate cannot be retrieved, authentication
19682c593315Sopenharmony_ci    // without certificate is used, such as PSK.
19692c593315Sopenharmony_ci    return 0;
19702c593315Sopenharmony_ci  }
19712c593315Sopenharmony_ci#if !OPENSSL_3_0_0_API
19722c593315Sopenharmony_ci  auto cert_deleter = defer(X509_free, cert);
19732c593315Sopenharmony_ci#endif // !OPENSSL_3_0_0_API
19742c593315Sopenharmony_ci
19752c593315Sopenharmony_ci  if (verify_hostname(cert, host, addr) != 0) {
19762c593315Sopenharmony_ci    LOG(ERROR) << "Certificate verification failed: hostname does not match";
19772c593315Sopenharmony_ci    return -1;
19782c593315Sopenharmony_ci  }
19792c593315Sopenharmony_ci  return 0;
19802c593315Sopenharmony_ci}
19812c593315Sopenharmony_ci
19822c593315Sopenharmony_ciint check_cert(SSL *ssl, const DownstreamAddr *addr, const Address *raddr) {
19832c593315Sopenharmony_ci  auto hostname =
19842c593315Sopenharmony_ci      addr->sni.empty() ? StringRef{addr->host} : StringRef{addr->sni};
19852c593315Sopenharmony_ci  return check_cert(ssl, raddr, hostname);
19862c593315Sopenharmony_ci}
19872c593315Sopenharmony_ci
19882c593315Sopenharmony_ciCertLookupTree::CertLookupTree() {}
19892c593315Sopenharmony_ci
19902c593315Sopenharmony_cissize_t CertLookupTree::add_cert(const StringRef &hostname, size_t idx) {
19912c593315Sopenharmony_ci  std::array<uint8_t, NI_MAXHOST> buf;
19922c593315Sopenharmony_ci
19932c593315Sopenharmony_ci  // NI_MAXHOST includes terminal NULL byte
19942c593315Sopenharmony_ci  if (hostname.empty() || hostname.size() + 1 > buf.size()) {
19952c593315Sopenharmony_ci    return -1;
19962c593315Sopenharmony_ci  }
19972c593315Sopenharmony_ci
19982c593315Sopenharmony_ci  auto wildcard_it = std::find(std::begin(hostname), std::end(hostname), '*');
19992c593315Sopenharmony_ci  if (wildcard_it != std::end(hostname) &&
20002c593315Sopenharmony_ci      wildcard_it + 1 != std::end(hostname)) {
20012c593315Sopenharmony_ci    auto wildcard_prefix = StringRef{std::begin(hostname), wildcard_it};
20022c593315Sopenharmony_ci    auto wildcard_suffix = StringRef{wildcard_it + 1, std::end(hostname)};
20032c593315Sopenharmony_ci
20042c593315Sopenharmony_ci    auto rev_suffix = StringRef{std::begin(buf),
20052c593315Sopenharmony_ci                                std::reverse_copy(std::begin(wildcard_suffix),
20062c593315Sopenharmony_ci                                                  std::end(wildcard_suffix),
20072c593315Sopenharmony_ci                                                  std::begin(buf))};
20082c593315Sopenharmony_ci
20092c593315Sopenharmony_ci    WildcardPattern *wpat;
20102c593315Sopenharmony_ci
20112c593315Sopenharmony_ci    if (wildcard_patterns_.size() !=
20122c593315Sopenharmony_ci        rev_wildcard_router_.add_route(rev_suffix, wildcard_patterns_.size())) {
20132c593315Sopenharmony_ci      auto wcidx = rev_wildcard_router_.match(rev_suffix);
20142c593315Sopenharmony_ci
20152c593315Sopenharmony_ci      assert(wcidx != -1);
20162c593315Sopenharmony_ci
20172c593315Sopenharmony_ci      wpat = &wildcard_patterns_[wcidx];
20182c593315Sopenharmony_ci    } else {
20192c593315Sopenharmony_ci      wildcard_patterns_.emplace_back();
20202c593315Sopenharmony_ci      wpat = &wildcard_patterns_.back();
20212c593315Sopenharmony_ci    }
20222c593315Sopenharmony_ci
20232c593315Sopenharmony_ci    auto rev_prefix = StringRef{std::begin(buf),
20242c593315Sopenharmony_ci                                std::reverse_copy(std::begin(wildcard_prefix),
20252c593315Sopenharmony_ci                                                  std::end(wildcard_prefix),
20262c593315Sopenharmony_ci                                                  std::begin(buf))};
20272c593315Sopenharmony_ci
20282c593315Sopenharmony_ci    for (auto &p : wpat->rev_prefix) {
20292c593315Sopenharmony_ci      if (p.prefix == rev_prefix) {
20302c593315Sopenharmony_ci        return p.idx;
20312c593315Sopenharmony_ci      }
20322c593315Sopenharmony_ci    }
20332c593315Sopenharmony_ci
20342c593315Sopenharmony_ci    wpat->rev_prefix.emplace_back(rev_prefix, idx);
20352c593315Sopenharmony_ci
20362c593315Sopenharmony_ci    return idx;
20372c593315Sopenharmony_ci  }
20382c593315Sopenharmony_ci
20392c593315Sopenharmony_ci  return router_.add_route(hostname, idx);
20402c593315Sopenharmony_ci}
20412c593315Sopenharmony_ci
20422c593315Sopenharmony_cissize_t CertLookupTree::lookup(const StringRef &hostname) {
20432c593315Sopenharmony_ci  std::array<uint8_t, NI_MAXHOST> buf;
20442c593315Sopenharmony_ci
20452c593315Sopenharmony_ci  // NI_MAXHOST includes terminal NULL byte
20462c593315Sopenharmony_ci  if (hostname.empty() || hostname.size() + 1 > buf.size()) {
20472c593315Sopenharmony_ci    return -1;
20482c593315Sopenharmony_ci  }
20492c593315Sopenharmony_ci
20502c593315Sopenharmony_ci  // Always prefer exact match
20512c593315Sopenharmony_ci  auto idx = router_.match(hostname);
20522c593315Sopenharmony_ci  if (idx != -1) {
20532c593315Sopenharmony_ci    return idx;
20542c593315Sopenharmony_ci  }
20552c593315Sopenharmony_ci
20562c593315Sopenharmony_ci  if (wildcard_patterns_.empty()) {
20572c593315Sopenharmony_ci    return -1;
20582c593315Sopenharmony_ci  }
20592c593315Sopenharmony_ci
20602c593315Sopenharmony_ci  ssize_t best_idx = -1;
20612c593315Sopenharmony_ci  size_t best_prefixlen = 0;
20622c593315Sopenharmony_ci  const RNode *last_node = nullptr;
20632c593315Sopenharmony_ci
20642c593315Sopenharmony_ci  auto rev_host = StringRef{
20652c593315Sopenharmony_ci      std::begin(buf), std::reverse_copy(std::begin(hostname),
20662c593315Sopenharmony_ci                                         std::end(hostname), std::begin(buf))};
20672c593315Sopenharmony_ci
20682c593315Sopenharmony_ci  for (;;) {
20692c593315Sopenharmony_ci    size_t nread = 0;
20702c593315Sopenharmony_ci
20712c593315Sopenharmony_ci    auto wcidx =
20722c593315Sopenharmony_ci        rev_wildcard_router_.match_prefix(&nread, &last_node, rev_host);
20732c593315Sopenharmony_ci    if (wcidx == -1) {
20742c593315Sopenharmony_ci      return best_idx;
20752c593315Sopenharmony_ci    }
20762c593315Sopenharmony_ci
20772c593315Sopenharmony_ci    // '*' must match at least one byte
20782c593315Sopenharmony_ci    if (nread == rev_host.size()) {
20792c593315Sopenharmony_ci      return best_idx;
20802c593315Sopenharmony_ci    }
20812c593315Sopenharmony_ci
20822c593315Sopenharmony_ci    rev_host = StringRef{std::begin(rev_host) + nread, std::end(rev_host)};
20832c593315Sopenharmony_ci
20842c593315Sopenharmony_ci    auto rev_prefix = StringRef{std::begin(rev_host) + 1, std::end(rev_host)};
20852c593315Sopenharmony_ci
20862c593315Sopenharmony_ci    auto &wpat = wildcard_patterns_[wcidx];
20872c593315Sopenharmony_ci    for (auto &wprefix : wpat.rev_prefix) {
20882c593315Sopenharmony_ci      if (!util::ends_with(rev_prefix, wprefix.prefix)) {
20892c593315Sopenharmony_ci        continue;
20902c593315Sopenharmony_ci      }
20912c593315Sopenharmony_ci
20922c593315Sopenharmony_ci      auto prefixlen =
20932c593315Sopenharmony_ci          wprefix.prefix.size() +
20942c593315Sopenharmony_ci          (reinterpret_cast<const uint8_t *>(&rev_host[0]) - &buf[0]);
20952c593315Sopenharmony_ci
20962c593315Sopenharmony_ci      // Breaking a tie with longer suffix
20972c593315Sopenharmony_ci      if (prefixlen < best_prefixlen) {
20982c593315Sopenharmony_ci        continue;
20992c593315Sopenharmony_ci      }
21002c593315Sopenharmony_ci
21012c593315Sopenharmony_ci      best_idx = wprefix.idx;
21022c593315Sopenharmony_ci      best_prefixlen = prefixlen;
21032c593315Sopenharmony_ci    }
21042c593315Sopenharmony_ci  }
21052c593315Sopenharmony_ci}
21062c593315Sopenharmony_ci
21072c593315Sopenharmony_civoid CertLookupTree::dump() const {
21082c593315Sopenharmony_ci  std::cerr << "exact:" << std::endl;
21092c593315Sopenharmony_ci  router_.dump();
21102c593315Sopenharmony_ci  std::cerr << "wildcard suffix (reversed):" << std::endl;
21112c593315Sopenharmony_ci  rev_wildcard_router_.dump();
21122c593315Sopenharmony_ci}
21132c593315Sopenharmony_ci
21142c593315Sopenharmony_ciint cert_lookup_tree_add_ssl_ctx(
21152c593315Sopenharmony_ci    CertLookupTree *lt, std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
21162c593315Sopenharmony_ci    SSL_CTX *ssl_ctx) {
21172c593315Sopenharmony_ci  std::array<uint8_t, NI_MAXHOST> buf;
21182c593315Sopenharmony_ci
21192c593315Sopenharmony_ci#if LIBRESSL_2_7_API ||                                                        \
21202c593315Sopenharmony_ci    (!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L)
21212c593315Sopenharmony_ci  auto cert = SSL_CTX_get0_certificate(ssl_ctx);
21222c593315Sopenharmony_ci#else  // !LIBRESSL_2_7_API && OPENSSL_VERSION_NUMBER < 0x10002000L
21232c593315Sopenharmony_ci  auto tls_ctx_data =
21242c593315Sopenharmony_ci      static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
21252c593315Sopenharmony_ci  auto cert = load_certificate(tls_ctx_data->cert_file);
21262c593315Sopenharmony_ci  auto cert_deleter = defer(X509_free, cert);
21272c593315Sopenharmony_ci#endif // !LIBRESSL_2_7_API && OPENSSL_VERSION_NUMBER < 0x10002000L
21282c593315Sopenharmony_ci
21292c593315Sopenharmony_ci  auto altnames = static_cast<GENERAL_NAMES *>(
21302c593315Sopenharmony_ci      X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
21312c593315Sopenharmony_ci  if (altnames) {
21322c593315Sopenharmony_ci    auto altnames_deleter = defer(GENERAL_NAMES_free, altnames);
21332c593315Sopenharmony_ci    size_t n = sk_GENERAL_NAME_num(altnames);
21342c593315Sopenharmony_ci    auto dns_found = false;
21352c593315Sopenharmony_ci    for (size_t i = 0; i < n; ++i) {
21362c593315Sopenharmony_ci      auto altname = sk_GENERAL_NAME_value(altnames, i);
21372c593315Sopenharmony_ci      if (altname->type != GEN_DNS) {
21382c593315Sopenharmony_ci        continue;
21392c593315Sopenharmony_ci      }
21402c593315Sopenharmony_ci
21412c593315Sopenharmony_ci      auto name = ASN1_STRING_get0_data(altname->d.ia5);
21422c593315Sopenharmony_ci      if (!name) {
21432c593315Sopenharmony_ci        continue;
21442c593315Sopenharmony_ci      }
21452c593315Sopenharmony_ci
21462c593315Sopenharmony_ci      auto len = ASN1_STRING_length(altname->d.ia5);
21472c593315Sopenharmony_ci      if (len == 0) {
21482c593315Sopenharmony_ci        continue;
21492c593315Sopenharmony_ci      }
21502c593315Sopenharmony_ci      if (std::find(name, name + len, '\0') != name + len) {
21512c593315Sopenharmony_ci        // Embedded NULL is not permitted.
21522c593315Sopenharmony_ci        continue;
21532c593315Sopenharmony_ci      }
21542c593315Sopenharmony_ci
21552c593315Sopenharmony_ci      if (name[len - 1] == '.') {
21562c593315Sopenharmony_ci        --len;
21572c593315Sopenharmony_ci        if (len == 0) {
21582c593315Sopenharmony_ci          continue;
21592c593315Sopenharmony_ci        }
21602c593315Sopenharmony_ci      }
21612c593315Sopenharmony_ci
21622c593315Sopenharmony_ci      dns_found = true;
21632c593315Sopenharmony_ci
21642c593315Sopenharmony_ci      if (static_cast<size_t>(len) + 1 > buf.size()) {
21652c593315Sopenharmony_ci        continue;
21662c593315Sopenharmony_ci      }
21672c593315Sopenharmony_ci
21682c593315Sopenharmony_ci      auto end_buf = std::copy_n(name, len, std::begin(buf));
21692c593315Sopenharmony_ci      util::inp_strlower(std::begin(buf), end_buf);
21702c593315Sopenharmony_ci
21712c593315Sopenharmony_ci      auto idx = lt->add_cert(StringRef{std::begin(buf), end_buf},
21722c593315Sopenharmony_ci                              indexed_ssl_ctx.size());
21732c593315Sopenharmony_ci      if (idx == -1) {
21742c593315Sopenharmony_ci        continue;
21752c593315Sopenharmony_ci      }
21762c593315Sopenharmony_ci
21772c593315Sopenharmony_ci      if (static_cast<size_t>(idx) < indexed_ssl_ctx.size()) {
21782c593315Sopenharmony_ci        indexed_ssl_ctx[idx].push_back(ssl_ctx);
21792c593315Sopenharmony_ci      } else {
21802c593315Sopenharmony_ci        assert(static_cast<size_t>(idx) == indexed_ssl_ctx.size());
21812c593315Sopenharmony_ci        indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx});
21822c593315Sopenharmony_ci      }
21832c593315Sopenharmony_ci    }
21842c593315Sopenharmony_ci
21852c593315Sopenharmony_ci    // Don't bother CN if we have dNSName.
21862c593315Sopenharmony_ci    if (dns_found) {
21872c593315Sopenharmony_ci      return 0;
21882c593315Sopenharmony_ci    }
21892c593315Sopenharmony_ci  }
21902c593315Sopenharmony_ci
21912c593315Sopenharmony_ci  auto cn = get_common_name(cert);
21922c593315Sopenharmony_ci  if (cn.empty()) {
21932c593315Sopenharmony_ci    return 0;
21942c593315Sopenharmony_ci  }
21952c593315Sopenharmony_ci
21962c593315Sopenharmony_ci  if (cn[cn.size() - 1] == '.') {
21972c593315Sopenharmony_ci    if (cn.size() == 1) {
21982c593315Sopenharmony_ci      OPENSSL_free(const_cast<char *>(cn.c_str()));
21992c593315Sopenharmony_ci
22002c593315Sopenharmony_ci      return 0;
22012c593315Sopenharmony_ci    }
22022c593315Sopenharmony_ci
22032c593315Sopenharmony_ci    cn = StringRef{cn.c_str(), cn.size() - 1};
22042c593315Sopenharmony_ci  }
22052c593315Sopenharmony_ci
22062c593315Sopenharmony_ci  auto end_buf = std::copy(std::begin(cn), std::end(cn), std::begin(buf));
22072c593315Sopenharmony_ci
22082c593315Sopenharmony_ci  OPENSSL_free(const_cast<char *>(cn.c_str()));
22092c593315Sopenharmony_ci
22102c593315Sopenharmony_ci  util::inp_strlower(std::begin(buf), end_buf);
22112c593315Sopenharmony_ci
22122c593315Sopenharmony_ci  auto idx =
22132c593315Sopenharmony_ci      lt->add_cert(StringRef{std::begin(buf), end_buf}, indexed_ssl_ctx.size());
22142c593315Sopenharmony_ci  if (idx == -1) {
22152c593315Sopenharmony_ci    return 0;
22162c593315Sopenharmony_ci  }
22172c593315Sopenharmony_ci
22182c593315Sopenharmony_ci  if (static_cast<size_t>(idx) < indexed_ssl_ctx.size()) {
22192c593315Sopenharmony_ci    indexed_ssl_ctx[idx].push_back(ssl_ctx);
22202c593315Sopenharmony_ci  } else {
22212c593315Sopenharmony_ci    assert(static_cast<size_t>(idx) == indexed_ssl_ctx.size());
22222c593315Sopenharmony_ci    indexed_ssl_ctx.emplace_back(std::vector<SSL_CTX *>{ssl_ctx});
22232c593315Sopenharmony_ci  }
22242c593315Sopenharmony_ci
22252c593315Sopenharmony_ci  return 0;
22262c593315Sopenharmony_ci}
22272c593315Sopenharmony_ci
22282c593315Sopenharmony_cibool in_proto_list(const std::vector<StringRef> &protos,
22292c593315Sopenharmony_ci                   const StringRef &needle) {
22302c593315Sopenharmony_ci  for (auto &proto : protos) {
22312c593315Sopenharmony_ci    if (util::streq(proto, needle)) {
22322c593315Sopenharmony_ci      return true;
22332c593315Sopenharmony_ci    }
22342c593315Sopenharmony_ci  }
22352c593315Sopenharmony_ci  return false;
22362c593315Sopenharmony_ci}
22372c593315Sopenharmony_ci
22382c593315Sopenharmony_cibool upstream_tls_enabled(const ConnectionConfig &connconf) {
22392c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
22402c593315Sopenharmony_ci  if (connconf.quic_listener.addrs.size()) {
22412c593315Sopenharmony_ci    return true;
22422c593315Sopenharmony_ci  }
22432c593315Sopenharmony_ci#endif // ENABLE_HTTP3
22442c593315Sopenharmony_ci
22452c593315Sopenharmony_ci  const auto &faddrs = connconf.listener.addrs;
22462c593315Sopenharmony_ci  return std::any_of(std::begin(faddrs), std::end(faddrs),
22472c593315Sopenharmony_ci                     [](const UpstreamAddr &faddr) { return faddr.tls; });
22482c593315Sopenharmony_ci}
22492c593315Sopenharmony_ci
22502c593315Sopenharmony_ciX509 *load_certificate(const char *filename) {
22512c593315Sopenharmony_ci  auto bio = BIO_new(BIO_s_file());
22522c593315Sopenharmony_ci  if (!bio) {
22532c593315Sopenharmony_ci    fprintf(stderr, "BIO_new() failed\n");
22542c593315Sopenharmony_ci    return nullptr;
22552c593315Sopenharmony_ci  }
22562c593315Sopenharmony_ci  auto bio_deleter = defer(BIO_vfree, bio);
22572c593315Sopenharmony_ci  if (!BIO_read_filename(bio, filename)) {
22582c593315Sopenharmony_ci    fprintf(stderr, "Could not read certificate file '%s'\n", filename);
22592c593315Sopenharmony_ci    return nullptr;
22602c593315Sopenharmony_ci  }
22612c593315Sopenharmony_ci  auto cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
22622c593315Sopenharmony_ci  if (!cert) {
22632c593315Sopenharmony_ci    fprintf(stderr, "Could not read X509 structure from file '%s'\n", filename);
22642c593315Sopenharmony_ci    return nullptr;
22652c593315Sopenharmony_ci  }
22662c593315Sopenharmony_ci
22672c593315Sopenharmony_ci  return cert;
22682c593315Sopenharmony_ci}
22692c593315Sopenharmony_ci
22702c593315Sopenharmony_ciSSL_CTX *
22712c593315Sopenharmony_cisetup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
22722c593315Sopenharmony_ci                         std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
22732c593315Sopenharmony_ci                         CertLookupTree *cert_tree
22742c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
22752c593315Sopenharmony_ci                         ,
22762c593315Sopenharmony_ci                         neverbleed_t *nb
22772c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
22782c593315Sopenharmony_ci) {
22792c593315Sopenharmony_ci  auto config = get_config();
22802c593315Sopenharmony_ci
22812c593315Sopenharmony_ci  if (!upstream_tls_enabled(config->conn)) {
22822c593315Sopenharmony_ci    return nullptr;
22832c593315Sopenharmony_ci  }
22842c593315Sopenharmony_ci
22852c593315Sopenharmony_ci  auto &tlsconf = config->tls;
22862c593315Sopenharmony_ci
22872c593315Sopenharmony_ci  auto ssl_ctx = create_ssl_context(tlsconf.private_key_file.c_str(),
22882c593315Sopenharmony_ci                                    tlsconf.cert_file.c_str(), tlsconf.sct_data
22892c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
22902c593315Sopenharmony_ci                                    ,
22912c593315Sopenharmony_ci                                    nb
22922c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
22932c593315Sopenharmony_ci  );
22942c593315Sopenharmony_ci
22952c593315Sopenharmony_ci  all_ssl_ctx.push_back(ssl_ctx);
22962c593315Sopenharmony_ci
22972c593315Sopenharmony_ci  assert(cert_tree);
22982c593315Sopenharmony_ci
22992c593315Sopenharmony_ci  if (cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) == -1) {
23002c593315Sopenharmony_ci    LOG(FATAL) << "Failed to add default certificate.";
23012c593315Sopenharmony_ci    DIE();
23022c593315Sopenharmony_ci  }
23032c593315Sopenharmony_ci
23042c593315Sopenharmony_ci  for (auto &c : tlsconf.subcerts) {
23052c593315Sopenharmony_ci    auto ssl_ctx = create_ssl_context(c.private_key_file.c_str(),
23062c593315Sopenharmony_ci                                      c.cert_file.c_str(), c.sct_data
23072c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
23082c593315Sopenharmony_ci                                      ,
23092c593315Sopenharmony_ci                                      nb
23102c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
23112c593315Sopenharmony_ci    );
23122c593315Sopenharmony_ci    all_ssl_ctx.push_back(ssl_ctx);
23132c593315Sopenharmony_ci
23142c593315Sopenharmony_ci    if (cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) ==
23152c593315Sopenharmony_ci        -1) {
23162c593315Sopenharmony_ci      LOG(FATAL) << "Failed to add sub certificate.";
23172c593315Sopenharmony_ci      DIE();
23182c593315Sopenharmony_ci    }
23192c593315Sopenharmony_ci  }
23202c593315Sopenharmony_ci
23212c593315Sopenharmony_ci  return ssl_ctx;
23222c593315Sopenharmony_ci}
23232c593315Sopenharmony_ci
23242c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
23252c593315Sopenharmony_ciSSL_CTX *setup_quic_server_ssl_context(
23262c593315Sopenharmony_ci    std::vector<SSL_CTX *> &all_ssl_ctx,
23272c593315Sopenharmony_ci    std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx,
23282c593315Sopenharmony_ci    CertLookupTree *cert_tree
23292c593315Sopenharmony_ci#  ifdef HAVE_NEVERBLEED
23302c593315Sopenharmony_ci    ,
23312c593315Sopenharmony_ci    neverbleed_t *nb
23322c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
23332c593315Sopenharmony_ci) {
23342c593315Sopenharmony_ci  auto config = get_config();
23352c593315Sopenharmony_ci
23362c593315Sopenharmony_ci  if (!upstream_tls_enabled(config->conn)) {
23372c593315Sopenharmony_ci    return nullptr;
23382c593315Sopenharmony_ci  }
23392c593315Sopenharmony_ci
23402c593315Sopenharmony_ci  auto &tlsconf = config->tls;
23412c593315Sopenharmony_ci
23422c593315Sopenharmony_ci  auto ssl_ctx =
23432c593315Sopenharmony_ci      create_quic_ssl_context(tlsconf.private_key_file.c_str(),
23442c593315Sopenharmony_ci                              tlsconf.cert_file.c_str(), tlsconf.sct_data
23452c593315Sopenharmony_ci#  ifdef HAVE_NEVERBLEED
23462c593315Sopenharmony_ci                              ,
23472c593315Sopenharmony_ci                              nb
23482c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
23492c593315Sopenharmony_ci      );
23502c593315Sopenharmony_ci
23512c593315Sopenharmony_ci  all_ssl_ctx.push_back(ssl_ctx);
23522c593315Sopenharmony_ci
23532c593315Sopenharmony_ci  assert(cert_tree);
23542c593315Sopenharmony_ci
23552c593315Sopenharmony_ci  if (cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) == -1) {
23562c593315Sopenharmony_ci    LOG(FATAL) << "Failed to add default certificate.";
23572c593315Sopenharmony_ci    DIE();
23582c593315Sopenharmony_ci  }
23592c593315Sopenharmony_ci
23602c593315Sopenharmony_ci  for (auto &c : tlsconf.subcerts) {
23612c593315Sopenharmony_ci    auto ssl_ctx = create_quic_ssl_context(c.private_key_file.c_str(),
23622c593315Sopenharmony_ci                                           c.cert_file.c_str(), c.sct_data
23632c593315Sopenharmony_ci#  ifdef HAVE_NEVERBLEED
23642c593315Sopenharmony_ci                                           ,
23652c593315Sopenharmony_ci                                           nb
23662c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
23672c593315Sopenharmony_ci    );
23682c593315Sopenharmony_ci    all_ssl_ctx.push_back(ssl_ctx);
23692c593315Sopenharmony_ci
23702c593315Sopenharmony_ci    if (cert_lookup_tree_add_ssl_ctx(cert_tree, indexed_ssl_ctx, ssl_ctx) ==
23712c593315Sopenharmony_ci        -1) {
23722c593315Sopenharmony_ci      LOG(FATAL) << "Failed to add sub certificate.";
23732c593315Sopenharmony_ci      DIE();
23742c593315Sopenharmony_ci    }
23752c593315Sopenharmony_ci  }
23762c593315Sopenharmony_ci
23772c593315Sopenharmony_ci  return ssl_ctx;
23782c593315Sopenharmony_ci}
23792c593315Sopenharmony_ci#endif // ENABLE_HTTP3
23802c593315Sopenharmony_ci
23812c593315Sopenharmony_ciSSL_CTX *setup_downstream_client_ssl_context(
23822c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
23832c593315Sopenharmony_ci    neverbleed_t *nb
23842c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
23852c593315Sopenharmony_ci) {
23862c593315Sopenharmony_ci  auto &tlsconf = get_config()->tls;
23872c593315Sopenharmony_ci
23882c593315Sopenharmony_ci  return create_ssl_client_context(
23892c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
23902c593315Sopenharmony_ci      nb,
23912c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
23922c593315Sopenharmony_ci      tlsconf.cacert, tlsconf.client.cert_file, tlsconf.client.private_key_file,
23932c593315Sopenharmony_ci      select_next_proto_cb);
23942c593315Sopenharmony_ci}
23952c593315Sopenharmony_ci
23962c593315Sopenharmony_civoid setup_downstream_http2_alpn(SSL *ssl) {
23972c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L
23982c593315Sopenharmony_ci  // ALPN advertisement
23992c593315Sopenharmony_ci  auto alpn = util::get_default_alpn();
24002c593315Sopenharmony_ci  SSL_set_alpn_protos(ssl, alpn.data(), alpn.size());
24012c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
24022c593315Sopenharmony_ci}
24032c593315Sopenharmony_ci
24042c593315Sopenharmony_civoid setup_downstream_http1_alpn(SSL *ssl) {
24052c593315Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L
24062c593315Sopenharmony_ci  // ALPN advertisement
24072c593315Sopenharmony_ci  SSL_set_alpn_protos(ssl, NGHTTP2_H1_1_ALPN.byte(), NGHTTP2_H1_1_ALPN.size());
24082c593315Sopenharmony_ci#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
24092c593315Sopenharmony_ci}
24102c593315Sopenharmony_ci
24112c593315Sopenharmony_cistd::unique_ptr<CertLookupTree> create_cert_lookup_tree() {
24122c593315Sopenharmony_ci  auto config = get_config();
24132c593315Sopenharmony_ci  if (!upstream_tls_enabled(config->conn)) {
24142c593315Sopenharmony_ci    return nullptr;
24152c593315Sopenharmony_ci  }
24162c593315Sopenharmony_ci  return std::make_unique<CertLookupTree>();
24172c593315Sopenharmony_ci}
24182c593315Sopenharmony_ci
24192c593315Sopenharmony_cinamespace {
24202c593315Sopenharmony_cistd::vector<uint8_t> serialize_ssl_session(SSL_SESSION *session) {
24212c593315Sopenharmony_ci  auto len = i2d_SSL_SESSION(session, nullptr);
24222c593315Sopenharmony_ci  auto buf = std::vector<uint8_t>(len);
24232c593315Sopenharmony_ci  auto p = buf.data();
24242c593315Sopenharmony_ci  i2d_SSL_SESSION(session, &p);
24252c593315Sopenharmony_ci
24262c593315Sopenharmony_ci  return buf;
24272c593315Sopenharmony_ci}
24282c593315Sopenharmony_ci} // namespace
24292c593315Sopenharmony_ci
24302c593315Sopenharmony_civoid try_cache_tls_session(TLSSessionCache *cache, SSL_SESSION *session,
24312c593315Sopenharmony_ci                           const std::chrono::steady_clock::time_point &t) {
24322c593315Sopenharmony_ci  if (cache->last_updated + 1min > t) {
24332c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
24342c593315Sopenharmony_ci      LOG(INFO) << "Client session cache entry is still fresh.";
24352c593315Sopenharmony_ci    }
24362c593315Sopenharmony_ci    return;
24372c593315Sopenharmony_ci  }
24382c593315Sopenharmony_ci
24392c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
24402c593315Sopenharmony_ci    LOG(INFO) << "Update client cache entry "
24412c593315Sopenharmony_ci              << "timestamp = " << t.time_since_epoch().count();
24422c593315Sopenharmony_ci  }
24432c593315Sopenharmony_ci
24442c593315Sopenharmony_ci  cache->session_data = serialize_ssl_session(session);
24452c593315Sopenharmony_ci  cache->last_updated = t;
24462c593315Sopenharmony_ci}
24472c593315Sopenharmony_ci
24482c593315Sopenharmony_ciSSL_SESSION *reuse_tls_session(const TLSSessionCache &cache) {
24492c593315Sopenharmony_ci  if (cache.session_data.empty()) {
24502c593315Sopenharmony_ci    return nullptr;
24512c593315Sopenharmony_ci  }
24522c593315Sopenharmony_ci
24532c593315Sopenharmony_ci  auto p = cache.session_data.data();
24542c593315Sopenharmony_ci  return d2i_SSL_SESSION(nullptr, &p, cache.session_data.size());
24552c593315Sopenharmony_ci}
24562c593315Sopenharmony_ci
24572c593315Sopenharmony_ciint proto_version_from_string(const StringRef &v) {
24582c593315Sopenharmony_ci#ifdef TLS1_3_VERSION
24592c593315Sopenharmony_ci  if (util::strieq_l("TLSv1.3", v)) {
24602c593315Sopenharmony_ci    return TLS1_3_VERSION;
24612c593315Sopenharmony_ci  }
24622c593315Sopenharmony_ci#endif // TLS1_3_VERSION
24632c593315Sopenharmony_ci  if (util::strieq_l("TLSv1.2", v)) {
24642c593315Sopenharmony_ci    return TLS1_2_VERSION;
24652c593315Sopenharmony_ci  }
24662c593315Sopenharmony_ci  if (util::strieq_l("TLSv1.1", v)) {
24672c593315Sopenharmony_ci    return TLS1_1_VERSION;
24682c593315Sopenharmony_ci  }
24692c593315Sopenharmony_ci  if (util::strieq_l("TLSv1.0", v)) {
24702c593315Sopenharmony_ci    return TLS1_VERSION;
24712c593315Sopenharmony_ci  }
24722c593315Sopenharmony_ci  return -1;
24732c593315Sopenharmony_ci}
24742c593315Sopenharmony_ci
24752c593315Sopenharmony_ciint verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp,
24762c593315Sopenharmony_ci                         size_t ocsp_resplen) {
24772c593315Sopenharmony_ci
24782c593315Sopenharmony_ci#if !defined(OPENSSL_NO_OCSP) && !LIBRESSL_IN_USE &&                           \
24792c593315Sopenharmony_ci    OPENSSL_VERSION_NUMBER >= 0x10002000L
24802c593315Sopenharmony_ci  int rv;
24812c593315Sopenharmony_ci
24822c593315Sopenharmony_ci  STACK_OF(X509) * chain_certs;
24832c593315Sopenharmony_ci  SSL_CTX_get0_chain_certs(ssl_ctx, &chain_certs);
24842c593315Sopenharmony_ci
24852c593315Sopenharmony_ci  auto resp = d2i_OCSP_RESPONSE(nullptr, &ocsp_resp, ocsp_resplen);
24862c593315Sopenharmony_ci  if (resp == nullptr) {
24872c593315Sopenharmony_ci    LOG(ERROR) << "d2i_OCSP_RESPONSE failed";
24882c593315Sopenharmony_ci    return -1;
24892c593315Sopenharmony_ci  }
24902c593315Sopenharmony_ci  auto resp_deleter = defer(OCSP_RESPONSE_free, resp);
24912c593315Sopenharmony_ci
24922c593315Sopenharmony_ci  if (OCSP_response_status(resp) != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
24932c593315Sopenharmony_ci    LOG(ERROR) << "OCSP response status is not successful";
24942c593315Sopenharmony_ci    return -1;
24952c593315Sopenharmony_ci  }
24962c593315Sopenharmony_ci
24972c593315Sopenharmony_ci  ERR_clear_error();
24982c593315Sopenharmony_ci
24992c593315Sopenharmony_ci  auto bs = OCSP_response_get1_basic(resp);
25002c593315Sopenharmony_ci  if (bs == nullptr) {
25012c593315Sopenharmony_ci    LOG(ERROR) << "OCSP_response_get1_basic failed: "
25022c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
25032c593315Sopenharmony_ci    return -1;
25042c593315Sopenharmony_ci  }
25052c593315Sopenharmony_ci  auto bs_deleter = defer(OCSP_BASICRESP_free, bs);
25062c593315Sopenharmony_ci
25072c593315Sopenharmony_ci  auto store = SSL_CTX_get_cert_store(ssl_ctx);
25082c593315Sopenharmony_ci
25092c593315Sopenharmony_ci  ERR_clear_error();
25102c593315Sopenharmony_ci
25112c593315Sopenharmony_ci  rv = OCSP_basic_verify(bs, chain_certs, store, 0);
25122c593315Sopenharmony_ci
25132c593315Sopenharmony_ci  if (rv != 1) {
25142c593315Sopenharmony_ci    LOG(ERROR) << "OCSP_basic_verify failed: "
25152c593315Sopenharmony_ci               << ERR_error_string(ERR_get_error(), nullptr);
25162c593315Sopenharmony_ci    return -1;
25172c593315Sopenharmony_ci  }
25182c593315Sopenharmony_ci
25192c593315Sopenharmony_ci  auto sresp = OCSP_resp_get0(bs, 0);
25202c593315Sopenharmony_ci  if (sresp == nullptr) {
25212c593315Sopenharmony_ci    LOG(ERROR) << "OCSP response verification failed: no single response";
25222c593315Sopenharmony_ci    return -1;
25232c593315Sopenharmony_ci  }
25242c593315Sopenharmony_ci
25252c593315Sopenharmony_ci#  if OPENSSL_1_1_API
25262c593315Sopenharmony_ci  auto certid = OCSP_SINGLERESP_get0_id(sresp);
25272c593315Sopenharmony_ci#  else  // !OPENSSL_1_1_API
25282c593315Sopenharmony_ci  auto certid = sresp->certId;
25292c593315Sopenharmony_ci#  endif // !OPENSSL_1_1_API
25302c593315Sopenharmony_ci  assert(certid != nullptr);
25312c593315Sopenharmony_ci
25322c593315Sopenharmony_ci  ASN1_INTEGER *serial;
25332c593315Sopenharmony_ci  rv = OCSP_id_get0_info(nullptr, nullptr, nullptr, &serial,
25342c593315Sopenharmony_ci                         const_cast<OCSP_CERTID *>(certid));
25352c593315Sopenharmony_ci  if (rv != 1) {
25362c593315Sopenharmony_ci    LOG(ERROR) << "OCSP_id_get0_info failed";
25372c593315Sopenharmony_ci    return -1;
25382c593315Sopenharmony_ci  }
25392c593315Sopenharmony_ci
25402c593315Sopenharmony_ci  if (serial == nullptr) {
25412c593315Sopenharmony_ci    LOG(ERROR) << "OCSP response does not contain serial number";
25422c593315Sopenharmony_ci    return -1;
25432c593315Sopenharmony_ci  }
25442c593315Sopenharmony_ci
25452c593315Sopenharmony_ci  auto cert = SSL_CTX_get0_certificate(ssl_ctx);
25462c593315Sopenharmony_ci  auto cert_serial = X509_get_serialNumber(cert);
25472c593315Sopenharmony_ci
25482c593315Sopenharmony_ci  if (ASN1_INTEGER_cmp(cert_serial, serial)) {
25492c593315Sopenharmony_ci    LOG(ERROR) << "OCSP verification serial numbers do not match";
25502c593315Sopenharmony_ci    return -1;
25512c593315Sopenharmony_ci  }
25522c593315Sopenharmony_ci
25532c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
25542c593315Sopenharmony_ci    LOG(INFO) << "OCSP verification succeeded";
25552c593315Sopenharmony_ci  }
25562c593315Sopenharmony_ci#endif // !defined(OPENSSL_NO_OCSP) && !LIBRESSL_IN_USE
25572c593315Sopenharmony_ci       // && OPENSSL_VERSION_NUMBER >= 0x10002000L
25582c593315Sopenharmony_ci
25592c593315Sopenharmony_ci  return 0;
25602c593315Sopenharmony_ci}
25612c593315Sopenharmony_ci
25622c593315Sopenharmony_cissize_t get_x509_fingerprint(uint8_t *dst, size_t dstlen, const X509 *x,
25632c593315Sopenharmony_ci                             const EVP_MD *md) {
25642c593315Sopenharmony_ci  unsigned int len = dstlen;
25652c593315Sopenharmony_ci  if (X509_digest(x, md, dst, &len) != 1) {
25662c593315Sopenharmony_ci    return -1;
25672c593315Sopenharmony_ci  }
25682c593315Sopenharmony_ci  return len;
25692c593315Sopenharmony_ci}
25702c593315Sopenharmony_ci
25712c593315Sopenharmony_cinamespace {
25722c593315Sopenharmony_ciStringRef get_x509_name(BlockAllocator &balloc, X509_NAME *nm) {
25732c593315Sopenharmony_ci  auto b = BIO_new(BIO_s_mem());
25742c593315Sopenharmony_ci  if (!b) {
25752c593315Sopenharmony_ci    return StringRef{};
25762c593315Sopenharmony_ci  }
25772c593315Sopenharmony_ci
25782c593315Sopenharmony_ci  auto b_deleter = defer(BIO_free, b);
25792c593315Sopenharmony_ci
25802c593315Sopenharmony_ci  // Not documented, but it seems that X509_NAME_print_ex returns the
25812c593315Sopenharmony_ci  // number of bytes written into b.
25822c593315Sopenharmony_ci  auto slen = X509_NAME_print_ex(b, nm, 0, XN_FLAG_RFC2253);
25832c593315Sopenharmony_ci  if (slen <= 0) {
25842c593315Sopenharmony_ci    return StringRef{};
25852c593315Sopenharmony_ci  }
25862c593315Sopenharmony_ci
25872c593315Sopenharmony_ci  auto iov = make_byte_ref(balloc, slen + 1);
25882c593315Sopenharmony_ci  BIO_read(b, iov.base, slen);
25892c593315Sopenharmony_ci  iov.base[slen] = '\0';
25902c593315Sopenharmony_ci  return StringRef{iov.base, static_cast<size_t>(slen)};
25912c593315Sopenharmony_ci}
25922c593315Sopenharmony_ci} // namespace
25932c593315Sopenharmony_ci
25942c593315Sopenharmony_ciStringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x) {
25952c593315Sopenharmony_ci  return get_x509_name(balloc, X509_get_subject_name(x));
25962c593315Sopenharmony_ci}
25972c593315Sopenharmony_ci
25982c593315Sopenharmony_ciStringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x) {
25992c593315Sopenharmony_ci  return get_x509_name(balloc, X509_get_issuer_name(x));
26002c593315Sopenharmony_ci}
26012c593315Sopenharmony_ci
26022c593315Sopenharmony_ciStringRef get_x509_serial(BlockAllocator &balloc, X509 *x) {
26032c593315Sopenharmony_ci  auto sn = X509_get_serialNumber(x);
26042c593315Sopenharmony_ci  auto bn = BN_new();
26052c593315Sopenharmony_ci  auto bn_d = defer(BN_free, bn);
26062c593315Sopenharmony_ci  if (!ASN1_INTEGER_to_BN(sn, bn) || BN_num_bytes(bn) > 20) {
26072c593315Sopenharmony_ci    return StringRef{};
26082c593315Sopenharmony_ci  }
26092c593315Sopenharmony_ci
26102c593315Sopenharmony_ci  std::array<uint8_t, 20> b;
26112c593315Sopenharmony_ci  auto n = BN_bn2bin(bn, b.data());
26122c593315Sopenharmony_ci  assert(n <= 20);
26132c593315Sopenharmony_ci
26142c593315Sopenharmony_ci  return util::format_hex(balloc, StringRef{b.data(), static_cast<size_t>(n)});
26152c593315Sopenharmony_ci}
26162c593315Sopenharmony_ci
26172c593315Sopenharmony_cinamespace {
26182c593315Sopenharmony_ci// Performs conversion from |at| to time_t.  The result is stored in
26192c593315Sopenharmony_ci// |t|.  This function returns 0 if it succeeds, or -1.
26202c593315Sopenharmony_ciint time_t_from_asn1_time(time_t &t, const ASN1_TIME *at) {
26212c593315Sopenharmony_ci  int rv;
26222c593315Sopenharmony_ci
26232c593315Sopenharmony_ci#if OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
26242c593315Sopenharmony_ci  struct tm tm;
26252c593315Sopenharmony_ci  rv = ASN1_TIME_to_tm(at, &tm);
26262c593315Sopenharmony_ci  if (rv != 1) {
26272c593315Sopenharmony_ci    return -1;
26282c593315Sopenharmony_ci  }
26292c593315Sopenharmony_ci
26302c593315Sopenharmony_ci  t = nghttp2_timegm(&tm);
26312c593315Sopenharmony_ci#else // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL))
26322c593315Sopenharmony_ci  auto b = BIO_new(BIO_s_mem());
26332c593315Sopenharmony_ci  if (!b) {
26342c593315Sopenharmony_ci    return -1;
26352c593315Sopenharmony_ci  }
26362c593315Sopenharmony_ci
26372c593315Sopenharmony_ci  auto bio_deleter = defer(BIO_free, b);
26382c593315Sopenharmony_ci
26392c593315Sopenharmony_ci  rv = ASN1_TIME_print(b, at);
26402c593315Sopenharmony_ci  if (rv != 1) {
26412c593315Sopenharmony_ci    return -1;
26422c593315Sopenharmony_ci  }
26432c593315Sopenharmony_ci
26442c593315Sopenharmony_ci#  ifdef OPENSSL_IS_BORINGSSL
26452c593315Sopenharmony_ci  char *s;
26462c593315Sopenharmony_ci#  else
26472c593315Sopenharmony_ci  unsigned char *s;
26482c593315Sopenharmony_ci#  endif
26492c593315Sopenharmony_ci  auto slen = BIO_get_mem_data(b, &s);
26502c593315Sopenharmony_ci  auto tt = util::parse_openssl_asn1_time_print(
26512c593315Sopenharmony_ci      StringRef{s, static_cast<size_t>(slen)});
26522c593315Sopenharmony_ci  if (tt == 0) {
26532c593315Sopenharmony_ci    return -1;
26542c593315Sopenharmony_ci  }
26552c593315Sopenharmony_ci
26562c593315Sopenharmony_ci  t = tt;
26572c593315Sopenharmony_ci#endif // !(OPENSSL_1_1_1_API && !defined(OPENSSL_IS_BORINGSSL))
26582c593315Sopenharmony_ci
26592c593315Sopenharmony_ci  return 0;
26602c593315Sopenharmony_ci}
26612c593315Sopenharmony_ci} // namespace
26622c593315Sopenharmony_ci
26632c593315Sopenharmony_ciint get_x509_not_before(time_t &t, X509 *x) {
26642c593315Sopenharmony_ci#if OPENSSL_1_1_API
26652c593315Sopenharmony_ci  auto at = X509_get0_notBefore(x);
26662c593315Sopenharmony_ci#else  // !OPENSSL_1_1_API
26672c593315Sopenharmony_ci  auto at = X509_get_notBefore(x);
26682c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API
26692c593315Sopenharmony_ci  if (!at) {
26702c593315Sopenharmony_ci    return -1;
26712c593315Sopenharmony_ci  }
26722c593315Sopenharmony_ci
26732c593315Sopenharmony_ci  return time_t_from_asn1_time(t, at);
26742c593315Sopenharmony_ci}
26752c593315Sopenharmony_ci
26762c593315Sopenharmony_ciint get_x509_not_after(time_t &t, X509 *x) {
26772c593315Sopenharmony_ci#if OPENSSL_1_1_API
26782c593315Sopenharmony_ci  auto at = X509_get0_notAfter(x);
26792c593315Sopenharmony_ci#else  // !OPENSSL_1_1_API
26802c593315Sopenharmony_ci  auto at = X509_get_notAfter(x);
26812c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API
26822c593315Sopenharmony_ci  if (!at) {
26832c593315Sopenharmony_ci    return -1;
26842c593315Sopenharmony_ci  }
26852c593315Sopenharmony_ci
26862c593315Sopenharmony_ci  return time_t_from_asn1_time(t, at);
26872c593315Sopenharmony_ci}
26882c593315Sopenharmony_ci
26892c593315Sopenharmony_ci} // namespace tls
26902c593315Sopenharmony_ci
26912c593315Sopenharmony_ci} // namespace shrpx
2692