Skip to content

clazel-x509: vendor x509-limbo and run it through the decoders - #18

Merged
atiernan merged 11 commits into
mainfrom
phase3/x509-limbo
Oct 27, 2026
Merged

atiernan merged 11 commits into
mainfrom
phase3/x509-limbo

Conversation

@atiernan

Copy link
Copy Markdown
Member

Stacked on #14, parallel to #15 (both add a section to the new crates/clazel-x509/README.md, so whichever lands second needs a trivial merge). This is the x509-limbo conformance corpus from Phase 3 §3.5b.

Vendored

crates/clazel-x509/tests/data/x509-limbo/ holds:

  • limbo.json, byte for byte from C2SP/x509-limbo 1080e565f26e544bbe9cf99953be8a57c08e7e20: 41,791,455 bytes, SHA-256 611e337b…acd4de, re-checked locally;
  • upstream's LICENSE (Apache-2.0) as LICENSE.md;
  • SOURCE.md, which notes that upstream's README claims Apache-2.0 / MIT but the repo ships only the Apache text.

Derived (ours, reproducible)

The xtask testdata converter xtask/src/testdata/x509_limbo.rs writes:

  • tests/generated/x509_limbo.rs, a 3.3 MB index of the testcases;
  • tests/generated/x509_limbo_certs.bin, 17.4 MB holding the 30,379 distinct certificate DERs.

It does not turn the 41.8 MB of JSON into Rust literals. testdata.rs gains EXTRA_OUTPUTS, so cargo xtask check also fails on a stale or orphaned binary output. The converter decodes PEM with its own small strict base64 decoder, because clazel-base64 would pull vstd into xtask. It adds no new dependencies.

Harness (tests/conformance_limbo.rs; 0.46 s in debug; ignored under Miri)

  • Every one of the 30,379 certificates runs through every existing decoder, with the accepted counts pinned.
  • All 927 SERVER testcases that expect SUCCESS for a DNS or IP peer name are accepted by check_leaf_certificate.
  • No certificate in any SUCCESS testcase is rejected by any decoder.
  • The other 8,875 testcases are listed by id with a reason in tests/limbo/not_yet_supported.rs. Most say "needs path validation (3.5b)"; others need CRL checking, chain-search limits, ML-DSA or client-certificate validation. The test fails if an id appears or disappears, or if a listed case starts passing.

Findings

  • No decoder bugs.
  • rfc5280::ca-as-leaf and pathlen::validation-ignores-pathlen-in-leaf expect SUCCESS under RFC 5280, but our stricter WebPKI leaf policy rejects a CA:TRUE leaf. They are listed as a policy difference. mozilla::pkix makes the same choice: it rejects a CA certificate used as an end entity.

Local results

I re-ran these:

  • cargo xtask check reported STATIC CHECKS PASSED, with both derived files up to date.
  • cargo test -p clazel-x509 gives 56 passed, 0 failed.
  • cargo fmt --all --check and strict clippy (clazel-x509, xtask) are clean.

No Verus or full verify was run. Intermediate commit e4fe0b2 has a failing test, which 208d884 fixes. The crate stays at tier 0.

🤖 Generated with Claude Code

atiernan and others added 10 commits October 26, 2026 15:10
clazel-der (ITU-T X.690 DER decoder and encoder, Phase 3 item 3.5a),
taken unchanged from phase3/tls-handover so it can land on its own
instead of inside #1. Adds the allowlist rows for its test-only
reference engine (der 0.8.2, const-oid, zeroize) and the lock entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Suites may now also write a binary artefact beside the Rust table, checked
for staleness like the tables. The 41.8 MB corpus becomes a 3.3 MB index and
a 17.4 MB certificate file instead of Rust literals.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
limbo.json is byte for byte from upstream (41,791,455 bytes, SHA-256 in
SOURCE.md); the index and certificate blob are generated by xtask testdata.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…hecks

No path validation yet: every certificate goes through every decoder, the
SERVER/SUCCESS leaves are pinned to check_leaf_certificate, and all other
testcases are listed by id with a reason.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI's conformance step fails a tests/conformance*.rs that prints no
clazel-conformance line. One unit per testcase: pinned and passing,
listed in NOT_YET_SUPPORTED (expected failures, each with a reason), or
neither.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolves the conflicts with the x509 and trust-store stack on main:
lib.rs and spki/exec.rs take main's (the roots module; the open SPKI
views), and README.md keeps main's root-table section and adds the
x509-limbo section after it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@atiernan
atiernan changed the base branch from phase3/x509 to main October 27, 2026 11:08
@atiernan
atiernan marked this pull request as ready for review October 27, 2026 13:56
@atiernan
atiernan merged commit 48bf395 into main Oct 27, 2026
25 checks passed
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