+++ title = "The device trusts the two ISRG roots for what it fetches" description = "The firmware talks to the project's Gitea over HTTPS (issue #6, and #4 after it). A TLS client has to decide whose certificates it believes. Three ways were possible:" weight = 9 [extra] docs = true source = "docs/adr/0009-the-device-trusts-the-isrg-roots.md" tag = "ADR 0009" +++ The firmware talks to the project's Gitea over HTTPS (issue #6, and #4 after it). A TLS client has to decide whose certificates it believes. Three ways were possible: - **The framework's bundle**, about 130 certificate authorities (about 60 KB of flash). Any of them could vouch for `git.twis.la`. - **Pin the server's certificate**, as the Gemini App does for capsules. The server's certificate is replaced every few months, so a pin would ask the question again at every renewal. - **Carry the roots the server's chain ends in:** `ISRG Root X1` (RSA 4096) and `ISRG Root X2` (ECDSA P-384), the Let's Encrypt roots, about 2.7 KB of flash (`src/platform/ca_roots.h`). We chose the third. The chain and the name are checked by mbedTLS during the handshake. It trusts one organisation's two roots, valid until 2035 and 2040, and a renewal changes nothing. ## What it costs - **If the server moves to another CA, the device can no longer reach it**, and the next firmware, carrying that CA's root, has to come from the PC or the SD card. Both still work; they don't use TLS. - The roots are public data checked against the published fingerprints (listed in the file), refreshed by hand if Let's Encrypt ever changes them. ## What it doesn't change The Update File's own signature (ADR 0003) is what decides what gets installed. A hijacked connection could hide a release, or serve an older signed one, but never make the device install firmware that isn't ours. The TLS check matters more for #4, where a token will travel over it. ## Measured while building it A TLS connection to this server peaks at about 52 KB of heap, **the same whether the certificate is checked or not**, so skipping the check would have saved nothing. The cost is the connection itself (record buffers and handshake), not the trust decision.