Blame SOURCES/0001-Use-openssl-1.0.1.patch

503c61
From 52f8e271e6ca0986aa242b522a0718ffc9870040 Mon Sep 17 00:00:00 2001
503c61
From: Zuzana Svetlikova <zsvetlik@redhat.com>
503c61
Date: Wed, 6 Sep 2017 14:52:08 +0200
503c61
Subject: [PATCH] Use OpenSSL 1.0.1
8dc1ea
8dc1ea
---
8dc1ea
 doc/api/tls.md        |   6 ++
8dc1ea
 src/node_constants.cc |   5 ++
8dc1ea
 src/node_crypto.cc    | 201 ++++++++++++++++++++++++++++++++++++++++++++++----
8dc1ea
 src/node_crypto.h     |  16 ++++
8dc1ea
 src/tls_wrap.cc       |   8 ++
8dc1ea
 5 files changed, 223 insertions(+), 13 deletions(-)
8dc1ea
8dc1ea
diff --git a/doc/api/tls.md b/doc/api/tls.md
503c61
index b7e5c8f15e..6b3069f935 100644
8dc1ea
--- a/doc/api/tls.md
8dc1ea
+++ b/doc/api/tls.md
503c61
@@ -115,6 +115,12 @@ handshake extensions:
8dc1ea
 * SNI - Allows the use of one TLS server for multiple hostnames with different
8dc1ea
   SSL certificates.
8dc1ea
 
8dc1ea
+  **NOTE**: dueto a design flaw in node **SNI cannot be
8dc1ea
+  used on the server side**, even so all parameters in related functions are
8dc1ea
+  accepted for compatibility reasons. And thus the related events will not
8dc1ea
+  fire unless one aranges this explicitly. This may change, when the OS
8dc1ea
+  provides OpenSSL v1.0.2 or better and node gets linked to this version.
8dc1ea
+
8dc1ea
 *Note*: Use of ALPN is recommended over NPN. The NPN extension has never been
8dc1ea
 formally defined or documented and generally not recommended for use.
8dc1ea
 
8dc1ea
diff --git a/src/node_constants.cc b/src/node_constants.cc
503c61
index 750df9c669..d693851c4b 100644
8dc1ea
--- a/src/node_constants.cc
8dc1ea
+++ b/src/node_constants.cc
8dc1ea
@@ -14,7 +14,10 @@
8dc1ea
 #include <sys/stat.h>
8dc1ea
 
8dc1ea
 #if HAVE_OPENSSL
8dc1ea
+# include <openssl/opensslconf.h>
8dc1ea
+# ifndef OPENSSL_NO_EC
8dc1ea
 # include <openssl/ec.h>
8dc1ea
+# endif
8dc1ea
 # include <openssl/ssl.h>
8dc1ea
 # ifndef OPENSSL_NO_ENGINE
8dc1ea
 #  include <openssl/engine.h>
8dc1ea
@@ -976,12 +979,14 @@ void DefineOpenSSLConstants(Local<Object> target) {
8dc1ea
 
8dc1ea
 #if HAVE_OPENSSL
8dc1ea
   // NOTE: These are not defines
8dc1ea
+# ifndef OPENSSL_NO_EC
8dc1ea
   NODE_DEFINE_CONSTANT(target, POINT_CONVERSION_COMPRESSED);
8dc1ea
 
8dc1ea
   NODE_DEFINE_CONSTANT(target, POINT_CONVERSION_UNCOMPRESSED);
8dc1ea
 
8dc1ea
   NODE_DEFINE_CONSTANT(target, POINT_CONVERSION_HYBRID);
8dc1ea
 #endif
8dc1ea
+#endif
8dc1ea
 }
8dc1ea
 
8dc1ea
 void DefineSystemConstants(Local<Object> target) {
8dc1ea
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
503c61
index aa2dafebc5..471adb2687 100644
8dc1ea
--- a/src/node_crypto.cc
8dc1ea
+++ b/src/node_crypto.cc
503c61
@@ -28,6 +28,82 @@
8dc1ea
 #include <stdlib.h>
8dc1ea
 #include <string.h>
8dc1ea
 
8dc1ea
+#ifndef SSL_get_server_tmp_key
8dc1ea
+/*
8dc1ea
+	1.0.2 SSL_get_server_tmp_key(s, pk) "backport". BAD HACK!!!
8dc1ea
+	NOTE: This imports "foreign" knowledge and thus will break, when SESS_CERT
8dc1ea
+	      or CERT_PKEY change, which is definitely the case for the later for
8dc1ea
+	      all OpenSSL lib vers != 1.0.1. So don't try to bind to something else!
8dc1ea
+ */
8dc1ea
+# define SSL_PKEY_NUM            8
8dc1ea
+typedef struct cert_pkey_st {
8dc1ea
+    X509 *x509;
8dc1ea
+    EVP_PKEY *privatekey;
8dc1ea
+    /* Digest to use when signing */
8dc1ea
+    const EVP_MD *digest;
8dc1ea
+} CERT_PKEY;
8dc1ea
+
8dc1ea
+typedef struct sess_cert_st {
8dc1ea
+    STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */
8dc1ea
+    /* The 'peer_...' members are used only by clients. */
8dc1ea
+    int peer_cert_type;
8dc1ea
+    CERT_PKEY *peer_key;        /* points to an element of peer_pkeys (never
8dc1ea
+                                 * NULL!) */
8dc1ea
+    CERT_PKEY peer_pkeys[SSL_PKEY_NUM];
8dc1ea
+    /*
8dc1ea
+     * Obviously we don't have the private keys of these, so maybe we
8dc1ea
+     * shouldn't even use the CERT_PKEY type here.
8dc1ea
+     */
8dc1ea
+# ifndef OPENSSL_NO_RSA
8dc1ea
+    RSA *peer_rsa_tmp;          /* not used for SSL 2 */
8dc1ea
+# endif
8dc1ea
+# ifndef OPENSSL_NO_DH
8dc1ea
+    DH *peer_dh_tmp;            /* not used for SSL 2 */
8dc1ea
+# endif
8dc1ea
+# ifndef OPENSSL_NO_ECDH
8dc1ea
+    EC_KEY *peer_ecdh_tmp;
8dc1ea
+# endif
8dc1ea
+    int references;             /* actually always 1 at the moment */
8dc1ea
+} SESS_CERT;
8dc1ea
+
8dc1ea
+static long SSL_get_server_tmp_key(SSL *s, void *parg) {
8dc1ea
+	if (s->server || !s->session || !s->session->sess_cert)
8dc1ea
+		return 0;
8dc1ea
+	else {
8dc1ea
+		SESS_CERT *sc;
8dc1ea
+		EVP_PKEY *ptmp;
8dc1ea
+		int rv = 0;
8dc1ea
+		sc = s->session->sess_cert;
8dc1ea
+#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_ECDH)
8dc1ea
+		if (!sc->peer_rsa_tmp && !sc->peer_dh_tmp && !sc->peer_ecdh_tmp)
8dc1ea
+			return 0;
8dc1ea
+#endif
8dc1ea
+		ptmp = EVP_PKEY_new();
8dc1ea
+		if (!ptmp)
8dc1ea
+			return 0;
8dc1ea
+		if (0) ;
8dc1ea
+#ifndef OPENSSL_NO_RSA
8dc1ea
+		else if (sc->peer_rsa_tmp)
8dc1ea
+			rv = EVP_PKEY_set1_RSA(ptmp, sc->peer_rsa_tmp);
8dc1ea
+#endif
8dc1ea
+#ifndef OPENSSL_NO_DH
8dc1ea
+		else if (sc->peer_dh_tmp)
8dc1ea
+			rv = EVP_PKEY_set1_DH(ptmp, sc->peer_dh_tmp);
8dc1ea
+#endif
8dc1ea
+#ifndef OPENSSL_NO_ECDH
8dc1ea
+		else if (sc->peer_ecdh_tmp)
8dc1ea
+			rv = EVP_PKEY_set1_EC_KEY(ptmp, sc->peer_ecdh_tmp);
8dc1ea
+#endif
8dc1ea
+		if (rv) {
8dc1ea
+			*(EVP_PKEY **)parg = ptmp;
8dc1ea
+			return 1;
8dc1ea
+		}
8dc1ea
+		EVP_PKEY_free(ptmp);
8dc1ea
+		return 0;
8dc1ea
+	}
8dc1ea
+}
8dc1ea
+#endif /* SSL_get_server_tmp_key */
8dc1ea
+
8dc1ea
 #define THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(val, prefix)                  \
8dc1ea
   do {                                                                         \
8dc1ea
     if (!Buffer::HasInstance(val) && !val->IsString()) {                       \
503c61
@@ -166,7 +242,11 @@ template int SSLWrap<TLSWrap>::TLSExtStatusCallback(SSL* s, void* arg);
8dc1ea
 #endif
8dc1ea
 
8dc1ea
 template void SSLWrap<TLSWrap>::DestroySSL();
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
 template int SSLWrap<TLSWrap>::SSLCertCallback(SSL* s, void* arg);
8dc1ea
+#else
8dc1ea
+template int SSLWrap<TLSWrap>::SSLCertCallback(SSL* s, X509 **x509, EVP_PKEY **pkey);
8dc1ea
+#endif
8dc1ea
 template void SSLWrap<TLSWrap>::WaitForCertCb(CertCb cb, void* arg);
8dc1ea
 
8dc1ea
 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
503c61
@@ -296,8 +376,12 @@ void SecureContext::Initialize(Environment* env, Local<Object> target) {
8dc1ea
   env->SetProtoMethod(t, "addCRL", SecureContext::AddCRL);
8dc1ea
   env->SetProtoMethod(t, "addRootCerts", SecureContext::AddRootCerts);
8dc1ea
   env->SetProtoMethod(t, "setCiphers", SecureContext::SetCiphers);
8dc1ea
+#ifndef OPENSSL_NO_ECDH
8dc1ea
   env->SetProtoMethod(t, "setECDHCurve", SecureContext::SetECDHCurve);
8dc1ea
+#endif
8dc1ea
+#ifndef OPENSSL_NO_DH
8dc1ea
   env->SetProtoMethod(t, "setDHParam", SecureContext::SetDHParam);
8dc1ea
+#endif
8dc1ea
   env->SetProtoMethod(t, "setOptions", SecureContext::SetOptions);
8dc1ea
   env->SetProtoMethod(t, "setSessionIdContext",
8dc1ea
                       SecureContext::SetSessionIdContext);
503c61
@@ -532,8 +616,20 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
8dc1ea
     for (int i = 0; i < sk_X509_num(extra_certs); i++) {
8dc1ea
       X509* ca = sk_X509_value(extra_certs, i);
8dc1ea
 
8dc1ea
-      // NOTE: Increments reference count on `ca`
8dc1ea
-      r = SSL_CTX_add1_chain_cert(ctx, ca);
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
+		// If ctx->cert->key != NULL create ctx->cert->key->chain if not
8dc1ea
+		// already there, push 'ca' to this chain and finally increment the ca
8dc1ea
+		// reference count by 1 (this is the diff between *_add1_* and *_add0_*
8dc1ea
+		// - the later increments by 0 ;-)) and return 1. Otherwise or if
8dc1ea
+		// something fails in between, return 0.
8dc1ea
+		r = SSL_CTX_add1_chain_cert(ctx, ca);
8dc1ea
+#else
8dc1ea
+		// Create ctx->extra_certs if not already there, just push 'ca' to this
8dc1ea
+		// chain and return 1. If something fails, return 0.
8dc1ea
+		// NOTE: 1.0.1- does not support multiple certs having its own chain in
8dc1ea
+		//       a single context. There is just one: extra_chain!
8dc1ea
+		r = SSL_CTX_add_extra_chain_cert(ctx, ca);
8dc1ea
+#endif
8dc1ea
 
8dc1ea
       if (!r) {
8dc1ea
         ret = 0;
503c61
@@ -889,6 +985,7 @@ void SecureContext::SetCiphers(const FunctionCallbackInfo<Value>& args) {
8dc1ea
 }
8dc1ea
 
8dc1ea
 
8dc1ea
+#ifndef OPENSSL_NO_ECDH
8dc1ea
 void SecureContext::SetECDHCurve(const FunctionCallbackInfo<Value>& args) {
8dc1ea
   SecureContext* sc;
8dc1ea
   ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
503c61
@@ -916,8 +1013,10 @@ void SecureContext::SetECDHCurve(const FunctionCallbackInfo<Value>& args) {
8dc1ea
 
8dc1ea
   EC_KEY_free(ecdh);
8dc1ea
 }
8dc1ea
+#endif
8dc1ea
 
8dc1ea
 
8dc1ea
+#ifndef OPENSSL_NO_DH
8dc1ea
 void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
8dc1ea
   SecureContext* sc;
8dc1ea
   ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
503c61
@@ -956,6 +1055,7 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
8dc1ea
   if (!r)
8dc1ea
     return env->ThrowTypeError("Error setting temp DH parameter");
8dc1ea
 }
8dc1ea
+#endif
8dc1ea
 
8dc1ea
 
8dc1ea
 void SecureContext::SetOptions(const FunctionCallbackInfo<Value>& args) {
503c61
@@ -1979,6 +2079,7 @@ void SSLWrap<Base>::GetEphemeralKeyInfo(
8dc1ea
         info->Set(env->size_string(),
8dc1ea
                   Integer::New(env->isolate(), EVP_PKEY_bits(key)));
8dc1ea
         break;
8dc1ea
+#ifndef OPENSSL_NO_ECDH
8dc1ea
       case EVP_PKEY_EC:
8dc1ea
         {
8dc1ea
           EC_KEY* ec = EVP_PKEY_get1_EC_KEY(key);
503c61
@@ -1991,6 +2092,7 @@ void SSLWrap<Base>::GetEphemeralKeyInfo(
8dc1ea
           info->Set(env->size_string(),
8dc1ea
                     Integer::New(env->isolate(), EVP_PKEY_bits(key)));
8dc1ea
         }
8dc1ea
+#endif
8dc1ea
     }
8dc1ea
     EVP_PKEY_free(key);
8dc1ea
   }
503c61
@@ -2409,7 +2511,12 @@ void SSLWrap<Base>::WaitForCertCb(CertCb cb, void* arg) {
8dc1ea
 
8dc1ea
 
8dc1ea
 template <class Base>
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
 int SSLWrap<Base>::SSLCertCallback(SSL* s, void* arg) {
8dc1ea
+#else
8dc1ea
+/* NOTE: For now this callback gets usually never called dueto design flaws */
8dc1ea
+int SSLWrap<Base>::SSLCertCallback(SSL* s, X509 **x509, EVP_PKEY **pkey) {
8dc1ea
+#endif
8dc1ea
   Base* w = static_cast<Base*>(SSL_get_app_data(s));
8dc1ea
 
8dc1ea
   if (!w->is_server())
503c61
@@ -2478,19 +2585,53 @@ void SSLWrap<Base>::CertCbDone(const FunctionCallbackInfo<Value>& args) {
8dc1ea
     w->sni_context_.Reset(env->isolate(), ctx);
8dc1ea
 
8dc1ea
     int rv;
8dc1ea
+	X509* x509;
8dc1ea
+	EVP_PKEY* pkey;
8dc1ea
+	STACK_OF(X509)* chain;
8dc1ea
 
8dc1ea
     // NOTE: reference count is not increased by this API methods
8dc1ea
-    X509* x509 = SSL_CTX_get0_certificate(sc->ctx_);
8dc1ea
-    EVP_PKEY* pkey = SSL_CTX_get0_privatekey(sc->ctx_);
8dc1ea
-    STACK_OF(X509)* chain;
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
+	x509 = SSL_CTX_get0_certificate(sc->ctx_);
8dc1ea
+	pkey = SSL_CTX_get0_privatekey(sc->ctx_);
8dc1ea
+	rv = SSL_CTX_get0_chain_certs(sc->ctx_, &chain);
8dc1ea
+#else
8dc1ea
+	SSL *ssl = SSL_new(sc->ctx_);
8dc1ea
+	rv = SSL_CTX_get_extra_chain_certs(sc->ctx_, &chain);
8dc1ea
+	if (ssl) {
8dc1ea
+		SSL_set_connect_state(ssl);	/* just cleanup/reset state - cheap */
8dc1ea
+		x509 = SSL_get_certificate(ssl);
8dc1ea
+		SSL_free(ssl);
8dc1ea
+	} else {
8dc1ea
+		x509 = NULL;
8dc1ea
+		pkey = NULL;
8dc1ea
+	}
8dc1ea
+#endif
8dc1ea
 
8dc1ea
-    rv = SSL_CTX_get0_chain_certs(sc->ctx_, &chain);
8dc1ea
-    if (rv)
8dc1ea
-      rv = SSL_use_certificate(w->ssl_, x509);
8dc1ea
-    if (rv)
8dc1ea
-      rv = SSL_use_PrivateKey(w->ssl_, pkey);
8dc1ea
-    if (rv && chain != nullptr)
8dc1ea
-      rv = SSL_set1_chain(w->ssl_, chain);
8dc1ea
+	if (rv)
8dc1ea
+		rv = SSL_use_certificate(w->ssl_, x509);
8dc1ea
+	if (rv)
8dc1ea
+		rv = SSL_use_PrivateKey(w->ssl_, pkey);
8dc1ea
+	if (rv && chain != nullptr) {
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
+		// replaces w->ssl_->cert->key->chain with a copy of the given chain,
8dc1ea
+		// which is allowed to be NULL
8dc1ea
+		rv = SSL_set1_chain(w->ssl_, chain);
8dc1ea
+#else
8dc1ea
+		// just replace the extra chain with the given chain - 1.0.1- does not
8dc1ea
+		// support chain per cert
8dc1ea
+		SSL_CTX_clear_extra_chain_certs(w->ssl_->ctx);
8dc1ea
+		if (chain != NULL) {
8dc1ea
+			int i;
8dc1ea
+			SSL_CTX* ctx = w->ssl_->ctx;
8dc1ea
+			for (i = 0; i < sk_X509_num(chain); i++) {
8dc1ea
+				// can't do anything: however others might be ok and still
8dc1ea
+				// satisfy requirements
8dc1ea
+				SSL_CTX_add_extra_chain_cert(ctx, sk_X509_value(chain,i));
8dc1ea
+			}
8dc1ea
+		}
8dc1ea
+		rv = 1;
8dc1ea
+#endif
8dc1ea
+	}
8dc1ea
     if (rv)
8dc1ea
       rv = w->SetCACerts(sc);
8dc1ea
     if (!rv) {
503c61
@@ -2554,10 +2695,14 @@ void SSLWrap<Base>::SetSNIContext(SecureContext* sc) {
8dc1ea
 
8dc1ea
 template <class Base>
8dc1ea
 int SSLWrap<Base>::SetCACerts(SecureContext* sc) {
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
   int err = SSL_set1_verify_cert_store(ssl_, SSL_CTX_get_cert_store(sc->ctx_));
8dc1ea
   if (err != 1)
8dc1ea
     return err;
8dc1ea
-
8dc1ea
+#else
8dc1ea
+  // there is no ssl_->cert->verify_store in <= 1.0.1. So no need to: free the
8dc1ea
+  // old store, set the new one to it and increment its ref count.
8dc1ea
+#endif
8dc1ea
   STACK_OF(X509_NAME)* list = SSL_dup_CA_list(
8dc1ea
       SSL_CTX_get_client_CA_list(sc->ctx_));
8dc1ea
 
503c61
@@ -2873,7 +3018,11 @@ inline int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
8dc1ea
   SSL* ssl = static_cast<SSL*>(
8dc1ea
       X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
8dc1ea
 
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
   if (SSL_is_server(ssl))
8dc1ea
+#else
8dc1ea
+  if (ssl->server)
8dc1ea
+#endif
503c61
     return CHECK_OK;
8dc1ea
 
8dc1ea
   // Client needs to check if the server cert is listed in the
503c61
@@ -2956,7 +3105,21 @@ void Connection::New(const FunctionCallbackInfo<Value>& args) {
8dc1ea
 
8dc1ea
   InitNPN(sc);
8dc1ea
 
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
   SSL_set_cert_cb(conn->ssl_, SSLWrap<Connection>::SSLCertCallback, conn);
8dc1ea
+#else
8dc1ea
+  /* 1.0.1 and less have no general cert callback. The closest for a client is
8dc1ea
+     SSL_CTX_set_client_cert_cb(conn->ssl_->ctx, SSLWrap<Connection>::SSLCertCallback);
8dc1ea
+     but on the client it is not needed/used by this implementation. Since this
8dc1ea
+     the SSLCertCallback actually calls lib/_tls_wrap.js:oncertcb(), which in
8dc1ea
+     turn loadSNI() and this the actual SNICallback of the JSON object, sets
8dc1ea
+     the context and finally requestOCSP() and certCbDone(). Not sure, why
8dc1ea
+     the SNICallback of the JSON object, doesn't get invoked via
8dc1ea
+     SelectSNIContextCallback_() - design flaw because lets do 2 things at once
8dc1ea
+     (i.e. do SNICallback and attach the certs ca chain), however, this means
8dc1ea
+     no server side support for the SNI TLS/OCSP_state extension anymore.
8dc1ea
+   */
8dc1ea
+#endif
8dc1ea
 
8dc1ea
 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
8dc1ea
   if (is_server) {
503c61
@@ -4543,6 +4706,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
8dc1ea
 }
8dc1ea
 
8dc1ea
 
8dc1ea
+#ifndef OPENSSL_NO_DH
8dc1ea
 void DiffieHellman::Initialize(Environment* env, Local<Object> target) {
8dc1ea
   Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
8dc1ea
 
503c61
@@ -4944,8 +5108,10 @@ bool DiffieHellman::VerifyContext() {
8dc1ea
   verifyError_ = codes;
8dc1ea
   return true;
8dc1ea
 }
8dc1ea
+#endif
8dc1ea
 
8dc1ea
 
8dc1ea
+#ifndef OPENSSL_NO_ECDH
8dc1ea
 void ECDH::Initialize(Environment* env, Local<Object> target) {
8dc1ea
   HandleScope scope(env->isolate());
8dc1ea
 
503c61
@@ -5175,6 +5341,7 @@ void ECDH::SetPrivateKey(const FunctionCallbackInfo<Value>& args) {
8dc1ea
 
8dc1ea
   EC_POINT_free(pub);
8dc1ea
 }
8dc1ea
+#endif
8dc1ea
 
8dc1ea
 
8dc1ea
 void ECDH::SetPublicKey(const FunctionCallbackInfo<Value>& args) {
503c61
@@ -5730,6 +5897,7 @@ void GetHashes(const FunctionCallbackInfo<Value>& args) {
8dc1ea
 }
8dc1ea
 
8dc1ea
 
8dc1ea
+# ifndef OPENSSL_NO_EC
8dc1ea
 void GetCurves(const FunctionCallbackInfo<Value>& args) {
8dc1ea
   Environment* env = Environment::GetCurrent(args);
8dc1ea
   const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
503c61
@@ -5754,6 +5922,7 @@ void GetCurves(const FunctionCallbackInfo<Value>& args) {
8dc1ea
 
8dc1ea
   args.GetReturnValue().Set(arr);
8dc1ea
 }
8dc1ea
+#endif
8dc1ea
 
8dc1ea
 
8dc1ea
 bool VerifySpkac(const char* data, unsigned int len) {
503c61
@@ -6065,8 +6234,12 @@ void InitCrypto(Local<Object> target,
8dc1ea
   SecureContext::Initialize(env, target);
8dc1ea
   Connection::Initialize(env, target);
8dc1ea
   CipherBase::Initialize(env, target);
8dc1ea
+# ifndef OPENSSL_NO_EC
8dc1ea
   DiffieHellman::Initialize(env, target);
8dc1ea
+#endif
8dc1ea
+#ifndef OPENSSL_NO_ECDH
8dc1ea
   ECDH::Initialize(env, target);
8dc1ea
+#endif
8dc1ea
   Hmac::Initialize(env, target);
8dc1ea
   Hash::Initialize(env, target);
8dc1ea
   Sign::Initialize(env, target);
503c61
@@ -6086,7 +6259,9 @@ void InitCrypto(Local<Object> target,
8dc1ea
   env->SetMethod(target, "getSSLCiphers", GetSSLCiphers);
8dc1ea
   env->SetMethod(target, "getCiphers", GetCiphers);
8dc1ea
   env->SetMethod(target, "getHashes", GetHashes);
8dc1ea
+# ifndef OPENSSL_NO_EC
8dc1ea
   env->SetMethod(target, "getCurves", GetCurves);
8dc1ea
+#endif
8dc1ea
   env->SetMethod(target, "publicEncrypt",
8dc1ea
                  PublicKeyCipher::Cipher
8dc1ea
                                          EVP_PKEY_encrypt_init,
8dc1ea
diff --git a/src/node_crypto.h b/src/node_crypto.h
503c61
index 746c954b26..796767fdb3 100644
8dc1ea
--- a/src/node_crypto.h
8dc1ea
+++ b/src/node_crypto.h
8dc1ea
@@ -18,8 +18,12 @@
8dc1ea
 #include "v8.h"
8dc1ea
 
8dc1ea
 #include <openssl/ssl.h>
8dc1ea
+# ifndef OPENSSL_NO_EC
8dc1ea
 #include <openssl/ec.h>
8dc1ea
+# endif
8dc1ea
+# ifndef OPENSSL_NO_ECDH
8dc1ea
 #include <openssl/ecdh.h>
8dc1ea
+# endif
8dc1ea
 #ifndef OPENSSL_NO_ENGINE
8dc1ea
 # include <openssl/engine.h>
8dc1ea
 #endif  // !OPENSSL_NO_ENGINE
503c61
@@ -100,8 +104,12 @@ class SecureContext : public BaseObject {
8dc1ea
   static void AddCRL(const v8::FunctionCallbackInfo<v8::Value>& args);
8dc1ea
   static void AddRootCerts(const v8::FunctionCallbackInfo<v8::Value>& args);
8dc1ea
   static void SetCiphers(const v8::FunctionCallbackInfo<v8::Value>& args);
8dc1ea
+#ifndef OPENSSL_NO_ECDH
8dc1ea
   static void SetECDHCurve(const v8::FunctionCallbackInfo<v8::Value>& args);
8dc1ea
+#endif
8dc1ea
+# ifndef OPENSSL_NO_DH
8dc1ea
   static void SetDHParam(const v8::FunctionCallbackInfo<v8::Value>& args);
8dc1ea
+#endif
8dc1ea
   static void SetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
8dc1ea
   static void SetSessionIdContext(
8dc1ea
       const v8::FunctionCallbackInfo<v8::Value>& args);
503c61
@@ -273,7 +281,11 @@ class SSLWrap {
8dc1ea
                                 unsigned int inlen,
8dc1ea
                                 void* arg);
8dc1ea
   static int TLSExtStatusCallback(SSL* s, void* arg);
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
   static int SSLCertCallback(SSL* s, void* arg);
8dc1ea
+#else
8dc1ea
+  static int SSLCertCallback(SSL* s, X509 **x509, EVP_PKEY **pkey);
8dc1ea
+#endif
8dc1ea
   static void SSLGetter(v8::Local<v8::String> property,
8dc1ea
                         const v8::PropertyCallbackInfo<v8::Value>& info);
8dc1ea
 
503c61
@@ -635,6 +647,7 @@ class PublicKeyCipher {
8dc1ea
   static void Cipher(const v8::FunctionCallbackInfo<v8::Value>& args);
8dc1ea
 };
8dc1ea
 
8dc1ea
+#ifndef OPENSSL_NO_DH
8dc1ea
 class DiffieHellman : public BaseObject {
8dc1ea
  public:
8dc1ea
   ~DiffieHellman() override {
503c61
@@ -680,7 +693,9 @@ class DiffieHellman : public BaseObject {
8dc1ea
   int verifyError_;
8dc1ea
   DH* dh;
8dc1ea
 };
8dc1ea
+#endif
8dc1ea
 
8dc1ea
+# ifndef OPENSSL_NO_ECDH
8dc1ea
 class ECDH : public BaseObject {
8dc1ea
  public:
8dc1ea
   ~ECDH() override {
503c61
@@ -717,6 +732,7 @@ class ECDH : public BaseObject {
8dc1ea
   EC_KEY* key_;
8dc1ea
   const EC_GROUP* group_;
8dc1ea
 };
8dc1ea
+#endif
8dc1ea
 
8dc1ea
 bool EntropySource(unsigned char* buffer, size_t length);
8dc1ea
 #ifndef OPENSSL_NO_ENGINE
8dc1ea
diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc
503c61
index 78ba7126df..a377423bb9 100644
8dc1ea
--- a/src/tls_wrap.cc
8dc1ea
+++ b/src/tls_wrap.cc
503c61
@@ -143,7 +143,15 @@ void TLSWrap::InitSSL() {
8dc1ea
 
8dc1ea
   InitNPN(sc_);
8dc1ea
 
8dc1ea
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
8dc1ea
   SSL_set_cert_cb(ssl_, SSLWrap<TLSWrap>::SSLCertCallback, this);
8dc1ea
+#else
8dc1ea
+  /* 1.0.1 and less have at most for the client side the function
8dc1ea
+     SSL_CTX_set_client_cert_cb(ssl_->ctx, SSLWrap<TLSWrap>::SSLCertCallback);
8dc1ea
+     but on the client it is not needed/used by this implementation.
8dc1ea
+     For more info see comments in src/node_crypto.cc Connection::New().
8dc1ea
+   */
8dc1ea
+#endif
8dc1ea
 
8dc1ea
   if (is_server()) {
8dc1ea
     SSL_set_accept_state(ssl_);
8dc1ea
-- 
503c61
2.14.1
8dc1ea