From 5d2ecfef56e49a8e4bfad25a582ff1597987f717 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Wed, 6 Nov 2024 20:55:13 +0300 Subject: libcurl: update to 8.11.0 --- libs/libcurl/src/vtls/wolfssl.c | 469 ++++++++++++++++++++++++---------------- 1 file changed, 279 insertions(+), 190 deletions(-) (limited to 'libs/libcurl/src/vtls/wolfssl.c') diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index 458219ef61..9a05f82946 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -97,9 +97,25 @@ #endif #endif -#if defined(HAVE_WOLFSSL_FULL_BIO) && HAVE_WOLFSSL_FULL_BIO +#ifdef HAVE_WOLFSSL_BIO #define USE_BIO_CHAIN -#else +#ifdef HAVE_WOLFSSL_FULL_BIO +#define USE_FULL_BIO +#else /* HAVE_WOLFSSL_FULL_BIO */ +#undef USE_FULL_BIO +#endif +/* wolfSSL 5.7.4 and older do not have these symbols, but only the + * OpenSSL ones. */ +#ifndef WOLFSSL_BIO_CTRL_GET_CLOSE +#define WOLFSSL_BIO_CTRL_GET_CLOSE BIO_CTRL_GET_CLOSE +#define WOLFSSL_BIO_CTRL_SET_CLOSE BIO_CTRL_SET_CLOSE +#define WOLFSSL_BIO_CTRL_FLUSH BIO_CTRL_FLUSH +#define WOLFSSL_BIO_CTRL_DUP BIO_CTRL_DUP +#define wolfSSL_BIO_set_retry_write BIO_set_retry_write +#define wolfSSL_BIO_set_retry_read BIO_set_retry_read +#endif /* !WOLFSSL_BIO_CTRL_GET_CLOSE */ + +#else /* HAVE_WOLFSSL_BIO */ #undef USE_BIO_CHAIN #endif @@ -163,7 +179,7 @@ wolfssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret, #endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */ static void -wolfssl_log_tls12_secret(SSL *ssl) +wolfssl_log_tls12_secret(WOLFSSL *ssl) { unsigned char *ms, *sr, *cr; unsigned int msLen, srLen, crLen, i, x = 0; @@ -187,7 +203,7 @@ wolfssl_log_tls12_secret(SSL *ssl) #endif if(wolfSSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) != - SSL_SUCCESS) { + WOLFSSL_SUCCESS) { return; } @@ -208,11 +224,11 @@ wolfssl_log_tls12_secret(SSL *ssl) static int wolfssl_do_file_type(const char *type) { if(!type || !type[0]) - return SSL_FILETYPE_PEM; + return WOLFSSL_FILETYPE_PEM; if(strcasecompare(type, "PEM")) - return SSL_FILETYPE_PEM; + return WOLFSSL_FILETYPE_PEM; if(strcasecompare(type, "DER")) - return SSL_FILETYPE_ASN1; + return WOLFSSL_FILETYPE_ASN1; return -1; } @@ -237,7 +253,9 @@ static const struct group_name_map gnm[] = { static int wolfssl_bio_cf_create(WOLFSSL_BIO *bio) { +#ifdef USE_FULL_BIO wolfSSL_BIO_set_shutdown(bio, 1); +#endif wolfSSL_BIO_set_data(bio, NULL); return 1; } @@ -251,28 +269,35 @@ static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio) static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr) { - struct Curl_cfilter *cf = BIO_get_data(bio); + struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); long ret = 1; (void)cf; (void)ptr; + (void)num; switch(cmd) { - case BIO_CTRL_GET_CLOSE: + case WOLFSSL_BIO_CTRL_GET_CLOSE: +#ifdef USE_FULL_BIO ret = (long)wolfSSL_BIO_get_shutdown(bio); +#else + ret = 0; +#endif break; - case BIO_CTRL_SET_CLOSE: + case WOLFSSL_BIO_CTRL_SET_CLOSE: +#ifdef USE_FULL_BIO wolfSSL_BIO_set_shutdown(bio, (int)num); +#endif break; - case BIO_CTRL_FLUSH: + case WOLFSSL_BIO_CTRL_FLUSH: /* we do no delayed writes, but if we ever would, this * needs to trigger it. */ ret = 1; break; - case BIO_CTRL_DUP: + case WOLFSSL_BIO_CTRL_DUP: ret = 1; break; -#ifdef BIO_CTRL_EOF - case BIO_CTRL_EOF: +#ifdef WOLFSSL_BIO_CTRL_EOF + case WOLFSSL_BIO_CTRL_EOF: /* EOF has been reached on input? */ return (!cf->next || !cf->next->connected); #endif @@ -309,9 +334,11 @@ static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio, backend->io_result = result; CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d", blen, nwritten, result); +#ifdef USE_FULL_BIO wolfSSL_BIO_clear_retry_flags(bio); +#endif if(nwritten < 0 && CURLE_AGAIN == result) { - BIO_set_retry_write(bio); + wolfSSL_BIO_set_retry_write(bio); if(backend->shutting_down && !backend->io_send_blocked_len) backend->io_send_blocked_len = blen; } @@ -338,9 +365,11 @@ static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result); backend->io_result = result; CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result); +#ifdef USE_FULL_BIO wolfSSL_BIO_clear_retry_flags(bio); +#endif if(nread < 0 && CURLE_AGAIN == result) - BIO_set_retry_read(bio); + wolfSSL_BIO_set_retry_read(bio); else if(nread == 0) connssl->peer_closed = TRUE; return (int)nread; @@ -350,7 +379,8 @@ static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL; static void wolfssl_bio_cf_init_methods(void) { - wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO"); + wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(WOLFSSL_BIO_MEMORY, + "wolfSSL CF BIO"); wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write); wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read); wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl); @@ -370,9 +400,114 @@ static void wolfssl_bio_cf_free_methods(void) #endif /* !USE_BIO_CHAIN */ +static void wolfssl_session_free(void *sdata, size_t slen) +{ + (void)slen; + free(sdata); +} + +CURLcode wssl_cache_session(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct ssl_peer *peer, + WOLFSSL_SESSION *session) +{ + CURLcode result = CURLE_OK; + unsigned char *sdata = NULL; + unsigned int slen; + + if(!session) + goto out; + + slen = wolfSSL_i2d_SSL_SESSION(session, NULL); + if(slen <= 0) { + CURL_TRC_CF(data, cf, "fail to assess session length: %u", slen); + result = CURLE_FAILED_INIT; + goto out; + } + sdata = calloc(1, slen); + if(!sdata) { + failf(data, "unable to allocate session buffer of %u bytes", slen); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + slen = wolfSSL_i2d_SSL_SESSION(session, &sdata); + if(slen <= 0) { + CURL_TRC_CF(data, cf, "fail to serialize session: %u", slen); + result = CURLE_FAILED_INIT; + goto out; + } + + Curl_ssl_sessionid_lock(data); + result = Curl_ssl_set_sessionid(cf, data, peer, NULL, + sdata, slen, wolfssl_session_free); + Curl_ssl_sessionid_unlock(data); + if(result) + failf(data, "failed to add new ssl session to cache (%d)", result); + else { + CURL_TRC_CF(data, cf, "added new session to cache"); + sdata = NULL; + } + +out: + free(sdata); + return 0; +} + +static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session) +{ + struct Curl_cfilter *cf; + + cf = (struct Curl_cfilter*)wolfSSL_get_app_data(ssl); + DEBUGASSERT(cf != NULL); + if(cf && session) { + struct ssl_connect_data *connssl = cf->ctx; + struct Curl_easy *data = CF_DATA_CURRENT(cf); + DEBUGASSERT(connssl); + DEBUGASSERT(data); + if(connssl && data) { + (void)wssl_cache_session(cf, data, &connssl->peer, session); + } + } + return 0; +} + +CURLcode wssl_setup_session(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct wolfssl_ctx *wss, + struct ssl_peer *peer) +{ + void *psdata; + const unsigned char *sdata = NULL; + size_t slen = 0; + CURLcode result = CURLE_OK; + + Curl_ssl_sessionid_lock(data); + if(!Curl_ssl_getsessionid(cf, data, peer, &psdata, &slen, NULL)) { + WOLFSSL_SESSION *session; + sdata = psdata; + session = wolfSSL_d2i_SSL_SESSION(NULL, &sdata, (long)slen); + if(session) { + int ret = wolfSSL_set_session(wss->handle, session); + if(ret != WOLFSSL_SUCCESS) { + Curl_ssl_delsessionid(data, psdata); + infof(data, "previous session not accepted (%d), " + "removing from cache", ret); + } + else + infof(data, "SSL reusing session ID"); + wolfSSL_SESSION_free(session); + } + else { + failf(data, "could not decode previous session"); + } + } + Curl_ssl_sessionid_unlock(data); + return result; +} + static CURLcode populate_x509_store(struct Curl_cfilter *cf, struct Curl_easy *data, - X509_STORE *store, + WOLFSSL_X509_STORE *store, struct wolfssl_ctx *wssl) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); @@ -382,7 +517,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, (ca_info_blob ? NULL : conn_config->CAfile); const char * const ssl_capath = conn_config->CApath; struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); - bool imported_native_ca = false; + bool imported_native_ca = FALSE; #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS) /* load native CA certificates */ @@ -391,7 +526,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, infof(data, "error importing native CA store, continuing anyway"); } else { - imported_native_ca = true; + imported_native_ca = TRUE; infof(data, "successfully imported native CA store"); wssl->x509_store_setup = TRUE; } @@ -402,7 +537,8 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, if(ca_info_blob) { if(wolfSSL_CTX_load_verify_buffer(wssl->ctx, ca_info_blob->data, (long)ca_info_blob->len, - SSL_FILETYPE_PEM) != SSL_SUCCESS) { + WOLFSSL_FILETYPE_PEM) != + WOLFSSL_SUCCESS) { if(imported_native_ca) { infof(data, "error importing CA certificate blob, continuing anyway"); } @@ -421,7 +557,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, /* load trusted cacert from file if not blob */ CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d", - ssl_cafile? ssl_cafile : "none", !!ca_info_blob); + ssl_cafile ? ssl_cafile : "none", !!ca_info_blob); if(!store) return CURLE_OUT_OF_MEMORY; @@ -431,7 +567,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, ssl_cafile, ssl_capath, WOLFSSL_LOAD_FLAG_IGNORE_ERR); - if(SSL_SUCCESS != rc) { + if(WOLFSSL_SUCCESS != rc) { if(conn_config->verifypeer) { /* Fail if we insist on successfully verifying the server. */ failf(data, "error setting certificate verify locations:" @@ -493,7 +629,7 @@ cached_x509_store_expired(const struct Curl_easy *data, timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; if(timeout_ms < 0) - return false; + return FALSE; return elapsed_ms >= timeout_ms; } @@ -509,17 +645,17 @@ cached_x509_store_different(struct Curl_cfilter *cf, return strcmp(mb->CAfile, conn_config->CAfile); } -static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, - const struct Curl_easy *data) +static WOLFSSL_X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, + const struct Curl_easy *data) { struct Curl_multi *multi = data->multi; struct wssl_x509_share *share; WOLFSSL_X509_STORE *store = NULL; DEBUGASSERT(multi); - share = multi? Curl_hash_pick(&multi->proto_hash, - (void *)MPROTO_WSSL_X509_KEY, - sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL; + share = multi ? Curl_hash_pick(&multi->proto_hash, + (void *)MPROTO_WSSL_X509_KEY, + sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL; if(share && share->store && !cached_x509_store_expired(data, share) && !cached_x509_store_different(cf, share)) { @@ -531,7 +667,7 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, static void set_cached_x509_store(struct Curl_cfilter *cf, const struct Curl_easy *data, - X509_STORE *store) + WOLFSSL_X509_STORE *store) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct Curl_multi *multi = data->multi; @@ -563,13 +699,13 @@ static void set_cached_x509_store(struct Curl_cfilter *cf, if(conn_config->CAfile) { CAfile = strdup(conn_config->CAfile); if(!CAfile) { - X509_STORE_free(store); + wolfSSL_X509_STORE_free(store); return; } } if(share->store) { - X509_STORE_free(share->store); + wolfSSL_X509_STORE_free(share->store); free(share->CAfile); } @@ -609,7 +745,7 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, else if(cache_criteria_met) { /* wolfSSL's initial store in CTX is not shareable by default. * Make a new one, suitable for adding to the cache. See #14278 */ - X509_STORE *store = wolfSSL_X509_STORE_new(); + WOLFSSL_X509_STORE *store = wolfSSL_X509_STORE_new(); if(!store) { failf(data, "SSL: could not create a X509 store"); return CURLE_OUT_OF_MEMORY; @@ -623,7 +759,7 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, } else { /* We never share the CTX's store, use it. */ - X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx); + WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx); result = populate_x509_store(cf, data, store, wssl); } @@ -631,36 +767,35 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, } #ifdef WOLFSSL_TLS13 -static size_t -wssl_get_default_ciphers(bool tls13, char *buf, size_t size) +static CURLcode +wssl_add_default_ciphers(bool tls13, struct dynbuf *buf) { - size_t len = 0; - char *term = buf; int i; char *str; - size_t n; for(i = 0; (str = wolfSSL_get_cipher_list(i)); i++) { + size_t n; if((strncmp(str, "TLS13", 5) == 0) != tls13) continue; - n = strlen(str); - if(buf && len + n + 1 <= size) { - memcpy(buf + len, str, n); - term = buf + len + n; - *term = ':'; + /* if there already is data in the string, add colon separator */ + if(Curl_dyn_len(buf)) { + CURLcode result = Curl_dyn_addn(buf, ":", 1); + if(result) + return result; } - len += n + 1; - } - if(buf) - *term = '\0'; + n = strlen(str); + if(Curl_dyn_addn(buf, str, n)) + return CURLE_OUT_OF_MEMORY; + } - return len > 0 ? len - 1 : 0; + return CURLE_OK; } #endif -#if LIBWOLFSSL_VERSION_HEX < 0x04002000 /* 4.2.0 (2019) */ +/* 4.2.0 (2019) */ +#if LIBWOLFSSL_VERSION_HEX < 0x04002000 || !defined(OPENSSL_EXTRA) static int wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) { @@ -707,7 +842,7 @@ static CURLcode wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) { int res; - char *ciphers, *curves; + char *curves; struct ssl_connect_data *connssl = cf->ctx; struct wolfssl_ctx *backend = (struct wolfssl_ctx *)connssl->backend; @@ -798,50 +933,50 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) } #ifndef WOLFSSL_TLS13 - ciphers = conn_config->cipher_list; - if(ciphers) { - if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) { - failf(data, "failed setting cipher list: %s", ciphers); - return CURLE_SSL_CIPHER; + { + char *ciphers = conn_config->cipher_list; + if(ciphers) { + if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) { + failf(data, "failed setting cipher list: %s", ciphers); + return CURLE_SSL_CIPHER; + } + infof(data, "Cipher selection: %s", ciphers); } - infof(data, "Cipher selection: %s", ciphers); } #else +#define MAX_CIPHER_LEN 4096 if(conn_config->cipher_list || conn_config->cipher_list13) { const char *ciphers12 = conn_config->cipher_list; const char *ciphers13 = conn_config->cipher_list13; - - /* Set ciphers to a combination of ciphers_list and ciphers_list13. - * If cipher_list is not set use the default TLSv1.2 (1.1, 1.0) ciphers. - * If cipher_list13 is not set use the default TLSv1.3 ciphers. */ - size_t len13 = ciphers13 ? strlen(ciphers13) - : wssl_get_default_ciphers(true, NULL, 0); - size_t len12 = ciphers12 ? strlen(ciphers12) - : wssl_get_default_ciphers(false, NULL, 0); - - ciphers = malloc(len13 + 1 + len12 + 1); - if(!ciphers) - return CURLE_OUT_OF_MEMORY; + struct dynbuf c; + CURLcode result; + Curl_dyn_init(&c, MAX_CIPHER_LEN); if(ciphers13) - memcpy(ciphers, ciphers13, len13); + result = Curl_dyn_add(&c, ciphers13); else - wssl_get_default_ciphers(true, ciphers, len13 + 1); - ciphers[len13] = ':'; + result = wssl_add_default_ciphers(TRUE, &c); - if(ciphers12) - memcpy(ciphers + len13 + 1, ciphers12, len12); - else - wssl_get_default_ciphers(false, ciphers + len13 + 1, len12 + 1); - ciphers[len13 + 1 + len12] = '\0'; + if(!result) { + if(ciphers12) { + if(Curl_dyn_len(&c)) + result = Curl_dyn_addn(&c, ":", 1); + if(!result) + result = Curl_dyn_add(&c, ciphers12); + } + else + result = wssl_add_default_ciphers(FALSE, &c); + } + if(result) + return result; - if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) { - failf(data, "failed setting cipher list: %s", ciphers); - free(ciphers); + if(!wolfSSL_CTX_set_cipher_list(backend->ctx, Curl_dyn_ptr(&c))) { + failf(data, "failed setting cipher list: %s", Curl_dyn_ptr(&c)); + Curl_dyn_free(&c); return CURLE_SSL_CIPHER; } - infof(data, "Cipher selection: %s", ciphers); - free(ciphers); + infof(data, "Cipher selection: %s", Curl_dyn_ptr(&c)); + Curl_dyn_free(&c); } #endif @@ -859,7 +994,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(pqkem == 0) #endif { - if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) { + if(!wolfSSL_CTX_set1_curves_list(backend->ctx, curves)) { failf(data, "failed setting curves list: '%s'", curves); return CURLE_SSL_CIPHER; } @@ -960,8 +1095,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ wolfSSL_CTX_set_verify(backend->ctx, - conn_config->verifypeer?SSL_VERIFY_PEER: - SSL_VERIFY_NONE, NULL); + conn_config->verifypeer ? WOLFSSL_VERIFY_PEER : + WOLFSSL_VERIFY_NONE, NULL); #ifdef HAVE_SNI if(connssl->peer.sni) { @@ -1028,7 +1163,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(result || wolfSSL_UseALPN(backend->handle, (char *)proto.data, (unsigned int)proto.len, - WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != WOLFSSL_SUCCESS) { failf(data, "SSL: failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } @@ -1056,20 +1191,11 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* Check if there is a cached ID we can/should use here! */ if(ssl_config->primary.cache_session) { - void *ssl_sessionid = NULL; - - Curl_ssl_sessionid_lock(data); - if(!Curl_ssl_getsessionid(cf, data, &connssl->peer, - &ssl_sessionid, NULL)) { - /* we got a session id, use it! */ - if(!SSL_set_session(backend->handle, ssl_sessionid)) { - Curl_ssl_delsessionid(data, ssl_sessionid); - infof(data, "cannot use session ID, going on without"); - } - else - infof(data, "SSL reusing session ID"); - } - Curl_ssl_sessionid_unlock(data); + /* Set session from cache if there is one */ + (void)wssl_setup_session(cf, data, backend, &connssl->peer); + /* Register to get notified when a new session is received */ + wolfSSL_set_app_data(backend->handle, cf); + wolfSSL_CTX_sess_set_new_cb(backend->ctx, wssl_vtls_new_session_cb); } #ifdef USE_ECH @@ -1152,7 +1278,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) { WOLFSSL_BIO *bio; - bio = BIO_new(wolfssl_bio_cf_method); + bio = wolfSSL_BIO_new(wolfssl_bio_cf_method); if(!bio) return CURLE_OUT_OF_MEMORY; @@ -1200,8 +1326,8 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) (struct wolfssl_ctx *)connssl->backend; struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); #ifndef CURL_DISABLE_PROXY - const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)? - data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]: + const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY]; #else const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; @@ -1213,9 +1339,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* Enable RFC2818 checks */ if(conn_config->verifyhost) { - char *snihost = connssl->peer.sni? - connssl->peer.sni : connssl->peer.hostname; - if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE) + char *snihost = connssl->peer.sni ? + connssl->peer.sni : connssl->peer.hostname; + if(wolfSSL_check_domain_name(backend->handle, snihost) == WOLFSSL_FAILURE) return CURLE_SSL_CONNECT_ERROR; } @@ -1244,7 +1370,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever * changes, the worst case is that no key is logged on error. */ - if(ret == SSL_SUCCESS || + if(ret == WOLFSSL_SUCCESS || (!wolfSSL_want_read(backend->handle) && !wolfSSL_want_write(backend->handle))) { wolfssl_log_tls12_secret(backend->handle); @@ -1258,11 +1384,11 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) if(ret != 1) { int detail = wolfSSL_get_error(backend->handle, ret); - if(SSL_ERROR_WANT_READ == detail) { + if(WOLFSSL_ERROR_WANT_READ == detail) { connssl->io_need = CURL_SSL_IO_NEED_RECV; return CURLE_OK; } - else if(SSL_ERROR_WANT_WRITE == detail) { + else if(WOLFSSL_ERROR_WANT_WRITE == detail) { connssl->io_need = CURL_SSL_IO_NEED_SEND; return CURLE_OK; } @@ -1354,7 +1480,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) if(pinnedpubkey) { #ifdef KEEP_PEER_CERT - X509 *x509; + WOLFSSL_X509 *x509; const char *x509_der; int x509_der_len; struct Curl_X509certificate x509_parsed; @@ -1406,12 +1532,12 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len); - if(rc == SSL_SUCCESS) { - Curl_alpn_set_negotiated(cf, data, (const unsigned char *)protocol, - protocol_len); + if(rc == WOLFSSL_SUCCESS) { + Curl_alpn_set_negotiated(cf, data, connssl, + (const unsigned char *)protocol, protocol_len); } - else if(rc == SSL_ALPN_NOT_FOUND) - Curl_alpn_set_negotiated(cf, data, NULL, 0); + else if(rc == WOLFSSL_ALPN_NOT_FOUND) + Curl_alpn_set_negotiated(cf, data, connssl, NULL, 0); else { failf(data, "ALPN, failure getting protocol, error %d", rc); return CURLE_SSL_CONNECT_ERROR; @@ -1431,50 +1557,6 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; } - -static void wolfssl_session_free(void *sessionid, size_t idsize) -{ - (void)idsize; - wolfSSL_SESSION_free(sessionid); -} - - -static CURLcode -wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) -{ - CURLcode result = CURLE_OK; - struct ssl_connect_data *connssl = cf->ctx; - struct wolfssl_ctx *backend = - (struct wolfssl_ctx *)connssl->backend; - const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); - - DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - DEBUGASSERT(backend); - - if(ssl_config->primary.cache_session) { - /* wolfSSL_get1_session allocates memory that has to be freed. */ - WOLFSSL_SESSION *our_ssl_sessionid = wolfSSL_get1_session(backend->handle); - - if(our_ssl_sessionid) { - Curl_ssl_sessionid_lock(data); - /* call takes ownership of `our_ssl_sessionid` */ - result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, - our_ssl_sessionid, 0, - wolfssl_session_free); - Curl_ssl_sessionid_unlock(data); - if(result) { - failf(data, "failed to store ssl session"); - return result; - } - } - } - - connssl->connecting_state = ssl_connect_done; - - return result; -} - - static ssize_t wolfssl_send(struct Curl_cfilter *cf, struct Curl_easy *data, const void *mem, @@ -1496,8 +1578,8 @@ static ssize_t wolfssl_send(struct Curl_cfilter *cf, int err = wolfSSL_get_error(backend->handle, rc); switch(err) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: + case WOLFSSL_ERROR_WANT_READ: + case WOLFSSL_ERROR_WANT_WRITE: /* there is data pending, re-invoke SSL_write() */ CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len); *curlcode = CURLE_AGAIN; @@ -1546,14 +1628,14 @@ static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf, wctx->shutting_down = TRUE; connssl->io_need = CURL_SSL_IO_NEED_NONE; *done = FALSE; - if(!(wolfSSL_get_shutdown(wctx->handle) & SSL_SENT_SHUTDOWN)) { + if(!(wolfSSL_get_shutdown(wctx->handle) & WOLFSSL_SENT_SHUTDOWN)) { /* We have not started the shutdown from our side yet. Check * if the server already sent us one. */ - ERR_clear_error(); + wolfSSL_ERR_clear_error(); nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf)); err = wolfSSL_get_error(wctx->handle, nread); CURL_TRC_CF(data, cf, "wolfSSL_read, nread=%d, err=%d", nread, err); - if(!nread && err == SSL_ERROR_ZERO_RETURN) { + if(!nread && err == WOLFSSL_ERROR_ZERO_RETURN) { bool input_pending; /* Yes, it did. */ if(!send_shutdown) { @@ -1576,13 +1658,13 @@ static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf, /* SSL should now have started the shutdown from our side. Since it * was not complete, we are lacking the close notify from the server. */ if(send_shutdown) { - ERR_clear_error(); + wolfSSL_ERR_clear_error(); if(wolfSSL_shutdown(wctx->handle) == 1) { CURL_TRC_CF(data, cf, "SSL shutdown finished"); *done = TRUE; goto out; } - if(SSL_ERROR_WANT_WRITE == wolfSSL_get_error(wctx->handle, nread)) { + if(WOLFSSL_ERROR_WANT_WRITE == wolfSSL_get_error(wctx->handle, nread)) { CURL_TRC_CF(data, cf, "SSL shutdown still wants to send"); connssl->io_need = CURL_SSL_IO_NEED_SEND; goto out; @@ -1592,25 +1674,25 @@ static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf, } for(i = 0; i < 10; ++i) { - ERR_clear_error(); + wolfSSL_ERR_clear_error(); nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf)); if(nread <= 0) break; } err = wolfSSL_get_error(wctx->handle, nread); switch(err) { - case SSL_ERROR_ZERO_RETURN: /* no more data */ + case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */ CURL_TRC_CF(data, cf, "SSL shutdown received"); *done = TRUE; break; - case SSL_ERROR_NONE: /* just did not get anything */ - case SSL_ERROR_WANT_READ: + case WOLFSSL_ERROR_NONE: /* just did not get anything */ + case WOLFSSL_ERROR_WANT_READ: /* SSL has send its notify and now wants to read the reply * from the server. We are not really interested in that. */ CURL_TRC_CF(data, cf, "SSL shutdown sent, want receive"); connssl->io_need = CURL_SSL_IO_NEED_RECV; break; - case SSL_ERROR_WANT_WRITE: + case WOLFSSL_ERROR_WANT_WRITE: CURL_TRC_CF(data, cf, "SSL shutdown send blocked"); connssl->io_need = CURL_SSL_IO_NEED_SEND; break; @@ -1671,13 +1753,18 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, int err = wolfSSL_get_error(backend->handle, nread); switch(err) { - case SSL_ERROR_ZERO_RETURN: /* no more data */ + case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen); *curlcode = CURLE_OK; return 0; - case SSL_ERROR_NONE: - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: + case WOLFSSL_ERROR_NONE: + case WOLFSSL_ERROR_WANT_READ: + case WOLFSSL_ERROR_WANT_WRITE: + if(!backend->io_result && connssl->peer_closed) { + CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen); + *curlcode = CURLE_OK; + return 0; + } /* there is data pending, re-invoke wolfSSL_read() */ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen); *curlcode = CURLE_AGAIN; @@ -1688,7 +1775,12 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, *curlcode = CURLE_AGAIN; return -1; } - { + else if(!backend->io_result && connssl->peer_closed) { + CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen); + *curlcode = CURLE_OK; + return 0; + } + else { char error_buffer[256]; failf(data, "SSL read: %s, errno %d", wolfssl_strerror((unsigned long)err, error_buffer, @@ -1721,7 +1813,7 @@ static int wolfssl_init(void) #ifdef OPENSSL_EXTRA Curl_tls_keylog_open(); #endif - ret = (wolfSSL_Init() == SSL_SUCCESS); + ret = (wolfSSL_Init() == WOLFSSL_SUCCESS); wolfssl_bio_cf_init_methods(); return ret; } @@ -1748,7 +1840,7 @@ static bool wolfssl_data_pending(struct Curl_cfilter *cf, backend = (struct wolfssl_ctx *)ctx->backend; if(backend->handle) /* SSL is in use */ - return (0 != wolfSSL_pending(backend->handle)) ? TRUE : FALSE; + return wolfSSL_pending(backend->handle); else return FALSE; } @@ -1762,7 +1854,6 @@ wolfssl_connect_common(struct Curl_cfilter *cf, CURLcode result; struct ssl_connect_data *connssl = cf->ctx; curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); - int what; /* check if the connection has already been established */ if(ssl_connection_complete == connssl->state) { @@ -1798,14 +1889,12 @@ wolfssl_connect_common(struct Curl_cfilter *cf, /* if ssl is expecting something, check if it is available. */ if(connssl->io_need) { - - curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND)? - sockfd:CURL_SOCKET_BAD; - curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV)? - sockfd:CURL_SOCKET_BAD; - - what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, - nonblocking?0:timeout_ms); + curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ? + sockfd : CURL_SOCKET_BAD; + curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ? + sockfd : CURL_SOCKET_BAD; + int what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, + nonblocking ? 0 : timeout_ms); if(what < 0) { /* fatal error */ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); @@ -1838,9 +1927,9 @@ wolfssl_connect_common(struct Curl_cfilter *cf, } /* repeat step2 until all transactions are done. */ if(ssl_connect_3 == connssl->connecting_state) { - result = wolfssl_connect_step3(cf, data); - if(result) - return result; + /* In other backends, this is where we verify the certificate, but + * wolfSSL already does that as part of the handshake. */ + connssl->connecting_state = ssl_connect_done; } if(ssl_connect_done == connssl->connecting_state) { -- cgit v1.2.3