Skip to content

Add a blocklist covering disabled roots and compromised intermediates - #11

Merged
MagicalTux merged 2 commits into
masterfrom
blocklist
Oct 23, 2026
Merged

MagicalTux merged 2 commits into
masterfrom
blocklist

Conversation

@MagicalTux

@MagicalTux MagicalTux commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

cacrt now ships a blocklist of certificates that must never be trusted, wherever they come from. A caller checks every certificate in its chain, root included. A root we have disabled is then still rejected when it comes from an OS store that still trusts it, and a compromised intermediate can be blocked without killing its whole CA.

What's blocked (19 certificates)

  • 3 disabled roots (roots/**/*.disabled): emSign ECC Root CA - G3, Buypass Class 2 and Class 3. From now on, a disabled root is automatically a blocked root.
  • 16 eMudhra intermediates (blocked/2026-10-emudhra-intermediates/): the 8 compromised keys, each issued by emSign and cross-signed by Sectigo AAA. No private keys; those stay in evidence/, outside the crate.

Entries are keyed by SHA-256 of the certificate and of its SPKI. Matching on the key catches cross-signs and reissues we've never seen.

API

blocked() all entries: kind(), label(), reason(), both hashes
blocked_by_spki(&[u8; 32]) is this key blocked?
blocked_by_cert(&[u8; 32]) is this certificate blocked?

The caller hashes, so the library stays static data and comparisons: no_std, no alloc, no runtime hashing. Callers are TLS libraries that already parse DER.

Build-time guarantees

  • every entry needs a # Blocked: <reason> header
  • # SHA256 fingerprint: / # SPKI SHA256: headers must match the certificate; the eMudhra ones come from the incident's JSON, which independently checks the build's SHA-256 and SPKI extraction
  • the build fails if a blocked key is also a trusted root's key (I confirmed it does, by temporarily blocking GlobalSign R3)

Checks

cargo fmt, clippy, tests (including tests that play the caller: hash the DER, then query), thumbv7em-none-eabi, MSRV 1.86, cargo doc -D warnings, cacrt-tool verify, cargo package.

Caveat

The blocklist protects only verifiers that call it; rustls and OpenSSL don't know about it. When a root program removes a root, we still disable the root, which also blocks it. The README, CURATION.md and CHANGELOG-roots.md document all of this.

🤖 Generated with Claude Code

MagicalTux and others added 2 commits October 24, 2026 06:32
Ship a blocklist alongside the trust store so callers can reject a
certificate wherever it comes from, including a root supplied by the OS
store. It holds every disabled root (roots/**/*.disabled) and the 16
compromised eMudhra intermediate certificates (blocked/), keyed by the
SHA-256 of the certificate and of its SubjectPublicKeyInfo.

- blocked(), blocked_by_spki(), blocked_by_cert(): static lookups, no
  runtime hashing
- optional `check` feature: blocked_by_der() and check_chain() parse and
  hash DER chains; still no_std, no alloc, no dependencies
- build.rs fingerprints each entry with a shared core-only SHA-256,
  requires a `# Blocked:` reason header, checks published fingerprint
  headers, and fails if a blocked key is also a trusted root's key
- docs: README, CURATION.md, CHANGELOG-roots.md; CI covers the feature

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e DER

Remove check_chain()/blocked_by_der() and the runtime DER walker. The
library is back to static data and comparisons; SHA-256 moves to
build_support as a build-time helper only. The DER-level tests now play
the caller's role, hashing with the build helpers and querying
blocked_by_spki()/blocked_by_cert().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MagicalTux
MagicalTux merged commit 9afa795 into master Oct 23, 2026
3 checks passed
@MagicalTux MagicalTux mentioned this pull request Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant