From ef000a08653a52f96285aebcc49d0849ee8ccd64 Mon Sep 17 00:00:00 2001 From: "hrushikesh.bhosale" Date: Mon, 15 Jun 2026 18:36:50 +0530 Subject: [PATCH 1/2] fix(esp-wolfssl): send SNI and skip OCSP when skip_common_name is set Migrated from esp-idf PR #14684. When esp_tls_cfg_t.skip_common_name is set, peer-certificate hostname verification is disabled, but: - SNI must still be sent so virtual-host / CDN servers return the certificate for the requested host. Previously SNI was set only inside the !skip_common_name branch, so it was wrongly skipped along with the hostname check. - OCSP status checking is now skipped too, so the relaxed-verification request is not defeated by an OCSP failure. Verified on ESP32-C5: a client with skip_common_name=true connecting to an SNI-dependent host (www.howsmyssl.com) completes the handshake, which only succeeds if SNI was sent so the chain verifies against the provided root CA. --- port/esp_tls_wolfssl.c | 43 +++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/port/esp_tls_wolfssl.c b/port/esp_tls_wolfssl.c index ed8127b..0703941 100644 --- a/port/esp_tls_wolfssl.c +++ b/port/esp_tls_wolfssl.c @@ -364,6 +364,17 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls return ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED; } free(use_host); + } else { + /* skip_common_name only disables hostname *verification* of the peer + * certificate; SNI must still be sent so the server presents the + * certificate for the requested host (e.g. virtual hosts / CDNs). + * See esp-idf PR #14684. */ + if (hostname != NULL && hostlen > 0) { + if ((ret = wolfSSL_UseSNI(tls->priv_ssl, WOLFSSL_SNI_HOST_NAME, hostname, hostlen)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "wolfSSL_UseSNI failed, returned %d", ret); + return ESP_ERR_WOLFSSL_SSL_SET_HOSTNAME_FAILED; + } + } } if (cfg->alpn_protos) { @@ -383,21 +394,27 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls } #ifdef CONFIG_WOLFSSL_HAVE_OCSP - int ocsp_options = 0; + /* OCSP status checking is part of certificate verification. When the caller + * opts out of strict (common-name) verification, skip OCSP too so the + * relaxed-verification request is not defeated by an OCSP failure. + * See esp-idf PR #14684. */ + if (!cfg->skip_common_name) { + int ocsp_options = 0; #ifdef ESP_TLS_OCSP_CHECKALL - ocsp_options |= WOLFSSL_OCSP_CHECKALL; + ocsp_options |= WOLFSSL_OCSP_CHECKALL; #endif - if ((ret = wolfSSL_CTX_EnableOCSP((WOLFSSL_CTX *)tls->priv_ctx, ocsp_options)) != WOLFSSL_SUCCESS) { - ESP_LOGE(TAG, "wolfSSL_CTX_EnableOCSP failed, returned %d", ret); - return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; - } - if ((ret = wolfSSL_CTX_EnableOCSPStapling((WOLFSSL_CTX *)tls->priv_ctx )) != WOLFSSL_SUCCESS) { - ESP_LOGE(TAG, "wolfSSL_CTX_EnableOCSPStapling failed, returned %d", ret); - return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; - } - if ((ret = wolfSSL_UseOCSPStapling((WOLFSSL *)tls->priv_ssl, WOLFSSL_CSR_OCSP, WOLFSSL_CSR_OCSP_USE_NONCE)) != WOLFSSL_SUCCESS) { - ESP_LOGE(TAG, "wolfSSL_UseOCSPStapling failed, returned %d", ret); - return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; + if ((ret = wolfSSL_CTX_EnableOCSP((WOLFSSL_CTX *)tls->priv_ctx, ocsp_options)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "wolfSSL_CTX_EnableOCSP failed, returned %d", ret); + return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; + } + if ((ret = wolfSSL_CTX_EnableOCSPStapling((WOLFSSL_CTX *)tls->priv_ctx )) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "wolfSSL_CTX_EnableOCSPStapling failed, returned %d", ret); + return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; + } + if ((ret = wolfSSL_UseOCSPStapling((WOLFSSL *)tls->priv_ssl, WOLFSSL_CSR_OCSP, WOLFSSL_CSR_OCSP_USE_NONCE)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "wolfSSL_UseOCSPStapling failed, returned %d", ret); + return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; + } } #endif /* CONFIG_WOLFSSL_HAVE_OCSP */ From 35876bdba910d01fa4a7c978565d7c9d51f9843d Mon Sep 17 00:00:00 2001 From: "hrushikesh.bhosale" Date: Wed, 17 Jun 2026 12:53:15 +0530 Subject: [PATCH 2/2] fix(esp-wolfssl): drop OCSP-skip, keep SNI on skip_common_name Revert the OCSP part of the skip_common_name change. OCSP revocation checking is identified by the certificate's issuer + serial number (RFC 6960 sec 4.1.1), not by the server hostname/CN, so it is independent of common-name matching and does not 'fail because the CN does not match'. OCSP remains governed solely by CONFIG_WOLFSSL_HAVE_OCSP. The SNI change is kept: SNI (RFC 6066) selects which certificate the server returns and is independent of hostname verification, matching common TLS client behaviour (e.g. curl -k still sends SNI). --- port/esp_tls_wolfssl.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/port/esp_tls_wolfssl.c b/port/esp_tls_wolfssl.c index 0703941..10711ab 100644 --- a/port/esp_tls_wolfssl.c +++ b/port/esp_tls_wolfssl.c @@ -394,27 +394,21 @@ static esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls } #ifdef CONFIG_WOLFSSL_HAVE_OCSP - /* OCSP status checking is part of certificate verification. When the caller - * opts out of strict (common-name) verification, skip OCSP too so the - * relaxed-verification request is not defeated by an OCSP failure. - * See esp-idf PR #14684. */ - if (!cfg->skip_common_name) { - int ocsp_options = 0; + int ocsp_options = 0; #ifdef ESP_TLS_OCSP_CHECKALL - ocsp_options |= WOLFSSL_OCSP_CHECKALL; + ocsp_options |= WOLFSSL_OCSP_CHECKALL; #endif - if ((ret = wolfSSL_CTX_EnableOCSP((WOLFSSL_CTX *)tls->priv_ctx, ocsp_options)) != WOLFSSL_SUCCESS) { - ESP_LOGE(TAG, "wolfSSL_CTX_EnableOCSP failed, returned %d", ret); - return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; - } - if ((ret = wolfSSL_CTX_EnableOCSPStapling((WOLFSSL_CTX *)tls->priv_ctx )) != WOLFSSL_SUCCESS) { - ESP_LOGE(TAG, "wolfSSL_CTX_EnableOCSPStapling failed, returned %d", ret); - return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; - } - if ((ret = wolfSSL_UseOCSPStapling((WOLFSSL *)tls->priv_ssl, WOLFSSL_CSR_OCSP, WOLFSSL_CSR_OCSP_USE_NONCE)) != WOLFSSL_SUCCESS) { - ESP_LOGE(TAG, "wolfSSL_UseOCSPStapling failed, returned %d", ret); - return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; - } + if ((ret = wolfSSL_CTX_EnableOCSP((WOLFSSL_CTX *)tls->priv_ctx, ocsp_options)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "wolfSSL_CTX_EnableOCSP failed, returned %d", ret); + return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; + } + if ((ret = wolfSSL_CTX_EnableOCSPStapling((WOLFSSL_CTX *)tls->priv_ctx )) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "wolfSSL_CTX_EnableOCSPStapling failed, returned %d", ret); + return ESP_ERR_WOLFSSL_CTX_SETUP_FAILED; + } + if ((ret = wolfSSL_UseOCSPStapling((WOLFSSL *)tls->priv_ssl, WOLFSSL_CSR_OCSP, WOLFSSL_CSR_OCSP_USE_NONCE)) != WOLFSSL_SUCCESS) { + ESP_LOGE(TAG, "wolfSSL_UseOCSPStapling failed, returned %d", ret); + return ESP_ERR_WOLFSSL_SSL_SETUP_FAILED; } #endif /* CONFIG_WOLFSSL_HAVE_OCSP */