From ffe136b5e37fbec2d5fc749a9afdd34522c9797a Mon Sep 17 00:00:00 2001 From: Joe Birr-Pixton Date: Tue, 25 Nov 2025 13:54:06 +0000 Subject: [PATCH] Skip over issuerUniqueID and subjectUniqueID --- src/cert.rs | 24 ++++++++++++++++++++ src/der.rs | 3 +++ src/error.rs | 2 ++ tests/integration.rs | 9 ++++++++ tests/misc/issuer_and_subject_unique_id.der | Bin 0 -> 451 bytes 5 files changed, 38 insertions(+) create mode 100644 tests/misc/issuer_and_subject_unique_id.der diff --git a/src/cert.rs b/src/cert.rs index 1d938f2c..b1865c24 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -106,6 +106,30 @@ impl<'a> Cert<'a> { der: CertificateDer::from(cert_der.as_slice_less_safe()), }; + // Skip over optional and unhandled: + // + // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + // -- If present, version MUST be v2 or v3 + // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + // -- If present, version MUST be v2 or v3 + for (tag, id) in [ + ( + der::Tag::ContextSpecificPrimitive1, + DerTypeId::IssuerUniqueId, + ), + ( + der::Tag::ContextSpecificPrimitive2, + DerTypeId::SubjectUniqueId, + ), + ] { + if tbs.peek(tag.into()) { + der::nested(tbs, tag, Error::TrailingData(id), |tagged| { + tagged.skip_to_end(); + Ok(()) + })?; + } + } + // When used to read X509v3 Certificate.tbsCertificate.extensions, we allow // the extensions to be empty. This is in spite of RFC5280: // diff --git a/src/der.rs b/src/der.rs index af6e6921..9ad58455 100644 --- a/src/der.rs +++ b/src/der.rs @@ -73,6 +73,9 @@ pub(crate) enum Tag { ContextSpecificConstructed0 = CONTEXT_SPECIFIC | CONSTRUCTED | 0, ContextSpecificConstructed1 = CONTEXT_SPECIFIC | CONSTRUCTED | 1, ContextSpecificConstructed3 = CONTEXT_SPECIFIC | CONSTRUCTED | 3, + + ContextSpecificPrimitive1 = CONTEXT_SPECIFIC | 1, + ContextSpecificPrimitive2 = CONTEXT_SPECIFIC | 2, } pub(crate) const CONSTRUCTED: u8 = 0x20; diff --git a/src/error.rs b/src/error.rs index a38d5286..adb151e5 100644 --- a/src/error.rs +++ b/src/error.rs @@ -399,4 +399,6 @@ pub enum DerTypeId { RevokedCertificateExtension, RevokedCertEntry, IssuingDistributionPoint, + IssuerUniqueId, + SubjectUniqueId, } diff --git a/tests/integration.rs b/tests/integration.rs index ff45217c..8beaf85d 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -273,6 +273,15 @@ fn read_ee_with_large_pos_serial() { webpki::EndEntityCert::try_from(&ee).expect("should parse 20-octet positive serial number"); } +#[test] +#[cfg(feature = "alloc")] +fn read_ee_with_issuer_and_subject_unique_ids() { + let ee = CertificateDer::from(&include_bytes!("misc/issuer_and_subject_unique_id.der")[..]); + + webpki::EndEntityCert::try_from(&ee) + .expect("should skip over issuerUniqueID and subjectUniqueID"); +} + #[test] fn list_netflix_names() { expect_cert_dns_names( diff --git a/tests/misc/issuer_and_subject_unique_id.der b/tests/misc/issuer_and_subject_unique_id.der new file mode 100644 index 0000000000000000000000000000000000000000..981c1c523f3084fee072afcfbbedcd125d8260ab GIT binary patch literal 451 zcmXqLV%%@g#8|k1nTe5!NrYkD)O$Z_*SB9@7vWuhQ8XuLf8q%PRyJns)B=M5Lq7u_ zHs(+kW*%3|G$V`TWFx~Qb5rvq^F#xqG&2KBBa>u91Iwh8Br~H#lO!_((Ctnx1hh zu`u;FCrr