|
1 | 1 | # Certificates used for HTTPS |
2 | 2 |
|
3 | | -These certificates are fetched from [CURL's website](https://curl.se/docs/caextract.html) and are used for HTTPS connections. |
| 3 | +This project uses a curated CA certificate bundle for TLS/SSL verification on the ESP32. |
4 | 4 |
|
5 | | -## How to update |
| 5 | +The bundle is sourced from **curl’s official CA extract** and can optionally be extended with **user-provided custom CA certificates**. |
6 | 6 |
|
7 | | -1. Download the latest version of the certificate bundle along with its sha256 from [CURL's website](https://curl.se/docs/caextract.html). |
8 | | -2. Replace the `cacrt_all.pem` file in this directory with the new one. |
9 | | -3. Run `gen_crt_bundle.py` to generate the new `x509_crt_bundle` file. |
10 | | -4. Commit the changes. |
| 7 | +## Source of Trust |
| 8 | + |
| 9 | +- The base CA bundle comes from: |
| 10 | + [https://curl.se/docs/caextract.html](https://curl.se/docs/caextract.html) |
| 11 | +- `cacert.pem` is downloaded directly from curl.se |
| 12 | +- A SHA-256 checksum is computed locally and compared against curl’s published checksum |
| 13 | +- All certificates are parsed and validated using `cryptography` |
| 14 | +- Any parsing error, mismatch, or invalid certificate **aborts generation** |
| 15 | + |
| 16 | +> ⚠️ **Trust warning** |
| 17 | +> The PEM file and its checksum are fetched from the same domain. |
| 18 | +> If curl.se were compromised or TLS trust failed, both could be malicious but internally consistent. |
| 19 | +> **Manual verification against curl’s website is therefore mandatory.** |
| 20 | +
|
| 21 | +## Updating the Bundle |
| 22 | + |
| 23 | +### 1. Generate |
| 24 | + |
| 25 | +Run: |
| 26 | + |
| 27 | +```sh |
| 28 | +python3 gen_crt_bundle.py |
| 29 | +``` |
| 30 | + |
| 31 | +The script will: |
| 32 | + |
| 33 | +- Download `cacert.pem` |
| 34 | +- Compute its SHA-256 hash |
| 35 | +- Download curl’s published checksum |
| 36 | +- Verify the PEM matches the computed checksum |
| 37 | +- Optionally include custom certificates (see below) |
| 38 | +- Abort on any error or inconsistency |
| 39 | + |
| 40 | +### 2. **Mandatory Manual Verification** |
| 41 | + |
| 42 | +⚠️ **Do not commit anything before completing the steps below.** |
| 43 | + |
| 44 | +1. Open: [https://curl.se/docs/caextract.html](https://curl.se/docs/caextract.html) |
| 45 | +2. Locate the latest published SHA-256 checksum |
| 46 | +3. Manually compare it against: |
| 47 | + |
| 48 | +```sh |
| 49 | +sha256sum cacert.pem |
| 50 | +``` |
| 51 | + |
| 52 | +Both values **must match exactly**. |
| 53 | + |
| 54 | +If they do not: |
| 55 | + |
| 56 | +- Do not commit |
| 57 | +- Treat the bundle as untrusted |
| 58 | + |
| 59 | +> Automatic checks ensure internal consistency. |
| 60 | +> Manual verification establishes the external trust boundary. |
| 61 | +
|
| 62 | +### 3. Commit |
| 63 | + |
| 64 | +After successful manual verification, commit: |
| 65 | + |
| 66 | +- `cacert.pem` |
| 67 | +- `x509_crt_bundle` |
| 68 | + |
| 69 | +❌ **Never commit anything under `custom_certs/`.** |
| 70 | + |
| 71 | +## Custom Certificates (Optional) |
| 72 | + |
| 73 | +Self-hosted setups may require trusting additional Certificate Authorities (e.g. internal PKI or private reverse proxies). |
| 74 | + |
| 75 | +Custom CA certificates can be added locally and merged into the bundle. |
| 76 | + |
| 77 | +### How to add |
| 78 | + |
| 79 | +Place certificates in: |
| 80 | + |
| 81 | +```text |
| 82 | +custom_certs/ |
| 83 | +``` |
| 84 | + |
| 85 | +Only files ending in `.pem` are considered. |
| 86 | + |
| 87 | +### Requirements |
| 88 | + |
| 89 | +Each custom certificate file must contain exactly one PEM certificate block and nothing else. |
| 90 | + |
| 91 | +The script will parse and validate them as CA certificates and reject anything invalid or duplicated. |
| 92 | + |
| 93 | +> ⚠️ Adding custom CAs expands the ESP32’s trust boundary. |
| 94 | +> Only add certificates you fully trust and control. |
| 95 | +
|
| 96 | +If `custom_certs/` does not exist or doesn't contain any .pem certificates, only curl’s CA bundle is used. |
| 97 | + |
| 98 | +## Trust Model Summary |
| 99 | + |
| 100 | +- Automatic verification protects against corruption and mismatched downloads |
| 101 | +- Manual verification anchors trust outside the update mechanism |
| 102 | +- Custom certificates explicitly extend trust and are opt-in only |
| 103 | +- The generated bundle is deterministic for a given input set |
11 | 104 |
|
12 | 105 | ## References |
13 | 106 |
|
14 | | -- [CURL's website](https://curl.se/docs/caextract.html) |
15 | | -- [Espressif's documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_crt_bundle.html) |
16 | | -- [WiFiClientSecure Documentation](https://github.com/espressif/arduino-esp32/tree/master/libraries/WiFiClientSecure#using-a-bundle-of-root-certificate-authority-certificates) |
| 107 | +- [curl - CA Extract](https://curl.se/docs/caextract.html) |
| 108 | +- [Espressif ESP-IDF certificate bundle documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/esp_crt_bundle.html) |
0 commit comments