From: Jan Venekamp <1422460+jan2000@users.noreply.github.com> Date: Mon, 19 Aug 2024 01:59:08 +0000 (+0200) Subject: mbedtls: no longer use MBEDTLS_SSL_VERIFY_OPTIONAL X-Git-Tag: curl-8_10_0~187 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=925aea1aba76fcb3f024919b0f6ea5686bfa153a;p=thirdparty%2Fcurl.git mbedtls: no longer use MBEDTLS_SSL_VERIFY_OPTIONAL With mbedTLS if the minimum version of TLS is set to 1.3, MBEDTLS_SSL_VERIFY_OPTIONAL is not available in client mode. See: https://github.com/Mbed-TLS/mbedtls/blob/2ca6c285/library/ssl_tls.c#L1357 Also, there might be plans to remove it completely in future mbedTLS versions. Switch to always use MBEDTLS_SSL_VERIFY_REQUIRED. If verifypeer or verifyhost are disabled the corresponding error flags are cleared in the verify callback function. That is also where verification errors are logged. Closes #14591 --- diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 217fd0dcb8..1cf7c04697 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -115,11 +115,6 @@ struct mbed_ssl_backend_data { BIT(sent_shutdown); }; -struct verify_cb_data { - struct Curl_easy *data; - struct Curl_cfilter *cf; -}; - /* apply threading? */ #if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ defined(_WIN32) @@ -490,28 +485,22 @@ add_ciphers: return CURLE_OK; } -static void dump_cert_info(struct Curl_easy *data, - const mbedtls_x509_crt *peercert) +static void +mbed_dump_cert_info(struct Curl_easy *data, const mbedtls_x509_crt *crt) { -#if !defined(CURL_DISABLE_VERBOSE_STRINGS) && \ - !defined(MBEDTLS_X509_REMOVE_INFO) +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) || \ + (MBEDTLS_VERSION_NUMBER >= 0x03000000 && defined(MBEDTLS_X509_REMOVE_INFO)) + (void) data, (void) crt; +#else const size_t bufsize = 16384; - char *buffer = malloc(bufsize); + char *p, *buffer = malloc(bufsize); - if(!buffer) - return; - - if(mbedtls_x509_crt_info(buffer, bufsize, " ", peercert) > 0) { - char *p = buffer; + if(buffer && mbedtls_x509_crt_info(buffer, bufsize, " ", crt) > 0) { infof(data, "Server certificate:"); - while(*p) { - char *nl = strchr(p, '\n'); - if(nl) - *nl = '\0'; - infof(data, "%s", p); - if(!nl) - break; - p = nl + 1; + for(p = buffer; *p; *p && p++) { + size_t s = strcspn(p, "\n"); + infof(data, "%.*s", (int) s, p); + p += s; } } else @@ -521,63 +510,52 @@ static void dump_cert_info(struct Curl_easy *data, #endif } -static int count_server_cert(const mbedtls_x509_crt *peercert) +static void +mbed_extract_certinfo(struct Curl_easy *data, const mbedtls_x509_crt *crt) { - int count = 1; + CURLcode result; + const mbedtls_x509_crt *cur; + int i; - DEBUGASSERT(peercert); + for(i = 0, cur = crt; cur; ++i, cur = cur->next); + result = Curl_ssl_init_certinfo(data, i); - while(peercert->next) { - ++count; - peercert = peercert->next; + for(i = 0, cur = crt; result == CURLE_OK && cur; ++i, cur = cur->next) { + const char *beg = (const char *) cur->raw.p; + const char *end = beg + cur->raw.len; + result = Curl_extract_certinfo(data, i, beg, end); } - return count; -} - -static CURLcode collect_server_cert_single(struct Curl_easy *data, - const mbedtls_x509_crt *server_cert, - int idx) -{ - const char *beg, *end; - - DEBUGASSERT(server_cert); - - beg = (const char *)server_cert->raw.p; - end = beg + server_cert->raw.len; - return Curl_extract_certinfo(data, idx, beg, end); } -static int mbed_verify(void *udata, mbedtls_x509_crt *crt, - int depth, uint32_t *flags) +static int mbed_verify_cb(void *ptr, mbedtls_x509_crt *crt, + int depth, uint32_t *flags) { - struct verify_cb_data *cb_data = udata; - struct Curl_easy *data = cb_data->data; - struct Curl_cfilter *cf = cb_data->cf; + struct Curl_cfilter *cf = (struct Curl_cfilter *) ptr; struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); + struct Curl_easy *data = CF_DATA_CURRENT(cf); if(depth == 0) { if(data->set.verbose) - dump_cert_info(data, crt); - - if(data->set.ssl.certinfo) { - mbedtls_x509_crt *peercert = crt; - int count = count_server_cert(peercert); - CURLcode result = Curl_ssl_init_certinfo(data, count); - int i; - for(i = 0; result == CURLE_OK && peercert; i++) { - result = collect_server_cert_single(data, peercert, i); - peercert = peercert->next; - } - } + mbed_dump_cert_info(data, crt); + if(data->set.ssl.certinfo) + mbed_extract_certinfo(data, crt); } - /* we clear any faults the mbedtls' own verification found if needed. - * See */ if(!conn_config->verifypeer) *flags = 0; else if(!conn_config->verifyhost) *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; + if(*flags) { +#if MBEDTLS_VERSION_NUMBER < 0x03000000 || !defined(MBEDTLS_X509_REMOVE_INFO) + char buf[128]; + mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags); + failf(data, "mbedTLS: %s", buf); +#else + failf(data, "mbedTLS: cerificate verification error 0x%08x", *flags); +#endif + } + return 0; } @@ -838,6 +816,12 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_CONNECT_ERROR; } + /* Always let mbedTLS verify certificates, if verifypeer or verifyhost are + * disabled we clear the corresponding error flags in the verify callback + * function. That is also where we log verification errors. */ + mbedtls_ssl_conf_verify(&backend->config, mbed_verify_cb, cf); + mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_init(&backend->ssl); backend->initialized = TRUE; @@ -849,15 +833,6 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(ret != CURLE_OK) return ret; -#ifdef TLS13_SUPPORT - if(conn_config->version == CURL_SSLVERSION_TLSv1_3) - mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_REQUIRED); - else - mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL); -#else - mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL); -#endif - mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random, &backend->ctr_drbg); @@ -999,7 +974,6 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) struct ssl_connect_data *connssl = cf->ctx; struct mbed_ssl_backend_data *backend = (struct mbed_ssl_backend_data *)connssl->backend; - struct verify_cb_data cb_data = { data, cf }; #ifndef CURL_DISABLE_PROXY const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]: @@ -1010,8 +984,6 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGASSERT(backend); - mbedtls_ssl_conf_verify(&backend->config, mbed_verify, &cb_data); - ret = mbedtls_ssl_handshake(&backend->ssl); if(ret == MBEDTLS_ERR_SSL_WANT_READ) { @@ -1023,8 +995,8 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; } else if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - infof(data, "peer certificate could not be verified"); - /* fall through to flag checking below for better error messages */ + failf(data, "peer certificate could not be verified"); + return CURLE_PEER_FAILED_VERIFICATION; } else if(ret) { char errorbuf[128]; @@ -1052,29 +1024,6 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) infof(data, "mbedTLS: %s Handshake complete", mbedtls_ssl_get_version(&backend->ssl)); #endif - ret = mbedtls_ssl_get_verify_result(&backend->ssl); - - if(ret) { - if(ret & MBEDTLS_X509_BADCERT_EXPIRED) - failf(data, "Cert verify failed: BADCERT_EXPIRED"); - - else if(ret & MBEDTLS_X509_BADCERT_REVOKED) - failf(data, "Cert verify failed: BADCERT_REVOKED"); - - else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) - failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); - - else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) - failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); - - else if(ret & MBEDTLS_X509_BADCERT_FUTURE) - failf(data, "Cert verify failed: BADCERT_FUTURE"); - - else - failf(data, "peer certificate could not be verified"); - - return CURLE_PEER_FAILED_VERIFICATION; - } if(pinnedpubkey) { int size;