Skip to content

feat(corim): add x5chain trust verification with PKIX and CRL support#276

Draft
magickli1 wants to merge 1 commit into
veraison:mainfrom
magickli1:feat/x5chain-trust-verify
Draft

feat(corim): add x5chain trust verification with PKIX and CRL support#276
magickli1 wants to merge 1 commit into
veraison:mainfrom
magickli1:feat/x5chain-trust-verify

Conversation

@magickli1

@magickli1 magickli1 commented Jun 21, 2026

Copy link
Copy Markdown

Summary

Adds library support to verify CoRIMs signed with a COSE Sign1 x5chain header: PKIX path validation (explicit and/or system trust anchors), optional CRL checks, then COSE signature verification with the PKIX-validated leaf key. See sections below for API, trust-pool semantics, and verification order.

New API

  • TrustedRoots — root CA pool, optional CRLs, optional CurrentTime (zero = time.Now())
  • TrustedRootPool(readFile, rootPaths, crlPaths, includeSystemRoots) — load trust material from files; duplicate DER roots across rootPaths are added once; PEM root files may bundle multiple certificates (x509.CertPool.AppendCertsFromPEM); DER root files use x509.ParseCertificate; DER CRL files use x509.ParseRevocationList; PEM CRL files may contain multiple blocks (encoding/pem.Decode — no stdlib CRL bundle API)
  • SignedCorim.VerifyX509ChainTrust(trusted) — validate x5chain (leaf-only or leaf + intermediates) and verify the COSE signature

Call SignedCorim.FromCOSE first. Key-based verification without PKIX trust remains SignedCorim.Verify.

Trust pool semantics:

  • Pool == nil loads system roots at verify time
  • empty non-nil pool is explicit-trust-only (no system roots)
  • TrustedRootPool(..., includeSystemRoots: true) merges the OS trust store with rootPaths; false uses only explicit roots

Prefer TrustedRootPool for embedders loading trust material from files.

Verification order

  1. Leaf signing certificate policy (non-CA; digitalSignature when KeyUsage is present; certs without a KeyUsage extension pass this step)
  2. PKIX path validation with ExtKeyUsageAny against trusted.Pool — no standard EKU for CoRIM/RIM signing; leaf KeyUsage (when present) and COSE verify still constrain signing use
  3. CRL checks when trusted.CRLs is non-empty (CRLs from issuers outside the verified chain are ignored; in-chain issuers with no matching CRL are skipped — fail-open; provide a CRL per issuer you intend to check; multiple CRLs per issuer: check all valid ones, fail if all matching CRLs are invalid)
  4. COSE signature verification with the PKIX-validated leaf key (not COSE kid)

When PKIX returns multiple valid chains, pick the path with the most certificate (DER) overlap with the presented x5chain so CRL and signature steps follow the path attested in the COSE header, not an arbitrary equivalent path (ties: first best-scoring chain).

Other changes

  • FromCOSE / extractX5Chain: FromCOSE clears x5chain fields before decode; on success, extractX5Chain assigns directly (no longer via AddSigningCert); a failed FromCOSE leaves x5chain fields nil; direct extractX5Chain calls preserve existing fields on parse failure; clear stale certs when the header is absent or the chain shrinks
  • Test fixtures: scripts/gen-certs.sh adds PKIX extensions; make test-certs regenerate FORCE=1 re-issues testdata/*.der (keys unchanged)

Out of scope

  • OCSP / AIA fetching
  • kid vs x5chain leaf cross-check (COSE treats kid as a hint; use Verify for external-key verify)
  • IsCA check when loading trust files from disk
  • Exported chain-only verify without trust (Go exposes trust+signature via VerifyX509ChainTrust only)

Test plan

  • make presubmit passes (coverage ≥84.4%, lint clean)
  • x509chain_test.go: VerifyX509ChainTrust, TrustedRootPool (DER/PEM roots and CRLs), unit tests for validateSigningCertificate, checkRevocation, selectVerifiedChain; happy path, untrusted root, expiry, revocation, tampered payload, signing-key mismatch
  • signedcorim_test.go: 5 appended tests — FromCOSE_x5chain_idempotent, resetsIntermediatesOnShrink, clearsX5ChainWhenHeaderAbsent, resetsStaleIntermediateCerts, extractX5Chain_preservesStateOnError

Validate x5chain-signed CoRIMs via TrustedRoots, TrustedRootPool, and
SignedCorim.VerifyX509ChainTrust (PKIX, optional CRL, leaf-key signature).
Fix FromCOSE x5chain stale state; regenerate PKIX test fixtures.
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