Home | History | Annotate | Download | only in vtls
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 
     23 /*
     24  * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
     25  * but vtls.c should ever call or use these functions.
     26  *
     27  * Note: don't use the GnuTLS' *_t variable type names in this source code,
     28  * since they were not present in 1.0.X.
     29  */
     30 
     31 #include "curl_setup.h"
     32 
     33 #ifdef USE_GNUTLS
     34 
     35 #include <gnutls/abstract.h>
     36 #include <gnutls/gnutls.h>
     37 #include <gnutls/x509.h>
     38 
     39 #ifdef USE_GNUTLS_NETTLE
     40 #include <gnutls/crypto.h>
     41 #include <nettle/md5.h>
     42 #include <nettle/sha2.h>
     43 #else
     44 #include <gcrypt.h>
     45 #endif
     46 
     47 #include "urldata.h"
     48 #include "sendf.h"
     49 #include "inet_pton.h"
     50 #include "gtls.h"
     51 #include "vtls.h"
     52 #include "parsedate.h"
     53 #include "connect.h" /* for the connect timeout */
     54 #include "select.h"
     55 #include "strcase.h"
     56 #include "warnless.h"
     57 #include "x509asn1.h"
     58 #include "curl_printf.h"
     59 #include "curl_memory.h"
     60 /* The last #include file should be: */
     61 #include "memdebug.h"
     62 
     63 #ifndef GNUTLS_POINTER_TO_SOCKET_CAST
     64 #define GNUTLS_POINTER_TO_SOCKET_CAST(p) \
     65   ((curl_socket_t) ((char *)(p) - (char *)NULL))
     66 #endif
     67 #ifndef GNUTLS_SOCKET_TO_POINTER_CAST
     68 #define GNUTLS_SOCKET_TO_POINTER_CAST(s) \
     69   ((void *) ((char *)NULL + (s)))
     70 #endif
     71 
     72 /* Enable GnuTLS debugging by defining GTLSDEBUG */
     73 /*#define GTLSDEBUG */
     74 
     75 #ifdef GTLSDEBUG
     76 static void tls_log_func(int level, const char *str)
     77 {
     78     fprintf(stderr, "|<%d>| %s", level, str);
     79 }
     80 #endif
     81 static bool gtls_inited = FALSE;
     82 
     83 #if defined(GNUTLS_VERSION_NUMBER)
     84 #  if (GNUTLS_VERSION_NUMBER >= 0x020c00)
     85 #    undef gnutls_transport_set_lowat
     86 #    define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
     87 #    define USE_GNUTLS_PRIORITY_SET_DIRECT 1
     88 #  endif
     89 #  if (GNUTLS_VERSION_NUMBER >= 0x020c03)
     90 #    define GNUTLS_MAPS_WINSOCK_ERRORS 1
     91 #  endif
     92 
     93 #  if HAVE_GNUTLS_ALPN_SET_PROTOCOLS
     94 #    define HAS_ALPN
     95 #  endif
     96 
     97 #  if HAVE_GNUTLS_OCSP_REQ_INIT
     98 #    define HAS_OCSP
     99 #  endif
    100 
    101 #  if (GNUTLS_VERSION_NUMBER >= 0x030306)
    102 #    define HAS_CAPATH
    103 #  endif
    104 #endif
    105 
    106 #ifdef HAS_OCSP
    107 # include <gnutls/ocsp.h>
    108 #endif
    109 
    110 struct ssl_backend_data {
    111   gnutls_session_t session;
    112   gnutls_certificate_credentials_t cred;
    113 #ifdef USE_TLS_SRP
    114   gnutls_srp_client_credentials_t srp_client_cred;
    115 #endif
    116 };
    117 
    118 #define BACKEND connssl->backend
    119 
    120 /*
    121  * Custom push and pull callback functions used by GNU TLS to read and write
    122  * to the socket.  These functions are simple wrappers to send() and recv()
    123  * (although here using the sread/swrite macros as defined by
    124  * curl_setup_once.h).
    125  * We use custom functions rather than the GNU TLS defaults because it allows
    126  * us to get specific about the fourth "flags" argument, and to use arbitrary
    127  * private data with gnutls_transport_set_ptr if we wish.
    128  *
    129  * When these custom push and pull callbacks fail, GNU TLS checks its own
    130  * session-specific error variable, and when not set also its own global
    131  * errno variable, in order to take appropriate action. GNU TLS does not
    132  * require that the transport is actually a socket. This implies that for
    133  * Windows builds these callbacks should ideally set the session-specific
    134  * error variable using function gnutls_transport_set_errno or as a last
    135  * resort global errno variable using gnutls_transport_set_global_errno,
    136  * with a transport agnostic error value. This implies that some winsock
    137  * error translation must take place in these callbacks.
    138  *
    139  * Paragraph above applies to GNU TLS versions older than 2.12.3, since
    140  * this version GNU TLS does its own internal winsock error translation
    141  * using system_errno() function.
    142  */
    143 
    144 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
    145 #  define gtls_EINTR  4
    146 #  define gtls_EIO    5
    147 #  define gtls_EAGAIN 11
    148 static int gtls_mapped_sockerrno(void)
    149 {
    150   switch(SOCKERRNO) {
    151   case WSAEWOULDBLOCK:
    152     return gtls_EAGAIN;
    153   case WSAEINTR:
    154     return gtls_EINTR;
    155   default:
    156     break;
    157   }
    158   return gtls_EIO;
    159 }
    160 #endif
    161 
    162 static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
    163 {
    164   ssize_t ret = swrite(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
    165 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
    166   if(ret < 0)
    167     gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
    168 #endif
    169   return ret;
    170 }
    171 
    172 static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
    173 {
    174   ssize_t ret = sread(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
    175 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
    176   if(ret < 0)
    177     gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
    178 #endif
    179   return ret;
    180 }
    181 
    182 static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
    183 {
    184   return gnutls_record_send((gnutls_session_t) s, buf, len);
    185 }
    186 
    187 static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
    188 {
    189   return gnutls_record_recv((gnutls_session_t) s, buf, len);
    190 }
    191 
    192 /* Curl_gtls_init()
    193  *
    194  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
    195  * are not thread-safe and thus this function itself is not thread-safe and
    196  * must only be called from within curl_global_init() to keep the thread
    197  * situation under control!
    198  */
    199 static int Curl_gtls_init(void)
    200 {
    201   int ret = 1;
    202   if(!gtls_inited) {
    203     ret = gnutls_global_init()?0:1;
    204 #ifdef GTLSDEBUG
    205     gnutls_global_set_log_function(tls_log_func);
    206     gnutls_global_set_log_level(2);
    207 #endif
    208     gtls_inited = TRUE;
    209   }
    210   return ret;
    211 }
    212 
    213 static void Curl_gtls_cleanup(void)
    214 {
    215   if(gtls_inited) {
    216     gnutls_global_deinit();
    217     gtls_inited = FALSE;
    218   }
    219 }
    220 
    221 #ifndef CURL_DISABLE_VERBOSE_STRINGS
    222 static void showtime(struct Curl_easy *data,
    223                      const char *text,
    224                      time_t stamp)
    225 {
    226   struct tm buffer;
    227   const struct tm *tm = &buffer;
    228   char str[96];
    229   CURLcode result = Curl_gmtime(stamp, &buffer);
    230   if(result)
    231     return;
    232 
    233   snprintf(str,
    234            sizeof(str),
    235            "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
    236            text,
    237            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
    238            tm->tm_mday,
    239            Curl_month[tm->tm_mon],
    240            tm->tm_year + 1900,
    241            tm->tm_hour,
    242            tm->tm_min,
    243            tm->tm_sec);
    244   infof(data, "%s\n", str);
    245 }
    246 #endif
    247 
    248 static gnutls_datum_t load_file(const char *file)
    249 {
    250   FILE *f;
    251   gnutls_datum_t loaded_file = { NULL, 0 };
    252   long filelen;
    253   void *ptr;
    254 
    255   f = fopen(file, "rb");
    256   if(!f)
    257     return loaded_file;
    258   if(fseek(f, 0, SEEK_END) != 0
    259      || (filelen = ftell(f)) < 0
    260      || fseek(f, 0, SEEK_SET) != 0
    261      || !(ptr = malloc((size_t)filelen)))
    262     goto out;
    263   if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
    264     free(ptr);
    265     goto out;
    266   }
    267 
    268   loaded_file.data = ptr;
    269   loaded_file.size = (unsigned int)filelen;
    270 out:
    271   fclose(f);
    272   return loaded_file;
    273 }
    274 
    275 static void unload_file(gnutls_datum_t data)
    276 {
    277   free(data.data);
    278 }
    279 
    280 
    281 /* this function does a SSL/TLS (re-)handshake */
    282 static CURLcode handshake(struct connectdata *conn,
    283                           int sockindex,
    284                           bool duringconnect,
    285                           bool nonblocking)
    286 {
    287   struct Curl_easy *data = conn->data;
    288   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    289   gnutls_session_t session = BACKEND->session;
    290   curl_socket_t sockfd = conn->sock[sockindex];
    291   time_t timeout_ms;
    292   int rc;
    293   int what;
    294 
    295   for(;;) {
    296     /* check allowed time left */
    297     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
    298 
    299     if(timeout_ms < 0) {
    300       /* no need to continue if time already is up */
    301       failf(data, "SSL connection timeout");
    302       return CURLE_OPERATION_TIMEDOUT;
    303     }
    304 
    305     /* if ssl is expecting something, check if it's available. */
    306     if(connssl->connecting_state == ssl_connect_2_reading
    307        || connssl->connecting_state == ssl_connect_2_writing) {
    308 
    309       curl_socket_t writefd = ssl_connect_2_writing ==
    310         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
    311       curl_socket_t readfd = ssl_connect_2_reading ==
    312         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
    313 
    314       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
    315                                nonblocking?0:
    316                                timeout_ms?timeout_ms:1000);
    317       if(what < 0) {
    318         /* fatal error */
    319         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
    320         return CURLE_SSL_CONNECT_ERROR;
    321       }
    322       else if(0 == what) {
    323         if(nonblocking)
    324           return CURLE_OK;
    325         else if(timeout_ms) {
    326           /* timeout */
    327           failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
    328           return CURLE_OPERATION_TIMEDOUT;
    329         }
    330       }
    331       /* socket is readable or writable */
    332     }
    333 
    334     rc = gnutls_handshake(session);
    335 
    336     if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
    337       connssl->connecting_state =
    338         gnutls_record_get_direction(session)?
    339         ssl_connect_2_writing:ssl_connect_2_reading;
    340       continue;
    341     }
    342     else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
    343       const char *strerr = NULL;
    344 
    345       if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
    346         int alert = gnutls_alert_get(session);
    347         strerr = gnutls_alert_get_name(alert);
    348       }
    349 
    350       if(strerr == NULL)
    351         strerr = gnutls_strerror(rc);
    352 
    353       infof(data, "gnutls_handshake() warning: %s\n", strerr);
    354       continue;
    355     }
    356     else if(rc < 0) {
    357       const char *strerr = NULL;
    358 
    359       if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
    360         int alert = gnutls_alert_get(session);
    361         strerr = gnutls_alert_get_name(alert);
    362       }
    363 
    364       if(strerr == NULL)
    365         strerr = gnutls_strerror(rc);
    366 
    367       failf(data, "gnutls_handshake() failed: %s", strerr);
    368       return CURLE_SSL_CONNECT_ERROR;
    369     }
    370 
    371     /* Reset our connect state machine */
    372     connssl->connecting_state = ssl_connect_1;
    373     return CURLE_OK;
    374   }
    375 }
    376 
    377 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
    378 {
    379   if(!type || !type[0])
    380     return GNUTLS_X509_FMT_PEM;
    381   if(strcasecompare(type, "PEM"))
    382     return GNUTLS_X509_FMT_PEM;
    383   if(strcasecompare(type, "DER"))
    384     return GNUTLS_X509_FMT_DER;
    385   return -1;
    386 }
    387 
    388 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
    389 static CURLcode
    390 set_ssl_version_min_max(int *list, size_t list_size, struct connectdata *conn)
    391 {
    392   struct Curl_easy *data = conn->data;
    393   long ssl_version = SSL_CONN_CONFIG(version);
    394   long ssl_version_max = SSL_CONN_CONFIG(version_max);
    395   long i = ssl_version;
    396   long protocol_priority_idx = 0;
    397 
    398   switch(ssl_version_max) {
    399     case CURL_SSLVERSION_MAX_NONE:
    400       ssl_version_max = ssl_version << 16;
    401       break;
    402     case CURL_SSLVERSION_MAX_DEFAULT:
    403       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
    404       break;
    405   }
    406 
    407   for(; i <= (ssl_version_max >> 16) &&
    408         protocol_priority_idx < list_size; ++i) {
    409     switch(i) {
    410       case CURL_SSLVERSION_TLSv1_0:
    411         protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0;
    412         break;
    413       case CURL_SSLVERSION_TLSv1_1:
    414         protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1;
    415         break;
    416       case CURL_SSLVERSION_TLSv1_2:
    417         protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2;
    418         break;
    419       case CURL_SSLVERSION_TLSv1_3:
    420         failf(data, "GnuTLS: TLS 1.3 is not yet supported");
    421         return CURLE_SSL_CONNECT_ERROR;
    422     }
    423   }
    424   return CURLE_OK;
    425 }
    426 #else
    427 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
    428 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
    429    requested in the priority string, so treat it specially
    430  */
    431 #define GNUTLS_SRP "+SRP"
    432 
    433 static CURLcode
    434 set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
    435 {
    436   struct Curl_easy *data = conn->data;
    437   long ssl_version = SSL_CONN_CONFIG(version);
    438   long ssl_version_max = SSL_CONN_CONFIG(version_max);
    439   if(ssl_version == CURL_SSLVERSION_TLSv1_3 ||
    440      ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) {
    441     failf(data, "GnuTLS: TLS 1.3 is not yet supported");
    442     return CURLE_SSL_CONNECT_ERROR;
    443   }
    444   if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
    445     ssl_version_max = ssl_version << 16;
    446   }
    447   switch(ssl_version | ssl_version_max) {
    448     case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
    449       *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    450                       "+VERS-TLS1.0:" GNUTLS_SRP;
    451       return CURLE_OK;
    452     case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
    453       *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    454                       "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP;
    455       return CURLE_OK;
    456     case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
    457     case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
    458       *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    459                       "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
    460       return CURLE_OK;
    461     case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
    462       *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    463                       "+VERS-TLS1.1:" GNUTLS_SRP;
    464       return CURLE_OK;
    465     case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
    466     case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
    467       *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    468                       "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
    469       return CURLE_OK;
    470     case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
    471     case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
    472       *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
    473                       "+VERS-TLS1.2:" GNUTLS_SRP;
    474       return CURLE_OK;
    475   }
    476 
    477   failf(data, "GnuTLS: cannot set ssl protocol");
    478   return CURLE_SSL_CONNECT_ERROR;
    479 }
    480 #endif
    481 
    482 static CURLcode
    483 gtls_connect_step1(struct connectdata *conn,
    484                    int sockindex)
    485 {
    486   struct Curl_easy *data = conn->data;
    487   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    488   unsigned int init_flags;
    489   gnutls_session_t session;
    490   int rc;
    491   bool sni = TRUE; /* default is SNI enabled */
    492   void *transport_ptr = NULL;
    493   gnutls_push_func gnutls_transport_push = NULL;
    494   gnutls_pull_func gnutls_transport_pull = NULL;
    495 #ifdef ENABLE_IPV6
    496   struct in6_addr addr;
    497 #else
    498   struct in_addr addr;
    499 #endif
    500 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
    501   static const int cipher_priority[] = {
    502   /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
    503      but this code path is only ever used for ver. < 2.12.0.
    504      GNUTLS_CIPHER_AES_128_GCM,
    505      GNUTLS_CIPHER_AES_256_GCM,
    506   */
    507     GNUTLS_CIPHER_AES_128_CBC,
    508     GNUTLS_CIPHER_AES_256_CBC,
    509     GNUTLS_CIPHER_CAMELLIA_128_CBC,
    510     GNUTLS_CIPHER_CAMELLIA_256_CBC,
    511     GNUTLS_CIPHER_3DES_CBC,
    512   };
    513   static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
    514   int protocol_priority[] = { 0, 0, 0, 0 };
    515 #else
    516   const char *prioritylist;
    517   const char *err = NULL;
    518 #endif
    519 
    520   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    521     conn->host.name;
    522 
    523   if(connssl->state == ssl_connection_complete)
    524     /* to make us tolerant against being called more than once for the
    525        same connection */
    526     return CURLE_OK;
    527 
    528   if(!gtls_inited)
    529     Curl_gtls_init();
    530 
    531   if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
    532     failf(data, "GnuTLS does not support SSLv2");
    533     return CURLE_SSL_CONNECT_ERROR;
    534   }
    535   else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
    536     sni = FALSE; /* SSLv3 has no SNI */
    537 
    538   /* allocate a cred struct */
    539   rc = gnutls_certificate_allocate_credentials(&BACKEND->cred);
    540   if(rc != GNUTLS_E_SUCCESS) {
    541     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
    542     return CURLE_SSL_CONNECT_ERROR;
    543   }
    544 
    545 #ifdef USE_TLS_SRP
    546   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
    547     infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
    548 
    549     rc = gnutls_srp_allocate_client_credentials(
    550            &BACKEND->srp_client_cred);
    551     if(rc != GNUTLS_E_SUCCESS) {
    552       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
    553             gnutls_strerror(rc));
    554       return CURLE_OUT_OF_MEMORY;
    555     }
    556 
    557     rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred,
    558                                            SSL_SET_OPTION(username),
    559                                            SSL_SET_OPTION(password));
    560     if(rc != GNUTLS_E_SUCCESS) {
    561       failf(data, "gnutls_srp_set_client_cred() failed: %s",
    562             gnutls_strerror(rc));
    563       return CURLE_BAD_FUNCTION_ARGUMENT;
    564     }
    565   }
    566 #endif
    567 
    568   if(SSL_CONN_CONFIG(CAfile)) {
    569     /* set the trusted CA cert bundle file */
    570     gnutls_certificate_set_verify_flags(BACKEND->cred,
    571                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
    572 
    573     rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred,
    574                                                 SSL_CONN_CONFIG(CAfile),
    575                                                 GNUTLS_X509_FMT_PEM);
    576     if(rc < 0) {
    577       infof(data, "error reading ca cert file %s (%s)\n",
    578             SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
    579       if(SSL_CONN_CONFIG(verifypeer))
    580         return CURLE_SSL_CACERT_BADFILE;
    581     }
    582     else
    583       infof(data, "found %d certificates in %s\n", rc,
    584             SSL_CONN_CONFIG(CAfile));
    585   }
    586 
    587 #ifdef HAS_CAPATH
    588   if(SSL_CONN_CONFIG(CApath)) {
    589     /* set the trusted CA cert directory */
    590     rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred,
    591                                                SSL_CONN_CONFIG(CApath),
    592                                                GNUTLS_X509_FMT_PEM);
    593     if(rc < 0) {
    594       infof(data, "error reading ca cert file %s (%s)\n",
    595             SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
    596       if(SSL_CONN_CONFIG(verifypeer))
    597         return CURLE_SSL_CACERT_BADFILE;
    598     }
    599     else
    600       infof(data, "found %d certificates in %s\n",
    601             rc, SSL_CONN_CONFIG(CApath));
    602   }
    603 #endif
    604 
    605 #ifdef CURL_CA_FALLBACK
    606   /* use system ca certificate store as fallback */
    607   if(SSL_CONN_CONFIG(verifypeer) &&
    608      !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
    609     gnutls_certificate_set_x509_system_trust(BACKEND->cred);
    610   }
    611 #endif
    612 
    613   if(SSL_SET_OPTION(CRLfile)) {
    614     /* set the CRL list file */
    615     rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred,
    616                                               SSL_SET_OPTION(CRLfile),
    617                                               GNUTLS_X509_FMT_PEM);
    618     if(rc < 0) {
    619       failf(data, "error reading crl file %s (%s)",
    620             SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
    621       return CURLE_SSL_CRL_BADFILE;
    622     }
    623     else
    624       infof(data, "found %d CRL in %s\n",
    625             rc, SSL_SET_OPTION(CRLfile));
    626   }
    627 
    628   /* Initialize TLS session as a client */
    629   init_flags = GNUTLS_CLIENT;
    630 
    631 #if defined(GNUTLS_NO_TICKETS)
    632   /* Disable TLS session tickets */
    633   init_flags |= GNUTLS_NO_TICKETS;
    634 #endif
    635 
    636   rc = gnutls_init(&BACKEND->session, init_flags);
    637   if(rc != GNUTLS_E_SUCCESS) {
    638     failf(data, "gnutls_init() failed: %d", rc);
    639     return CURLE_SSL_CONNECT_ERROR;
    640   }
    641 
    642   /* convenient assign */
    643   session = BACKEND->session;
    644 
    645   if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
    646 #ifdef ENABLE_IPV6
    647      (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
    648 #endif
    649      sni &&
    650      (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
    651                              strlen(hostname)) < 0))
    652     infof(data, "WARNING: failed to configure server name indication (SNI) "
    653           "TLS extension\n");
    654 
    655   /* Use default priorities */
    656   rc = gnutls_set_default_priority(session);
    657   if(rc != GNUTLS_E_SUCCESS)
    658     return CURLE_SSL_CONNECT_ERROR;
    659 
    660 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
    661   rc = gnutls_cipher_set_priority(session, cipher_priority);
    662   if(rc != GNUTLS_E_SUCCESS)
    663     return CURLE_SSL_CONNECT_ERROR;
    664 
    665   /* Sets the priority on the certificate types supported by gnutls. Priority
    666    is higher for types specified before others. After specifying the types
    667    you want, you must append a 0. */
    668   rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
    669   if(rc != GNUTLS_E_SUCCESS)
    670     return CURLE_SSL_CONNECT_ERROR;
    671 
    672   if(SSL_CONN_CONFIG(cipher_list) != NULL) {
    673     failf(data, "can't pass a custom cipher list to older GnuTLS"
    674           " versions");
    675     return CURLE_SSL_CONNECT_ERROR;
    676   }
    677 
    678   switch(SSL_CONN_CONFIG(version)) {
    679     case CURL_SSLVERSION_SSLv3:
    680       protocol_priority[0] = GNUTLS_SSL3;
    681       break;
    682     case CURL_SSLVERSION_DEFAULT:
    683     case CURL_SSLVERSION_TLSv1:
    684       protocol_priority[0] = GNUTLS_TLS1_0;
    685       protocol_priority[1] = GNUTLS_TLS1_1;
    686       protocol_priority[2] = GNUTLS_TLS1_2;
    687       break;
    688     case CURL_SSLVERSION_TLSv1_0:
    689     case CURL_SSLVERSION_TLSv1_1:
    690     case CURL_SSLVERSION_TLSv1_2:
    691     case CURL_SSLVERSION_TLSv1_3:
    692       {
    693         CURLcode result = set_ssl_version_min_max(protocol_priority,
    694                 sizeof(protocol_priority)/sizeof(protocol_priority[0]), conn);
    695         if(result != CURLE_OK)
    696           return result;
    697         break;
    698       }
    699     case CURL_SSLVERSION_SSLv2:
    700       failf(data, "GnuTLS does not support SSLv2");
    701       return CURLE_SSL_CONNECT_ERROR;
    702     default:
    703       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
    704       return CURLE_SSL_CONNECT_ERROR;
    705   }
    706   rc = gnutls_protocol_set_priority(session, protocol_priority);
    707   if(rc != GNUTLS_E_SUCCESS) {
    708     failf(data, "Did you pass a valid GnuTLS cipher list?");
    709     return CURLE_SSL_CONNECT_ERROR;
    710   }
    711 
    712 #else
    713   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
    714    * removed if a run-time error indicates that SRP is not supported by this
    715    * GnuTLS version */
    716   switch(SSL_CONN_CONFIG(version)) {
    717     case CURL_SSLVERSION_SSLv3:
    718       prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
    719       sni = false;
    720       break;
    721     case CURL_SSLVERSION_DEFAULT:
    722     case CURL_SSLVERSION_TLSv1:
    723       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
    724       break;
    725     case CURL_SSLVERSION_TLSv1_0:
    726     case CURL_SSLVERSION_TLSv1_1:
    727     case CURL_SSLVERSION_TLSv1_2:
    728     case CURL_SSLVERSION_TLSv1_3:
    729       {
    730         CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
    731         if(result != CURLE_OK)
    732           return result;
    733         break;
    734       }
    735     case CURL_SSLVERSION_SSLv2:
    736       failf(data, "GnuTLS does not support SSLv2");
    737       return CURLE_SSL_CONNECT_ERROR;
    738     default:
    739       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
    740       return CURLE_SSL_CONNECT_ERROR;
    741   }
    742   rc = gnutls_priority_set_direct(session, prioritylist, &err);
    743   if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
    744     if(!strcmp(err, GNUTLS_SRP)) {
    745       /* This GnuTLS was probably compiled without support for SRP.
    746        * Note that fact and try again without it. */
    747       int validprioritylen = curlx_uztosi(err - prioritylist);
    748       char *prioritycopy = strdup(prioritylist);
    749       if(!prioritycopy)
    750         return CURLE_OUT_OF_MEMORY;
    751 
    752       infof(data, "This GnuTLS does not support SRP\n");
    753       if(validprioritylen)
    754         /* Remove the :+SRP */
    755         prioritycopy[validprioritylen - 1] = 0;
    756       rc = gnutls_priority_set_direct(session, prioritycopy, &err);
    757       free(prioritycopy);
    758     }
    759   }
    760   if(rc != GNUTLS_E_SUCCESS) {
    761     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
    762           rc, err);
    763     return CURLE_SSL_CONNECT_ERROR;
    764   }
    765 #endif
    766 
    767 #ifdef HAS_ALPN
    768   if(conn->bits.tls_enable_alpn) {
    769     int cur = 0;
    770     gnutls_datum_t protocols[2];
    771 
    772 #ifdef USE_NGHTTP2
    773     if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
    774        (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
    775       protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
    776       protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
    777       cur++;
    778       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
    779     }
    780 #endif
    781 
    782     protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
    783     protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
    784     cur++;
    785     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
    786 
    787     gnutls_alpn_set_protocols(session, protocols, cur, 0);
    788   }
    789 #endif
    790 
    791   if(SSL_SET_OPTION(cert)) {
    792     if(SSL_SET_OPTION(key_passwd)) {
    793 #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
    794       const unsigned int supported_key_encryption_algorithms =
    795         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
    796         GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
    797         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
    798         GNUTLS_PKCS_USE_PBES2_AES_256;
    799       rc = gnutls_certificate_set_x509_key_file2(
    800            BACKEND->cred,
    801            SSL_SET_OPTION(cert),
    802            SSL_SET_OPTION(key) ?
    803            SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
    804            do_file_type(SSL_SET_OPTION(cert_type)),
    805            SSL_SET_OPTION(key_passwd),
    806            supported_key_encryption_algorithms);
    807       if(rc != GNUTLS_E_SUCCESS) {
    808         failf(data,
    809               "error reading X.509 potentially-encrypted key file: %s",
    810               gnutls_strerror(rc));
    811         return CURLE_SSL_CONNECT_ERROR;
    812       }
    813 #else
    814       failf(data, "gnutls lacks support for encrypted key files");
    815       return CURLE_SSL_CONNECT_ERROR;
    816 #endif
    817     }
    818     else {
    819       if(gnutls_certificate_set_x509_key_file(
    820            BACKEND->cred,
    821            SSL_SET_OPTION(cert),
    822            SSL_SET_OPTION(key) ?
    823            SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
    824            do_file_type(SSL_SET_OPTION(cert_type)) ) !=
    825          GNUTLS_E_SUCCESS) {
    826         failf(data, "error reading X.509 key or certificate file");
    827         return CURLE_SSL_CONNECT_ERROR;
    828       }
    829     }
    830   }
    831 
    832 #ifdef USE_TLS_SRP
    833   /* put the credentials to the current session */
    834   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
    835     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
    836                                 BACKEND->srp_client_cred);
    837     if(rc != GNUTLS_E_SUCCESS) {
    838       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
    839       return CURLE_SSL_CONNECT_ERROR;
    840     }
    841   }
    842   else
    843 #endif
    844   {
    845     rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
    846                                 BACKEND->cred);
    847     if(rc != GNUTLS_E_SUCCESS) {
    848       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
    849       return CURLE_SSL_CONNECT_ERROR;
    850     }
    851   }
    852 
    853   if(conn->proxy_ssl[sockindex].use) {
    854     transport_ptr = conn->proxy_ssl[sockindex].backend->session;
    855     gnutls_transport_push = Curl_gtls_push_ssl;
    856     gnutls_transport_pull = Curl_gtls_pull_ssl;
    857   }
    858   else {
    859     /* file descriptor for the socket */
    860     transport_ptr = GNUTLS_SOCKET_TO_POINTER_CAST(conn->sock[sockindex]);
    861     gnutls_transport_push = Curl_gtls_push;
    862     gnutls_transport_pull = Curl_gtls_pull;
    863   }
    864 
    865   /* set the connection handle */
    866   gnutls_transport_set_ptr(session, transport_ptr);
    867 
    868   /* register callback functions to send and receive data. */
    869   gnutls_transport_set_push_function(session, gnutls_transport_push);
    870   gnutls_transport_set_pull_function(session, gnutls_transport_pull);
    871 
    872   /* lowat must be set to zero when using custom push and pull functions. */
    873   gnutls_transport_set_lowat(session, 0);
    874 
    875 #ifdef HAS_OCSP
    876   if(SSL_CONN_CONFIG(verifystatus)) {
    877     rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
    878     if(rc != GNUTLS_E_SUCCESS) {
    879       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
    880       return CURLE_SSL_CONNECT_ERROR;
    881     }
    882   }
    883 #endif
    884 
    885   /* This might be a reconnect, so we check for a session ID in the cache
    886      to speed up things */
    887   if(SSL_SET_OPTION(primary.sessionid)) {
    888     void *ssl_sessionid;
    889     size_t ssl_idsize;
    890 
    891     Curl_ssl_sessionid_lock(conn);
    892     if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
    893       /* we got a session id, use it! */
    894       gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
    895 
    896       /* Informational message */
    897       infof(data, "SSL re-using session ID\n");
    898     }
    899     Curl_ssl_sessionid_unlock(conn);
    900   }
    901 
    902   return CURLE_OK;
    903 }
    904 
    905 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
    906                                     gnutls_x509_crt_t cert,
    907                                     const char *pinnedpubkey)
    908 {
    909   /* Scratch */
    910   size_t len1 = 0, len2 = 0;
    911   unsigned char *buff1 = NULL;
    912 
    913   gnutls_pubkey_t key = NULL;
    914 
    915   /* Result is returned to caller */
    916   int ret = 0;
    917   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    918 
    919   /* if a path wasn't specified, don't pin */
    920   if(NULL == pinnedpubkey)
    921     return CURLE_OK;
    922 
    923   if(NULL == cert)
    924     return result;
    925 
    926   do {
    927     /* Begin Gyrations to get the public key     */
    928     gnutls_pubkey_init(&key);
    929 
    930     ret = gnutls_pubkey_import_x509(key, cert, 0);
    931     if(ret < 0)
    932       break; /* failed */
    933 
    934     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
    935     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
    936       break; /* failed */
    937 
    938     buff1 = malloc(len1);
    939     if(NULL == buff1)
    940       break; /* failed */
    941 
    942     len2 = len1;
    943 
    944     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
    945     if(ret < 0 || len1 != len2)
    946       break; /* failed */
    947 
    948     /* End Gyrations */
    949 
    950     /* The one good exit point */
    951     result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
    952   } while(0);
    953 
    954   if(NULL != key)
    955     gnutls_pubkey_deinit(key);
    956 
    957   Curl_safefree(buff1);
    958 
    959   return result;
    960 }
    961 
    962 static Curl_recv gtls_recv;
    963 static Curl_send gtls_send;
    964 
    965 static CURLcode
    966 gtls_connect_step3(struct connectdata *conn,
    967                    int sockindex)
    968 {
    969   unsigned int cert_list_size;
    970   const gnutls_datum_t *chainp;
    971   unsigned int verify_status = 0;
    972   gnutls_x509_crt_t x509_cert, x509_issuer;
    973   gnutls_datum_t issuerp;
    974   char certbuf[256] = ""; /* big enough? */
    975   size_t size;
    976   time_t certclock;
    977   const char *ptr;
    978   struct Curl_easy *data = conn->data;
    979   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    980   gnutls_session_t session = BACKEND->session;
    981   int rc;
    982 #ifdef HAS_ALPN
    983   gnutls_datum_t proto;
    984 #endif
    985   CURLcode result = CURLE_OK;
    986 #ifndef CURL_DISABLE_VERBOSE_STRINGS
    987   unsigned int algo;
    988   unsigned int bits;
    989   gnutls_protocol_t version = gnutls_protocol_get_version(session);
    990 #endif
    991   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    992     conn->host.name;
    993 
    994   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
    995   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
    996                                      gnutls_cipher_get(session),
    997                                      gnutls_mac_get(session));
    998 
    999   infof(data, "SSL connection using %s / %s\n",
   1000         gnutls_protocol_get_name(version), ptr);
   1001 
   1002   /* This function will return the peer's raw certificate (chain) as sent by
   1003      the peer. These certificates are in raw format (DER encoded for
   1004      X.509). In case of a X.509 then a certificate list may be present. The
   1005      first certificate in the list is the peer's certificate, following the
   1006      issuer's certificate, then the issuer's issuer etc. */
   1007 
   1008   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
   1009   if(!chainp) {
   1010     if(SSL_CONN_CONFIG(verifypeer) ||
   1011        SSL_CONN_CONFIG(verifyhost) ||
   1012        SSL_SET_OPTION(issuercert)) {
   1013 #ifdef USE_TLS_SRP
   1014       if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
   1015          && SSL_SET_OPTION(username) != NULL
   1016          && !SSL_CONN_CONFIG(verifypeer)
   1017          && gnutls_cipher_get(session)) {
   1018         /* no peer cert, but auth is ok if we have SRP user and cipher and no
   1019            peer verify */
   1020       }
   1021       else {
   1022 #endif
   1023         failf(data, "failed to get server cert");
   1024         return CURLE_PEER_FAILED_VERIFICATION;
   1025 #ifdef USE_TLS_SRP
   1026       }
   1027 #endif
   1028     }
   1029     infof(data, "\t common name: WARNING couldn't obtain\n");
   1030   }
   1031 
   1032   if(data->set.ssl.certinfo && chainp) {
   1033     unsigned int i;
   1034 
   1035     result = Curl_ssl_init_certinfo(data, cert_list_size);
   1036     if(result)
   1037       return result;
   1038 
   1039     for(i = 0; i < cert_list_size; i++) {
   1040       const char *beg = (const char *) chainp[i].data;
   1041       const char *end = beg + chainp[i].size;
   1042 
   1043       result = Curl_extract_certinfo(conn, i, beg, end);
   1044       if(result)
   1045         return result;
   1046     }
   1047   }
   1048 
   1049   if(SSL_CONN_CONFIG(verifypeer)) {
   1050     /* This function will try to verify the peer's certificate and return its
   1051        status (trusted, invalid etc.). The value of status should be one or
   1052        more of the gnutls_certificate_status_t enumerated elements bitwise
   1053        or'd. To avoid denial of service attacks some default upper limits
   1054        regarding the certificate key size and chain size are set. To override
   1055        them use gnutls_certificate_set_verify_limits(). */
   1056 
   1057     rc = gnutls_certificate_verify_peers2(session, &verify_status);
   1058     if(rc < 0) {
   1059       failf(data, "server cert verify failed: %d", rc);
   1060       return CURLE_SSL_CONNECT_ERROR;
   1061     }
   1062 
   1063     /* verify_status is a bitmask of gnutls_certificate_status bits */
   1064     if(verify_status & GNUTLS_CERT_INVALID) {
   1065       if(SSL_CONN_CONFIG(verifypeer)) {
   1066         failf(data, "server certificate verification failed. CAfile: %s "
   1067               "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
   1068               "none",
   1069               SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
   1070         return CURLE_SSL_CACERT;
   1071       }
   1072       else
   1073         infof(data, "\t server certificate verification FAILED\n");
   1074     }
   1075     else
   1076       infof(data, "\t server certificate verification OK\n");
   1077   }
   1078   else
   1079     infof(data, "\t server certificate verification SKIPPED\n");
   1080 
   1081 #ifdef HAS_OCSP
   1082   if(SSL_CONN_CONFIG(verifystatus)) {
   1083     if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
   1084       gnutls_datum_t status_request;
   1085       gnutls_ocsp_resp_t ocsp_resp;
   1086 
   1087       gnutls_ocsp_cert_status_t status;
   1088       gnutls_x509_crl_reason_t reason;
   1089 
   1090       rc = gnutls_ocsp_status_request_get(session, &status_request);
   1091 
   1092       infof(data, "\t server certificate status verification FAILED\n");
   1093 
   1094       if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
   1095         failf(data, "No OCSP response received");
   1096         return CURLE_SSL_INVALIDCERTSTATUS;
   1097       }
   1098 
   1099       if(rc < 0) {
   1100         failf(data, "Invalid OCSP response received");
   1101         return CURLE_SSL_INVALIDCERTSTATUS;
   1102       }
   1103 
   1104       gnutls_ocsp_resp_init(&ocsp_resp);
   1105 
   1106       rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
   1107       if(rc < 0) {
   1108         failf(data, "Invalid OCSP response received");
   1109         return CURLE_SSL_INVALIDCERTSTATUS;
   1110       }
   1111 
   1112       rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
   1113                                        &status, NULL, NULL, NULL, &reason);
   1114 
   1115       switch(status) {
   1116       case GNUTLS_OCSP_CERT_GOOD:
   1117         break;
   1118 
   1119       case GNUTLS_OCSP_CERT_REVOKED: {
   1120         const char *crl_reason;
   1121 
   1122         switch(reason) {
   1123           default:
   1124           case GNUTLS_X509_CRLREASON_UNSPECIFIED:
   1125             crl_reason = "unspecified reason";
   1126             break;
   1127 
   1128           case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
   1129             crl_reason = "private key compromised";
   1130             break;
   1131 
   1132           case GNUTLS_X509_CRLREASON_CACOMPROMISE:
   1133             crl_reason = "CA compromised";
   1134             break;
   1135 
   1136           case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
   1137             crl_reason = "affiliation has changed";
   1138             break;
   1139 
   1140           case GNUTLS_X509_CRLREASON_SUPERSEDED:
   1141             crl_reason = "certificate superseded";
   1142             break;
   1143 
   1144           case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
   1145             crl_reason = "operation has ceased";
   1146             break;
   1147 
   1148           case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
   1149             crl_reason = "certificate is on hold";
   1150             break;
   1151 
   1152           case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
   1153             crl_reason = "will be removed from delta CRL";
   1154             break;
   1155 
   1156           case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
   1157             crl_reason = "privilege withdrawn";
   1158             break;
   1159 
   1160           case GNUTLS_X509_CRLREASON_AACOMPROMISE:
   1161             crl_reason = "AA compromised";
   1162             break;
   1163         }
   1164 
   1165         failf(data, "Server certificate was revoked: %s", crl_reason);
   1166         break;
   1167       }
   1168 
   1169       default:
   1170       case GNUTLS_OCSP_CERT_UNKNOWN:
   1171         failf(data, "Server certificate status is unknown");
   1172         break;
   1173       }
   1174 
   1175       gnutls_ocsp_resp_deinit(ocsp_resp);
   1176 
   1177       return CURLE_SSL_INVALIDCERTSTATUS;
   1178     }
   1179     else
   1180       infof(data, "\t server certificate status verification OK\n");
   1181   }
   1182   else
   1183     infof(data, "\t server certificate status verification SKIPPED\n");
   1184 #endif
   1185 
   1186   /* initialize an X.509 certificate structure. */
   1187   gnutls_x509_crt_init(&x509_cert);
   1188 
   1189   if(chainp)
   1190     /* convert the given DER or PEM encoded Certificate to the native
   1191        gnutls_x509_crt_t format */
   1192     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
   1193 
   1194   if(SSL_SET_OPTION(issuercert)) {
   1195     gnutls_x509_crt_init(&x509_issuer);
   1196     issuerp = load_file(SSL_SET_OPTION(issuercert));
   1197     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
   1198     rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
   1199     gnutls_x509_crt_deinit(x509_issuer);
   1200     unload_file(issuerp);
   1201     if(rc <= 0) {
   1202       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
   1203             SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
   1204       gnutls_x509_crt_deinit(x509_cert);
   1205       return CURLE_SSL_ISSUER_ERROR;
   1206     }
   1207     infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
   1208           SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
   1209   }
   1210 
   1211   size = sizeof(certbuf);
   1212   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
   1213                                      0, /* the first and only one */
   1214                                      FALSE,
   1215                                      certbuf,
   1216                                      &size);
   1217   if(rc) {
   1218     infof(data, "error fetching CN from cert:%s\n",
   1219           gnutls_strerror(rc));
   1220   }
   1221 
   1222   /* This function will check if the given certificate's subject matches the
   1223      given hostname. This is a basic implementation of the matching described
   1224      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
   1225      alternative name PKIX extension. Returns non zero on success, and zero on
   1226      failure. */
   1227   rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
   1228 #if GNUTLS_VERSION_NUMBER < 0x030306
   1229   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
   1230      addresses. */
   1231   if(!rc) {
   1232 #ifdef ENABLE_IPV6
   1233     #define use_addr in6_addr
   1234 #else
   1235     #define use_addr in_addr
   1236 #endif
   1237     unsigned char addrbuf[sizeof(struct use_addr)];
   1238     unsigned char certaddr[sizeof(struct use_addr)];
   1239     size_t addrlen = 0, certaddrlen;
   1240     int i;
   1241     int ret = 0;
   1242 
   1243     if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
   1244       addrlen = 4;
   1245 #ifdef ENABLE_IPV6
   1246     else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
   1247       addrlen = 16;
   1248 #endif
   1249 
   1250     if(addrlen) {
   1251       for(i = 0; ; i++) {
   1252         certaddrlen = sizeof(certaddr);
   1253         ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
   1254                                                    &certaddrlen, NULL);
   1255         /* If this happens, it wasn't an IP address. */
   1256         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
   1257           continue;
   1258         if(ret < 0)
   1259           break;
   1260         if(ret != GNUTLS_SAN_IPADDRESS)
   1261           continue;
   1262         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
   1263           rc = 1;
   1264           break;
   1265         }
   1266       }
   1267     }
   1268   }
   1269 #endif
   1270   if(!rc) {
   1271     const char * const dispname = SSL_IS_PROXY() ?
   1272       conn->http_proxy.host.dispname : conn->host.dispname;
   1273 
   1274     if(SSL_CONN_CONFIG(verifyhost)) {
   1275       failf(data, "SSL: certificate subject name (%s) does not match "
   1276             "target host name '%s'", certbuf, dispname);
   1277       gnutls_x509_crt_deinit(x509_cert);
   1278       return CURLE_PEER_FAILED_VERIFICATION;
   1279     }
   1280     else
   1281       infof(data, "\t common name: %s (does not match '%s')\n",
   1282             certbuf, dispname);
   1283   }
   1284   else
   1285     infof(data, "\t common name: %s (matched)\n", certbuf);
   1286 
   1287   /* Check for time-based validity */
   1288   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
   1289 
   1290   if(certclock == (time_t)-1) {
   1291     if(SSL_CONN_CONFIG(verifypeer)) {
   1292       failf(data, "server cert expiration date verify failed");
   1293       gnutls_x509_crt_deinit(x509_cert);
   1294       return CURLE_SSL_CONNECT_ERROR;
   1295     }
   1296     else
   1297       infof(data, "\t server certificate expiration date verify FAILED\n");
   1298   }
   1299   else {
   1300     if(certclock < time(NULL)) {
   1301       if(SSL_CONN_CONFIG(verifypeer)) {
   1302         failf(data, "server certificate expiration date has passed.");
   1303         gnutls_x509_crt_deinit(x509_cert);
   1304         return CURLE_PEER_FAILED_VERIFICATION;
   1305       }
   1306       else
   1307         infof(data, "\t server certificate expiration date FAILED\n");
   1308     }
   1309     else
   1310       infof(data, "\t server certificate expiration date OK\n");
   1311   }
   1312 
   1313   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
   1314 
   1315   if(certclock == (time_t)-1) {
   1316     if(SSL_CONN_CONFIG(verifypeer)) {
   1317       failf(data, "server cert activation date verify failed");
   1318       gnutls_x509_crt_deinit(x509_cert);
   1319       return CURLE_SSL_CONNECT_ERROR;
   1320     }
   1321     else
   1322       infof(data, "\t server certificate activation date verify FAILED\n");
   1323   }
   1324   else {
   1325     if(certclock > time(NULL)) {
   1326       if(SSL_CONN_CONFIG(verifypeer)) {
   1327         failf(data, "server certificate not activated yet.");
   1328         gnutls_x509_crt_deinit(x509_cert);
   1329         return CURLE_PEER_FAILED_VERIFICATION;
   1330       }
   1331       else
   1332         infof(data, "\t server certificate activation date FAILED\n");
   1333     }
   1334     else
   1335       infof(data, "\t server certificate activation date OK\n");
   1336   }
   1337 
   1338   ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
   1339         data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
   1340   if(ptr) {
   1341     result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
   1342     if(result != CURLE_OK) {
   1343       failf(data, "SSL: public key does not match pinned public key!");
   1344       gnutls_x509_crt_deinit(x509_cert);
   1345       return result;
   1346     }
   1347   }
   1348 
   1349   /* Show:
   1350 
   1351   - subject
   1352   - start date
   1353   - expire date
   1354   - common name
   1355   - issuer
   1356 
   1357   */
   1358 
   1359 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   1360   /* public key algorithm's parameters */
   1361   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
   1362   infof(data, "\t certificate public key: %s\n",
   1363         gnutls_pk_algorithm_get_name(algo));
   1364 
   1365   /* version of the X.509 certificate. */
   1366   infof(data, "\t certificate version: #%d\n",
   1367         gnutls_x509_crt_get_version(x509_cert));
   1368 
   1369 
   1370   size = sizeof(certbuf);
   1371   gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
   1372   infof(data, "\t subject: %s\n", certbuf);
   1373 
   1374   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
   1375   showtime(data, "start date", certclock);
   1376 
   1377   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
   1378   showtime(data, "expire date", certclock);
   1379 
   1380   size = sizeof(certbuf);
   1381   gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
   1382   infof(data, "\t issuer: %s\n", certbuf);
   1383 
   1384   /* compression algorithm (if any) */
   1385   ptr = gnutls_compression_get_name(gnutls_compression_get(session));
   1386   /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
   1387   infof(data, "\t compression: %s\n", ptr);
   1388 #endif
   1389 
   1390   gnutls_x509_crt_deinit(x509_cert);
   1391 
   1392 #ifdef HAS_ALPN
   1393   if(conn->bits.tls_enable_alpn) {
   1394     rc = gnutls_alpn_get_selected_protocol(session, &proto);
   1395     if(rc == 0) {
   1396       infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
   1397           proto.data);
   1398 
   1399 #ifdef USE_NGHTTP2
   1400       if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
   1401          !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
   1402                  NGHTTP2_PROTO_VERSION_ID_LEN)) {
   1403         conn->negnpn = CURL_HTTP_VERSION_2;
   1404       }
   1405       else
   1406 #endif
   1407       if(proto.size == ALPN_HTTP_1_1_LENGTH &&
   1408          !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
   1409         conn->negnpn = CURL_HTTP_VERSION_1_1;
   1410       }
   1411     }
   1412     else
   1413       infof(data, "ALPN, server did not agree to a protocol\n");
   1414   }
   1415 #endif
   1416 
   1417   conn->ssl[sockindex].state = ssl_connection_complete;
   1418   conn->recv[sockindex] = gtls_recv;
   1419   conn->send[sockindex] = gtls_send;
   1420 
   1421   if(SSL_SET_OPTION(primary.sessionid)) {
   1422     /* we always unconditionally get the session id here, as even if we
   1423        already got it from the cache and asked to use it in the connection, it
   1424        might've been rejected and then a new one is in use now and we need to
   1425        detect that. */
   1426     bool incache;
   1427     void *ssl_sessionid;
   1428     void *connect_sessionid;
   1429     size_t connect_idsize = 0;
   1430 
   1431     /* get the session ID data size */
   1432     gnutls_session_get_data(session, NULL, &connect_idsize);
   1433     connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
   1434 
   1435     if(connect_sessionid) {
   1436       /* extract session ID to the allocated buffer */
   1437       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
   1438 
   1439       Curl_ssl_sessionid_lock(conn);
   1440       incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
   1441                                         sockindex));
   1442       if(incache) {
   1443         /* there was one before in the cache, so instead of risking that the
   1444            previous one was rejected, we just kill that and store the new */
   1445         Curl_ssl_delsessionid(conn, ssl_sessionid);
   1446       }
   1447 
   1448       /* store this session id */
   1449       result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
   1450                                      sockindex);
   1451       Curl_ssl_sessionid_unlock(conn);
   1452       if(result) {
   1453         free(connect_sessionid);
   1454         result = CURLE_OUT_OF_MEMORY;
   1455       }
   1456     }
   1457     else
   1458       result = CURLE_OUT_OF_MEMORY;
   1459   }
   1460 
   1461   return result;
   1462 }
   1463 
   1464 
   1465 /*
   1466  * This function is called after the TCP connect has completed. Setup the TLS
   1467  * layer and do all necessary magic.
   1468  */
   1469 /* We use connssl->connecting_state to keep track of the connection status;
   1470    there are three states: 'ssl_connect_1' (not started yet or complete),
   1471    'ssl_connect_2_reading' (waiting for data from server), and
   1472    'ssl_connect_2_writing' (waiting to be able to write).
   1473  */
   1474 static CURLcode
   1475 gtls_connect_common(struct connectdata *conn,
   1476                     int sockindex,
   1477                     bool nonblocking,
   1478                     bool *done)
   1479 {
   1480   int rc;
   1481   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   1482 
   1483   /* Initiate the connection, if not already done */
   1484   if(ssl_connect_1 == connssl->connecting_state) {
   1485     rc = gtls_connect_step1(conn, sockindex);
   1486     if(rc)
   1487       return rc;
   1488   }
   1489 
   1490   rc = handshake(conn, sockindex, TRUE, nonblocking);
   1491   if(rc)
   1492     /* handshake() sets its own error message with failf() */
   1493     return rc;
   1494 
   1495   /* Finish connecting once the handshake is done */
   1496   if(ssl_connect_1 == connssl->connecting_state) {
   1497     rc = gtls_connect_step3(conn, sockindex);
   1498     if(rc)
   1499       return rc;
   1500   }
   1501 
   1502   *done = ssl_connect_1 == connssl->connecting_state;
   1503 
   1504   return CURLE_OK;
   1505 }
   1506 
   1507 static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
   1508                                               int sockindex, bool *done)
   1509 {
   1510   return gtls_connect_common(conn, sockindex, TRUE, done);
   1511 }
   1512 
   1513 static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
   1514 {
   1515   CURLcode result;
   1516   bool done = FALSE;
   1517 
   1518   result = gtls_connect_common(conn, sockindex, FALSE, &done);
   1519   if(result)
   1520     return result;
   1521 
   1522   DEBUGASSERT(done);
   1523 
   1524   return CURLE_OK;
   1525 }
   1526 
   1527 static bool Curl_gtls_data_pending(const struct connectdata *conn,
   1528                                    int connindex)
   1529 {
   1530   const struct ssl_connect_data *connssl = &conn->ssl[connindex];
   1531   bool res = FALSE;
   1532   if(BACKEND->session &&
   1533      0 != gnutls_record_check_pending(BACKEND->session))
   1534     res = TRUE;
   1535 
   1536   connssl = &conn->proxy_ssl[connindex];
   1537   if(BACKEND->session &&
   1538      0 != gnutls_record_check_pending(BACKEND->session))
   1539     res = TRUE;
   1540 
   1541   return res;
   1542 }
   1543 
   1544 static ssize_t gtls_send(struct connectdata *conn,
   1545                          int sockindex,
   1546                          const void *mem,
   1547                          size_t len,
   1548                          CURLcode *curlcode)
   1549 {
   1550   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   1551   ssize_t rc = gnutls_record_send(BACKEND->session, mem, len);
   1552 
   1553   if(rc < 0) {
   1554     *curlcode = (rc == GNUTLS_E_AGAIN)
   1555       ? CURLE_AGAIN
   1556       : CURLE_SEND_ERROR;
   1557 
   1558     rc = -1;
   1559   }
   1560 
   1561   return rc;
   1562 }
   1563 
   1564 static void close_one(struct ssl_connect_data *connssl)
   1565 {
   1566   if(BACKEND->session) {
   1567     gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR);
   1568     gnutls_deinit(BACKEND->session);
   1569     BACKEND->session = NULL;
   1570   }
   1571   if(BACKEND->cred) {
   1572     gnutls_certificate_free_credentials(BACKEND->cred);
   1573     BACKEND->cred = NULL;
   1574   }
   1575 #ifdef USE_TLS_SRP
   1576   if(BACKEND->srp_client_cred) {
   1577     gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
   1578     BACKEND->srp_client_cred = NULL;
   1579   }
   1580 #endif
   1581 }
   1582 
   1583 static void Curl_gtls_close(struct connectdata *conn, int sockindex)
   1584 {
   1585   close_one(&conn->ssl[sockindex]);
   1586   close_one(&conn->proxy_ssl[sockindex]);
   1587 }
   1588 
   1589 /*
   1590  * This function is called to shut down the SSL layer but keep the
   1591  * socket open (CCC - Clear Command Channel)
   1592  */
   1593 static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
   1594 {
   1595   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   1596   ssize_t result;
   1597   int retval = 0;
   1598   struct Curl_easy *data = conn->data;
   1599   int done = 0;
   1600   char buf[120];
   1601 
   1602   /* This has only been tested on the proftpd server, and the mod_tls code
   1603      sends a close notify alert without waiting for a close notify alert in
   1604      response. Thus we wait for a close notify alert from the server, but
   1605      we do not send one. Let's hope other servers do the same... */
   1606 
   1607   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
   1608       gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR);
   1609 
   1610   if(BACKEND->session) {
   1611     while(!done) {
   1612       int what = SOCKET_READABLE(conn->sock[sockindex],
   1613                                  SSL_SHUTDOWN_TIMEOUT);
   1614       if(what > 0) {
   1615         /* Something to read, let's do it and hope that it is the close
   1616            notify alert from the server */
   1617         result = gnutls_record_recv(BACKEND->session,
   1618                                     buf, sizeof(buf));
   1619         switch(result) {
   1620         case 0:
   1621           /* This is the expected response. There was no data but only
   1622              the close notify alert */
   1623           done = 1;
   1624           break;
   1625         case GNUTLS_E_AGAIN:
   1626         case GNUTLS_E_INTERRUPTED:
   1627           infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
   1628           break;
   1629         default:
   1630           retval = -1;
   1631           done = 1;
   1632           break;
   1633         }
   1634       }
   1635       else if(0 == what) {
   1636         /* timeout */
   1637         failf(data, "SSL shutdown timeout");
   1638         done = 1;
   1639         break;
   1640       }
   1641       else {
   1642         /* anything that gets here is fatally bad */
   1643         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
   1644         retval = -1;
   1645         done = 1;
   1646       }
   1647     }
   1648     gnutls_deinit(BACKEND->session);
   1649   }
   1650   gnutls_certificate_free_credentials(BACKEND->cred);
   1651 
   1652 #ifdef USE_TLS_SRP
   1653   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
   1654      && SSL_SET_OPTION(username) != NULL)
   1655     gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
   1656 #endif
   1657 
   1658   BACKEND->cred = NULL;
   1659   BACKEND->session = NULL;
   1660 
   1661   return retval;
   1662 }
   1663 
   1664 static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
   1665                          int num,                  /* socketindex */
   1666                          char *buf,                /* store read data here */
   1667                          size_t buffersize,        /* max amount to read */
   1668                          CURLcode *curlcode)
   1669 {
   1670   struct ssl_connect_data *connssl = &conn->ssl[num];
   1671   ssize_t ret;
   1672 
   1673   ret = gnutls_record_recv(BACKEND->session, buf, buffersize);
   1674   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
   1675     *curlcode = CURLE_AGAIN;
   1676     return -1;
   1677   }
   1678 
   1679   if(ret == GNUTLS_E_REHANDSHAKE) {
   1680     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
   1681        proper way" takes a whole lot of work. */
   1682     CURLcode result = handshake(conn, num, FALSE, FALSE);
   1683     if(result)
   1684       /* handshake() writes error message on its own */
   1685       *curlcode = result;
   1686     else
   1687       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
   1688     return -1;
   1689   }
   1690 
   1691   if(ret < 0) {
   1692     failf(conn->data, "GnuTLS recv error (%d): %s",
   1693 
   1694           (int)ret, gnutls_strerror((int)ret));
   1695     *curlcode = CURLE_RECV_ERROR;
   1696     return -1;
   1697   }
   1698 
   1699   return ret;
   1700 }
   1701 
   1702 static void Curl_gtls_session_free(void *ptr)
   1703 {
   1704   free(ptr);
   1705 }
   1706 
   1707 static size_t Curl_gtls_version(char *buffer, size_t size)
   1708 {
   1709   return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
   1710 }
   1711 
   1712 #ifndef USE_GNUTLS_NETTLE
   1713 static int Curl_gtls_seed(struct Curl_easy *data)
   1714 {
   1715   /* we have the "SSL is seeded" boolean static to prevent multiple
   1716      time-consuming seedings in vain */
   1717   static bool ssl_seeded = FALSE;
   1718 
   1719   /* Quickly add a bit of entropy */
   1720   gcry_fast_random_poll();
   1721 
   1722   if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
   1723      data->set.str[STRING_SSL_EGDSOCKET]) {
   1724 
   1725     /* TODO: to a good job seeding the RNG
   1726        This may involve the gcry_control function and these options:
   1727        GCRYCTL_SET_RANDOM_SEED_FILE
   1728        GCRYCTL_SET_RNDEGD_SOCKET
   1729     */
   1730     ssl_seeded = TRUE;
   1731   }
   1732   return 0;
   1733 }
   1734 #endif
   1735 
   1736 /* data might be NULL! */
   1737 static CURLcode Curl_gtls_random(struct Curl_easy *data,
   1738                                  unsigned char *entropy, size_t length)
   1739 {
   1740 #if defined(USE_GNUTLS_NETTLE)
   1741   int rc;
   1742   (void)data;
   1743   rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
   1744   return rc?CURLE_FAILED_INIT:CURLE_OK;
   1745 #elif defined(USE_GNUTLS)
   1746   if(data)
   1747     Curl_gtls_seed(data); /* Initiate the seed if not already done */
   1748   gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
   1749 #endif
   1750   return CURLE_OK;
   1751 }
   1752 
   1753 static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
   1754                                  size_t tmplen,
   1755                                  unsigned char *md5sum, /* output */
   1756                                  size_t md5len)
   1757 {
   1758 #if defined(USE_GNUTLS_NETTLE)
   1759   struct md5_ctx MD5pw;
   1760   md5_init(&MD5pw);
   1761   md5_update(&MD5pw, (unsigned int)tmplen, tmp);
   1762   md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
   1763 #elif defined(USE_GNUTLS)
   1764   gcry_md_hd_t MD5pw;
   1765   gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
   1766   gcry_md_write(MD5pw, tmp, tmplen);
   1767   memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
   1768   gcry_md_close(MD5pw);
   1769 #endif
   1770   return CURLE_OK;
   1771 }
   1772 
   1773 static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
   1774                                 size_t tmplen,
   1775                                 unsigned char *sha256sum, /* output */
   1776                                 size_t sha256len)
   1777 {
   1778 #if defined(USE_GNUTLS_NETTLE)
   1779   struct sha256_ctx SHA256pw;
   1780   sha256_init(&SHA256pw);
   1781   sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
   1782   sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
   1783 #elif defined(USE_GNUTLS)
   1784   gcry_md_hd_t SHA256pw;
   1785   gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
   1786   gcry_md_write(SHA256pw, tmp, tmplen);
   1787   memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
   1788   gcry_md_close(SHA256pw);
   1789 #endif
   1790 }
   1791 
   1792 static bool Curl_gtls_cert_status_request(void)
   1793 {
   1794 #ifdef HAS_OCSP
   1795   return TRUE;
   1796 #else
   1797   return FALSE;
   1798 #endif
   1799 }
   1800 
   1801 static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
   1802                                      CURLINFO info UNUSED_PARAM)
   1803 {
   1804   (void)info;
   1805   return BACKEND->session;
   1806 }
   1807 
   1808 const struct Curl_ssl Curl_ssl_gnutls = {
   1809   { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
   1810 
   1811   1, /* have_ca_path */
   1812   1, /* have_certinfo */
   1813   1, /* have_pinnedpubkey */
   1814   0, /* have_ssl_ctx */
   1815   1, /* support_https_proxy */
   1816 
   1817   sizeof(struct ssl_backend_data),
   1818 
   1819   Curl_gtls_init,                /* init */
   1820   Curl_gtls_cleanup,             /* cleanup */
   1821   Curl_gtls_version,             /* version */
   1822   Curl_none_check_cxn,           /* check_cxn */
   1823   Curl_gtls_shutdown,            /* shutdown */
   1824   Curl_gtls_data_pending,        /* data_pending */
   1825   Curl_gtls_random,              /* random */
   1826   Curl_gtls_cert_status_request, /* cert_status_request */
   1827   Curl_gtls_connect,             /* connect */
   1828   Curl_gtls_connect_nonblocking, /* connect_nonblocking */
   1829   Curl_gtls_get_internals,       /* get_internals */
   1830   Curl_gtls_close,               /* close_one */
   1831   Curl_none_close_all,           /* close_all */
   1832   Curl_gtls_session_free,        /* session_free */
   1833   Curl_none_set_engine,          /* set_engine */
   1834   Curl_none_set_engine_default,  /* set_engine_default */
   1835   Curl_none_engines_list,        /* engines_list */
   1836   Curl_none_false_start,         /* false_start */
   1837   Curl_gtls_md5sum,              /* md5sum */
   1838   Curl_gtls_sha256sum            /* sha256sum */
   1839 };
   1840 
   1841 #endif /* USE_GNUTLS */
   1842