ESP32/Living on a network/48. HTTPS and certificates
Your chip
Your language
Living on a network · 48 of 81

HTTPS and certificates

TLS on a microcontroller works, and it fails in two ways that do not look like certificate problems - a handshake that cannot find enough contiguous heap, and a root certificate that expires on a date you chose years earlier.

/esp32/https-and-certificates · arduino · S3

The two real failures

RSA-2048 handshake
connects
Free heap at connect time90 kB
Years the device has been out there2 yr
Handshake needs
42 kB
Result
connected
Bytes on the wire
4 kB
Connected, with 48 kB to spare. Do not reach for setInsecure() to make a problem go away: it turns off the verification that is the entire point, and a device that accepts any certificate will happily send its readings to whoever is nearest.

What a certificate on the board is for

The board is checking that the server is who it claims to be. That check needs a root certificate — the one that signed the server's certificate — compiled into the firmware, because the board has no operating system certificate store.

Pin the root, not the server's own certificate. Servers rotate theirs every few months; roots last a decade. Pinning the leaf means an outage each renewal.

Prefer EC over RSA

An ECDSA P-256 root costs roughly half the memory and half the traffic of RSA-2048 for the same security. On a chip where the handshake is the largest allocation the firmware ever makes, that is the difference between working and not.

Sync the clock first

Certificate validity is a date range. A board that boots at 1 January 1970 will reject every valid certificate it is shown. NTP before TLS, always.

On your S3
ChipXtensa LX7 · 2 × 240 MHz
Board settingESP32S3 Dev Module
Default I2CSDA 8 · SCL 9
Watch out forThe port vanishes after upload

The code

A root certificate in the sketch, a client that verifies against it, and the connection closed when it is done. setInsecure is the line to never write in something that leaves your desk.

https_get.ino
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>

// ISRG Root X1 - abbreviated. Paste the whole PEM in real code.
const char *ROOT_CA = R"(-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
...
-----END CERTIFICATE-----)";

void setup() {
  Serial.begin(115200);
  WiFi.begin("your-network", "your-password");
  while (WiFi.status() != WL_CONNECTED) delay(250);

  Serial.printf("largest free block %u\n",
                heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));

  WiFiClientSecure client;
  client.setCACert(ROOT_CA);          // never setInsecure() in production

  HTTPClient http;
  if (http.begin(client, "https://example.com/api/readings")) {
    int code = http.POST("{\"temp\":21.4}");
    Serial.printf("HTTP %d\n", code);
    http.end();                        // free the TLS buffers now
  }
}

void loop() {}

Only the root is pinned here, not the server's own certificate. That survives the server rotating its certificate every 90 days, which pinning the leaf does not.

When it does not work

The connection fails and the certificate is definitely right

Out of memory. The handshake needs tens of kilobytes in one contiguous block. Open the connection before allocating display or camera buffers, and close it afterwards.

It worked for two years and stopped on a Tuesday

The root certificate expired. Nothing changed on the device - the date passed. This is why HTTPS and OTA belong together, and why bundling two roots is worth the flash.

Certificate verify failed and the clock is at 1970

Verification checks the date. Sync NTP before the first HTTPS connection or every certificate looks not yet valid.

setInsecure fixed it

It did not fix it, it switched off the check. The connection is still encrypted and now anybody who can answer that hostname is trusted, which is most of the point gone.

Where this goes next

All of this assumed a radio. The next page is what to do when the board lives in a metal cabinet.

Ethernet instead of Wi-Fi

Edit this page — content/esp32/https-and-certificates.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32 on the forum