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