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
This commit is contained in:
Jan Venekamp 2024-08-19 03:59:08 +02:00 committed by Daniel Stenberg
parent e8bfa96393
commit 925aea1aba
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -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)
static int mbed_verify_cb(void *ptr, mbedtls_x509_crt *crt,
int depth, uint32_t *flags)
{
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)
{
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 <https://github.com/Mbed-TLS/mbedtls/issues/9210> */
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;