TLS on a microcontroller: footprint, handshake cost and certificate lifecycle
Putting TLS into a connected device is not a cryptographic problem: the algorithms are the same as on a server. The problems are memory footprint, handshake time on an 80 MHz core, and above all what happens when a certificate expires on ten thousand devices already installed.
Footprint, item by item
A complete TLS stack is not just a library. Four items add up.
| Item | Typical flash |
|---|---|
| TLS stack, TLS 1.3, one ECC suite | 30 to 50 KB |
| Software crypto primitives | 15 to 30 KB |
| Root certificate store | 1 to 2 KB per certificate |
| Session buffers, per connection | 4 to 16 KB of RAM |
The item that catches people out is the last one. TLS requires a buffer able to hold a full record, up to 16 KB. On a microcontroller with 64 KB of RAM, a single connection can eat a quarter of memory. The max_fragment_length extension, or record_size_limit in TLS 1.3, brings that down to 512 or 1,024 bytes, provided the server accepts it. That is the first setting to make, before any other optimisation.
Actually reducing the footprint
One cipher suite only. Compiling the stack with a single suite removes everything else. TLS_AES_128_GCM_SHA256 with ECDHE and ECDSA P-256 certificates is a sound, compact choice.
Drop RSA. A 2048-bit RSA key costs more flash, more RAM and far more compute time than an ECDSA P-256 key for equivalent security. The handshake difference is a factor of five to ten on a Cortex-M.
TLS 1.3 rather than 1.2. Fewer round trips, fewer suites to handle, and removing obsolete modes shrinks both the code and the attack surface.
One root certificate. Embedding a public root store is a common mistake: it costs tens of kilobytes and extends trust to hundreds of authorities you do not need. A device talking to your server only needs your authority.
The cost of a handshake
This is the most underestimated part. Orders of magnitude on an 80 MHz Cortex-M4 with no hardware acceleration:
| Operation | Time |
|---|---|
| ECDHE P-256 key exchange | 200 to 500 ms |
| ECDSA P-256 signature verification | 100 to 250 ms |
| RSA 2048 signature | 1 to 3 s |
| AES-GCM encryption, 1 KB | under one millisecond |
The figures in this section are observed orders of magnitude, not specifications. They depend on silicon, compiler and configuration. Measure your own before sizing a product on them.
A full handshake therefore typically takes half a second to two seconds. On a battery device that wakes to send one measurement, that cost dominates the transmission itself, and it is paid in battery life.
Two levers change the scale. The hardware accelerator present on many recent microcontrollers divides these times by five to fifty; the TLS stack still has to be configured to use it, which is never automatic. And session resumption, with TLS 1.3 tickets, removes asymmetric cryptography from subsequent connections: a few milliseconds instead of several hundred.
For a device that connects periodically to the same server, session resumption is the first battery-life lever, ahead even of the choice of modem.
Chain validation, where implementations cheat
A successful handshake proves nothing if validation is incomplete. Four checks are mandatory, and it is common to find one or two disabled in production.
The signature chain must reach a trusted root. The validity period must be respected, which requires a correct clock. The host name must match the appropriate certificate field, otherwise any valid certificate is accepted. And revocation must be checked.
The date check raises a genuine embedded problem: with no backed-up clock, a device that boots believes it is 1970 and rejects every certificate, or worse, accepts it because the check was disabled for exactly that reason. The correct answer is to synchronise time before the first TLS connection, over a channel whose security does not depend on TLS, then refuse to operate until the time is plausible.
Revocation is rarely practical on embedded devices: lists are too large and OCSP adds a network dependency. The alternative is OCSP stapling, where the server supplies proof of non-revocation itself, at no cost to the client.
Renewal, the real trap
Certificates expire. That is certain, and it is what takes whole fleets offline.
Three decisions to make before production. The client certificate lifetime, which must be consistent with the product lifetime: a two-year certificate on a device that will live ten years demands a working renewal mechanism. Automatic renewal, which must be tested, including its failure path. And your certificate authority's own expiry: if it expires, the whole fleet drops on the same day.
The safest practice is to embed a very long-lived root authority, twenty to thirty years, use it only to sign intermediate authorities, and renew device certificates through an automated protocol.
References
- IETF, RFC 8446, TLS 1.3, session resumption and tickets
- IETF, RFC 8449, Record Size Limit, successor to
max_fragment_length - IETF, RFC 6066, TLS extensions including
max_fragment_length - IETF, RFC 6960 and RFC 6961, OCSP and stapling
- wolfSSL manual, build options and hardware acceleration
Going further
These trade-offs become concrete once you have measured a handshake on target, enabled a hardware accelerator and seen the gain, then simulated a certificate expiry to observe what the device really does. That is what our wolfSSL embedded security courses cover.