Sitelet https://github.com/RustCrypto/formats/pull/2445
Skip to content

x509-cert: accept v1 CRLs (TBSCertList.version is OPTIONAL) - #2445

Open
yuxi-liu-wired wants to merge 1 commit into
RustCrypto:masterfrom
yuxi-liu-wired:fix/crl-version-optional
Open

yuxi-liu-wired wants to merge 1 commit into
RustCrypto:masterfrom
yuxi-liu-wired:fix/crl-version-optional

Conversation

@yuxi-liu-wired

Copy link
Copy Markdown
Contributor

RFC 5280 Section 5.1:

TBSCertList  ::=  SEQUENCE  {
     version                 Version OPTIONAL, -- if present, MUST be v2
     ...

The doc comment on TbsCertList quotes this, but the field is declared as a required Version. So every v1 CRL, which omits the field, fails to decode:

CertificateList::<Rfc5280>::from_der(v1_crl);
// Err: unexpected ASN.1 DER tag: expected INTEGER, got SEQUENCE

pyca/cryptography and OpenSSL both accept these CRLs (x509-parser's test assets include one).

Fix: mark the field #[asn1(default = "Default::default")], so it defaults to Version::V1, as TbsCertificate already does for its version. With that:

  • a missing version decodes as V1
  • V1 is omitted when encoding, so v1 CRLs re-encode to the same bytes
  • v2 CRLs, including those built by CrlBuilder, keep their explicit INTEGER 1

decode_v1_crl_without_version in tests/crl.rs covers both cases and fails on master, and builder_crl still passes. The x509-cert CI steps (--no-default-features, default, --features arbitrary/hazmat/sct, the feature powerset, --all-features in debug and release, on stable and 1.85), cargo fmt --check and cargo +1.90.0 clippy --all-features --tests all pass.

Found by fuzzing CRL decoding against pyca/cryptography. This PR was produced by AI agents (Claude), from the fuzzing and the fix through to this description.

RFC 5280 Section 5.1 defines `version Version OPTIONAL -- if present,
MUST be v2`, as the doc comment on `TbsCertList` already quotes. v1 CRLs
omit the field. `TbsCertList` declared it as a required field, so every
v1 CRL failed to decode with "expected INTEGER, got SEQUENCE".
pyca/cryptography and OpenSSL accept them.

Mark it `#[asn1(default = "Default::default")]` (`Version::V1`), as
`TbsCertificate` does for its version. A missing version decodes as
`V1`, `V1` is omitted when encoding (so v1 CRLs re-encode unchanged),
and v2 CRLs, including the ones the CRL builder produces, keep their
explicit `INTEGER 1`.

Found by fuzzing CRL decoding against pyca/cryptography.

This branch has not been deployed

No deployments
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