gnutls: handle IP address in cert name check
[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   const char* prioritylist;
389   const char *err = NULL;
390 #endif
391 #ifdef HAS_ALPN
392   int protocols_size = 2;
393   gnutls_datum_t protocols[2];
394 #endif
395
396   if(conn->ssl[sockindex].state == ssl_connection_complete)
397     /* to make us tolerant against being called more than once for the
398        same connection */
399     return CURLE_OK;
400
401   if(!gtls_inited)
402     Curl_gtls_init();
403
404   /* GnuTLS only supports SSLv3 and TLSv1 */
405   if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
406     failf(data, "GnuTLS does not support SSLv2");
407     return CURLE_SSL_CONNECT_ERROR;
408   }
409   else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
410     sni = FALSE; /* SSLv3 has no SNI */
411
412   /* allocate a cred struct */
413   rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
414   if(rc != GNUTLS_E_SUCCESS) {
415     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
416     return CURLE_SSL_CONNECT_ERROR;
417   }
418
419 #ifdef USE_TLS_SRP
420   if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
421     infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
422
423     rc = gnutls_srp_allocate_client_credentials(
424            &conn->ssl[sockindex].srp_client_cred);
425     if(rc != GNUTLS_E_SUCCESS) {
426       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
427             gnutls_strerror(rc));
428       return CURLE_OUT_OF_MEMORY;
429     }
430
431     rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
432                                            srp_client_cred,
433                                            data->set.ssl.username,
434                                            data->set.ssl.password);
435     if(rc != GNUTLS_E_SUCCESS) {
436       failf(data, "gnutls_srp_set_client_cred() failed: %s",
437             gnutls_strerror(rc));
438       return CURLE_BAD_FUNCTION_ARGUMENT;
439     }
440   }
441 #endif
442
443   if(data->set.ssl.CAfile) {
444     /* set the trusted CA cert bundle file */
445     gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
446                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
447
448     rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
449                                                 data->set.ssl.CAfile,
450                                                 GNUTLS_X509_FMT_PEM);
451     if(rc < 0) {
452       infof(data, "error reading ca cert file %s (%s)\n",
453             data->set.ssl.CAfile, gnutls_strerror(rc));
454       if(data->set.ssl.verifypeer)
455         return CURLE_SSL_CACERT_BADFILE;
456     }
457     else
458       infof(data, "found %d certificates in %s\n",
459             rc, data->set.ssl.CAfile);
460   }
461
462   if(data->set.ssl.CRLfile) {
463     /* set the CRL list file */
464     rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
465                                               data->set.ssl.CRLfile,
466                                               GNUTLS_X509_FMT_PEM);
467     if(rc < 0) {
468       failf(data, "error reading crl file %s (%s)",
469             data->set.ssl.CRLfile, gnutls_strerror(rc));
470       return CURLE_SSL_CRL_BADFILE;
471     }
472     else
473       infof(data, "found %d CRL in %s\n",
474             rc, data->set.ssl.CRLfile);
475   }
476
477   /* Initialize TLS session as a client */
478   rc = gnutls_init(&conn->ssl[sockindex].session, GNUTLS_CLIENT);
479   if(rc != GNUTLS_E_SUCCESS) {
480     failf(data, "gnutls_init() failed: %d", rc);
481     return CURLE_SSL_CONNECT_ERROR;
482   }
483
484   /* convenient assign */
485   session = conn->ssl[sockindex].session;
486
487   if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
488 #ifdef ENABLE_IPV6
489      (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
490 #endif
491      sni &&
492      (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
493                              strlen(conn->host.name)) < 0))
494     infof(data, "WARNING: failed to configure server name indication (SNI) "
495           "TLS extension\n");
496
497   /* Use default priorities */
498   rc = gnutls_set_default_priority(session);
499   if(rc != GNUTLS_E_SUCCESS)
500     return CURLE_SSL_CONNECT_ERROR;
501
502 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
503   rc = gnutls_cipher_set_priority(session, cipher_priority);
504   if(rc != GNUTLS_E_SUCCESS)
505     return CURLE_SSL_CONNECT_ERROR;
506
507   /* Sets the priority on the certificate types supported by gnutls. Priority
508    is higher for types specified before others. After specifying the types
509    you want, you must append a 0. */
510   rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
511   if(rc != GNUTLS_E_SUCCESS)
512     return CURLE_SSL_CONNECT_ERROR;
513
514   if(data->set.ssl.cipher_list != NULL) {
515     failf(data, "can't pass a custom cipher list to older GnuTLS"
516           " versions");
517     return CURLE_SSL_CONNECT_ERROR;
518   }
519
520   switch (data->set.ssl.version) {
521     case CURL_SSLVERSION_SSLv3:
522       protocol_priority[0] = GNUTLS_SSL3;
523       break;
524     case CURL_SSLVERSION_DEFAULT:
525     case CURL_SSLVERSION_TLSv1:
526       protocol_priority[0] = GNUTLS_TLS1_0;
527       protocol_priority[1] = GNUTLS_TLS1_1;
528       protocol_priority[2] = GNUTLS_TLS1_2;
529       break;
530     case CURL_SSLVERSION_TLSv1_0:
531       protocol_priority[0] = GNUTLS_TLS1_0;
532       break;
533     case CURL_SSLVERSION_TLSv1_1:
534       protocol_priority[0] = GNUTLS_TLS1_1;
535       break;
536     case CURL_SSLVERSION_TLSv1_2:
537       protocol_priority[0] = GNUTLS_TLS1_2;
538     break;
539       case CURL_SSLVERSION_SSLv2:
540     default:
541       failf(data, "GnuTLS does not support SSLv2");
542       return CURLE_SSL_CONNECT_ERROR;
543       break;
544   }
545   rc = gnutls_protocol_set_priority(session, protocol_priority);
546   if(rc != GNUTLS_E_SUCCESS) {
547     failf(data, "Did you pass a valid GnuTLS cipher list?");
548     return CURLE_SSL_CONNECT_ERROR;
549   }
550
551 #else
552   switch (data->set.ssl.version) {
553     case CURL_SSLVERSION_SSLv3:
554       prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
555       sni = false;
556       break;
557     case CURL_SSLVERSION_DEFAULT:
558     case CURL_SSLVERSION_TLSv1:
559       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:+SRP";
560       break;
561     case CURL_SSLVERSION_TLSv1_0:
562       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
563                      "+VERS-TLS1.0:+SRP";
564       break;
565     case CURL_SSLVERSION_TLSv1_1:
566       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
567                      "+VERS-TLS1.1:+SRP";
568       break;
569     case CURL_SSLVERSION_TLSv1_2:
570       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
571                      "+VERS-TLS1.2:+SRP";
572       break;
573     case CURL_SSLVERSION_SSLv2:
574     default:
575       failf(data, "GnuTLS does not support SSLv2");
576       return CURLE_SSL_CONNECT_ERROR;
577       break;
578   }
579   rc = gnutls_priority_set_direct(session, prioritylist, &err);
580   if(rc != GNUTLS_E_SUCCESS) {
581     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
582           rc, err);
583     return CURLE_SSL_CONNECT_ERROR;
584   }
585 #endif
586
587 #ifdef HAS_ALPN
588   if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
589     if(data->set.ssl_enable_alpn) {
590       protocols[0].data = NGHTTP2_PROTO_VERSION_ID;
591       protocols[0].size = NGHTTP2_PROTO_VERSION_ID_LEN;
592       protocols[1].data = ALPN_HTTP_1_1;
593       protocols[1].size = ALPN_HTTP_1_1_LENGTH;
594       gnutls_alpn_set_protocols(session, protocols, protocols_size, 0);
595       infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
596             ALPN_HTTP_1_1);
597     }
598     else {
599       infof(data, "SSL, can't negotiate HTTP/2.0 without ALPN\n");
600     }
601   }
602 #endif
603
604   if(data->set.str[STRING_CERT]) {
605     if(gnutls_certificate_set_x509_key_file(
606          conn->ssl[sockindex].cred,
607          data->set.str[STRING_CERT],
608          data->set.str[STRING_KEY] ?
609          data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
610          do_file_type(data->set.str[STRING_CERT_TYPE]) ) !=
611        GNUTLS_E_SUCCESS) {
612       failf(data, "error reading X.509 key or certificate file");
613       return CURLE_SSL_CONNECT_ERROR;
614     }
615   }
616
617 #ifdef USE_TLS_SRP
618   /* put the credentials to the current session */
619   if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
620     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
621                                 conn->ssl[sockindex].srp_client_cred);
622     if(rc != GNUTLS_E_SUCCESS)
623       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
624   }
625   else
626 #endif
627     rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
628                                 conn->ssl[sockindex].cred);
629
630   /* set the connection handle (file descriptor for the socket) */
631   gnutls_transport_set_ptr(session,
632                            GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
633
634   /* register callback functions to send and receive data. */
635   gnutls_transport_set_push_function(session, Curl_gtls_push);
636   gnutls_transport_set_pull_function(session, Curl_gtls_pull);
637
638   /* lowat must be set to zero when using custom push and pull functions. */
639   gnutls_transport_set_lowat(session, 0);
640
641   /* This might be a reconnect, so we check for a session ID in the cache
642      to speed up things */
643
644   if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
645     /* we got a session id, use it! */
646     gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
647
648     /* Informational message */
649     infof (data, "SSL re-using session ID\n");
650   }
651
652   return CURLE_OK;
653 }
654
655 static Curl_recv gtls_recv;
656 static Curl_send gtls_send;
657
658 static CURLcode
659 gtls_connect_step3(struct connectdata *conn,
660                    int sockindex)
661 {
662   unsigned int cert_list_size;
663   const gnutls_datum_t *chainp;
664   unsigned int verify_status;
665   gnutls_x509_crt_t x509_cert,x509_issuer;
666   gnutls_datum_t issuerp;
667   char certbuf[256] = ""; /* big enough? */
668   size_t size;
669   unsigned int algo;
670   unsigned int bits;
671   time_t certclock;
672   const char *ptr;
673   struct SessionHandle *data = conn->data;
674   gnutls_session_t session = conn->ssl[sockindex].session;
675   int rc;
676   int incache;
677   void *ssl_sessionid;
678 #ifdef HAS_ALPN
679   gnutls_datum_t proto;
680 #endif
681   CURLcode result = CURLE_OK;
682
683   /* This function will return the peer's raw certificate (chain) as sent by
684      the peer. These certificates are in raw format (DER encoded for
685      X.509). In case of a X.509 then a certificate list may be present. The
686      first certificate in the list is the peer's certificate, following the
687      issuer's certificate, then the issuer's issuer etc. */
688
689   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
690   if(!chainp) {
691     if(data->set.ssl.verifypeer ||
692        data->set.ssl.verifyhost ||
693        data->set.ssl.issuercert) {
694 #ifdef USE_TLS_SRP
695       if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
696          && data->set.ssl.username != NULL
697          && !data->set.ssl.verifypeer
698          && gnutls_cipher_get(session)) {
699         /* no peer cert, but auth is ok if we have SRP user and cipher and no
700            peer verify */
701       }
702       else {
703 #endif
704         failf(data, "failed to get server cert");
705         return CURLE_PEER_FAILED_VERIFICATION;
706 #ifdef USE_TLS_SRP
707       }
708 #endif
709     }
710     infof(data, "\t common name: WARNING couldn't obtain\n");
711   }
712
713   if(data->set.ssl.verifypeer) {
714     /* This function will try to verify the peer's certificate and return its
715        status (trusted, invalid etc.). The value of status should be one or
716        more of the gnutls_certificate_status_t enumerated elements bitwise
717        or'd. To avoid denial of service attacks some default upper limits
718        regarding the certificate key size and chain size are set. To override
719        them use gnutls_certificate_set_verify_limits(). */
720
721     rc = gnutls_certificate_verify_peers2(session, &verify_status);
722     if(rc < 0) {
723       failf(data, "server cert verify failed: %d", rc);
724       return CURLE_SSL_CONNECT_ERROR;
725     }
726
727     /* verify_status is a bitmask of gnutls_certificate_status bits */
728     if(verify_status & GNUTLS_CERT_INVALID) {
729       if(data->set.ssl.verifypeer) {
730         failf(data, "server certificate verification failed. CAfile: %s "
731               "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
732               data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
733         return CURLE_SSL_CACERT;
734       }
735       else
736         infof(data, "\t server certificate verification FAILED\n");
737     }
738     else
739       infof(data, "\t server certificate verification OK\n");
740   }
741   else
742     infof(data, "\t server certificate verification SKIPPED\n");
743
744   /* initialize an X.509 certificate structure. */
745   gnutls_x509_crt_init(&x509_cert);
746
747   if(chainp)
748     /* convert the given DER or PEM encoded Certificate to the native
749        gnutls_x509_crt_t format */
750     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
751
752   if(data->set.ssl.issuercert) {
753     gnutls_x509_crt_init(&x509_issuer);
754     issuerp = load_file(data->set.ssl.issuercert);
755     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
756     rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer);
757     unload_file(issuerp);
758     if(rc <= 0) {
759       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
760             data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
761       return CURLE_SSL_ISSUER_ERROR;
762     }
763     infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
764           data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
765   }
766
767   size=sizeof(certbuf);
768   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
769                                      0, /* the first and only one */
770                                      FALSE,
771                                      certbuf,
772                                      &size);
773   if(rc) {
774     infof(data, "error fetching CN from cert:%s\n",
775           gnutls_strerror(rc));
776   }
777
778   /* This function will check if the given certificate's subject matches the
779      given hostname. This is a basic implementation of the matching described
780      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
781      alternative name PKIX extension. Returns non zero on success, and zero on
782      failure. */
783   rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
784 #if GNUTLS_VERSION_NUMBER < 0x030306
785   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
786      addresses. */
787   if(!rc) {
788 #ifdef ENABLE_IPV6
789     #define use_addr in6_addr
790 #else
791     #define use_addr in_addr
792 #endif
793     unsigned char addrbuf[sizeof(struct use_addr)];
794     unsigned char certaddr[sizeof(struct use_addr)];
795     size_t addrlen = 0, certaddrlen;
796     int i;
797     int ret = 0;
798
799     if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
800       addrlen = 4;
801 #ifdef ENABLE_IPV6
802     else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
803       addrlen = 16;
804 #endif
805
806     if(addrlen) {
807       for(i=0; ; i++) {
808         certaddrlen = sizeof(certaddr);
809         ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
810                                                    &certaddrlen, NULL);
811         /* If this happens, it wasn't an IP address. */
812         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
813           continue;
814         if(ret < 0)
815           break;
816         if(ret != GNUTLS_SAN_IPADDRESS)
817           continue;
818         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
819           rc = 1;
820           break;
821         }
822       }
823     }
824   }
825 #endif
826   if(!rc) {
827     if(data->set.ssl.verifyhost) {
828       failf(data, "SSL: certificate subject name (%s) does not match "
829             "target host name '%s'", certbuf, conn->host.dispname);
830       gnutls_x509_crt_deinit(x509_cert);
831       return CURLE_PEER_FAILED_VERIFICATION;
832     }
833     else
834       infof(data, "\t common name: %s (does not match '%s')\n",
835             certbuf, conn->host.dispname);
836   }
837   else
838     infof(data, "\t common name: %s (matched)\n", certbuf);
839
840   /* Check for time-based validity */
841   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
842
843   if(certclock == (time_t)-1) {
844     if(data->set.ssl.verifypeer) {
845       failf(data, "server cert expiration date verify failed");
846       return CURLE_SSL_CONNECT_ERROR;
847     }
848     else
849       infof(data, "\t server certificate expiration date verify FAILED\n");
850   }
851   else {
852     if(certclock < time(NULL)) {
853       if(data->set.ssl.verifypeer) {
854         failf(data, "server certificate expiration date has passed.");
855         return CURLE_PEER_FAILED_VERIFICATION;
856       }
857       else
858         infof(data, "\t server certificate expiration date FAILED\n");
859     }
860     else
861       infof(data, "\t server certificate expiration date OK\n");
862   }
863
864   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
865
866   if(certclock == (time_t)-1) {
867     if(data->set.ssl.verifypeer) {
868       failf(data, "server cert activation date verify failed");
869       return CURLE_SSL_CONNECT_ERROR;
870     }
871     else
872       infof(data, "\t server certificate activation date verify FAILED\n");
873   }
874   else {
875     if(certclock > time(NULL)) {
876       if(data->set.ssl.verifypeer) {
877         failf(data, "server certificate not activated yet.");
878         return CURLE_PEER_FAILED_VERIFICATION;
879       }
880       else
881         infof(data, "\t server certificate activation date FAILED\n");
882     }
883     else
884       infof(data, "\t server certificate activation date OK\n");
885   }
886
887   /* Show:
888
889   - ciphers used
890   - subject
891   - start date
892   - expire date
893   - common name
894   - issuer
895
896   */
897
898   /* public key algorithm's parameters */
899   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
900   infof(data, "\t certificate public key: %s\n",
901         gnutls_pk_algorithm_get_name(algo));
902
903   /* version of the X.509 certificate. */
904   infof(data, "\t certificate version: #%d\n",
905         gnutls_x509_crt_get_version(x509_cert));
906
907
908   size = sizeof(certbuf);
909   gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
910   infof(data, "\t subject: %s\n", certbuf);
911
912   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
913   showtime(data, "start date", certclock);
914
915   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
916   showtime(data, "expire date", certclock);
917
918   size = sizeof(certbuf);
919   gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
920   infof(data, "\t issuer: %s\n", certbuf);
921
922   gnutls_x509_crt_deinit(x509_cert);
923
924   /* compression algorithm (if any) */
925   ptr = gnutls_compression_get_name(gnutls_compression_get(session));
926   /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
927   infof(data, "\t compression: %s\n", ptr);
928
929   /* the name of the cipher used. ie 3DES. */
930   ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
931   infof(data, "\t cipher: %s\n", ptr);
932
933   /* the MAC algorithms name. ie SHA1 */
934   ptr = gnutls_mac_get_name(gnutls_mac_get(session));
935   infof(data, "\t MAC: %s\n", ptr);
936
937 #ifdef HAS_ALPN
938   if(data->set.ssl_enable_alpn) {
939     rc = gnutls_alpn_get_selected_protocol(session, &proto);
940     if(rc == 0) {
941       infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
942           proto.data);
943
944       if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
945         memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
946         NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
947         conn->negnpn = NPN_HTTP2;
948       }
949       else if(proto.size == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
950           proto.data, ALPN_HTTP_1_1_LENGTH) == 0) {
951         conn->negnpn = NPN_HTTP1_1;
952       }
953     }
954     else {
955       infof(data, "ALPN, server did not agree to a protocol\n");
956     }
957   }
958 #endif
959
960   conn->ssl[sockindex].state = ssl_connection_complete;
961   conn->recv[sockindex] = gtls_recv;
962   conn->send[sockindex] = gtls_send;
963
964   {
965     /* we always unconditionally get the session id here, as even if we
966        already got it from the cache and asked to use it in the connection, it
967        might've been rejected and then a new one is in use now and we need to
968        detect that. */
969     void *connect_sessionid;
970     size_t connect_idsize = 0;
971
972     /* get the session ID data size */
973     gnutls_session_get_data(session, NULL, &connect_idsize);
974     connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
975
976     if(connect_sessionid) {
977       /* extract session ID to the allocated buffer */
978       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
979
980       incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
981       if(incache) {
982         /* there was one before in the cache, so instead of risking that the
983            previous one was rejected, we just kill that and store the new */
984         Curl_ssl_delsessionid(conn, ssl_sessionid);
985       }
986
987       /* store this session id */
988       result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
989       if(result) {
990         free(connect_sessionid);
991         result = CURLE_OUT_OF_MEMORY;
992       }
993     }
994     else
995       result = CURLE_OUT_OF_MEMORY;
996   }
997
998   return result;
999 }
1000
1001
1002 /*
1003  * This function is called after the TCP connect has completed. Setup the TLS
1004  * layer and do all necessary magic.
1005  */
1006 /* We use connssl->connecting_state to keep track of the connection status;
1007    there are three states: 'ssl_connect_1' (not started yet or complete),
1008    'ssl_connect_2_reading' (waiting for data from server), and
1009    'ssl_connect_2_writing' (waiting to be able to write).
1010  */
1011 static CURLcode
1012 gtls_connect_common(struct connectdata *conn,
1013                     int sockindex,
1014                     bool nonblocking,
1015                     bool *done)
1016 {
1017   int rc;
1018   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1019
1020   /* Initiate the connection, if not already done */
1021   if(ssl_connect_1==connssl->connecting_state) {
1022     rc = gtls_connect_step1 (conn, sockindex);
1023     if(rc)
1024       return rc;
1025   }
1026
1027   rc = handshake(conn, sockindex, TRUE, nonblocking);
1028   if(rc)
1029     /* handshake() sets its own error message with failf() */
1030     return rc;
1031
1032   /* Finish connecting once the handshake is done */
1033   if(ssl_connect_1==connssl->connecting_state) {
1034     rc = gtls_connect_step3(conn, sockindex);
1035     if(rc)
1036       return rc;
1037   }
1038
1039   *done = ssl_connect_1==connssl->connecting_state;
1040
1041   return CURLE_OK;
1042 }
1043
1044 CURLcode
1045 Curl_gtls_connect_nonblocking(struct connectdata *conn,
1046                               int sockindex,
1047                               bool *done)
1048 {
1049   return gtls_connect_common(conn, sockindex, TRUE, done);
1050 }
1051
1052 CURLcode
1053 Curl_gtls_connect(struct connectdata *conn,
1054                   int sockindex)
1055
1056 {
1057   CURLcode retcode;
1058   bool done = FALSE;
1059
1060   retcode = gtls_connect_common(conn, sockindex, FALSE, &done);
1061   if(retcode)
1062     return retcode;
1063
1064   DEBUGASSERT(done);
1065
1066   return CURLE_OK;
1067 }
1068
1069 static ssize_t gtls_send(struct connectdata *conn,
1070                          int sockindex,
1071                          const void *mem,
1072                          size_t len,
1073                          CURLcode *curlcode)
1074 {
1075   ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
1076
1077   if(rc < 0 ) {
1078     *curlcode = (rc == GNUTLS_E_AGAIN)
1079       ? CURLE_AGAIN
1080       : CURLE_SEND_ERROR;
1081
1082     rc = -1;
1083   }
1084
1085   return rc;
1086 }
1087
1088 void Curl_gtls_close_all(struct SessionHandle *data)
1089 {
1090   /* FIX: make the OpenSSL code more generic and use parts of it here */
1091   (void)data;
1092 }
1093
1094 static void close_one(struct connectdata *conn,
1095                       int idx)
1096 {
1097   if(conn->ssl[idx].session) {
1098     gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
1099     gnutls_deinit(conn->ssl[idx].session);
1100     conn->ssl[idx].session = NULL;
1101   }
1102   if(conn->ssl[idx].cred) {
1103     gnutls_certificate_free_credentials(conn->ssl[idx].cred);
1104     conn->ssl[idx].cred = NULL;
1105   }
1106 #ifdef USE_TLS_SRP
1107   if(conn->ssl[idx].srp_client_cred) {
1108     gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
1109     conn->ssl[idx].srp_client_cred = NULL;
1110   }
1111 #endif
1112 }
1113
1114 void Curl_gtls_close(struct connectdata *conn, int sockindex)
1115 {
1116   close_one(conn, sockindex);
1117 }
1118
1119 /*
1120  * This function is called to shut down the SSL layer but keep the
1121  * socket open (CCC - Clear Command Channel)
1122  */
1123 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
1124 {
1125   ssize_t result;
1126   int retval = 0;
1127   struct SessionHandle *data = conn->data;
1128   int done = 0;
1129   char buf[120];
1130
1131   /* This has only been tested on the proftpd server, and the mod_tls code
1132      sends a close notify alert without waiting for a close notify alert in
1133      response. Thus we wait for a close notify alert from the server, but
1134      we do not send one. Let's hope other servers do the same... */
1135
1136   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1137       gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
1138
1139   if(conn->ssl[sockindex].session) {
1140     while(!done) {
1141       int what = Curl_socket_ready(conn->sock[sockindex],
1142                                    CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
1143       if(what > 0) {
1144         /* Something to read, let's do it and hope that it is the close
1145            notify alert from the server */
1146         result = gnutls_record_recv(conn->ssl[sockindex].session,
1147                                     buf, sizeof(buf));
1148         switch(result) {
1149         case 0:
1150           /* This is the expected response. There was no data but only
1151              the close notify alert */
1152           done = 1;
1153           break;
1154         case GNUTLS_E_AGAIN:
1155         case GNUTLS_E_INTERRUPTED:
1156           infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1157           break;
1158         default:
1159           retval = -1;
1160           done = 1;
1161           break;
1162         }
1163       }
1164       else if(0 == what) {
1165         /* timeout */
1166         failf(data, "SSL shutdown timeout");
1167         done = 1;
1168         break;
1169       }
1170       else {
1171         /* anything that gets here is fatally bad */
1172         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1173         retval = -1;
1174         done = 1;
1175       }
1176     }
1177     gnutls_deinit(conn->ssl[sockindex].session);
1178   }
1179   gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
1180
1181 #ifdef USE_TLS_SRP
1182   if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
1183      && data->set.ssl.username != NULL)
1184     gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
1185 #endif
1186
1187   conn->ssl[sockindex].cred = NULL;
1188   conn->ssl[sockindex].session = NULL;
1189
1190   return retval;
1191 }
1192
1193 static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
1194                          int num,                  /* socketindex */
1195                          char *buf,                /* store read data here */
1196                          size_t buffersize,        /* max amount to read */
1197                          CURLcode *curlcode)
1198 {
1199   ssize_t ret;
1200
1201   ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
1202   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1203     *curlcode = CURLE_AGAIN;
1204     return -1;
1205   }
1206
1207   if(ret == GNUTLS_E_REHANDSHAKE) {
1208     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1209        proper way" takes a whole lot of work. */
1210     CURLcode rc = handshake(conn, num, FALSE, FALSE);
1211     if(rc)
1212       /* handshake() writes error message on its own */
1213       *curlcode = rc;
1214     else
1215       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1216     return -1;
1217   }
1218
1219   if(ret < 0) {
1220     failf(conn->data, "GnuTLS recv error (%d): %s",
1221           (int)ret, gnutls_strerror((int)ret));
1222     *curlcode = CURLE_RECV_ERROR;
1223     return -1;
1224   }
1225
1226   return ret;
1227 }
1228
1229 void Curl_gtls_session_free(void *ptr)
1230 {
1231   free(ptr);
1232 }
1233
1234 size_t Curl_gtls_version(char *buffer, size_t size)
1235 {
1236   return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1237 }
1238
1239 int Curl_gtls_seed(struct SessionHandle *data)
1240 {
1241   /* we have the "SSL is seeded" boolean static to prevent multiple
1242      time-consuming seedings in vain */
1243   static bool ssl_seeded = FALSE;
1244
1245   /* Quickly add a bit of entropy */
1246 #ifndef USE_GNUTLS_NETTLE
1247   gcry_fast_random_poll();
1248 #endif
1249
1250   if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1251      data->set.str[STRING_SSL_EGDSOCKET]) {
1252
1253     /* TODO: to a good job seeding the RNG
1254        This may involve the gcry_control function and these options:
1255        GCRYCTL_SET_RANDOM_SEED_FILE
1256        GCRYCTL_SET_RNDEGD_SOCKET
1257     */
1258     ssl_seeded = TRUE;
1259   }
1260   return 0;
1261 }
1262
1263 void Curl_gtls_random(struct SessionHandle *data,
1264                       unsigned char *entropy,
1265                       size_t length)
1266 {
1267 #if defined(USE_GNUTLS_NETTLE)
1268   (void)data;
1269   gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1270 #elif defined(USE_GNUTLS)
1271   Curl_gtls_seed(data); /* Initiate the seed if not already done */
1272   gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1273 #endif
1274 }
1275
1276 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
1277                       size_t tmplen,
1278                       unsigned char *md5sum, /* output */
1279                       size_t md5len)
1280 {
1281 #if defined(USE_GNUTLS_NETTLE)
1282   struct md5_ctx MD5pw;
1283   md5_init(&MD5pw);
1284   md5_update(&MD5pw, (unsigned int)tmplen, tmp);
1285   md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
1286 #elif defined(USE_GNUTLS)
1287   gcry_md_hd_t MD5pw;
1288   gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1289   gcry_md_write(MD5pw, tmp, tmplen);
1290   memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
1291   gcry_md_close(MD5pw);
1292 #endif
1293 }
1294
1295 #endif /* USE_GNUTLS */