Blob Blame History Raw
From e7f1280d006dc5e50f0d3844b63b7c746ced3cb9 Mon Sep 17 00:00:00 2001
From: Your Name <you@example.com>
Date: Thu, 13 Sep 2018 13:55:29 +0000
Subject: [PATCH 1/2] Rebase 10.1

---
 src/node_constants.cc                              |  12 +-
 src/node_crypto.cc                                 | 294 ++++++++++++++++++---
 src/node_crypto.h                                  |   2 +
 .../test-tls-client-getephemeralkeyinfo.js         |   6 +-
 4 files changed, 271 insertions(+), 43 deletions(-)

diff --git a/src/node_constants.cc b/src/node_constants.cc
index b6c7bf3..28ca346 100644
--- a/src/node_constants.cc
+++ b/src/node_constants.cc
@@ -951,8 +951,12 @@ void DefineOpenSSLConstants(Local<Object> target) {
     NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_RAND);
 # endif
 
-# ifdef ENGINE_METHOD_EC
-    NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_EC);
+# ifdef ENGINE_METHOD_ECDH
+    NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ECDH);
+# endif
+
+# ifdef ENGINE_METHOD_ECDSA
+    NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ECDSA);
 # endif
 
 # ifdef ENGINE_METHOD_CIPHERS
@@ -963,6 +967,10 @@ void DefineOpenSSLConstants(Local<Object> target) {
     NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DIGESTS);
 # endif
 
+# ifdef ENGINE_METHOD_STORE
+    NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_STORE);
+# endif
+
 # ifdef ENGINE_METHOD_PKEY_METHS
     NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_PKEY_METHS);
 # endif
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index 203d6b4..7bdb1b1 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -109,6 +109,119 @@ struct OpenSSLBufferDeleter {
 };
 using OpenSSLBuffer = std::unique_ptr<char[], OpenSSLBufferDeleter>;
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+static void RSA_get0_key(const RSA* r, const BIGNUM** n, const BIGNUM** e,
+                         const BIGNUM** d) {
+  if (n != nullptr) {
+    *n = r->n;
+  }
+  if (e != nullptr) {
+    *e = r->e;
+  }
+  if (d != nullptr) {
+    *d = r->d;
+  }
+}
+
+static void DH_get0_pqg(const DH* dh, const BIGNUM** p, const BIGNUM** q,
+                        const BIGNUM** g) {
+  if (p != nullptr) {
+    *p = dh->p;
+  }
+  if (q != nullptr) {
+    *q = dh->q;
+  }
+  if (g != nullptr) {
+    *g = dh->g;
+  }
+}
+
+static int DH_set0_pqg(DH* dh, BIGNUM* p, BIGNUM* q, BIGNUM* g) {
+  if ((dh->p == nullptr && p == nullptr) ||
+      (dh->g == nullptr && g == nullptr)) {
+    return 0;
+  }
+
+  if (p != nullptr) {
+    BN_free(dh->p);
+    dh->p = p;
+  }
+  if (q != nullptr) {
+    BN_free(dh->q);
+    dh->q = q;
+  }
+  if (g != nullptr) {
+    BN_free(dh->g);
+    dh->g = g;
+  }
+
+  return 1;
+}
+
+static void DH_get0_key(const DH* dh, const BIGNUM** pub_key,
+                        const BIGNUM** priv_key) {
+  if (pub_key != nullptr) {
+    *pub_key = dh->pub_key;
+  }
+  if (priv_key != nullptr) {
+    *priv_key = dh->priv_key;
+  }
+}
+
+static int DH_set0_key(DH* dh, BIGNUM* pub_key, BIGNUM* priv_key) {
+  if (pub_key != nullptr) {
+    BN_free(dh->pub_key);
+    dh->pub_key = pub_key;
+  }
+  if (priv_key != nullptr) {
+    BN_free(dh->priv_key);
+    dh->priv_key = priv_key;
+  }
+
+  return 1;
+}
+
+static const SSL_METHOD* TLS_method() { return SSLv23_method(); }
+
+static void SSL_SESSION_get0_ticket(const SSL_SESSION* s,
+                                    const unsigned char** tick, size_t* len) {
+  *len = s->tlsext_ticklen;
+  if (tick != nullptr) {
+    *tick = s->tlsext_tick;
+  }
+}
+
+#define SSL_get_tlsext_status_type(ssl) (ssl->tlsext_status_type)
+
+static int X509_STORE_up_ref(X509_STORE* store) {
+  CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
+  return 1;
+}
+
+static int X509_up_ref(X509* cert) {
+  CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509);
+  return 1;
+}
+
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+
+HMAC_CTX* HMAC_CTX_new() {
+  HMAC_CTX* ctx = Malloc<HMAC_CTX>(1);
+  HMAC_CTX_init(ctx);
+  return ctx;
+}
+
+void HMAC_CTX_free(HMAC_CTX* ctx) {
+  if (ctx == nullptr) {
+    return;
+  }
+  HMAC_CTX_cleanup(ctx);
+  free(ctx);
+}
+#endif  // OPENSSL_VERSION_NUMBER < 0x10100000L
+
+
 static const char* const root_certs[] = {
 #include "node_root_certs.h"  // NOLINT(build/include_order)
 };
@@ -125,11 +238,19 @@ template void SSLWrap<TLSWrap>::AddMethods(Environment* env,
 template void SSLWrap<TLSWrap>::ConfigureSecureContext(SecureContext* sc);
 template void SSLWrap<TLSWrap>::SetSNIContext(SecureContext* sc);
 template int SSLWrap<TLSWrap>::SetCACerts(SecureContext* sc);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+template SSL_SESSION* SSLWrap<TLSWrap>::GetSessionCallback(
+    SSL* s,
+    unsigned char* key,
+    int len,
+    int* copy);
+#else
 template SSL_SESSION* SSLWrap<TLSWrap>::GetSessionCallback(
     SSL* s,
     const unsigned char* key,
     int len,
     int* copy);
+#endif
 template int SSLWrap<TLSWrap>::NewSessionCallback(SSL* s,
                                                   SSL_SESSION* sess);
 template void SSLWrap<TLSWrap>::OnClientHello(
@@ -148,6 +269,34 @@ template int SSLWrap<TLSWrap>::SelectALPNCallback(
     void* arg);
 
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+static Mutex* mutexes;
+
+static void crypto_threadid_cb(CRYPTO_THREADID* tid) {
+  static_assert(sizeof(uv_thread_t) <= sizeof(void*),
+                "uv_thread_t does not fit in a pointer");
+  CRYPTO_THREADID_set_pointer(tid, reinterpret_cast<void*>(uv_thread_self()));
+}
+
+
+static void crypto_lock_init(void) {
+  mutexes = new Mutex[CRYPTO_num_locks()];
+}
+
+
+static void crypto_lock_cb(int mode, int n, const char* file, int line) {
+  CHECK(!(mode & CRYPTO_LOCK) ^ !(mode & CRYPTO_UNLOCK));
+  CHECK(!(mode & CRYPTO_READ) ^ !(mode & CRYPTO_WRITE));
+
+  auto mutex = &mutexes[n];
+  if (mode & CRYPTO_LOCK)
+    mutex->Lock();
+  else
+    mutex->Unlock();
+}
+#endif
+
+
 static int PasswordCallback(char* buf, int size, int rwflag, void* u) {
   if (u) {
     size_t buflen = static_cast<size_t>(size);
@@ -381,8 +530,8 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
   ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
   Environment* env = sc->env();
 
-  int min_version = 0;
-  int max_version = 0;
+  // int min_version = 0;
+  // int max_version = 0;
   const SSL_METHOD* method = TLS_method();
 
   if (args.Length() == 1 && args[0]->IsString()) {
@@ -405,47 +554,47 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
     } else if (strcmp(*sslmethod, "SSLv3_client_method") == 0) {
       return env->ThrowError("SSLv3 methods disabled");
     } else if (strcmp(*sslmethod, "SSLv23_method") == 0) {
-      method = TLS_method();
+      method = SSLv23_method();
     } else if (strcmp(*sslmethod, "SSLv23_server_method") == 0) {
-      method = TLS_server_method();
+      method = SSLv23_server_method();
     } else if (strcmp(*sslmethod, "SSLv23_client_method") == 0) {
-      method = TLS_client_method();
+      method = SSLv23_client_method();
     } else if (strcmp(*sslmethod, "TLSv1_method") == 0) {
-      min_version = TLS1_VERSION;
-      max_version = TLS1_VERSION;
-      method = TLS_method();
+      // min_version = TLS1_VERSION;
+      // max_version = TLS1_VERSION;
+      method = TLSv1_method();
     } else if (strcmp(*sslmethod, "TLSv1_server_method") == 0) {
-      min_version = TLS1_VERSION;
-      max_version = TLS1_VERSION;
-      method = TLS_server_method();
+      // min_version = TLS1_VERSION;
+      // max_version = TLS1_VERSION;
+      method = TLSv1_server_method();
     } else if (strcmp(*sslmethod, "TLSv1_client_method") == 0) {
-      min_version = TLS1_VERSION;
-      max_version = TLS1_VERSION;
-      method = TLS_client_method();
+      // min_version = TLS1_VERSION;
+      // max_version = TLS1_VERSION;
+      method = TLSv1_client_method();
     } else if (strcmp(*sslmethod, "TLSv1_1_method") == 0) {
-      min_version = TLS1_1_VERSION;
-      max_version = TLS1_1_VERSION;
-      method = TLS_method();
+      // min_version = TLS1_1_VERSION;
+      // max_version = TLS1_1_VERSION;
+      method = TLSv1_1_method();
     } else if (strcmp(*sslmethod, "TLSv1_1_server_method") == 0) {
-      min_version = TLS1_1_VERSION;
-      max_version = TLS1_1_VERSION;
-      method = TLS_server_method();
+      // min_version = TLS1_1_VERSION;
+      // max_version = TLS1_1_VERSION;
+      method = TLSv1_1_server_method();
     } else if (strcmp(*sslmethod, "TLSv1_1_client_method") == 0) {
-      min_version = TLS1_1_VERSION;
-      max_version = TLS1_1_VERSION;
-      method = TLS_client_method();
+      // min_version = TLS1_1_VERSION;
+      // max_version = TLS1_1_VERSION;
+      method = TLSv1_1_client_method();
     } else if (strcmp(*sslmethod, "TLSv1_2_method") == 0) {
-      min_version = TLS1_2_VERSION;
-      max_version = TLS1_2_VERSION;
-      method = TLS_method();
+      // min_version = TLS1_2_VERSION;
+      // max_version = TLS1_2_VERSION;
+      method = TLSv1_2_method();
     } else if (strcmp(*sslmethod, "TLSv1_2_server_method") == 0) {
-      min_version = TLS1_2_VERSION;
-      max_version = TLS1_2_VERSION;
-      method = TLS_server_method();
+      // min_version = TLS1_2_VERSION;
+      // max_version = TLS1_2_VERSION;
+      method = TLSv1_2_server_method();
     } else if (strcmp(*sslmethod, "TLSv1_2_client_method") == 0) {
-      min_version = TLS1_2_VERSION;
-      max_version = TLS1_2_VERSION;
-      method = TLS_client_method();
+      // min_version = TLS1_2_VERSION;
+      // max_version = TLS1_2_VERSION;
+      method = TLSv1_2_client_method();
     } else {
       return env->ThrowError("Unknown method");
     }
@@ -467,6 +616,7 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
                                  SSL_SESS_CACHE_NO_INTERNAL |
                                  SSL_SESS_CACHE_NO_AUTO_CLEAR);
 
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
   SSL_CTX_set_min_proto_version(sc->ctx_.get(), min_version);
   SSL_CTX_set_max_proto_version(sc->ctx_.get(), max_version);
   // OpenSSL 1.1.0 changed the ticket key size, but the OpenSSL 1.0.x size was
@@ -478,6 +628,7 @@ void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
     return env->ThrowError("Error generating ticket keys");
   }
   SSL_CTX_set_tlsext_ticket_key_cb(sc->ctx_.get(), TicketCompatibilityCallback);
+#endif
 }
 
 
@@ -925,6 +1076,11 @@ void SecureContext::SetECDHCurve(const FunctionCallbackInfo<Value>& args) {
 
   node::Utf8Value curve(env->isolate(), args[0]);
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  SSL_CTX_set_options(sc->ctx_, SSL_OP_SINGLE_ECDH_USE);
+  SSL_CTX_set_ecdh_auto(sc->ctx_, 1);
+#endif
+
   if (strcmp(*curve, "auto") == 0)
     return;
 
@@ -1179,9 +1335,17 @@ void SecureContext::GetTicketKeys(const FunctionCallbackInfo<Value>& args) {
   ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
 
   Local<Object> buff = Buffer::New(wrap->env(), 48).ToLocalChecked();
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
   memcpy(Buffer::Data(buff), wrap->ticket_key_name_, 16);
   memcpy(Buffer::Data(buff) + 16, wrap->ticket_key_hmac_, 16);
   memcpy(Buffer::Data(buff) + 32, wrap->ticket_key_aes_, 16);
+#else
+  if (SSL_CTX_get_tlsext_ticket_keys(wrap->ctx_,
+                                     Buffer::Data(buff),
+                                     Buffer::Length(buff)) != 1) {
+    return wrap->env()->ThrowError("Failed to fetch tls ticket keys");
+  }
+#endif
 
   args.GetReturnValue().Set(buff);
 #endif  // !def(OPENSSL_NO_TLSEXT) && def(SSL_CTX_get_tlsext_ticket_keys)
@@ -1205,9 +1369,17 @@ void SecureContext::SetTicketKeys(const FunctionCallbackInfo<Value>& args) {
         env, "Ticket keys length must be 48 bytes");
   }
 
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
   memcpy(wrap->ticket_key_name_, Buffer::Data(args[0]), 16);
   memcpy(wrap->ticket_key_hmac_, Buffer::Data(args[0]) + 16, 16);
   memcpy(wrap->ticket_key_aes_, Buffer::Data(args[0]) + 32, 16);
+#else
+  if (SSL_CTX_set_tlsext_ticket_keys(wrap->ctx_,
+                                     Buffer::Data(args[0]),
+                                     Buffer::Length(args[0])) != 1) {
+    return env->ThrowError("Failed to fetch tls ticket keys");
+  }
+#endif
 
   args.GetReturnValue().Set(true);
 #endif  // !def(OPENSSL_NO_TLSEXT) && def(SSL_CTX_get_tlsext_ticket_keys)
@@ -1215,6 +1387,14 @@ void SecureContext::SetTicketKeys(const FunctionCallbackInfo<Value>& args) {
 
 
 void SecureContext::SetFreeListLength(const FunctionCallbackInfo<Value>& args) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  // |freelist_max_len| was removed in OpenSSL 1.1.0. In that version OpenSSL
+  // mallocs and frees buffers directly, without the use of a freelist.
+  SecureContext* wrap;
+  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
+
+  wrap->ctx_->freelist_max_len = args[0]->Int32Value();
+#endif
 }
 
 
@@ -1311,6 +1491,7 @@ int SecureContext::TicketKeyCallback(SSL* ssl,
 }
 
 
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
 int SecureContext::TicketCompatibilityCallback(SSL* ssl,
                                                unsigned char* name,
                                                unsigned char* iv,
@@ -1345,6 +1526,7 @@ int SecureContext::TicketCompatibilityCallback(SSL* ssl,
   }
   return 1;
 }
+#endif
 
 
 template <bool primary>
@@ -1413,11 +1595,19 @@ void SSLWrap<Base>::ConfigureSecureContext(SecureContext* sc) {
 }
 
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+template <class Base>
+SSL_SESSION* SSLWrap<Base>::GetSessionCallback(SSL* s,
+                                               unsigned char* key,
+                                               int len,
+                                               int* copy) {
+#else
 template <class Base>
 SSL_SESSION* SSLWrap<Base>::GetSessionCallback(SSL* s,
                                                const unsigned char* key,
                                                int len,
                                                int* copy) {
+#endif
   Base* w = static_cast<Base*>(SSL_get_app_data(s));
 
   *copy = 0;
@@ -2077,6 +2267,7 @@ void SSLWrap<Base>::GetEphemeralKeyInfo(
                   Integer::New(env->isolate(), EVP_PKEY_bits(key))).FromJust();
         break;
       case EVP_PKEY_EC:
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
       // TODO(shigeki) Change this to EVP_PKEY_X25519 and add EVP_PKEY_X448
       // after upgrading to 1.1.1.
       case NID_X25519:
@@ -2097,9 +2288,24 @@ void SSLWrap<Base>::GetEphemeralKeyInfo(
                                   curve_name)).FromJust();
           info->Set(context, env->size_string(),
                     Integer::New(env->isolate(),
-                                 EVP_PKEY_bits(key))).FromJust();
+                                  EVP_PKEY_bits(key))).FromJust();
         }
         break;
+#else
+        {
+          EC_KEY* ec = EVP_PKEY_get1_EC_KEY(key);
+          int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+          EC_KEY_free(ec);
+          info->Set(context, env->type_string(),
+                    FIXED_ONE_BYTE_STRING(env->isolate(), "ECDH")).FromJust();
+          info->Set(context, env->name_string(),
+                    OneByteString(args.GetIsolate(),
+                                  OBJ_nid2sn(nid))).FromJust();
+          info->Set(context, env->size_string(),
+                    Integer::New(env->isolate(),
+                                  EVP_PKEY_bits(key))).FromJust();
+         }
+#endif
     }
     EVP_PKEY_free(key);
   }
@@ -2778,10 +2984,10 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, int iv_len,
   CHECK(IsAuthenticatedMode());
   MarkPopErrorOnReturn mark_pop_error_on_return;
 
-  if (!EVP_CIPHER_CTX_ctrl(ctx_.get(),
-                           EVP_CTRL_AEAD_SET_IVLEN,
-                           iv_len,
-                           nullptr)) {
+  // TODO(tniessen) Use EVP_CTRL_AEAD_SET_IVLEN when migrating to OpenSSL 1.1.0
+  static_assert(EVP_CTRL_CCM_SET_IVLEN == EVP_CTRL_GCM_SET_IVLEN,
+                "OpenSSL constants differ between GCM and CCM");
+  if (!EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_SET_IVLEN, iv_len, nullptr)) {
     env()->ThrowError("Invalid IV length");
     return false;
   }
@@ -3137,8 +3343,10 @@ bool CipherBase::Final(unsigned char** out, int* out_len) {
         CHECK(mode == EVP_CIPH_GCM_MODE);
         auth_tag_len_ = sizeof(auth_tag_);
       }
-      CHECK_EQ(1, EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_GET_TAG,
-                      auth_tag_len_,
+      // TOOD(tniessen) Use EVP_CTRL_AEAP_GET_TAG in OpenSSL 1.1.0
+      static_assert(EVP_CTRL_CCM_GET_TAG == EVP_CTRL_GCM_GET_TAG,
+                    "OpenSSL constants differ between GCM and CCM");
+      CHECK_EQ(1, EVP_CIPHER_CTX_ctrl(ctx_, EVP_CTRL_GCM_GET_TAG, auth_tag_len_,
                       reinterpret_cast<unsigned char*>(auth_tag_)));
     }
   }
@@ -3414,12 +3622,14 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
 
 SignBase::Error SignBase::Init(const char* sign_type) {
   CHECK_NULL(mdctx_);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
   // Historically, "dss1" and "DSS1" were DSA aliases for SHA-1
   // exposed through the public API.
   if (strcmp(sign_type, "dss1") == 0 ||
       strcmp(sign_type, "DSS1") == 0) {
     sign_type = "SHA1";
   }
+#endif
   const EVP_MD* md = EVP_get_digestbyname(sign_type);
   if (md == nullptr)
     return kSignUnknownDigest;
@@ -5124,6 +5334,12 @@ void InitCryptoOnce() {
   SSL_library_init();
   OpenSSL_add_all_algorithms();
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  crypto_lock_init();
+  CRYPTO_set_locking_callback(crypto_lock_cb);
+  CRYPTO_THREADID_set_callback(crypto_threadid_cb);
+#endif
+
 #ifdef NODE_FIPS_MODE
   /* Override FIPS settings in cnf file, if needed. */
   unsigned long err = 0;  // NOLINT(runtime/int)
diff --git a/src/node_crypto.h b/src/node_crypto.h
index 86aa3ba..e850358 100644
--- a/src/node_crypto.h
+++ b/src/node_crypto.h
@@ -44,8 +44,10 @@
 #endif  // !OPENSSL_NO_ENGINE
 #include <openssl/err.h>
 #include <openssl/evp.h>
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
 // TODO(shigeki) Remove this after upgrading to 1.1.1
 #include <openssl/obj_mac.h>
+#endif
 #include <openssl/pem.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
diff --git a/test/parallel/test-tls-client-getephemeralkeyinfo.js b/test/parallel/test-tls-client-getephemeralkeyinfo.js
index 9432a27..411fdc7 100644
--- a/test/parallel/test-tls-client-getephemeralkeyinfo.js
+++ b/test/parallel/test-tls-client-getephemeralkeyinfo.js
@@ -82,18 +82,20 @@ function testECDHE256() {
 }
 
 function testECDHE512() {
-  test(521, 'ECDH', 'secp521r1', testX25519);
+  test(521, 'ECDH', 'secp521r1', null);
   ntests++;
 }
 
+/*
 function testX25519() {
   test(253, 'ECDH', 'X25519', null);
   ntests++;
 }
+*/
 
 testNOT_PFS();
 
 process.on('exit', function() {
   assert.strictEqual(ntests, nsuccess);
-  assert.strictEqual(ntests, 6);
+  assert.strictEqual(ntests, 5);
 });
-- 
1.8.3.1