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