The TLS Extension Cloud Providers Keep Ignoring (and Embedded IoT Pays the Price)

IoT

6 mins read

The TLS Extension Cloud Providers Keep Ignoring (and Embedded IoT Pays the Price)

When building IoT products, we often assume the cloud is “just there,” ready to handle whatever our devices throw at it. But if we’re targeting MCUs with few hundred kilobytes of ram (~256kB, 512kB) the reality is harsher: the cloud isn’t fully ready for us.

 

This became crystal clear to me while working on TLS with an ESP32-WROOM-32E using mbedTLS. What looked like a small optimization challenge turned into a fundamental mismatch between embedded constraints and cloud defaults.

 

TLS Buffers: The Hidden Cost

 

TLS is expensive in RAM. On the ESP32:

  • mbedTLS allocates 16 kB input + 16 kB output buffers which means that 32 kB are gone instantly.
  • Add a bit more extra for intermediate allocations and we end up with 40kB of RAM just to open a TLS connection.

 

When we’re juggling Wi-Fi stacks, app logic, and peripherals, that cost is painful.

I tried reducing the buffer sizes to 4 kB for both input and output buffers and it almost worked.. Until real cloud traffic arrived.

 

The Real Problem: Servers Don’t Negotiate Down

 

TLS includes an extension called Maximum Fragment Length (MFL) (RFC 6066). It lets a constrained device say:

“Hey server, please don’t send us TLS records bigger than 4096 bytes.”

 

If honored, this lets a device shrink its input buffer safely.

The catch? Most big cloud providers ignore it.

 

  • AWS IoT Core always sends up to 16 kB TLS records.
  • Azure IoT Hub has preview support for MFL, but it’s not generally available in SDKs yet.
  • Google Cloud IoT Core (shut down in 2023) never supported it either.

That means: even if our MCU asks nicely for 4kB chunks, the server still blasts it with 16kB records. If our buffer can’t hold them, we die with the dreaded -0x7200 MBEDTLS_ERR_SSL_INVALID_RECORD error code.

 

Why the Error Happens (-0x7200)

 

TLS sends data in records:

 

  • Record header says “N bytes follow.”
  • Sender encrypts exactly N bytes of payload plus calculates and appends a Message Authentication Code (MAC) for it in the record header.
  • Receiver must buffer the entire record before verifying.

 

If the server sends a 10kB record and our buffer is only 8kB, we lose! The TLS layer throws a -0x7200 MBEDTLS_ERR_SSL_INVALID_RECORD error at us! This error isn’t caused by packets being corrupted by some noise in the communication stack; it almost always means the client’s TLS buffer is too small to hold the incoming record, so payloads MAC verification fails!

 

This can happen at any time during the TLS connection or it can also happen during the TLS connection establishment if the certificate chains or key-exchange messages exceed the size of the client’s incoming buffer (in my case, 4kB).

 

Provider Positions on MFL Extension

 

Here’s what the docs (and reality) say:

  • AWS IoT Core
    No mention of MFL support. Device Advisor even tests whether your device can handle maximum-size TLS fragments, implying full 16 kB is expected.
    AWS IoT Device Advisor – TLS Receive Maximum Size Fragments
  • Azure IoT Hub
    Preview feature for MFL support, but not mainstream yet.
    Microsoft Q&A: TLS Maximum Fragment Length Negotiation
  • Google Cloud IoT Core
    Service discontinued (2023). No evidence it ever supported MFL.
  • Other TLS providers
    • BoringSSL: does not implement MFL.
    • openSSL/ mbedTLS / wolfSSL: do implement MFL, so we can use it if we control both ends.

 

How this impacted the File download speeds in my IoT Solution

 

At one point, my team and I tried to speed up file downloads from AWS Content Delivery Networks (CDNs). The idea was simple: instead of issuing repeated requests with Range headers for each segment of a file, we could just open a single HTTPS connection and accept the data as it streams. This reduces overhead, improves throughput, and lets the device process data incrementally. For this, we used chunked transfer encoding in HTTP/1.1.

 

The flow control of such a stream is handled entirely by TCP. TCP ensures reliable, ordered delivery and applies backpressure so the sender never overwhelms the receiver. HTTP chunking just provides application-level framing, while TLS encrypts the byte stream into records.

 

Unfortunately, chunked transfer encoding still rides on top of TLS records. The CDN server encrypted and sent chunks inside full 16 kB TLS records. Since our device couldn’t increase the TLS input buffer beyond 8kB (due to memory constraints), we ended up in the same situation: the server would push a 16kB record, and mbedTLS would fail with: -0x7200 MBEDTLS_ERR_SSL_INVALID_RECORD

 

In the end, we had to fall back to using repeated requests with Range headers to fetch smaller file segments safely, even though this added extra overhead and reduced efficiency compared to streaming.

 

A Note on Google’s Optimization

 

Interestingly, Google once tackled a related problem when streaming media. They implemented dynamic TLS record sizing:

 

  • Start with small records (~2 kB) to minimize latency for the first chunks of audio/video.
  • Gradually increase record size to 16 kB for efficiency during long transfers.

 

This hybrid approach improved user experience without sacrificing throughput. More details can be found here: Optimizing TLS Record Size and Buffering Latency.

 

Lessons Learned

 

  • Big Cloud Providers ≠ TLS MCU-friendly. Servers assume 16 kB TLS records are fine.
  • MFL negotiation exists but is ignored. Don’t rely on it unless you control the server and TLS stack.
  • Error -0x7200 MBEDTLS_ERR_SSL_INVALID_RECORD is not the network noise — it’s just an oversized TLS record.
  • Design choices matter. For RAM memory constrained MCUs:
    • Add RAM / pick a bigger chip.
    • Use a proxy/gateway that enforces smaller TLS records.
    • Or run your own service with openSSL/mbedTLS/wolfSSL server side.

 

Final Thoughts

 

Large cloud providers are “ready” for IoT in case your devices have 40kB to spare for one TLS connection. If not, the lack of TLS MFL Extension support makes life harder than it needs to be.

 

Until cloud providers adopt this extension, embedded engineers will keep fighting buffer mismatches or be forced to overprovision hardware. In a world chasing ultra-low-cost, ultra-low-power IoT, that feels like a gap worth closing.

OUR NEWSLETTER

With us, anyone can achieve their business goals.