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