wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
                     int sockindex)
{
  int ret = -1;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  struct ssl_backend_data *backend = connssl->backend;
#ifndef CURL_DISABLE_PROXY
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
  const char * const dispname = SSL_IS_PROXY() ?
    conn->http_proxy.host.dispname : conn->host.dispname;
  const char * const pinnedpubkey = SSL_IS_PROXY() ?
    data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
    data->set.str[STRING_SSL_PINNEDPUBLICKEY];
#else
  const char * const hostname = conn->host.name;
  const char * const dispname = conn->host.dispname;
  const char * const pinnedpubkey =
    data->set.str[STRING_SSL_PINNEDPUBLICKEY];
#endif

  conn->recv[sockindex] = wolfssl_recv;
  conn->send[sockindex] = wolfssl_send;

  /* Enable RFC2818 checks */
  if(SSL_CONN_CONFIG(verifyhost)) {
    ret = wolfSSL_check_domain_name(backend->handle, hostname);
    if(ret == SSL_FAILURE)
      return CURLE_OUT_OF_MEMORY;
  }

  ret = SSL_connect(backend->handle);

#ifdef OPENSSL_EXTRA
  if(Curl_tls_keylog_enabled()) {
    /* If key logging is enabled, wait for the handshake to complete and then
     * proceed with logging secrets (for TLS 1.2 or older).
     *
     * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
     * for the server response. At that point the master secret is not yet
     * available, so we must not try to read it.
     * To log the secret on completion with a handshake failure, detect
     * completion via the observation that there is nothing to read or write.
     * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
     * changes, the worst case is that no key is logged on error.
     */
    if(ret == SSL_SUCCESS ||
       (!wolfSSL_want_read(backend->handle) &&
        !wolfSSL_want_write(backend->handle))) {
      wolfssl_log_tls12_secret(backend->handle);
      /* Client Random and master secrets are no longer needed, erase these.
       * Ignored while the handshake is still in progress. */
      wolfSSL_FreeArrays(backend->handle);
    }
  }
#endif  /* OPENSSL_EXTRA */

  if(ret != 1) {
    char error_buffer[WOLFSSL_MAX_ERROR_SZ];
    int  detail = SSL_get_error(backend->handle, ret);

    if(SSL_ERROR_WANT_READ == detail) {
      connssl->connecting_state = ssl_connect_2_reading;
      return CURLE_OK;
    }
    else if(SSL_ERROR_WANT_WRITE == detail) {
      connssl->connecting_state = ssl_connect_2_writing;
      return CURLE_OK;
    }
    /* There is no easy way to override only the CN matching.
     * This will enable the override of both mismatching SubjectAltNames
     * as also mismatching CN fields */
    else if(DOMAIN_NAME_MISMATCH == detail) {
#if 1
      failf(data, "\tsubject alt name(s) or common name do not match \"%s\"",
            dispname);
      return CURLE_PEER_FAILED_VERIFICATION;
#else
      /* When the wolfssl_check_domain_name() is used and you desire to
       * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost
       * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
       * error. The only way to do this is currently to switch the
       * Wolfssl_check_domain_name() in and out based on the
       * 'conn->ssl_config.verifyhost' value. */
      if(SSL_CONN_CONFIG(verifyhost)) {
        failf(data,
              "\tsubject alt name(s) or common name do not match \"%s\"\n",
              dispname);
        return CURLE_PEER_FAILED_VERIFICATION;
      }
      else {
        infof(data,
              "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
              dispname);
        return CURLE_OK;
      }
#endif
    }
#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
    else if(ASN_NO_SIGNER_E == detail) {
      if(SSL_CONN_CONFIG(verifypeer)) {
        failf(data, "\tCA signer not available for verification");
        return CURLE_SSL_CACERT_BADFILE;
      }
      else {
        /* Just continue with a warning if no strict certificate
           verification is required. */
        infof(data, "CA signer not available for verification, "
                    "continuing anyway\n");
      }
    }
#endif
    else {
      failf(data, "SSL_connect failed with error %d: %s", detail,
          ERR_error_string(detail, error_buffer));
      return CURLE_SSL_CONNECT_ERROR;
    }
  }

  if(pinnedpubkey) {
#ifdef KEEP_PEER_CERT
    X509 *x509;
    const char *x509_der;
    int x509_der_len;
    struct Curl_X509certificate x509_parsed;
    struct Curl_asn1Element *pubkey;
    CURLcode result;

    x509 = SSL_get_peer_certificate(backend->handle);
    if(!x509) {
      failf(data, "SSL: failed retrieving server certificate");
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
    if(!x509_der) {
      failf(data, "SSL: failed retrieving ASN.1 server certificate");
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    memset(&x509_parsed, 0, sizeof(x509_parsed));
    if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;

    pubkey = &x509_parsed.subjectPublicKeyInfo;
    if(!pubkey->header || pubkey->end <= pubkey->header) {
      failf(data, "SSL: failed retrieving public key from server certificate");
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    result = Curl_pin_peer_pubkey(data,
                                  pinnedpubkey,
                                  (const unsigned char *)pubkey->header,
                                  (size_t)(pubkey->end - pubkey->header));
    if(result) {
      failf(data, "SSL: public key does not match pinned public key!");
      return result;
    }
#else
    failf(data, "Library lacks pinning support built-in");
    return CURLE_NOT_BUILT_IN;
#endif
  }

#ifdef HAVE_ALPN
  if(conn->bits.tls_enable_alpn) {
    int rc;
    char *protocol = NULL;
    unsigned short protocol_len = 0;

    rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);

    if(rc == SSL_SUCCESS) {
      infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
            protocol);

      if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
         !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
        conn->negnpn = CURL_HTTP_VERSION_1_1;
#ifdef USE_NGHTTP2
      else if(data->state.httpversion >= CURL_HTTP_VERSION_2 &&
              protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
              !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID,
                      NGHTTP2_PROTO_VERSION_ID_LEN))
        conn->negnpn = CURL_HTTP_VERSION_2;
#endif
      else
        infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
              protocol);
      Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
                          BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
    }
    else if(rc == SSL_ALPN_NOT_FOUND)
      infof(data, "ALPN, server did not agree to a protocol\n");
    else {
      failf(data, "ALPN, failure getting protocol, error %d", rc);
      return CURLE_SSL_CONNECT_ERROR;
    }
  }
#endif /* HAVE_ALPN */

  connssl->connecting_state = ssl_connect_3;
#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
  infof(data, "SSL connection using %s / %s\n",
        wolfSSL_get_version(backend->handle),
        wolfSSL_get_cipher_name(backend->handle));
#else
  infof(data, "SSL connected\n");
#endif

  return CURLE_OK;
}