11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include "crypto/crypto_tls.h"
231cb0ef41Sopenharmony_ci#include "crypto/crypto_context.h"
241cb0ef41Sopenharmony_ci#include "crypto/crypto_common.h"
251cb0ef41Sopenharmony_ci#include "crypto/crypto_util.h"
261cb0ef41Sopenharmony_ci#include "crypto/crypto_bio.h"
271cb0ef41Sopenharmony_ci#include "crypto/crypto_clienthello-inl.h"
281cb0ef41Sopenharmony_ci#include "async_wrap-inl.h"
291cb0ef41Sopenharmony_ci#include "debug_utils-inl.h"
301cb0ef41Sopenharmony_ci#include "memory_tracker-inl.h"
311cb0ef41Sopenharmony_ci#include "node_buffer.h"
321cb0ef41Sopenharmony_ci#include "node_errors.h"
331cb0ef41Sopenharmony_ci#include "stream_base-inl.h"
341cb0ef41Sopenharmony_ci#include "util-inl.h"
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_cinamespace node {
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ciusing v8::Array;
391cb0ef41Sopenharmony_ciusing v8::ArrayBuffer;
401cb0ef41Sopenharmony_ciusing v8::ArrayBufferView;
411cb0ef41Sopenharmony_ciusing v8::BackingStore;
421cb0ef41Sopenharmony_ciusing v8::Boolean;
431cb0ef41Sopenharmony_ciusing v8::Context;
441cb0ef41Sopenharmony_ciusing v8::DontDelete;
451cb0ef41Sopenharmony_ciusing v8::Exception;
461cb0ef41Sopenharmony_ciusing v8::False;
471cb0ef41Sopenharmony_ciusing v8::Function;
481cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
491cb0ef41Sopenharmony_ciusing v8::FunctionTemplate;
501cb0ef41Sopenharmony_ciusing v8::HandleScope;
511cb0ef41Sopenharmony_ciusing v8::Integer;
521cb0ef41Sopenharmony_ciusing v8::Isolate;
531cb0ef41Sopenharmony_ciusing v8::Local;
541cb0ef41Sopenharmony_ciusing v8::MaybeLocal;
551cb0ef41Sopenharmony_ciusing v8::Null;
561cb0ef41Sopenharmony_ciusing v8::Object;
571cb0ef41Sopenharmony_ciusing v8::PropertyAttribute;
581cb0ef41Sopenharmony_ciusing v8::ReadOnly;
591cb0ef41Sopenharmony_ciusing v8::Signature;
601cb0ef41Sopenharmony_ciusing v8::String;
611cb0ef41Sopenharmony_ciusing v8::Uint32;
621cb0ef41Sopenharmony_ciusing v8::Value;
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_cinamespace crypto {
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_cinamespace {
671cb0ef41Sopenharmony_ciSSL_SESSION* GetSessionCallback(
681cb0ef41Sopenharmony_ci    SSL* s,
691cb0ef41Sopenharmony_ci    const unsigned char* key,
701cb0ef41Sopenharmony_ci    int len,
711cb0ef41Sopenharmony_ci    int* copy) {
721cb0ef41Sopenharmony_ci  TLSWrap* w = static_cast<TLSWrap*>(SSL_get_app_data(s));
731cb0ef41Sopenharmony_ci  *copy = 0;
741cb0ef41Sopenharmony_ci  return w->ReleaseSession();
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_civoid OnClientHello(
781cb0ef41Sopenharmony_ci    void* arg,
791cb0ef41Sopenharmony_ci    const ClientHelloParser::ClientHello& hello) {
801cb0ef41Sopenharmony_ci  TLSWrap* w = static_cast<TLSWrap*>(arg);
811cb0ef41Sopenharmony_ci  Environment* env = w->env();
821cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
831cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  Local<Object> hello_obj = Object::New(env->isolate());
861cb0ef41Sopenharmony_ci  Local<String> servername = (hello.servername() == nullptr)
871cb0ef41Sopenharmony_ci      ? String::Empty(env->isolate())
881cb0ef41Sopenharmony_ci      : OneByteString(env->isolate(),
891cb0ef41Sopenharmony_ci                      hello.servername(),
901cb0ef41Sopenharmony_ci                      hello.servername_size());
911cb0ef41Sopenharmony_ci  Local<Object> buf =
921cb0ef41Sopenharmony_ci      Buffer::Copy(
931cb0ef41Sopenharmony_ci          env,
941cb0ef41Sopenharmony_ci          reinterpret_cast<const char*>(hello.session_id()),
951cb0ef41Sopenharmony_ci          hello.session_size()).FromMaybe(Local<Object>());
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  if ((buf.IsEmpty() ||
981cb0ef41Sopenharmony_ci       hello_obj->Set(env->context(), env->session_id_string(), buf)
991cb0ef41Sopenharmony_ci           .IsNothing()) ||
1001cb0ef41Sopenharmony_ci      hello_obj->Set(env->context(), env->servername_string(), servername)
1011cb0ef41Sopenharmony_ci          .IsNothing() ||
1021cb0ef41Sopenharmony_ci      hello_obj
1031cb0ef41Sopenharmony_ci          ->Set(env->context(),
1041cb0ef41Sopenharmony_ci                env->tls_ticket_string(),
1051cb0ef41Sopenharmony_ci                Boolean::New(env->isolate(), hello.has_ticket()))
1061cb0ef41Sopenharmony_ci          .IsNothing()) {
1071cb0ef41Sopenharmony_ci    return;
1081cb0ef41Sopenharmony_ci  }
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  Local<Value> argv[] = { hello_obj };
1111cb0ef41Sopenharmony_ci  w->MakeCallback(env->onclienthello_string(), arraysize(argv), argv);
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_civoid KeylogCallback(const SSL* s, const char* line) {
1151cb0ef41Sopenharmony_ci  TLSWrap* w = static_cast<TLSWrap*>(SSL_get_app_data(s));
1161cb0ef41Sopenharmony_ci  Environment* env = w->env();
1171cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
1181cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  const size_t size = strlen(line);
1211cb0ef41Sopenharmony_ci  Local<Value> line_bf = Buffer::Copy(env, line, 1 + size)
1221cb0ef41Sopenharmony_ci      .FromMaybe(Local<Value>());
1231cb0ef41Sopenharmony_ci  if (UNLIKELY(line_bf.IsEmpty()))
1241cb0ef41Sopenharmony_ci    return;
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci  char* data = Buffer::Data(line_bf);
1271cb0ef41Sopenharmony_ci  data[size] = '\n';
1281cb0ef41Sopenharmony_ci  w->MakeCallback(env->onkeylog_string(), 1, &line_bf);
1291cb0ef41Sopenharmony_ci}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ciint NewSessionCallback(SSL* s, SSL_SESSION* sess) {
1321cb0ef41Sopenharmony_ci  TLSWrap* w = static_cast<TLSWrap*>(SSL_get_app_data(s));
1331cb0ef41Sopenharmony_ci  Environment* env = w->env();
1341cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
1351cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  if (!w->has_session_callbacks())
1381cb0ef41Sopenharmony_ci    return 0;
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci  // Check if session is small enough to be stored
1411cb0ef41Sopenharmony_ci  int size = i2d_SSL_SESSION(sess, nullptr);
1421cb0ef41Sopenharmony_ci  if (UNLIKELY(size > SecureContext::kMaxSessionSize))
1431cb0ef41Sopenharmony_ci    return 0;
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  // Serialize session
1461cb0ef41Sopenharmony_ci  Local<Object> session = Buffer::New(env, size).FromMaybe(Local<Object>());
1471cb0ef41Sopenharmony_ci  if (UNLIKELY(session.IsEmpty()))
1481cb0ef41Sopenharmony_ci    return 0;
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  unsigned char* session_data =
1511cb0ef41Sopenharmony_ci      reinterpret_cast<unsigned char*>(Buffer::Data(session));
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  CHECK_EQ(i2d_SSL_SESSION(sess, &session_data), size);
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  unsigned int session_id_length;
1561cb0ef41Sopenharmony_ci  const unsigned char* session_id_data =
1571cb0ef41Sopenharmony_ci      SSL_SESSION_get_id(sess, &session_id_length);
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  Local<Object> session_id = Buffer::Copy(
1601cb0ef41Sopenharmony_ci      env,
1611cb0ef41Sopenharmony_ci      reinterpret_cast<const char*>(session_id_data),
1621cb0ef41Sopenharmony_ci      session_id_length).FromMaybe(Local<Object>());
1631cb0ef41Sopenharmony_ci  if (UNLIKELY(session_id.IsEmpty()))
1641cb0ef41Sopenharmony_ci    return 0;
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  Local<Value> argv[] = {
1671cb0ef41Sopenharmony_ci    session_id,
1681cb0ef41Sopenharmony_ci    session
1691cb0ef41Sopenharmony_ci  };
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  // On servers, we pause the handshake until callback of 'newSession', which
1721cb0ef41Sopenharmony_ci  // calls NewSessionDoneCb(). On clients, there is no callback to wait for.
1731cb0ef41Sopenharmony_ci  if (w->is_server())
1741cb0ef41Sopenharmony_ci    w->set_awaiting_new_session(true);
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  w->MakeCallback(env->onnewsession_string(), arraysize(argv), argv);
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  return 0;
1791cb0ef41Sopenharmony_ci}
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ciint SSLCertCallback(SSL* s, void* arg) {
1821cb0ef41Sopenharmony_ci  TLSWrap* w = static_cast<TLSWrap*>(SSL_get_app_data(s));
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  if (!w->is_server() || !w->is_waiting_cert_cb())
1851cb0ef41Sopenharmony_ci    return 1;
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  if (w->is_cert_cb_running())
1881cb0ef41Sopenharmony_ci    // Not an error. Suspend handshake with SSL_ERROR_WANT_X509_LOOKUP, and
1891cb0ef41Sopenharmony_ci    // handshake will continue after certcb is done.
1901cb0ef41Sopenharmony_ci    return -1;
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  Environment* env = w->env();
1931cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
1941cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
1951cb0ef41Sopenharmony_ci  w->set_cert_cb_running();
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  Local<Object> info = Object::New(env->isolate());
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  const char* servername = GetServerName(s);
2001cb0ef41Sopenharmony_ci  Local<String> servername_str = (servername == nullptr)
2011cb0ef41Sopenharmony_ci      ? String::Empty(env->isolate())
2021cb0ef41Sopenharmony_ci      : OneByteString(env->isolate(), servername, strlen(servername));
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci  Local<Value> ocsp = Boolean::New(
2051cb0ef41Sopenharmony_ci      env->isolate(), SSL_get_tlsext_status_type(s) == TLSEXT_STATUSTYPE_ocsp);
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci  if (info->Set(env->context(), env->servername_string(), servername_str)
2081cb0ef41Sopenharmony_ci          .IsNothing() ||
2091cb0ef41Sopenharmony_ci      info->Set(env->context(), env->ocsp_request_string(), ocsp).IsNothing()) {
2101cb0ef41Sopenharmony_ci    return 1;
2111cb0ef41Sopenharmony_ci  }
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  Local<Value> argv[] = { info };
2141cb0ef41Sopenharmony_ci  w->MakeCallback(env->oncertcb_string(), arraysize(argv), argv);
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  return w->is_cert_cb_running() ? -1 : 1;
2171cb0ef41Sopenharmony_ci}
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ciint SelectALPNCallback(
2201cb0ef41Sopenharmony_ci    SSL* s,
2211cb0ef41Sopenharmony_ci    const unsigned char** out,
2221cb0ef41Sopenharmony_ci    unsigned char* outlen,
2231cb0ef41Sopenharmony_ci    const unsigned char* in,
2241cb0ef41Sopenharmony_ci    unsigned int inlen,
2251cb0ef41Sopenharmony_ci    void* arg) {
2261cb0ef41Sopenharmony_ci  TLSWrap* w = static_cast<TLSWrap*>(SSL_get_app_data(s));
2271cb0ef41Sopenharmony_ci  if (w->alpn_callback_enabled_) {
2281cb0ef41Sopenharmony_ci    Environment* env = w->env();
2291cb0ef41Sopenharmony_ci    HandleScope handle_scope(env->isolate());
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci    Local<Value> callback_arg =
2321cb0ef41Sopenharmony_ci        Buffer::Copy(env, reinterpret_cast<const char*>(in), inlen)
2331cb0ef41Sopenharmony_ci            .ToLocalChecked();
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci    MaybeLocal<Value> maybe_callback_result =
2361cb0ef41Sopenharmony_ci        w->MakeCallback(env->alpn_callback_string(), 1, &callback_arg);
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci    if (UNLIKELY(maybe_callback_result.IsEmpty())) {
2391cb0ef41Sopenharmony_ci      // Implies the callback didn't return, because some exception was thrown
2401cb0ef41Sopenharmony_ci      // during processing, e.g. if callback returned an invalid ALPN value.
2411cb0ef41Sopenharmony_ci      return SSL_TLSEXT_ERR_ALERT_FATAL;
2421cb0ef41Sopenharmony_ci    }
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci    Local<Value> callback_result = maybe_callback_result.ToLocalChecked();
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci    if (callback_result->IsUndefined()) {
2471cb0ef41Sopenharmony_ci      // If you set an ALPN callback, but you return undefined for an ALPN
2481cb0ef41Sopenharmony_ci      // request, you're rejecting all proposed ALPN protocols, and so we send
2491cb0ef41Sopenharmony_ci      // a fatal alert:
2501cb0ef41Sopenharmony_ci      return SSL_TLSEXT_ERR_ALERT_FATAL;
2511cb0ef41Sopenharmony_ci    }
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci    CHECK(callback_result->IsNumber());
2541cb0ef41Sopenharmony_ci    unsigned int result_int = callback_result.As<v8::Number>()->Value();
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci    // The callback returns an offset into the given buffer, for the selected
2571cb0ef41Sopenharmony_ci    // protocol that should be returned. We then set outlen & out to point
2581cb0ef41Sopenharmony_ci    // to the selected input length & value directly:
2591cb0ef41Sopenharmony_ci    *outlen = *(in + result_int);
2601cb0ef41Sopenharmony_ci    *out = (in + result_int + 1);
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci    return SSL_TLSEXT_ERR_OK;
2631cb0ef41Sopenharmony_ci  }
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci  const std::vector<unsigned char>& alpn_protos = w->alpn_protos_;
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci  if (alpn_protos.empty()) return SSL_TLSEXT_ERR_NOACK;
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci  int status = SSL_select_next_proto(const_cast<unsigned char**>(out),
2701cb0ef41Sopenharmony_ci                                     outlen,
2711cb0ef41Sopenharmony_ci                                     alpn_protos.data(),
2721cb0ef41Sopenharmony_ci                                     alpn_protos.size(),
2731cb0ef41Sopenharmony_ci                                     in,
2741cb0ef41Sopenharmony_ci                                     inlen);
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  // According to 3.2. Protocol Selection of RFC7301, fatal
2771cb0ef41Sopenharmony_ci  // no_application_protocol alert shall be sent but OpenSSL 1.0.2 does not
2781cb0ef41Sopenharmony_ci  // support it yet. See
2791cb0ef41Sopenharmony_ci  // https://rt.openssl.org/Ticket/Display.html?id=3463&user=guest&pass=guest
2801cb0ef41Sopenharmony_ci  return status == OPENSSL_NPN_NEGOTIATED
2811cb0ef41Sopenharmony_ci      ? SSL_TLSEXT_ERR_OK
2821cb0ef41Sopenharmony_ci      : SSL_TLSEXT_ERR_NOACK;
2831cb0ef41Sopenharmony_ci}
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ciint TLSExtStatusCallback(SSL* s, void* arg) {
2861cb0ef41Sopenharmony_ci  TLSWrap* w = static_cast<TLSWrap*>(SSL_get_app_data(s));
2871cb0ef41Sopenharmony_ci  Environment* env = w->env();
2881cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  if (w->is_client()) {
2911cb0ef41Sopenharmony_ci    // Incoming response
2921cb0ef41Sopenharmony_ci    Local<Value> arg;
2931cb0ef41Sopenharmony_ci    if (GetSSLOCSPResponse(env, s, Null(env->isolate())).ToLocal(&arg))
2941cb0ef41Sopenharmony_ci      w->MakeCallback(env->onocspresponse_string(), 1, &arg);
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci    // No async acceptance is possible, so always return 1 to accept the
2971cb0ef41Sopenharmony_ci    // response.  The listener for 'OCSPResponse' event has no control over
2981cb0ef41Sopenharmony_ci    // return value, but it can .destroy() the connection if the response is not
2991cb0ef41Sopenharmony_ci    // acceptable.
3001cb0ef41Sopenharmony_ci    return 1;
3011cb0ef41Sopenharmony_ci  }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  // Outgoing response
3041cb0ef41Sopenharmony_ci  Local<ArrayBufferView> obj =
3051cb0ef41Sopenharmony_ci      w->ocsp_response().FromMaybe(Local<ArrayBufferView>());
3061cb0ef41Sopenharmony_ci  if (UNLIKELY(obj.IsEmpty()))
3071cb0ef41Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  size_t len = obj->ByteLength();
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci  // OpenSSL takes control of the pointer after accepting it
3121cb0ef41Sopenharmony_ci  unsigned char* data = MallocOpenSSL<unsigned char>(len);
3131cb0ef41Sopenharmony_ci  obj->CopyContents(data, len);
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  if (!SSL_set_tlsext_status_ocsp_resp(s, data, len))
3161cb0ef41Sopenharmony_ci    OPENSSL_free(data);
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci  w->ClearOcspResponse();
3191cb0ef41Sopenharmony_ci
3201cb0ef41Sopenharmony_ci  return SSL_TLSEXT_ERR_OK;
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_civoid ConfigureSecureContext(SecureContext* sc) {
3241cb0ef41Sopenharmony_ci  // OCSP stapling
3251cb0ef41Sopenharmony_ci  SSL_CTX_set_tlsext_status_cb(sc->ctx().get(), TLSExtStatusCallback);
3261cb0ef41Sopenharmony_ci  SSL_CTX_set_tlsext_status_arg(sc->ctx().get(), nullptr);
3271cb0ef41Sopenharmony_ci}
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ciinline bool Set(
3301cb0ef41Sopenharmony_ci    Environment* env,
3311cb0ef41Sopenharmony_ci    Local<Object> target,
3321cb0ef41Sopenharmony_ci    Local<String> name,
3331cb0ef41Sopenharmony_ci    const char* value,
3341cb0ef41Sopenharmony_ci    bool ignore_null = true) {
3351cb0ef41Sopenharmony_ci  if (value == nullptr)
3361cb0ef41Sopenharmony_ci    return ignore_null;
3371cb0ef41Sopenharmony_ci  return !target->Set(
3381cb0ef41Sopenharmony_ci      env->context(),
3391cb0ef41Sopenharmony_ci      name,
3401cb0ef41Sopenharmony_ci      OneByteString(env->isolate(), value))
3411cb0ef41Sopenharmony_ci          .IsNothing();
3421cb0ef41Sopenharmony_ci}
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_cistd::string GetBIOError() {
3451cb0ef41Sopenharmony_ci  std::string ret;
3461cb0ef41Sopenharmony_ci  ERR_print_errors_cb(
3471cb0ef41Sopenharmony_ci      [](const char* str, size_t len, void* opaque) {
3481cb0ef41Sopenharmony_ci        static_cast<std::string*>(opaque)->assign(str, len);
3491cb0ef41Sopenharmony_ci        return 0;
3501cb0ef41Sopenharmony_ci      },
3511cb0ef41Sopenharmony_ci      static_cast<void*>(&ret));
3521cb0ef41Sopenharmony_ci  return ret;
3531cb0ef41Sopenharmony_ci}
3541cb0ef41Sopenharmony_ci}  // namespace
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ciTLSWrap::TLSWrap(Environment* env,
3571cb0ef41Sopenharmony_ci                 Local<Object> obj,
3581cb0ef41Sopenharmony_ci                 Kind kind,
3591cb0ef41Sopenharmony_ci                 StreamBase* stream,
3601cb0ef41Sopenharmony_ci                 SecureContext* sc,
3611cb0ef41Sopenharmony_ci                 UnderlyingStreamWriteStatus under_stream_ws)
3621cb0ef41Sopenharmony_ci    : AsyncWrap(env, obj, AsyncWrap::PROVIDER_TLSWRAP),
3631cb0ef41Sopenharmony_ci      StreamBase(env),
3641cb0ef41Sopenharmony_ci      env_(env),
3651cb0ef41Sopenharmony_ci      kind_(kind),
3661cb0ef41Sopenharmony_ci      sc_(sc),
3671cb0ef41Sopenharmony_ci      has_active_write_issued_by_prev_listener_(
3681cb0ef41Sopenharmony_ci          under_stream_ws == UnderlyingStreamWriteStatus::kHasActive) {
3691cb0ef41Sopenharmony_ci  MakeWeak();
3701cb0ef41Sopenharmony_ci  CHECK(sc_);
3711cb0ef41Sopenharmony_ci  ssl_ = sc_->CreateSSL();
3721cb0ef41Sopenharmony_ci  CHECK(ssl_);
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci  sc_->SetGetSessionCallback(GetSessionCallback);
3751cb0ef41Sopenharmony_ci  sc_->SetNewSessionCallback(NewSessionCallback);
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_ci  StreamBase::AttachToObject(GetObject());
3781cb0ef41Sopenharmony_ci  stream->PushStreamListener(this);
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci  env_->isolate()->AdjustAmountOfExternalAllocatedMemory(kExternalSize);
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci  InitSSL();
3831cb0ef41Sopenharmony_ci  Debug(this, "Created new TLSWrap");
3841cb0ef41Sopenharmony_ci}
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ciTLSWrap::~TLSWrap() {
3871cb0ef41Sopenharmony_ci  Destroy();
3881cb0ef41Sopenharmony_ci}
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ciMaybeLocal<ArrayBufferView> TLSWrap::ocsp_response() const {
3911cb0ef41Sopenharmony_ci  if (ocsp_response_.IsEmpty())
3921cb0ef41Sopenharmony_ci    return MaybeLocal<ArrayBufferView>();
3931cb0ef41Sopenharmony_ci  return PersistentToLocal::Default(env()->isolate(), ocsp_response_);
3941cb0ef41Sopenharmony_ci}
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_civoid TLSWrap::ClearOcspResponse() {
3971cb0ef41Sopenharmony_ci  ocsp_response_.Reset();
3981cb0ef41Sopenharmony_ci}
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ciSSL_SESSION* TLSWrap::ReleaseSession() {
4011cb0ef41Sopenharmony_ci  return next_sess_.release();
4021cb0ef41Sopenharmony_ci}
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_civoid TLSWrap::InvokeQueued(int status, const char* error_str) {
4051cb0ef41Sopenharmony_ci  Debug(this, "Invoking queued write callbacks (%d, %s)", status, error_str);
4061cb0ef41Sopenharmony_ci  if (!write_callback_scheduled_)
4071cb0ef41Sopenharmony_ci    return;
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  if (current_write_) {
4101cb0ef41Sopenharmony_ci    BaseObjectPtr<AsyncWrap> current_write = std::move(current_write_);
4111cb0ef41Sopenharmony_ci    current_write_.reset();
4121cb0ef41Sopenharmony_ci    WriteWrap* w = WriteWrap::FromObject(current_write);
4131cb0ef41Sopenharmony_ci    w->Done(status, error_str);
4141cb0ef41Sopenharmony_ci  }
4151cb0ef41Sopenharmony_ci}
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_civoid TLSWrap::NewSessionDoneCb() {
4181cb0ef41Sopenharmony_ci  Debug(this, "New session callback done");
4191cb0ef41Sopenharmony_ci  Cycle();
4201cb0ef41Sopenharmony_ci}
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_civoid TLSWrap::InitSSL() {
4231cb0ef41Sopenharmony_ci  // Initialize SSL – OpenSSL takes ownership of these.
4241cb0ef41Sopenharmony_ci  enc_in_ = NodeBIO::New(env()).release();
4251cb0ef41Sopenharmony_ci  enc_out_ = NodeBIO::New(env()).release();
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci  SSL_set_bio(ssl_.get(), enc_in_, enc_out_);
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  // NOTE: This could be overridden in SetVerifyMode
4301cb0ef41Sopenharmony_ci  SSL_set_verify(ssl_.get(), SSL_VERIFY_NONE, VerifyCallback);
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci#ifdef SSL_MODE_RELEASE_BUFFERS
4331cb0ef41Sopenharmony_ci  SSL_set_mode(ssl_.get(), SSL_MODE_RELEASE_BUFFERS);
4341cb0ef41Sopenharmony_ci#endif  // SSL_MODE_RELEASE_BUFFERS
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci  // This is default in 1.1.1, but set it anyway, Cycle() doesn't currently
4371cb0ef41Sopenharmony_ci  // re-call ClearIn() if SSL_read() returns SSL_ERROR_WANT_READ, so data can be
4381cb0ef41Sopenharmony_ci  // left sitting in the incoming enc_in_ and never get processed.
4391cb0ef41Sopenharmony_ci  // - https://wiki.openssl.org/index.php/TLS1.3#Non-application_data_records
4401cb0ef41Sopenharmony_ci  SSL_set_mode(ssl_.get(), SSL_MODE_AUTO_RETRY);
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci#ifdef OPENSSL_IS_BORINGSSL
4431cb0ef41Sopenharmony_ci  // OpenSSL allows renegotiation by default, but BoringSSL disables it.
4441cb0ef41Sopenharmony_ci  // Configure BoringSSL to match OpenSSL's behavior.
4451cb0ef41Sopenharmony_ci  SSL_set_renegotiate_mode(ssl_.get(), ssl_renegotiate_freely);
4461cb0ef41Sopenharmony_ci#endif
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  SSL_set_app_data(ssl_.get(), this);
4491cb0ef41Sopenharmony_ci  // Using InfoCallback isn't how we are supposed to check handshake progress:
4501cb0ef41Sopenharmony_ci  //   https://github.com/openssl/openssl/issues/7199#issuecomment-420915993
4511cb0ef41Sopenharmony_ci  //
4521cb0ef41Sopenharmony_ci  // Note on when this gets called on various openssl versions:
4531cb0ef41Sopenharmony_ci  //   https://github.com/openssl/openssl/issues/7199#issuecomment-420670544
4541cb0ef41Sopenharmony_ci  SSL_set_info_callback(ssl_.get(), SSLInfoCallback);
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  if (is_server())
4571cb0ef41Sopenharmony_ci    sc_->SetSelectSNIContextCallback(SelectSNIContextCallback);
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  ConfigureSecureContext(sc_.get());
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci  SSL_set_cert_cb(ssl_.get(), SSLCertCallback, this);
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci  if (is_server()) {
4641cb0ef41Sopenharmony_ci    SSL_set_accept_state(ssl_.get());
4651cb0ef41Sopenharmony_ci  } else if (is_client()) {
4661cb0ef41Sopenharmony_ci    // Enough space for server response (hello, cert)
4671cb0ef41Sopenharmony_ci    NodeBIO::FromBIO(enc_in_)->set_initial(kInitialClientBufferLength);
4681cb0ef41Sopenharmony_ci    SSL_set_connect_state(ssl_.get());
4691cb0ef41Sopenharmony_ci  } else {
4701cb0ef41Sopenharmony_ci    // Unexpected
4711cb0ef41Sopenharmony_ci    ABORT();
4721cb0ef41Sopenharmony_ci  }
4731cb0ef41Sopenharmony_ci}
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_civoid TLSWrap::Wrap(const FunctionCallbackInfo<Value>& args) {
4761cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 4);
4791cb0ef41Sopenharmony_ci  CHECK(args[0]->IsObject());
4801cb0ef41Sopenharmony_ci  CHECK(args[1]->IsObject());
4811cb0ef41Sopenharmony_ci  CHECK(args[2]->IsBoolean());
4821cb0ef41Sopenharmony_ci  CHECK(args[3]->IsBoolean());
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci  Local<Object> sc = args[1].As<Object>();
4851cb0ef41Sopenharmony_ci  Kind kind = args[2]->IsTrue() ? Kind::kServer : Kind::kClient;
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_ci  UnderlyingStreamWriteStatus under_stream_ws =
4881cb0ef41Sopenharmony_ci      args[3]->IsTrue() ? UnderlyingStreamWriteStatus::kHasActive
4891cb0ef41Sopenharmony_ci                        : UnderlyingStreamWriteStatus::kVacancy;
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ci  StreamBase* stream = StreamBase::FromObject(args[0].As<Object>());
4921cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(stream);
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci  Local<Object> obj;
4951cb0ef41Sopenharmony_ci  if (!env->tls_wrap_constructor_function()
4961cb0ef41Sopenharmony_ci           ->NewInstance(env->context())
4971cb0ef41Sopenharmony_ci           .ToLocal(&obj)) {
4981cb0ef41Sopenharmony_ci    return;
4991cb0ef41Sopenharmony_ci  }
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci  TLSWrap* res = new TLSWrap(
5021cb0ef41Sopenharmony_ci      env, obj, kind, stream, Unwrap<SecureContext>(sc), under_stream_ws);
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(res->object());
5051cb0ef41Sopenharmony_ci}
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_civoid TLSWrap::Receive(const FunctionCallbackInfo<Value>& args) {
5081cb0ef41Sopenharmony_ci  TLSWrap* wrap;
5091cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci  ArrayBufferViewContents<char> buffer(args[0]);
5121cb0ef41Sopenharmony_ci  const char* data = buffer.data();
5131cb0ef41Sopenharmony_ci  size_t len = buffer.length();
5141cb0ef41Sopenharmony_ci  Debug(wrap, "Receiving %zu bytes injected from JS", len);
5151cb0ef41Sopenharmony_ci
5161cb0ef41Sopenharmony_ci  // Copy given buffer entirely or partiall if handle becomes closed
5171cb0ef41Sopenharmony_ci  while (len > 0 && wrap->IsAlive() && !wrap->IsClosing()) {
5181cb0ef41Sopenharmony_ci    uv_buf_t buf = wrap->OnStreamAlloc(len);
5191cb0ef41Sopenharmony_ci    size_t copy = buf.len > len ? len : buf.len;
5201cb0ef41Sopenharmony_ci    memcpy(buf.base, data, copy);
5211cb0ef41Sopenharmony_ci    buf.len = copy;
5221cb0ef41Sopenharmony_ci    wrap->OnStreamRead(copy, buf);
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci    data += copy;
5251cb0ef41Sopenharmony_ci    len -= copy;
5261cb0ef41Sopenharmony_ci  }
5271cb0ef41Sopenharmony_ci}
5281cb0ef41Sopenharmony_ci
5291cb0ef41Sopenharmony_civoid TLSWrap::Start(const FunctionCallbackInfo<Value>& args) {
5301cb0ef41Sopenharmony_ci  TLSWrap* wrap;
5311cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci  CHECK(!wrap->started_);
5341cb0ef41Sopenharmony_ci  wrap->started_ = true;
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci  // Send ClientHello handshake
5371cb0ef41Sopenharmony_ci  CHECK(wrap->is_client());
5381cb0ef41Sopenharmony_ci  // Seems odd to read when when we want to send, but SSL_read() triggers a
5391cb0ef41Sopenharmony_ci  // handshake if a session isn't established, and handshake will cause
5401cb0ef41Sopenharmony_ci  // encrypted data to become available for output.
5411cb0ef41Sopenharmony_ci  wrap->ClearOut();
5421cb0ef41Sopenharmony_ci  wrap->EncOut();
5431cb0ef41Sopenharmony_ci}
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_civoid TLSWrap::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
5461cb0ef41Sopenharmony_ci  if (!(where & (SSL_CB_HANDSHAKE_START | SSL_CB_HANDSHAKE_DONE)))
5471cb0ef41Sopenharmony_ci    return;
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  // SSL_renegotiate_pending() should take `const SSL*`, but it does not.
5501cb0ef41Sopenharmony_ci  SSL* ssl = const_cast<SSL*>(ssl_);
5511cb0ef41Sopenharmony_ci  TLSWrap* c = static_cast<TLSWrap*>(SSL_get_app_data(ssl_));
5521cb0ef41Sopenharmony_ci  Environment* env = c->env();
5531cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
5541cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
5551cb0ef41Sopenharmony_ci  Local<Object> object = c->object();
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci  if (where & SSL_CB_HANDSHAKE_START) {
5581cb0ef41Sopenharmony_ci    Debug(c, "SSLInfoCallback(SSL_CB_HANDSHAKE_START);");
5591cb0ef41Sopenharmony_ci    // Start is tracked to limit number and frequency of renegotiation attempts,
5601cb0ef41Sopenharmony_ci    // since excessive renegotiation may be an attack.
5611cb0ef41Sopenharmony_ci    Local<Value> callback;
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_ci    if (object->Get(env->context(), env->onhandshakestart_string())
5641cb0ef41Sopenharmony_ci            .ToLocal(&callback) && callback->IsFunction()) {
5651cb0ef41Sopenharmony_ci      Local<Value> argv[] = { env->GetNow() };
5661cb0ef41Sopenharmony_ci      c->MakeCallback(callback.As<Function>(), arraysize(argv), argv);
5671cb0ef41Sopenharmony_ci    }
5681cb0ef41Sopenharmony_ci  }
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci  // SSL_CB_HANDSHAKE_START and SSL_CB_HANDSHAKE_DONE are called
5711cb0ef41Sopenharmony_ci  // sending HelloRequest in OpenSSL-1.1.1.
5721cb0ef41Sopenharmony_ci  // We need to check whether this is in a renegotiation state or not.
5731cb0ef41Sopenharmony_ci  if (where & SSL_CB_HANDSHAKE_DONE && !SSL_renegotiate_pending(ssl)) {
5741cb0ef41Sopenharmony_ci    Debug(c, "SSLInfoCallback(SSL_CB_HANDSHAKE_DONE);");
5751cb0ef41Sopenharmony_ci    CHECK(!SSL_renegotiate_pending(ssl));
5761cb0ef41Sopenharmony_ci    Local<Value> callback;
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_ci    c->established_ = true;
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci    if (object->Get(env->context(), env->onhandshakedone_string())
5811cb0ef41Sopenharmony_ci          .ToLocal(&callback) && callback->IsFunction()) {
5821cb0ef41Sopenharmony_ci      c->MakeCallback(callback.As<Function>(), 0, nullptr);
5831cb0ef41Sopenharmony_ci    }
5841cb0ef41Sopenharmony_ci  }
5851cb0ef41Sopenharmony_ci}
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_civoid TLSWrap::EncOut() {
5881cb0ef41Sopenharmony_ci  Debug(this, "Trying to write encrypted output");
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci  // Ignore cycling data if ClientHello wasn't yet parsed
5911cb0ef41Sopenharmony_ci  if (!hello_parser_.IsEnded()) {
5921cb0ef41Sopenharmony_ci    Debug(this, "Returning from EncOut(), hello_parser_ active");
5931cb0ef41Sopenharmony_ci    return;
5941cb0ef41Sopenharmony_ci  }
5951cb0ef41Sopenharmony_ci
5961cb0ef41Sopenharmony_ci  // Write in progress
5971cb0ef41Sopenharmony_ci  if (write_size_ != 0) {
5981cb0ef41Sopenharmony_ci    Debug(this, "Returning from EncOut(), write currently in progress");
5991cb0ef41Sopenharmony_ci    return;
6001cb0ef41Sopenharmony_ci  }
6011cb0ef41Sopenharmony_ci
6021cb0ef41Sopenharmony_ci  // Wait for `newSession` callback to be invoked
6031cb0ef41Sopenharmony_ci  if (is_awaiting_new_session()) {
6041cb0ef41Sopenharmony_ci    Debug(this, "Returning from EncOut(), awaiting new session");
6051cb0ef41Sopenharmony_ci    return;
6061cb0ef41Sopenharmony_ci  }
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ci  if (UNLIKELY(has_active_write_issued_by_prev_listener_)) {
6091cb0ef41Sopenharmony_ci    Debug(this,
6101cb0ef41Sopenharmony_ci          "Returning from EncOut(), "
6111cb0ef41Sopenharmony_ci          "has_active_write_issued_by_prev_listener_ is true");
6121cb0ef41Sopenharmony_ci    return;
6131cb0ef41Sopenharmony_ci  }
6141cb0ef41Sopenharmony_ci
6151cb0ef41Sopenharmony_ci  // Split-off queue
6161cb0ef41Sopenharmony_ci  if (established_ && current_write_) {
6171cb0ef41Sopenharmony_ci    Debug(this, "EncOut() write is scheduled");
6181cb0ef41Sopenharmony_ci    write_callback_scheduled_ = true;
6191cb0ef41Sopenharmony_ci  }
6201cb0ef41Sopenharmony_ci
6211cb0ef41Sopenharmony_ci  if (ssl_ == nullptr) {
6221cb0ef41Sopenharmony_ci    Debug(this, "Returning from EncOut(), ssl_ == nullptr");
6231cb0ef41Sopenharmony_ci    return;
6241cb0ef41Sopenharmony_ci  }
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_ci  // No encrypted output ready to write to the underlying stream.
6271cb0ef41Sopenharmony_ci  if (BIO_pending(enc_out_) == 0) {
6281cb0ef41Sopenharmony_ci    Debug(this, "No pending encrypted output");
6291cb0ef41Sopenharmony_ci    if (!pending_cleartext_input_ ||
6301cb0ef41Sopenharmony_ci        pending_cleartext_input_->ByteLength() == 0) {
6311cb0ef41Sopenharmony_ci      if (!in_dowrite_) {
6321cb0ef41Sopenharmony_ci        Debug(this, "No pending cleartext input, not inside DoWrite()");
6331cb0ef41Sopenharmony_ci        InvokeQueued(0);
6341cb0ef41Sopenharmony_ci      } else {
6351cb0ef41Sopenharmony_ci        Debug(this, "No pending cleartext input, inside DoWrite()");
6361cb0ef41Sopenharmony_ci        // TODO(@sam-github, @addaleax) If in_dowrite_ is true, appdata was
6371cb0ef41Sopenharmony_ci        // passed to SSL_write().  If we are here, the data was not encrypted to
6381cb0ef41Sopenharmony_ci        // enc_out_ yet.  Calling Done() "works", but since the write is not
6391cb0ef41Sopenharmony_ci        // flushed, its too soon.  Just returning and letting the next EncOut()
6401cb0ef41Sopenharmony_ci        // call Done() passes the test suite, but without more careful analysis,
6411cb0ef41Sopenharmony_ci        // its not clear if it is always correct. Not calling Done() could block
6421cb0ef41Sopenharmony_ci        // data flow, so for now continue to call Done(), just do it in the next
6431cb0ef41Sopenharmony_ci        // tick.
6441cb0ef41Sopenharmony_ci        BaseObjectPtr<TLSWrap> strong_ref{this};
6451cb0ef41Sopenharmony_ci        env()->SetImmediate([this, strong_ref](Environment* env) {
6461cb0ef41Sopenharmony_ci          InvokeQueued(0);
6471cb0ef41Sopenharmony_ci        });
6481cb0ef41Sopenharmony_ci      }
6491cb0ef41Sopenharmony_ci    }
6501cb0ef41Sopenharmony_ci    return;
6511cb0ef41Sopenharmony_ci  }
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_ci  char* data[kSimultaneousBufferCount];
6541cb0ef41Sopenharmony_ci  size_t size[arraysize(data)];
6551cb0ef41Sopenharmony_ci  size_t count = arraysize(data);
6561cb0ef41Sopenharmony_ci  write_size_ = NodeBIO::FromBIO(enc_out_)->PeekMultiple(data, size, &count);
6571cb0ef41Sopenharmony_ci  CHECK(write_size_ != 0 && count != 0);
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci  uv_buf_t buf[arraysize(data)];
6601cb0ef41Sopenharmony_ci  uv_buf_t* bufs = buf;
6611cb0ef41Sopenharmony_ci  for (size_t i = 0; i < count; i++)
6621cb0ef41Sopenharmony_ci    buf[i] = uv_buf_init(data[i], size[i]);
6631cb0ef41Sopenharmony_ci
6641cb0ef41Sopenharmony_ci  Debug(this, "Writing %zu buffers to the underlying stream", count);
6651cb0ef41Sopenharmony_ci  StreamWriteResult res = underlying_stream()->Write(bufs, count);
6661cb0ef41Sopenharmony_ci  if (res.err != 0) {
6671cb0ef41Sopenharmony_ci    InvokeQueued(res.err);
6681cb0ef41Sopenharmony_ci    return;
6691cb0ef41Sopenharmony_ci  }
6701cb0ef41Sopenharmony_ci
6711cb0ef41Sopenharmony_ci  if (!res.async) {
6721cb0ef41Sopenharmony_ci    Debug(this, "Write finished synchronously");
6731cb0ef41Sopenharmony_ci    HandleScope handle_scope(env()->isolate());
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci    // Simulate asynchronous finishing, TLS cannot handle this at the moment.
6761cb0ef41Sopenharmony_ci    BaseObjectPtr<TLSWrap> strong_ref{this};
6771cb0ef41Sopenharmony_ci    env()->SetImmediate([this, strong_ref](Environment* env) {
6781cb0ef41Sopenharmony_ci      OnStreamAfterWrite(nullptr, 0);
6791cb0ef41Sopenharmony_ci    });
6801cb0ef41Sopenharmony_ci  }
6811cb0ef41Sopenharmony_ci}
6821cb0ef41Sopenharmony_ci
6831cb0ef41Sopenharmony_civoid TLSWrap::OnStreamAfterWrite(WriteWrap* req_wrap, int status) {
6841cb0ef41Sopenharmony_ci  Debug(this, "OnStreamAfterWrite(status = %d)", status);
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci  if (UNLIKELY(has_active_write_issued_by_prev_listener_)) {
6871cb0ef41Sopenharmony_ci    Debug(this, "Notify write finish to the previous_listener_");
6881cb0ef41Sopenharmony_ci    CHECK_EQ(write_size_, 0);  // we must have restrained writes
6891cb0ef41Sopenharmony_ci
6901cb0ef41Sopenharmony_ci    previous_listener_->OnStreamAfterWrite(req_wrap, status);
6911cb0ef41Sopenharmony_ci    return;
6921cb0ef41Sopenharmony_ci  }
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ci  if (current_empty_write_) {
6951cb0ef41Sopenharmony_ci    Debug(this, "Had empty write");
6961cb0ef41Sopenharmony_ci    BaseObjectPtr<AsyncWrap> current_empty_write =
6971cb0ef41Sopenharmony_ci        std::move(current_empty_write_);
6981cb0ef41Sopenharmony_ci    current_empty_write_.reset();
6991cb0ef41Sopenharmony_ci    WriteWrap* finishing = WriteWrap::FromObject(current_empty_write);
7001cb0ef41Sopenharmony_ci    finishing->Done(status);
7011cb0ef41Sopenharmony_ci    return;
7021cb0ef41Sopenharmony_ci  }
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_ci  if (ssl_ == nullptr) {
7051cb0ef41Sopenharmony_ci    Debug(this, "ssl_ == nullptr, marking as cancelled");
7061cb0ef41Sopenharmony_ci    status = UV_ECANCELED;
7071cb0ef41Sopenharmony_ci  }
7081cb0ef41Sopenharmony_ci
7091cb0ef41Sopenharmony_ci  // Handle error
7101cb0ef41Sopenharmony_ci  if (status) {
7111cb0ef41Sopenharmony_ci    if (shutdown_) {
7121cb0ef41Sopenharmony_ci      Debug(this, "Ignoring error after shutdown");
7131cb0ef41Sopenharmony_ci      return;
7141cb0ef41Sopenharmony_ci    }
7151cb0ef41Sopenharmony_ci
7161cb0ef41Sopenharmony_ci    // Notify about error
7171cb0ef41Sopenharmony_ci    InvokeQueued(status);
7181cb0ef41Sopenharmony_ci    return;
7191cb0ef41Sopenharmony_ci  }
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  // Commit
7221cb0ef41Sopenharmony_ci  NodeBIO::FromBIO(enc_out_)->Read(nullptr, write_size_);
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ci  // Ensure that the progress will be made and `InvokeQueued` will be called.
7251cb0ef41Sopenharmony_ci  ClearIn();
7261cb0ef41Sopenharmony_ci
7271cb0ef41Sopenharmony_ci  // Try writing more data
7281cb0ef41Sopenharmony_ci  write_size_ = 0;
7291cb0ef41Sopenharmony_ci  EncOut();
7301cb0ef41Sopenharmony_ci}
7311cb0ef41Sopenharmony_ci
7321cb0ef41Sopenharmony_civoid TLSWrap::ClearOut() {
7331cb0ef41Sopenharmony_ci  Debug(this, "Trying to read cleartext output");
7341cb0ef41Sopenharmony_ci  // Ignore cycling data if ClientHello wasn't yet parsed
7351cb0ef41Sopenharmony_ci  if (!hello_parser_.IsEnded()) {
7361cb0ef41Sopenharmony_ci    Debug(this, "Returning from ClearOut(), hello_parser_ active");
7371cb0ef41Sopenharmony_ci    return;
7381cb0ef41Sopenharmony_ci  }
7391cb0ef41Sopenharmony_ci
7401cb0ef41Sopenharmony_ci  // No reads after EOF
7411cb0ef41Sopenharmony_ci  if (eof_) {
7421cb0ef41Sopenharmony_ci    Debug(this, "Returning from ClearOut(), EOF reached");
7431cb0ef41Sopenharmony_ci    return;
7441cb0ef41Sopenharmony_ci  }
7451cb0ef41Sopenharmony_ci
7461cb0ef41Sopenharmony_ci  if (ssl_ == nullptr) {
7471cb0ef41Sopenharmony_ci    Debug(this, "Returning from ClearOut(), ssl_ == nullptr");
7481cb0ef41Sopenharmony_ci    return;
7491cb0ef41Sopenharmony_ci  }
7501cb0ef41Sopenharmony_ci
7511cb0ef41Sopenharmony_ci  MarkPopErrorOnReturn mark_pop_error_on_return;
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_ci  char out[kClearOutChunkSize];
7541cb0ef41Sopenharmony_ci  int read;
7551cb0ef41Sopenharmony_ci  for (;;) {
7561cb0ef41Sopenharmony_ci    read = SSL_read(ssl_.get(), out, sizeof(out));
7571cb0ef41Sopenharmony_ci    Debug(this, "Read %d bytes of cleartext output", read);
7581cb0ef41Sopenharmony_ci
7591cb0ef41Sopenharmony_ci    if (read <= 0)
7601cb0ef41Sopenharmony_ci      break;
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_ci    char* current = out;
7631cb0ef41Sopenharmony_ci    while (read > 0) {
7641cb0ef41Sopenharmony_ci      int avail = read;
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci      uv_buf_t buf = EmitAlloc(avail);
7671cb0ef41Sopenharmony_ci      if (static_cast<int>(buf.len) < avail)
7681cb0ef41Sopenharmony_ci        avail = buf.len;
7691cb0ef41Sopenharmony_ci      memcpy(buf.base, current, avail);
7701cb0ef41Sopenharmony_ci      EmitRead(avail, buf);
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_ci      // Caveat emptor: OnRead() calls into JS land which can result in
7731cb0ef41Sopenharmony_ci      // the SSL context object being destroyed.  We have to carefully
7741cb0ef41Sopenharmony_ci      // check that ssl_ != nullptr afterwards.
7751cb0ef41Sopenharmony_ci      if (ssl_ == nullptr) {
7761cb0ef41Sopenharmony_ci        Debug(this, "Returning from read loop, ssl_ == nullptr");
7771cb0ef41Sopenharmony_ci        return;
7781cb0ef41Sopenharmony_ci      }
7791cb0ef41Sopenharmony_ci
7801cb0ef41Sopenharmony_ci      read -= avail;
7811cb0ef41Sopenharmony_ci      current += avail;
7821cb0ef41Sopenharmony_ci    }
7831cb0ef41Sopenharmony_ci  }
7841cb0ef41Sopenharmony_ci
7851cb0ef41Sopenharmony_ci  // We need to check whether an error occurred or the connection was
7861cb0ef41Sopenharmony_ci  // shutdown cleanly (SSL_ERROR_ZERO_RETURN) even when read == 0.
7871cb0ef41Sopenharmony_ci  // See node#1642 and SSL_read(3SSL) for details. SSL_get_error must be
7881cb0ef41Sopenharmony_ci  // called immediately after SSL_read, without calling into JS, which may
7891cb0ef41Sopenharmony_ci  // change OpenSSL's error queue, modify ssl_, or even destroy ssl_
7901cb0ef41Sopenharmony_ci  // altogether.
7911cb0ef41Sopenharmony_ci  if (read <= 0) {
7921cb0ef41Sopenharmony_ci    HandleScope handle_scope(env()->isolate());
7931cb0ef41Sopenharmony_ci    Local<Value> error;
7941cb0ef41Sopenharmony_ci    int err = SSL_get_error(ssl_.get(), read);
7951cb0ef41Sopenharmony_ci    switch (err) {
7961cb0ef41Sopenharmony_ci      case SSL_ERROR_ZERO_RETURN:
7971cb0ef41Sopenharmony_ci        if (!eof_) {
7981cb0ef41Sopenharmony_ci          eof_ = true;
7991cb0ef41Sopenharmony_ci          EmitRead(UV_EOF);
8001cb0ef41Sopenharmony_ci        }
8011cb0ef41Sopenharmony_ci        return;
8021cb0ef41Sopenharmony_ci
8031cb0ef41Sopenharmony_ci      case SSL_ERROR_SSL:
8041cb0ef41Sopenharmony_ci      case SSL_ERROR_SYSCALL:
8051cb0ef41Sopenharmony_ci        {
8061cb0ef41Sopenharmony_ci          unsigned long ssl_err = ERR_peek_error();  // NOLINT(runtime/int)
8071cb0ef41Sopenharmony_ci
8081cb0ef41Sopenharmony_ci          Local<Context> context = env()->isolate()->GetCurrentContext();
8091cb0ef41Sopenharmony_ci          if (UNLIKELY(context.IsEmpty())) return;
8101cb0ef41Sopenharmony_ci          const std::string error_str = GetBIOError();
8111cb0ef41Sopenharmony_ci          Local<String> message = OneByteString(
8121cb0ef41Sopenharmony_ci              env()->isolate(), error_str.c_str(), error_str.size());
8131cb0ef41Sopenharmony_ci          if (UNLIKELY(message.IsEmpty())) return;
8141cb0ef41Sopenharmony_ci          error = Exception::Error(message);
8151cb0ef41Sopenharmony_ci          if (UNLIKELY(error.IsEmpty())) return;
8161cb0ef41Sopenharmony_ci          Local<Object> obj;
8171cb0ef41Sopenharmony_ci          if (UNLIKELY(!error->ToObject(context).ToLocal(&obj))) return;
8181cb0ef41Sopenharmony_ci
8191cb0ef41Sopenharmony_ci          const char* ls = ERR_lib_error_string(ssl_err);
8201cb0ef41Sopenharmony_ci          const char* fs = ERR_func_error_string(ssl_err);
8211cb0ef41Sopenharmony_ci          const char* rs = ERR_reason_error_string(ssl_err);
8221cb0ef41Sopenharmony_ci          if (!Set(env(), obj, env()->library_string(), ls) ||
8231cb0ef41Sopenharmony_ci              !Set(env(), obj, env()->function_string(), fs) ||
8241cb0ef41Sopenharmony_ci              !Set(env(), obj, env()->reason_string(), rs, false)) return;
8251cb0ef41Sopenharmony_ci          // SSL has no API to recover the error name from the number, so we
8261cb0ef41Sopenharmony_ci          // transform reason strings like "this error" to "ERR_SSL_THIS_ERROR",
8271cb0ef41Sopenharmony_ci          // which ends up being close to the original error macro name.
8281cb0ef41Sopenharmony_ci          std::string code(rs);
8291cb0ef41Sopenharmony_ci          // TODO(RaisinTen): Pass an appropriate execution policy when it is
8301cb0ef41Sopenharmony_ci          // implemented in our supported compilers.
8311cb0ef41Sopenharmony_ci          std::transform(code.begin(), code.end(), code.begin(),
8321cb0ef41Sopenharmony_ci                         [](char c) { return c == ' ' ? '_' : ToUpper(c); });
8331cb0ef41Sopenharmony_ci          if (!Set(env(), obj,
8341cb0ef41Sopenharmony_ci                   env()->code_string(), ("ERR_SSL_" + code).c_str())) return;
8351cb0ef41Sopenharmony_ci        }
8361cb0ef41Sopenharmony_ci        break;
8371cb0ef41Sopenharmony_ci
8381cb0ef41Sopenharmony_ci      default:
8391cb0ef41Sopenharmony_ci        return;
8401cb0ef41Sopenharmony_ci    }
8411cb0ef41Sopenharmony_ci
8421cb0ef41Sopenharmony_ci    Debug(this, "Got SSL error (%d), calling onerror", err);
8431cb0ef41Sopenharmony_ci    // When TLS Alert are stored in wbio,
8441cb0ef41Sopenharmony_ci    // it should be flushed to socket before destroyed.
8451cb0ef41Sopenharmony_ci    if (BIO_pending(enc_out_) != 0)
8461cb0ef41Sopenharmony_ci      EncOut();
8471cb0ef41Sopenharmony_ci
8481cb0ef41Sopenharmony_ci    MakeCallback(env()->onerror_string(), 1, &error);
8491cb0ef41Sopenharmony_ci  }
8501cb0ef41Sopenharmony_ci}
8511cb0ef41Sopenharmony_ci
8521cb0ef41Sopenharmony_civoid TLSWrap::ClearIn() {
8531cb0ef41Sopenharmony_ci  Debug(this, "Trying to write cleartext input");
8541cb0ef41Sopenharmony_ci  // Ignore cycling data if ClientHello wasn't yet parsed
8551cb0ef41Sopenharmony_ci  if (!hello_parser_.IsEnded()) {
8561cb0ef41Sopenharmony_ci    Debug(this, "Returning from ClearIn(), hello_parser_ active");
8571cb0ef41Sopenharmony_ci    return;
8581cb0ef41Sopenharmony_ci  }
8591cb0ef41Sopenharmony_ci
8601cb0ef41Sopenharmony_ci  if (ssl_ == nullptr) {
8611cb0ef41Sopenharmony_ci    Debug(this, "Returning from ClearIn(), ssl_ == nullptr");
8621cb0ef41Sopenharmony_ci    return;
8631cb0ef41Sopenharmony_ci  }
8641cb0ef41Sopenharmony_ci
8651cb0ef41Sopenharmony_ci  if (!pending_cleartext_input_ ||
8661cb0ef41Sopenharmony_ci      pending_cleartext_input_->ByteLength() == 0) {
8671cb0ef41Sopenharmony_ci    Debug(this, "Returning from ClearIn(), no pending data");
8681cb0ef41Sopenharmony_ci    return;
8691cb0ef41Sopenharmony_ci  }
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> bs = std::move(pending_cleartext_input_);
8721cb0ef41Sopenharmony_ci  MarkPopErrorOnReturn mark_pop_error_on_return;
8731cb0ef41Sopenharmony_ci
8741cb0ef41Sopenharmony_ci  NodeBIO::FromBIO(enc_out_)->set_allocate_tls_hint(bs->ByteLength());
8751cb0ef41Sopenharmony_ci  int written = SSL_write(ssl_.get(), bs->Data(), bs->ByteLength());
8761cb0ef41Sopenharmony_ci  Debug(this, "Writing %zu bytes, written = %d", bs->ByteLength(), written);
8771cb0ef41Sopenharmony_ci  CHECK(written == -1 || written == static_cast<int>(bs->ByteLength()));
8781cb0ef41Sopenharmony_ci
8791cb0ef41Sopenharmony_ci  // All written
8801cb0ef41Sopenharmony_ci  if (written != -1) {
8811cb0ef41Sopenharmony_ci    Debug(this, "Successfully wrote all data to SSL");
8821cb0ef41Sopenharmony_ci    return;
8831cb0ef41Sopenharmony_ci  }
8841cb0ef41Sopenharmony_ci
8851cb0ef41Sopenharmony_ci  // Error or partial write
8861cb0ef41Sopenharmony_ci  int err = SSL_get_error(ssl_.get(), written);
8871cb0ef41Sopenharmony_ci  if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
8881cb0ef41Sopenharmony_ci    Debug(this, "Got SSL error (%d)", err);
8891cb0ef41Sopenharmony_ci    write_callback_scheduled_ = true;
8901cb0ef41Sopenharmony_ci    // TODO(@sam-github) Should forward an error object with
8911cb0ef41Sopenharmony_ci    // .code/.function/.etc, if possible.
8921cb0ef41Sopenharmony_ci    InvokeQueued(UV_EPROTO, GetBIOError().c_str());
8931cb0ef41Sopenharmony_ci    return;
8941cb0ef41Sopenharmony_ci  }
8951cb0ef41Sopenharmony_ci
8961cb0ef41Sopenharmony_ci  Debug(this, "Pushing data back");
8971cb0ef41Sopenharmony_ci  // Push back the not-yet-written data. This can be skipped in the error
8981cb0ef41Sopenharmony_ci  // case because no further writes would succeed anyway.
8991cb0ef41Sopenharmony_ci  pending_cleartext_input_ = std::move(bs);
9001cb0ef41Sopenharmony_ci}
9011cb0ef41Sopenharmony_ci
9021cb0ef41Sopenharmony_cistd::string TLSWrap::diagnostic_name() const {
9031cb0ef41Sopenharmony_ci  std::string name = "TLSWrap ";
9041cb0ef41Sopenharmony_ci  name += is_server() ? "server (" : "client (";
9051cb0ef41Sopenharmony_ci  name += std::to_string(static_cast<int64_t>(get_async_id())) + ")";
9061cb0ef41Sopenharmony_ci  return name;
9071cb0ef41Sopenharmony_ci}
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_ciAsyncWrap* TLSWrap::GetAsyncWrap() {
9101cb0ef41Sopenharmony_ci  return static_cast<AsyncWrap*>(this);
9111cb0ef41Sopenharmony_ci}
9121cb0ef41Sopenharmony_ci
9131cb0ef41Sopenharmony_cibool TLSWrap::IsIPCPipe() {
9141cb0ef41Sopenharmony_ci  return underlying_stream()->IsIPCPipe();
9151cb0ef41Sopenharmony_ci}
9161cb0ef41Sopenharmony_ci
9171cb0ef41Sopenharmony_ciint TLSWrap::GetFD() {
9181cb0ef41Sopenharmony_ci  return underlying_stream()->GetFD();
9191cb0ef41Sopenharmony_ci}
9201cb0ef41Sopenharmony_ci
9211cb0ef41Sopenharmony_cibool TLSWrap::IsAlive() {
9221cb0ef41Sopenharmony_ci  return ssl_ &&
9231cb0ef41Sopenharmony_ci      underlying_stream() != nullptr &&
9241cb0ef41Sopenharmony_ci      underlying_stream()->IsAlive();
9251cb0ef41Sopenharmony_ci}
9261cb0ef41Sopenharmony_ci
9271cb0ef41Sopenharmony_cibool TLSWrap::IsClosing() {
9281cb0ef41Sopenharmony_ci  return underlying_stream()->IsClosing();
9291cb0ef41Sopenharmony_ci}
9301cb0ef41Sopenharmony_ci
9311cb0ef41Sopenharmony_ciint TLSWrap::ReadStart() {
9321cb0ef41Sopenharmony_ci  Debug(this, "ReadStart()");
9331cb0ef41Sopenharmony_ci  if (underlying_stream() != nullptr && !eof_)
9341cb0ef41Sopenharmony_ci    return underlying_stream()->ReadStart();
9351cb0ef41Sopenharmony_ci  return 0;
9361cb0ef41Sopenharmony_ci}
9371cb0ef41Sopenharmony_ci
9381cb0ef41Sopenharmony_ciint TLSWrap::ReadStop() {
9391cb0ef41Sopenharmony_ci  Debug(this, "ReadStop()");
9401cb0ef41Sopenharmony_ci  return underlying_stream() != nullptr ? underlying_stream()->ReadStop() : 0;
9411cb0ef41Sopenharmony_ci}
9421cb0ef41Sopenharmony_ci
9431cb0ef41Sopenharmony_ciconst char* TLSWrap::Error() const {
9441cb0ef41Sopenharmony_ci  return error_.empty() ? nullptr : error_.c_str();
9451cb0ef41Sopenharmony_ci}
9461cb0ef41Sopenharmony_ci
9471cb0ef41Sopenharmony_civoid TLSWrap::ClearError() {
9481cb0ef41Sopenharmony_ci  error_.clear();
9491cb0ef41Sopenharmony_ci}
9501cb0ef41Sopenharmony_ci
9511cb0ef41Sopenharmony_ci// Called by StreamBase::Write() to request async write of clear text into SSL.
9521cb0ef41Sopenharmony_ci// TODO(@sam-github) Should there be a TLSWrap::DoTryWrite()?
9531cb0ef41Sopenharmony_ciint TLSWrap::DoWrite(WriteWrap* w,
9541cb0ef41Sopenharmony_ci                     uv_buf_t* bufs,
9551cb0ef41Sopenharmony_ci                     size_t count,
9561cb0ef41Sopenharmony_ci                     uv_stream_t* send_handle) {
9571cb0ef41Sopenharmony_ci  CHECK_NULL(send_handle);
9581cb0ef41Sopenharmony_ci  Debug(this, "DoWrite()");
9591cb0ef41Sopenharmony_ci
9601cb0ef41Sopenharmony_ci  if (ssl_ == nullptr) {
9611cb0ef41Sopenharmony_ci    ClearError();
9621cb0ef41Sopenharmony_ci    error_ = "Write after DestroySSL";
9631cb0ef41Sopenharmony_ci    return UV_EPROTO;
9641cb0ef41Sopenharmony_ci  }
9651cb0ef41Sopenharmony_ci
9661cb0ef41Sopenharmony_ci  size_t length = 0;
9671cb0ef41Sopenharmony_ci  size_t i;
9681cb0ef41Sopenharmony_ci  size_t nonempty_i = 0;
9691cb0ef41Sopenharmony_ci  size_t nonempty_count = 0;
9701cb0ef41Sopenharmony_ci  for (i = 0; i < count; i++) {
9711cb0ef41Sopenharmony_ci    length += bufs[i].len;
9721cb0ef41Sopenharmony_ci    if (bufs[i].len > 0) {
9731cb0ef41Sopenharmony_ci      nonempty_i = i;
9741cb0ef41Sopenharmony_ci      nonempty_count += 1;
9751cb0ef41Sopenharmony_ci    }
9761cb0ef41Sopenharmony_ci  }
9771cb0ef41Sopenharmony_ci
9781cb0ef41Sopenharmony_ci  // We want to trigger a Write() on the underlying stream to drive the stream
9791cb0ef41Sopenharmony_ci  // system, but don't want to encrypt empty buffers into a TLS frame, so see
9801cb0ef41Sopenharmony_ci  // if we can find something to Write().
9811cb0ef41Sopenharmony_ci  // First, call ClearOut(). It does an SSL_read(), which might cause handshake
9821cb0ef41Sopenharmony_ci  // or other internal messages to be encrypted. If it does, write them later
9831cb0ef41Sopenharmony_ci  // with EncOut().
9841cb0ef41Sopenharmony_ci  // If there is still no encrypted output, call Write(bufs) on the underlying
9851cb0ef41Sopenharmony_ci  // stream. Since the bufs are empty, it won't actually write non-TLS data
9861cb0ef41Sopenharmony_ci  // onto the socket, we just want the side-effects. After, make sure the
9871cb0ef41Sopenharmony_ci  // WriteWrap was accepted by the stream, or that we call Done() on it.
9881cb0ef41Sopenharmony_ci  if (length == 0) {
9891cb0ef41Sopenharmony_ci    Debug(this, "Empty write");
9901cb0ef41Sopenharmony_ci    ClearOut();
9911cb0ef41Sopenharmony_ci    if (BIO_pending(enc_out_) == 0) {
9921cb0ef41Sopenharmony_ci      Debug(this, "No pending encrypted output, writing to underlying stream");
9931cb0ef41Sopenharmony_ci      CHECK(!current_empty_write_);
9941cb0ef41Sopenharmony_ci      current_empty_write_.reset(w->GetAsyncWrap());
9951cb0ef41Sopenharmony_ci      StreamWriteResult res =
9961cb0ef41Sopenharmony_ci          underlying_stream()->Write(bufs, count, send_handle);
9971cb0ef41Sopenharmony_ci      if (!res.async) {
9981cb0ef41Sopenharmony_ci        BaseObjectPtr<TLSWrap> strong_ref{this};
9991cb0ef41Sopenharmony_ci        env()->SetImmediate([this, strong_ref](Environment* env) {
10001cb0ef41Sopenharmony_ci          OnStreamAfterWrite(WriteWrap::FromObject(current_empty_write_), 0);
10011cb0ef41Sopenharmony_ci        });
10021cb0ef41Sopenharmony_ci      }
10031cb0ef41Sopenharmony_ci      return 0;
10041cb0ef41Sopenharmony_ci    }
10051cb0ef41Sopenharmony_ci  }
10061cb0ef41Sopenharmony_ci
10071cb0ef41Sopenharmony_ci  // Store the current write wrap
10081cb0ef41Sopenharmony_ci  CHECK(!current_write_);
10091cb0ef41Sopenharmony_ci  current_write_.reset(w->GetAsyncWrap());
10101cb0ef41Sopenharmony_ci
10111cb0ef41Sopenharmony_ci  // Write encrypted data to underlying stream and call Done().
10121cb0ef41Sopenharmony_ci  if (length == 0) {
10131cb0ef41Sopenharmony_ci    EncOut();
10141cb0ef41Sopenharmony_ci    return 0;
10151cb0ef41Sopenharmony_ci  }
10161cb0ef41Sopenharmony_ci
10171cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> bs;
10181cb0ef41Sopenharmony_ci  MarkPopErrorOnReturn mark_pop_error_on_return;
10191cb0ef41Sopenharmony_ci
10201cb0ef41Sopenharmony_ci  int written = 0;
10211cb0ef41Sopenharmony_ci
10221cb0ef41Sopenharmony_ci  // It is common for zero length buffers to be written,
10231cb0ef41Sopenharmony_ci  // don't copy data if there there is one buffer with data
10241cb0ef41Sopenharmony_ci  // and one or more zero length buffers.
10251cb0ef41Sopenharmony_ci  // _http_outgoing.js writes a zero length buffer in
10261cb0ef41Sopenharmony_ci  // in OutgoingMessage.prototype.end.  If there was a large amount
10271cb0ef41Sopenharmony_ci  // of data supplied to end() there is no sense allocating
10281cb0ef41Sopenharmony_ci  // and copying it when it could just be used.
10291cb0ef41Sopenharmony_ci
10301cb0ef41Sopenharmony_ci  if (nonempty_count != 1) {
10311cb0ef41Sopenharmony_ci    {
10321cb0ef41Sopenharmony_ci      NoArrayBufferZeroFillScope no_zero_fill_scope(env()->isolate_data());
10331cb0ef41Sopenharmony_ci      bs = ArrayBuffer::NewBackingStore(env()->isolate(), length);
10341cb0ef41Sopenharmony_ci    }
10351cb0ef41Sopenharmony_ci    size_t offset = 0;
10361cb0ef41Sopenharmony_ci    for (i = 0; i < count; i++) {
10371cb0ef41Sopenharmony_ci      memcpy(static_cast<char*>(bs->Data()) + offset,
10381cb0ef41Sopenharmony_ci             bufs[i].base, bufs[i].len);
10391cb0ef41Sopenharmony_ci      offset += bufs[i].len;
10401cb0ef41Sopenharmony_ci    }
10411cb0ef41Sopenharmony_ci
10421cb0ef41Sopenharmony_ci    NodeBIO::FromBIO(enc_out_)->set_allocate_tls_hint(length);
10431cb0ef41Sopenharmony_ci    written = SSL_write(ssl_.get(), bs->Data(), length);
10441cb0ef41Sopenharmony_ci  } else {
10451cb0ef41Sopenharmony_ci    // Only one buffer: try to write directly, only store if it fails
10461cb0ef41Sopenharmony_ci    uv_buf_t* buf = &bufs[nonempty_i];
10471cb0ef41Sopenharmony_ci    NodeBIO::FromBIO(enc_out_)->set_allocate_tls_hint(buf->len);
10481cb0ef41Sopenharmony_ci    written = SSL_write(ssl_.get(), buf->base, buf->len);
10491cb0ef41Sopenharmony_ci
10501cb0ef41Sopenharmony_ci    if (written == -1) {
10511cb0ef41Sopenharmony_ci      NoArrayBufferZeroFillScope no_zero_fill_scope(env()->isolate_data());
10521cb0ef41Sopenharmony_ci      bs = ArrayBuffer::NewBackingStore(env()->isolate(), length);
10531cb0ef41Sopenharmony_ci      memcpy(bs->Data(), buf->base, buf->len);
10541cb0ef41Sopenharmony_ci    }
10551cb0ef41Sopenharmony_ci  }
10561cb0ef41Sopenharmony_ci
10571cb0ef41Sopenharmony_ci  CHECK(written == -1 || written == static_cast<int>(length));
10581cb0ef41Sopenharmony_ci  Debug(this, "Writing %zu bytes, written = %d", length, written);
10591cb0ef41Sopenharmony_ci
10601cb0ef41Sopenharmony_ci  if (written == -1) {
10611cb0ef41Sopenharmony_ci    // If we stopped writing because of an error, it's fatal, discard the data.
10621cb0ef41Sopenharmony_ci    int err = SSL_get_error(ssl_.get(), written);
10631cb0ef41Sopenharmony_ci    if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
10641cb0ef41Sopenharmony_ci      // TODO(@jasnell): What are we doing with the error?
10651cb0ef41Sopenharmony_ci      Debug(this, "Got SSL error (%d), returning UV_EPROTO", err);
10661cb0ef41Sopenharmony_ci      current_write_.reset();
10671cb0ef41Sopenharmony_ci      return UV_EPROTO;
10681cb0ef41Sopenharmony_ci    }
10691cb0ef41Sopenharmony_ci
10701cb0ef41Sopenharmony_ci    Debug(this, "Saving data for later write");
10711cb0ef41Sopenharmony_ci    // Otherwise, save unwritten data so it can be written later by ClearIn().
10721cb0ef41Sopenharmony_ci    CHECK(!pending_cleartext_input_ ||
10731cb0ef41Sopenharmony_ci          pending_cleartext_input_->ByteLength() == 0);
10741cb0ef41Sopenharmony_ci    pending_cleartext_input_ = std::move(bs);
10751cb0ef41Sopenharmony_ci  }
10761cb0ef41Sopenharmony_ci
10771cb0ef41Sopenharmony_ci  // Write any encrypted/handshake output that may be ready.
10781cb0ef41Sopenharmony_ci  // Guard against sync call of current_write_->Done(), its unsupported.
10791cb0ef41Sopenharmony_ci  in_dowrite_ = true;
10801cb0ef41Sopenharmony_ci  EncOut();
10811cb0ef41Sopenharmony_ci  in_dowrite_ = false;
10821cb0ef41Sopenharmony_ci
10831cb0ef41Sopenharmony_ci  return 0;
10841cb0ef41Sopenharmony_ci}
10851cb0ef41Sopenharmony_ci
10861cb0ef41Sopenharmony_ciuv_buf_t TLSWrap::OnStreamAlloc(size_t suggested_size) {
10871cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(ssl_);
10881cb0ef41Sopenharmony_ci
10891cb0ef41Sopenharmony_ci  size_t size = suggested_size;
10901cb0ef41Sopenharmony_ci  char* base = NodeBIO::FromBIO(enc_in_)->PeekWritable(&size);
10911cb0ef41Sopenharmony_ci  return uv_buf_init(base, size);
10921cb0ef41Sopenharmony_ci}
10931cb0ef41Sopenharmony_ci
10941cb0ef41Sopenharmony_civoid TLSWrap::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
10951cb0ef41Sopenharmony_ci  Debug(this, "Read %zd bytes from underlying stream", nread);
10961cb0ef41Sopenharmony_ci
10971cb0ef41Sopenharmony_ci  // Ignore everything after close_notify (rfc5246#section-7.2.1)
10981cb0ef41Sopenharmony_ci  if (eof_)
10991cb0ef41Sopenharmony_ci    return;
11001cb0ef41Sopenharmony_ci
11011cb0ef41Sopenharmony_ci  if (nread < 0)  {
11021cb0ef41Sopenharmony_ci    // Error should be emitted only after all data was read
11031cb0ef41Sopenharmony_ci    ClearOut();
11041cb0ef41Sopenharmony_ci
11051cb0ef41Sopenharmony_ci    if (nread == UV_EOF) {
11061cb0ef41Sopenharmony_ci      // underlying stream already should have also called ReadStop on itself
11071cb0ef41Sopenharmony_ci      eof_ = true;
11081cb0ef41Sopenharmony_ci    }
11091cb0ef41Sopenharmony_ci
11101cb0ef41Sopenharmony_ci    EmitRead(nread);
11111cb0ef41Sopenharmony_ci    return;
11121cb0ef41Sopenharmony_ci  }
11131cb0ef41Sopenharmony_ci
11141cb0ef41Sopenharmony_ci  // DestroySSL() is the only thing that un-sets ssl_, but that also removes
11151cb0ef41Sopenharmony_ci  // this TLSWrap as a stream listener, so we should not receive OnStreamRead()
11161cb0ef41Sopenharmony_ci  // calls anymore.
11171cb0ef41Sopenharmony_ci  CHECK(ssl_);
11181cb0ef41Sopenharmony_ci
11191cb0ef41Sopenharmony_ci  // Commit the amount of data actually read into the peeked/allocated buffer
11201cb0ef41Sopenharmony_ci  // from the underlying stream.
11211cb0ef41Sopenharmony_ci  NodeBIO* enc_in = NodeBIO::FromBIO(enc_in_);
11221cb0ef41Sopenharmony_ci  enc_in->Commit(nread);
11231cb0ef41Sopenharmony_ci
11241cb0ef41Sopenharmony_ci  // Parse ClientHello first, if we need to. It's only parsed if session event
11251cb0ef41Sopenharmony_ci  // listeners are used on the server side.  "ended" is the initial state, so
11261cb0ef41Sopenharmony_ci  // can mean parsing was never started, or that parsing is finished. Either
11271cb0ef41Sopenharmony_ci  // way, ended means we can give the buffered data to SSL.
11281cb0ef41Sopenharmony_ci  if (!hello_parser_.IsEnded()) {
11291cb0ef41Sopenharmony_ci    size_t avail = 0;
11301cb0ef41Sopenharmony_ci    uint8_t* data = reinterpret_cast<uint8_t*>(enc_in->Peek(&avail));
11311cb0ef41Sopenharmony_ci    CHECK_IMPLIES(data == nullptr, avail == 0);
11321cb0ef41Sopenharmony_ci    Debug(this, "Passing %zu bytes to the hello parser", avail);
11331cb0ef41Sopenharmony_ci    return hello_parser_.Parse(data, avail);
11341cb0ef41Sopenharmony_ci  }
11351cb0ef41Sopenharmony_ci
11361cb0ef41Sopenharmony_ci  // Cycle OpenSSL's state
11371cb0ef41Sopenharmony_ci  Cycle();
11381cb0ef41Sopenharmony_ci}
11391cb0ef41Sopenharmony_ci
11401cb0ef41Sopenharmony_ciShutdownWrap* TLSWrap::CreateShutdownWrap(Local<Object> req_wrap_object) {
11411cb0ef41Sopenharmony_ci  return underlying_stream()->CreateShutdownWrap(req_wrap_object);
11421cb0ef41Sopenharmony_ci}
11431cb0ef41Sopenharmony_ci
11441cb0ef41Sopenharmony_ciint TLSWrap::DoShutdown(ShutdownWrap* req_wrap) {
11451cb0ef41Sopenharmony_ci  Debug(this, "DoShutdown()");
11461cb0ef41Sopenharmony_ci  MarkPopErrorOnReturn mark_pop_error_on_return;
11471cb0ef41Sopenharmony_ci
11481cb0ef41Sopenharmony_ci  if (ssl_ && SSL_shutdown(ssl_.get()) == 0)
11491cb0ef41Sopenharmony_ci    SSL_shutdown(ssl_.get());
11501cb0ef41Sopenharmony_ci
11511cb0ef41Sopenharmony_ci  shutdown_ = true;
11521cb0ef41Sopenharmony_ci  EncOut();
11531cb0ef41Sopenharmony_ci  return underlying_stream()->DoShutdown(req_wrap);
11541cb0ef41Sopenharmony_ci}
11551cb0ef41Sopenharmony_ci
11561cb0ef41Sopenharmony_civoid TLSWrap::SetVerifyMode(const FunctionCallbackInfo<Value>& args) {
11571cb0ef41Sopenharmony_ci  TLSWrap* wrap;
11581cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 2);
11611cb0ef41Sopenharmony_ci  CHECK(args[0]->IsBoolean());
11621cb0ef41Sopenharmony_ci  CHECK(args[1]->IsBoolean());
11631cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(wrap->ssl_);
11641cb0ef41Sopenharmony_ci
11651cb0ef41Sopenharmony_ci  int verify_mode;
11661cb0ef41Sopenharmony_ci  if (wrap->is_server()) {
11671cb0ef41Sopenharmony_ci    bool request_cert = args[0]->IsTrue();
11681cb0ef41Sopenharmony_ci    if (!request_cert) {
11691cb0ef41Sopenharmony_ci      // If no cert is requested, there will be none to reject as unauthorized.
11701cb0ef41Sopenharmony_ci      verify_mode = SSL_VERIFY_NONE;
11711cb0ef41Sopenharmony_ci    } else {
11721cb0ef41Sopenharmony_ci      bool reject_unauthorized = args[1]->IsTrue();
11731cb0ef41Sopenharmony_ci      verify_mode = SSL_VERIFY_PEER;
11741cb0ef41Sopenharmony_ci      if (reject_unauthorized)
11751cb0ef41Sopenharmony_ci        verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
11761cb0ef41Sopenharmony_ci    }
11771cb0ef41Sopenharmony_ci  } else {
11781cb0ef41Sopenharmony_ci    // Servers always send a cert if the cipher is not anonymous (anon is
11791cb0ef41Sopenharmony_ci    // disabled by default), so use VERIFY_NONE and check the cert after the
11801cb0ef41Sopenharmony_ci    // handshake has completed.
11811cb0ef41Sopenharmony_ci    verify_mode = SSL_VERIFY_NONE;
11821cb0ef41Sopenharmony_ci  }
11831cb0ef41Sopenharmony_ci
11841cb0ef41Sopenharmony_ci  // Always allow a connection. We'll reject in javascript.
11851cb0ef41Sopenharmony_ci  SSL_set_verify(wrap->ssl_.get(), verify_mode, VerifyCallback);
11861cb0ef41Sopenharmony_ci}
11871cb0ef41Sopenharmony_ci
11881cb0ef41Sopenharmony_civoid TLSWrap::EnableSessionCallbacks(const FunctionCallbackInfo<Value>& args) {
11891cb0ef41Sopenharmony_ci  TLSWrap* wrap;
11901cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
11911cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(wrap->ssl_);
11921cb0ef41Sopenharmony_ci  wrap->enable_session_callbacks();
11931cb0ef41Sopenharmony_ci
11941cb0ef41Sopenharmony_ci  // Clients don't use the HelloParser.
11951cb0ef41Sopenharmony_ci  if (wrap->is_client())
11961cb0ef41Sopenharmony_ci    return;
11971cb0ef41Sopenharmony_ci
11981cb0ef41Sopenharmony_ci  NodeBIO::FromBIO(wrap->enc_in_)->set_initial(kMaxHelloLength);
11991cb0ef41Sopenharmony_ci  wrap->hello_parser_.Start(OnClientHello,
12001cb0ef41Sopenharmony_ci                            OnClientHelloParseEnd,
12011cb0ef41Sopenharmony_ci                            wrap);
12021cb0ef41Sopenharmony_ci}
12031cb0ef41Sopenharmony_ci
12041cb0ef41Sopenharmony_civoid TLSWrap::EnableKeylogCallback(const FunctionCallbackInfo<Value>& args) {
12051cb0ef41Sopenharmony_ci  TLSWrap* wrap;
12061cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
12071cb0ef41Sopenharmony_ci  CHECK(wrap->sc_);
12081cb0ef41Sopenharmony_ci  wrap->sc_->SetKeylogCallback(KeylogCallback);
12091cb0ef41Sopenharmony_ci}
12101cb0ef41Sopenharmony_ci
12111cb0ef41Sopenharmony_ci// Check required capabilities were not excluded from the OpenSSL build:
12121cb0ef41Sopenharmony_ci// - OPENSSL_NO_SSL_TRACE excludes SSL_trace()
12131cb0ef41Sopenharmony_ci// - OPENSSL_NO_STDIO excludes BIO_new_fp()
12141cb0ef41Sopenharmony_ci// HAVE_SSL_TRACE is available on the internal tcp_wrap binding for the tests.
12151cb0ef41Sopenharmony_ci#if defined(OPENSSL_NO_SSL_TRACE) || defined(OPENSSL_NO_STDIO)
12161cb0ef41Sopenharmony_ci# define HAVE_SSL_TRACE 0
12171cb0ef41Sopenharmony_ci#else
12181cb0ef41Sopenharmony_ci# define HAVE_SSL_TRACE 1
12191cb0ef41Sopenharmony_ci#endif
12201cb0ef41Sopenharmony_ci
12211cb0ef41Sopenharmony_civoid TLSWrap::EnableTrace(const FunctionCallbackInfo<Value>& args) {
12221cb0ef41Sopenharmony_ci  TLSWrap* wrap;
12231cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
12241cb0ef41Sopenharmony_ci
12251cb0ef41Sopenharmony_ci#if HAVE_SSL_TRACE
12261cb0ef41Sopenharmony_ci  if (wrap->ssl_) {
12271cb0ef41Sopenharmony_ci    wrap->bio_trace_.reset(BIO_new_fp(stderr,  BIO_NOCLOSE | BIO_FP_TEXT));
12281cb0ef41Sopenharmony_ci    SSL_set_msg_callback(wrap->ssl_.get(), [](int write_p, int version, int
12291cb0ef41Sopenharmony_ci          content_type, const void* buf, size_t len, SSL* ssl, void* arg)
12301cb0ef41Sopenharmony_ci        -> void {
12311cb0ef41Sopenharmony_ci        // BIO_write(), etc., called by SSL_trace, may error. The error should
12321cb0ef41Sopenharmony_ci        // be ignored, trace is a "best effort", and its usually because stderr
12331cb0ef41Sopenharmony_ci        // is a non-blocking pipe, and its buffer has overflowed. Leaving errors
12341cb0ef41Sopenharmony_ci        // on the stack that can get picked up by later SSL_ calls causes
12351cb0ef41Sopenharmony_ci        // unwanted failures in SSL_ calls, so keep the error stack unchanged.
12361cb0ef41Sopenharmony_ci        MarkPopErrorOnReturn mark_pop_error_on_return;
12371cb0ef41Sopenharmony_ci        SSL_trace(write_p,  version, content_type, buf, len, ssl, arg);
12381cb0ef41Sopenharmony_ci    });
12391cb0ef41Sopenharmony_ci    SSL_set_msg_callback_arg(wrap->ssl_.get(), wrap->bio_trace_.get());
12401cb0ef41Sopenharmony_ci  }
12411cb0ef41Sopenharmony_ci#endif
12421cb0ef41Sopenharmony_ci}
12431cb0ef41Sopenharmony_ci
12441cb0ef41Sopenharmony_civoid TLSWrap::DestroySSL(const FunctionCallbackInfo<Value>& args) {
12451cb0ef41Sopenharmony_ci  TLSWrap* wrap;
12461cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
12471cb0ef41Sopenharmony_ci  wrap->Destroy();
12481cb0ef41Sopenharmony_ci  Debug(wrap, "DestroySSL() finished");
12491cb0ef41Sopenharmony_ci}
12501cb0ef41Sopenharmony_ci
12511cb0ef41Sopenharmony_civoid TLSWrap::Destroy() {
12521cb0ef41Sopenharmony_ci  if (!ssl_)
12531cb0ef41Sopenharmony_ci    return;
12541cb0ef41Sopenharmony_ci
12551cb0ef41Sopenharmony_ci  // If there is a write happening, mark it as finished.
12561cb0ef41Sopenharmony_ci  write_callback_scheduled_ = true;
12571cb0ef41Sopenharmony_ci
12581cb0ef41Sopenharmony_ci  // And destroy
12591cb0ef41Sopenharmony_ci  InvokeQueued(UV_ECANCELED, "Canceled because of SSL destruction");
12601cb0ef41Sopenharmony_ci
12611cb0ef41Sopenharmony_ci  env()->isolate()->AdjustAmountOfExternalAllocatedMemory(-kExternalSize);
12621cb0ef41Sopenharmony_ci  ssl_.reset();
12631cb0ef41Sopenharmony_ci
12641cb0ef41Sopenharmony_ci  enc_in_ = nullptr;
12651cb0ef41Sopenharmony_ci  enc_out_ = nullptr;
12661cb0ef41Sopenharmony_ci
12671cb0ef41Sopenharmony_ci  if (underlying_stream() != nullptr)
12681cb0ef41Sopenharmony_ci    underlying_stream()->RemoveStreamListener(this);
12691cb0ef41Sopenharmony_ci
12701cb0ef41Sopenharmony_ci  sc_.reset();
12711cb0ef41Sopenharmony_ci}
12721cb0ef41Sopenharmony_ci
12731cb0ef41Sopenharmony_civoid TLSWrap::EnableCertCb(const FunctionCallbackInfo<Value>& args) {
12741cb0ef41Sopenharmony_ci  TLSWrap* wrap;
12751cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
12761cb0ef41Sopenharmony_ci  wrap->WaitForCertCb(OnClientHelloParseEnd, wrap);
12771cb0ef41Sopenharmony_ci}
12781cb0ef41Sopenharmony_ci
12791cb0ef41Sopenharmony_civoid TLSWrap::WaitForCertCb(CertCb cb, void* arg) {
12801cb0ef41Sopenharmony_ci  cert_cb_ = cb;
12811cb0ef41Sopenharmony_ci  cert_cb_arg_ = arg;
12821cb0ef41Sopenharmony_ci}
12831cb0ef41Sopenharmony_ci
12841cb0ef41Sopenharmony_civoid TLSWrap::OnClientHelloParseEnd(void* arg) {
12851cb0ef41Sopenharmony_ci  TLSWrap* c = static_cast<TLSWrap*>(arg);
12861cb0ef41Sopenharmony_ci  Debug(c, "OnClientHelloParseEnd()");
12871cb0ef41Sopenharmony_ci  c->Cycle();
12881cb0ef41Sopenharmony_ci}
12891cb0ef41Sopenharmony_ci
12901cb0ef41Sopenharmony_civoid TLSWrap::EnableALPNCb(const FunctionCallbackInfo<Value>& args) {
12911cb0ef41Sopenharmony_ci  TLSWrap* wrap;
12921cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
12931cb0ef41Sopenharmony_ci  wrap->alpn_callback_enabled_ = true;
12941cb0ef41Sopenharmony_ci
12951cb0ef41Sopenharmony_ci  SSL* ssl = wrap->ssl_.get();
12961cb0ef41Sopenharmony_ci  SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
12971cb0ef41Sopenharmony_ci  SSL_CTX_set_alpn_select_cb(ssl_ctx, SelectALPNCallback, nullptr);
12981cb0ef41Sopenharmony_ci}
12991cb0ef41Sopenharmony_ci
13001cb0ef41Sopenharmony_civoid TLSWrap::GetServername(const FunctionCallbackInfo<Value>& args) {
13011cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
13021cb0ef41Sopenharmony_ci
13031cb0ef41Sopenharmony_ci  TLSWrap* wrap;
13041cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
13051cb0ef41Sopenharmony_ci
13061cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(wrap->ssl_);
13071cb0ef41Sopenharmony_ci
13081cb0ef41Sopenharmony_ci  const char* servername = GetServerName(wrap->ssl_.get());
13091cb0ef41Sopenharmony_ci  if (servername != nullptr) {
13101cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(OneByteString(env->isolate(), servername));
13111cb0ef41Sopenharmony_ci  } else {
13121cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(false);
13131cb0ef41Sopenharmony_ci  }
13141cb0ef41Sopenharmony_ci}
13151cb0ef41Sopenharmony_ci
13161cb0ef41Sopenharmony_civoid TLSWrap::SetServername(const FunctionCallbackInfo<Value>& args) {
13171cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
13181cb0ef41Sopenharmony_ci
13191cb0ef41Sopenharmony_ci  TLSWrap* wrap;
13201cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
13211cb0ef41Sopenharmony_ci
13221cb0ef41Sopenharmony_ci  CHECK_EQ(args.Length(), 1);
13231cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
13241cb0ef41Sopenharmony_ci  CHECK(!wrap->started_);
13251cb0ef41Sopenharmony_ci  CHECK(wrap->is_client());
13261cb0ef41Sopenharmony_ci
13271cb0ef41Sopenharmony_ci  CHECK(wrap->ssl_);
13281cb0ef41Sopenharmony_ci
13291cb0ef41Sopenharmony_ci  Utf8Value servername(env->isolate(), args[0].As<String>());
13301cb0ef41Sopenharmony_ci  SSL_set_tlsext_host_name(wrap->ssl_.get(), *servername);
13311cb0ef41Sopenharmony_ci}
13321cb0ef41Sopenharmony_ci
13331cb0ef41Sopenharmony_ciint TLSWrap::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
13341cb0ef41Sopenharmony_ci  TLSWrap* p = static_cast<TLSWrap*>(SSL_get_app_data(s));
13351cb0ef41Sopenharmony_ci  Environment* env = p->env();
13361cb0ef41Sopenharmony_ci  HandleScope handle_scope(env->isolate());
13371cb0ef41Sopenharmony_ci  Context::Scope context_scope(env->context());
13381cb0ef41Sopenharmony_ci
13391cb0ef41Sopenharmony_ci  const char* servername = GetServerName(s);
13401cb0ef41Sopenharmony_ci  if (!Set(env, p->GetOwner(), env->servername_string(), servername))
13411cb0ef41Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
13421cb0ef41Sopenharmony_ci
13431cb0ef41Sopenharmony_ci  Local<Value> ctx = p->object()->Get(env->context(), env->sni_context_string())
13441cb0ef41Sopenharmony_ci      .FromMaybe(Local<Value>());
13451cb0ef41Sopenharmony_ci
13461cb0ef41Sopenharmony_ci  if (UNLIKELY(ctx.IsEmpty()) || !ctx->IsObject())
13471cb0ef41Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
13481cb0ef41Sopenharmony_ci
13491cb0ef41Sopenharmony_ci  if (!env->secure_context_constructor_template()->HasInstance(ctx)) {
13501cb0ef41Sopenharmony_ci    // Failure: incorrect SNI context object
13511cb0ef41Sopenharmony_ci    Local<Value> err = Exception::TypeError(env->sni_context_err_string());
13521cb0ef41Sopenharmony_ci    p->MakeCallback(env->onerror_string(), 1, &err);
13531cb0ef41Sopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
13541cb0ef41Sopenharmony_ci  }
13551cb0ef41Sopenharmony_ci
13561cb0ef41Sopenharmony_ci  SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>());
13571cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(sc);
13581cb0ef41Sopenharmony_ci  p->sni_context_ = BaseObjectPtr<SecureContext>(sc);
13591cb0ef41Sopenharmony_ci
13601cb0ef41Sopenharmony_ci  ConfigureSecureContext(sc);
13611cb0ef41Sopenharmony_ci  CHECK_EQ(SSL_set_SSL_CTX(p->ssl_.get(), sc->ctx().get()), sc->ctx().get());
13621cb0ef41Sopenharmony_ci  p->SetCACerts(sc);
13631cb0ef41Sopenharmony_ci
13641cb0ef41Sopenharmony_ci  return SSL_TLSEXT_ERR_OK;
13651cb0ef41Sopenharmony_ci}
13661cb0ef41Sopenharmony_ci
13671cb0ef41Sopenharmony_ciint TLSWrap::SetCACerts(SecureContext* sc) {
13681cb0ef41Sopenharmony_ci  int err = SSL_set1_verify_cert_store(ssl_.get(),
13691cb0ef41Sopenharmony_ci                                       SSL_CTX_get_cert_store(sc->ctx().get()));
13701cb0ef41Sopenharmony_ci  if (err != 1)
13711cb0ef41Sopenharmony_ci    return err;
13721cb0ef41Sopenharmony_ci
13731cb0ef41Sopenharmony_ci  STACK_OF(X509_NAME)* list =
13741cb0ef41Sopenharmony_ci      SSL_dup_CA_list(SSL_CTX_get_client_CA_list(sc->ctx().get()));
13751cb0ef41Sopenharmony_ci
13761cb0ef41Sopenharmony_ci  // NOTE: `SSL_set_client_CA_list` takes the ownership of `list`
13771cb0ef41Sopenharmony_ci  SSL_set_client_CA_list(ssl_.get(), list);
13781cb0ef41Sopenharmony_ci  return 1;
13791cb0ef41Sopenharmony_ci}
13801cb0ef41Sopenharmony_ci
13811cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_PSK
13821cb0ef41Sopenharmony_ci
13831cb0ef41Sopenharmony_civoid TLSWrap::SetPskIdentityHint(const FunctionCallbackInfo<Value>& args) {
13841cb0ef41Sopenharmony_ci  TLSWrap* p;
13851cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&p, args.Holder());
13861cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(p->ssl_);
13871cb0ef41Sopenharmony_ci
13881cb0ef41Sopenharmony_ci  Environment* env = p->env();
13891cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
13901cb0ef41Sopenharmony_ci
13911cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());
13921cb0ef41Sopenharmony_ci  Utf8Value hint(isolate, args[0].As<String>());
13931cb0ef41Sopenharmony_ci
13941cb0ef41Sopenharmony_ci  if (!SSL_use_psk_identity_hint(p->ssl_.get(), *hint)) {
13951cb0ef41Sopenharmony_ci    Local<Value> err = node::ERR_TLS_PSK_SET_IDENTIY_HINT_FAILED(isolate);
13961cb0ef41Sopenharmony_ci    p->MakeCallback(env->onerror_string(), 1, &err);
13971cb0ef41Sopenharmony_ci  }
13981cb0ef41Sopenharmony_ci}
13991cb0ef41Sopenharmony_ci
14001cb0ef41Sopenharmony_civoid TLSWrap::EnablePskCallback(const FunctionCallbackInfo<Value>& args) {
14011cb0ef41Sopenharmony_ci  TLSWrap* wrap;
14021cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
14031cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(wrap->ssl_);
14041cb0ef41Sopenharmony_ci
14051cb0ef41Sopenharmony_ci  SSL_set_psk_server_callback(wrap->ssl_.get(), PskServerCallback);
14061cb0ef41Sopenharmony_ci  SSL_set_psk_client_callback(wrap->ssl_.get(), PskClientCallback);
14071cb0ef41Sopenharmony_ci}
14081cb0ef41Sopenharmony_ci
14091cb0ef41Sopenharmony_ciunsigned int TLSWrap::PskServerCallback(
14101cb0ef41Sopenharmony_ci    SSL* s,
14111cb0ef41Sopenharmony_ci    const char* identity,
14121cb0ef41Sopenharmony_ci    unsigned char* psk,
14131cb0ef41Sopenharmony_ci    unsigned int max_psk_len) {
14141cb0ef41Sopenharmony_ci  TLSWrap* p = static_cast<TLSWrap*>(SSL_get_app_data(s));
14151cb0ef41Sopenharmony_ci
14161cb0ef41Sopenharmony_ci  Environment* env = p->env();
14171cb0ef41Sopenharmony_ci  HandleScope scope(env->isolate());
14181cb0ef41Sopenharmony_ci
14191cb0ef41Sopenharmony_ci  Local<String> identity_str =
14201cb0ef41Sopenharmony_ci      String::NewFromUtf8(env->isolate(), identity).FromMaybe(Local<String>());
14211cb0ef41Sopenharmony_ci  if (UNLIKELY(identity_str.IsEmpty()))
14221cb0ef41Sopenharmony_ci    return 0;
14231cb0ef41Sopenharmony_ci
14241cb0ef41Sopenharmony_ci  // Make sure there are no utf8 replacement symbols.
14251cb0ef41Sopenharmony_ci  Utf8Value identity_utf8(env->isolate(), identity_str);
14261cb0ef41Sopenharmony_ci  if (identity_utf8 != identity) return 0;
14271cb0ef41Sopenharmony_ci
14281cb0ef41Sopenharmony_ci  Local<Value> argv[] = {
14291cb0ef41Sopenharmony_ci    identity_str,
14301cb0ef41Sopenharmony_ci    Integer::NewFromUnsigned(env->isolate(), max_psk_len)
14311cb0ef41Sopenharmony_ci  };
14321cb0ef41Sopenharmony_ci
14331cb0ef41Sopenharmony_ci  Local<Value> psk_val =
14341cb0ef41Sopenharmony_ci      p->MakeCallback(env->onpskexchange_symbol(), arraysize(argv), argv)
14351cb0ef41Sopenharmony_ci          .FromMaybe(Local<Value>());
14361cb0ef41Sopenharmony_ci  if (UNLIKELY(psk_val.IsEmpty()) || !psk_val->IsArrayBufferView())
14371cb0ef41Sopenharmony_ci    return 0;
14381cb0ef41Sopenharmony_ci
14391cb0ef41Sopenharmony_ci  ArrayBufferViewContents<char> psk_buf(psk_val);
14401cb0ef41Sopenharmony_ci
14411cb0ef41Sopenharmony_ci  if (psk_buf.length() > max_psk_len)
14421cb0ef41Sopenharmony_ci    return 0;
14431cb0ef41Sopenharmony_ci
14441cb0ef41Sopenharmony_ci  memcpy(psk, psk_buf.data(), psk_buf.length());
14451cb0ef41Sopenharmony_ci  return psk_buf.length();
14461cb0ef41Sopenharmony_ci}
14471cb0ef41Sopenharmony_ci
14481cb0ef41Sopenharmony_ciunsigned int TLSWrap::PskClientCallback(
14491cb0ef41Sopenharmony_ci    SSL* s,
14501cb0ef41Sopenharmony_ci    const char* hint,
14511cb0ef41Sopenharmony_ci    char* identity,
14521cb0ef41Sopenharmony_ci    unsigned int max_identity_len,
14531cb0ef41Sopenharmony_ci    unsigned char* psk,
14541cb0ef41Sopenharmony_ci    unsigned int max_psk_len) {
14551cb0ef41Sopenharmony_ci  TLSWrap* p = static_cast<TLSWrap*>(SSL_get_app_data(s));
14561cb0ef41Sopenharmony_ci
14571cb0ef41Sopenharmony_ci  Environment* env = p->env();
14581cb0ef41Sopenharmony_ci  HandleScope scope(env->isolate());
14591cb0ef41Sopenharmony_ci
14601cb0ef41Sopenharmony_ci  Local<Value> argv[] = {
14611cb0ef41Sopenharmony_ci    Null(env->isolate()),
14621cb0ef41Sopenharmony_ci    Integer::NewFromUnsigned(env->isolate(), max_psk_len),
14631cb0ef41Sopenharmony_ci    Integer::NewFromUnsigned(env->isolate(), max_identity_len)
14641cb0ef41Sopenharmony_ci  };
14651cb0ef41Sopenharmony_ci
14661cb0ef41Sopenharmony_ci  if (hint != nullptr) {
14671cb0ef41Sopenharmony_ci    Local<String> local_hint =
14681cb0ef41Sopenharmony_ci        String::NewFromUtf8(env->isolate(), hint).FromMaybe(Local<String>());
14691cb0ef41Sopenharmony_ci    if (UNLIKELY(local_hint.IsEmpty()))
14701cb0ef41Sopenharmony_ci      return 0;
14711cb0ef41Sopenharmony_ci
14721cb0ef41Sopenharmony_ci    argv[0] = local_hint;
14731cb0ef41Sopenharmony_ci  }
14741cb0ef41Sopenharmony_ci
14751cb0ef41Sopenharmony_ci  Local<Value> ret =
14761cb0ef41Sopenharmony_ci      p->MakeCallback(env->onpskexchange_symbol(), arraysize(argv), argv)
14771cb0ef41Sopenharmony_ci          .FromMaybe(Local<Value>());
14781cb0ef41Sopenharmony_ci  if (UNLIKELY(ret.IsEmpty()) || !ret->IsObject())
14791cb0ef41Sopenharmony_ci    return 0;
14801cb0ef41Sopenharmony_ci
14811cb0ef41Sopenharmony_ci  Local<Object> obj = ret.As<Object>();
14821cb0ef41Sopenharmony_ci
14831cb0ef41Sopenharmony_ci  Local<Value> psk_val = obj->Get(env->context(), env->psk_string())
14841cb0ef41Sopenharmony_ci      .FromMaybe(Local<Value>());
14851cb0ef41Sopenharmony_ci  if (UNLIKELY(psk_val.IsEmpty()) || !psk_val->IsArrayBufferView())
14861cb0ef41Sopenharmony_ci    return 0;
14871cb0ef41Sopenharmony_ci
14881cb0ef41Sopenharmony_ci  ArrayBufferViewContents<char> psk_buf(psk_val);
14891cb0ef41Sopenharmony_ci  if (psk_buf.length() > max_psk_len)
14901cb0ef41Sopenharmony_ci    return 0;
14911cb0ef41Sopenharmony_ci
14921cb0ef41Sopenharmony_ci  Local<Value> identity_val = obj->Get(env->context(), env->identity_string())
14931cb0ef41Sopenharmony_ci      .FromMaybe(Local<Value>());
14941cb0ef41Sopenharmony_ci  if (UNLIKELY(identity_val.IsEmpty()) || !identity_val->IsString())
14951cb0ef41Sopenharmony_ci    return 0;
14961cb0ef41Sopenharmony_ci
14971cb0ef41Sopenharmony_ci  Utf8Value identity_buf(env->isolate(), identity_val);
14981cb0ef41Sopenharmony_ci
14991cb0ef41Sopenharmony_ci  if (identity_buf.length() > max_identity_len)
15001cb0ef41Sopenharmony_ci    return 0;
15011cb0ef41Sopenharmony_ci
15021cb0ef41Sopenharmony_ci  memcpy(identity, *identity_buf, identity_buf.length());
15031cb0ef41Sopenharmony_ci  memcpy(psk, psk_buf.data(), psk_buf.length());
15041cb0ef41Sopenharmony_ci
15051cb0ef41Sopenharmony_ci  return psk_buf.length();
15061cb0ef41Sopenharmony_ci}
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_ci#endif  // ifndef OPENSSL_NO_PSK
15091cb0ef41Sopenharmony_ci
15101cb0ef41Sopenharmony_civoid TLSWrap::GetWriteQueueSize(const FunctionCallbackInfo<Value>& info) {
15111cb0ef41Sopenharmony_ci  TLSWrap* wrap;
15121cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, info.This());
15131cb0ef41Sopenharmony_ci
15141cb0ef41Sopenharmony_ci  if (!wrap->ssl_)
15151cb0ef41Sopenharmony_ci    return info.GetReturnValue().Set(0);
15161cb0ef41Sopenharmony_ci
15171cb0ef41Sopenharmony_ci  uint32_t write_queue_size = BIO_pending(wrap->enc_out_);
15181cb0ef41Sopenharmony_ci  info.GetReturnValue().Set(write_queue_size);
15191cb0ef41Sopenharmony_ci}
15201cb0ef41Sopenharmony_ci
15211cb0ef41Sopenharmony_civoid TLSWrap::MemoryInfo(MemoryTracker* tracker) const {
15221cb0ef41Sopenharmony_ci  tracker->TrackField("ocsp_response", ocsp_response_);
15231cb0ef41Sopenharmony_ci  tracker->TrackField("sni_context", sni_context_);
15241cb0ef41Sopenharmony_ci  tracker->TrackField("error", error_);
15251cb0ef41Sopenharmony_ci  if (pending_cleartext_input_)
15261cb0ef41Sopenharmony_ci    tracker->TrackField("pending_cleartext_input", pending_cleartext_input_);
15271cb0ef41Sopenharmony_ci  if (enc_in_ != nullptr)
15281cb0ef41Sopenharmony_ci    tracker->TrackField("enc_in", NodeBIO::FromBIO(enc_in_));
15291cb0ef41Sopenharmony_ci  if (enc_out_ != nullptr)
15301cb0ef41Sopenharmony_ci    tracker->TrackField("enc_out", NodeBIO::FromBIO(enc_out_));
15311cb0ef41Sopenharmony_ci}
15321cb0ef41Sopenharmony_ci
15331cb0ef41Sopenharmony_civoid TLSWrap::CertCbDone(const FunctionCallbackInfo<Value>& args) {
15341cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
15351cb0ef41Sopenharmony_ci  TLSWrap* w;
15361cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
15371cb0ef41Sopenharmony_ci
15381cb0ef41Sopenharmony_ci  CHECK(w->is_waiting_cert_cb() && w->cert_cb_running_);
15391cb0ef41Sopenharmony_ci
15401cb0ef41Sopenharmony_ci  Local<Object> object = w->object();
15411cb0ef41Sopenharmony_ci  Local<Value> ctx = object->Get(env->context(), env->sni_context_string())
15421cb0ef41Sopenharmony_ci      .FromMaybe(Local<Value>());
15431cb0ef41Sopenharmony_ci  if (UNLIKELY(ctx.IsEmpty()))
15441cb0ef41Sopenharmony_ci    return;
15451cb0ef41Sopenharmony_ci
15461cb0ef41Sopenharmony_ci  Local<FunctionTemplate> cons = env->secure_context_constructor_template();
15471cb0ef41Sopenharmony_ci  if (cons->HasInstance(ctx)) {
15481cb0ef41Sopenharmony_ci    SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>());
15491cb0ef41Sopenharmony_ci    CHECK_NOT_NULL(sc);
15501cb0ef41Sopenharmony_ci    // Store the SNI context for later use.
15511cb0ef41Sopenharmony_ci    w->sni_context_ = BaseObjectPtr<SecureContext>(sc);
15521cb0ef41Sopenharmony_ci
15531cb0ef41Sopenharmony_ci    if (UseSNIContext(w->ssl_, w->sni_context_) && !w->SetCACerts(sc)) {
15541cb0ef41Sopenharmony_ci      // Not clear why sometimes we throw error, and sometimes we call
15551cb0ef41Sopenharmony_ci      // onerror(). Both cause .destroy(), but onerror does a bit more.
15561cb0ef41Sopenharmony_ci      unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
15571cb0ef41Sopenharmony_ci      return ThrowCryptoError(env, err, "CertCbDone");
15581cb0ef41Sopenharmony_ci    }
15591cb0ef41Sopenharmony_ci  } else if (ctx->IsObject()) {
15601cb0ef41Sopenharmony_ci    // Failure: incorrect SNI context object
15611cb0ef41Sopenharmony_ci    Local<Value> err = Exception::TypeError(env->sni_context_err_string());
15621cb0ef41Sopenharmony_ci    w->MakeCallback(env->onerror_string(), 1, &err);
15631cb0ef41Sopenharmony_ci    return;
15641cb0ef41Sopenharmony_ci  }
15651cb0ef41Sopenharmony_ci
15661cb0ef41Sopenharmony_ci  CertCb cb;
15671cb0ef41Sopenharmony_ci  void* arg;
15681cb0ef41Sopenharmony_ci
15691cb0ef41Sopenharmony_ci  cb = w->cert_cb_;
15701cb0ef41Sopenharmony_ci  arg = w->cert_cb_arg_;
15711cb0ef41Sopenharmony_ci
15721cb0ef41Sopenharmony_ci  w->cert_cb_running_ = false;
15731cb0ef41Sopenharmony_ci  w->cert_cb_ = nullptr;
15741cb0ef41Sopenharmony_ci  w->cert_cb_arg_ = nullptr;
15751cb0ef41Sopenharmony_ci
15761cb0ef41Sopenharmony_ci  cb(arg);
15771cb0ef41Sopenharmony_ci}
15781cb0ef41Sopenharmony_ci
15791cb0ef41Sopenharmony_civoid TLSWrap::SetALPNProtocols(const FunctionCallbackInfo<Value>& args) {
15801cb0ef41Sopenharmony_ci  TLSWrap* w;
15811cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
15821cb0ef41Sopenharmony_ci  Environment* env = w->env();
15831cb0ef41Sopenharmony_ci  if (args.Length() < 1 || !Buffer::HasInstance(args[0]))
15841cb0ef41Sopenharmony_ci    return env->ThrowTypeError("Must give a Buffer as first argument");
15851cb0ef41Sopenharmony_ci
15861cb0ef41Sopenharmony_ci  ArrayBufferViewContents<uint8_t> protos(args[0].As<ArrayBufferView>());
15871cb0ef41Sopenharmony_ci  SSL* ssl = w->ssl_.get();
15881cb0ef41Sopenharmony_ci  if (w->is_client()) {
15891cb0ef41Sopenharmony_ci    CHECK_EQ(0, SSL_set_alpn_protos(ssl, protos.data(), protos.length()));
15901cb0ef41Sopenharmony_ci  } else {
15911cb0ef41Sopenharmony_ci    w->alpn_protos_ = std::vector<unsigned char>(
15921cb0ef41Sopenharmony_ci        protos.data(), protos.data() + protos.length());
15931cb0ef41Sopenharmony_ci    SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
15941cb0ef41Sopenharmony_ci    SSL_CTX_set_alpn_select_cb(ssl_ctx, SelectALPNCallback, nullptr);
15951cb0ef41Sopenharmony_ci  }
15961cb0ef41Sopenharmony_ci}
15971cb0ef41Sopenharmony_ci
15981cb0ef41Sopenharmony_civoid TLSWrap::GetPeerCertificate(const FunctionCallbackInfo<Value>& args) {
15991cb0ef41Sopenharmony_ci  TLSWrap* w;
16001cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
16011cb0ef41Sopenharmony_ci  Environment* env = w->env();
16021cb0ef41Sopenharmony_ci
16031cb0ef41Sopenharmony_ci  bool abbreviated = args.Length() < 1 || !args[0]->IsTrue();
16041cb0ef41Sopenharmony_ci
16051cb0ef41Sopenharmony_ci  Local<Value> ret;
16061cb0ef41Sopenharmony_ci  if (GetPeerCert(
16071cb0ef41Sopenharmony_ci          env,
16081cb0ef41Sopenharmony_ci          w->ssl_,
16091cb0ef41Sopenharmony_ci          abbreviated,
16101cb0ef41Sopenharmony_ci          w->is_server()).ToLocal(&ret))
16111cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(ret);
16121cb0ef41Sopenharmony_ci}
16131cb0ef41Sopenharmony_ci
16141cb0ef41Sopenharmony_civoid TLSWrap::GetPeerX509Certificate(const FunctionCallbackInfo<Value>& args) {
16151cb0ef41Sopenharmony_ci  TLSWrap* w;
16161cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
16171cb0ef41Sopenharmony_ci  Environment* env = w->env();
16181cb0ef41Sopenharmony_ci
16191cb0ef41Sopenharmony_ci  X509Certificate::GetPeerCertificateFlag flag = w->is_server()
16201cb0ef41Sopenharmony_ci      ? X509Certificate::GetPeerCertificateFlag::SERVER
16211cb0ef41Sopenharmony_ci      : X509Certificate::GetPeerCertificateFlag::NONE;
16221cb0ef41Sopenharmony_ci
16231cb0ef41Sopenharmony_ci  Local<Value> ret;
16241cb0ef41Sopenharmony_ci  if (X509Certificate::GetPeerCert(env, w->ssl_, flag).ToLocal(&ret))
16251cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(ret);
16261cb0ef41Sopenharmony_ci}
16271cb0ef41Sopenharmony_ci
16281cb0ef41Sopenharmony_civoid TLSWrap::GetCertificate(const FunctionCallbackInfo<Value>& args) {
16291cb0ef41Sopenharmony_ci  TLSWrap* w;
16301cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
16311cb0ef41Sopenharmony_ci  Environment* env = w->env();
16321cb0ef41Sopenharmony_ci
16331cb0ef41Sopenharmony_ci  Local<Value> ret;
16341cb0ef41Sopenharmony_ci  if (GetCert(env, w->ssl_).ToLocal(&ret))
16351cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(ret);
16361cb0ef41Sopenharmony_ci}
16371cb0ef41Sopenharmony_ci
16381cb0ef41Sopenharmony_civoid TLSWrap::GetX509Certificate(const FunctionCallbackInfo<Value>& args) {
16391cb0ef41Sopenharmony_ci  TLSWrap* w;
16401cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
16411cb0ef41Sopenharmony_ci  Environment* env = w->env();
16421cb0ef41Sopenharmony_ci  Local<Value> ret;
16431cb0ef41Sopenharmony_ci  if (X509Certificate::GetCert(env, w->ssl_).ToLocal(&ret))
16441cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(ret);
16451cb0ef41Sopenharmony_ci}
16461cb0ef41Sopenharmony_ci
16471cb0ef41Sopenharmony_civoid TLSWrap::GetFinished(const FunctionCallbackInfo<Value>& args) {
16481cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
16491cb0ef41Sopenharmony_ci
16501cb0ef41Sopenharmony_ci  TLSWrap* w;
16511cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
16521cb0ef41Sopenharmony_ci
16531cb0ef41Sopenharmony_ci  // We cannot just pass nullptr to SSL_get_finished()
16541cb0ef41Sopenharmony_ci  // because it would further be propagated to memcpy(),
16551cb0ef41Sopenharmony_ci  // where the standard requirements as described in ISO/IEC 9899:2011
16561cb0ef41Sopenharmony_ci  // sections 7.21.2.1, 7.21.1.2, and 7.1.4, would be violated.
16571cb0ef41Sopenharmony_ci  // Thus, we use a dummy byte.
16581cb0ef41Sopenharmony_ci  char dummy[1];
16591cb0ef41Sopenharmony_ci  size_t len = SSL_get_finished(w->ssl_.get(), dummy, sizeof dummy);
16601cb0ef41Sopenharmony_ci  if (len == 0)
16611cb0ef41Sopenharmony_ci    return;
16621cb0ef41Sopenharmony_ci
16631cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> bs;
16641cb0ef41Sopenharmony_ci  {
16651cb0ef41Sopenharmony_ci    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
16661cb0ef41Sopenharmony_ci    bs = ArrayBuffer::NewBackingStore(env->isolate(), len);
16671cb0ef41Sopenharmony_ci  }
16681cb0ef41Sopenharmony_ci
16691cb0ef41Sopenharmony_ci  CHECK_EQ(bs->ByteLength(),
16701cb0ef41Sopenharmony_ci           SSL_get_finished(w->ssl_.get(), bs->Data(), bs->ByteLength()));
16711cb0ef41Sopenharmony_ci
16721cb0ef41Sopenharmony_ci  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
16731cb0ef41Sopenharmony_ci  Local<Value> buffer;
16741cb0ef41Sopenharmony_ci  if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return;
16751cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(buffer);
16761cb0ef41Sopenharmony_ci}
16771cb0ef41Sopenharmony_ci
16781cb0ef41Sopenharmony_civoid TLSWrap::GetPeerFinished(const FunctionCallbackInfo<Value>& args) {
16791cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
16801cb0ef41Sopenharmony_ci
16811cb0ef41Sopenharmony_ci  TLSWrap* w;
16821cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
16831cb0ef41Sopenharmony_ci
16841cb0ef41Sopenharmony_ci  // We cannot just pass nullptr to SSL_get_peer_finished()
16851cb0ef41Sopenharmony_ci  // because it would further be propagated to memcpy(),
16861cb0ef41Sopenharmony_ci  // where the standard requirements as described in ISO/IEC 9899:2011
16871cb0ef41Sopenharmony_ci  // sections 7.21.2.1, 7.21.1.2, and 7.1.4, would be violated.
16881cb0ef41Sopenharmony_ci  // Thus, we use a dummy byte.
16891cb0ef41Sopenharmony_ci  char dummy[1];
16901cb0ef41Sopenharmony_ci  size_t len = SSL_get_peer_finished(w->ssl_.get(), dummy, sizeof dummy);
16911cb0ef41Sopenharmony_ci  if (len == 0)
16921cb0ef41Sopenharmony_ci    return;
16931cb0ef41Sopenharmony_ci
16941cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> bs;
16951cb0ef41Sopenharmony_ci  {
16961cb0ef41Sopenharmony_ci    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
16971cb0ef41Sopenharmony_ci    bs = ArrayBuffer::NewBackingStore(env->isolate(), len);
16981cb0ef41Sopenharmony_ci  }
16991cb0ef41Sopenharmony_ci
17001cb0ef41Sopenharmony_ci  CHECK_EQ(bs->ByteLength(),
17011cb0ef41Sopenharmony_ci           SSL_get_peer_finished(w->ssl_.get(), bs->Data(), bs->ByteLength()));
17021cb0ef41Sopenharmony_ci
17031cb0ef41Sopenharmony_ci  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
17041cb0ef41Sopenharmony_ci  Local<Value> buffer;
17051cb0ef41Sopenharmony_ci  if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return;
17061cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(buffer);
17071cb0ef41Sopenharmony_ci}
17081cb0ef41Sopenharmony_ci
17091cb0ef41Sopenharmony_civoid TLSWrap::GetSession(const FunctionCallbackInfo<Value>& args) {
17101cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
17111cb0ef41Sopenharmony_ci
17121cb0ef41Sopenharmony_ci  TLSWrap* w;
17131cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
17141cb0ef41Sopenharmony_ci
17151cb0ef41Sopenharmony_ci  SSL_SESSION* sess = SSL_get_session(w->ssl_.get());
17161cb0ef41Sopenharmony_ci  if (sess == nullptr)
17171cb0ef41Sopenharmony_ci    return;
17181cb0ef41Sopenharmony_ci
17191cb0ef41Sopenharmony_ci  int slen = i2d_SSL_SESSION(sess, nullptr);
17201cb0ef41Sopenharmony_ci  if (slen <= 0)
17211cb0ef41Sopenharmony_ci    return;  // Invalid or malformed session.
17221cb0ef41Sopenharmony_ci
17231cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> bs;
17241cb0ef41Sopenharmony_ci  {
17251cb0ef41Sopenharmony_ci    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
17261cb0ef41Sopenharmony_ci    bs = ArrayBuffer::NewBackingStore(env->isolate(), slen);
17271cb0ef41Sopenharmony_ci  }
17281cb0ef41Sopenharmony_ci
17291cb0ef41Sopenharmony_ci  unsigned char* p = static_cast<unsigned char*>(bs->Data());
17301cb0ef41Sopenharmony_ci  CHECK_LT(0, i2d_SSL_SESSION(sess, &p));
17311cb0ef41Sopenharmony_ci
17321cb0ef41Sopenharmony_ci  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
17331cb0ef41Sopenharmony_ci  Local<Value> buffer;
17341cb0ef41Sopenharmony_ci  if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return;
17351cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(buffer);
17361cb0ef41Sopenharmony_ci}
17371cb0ef41Sopenharmony_ci
17381cb0ef41Sopenharmony_civoid TLSWrap::SetSession(const FunctionCallbackInfo<Value>& args) {
17391cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
17401cb0ef41Sopenharmony_ci
17411cb0ef41Sopenharmony_ci  TLSWrap* w;
17421cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
17431cb0ef41Sopenharmony_ci
17441cb0ef41Sopenharmony_ci  if (args.Length() < 1)
17451cb0ef41Sopenharmony_ci    return THROW_ERR_MISSING_ARGS(env, "Session argument is mandatory");
17461cb0ef41Sopenharmony_ci
17471cb0ef41Sopenharmony_ci  THROW_AND_RETURN_IF_NOT_BUFFER(env, args[0], "Session");
17481cb0ef41Sopenharmony_ci  ArrayBufferViewContents<unsigned char> sbuf(args[0]);
17491cb0ef41Sopenharmony_ci  SSLSessionPointer sess = GetTLSSession(sbuf.data(), sbuf.length());
17501cb0ef41Sopenharmony_ci  if (sess == nullptr)
17511cb0ef41Sopenharmony_ci    return;  // TODO(tniessen): figure out error handling
17521cb0ef41Sopenharmony_ci
17531cb0ef41Sopenharmony_ci  if (!SetTLSSession(w->ssl_, sess))
17541cb0ef41Sopenharmony_ci    return env->ThrowError("SSL_set_session error");
17551cb0ef41Sopenharmony_ci}
17561cb0ef41Sopenharmony_ci
17571cb0ef41Sopenharmony_civoid TLSWrap::IsSessionReused(const FunctionCallbackInfo<Value>& args) {
17581cb0ef41Sopenharmony_ci  TLSWrap* w;
17591cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
17601cb0ef41Sopenharmony_ci  bool yes = SSL_session_reused(w->ssl_.get());
17611cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(yes);
17621cb0ef41Sopenharmony_ci}
17631cb0ef41Sopenharmony_ci
17641cb0ef41Sopenharmony_civoid TLSWrap::VerifyError(const FunctionCallbackInfo<Value>& args) {
17651cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
17661cb0ef41Sopenharmony_ci  TLSWrap* w;
17671cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
17681cb0ef41Sopenharmony_ci
17691cb0ef41Sopenharmony_ci  // XXX(bnoordhuis) The UNABLE_TO_GET_ISSUER_CERT error when there is no
17701cb0ef41Sopenharmony_ci  // peer certificate is questionable but it's compatible with what was
17711cb0ef41Sopenharmony_ci  // here before.
17721cb0ef41Sopenharmony_ci  long x509_verify_error =  // NOLINT(runtime/int)
17731cb0ef41Sopenharmony_ci      VerifyPeerCertificate(
17741cb0ef41Sopenharmony_ci          w->ssl_,
17751cb0ef41Sopenharmony_ci          X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
17761cb0ef41Sopenharmony_ci
17771cb0ef41Sopenharmony_ci  if (x509_verify_error == X509_V_OK)
17781cb0ef41Sopenharmony_ci    return args.GetReturnValue().SetNull();
17791cb0ef41Sopenharmony_ci
17801cb0ef41Sopenharmony_ci  const char* reason = X509_verify_cert_error_string(x509_verify_error);
17811cb0ef41Sopenharmony_ci  const char* code = X509ErrorCode(x509_verify_error);
17821cb0ef41Sopenharmony_ci
17831cb0ef41Sopenharmony_ci  Local<Object> error =
17841cb0ef41Sopenharmony_ci      Exception::Error(OneByteString(env->isolate(), reason))
17851cb0ef41Sopenharmony_ci          ->ToObject(env->isolate()->GetCurrentContext())
17861cb0ef41Sopenharmony_ci              .FromMaybe(Local<Object>());
17871cb0ef41Sopenharmony_ci
17881cb0ef41Sopenharmony_ci  if (Set(env, error, env->code_string(), code))
17891cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(error);
17901cb0ef41Sopenharmony_ci}
17911cb0ef41Sopenharmony_ci
17921cb0ef41Sopenharmony_civoid TLSWrap::GetCipher(const FunctionCallbackInfo<Value>& args) {
17931cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
17941cb0ef41Sopenharmony_ci  TLSWrap* w;
17951cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
17961cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
17971cb0ef41Sopenharmony_ci      GetCipherInfo(env, w->ssl_).FromMaybe(Local<Object>()));
17981cb0ef41Sopenharmony_ci}
17991cb0ef41Sopenharmony_ci
18001cb0ef41Sopenharmony_civoid TLSWrap::LoadSession(const FunctionCallbackInfo<Value>& args) {
18011cb0ef41Sopenharmony_ci  TLSWrap* w;
18021cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
18031cb0ef41Sopenharmony_ci
18041cb0ef41Sopenharmony_ci  // TODO(@sam-github) check arg length and types in js, and CHECK in c++
18051cb0ef41Sopenharmony_ci  if (args.Length() >= 1 && Buffer::HasInstance(args[0])) {
18061cb0ef41Sopenharmony_ci    ArrayBufferViewContents<unsigned char> sbuf(args[0]);
18071cb0ef41Sopenharmony_ci
18081cb0ef41Sopenharmony_ci    const unsigned char* p = sbuf.data();
18091cb0ef41Sopenharmony_ci    SSL_SESSION* sess = d2i_SSL_SESSION(nullptr, &p, sbuf.length());
18101cb0ef41Sopenharmony_ci
18111cb0ef41Sopenharmony_ci    // Setup next session and move hello to the BIO buffer
18121cb0ef41Sopenharmony_ci    w->next_sess_.reset(sess);
18131cb0ef41Sopenharmony_ci  }
18141cb0ef41Sopenharmony_ci}
18151cb0ef41Sopenharmony_ci
18161cb0ef41Sopenharmony_civoid TLSWrap::GetSharedSigalgs(const FunctionCallbackInfo<Value>& args) {
18171cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
18181cb0ef41Sopenharmony_ci  TLSWrap* w;
18191cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
18201cb0ef41Sopenharmony_ci
18211cb0ef41Sopenharmony_ci  SSL* ssl = w->ssl_.get();
18221cb0ef41Sopenharmony_ci  int nsig = SSL_get_shared_sigalgs(ssl, 0, nullptr, nullptr, nullptr, nullptr,
18231cb0ef41Sopenharmony_ci                                    nullptr);
18241cb0ef41Sopenharmony_ci  MaybeStackBuffer<Local<Value>, 16> ret_arr(nsig);
18251cb0ef41Sopenharmony_ci
18261cb0ef41Sopenharmony_ci  for (int i = 0; i < nsig; i++) {
18271cb0ef41Sopenharmony_ci    int hash_nid;
18281cb0ef41Sopenharmony_ci    int sign_nid;
18291cb0ef41Sopenharmony_ci    std::string sig_with_md;
18301cb0ef41Sopenharmony_ci
18311cb0ef41Sopenharmony_ci    SSL_get_shared_sigalgs(ssl, i, &sign_nid, &hash_nid, nullptr, nullptr,
18321cb0ef41Sopenharmony_ci                           nullptr);
18331cb0ef41Sopenharmony_ci
18341cb0ef41Sopenharmony_ci    switch (sign_nid) {
18351cb0ef41Sopenharmony_ci      case EVP_PKEY_RSA:
18361cb0ef41Sopenharmony_ci        sig_with_md = "RSA+";
18371cb0ef41Sopenharmony_ci        break;
18381cb0ef41Sopenharmony_ci
18391cb0ef41Sopenharmony_ci      case EVP_PKEY_RSA_PSS:
18401cb0ef41Sopenharmony_ci        sig_with_md = "RSA-PSS+";
18411cb0ef41Sopenharmony_ci        break;
18421cb0ef41Sopenharmony_ci
18431cb0ef41Sopenharmony_ci      case EVP_PKEY_DSA:
18441cb0ef41Sopenharmony_ci        sig_with_md = "DSA+";
18451cb0ef41Sopenharmony_ci        break;
18461cb0ef41Sopenharmony_ci
18471cb0ef41Sopenharmony_ci      case EVP_PKEY_EC:
18481cb0ef41Sopenharmony_ci        sig_with_md = "ECDSA+";
18491cb0ef41Sopenharmony_ci        break;
18501cb0ef41Sopenharmony_ci
18511cb0ef41Sopenharmony_ci      case NID_ED25519:
18521cb0ef41Sopenharmony_ci        sig_with_md = "Ed25519+";
18531cb0ef41Sopenharmony_ci        break;
18541cb0ef41Sopenharmony_ci
18551cb0ef41Sopenharmony_ci      case NID_ED448:
18561cb0ef41Sopenharmony_ci        sig_with_md = "Ed448+";
18571cb0ef41Sopenharmony_ci        break;
18581cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_GOST
18591cb0ef41Sopenharmony_ci      case NID_id_GostR3410_2001:
18601cb0ef41Sopenharmony_ci        sig_with_md = "gost2001+";
18611cb0ef41Sopenharmony_ci        break;
18621cb0ef41Sopenharmony_ci
18631cb0ef41Sopenharmony_ci      case NID_id_GostR3410_2012_256:
18641cb0ef41Sopenharmony_ci        sig_with_md = "gost2012_256+";
18651cb0ef41Sopenharmony_ci        break;
18661cb0ef41Sopenharmony_ci
18671cb0ef41Sopenharmony_ci      case NID_id_GostR3410_2012_512:
18681cb0ef41Sopenharmony_ci        sig_with_md = "gost2012_512+";
18691cb0ef41Sopenharmony_ci        break;
18701cb0ef41Sopenharmony_ci#endif  // !OPENSSL_NO_GOST
18711cb0ef41Sopenharmony_ci      default:
18721cb0ef41Sopenharmony_ci        const char* sn = OBJ_nid2sn(sign_nid);
18731cb0ef41Sopenharmony_ci
18741cb0ef41Sopenharmony_ci        if (sn != nullptr) {
18751cb0ef41Sopenharmony_ci          sig_with_md = std::string(sn) + "+";
18761cb0ef41Sopenharmony_ci        } else {
18771cb0ef41Sopenharmony_ci          sig_with_md = "UNDEF+";
18781cb0ef41Sopenharmony_ci        }
18791cb0ef41Sopenharmony_ci        break;
18801cb0ef41Sopenharmony_ci    }
18811cb0ef41Sopenharmony_ci
18821cb0ef41Sopenharmony_ci    const char* sn_hash = OBJ_nid2sn(hash_nid);
18831cb0ef41Sopenharmony_ci    if (sn_hash != nullptr) {
18841cb0ef41Sopenharmony_ci      sig_with_md += std::string(sn_hash);
18851cb0ef41Sopenharmony_ci    } else {
18861cb0ef41Sopenharmony_ci      sig_with_md += "UNDEF";
18871cb0ef41Sopenharmony_ci    }
18881cb0ef41Sopenharmony_ci    ret_arr[i] = OneByteString(env->isolate(), sig_with_md.c_str());
18891cb0ef41Sopenharmony_ci  }
18901cb0ef41Sopenharmony_ci
18911cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
18921cb0ef41Sopenharmony_ci                 Array::New(env->isolate(), ret_arr.out(), ret_arr.length()));
18931cb0ef41Sopenharmony_ci}
18941cb0ef41Sopenharmony_ci
18951cb0ef41Sopenharmony_civoid TLSWrap::ExportKeyingMaterial(const FunctionCallbackInfo<Value>& args) {
18961cb0ef41Sopenharmony_ci  CHECK(args[0]->IsInt32());
18971cb0ef41Sopenharmony_ci  CHECK(args[1]->IsString());
18981cb0ef41Sopenharmony_ci
18991cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
19001cb0ef41Sopenharmony_ci  TLSWrap* w;
19011cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
19021cb0ef41Sopenharmony_ci
19031cb0ef41Sopenharmony_ci  uint32_t olen = args[0].As<Uint32>()->Value();
19041cb0ef41Sopenharmony_ci  Utf8Value label(env->isolate(), args[1]);
19051cb0ef41Sopenharmony_ci
19061cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> bs;
19071cb0ef41Sopenharmony_ci  {
19081cb0ef41Sopenharmony_ci    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
19091cb0ef41Sopenharmony_ci    bs = ArrayBuffer::NewBackingStore(env->isolate(), olen);
19101cb0ef41Sopenharmony_ci  }
19111cb0ef41Sopenharmony_ci
19121cb0ef41Sopenharmony_ci  ByteSource context;
19131cb0ef41Sopenharmony_ci  bool use_context = !args[2]->IsUndefined();
19141cb0ef41Sopenharmony_ci  if (use_context)
19151cb0ef41Sopenharmony_ci    context = ByteSource::FromBuffer(args[2]);
19161cb0ef41Sopenharmony_ci
19171cb0ef41Sopenharmony_ci  if (SSL_export_keying_material(
19181cb0ef41Sopenharmony_ci          w->ssl_.get(),
19191cb0ef41Sopenharmony_ci          static_cast<unsigned char*>(bs->Data()),
19201cb0ef41Sopenharmony_ci          olen,
19211cb0ef41Sopenharmony_ci          *label,
19221cb0ef41Sopenharmony_ci          label.length(),
19231cb0ef41Sopenharmony_ci          context.data<unsigned char>(),
19241cb0ef41Sopenharmony_ci          context.size(),
19251cb0ef41Sopenharmony_ci          use_context) != 1) {
19261cb0ef41Sopenharmony_ci    return ThrowCryptoError(
19271cb0ef41Sopenharmony_ci         env,
19281cb0ef41Sopenharmony_ci         ERR_get_error(),
19291cb0ef41Sopenharmony_ci         "SSL_export_keying_material");
19301cb0ef41Sopenharmony_ci  }
19311cb0ef41Sopenharmony_ci
19321cb0ef41Sopenharmony_ci  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
19331cb0ef41Sopenharmony_ci  Local<Value> buffer;
19341cb0ef41Sopenharmony_ci  if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&buffer)) return;
19351cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(buffer);
19361cb0ef41Sopenharmony_ci}
19371cb0ef41Sopenharmony_ci
19381cb0ef41Sopenharmony_civoid TLSWrap::EndParser(const FunctionCallbackInfo<Value>& args) {
19391cb0ef41Sopenharmony_ci  TLSWrap* w;
19401cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
19411cb0ef41Sopenharmony_ci  w->hello_parser_.End();
19421cb0ef41Sopenharmony_ci}
19431cb0ef41Sopenharmony_ci
19441cb0ef41Sopenharmony_civoid TLSWrap::Renegotiate(const FunctionCallbackInfo<Value>& args) {
19451cb0ef41Sopenharmony_ci  TLSWrap* w;
19461cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
19471cb0ef41Sopenharmony_ci  ClearErrorOnReturn clear_error_on_return;
19481cb0ef41Sopenharmony_ci  if (SSL_renegotiate(w->ssl_.get()) != 1)
19491cb0ef41Sopenharmony_ci    return ThrowCryptoError(w->env(), ERR_get_error());
19501cb0ef41Sopenharmony_ci}
19511cb0ef41Sopenharmony_ci
19521cb0ef41Sopenharmony_civoid TLSWrap::GetTLSTicket(const FunctionCallbackInfo<Value>& args) {
19531cb0ef41Sopenharmony_ci  TLSWrap* w;
19541cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
19551cb0ef41Sopenharmony_ci  Environment* env = w->env();
19561cb0ef41Sopenharmony_ci
19571cb0ef41Sopenharmony_ci  SSL_SESSION* sess = SSL_get_session(w->ssl_.get());
19581cb0ef41Sopenharmony_ci  if (sess == nullptr)
19591cb0ef41Sopenharmony_ci    return;
19601cb0ef41Sopenharmony_ci
19611cb0ef41Sopenharmony_ci  const unsigned char* ticket;
19621cb0ef41Sopenharmony_ci  size_t length;
19631cb0ef41Sopenharmony_ci  SSL_SESSION_get0_ticket(sess, &ticket, &length);
19641cb0ef41Sopenharmony_ci
19651cb0ef41Sopenharmony_ci  if (ticket != nullptr) {
19661cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(
19671cb0ef41Sopenharmony_ci        Buffer::Copy(env, reinterpret_cast<const char*>(ticket), length)
19681cb0ef41Sopenharmony_ci            .FromMaybe(Local<Object>()));
19691cb0ef41Sopenharmony_ci  }
19701cb0ef41Sopenharmony_ci}
19711cb0ef41Sopenharmony_ci
19721cb0ef41Sopenharmony_civoid TLSWrap::NewSessionDone(const FunctionCallbackInfo<Value>& args) {
19731cb0ef41Sopenharmony_ci  TLSWrap* w;
19741cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
19751cb0ef41Sopenharmony_ci  w->awaiting_new_session_ = false;
19761cb0ef41Sopenharmony_ci  w->NewSessionDoneCb();
19771cb0ef41Sopenharmony_ci}
19781cb0ef41Sopenharmony_ci
19791cb0ef41Sopenharmony_civoid TLSWrap::SetOCSPResponse(const FunctionCallbackInfo<Value>& args) {
19801cb0ef41Sopenharmony_ci  TLSWrap* w;
19811cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
19821cb0ef41Sopenharmony_ci  Environment* env = w->env();
19831cb0ef41Sopenharmony_ci
19841cb0ef41Sopenharmony_ci  if (args.Length() < 1)
19851cb0ef41Sopenharmony_ci    return THROW_ERR_MISSING_ARGS(env, "OCSP response argument is mandatory");
19861cb0ef41Sopenharmony_ci
19871cb0ef41Sopenharmony_ci  THROW_AND_RETURN_IF_NOT_BUFFER(env, args[0], "OCSP response");
19881cb0ef41Sopenharmony_ci
19891cb0ef41Sopenharmony_ci  w->ocsp_response_.Reset(args.GetIsolate(), args[0].As<ArrayBufferView>());
19901cb0ef41Sopenharmony_ci}
19911cb0ef41Sopenharmony_ci
19921cb0ef41Sopenharmony_civoid TLSWrap::RequestOCSP(const FunctionCallbackInfo<Value>& args) {
19931cb0ef41Sopenharmony_ci  TLSWrap* w;
19941cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
19951cb0ef41Sopenharmony_ci
19961cb0ef41Sopenharmony_ci  SSL_set_tlsext_status_type(w->ssl_.get(), TLSEXT_STATUSTYPE_ocsp);
19971cb0ef41Sopenharmony_ci}
19981cb0ef41Sopenharmony_ci
19991cb0ef41Sopenharmony_civoid TLSWrap::GetEphemeralKeyInfo(const FunctionCallbackInfo<Value>& args) {
20001cb0ef41Sopenharmony_ci  TLSWrap* w;
20011cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
20021cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
20031cb0ef41Sopenharmony_ci
20041cb0ef41Sopenharmony_ci  CHECK(w->ssl_);
20051cb0ef41Sopenharmony_ci
20061cb0ef41Sopenharmony_ci  // tmp key is available on only client
20071cb0ef41Sopenharmony_ci  if (w->is_server())
20081cb0ef41Sopenharmony_ci    return args.GetReturnValue().SetNull();
20091cb0ef41Sopenharmony_ci
20101cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(GetEphemeralKey(env, w->ssl_)
20111cb0ef41Sopenharmony_ci      .FromMaybe(Local<Value>()));
20121cb0ef41Sopenharmony_ci
20131cb0ef41Sopenharmony_ci  // TODO(@sam-github) semver-major: else return ThrowCryptoError(env,
20141cb0ef41Sopenharmony_ci  // ERR_get_error())
20151cb0ef41Sopenharmony_ci}
20161cb0ef41Sopenharmony_ci
20171cb0ef41Sopenharmony_civoid TLSWrap::GetProtocol(const FunctionCallbackInfo<Value>& args) {
20181cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
20191cb0ef41Sopenharmony_ci  TLSWrap* w;
20201cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
20211cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
20221cb0ef41Sopenharmony_ci      OneByteString(env->isolate(), SSL_get_version(w->ssl_.get())));
20231cb0ef41Sopenharmony_ci}
20241cb0ef41Sopenharmony_ci
20251cb0ef41Sopenharmony_civoid TLSWrap::GetALPNNegotiatedProto(const FunctionCallbackInfo<Value>& args) {
20261cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
20271cb0ef41Sopenharmony_ci  TLSWrap* w;
20281cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
20291cb0ef41Sopenharmony_ci
20301cb0ef41Sopenharmony_ci  const unsigned char* alpn_proto;
20311cb0ef41Sopenharmony_ci  unsigned int alpn_proto_len;
20321cb0ef41Sopenharmony_ci
20331cb0ef41Sopenharmony_ci  SSL_get0_alpn_selected(w->ssl_.get(), &alpn_proto, &alpn_proto_len);
20341cb0ef41Sopenharmony_ci
20351cb0ef41Sopenharmony_ci  Local<Value> result;
20361cb0ef41Sopenharmony_ci  if (alpn_proto_len == 0) {
20371cb0ef41Sopenharmony_ci    result = False(env->isolate());
20381cb0ef41Sopenharmony_ci  } else if (alpn_proto_len == sizeof("h2") - 1 &&
20391cb0ef41Sopenharmony_ci             0 == memcmp(alpn_proto, "h2", sizeof("h2") - 1)) {
20401cb0ef41Sopenharmony_ci    result = env->h2_string();
20411cb0ef41Sopenharmony_ci  } else if (alpn_proto_len == sizeof("http/1.1") - 1 &&
20421cb0ef41Sopenharmony_ci             0 == memcmp(alpn_proto, "http/1.1", sizeof("http/1.1") - 1)) {
20431cb0ef41Sopenharmony_ci    result = env->http_1_1_string();
20441cb0ef41Sopenharmony_ci  } else {
20451cb0ef41Sopenharmony_ci    result = OneByteString(env->isolate(), alpn_proto, alpn_proto_len);
20461cb0ef41Sopenharmony_ci  }
20471cb0ef41Sopenharmony_ci
20481cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(result);
20491cb0ef41Sopenharmony_ci}
20501cb0ef41Sopenharmony_ci
20511cb0ef41Sopenharmony_civoid TLSWrap::WritesIssuedByPrevListenerDone(
20521cb0ef41Sopenharmony_ci    const FunctionCallbackInfo<Value>& args) {
20531cb0ef41Sopenharmony_ci  TLSWrap* w;
20541cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
20551cb0ef41Sopenharmony_ci
20561cb0ef41Sopenharmony_ci  Debug(w, "WritesIssuedByPrevListenerDone is called");
20571cb0ef41Sopenharmony_ci  w->has_active_write_issued_by_prev_listener_ = false;
20581cb0ef41Sopenharmony_ci  w->EncOut();  // resume all of our restrained writes
20591cb0ef41Sopenharmony_ci}
20601cb0ef41Sopenharmony_ci
20611cb0ef41Sopenharmony_civoid TLSWrap::Cycle() {
20621cb0ef41Sopenharmony_ci  // Prevent recursion
20631cb0ef41Sopenharmony_ci  if (++cycle_depth_ > 1)
20641cb0ef41Sopenharmony_ci    return;
20651cb0ef41Sopenharmony_ci
20661cb0ef41Sopenharmony_ci  for (; cycle_depth_ > 0; cycle_depth_--) {
20671cb0ef41Sopenharmony_ci    ClearIn();
20681cb0ef41Sopenharmony_ci    ClearOut();
20691cb0ef41Sopenharmony_ci    // EncIn() doesn't exist, it happens via stream listener callbacks.
20701cb0ef41Sopenharmony_ci    EncOut();
20711cb0ef41Sopenharmony_ci  }
20721cb0ef41Sopenharmony_ci}
20731cb0ef41Sopenharmony_ci
20741cb0ef41Sopenharmony_ci#ifdef SSL_set_max_send_fragment
20751cb0ef41Sopenharmony_civoid TLSWrap::SetMaxSendFragment(const FunctionCallbackInfo<Value>& args) {
20761cb0ef41Sopenharmony_ci  CHECK(args.Length() >= 1 && args[0]->IsNumber());
20771cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
20781cb0ef41Sopenharmony_ci  TLSWrap* w;
20791cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
20801cb0ef41Sopenharmony_ci  int rv = SSL_set_max_send_fragment(
20811cb0ef41Sopenharmony_ci      w->ssl_.get(),
20821cb0ef41Sopenharmony_ci      args[0]->Int32Value(env->context()).FromJust());
20831cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(rv);
20841cb0ef41Sopenharmony_ci}
20851cb0ef41Sopenharmony_ci#endif  // SSL_set_max_send_fragment
20861cb0ef41Sopenharmony_ci
20871cb0ef41Sopenharmony_civoid TLSWrap::Initialize(
20881cb0ef41Sopenharmony_ci    Local<Object> target,
20891cb0ef41Sopenharmony_ci    Local<Value> unused,
20901cb0ef41Sopenharmony_ci    Local<Context> context,
20911cb0ef41Sopenharmony_ci    void* priv) {
20921cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(context);
20931cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
20941cb0ef41Sopenharmony_ci
20951cb0ef41Sopenharmony_ci  SetMethod(context, target, "wrap", TLSWrap::Wrap);
20961cb0ef41Sopenharmony_ci
20971cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(target, HAVE_SSL_TRACE);
20981cb0ef41Sopenharmony_ci
20991cb0ef41Sopenharmony_ci  Local<FunctionTemplate> t = BaseObject::MakeLazilyInitializedJSTemplate(env);
21001cb0ef41Sopenharmony_ci  Local<String> tlsWrapString =
21011cb0ef41Sopenharmony_ci      FIXED_ONE_BYTE_STRING(env->isolate(), "TLSWrap");
21021cb0ef41Sopenharmony_ci  t->SetClassName(tlsWrapString);
21031cb0ef41Sopenharmony_ci  t->InstanceTemplate()->SetInternalFieldCount(StreamBase::kInternalFieldCount);
21041cb0ef41Sopenharmony_ci
21051cb0ef41Sopenharmony_ci  Local<FunctionTemplate> get_write_queue_size =
21061cb0ef41Sopenharmony_ci      FunctionTemplate::New(env->isolate(),
21071cb0ef41Sopenharmony_ci                            GetWriteQueueSize,
21081cb0ef41Sopenharmony_ci                            Local<Value>(),
21091cb0ef41Sopenharmony_ci                            Signature::New(env->isolate(), t));
21101cb0ef41Sopenharmony_ci  t->PrototypeTemplate()->SetAccessorProperty(
21111cb0ef41Sopenharmony_ci      env->write_queue_size_string(),
21121cb0ef41Sopenharmony_ci      get_write_queue_size,
21131cb0ef41Sopenharmony_ci      Local<FunctionTemplate>(),
21141cb0ef41Sopenharmony_ci      static_cast<PropertyAttribute>(ReadOnly | DontDelete));
21151cb0ef41Sopenharmony_ci
21161cb0ef41Sopenharmony_ci  t->Inherit(AsyncWrap::GetConstructorTemplate(env));
21171cb0ef41Sopenharmony_ci
21181cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "certCbDone", CertCbDone);
21191cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "destroySSL", DestroySSL);
21201cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "enableCertCb", EnableCertCb);
21211cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "enableALPNCb", EnableALPNCb);
21221cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "endParser", EndParser);
21231cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "enableKeylogCallback", EnableKeylogCallback);
21241cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "enableSessionCallbacks", EnableSessionCallbacks);
21251cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "enableTrace", EnableTrace);
21261cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "getServername", GetServername);
21271cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "loadSession", LoadSession);
21281cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "newSessionDone", NewSessionDone);
21291cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "receive", Receive);
21301cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "renegotiate", Renegotiate);
21311cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "requestOCSP", RequestOCSP);
21321cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setALPNProtocols", SetALPNProtocols);
21331cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setOCSPResponse", SetOCSPResponse);
21341cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setServername", SetServername);
21351cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setSession", SetSession);
21361cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setVerifyMode", SetVerifyMode);
21371cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "start", Start);
21381cb0ef41Sopenharmony_ci  SetProtoMethod(isolate,
21391cb0ef41Sopenharmony_ci                 t,
21401cb0ef41Sopenharmony_ci                 "writesIssuedByPrevListenerDone",
21411cb0ef41Sopenharmony_ci                 WritesIssuedByPrevListenerDone);
21421cb0ef41Sopenharmony_ci
21431cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(
21441cb0ef41Sopenharmony_ci      isolate, t, "exportKeyingMaterial", ExportKeyingMaterial);
21451cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "isSessionReused", IsSessionReused);
21461cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(
21471cb0ef41Sopenharmony_ci      isolate, t, "getALPNNegotiatedProtocol", GetALPNNegotiatedProto);
21481cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getCertificate", GetCertificate);
21491cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(
21501cb0ef41Sopenharmony_ci      isolate, t, "getX509Certificate", GetX509Certificate);
21511cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getCipher", GetCipher);
21521cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(
21531cb0ef41Sopenharmony_ci      isolate, t, "getEphemeralKeyInfo", GetEphemeralKeyInfo);
21541cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getFinished", GetFinished);
21551cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(
21561cb0ef41Sopenharmony_ci      isolate, t, "getPeerCertificate", GetPeerCertificate);
21571cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(
21581cb0ef41Sopenharmony_ci      isolate, t, "getPeerX509Certificate", GetPeerX509Certificate);
21591cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getPeerFinished", GetPeerFinished);
21601cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getProtocol", GetProtocol);
21611cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getSession", GetSession);
21621cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getSharedSigalgs", GetSharedSigalgs);
21631cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "getTLSTicket", GetTLSTicket);
21641cb0ef41Sopenharmony_ci  SetProtoMethodNoSideEffect(isolate, t, "verifyError", VerifyError);
21651cb0ef41Sopenharmony_ci
21661cb0ef41Sopenharmony_ci#ifdef SSL_set_max_send_fragment
21671cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setMaxSendFragment", SetMaxSendFragment);
21681cb0ef41Sopenharmony_ci#endif  // SSL_set_max_send_fragment
21691cb0ef41Sopenharmony_ci
21701cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_PSK
21711cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "enablePskCallback", EnablePskCallback);
21721cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "setPskIdentityHint", SetPskIdentityHint);
21731cb0ef41Sopenharmony_ci#endif  // !OPENSSL_NO_PSK
21741cb0ef41Sopenharmony_ci
21751cb0ef41Sopenharmony_ci  StreamBase::AddMethods(env, t);
21761cb0ef41Sopenharmony_ci
21771cb0ef41Sopenharmony_ci  Local<Function> fn = t->GetFunction(env->context()).ToLocalChecked();
21781cb0ef41Sopenharmony_ci
21791cb0ef41Sopenharmony_ci  env->set_tls_wrap_constructor_function(fn);
21801cb0ef41Sopenharmony_ci
21811cb0ef41Sopenharmony_ci  target->Set(env->context(), tlsWrapString, fn).Check();
21821cb0ef41Sopenharmony_ci}
21831cb0ef41Sopenharmony_ci
21841cb0ef41Sopenharmony_civoid TLSWrap::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
21851cb0ef41Sopenharmony_ci  registry->Register(TLSWrap::Wrap);
21861cb0ef41Sopenharmony_ci  registry->Register(GetWriteQueueSize);
21871cb0ef41Sopenharmony_ci
21881cb0ef41Sopenharmony_ci  registry->Register(CertCbDone);
21891cb0ef41Sopenharmony_ci  registry->Register(DestroySSL);
21901cb0ef41Sopenharmony_ci  registry->Register(EnableCertCb);
21911cb0ef41Sopenharmony_ci  registry->Register(EnableALPNCb);
21921cb0ef41Sopenharmony_ci  registry->Register(EndParser);
21931cb0ef41Sopenharmony_ci  registry->Register(EnableKeylogCallback);
21941cb0ef41Sopenharmony_ci  registry->Register(EnableSessionCallbacks);
21951cb0ef41Sopenharmony_ci  registry->Register(EnableTrace);
21961cb0ef41Sopenharmony_ci  registry->Register(GetServername);
21971cb0ef41Sopenharmony_ci  registry->Register(LoadSession);
21981cb0ef41Sopenharmony_ci  registry->Register(NewSessionDone);
21991cb0ef41Sopenharmony_ci  registry->Register(Receive);
22001cb0ef41Sopenharmony_ci  registry->Register(Renegotiate);
22011cb0ef41Sopenharmony_ci  registry->Register(RequestOCSP);
22021cb0ef41Sopenharmony_ci  registry->Register(SetALPNProtocols);
22031cb0ef41Sopenharmony_ci  registry->Register(SetOCSPResponse);
22041cb0ef41Sopenharmony_ci  registry->Register(SetServername);
22051cb0ef41Sopenharmony_ci  registry->Register(SetSession);
22061cb0ef41Sopenharmony_ci  registry->Register(SetVerifyMode);
22071cb0ef41Sopenharmony_ci  registry->Register(Start);
22081cb0ef41Sopenharmony_ci  registry->Register(ExportKeyingMaterial);
22091cb0ef41Sopenharmony_ci  registry->Register(IsSessionReused);
22101cb0ef41Sopenharmony_ci  registry->Register(GetALPNNegotiatedProto);
22111cb0ef41Sopenharmony_ci  registry->Register(GetCertificate);
22121cb0ef41Sopenharmony_ci  registry->Register(GetX509Certificate);
22131cb0ef41Sopenharmony_ci  registry->Register(GetCipher);
22141cb0ef41Sopenharmony_ci  registry->Register(GetEphemeralKeyInfo);
22151cb0ef41Sopenharmony_ci  registry->Register(GetFinished);
22161cb0ef41Sopenharmony_ci  registry->Register(GetPeerCertificate);
22171cb0ef41Sopenharmony_ci  registry->Register(GetPeerX509Certificate);
22181cb0ef41Sopenharmony_ci  registry->Register(GetPeerFinished);
22191cb0ef41Sopenharmony_ci  registry->Register(GetProtocol);
22201cb0ef41Sopenharmony_ci  registry->Register(GetSession);
22211cb0ef41Sopenharmony_ci  registry->Register(GetSharedSigalgs);
22221cb0ef41Sopenharmony_ci  registry->Register(GetTLSTicket);
22231cb0ef41Sopenharmony_ci  registry->Register(VerifyError);
22241cb0ef41Sopenharmony_ci  registry->Register(WritesIssuedByPrevListenerDone);
22251cb0ef41Sopenharmony_ci
22261cb0ef41Sopenharmony_ci#ifdef SSL_set_max_send_fragment
22271cb0ef41Sopenharmony_ci  registry->Register(SetMaxSendFragment);
22281cb0ef41Sopenharmony_ci#endif  // SSL_set_max_send_fragment
22291cb0ef41Sopenharmony_ci
22301cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_PSK
22311cb0ef41Sopenharmony_ci  registry->Register(EnablePskCallback);
22321cb0ef41Sopenharmony_ci  registry->Register(SetPskIdentityHint);
22331cb0ef41Sopenharmony_ci#endif  // !OPENSSL_NO_PSK
22341cb0ef41Sopenharmony_ci}
22351cb0ef41Sopenharmony_ci
22361cb0ef41Sopenharmony_ci}  // namespace crypto
22371cb0ef41Sopenharmony_ci}  // namespace node
22381cb0ef41Sopenharmony_ci
22391cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(tls_wrap, node::crypto::TLSWrap::Initialize)
22401cb0ef41Sopenharmony_ciNODE_BINDING_EXTERNAL_REFERENCE(
22411cb0ef41Sopenharmony_ci    tls_wrap, node::crypto::TLSWrap::RegisterExternalReferences)
2242