From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Wed, 12 Feb 2020 15:08:04 -0800
Subject: fix: handle BoringSSL and OpenSSL incompatibilities

This patch corrects for imcompatibilities between OpenSSL, which Node.js uses,
and BoringSSL which Electron uses via Chromium. Each incompatibility typically has
~2 paths forward:
* Upstream a shim or adapted implementation to BoringSSL
* Alter Node.js functionality to something which both libraries can handle.

Where possible, we should seek to make this patch as minimal as possible.

Upstreams:
- https://github.com/nodejs/node/pull/39054
- https://github.com/nodejs/node/pull/39138
- https://github.com/nodejs/node/pull/39136

diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc
index 461819ce0fa732048e4365c40a86ef55d984c35f..f1c85e94cf526d0255f47c003664680d26413ec3 100644
--- a/deps/ncrypto/ncrypto.cc
+++ b/deps/ncrypto/ncrypto.cc
@@ -11,6 +11,7 @@
 #include <array>
 #include <cstring>
 #include <string_view>
+#include <vector>
 #if OPENSSL_VERSION_MAJOR >= 3
 #include <openssl/core_names.h>
 #include <openssl/params.h>
@@ -3090,9 +3091,11 @@ const Cipher Cipher::AES_256_GCM = Cipher::FromNid(NID_aes_256_gcm);
 const Cipher Cipher::AES_128_KW = Cipher::FromNid(NID_id_aes128_wrap);
 const Cipher Cipher::AES_192_KW = Cipher::FromNid(NID_id_aes192_wrap);
 const Cipher Cipher::AES_256_KW = Cipher::FromNid(NID_id_aes256_wrap);
+#ifndef OPENSSL_IS_BORINGSSL
 const Cipher Cipher::AES_128_OCB = Cipher::FromNid(NID_aes_128_ocb);
 const Cipher Cipher::AES_192_OCB = Cipher::FromNid(NID_aes_192_ocb);
 const Cipher Cipher::AES_256_OCB = Cipher::FromNid(NID_aes_256_ocb);
+#endif
 const Cipher Cipher::CHACHA20_POLY1305 = Cipher::FromNid(NID_chacha20_poly1305);
 
 bool Cipher::isGcmMode() const {
diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h
index 175ec8ba0f2a908ffad2ce48434aeed573b09c90..3218590ddce1e92c2a9d776f20f9fb016612061d 100644
--- a/deps/ncrypto/ncrypto.h
+++ b/deps/ncrypto/ncrypto.h
@@ -306,9 +306,13 @@ class Cipher final {
 #else
   static constexpr size_t MAX_AUTH_TAG_LENGTH = 16;
 #endif
-  static_assert(EVP_GCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH &&
-                EVP_CCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH &&
-                EVP_CHACHAPOLY_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH);
+  static_assert(EVP_GCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH
+#ifndef OPENSSL_IS_BORINGSSL
+                && EVP_CCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH
+                && EVP_CHACHAPOLY_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH);
+#else
+                );
+#endif
 
   Cipher() = default;
   Cipher(const EVP_CIPHER* cipher) : cipher_(cipher) {}
diff --git a/node.gni b/node.gni
index 156fee33b3813fe4d94a1c9585f217a99dbfbd5f..8239967653fee7791800ee3292e77b91bffaaef9 100644
--- a/node.gni
+++ b/node.gni
@@ -11,7 +11,7 @@ declare_args() {
   node_v8_path = "//v8"
 
   # The location of OpenSSL - use the one from node's deps by default.
-  node_openssl_path = "$node_path/deps/openssl"
+  node_openssl_path = "//third_party/boringssl"
 
   # The location of simdutf - use the one from node's deps by default.
   node_simdutf_path = "//third_party/simdutf"
diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc
index ed509e5c9fe79c5d545180fef0fea9ab6f1ba39b..9446314c95e57ea408568d107a9f6e76886650cb 100644
--- a/src/crypto/crypto_cipher.cc
+++ b/src/crypto/crypto_cipher.cc
@@ -447,6 +447,7 @@ bool CipherBase::InitAuthenticated(const char* cipher_type,
     }
   } else {
     if (auth_tag_len == kNoAuthTagLength) {
+#ifndef OPENSSL_IS_BORINGSSL
       // We treat ChaCha20-Poly1305 specially. Like GCM, the authentication tag
       // length defaults to 16 bytes when encrypting. Unlike GCM, the
       // authentication tag length also defaults to 16 bytes when decrypting,
@@ -458,6 +459,9 @@ bool CipherBase::InitAuthenticated(const char* cipher_type,
           env(), "authTagLength required for %s", cipher_type);
         return false;
       }
+#else
+      return false;
+#endif
     }
 
     // TODO(tniessen) Support CCM decryption in FIPS mode
diff --git a/src/crypto/crypto_common.cc b/src/crypto/crypto_common.cc
index d005bf0ffb93445fa6611a1beb1b465764271ede..01770687bd191c61af02e76d7de24bbac5c47b8f 100644
--- a/src/crypto/crypto_common.cc
+++ b/src/crypto/crypto_common.cc
@@ -90,7 +90,7 @@ StackOfX509 CloneSSLCerts(X509Pointer&& cert,
   if (!peer_certs) return StackOfX509();
   if (cert && !sk_X509_push(peer_certs.get(), cert.release()))
     return StackOfX509();
-  for (int i = 0; i < sk_X509_num(ssl_certs); i++) {
+  for (size_t i = 0; i < sk_X509_num(ssl_certs); i++) {
     X509Pointer cert(X509_dup(sk_X509_value(ssl_certs, i)));
     if (!cert || !sk_X509_push(peer_certs.get(), cert.get()))
       return StackOfX509();
@@ -106,7 +106,7 @@ MaybeLocal<Object> AddIssuerChainToObject(X509Pointer* cert,
                                           Environment* const env) {
   cert->reset(sk_X509_delete(peer_certs.get(), 0));
   for (;;) {
-    int i;
+    size_t i;
     for (i = 0; i < sk_X509_num(peer_certs.get()); i++) {
       X509View ca(sk_X509_value(peer_certs.get(), i));
       if (!cert->view().isIssuedBy(ca)) continue;
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
index 4e968477ebcc08fb0ccd6abd4d66240309cf76e8..2e3f31e1765024373c3fc2acd33fc3bfb352a906 100644
--- a/src/crypto/crypto_context.cc
+++ b/src/crypto/crypto_context.cc
@@ -143,7 +143,7 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
     // the CA certificates.
     SSL_CTX_clear_extra_chain_certs(ctx);
 
-    for (int i = 0; i < sk_X509_num(extra_certs); i++) {
+    for (size_t i = 0; i < sk_X509_num(extra_certs); i++) {
       X509* ca = sk_X509_value(extra_certs, i);
 
       // NOTE: Increments reference count on `ca`
@@ -1855,11 +1855,12 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
   // If the user specified "auto" for dhparams, the JavaScript layer will pass
   // true to this function instead of the original string. Any other string
   // value will be interpreted as custom DH parameters below.
+#ifndef OPENSSL_IS_BORINGSSL
   if (args[0]->IsTrue()) {
     CHECK(SSL_CTX_set_dh_auto(sc->ctx_.get(), true));
     return;
   }
-
+#endif
   DHPointer dh;
   {
     BIOPointer bio(LoadBIO(env, args[0]));
@@ -2085,7 +2086,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
   }
 
   // Add CA certs too
-  for (int i = 0; i < sk_X509_num(extra_certs.get()); i++) {
+  for (size_t i = 0; i < sk_X509_num(extra_certs.get()); i++) {
     X509* ca = sk_X509_value(extra_certs.get(), i);
 
     X509_STORE_add_cert(sc->GetCertStoreOwnedByThisSecureContext(), ca);
diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
index e35fda9ad2e8c52c75492d66566dc6e6c57dd2ae..46a7d1396dc1a175ae99f4e403721f1730fdd320 100644
--- a/src/crypto/crypto_dh.cc
+++ b/src/crypto/crypto_dh.cc
@@ -309,15 +309,17 @@ void ComputeSecret(const FunctionCallbackInfo<Value>& args) {
   BignumPointer key(key_buf.data(), key_buf.size());
 
   switch (dh.checkPublicKey(key)) {
-    case DHPointer::CheckPublicKeyResult::INVALID:
-      // Fall-through
     case DHPointer::CheckPublicKeyResult::CHECK_FAILED:
       return THROW_ERR_CRYPTO_INVALID_KEYTYPE(env,
                                               "Unspecified validation error");
+#ifndef OPENSSL_IS_BORINGSSL
     case DHPointer::CheckPublicKeyResult::TOO_SMALL:
       return THROW_ERR_CRYPTO_INVALID_KEYLEN(env, "Supplied key is too small");
     case DHPointer::CheckPublicKeyResult::TOO_LARGE:
       return THROW_ERR_CRYPTO_INVALID_KEYLEN(env, "Supplied key is too large");
+#endif
+    case DHPointer::CheckPublicKeyResult::INVALID:
+      return THROW_ERR_CRYPTO_INVALID_KEYTYPE(env, "Supplied key is invalid");
     case DHPointer::CheckPublicKeyResult::NONE:
       break;
   }
diff --git a/src/crypto/crypto_hash.cc b/src/crypto/crypto_hash.cc
index 33cde71b105c7cf22b559583d2e46bfb50016f6d..659910992dff7c05bb7e367e1cba14256b46dea4 100644
--- a/src/crypto/crypto_hash.cc
+++ b/src/crypto/crypto_hash.cc
@@ -232,7 +232,7 @@ void Hash::OneShotDigest(const FunctionCallbackInfo<Value>& args) {
   enum encoding output_enc = ParseEncoding(isolate, args[4], args[5], HEX);
 
   bool is_xof = (EVP_MD_flags(md) & EVP_MD_FLAG_XOF) != 0;
-  int output_length = EVP_MD_size(md);
+  size_t output_length = EVP_MD_size(md);
 
   // This is to cause hash() to fail when an incorrect
   // outputLength option was passed for a non-XOF hash function.
diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc
index e805a984322c8348ceba950fe6f45e002ade10b3..bb9b1f8e1b3c6dd8479ee463e303088e3240d6be 100644
--- a/src/crypto/crypto_keys.cc
+++ b/src/crypto/crypto_keys.cc
@@ -1034,6 +1034,7 @@ void KeyObjectHandle::GetAsymmetricKeyType(
 }
 
 bool KeyObjectHandle::CheckEcKeyData() const {
+#ifndef OPENSSL_IS_BORINGSSL
   MarkPopErrorOnReturn mark_pop_error_on_return;
 
   const auto& key = data_.GetAsymmetricKey();
@@ -1043,6 +1044,9 @@ bool KeyObjectHandle::CheckEcKeyData() const {
 
   return data_.GetKeyType() == kKeyTypePrivate ? ctx.privateCheck()
                                                : ctx.publicCheck();
+#else
+  return true;
+#endif
 }
 
 void KeyObjectHandle::CheckEcKeyData(const FunctionCallbackInfo<Value>& args) {
diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
index 205e248e0f20f019e189a6c69d3c011a616b3939..12b0d804c6f1d4998b85160b0aac8eb7a3b5576b 100644
--- a/src/crypto/crypto_util.cc
+++ b/src/crypto/crypto_util.cc
@@ -533,24 +533,15 @@ Maybe<void> Decorate(Environment* env,
     V(BIO)                                                                    \
     V(PKCS7)                                                                  \
     V(X509V3)                                                                 \
-    V(PKCS12)                                                                 \
     V(RAND)                                                                   \
-    V(DSO)                                                                    \
     V(ENGINE)                                                                 \
     V(OCSP)                                                                   \
     V(UI)                                                                     \
     V(COMP)                                                                   \
     V(ECDSA)                                                                  \
     V(ECDH)                                                                   \
-    V(OSSL_STORE)                                                             \
-    V(FIPS)                                                                   \
-    V(CMS)                                                                    \
-    V(TS)                                                                     \
     V(HMAC)                                                                   \
-    V(CT)                                                                     \
-    V(ASYNC)                                                                  \
-    V(KDF)                                                                    \
-    V(SM2)                                                                    \
+    V(HKDF)                                                                    \
     V(USER)                                                                   \
 
 #define V(name) case ERR_LIB_##name: lib = #name "_"; break;
diff --git a/src/env.h b/src/env.h
index 3ab33341806ad6c0b06b982a30a57b7b5399e38f..754ddf7b331465c56081db05d6fd2a45fe50596a 100644
--- a/src/env.h
+++ b/src/env.h
@@ -52,7 +52,7 @@
 #include "v8-profiler.h"
 #include "v8.h"
 
-#if HAVE_OPENSSL
+#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3
 #include <openssl/evp.h>
 #endif
 
@@ -1059,7 +1059,7 @@ class Environment final : public MemoryRetainer {
     kExitInfoFieldCount
   };
 
-#if HAVE_OPENSSL
+#if HAVE_OPENSSL// && !defined(OPENSSL_IS_BORINGSSL)
 #if OPENSSL_VERSION_MAJOR >= 3
   // We declare another alias here to avoid having to include crypto_util.h
   using EVPMDPointer = DeleteFnPtr<EVP_MD, EVP_MD_free>;
diff --git a/src/node_metadata.h b/src/node_metadata.h
index 7f6268a1d83d3182b318bc95fd2ee119a2df8dea..f2ee335aa98a2465f63dafa33664197acc6f79b1 100644
--- a/src/node_metadata.h
+++ b/src/node_metadata.h
@@ -8,7 +8,7 @@
 #include <utility>
 #include "node_version.h"
 
-#if HAVE_OPENSSL
+#if 0
 #include <openssl/crypto.h>
 #if NODE_OPENSSL_HAS_QUIC
 #include <openssl/quic.h>
diff --git a/src/node_options.h b/src/node_options.h
index 887ead81d4b8bd55351091c06ed641c6a87b8419..6d4df44ccc06c3278948879a2430ab6f459cbec4 100644
--- a/src/node_options.h
+++ b/src/node_options.h
@@ -11,7 +11,7 @@
 #include "node_mutex.h"
 #include "util.h"
 
-#if HAVE_OPENSSL
+#if 0
 #include "openssl/opensslv.h"
 #endif
 
