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(>ls->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, >ls->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(>ls->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(>ls->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