xref: /curl/lib/vtls/gtls.c (revision 9cc24640)
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 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.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  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 
25 /*
26  * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
27  * but vtls.c should ever call or use these functions.
28  *
29  * Note: do not use the GnuTLS' *_t variable type names in this source code,
30  * since they were not present in 1.0.X.
31  */
32 
33 #include "curl_setup.h"
34 
35 #ifdef USE_GNUTLS
36 
37 #include <gnutls/abstract.h>
38 #include <gnutls/gnutls.h>
39 #include <gnutls/x509.h>
40 #include <gnutls/crypto.h>
41 #include <nettle/sha2.h>
42 
43 #include "urldata.h"
44 #include "sendf.h"
45 #include "inet_pton.h"
46 #include "keylog.h"
47 #include "gtls.h"
48 #include "vtls.h"
49 #include "vtls_int.h"
50 #include "vauth/vauth.h"
51 #include "parsedate.h"
52 #include "connect.h" /* for the connect timeout */
53 #include "progress.h"
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 #ifndef ARRAYSIZE
65 #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
66 #endif
67 
68 #define QUIC_PRIORITY \
69   "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
70   "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
71   "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
72   "%DISABLE_TLS13_COMPAT_MODE"
73 
74 /* Enable GnuTLS debugging by defining GTLSDEBUG */
75 /*#define GTLSDEBUG */
76 
77 #ifdef GTLSDEBUG
tls_log_func(int level,const char * str)78 static void tls_log_func(int level, const char *str)
79 {
80     fprintf(stderr, "|<%d>| %s", level, str);
81 }
82 #endif
83 static bool gtls_inited = FALSE;
84 
85 #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
86 #error "too old GnuTLS version"
87 #endif
88 
89 # include <gnutls/ocsp.h>
90 
91 struct gtls_ssl_backend_data {
92   struct gtls_ctx gtls;
93 };
94 
gtls_push(void * s,const void * buf,size_t blen)95 static ssize_t gtls_push(void *s, const void *buf, size_t blen)
96 {
97   struct Curl_cfilter *cf = s;
98   struct ssl_connect_data *connssl = cf->ctx;
99   struct gtls_ssl_backend_data *backend =
100     (struct gtls_ssl_backend_data *)connssl->backend;
101   struct Curl_easy *data = CF_DATA_CURRENT(cf);
102   ssize_t nwritten;
103   CURLcode result;
104 
105   DEBUGASSERT(data);
106   nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &result);
107   CURL_TRC_CF(data, cf, "gtls_push(len=%zu) -> %zd, err=%d",
108               blen, nwritten, result);
109   backend->gtls.io_result = result;
110   if(nwritten < 0) {
111     gnutls_transport_set_errno(backend->gtls.session,
112                                (CURLE_AGAIN == result) ? EAGAIN : EINVAL);
113     nwritten = -1;
114   }
115   return nwritten;
116 }
117 
gtls_pull(void * s,void * buf,size_t blen)118 static ssize_t gtls_pull(void *s, void *buf, size_t blen)
119 {
120   struct Curl_cfilter *cf = s;
121   struct ssl_connect_data *connssl = cf->ctx;
122   struct gtls_ssl_backend_data *backend =
123     (struct gtls_ssl_backend_data *)connssl->backend;
124   struct Curl_easy *data = CF_DATA_CURRENT(cf);
125   ssize_t nread;
126   CURLcode result;
127 
128   DEBUGASSERT(data);
129   if(!backend->gtls.shared_creds->trust_setup) {
130     result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
131     if(result) {
132       gnutls_transport_set_errno(backend->gtls.session, EINVAL);
133       backend->gtls.io_result = result;
134       return -1;
135     }
136   }
137 
138   nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
139   CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %zd, err=%d",
140               blen, nread, result);
141   backend->gtls.io_result = result;
142   if(nread < 0) {
143     gnutls_transport_set_errno(backend->gtls.session,
144                                (CURLE_AGAIN == result) ? EAGAIN : EINVAL);
145     nread = -1;
146   }
147   else if(nread == 0)
148     connssl->peer_closed = TRUE;
149   return nread;
150 }
151 
152 /* gtls_init()
153  *
154  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
155  * are not thread-safe and thus this function itself is not thread-safe and
156  * must only be called from within curl_global_init() to keep the thread
157  * situation under control!
158  */
gtls_init(void)159 static int gtls_init(void)
160 {
161   int ret = 1;
162   if(!gtls_inited) {
163     ret = gnutls_global_init() ? 0 : 1;
164 #ifdef GTLSDEBUG
165     gnutls_global_set_log_function(tls_log_func);
166     gnutls_global_set_log_level(2);
167 #endif
168     gtls_inited = TRUE;
169   }
170   return ret;
171 }
172 
gtls_cleanup(void)173 static void gtls_cleanup(void)
174 {
175   if(gtls_inited) {
176     gnutls_global_deinit();
177     gtls_inited = FALSE;
178   }
179 }
180 
181 #ifndef CURL_DISABLE_VERBOSE_STRINGS
showtime(struct Curl_easy * data,const char * text,time_t stamp)182 static void showtime(struct Curl_easy *data,
183                      const char *text,
184                      time_t stamp)
185 {
186   struct tm buffer;
187   const struct tm *tm = &buffer;
188   char str[96];
189   CURLcode result = Curl_gmtime(stamp, &buffer);
190   if(result)
191     return;
192 
193   msnprintf(str,
194             sizeof(str),
195             "  %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
196             text,
197             Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
198             tm->tm_mday,
199             Curl_month[tm->tm_mon],
200             tm->tm_year + 1900,
201             tm->tm_hour,
202             tm->tm_min,
203             tm->tm_sec);
204   infof(data, "%s", str);
205 }
206 #endif
207 
load_file(const char * file)208 static gnutls_datum_t load_file(const char *file)
209 {
210   FILE *f;
211   gnutls_datum_t loaded_file = { NULL, 0 };
212   long filelen;
213   void *ptr;
214 
215   f = fopen(file, "rb");
216   if(!f)
217     return loaded_file;
218   if(fseek(f, 0, SEEK_END) != 0
219      || (filelen = ftell(f)) < 0
220      || fseek(f, 0, SEEK_SET) != 0
221      || !(ptr = malloc((size_t)filelen)))
222     goto out;
223   if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
224     free(ptr);
225     goto out;
226   }
227 
228   loaded_file.data = ptr;
229   loaded_file.size = (unsigned int)filelen;
230 out:
231   fclose(f);
232   return loaded_file;
233 }
234 
unload_file(gnutls_datum_t data)235 static void unload_file(gnutls_datum_t data)
236 {
237   free(data.data);
238 }
239 
240 
241 /* this function does a SSL/TLS (re-)handshake */
handshake(struct Curl_cfilter * cf,struct Curl_easy * data,bool duringconnect,bool nonblocking)242 static CURLcode handshake(struct Curl_cfilter *cf,
243                           struct Curl_easy *data,
244                           bool duringconnect,
245                           bool nonblocking)
246 {
247   struct ssl_connect_data *connssl = cf->ctx;
248   struct gtls_ssl_backend_data *backend =
249     (struct gtls_ssl_backend_data *)connssl->backend;
250   gnutls_session_t session;
251   curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
252 
253   DEBUGASSERT(backend);
254   session = backend->gtls.session;
255   connssl->connecting_state = ssl_connect_2;
256 
257   for(;;) {
258     timediff_t timeout_ms;
259     int rc;
260 
261     /* check allowed time left */
262     timeout_ms = Curl_timeleft(data, NULL, duringconnect);
263 
264     if(timeout_ms < 0) {
265       /* no need to continue if time already is up */
266       failf(data, "SSL connection timeout");
267       return CURLE_OPERATION_TIMEDOUT;
268     }
269 
270     /* if ssl is expecting something, check if it is available. */
271     if(connssl->io_need) {
272       int what;
273       curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
274         sockfd : CURL_SOCKET_BAD;
275       curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
276         sockfd : CURL_SOCKET_BAD;
277 
278       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
279                                nonblocking ? 0 :
280                                timeout_ms ? timeout_ms : 1000);
281       if(what < 0) {
282         /* fatal error */
283         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
284         return CURLE_SSL_CONNECT_ERROR;
285       }
286       else if(0 == what) {
287         if(nonblocking)
288           return CURLE_AGAIN;
289         else if(timeout_ms) {
290           /* timeout */
291           failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
292           return CURLE_OPERATION_TIMEDOUT;
293         }
294       }
295       /* socket is readable or writable */
296     }
297 
298     connssl->io_need = CURL_SSL_IO_NEED_NONE;
299     backend->gtls.io_result = CURLE_OK;
300     rc = gnutls_handshake(session);
301 
302     if(!backend->gtls.shared_creds->trust_setup) {
303       /* After having send off the ClientHello, we prepare the trust
304        * store to verify the coming certificate from the server */
305       CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
306       if(result)
307         return result;
308     }
309 
310     if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
311       connssl->io_need =
312         gnutls_record_get_direction(session) ?
313         CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
314       continue;
315     }
316     else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
317       const char *strerr = NULL;
318 
319       if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
320         gnutls_alert_description_t alert = gnutls_alert_get(session);
321         strerr = gnutls_alert_get_name(alert);
322       }
323 
324       if(!strerr)
325         strerr = gnutls_strerror(rc);
326 
327       infof(data, "gnutls_handshake() warning: %s", strerr);
328       continue;
329     }
330     else if((rc < 0) && backend->gtls.io_result) {
331       return backend->gtls.io_result;
332     }
333     else if(rc < 0) {
334       const char *strerr = NULL;
335 
336       if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
337         gnutls_alert_description_t alert = gnutls_alert_get(session);
338         strerr = gnutls_alert_get_name(alert);
339       }
340 
341       if(!strerr)
342         strerr = gnutls_strerror(rc);
343 
344       failf(data, "GnuTLS, handshake failed: %s", strerr);
345       return CURLE_SSL_CONNECT_ERROR;
346     }
347 
348     /* Reset our connect state machine */
349     connssl->connecting_state = ssl_connect_1;
350     return CURLE_OK;
351   }
352 }
353 
gnutls_do_file_type(const char * type)354 static gnutls_x509_crt_fmt_t gnutls_do_file_type(const char *type)
355 {
356   if(!type || !type[0])
357     return GNUTLS_X509_FMT_PEM;
358   if(strcasecompare(type, "PEM"))
359     return GNUTLS_X509_FMT_PEM;
360   if(strcasecompare(type, "DER"))
361     return GNUTLS_X509_FMT_DER;
362   return GNUTLS_X509_FMT_PEM; /* default to PEM */
363 }
364 
365 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
366 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
367    requested in the priority string, so treat it specially
368  */
369 #define GNUTLS_SRP "+SRP"
370 
371 static CURLcode
gnutls_set_ssl_version_min_max(struct Curl_easy * data,struct ssl_peer * peer,struct ssl_primary_config * conn_config,const char ** prioritylist,const char * tls13support)372 gnutls_set_ssl_version_min_max(struct Curl_easy *data,
373                                struct ssl_peer *peer,
374                                struct ssl_primary_config *conn_config,
375                                const char **prioritylist,
376                                const char *tls13support)
377 {
378   long ssl_version = conn_config->version;
379   long ssl_version_max = conn_config->version_max;
380 
381   if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
382      (ssl_version == CURL_SSLVERSION_TLSv1))
383     ssl_version = CURL_SSLVERSION_TLSv1_0;
384   if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
385     ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
386 
387   if(peer->transport == TRNSPRT_QUIC) {
388     if((ssl_version_max != CURL_SSLVERSION_MAX_DEFAULT) &&
389        (ssl_version_max < CURL_SSLVERSION_MAX_TLSv1_3)) {
390       failf(data, "QUIC needs at least TLS version 1.3");
391       return CURLE_SSL_CONNECT_ERROR;
392      }
393     *prioritylist = QUIC_PRIORITY;
394     return CURLE_OK;
395   }
396 
397   if(!tls13support) {
398     /* If the running GnuTLS does not support TLS 1.3, we must not specify a
399        prioritylist involving that since it will make GnuTLS return an en
400        error back at us */
401     if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
402        (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
403       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
404     }
405   }
406   else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
407     ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
408   }
409 
410   switch(ssl_version | ssl_version_max) {
411   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
412     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
413       "+VERS-TLS1.0";
414     return CURLE_OK;
415   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
416     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
417       "+VERS-TLS1.1:+VERS-TLS1.0";
418     return CURLE_OK;
419   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
420     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
421       "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
422     return CURLE_OK;
423   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
424     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
425       "+VERS-TLS1.1";
426     return CURLE_OK;
427   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
428     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
429       "+VERS-TLS1.2:+VERS-TLS1.1";
430     return CURLE_OK;
431   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
432     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
433       "+VERS-TLS1.2";
434     return CURLE_OK;
435   case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
436     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
437       "+VERS-TLS1.3";
438     return CURLE_OK;
439   case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
440     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
441     return CURLE_OK;
442   case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
443     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
444       "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
445     return CURLE_OK;
446   case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
447     *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
448       "+VERS-TLS1.3:+VERS-TLS1.2";
449     return CURLE_OK;
450   }
451 
452   failf(data, "GnuTLS: cannot set ssl protocol");
453   return CURLE_SSL_CONNECT_ERROR;
454 }
455 
Curl_gtls_shared_creds_create(struct Curl_easy * data,struct gtls_shared_creds ** pcreds)456 CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data,
457                                        struct gtls_shared_creds **pcreds)
458 {
459   struct gtls_shared_creds *shared;
460   int rc;
461 
462   *pcreds = NULL;
463   shared = calloc(1, sizeof(*shared));
464   if(!shared)
465     return CURLE_OUT_OF_MEMORY;
466 
467   rc = gnutls_certificate_allocate_credentials(&shared->creds);
468   if(rc != GNUTLS_E_SUCCESS) {
469     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
470     free(shared);
471     return CURLE_SSL_CONNECT_ERROR;
472   }
473 
474   shared->refcount = 1;
475   shared->time = Curl_now();
476   *pcreds = shared;
477   return CURLE_OK;
478 }
479 
Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds * creds)480 CURLcode Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds *creds)
481 {
482   DEBUGASSERT(creds);
483   if(creds->refcount < SIZE_T_MAX) {
484     ++creds->refcount;
485     return CURLE_OK;
486   }
487   return CURLE_BAD_FUNCTION_ARGUMENT;
488 }
489 
Curl_gtls_shared_creds_free(struct gtls_shared_creds ** pcreds)490 void Curl_gtls_shared_creds_free(struct gtls_shared_creds **pcreds)
491 {
492   struct gtls_shared_creds *shared = *pcreds;
493   *pcreds = NULL;
494   if(shared) {
495     --shared->refcount;
496     if(!shared->refcount) {
497       gnutls_certificate_free_credentials(shared->creds);
498       free(shared->CAfile);
499       free(shared);
500     }
501   }
502 }
503 
gtls_populate_creds(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_certificate_credentials_t creds)504 static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
505                                     struct Curl_easy *data,
506                                     gnutls_certificate_credentials_t creds)
507 {
508   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
509   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
510   int rc;
511 
512   if(config->verifypeer) {
513     bool imported_native_ca = FALSE;
514 
515     if(ssl_config->native_ca_store) {
516       rc = gnutls_certificate_set_x509_system_trust(creds);
517       if(rc < 0)
518         infof(data, "error reading native ca store (%s), continuing anyway",
519               gnutls_strerror(rc));
520       else {
521         infof(data, "found %d certificates in native ca store", rc);
522         if(rc > 0)
523           imported_native_ca = TRUE;
524       }
525     }
526 
527     if(config->CAfile) {
528       /* set the trusted CA cert bundle file */
529       gnutls_certificate_set_verify_flags(creds,
530                                           GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
531 
532       rc = gnutls_certificate_set_x509_trust_file(creds,
533                                                   config->CAfile,
534                                                   GNUTLS_X509_FMT_PEM);
535       if(rc < 0) {
536         infof(data, "error reading ca cert file %s (%s)%s",
537               config->CAfile, gnutls_strerror(rc),
538               (imported_native_ca ? ", continuing anyway" : ""));
539         if(!imported_native_ca) {
540           ssl_config->certverifyresult = rc;
541           return CURLE_SSL_CACERT_BADFILE;
542         }
543       }
544       else
545         infof(data, "found %d certificates in %s", rc, config->CAfile);
546     }
547 
548     if(config->CApath) {
549       /* set the trusted CA cert directory */
550       rc = gnutls_certificate_set_x509_trust_dir(creds, config->CApath,
551                                                  GNUTLS_X509_FMT_PEM);
552       if(rc < 0) {
553         infof(data, "error reading ca cert file %s (%s)%s",
554               config->CApath, gnutls_strerror(rc),
555               (imported_native_ca ? ", continuing anyway" : ""));
556         if(!imported_native_ca) {
557           ssl_config->certverifyresult = rc;
558           return CURLE_SSL_CACERT_BADFILE;
559         }
560       }
561       else
562         infof(data, "found %d certificates in %s", rc, config->CApath);
563     }
564   }
565 
566   if(config->CRLfile) {
567     /* set the CRL list file */
568     rc = gnutls_certificate_set_x509_crl_file(creds, config->CRLfile,
569                                               GNUTLS_X509_FMT_PEM);
570     if(rc < 0) {
571       failf(data, "error reading crl file %s (%s)",
572             config->CRLfile, gnutls_strerror(rc));
573       return CURLE_SSL_CRL_BADFILE;
574     }
575     else
576       infof(data, "found %d CRL in %s", rc, config->CRLfile);
577   }
578 
579   return CURLE_OK;
580 }
581 
582 /* key to use at `multi->proto_hash` */
583 #define MPROTO_GTLS_X509_KEY   "tls:gtls:x509:share"
584 
gtls_shared_creds_expired(const struct Curl_easy * data,const struct gtls_shared_creds * sc)585 static bool gtls_shared_creds_expired(const struct Curl_easy *data,
586                                       const struct gtls_shared_creds *sc)
587 {
588   const struct ssl_general_config *cfg = &data->set.general_ssl;
589   struct curltime now = Curl_now();
590   timediff_t elapsed_ms = Curl_timediff(now, sc->time);
591   timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
592 
593   if(timeout_ms < 0)
594     return FALSE;
595 
596   return elapsed_ms >= timeout_ms;
597 }
598 
gtls_shared_creds_different(struct Curl_cfilter * cf,const struct gtls_shared_creds * sc)599 static bool gtls_shared_creds_different(struct Curl_cfilter *cf,
600                                         const struct gtls_shared_creds *sc)
601 {
602   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
603   if(!sc->CAfile || !conn_config->CAfile)
604     return sc->CAfile != conn_config->CAfile;
605 
606   return strcmp(sc->CAfile, conn_config->CAfile);
607 }
608 
609 static struct gtls_shared_creds*
gtls_get_cached_creds(struct Curl_cfilter * cf,struct Curl_easy * data)610 gtls_get_cached_creds(struct Curl_cfilter *cf, struct Curl_easy *data)
611 {
612   struct gtls_shared_creds *shared_creds;
613 
614   if(data->multi) {
615     shared_creds = Curl_hash_pick(&data->multi->proto_hash,
616                                   (void *)MPROTO_GTLS_X509_KEY,
617                                   sizeof(MPROTO_GTLS_X509_KEY)-1);
618      if(shared_creds && shared_creds->creds &&
619         !gtls_shared_creds_expired(data, shared_creds) &&
620         !gtls_shared_creds_different(cf, shared_creds)) {
621        return shared_creds;
622      }
623   }
624   return NULL;
625 }
626 
gtls_shared_creds_hash_free(void * key,size_t key_len,void * p)627 static void gtls_shared_creds_hash_free(void *key, size_t key_len, void *p)
628 {
629   struct gtls_shared_creds *sc = p;
630   DEBUGASSERT(key_len == (sizeof(MPROTO_GTLS_X509_KEY)-1));
631   DEBUGASSERT(!memcmp(MPROTO_GTLS_X509_KEY, key, key_len));
632   (void)key;
633   (void)key_len;
634   Curl_gtls_shared_creds_free(&sc); /* down reference */
635 }
636 
gtls_set_cached_creds(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_shared_creds * sc)637 static void gtls_set_cached_creds(struct Curl_cfilter *cf,
638                                   struct Curl_easy *data,
639                                   struct gtls_shared_creds *sc)
640 {
641   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
642 
643   DEBUGASSERT(sc);
644   DEBUGASSERT(sc->creds);
645   DEBUGASSERT(!sc->CAfile);
646   DEBUGASSERT(sc->refcount == 1);
647   if(!data->multi)
648     return;
649 
650   if(conn_config->CAfile) {
651     sc->CAfile = strdup(conn_config->CAfile);
652     if(!sc->CAfile)
653       return;
654   }
655 
656   if(Curl_gtls_shared_creds_up_ref(sc))
657     return;
658 
659   if(!Curl_hash_add2(&data->multi->proto_hash,
660                     (void *)MPROTO_GTLS_X509_KEY,
661                     sizeof(MPROTO_GTLS_X509_KEY)-1,
662                     sc, gtls_shared_creds_hash_free)) {
663     Curl_gtls_shared_creds_free(&sc); /* down reference again */
664     return;
665   }
666 }
667 
Curl_gtls_client_trust_setup(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_ctx * gtls)668 CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
669                                       struct Curl_easy *data,
670                                       struct gtls_ctx *gtls)
671 {
672   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
673   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
674   struct gtls_shared_creds *cached_creds = NULL;
675   bool cache_criteria_met;
676   CURLcode result;
677   int rc;
678 
679 
680   /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
681      or no source is provided and we are falling back to OpenSSL's built-in
682      default. */
683   cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
684     conn_config->verifypeer &&
685     !conn_config->CApath &&
686     !conn_config->ca_info_blob &&
687     !ssl_config->primary.CRLfile &&
688     !ssl_config->native_ca_store &&
689     !conn_config->clientcert; /* GnuTLS adds client cert to its credentials! */
690 
691   if(cache_criteria_met)
692     cached_creds = gtls_get_cached_creds(cf, data);
693 
694   if(cached_creds && !Curl_gtls_shared_creds_up_ref(cached_creds)) {
695     CURL_TRC_CF(data, cf, "using shared trust anchors and CRLs");
696     Curl_gtls_shared_creds_free(&gtls->shared_creds);
697     gtls->shared_creds = cached_creds;
698     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
699                                 gtls->shared_creds->creds);
700     if(rc != GNUTLS_E_SUCCESS) {
701       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
702       return CURLE_SSL_CONNECT_ERROR;
703     }
704   }
705   else {
706     CURL_TRC_CF(data, cf, "loading trust anchors and CRLs");
707     result = gtls_populate_creds(cf, data, gtls->shared_creds->creds);
708     if(result)
709       return result;
710     gtls->shared_creds->trust_setup = TRUE;
711     if(cache_criteria_met)
712       gtls_set_cached_creds(cf, data, gtls->shared_creds);
713   }
714   return CURLE_OK;
715 }
716 
gtls_sessionid_free(void * sessionid,size_t idsize)717 static void gtls_sessionid_free(void *sessionid, size_t idsize)
718 {
719   (void)idsize;
720   free(sessionid);
721 }
722 
Curl_gtls_update_session_id(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session,struct ssl_peer * peer,const char * alpn)723 CURLcode Curl_gtls_update_session_id(struct Curl_cfilter *cf,
724                                      struct Curl_easy *data,
725                                      gnutls_session_t session,
726                                      struct ssl_peer *peer,
727                                      const char *alpn)
728 {
729   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
730   void *connect_sessionid;
731   size_t connect_idsize = 0;
732   CURLcode result = CURLE_OK;
733 
734   if(!ssl_config->primary.cache_session)
735     return CURLE_OK;
736 
737   /* we always unconditionally get the session id here, as even if we
738      already got it from the cache and asked to use it in the connection, it
739      might've been rejected and then a new one is in use now and we need to
740      detect that. */
741 
742   /* get the session ID data size */
743   gnutls_session_get_data(session, NULL, &connect_idsize);
744   if(!connect_idsize) /* gnutls does this for some version combinations */
745     return CURLE_OK;
746 
747   connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
748   if(!connect_sessionid)
749     return CURLE_OUT_OF_MEMORY;
750 
751   /* extract session ID to the allocated buffer */
752   gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
753 
754   CURL_TRC_CF(data, cf, "get session id (len=%zu, alpn=%s) and store in cache",
755               connect_idsize, alpn ? alpn : "-");
756   Curl_ssl_sessionid_lock(data);
757   /* store this session id, takes ownership */
758   result = Curl_ssl_set_sessionid(cf, data, peer, alpn,
759                                   connect_sessionid, connect_idsize,
760                                   gtls_sessionid_free);
761   Curl_ssl_sessionid_unlock(data);
762   return result;
763 }
764 
cf_gtls_update_session_id(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)765 static CURLcode cf_gtls_update_session_id(struct Curl_cfilter *cf,
766                                           struct Curl_easy *data,
767                                           gnutls_session_t session)
768 {
769   struct ssl_connect_data *connssl = cf->ctx;
770   return Curl_gtls_update_session_id(cf, data, session, &connssl->peer,
771                                      connssl->alpn_negotiated);
772 }
773 
gtls_handshake_cb(gnutls_session_t session,unsigned int htype,unsigned when,unsigned int incoming,const gnutls_datum_t * msg)774 static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
775                              unsigned when, unsigned int incoming,
776                              const gnutls_datum_t *msg)
777 {
778   struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
779 
780   (void)msg;
781   (void)incoming;
782   if(when) { /* after message has been processed */
783     struct Curl_easy *data = CF_DATA_CURRENT(cf);
784     if(data) {
785       CURL_TRC_CF(data, cf, "handshake: %s message type %d",
786                   incoming ? "incoming" : "outgoing", htype);
787       switch(htype) {
788       case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
789         cf_gtls_update_session_id(cf, data, session);
790         break;
791       }
792       default:
793         break;
794       }
795     }
796   }
797   return 0;
798 }
799 
gtls_client_init(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,struct gtls_ctx * gtls)800 static CURLcode gtls_client_init(struct Curl_cfilter *cf,
801                                  struct Curl_easy *data,
802                                  struct ssl_peer *peer,
803                                  struct gtls_ctx *gtls)
804 {
805   struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
806   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
807   unsigned int init_flags;
808   int rc;
809   bool sni = TRUE; /* default is SNI enabled */
810   const char *prioritylist;
811   const char *err = NULL;
812   const char *tls13support;
813   CURLcode result;
814 
815   if(!gtls_inited)
816     gtls_init();
817 
818   if(config->version == CURL_SSLVERSION_SSLv2) {
819     failf(data, "GnuTLS does not support SSLv2");
820     return CURLE_SSL_CONNECT_ERROR;
821   }
822   else if(config->version == CURL_SSLVERSION_SSLv3)
823     sni = FALSE; /* SSLv3 has no SNI */
824 
825   /* allocate a shared creds struct */
826   result = Curl_gtls_shared_creds_create(data, &gtls->shared_creds);
827   if(result)
828     return result;
829 
830 #ifdef USE_GNUTLS_SRP
831   if(config->username && Curl_auth_allowed_to_host(data)) {
832     infof(data, "Using TLS-SRP username: %s", config->username);
833 
834     rc = gnutls_srp_allocate_client_credentials(&gtls->srp_client_cred);
835     if(rc != GNUTLS_E_SUCCESS) {
836       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
837             gnutls_strerror(rc));
838       return CURLE_OUT_OF_MEMORY;
839     }
840 
841     rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
842                                            config->username,
843                                            config->password);
844     if(rc != GNUTLS_E_SUCCESS) {
845       failf(data, "gnutls_srp_set_client_cred() failed: %s",
846             gnutls_strerror(rc));
847       return CURLE_BAD_FUNCTION_ARGUMENT;
848     }
849   }
850 #endif
851 
852   ssl_config->certverifyresult = 0;
853 
854   /* Initialize TLS session as a client */
855   init_flags = GNUTLS_CLIENT;
856 
857 #if defined(GNUTLS_FORCE_CLIENT_CERT)
858   init_flags |= GNUTLS_FORCE_CLIENT_CERT;
859 #endif
860 
861 #if defined(GNUTLS_NO_TICKETS_TLS12)
862     init_flags |= GNUTLS_NO_TICKETS_TLS12;
863 #elif defined(GNUTLS_NO_TICKETS)
864   /* Disable TLS session tickets for non 1.3 connections */
865   if((config->version != CURL_SSLVERSION_TLSv1_3) &&
866      (config->version != CURL_SSLVERSION_DEFAULT))
867     init_flags |= GNUTLS_NO_TICKETS;
868 #endif
869 
870 #if defined(GNUTLS_NO_STATUS_REQUEST)
871   if(!config->verifystatus)
872     /* Disable the "status_request" TLS extension, enabled by default since
873        GnuTLS 3.8.0. */
874     init_flags |= GNUTLS_NO_STATUS_REQUEST;
875 #endif
876 
877   rc = gnutls_init(&gtls->session, init_flags);
878   if(rc != GNUTLS_E_SUCCESS) {
879     failf(data, "gnutls_init() failed: %d", rc);
880     return CURLE_SSL_CONNECT_ERROR;
881   }
882 
883   if(sni && peer->sni) {
884     if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
885                               peer->sni, strlen(peer->sni)) < 0) {
886       failf(data, "Failed to set SNI");
887       return CURLE_SSL_CONNECT_ERROR;
888     }
889   }
890 
891   /* Use default priorities */
892   rc = gnutls_set_default_priority(gtls->session);
893   if(rc != GNUTLS_E_SUCCESS)
894     return CURLE_SSL_CONNECT_ERROR;
895 
896   /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
897   tls13support = gnutls_check_version("3.6.5");
898 
899   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
900    * removed if a runtime error indicates that SRP is not supported by this
901    * GnuTLS version */
902 
903   if(config->version == CURL_SSLVERSION_SSLv2 ||
904      config->version == CURL_SSLVERSION_SSLv3) {
905     failf(data, "GnuTLS does not support SSLv2 or SSLv3");
906     return CURLE_SSL_CONNECT_ERROR;
907   }
908 
909   if(config->version == CURL_SSLVERSION_TLSv1_3) {
910     if(!tls13support) {
911       failf(data, "This GnuTLS installation does not support TLS 1.3");
912       return CURLE_SSL_CONNECT_ERROR;
913     }
914   }
915 
916   /* At this point we know we have a supported TLS version, so set it */
917   result = gnutls_set_ssl_version_min_max(data, peer,
918                                           config, &prioritylist, tls13support);
919   if(result)
920     return result;
921 
922 #ifdef USE_GNUTLS_SRP
923   /* Only add SRP to the cipher list if SRP is requested. Otherwise
924    * GnuTLS will disable TLS 1.3 support. */
925   if(config->username) {
926     char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
927     if(!prioritysrp)
928       return CURLE_OUT_OF_MEMORY;
929     rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
930     free(prioritysrp);
931 
932     if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
933       infof(data, "This GnuTLS does not support SRP");
934     }
935   }
936   else {
937 #endif
938     infof(data, "GnuTLS ciphers: %s", prioritylist);
939     rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
940 #ifdef USE_GNUTLS_SRP
941   }
942 #endif
943 
944   if(rc != GNUTLS_E_SUCCESS) {
945     failf(data, "Error %d setting GnuTLS cipher list starting with %s",
946           rc, err);
947     return CURLE_SSL_CONNECT_ERROR;
948   }
949 
950   if(config->clientcert) {
951     if(!gtls->shared_creds->trust_setup) {
952       result = Curl_gtls_client_trust_setup(cf, data, gtls);
953       if(result)
954         return result;
955     }
956     if(ssl_config->cert_type && strcasecompare(ssl_config->cert_type, "P12")) {
957       rc = gnutls_certificate_set_x509_simple_pkcs12_file(
958         gtls->shared_creds->creds, config->clientcert, GNUTLS_X509_FMT_DER,
959         ssl_config->key_passwd ? ssl_config->key_passwd : "");
960       if(rc != GNUTLS_E_SUCCESS) {
961         failf(data,
962               "error reading X.509 potentially-encrypted key or certificate "
963               "file: %s",
964               gnutls_strerror(rc));
965         return CURLE_SSL_CONNECT_ERROR;
966       }
967     }
968     else if(ssl_config->key_passwd) {
969       const unsigned int supported_key_encryption_algorithms =
970         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
971         GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
972         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
973         GNUTLS_PKCS_USE_PBES2_AES_256;
974       rc = gnutls_certificate_set_x509_key_file2(
975            gtls->shared_creds->creds,
976            config->clientcert,
977            ssl_config->key ? ssl_config->key : config->clientcert,
978            gnutls_do_file_type(ssl_config->cert_type),
979            ssl_config->key_passwd,
980            supported_key_encryption_algorithms);
981       if(rc != GNUTLS_E_SUCCESS) {
982         failf(data,
983               "error reading X.509 potentially-encrypted key file: %s",
984               gnutls_strerror(rc));
985         return CURLE_SSL_CONNECT_ERROR;
986       }
987     }
988     else {
989       if(gnutls_certificate_set_x509_key_file(
990            gtls->shared_creds->creds,
991            config->clientcert,
992            ssl_config->key ? ssl_config->key : config->clientcert,
993            gnutls_do_file_type(ssl_config->cert_type) ) !=
994          GNUTLS_E_SUCCESS) {
995         failf(data, "error reading X.509 key or certificate file");
996         return CURLE_SSL_CONNECT_ERROR;
997       }
998     }
999   }
1000 
1001 #ifdef USE_GNUTLS_SRP
1002   /* put the credentials to the current session */
1003   if(config->username) {
1004     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
1005                                 gtls->srp_client_cred);
1006     if(rc != GNUTLS_E_SUCCESS) {
1007       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
1008       return CURLE_SSL_CONNECT_ERROR;
1009     }
1010   }
1011   else
1012 #endif
1013   {
1014     rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
1015                                 gtls->shared_creds->creds);
1016     if(rc != GNUTLS_E_SUCCESS) {
1017       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
1018       return CURLE_SSL_CONNECT_ERROR;
1019     }
1020   }
1021 
1022   if(config->verifystatus) {
1023     rc = gnutls_ocsp_status_request_enable_client(gtls->session,
1024                                                   NULL, 0, NULL);
1025     if(rc != GNUTLS_E_SUCCESS) {
1026       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
1027       return CURLE_SSL_CONNECT_ERROR;
1028     }
1029   }
1030 
1031   return CURLE_OK;
1032 }
1033 
keylog_callback(gnutls_session_t session,const char * label,const gnutls_datum_t * secret)1034 static int keylog_callback(gnutls_session_t session, const char *label,
1035                            const gnutls_datum_t *secret)
1036 {
1037   gnutls_datum_t crandom;
1038   gnutls_datum_t srandom;
1039 
1040   gnutls_session_get_random(session, &crandom, &srandom);
1041   if(crandom.size != 32) {
1042     return -1;
1043   }
1044 
1045   Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
1046   return 0;
1047 }
1048 
Curl_gtls_ctx_init(struct gtls_ctx * gctx,struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,const unsigned char * alpn,size_t alpn_len,struct ssl_connect_data * connssl,Curl_gtls_ctx_setup_cb * cb_setup,void * cb_user_data,void * ssl_user_data)1049 CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
1050                             struct Curl_cfilter *cf,
1051                             struct Curl_easy *data,
1052                             struct ssl_peer *peer,
1053                             const unsigned char *alpn, size_t alpn_len,
1054                             struct ssl_connect_data *connssl,
1055                             Curl_gtls_ctx_setup_cb *cb_setup,
1056                             void *cb_user_data,
1057                             void *ssl_user_data)
1058 {
1059   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1060   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1061   gnutls_datum_t gtls_alpns[5];
1062   size_t gtls_alpns_count = 0;
1063   CURLcode result;
1064 
1065   DEBUGASSERT(gctx);
1066 
1067   result = gtls_client_init(cf, data, peer, gctx);
1068   if(result)
1069     return result;
1070 
1071   gnutls_session_set_ptr(gctx->session, ssl_user_data);
1072 
1073   if(cb_setup) {
1074     result = cb_setup(cf, data, cb_user_data);
1075     if(result)
1076       return result;
1077   }
1078 
1079   /* Open the file if a TLS or QUIC backend has not done this before. */
1080   Curl_tls_keylog_open();
1081   if(Curl_tls_keylog_enabled()) {
1082     gnutls_session_set_keylog_function(gctx->session, keylog_callback);
1083   }
1084 
1085   /* This might be a reconnect, so we check for a session ID in the cache
1086      to speed up things */
1087   if(conn_config->cache_session) {
1088     void *ssl_sessionid;
1089     size_t ssl_idsize;
1090     char *session_alpn;
1091     Curl_ssl_sessionid_lock(data);
1092     if(!Curl_ssl_getsessionid(cf, data, peer,
1093                               &ssl_sessionid, &ssl_idsize, &session_alpn)) {
1094       /* we got a session id, use it! */
1095       int rc;
1096 
1097       rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
1098       if(rc < 0)
1099         infof(data, "SSL failed to set session ID");
1100       else {
1101         infof(data, "SSL reusing session ID (size=%zu, alpn=%s)",
1102               ssl_idsize, session_alpn ? session_alpn : "-");
1103 #ifdef DEBUGBUILD
1104         if((ssl_config->earlydata || !!getenv("CURL_USE_EARLYDATA")) &&
1105 #else
1106         if(ssl_config->earlydata &&
1107 #endif
1108            !cf->conn->connect_only && connssl &&
1109            (gnutls_protocol_get_version(gctx->session) == GNUTLS_TLS1_3) &&
1110            Curl_alpn_contains_proto(connssl->alpn, session_alpn)) {
1111           connssl->earlydata_max =
1112             gnutls_record_get_max_early_data_size(gctx->session);
1113           if((!connssl->earlydata_max ||
1114               connssl->earlydata_max == 0xFFFFFFFFUL)) {
1115             /* Seems to be GnuTLS way to signal no EarlyData in session */
1116             CURL_TRC_CF(data, cf, "TLS session does not allow earlydata");
1117           }
1118           else {
1119             CURL_TRC_CF(data, cf, "TLS session allows %zu earlydata bytes, "
1120                         "reusing ALPN '%s'",
1121                         connssl->earlydata_max, session_alpn);
1122             connssl->earlydata_state = ssl_earlydata_use;
1123             connssl->state = ssl_connection_deferred;
1124             result = Curl_alpn_set_negotiated(cf, data, connssl,
1125                             (const unsigned char *)session_alpn,
1126                             session_alpn ? strlen(session_alpn) : 0);
1127             if(result)
1128               return result;
1129             /* We only try the ALPN protocol the session used before,
1130              * otherwise we might send early data for the wrong protocol */
1131             gtls_alpns[0].data = (unsigned char *)session_alpn;
1132             gtls_alpns[0].size = (unsigned)strlen(session_alpn);
1133             gtls_alpns_count = 1;
1134           }
1135         }
1136       }
1137     }
1138     Curl_ssl_sessionid_unlock(data);
1139   }
1140 
1141   /* convert the ALPN string from our arguments to a list of strings that
1142    * gnutls wants and will convert internally back to this string for sending
1143    * to the server. nice. */
1144   if(!gtls_alpns_count && alpn && alpn_len) {
1145     size_t i, alen = alpn_len;
1146     unsigned char *s = (unsigned char *)alpn;
1147     unsigned char slen;
1148     for(i = 0; (i < ARRAYSIZE(gtls_alpns)) && alen; ++i) {
1149       slen = s[0];
1150       if(slen >= alen)
1151         return CURLE_FAILED_INIT;
1152       gtls_alpns[i].data = s + 1;
1153       gtls_alpns[i].size = slen;
1154       s += slen + 1;
1155       alen -= (size_t)slen + 1;
1156     }
1157     if(alen) /* not all alpn chars used, wrong format or too many */
1158         return CURLE_FAILED_INIT;
1159     gtls_alpns_count = i;
1160   }
1161 
1162   if(gtls_alpns_count &&
1163      gnutls_alpn_set_protocols(gctx->session,
1164                                gtls_alpns, (unsigned int)gtls_alpns_count,
1165                                GNUTLS_ALPN_MANDATORY)) {
1166     failf(data, "failed setting ALPN");
1167     return CURLE_SSL_CONNECT_ERROR;
1168   }
1169 
1170   return CURLE_OK;
1171 }
1172 
1173 static CURLcode
gtls_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)1174 gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
1175 {
1176   struct ssl_connect_data *connssl = cf->ctx;
1177   struct gtls_ssl_backend_data *backend =
1178     (struct gtls_ssl_backend_data *)connssl->backend;
1179   struct alpn_proto_buf proto;
1180   CURLcode result;
1181 
1182   DEBUGASSERT(backend);
1183   DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
1184 
1185   if(connssl->state == ssl_connection_complete)
1186     /* to make us tolerant against being called more than once for the
1187        same connection */
1188     return CURLE_OK;
1189 
1190   memset(&proto, 0, sizeof(proto));
1191   if(connssl->alpn) {
1192     result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
1193     if(result) {
1194       failf(data, "Error determining ALPN");
1195       return CURLE_SSL_CONNECT_ERROR;
1196     }
1197   }
1198 
1199   result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
1200                               proto.data, proto.len, connssl, NULL, NULL, cf);
1201   if(result)
1202     return result;
1203 
1204   if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
1205     Curl_alpn_to_proto_str(&proto, connssl->alpn);
1206     infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
1207   }
1208 
1209   gnutls_handshake_set_hook_function(backend->gtls.session,
1210                                      GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
1211                                      gtls_handshake_cb);
1212 
1213   /* register callback functions and handle to send and receive data. */
1214   gnutls_transport_set_ptr(backend->gtls.session, cf);
1215   gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
1216   gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
1217 
1218   return CURLE_OK;
1219 }
1220 
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)1221 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
1222                                     gnutls_x509_crt_t cert,
1223                                     const char *pinnedpubkey)
1224 {
1225   /* Scratch */
1226   size_t len1 = 0, len2 = 0;
1227   unsigned char *buff1 = NULL;
1228 
1229   gnutls_pubkey_t key = NULL;
1230 
1231   /* Result is returned to caller */
1232   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1233 
1234   /* if a path was not specified, do not pin */
1235   if(!pinnedpubkey)
1236     return CURLE_OK;
1237 
1238   if(!cert)
1239     return result;
1240 
1241   do {
1242     int ret;
1243 
1244     /* Begin Gyrations to get the public key     */
1245     gnutls_pubkey_init(&key);
1246 
1247     ret = gnutls_pubkey_import_x509(key, cert, 0);
1248     if(ret < 0)
1249       break; /* failed */
1250 
1251     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
1252     if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
1253       break; /* failed */
1254 
1255     buff1 = malloc(len1);
1256     if(!buff1)
1257       break; /* failed */
1258 
1259     len2 = len1;
1260 
1261     ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
1262     if(ret < 0 || len1 != len2)
1263       break; /* failed */
1264 
1265     /* End Gyrations */
1266 
1267     /* The one good exit point */
1268     result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
1269   } while(0);
1270 
1271   if(key)
1272     gnutls_pubkey_deinit(key);
1273 
1274   Curl_safefree(buff1);
1275 
1276   return result;
1277 }
1278 
1279 CURLcode
Curl_gtls_verifyserver(struct Curl_easy * data,gnutls_session_t session,struct ssl_primary_config * config,struct ssl_config_data * ssl_config,struct ssl_peer * peer,const char * pinned_key)1280 Curl_gtls_verifyserver(struct Curl_easy *data,
1281                        gnutls_session_t session,
1282                        struct ssl_primary_config *config,
1283                        struct ssl_config_data *ssl_config,
1284                        struct ssl_peer *peer,
1285                        const char *pinned_key)
1286 {
1287   unsigned int cert_list_size;
1288   const gnutls_datum_t *chainp;
1289   unsigned int verify_status = 0;
1290   gnutls_x509_crt_t x509_cert, x509_issuer;
1291   gnutls_datum_t issuerp;
1292   gnutls_datum_t certfields;
1293   char certname[65] = ""; /* limited to 64 chars by ASN.1 */
1294   size_t size;
1295   time_t certclock;
1296   int rc;
1297   CURLcode result = CURLE_OK;
1298 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1299   const char *ptr;
1300   int algo;
1301   unsigned int bits;
1302   gnutls_protocol_t version = gnutls_protocol_get_version(session);
1303 #endif
1304   long * const certverifyresult = &ssl_config->certverifyresult;
1305 
1306 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1307   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
1308   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
1309                                      gnutls_cipher_get(session),
1310                                      gnutls_mac_get(session));
1311 
1312   infof(data, "SSL connection using %s / %s",
1313         gnutls_protocol_get_name(version), ptr);
1314 #endif
1315 
1316   /* This function will return the peer's raw certificate (chain) as sent by
1317      the peer. These certificates are in raw format (DER encoded for
1318      X.509). In case of a X.509 then a certificate list may be present. The
1319      first certificate in the list is the peer's certificate, following the
1320      issuer's certificate, then the issuer's issuer etc. */
1321 
1322   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1323   if(!chainp) {
1324     if(config->verifypeer ||
1325        config->verifyhost ||
1326        config->issuercert) {
1327 #ifdef USE_GNUTLS_SRP
1328       if(ssl_config->primary.username && !config->verifypeer &&
1329          gnutls_cipher_get(session)) {
1330         /* no peer cert, but auth is ok if we have SRP user and cipher and no
1331            peer verify */
1332       }
1333       else {
1334 #endif
1335         failf(data, "failed to get server cert");
1336         *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
1337         return CURLE_PEER_FAILED_VERIFICATION;
1338 #ifdef USE_GNUTLS_SRP
1339       }
1340 #endif
1341     }
1342     infof(data, " common name: WARNING could not obtain");
1343   }
1344 
1345   if(data->set.ssl.certinfo && chainp) {
1346     unsigned int i;
1347 
1348     result = Curl_ssl_init_certinfo(data, (int)cert_list_size);
1349     if(result)
1350       return result;
1351 
1352     for(i = 0; i < cert_list_size; i++) {
1353       const char *beg = (const char *) chainp[i].data;
1354       const char *end = beg + chainp[i].size;
1355 
1356       result = Curl_extract_certinfo(data, (int)i, beg, end);
1357       if(result)
1358         return result;
1359     }
1360   }
1361 
1362   if(config->verifypeer) {
1363     /* This function will try to verify the peer's certificate and return its
1364        status (trusted, invalid etc.). The value of status should be one or
1365        more of the gnutls_certificate_status_t enumerated elements bitwise
1366        or'd. To avoid denial of service attacks some default upper limits
1367        regarding the certificate key size and chain size are set. To override
1368        them use gnutls_certificate_set_verify_limits(). */
1369 
1370     rc = gnutls_certificate_verify_peers2(session, &verify_status);
1371     if(rc < 0) {
1372       failf(data, "server cert verify failed: %d", rc);
1373       *certverifyresult = rc;
1374       return CURLE_SSL_CONNECT_ERROR;
1375     }
1376 
1377     *certverifyresult = verify_status;
1378 
1379     /* verify_status is a bitmask of gnutls_certificate_status bits */
1380     if(verify_status & GNUTLS_CERT_INVALID) {
1381       if(config->verifypeer) {
1382         const char *cause = "certificate error, no details available";
1383         if(verify_status & GNUTLS_CERT_EXPIRED)
1384           cause = "certificate has expired";
1385         else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1386           cause = "certificate signer not trusted";
1387         else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
1388           cause = "certificate uses insecure algorithm";
1389         else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
1390           cause = "attached OCSP status response is invalid";
1391         failf(data, "server verification failed: %s. (CAfile: %s "
1392               "CRLfile: %s)", cause,
1393               config->CAfile ? config->CAfile : "none",
1394               ssl_config->primary.CRLfile ?
1395               ssl_config->primary.CRLfile : "none");
1396         return CURLE_PEER_FAILED_VERIFICATION;
1397       }
1398       else
1399         infof(data, "  server certificate verification FAILED");
1400     }
1401     else
1402       infof(data, "  server certificate verification OK");
1403   }
1404   else
1405     infof(data, "  server certificate verification SKIPPED");
1406 
1407   if(config->verifystatus) {
1408     gnutls_datum_t status_request;
1409     gnutls_ocsp_resp_t ocsp_resp;
1410     gnutls_ocsp_cert_status_t status;
1411     gnutls_x509_crl_reason_t reason;
1412 
1413     rc = gnutls_ocsp_status_request_get(session, &status_request);
1414 
1415     if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1416       failf(data, "No OCSP response received");
1417       return CURLE_SSL_INVALIDCERTSTATUS;
1418     }
1419 
1420     if(rc < 0) {
1421       failf(data, "Invalid OCSP response received");
1422       return CURLE_SSL_INVALIDCERTSTATUS;
1423     }
1424 
1425     gnutls_ocsp_resp_init(&ocsp_resp);
1426 
1427     rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1428     if(rc < 0) {
1429       failf(data, "Invalid OCSP response received");
1430       return CURLE_SSL_INVALIDCERTSTATUS;
1431     }
1432 
1433     (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1434                                       &status, NULL, NULL, NULL, &reason);
1435 
1436     switch(status) {
1437     case GNUTLS_OCSP_CERT_GOOD:
1438       break;
1439 
1440     case GNUTLS_OCSP_CERT_REVOKED: {
1441       const char *crl_reason;
1442 
1443       switch(reason) {
1444       default:
1445       case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1446         crl_reason = "unspecified reason";
1447         break;
1448 
1449       case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1450         crl_reason = "private key compromised";
1451         break;
1452 
1453       case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1454         crl_reason = "CA compromised";
1455         break;
1456 
1457       case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1458         crl_reason = "affiliation has changed";
1459         break;
1460 
1461       case GNUTLS_X509_CRLREASON_SUPERSEDED:
1462         crl_reason = "certificate superseded";
1463         break;
1464 
1465       case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1466         crl_reason = "operation has ceased";
1467         break;
1468 
1469       case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1470         crl_reason = "certificate is on hold";
1471         break;
1472 
1473       case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1474         crl_reason = "will be removed from delta CRL";
1475         break;
1476 
1477       case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1478         crl_reason = "privilege withdrawn";
1479         break;
1480 
1481       case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1482         crl_reason = "AA compromised";
1483         break;
1484       }
1485 
1486       failf(data, "Server certificate was revoked: %s", crl_reason);
1487       break;
1488     }
1489 
1490     default:
1491     case GNUTLS_OCSP_CERT_UNKNOWN:
1492       failf(data, "Server certificate status is unknown");
1493       break;
1494     }
1495 
1496     gnutls_ocsp_resp_deinit(ocsp_resp);
1497     if(status != GNUTLS_OCSP_CERT_GOOD)
1498       return CURLE_SSL_INVALIDCERTSTATUS;
1499   }
1500   else
1501     infof(data, "  server certificate status verification SKIPPED");
1502 
1503   /* initialize an X.509 certificate structure. */
1504   gnutls_x509_crt_init(&x509_cert);
1505 
1506   if(chainp)
1507     /* convert the given DER or PEM encoded Certificate to the native
1508        gnutls_x509_crt_t format */
1509     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1510 
1511   if(config->issuercert) {
1512     gnutls_x509_crt_init(&x509_issuer);
1513     issuerp = load_file(config->issuercert);
1514     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1515     rc = (int)gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1516     gnutls_x509_crt_deinit(x509_issuer);
1517     unload_file(issuerp);
1518     if(rc <= 0) {
1519       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1520             config->issuercert ? config->issuercert : "none");
1521       gnutls_x509_crt_deinit(x509_cert);
1522       return CURLE_SSL_ISSUER_ERROR;
1523     }
1524     infof(data, "  server certificate issuer check OK (Issuer Cert: %s)",
1525           config->issuercert ? config->issuercert : "none");
1526   }
1527 
1528   size = sizeof(certname);
1529   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1530                                      0, /* the first and only one */
1531                                      FALSE,
1532                                      certname,
1533                                      &size);
1534   if(rc) {
1535     infof(data, "error fetching CN from cert:%s",
1536           gnutls_strerror(rc));
1537   }
1538 
1539   /* This function will check if the given certificate's subject matches the
1540      given hostname. This is a basic implementation of the matching described
1541      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1542      alternative name PKIX extension. Returns non zero on success, and zero on
1543      failure. */
1544 
1545   /* This function does not handle trailing dots, so if we have an SNI name
1546      use that and fallback to the hostname only if there is no SNI (like for
1547      IP addresses) */
1548   rc = (int)gnutls_x509_crt_check_hostname(x509_cert,
1549                                            peer->sni ? peer->sni :
1550                                            peer->hostname);
1551 #if GNUTLS_VERSION_NUMBER < 0x030306
1552   /* Before 3.3.6, gnutls_x509_crt_check_hostname() did not check IP
1553      addresses. */
1554   if(!rc) {
1555 #ifdef USE_IPV6
1556     #define use_addr in6_addr
1557 #else
1558     #define use_addr in_addr
1559 #endif
1560     unsigned char addrbuf[sizeof(struct use_addr)];
1561     size_t addrlen = 0;
1562 
1563     if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
1564       addrlen = 4;
1565 #ifdef USE_IPV6
1566     else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
1567       addrlen = 16;
1568 #endif
1569 
1570     if(addrlen) {
1571       unsigned char certaddr[sizeof(struct use_addr)];
1572       int i;
1573 
1574       for(i = 0; ; i++) {
1575         size_t certaddrlen = sizeof(certaddr);
1576         int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1577                                                        &certaddrlen, NULL);
1578         /* If this happens, it was not an IP address. */
1579         if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1580           continue;
1581         if(ret < 0)
1582           break;
1583         if(ret != GNUTLS_SAN_IPADDRESS)
1584           continue;
1585         if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1586           rc = 1;
1587           break;
1588         }
1589       }
1590     }
1591   }
1592 #endif
1593   if(!rc) {
1594     if(config->verifyhost) {
1595       failf(data, "SSL: certificate subject name (%s) does not match "
1596             "target hostname '%s'", certname, peer->dispname);
1597       gnutls_x509_crt_deinit(x509_cert);
1598       return CURLE_PEER_FAILED_VERIFICATION;
1599     }
1600     else
1601       infof(data, "  common name: %s (does not match '%s')",
1602             certname, peer->dispname);
1603   }
1604   else
1605     infof(data, "  common name: %s (matched)", certname);
1606 
1607   /* Check for time-based validity */
1608   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1609 
1610   if(certclock == (time_t)-1) {
1611     if(config->verifypeer) {
1612       failf(data, "server cert expiration date verify failed");
1613       *certverifyresult = GNUTLS_CERT_EXPIRED;
1614       gnutls_x509_crt_deinit(x509_cert);
1615       return CURLE_SSL_CONNECT_ERROR;
1616     }
1617     else
1618       infof(data, "  server certificate expiration date verify FAILED");
1619   }
1620   else {
1621     if(certclock < time(NULL)) {
1622       if(config->verifypeer) {
1623         failf(data, "server certificate expiration date has passed.");
1624         *certverifyresult = GNUTLS_CERT_EXPIRED;
1625         gnutls_x509_crt_deinit(x509_cert);
1626         return CURLE_PEER_FAILED_VERIFICATION;
1627       }
1628       else
1629         infof(data, "  server certificate expiration date FAILED");
1630     }
1631     else
1632       infof(data, "  server certificate expiration date OK");
1633   }
1634 
1635   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1636 
1637   if(certclock == (time_t)-1) {
1638     if(config->verifypeer) {
1639       failf(data, "server cert activation date verify failed");
1640       *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1641       gnutls_x509_crt_deinit(x509_cert);
1642       return CURLE_SSL_CONNECT_ERROR;
1643     }
1644     else
1645       infof(data, "  server certificate activation date verify FAILED");
1646   }
1647   else {
1648     if(certclock > time(NULL)) {
1649       if(config->verifypeer) {
1650         failf(data, "server certificate not activated yet.");
1651         *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1652         gnutls_x509_crt_deinit(x509_cert);
1653         return CURLE_PEER_FAILED_VERIFICATION;
1654       }
1655       else
1656         infof(data, "  server certificate activation date FAILED");
1657     }
1658     else
1659       infof(data, "  server certificate activation date OK");
1660   }
1661 
1662   if(pinned_key) {
1663     result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
1664     if(result != CURLE_OK) {
1665       failf(data, "SSL: public key does not match pinned public key");
1666       gnutls_x509_crt_deinit(x509_cert);
1667       return result;
1668     }
1669   }
1670 
1671   /* Show:
1672 
1673   - subject
1674   - start date
1675   - expire date
1676   - common name
1677   - issuer
1678 
1679   */
1680 
1681 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1682   /* public key algorithm's parameters */
1683   algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1684   infof(data, "  certificate public key: %s",
1685         gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo));
1686 
1687   /* version of the X.509 certificate. */
1688   infof(data, "  certificate version: #%d",
1689         gnutls_x509_crt_get_version(x509_cert));
1690 
1691 
1692   rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1693   if(rc)
1694     infof(data, "Failed to get certificate name");
1695   else {
1696     infof(data, "  subject: %s", certfields.data);
1697 
1698     certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1699     showtime(data, "start date", certclock);
1700 
1701     certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1702     showtime(data, "expire date", certclock);
1703 
1704     gnutls_free(certfields.data);
1705   }
1706 
1707   rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1708   if(rc)
1709     infof(data, "Failed to get certificate issuer");
1710   else {
1711     infof(data, "  issuer: %s", certfields.data);
1712 
1713     gnutls_free(certfields.data);
1714   }
1715 #endif
1716 
1717   gnutls_x509_crt_deinit(x509_cert);
1718 
1719   return result;
1720 }
1721 
gtls_verifyserver(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)1722 static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
1723                                   struct Curl_easy *data,
1724                                   gnutls_session_t session)
1725 {
1726   struct ssl_connect_data *connssl = cf->ctx;
1727   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1728   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1729 #ifndef CURL_DISABLE_PROXY
1730   const char *pinned_key = Curl_ssl_cf_is_proxy(cf) ?
1731     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1732     data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1733 #else
1734   const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1735 #endif
1736   CURLcode result;
1737 
1738   result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
1739                                   &connssl->peer, pinned_key);
1740   if(result)
1741     goto out;
1742 
1743   /* Only on TLSv1.2 or lower do we have the session id now. For
1744    * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
1745   if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
1746     result = cf_gtls_update_session_id(cf, data, session);
1747 
1748 out:
1749   return result;
1750 }
1751 
gtls_set_earlydata(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t blen)1752 static CURLcode gtls_set_earlydata(struct Curl_cfilter *cf,
1753                                    struct Curl_easy *data,
1754                                    const void *buf, size_t blen)
1755 {
1756   struct ssl_connect_data *connssl = cf->ctx;
1757   ssize_t nwritten = 0;
1758   CURLcode result = CURLE_OK;
1759 
1760   DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_use);
1761   DEBUGASSERT(Curl_bufq_is_empty(&connssl->earlydata));
1762   if(blen) {
1763     if(blen > connssl->earlydata_max)
1764       blen = connssl->earlydata_max;
1765     nwritten = Curl_bufq_write(&connssl->earlydata, buf, blen, &result);
1766     CURL_TRC_CF(data, cf, "gtls_set_earlydata(len=%zu) -> %zd",
1767                 blen, nwritten);
1768     if(nwritten < 0)
1769       return result;
1770   }
1771   connssl->earlydata_state = ssl_earlydata_sending;
1772   connssl->earlydata_skip = Curl_bufq_len(&connssl->earlydata);
1773   return CURLE_OK;
1774 }
1775 
gtls_send_earlydata(struct Curl_cfilter * cf,struct Curl_easy * data)1776 static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf,
1777                                     struct Curl_easy *data)
1778 {
1779   struct ssl_connect_data *connssl = cf->ctx;
1780   struct gtls_ssl_backend_data *backend =
1781       (struct gtls_ssl_backend_data *)connssl->backend;
1782   CURLcode result = CURLE_OK;
1783   const unsigned char *buf;
1784   size_t blen;
1785   ssize_t n;
1786 
1787   DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sending);
1788   backend->gtls.io_result = CURLE_OK;
1789   while(Curl_bufq_peek(&connssl->earlydata, &buf, &blen)) {
1790     n = gnutls_record_send_early_data(backend->gtls.session, buf, blen);
1791     CURL_TRC_CF(data, cf, "gtls_send_earlydata(len=%zu) -> %zd",
1792                 blen, n);
1793     if(n < 0) {
1794       if(n == GNUTLS_E_AGAIN)
1795         result = CURLE_AGAIN;
1796       else
1797         result = backend->gtls.io_result ?
1798                  backend->gtls.io_result : CURLE_SEND_ERROR;
1799       goto out;
1800     }
1801     else if(!n) {
1802       /* gnutls is buggy, it *SHOULD* return the amount of bytes it took in.
1803        * Instead it returns 0 if everything was written. */
1804       n = (ssize_t)blen;
1805     }
1806 
1807     Curl_bufq_skip(&connssl->earlydata, (size_t)n);
1808   }
1809   /* sent everything there was */
1810   infof(data, "SSL sending %" FMT_OFF_T " bytes of early data",
1811         connssl->earlydata_skip);
1812 out:
1813   return result;
1814 }
1815 
1816 /*
1817  * This function is called after the TCP connect has completed. Setup the TLS
1818  * layer and do all necessary magic.
1819  */
1820 /* We use connssl->connecting_state to keep track of the connection status;
1821    there are three states: 'ssl_connect_1' (not started yet or complete),
1822    'ssl_connect_2' (doing handshake with the server), and
1823    'ssl_connect_3' (verifying and getting stats).
1824  */
1825 static CURLcode
gtls_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1826 gtls_connect_common(struct Curl_cfilter *cf,
1827                     struct Curl_easy *data,
1828                     bool nonblocking,
1829                     bool *done) {
1830   struct ssl_connect_data *connssl = cf->ctx;
1831   struct gtls_ssl_backend_data *backend =
1832       (struct gtls_ssl_backend_data *)connssl->backend;
1833   CURLcode result = CURLE_OK;
1834 
1835   DEBUGASSERT(backend);
1836 
1837   /* Initiate the connection, if not already done */
1838   if(connssl->connecting_state == ssl_connect_1) {
1839     result = gtls_connect_step1(cf, data);
1840     if(result)
1841       goto out;
1842     connssl->connecting_state = ssl_connect_2;
1843   }
1844 
1845   if(connssl->connecting_state == ssl_connect_2) {
1846     if(connssl->earlydata_state == ssl_earlydata_use) {
1847       goto out;
1848     }
1849     else if(connssl->earlydata_state == ssl_earlydata_sending) {
1850       result = gtls_send_earlydata(cf, data);
1851       if(result)
1852         goto out;
1853       connssl->earlydata_state = ssl_earlydata_sent;
1854       if(!Curl_ssl_cf_is_proxy(cf))
1855         Curl_pgrsEarlyData(data, (curl_off_t)connssl->earlydata_skip);
1856     }
1857     DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
1858                 (connssl->earlydata_state == ssl_earlydata_sent));
1859 
1860     result = handshake(cf, data, TRUE, nonblocking);
1861     if(result)
1862       goto out;
1863     connssl->connecting_state = ssl_connect_3;
1864   }
1865 
1866   /* Finish connecting once the handshake is done */
1867   if(connssl->connecting_state == ssl_connect_3) {
1868     gnutls_datum_t proto;
1869     int rc;
1870     result = gtls_verifyserver(cf, data, backend->gtls.session);
1871     if(result)
1872       goto out;
1873 
1874     connssl->state = ssl_connection_complete;
1875     connssl->connecting_state = ssl_connect_1;
1876 
1877     rc = gnutls_alpn_get_selected_protocol(backend->gtls.session, &proto);
1878     if(rc) {  /* No ALPN from server */
1879       proto.data = NULL;
1880       proto.size = 0;
1881     }
1882 
1883     result = Curl_alpn_set_negotiated(cf, data, connssl,
1884                                       proto.data, proto.size);
1885     if(result)
1886       goto out;
1887 
1888     if(connssl->earlydata_state == ssl_earlydata_sent) {
1889       if(gnutls_session_get_flags(backend->gtls.session) &
1890          GNUTLS_SFLAGS_EARLY_DATA) {
1891         connssl->earlydata_state = ssl_earlydata_accepted;
1892         infof(data, "Server accepted %zu bytes of TLS early data.",
1893               connssl->earlydata_skip);
1894       }
1895       else {
1896         connssl->earlydata_state = ssl_earlydata_rejected;
1897         if(!Curl_ssl_cf_is_proxy(cf))
1898           Curl_pgrsEarlyData(data, -(curl_off_t)connssl->earlydata_skip);
1899         infof(data, "Server rejected TLS early data.");
1900         connssl->earlydata_skip = 0;
1901       }
1902     }
1903   }
1904 
1905 out:
1906   if(result == CURLE_AGAIN) {
1907     *done = FALSE;
1908     return CURLE_OK;
1909   }
1910   *done = ((connssl->connecting_state == ssl_connect_1) ||
1911            (connssl->state == ssl_connection_deferred));
1912   return result;
1913 }
1914 
gtls_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1915 static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
1916                                          struct Curl_easy *data,
1917                                          bool *done)
1918 {
1919   struct ssl_connect_data *connssl = cf->ctx;
1920   if(connssl->state == ssl_connection_deferred) {
1921     /* We refuse to be pushed, we are waiting for someone to send/recv. */
1922     *done = TRUE;
1923     return CURLE_OK;
1924   }
1925   return gtls_connect_common(cf, data, TRUE, done);
1926 }
1927 
gtls_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1928 static CURLcode gtls_connect(struct Curl_cfilter *cf,
1929                              struct Curl_easy *data)
1930 {
1931   CURLcode result;
1932   bool done = FALSE;
1933 
1934   result = gtls_connect_common(cf, data, FALSE, &done);
1935   if(result)
1936     return result;
1937 
1938   DEBUGASSERT(done);
1939 
1940   return CURLE_OK;
1941 }
1942 
gtls_connect_deferred(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t blen,bool * done)1943 static CURLcode gtls_connect_deferred(struct Curl_cfilter *cf,
1944                                       struct Curl_easy *data,
1945                                       const void *buf,
1946                                       size_t blen,
1947                                       bool *done)
1948 {
1949   struct ssl_connect_data *connssl = cf->ctx;
1950   CURLcode result = CURLE_OK;
1951 
1952   DEBUGASSERT(connssl->state == ssl_connection_deferred);
1953   *done = FALSE;
1954   if(connssl->earlydata_state == ssl_earlydata_use) {
1955     result = gtls_set_earlydata(cf, data, buf, blen);
1956     if(result)
1957       return result;
1958   }
1959 
1960   return gtls_connect_common(cf, data, TRUE, done);
1961 }
1962 
gtls_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1963 static bool gtls_data_pending(struct Curl_cfilter *cf,
1964                               const struct Curl_easy *data)
1965 {
1966   struct ssl_connect_data *ctx = cf->ctx;
1967   struct gtls_ssl_backend_data *backend;
1968 
1969   (void)data;
1970   DEBUGASSERT(ctx && ctx->backend);
1971   backend = (struct gtls_ssl_backend_data *)ctx->backend;
1972   if(backend->gtls.session &&
1973      0 != gnutls_record_check_pending(backend->gtls.session))
1974     return TRUE;
1975   return FALSE;
1976 }
1977 
gtls_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t blen,CURLcode * curlcode)1978 static ssize_t gtls_send(struct Curl_cfilter *cf,
1979                          struct Curl_easy *data,
1980                          const void *buf,
1981                          size_t blen,
1982                          CURLcode *curlcode)
1983 {
1984   struct ssl_connect_data *connssl = cf->ctx;
1985   struct gtls_ssl_backend_data *backend =
1986     (struct gtls_ssl_backend_data *)connssl->backend;
1987   ssize_t rc;
1988   size_t nwritten, total_written = 0;
1989 
1990   DEBUGASSERT(backend);
1991 
1992   if(connssl->state == ssl_connection_deferred) {
1993     bool done = FALSE;
1994     *curlcode = gtls_connect_deferred(cf, data, buf, blen, &done);
1995     if(*curlcode) {
1996       rc = -1;
1997       goto out;
1998     }
1999     else if(!done) {
2000       *curlcode = CURLE_AGAIN;
2001       rc = -1;
2002       goto out;
2003     }
2004     DEBUGASSERT(connssl->state == ssl_connection_complete);
2005   }
2006 
2007   if(connssl->earlydata_skip) {
2008     if(connssl->earlydata_skip >= blen) {
2009       connssl->earlydata_skip -= blen;
2010       *curlcode = CURLE_OK;
2011       rc = (ssize_t)blen;
2012       goto out;
2013     }
2014     else {
2015       total_written += connssl->earlydata_skip;
2016       buf = ((const char *)buf) + connssl->earlydata_skip;
2017       blen -= connssl->earlydata_skip;
2018       connssl->earlydata_skip = 0;
2019     }
2020   }
2021 
2022   while(blen) {
2023     backend->gtls.io_result = CURLE_OK;
2024     rc = gnutls_record_send(backend->gtls.session, buf, blen);
2025 
2026     if(rc < 0) {
2027       if(total_written && (rc == GNUTLS_E_AGAIN)) {
2028         *curlcode = CURLE_OK;
2029         rc = (ssize_t)total_written;
2030         goto out;
2031       }
2032       *curlcode = (rc == GNUTLS_E_AGAIN) ?
2033         CURLE_AGAIN :
2034         (backend->gtls.io_result ? backend->gtls.io_result : CURLE_SEND_ERROR);
2035 
2036       rc = -1;
2037       goto out;
2038     }
2039     nwritten = (size_t)rc;
2040     total_written += nwritten;
2041     DEBUGASSERT(nwritten <= blen);
2042     buf = (char *)buf + nwritten;
2043     blen -= nwritten;
2044   }
2045   rc = total_written;
2046 
2047 out:
2048   return rc;
2049 }
2050 
2051 /*
2052  * This function is called to shut down the SSL layer but keep the
2053  * socket open (CCC - Clear Command Channel)
2054  */
gtls_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)2055 static CURLcode gtls_shutdown(struct Curl_cfilter *cf,
2056                               struct Curl_easy *data,
2057                               bool send_shutdown, bool *done)
2058 {
2059   struct ssl_connect_data *connssl = cf->ctx;
2060   struct gtls_ssl_backend_data *backend =
2061     (struct gtls_ssl_backend_data *)connssl->backend;
2062   char buf[1024];
2063   CURLcode result = CURLE_OK;
2064   ssize_t nread;
2065   size_t i;
2066 
2067   DEBUGASSERT(backend);
2068    /* If we have no handshaked connection or already shut down */
2069   if(!backend->gtls.session || cf->shutdown ||
2070      connssl->state != ssl_connection_complete) {
2071     *done = TRUE;
2072     goto out;
2073   }
2074 
2075   connssl->io_need = CURL_SSL_IO_NEED_NONE;
2076   *done = FALSE;
2077 
2078   if(!backend->gtls.sent_shutdown) {
2079     /* do this only once */
2080     backend->gtls.sent_shutdown = TRUE;
2081     if(send_shutdown) {
2082       int ret = gnutls_bye(backend->gtls.session, GNUTLS_SHUT_RDWR);
2083       if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
2084         CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye EAGAIN");
2085         connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
2086           CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
2087         backend->gtls.sent_shutdown = FALSE;
2088         result = CURLE_OK;
2089         goto out;
2090       }
2091       if(ret != GNUTLS_E_SUCCESS) {
2092         CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye error: '%s'(%d)",
2093                     gnutls_strerror((int)ret), (int)ret);
2094         result = CURLE_RECV_ERROR;
2095         goto out;
2096       }
2097     }
2098   }
2099 
2100   /* SSL should now have started the shutdown from our side. Since it
2101    * was not complete, we are lacking the close notify from the server. */
2102   for(i = 0; i < 10; ++i) {
2103     nread = gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
2104     if(nread <= 0)
2105       break;
2106   }
2107   if(nread > 0) {
2108     /* still data coming in? */
2109   }
2110   else if(nread == 0) {
2111     /* We got the close notify alert and are done. */
2112     *done = TRUE;
2113   }
2114   else if((nread == GNUTLS_E_AGAIN) || (nread == GNUTLS_E_INTERRUPTED)) {
2115     connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
2116       CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
2117   }
2118   else {
2119     CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)",
2120                 gnutls_strerror((int)nread), (int)nread);
2121     result = CURLE_RECV_ERROR;
2122   }
2123 
2124 out:
2125   cf->shutdown = (result || *done);
2126   return result;
2127 }
2128 
gtls_close(struct Curl_cfilter * cf,struct Curl_easy * data)2129 static void gtls_close(struct Curl_cfilter *cf,
2130                        struct Curl_easy *data)
2131 {
2132   struct ssl_connect_data *connssl = cf->ctx;
2133   struct gtls_ssl_backend_data *backend =
2134     (struct gtls_ssl_backend_data *)connssl->backend;
2135 
2136   (void) data;
2137   DEBUGASSERT(backend);
2138   CURL_TRC_CF(data, cf, "close");
2139   if(backend->gtls.session) {
2140     gnutls_deinit(backend->gtls.session);
2141     backend->gtls.session = NULL;
2142   }
2143   if(backend->gtls.shared_creds) {
2144     Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
2145   }
2146 #ifdef USE_GNUTLS_SRP
2147   if(backend->gtls.srp_client_cred) {
2148     gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
2149     backend->gtls.srp_client_cred = NULL;
2150   }
2151 #endif
2152 }
2153 
gtls_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t buffersize,CURLcode * curlcode)2154 static ssize_t gtls_recv(struct Curl_cfilter *cf,
2155                          struct Curl_easy *data,
2156                          char *buf,
2157                          size_t buffersize,
2158                          CURLcode *curlcode)
2159 {
2160   struct ssl_connect_data *connssl = cf->ctx;
2161   struct gtls_ssl_backend_data *backend =
2162     (struct gtls_ssl_backend_data *)connssl->backend;
2163   ssize_t ret;
2164 
2165   (void)data;
2166   DEBUGASSERT(backend);
2167 
2168   if(connssl->state == ssl_connection_deferred) {
2169     bool done = FALSE;
2170     *curlcode = gtls_connect_deferred(cf, data, NULL, 0, &done);
2171     if(*curlcode) {
2172       ret = -1;
2173       goto out;
2174     }
2175     else if(!done) {
2176       *curlcode = CURLE_AGAIN;
2177       ret = -1;
2178       goto out;
2179     }
2180     DEBUGASSERT(connssl->state == ssl_connection_complete);
2181   }
2182 
2183   ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
2184   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
2185     *curlcode = CURLE_AGAIN;
2186     ret = -1;
2187     goto out;
2188   }
2189 
2190   if(ret == GNUTLS_E_REHANDSHAKE) {
2191     /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
2192        proper way" takes a whole lot of work. */
2193     CURLcode result = handshake(cf, data, FALSE, FALSE);
2194     if(result)
2195       /* handshake() writes error message on its own */
2196       *curlcode = result;
2197     else
2198       *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
2199     ret = -1;
2200     goto out;
2201   }
2202 
2203   if(ret < 0) {
2204     failf(data, "GnuTLS recv error (%d): %s",
2205           (int)ret, gnutls_strerror((int)ret));
2206     *curlcode = backend->gtls.io_result ?
2207       backend->gtls.io_result : CURLE_RECV_ERROR;
2208     ret = -1;
2209     goto out;
2210   }
2211 
2212 out:
2213   return ret;
2214 }
2215 
gtls_version(char * buffer,size_t size)2216 static size_t gtls_version(char *buffer, size_t size)
2217 {
2218   return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
2219 }
2220 
2221 /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)2222 static CURLcode gtls_random(struct Curl_easy *data,
2223                             unsigned char *entropy, size_t length)
2224 {
2225   int rc;
2226   (void)data;
2227   rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
2228   return rc ? CURLE_FAILED_INIT : CURLE_OK;
2229 }
2230 
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)2231 static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
2232                                size_t tmplen,
2233                                unsigned char *sha256sum, /* output */
2234                                size_t sha256len)
2235 {
2236   struct sha256_ctx SHA256pw;
2237   sha256_init(&SHA256pw);
2238   sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
2239   sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
2240   return CURLE_OK;
2241 }
2242 
gtls_cert_status_request(void)2243 static bool gtls_cert_status_request(void)
2244 {
2245   return TRUE;
2246 }
2247 
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)2248 static void *gtls_get_internals(struct ssl_connect_data *connssl,
2249                                 CURLINFO info UNUSED_PARAM)
2250 {
2251   struct gtls_ssl_backend_data *backend =
2252     (struct gtls_ssl_backend_data *)connssl->backend;
2253   (void)info;
2254   DEBUGASSERT(backend);
2255   return backend->gtls.session;
2256 }
2257 
2258 const struct Curl_ssl Curl_ssl_gnutls = {
2259   { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
2260 
2261   SSLSUPP_CA_PATH  |
2262   SSLSUPP_CERTINFO |
2263   SSLSUPP_PINNEDPUBKEY |
2264   SSLSUPP_HTTPS_PROXY |
2265   SSLSUPP_CA_CACHE,
2266 
2267   sizeof(struct gtls_ssl_backend_data),
2268 
2269   gtls_init,                     /* init */
2270   gtls_cleanup,                  /* cleanup */
2271   gtls_version,                  /* version */
2272   Curl_none_check_cxn,           /* check_cxn */
2273   gtls_shutdown,                 /* shutdown */
2274   gtls_data_pending,             /* data_pending */
2275   gtls_random,                   /* random */
2276   gtls_cert_status_request,      /* cert_status_request */
2277   gtls_connect,                  /* connect */
2278   gtls_connect_nonblocking,      /* connect_nonblocking */
2279   Curl_ssl_adjust_pollset,       /* adjust_pollset */
2280   gtls_get_internals,            /* get_internals */
2281   gtls_close,                    /* close_one */
2282   Curl_none_close_all,           /* close_all */
2283   Curl_none_set_engine,          /* set_engine */
2284   Curl_none_set_engine_default,  /* set_engine_default */
2285   Curl_none_engines_list,        /* engines_list */
2286   Curl_none_false_start,         /* false_start */
2287   gtls_sha256sum,                /* sha256sum */
2288   NULL,                          /* associate_connection */
2289   NULL,                          /* disassociate_connection */
2290   gtls_recv,                     /* recv decrypted data */
2291   gtls_send,                     /* send data to encrypt */
2292   NULL,                          /* get_channel_binding */
2293 };
2294 
2295 #endif /* USE_GNUTLS */
2296