From 35c0117f479c62f78bf022fc403f9a0840b63ad9 Mon Sep 17 00:00:00 2001 From: Sergey Markelov Date: Tue, 12 Mar 2024 17:21:06 -0700 Subject: [PATCH] mbedtls: support CURLOPT_CERTINFO Closes #13113 --- docs/libcurl/opts/CURLINFO_CERTINFO.md | 7 +-- docs/libcurl/opts/CURLOPT_CERTINFO.md | 1 + lib/vtls/mbedtls.c | 62 ++++++++++++++++++++++++++ lib/vtls/x509asn1.c | 6 ++- lib/vtls/x509asn1.h | 3 +- tests/data/test3102 | 1 - tests/test1275.pl | 1 + 7 files changed, 74 insertions(+), 7 deletions(-) diff --git a/docs/libcurl/opts/CURLINFO_CERTINFO.md b/docs/libcurl/opts/CURLINFO_CERTINFO.md index 633beed17b..203e39ccdd 100644 --- a/docs/libcurl/opts/CURLINFO_CERTINFO.md +++ b/docs/libcurl/opts/CURLINFO_CERTINFO.md @@ -93,9 +93,10 @@ See also the *certinfo.c* example. # AVAILABILITY -This option is only working in libcurl built with OpenSSL, GnuTLS, Schannel or -Secure Transport. GnuTLS support added in 7.42.0. Schannel support added in -7.50.0. Secure Transport support added in 7.79.0. +This option is only working in libcurl built with OpenSSL, GnuTLS, Schannel, +Secure Transport or mbedTLS. GnuTLS support added in 7.42.0. Schannel support +added in 7.50.0. Secure Transport support added in 7.79.0. mbedTLS support added +in 8.9.0. Added in 7.19.1 diff --git a/docs/libcurl/opts/CURLOPT_CERTINFO.md b/docs/libcurl/opts/CURLOPT_CERTINFO.md index 71339cd032..5aaa219b90 100644 --- a/docs/libcurl/opts/CURLOPT_CERTINFO.md +++ b/docs/libcurl/opts/CURLOPT_CERTINFO.md @@ -85,6 +85,7 @@ int main(void) # AVAILABILITY Schannel support added in 7.50.0. Secure Transport support added in 7.79.0. +mbedTLS support added in 8.9.0. # RETURN VALUE diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 45c78de1e7..3748709d4c 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -75,6 +75,7 @@ #include "mbedtls.h" #include "vtls.h" #include "vtls_int.h" +#include "x509asn1.h" #include "parsedate.h" #include "connect.h" /* for the connect timeout */ #include "select.h" @@ -922,6 +923,60 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; } +static int count_server_cert(const mbedtls_x509_crt *peercert) +{ + int count = 1; + + DEBUGASSERT(peercert); + + while(peercert->next) { + ++count; + peercert = peercert->next; + } + 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 CURLcode collect_server_cert(struct Curl_cfilter *cf, + struct Curl_easy *data, + const struct mbedtls_x509_crt *peercert) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + const bool show_verbose_server_cert = data->set.verbose; +#else + const bool show_verbose_server_cert = false; +#endif + struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); + CURLcode result = CURLE_PEER_FAILED_VERIFICATION; + int i, count; + + if(!show_verbose_server_cert && !ssl_config->certinfo) + return CURLE_OK; + + if(!peercert) + return result; + + count = count_server_cert(peercert); + result = Curl_ssl_init_certinfo(data, count); + for(i = 0 ; !result && peercert ; i++) { + result = collect_server_cert_single(data, peercert, i); + peercert = peercert->next; + } + return result; +} + static CURLcode mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) { @@ -1004,6 +1059,12 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) peercert = mbedtls_ssl_get_peer_cert(&backend->ssl); + if(peercert) { + const CURLcode result = collect_server_cert(cf, data, peercert); + if(result) + return result; + } + if(peercert && data->set.verbose) { #ifndef MBEDTLS_X509_REMOVE_INFO const size_t bufsize = 16384; @@ -1611,6 +1672,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = { SSLSUPP_CA_PATH | SSLSUPP_CAINFO_BLOB | + SSLSUPP_CERTINFO | SSLSUPP_PINNEDPUBKEY | SSLSUPP_SSL_CTX | SSLSUPP_HTTPS_PROXY, diff --git a/lib/vtls/x509asn1.c b/lib/vtls/x509asn1.c index 8aa9504ce3..c896838de7 100644 --- a/lib/vtls/x509asn1.c +++ b/lib/vtls/x509asn1.c @@ -25,13 +25,15 @@ #include "curl_setup.h" #if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \ - defined(USE_SCHANNEL) || defined(USE_SECTRANSP) + defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ + defined(USE_MBEDTLS) #if defined(USE_WOLFSSL) || defined(USE_SCHANNEL) #define WANT_PARSEX509 /* uses Curl_parseX509() */ #endif -#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) +#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ + defined(USE_MBEDTLS) #define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */ #define WANT_PARSEX509 /* ... uses Curl_parseX509() */ #endif diff --git a/lib/vtls/x509asn1.h b/lib/vtls/x509asn1.h index 23a67b828a..5844460467 100644 --- a/lib/vtls/x509asn1.h +++ b/lib/vtls/x509asn1.h @@ -28,7 +28,8 @@ #include "curl_setup.h" #if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \ - defined(USE_SCHANNEL) || defined(USE_SECTRANSP) + defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ + defined(USE_MBEDTLS) #include "cfilters.h" #include "urldata.h" diff --git a/tests/data/test3102 b/tests/data/test3102 index 4df7ba9c1f..7635e65432 100644 --- a/tests/data/test3102 +++ b/tests/data/test3102 @@ -20,7 +20,6 @@ HTTP GET SSL !bearssl -!mbedtls !rustls !wolfssl diff --git a/tests/test1275.pl b/tests/test1275.pl index 47ce799578..353391d2f3 100755 --- a/tests/test1275.pl +++ b/tests/test1275.pl @@ -32,6 +32,7 @@ my $errors; my %accepted=('curl' => 1, 'libcurl' => 1, 'macOS' => 1, + 'mbedTLS' => 1, 'c-ares' => 1); sub checkfile {