From ac6286966da5d3adec5b61733bb382193af44e6f Mon Sep 17 00:00:00 2001 From: afldl <18260596452@163.com> Date: Wed, 10 Jun 2026 21:05:54 +0800 Subject: [PATCH 1/7] Reject CONTEXT-SPECIFIC tag class in serial number parser --- src/x509.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/x509.rs b/src/x509.rs index c33a00aa..14d83a31 100644 --- a/src/x509.rs +++ b/src/x509.rs @@ -10,9 +10,9 @@ use crate::public_key::*; use asn1_rs::num_bigint::BigUint; use asn1_rs::{ - Alias, Any, BerError, BitString, BmpString, Choice, DerParser, Enumerated, FromDer, Header, - Input, Integer, OptTaggedExplicit, PrintableString, Sequence, Tag, Tagged, TeletexString, - UniversalString, Utf8String, + Alias, Any, BerError, BitString, BmpString, Choice, Class, DerParser, Enumerated, FromDer, + Header, Input, Integer, OptTaggedExplicit, PrintableString, Sequence, Tag, Tagged, + TeletexString, UniversalString, Utf8String, }; use core::convert::TryFrom; use data_encoding::HEXUPPER; @@ -612,6 +612,10 @@ pub(crate) fn parse_serial(input: Input<'_>) -> IResult, (&[u8], BigUi // RFC 5280 4.1.2.2: "The serial number MUST be a positive integer" // however, many CAs do not respect this and send integers with MSB set, // so we do not use `as_biguint()` + // X.690 §8.1.2: tag class must be UNIVERSAL for INTEGER + if any.class() != Class::Universal { + return Err(Err::Error(X509Error::InvalidSerial)); + } any.tag() .assert_eq(Tag::Integer) .map_err(|_| X509Error::InvalidSerial)?; @@ -755,4 +759,13 @@ mod tests { assert_eq!(v.not_before.to_datetime().year(), 2019); assert_eq!(v.not_after.to_datetime().year(), 2029); } + + #[test] + fn test_serial_rejects_context_specific_tag() { + // Tag byte 0x02 (UNIVERSAL INTEGER) → 0x82 (CONTEXT-SPECIFIC [2]) + // X.690 §8.1.2: tag class must match the expected type + let data: &[u8] = &[0x82, 0x01, 0x01]; // CONTEXT-SPECIFIC [2], length 1, value 1 + let r = parse_serial(Input::from(data)); + assert!(r.is_err(), "should reject CONTEXT-SPECIFIC tag for serial number"); + } } From 2cd636e7796b4c63a2a15e03c8bf528200a8f791 Mon Sep 17 00:00:00 2001 From: afldl <18260596452@163.com> Date: Wed, 10 Jun 2026 21:21:26 +0800 Subject: [PATCH 2/7] Reject CONTEXT-SPECIFIC tag class in serial number parser --- src/x509.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/x509.rs b/src/x509.rs index 14d83a31..1820d963 100644 --- a/src/x509.rs +++ b/src/x509.rs @@ -766,6 +766,9 @@ mod tests { // X.690 §8.1.2: tag class must match the expected type let data: &[u8] = &[0x82, 0x01, 0x01]; // CONTEXT-SPECIFIC [2], length 1, value 1 let r = parse_serial(Input::from(data)); - assert!(r.is_err(), "should reject CONTEXT-SPECIFIC tag for serial number"); + assert!( + r.is_err(), + "should reject CONTEXT-SPECIFIC tag for serial number" + ); } } From 93e2bb6c3ad8b86e6bc56ecba4de57610c37166f Mon Sep 17 00:00:00 2001 From: afldl <18260596452@163.com> Date: Wed, 10 Jun 2026 22:07:01 +0800 Subject: [PATCH 3/7] Fix clippy collapsible_match in validate modules From 676248f0e0906838d9df9cd9864e0d11805a36ef Mon Sep 17 00:00:00 2001 From: afldl <18260596452@163.com> Date: Wed, 10 Jun 2026 22:07:14 +0800 Subject: [PATCH 4/7] Fix clippy collapsible_match in validate modules --- src/validate/extensions.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/validate/extensions.rs b/src/validate/extensions.rs index b8ef1d1b..e49f26f2 100644 --- a/src/validate/extensions.rs +++ b/src/validate/extensions.rs @@ -97,11 +97,10 @@ impl<'a> Validator<'a> for X509ExtensionsValidator { test_critical!(SHOULD NOT ext, l, "SubjectAltName"); for name in san.general_names() { match name { - GeneralName::DNSName(ref s) | GeneralName::RFC822Name(ref s) => { - // should be an ia5string - if !s.as_bytes().iter().all(u8::is_ascii) { - l.warn(&format!("Invalid charset in 'SAN' entry '{s}'")); - } + GeneralName::DNSName(ref s) | GeneralName::RFC822Name(ref s) + if !s.as_bytes().iter().all(u8::is_ascii) => + { + l.warn(&format!("Invalid charset in 'SAN' entry '{s}'")); } _ => (), } From 9eebbe879208203d659d96152a596b13859d79af Mon Sep 17 00:00:00 2001 From: afldl <18260596452@163.com> Date: Wed, 10 Jun 2026 22:07:26 +0800 Subject: [PATCH 5/7] Fix clippy collapsible_match in validate modules --- src/validate/structure.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/validate/structure.rs b/src/validate/structure.rs index 1b3a358a..8ba530f1 100644 --- a/src/validate/structure.rs +++ b/src/validate/structure.rs @@ -140,11 +140,10 @@ impl<'a> Validator<'a> for TbsCertificateStructureValidator { if let ParsedExtension::SubjectAlternativeName(san) = ext.parsed_extension() { for name in san.general_names() { match name { - GeneralName::DNSName(ref s) | GeneralName::RFC822Name(ref s) => { - // should be an ia5string - if !s.as_bytes().iter().all(u8::is_ascii) { - l.warn(&format!("Invalid charset in 'SAN' entry '{s}'")); - } + GeneralName::DNSName(ref s) | GeneralName::RFC822Name(ref s) + if !s.as_bytes().iter().all(u8::is_ascii) => + { + l.warn(&format!("Invalid charset in 'SAN' entry '{s}'")); } _ => (), } From 6b9a4b71b32b31dcfe5edd38a72935be9c59c3ae Mon Sep 17 00:00:00 2001 From: afldl <18260596452@163.com> Date: Wed, 10 Jun 2026 22:07:47 +0800 Subject: [PATCH 6/7] Fix clippy collapsible_match in validate/extensions.rs From 362d317e37c3a88cb71d21491a8f46895f6b4d76 Mon Sep 17 00:00:00 2001 From: afldl <18260596452@163.com> Date: Wed, 10 Jun 2026 22:08:06 +0800 Subject: [PATCH 7/7] Fix clippy collapsible_match in validate/structure.rs