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#ifndef SHRPX_TLS_H 262c593315Sopenharmony_ci#define SHRPX_TLS_H 272c593315Sopenharmony_ci 282c593315Sopenharmony_ci#include "shrpx.h" 292c593315Sopenharmony_ci 302c593315Sopenharmony_ci#include <vector> 312c593315Sopenharmony_ci#include <mutex> 322c593315Sopenharmony_ci 332c593315Sopenharmony_ci#include <openssl/ssl.h> 342c593315Sopenharmony_ci#include <openssl/err.h> 352c593315Sopenharmony_ci 362c593315Sopenharmony_ci#include <ev.h> 372c593315Sopenharmony_ci 382c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 392c593315Sopenharmony_ci# include <neverbleed.h> 402c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 412c593315Sopenharmony_ci 422c593315Sopenharmony_ci#include "network.h" 432c593315Sopenharmony_ci#include "shrpx_config.h" 442c593315Sopenharmony_ci#include "shrpx_router.h" 452c593315Sopenharmony_ci 462c593315Sopenharmony_cinamespace shrpx { 472c593315Sopenharmony_ci 482c593315Sopenharmony_ciclass ClientHandler; 492c593315Sopenharmony_ciclass Worker; 502c593315Sopenharmony_ciclass DownstreamConnectionPool; 512c593315Sopenharmony_cistruct DownstreamAddr; 522c593315Sopenharmony_cistruct UpstreamAddr; 532c593315Sopenharmony_ci 542c593315Sopenharmony_cinamespace tls { 552c593315Sopenharmony_ci 562c593315Sopenharmony_cistruct TLSSessionCache { 572c593315Sopenharmony_ci // ASN1 representation of SSL_SESSION object. See 582c593315Sopenharmony_ci // i2d_SSL_SESSION(3SSL). 592c593315Sopenharmony_ci std::vector<uint8_t> session_data; 602c593315Sopenharmony_ci // The last time stamp when this cache entry is created or updated. 612c593315Sopenharmony_ci std::chrono::steady_clock::time_point last_updated; 622c593315Sopenharmony_ci}; 632c593315Sopenharmony_ci 642c593315Sopenharmony_ci// This struct stores the additional information per SSL_CTX. This is 652c593315Sopenharmony_ci// attached to SSL_CTX using SSL_CTX_set_app_data(). 662c593315Sopenharmony_cistruct TLSContextData { 672c593315Sopenharmony_ci // SCT data formatted so that this can be directly sent as 682c593315Sopenharmony_ci // extension_data of signed_certificate_timestamp. 692c593315Sopenharmony_ci std::vector<uint8_t> sct_data; 702c593315Sopenharmony_ci#ifndef HAVE_ATOMIC_STD_SHARED_PTR 712c593315Sopenharmony_ci // Protects ocsp_data; 722c593315Sopenharmony_ci std::mutex mu; 732c593315Sopenharmony_ci#endif // !HAVE_ATOMIC_STD_SHARED_PTR 742c593315Sopenharmony_ci // OCSP response 752c593315Sopenharmony_ci std::shared_ptr<std::vector<uint8_t>> ocsp_data; 762c593315Sopenharmony_ci 772c593315Sopenharmony_ci // Path to certificate file 782c593315Sopenharmony_ci const char *cert_file; 792c593315Sopenharmony_ci}; 802c593315Sopenharmony_ci 812c593315Sopenharmony_ci// Create server side SSL_CTX 822c593315Sopenharmony_ciSSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file, 832c593315Sopenharmony_ci const std::vector<uint8_t> &sct_data 842c593315Sopenharmony_ci 852c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 862c593315Sopenharmony_ci , 872c593315Sopenharmony_ci neverbleed_t *nb 882c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 892c593315Sopenharmony_ci); 902c593315Sopenharmony_ci 912c593315Sopenharmony_ci// Create client side SSL_CTX. This does not configure ALPN settings. 922c593315Sopenharmony_ci// |next_proto_select_cb| is for NPN. 932c593315Sopenharmony_ciSSL_CTX *create_ssl_client_context( 942c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 952c593315Sopenharmony_ci neverbleed_t *nb, 962c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 972c593315Sopenharmony_ci const StringRef &cacert, const StringRef &cert_file, 982c593315Sopenharmony_ci const StringRef &private_key_file, 992c593315Sopenharmony_ci int (*next_proto_select_cb)(SSL *s, unsigned char **out, 1002c593315Sopenharmony_ci unsigned char *outlen, const unsigned char *in, 1012c593315Sopenharmony_ci unsigned int inlen, void *arg)); 1022c593315Sopenharmony_ci 1032c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 1042c593315Sopenharmony_ciSSL_CTX *create_quic_ssl_client_context( 1052c593315Sopenharmony_ci# ifdef HAVE_NEVERBLEED 1062c593315Sopenharmony_ci neverbleed_t *nb, 1072c593315Sopenharmony_ci# endif // HAVE_NEVERBLEED 1082c593315Sopenharmony_ci const StringRef &cacert, const StringRef &cert_file, 1092c593315Sopenharmony_ci const StringRef &private_key_file, 1102c593315Sopenharmony_ci int (*next_proto_select_cb)(SSL *s, unsigned char **out, 1112c593315Sopenharmony_ci unsigned char *outlen, const unsigned char *in, 1122c593315Sopenharmony_ci unsigned int inlen, void *arg)); 1132c593315Sopenharmony_ci#endif // ENABLE_HTTP3 1142c593315Sopenharmony_ci 1152c593315Sopenharmony_ciClientHandler *accept_connection(Worker *worker, int fd, sockaddr *addr, 1162c593315Sopenharmony_ci int addrlen, const UpstreamAddr *faddr); 1172c593315Sopenharmony_ci 1182c593315Sopenharmony_ci// Check peer's certificate against given |address| and |host|. 1192c593315Sopenharmony_ciint check_cert(SSL *ssl, const Address *addr, const StringRef &host); 1202c593315Sopenharmony_ci// Check peer's certificate against given host name described in 1212c593315Sopenharmony_ci// |addr| and numeric address in |raddr|. Note that |raddr| might not 1222c593315Sopenharmony_ci// point to &addr->addr. 1232c593315Sopenharmony_ciint check_cert(SSL *ssl, const DownstreamAddr *addr, const Address *raddr); 1242c593315Sopenharmony_ci 1252c593315Sopenharmony_ci// Verify |cert| using numeric IP address. |hostname| and |addr| 1262c593315Sopenharmony_ci// should contain the same numeric IP address. This function returns 1272c593315Sopenharmony_ci// 0 if it succeeds, or -1. 1282c593315Sopenharmony_ciint verify_numeric_hostname(X509 *cert, const StringRef &hostname, 1292c593315Sopenharmony_ci const Address *addr); 1302c593315Sopenharmony_ci 1312c593315Sopenharmony_ci// Verify |cert| using DNS name hostname. This function returns 0 if 1322c593315Sopenharmony_ci// it succeeds, or -1. 1332c593315Sopenharmony_ciint verify_dns_hostname(X509 *cert, const StringRef &hostname); 1342c593315Sopenharmony_ci 1352c593315Sopenharmony_cistruct WildcardRevPrefix { 1362c593315Sopenharmony_ci WildcardRevPrefix(const StringRef &prefix, size_t idx) 1372c593315Sopenharmony_ci : prefix(std::begin(prefix), std::end(prefix)), idx(idx) {} 1382c593315Sopenharmony_ci 1392c593315Sopenharmony_ci // "Prefix" of wildcard pattern. It is reversed from original form. 1402c593315Sopenharmony_ci // For example, if the original wildcard is "test*.nghttp2.org", 1412c593315Sopenharmony_ci // prefix would be "tset". 1422c593315Sopenharmony_ci ImmutableString prefix; 1432c593315Sopenharmony_ci // The index of SSL_CTX. See ConnectionHandler::get_ssl_ctx(). 1442c593315Sopenharmony_ci size_t idx; 1452c593315Sopenharmony_ci}; 1462c593315Sopenharmony_ci 1472c593315Sopenharmony_cistruct WildcardPattern { 1482c593315Sopenharmony_ci // Wildcard host sharing only suffix is probably rare, so we just do 1492c593315Sopenharmony_ci // linear search. 1502c593315Sopenharmony_ci std::vector<WildcardRevPrefix> rev_prefix; 1512c593315Sopenharmony_ci}; 1522c593315Sopenharmony_ci 1532c593315Sopenharmony_ciclass CertLookupTree { 1542c593315Sopenharmony_cipublic: 1552c593315Sopenharmony_ci CertLookupTree(); 1562c593315Sopenharmony_ci 1572c593315Sopenharmony_ci // Adds hostname pattern |hostname| to the lookup tree, associating 1582c593315Sopenharmony_ci // value |index|. When the queried host matches this pattern, 1592c593315Sopenharmony_ci // |index| is returned. We support wildcard pattern. The left most 1602c593315Sopenharmony_ci // '*' is considered as wildcard character, and it must match at 1612c593315Sopenharmony_ci // least one character. If the same pattern has been already added, 1622c593315Sopenharmony_ci // this function does not alter the tree, and returns the existing 1632c593315Sopenharmony_ci // matching index. 1642c593315Sopenharmony_ci // 1652c593315Sopenharmony_ci // The caller should lower-case |hostname| since this function does 1662c593315Sopenharmony_ci // do that, and lookup function performs case-sensitive match. 1672c593315Sopenharmony_ci // 1682c593315Sopenharmony_ci // TODO Treat wildcard pattern described as RFC 6125. 1692c593315Sopenharmony_ci // 1702c593315Sopenharmony_ci // This function returns the index. It returns -1 if it fails 1712c593315Sopenharmony_ci // (e.g., hostname is too long). If the returned index equals to 1722c593315Sopenharmony_ci // |index|, then hostname is added to the tree with the value 1732c593315Sopenharmony_ci // |index|. If it is not -1, and does not equal to |index|, same 1742c593315Sopenharmony_ci // hostname has already been added to the tree. 1752c593315Sopenharmony_ci ssize_t add_cert(const StringRef &hostname, size_t index); 1762c593315Sopenharmony_ci 1772c593315Sopenharmony_ci // Looks up index using the given |hostname|. The exact match takes 1782c593315Sopenharmony_ci // precedence over wildcard match. For wildcard match, longest 1792c593315Sopenharmony_ci // match (sum of matched suffix and prefix length in bytes) is 1802c593315Sopenharmony_ci // preferred, breaking a tie with longer suffix. 1812c593315Sopenharmony_ci // 1822c593315Sopenharmony_ci // The caller should lower-case |hostname| since this function 1832c593315Sopenharmony_ci // performs case-sensitive match. 1842c593315Sopenharmony_ci ssize_t lookup(const StringRef &hostname); 1852c593315Sopenharmony_ci 1862c593315Sopenharmony_ci // Dumps the contents of this lookup tree to stderr. 1872c593315Sopenharmony_ci void dump() const; 1882c593315Sopenharmony_ci 1892c593315Sopenharmony_ciprivate: 1902c593315Sopenharmony_ci // Exact match 1912c593315Sopenharmony_ci Router router_; 1922c593315Sopenharmony_ci // Wildcard reversed suffix match. The returned index is into 1932c593315Sopenharmony_ci // wildcard_patterns_. 1942c593315Sopenharmony_ci Router rev_wildcard_router_; 1952c593315Sopenharmony_ci // Stores wildcard suffix patterns. 1962c593315Sopenharmony_ci std::vector<WildcardPattern> wildcard_patterns_; 1972c593315Sopenharmony_ci}; 1982c593315Sopenharmony_ci 1992c593315Sopenharmony_ci// Adds hostnames in certificate in |ssl_ctx| to lookup tree |lt|. 2002c593315Sopenharmony_ci// The subjectAltNames and commonName are considered as eligible 2012c593315Sopenharmony_ci// hostname. If there is at least one dNSName in subjectAltNames, 2022c593315Sopenharmony_ci// commonName is not considered. |ssl_ctx| is also added to 2032c593315Sopenharmony_ci// |indexed_ssl_ctx|. This function returns 0 if it succeeds, or -1. 2042c593315Sopenharmony_ciint cert_lookup_tree_add_ssl_ctx( 2052c593315Sopenharmony_ci CertLookupTree *lt, std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx, 2062c593315Sopenharmony_ci SSL_CTX *ssl_ctx); 2072c593315Sopenharmony_ci 2082c593315Sopenharmony_ci// Returns true if |proto| is included in the 2092c593315Sopenharmony_ci// protocol list |protos|. 2102c593315Sopenharmony_cibool in_proto_list(const std::vector<StringRef> &protos, 2112c593315Sopenharmony_ci const StringRef &proto); 2122c593315Sopenharmony_ci 2132c593315Sopenharmony_ci// Returns true if security requirement for HTTP/2 is fulfilled. 2142c593315Sopenharmony_cibool check_http2_requirement(SSL *ssl); 2152c593315Sopenharmony_ci 2162c593315Sopenharmony_ci// Returns SSL/TLS option mask to disable SSL/TLS protocol version not 2172c593315Sopenharmony_ci// included in |tls_proto_list|. The returned mask can be directly 2182c593315Sopenharmony_ci// passed to SSL_CTX_set_options(). 2192c593315Sopenharmony_cilong int create_tls_proto_mask(const std::vector<StringRef> &tls_proto_list); 2202c593315Sopenharmony_ci 2212c593315Sopenharmony_ciint set_alpn_prefs(std::vector<unsigned char> &out, 2222c593315Sopenharmony_ci const std::vector<StringRef> &protos); 2232c593315Sopenharmony_ci 2242c593315Sopenharmony_ci// Setups server side SSL_CTX. This function inspects get_config() 2252c593315Sopenharmony_ci// and if upstream_no_tls is true, returns nullptr. Otherwise 2262c593315Sopenharmony_ci// construct default SSL_CTX. If subcerts are available 2272c593315Sopenharmony_ci// (get_config()->subcerts), caller should provide CertLookupTree 2282c593315Sopenharmony_ci// object as |cert_tree| parameter, otherwise SNI does not work. All 2292c593315Sopenharmony_ci// the created SSL_CTX is stored into |all_ssl_ctx|. They are also 2302c593315Sopenharmony_ci// added to |indexed_ssl_ctx|. |cert_tree| uses its index to 2312c593315Sopenharmony_ci// associate hostname to the SSL_CTX. 2322c593315Sopenharmony_ciSSL_CTX * 2332c593315Sopenharmony_cisetup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx, 2342c593315Sopenharmony_ci std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx, 2352c593315Sopenharmony_ci CertLookupTree *cert_tree 2362c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 2372c593315Sopenharmony_ci , 2382c593315Sopenharmony_ci neverbleed_t *nb 2392c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 2402c593315Sopenharmony_ci); 2412c593315Sopenharmony_ci 2422c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 2432c593315Sopenharmony_ciSSL_CTX *setup_quic_server_ssl_context( 2442c593315Sopenharmony_ci std::vector<SSL_CTX *> &all_ssl_ctx, 2452c593315Sopenharmony_ci std::vector<std::vector<SSL_CTX *>> &indexed_ssl_ctx, 2462c593315Sopenharmony_ci CertLookupTree *cert_tree 2472c593315Sopenharmony_ci# ifdef HAVE_NEVERBLEED 2482c593315Sopenharmony_ci , 2492c593315Sopenharmony_ci neverbleed_t *nb 2502c593315Sopenharmony_ci# endif // HAVE_NEVERBLEED 2512c593315Sopenharmony_ci); 2522c593315Sopenharmony_ci#endif // ENABLE_HTTP3 2532c593315Sopenharmony_ci 2542c593315Sopenharmony_ci// Setups client side SSL_CTX. 2552c593315Sopenharmony_ciSSL_CTX *setup_downstream_client_ssl_context( 2562c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED 2572c593315Sopenharmony_ci neverbleed_t *nb 2582c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED 2592c593315Sopenharmony_ci); 2602c593315Sopenharmony_ci 2612c593315Sopenharmony_ci// Sets ALPN settings in |SSL| suitable for HTTP/2 use. 2622c593315Sopenharmony_civoid setup_downstream_http2_alpn(SSL *ssl); 2632c593315Sopenharmony_ci// Sets ALPN settings in |SSL| suitable for HTTP/1.1 use. 2642c593315Sopenharmony_civoid setup_downstream_http1_alpn(SSL *ssl); 2652c593315Sopenharmony_ci 2662c593315Sopenharmony_ci// Creates CertLookupTree. If frontend is configured not to use TLS, 2672c593315Sopenharmony_ci// this function returns nullptr. 2682c593315Sopenharmony_cistd::unique_ptr<CertLookupTree> create_cert_lookup_tree(); 2692c593315Sopenharmony_ci 2702c593315Sopenharmony_ciSSL *create_ssl(SSL_CTX *ssl_ctx); 2712c593315Sopenharmony_ci 2722c593315Sopenharmony_ci// Returns true if SSL/TLS is enabled on upstream 2732c593315Sopenharmony_cibool upstream_tls_enabled(const ConnectionConfig &connconf); 2742c593315Sopenharmony_ci 2752c593315Sopenharmony_ci// Performs TLS hostname match. |pattern| can contain wildcard 2762c593315Sopenharmony_ci// character '*', which matches prefix of target hostname. There are 2772c593315Sopenharmony_ci// several restrictions to make wildcard work. The matching algorithm 2782c593315Sopenharmony_ci// is based on RFC 6125. 2792c593315Sopenharmony_cibool tls_hostname_match(const StringRef &pattern, const StringRef &hostname); 2802c593315Sopenharmony_ci 2812c593315Sopenharmony_ci// Caches |session|. |session| is serialized into ASN1 2822c593315Sopenharmony_ci// representation, and stored. |t| is used as a time stamp. 2832c593315Sopenharmony_ci// Depending on the existing cache's time stamp, |session| might not 2842c593315Sopenharmony_ci// be cached. 2852c593315Sopenharmony_civoid try_cache_tls_session(TLSSessionCache *cache, SSL_SESSION *session, 2862c593315Sopenharmony_ci const std::chrono::steady_clock::time_point &t); 2872c593315Sopenharmony_ci 2882c593315Sopenharmony_ci// Returns cached session associated |addr|. If no cache entry is 2892c593315Sopenharmony_ci// found associated to |addr|, nullptr will be returned. 2902c593315Sopenharmony_ciSSL_SESSION *reuse_tls_session(const TLSSessionCache &addr); 2912c593315Sopenharmony_ci 2922c593315Sopenharmony_ci// Loads certificate form file |filename|. The caller should delete 2932c593315Sopenharmony_ci// the returned object using X509_free(). 2942c593315Sopenharmony_ciX509 *load_certificate(const char *filename); 2952c593315Sopenharmony_ci 2962c593315Sopenharmony_ci// Returns TLS version from |v|. The returned value is defined in 2972c593315Sopenharmony_ci// OpenSSL header file. This function returns -1 if |v| is not valid 2982c593315Sopenharmony_ci// TLS version string. 2992c593315Sopenharmony_ciint proto_version_from_string(const StringRef &v); 3002c593315Sopenharmony_ci 3012c593315Sopenharmony_ci// Verifies OCSP response |ocsp_resp| of length |ocsp_resplen|. This 3022c593315Sopenharmony_ci// function returns 0 if it succeeds, or -1. 3032c593315Sopenharmony_ciint verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp, 3042c593315Sopenharmony_ci size_t ocsp_resplen); 3052c593315Sopenharmony_ci 3062c593315Sopenharmony_ci// Stores fingerprint of |x| in |dst| of length |dstlen|. |md| 3072c593315Sopenharmony_ci// specifies hash function to use, and |dstlen| must be large enough 3082c593315Sopenharmony_ci// to include hash value (e.g., 32 bytes for SHA-256). This function 3092c593315Sopenharmony_ci// returns the number of bytes written in |dst|, or -1. 3102c593315Sopenharmony_cissize_t get_x509_fingerprint(uint8_t *dst, size_t dstlen, const X509 *x, 3112c593315Sopenharmony_ci const EVP_MD *md); 3122c593315Sopenharmony_ci 3132c593315Sopenharmony_ci// Returns subject name of |x|. If this function fails to get subject 3142c593315Sopenharmony_ci// name, it returns an empty string. 3152c593315Sopenharmony_ciStringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x); 3162c593315Sopenharmony_ci 3172c593315Sopenharmony_ci// Returns issuer name of |x|. If this function fails to get issuer 3182c593315Sopenharmony_ci// name, it returns an empty string. 3192c593315Sopenharmony_ciStringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x); 3202c593315Sopenharmony_ci 3212c593315Sopenharmony_ci// Returns serial number of |x|. If this function fails to get serial 3222c593315Sopenharmony_ci// number, it returns an empty string. number 3232c593315Sopenharmony_ciStringRef get_x509_serial(BlockAllocator &balloc, X509 *x); 3242c593315Sopenharmony_ci 3252c593315Sopenharmony_ci// Fills NotBefore of |x| in |t|. This function returns 0 if it 3262c593315Sopenharmony_ci// succeeds, or -1. 3272c593315Sopenharmony_ciint get_x509_not_before(time_t &t, X509 *x); 3282c593315Sopenharmony_ci 3292c593315Sopenharmony_ci// Fills NotAfter of |x| in |t|. This function returns 0 if it 3302c593315Sopenharmony_ci// succeeds, or -1. 3312c593315Sopenharmony_ciint get_x509_not_after(time_t &t, X509 *x); 3322c593315Sopenharmony_ci 3332c593315Sopenharmony_ci} // namespace tls 3342c593315Sopenharmony_ci 3352c593315Sopenharmony_ci} // namespace shrpx 3362c593315Sopenharmony_ci 3372c593315Sopenharmony_ci#endif // SHRPX_TLS_H 338