feat(esp_http_client_mutual_auth): add mutual TLS example

Closes https://github.com/espressif/esp-idf/issues/18393
This commit is contained in:
Ashish Sharma
2026-05-29 11:58:25 +08:00
parent fb2e11f070
commit c6e86872d6
24 changed files with 811 additions and 0 deletions
@@ -0,0 +1,104 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
# ESP HTTP Client Mutual TLS Authentication Example
This example demonstrates mutual TLS (mTLS) authentication using `esp_http_client`. The server verifies the client's identity via a client certificate, and the client verifies the server using a CA certificate.
Two client key modes are supported, selectable via Kconfig:
| Mode | Kconfig | Client key source |
|------|---------|-------------------|
| **Software keys** (default) | `EXAMPLE_MUTUAL_AUTH_USE_HW_RSA_DS=n` | PEM files embedded in firmware |
| **DS peripheral** | `EXAMPLE_MUTUAL_AUTH_USE_HW_RSA_DS=y` | Hardware Digital Signature peripheral via `esp_secure_cert` partition |
## How it works
1. Device connects to Wi-Fi or Ethernet (via `protocol_examples_common`)
2. Prompts for HTTPS server URL on serial console
3. Performs HTTPS GET with mutual TLS — sends client certificate to server
4. Logs the HTTP status code
## Quick start (software key mode)
```bash
idf.py set-target esp32c3
idf.py build flash monitor
```
When prompted, enter the URL of an HTTPS server that requires client certificates. The pre-generated certificates in `main/certs/` are used automatically.
## Certificates
Pre-generated certificates with 10-year lifetime are in `main/certs/`. A single CA signs both client and server certificates. See `main/certs/README.md` for OpenSSL commands to regenerate.
| File | Purpose | Embedded in firmware? |
|------|---------|----------------------|
| `ca_cert.pem` | CA certificate (verifies server) | Yes (both modes) |
| `client_cert.pem` | Client certificate | Yes (software mode only) |
| `client_key.pem` | Client private key | Yes (software mode only) |
| `server_cert.pem` | Server certificate (pytest) | No |
| `server_key.pem` | Server private key (pytest) | No |
## DS peripheral mode
The DS (Digital Signature) peripheral holds the client private key in hardware. The client certificate and DS context are stored in the `esp_secure_cert` partition.
### Prerequisites
- ESP32-C3 or other chip with `SOC_DIG_SIGN_SUPPORTED`
- `esp-secure-cert-tool` (`pip install esp-secure-cert-tool`)
### Provisioning
1. **Generate DS partition and HMAC key** (from the example directory):
```bash
configure_esp_secure_cert.py \
--device-cert main/certs/client_cert.pem \
--target_chip esp32c3 \
--configure_ds --priv_key_algo RSA 2048 \
--skip_flash --keep_ds_data_on_host \
--private-key main/certs/client_key.pem \
--efuse_key_id 1
```
Copy the output files to `main/certs/esp_secure_cert_data/`:
- `esp_secure_cert.bin`
- `hmac_key.bin`
2. **Burn HMAC key to eFuse:**
```bash
# QEMU
idf.py qemu efuse-burn-key --do-not-confirm BLOCK_KEY1 \
main/certs/esp_secure_cert_data/hmac_key.bin HMAC_DOWN_DIGITAL_SIGNATURE
# Hardware (irreversible!)
idf.py efuse-burn-key --do-not-confirm BLOCK_KEY1 \
main/certs/esp_secure_cert_data/hmac_key.bin HMAC_DOWN_DIGITAL_SIGNATURE
```
3. **Build and flash:**
```bash
idf.py -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.ci.qemu_ds" build flash monitor
```
## QEMU testing
Three QEMU tests are included:
- `test_mutual_auth_software_keys` — software key mTLS, expects HTTP 200
- `test_mutual_auth_ds` — DS peripheral mTLS, expects HTTP 200
- `test_mutual_auth_ds_fails_wrong_credentials` — DS with wrong server CA, expects failure
The tests start a local HTTPS server with mutual TLS, inject the URL via serial, and verify device output.
## Troubleshooting
**TLS handshake failed: BAD_SIGNATURE**
The client certificate is not signed by the CA the server expects. Regenerate certs using the commands in `main/certs/README.md`.
**ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL**
The HMAC key in eFuse does not match the key used to create the DS partition. For QEMU, delete the eFuse image and regenerate it from the current `hmac_key.bin`.