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