diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js
index 35d5ba3..37081d9 100644
--- a/lib/_tls_wrap.js
+++ b/lib/_tls_wrap.js
@@ -165,26 +165,31 @@ function onclienthello(hello) {
     if (err)
       return self.destroy(err);
 
-    self._handle.endParser();
-  });
-}
-
-
-function oncertcb(info) {
-  var self = this;
-  var servername = info.servername;
-
-  loadSNI(self, servername, function(err, ctx) {
-    if (err)
-      return self.destroy(err);
-    requestOCSP(self, info, ctx, function(err) {
+    // Servername came from SSL session
+    // NOTE: TLS Session ticket doesn't include servername information
+    //
+    // Another note, From RFC3546:
+    //
+    //   If, on the other hand, the older
+    //   session is resumed, then the server MUST ignore extensions appearing
+    //   in the client hello, and send a server hello containing no
+    //   extensions; in this case the extension functionality negotiated
+    //   during the original session initiation is applied to the resumed
+    //   session.
+    //
+    // Therefore we should account session loading when dealing with servername
+    var servername = session && session.servername || hello.servername;
+    loadSNI(self, servername, function(err, ctx) {
       if (err)
         return self.destroy(err);
-
-      if (!self._handle)
-        return self.destroy(new Error('Socket is closed'));
-
-      self._handle.certCbDone();
+      requestOCSP(self, hello, ctx, function(err) {
+        if (err)
+          return self.destroy(err);
+
+        if (!self._handle)
+          return self.destroy(new Error('Socket is closed'));
+        self._handle.endParser();
+      });
     });
   });
 }
@@ -409,18 +414,15 @@ TLSSocket.prototype._init = function(socket, wrap) {
     ssl.onhandshakestart = onhandshakestart.bind(this);
     ssl.onhandshakedone = onhandshakedone.bind(this);
     ssl.onclienthello = onclienthello.bind(this);
-    ssl.oncertcb = oncertcb.bind(this);
     ssl.onnewsession = onnewsession.bind(this);
     ssl.lastHandshakeTime = 0;
     ssl.handshakes = 0;
 
-    if (this.server) {
-      if (this.server.listenerCount('resumeSession') > 0 ||
-          this.server.listenerCount('newSession') > 0) {
-        ssl.enableSessionCallbacks();
-      }
-      if (this.server.listenerCount('OCSPRequest') > 0)
-        ssl.enableCertCb();
+    if (this.server &&
+        (this.server.listenerCount('resumeSession') > 0 ||
+         this.server.listenerCount('newSession') > 0 ||
+         this.server.listenerCount('OCSPRequest') > 0)) {
+      ssl.enableSessionCallbacks();
     }
   } else {
     ssl.onhandshakestart = function() {};
@@ -462,7 +464,7 @@ TLSSocket.prototype._init = function(socket, wrap) {
        options.server._contexts.length)) {
     assert(typeof options.SNICallback === 'function');
     this._SNICallback = options.SNICallback;
-    ssl.enableCertCb();
+    ssl.enableHelloParser();
   }
 
   if (process.features.tls_npn && options.NPNProtocols)
diff --git a/src/env.h b/src/env.h
index ea5e8fe..995f151 100644
--- a/src/env.h
+++ b/src/env.h
@@ -56,7 +56,6 @@ namespace node {
   V(bytes_parsed_string, "bytesParsed")                                       \
   V(callback_string, "callback")                                              \
   V(change_string, "change")                                                  \
-  V(oncertcb_string, "oncertcb")                                              \
   V(onclose_string, "_onclose")                                               \
   V(code_string, "code")                                                      \
   V(compare_string, "compare")                                                \
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index f0d353f..fcaf77d 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -129,8 +129,6 @@ template class SSLWrap<TLSWrap>;
 template void SSLWrap<TLSWrap>::AddMethods(Environment* env,
                                            Local<FunctionTemplate> t);
 template void SSLWrap<TLSWrap>::InitNPN(SecureContext* sc);
-template void SSLWrap<TLSWrap>::SetSNIContext(SecureContext* sc);
-template int SSLWrap<TLSWrap>::SetCACerts(SecureContext* sc);
 template SSL_SESSION* SSLWrap<TLSWrap>::GetSessionCallback(
     SSL* s,
     unsigned char* key,
@@ -158,8 +156,6 @@ template int SSLWrap<TLSWrap>::SelectNextProtoCallback(
 #endif
 template int SSLWrap<TLSWrap>::TLSExtStatusCallback(SSL* s, void* arg);
 template void SSLWrap<TLSWrap>::DestroySSL();
-template int SSLWrap<TLSWrap>::SSLCertCallback(SSL* s, void* arg);
-template void SSLWrap<TLSWrap>::WaitForCertCb(CertCb cb, void* arg);
 
 
 static void crypto_threadid_cb(CRYPTO_THREADID* tid) {
@@ -513,35 +509,45 @@ int SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) {
 }
 
 
+// Read a file that contains our certificate in "PEM" format,
+// possibly followed by a sequence of CA certificates that should be
+// sent to the peer in the Certificate message.
+//
+// Taken from OpenSSL - editted for style.
 int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
-                                  X509* x,
-                                  STACK_OF(X509)* extra_certs,
+                                  BIO* in,
                                   X509** cert,
                                   X509** issuer) {
-  CHECK_EQ(*issuer, nullptr);
-  CHECK_EQ(*cert, nullptr);
+  int ret = 0;
+  X509* x = nullptr;
 
-  int ret = SSL_CTX_use_certificate(ctx, x);
+  x = PEM_read_bio_X509_AUX(in, nullptr, CryptoPemCallback, nullptr);
+
+  if (x == nullptr) {
+    SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
+    goto end;
+  }
+
+  ret = SSL_CTX_use_certificate(ctx, x);
 
   if (ret) {
     // If we could set up our certificate, now proceed to
     // the CA certificates.
+    X509 *ca;
     int r;
+    unsigned long err;
 
     if (ctx->extra_certs != nullptr) {
       sk_X509_pop_free(ctx->extra_certs, X509_free);
       ctx->extra_certs = nullptr;
     }
 
-    for (int i = 0; i < sk_X509_num(extra_certs); i++) {
-      X509* ca = sk_X509_value(extra_certs, i);
-
-      // NOTE: Increments reference count on `ca`
-      r = SSL_CTX_add1_chain_cert(ctx, ca);
+    while ((ca = PEM_read_bio_X509(in, nullptr, CryptoPemCallback, nullptr))) {
+      r = SSL_CTX_add_extra_chain_cert(ctx, ca);
 
       if (!r) {
+        X509_free(ca);
         ret = 0;
-        *issuer = nullptr;
         goto end;
       }
       // Note that we must not free r if it was successfully
@@ -552,9 +558,18 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
       // Find issuer
       if (*issuer != nullptr || X509_check_issued(ca, x) != X509_V_OK)
         continue;
-
       *issuer = ca;
     }
+
+    // When the while loop ends, it's usually just EOF.
+    err = ERR_peek_last_error();
+    if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
+        ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
+      ERR_clear_error();
+    } else  {
+      // some real error
+      ret = 0;
+    }
   }
 
   // Try getting issuer from a cert store
@@ -566,88 +581,13 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
       // no need to free `store`
     } else {
       // Increment issuer reference count
-      *issuer = X509_dup(*issuer);
-      if (*issuer == nullptr) {
-        ret = 0;
-        goto end;
-      }
+      CRYPTO_add(&(*issuer)->references, 1, CRYPTO_LOCK_X509);
     }
   }
 
  end:
-  if (ret && x != nullptr) {
-    *cert = X509_dup(x);
-    if (*cert == nullptr)
-      ret = 0;
-  }
-  return ret;
-}
-
-
-// Read a file that contains our certificate in "PEM" format,
-// possibly followed by a sequence of CA certificates that should be
-// sent to the peer in the Certificate message.
-//
-// Taken from OpenSSL - edited for style.
-int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
-                                  BIO* in,
-                                  X509** cert,
-                                  X509** issuer) {
-  X509* x = nullptr;
-
-  // Just to ensure that `ERR_peek_last_error` below will return only errors
-  // that we are interested in
-  ERR_clear_error();
-
-  x = PEM_read_bio_X509_AUX(in, nullptr, CryptoPemCallback, nullptr);
-
-  if (x == nullptr) {
-    SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
-    return 0;
-  }
-
-  X509* extra = nullptr;
-  int ret = 0;
-  unsigned long err = 0;
-
-  // Read extra certs
-  STACK_OF(X509)* extra_certs = sk_X509_new_null();
-  if (extra_certs == nullptr) {
-    SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_MALLOC_FAILURE);
-    goto done;
-  }
-
-  while ((extra = PEM_read_bio_X509(in, nullptr, CryptoPemCallback, nullptr))) {
-    if (sk_X509_push(extra_certs, extra))
-      continue;
-
-    // Failure, free all certs
-    goto done;
-  }
-  extra = nullptr;
-
-  // When the while loop ends, it's usually just EOF.
-  err = ERR_peek_last_error();
-  if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
-      ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
-    ERR_clear_error();
-  } else  {
-    // some real error
-    goto done;
-  }
-
-  ret = SSL_CTX_use_certificate_chain(ctx, x, extra_certs, cert, issuer);
-  if (!ret)
-    goto done;
-
- done:
-  if (extra_certs != nullptr)
-    sk_X509_pop_free(extra_certs, X509_free);
-  if (extra != nullptr)
-    X509_free(extra);
   if (x != nullptr)
-    X509_free(x);
-
+    *cert = x;
   return ret;
 }
 
@@ -665,16 +605,6 @@ void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
   if (!bio)
     return;
 
-  // Free previous certs
-  if (sc->issuer_ != nullptr) {
-    X509_free(sc->issuer_);
-    sc->issuer_ = nullptr;
-  }
-  if (sc->cert_ != nullptr) {
-    X509_free(sc->cert_);
-    sc->cert_ = nullptr;
-  }
-
   int rv = SSL_CTX_use_certificate_chain(sc->ctx_,
                                          bio,
                                          &sc->cert_,
@@ -946,7 +876,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
   PKCS12* p12 = nullptr;
   EVP_PKEY* pkey = nullptr;
   X509* cert = nullptr;
-  STACK_OF(X509)* extra_certs = nullptr;
+  STACK_OF(X509)* extraCerts = nullptr;
   char* pass = nullptr;
   bool ret = false;
 
@@ -971,33 +901,28 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
     pass[passlen] = '\0';
   }
 
-  // Free previous certs
-  if (sc->issuer_ != nullptr) {
-    X509_free(sc->issuer_);
-    sc->issuer_ = nullptr;
-  }
-  if (sc->cert_ != nullptr) {
-    X509_free(sc->cert_);
-    sc->cert_ = nullptr;
-  }
-
   if (d2i_PKCS12_bio(in, &p12) &&
-      PKCS12_parse(p12, pass, &pkey, &cert, &extra_certs) &&
-      SSL_CTX_use_certificate_chain(sc->ctx_,
-                                    cert,
-                                    extra_certs,
-                                    &sc->cert_,
-                                    &sc->issuer_) &&
+      PKCS12_parse(p12, pass, &pkey, &cert, &extraCerts) &&
+      SSL_CTX_use_certificate(sc->ctx_, cert) &&
       SSL_CTX_use_PrivateKey(sc->ctx_, pkey)) {
-    ret = true;
-  }
+    // set extra certs
+    while (X509* x509 = sk_X509_pop(extraCerts)) {
+      if (!sc->ca_store_) {
+        sc->ca_store_ = X509_STORE_new();
+        SSL_CTX_set_cert_store(sc->ctx_, sc->ca_store_);
+      }
+
+      X509_STORE_add_cert(sc->ca_store_, x509);
+      SSL_CTX_add_client_CA(sc->ctx_, x509);
+      X509_free(x509);
+    }
 
-  if (pkey != nullptr)
     EVP_PKEY_free(pkey);
-  if (cert != nullptr)
     X509_free(cert);
-  if (extra_certs != nullptr)
-    sk_X509_free(extra_certs);
+    sk_X509_free(extraCerts);
+
+    ret = true;
+  }
 
   PKCS12_free(p12);
   BIO_free_all(in);
@@ -1052,7 +977,7 @@ void SecureContext::SetTicketKeys(const FunctionCallbackInfo<Value>& args) {
 void SecureContext::SetFreeListLength(const FunctionCallbackInfo<Value>& args) {
   SecureContext* wrap = Unwrap<SecureContext>(args.Holder());
 
-  wrap->ctx_->freelist_max_len = args[0]->Int32Value();
+  // wrap->ctx_->freelist_max_len = args[0]->Int32Value();
 }
 
 
@@ -1191,7 +1116,6 @@ void SSLWrap<Base>::AddMethods(Environment* env, Local<FunctionTemplate> t) {
   env->SetProtoMethod(t, "verifyError", VerifyError);
   env->SetProtoMethod(t, "getCurrentCipher", GetCurrentCipher);
   env->SetProtoMethod(t, "endParser", EndParser);
-  env->SetProtoMethod(t, "certCbDone", CertCbDone);
   env->SetProtoMethod(t, "renegotiate", Renegotiate);
   env->SetProtoMethod(t, "shutdownSSL", Shutdown);
   env->SetProtoMethod(t, "getTLSTicket", GetTLSTicket);
@@ -2080,124 +2004,6 @@ int SSLWrap<Base>::TLSExtStatusCallback(SSL* s, void* arg) {
 
 
 template <class Base>
-void SSLWrap<Base>::WaitForCertCb(CertCb cb, void* arg) {
-  cert_cb_ = cb;
-  cert_cb_arg_ = arg;
-}
-
-
-template <class Base>
-int SSLWrap<Base>::SSLCertCallback(SSL* s, void* arg) {
-  Base* w = static_cast<Base*>(SSL_get_app_data(s));
-
-  if (!w->is_server())
-    return 1;
-
-  if (!w->is_waiting_cert_cb())
-    return 1;
-
-  if (w->cert_cb_running_)
-    return -1;
-
-  Environment* env = w->env();
-  HandleScope handle_scope(env->isolate());
-  Context::Scope context_scope(env->context());
-  w->cert_cb_running_ = true;
-
-  Local<Object> info = Object::New(env->isolate());
-
-  SSL_SESSION* sess = SSL_get_session(s);
-  if (sess != nullptr) {
-    if (sess->tlsext_hostname == nullptr) {
-      info->Set(env->servername_string(), String::Empty(env->isolate()));
-    } else {
-      Local<String> servername = OneByteString(env->isolate(),
-                                               sess->tlsext_hostname,
-                                               strlen(sess->tlsext_hostname));
-      info->Set(env->servername_string(), servername);
-    }
-    info->Set(env->tls_ticket_string(),
-              Boolean::New(env->isolate(), sess->tlsext_ticklen != 0));
-  }
-  bool ocsp = s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp;
-  info->Set(env->ocsp_request_string(), Boolean::New(env->isolate(), ocsp));
-
-  Local<Value> argv[] = { info };
-  w->MakeCallback(env->oncertcb_string(), ARRAY_SIZE(argv), argv);
-
-  if (!w->cert_cb_running_)
-    return 1;
-
-  // Performing async action, wait...
-  return -1;
-}
-
-
-template <class Base>
-void SSLWrap<Base>::CertCbDone(const FunctionCallbackInfo<Value>& args) {
-  Base* w = Unwrap<Base>(args.Holder());
-  Environment* env = w->env();
-
-  CHECK(w->is_waiting_cert_cb() && w->cert_cb_running_);
-
-  Local<Object> object = w->object();
-  Local<Value> ctx = object->Get(env->sni_context_string());
-  Local<FunctionTemplate> cons = env->secure_context_constructor_template();
-
-  // Not an object, probably undefined or null
-  if (!ctx->IsObject())
-    goto fire_cb;
-
-  if (cons->HasInstance(ctx)) {
-    SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>());
-    w->sni_context_.Reset();
-    w->sni_context_.Reset(env->isolate(), ctx);
-
-    int rv;
-
-    // NOTE: reference count is not increased by this API methods
-    X509* x509 = SSL_CTX_get0_certificate(sc->ctx_);
-    EVP_PKEY* pkey = SSL_CTX_get0_privatekey(sc->ctx_);
-    STACK_OF(X509)* chain;
-
-    rv = SSL_CTX_get0_chain_certs(sc->ctx_, &chain);
-    if (rv)
-      rv = SSL_use_certificate(w->ssl_, x509);
-    if (rv)
-      rv = SSL_use_PrivateKey(w->ssl_, pkey);
-    if (rv && chain != nullptr)
-      rv = SSL_set1_chain(w->ssl_, chain);
-    if (rv)
-      rv = w->SetCACerts(sc);
-    if (!rv) {
-      unsigned long err = ERR_get_error();
-      if (!err)
-        return env->ThrowError("CertCbDone");
-      return ThrowCryptoError(env, err);
-    }
-  } else {
-    // Failure: incorrect SNI context object
-    Local<Value> err = Exception::TypeError(env->sni_context_err_string());
-    w->MakeCallback(env->onerror_string(), 1, &err);
-    return;
-  }
-
- fire_cb:
-  CertCb cb;
-  void* arg;
-
-  cb = w->cert_cb_;
-  arg = w->cert_cb_arg_;
-
-  w->cert_cb_running_ = false;
-  w->cert_cb_ = nullptr;
-  w->cert_cb_arg_ = nullptr;
-
-  cb(arg);
-}
-
-
-template <class Base>
 void SSLWrap<Base>::SSLGetter(Local<String> property,
                         const PropertyCallbackInfo<Value>& info) {
   HandleScope scope(info.GetIsolate());
@@ -2219,30 +2025,6 @@ void SSLWrap<Base>::DestroySSL() {
 }
 
 
-template <class Base>
-void SSLWrap<Base>::SetSNIContext(SecureContext* sc) {
-  InitNPN(sc);
-  CHECK_EQ(SSL_set_SSL_CTX(ssl_, sc->ctx_), sc->ctx_);
-
-  SetCACerts(sc);
-}
-
-
-template <class Base>
-int SSLWrap<Base>::SetCACerts(SecureContext* sc) {
-  int err = SSL_set1_verify_cert_store(ssl_, SSL_CTX_get_cert_store(sc->ctx_));
-  if (err != 1)
-    return err;
-
-  STACK_OF(X509_NAME)* list = SSL_dup_CA_list(
-      SSL_CTX_get_client_CA_list(sc->ctx_));
-
-  // NOTE: `SSL_set_client_CA_list` takes the ownership of `list`
-  SSL_set_client_CA_list(ssl_, list);
-  return 1;
-}
-
-
 void Connection::OnClientHelloParseEnd(void* arg) {
   Connection* conn = static_cast<Connection*>(arg);
 
@@ -2327,10 +2109,6 @@ int Connection::HandleSSLError(const char* func,
     DEBUG_PRINT("[%p] SSL: %s want read\n", ssl_, func);
     return 0;
 
-  } else if (err == SSL_ERROR_WANT_X509_LOOKUP) {
-    DEBUG_PRINT("[%p] SSL: %s want x509 lookup\n", ssl_, func);
-    return 0;
-
   } else if (err == SSL_ERROR_ZERO_RETURN) {
     HandleScope scope(ssl_env()->isolate());
 
@@ -2511,7 +2289,7 @@ inline int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
   SSL* ssl = static_cast<SSL*>(
       X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
 
-  if (SSL_is_server(ssl))
+  if (ssl->server)
     return 1;
 
   // Client needs to check if the server cert is listed in the
@@ -2538,7 +2316,7 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
 
     // Call the SNI callback and use its return value as context
     if (!conn->sniObject_.IsEmpty()) {
-      conn->sni_context_.Reset();
+      conn->sniContext_.Reset();
 
       Local<Object> sni_obj = PersistentToLocal(env->isolate(),
                                                 conn->sniObject_);
@@ -2554,9 +2332,10 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
       Local<FunctionTemplate> secure_context_constructor_template =
           env->secure_context_constructor_template();
       if (secure_context_constructor_template->HasInstance(ret)) {
-        conn->sni_context_.Reset(env->isolate(), ret);
+        conn->sniContext_.Reset(env->isolate(), ret);
         SecureContext* sc = Unwrap<SecureContext>(ret.As<Object>());
-        conn->SetSNIContext(sc);
+        InitNPN(sc);
+        SSL_set_SSL_CTX(s, sc->ctx_);
       } else {
         return SSL_TLSEXT_ERR_NOACK;
       }
@@ -2592,8 +2371,6 @@ void Connection::New(const FunctionCallbackInfo<Value>& args) {
 
   InitNPN(sc);
 
-  SSL_set_cert_cb(conn->ssl_, SSLWrap<Connection>::SSLCertCallback, conn);
-
 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
   if (is_server) {
     SSL_CTX_set_tlsext_servername_callback(sc->ctx_, SelectSNIContextCallback_);
diff --git a/src/node_crypto.h b/src/node_crypto.h
index cb94650..6373fc4 100644
--- a/src/node_crypto.h
+++ b/src/node_crypto.h
@@ -179,10 +179,7 @@ class SSLWrap {
         kind_(kind),
         next_sess_(nullptr),
         session_callbacks_(false),
-        new_session_wait_(false),
-        cert_cb_(nullptr),
-        cert_cb_arg_(nullptr),
-        cert_cb_running_(false) {
+        new_session_wait_(false) {
     ssl_ = SSL_new(sc->ctx_);
     env_->isolate()->AdjustAmountOfExternalAllocatedMemory(kExternalSize);
     CHECK_NE(ssl_, nullptr);
@@ -199,9 +196,6 @@ class SSLWrap {
     npn_protos_.Reset();
     selected_npn_proto_.Reset();
 #endif
-#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
-    sni_context_.Reset();
-#endif
 #ifdef NODE__HAVE_TLSEXT_STATUS_CB
     ocsp_response_.Reset();
 #endif  // NODE__HAVE_TLSEXT_STATUS_CB
@@ -212,11 +206,8 @@ class SSLWrap {
   inline bool is_server() const { return kind_ == kServer; }
   inline bool is_client() const { return kind_ == kClient; }
   inline bool is_waiting_new_session() const { return new_session_wait_; }
-  inline bool is_waiting_cert_cb() const { return cert_cb_ != nullptr; }
 
  protected:
-  typedef void (*CertCb)(void* arg);
-
   // Size allocated by OpenSSL: one for SSL structure, one for SSL3_STATE and
   // some for buffers.
   // NOTE: Actually it is much more than this
@@ -244,7 +235,6 @@ class SSLWrap {
   static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void EndParser(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void CertCbDone(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void Renegotiate(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void Shutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void GetTLSTicket(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -273,14 +263,10 @@ class SSLWrap {
                                      void* arg);
 #endif  // OPENSSL_NPN_NEGOTIATED
   static int TLSExtStatusCallback(SSL* s, void* arg);
-  static int SSLCertCallback(SSL* s, void* arg);
   static void SSLGetter(v8::Local<v8::String> property,
                         const v8::PropertyCallbackInfo<v8::Value>& info);
 
   void DestroySSL();
-  void WaitForCertCb(CertCb cb, void* arg);
-  void SetSNIContext(SecureContext* sc);
-  int SetCACerts(SecureContext* sc);
 
   inline Environment* ssl_env() const {
     return env_;
@@ -292,12 +278,6 @@ class SSLWrap {
   SSL* ssl_;
   bool session_callbacks_;
   bool new_session_wait_;
-
-  // SSL_set_cert_cb
-  CertCb cert_cb_;
-  void* cert_cb_arg_;
-  bool cert_cb_running_;
-
   ClientHelloParser hello_parser_;
 
 #ifdef NODE__HAVE_TLSEXT_STATUS_CB
@@ -309,10 +289,6 @@ class SSLWrap {
   v8::Persistent<v8::Value> selected_npn_proto_;
 #endif  // OPENSSL_NPN_NEGOTIATED
 
-#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
-  v8::Persistent<v8::Value> sni_context_;
-#endif
-
   friend class SecureContext;
 };
 
@@ -324,6 +300,7 @@ class Connection : public SSLWrap<Connection>, public AsyncWrap {
   ~Connection() override {
 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
     sniObject_.Reset();
+    sniContext_.Reset();
     servername_.Reset();
 #endif
   }
@@ -338,6 +315,7 @@ class Connection : public SSLWrap<Connection>, public AsyncWrap {
 
 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
   v8::Persistent<v8::Object> sniObject_;
+  v8::Persistent<v8::Value> sniContext_;
   v8::Persistent<v8::String> servername_;
 #endif
 
diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc
index d7bf4ed..68c98d5 100644
--- a/src/tls_wrap.cc
+++ b/src/tls_wrap.cc
@@ -141,8 +141,6 @@ void TLSWrap::InitSSL() {
 
   InitNPN(sc_);
 
-  SSL_set_cert_cb(ssl_, SSLWrap<TLSWrap>::SSLCertCallback, this);
-
   if (is_server()) {
     SSL_set_accept_state(ssl_);
   } else if (is_client()) {
@@ -353,7 +351,6 @@ Local<Value> TLSWrap::GetSSLError(int status, int* err, const char** msg) {
     case SSL_ERROR_NONE:
     case SSL_ERROR_WANT_READ:
     case SSL_ERROR_WANT_WRITE:
-    case SSL_ERROR_WANT_X509_LOOKUP:
       break;
     case SSL_ERROR_ZERO_RETURN:
       return scope.Escape(env()->zero_return_string());
@@ -761,6 +758,12 @@ void TLSWrap::EnableSessionCallbacks(
         "EnableSessionCallbacks after destroySSL");
   }
   wrap->enable_session_callbacks();
+  EnableHelloParser(args);
+}
+
+
+void TLSWrap::EnableHelloParser(const FunctionCallbackInfo<Value>& args) {
+  TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder());
   NodeBIO::FromBIO(wrap->enc_in_)->set_initial(kMaxHelloLength);
   wrap->hello_parser_.Start(SSLWrap<TLSWrap>::OnClientHello,
                             OnClientHelloParseEnd,
@@ -785,12 +788,6 @@ void TLSWrap::DestroySSL(const FunctionCallbackInfo<Value>& args) {
 }
 
 
-void TLSWrap::EnableCertCb(const FunctionCallbackInfo<Value>& args) {
-  TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder());
-  wrap->WaitForCertCb(OnClientHelloParseEnd, wrap);
-}
-
-
 void TLSWrap::OnClientHelloParseEnd(void* arg) {
   TLSWrap* c = static_cast<TLSWrap*>(arg);
   c->Cycle();
@@ -867,7 +864,8 @@ int TLSWrap::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
   p->sni_context_.Reset(env->isolate(), ctx);
 
   SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>());
-  p->SetSNIContext(sc);
+  InitNPN(sc);
+  SSL_set_SSL_CTX(s, sc->ctx_);
   return SSL_TLSEXT_ERR_OK;
 }
 #endif  // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
@@ -888,8 +886,8 @@ void TLSWrap::Initialize(Local<Object> target,
   env->SetProtoMethod(t, "start", Start);
   env->SetProtoMethod(t, "setVerifyMode", SetVerifyMode);
   env->SetProtoMethod(t, "enableSessionCallbacks", EnableSessionCallbacks);
+  env->SetProtoMethod(t, "enableHelloParser", EnableHelloParser);
   env->SetProtoMethod(t, "destroySSL", DestroySSL);
-  env->SetProtoMethod(t, "enableCertCb", EnableCertCb);
 
   StreamBase::AddMethods<TLSWrap>(env, t, StreamBase::kFlagHasWritev);
   SSLWrap<TLSWrap>::AddMethods(env, t);
diff --git a/src/tls_wrap.h b/src/tls_wrap.h
index 31d1952..a4aa3f7 100644
--- a/src/tls_wrap.h
+++ b/src/tls_wrap.h
@@ -132,7 +132,7 @@ class TLSWrap : public AsyncWrap,
   static void SetVerifyMode(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void EnableSessionCallbacks(
       const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void EnableCertCb(
+  static void EnableHelloParser(
       const v8::FunctionCallbackInfo<v8::Value>& args);
   static void DestroySSL(const v8::FunctionCallbackInfo<v8::Value>& args);
 
@@ -161,6 +161,10 @@ class TLSWrap : public AsyncWrap,
   // If true - delivered EOF to the js-land, either after `close_notify`, or
   // after the `UV_EOF` on socket.
   bool eof_;
+
+#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
+  v8::Persistent<v8::Value> sni_context_;
+#endif  // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
 };
 
 }  // namespace node
diff --git a/test/fixtures/keys/Makefile b/test/fixtures/keys/Makefile
index 1148e52..1439862 100644
--- a/test/fixtures/keys/Makefile
+++ b/test/fixtures/keys/Makefile
@@ -79,14 +79,6 @@ agent1-cert.pem: agent1-csr.pem ca1-cert.pem ca1-key.pem
 		-CAcreateserial \
 		-out agent1-cert.pem
 
-agent1-pfx.pem: agent1-cert.pem agent1-key.pem ca1-cert.pem
-	openssl pkcs12 -export \
-		-in agent1-cert.pem \
-		-inkey agent1-key.pem \
-		-certfile ca1-cert.pem \
-		-out agent1-pfx.pem \
-		-password pass:sample
-
 agent1-verify: agent1-cert.pem ca1-cert.pem
 	openssl verify -CAfile ca1-cert.pem agent1-cert.pem
 
diff --git a/test/parallel/test-tls-ocsp-callback.js b/test/parallel/test-tls-ocsp-callback.js
index e9443f4..64b6a6c 100644
--- a/test/parallel/test-tls-ocsp-callback.js
+++ b/test/parallel/test-tls-ocsp-callback.js
@@ -22,7 +22,11 @@ var constants = require('constants');
 var fs = require('fs');
 var join = require('path').join;
 
-var pfx = fs.readFileSync(join(common.fixturesDir, 'keys', 'agent1-pfx.pem'));
+test({ response: false }, function() {
+  test({ response: 'hello world' }, function() {
+    test({ ocsp: false });
+  });
+});
 
 function test(testOptions, cb) {
 
@@ -42,13 +46,6 @@ function test(testOptions, cb) {
   var ocspCount = 0;
   var ocspResponse;
 
-  if (testOptions.pfx) {
-    delete options.key;
-    delete options.cert;
-    options.pfx = testOptions.pfx;
-    options.passphrase = testOptions.passphrase;
-  }
-
   var server = tls.createServer(options, function(cleartext) {
     cleartext.on('error', function(er) {
       // We're ok with getting ECONNRESET in this test, but it's
@@ -108,23 +105,3 @@ function test(testOptions, cb) {
     assert.equal(ocspCount, 1);
   });
 }
-
-var tests = [
-  { response: false },
-  { response: 'hello world' },
-  { ocsp: false }
-];
-
-if (!common.hasFipsCrypto) {
-  tests.push({ pfx: pfx, passphrase: 'sample', response: 'hello pfx' });
-}
-
-function runTests(i) {
-  if (i === tests.length) return;
-
-  test(tests[i], common.mustCall(function() {
-    runTests(i + 1);
-  }));
-}
-
-runTests(0);
diff --git a/test/parallel/test-tls-sni-option.js b/test/parallel/test-tls-sni-option.js
index 510b929..5b0bd53 100644
--- a/test/parallel/test-tls-sni-option.js
+++ b/test/parallel/test-tls-sni-option.js
@@ -26,8 +26,6 @@ function loadPEM(n) {
 var serverOptions = {
   key: loadPEM('agent2-key'),
   cert: loadPEM('agent2-cert'),
-  requestCert: true,
-  rejectUnauthorized: false,
   SNICallback: function(servername, callback) {
     var context = SNIContexts[servername];
 
@@ -48,8 +46,7 @@ var serverOptions = {
 var SNIContexts = {
   'a.example.com': {
     key: loadPEM('agent1-key'),
-    cert: loadPEM('agent1-cert'),
-    ca: [ loadPEM('ca2-cert') ]
+    cert: loadPEM('agent1-cert')
   },
   'b.example.com': {
     key: loadPEM('agent3-key'),
@@ -71,13 +68,6 @@ var clientsOptions = [{
   rejectUnauthorized: false
 }, {
   port: serverPort,
-  key: loadPEM('agent4-key'),
-  cert: loadPEM('agent4-cert'),
-  ca: [loadPEM('ca1-cert')],
-  servername: 'a.example.com',
-  rejectUnauthorized: false
-}, {
-  port: serverPort,
   key: loadPEM('agent2-key'),
   cert: loadPEM('agent2-cert'),
   ca: [loadPEM('ca2-cert')],
@@ -107,7 +97,7 @@ let serverError;
 let clientError;
 
 var server = tls.createServer(serverOptions, function(c) {
-  serverResults.push({ sni: c.servername, authorized: c.authorized });
+  serverResults.push(c.servername);
 });
 
 server.on('clientError', function(err) {
@@ -154,16 +144,9 @@ function startTest() {
 }
 
 process.on('exit', function() {
-  assert.deepEqual(serverResults, [
-    { sni: 'a.example.com', authorized: false },
-    { sni: 'a.example.com', authorized: true },
-    { sni: 'b.example.com', authorized: false },
-    { sni: 'c.wrong.com', authorized: false },
-    null
-  ]);
-  assert.deepEqual(clientResults, [true, true, true, false, false]);
-  assert.deepEqual(clientErrors, [null, null, null, null, 'socket hang up']);
-  assert.deepEqual(serverErrors, [
-    null, null, null, null, 'Invalid SNI context'
-  ]);
+  assert.deepEqual(serverResults, ['a.example.com', 'b.example.com',
+                                   'c.wrong.com', null]);
+  assert.deepEqual(clientResults, [true, true, false, false]);
+  assert.deepEqual(clientErrors, [null, null, null, 'socket hang up']);
+  assert.deepEqual(serverErrors, [null, null, null, 'Invalid SNI context']);
 });
