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