Imported Upstream version 7.59.0
[platform/upstream/curl.git] / lib / vtls / gskit.c
index a0d462b..afc90a8 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -61,9 +61,7 @@
 #endif
 
 
-#ifdef HAVE_LIMITS_H
-#  include <limits.h>
-#endif
+#include <limits.h>
 
 #include <curl/curl.h>
 #include "urldata.h"
 #define CURL_GSKPROTO_TLSV12_MASK        (1 << CURL_GSKPROTO_TLSV12)
 #define CURL_GSKPROTO_LAST      5
 
+struct ssl_backend_data {
+  gsk_handle handle;
+  int iocport;
+  int localfd;
+  int remotefd;
+};
+
+#define BACKEND connssl->backend
 
 /* Supported ciphers. */
 typedef struct {
@@ -320,7 +326,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
 
   /* We allocate GSKit buffers of the same size as the input string: since
      GSKit tokens are always shorter than their cipher names, allocated buffers
-     will always be large enough to accomodate the result. */
+     will always be large enough to accommodate the result. */
   l = strlen(cipherlist) + 1;
   memset((char *) ciphers, 0, sizeof ciphers);
   for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
@@ -427,7 +433,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
 }
 
 
-int Curl_gskit_init(void)
+static int Curl_gskit_init(void)
 {
   /* No initialisation needed. */
 
@@ -435,7 +441,7 @@ int Curl_gskit_init(void)
 }
 
 
-void Curl_gskit_cleanup(void)
+static void Curl_gskit_cleanup(void)
 {
   /* Nothing to do. */
 }
@@ -495,14 +501,14 @@ static void cancel_async_handshake(struct connectdata *conn, int sockindex)
   Qso_OverlappedIO_t cstat;
 
   if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
-    QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
+    QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
 }
 
 
 static void close_async_handshake(struct ssl_connect_data *connssl)
 {
-  QsoDestroyIOCompletionPort(connssl->iocport);
-  connssl->iocport = -1;
+  QsoDestroyIOCompletionPort(BACKEND->iocport);
+  BACKEND->iocport = -1;
 }
 
 /* SSL over SSL
@@ -620,12 +626,12 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
   FD_ZERO(&fds_write);
   n = -1;
   if(directions & SOS_READ) {
-    FD_SET(connssl->remotefd, &fds_write);
-    n = connssl->remotefd;
+    FD_SET(BACKEND->remotefd, &fds_write);
+    n = BACKEND->remotefd;
   }
   if(directions & SOS_WRITE) {
-    FD_SET(connssl->remotefd, &fds_read);
-    n = connssl->remotefd;
+    FD_SET(BACKEND->remotefd, &fds_read);
+    n = BACKEND->remotefd;
     FD_SET(conn->sock[sockindex], &fds_write);
     if(n < conn->sock[sockindex])
       n = conn->sock[sockindex];
@@ -634,14 +640,15 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
   if(i < 0)
     return -1;  /* Select error. */
 
-  if(FD_ISSET(connssl->remotefd, &fds_write)) {
+  if(FD_ISSET(BACKEND->remotefd, &fds_write)) {
     /* Try getting data from HTTPS proxy and pipe it upstream. */
     n = 0;
-    i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
+    i = gsk_secure_soc_read(connproxyssl->backend->handle,
+                            buf, sizeof buf, &n);
     switch(i) {
     case GSK_OK:
       if(n) {
-        i = write(connssl->remotefd, buf, n);
+        i = write(BACKEND->remotefd, buf, n);
         if(i < 0)
           return -1;
         ret = 1;
@@ -655,14 +662,14 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
     }
   }
 
-  if(FD_ISSET(connssl->remotefd, &fds_read) &&
+  if(FD_ISSET(BACKEND->remotefd, &fds_read) &&
      FD_ISSET(conn->sock[sockindex], &fds_write)) {
     /* Pipe data to HTTPS proxy. */
-    n = read(connssl->remotefd, buf, sizeof buf);
+    n = read(BACKEND->remotefd, buf, sizeof buf);
     if(n < 0)
       return -1;
     if(n) {
-      i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
+      i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
       if(i != GSK_OK || n != m)
         return -1;
       ret = 1;
@@ -676,23 +683,23 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
 static void close_one(struct ssl_connect_data *connssl,
                       struct connectdata *conn, int sockindex)
 {
-  if(connssl->handle) {
-    gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
+  if(BACKEND->handle) {
+    gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
               "gsk_secure_soc_close()", 0);
     /* Last chance to drain output. */
     while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
       ;
-    connssl->handle = (gsk_handle) NULL;
-    if(connssl->localfd >= 0) {
-      close(connssl->localfd);
-      connssl->localfd = -1;
+    BACKEND->handle = (gsk_handle) NULL;
+    if(BACKEND->localfd >= 0) {
+      close(BACKEND->localfd);
+      BACKEND->localfd = -1;
     }
-    if(connssl->remotefd >= 0) {
-      close(connssl->remotefd);
-      connssl->remotefd = -1;
+    if(BACKEND->remotefd >= 0) {
+      close(BACKEND->remotefd);
+      BACKEND->remotefd = -1;
     }
   }
-  if(connssl->iocport >= 0)
+  if(BACKEND->iocport >= 0)
     close_async_handshake(connssl);
 }
 
@@ -700,13 +707,14 @@ static void close_one(struct ssl_connect_data *connssl,
 static ssize_t gskit_send(struct connectdata *conn, int sockindex,
                            const void *mem, size_t len, CURLcode *curlcode)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct Curl_easy *data = conn->data;
   CURLcode cc = CURLE_SEND_ERROR;
   int written;
 
   if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
     cc = gskit_status(data,
-                      gsk_secure_soc_write(conn->ssl[sockindex].handle,
+                      gsk_secure_soc_write(BACKEND->handle,
                                            (char *) mem, (int) len, &written),
                       "gsk_secure_soc_write()", CURLE_SEND_ERROR);
     if(cc == CURLE_OK)
@@ -724,6 +732,7 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
 static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
                            size_t buffersize, CURLcode *curlcode)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[num];
   struct Curl_easy *data = conn->data;
   int buffsize;
   int nread;
@@ -731,7 +740,7 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
 
   if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
     buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
-    cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+    cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
                                                 buf, buffsize, &nread),
                       "gsk_secure_soc_read()", CURLE_RECV_ERROR);
   }
@@ -748,6 +757,40 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
   return (ssize_t) nread;
 }
 
+static CURLcode
+set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
+{
+  struct Curl_easy *data = conn->data;
+  long ssl_version = SSL_CONN_CONFIG(version);
+  long ssl_version_max = SSL_CONN_CONFIG(version_max);
+  long i = ssl_version;
+  switch(ssl_version_max) {
+    case CURL_SSLVERSION_MAX_NONE:
+      ssl_version_max = ssl_version;
+      break;
+    case CURL_SSLVERSION_MAX_DEFAULT:
+      ssl_version_max = CURL_SSLVERSION_TLSv1_2;
+      break;
+  }
+  for(; i <= (ssl_version_max >> 16); ++i) {
+    switch(i) {
+      case CURL_SSLVERSION_TLSv1_0:
+        *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
+        break;
+      case CURL_SSLVERSION_TLSv1_1:
+        *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
+        break;
+      case CURL_SSLVERSION_TLSv1_2:
+        *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
+        break;
+      case CURL_SSLVERSION_TLSv1_3:
+        failf(data, "GSKit: TLS 1.3 is not yet supported");
+        return CURLE_SSL_CONNECT_ERROR;
+    }
+  }
+
+  return CURLE_OK;
+}
 
 static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
 {
@@ -764,7 +807,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
     conn->host.name;
   const char *sni;
-  unsigned int protoflags;
+  unsigned int protoflags = 0;
   long timeout;
   Qso_OverlappedIO_t commarea;
   int sockpair[2];
@@ -772,10 +815,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
 
   /* Create SSL environment, start (preferably asynchronous) handshake. */
 
-  connssl->handle = (gsk_handle) NULL;
-  connssl->iocport = -1;
-  connssl->localfd = -1;
-  connssl->remotefd = -1;
+  BACKEND->handle = (gsk_handle) NULL;
+  BACKEND->iocport = -1;
+  BACKEND->localfd = -1;
+  BACKEND->remotefd = -1;
 
   /* GSKit supports two ways of specifying an SSL context: either by
    *  application identifier (that should have been defined at the system
@@ -808,7 +851,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   }
 
   /* Create secure session. */
-  result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
+  result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
                         "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
   gsk_environment_close(&envir);
   if(result)
@@ -818,18 +861,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   if(conn->proxy_ssl[sockindex].use) {
     if(inetsocketpair(sockpair))
       return CURLE_SSL_CONNECT_ERROR;
-    connssl->localfd = sockpair[0];
-    connssl->remotefd = sockpair[1];
-    setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
+    BACKEND->localfd = sockpair[0];
+    BACKEND->remotefd = sockpair[1];
+    setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
                (void *) sobufsize, sizeof sobufsize);
-    setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
+    setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
                (void *) sobufsize, sizeof sobufsize);
-    setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
+    setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
                (void *) sobufsize, sizeof sobufsize);
-    setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
+    setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
                (void *) sobufsize, sizeof sobufsize);
-    curlx_nonblock(connssl->localfd, TRUE);
-    curlx_nonblock(connssl->remotefd, TRUE);
+    curlx_nonblock(BACKEND->localfd, TRUE);
+    curlx_nonblock(BACKEND->remotefd, TRUE);
   }
 
   /* Determine which SSL/TLS version should be enabled. */
@@ -849,17 +892,13 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
                  CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
     break;
   case CURL_SSLVERSION_TLSv1_0:
-    protoflags = CURL_GSKPROTO_TLSV10_MASK;
-    break;
   case CURL_SSLVERSION_TLSv1_1:
-    protoflags = CURL_GSKPROTO_TLSV11_MASK;
-    break;
   case CURL_SSLVERSION_TLSv1_2:
-    protoflags = CURL_GSKPROTO_TLSV12_MASK;
-    break;
   case CURL_SSLVERSION_TLSv1_3:
-    failf(data, "GSKit: TLS 1.3 is not yet supported");
-    return CURLE_SSL_CONNECT_ERROR;
+    result = set_ssl_version_min_max(&protoflags, conn);
+    if(result != CURLE_OK)
+      return result;
+    break;
   default:
     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
     return CURLE_SSL_CONNECT_ERROR;
@@ -867,7 +906,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
 
   /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
   if(sni) {
-    result = set_buffer(data, connssl->handle,
+    result = set_buffer(data, BACKEND->handle,
                         GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
     if(result == CURLE_UNSUPPORTED_PROTOCOL)
       result = CURLE_OK;
@@ -881,34 +920,34 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     if(timeout < 0)
       result = CURLE_OPERATION_TIMEDOUT;
     else
-      result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
+      result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
                            (timeout + 999) / 1000);
   }
   if(!result)
-    result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
+    result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
   if(!result)
-    result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
-                         connssl->localfd: conn->sock[sockindex]);
+    result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
+                         BACKEND->localfd: conn->sock[sockindex]);
   if(!result)
-    result = set_ciphers(conn, connssl->handle, &protoflags);
+    result = set_ciphers(conn, BACKEND->handle, &protoflags);
   if(!protoflags) {
     failf(data, "No SSL protocol/cipher combination enabled");
     result = CURLE_SSL_CIPHER;
   }
   if(!result)
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
                       (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
                       GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
   if(!result)
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
                       (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
                       GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
   if(!result)
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
                       (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
                       GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
   if(!result) {
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
                       (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
                       GSK_TRUE: GSK_FALSE, TRUE);
     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -920,7 +959,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     }
   }
   if(!result) {
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
                       (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
                       GSK_TRUE: GSK_FALSE, TRUE);
     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -932,18 +971,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     }
   }
   if(!result)
-    result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
+    result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
                       verifypeer? GSK_SERVER_AUTH_FULL:
                       GSK_SERVER_AUTH_PASSTHRU, FALSE);
 
   if(!result) {
     /* Start handshake. Try asynchronous first. */
     memset(&commarea, 0, sizeof commarea);
-    connssl->iocport = QsoCreateIOCompletionPort();
-    if(connssl->iocport != -1) {
+    BACKEND->iocport = QsoCreateIOCompletionPort();
+    if(BACKEND->iocport != -1) {
       result = gskit_status(data,
-                            gsk_secure_soc_startInit(connssl->handle,
-                                                     connssl->iocport,
+                            gsk_secure_soc_startInit(BACKEND->handle,
+                                                     BACKEND->iocport,
                                                      &commarea),
                             "gsk_secure_soc_startInit()",
                             CURLE_SSL_CONNECT_ERROR);
@@ -963,7 +1002,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     }
     else {
       /* No more completion port available. Use synchronous IO. */
-      result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
+      result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
                             "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
       if(!result) {
         connssl->connecting_state = ssl_connect_3;
@@ -996,7 +1035,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
       timeout_ms = 0;
     stmv.tv_sec = timeout_ms / 1000;
     stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
-    switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+    switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat, &stmv)) {
     case 1:             /* Operation complete. */
       break;
     case -1:            /* An error occurred: handshake still in progress. */
@@ -1045,7 +1084,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
 
   /* SSL handshake done: gather certificate info and verify host. */
 
-  if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
+  if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
                                                     GSK_PARTNER_CERT_INFO,
                                                     &cdev, &cdec),
                   "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
@@ -1186,9 +1225,8 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
 }
 
 
-CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
-                                        int sockindex,
-                                        bool *done)
+static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
+                                               int sockindex, bool *done)
 {
   CURLcode result;
 
@@ -1199,7 +1237,7 @@ CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
 }
 
 
-CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done;
@@ -1215,14 +1253,14 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
 }
 
 
-void Curl_gskit_close(struct connectdata *conn, int sockindex)
+static void Curl_gskit_close(struct connectdata *conn, int sockindex)
 {
   close_one(&conn->ssl[sockindex], conn, sockindex);
   close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
 }
 
 
-int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct Curl_easy *data = conn->data;
@@ -1231,7 +1269,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
   int rc;
   char buf[120];
 
-  if(!connssl->handle)
+  if(!BACKEND->handle)
     return 0;
 
   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@@ -1276,21 +1314,22 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
 }
 
 
-size_t Curl_gskit_version(char *buffer, size_t size)
+static size_t Curl_gskit_version(char *buffer, size_t size)
 {
   strncpy(buffer, "GSKit", size);
   return strlen(buffer);
 }
 
 
-int Curl_gskit_check_cxn(struct connectdata *cxn)
+static int Curl_gskit_check_cxn(struct connectdata *cxn)
 {
+  struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
   int err;
   int errlen;
 
   /* The only thing that can be tested here is at the socket level. */
 
-  if(!cxn->ssl[FIRSTSOCKET].handle)
+  if(!BACKEND->handle)
     return 0; /* connection has been closed */
 
   err = 0;
@@ -1304,4 +1343,46 @@ int Curl_gskit_check_cxn(struct connectdata *cxn)
   return -1;  /* connection status unknown */
 }
 
+static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
+                                      CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_gskit = {
+  { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
+
+  0, /* have_ca_path */
+  1, /* have_certinfo */
+  1, /* have_pinnedpubkey */
+  0, /* have_ssl_ctx */
+  /* TODO: convert to 1 and fix test #1014 (if need) */
+  0, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_gskit_init,                /* init */
+  Curl_gskit_cleanup,             /* cleanup */
+  Curl_gskit_version,             /* version */
+  Curl_gskit_check_cxn,           /* check_cxn */
+  Curl_gskit_shutdown,            /* shutdown */
+  Curl_none_data_pending,         /* data_pending */
+  Curl_none_random,               /* random */
+  Curl_none_cert_status_request,  /* cert_status_request */
+  Curl_gskit_connect,             /* connect */
+  Curl_gskit_connect_nonblocking, /* connect_nonblocking */
+  Curl_gskit_get_internals,       /* get_internals */
+  Curl_gskit_close,               /* close_one */
+  Curl_none_close_all,            /* close_all */
+  /* No session handling for GSKit */
+  Curl_none_session_free,         /* session_free */
+  Curl_none_set_engine,           /* set_engine */
+  Curl_none_set_engine_default,   /* set_engine_default */
+  Curl_none_engines_list,         /* engines_list */
+  Curl_none_false_start,          /* false_start */
+  Curl_none_md5sum,               /* md5sum */
+  NULL                            /* sha256sum */
+};
+
 #endif /* USE_GSKIT */