1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@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 http://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/gnutls.h>
36#include <gnutls/x509.h>
37
38#ifdef USE_GNUTLS_NETTLE
39#include <gnutls/crypto.h>
40#include <nettle/md5.h>
41#else
42#include <gcrypt.h>
43#endif
44
45#include "urldata.h"
46#include "sendf.h"
47#include "inet_pton.h"
48#include "gtls.h"
49#include "vtls.h"
50#include "parsedate.h"
51#include "connect.h" /* for the connect timeout */
52#include "select.h"
53#include "rawstr.h"
54#include "warnless.h"
55
56#define _MPRINTF_REPLACE /* use our functions only */
57#include <curl/mprintf.h>
58#include "curl_memory.h"
59/* The last #include file should be: */
60#include "memdebug.h"
61
62/*
63 Some hackish cast macros based on:
64 http://library.gnome.org/devel/glib/unstable/glib-Type-Conversion-Macros.html
65*/
66#ifndef GNUTLS_POINTER_TO_INT_CAST
67#define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
68#endif
69#ifndef GNUTLS_INT_TO_POINTER_CAST
70#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
71#endif
72
73/* Enable GnuTLS debugging by defining GTLSDEBUG */
74/*#define GTLSDEBUG */
75
76#ifdef GTLSDEBUG
77static void tls_log_func(int level, const char *str)
78{
79    fprintf(stderr, "|<%d>| %s", level, str);
80}
81#endif
82static bool gtls_inited = FALSE;
83
84#if defined(GNUTLS_VERSION_NUMBER)
85#  if (GNUTLS_VERSION_NUMBER >= 0x020c00)
86#    undef gnutls_transport_set_lowat
87#    define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
88#    define USE_GNUTLS_PRIORITY_SET_DIRECT 1
89#  endif
90#  if (GNUTLS_VERSION_NUMBER >= 0x020c03)
91#    define GNUTLS_MAPS_WINSOCK_ERRORS 1
92#  endif
93
94#  ifdef USE_NGHTTP2
95#    undef HAS_ALPN
96#    if (GNUTLS_VERSION_NUMBER >= 0x030200)
97#      define HAS_ALPN
98#    endif
99#  endif
100#endif
101
102/*
103 * Custom push and pull callback functions used by GNU TLS to read and write
104 * to the socket.  These functions are simple wrappers to send() and recv()
105 * (although here using the sread/swrite macros as defined by
106 * curl_setup_once.h).
107 * We use custom functions rather than the GNU TLS defaults because it allows
108 * us to get specific about the fourth "flags" argument, and to use arbitrary
109 * private data with gnutls_transport_set_ptr if we wish.
110 *
111 * When these custom push and pull callbacks fail, GNU TLS checks its own
112 * session-specific error variable, and when not set also its own global
113 * errno variable, in order to take appropriate action. GNU TLS does not
114 * require that the transport is actually a socket. This implies that for
115 * Windows builds these callbacks should ideally set the session-specific
116 * error variable using function gnutls_transport_set_errno or as a last
117 * resort global errno variable using gnutls_transport_set_global_errno,
118 * with a transport agnostic error value. This implies that some winsock
119 * error translation must take place in these callbacks.
120 *
121 * Paragraph above applies to GNU TLS versions older than 2.12.3, since
122 * this version GNU TLS does its own internal winsock error translation
123 * using system_errno() function.
124 */
125
126#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
127#  define gtls_EINTR  4
128#  define gtls_EIO    5
129#  define gtls_EAGAIN 11
130static int gtls_mapped_sockerrno(void)
131{
132  switch(SOCKERRNO) {
133  case WSAEWOULDBLOCK:
134    return gtls_EAGAIN;
135  case WSAEINTR:
136    return gtls_EINTR;
137  default:
138    break;
139  }
140  return gtls_EIO;
141}
142#endif
143
144static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
145{
146  ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
147#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
148  if(ret < 0)
149    gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
150#endif
151  return ret;
152}
153
154static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
155{
156  ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
157#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
158  if(ret < 0)
159    gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
160#endif
161  return ret;
162}
163
164/* Curl_gtls_init()
165 *
166 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
167 * are not thread-safe and thus this function itself is not thread-safe and
168 * must only be called from within curl_global_init() to keep the thread
169 * situation under control!
170 */
171int Curl_gtls_init(void)
172{
173  int ret = 1;
174  if(!gtls_inited) {
175    ret = gnutls_global_init()?0:1;
176#ifdef GTLSDEBUG
177    gnutls_global_set_log_function(tls_log_func);
178    gnutls_global_set_log_level(2);
179#endif
180    gtls_inited = TRUE;
181  }
182  return ret;
183}
184
185int Curl_gtls_cleanup(void)
186{
187  if(gtls_inited) {
188    gnutls_global_deinit();
189    gtls_inited = FALSE;
190  }
191  return 1;
192}
193
194static void showtime(struct SessionHandle *data,
195                     const char *text,
196                     time_t stamp)
197{
198  struct tm buffer;
199  const struct tm *tm = &buffer;
200  CURLcode result = Curl_gmtime(stamp, &buffer);
201  if(result)
202    return;
203
204  snprintf(data->state.buffer,
205           BUFSIZE,
206           "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n",
207           text,
208           Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
209           tm->tm_mday,
210           Curl_month[tm->tm_mon],
211           tm->tm_year + 1900,
212           tm->tm_hour,
213           tm->tm_min,
214           tm->tm_sec);
215  infof(data, "%s\n", data->state.buffer);
216}
217
218static gnutls_datum_t load_file (const char *file)
219{
220  FILE *f;
221  gnutls_datum_t loaded_file = { NULL, 0 };
222  long filelen;
223  void *ptr;
224
225  if(!(f = fopen(file, "r")))
226    return loaded_file;
227  if(fseek(f, 0, SEEK_END) != 0
228     || (filelen = ftell(f)) < 0
229     || fseek(f, 0, SEEK_SET) != 0
230     || !(ptr = malloc((size_t)filelen)))
231    goto out;
232  if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
233    free(ptr);
234    goto out;
235  }
236
237  loaded_file.data = ptr;
238  loaded_file.size = (unsigned int)filelen;
239out:
240  fclose(f);
241  return loaded_file;
242}
243
244static void unload_file(gnutls_datum_t data) {
245  free(data.data);
246}
247
248
249/* this function does a SSL/TLS (re-)handshake */
250static CURLcode handshake(struct connectdata *conn,
251                          int sockindex,
252                          bool duringconnect,
253                          bool nonblocking)
254{
255  struct SessionHandle *data = conn->data;
256  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
257  gnutls_session_t session = conn->ssl[sockindex].session;
258  curl_socket_t sockfd = conn->sock[sockindex];
259  long timeout_ms;
260  int rc;
261  int what;
262
263  for(;;) {
264    /* check allowed time left */
265    timeout_ms = Curl_timeleft(data, NULL, duringconnect);
266
267    if(timeout_ms < 0) {
268      /* no need to continue if time already is up */
269      failf(data, "SSL connection timeout");
270      return CURLE_OPERATION_TIMEDOUT;
271    }
272
273    /* if ssl is expecting something, check if it's available. */
274    if(connssl->connecting_state == ssl_connect_2_reading
275       || connssl->connecting_state == ssl_connect_2_writing) {
276
277      curl_socket_t writefd = ssl_connect_2_writing==
278        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
279      curl_socket_t readfd = ssl_connect_2_reading==
280        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
281
282      what = Curl_socket_ready(readfd, writefd,
283                               nonblocking?0:
284                               timeout_ms?timeout_ms:1000);
285      if(what < 0) {
286        /* fatal error */
287        failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
288        return CURLE_SSL_CONNECT_ERROR;
289      }
290      else if(0 == what) {
291        if(nonblocking)
292          return CURLE_OK;
293        else if(timeout_ms) {
294          /* timeout */
295          failf(data, "SSL connection timeout at %ld", timeout_ms);
296          return CURLE_OPERATION_TIMEDOUT;
297        }
298      }
299      /* socket is readable or writable */
300    }
301
302    rc = gnutls_handshake(session);
303
304    if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
305      connssl->connecting_state =
306        gnutls_record_get_direction(session)?
307        ssl_connect_2_writing:ssl_connect_2_reading;
308      continue;
309      if(nonblocking)
310        return CURLE_OK;
311    }
312    else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
313      const char *strerr = NULL;
314
315      if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
316        int alert = gnutls_alert_get(session);
317        strerr = gnutls_alert_get_name(alert);
318      }
319
320      if(strerr == NULL)
321        strerr = gnutls_strerror(rc);
322
323      failf(data, "gnutls_handshake() warning: %s", strerr);
324    }
325    else if(rc < 0) {
326      const char *strerr = NULL;
327
328      if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
329        int alert = gnutls_alert_get(session);
330        strerr = gnutls_alert_get_name(alert);
331      }
332
333      if(strerr == NULL)
334        strerr = gnutls_strerror(rc);
335
336      failf(data, "gnutls_handshake() failed: %s", strerr);
337      return CURLE_SSL_CONNECT_ERROR;
338    }
339
340    /* Reset our connect state machine */
341    connssl->connecting_state = ssl_connect_1;
342    return CURLE_OK;
343  }
344}
345
346static gnutls_x509_crt_fmt_t do_file_type(const char *type)
347{
348  if(!type || !type[0])
349    return GNUTLS_X509_FMT_PEM;
350  if(Curl_raw_equal(type, "PEM"))
351    return GNUTLS_X509_FMT_PEM;
352  if(Curl_raw_equal(type, "DER"))
353    return GNUTLS_X509_FMT_DER;
354  return -1;
355}
356
357static CURLcode
358gtls_connect_step1(struct connectdata *conn,
359                   int sockindex)
360{
361  struct SessionHandle *data = conn->data;
362  gnutls_session_t session;
363  int rc;
364  void *ssl_sessionid;
365  size_t ssl_idsize;
366  bool sni = TRUE; /* default is SNI enabled */
367#ifdef ENABLE_IPV6
368  struct in6_addr addr;
369#else
370  struct in_addr addr;
371#endif
372#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
373  static const int cipher_priority[] = {
374  /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
375     but this code path is only ever used for ver. < 2.12.0.
376     GNUTLS_CIPHER_AES_128_GCM,
377     GNUTLS_CIPHER_AES_256_GCM,
378  */
379    GNUTLS_CIPHER_AES_128_CBC,
380    GNUTLS_CIPHER_AES_256_CBC,
381    GNUTLS_CIPHER_CAMELLIA_128_CBC,
382    GNUTLS_CIPHER_CAMELLIA_256_CBC,
383    GNUTLS_CIPHER_3DES_CBC,
384  };
385  static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
386  static int protocol_priority[] = { 0, 0, 0, 0 };
387#else
388#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
389/* If GnuTLS was compiled without support for SRP it will error out if SRP is
390   requested in the priority string, so treat it specially
391 */
392#define GNUTLS_SRP "+SRP"
393  const char* prioritylist;
394  const char *err = NULL;
395#endif
396#ifdef HAS_ALPN
397  int protocols_size = 2;
398  gnutls_datum_t protocols[2];
399#endif
400
401  if(conn->ssl[sockindex].state == ssl_connection_complete)
402    /* to make us tolerant against being called more than once for the
403       same connection */
404    return CURLE_OK;
405
406  if(!gtls_inited)
407    Curl_gtls_init();
408
409  /* GnuTLS only supports SSLv3 and TLSv1 */
410  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
411    failf(data, "GnuTLS does not support SSLv2");
412    return CURLE_SSL_CONNECT_ERROR;
413  }
414  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
415    sni = FALSE; /* SSLv3 has no SNI */
416
417  /* allocate a cred struct */
418  rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
419  if(rc != GNUTLS_E_SUCCESS) {
420    failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
421    return CURLE_SSL_CONNECT_ERROR;
422  }
423
424#ifdef USE_TLS_SRP
425  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
426    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
427
428    rc = gnutls_srp_allocate_client_credentials(
429           &conn->ssl[sockindex].srp_client_cred);
430    if(rc != GNUTLS_E_SUCCESS) {
431      failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
432            gnutls_strerror(rc));
433      return CURLE_OUT_OF_MEMORY;
434    }
435
436    rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
437                                           srp_client_cred,
438                                           data->set.ssl.username,
439                                           data->set.ssl.password);
440    if(rc != GNUTLS_E_SUCCESS) {
441      failf(data, "gnutls_srp_set_client_cred() failed: %s",
442            gnutls_strerror(rc));
443      return CURLE_BAD_FUNCTION_ARGUMENT;
444    }
445  }
446#endif
447
448  if(data->set.ssl.CAfile) {
449    /* set the trusted CA cert bundle file */
450    gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
451                                        GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
452
453    rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
454                                                data->set.ssl.CAfile,
455                                                GNUTLS_X509_FMT_PEM);
456    if(rc < 0) {
457      infof(data, "error reading ca cert file %s (%s)\n",
458            data->set.ssl.CAfile, gnutls_strerror(rc));
459      if(data->set.ssl.verifypeer)
460        return CURLE_SSL_CACERT_BADFILE;
461    }
462    else
463      infof(data, "found %d certificates in %s\n",
464            rc, data->set.ssl.CAfile);
465  }
466
467  if(data->set.ssl.CRLfile) {
468    /* set the CRL list file */
469    rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
470                                              data->set.ssl.CRLfile,
471                                              GNUTLS_X509_FMT_PEM);
472    if(rc < 0) {
473      failf(data, "error reading crl file %s (%s)",
474            data->set.ssl.CRLfile, gnutls_strerror(rc));
475      return CURLE_SSL_CRL_BADFILE;
476    }
477    else
478      infof(data, "found %d CRL in %s\n",
479            rc, data->set.ssl.CRLfile);
480  }
481
482  /* Initialize TLS session as a client */
483  rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
484  if(rc != GNUTLS_E_SUCCESS) {
485    failf(data, "gnutls_init() failed: %d", rc);
486    return CURLE_SSL_CONNECT_ERROR;
487  }
488
489  /* convenient assign */
490  session = conn->ssl[sockindex].session;
491
492  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
493#ifdef ENABLE_IPV6
494     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
495#endif
496     sni &&
497     (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
498                             strlen(conn->host.name)) < 0))
499    infof(data, "WARNING: failed to configure server name indication (SNI) "
500          "TLS extension\n");
501
502  /* Use default priorities */
503  rc = gnutls_set_default_priority(session);
504  if(rc != GNUTLS_E_SUCCESS)
505    return CURLE_SSL_CONNECT_ERROR;
506
507#ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
508  rc = gnutls_cipher_set_priority(session, cipher_priority);
509  if(rc != GNUTLS_E_SUCCESS)
510    return CURLE_SSL_CONNECT_ERROR;
511
512  /* Sets the priority on the certificate types supported by gnutls. Priority
513   is higher for types specified before others. After specifying the types
514   you want, you must append a 0. */
515  rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
516  if(rc != GNUTLS_E_SUCCESS)
517    return CURLE_SSL_CONNECT_ERROR;
518
519  if(data->set.ssl.cipher_list != NULL) {
520    failf(data, "can't pass a custom cipher list to older GnuTLS"
521          " versions");
522    return CURLE_SSL_CONNECT_ERROR;
523  }
524
525  switch (data->set.ssl.version) {
526    case CURL_SSLVERSION_SSLv3:
527      protocol_priority[0] = GNUTLS_SSL3;
528      break;
529    case CURL_SSLVERSION_DEFAULT:
530    case CURL_SSLVERSION_TLSv1:
531      protocol_priority[0] = GNUTLS_TLS1_0;
532      protocol_priority[1] = GNUTLS_TLS1_1;
533      protocol_priority[2] = GNUTLS_TLS1_2;
534      break;
535    case CURL_SSLVERSION_TLSv1_0:
536      protocol_priority[0] = GNUTLS_TLS1_0;
537      break;
538    case CURL_SSLVERSION_TLSv1_1:
539      protocol_priority[0] = GNUTLS_TLS1_1;
540      break;
541    case CURL_SSLVERSION_TLSv1_2:
542      protocol_priority[0] = GNUTLS_TLS1_2;
543    break;
544      case CURL_SSLVERSION_SSLv2:
545    default:
546      failf(data, "GnuTLS does not support SSLv2");
547      return CURLE_SSL_CONNECT_ERROR;
548      break;
549  }
550  rc = gnutls_protocol_set_priority(session, protocol_priority);
551  if(rc != GNUTLS_E_SUCCESS) {
552    failf(data, "Did you pass a valid GnuTLS cipher list?");
553    return CURLE_SSL_CONNECT_ERROR;
554  }
555
556#else
557  /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
558   * removed if a run-time error indicates that SRP is not supported by this
559   * GnuTLS version */
560  switch (data->set.ssl.version) {
561    case CURL_SSLVERSION_SSLv3:
562      prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
563      sni = false;
564      break;
565    case CURL_SSLVERSION_DEFAULT:
566    case CURL_SSLVERSION_TLSv1:
567      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
568      break;
569    case CURL_SSLVERSION_TLSv1_0:
570      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
571                     "+VERS-TLS1.0:" GNUTLS_SRP;
572      break;
573    case CURL_SSLVERSION_TLSv1_1:
574      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
575                     "+VERS-TLS1.1:" GNUTLS_SRP;
576      break;
577    case CURL_SSLVERSION_TLSv1_2:
578      prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
579                     "+VERS-TLS1.2:" GNUTLS_SRP;
580      break;
581    case CURL_SSLVERSION_SSLv2:
582    default:
583      failf(data, "GnuTLS does not support SSLv2");
584      return CURLE_SSL_CONNECT_ERROR;
585      break;
586  }
587  rc = gnutls_priority_set_direct(session, prioritylist, &err);
588  if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
589    if(!strcmp(err, GNUTLS_SRP)) {
590      /* This GnuTLS was probably compiled without support for SRP.
591       * Note that fact and try again without it. */
592      int validprioritylen = curlx_uztosi(err - prioritylist);
593      char *prioritycopy = strdup(prioritylist);
594      if(!prioritycopy)
595        return CURLE_OUT_OF_MEMORY;
596
597      infof(data, "This GnuTLS does not support SRP\n");
598      if(validprioritylen)
599        /* Remove the :+SRP */
600        prioritycopy[validprioritylen - 1] = 0;
601      rc = gnutls_priority_set_direct(session, prioritycopy, &err);
602      free(prioritycopy);
603    }
604  }
605  if(rc != GNUTLS_E_SUCCESS) {
606    failf(data, "Error %d setting GnuTLS cipher list starting with %s",
607          rc, err);
608    return CURLE_SSL_CONNECT_ERROR;
609  }
610#endif
611
612#ifdef HAS_ALPN
613  if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
614    if(data->set.ssl_enable_alpn) {
615      protocols[0].data = NGHTTP2_PROTO_VERSION_ID;
616      protocols[0].size = NGHTTP2_PROTO_VERSION_ID_LEN;
617      protocols[1].data = ALPN_HTTP_1_1;
618      protocols[1].size = ALPN_HTTP_1_1_LENGTH;
619      gnutls_alpn_set_protocols(session, protocols, protocols_size, 0);
620      infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
621            ALPN_HTTP_1_1);
622    }
623    else {
624      infof(data, "SSL, can't negotiate HTTP/2.0 without ALPN\n");
625    }
626  }
627#endif
628
629  if(data->set.str[STRING_CERT]) {
630    if(gnutls_certificate_set_x509_key_file(
631         conn->ssl[sockindex].cred,
632         data->set.str[STRING_CERT],
633         data->set.str[STRING_KEY] ?
634         data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
635         do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
636       GNUTLS_E_SUCCESS) {
637      failf(data, "error reading X.509 key or certificate file");
638      return CURLE_SSL_CONNECT_ERROR;
639    }
640  }
641
642#ifdef USE_TLS_SRP
643  /* put the credentials to the current session */
644  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
645    rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
646                                conn->ssl[sockindex].srp_client_cred);
647    if(rc != GNUTLS_E_SUCCESS)
648      failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
649  }
650  else
651#endif
652    rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
653                                conn->ssl[sockindex].cred);
654
655  /* set the connection handle (file descriptor for the socket) */
656  gnutls_transport_set_ptr(session,
657                           GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
658
659  /* register callback functions to send and receive data. */
660  gnutls_transport_set_push_function(session, Curl_gtls_push);
661  gnutls_transport_set_pull_function(session, Curl_gtls_pull);
662
663  /* lowat must be set to zero when using custom push and pull functions. */
664  gnutls_transport_set_lowat(session, 0);
665
666  /* This might be a reconnect, so we check for a session ID in the cache
667     to speed up things */
668
669  if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
670    /* we got a session id, use it! */
671    gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
672
673    /* Informational message */
674    infof (data, "SSL re-using session ID\n");
675  }
676
677  return CURLE_OK;
678}
679
680static Curl_recv gtls_recv;
681static Curl_send gtls_send;
682
683static CURLcode
684gtls_connect_step3(struct connectdata *conn,
685                   int sockindex)
686{
687  unsigned int cert_list_size;
688  const gnutls_datum_t *chainp;
689  unsigned int verify_status;
690  gnutls_x509_crt_t x509_cert,x509_issuer;
691  gnutls_datum_t issuerp;
692  char certbuf[256] = ""; /* big enough? */
693  size_t size;
694  unsigned int algo;
695  unsigned int bits;
696  time_t certclock;
697  const char *ptr;
698  struct SessionHandle *data = conn->data;
699  gnutls_session_t session = conn->ssl[sockindex].session;
700  int rc;
701  int incache;
702  void *ssl_sessionid;
703#ifdef HAS_ALPN
704  gnutls_datum_t proto;
705#endif
706  CURLcode result = CURLE_OK;
707
708  /* This function will return the peer's raw certificate (chain) as sent by
709     the peer. These certificates are in raw format (DER encoded for
710     X.509). In case of a X.509 then a certificate list may be present. The
711     first certificate in the list is the peer's certificate, following the
712     issuer's certificate, then the issuer's issuer etc. */
713
714  chainp = gnutls_certificate_get_peers(session, &cert_list_size);
715  if(!chainp) {
716    if(data->set.ssl.verifypeer ||
717       data->set.ssl.verifyhost ||
718       data->set.ssl.issuercert) {
719#ifdef USE_TLS_SRP
720      if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
721         && data->set.ssl.username != NULL
722         && !data->set.ssl.verifypeer
723         && gnutls_cipher_get(session)) {
724        /* no peer cert, but auth is ok if we have SRP user and cipher and no
725           peer verify */
726      }
727      else {
728#endif
729        failf(data, "failed to get server cert");
730        return CURLE_PEER_FAILED_VERIFICATION;
731#ifdef USE_TLS_SRP
732      }
733#endif
734    }
735    infof(data, "\t common name: WARNING couldn't obtain\n");
736  }
737
738  if(data->set.ssl.verifypeer) {
739    /* This function will try to verify the peer's certificate and return its
740       status (trusted, invalid etc.). The value of status should be one or
741       more of the gnutls_certificate_status_t enumerated elements bitwise
742       or'd. To avoid denial of service attacks some default upper limits
743       regarding the certificate key size and chain size are set. To override
744       them use gnutls_certificate_set_verify_limits(). */
745
746    rc = gnutls_certificate_verify_peers2(session, &verify_status);
747    if(rc < 0) {
748      failf(data, "server cert verify failed: %d", rc);
749      return CURLE_SSL_CONNECT_ERROR;
750    }
751
752    /* verify_status is a bitmask of gnutls_certificate_status bits */
753    if(verify_status & GNUTLS_CERT_INVALID) {
754      if(data->set.ssl.verifypeer) {
755        failf(data, "server certificate verification failed. CAfile: %s "
756              "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
757              data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
758        return CURLE_SSL_CACERT;
759      }
760      else
761        infof(data, "\t server certificate verification FAILED\n");
762    }
763    else
764      infof(data, "\t server certificate verification OK\n");
765  }
766  else
767    infof(data, "\t server certificate verification SKIPPED\n");
768
769  /* initialize an X.509 certificate structure. */
770  gnutls_x509_crt_init(&x509_cert);
771
772  if(chainp)
773    /* convert the given DER or PEM encoded Certificate to the native
774       gnutls_x509_crt_t format */
775    gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
776
777  if(data->set.ssl.issuercert) {
778    gnutls_x509_crt_init(&x509_issuer);
779    issuerp = load_file(data->set.ssl.issuercert);
780    gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
781    rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer);
782    unload_file(issuerp);
783    if(rc <= 0) {
784      failf(data, "server certificate issuer check failed (IssuerCert: %s)",
785            data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
786      return CURLE_SSL_ISSUER_ERROR;
787    }
788    infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
789          data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
790  }
791
792  size=sizeof(certbuf);
793  rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
794                                     0, /* the first and only one */
795                                     FALSE,
796                                     certbuf,
797                                     &size);
798  if(rc) {
799    infof(data, "error fetching CN from cert:%s\n",
800          gnutls_strerror(rc));
801  }
802
803  /* This function will check if the given certificate's subject matches the
804     given hostname. This is a basic implementation of the matching described
805     in RFC2818 (HTTPS), which takes into account wildcards, and the subject
806     alternative name PKIX extension. Returns non zero on success, and zero on
807     failure. */
808  rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
809#if GNUTLS_VERSION_NUMBER < 0x030306
810  /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
811     addresses. */
812  if(!rc) {
813#ifdef ENABLE_IPV6
814    #define use_addr in6_addr
815#else
816    #define use_addr in_addr
817#endif
818    unsigned char addrbuf[sizeof(struct use_addr)];
819    unsigned char certaddr[sizeof(struct use_addr)];
820    size_t addrlen = 0, certaddrlen;
821    int i;
822    int ret = 0;
823
824    if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
825      addrlen = 4;
826#ifdef ENABLE_IPV6
827    else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
828      addrlen = 16;
829#endif
830
831    if(addrlen) {
832      for(i=0; ; i++) {
833        certaddrlen = sizeof(certaddr);
834        ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
835                                                   &certaddrlen, NULL);
836        /* If this happens, it wasn't an IP address. */
837        if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
838          continue;
839        if(ret < 0)
840          break;
841        if(ret != GNUTLS_SAN_IPADDRESS)
842          continue;
843        if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
844          rc = 1;
845          break;
846        }
847      }
848    }
849  }
850#endif
851  if(!rc) {
852    if(data->set.ssl.verifyhost) {
853      failf(data, "SSL: certificate subject name (%s) does not match "
854            "target host name '%s'", certbuf, conn->host.dispname);
855      gnutls_x509_crt_deinit(x509_cert);
856      return CURLE_PEER_FAILED_VERIFICATION;
857    }
858    else
859      infof(data, "\t common name: %s (does not match '%s')\n",
860            certbuf, conn->host.dispname);
861  }
862  else
863    infof(data, "\t common name: %s (matched)\n", certbuf);
864
865  /* Check for time-based validity */
866  certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
867
868  if(certclock == (time_t)-1) {
869    if(data->set.ssl.verifypeer) {
870      failf(data, "server cert expiration date verify failed");
871      return CURLE_SSL_CONNECT_ERROR;
872    }
873    else
874      infof(data, "\t server certificate expiration date verify FAILED\n");
875  }
876  else {
877    if(certclock < time(NULL)) {
878      if(data->set.ssl.verifypeer) {
879        failf(data, "server certificate expiration date has passed.");
880        return CURLE_PEER_FAILED_VERIFICATION;
881      }
882      else
883        infof(data, "\t server certificate expiration date FAILED\n");
884    }
885    else
886      infof(data, "\t server certificate expiration date OK\n");
887  }
888
889  certclock = gnutls_x509_crt_get_activation_time(x509_cert);
890
891  if(certclock == (time_t)-1) {
892    if(data->set.ssl.verifypeer) {
893      failf(data, "server cert activation date verify failed");
894      return CURLE_SSL_CONNECT_ERROR;
895    }
896    else
897      infof(data, "\t server certificate activation date verify FAILED\n");
898  }
899  else {
900    if(certclock > time(NULL)) {
901      if(data->set.ssl.verifypeer) {
902        failf(data, "server certificate not activated yet.");
903        return CURLE_PEER_FAILED_VERIFICATION;
904      }
905      else
906        infof(data, "\t server certificate activation date FAILED\n");
907    }
908    else
909      infof(data, "\t server certificate activation date OK\n");
910  }
911
912  /* Show:
913
914  - ciphers used
915  - subject
916  - start date
917  - expire date
918  - common name
919  - issuer
920
921  */
922
923  /* public key algorithm's parameters */
924  algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
925  infof(data, "\t certificate public key: %s\n",
926        gnutls_pk_algorithm_get_name(algo));
927
928  /* version of the X.509 certificate. */
929  infof(data, "\t certificate version: #%d\n",
930        gnutls_x509_crt_get_version(x509_cert));
931
932
933  size = sizeof(certbuf);
934  gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
935  infof(data, "\t subject: %s\n", certbuf);
936
937  certclock = gnutls_x509_crt_get_activation_time(x509_cert);
938  showtime(data, "start date", certclock);
939
940  certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
941  showtime(data, "expire date", certclock);
942
943  size = sizeof(certbuf);
944  gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
945  infof(data, "\t issuer: %s\n", certbuf);
946
947  gnutls_x509_crt_deinit(x509_cert);
948
949  /* compression algorithm (if any) */
950  ptr = gnutls_compression_get_name(gnutls_compression_get(session));
951  /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
952  infof(data, "\t compression: %s\n", ptr);
953
954  /* the name of the cipher used. ie 3DES. */
955  ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
956  infof(data, "\t cipher: %s\n", ptr);
957
958  /* the MAC algorithms name. ie SHA1 */
959  ptr = gnutls_mac_get_name(gnutls_mac_get(session));
960  infof(data, "\t MAC: %s\n", ptr);
961
962#ifdef HAS_ALPN
963  if(data->set.ssl_enable_alpn) {
964    rc = gnutls_alpn_get_selected_protocol(session, &proto);
965    if(rc == 0) {
966      infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
967          proto.data);
968
969      if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
970        memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
971        NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
972        conn->negnpn = NPN_HTTP2;
973      }
974      else if(proto.size == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
975          proto.data, ALPN_HTTP_1_1_LENGTH) == 0) {
976        conn->negnpn = NPN_HTTP1_1;
977      }
978    }
979    else {
980      infof(data, "ALPN, server did not agree to a protocol\n");
981    }
982  }
983#endif
984
985  conn->ssl[sockindex].state = ssl_connection_complete;
986  conn->recv[sockindex] = gtls_recv;
987  conn->send[sockindex] = gtls_send;
988
989  {
990    /* we always unconditionally get the session id here, as even if we
991       already got it from the cache and asked to use it in the connection, it
992       might've been rejected and then a new one is in use now and we need to
993       detect that. */
994    void *connect_sessionid;
995    size_t connect_idsize = 0;
996
997    /* get the session ID data size */
998    gnutls_session_get_data(session, NULL, &connect_idsize);
999    connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1000
1001    if(connect_sessionid) {
1002      /* extract session ID to the allocated buffer */
1003      gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1004
1005      incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
1006      if(incache) {
1007        /* there was one before in the cache, so instead of risking that the
1008           previous one was rejected, we just kill that and store the new */
1009        Curl_ssl_delsessionid(conn, ssl_sessionid);
1010      }
1011
1012      /* store this session id */
1013      result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
1014      if(result) {
1015        free(connect_sessionid);
1016        result = CURLE_OUT_OF_MEMORY;
1017      }
1018    }
1019    else
1020      result = CURLE_OUT_OF_MEMORY;
1021  }
1022
1023  return result;
1024}
1025
1026
1027/*
1028 * This function is called after the TCP connect has completed. Setup the TLS
1029 * layer and do all necessary magic.
1030 */
1031/* We use connssl->connecting_state to keep track of the connection status;
1032   there are three states: 'ssl_connect_1' (not started yet or complete),
1033   'ssl_connect_2_reading' (waiting for data from server), and
1034   'ssl_connect_2_writing' (waiting to be able to write).
1035 */
1036static CURLcode
1037gtls_connect_common(struct connectdata *conn,
1038                    int sockindex,
1039                    bool nonblocking,
1040                    bool *done)
1041{
1042  int rc;
1043  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1044
1045  /* Initiate the connection, if not already done */
1046  if(ssl_connect_1==connssl->connecting_state) {
1047    rc = gtls_connect_step1 (conn, sockindex);
1048    if(rc)
1049      return rc;
1050  }
1051
1052  rc = handshake(conn, sockindex, TRUE, nonblocking);
1053  if(rc)
1054    /* handshake() sets its own error message with failf() */
1055    return rc;
1056
1057  /* Finish connecting once the handshake is done */
1058  if(ssl_connect_1==connssl->connecting_state) {
1059    rc = gtls_connect_step3(conn, sockindex);
1060    if(rc)
1061      return rc;
1062  }
1063
1064  *done = ssl_connect_1==connssl->connecting_state;
1065
1066  return CURLE_OK;
1067}
1068
1069CURLcode
1070Curl_gtls_connect_nonblocking(struct connectdata *conn,
1071                              int sockindex,
1072                              bool *done)
1073{
1074  return gtls_connect_common(conn, sockindex, TRUE, done);
1075}
1076
1077CURLcode
1078Curl_gtls_connect(struct connectdata *conn,
1079                  int sockindex)
1080
1081{
1082  CURLcode retcode;
1083  bool done = FALSE;
1084
1085  retcode = gtls_connect_common(conn, sockindex, FALSE, &done);
1086  if(retcode)
1087    return retcode;
1088
1089  DEBUGASSERT(done);
1090
1091  return CURLE_OK;
1092}
1093
1094static ssize_t gtls_send(struct connectdata *conn,
1095                         int sockindex,
1096                         const void *mem,
1097                         size_t len,
1098                         CURLcode *curlcode)
1099{
1100  ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
1101
1102  if(rc < 0 ) {
1103    *curlcode = (rc == GNUTLS_E_AGAIN)
1104      ? CURLE_AGAIN
1105      : CURLE_SEND_ERROR;
1106
1107    rc = -1;
1108  }
1109
1110  return rc;
1111}
1112
1113void Curl_gtls_close_all(struct SessionHandle *data)
1114{
1115  /* FIX: make the OpenSSL code more generic and use parts of it here */
1116  (void)data;
1117}
1118
1119static void close_one(struct connectdata *conn,
1120                      int idx)
1121{
1122  if(conn->ssl[idx].session) {
1123    gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
1124    gnutls_deinit(conn->ssl[idx].session);
1125    conn->ssl[idx].session = NULL;
1126  }
1127  if(conn->ssl[idx].cred) {
1128    gnutls_certificate_free_credentials(conn->ssl[idx].cred);
1129    conn->ssl[idx].cred = NULL;
1130  }
1131#ifdef USE_TLS_SRP
1132  if(conn->ssl[idx].srp_client_cred) {
1133    gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
1134    conn->ssl[idx].srp_client_cred = NULL;
1135  }
1136#endif
1137}
1138
1139void Curl_gtls_close(struct connectdata *conn, int sockindex)
1140{
1141  close_one(conn, sockindex);
1142}
1143
1144/*
1145 * This function is called to shut down the SSL layer but keep the
1146 * socket open (CCC - Clear Command Channel)
1147 */
1148int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
1149{
1150  ssize_t result;
1151  int retval = 0;
1152  struct SessionHandle *data = conn->data;
1153  int done = 0;
1154  char buf[120];
1155
1156  /* This has only been tested on the proftpd server, and the mod_tls code
1157     sends a close notify alert without waiting for a close notify alert in
1158     response. Thus we wait for a close notify alert from the server, but
1159     we do not send one. Let's hope other servers do the same... */
1160
1161  if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1162      gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
1163
1164  if(conn->ssl[sockindex].session) {
1165    while(!done) {
1166      int what = Curl_socket_ready(conn->sock[sockindex],
1167                                   CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
1168      if(what > 0) {
1169        /* Something to read, let's do it and hope that it is the close
1170           notify alert from the server */
1171        result = gnutls_record_recv(conn->ssl[sockindex].session,
1172                                    buf, sizeof(buf));
1173        switch(result) {
1174        case 0:
1175          /* This is the expected response. There was no data but only
1176             the close notify alert */
1177          done = 1;
1178          break;
1179        case GNUTLS_E_AGAIN:
1180        case GNUTLS_E_INTERRUPTED:
1181          infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1182          break;
1183        default:
1184          retval = -1;
1185          done = 1;
1186          break;
1187        }
1188      }
1189      else if(0 == what) {
1190        /* timeout */
1191        failf(data, "SSL shutdown timeout");
1192        done = 1;
1193        break;
1194      }
1195      else {
1196        /* anything that gets here is fatally bad */
1197        failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1198        retval = -1;
1199        done = 1;
1200      }
1201    }
1202    gnutls_deinit(conn->ssl[sockindex].session);
1203  }
1204  gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
1205
1206#ifdef USE_TLS_SRP
1207  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
1208     && data->set.ssl.username != NULL)
1209    gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
1210#endif
1211
1212  conn->ssl[sockindex].cred = NULL;
1213  conn->ssl[sockindex].session = NULL;
1214
1215  return retval;
1216}
1217
1218static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
1219                         int num,                  /* socketindex */
1220                         char *buf,                /* store read data here */
1221                         size_t buffersize,        /* max amount to read */
1222                         CURLcode *curlcode)
1223{
1224  ssize_t ret;
1225
1226  ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
1227  if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1228    *curlcode = CURLE_AGAIN;
1229    return -1;
1230  }
1231
1232  if(ret == GNUTLS_E_REHANDSHAKE) {
1233    /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1234       proper way" takes a whole lot of work. */
1235    CURLcode rc = handshake(conn, num, FALSE, FALSE);
1236    if(rc)
1237      /* handshake() writes error message on its own */
1238      *curlcode = rc;
1239    else
1240      *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1241    return -1;
1242  }
1243
1244  if(ret < 0) {
1245    failf(conn->data, "GnuTLS recv error (%d): %s",
1246          (int)ret, gnutls_strerror((int)ret));
1247    *curlcode = CURLE_RECV_ERROR;
1248    return -1;
1249  }
1250
1251  return ret;
1252}
1253
1254void Curl_gtls_session_free(void *ptr)
1255{
1256  free(ptr);
1257}
1258
1259size_t Curl_gtls_version(char *buffer, size_t size)
1260{
1261  return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1262}
1263
1264int Curl_gtls_seed(struct SessionHandle *data)
1265{
1266  /* we have the "SSL is seeded" boolean static to prevent multiple
1267     time-consuming seedings in vain */
1268  static bool ssl_seeded = FALSE;
1269
1270  /* Quickly add a bit of entropy */
1271#ifndef USE_GNUTLS_NETTLE
1272  gcry_fast_random_poll();
1273#endif
1274
1275  if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1276     data->set.str[STRING_SSL_EGDSOCKET]) {
1277
1278    /* TODO: to a good job seeding the RNG
1279       This may involve the gcry_control function and these options:
1280       GCRYCTL_SET_RANDOM_SEED_FILE
1281       GCRYCTL_SET_RNDEGD_SOCKET
1282    */
1283    ssl_seeded = TRUE;
1284  }
1285  return 0;
1286}
1287
1288void Curl_gtls_random(struct SessionHandle *data,
1289                      unsigned char *entropy,
1290                      size_t length)
1291{
1292#if defined(USE_GNUTLS_NETTLE)
1293  (void)data;
1294  gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1295#elif defined(USE_GNUTLS)
1296  Curl_gtls_seed(data); /* Initiate the seed if not already done */
1297  gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1298#endif
1299}
1300
1301void Curl_gtls_md5sum(unsigned char *tmp, /* input */
1302                      size_t tmplen,
1303                      unsigned char *md5sum, /* output */
1304                      size_t md5len)
1305{
1306#if defined(USE_GNUTLS_NETTLE)
1307  struct md5_ctx MD5pw;
1308  md5_init(&MD5pw);
1309  md5_update(&MD5pw, (unsigned int)tmplen, tmp);
1310  md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
1311#elif defined(USE_GNUTLS)
1312  gcry_md_hd_t MD5pw;
1313  gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1314  gcry_md_write(MD5pw, tmp, tmplen);
1315  memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
1316  gcry_md_close(MD5pw);
1317#endif
1318}
1319
1320#endif /* USE_GNUTLS */
1321