1. Today’s topic
Today we examine secure device-to-server communication:
TCP
→ TLS handshake
→ server certificate verification
→ optional client certificate
→ encrypted MQTT/HTTPSThe central idea: TLS protects a connection only when the device checks not merely that encryption exists, but server authenticity, hostname, and certificate validity.
2. Why this matters in your projects
LTE carries phase events, fault snapshots, settings, OTA manifests, and control commands. Without correct TLS verification, a device may connect to a fake broker and accept a harmful command. For OTA, a CA/hostname error may enable image substitution or prevent the whole fleet from updating. For STM32 with Ethernet/Wi-Fi/PPP, the architecture is similar:
LwIP / NetX Duo
→ Mbed TLS
→ CA store
→ optional mTLS
→ MQTT/HTTPS3. Theory
7.3.1 3.1. What TLS protects
Confidentiality:
outsiders cannot read the payload.
Integrity:
a packet cannot be changed unnoticed.
Authentication:
the client verifies that the server is genuine.With mTLS, the server also verifies the device certificate.
7.3.2 3.2. Ordinary TLS and mTLS
Ordinary TLS:
ESP32 → ClientHello + SNI → Broker
ESP32 ← server certificate chain ← Broker
ESP32 verifies CA, hostname, timemTLS:
the device verifies the server certificate
the server verifies the device client certificate7.3.3 3.3. Certificate chain
Root CA
└── Intermediate CA
└── mqtt.example.comThe device usually stores a Root CA or a limited CA set rather than the broker’s leaf certificate.
7.3.4 3.4. CA bundle or a private CA
A CA bundle is convenient for public endpoints but trusts many CAs and consumes Flash. A private CA narrows the trust boundary but requires a protected CA private key and issuance, rotation, and revocation procedures.
7.3.5 3.5. Hostname verification and SNI
CA verification asks:
was the certificate signed by a trusted CA?Hostname verification asks:
was the certificate issued specifically for mqtt.example.com?Do not disable hostname verification in production.
7.3.6 3.6. TLS depends on time
X.509 certificates have Not Before and Not After. Therefore the device needs sufficiently plausible UTC. Bootstrap strategy:
1. Load last-known-good UTC from RTC/NVS.
2. Do not reduce it below the last confirmed value.
3. Use EC25 network time only as a hint.
4. Check a reasonable year/range.
5. Establish TLS.
6. Obtain more reliable synchronization.
7. Update last-known-good time.7.3.7 3.7. Where TLS terminates: ESP32 or EC25
TLS on ESP32 through PPPoS:
EC25 → PPP → lwIP → ESP-TLS/Mbed TLS → MQTT/HTTPSAdvantages: one TLS stack, better diagnostics, a single CA store, and less dependence on AT firmware. Disadvantages: ESP32 RAM/CPU use and UART PPP load. TLS inside EC25:
ESP32 → AT commands → EC25 TLS/MQTT stack → brokerAdvantages: the modem performs TLS computation and uses less ESP32 heap. Disadvantages: more complex certificate management, diagnostics, and rotation, plus dependence on modem firmware.
7.3.8 3.8. Certificate lifecycle
typedef enum {
CERT_STATE_EMPTY = 0,
CERT_STATE_STAGED,
CERT_STATE_ACTIVE,
CERT_STATE_RENEWAL_REQUIRED,
CERT_STATE_REVOKED,
CERT_STATE_EXPIRED,
} certificate_state_t;
typedef struct {
uint32_t generation;
certificate_state_t state;
int64_t not_before_utc;
int64_t not_after_utc;
uint8_t fingerprint_sha256[32];
uint32_t connect_success_count;
uint32_t connect_fail_count;
} certificate_status_t;7.3.9 3.9. CA rotation
Safe:
CA_OLD
→ firmware trusts CA_OLD + CA_NEW
→ the server switches to CA_NEW
→ the fleet confirms connection
→ remove CA_OLD laterDangerous:
the server switched to CA_NEW
→ old devices know only CA_OLD
→ the fleet is offline7.3.10 3.10. TLS diagnostics
typedef enum {
TLS_STAGE_NONE = 0,
TLS_STAGE_DNS,
TLS_STAGE_TCP_CONNECT,
TLS_STAGE_CLIENT_HELLO,
TLS_STAGE_CERT_VERIFY,
TLS_STAGE_CLIENT_AUTH,
TLS_STAGE_ESTABLISHED,
} tls_stage_t;
typedef struct {
tls_stage_t last_stage;
int32_t last_tls_error;
int32_t last_verify_flags;
uint32_t handshake_ok;
uint32_t handshake_failed;
uint32_t hostname_failed;
uint32_t time_failed;
uint32_t client_auth_failed;
uint32_t max_handshake_ms;
uint32_t min_free_heap_during_handshake;
uint32_t certificate_generation;
} tls_diag_t;4. Common mistakes
1. Disabling server verification.
2. Checking CA but disabling hostname.
3. One client certificate for the entire fleet.
4. No time available before TLS.
5. Permanently embedding the server leaf certificate.
6. Switching server CA before device OTA.
7. Storing a private key in Git.
8. Printing PEM/DER in a debug log.
9. Ignoring certificate-buffer lifetime.
10. Confusing TLS termination: ESP32 and EC25 simultaneously.
11. Not measuring peak heap during TLS handshake.5. Practical assignment for 30-60 minutes
Create TLS_PKI_POLICY.md:
# TLS / PKI policy
1. All external MQTT and OTA connections use TLS.
2. Server certificate and hostname are always verified.
3. Insecure verification is forbidden in production.
4. Each device has a unique identity.
5. Private keys are never stored in Git or logs.
6. UTC quality is checked before certificate validation.
7. CA rotation uses an old+new overlap window.
8. Client certificate rotation is transactional.
9. TLS errors are classified, not retried blindly.
10. Certificate expiry is monitored before deployment.Inventory endpoints:
| Endpoint | Protocol | Authentication | Trust source |
|---|---|---|---|
| mqtt.example.com | MQTT/TLS | mTLS | private CA |
| ota.example.com | HTTPS | server TLS | CA bundle |
| api.example.com | HTTPS | token + TLS | CA bundle |Add a tls probe CLI that checks DNS/TCP/TLS/hostname/time/heap without sending application secrets.
6. Further reading
- ESP-TLS, X.509 Certificate Bundle, and ESP-MQTT TLS examples.
- Quectel EC25 SSL/MQTT/HTTP(S) application notes.
- STM32 Mbed TLS integration and STSAFE.
Brief recap
external endpoint
→ DNS
→ TCP
→ TLS handshake
→ CA chain verification
→ hostname/SNI verification
→ optional client certificate
→ encrypted MQTT/HTTPS
→ monitored certificate lifecycleExercise
A server certificate chains to a trusted CA but belongs to a different hostname. State the required connection decision and the diagnostic information that may be logged safely.
Self-check criteria: Keep hostname verification enabled and distinguish authentication failure from TCP or DNS failure.
Show the supplied answer
Reject the connection because CA trust does not establish the intended hostname. Record a bounded verification category, endpoint identity, time quality, and handshake status without logging private keys, PEM/DER material, or application secrets.
Exercise
Plan a CA_OLD to CA_NEW migration for devices that may remain offline during deployment. Define the ordering that preserves an authenticated update path.
Self-check criteria: Describe evidence at each stage and the offline-device recovery path; never solve rotation by disabling verification.
Show the supplied answer
First deploy firmware that trusts both CA_OLD and CA_NEW and verify device adoption. Then switch the server to CA_NEW and monitor connections; remove CA_OLD only later through a controlled policy after accounting for devices that missed the transition.