<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Upki on Jon Seager</title><link>https://jnsgr.uk/tags/upki/</link><description>Recent content in Upki on Jon Seager</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Mon, 16 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://jnsgr.uk/tags/upki/index.xml" rel="self" type="application/rss+xml"/><item><title>An update on upki</title><link>https://jnsgr.uk/2026/02/upki-update/</link><pubDate>Mon, 16 Feb 2026 00:00:00 +0000</pubDate><guid>https://jnsgr.uk/2026/02/upki-update/</guid><description>&lt;blockquote&gt;
&lt;p&gt;This article was originally posted &lt;a href="https://discourse.ubuntu.com/t/an-update-on-upki/77063" target="_blank" rel="noreferrer"&gt;on the Ubuntu Discourse&lt;/a&gt;, and is reposted here. I welcome comments and further discussion in that thread.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Last year, I &lt;a href="https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/" target="_blank" rel="noreferrer"&gt;announced&lt;/a&gt; that Canonical had begun supporting the development of &lt;a href="https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/" target="_blank" rel="noreferrer"&gt;upki&lt;/a&gt;, a project that will bring browser-grade Public Key Infrastructure (PKI) to Linux. Since then, development has been moving at pace thanks to the tireless work of &lt;a href="https://dirkjan.ochtman.nl/" target="_blank" rel="noreferrer"&gt;Dirkjan&lt;/a&gt; and &lt;a href="https://jbp.io/" target="_blank" rel="noreferrer"&gt;Joe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this post, I’ll explore the progress we’ve made, how you can try an early version, and where we’re going next.&lt;/p&gt;
&lt;h3 id="architecture--progress" class="relative group"&gt;Architecture &amp;amp; Progress &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#architecture--progress" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;As a reminder, upki’s primary goal is to provide a reliable, privacy-preserving, and efficient certificate revocation mechanism for Linux system utilities, package managers, and language runtimes. The solution is built around &lt;a href="https://blog.mozilla.org/security/2020/01/09/crlite-part-1-all-web-pki-revocations-compressed/" target="_blank" rel="noreferrer"&gt;CRLite&lt;/a&gt;, an efficient data format that compresses and distributes certificate revocation information at scale.&lt;/p&gt;
&lt;p&gt;The upki &lt;a href="https://github.com/rustls/upki" target="_blank" rel="noreferrer"&gt;repository&lt;/a&gt; is structured as a Cargo workspace containing five crates, each serving a distinct role:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;upki&lt;/code&gt;&lt;/strong&gt;: the core library and CLI tool. This crate contains the revocation query engine, the client-side sync logic for fetching filter updates, and the command-line interface. The revocation interface was originally embedded in the CLI, but has since been promoted into the library so that other Rust projects can use it directly as a dependency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;upki-mirror&lt;/code&gt;&lt;/strong&gt;: the server-side mirroring tool. This binary fetches and validates CRLite filters from Mozilla&amp;rsquo;s infrastructure such that they can be served using a standard web server like &lt;code&gt;nginx&lt;/code&gt; or &lt;code&gt;apache&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;upki-ffi&lt;/code&gt;&lt;/strong&gt;: the C Foreign Function Interface. Built as a &lt;code&gt;cdylib&lt;/code&gt;, this crate uses &lt;a href="https://github.com/mozilla/cbindgen" target="_blank" rel="noreferrer"&gt;&lt;code&gt;cbindgen&lt;/code&gt;&lt;/a&gt; to auto-generate a &lt;code&gt;upki.h&lt;/code&gt; header file, exposing the revocation query API to C, C++, Go and any other language with C FFI support.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;rustls-upki&lt;/code&gt;&lt;/strong&gt;: an integration crate that wires upki&amp;rsquo;s revocation engine into &lt;a href="https://github.com/rustls/rustls" target="_blank" rel="noreferrer"&gt;rustls&lt;/a&gt;, enabling any Rust application using rustls to perform CRLite-backed revocation checks transparently.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;revoke-test&lt;/code&gt;&lt;/strong&gt;: testing infrastructure for validating revocation queries against known-revoked certificates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The team recently released &lt;a href="https://github.com/rustls/upki/releases/tag/upki-0.1.0" target="_blank" rel="noreferrer"&gt;v0.1.0&lt;/a&gt;, which should help us to gather more feedback on the work we&amp;rsquo;ve done so far.&lt;/p&gt;
&lt;h3 id="how-to-try-it" class="relative group"&gt;How to try it &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#how-to-try-it" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;If you&amp;rsquo;d like to try the code in its current form, you&amp;rsquo;ll need to have a version of the Rust toolchain installed. The easiest way to do this on Ubuntu is &lt;a href="https://documentation.ubuntu.com/ubuntu-for-developers/howto/rust-setup/#installing-the-latest-rust-toolchain-using-rustup" target="_blank" rel="noreferrer"&gt;using the &lt;code&gt;rustup&lt;/code&gt; snap&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ensure you have a C compiler in your PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y build-essential curl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Install the rustup snap and get the stable toolchain&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo snap install --classic rustup
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rustup install stable
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Install upki&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cargo install upki
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.cargo/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Fetch revocation data. This will be done in the background&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# when installed through the distro in the future&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;upki fetch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;That should be all you need to install the development version of &lt;code&gt;upki&lt;/code&gt;, and you can now use it to run a revocation check by piping certificate output from &lt;code&gt;curl&lt;/code&gt; into &lt;code&gt;upki&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -sw &lt;span class="s1"&gt;&amp;#39;%{certs}&amp;#39;&lt;/span&gt; https://google.com &lt;span class="p"&gt;|&lt;/span&gt; upki revocation check
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NotRevoked
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Early versions of docs for the &lt;a href="https://docs.rs/upki-ffi/latest/upki/" target="_blank" rel="noreferrer"&gt;C FFI crate&lt;/a&gt; and &lt;a href="https://docs.rs/upki/latest/upki/" target="_blank" rel="noreferrer"&gt;Rust crate documentation&lt;/a&gt; are available, but if you&amp;rsquo;d like to explore, build the project from source, or contribute, the &lt;a href="https://github.com/rustls/upki" target="_blank" rel="noreferrer"&gt;repository&lt;/a&gt; is the best place to start. For an example of the C FFI interface in action you can take a look at the &lt;a href="https://github.com/rustls/upki-go-demo" target="_blank" rel="noreferrer"&gt;upki-go-demo&lt;/a&gt; Dirkjan published.&lt;/p&gt;
&lt;h3 id="next-steps" class="relative group"&gt;Next Steps &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#next-steps" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Now the foundational pieces are in place, our focus is shifting to external consumption, performance, and integration with the wider Linux ecosystem. In the coming days there should be an early &lt;code&gt;0.1.0&lt;/code&gt; binary release.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll also be doing some performance benchmarking on the initial fetch and of the revocation checks themselves. Currently, each revocation check reads several CRLite filter files into memory. There may be quick wins to improve this, but we’ll benchmark first and see if it warrants optimisation at this time.&lt;/p&gt;
&lt;p&gt;We also need to deploy some production infrastructure for serving the CRLite filters. If you follow the steps above, you&amp;rsquo;ll be fetching from a pre-production web server hosted at &lt;a href="https://upki.rustls.dev" target="_blank" rel="noreferrer"&gt;https://upki.rustls.dev&lt;/a&gt;. We&amp;rsquo;ve built a &lt;a href="https://github.com/jnsgruk/upki-mirror-k8s-operator" target="_blank" rel="noreferrer"&gt;Juju charm&lt;/a&gt; for operating the CRLite mirror on Kubernetes. This charm packages the &lt;code&gt;upki-mirror&lt;/code&gt; binary in a &lt;a href="https://ubuntu.com/blog/combining-distroless-and-ubuntu-chiselled-containers" target="_blank" rel="noreferrer"&gt;chiselled Rock&lt;/a&gt;, and will be deployed into Canonical&amp;rsquo;s datacentres to serve CRLite data at &lt;a href="https://crlite.ubuntu.com/" target="_blank" rel="noreferrer"&gt;crlite.ubuntu.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Our Ubuntu Foundations team is also working on packaging the various upki components for inclusion in the Ubuntu archive, which will enable you to &lt;code&gt;apt install upki&lt;/code&gt; in the future, and also enable us to package and enable it by default in Ubuntu 26.10 and beyond.&lt;/p&gt;
&lt;h3 id="further-down-the-road" class="relative group"&gt;Further Down the Road &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#further-down-the-road" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;While the work above covers what&amp;rsquo;s immediately in front of us, there is scope to expand upki&amp;rsquo;s capabilities further. Two areas of interest are Certificate Transparency enforcement, and support for Merkle Tree Certificates.&lt;/p&gt;
&lt;h4 id="certificate-transparency-enforcement" class="relative group"&gt;Certificate Transparency Enforcement &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#certificate-transparency-enforcement" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h4&gt;&lt;p&gt;While upki&amp;rsquo;s initial focus is on revocation checking, the project also aims to eventually support &lt;a href="https://certificate.transparency.dev/" target="_blank" rel="noreferrer"&gt;Certificate Transparency&lt;/a&gt; (CT) enforcement. CT is a more modern security measure that relies upon a set of publicly auditable, append-only logs that record every TLS certificate issued by a Certificate Authority (CA). This prevents CAs from issuing fraudulent or erroneous certificates without a means for that fraudulent activity to be discovered - a problem that has &lt;a href="https://blog.cloudflare.com/unauthorized-issuance-of-certificates-for-1-1-1-1/" target="_blank" rel="noreferrer"&gt;bitten organisations&lt;/a&gt; in the past.&lt;/p&gt;
&lt;p&gt;CT Enforcement would enable clients to refuse to establish a connection unless the server provides cryptographic proof that its certificate has been correctly logged. Browsers like Chrome and Firefox already enforce this, but the rest of the Linux ecosystem would need a tool such as upki to enable such functionality.&lt;/p&gt;
&lt;h4 id="intermediate-preloading" class="relative group"&gt;Intermediate Preloading &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#intermediate-preloading" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h4&gt;&lt;p&gt;A correctly configured TLS server should not only send its own certificate, but also the intermediate certificates needed to chain back to a trusted root. In practice, many servers omit the intermediate certificates, and because browsers have quietly worked around this for years, the misconfiguration often goes unnoticed.&lt;/p&gt;
&lt;p&gt;Firefox has been &lt;a href="https://blog.mozilla.org/security/2020/11/13/preloading-intermediate-ca-certificates-into-firefox/" target="_blank" rel="noreferrer"&gt;preloading all intermediates&lt;/a&gt; disclosed to the &lt;a href="https://www.ccadb.org/" target="_blank" rel="noreferrer"&gt;Common CA Database&lt;/a&gt; (CCADB) since Firefox 75, while Chrome and Edge will silently fetch missing intermediates using the Authority Information Access (AIA) extension in the server&amp;rsquo;s certificate. The result is that a broken certificate chain that works perfectly in every browser will produce an opaque &lt;code&gt;UNKNOWN_ISSUER&lt;/code&gt; error when accessed by Linux utilities like &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because upki already maintains a regularly synced local data store, it&amp;rsquo;s well positioned to ship the known set of intermediates alongside the CRLite filters. This wouldn&amp;rsquo;t provide a security improvement so much as a usability improvement. It would also bring non-browser clients up to parity with browsers with respect to connection reliability. There is an additional privacy benefit too: rather than fetching a missing intermediate from the issuing CA (which discloses browsing activity to the CA), the intermediate is already present locally.&lt;/p&gt;
&lt;h4 id="merkle-tree-certificates" class="relative group"&gt;Merkle Tree Certificates &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#merkle-tree-certificates" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h4&gt;&lt;p&gt;Looking even further ahead, upki could support the next generation of web PKI by including support for &lt;a href="https://datatracker.ietf.org/doc/draft-davidben-tls-merkle-tree-certs/" target="_blank" rel="noreferrer"&gt;Merkle Tree Certificates (MTCs)&lt;/a&gt;. This is an area of active development in the IETF, with Cloudflare and Chrome recently &lt;a href="https://blog.cloudflare.com/bootstrap-mtc/" target="_blank" rel="noreferrer"&gt;announcing an experimental deployment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The motivation for MTCs comes largely from the transition to &lt;a href="https://openquantumsafe.org/post-quantum-crypto.html" target="_blank" rel="noreferrer"&gt;Post-Quantum (PQ) cryptography&lt;/a&gt;. PQ signatures are significantly larger than their non-PQ counterparts. The signatures for &lt;a href="https://openquantumsafe.org/liboqs/algorithms/sig/ml-dsa.html" target="_blank" rel="noreferrer"&gt;ML-DSA-44&lt;/a&gt; are 2,420 bytes compared to 64 bytes for ECDSA-P256. A typical TLS handshake today involves multiple signatures and public keys across the certificate chain and CT proofs, which means a simple swap to PQ algorithms would add tens of kilobytes of overhead per connection and likely a noticeable increase in connection latency.&lt;/p&gt;
&lt;p&gt;MTCs address this by rethinking how certificates are validated. Rather than transmitting a full certificate chain with multiple signatures, a Certificate Authority can batch certificates into a Merkle Tree and sign only the tree&amp;rsquo;s root hash. The client then receives just a single signature, a public key, and a compact Merkle tree inclusion proof that demonstrates the certificate&amp;rsquo;s presence in the batch. The signed tree heads can be distributed to clients out-of-band, meaning the per-handshake overhead is drastically reduced.&lt;/p&gt;
&lt;p&gt;Because upki already maintains a local data store that is regularly synced, it could cache tree head data alongside CRLite filters, thereby enabling the inclusion proofs sent during TLS handshakes to be even smaller. Rather than proving inclusion all the way from the leaf to the root, the server could send a &amp;ldquo;truncated&amp;rdquo; proof that starts partway up the tree, with the client computing the remainder from data it already has locally. There is a &lt;a href="https://datatracker.ietf.org/doc/draft-davidben-tls-merkle-tree-certs/" target="_blank" rel="noreferrer"&gt;TLS extension&lt;/a&gt; being developed to negotiate this.&lt;/p&gt;
&lt;p&gt;The implementation of MTCs for TLS is still highly experimental. MTCs are not yet deployed in any browser, but upki will lay the groundwork for Linux system utilities to benefit from this evolution as the technology is adopted.&lt;/p&gt;
&lt;h3 id="summary" class="relative group"&gt;Summary &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#summary" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;In the few weeks since we announced upki, the core revocation engine has been established and is now functional, the CRLite mirroring tool is working and a production deployment in Canonical&amp;rsquo;s datacentres is ongoing. We&amp;rsquo;re now preparing for an alpha release and remain on track for an opt-in preview for Ubuntu 26.04 LTS.&lt;/p&gt;
&lt;p&gt;Beyond revocation, we&amp;rsquo;re keeping a close eye on the evolving PKI landscape and particularly CT enforcement and Merkle Tree Certificates.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to extend my thanks again to &lt;a href="https://dirkjan.ochtman.nl/" target="_blank" rel="noreferrer"&gt;Dirkjan&lt;/a&gt; and &lt;a href="https://jbp.io/" target="_blank" rel="noreferrer"&gt;Joe&lt;/a&gt; for their continued collaboration on this work, and the utmost professionalism they&amp;rsquo;ve demonstrated throughout.&lt;/p&gt;</description></item><item><title>Addressing Linux's Missing PKI Infrastructure</title><link>https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/</link><pubDate>Mon, 08 Dec 2025 00:00:00 +0000</pubDate><guid>https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/</guid><description>&lt;blockquote&gt;
&lt;p&gt;This article was originally posted &lt;a href="https://discourse.ubuntu.com/t/addressing-linuxs-missing-pki-infrastructure/73314" target="_blank" rel="noreferrer"&gt;on the Ubuntu Discourse&lt;/a&gt;, and is reposted here. I welcome comments and further discussion in that thread.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Earlier this year, &lt;a href="https://lwn.net/" target="_blank" rel="noreferrer"&gt;LWN&lt;/a&gt; featured an excellent article titled &amp;ldquo;&lt;a href="https://lwn.net/Articles/1033809/" target="_blank" rel="noreferrer"&gt;Linux&amp;rsquo;s missing CRL infrastructure&lt;/a&gt;&amp;rdquo;. The article highlighted a number of key issues surrounding traditional Public Key Infrastructure (PKI), but critically noted how even the available measures are effectively ignored by the majority of system-level software on Linux.&lt;/p&gt;
&lt;p&gt;One of the motivators for the discussion is that the Online Certificate Status Protocol (OCSP) will cease to be supported by Let&amp;rsquo;s Encrypt. The remaining alternative is to use Certificate Revocation Lists (CRLs), yet there is little or no support for managing (or even querying) these lists in most Linux system utilities.&lt;/p&gt;
&lt;p&gt;To solve this, I&amp;rsquo;m happy to share that in partnership with &lt;a href="https://github.com/rustls/rustls" target="_blank" rel="noreferrer"&gt;rustls&lt;/a&gt; maintainers &lt;a href="https://dirkjan.ochtman.nl/" target="_blank" rel="noreferrer"&gt;Dirkjan Ochtman&lt;/a&gt; and &lt;a href="https://jbp.io/" target="_blank" rel="noreferrer"&gt;Joe Birr-Pixton&lt;/a&gt;, we&amp;rsquo;re starting the development of upki: a universal PKI tool. This project initially aims to close the revocation gap through the combination of a new system utility and eventual library support for common TLS/SSL libraries such as &lt;a href="https://openssl-library.org/" target="_blank" rel="noreferrer"&gt;OpenSSL&lt;/a&gt;, &lt;a href="https://gnutls.org/" target="_blank" rel="noreferrer"&gt;GnuTLS&lt;/a&gt; and &lt;a href="https://github.com/rustls/rustls" target="_blank" rel="noreferrer"&gt;rustls&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-problem" class="relative group"&gt;The Problem &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#the-problem" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Online Certificate Authorities responsible for issuing TLS certificates have long had mechanisms for revoking known bad certificates. What constitutes a known bad certificate varies, but generally it means a certificate was issued either in error, or by a malicious actor of some form. There have been two primary mechanisms for this revocation: &lt;a href="https://datatracker.ietf.org/doc/html/rfc5280" target="_blank" rel="noreferrer"&gt;Certificate Revocation Lists&lt;/a&gt; (CRLs) and the &lt;a href="https://datatracker.ietf.org/doc/html/rfc6960" target="_blank" rel="noreferrer"&gt;Online Certificate Status Protocol&lt;/a&gt; (OCSP).&lt;/p&gt;
&lt;p&gt;In July 2024, &lt;a href="https://letsencrypt.org/" target="_blank" rel="noreferrer"&gt;Let’s Encrypt&lt;/a&gt; &lt;a href="https://letsencrypt.org/2024/07/23/replacing-ocsp-with-crls.html" target="_blank" rel="noreferrer"&gt;announced&lt;/a&gt; the deprecation of support for the Online Certificate Status Protocol (OCSP). This wasn&amp;rsquo;t entirely unexpected - the protocol has suffered from privacy defects which leak the browsing habits of users to Certificate Authorities. Various implementations have also suffered reliability issues that forced most implementers to adopt &amp;ldquo;soft-fail&amp;rdquo; policies, rendering the checks largely ineffective.&lt;/p&gt;
&lt;p&gt;The deprecation of OCSP leaves us with CRLs. Both Windows and macOS rely on operating system components to centralise the fetching and parsing of CRLs, but Linux has traditionally delegated this responsibility to individual applications. This is done most effectively in browsers such as Mozilla Firefox, Google Chrome and Chromium, but this has been achieved with bespoke infrastructure.&lt;/p&gt;
&lt;p&gt;However, Linux itself has fallen short by not providing consistent revocation checking infrastructure for the rest of userspace - tools such as curl, system package managers and language runtimes lack a unified mechanism to process this data.&lt;/p&gt;
&lt;p&gt;The ideal solution to this problem, which is slowly &lt;a href="https://letsencrypt.org/2025/12/02/from-90-to-45.html" target="_blank" rel="noreferrer"&gt;becoming more prevalent&lt;/a&gt;, is to issue short-lived credentials with an expiration of 10 days or less, somewhat removing the need for complicated revocation infrastructure, but reducing certificate lifetimes is happening slowly and requires significant automation.&lt;/p&gt;
&lt;h2 id="crlite" class="relative group"&gt;CRLite &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#crlite" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;There are several key challenges with CRLs in practice - the size of the list has grown dramatically as the web has scaled, and one must collate CRLs from all relevant certificate authorities in order to be useful. CRLite was originally proposed by researchers at IEEE S&amp;amp;P and subsequently adopted in Mozilla Firefox. It offers a pragmatic solution to the problem of distributing large CRL datasets to client machines.&lt;/p&gt;
&lt;p&gt;In a recent &lt;a href="https://hacks.mozilla.org/2025/08/crlite-fast-private-and-comprehensive-certificate-revocation-checking-in-firefox/" target="_blank" rel="noreferrer"&gt;blog post&lt;/a&gt;, Mozilla outlined how their CRLite implementation meant that on average users &amp;ldquo;downloaded 300kB of revocation data per day, a 4MB snapshot every 45 days and a sequence of &amp;ldquo;delta-updates&amp;rdquo; in-between&amp;rdquo;, which amounts to CRLite being 1000x more bandwidth-efficient than daily CRL downloads.&lt;/p&gt;
&lt;p&gt;At its core, CRLite is a data structure compressing the full set of web-PKI revocations into a compact, efficiently queryable form. You can find more information about CRLite&amp;rsquo;s design and implementation on &lt;a href="https://blog.mozilla.org/security/tag/crlite/" target="_blank" rel="noreferrer"&gt;Mozilla&amp;rsquo;s Security Blog&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="introducing-upki" class="relative group"&gt;Introducing upki &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#introducing-upki" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Following our work on &lt;a href="https://jnsgr.uk/2025/03/carefully-but-purposefully-oxidising-ubuntu/" target="_blank" rel="noreferrer"&gt;oxidizing Ubuntu&lt;/a&gt;, &lt;a href="https://dirkjan.ochtman.nl/" target="_blank" rel="noreferrer"&gt;Dirkjan&lt;/a&gt; reached out to me with a proposal to introduce a system-level utility backed by CRLite to non-browser users.&lt;/p&gt;
&lt;p&gt;upki will be an open source project, initially packaged for Ubuntu but available to all Linux distributions, and likely portable to other Unix-like operating systems. Written in Rust, upki supports three roles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Server-side mirroring tool&lt;/strong&gt;: responsible for downloading and mirroring the CRLite filters provided by Mozilla, enabling us to operate independent CDN infrastructure for CRLite users, and serving them to clients. This will insulate upki from changes in the Mozilla backend, and enable standing up an independent data source if required. The server-side tool will manifest as a service that periodically checks the Mozilla Firefox CRLite filters, downloads and validates the files, and serves them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Client-side sync tool&lt;/strong&gt;: run regularly by a systemd-timer, network-up events or similar, this tool ensures the contents of the CDN are reflected in the on-disk filter cache. This will be extremely low on bandwidth and CPU usage assuming everything is up to date.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Client-side query tool&lt;/strong&gt;: a CLI interface for querying revocation data. This will be useful for monitoring and deployment workflows, as well as for users without a good C FFI.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The latter two roles are served by a single Rust binary that runs in different modes depending on how it is invoked. The server-side tool will be a separate binary, since its use will be much less widespread. Under the hood, all of this will be powered by Rust library crates that can be integrated in other projects via crates.io.&lt;/p&gt;
&lt;p&gt;For the initial release, Canonical will stand up the backend infrastructure required to mirror and serve the CRLite data for upki users, though the backend will be configurable. This prevents unbounded load on Mozilla’s infrastructure and ensures long-term stability even if Firefox’s internal formats evolve.&lt;/p&gt;
&lt;p&gt;&lt;a href="01.png"&gt;
&lt;figure&gt;
&lt;picture
class="mx-auto my-0 rounded-md"
&gt;
&lt;source
srcset="https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_443927a2cc8ea5be.webp 330w,https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_f1c7127e41b7d6cc.webp 660w
,https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_705ea1ebe4137e28.webp 1024w
,https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_be2b5fbb2881c88a.webp 1320w
"
sizes="100vw"
type="image/webp"
/&gt;
&lt;img
width="1720"
height="1670"
class="mx-auto my-0 rounded-md"
alt="architecture diagram for upki"
loading="lazy" decoding="async"
src="https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_b16265b7d66a056c.png" srcset="https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_77c0dd2534a34637.png 330w,https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_b16265b7d66a056c.png 660w
,https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_21c7d0a4f341695e.png 1024w
,https://jnsgr.uk/2025/12/addressing-linuxs-missing-pki-infra/01_hu_34470e9d78fe7948.png 1320w
"
sizes="100vw"
/&gt;
&lt;/picture&gt;
&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="ecosystem-compatibility" class="relative group"&gt;Ecosystem Compatibility &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#ecosystem-compatibility" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;So far we&amp;rsquo;ve covered the introduction of a new Rust binary (and crate) for supporting the fetching, serving and querying of CRL data, but that doesn&amp;rsquo;t provide much service to the existing ecosystem of Linux applications and libraries in the problem statement.&lt;/p&gt;
&lt;p&gt;The upki project will also provide a shared object library for a stable ABI that allows C and C-FFI programs to make revocation queries, using the contents of the on-disk filter cache.&lt;/p&gt;
&lt;p&gt;Once &lt;code&gt;upki&lt;/code&gt; is released and available, work can begin on integrating existing crypto libraries such as OpenSSL, GNUtls and rustls. This will be performed through the shared object library by means of an optional callback mechanism these libraries can use to check the revocation lists before establishing a connection to a given server with a certificate.&lt;/p&gt;
&lt;h2 id="timeline" class="relative group"&gt;Timeline &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#timeline" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;While we&amp;rsquo;ve been discussing this project for a couple of months, ironing out the details of funding and design, work will soon begin on the initial implementation of upki.&lt;/p&gt;
&lt;p&gt;Our aim is to make upki available as an opt-in preview for the release of Ubuntu 26.04 LTS, meaning we&amp;rsquo;ll need to complete the implementation of the server/client functionality, and bootstrap the mirroring/serving infrastructure at Canonical before April 2026.&lt;/p&gt;
&lt;p&gt;In the following Ubuntu release cycle, the run up to Ubuntu 26.10, we&amp;rsquo;ll aim to ship the tool by default on Ubuntu systems, and begin work on integration with the likes of NSS, OpenSSL, GNUtls and rustls.&lt;/p&gt;
&lt;h2 id="summary" class="relative group"&gt;Summary &lt;span class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100"&gt;&lt;a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700" style="text-decoration-line: none !important;" href="#summary" aria-label="Anchor"&gt;#&lt;/a&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Linux has a clear gap in its handling of revocation data for PKIs. Over the coming months we&amp;rsquo;re hoping to address that gap by developing upki not just for Ubuntu, but for the entire ecosystem. Thanks to Mozilla&amp;rsquo;s work on CRLite, and the expertise of Dirkjan and Joe, we&amp;rsquo;re confident that we&amp;rsquo;ll deliver a resilient and efficient solution that should make a meaningful contribution to systems security across the web.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d like to do more reading on the subject, I&amp;rsquo;d recommend the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LWN.net:&lt;/strong&gt; &lt;a href="https://lwn.net/Articles/1033809/" target="_blank" rel="noreferrer"&gt;Linux&amp;rsquo;s missing CRL infrastructure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mozilla Security Blog:&lt;/strong&gt; &lt;a href="https://blog.mozilla.org/security/2020/01/09/crlite-part-1-all-web-pki-revocations-compressed/" target="_blank" rel="noreferrer"&gt;CRLite Part 1: All Web PKI Revocations Compressed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mozilla Security Blog:&lt;/strong&gt; &lt;a href="https://blog.mozilla.org/security/2020/01/09/crlite-part-2-end-to-end-design/" target="_blank" rel="noreferrer"&gt;CRLite Part 2: End-to-End Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Let’s Encrypt:&lt;/strong&gt; &lt;a href="https://letsencrypt.org/2024/07/23/replacing-ocsp-with-crls.html" target="_blank" rel="noreferrer"&gt;Replacing OCSP with CRLs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IEEE Symposium on Security &amp;amp; Privacy:&lt;/strong&gt; &lt;a href="https://www.google.com/search?q=https://ieeexplore.ieee.org/document/7958572" target="_blank" rel="noreferrer"&gt;CRLite: A Scalable System for Pushing All TLS Revocations to All Browsers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>