ADR-0002: TLS and crypto provider

Status

Accepted

Area

Networking / security

Context

The app talks TLS to several LAN devices, and the choice of crypto provider and TLS version support has real consequences for portability and interoperability.

  • The crypto provider must stay off aws-lc-rs, which needs a C toolchain and hurts the future Android build.

  • Pulling in reqwest with a TLS feature would install a second, possibly aws-lc-rs, crypto provider. Roku ECP is plain HTTP, so no TLS is needed there.

  • On-device testing against a 2016 Samsung UE55KU6179 revealed that default-features = false silently drops TLS 1.2, so rustls offered 1.3-only. That TV — like many pre-2018 sets — speaks only TLS 1.2 and rejected every ClientHello with a HandshakeFailure alert. The mocks missed it because both sides used 1.3.

  • Samsung and LG ship per-device self-signed certs with no CA and no stable hostname. The threat model is a LAN link to a device the user physically owns, so cert pinning buys nothing here.

Decision

  • Crypto provider: rustls ring, installed explicitly per-config via builder_with_provider, never relying on a process-default provider.

  • reqwest is built with no TLS feature at all, avoiding a second crypto provider.

  • The rustls tls12 feature is REQUIRED, and kept on for both rustls and tokio-rustls.

  • Self-signed cert acceptance is a dedicated AcceptAnyServerCert verifier in tls.rs, used only by the Samsung and LG WS connectors. The verifier is loudly commented and scoped to those two connectors.

Consequences

  • Staying on ring keeps us off aws-lc-rs and its C-toolchain dependency, protecting the future Android build.

  • Building reqwest with no TLS feature prevents a duplicate, possibly aws-lc-rs, crypto provider from being installed.

  • Keeping tls12 on restores interoperability with pre-2018 sets like the 2016 Samsung UE55KU6179 that speak only TLS 1.2.

  • Lesson logged: mock parity != real hardware. Both mock sides used TLS 1.3 and so missed the 1.2-only handshake failure that only appeared on real hardware.

  • Accepting self-signed certs via a narrowly scoped AcceptAnyServerCert verifier matches the LAN threat model without pretending cert pinning adds value for physically-owned devices.