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