11cb0ef41Sopenharmony_ci#pragma once 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 41cb0ef41Sopenharmony_ci#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ci#include <base_object.h> 71cb0ef41Sopenharmony_ci#include <crypto/crypto_context.h> 81cb0ef41Sopenharmony_ci#include <crypto/crypto_keys.h> 91cb0ef41Sopenharmony_ci#include <memory_tracker.h> 101cb0ef41Sopenharmony_ci#include <ngtcp2/ngtcp2_crypto.h> 111cb0ef41Sopenharmony_ci#include "bindingdata.h" 121cb0ef41Sopenharmony_ci#include "data.h" 131cb0ef41Sopenharmony_ci#include "sessionticket.h" 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cinamespace node { 161cb0ef41Sopenharmony_cinamespace quic { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciclass Session; 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ci// Every QUIC Session has exactly one TLSContext that maintains the state 211cb0ef41Sopenharmony_ci// of the TLS handshake and negotiated cipher keys after the handshake has 221cb0ef41Sopenharmony_ci// been completed. It is separated out from the main Session class only as a 231cb0ef41Sopenharmony_ci// convenience to help make the code more maintainable and understandable. 241cb0ef41Sopenharmony_ciclass TLSContext final : public MemoryRetainer { 251cb0ef41Sopenharmony_ci public: 261cb0ef41Sopenharmony_ci static constexpr auto DEFAULT_CIPHERS = "TLS_AES_128_GCM_SHA256:" 271cb0ef41Sopenharmony_ci "TLS_AES_256_GCM_SHA384:" 281cb0ef41Sopenharmony_ci "TLS_CHACHA20_POLY1305_" 291cb0ef41Sopenharmony_ci "SHA256:TLS_AES_128_CCM_SHA256"; 301cb0ef41Sopenharmony_ci static constexpr auto DEFAULT_GROUPS = "X25519:P-256:P-384:P-521"; 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci static inline const TLSContext& From(const SSL* ssl); 331cb0ef41Sopenharmony_ci static inline TLSContext& From(SSL* ssl); 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci struct Options final : public MemoryRetainer { 361cb0ef41Sopenharmony_ci // The protocol identifier to be used by this Session. 371cb0ef41Sopenharmony_ci std::string alpn = NGHTTP3_ALPN_H3; 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci // The SNI hostname to be used. This is used only by client Sessions to 401cb0ef41Sopenharmony_ci // identify the SNI host in the TLS client hello message. 411cb0ef41Sopenharmony_ci std::string hostname = ""; 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci // When true, TLS keylog data will be emitted to the JavaScript session. 441cb0ef41Sopenharmony_ci bool keylog = false; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci // When set, the peer certificate is verified against the list of supplied 471cb0ef41Sopenharmony_ci // CAs. If verification fails, the connection will be refused. 481cb0ef41Sopenharmony_ci bool reject_unauthorized = true; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci // When set, enables TLS tracing for the session. This should only be used 511cb0ef41Sopenharmony_ci // for debugging. 521cb0ef41Sopenharmony_ci bool enable_tls_trace = false; 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci // Options only used by server sessions: 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci // When set, instructs the server session to request a client authentication 571cb0ef41Sopenharmony_ci // certificate. 581cb0ef41Sopenharmony_ci bool request_peer_certificate = false; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci // Options only used by client sessions: 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci // When set, instructs the client session to verify the hostname default. 631cb0ef41Sopenharmony_ci // This is required by QUIC and enabled by default. We allow disabling it 641cb0ef41Sopenharmony_ci // only for debugging. 651cb0ef41Sopenharmony_ci bool verify_hostname_identity = true; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci // The TLS session ID context (only used on the server) 681cb0ef41Sopenharmony_ci std::string session_id_ctx = "Node.js QUIC Server"; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci // TLS cipher suite 711cb0ef41Sopenharmony_ci std::string ciphers = DEFAULT_CIPHERS; 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci // TLS groups 741cb0ef41Sopenharmony_ci std::string groups = DEFAULT_GROUPS; 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci // The TLS private key to use for this session. 771cb0ef41Sopenharmony_ci std::vector<std::shared_ptr<crypto::KeyObjectData>> keys; 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci // Collection of certificates to use for this session. 801cb0ef41Sopenharmony_ci std::vector<Store> certs; 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci // Optional certificate authority overrides to use. 831cb0ef41Sopenharmony_ci std::vector<Store> ca; 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci // Optional certificate revocation lists to use. 861cb0ef41Sopenharmony_ci std::vector<Store> crl; 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci void MemoryInfo(MemoryTracker* tracker) const override; 891cb0ef41Sopenharmony_ci SET_MEMORY_INFO_NAME(CryptoContext::Options) 901cb0ef41Sopenharmony_ci SET_SELF_SIZE(Options) 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci static v8::Maybe<const Options> From(Environment* env, 931cb0ef41Sopenharmony_ci v8::Local<v8::Value> value); 941cb0ef41Sopenharmony_ci }; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci static const Options kDefaultOptions; 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci TLSContext(Environment* env, 991cb0ef41Sopenharmony_ci Side side, 1001cb0ef41Sopenharmony_ci Session* session, 1011cb0ef41Sopenharmony_ci const Options& options); 1021cb0ef41Sopenharmony_ci TLSContext(const TLSContext&) = delete; 1031cb0ef41Sopenharmony_ci TLSContext(TLSContext&&) = delete; 1041cb0ef41Sopenharmony_ci TLSContext& operator=(const TLSContext&) = delete; 1051cb0ef41Sopenharmony_ci TLSContext& operator=(TLSContext&&) = delete; 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci // Start the TLS handshake. 1081cb0ef41Sopenharmony_ci void Start(); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci // TLS Keylogging is enabled per-Session by attaching a handler to the 1111cb0ef41Sopenharmony_ci // "keylog" event. Each keylog line is emitted to JavaScript where it can be 1121cb0ef41Sopenharmony_ci // routed to whatever destination makes sense. Typically, this will be to a 1131cb0ef41Sopenharmony_ci // keylog file that can be consumed by tools like Wireshark to intercept and 1141cb0ef41Sopenharmony_ci // decrypt QUIC network traffic. 1151cb0ef41Sopenharmony_ci void Keylog(const char* line) const; 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci // Called when a chunk of peer TLS handshake data is received. For every 1181cb0ef41Sopenharmony_ci // chunk, we move the TLS handshake further along until it is complete. 1191cb0ef41Sopenharmony_ci int Receive(ngtcp2_crypto_level crypto_level, 1201cb0ef41Sopenharmony_ci uint64_t offset, 1211cb0ef41Sopenharmony_ci const ngtcp2_vec& vec); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Object> cert(Environment* env) const; 1241cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Object> peer_cert(Environment* env) const; 1251cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> cipher_name(Environment* env) const; 1261cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> cipher_version(Environment* env) const; 1271cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Object> ephemeral_key(Environment* env) const; 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci // The SNI servername negotiated for the session 1301cb0ef41Sopenharmony_ci const std::string_view servername() const; 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci // The ALPN (protocol name) negotiated for the session 1331cb0ef41Sopenharmony_ci const std::string_view alpn() const; 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci // Triggers key update to begin. This will fail and return false if either a 1361cb0ef41Sopenharmony_ci // previous key update is in progress and has not been confirmed or if the 1371cb0ef41Sopenharmony_ci // initial handshake has not yet been confirmed. 1381cb0ef41Sopenharmony_ci bool InitiateKeyUpdate(); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci int VerifyPeerIdentity(); 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci Side side() const; 1431cb0ef41Sopenharmony_ci const Options& options() const; 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci int OnNewSession(SSL_SESSION* session); 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci void MaybeSetEarlySession(const SessionTicket& sessionTicket); 1481cb0ef41Sopenharmony_ci bool early_data_was_accepted() const; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci void MemoryInfo(MemoryTracker* tracker) const override; 1511cb0ef41Sopenharmony_ci SET_MEMORY_INFO_NAME(CryptoContext) 1521cb0ef41Sopenharmony_ci SET_SELF_SIZE(TLSContext) 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci private: 1551cb0ef41Sopenharmony_ci static ngtcp2_conn* getConnection(ngtcp2_crypto_conn_ref* ref); 1561cb0ef41Sopenharmony_ci ngtcp2_crypto_conn_ref conn_ref_; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci Side side_; 1591cb0ef41Sopenharmony_ci Environment* env_; 1601cb0ef41Sopenharmony_ci Session* session_; 1611cb0ef41Sopenharmony_ci const Options options_; 1621cb0ef41Sopenharmony_ci BaseObjectPtr<crypto::SecureContext> secure_context_; 1631cb0ef41Sopenharmony_ci crypto::SSLPointer ssl_; 1641cb0ef41Sopenharmony_ci crypto::BIOPointer bio_trace_; 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci bool in_key_update_ = false; 1671cb0ef41Sopenharmony_ci bool early_data_ = false; 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci friend class Session; 1701cb0ef41Sopenharmony_ci}; 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci} // namespace quic 1731cb0ef41Sopenharmony_ci} // namespace node 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci#endif // HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC 1761cb0ef41Sopenharmony_ci#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 177