1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
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.haxx.se/docs/copyright.html.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
24 * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
25 * but vtls.c should ever call or use these functions.
27 * Note: don't use the GnuTLS' *_t variable type names in this source code,
28 * since they were not present in 1.0.X.
31 #include "curl_setup.h"
35 #include <gnutls/abstract.h>
36 #include <gnutls/gnutls.h>
37 #include <gnutls/x509.h>
39 #ifdef USE_GNUTLS_NETTLE
40 #include <gnutls/crypto.h>
41 #include <nettle/md5.h>
42 #include <nettle/sha2.h>
49 #include "inet_pton.h"
52 #include "parsedate.h"
53 #include "connect.h" /* for the connect timeout */
58 #include "curl_printf.h"
59 #include "curl_memory.h"
60 /* The last #include file should be: */
64 Some hackish cast macros based on:
65 https://developer.gnome.org/glib/unstable/glib-Type-Conversion-Macros.html
67 #ifndef GNUTLS_POINTER_TO_INT_CAST
68 #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
70 #ifndef GNUTLS_INT_TO_POINTER_CAST
71 #define GNUTLS_INT_TO_POINTER_CAST(i) ((void *) (long) (i))
74 /* Enable GnuTLS debugging by defining GTLSDEBUG */
75 /*#define GTLSDEBUG */
78 static void tls_log_func(int level, const char *str)
80 fprintf(stderr, "|<%d>| %s", level, str);
83 static bool gtls_inited = FALSE;
85 #if defined(GNUTLS_VERSION_NUMBER)
86 # if (GNUTLS_VERSION_NUMBER >= 0x020c00)
87 # undef gnutls_transport_set_lowat
88 # define gnutls_transport_set_lowat(A,B) Curl_nop_stmt
89 # define USE_GNUTLS_PRIORITY_SET_DIRECT 1
91 # if (GNUTLS_VERSION_NUMBER >= 0x020c03)
92 # define GNUTLS_MAPS_WINSOCK_ERRORS 1
95 # if HAVE_GNUTLS_ALPN_SET_PROTOCOLS
99 # if HAVE_GNUTLS_OCSP_REQ_INIT
103 # if (GNUTLS_VERSION_NUMBER >= 0x030306)
109 # include <gnutls/ocsp.h>
113 * Custom push and pull callback functions used by GNU TLS to read and write
114 * to the socket. These functions are simple wrappers to send() and recv()
115 * (although here using the sread/swrite macros as defined by
116 * curl_setup_once.h).
117 * We use custom functions rather than the GNU TLS defaults because it allows
118 * us to get specific about the fourth "flags" argument, and to use arbitrary
119 * private data with gnutls_transport_set_ptr if we wish.
121 * When these custom push and pull callbacks fail, GNU TLS checks its own
122 * session-specific error variable, and when not set also its own global
123 * errno variable, in order to take appropriate action. GNU TLS does not
124 * require that the transport is actually a socket. This implies that for
125 * Windows builds these callbacks should ideally set the session-specific
126 * error variable using function gnutls_transport_set_errno or as a last
127 * resort global errno variable using gnutls_transport_set_global_errno,
128 * with a transport agnostic error value. This implies that some winsock
129 * error translation must take place in these callbacks.
131 * Paragraph above applies to GNU TLS versions older than 2.12.3, since
132 * this version GNU TLS does its own internal winsock error translation
133 * using system_errno() function.
136 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
137 # define gtls_EINTR 4
139 # define gtls_EAGAIN 11
140 static int gtls_mapped_sockerrno(void)
154 static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
156 ssize_t ret = swrite(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
157 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
159 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
164 static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
166 ssize_t ret = sread(GNUTLS_POINTER_TO_INT_CAST(s), buf, len);
167 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
169 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
174 static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
176 return gnutls_record_send((gnutls_session_t) s, buf, len);
179 static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
181 return gnutls_record_recv((gnutls_session_t) s, buf, len);
186 * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
187 * are not thread-safe and thus this function itself is not thread-safe and
188 * must only be called from within curl_global_init() to keep the thread
189 * situation under control!
191 int Curl_gtls_init(void)
195 ret = gnutls_global_init()?0:1;
197 gnutls_global_set_log_function(tls_log_func);
198 gnutls_global_set_log_level(2);
205 int Curl_gtls_cleanup(void)
208 gnutls_global_deinit();
214 static void showtime(struct Curl_easy *data,
219 const struct tm *tm = &buffer;
220 CURLcode result = Curl_gmtime(stamp, &buffer);
224 snprintf(data->state.buffer,
226 "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
228 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
230 Curl_month[tm->tm_mon],
235 infof(data, "%s\n", data->state.buffer);
238 static gnutls_datum_t load_file(const char *file)
241 gnutls_datum_t loaded_file = { NULL, 0 };
245 f = fopen(file, "rb");
248 if(fseek(f, 0, SEEK_END) != 0
249 || (filelen = ftell(f)) < 0
250 || fseek(f, 0, SEEK_SET) != 0
251 || !(ptr = malloc((size_t)filelen)))
253 if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
258 loaded_file.data = ptr;
259 loaded_file.size = (unsigned int)filelen;
265 static void unload_file(gnutls_datum_t data)
271 /* this function does a SSL/TLS (re-)handshake */
272 static CURLcode handshake(struct connectdata *conn,
277 struct Curl_easy *data = conn->data;
278 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
279 gnutls_session_t session = conn->ssl[sockindex].session;
280 curl_socket_t sockfd = conn->sock[sockindex];
286 /* check allowed time left */
287 timeout_ms = Curl_timeleft(data, NULL, duringconnect);
290 /* no need to continue if time already is up */
291 failf(data, "SSL connection timeout");
292 return CURLE_OPERATION_TIMEDOUT;
295 /* if ssl is expecting something, check if it's available. */
296 if(connssl->connecting_state == ssl_connect_2_reading
297 || connssl->connecting_state == ssl_connect_2_writing) {
299 curl_socket_t writefd = ssl_connect_2_writing==
300 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
301 curl_socket_t readfd = ssl_connect_2_reading==
302 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
304 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
306 timeout_ms?timeout_ms:1000);
309 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
310 return CURLE_SSL_CONNECT_ERROR;
315 else if(timeout_ms) {
317 failf(data, "SSL connection timeout at %ld", timeout_ms);
318 return CURLE_OPERATION_TIMEDOUT;
321 /* socket is readable or writable */
324 rc = gnutls_handshake(session);
326 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
327 connssl->connecting_state =
328 gnutls_record_get_direction(session)?
329 ssl_connect_2_writing:ssl_connect_2_reading;
332 else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
333 const char *strerr = NULL;
335 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
336 int alert = gnutls_alert_get(session);
337 strerr = gnutls_alert_get_name(alert);
341 strerr = gnutls_strerror(rc);
343 infof(data, "gnutls_handshake() warning: %s\n", strerr);
347 const char *strerr = NULL;
349 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
350 int alert = gnutls_alert_get(session);
351 strerr = gnutls_alert_get_name(alert);
355 strerr = gnutls_strerror(rc);
357 failf(data, "gnutls_handshake() failed: %s", strerr);
358 return CURLE_SSL_CONNECT_ERROR;
361 /* Reset our connect state machine */
362 connssl->connecting_state = ssl_connect_1;
367 static gnutls_x509_crt_fmt_t do_file_type(const char *type)
369 if(!type || !type[0])
370 return GNUTLS_X509_FMT_PEM;
371 if(strcasecompare(type, "PEM"))
372 return GNUTLS_X509_FMT_PEM;
373 if(strcasecompare(type, "DER"))
374 return GNUTLS_X509_FMT_DER;
379 gtls_connect_step1(struct connectdata *conn,
382 struct Curl_easy *data = conn->data;
383 unsigned int init_flags;
384 gnutls_session_t session;
386 bool sni = TRUE; /* default is SNI enabled */
387 void *transport_ptr = NULL;
388 gnutls_push_func gnutls_transport_push = NULL;
389 gnutls_pull_func gnutls_transport_pull = NULL;
391 struct in6_addr addr;
395 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
396 static const int cipher_priority[] = {
397 /* These two ciphers were added to GnuTLS as late as ver. 3.0.1,
398 but this code path is only ever used for ver. < 2.12.0.
399 GNUTLS_CIPHER_AES_128_GCM,
400 GNUTLS_CIPHER_AES_256_GCM,
402 GNUTLS_CIPHER_AES_128_CBC,
403 GNUTLS_CIPHER_AES_256_CBC,
404 GNUTLS_CIPHER_CAMELLIA_128_CBC,
405 GNUTLS_CIPHER_CAMELLIA_256_CBC,
406 GNUTLS_CIPHER_3DES_CBC,
408 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
409 static int protocol_priority[] = { 0, 0, 0, 0 };
411 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
412 /* If GnuTLS was compiled without support for SRP it will error out if SRP is
413 requested in the priority string, so treat it specially
415 #define GNUTLS_SRP "+SRP"
416 const char *prioritylist;
417 const char *err = NULL;
420 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
423 if(conn->ssl[sockindex].state == ssl_connection_complete)
424 /* to make us tolerant against being called more than once for the
431 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
432 failf(data, "GnuTLS does not support SSLv2");
433 return CURLE_SSL_CONNECT_ERROR;
435 else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
436 sni = FALSE; /* SSLv3 has no SNI */
438 /* allocate a cred struct */
439 rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
440 if(rc != GNUTLS_E_SUCCESS) {
441 failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
442 return CURLE_SSL_CONNECT_ERROR;
446 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
447 infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
449 rc = gnutls_srp_allocate_client_credentials(
450 &conn->ssl[sockindex].srp_client_cred);
451 if(rc != GNUTLS_E_SUCCESS) {
452 failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
453 gnutls_strerror(rc));
454 return CURLE_OUT_OF_MEMORY;
457 rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
459 SSL_SET_OPTION(username),
460 SSL_SET_OPTION(password));
461 if(rc != GNUTLS_E_SUCCESS) {
462 failf(data, "gnutls_srp_set_client_cred() failed: %s",
463 gnutls_strerror(rc));
464 return CURLE_BAD_FUNCTION_ARGUMENT;
469 if(SSL_CONN_CONFIG(CAfile)) {
470 /* set the trusted CA cert bundle file */
471 gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
472 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
474 rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
475 SSL_CONN_CONFIG(CAfile),
476 GNUTLS_X509_FMT_PEM);
478 infof(data, "error reading ca cert file %s (%s)\n",
479 SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
480 if(SSL_CONN_CONFIG(verifypeer))
481 return CURLE_SSL_CACERT_BADFILE;
484 infof(data, "found %d certificates in %s\n", rc,
485 SSL_CONN_CONFIG(CAfile));
489 if(SSL_CONN_CONFIG(CApath)) {
490 /* set the trusted CA cert directory */
491 rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
492 SSL_CONN_CONFIG(CApath),
493 GNUTLS_X509_FMT_PEM);
495 infof(data, "error reading ca cert file %s (%s)\n",
496 SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
497 if(SSL_CONN_CONFIG(verifypeer))
498 return CURLE_SSL_CACERT_BADFILE;
501 infof(data, "found %d certificates in %s\n",
502 rc, SSL_CONN_CONFIG(CApath));
506 #ifdef CURL_CA_FALLBACK
507 /* use system ca certificate store as fallback */
508 if(SSL_CONN_CONFIG(verifypeer) &&
509 !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
510 gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
514 if(SSL_SET_OPTION(CRLfile)) {
515 /* set the CRL list file */
516 rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
517 SSL_SET_OPTION(CRLfile),
518 GNUTLS_X509_FMT_PEM);
520 failf(data, "error reading crl file %s (%s)",
521 SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
522 return CURLE_SSL_CRL_BADFILE;
525 infof(data, "found %d CRL in %s\n",
526 rc, SSL_SET_OPTION(CRLfile));
529 /* Initialize TLS session as a client */
530 init_flags = GNUTLS_CLIENT;
532 #if defined(GNUTLS_NO_TICKETS)
533 /* Disable TLS session tickets */
534 init_flags |= GNUTLS_NO_TICKETS;
537 rc = gnutls_init(&conn->ssl[sockindex].session, init_flags);
538 if(rc != GNUTLS_E_SUCCESS) {
539 failf(data, "gnutls_init() failed: %d", rc);
540 return CURLE_SSL_CONNECT_ERROR;
543 /* convenient assign */
544 session = conn->ssl[sockindex].session;
546 if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
548 (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
551 (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
552 strlen(hostname)) < 0))
553 infof(data, "WARNING: failed to configure server name indication (SNI) "
556 /* Use default priorities */
557 rc = gnutls_set_default_priority(session);
558 if(rc != GNUTLS_E_SUCCESS)
559 return CURLE_SSL_CONNECT_ERROR;
561 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT
562 rc = gnutls_cipher_set_priority(session, cipher_priority);
563 if(rc != GNUTLS_E_SUCCESS)
564 return CURLE_SSL_CONNECT_ERROR;
566 /* Sets the priority on the certificate types supported by gnutls. Priority
567 is higher for types specified before others. After specifying the types
568 you want, you must append a 0. */
569 rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
570 if(rc != GNUTLS_E_SUCCESS)
571 return CURLE_SSL_CONNECT_ERROR;
573 if(SSL_CONN_CONFIG(cipher_list) != NULL) {
574 failf(data, "can't pass a custom cipher list to older GnuTLS"
576 return CURLE_SSL_CONNECT_ERROR;
579 switch(SSL_CONN_CONFIG(version) {
580 case CURL_SSLVERSION_SSLv3:
581 protocol_priority[0] = GNUTLS_SSL3;
583 case CURL_SSLVERSION_DEFAULT:
584 case CURL_SSLVERSION_TLSv1:
585 protocol_priority[0] = GNUTLS_TLS1_0;
586 protocol_priority[1] = GNUTLS_TLS1_1;
587 protocol_priority[2] = GNUTLS_TLS1_2;
589 case CURL_SSLVERSION_TLSv1_0:
590 protocol_priority[0] = GNUTLS_TLS1_0;
592 case CURL_SSLVERSION_TLSv1_1:
593 protocol_priority[0] = GNUTLS_TLS1_1;
595 case CURL_SSLVERSION_TLSv1_2:
596 protocol_priority[0] = GNUTLS_TLS1_2;
598 case CURL_SSLVERSION_TLSv1_3:
599 failf(data, "GnuTLS: TLS 1.3 is not yet supported");
600 return CURLE_SSL_CONNECT_ERROR;
601 case CURL_SSLVERSION_SSLv2:
602 failf(data, "GnuTLS does not support SSLv2");
603 return CURLE_SSL_CONNECT_ERROR;
605 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
606 return CURLE_SSL_CONNECT_ERROR;
608 rc = gnutls_protocol_set_priority(session, protocol_priority);
609 if(rc != GNUTLS_E_SUCCESS) {
610 failf(data, "Did you pass a valid GnuTLS cipher list?");
611 return CURLE_SSL_CONNECT_ERROR;
615 /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
616 * removed if a run-time error indicates that SRP is not supported by this
618 switch(SSL_CONN_CONFIG(version)) {
619 case CURL_SSLVERSION_SSLv3:
620 prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
623 case CURL_SSLVERSION_DEFAULT:
624 case CURL_SSLVERSION_TLSv1:
625 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:" GNUTLS_SRP;
627 case CURL_SSLVERSION_TLSv1_0:
628 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
629 "+VERS-TLS1.0:" GNUTLS_SRP;
631 case CURL_SSLVERSION_TLSv1_1:
632 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
633 "+VERS-TLS1.1:" GNUTLS_SRP;
635 case CURL_SSLVERSION_TLSv1_2:
636 prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
637 "+VERS-TLS1.2:" GNUTLS_SRP;
639 case CURL_SSLVERSION_TLSv1_3:
640 failf(data, "GnuTLS: TLS 1.3 is not yet supported");
641 return CURLE_SSL_CONNECT_ERROR;
642 case CURL_SSLVERSION_SSLv2:
643 failf(data, "GnuTLS does not support SSLv2");
644 return CURLE_SSL_CONNECT_ERROR;
646 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
647 return CURLE_SSL_CONNECT_ERROR;
649 rc = gnutls_priority_set_direct(session, prioritylist, &err);
650 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
651 if(!strcmp(err, GNUTLS_SRP)) {
652 /* This GnuTLS was probably compiled without support for SRP.
653 * Note that fact and try again without it. */
654 int validprioritylen = curlx_uztosi(err - prioritylist);
655 char *prioritycopy = strdup(prioritylist);
657 return CURLE_OUT_OF_MEMORY;
659 infof(data, "This GnuTLS does not support SRP\n");
661 /* Remove the :+SRP */
662 prioritycopy[validprioritylen - 1] = 0;
663 rc = gnutls_priority_set_direct(session, prioritycopy, &err);
667 if(rc != GNUTLS_E_SUCCESS) {
668 failf(data, "Error %d setting GnuTLS cipher list starting with %s",
670 return CURLE_SSL_CONNECT_ERROR;
675 if(conn->bits.tls_enable_alpn) {
677 gnutls_datum_t protocols[2];
680 if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
681 protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
682 protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
684 infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
688 protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
689 protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
691 infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
693 gnutls_alpn_set_protocols(session, protocols, cur, 0);
697 if(SSL_SET_OPTION(cert)) {
698 if(SSL_SET_OPTION(key_passwd)) {
699 #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
700 const unsigned int supported_key_encryption_algorithms =
701 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
702 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
703 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
704 GNUTLS_PKCS_USE_PBES2_AES_256;
705 rc = gnutls_certificate_set_x509_key_file2(
706 conn->ssl[sockindex].cred,
707 SSL_SET_OPTION(cert),
708 SSL_SET_OPTION(key) ?
709 SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
710 do_file_type(SSL_SET_OPTION(cert_type)),
711 SSL_SET_OPTION(key_passwd),
712 supported_key_encryption_algorithms);
713 if(rc != GNUTLS_E_SUCCESS) {
715 "error reading X.509 potentially-encrypted key file: %s",
716 gnutls_strerror(rc));
717 return CURLE_SSL_CONNECT_ERROR;
720 failf(data, "gnutls lacks support for encrypted key files");
721 return CURLE_SSL_CONNECT_ERROR;
725 if(gnutls_certificate_set_x509_key_file(
726 conn->ssl[sockindex].cred,
727 SSL_SET_OPTION(cert),
728 SSL_SET_OPTION(key) ?
729 SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
730 do_file_type(SSL_SET_OPTION(cert_type)) ) !=
732 failf(data, "error reading X.509 key or certificate file");
733 return CURLE_SSL_CONNECT_ERROR;
739 /* put the credentials to the current session */
740 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
741 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
742 conn->ssl[sockindex].srp_client_cred);
743 if(rc != GNUTLS_E_SUCCESS) {
744 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
745 return CURLE_SSL_CONNECT_ERROR;
751 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
752 conn->ssl[sockindex].cred);
753 if(rc != GNUTLS_E_SUCCESS) {
754 failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
755 return CURLE_SSL_CONNECT_ERROR;
759 if(conn->proxy_ssl[sockindex].use) {
760 transport_ptr = conn->proxy_ssl[sockindex].session;
761 gnutls_transport_push = Curl_gtls_push_ssl;
762 gnutls_transport_pull = Curl_gtls_pull_ssl;
765 /* file descriptor for the socket */
766 transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]);
767 gnutls_transport_push = Curl_gtls_push;
768 gnutls_transport_pull = Curl_gtls_pull;
771 /* set the connection handle */
772 gnutls_transport_set_ptr(session, transport_ptr);
774 /* register callback functions to send and receive data. */
775 gnutls_transport_set_push_function(session, gnutls_transport_push);
776 gnutls_transport_set_pull_function(session, gnutls_transport_pull);
778 /* lowat must be set to zero when using custom push and pull functions. */
779 gnutls_transport_set_lowat(session, 0);
782 if(SSL_CONN_CONFIG(verifystatus)) {
783 rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
784 if(rc != GNUTLS_E_SUCCESS) {
785 failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
786 return CURLE_SSL_CONNECT_ERROR;
791 /* This might be a reconnect, so we check for a session ID in the cache
792 to speed up things */
793 if(data->set.general_ssl.sessionid) {
797 Curl_ssl_sessionid_lock(conn);
798 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
799 /* we got a session id, use it! */
800 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
802 /* Informational message */
803 infof(data, "SSL re-using session ID\n");
805 Curl_ssl_sessionid_unlock(conn);
811 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
812 gnutls_x509_crt_t cert,
813 const char *pinnedpubkey)
816 size_t len1 = 0, len2 = 0;
817 unsigned char *buff1 = NULL;
819 gnutls_pubkey_t key = NULL;
821 /* Result is returned to caller */
823 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
825 /* if a path wasn't specified, don't pin */
826 if(NULL == pinnedpubkey)
833 /* Begin Gyrations to get the public key */
834 gnutls_pubkey_init(&key);
836 ret = gnutls_pubkey_import_x509(key, cert, 0);
840 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
841 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
844 buff1 = malloc(len1);
850 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
851 if(ret < 0 || len1 != len2)
856 /* The one good exit point */
857 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
861 gnutls_pubkey_deinit(key);
863 Curl_safefree(buff1);
868 static Curl_recv gtls_recv;
869 static Curl_send gtls_send;
872 gtls_connect_step3(struct connectdata *conn,
875 unsigned int cert_list_size;
876 const gnutls_datum_t *chainp;
877 unsigned int verify_status = 0;
878 gnutls_x509_crt_t x509_cert, x509_issuer;
879 gnutls_datum_t issuerp;
880 char certbuf[256] = ""; /* big enough? */
886 struct Curl_easy *data = conn->data;
887 gnutls_session_t session = conn->ssl[sockindex].session;
890 gnutls_datum_t proto;
892 CURLcode result = CURLE_OK;
893 gnutls_protocol_t version = gnutls_protocol_get_version(session);
894 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
897 /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
898 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
899 gnutls_cipher_get(session),
900 gnutls_mac_get(session));
902 infof(data, "SSL connection using %s / %s\n",
903 gnutls_protocol_get_name(version), ptr);
905 /* This function will return the peer's raw certificate (chain) as sent by
906 the peer. These certificates are in raw format (DER encoded for
907 X.509). In case of a X.509 then a certificate list may be present. The
908 first certificate in the list is the peer's certificate, following the
909 issuer's certificate, then the issuer's issuer etc. */
911 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
913 if(SSL_CONN_CONFIG(verifypeer) ||
914 SSL_CONN_CONFIG(verifyhost) ||
915 SSL_SET_OPTION(issuercert)) {
917 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
918 && SSL_SET_OPTION(username) != NULL
919 && !SSL_CONN_CONFIG(verifypeer)
920 && gnutls_cipher_get(session)) {
921 /* no peer cert, but auth is ok if we have SRP user and cipher and no
926 failf(data, "failed to get server cert");
927 return CURLE_PEER_FAILED_VERIFICATION;
932 infof(data, "\t common name: WARNING couldn't obtain\n");
935 if(data->set.ssl.certinfo && chainp) {
938 result = Curl_ssl_init_certinfo(data, cert_list_size);
942 for(i = 0; i < cert_list_size; i++) {
943 const char *beg = (const char *) chainp[i].data;
944 const char *end = beg + chainp[i].size;
946 result = Curl_extract_certinfo(conn, i, beg, end);
952 if(SSL_CONN_CONFIG(verifypeer)) {
953 /* This function will try to verify the peer's certificate and return its
954 status (trusted, invalid etc.). The value of status should be one or
955 more of the gnutls_certificate_status_t enumerated elements bitwise
956 or'd. To avoid denial of service attacks some default upper limits
957 regarding the certificate key size and chain size are set. To override
958 them use gnutls_certificate_set_verify_limits(). */
960 rc = gnutls_certificate_verify_peers2(session, &verify_status);
962 failf(data, "server cert verify failed: %d", rc);
963 return CURLE_SSL_CONNECT_ERROR;
966 /* verify_status is a bitmask of gnutls_certificate_status bits */
967 if(verify_status & GNUTLS_CERT_INVALID) {
968 if(SSL_CONN_CONFIG(verifypeer)) {
969 failf(data, "server certificate verification failed. CAfile: %s "
970 "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
972 SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
973 return CURLE_SSL_CACERT;
976 infof(data, "\t server certificate verification FAILED\n");
979 infof(data, "\t server certificate verification OK\n");
982 infof(data, "\t server certificate verification SKIPPED\n");
985 if(SSL_CONN_CONFIG(verifystatus)) {
986 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
987 gnutls_datum_t status_request;
988 gnutls_ocsp_resp_t ocsp_resp;
990 gnutls_ocsp_cert_status_t status;
991 gnutls_x509_crl_reason_t reason;
993 rc = gnutls_ocsp_status_request_get(session, &status_request);
995 infof(data, "\t server certificate status verification FAILED\n");
997 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
998 failf(data, "No OCSP response received");
999 return CURLE_SSL_INVALIDCERTSTATUS;
1003 failf(data, "Invalid OCSP response received");
1004 return CURLE_SSL_INVALIDCERTSTATUS;
1007 gnutls_ocsp_resp_init(&ocsp_resp);
1009 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1011 failf(data, "Invalid OCSP response received");
1012 return CURLE_SSL_INVALIDCERTSTATUS;
1015 rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1016 &status, NULL, NULL, NULL, &reason);
1019 case GNUTLS_OCSP_CERT_GOOD:
1022 case GNUTLS_OCSP_CERT_REVOKED: {
1023 const char *crl_reason;
1027 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1028 crl_reason = "unspecified reason";
1031 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1032 crl_reason = "private key compromised";
1035 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1036 crl_reason = "CA compromised";
1039 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1040 crl_reason = "affiliation has changed";
1043 case GNUTLS_X509_CRLREASON_SUPERSEDED:
1044 crl_reason = "certificate superseded";
1047 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1048 crl_reason = "operation has ceased";
1051 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1052 crl_reason = "certificate is on hold";
1055 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1056 crl_reason = "will be removed from delta CRL";
1059 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1060 crl_reason = "privilege withdrawn";
1063 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1064 crl_reason = "AA compromised";
1068 failf(data, "Server certificate was revoked: %s", crl_reason);
1073 case GNUTLS_OCSP_CERT_UNKNOWN:
1074 failf(data, "Server certificate status is unknown");
1078 gnutls_ocsp_resp_deinit(ocsp_resp);
1080 return CURLE_SSL_INVALIDCERTSTATUS;
1083 infof(data, "\t server certificate status verification OK\n");
1086 infof(data, "\t server certificate status verification SKIPPED\n");
1089 /* initialize an X.509 certificate structure. */
1090 gnutls_x509_crt_init(&x509_cert);
1093 /* convert the given DER or PEM encoded Certificate to the native
1094 gnutls_x509_crt_t format */
1095 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1097 if(SSL_SET_OPTION(issuercert)) {
1098 gnutls_x509_crt_init(&x509_issuer);
1099 issuerp = load_file(SSL_SET_OPTION(issuercert));
1100 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1101 rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1102 gnutls_x509_crt_deinit(x509_issuer);
1103 unload_file(issuerp);
1105 failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1106 SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
1107 gnutls_x509_crt_deinit(x509_cert);
1108 return CURLE_SSL_ISSUER_ERROR;
1110 infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
1111 SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
1114 size=sizeof(certbuf);
1115 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1116 0, /* the first and only one */
1121 infof(data, "error fetching CN from cert:%s\n",
1122 gnutls_strerror(rc));
1125 /* This function will check if the given certificate's subject matches the
1126 given hostname. This is a basic implementation of the matching described
1127 in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1128 alternative name PKIX extension. Returns non zero on success, and zero on
1130 rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
1131 #if GNUTLS_VERSION_NUMBER < 0x030306
1132 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1136 #define use_addr in6_addr
1138 #define use_addr in_addr
1140 unsigned char addrbuf[sizeof(struct use_addr)];
1141 unsigned char certaddr[sizeof(struct use_addr)];
1142 size_t addrlen = 0, certaddrlen;
1146 if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
1149 else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
1155 certaddrlen = sizeof(certaddr);
1156 ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1157 &certaddrlen, NULL);
1158 /* If this happens, it wasn't an IP address. */
1159 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1163 if(ret != GNUTLS_SAN_IPADDRESS)
1165 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1174 const char * const dispname = SSL_IS_PROXY() ?
1175 conn->http_proxy.host.dispname : conn->host.dispname;
1177 if(SSL_CONN_CONFIG(verifyhost)) {
1178 failf(data, "SSL: certificate subject name (%s) does not match "
1179 "target host name '%s'", certbuf, dispname);
1180 gnutls_x509_crt_deinit(x509_cert);
1181 return CURLE_PEER_FAILED_VERIFICATION;
1184 infof(data, "\t common name: %s (does not match '%s')\n",
1188 infof(data, "\t common name: %s (matched)\n", certbuf);
1190 /* Check for time-based validity */
1191 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1193 if(certclock == (time_t)-1) {
1194 if(SSL_CONN_CONFIG(verifypeer)) {
1195 failf(data, "server cert expiration date verify failed");
1196 gnutls_x509_crt_deinit(x509_cert);
1197 return CURLE_SSL_CONNECT_ERROR;
1200 infof(data, "\t server certificate expiration date verify FAILED\n");
1203 if(certclock < time(NULL)) {
1204 if(SSL_CONN_CONFIG(verifypeer)) {
1205 failf(data, "server certificate expiration date has passed.");
1206 gnutls_x509_crt_deinit(x509_cert);
1207 return CURLE_PEER_FAILED_VERIFICATION;
1210 infof(data, "\t server certificate expiration date FAILED\n");
1213 infof(data, "\t server certificate expiration date OK\n");
1216 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1218 if(certclock == (time_t)-1) {
1219 if(SSL_CONN_CONFIG(verifypeer)) {
1220 failf(data, "server cert activation date verify failed");
1221 gnutls_x509_crt_deinit(x509_cert);
1222 return CURLE_SSL_CONNECT_ERROR;
1225 infof(data, "\t server certificate activation date verify FAILED\n");
1228 if(certclock > time(NULL)) {
1229 if(SSL_CONN_CONFIG(verifypeer)) {
1230 failf(data, "server certificate not activated yet.");
1231 gnutls_x509_crt_deinit(x509_cert);
1232 return CURLE_PEER_FAILED_VERIFICATION;
1235 infof(data, "\t server certificate activation date FAILED\n");
1238 infof(data, "\t server certificate activation date OK\n");
1241 ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1242 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
1244 result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
1245 if(result != CURLE_OK) {
1246 failf(data, "SSL: public key does not match pinned public key!");
1247 gnutls_x509_crt_deinit(x509_cert);
1262 /* public key algorithm's parameters */
1263 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1264 infof(data, "\t certificate public key: %s\n",
1265 gnutls_pk_algorithm_get_name(algo));
1267 /* version of the X.509 certificate. */
1268 infof(data, "\t certificate version: #%d\n",
1269 gnutls_x509_crt_get_version(x509_cert));
1272 size = sizeof(certbuf);
1273 gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
1274 infof(data, "\t subject: %s\n", certbuf);
1276 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1277 showtime(data, "start date", certclock);
1279 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1280 showtime(data, "expire date", certclock);
1282 size = sizeof(certbuf);
1283 gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
1284 infof(data, "\t issuer: %s\n", certbuf);
1286 gnutls_x509_crt_deinit(x509_cert);
1288 /* compression algorithm (if any) */
1289 ptr = gnutls_compression_get_name(gnutls_compression_get(session));
1290 /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
1291 infof(data, "\t compression: %s\n", ptr);
1294 if(conn->bits.tls_enable_alpn) {
1295 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1297 infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
1301 if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
1302 !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
1303 NGHTTP2_PROTO_VERSION_ID_LEN)) {
1304 conn->negnpn = CURL_HTTP_VERSION_2;
1308 if(proto.size == ALPN_HTTP_1_1_LENGTH &&
1309 !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
1310 conn->negnpn = CURL_HTTP_VERSION_1_1;
1314 infof(data, "ALPN, server did not agree to a protocol\n");
1318 conn->ssl[sockindex].state = ssl_connection_complete;
1319 conn->recv[sockindex] = gtls_recv;
1320 conn->send[sockindex] = gtls_send;
1322 if(data->set.general_ssl.sessionid) {
1323 /* we always unconditionally get the session id here, as even if we
1324 already got it from the cache and asked to use it in the connection, it
1325 might've been rejected and then a new one is in use now and we need to
1328 void *ssl_sessionid;
1329 void *connect_sessionid;
1330 size_t connect_idsize = 0;
1332 /* get the session ID data size */
1333 gnutls_session_get_data(session, NULL, &connect_idsize);
1334 connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1336 if(connect_sessionid) {
1337 /* extract session ID to the allocated buffer */
1338 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1340 Curl_ssl_sessionid_lock(conn);
1341 incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
1344 /* there was one before in the cache, so instead of risking that the
1345 previous one was rejected, we just kill that and store the new */
1346 Curl_ssl_delsessionid(conn, ssl_sessionid);
1349 /* store this session id */
1350 result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
1352 Curl_ssl_sessionid_unlock(conn);
1354 free(connect_sessionid);
1355 result = CURLE_OUT_OF_MEMORY;
1359 result = CURLE_OUT_OF_MEMORY;
1367 * This function is called after the TCP connect has completed. Setup the TLS
1368 * layer and do all necessary magic.
1370 /* We use connssl->connecting_state to keep track of the connection status;
1371 there are three states: 'ssl_connect_1' (not started yet or complete),
1372 'ssl_connect_2_reading' (waiting for data from server), and
1373 'ssl_connect_2_writing' (waiting to be able to write).
1376 gtls_connect_common(struct connectdata *conn,
1382 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1384 /* Initiate the connection, if not already done */
1385 if(ssl_connect_1==connssl->connecting_state) {
1386 rc = gtls_connect_step1(conn, sockindex);
1391 rc = handshake(conn, sockindex, TRUE, nonblocking);
1393 /* handshake() sets its own error message with failf() */
1396 /* Finish connecting once the handshake is done */
1397 if(ssl_connect_1==connssl->connecting_state) {
1398 rc = gtls_connect_step3(conn, sockindex);
1403 *done = ssl_connect_1==connssl->connecting_state;
1409 Curl_gtls_connect_nonblocking(struct connectdata *conn,
1413 return gtls_connect_common(conn, sockindex, TRUE, done);
1417 Curl_gtls_connect(struct connectdata *conn,
1424 result = gtls_connect_common(conn, sockindex, FALSE, &done);
1433 bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
1436 if(conn->ssl[connindex].session &&
1437 0 != gnutls_record_check_pending(conn->ssl[connindex].session))
1440 if(conn->proxy_ssl[connindex].session &&
1441 0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
1447 static ssize_t gtls_send(struct connectdata *conn,
1453 ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
1456 *curlcode = (rc == GNUTLS_E_AGAIN)
1466 static void close_one(struct ssl_connect_data *ssl)
1469 gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
1470 gnutls_deinit(ssl->session);
1471 ssl->session = NULL;
1474 gnutls_certificate_free_credentials(ssl->cred);
1478 if(ssl->srp_client_cred) {
1479 gnutls_srp_free_client_credentials(ssl->srp_client_cred);
1480 ssl->srp_client_cred = NULL;
1485 void Curl_gtls_close(struct connectdata *conn, int sockindex)
1487 close_one(&conn->ssl[sockindex]);
1488 close_one(&conn->proxy_ssl[sockindex]);
1492 * This function is called to shut down the SSL layer but keep the
1493 * socket open (CCC - Clear Command Channel)
1495 int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
1499 struct Curl_easy *data = conn->data;
1503 /* This has only been tested on the proftpd server, and the mod_tls code
1504 sends a close notify alert without waiting for a close notify alert in
1505 response. Thus we wait for a close notify alert from the server, but
1506 we do not send one. Let's hope other servers do the same... */
1508 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1509 gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
1511 if(conn->ssl[sockindex].session) {
1513 int what = SOCKET_READABLE(conn->sock[sockindex],
1514 SSL_SHUTDOWN_TIMEOUT);
1516 /* Something to read, let's do it and hope that it is the close
1517 notify alert from the server */
1518 result = gnutls_record_recv(conn->ssl[sockindex].session,
1522 /* This is the expected response. There was no data but only
1523 the close notify alert */
1526 case GNUTLS_E_AGAIN:
1527 case GNUTLS_E_INTERRUPTED:
1528 infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1536 else if(0 == what) {
1538 failf(data, "SSL shutdown timeout");
1543 /* anything that gets here is fatally bad */
1544 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1549 gnutls_deinit(conn->ssl[sockindex].session);
1551 gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
1554 if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
1555 && SSL_SET_OPTION(username) != NULL)
1556 gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
1559 conn->ssl[sockindex].cred = NULL;
1560 conn->ssl[sockindex].session = NULL;
1565 static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
1566 int num, /* socketindex */
1567 char *buf, /* store read data here */
1568 size_t buffersize, /* max amount to read */
1573 ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
1574 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1575 *curlcode = CURLE_AGAIN;
1579 if(ret == GNUTLS_E_REHANDSHAKE) {
1580 /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1581 proper way" takes a whole lot of work. */
1582 CURLcode result = handshake(conn, num, FALSE, FALSE);
1584 /* handshake() writes error message on its own */
1587 *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1592 failf(conn->data, "GnuTLS recv error (%d): %s",
1593 (int)ret, gnutls_strerror((int)ret));
1594 *curlcode = CURLE_RECV_ERROR;
1601 void Curl_gtls_session_free(void *ptr)
1606 size_t Curl_gtls_version(char *buffer, size_t size)
1608 return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1611 #ifndef USE_GNUTLS_NETTLE
1612 static int Curl_gtls_seed(struct Curl_easy *data)
1614 /* we have the "SSL is seeded" boolean static to prevent multiple
1615 time-consuming seedings in vain */
1616 static bool ssl_seeded = FALSE;
1618 /* Quickly add a bit of entropy */
1619 gcry_fast_random_poll();
1621 if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1622 data->set.str[STRING_SSL_EGDSOCKET]) {
1624 /* TODO: to a good job seeding the RNG
1625 This may involve the gcry_control function and these options:
1626 GCRYCTL_SET_RANDOM_SEED_FILE
1627 GCRYCTL_SET_RNDEGD_SOCKET
1635 /* data might be NULL! */
1636 CURLcode Curl_gtls_random(struct Curl_easy *data,
1637 unsigned char *entropy,
1640 #if defined(USE_GNUTLS_NETTLE)
1643 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1644 return rc?CURLE_FAILED_INIT:CURLE_OK;
1645 #elif defined(USE_GNUTLS)
1647 Curl_gtls_seed(data); /* Initiate the seed if not already done */
1648 gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1653 void Curl_gtls_md5sum(unsigned char *tmp, /* input */
1655 unsigned char *md5sum, /* output */
1658 #if defined(USE_GNUTLS_NETTLE)
1659 struct md5_ctx MD5pw;
1661 md5_update(&MD5pw, (unsigned int)tmplen, tmp);
1662 md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
1663 #elif defined(USE_GNUTLS)
1665 gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1666 gcry_md_write(MD5pw, tmp, tmplen);
1667 memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
1668 gcry_md_close(MD5pw);
1672 void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
1674 unsigned char *sha256sum, /* output */
1677 #if defined(USE_GNUTLS_NETTLE)
1678 struct sha256_ctx SHA256pw;
1679 sha256_init(&SHA256pw);
1680 sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1681 sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1682 #elif defined(USE_GNUTLS)
1683 gcry_md_hd_t SHA256pw;
1684 gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
1685 gcry_md_write(SHA256pw, tmp, tmplen);
1686 memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
1687 gcry_md_close(SHA256pw);
1691 bool Curl_gtls_cert_status_request(void)
1700 #endif /* USE_GNUTLS */