Skip to content

Commit 2c8219f

Browse files
committed
x509-cert: relax serialnumber parsing, allow rfc-invalid values
Fixes #978
1 parent 9adb377 commit 2c8219f

File tree

3 files changed

+43
-11
lines changed

3 files changed

+43
-11
lines changed

x509-cert/src/serial_number.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ impl SerialNumber {
3232
/// Maximum length in bytes for a [`SerialNumber`]
3333
pub const MAX_LEN: Length = Length::new(20);
3434

35-
/// See notes in `SerialNumber::new` and `SerialNumber::decode_value`.
36-
const MAX_DECODE_LEN: Length = Length::new(21);
37-
3835
/// Create a new [`SerialNumber`] from a byte slice.
3936
///
4037
/// The byte slice **must** represent a positive integer.
@@ -74,15 +71,15 @@ impl EncodeValue for SerialNumber {
7471

7572
impl<'a> DecodeValue<'a> for SerialNumber {
7673
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
74+
// We explicitely allow any value to be parsed from PEM/DER formatted serial numbers
75+
// as per RFC 5280 section 4.1.2.2:
76+
// Note: Non-conforming CAs may issue certificates with serial numbers
77+
// that are negative or zero. Certificate users SHOULD be prepared to
78+
// gracefully handle such certificates.
79+
//
80+
// https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.2
7781
let inner = Int::decode_value(reader, header)?;
7882

79-
// See the note in `SerialNumber::new`: we permit lengths of 21 bytes here,
80-
// since some X.509 implementations interpret the limit of 20 bytes to refer
81-
// to the pre-encoded value.
82-
if inner.len() > SerialNumber::MAX_DECODE_LEN {
83-
return Err(ErrorKind::Overlength.into());
84-
}
85-
8683
Ok(Self { inner })
8784
}
8885
}

x509-cert/tests/certificate.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use x509_cert::Certificate;
1111
use x509_cert::*;
1212

1313
#[cfg(feature = "pem")]
14-
use der::DecodePem;
14+
use der::{pem::LineEnding, DecodePem, EncodePem};
1515

1616
// TODO - parse and compare extension values
1717
const EXTENSIONS: &[(&str, bool)] = &[
@@ -412,3 +412,22 @@ fn decode_cert_negative_serial_number() {
412412
let reencoded = cert.to_der().unwrap();
413413
assert_eq!(der_encoded_cert, reencoded.as_slice());
414414
}
415+
416+
#[cfg(feature = "pem")]
417+
#[test]
418+
fn decode_cert_overlength_serial_number() {
419+
let der_encoded_cert = include_bytes!("examples/qualcomm.pem");
420+
421+
let cert = Certificate::from_pem(der_encoded_cert).unwrap();
422+
assert_eq!(
423+
cert.tbs_certificate.serial_number.as_bytes(),
424+
&[
425+
0, 132, 206, 11, 246, 160, 254, 130, 78, 229, 229, 6, 202, 168, 157, 120, 198, 21, 1,
426+
98, 87, 113
427+
]
428+
);
429+
assert_eq!(cert.tbs_certificate.serial_number.as_bytes().len(), 22);
430+
431+
let reencoded = cert.to_pem(LineEnding::LF).unwrap();
432+
assert_eq!(der_encoded_cert, reencoded.as_bytes());
433+
}

x509-cert/tests/examples/qualcomm.pem

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIICnDCCAiGgAwIBAgIWAITOC/ag/oJO5eUGyqideMYVAWJXcTAKBggqhkjOPQQD
3+
AzB2MSQwIgYDVQQKDBtRdWFsY29tbSBUZWNobm9sb2dpZXMsIEluYy4xKjAoBgNV
4+
BAsMIVF1YWxjb21tIENyeXB0b2dyYXBoaWMgT3BlcmF0aW9uczEiMCAGA1UEAwwZ
5+
UU1DIEF0dGVzdGF0aW9uIFJvb3QgQ0EgNDAeFw0xNzA4MDEyMjE2MzJaFw0yNzA4
6+
MDEyMjE2MzJaMH4xJDAiBgNVBAoMG1F1YWxjb21tIFRlY2hub2xvZ2llcywgSW5j
7+
LjEqMCgGA1UECwwhUXVhbGNvbW0gQ3J5cHRvZ3JhcGhpYyBPcGVyYXRpb25zMSow
8+
KAYDVQQDDCFRTUMgQXR0ZXN0YXRpb24gUm9vdCBDQSA0IFN1YkNBIDEwdjAQBgcq
9+
hkjOPQIBBgUrgQQAIgNiAAQDsjssSUEFLyyBe17UmO3pMzqKS+V1jfQkhq7a7zmH
10+
LCrPFmfaKLm0/szdzZxn+zwhoYen3fgJIuZUaip8wAQxLe4550c1ZBl3iSTvYUbe
11+
J+gBz2DiJHRBOtY1bQH35NWjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0P
12+
AQH/BAQDAgEGMB0GA1UdDgQWBBTrVYStHPbaTn4k7bPerqZAmJcuXzAfBgNVHSME
13+
GDAWgBQBBnkODO3o7rgWy996xOf1BxR4VTAKBggqhkjOPQQDAwNpADBmAjEAmpM/
14+
Xvfawl4/A3jd0VVb6lOBh0Jy+zFz1Jz/hw+Xpm9G4XJCscBE7r7lbe2Xc1DHAjEA
15+
psnskI8pLJQwL80QzAwP3HvgyDUeedNpxnYNK797vqJu6uRMLsZBVHatLM1R4gyE
16+
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)