Files
meshtastic/.agents/skills/meshtastic/references/tls-ca-provisioning.md
T

45 lines
2.1 KiB
Markdown

# TLS Local CA Provisioning on Meshtastic
## How Meshtastic Stores Certificates
Stock Meshtastic firmware (`src/mesh/http/WebServer.cpp`) utilizes the `esp32_https_server` library with mbedTLS. During startup:
1. `taskCreateCert` opens ESP32 Preferences/NVS under the namespace `MeshtasticHTTPS`.
2. It checks for two binary keys:
* `PK`: DER-encoded RSA private key.
* `cert`: DER-encoded x509 leaf certificate.
3. If both keys exist and are non-empty, stock firmware loads them directly:
```cpp
cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen);
```
4. Only if keys are missing does it generate a self-signed certificate (`CN=meshtastic.local, O=Meshtastic, C=US`) and write them to NVS.
## Persistent Local CA Provisioning Strategy
Because stock Meshtastic reuses existing NVS keys, custom certificates survive subsequent OTA updates to stock firmware:
1. Generate a certificate from the private local root CA (`ericxliu.local`):
* Subject: `CN=meshtastic.local`
* SAN: `DNS:meshtastic.local, DNS:*.meshtastic.local`
2. Convert PEM certificate and key to DER binaries:
```bash
openssl x509 -in meshtastic.local.crt -outform DER -out meshtastic.local.crt.der
openssl rsa -in meshtastic.local.key -outform DER -out meshtastic.local.key.der
```
3. Generate a C header (`MeshtasticTlsCertificate.h`) containing both DER byte arrays using `xxd -i`.
4. In `WebServer.cpp::taskCreateCert`, inject the DER bytes before the check:
```cpp
prefs.begin("MeshtasticHTTPS", false);
prefs.putBytes("PK", meshtasticTlsPrivateKeyDer, sizeof(meshtasticTlsPrivateKeyDer));
prefs.putBytes("cert", meshtasticTlsCertificateDer, sizeof(meshtasticTlsCertificateDer));
```
5. On the first boot, the firmware writes the CA-signed certificate into NVS. Future boots and stock builds will use the persistent NVS certificate.
## Verification
Test from a machine trusting the local root CA:
```bash
# Verify TLS without -k
curl -v https://meshtastic.local/api/v1/fromradio
```
Expected output:
* `SSL certificate verify ok.`
* `subject: CN=meshtastic.local`
* `issuer: CN=ericxliu.local`
* `HTTP/1.1 200 OK` with CORS headers enabled.