HTC Desire Z browsers: what still loads HTTPS on Android 2.3

This was going to be a browser review. The research gave me five candidates for Android 2.3 and a column for how each one does HTTPS. One of the five ever ran on the phone, not in the version at the top of the list, and the most thorough part of the exercise turned out to be reading release notes. I have reviewed worse things more favourably.

The phone is an HTC Desire Z, a 2010 slider with a hardware keyboard, running CyanogenMod 7, which is Android 2.3 with an older web stack than any site I visit expects. The question for this part is narrow: which browsers on that phone can still open a modern HTTPS site, and why those and not the others. The answer has nothing to do with rendering. It is decided by where the TLS handshake happens.

The ceiling: TLS 1.0 and a root store that stopped#

Android 2.3 is API level 10. Android's own SSLSocket reference lists TLS 1.1 and 1.2 as supported from API 16 and enabled by default for client sockets from API 20. Below that, the platform offers SSLv3 and TLS 1.0, and the IETF formally deprecated TLS 1.0 and 1.1 in RFC 8996 in March 2021. Anything that uses the phone's own TLS stack is asking modern servers to speak a protocol they have been told to retire.

The certificates are a second problem on top of the first. Let's Encrypt's DST Root CA X3 cross-sign, the thing that let old devices trust its certificates, expired on September 30, 2021. Let's Encrypt's own page on the expiry names its examples of devices that will never trust the replacement root because they no longer get updates: "an iPhone 4 or an HTC Dream". The Dream is HTC's first Android phone. The Desire Z did not need to be named.

The shortlist, sorted by where TLS happens#

I sorted the candidates by the one property that matters here:

  • Wrappers around the system WebView (Via Browser and similar): they inherit the platform's TLS, so they inherit the ceiling.
  • Browsers that bring their own TLS (Firefox): the platform is never asked.
  • Proxy browsers (Opera Mini, UC Browser): the phone talks to the vendor's servers, and the servers talk to the site.
  • Cloud rendering (Puffin): the page is rendered on a server and streamed to the phone.

The wrappers are out before they start. That leaves three ways of not needing Android 2.3's TLS stack, and each one has its own catch.

Firefox 47: the right protocol, the wrong year#

Firefox 47.0 for Android shipped on June 7, 2016, and its release notes say it plainly: "Last release to support Android 2.3.x (Gingerbread)". Firefox 48's notes say goodbye with more feeling: "Support for Android 2.3 (Gingerbread) has ended. Farewell!" Mozilla's archive still keeps the build: /pub/mobile/releases/47.0/ has an android-api-9 directory, and 48.0 does not. The ARM APK in it, fennec-47.0.multi.android-arm.apk, is 36,530,195 bytes.

The TLS side is fine. Firefox does its TLS with Mozilla's own NSS library rather than Android's, and Firefox for Android 27's release notes list "Enabled TLS 1.1 (RFC 4346) and TLS 1.2 (RFC 5246) by default". Twenty releases later, Firefox 47 negotiates TLS 1.2 without asking the phone for anything.

The certificates are where it falls apart. Firefox also carries its own root store, and Let's Encrypt's compatibility list says Firefox trusts ISRG Root X1, the root its certificates now chain to, from version 50.0. Firefox 47 predates that by three releases, and the old cross-sign it would have leaned on expired in 2021. You brought your own TLS stack, Firefox, which is admirable. You also brought your own root store, packed in 2016, and it is missing the one root Let's Encrypt sites now need. For those sites, a modern handshake ends at an untrusted certificate.

I never installed it. That paragraph is the reading of three pages of release notes and one compatibility table, not a test, and I would rather say so than pretend 36 MB went onto the phone.

Opera Mini: the handshake happens somewhere else#

The shortlist's favourite was Opera Mini 20.0.2254.110284. APKMirror lists it as armeabi, Android 2.3+, dated November 21, 2016. The copy I tried to download from archive.org arrived as a 142.8 KB file, which is not what a browser APK of that generation weighs. I did not open it to find out what it was. I installed Opera Mini 7.6.4 instead, an older build from archive.org with sdkVersion:'3', and it loaded this blog over HTTPS with a padlock in the title bar; that night is in the launcher post.

It works because the phone never negotiates TLS with the site. Opera Mini sends its requests to Opera's compression proxy, which fetches the page, compresses it and sends it to the phone in Opera's own binary markup format, OBML. On an encrypted page in its compressing Extreme/Mini mode, Opera's servers decrypt the page, compress it, re-encrypt it and forward it. The site sees a modern client in one of Opera's data centres. The phone only has to reach Opera.

The cost is in that sentence. In that mode Opera's servers see the decrypted page, so it is not end-to-end encryption, and anything I would not hand to a third party does not go through it. The body of my blog page also stayed blank white under the title bar, and I did not chase why. For reading, it is the browser that works.

UC Browser and Puffin: crossed off#

UC Browser also uses a proxy design and also has builds for Android 2.3. I crossed it off without installing it. In May 2015, Citizen Lab reported that UC Browser sent user data, including the IMSI, IMEI, Android ID and Wi-Fi MAC address, without encryption to Umeng, an Alibaba analytics tool, in the Chinese-language version, and sent geolocation through Alibaba's AMAP without encryption as well. A browser whose job here would be to carry my HTTPS traffic does not get the job after that report.

Puffin renders pages on its own servers and streams the result. I crossed it off without testing it too, and I have nothing measured to say about it, so I will not say more.

Why two designs survived#

Neither survivor was built for Gingerbread. Firefox brings NSS because Firefox always brings NSS; it never relied on the platform's TLS stack in the first place. Opera Mini proxies because it was built as a proxy browser for phones on slow mobile networks long before TLS 1.0 was a problem. Both decisions predate Android 2.3, and both happen to route around exactly the part of it that aged worst.

The browsers that trusted the platform were making the reasonable bet, and on this phone the reasonable bet lost. The final score of my browser review: one browser installed, chosen because the favourite would not download, loading one page with a blank body. It passed. On Android 2.3 the bar is a padlock in the title bar, and I have learned not to ask for more from a phone that shipped six years before the root certificate it would need reached anyone's trust store.

Filed under: android, machines, networking, tls

Sources#