Skip to content

Commit 2e89193

Browse files
authored
Bugfixes in X509 decoder (#1927)
This PR fixes a few bugs: - Support cases where the "version" field doesn't exist (the version in this case should be v1) - Support cases where neither "extensions", "subject unique ID" and "issuer unique ID" exists - Add tests for these cases
1 parent a4b12ef commit 2e89193

File tree

4 files changed

+57
-25
lines changed

4 files changed

+57
-25
lines changed

Packet++/header/X509Decoder.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -596,10 +596,6 @@ namespace pcpp
596596
int m_ExtensionsOffset = -1;
597597

598598
X509TBSCertificate(Asn1SequenceRecord* root);
599-
int getIndex(int offset) const
600-
{
601-
return m_VersionOffset + offset;
602-
}
603599
};
604600

605601
/// @class X509Certificate

Packet++/src/X509Decoder.cpp

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -749,23 +749,26 @@ namespace pcpp
749749
m_SubjectOffset = currIndex++;
750750
m_SubjectPublicKeyInfoOffset = currIndex++;
751751

752-
record = root->getSubRecords().at(currIndex);
753-
754-
if (record->getTagClass() == Asn1TagClass::ContextSpecific && record->getTagType() == 1)
752+
if (root->getSubRecords().size() > static_cast<size_t>(currIndex))
755753
{
756-
m_IssuerUniqueID = currIndex++;
757754
record = root->getSubRecords().at(currIndex);
758-
}
759755

760-
if (record->getTagClass() == Asn1TagClass::ContextSpecific && record->getTagType() == 2)
761-
{
762-
m_SubjectUniqueID = currIndex++;
763-
record = root->getSubRecords().at(currIndex);
764-
}
765-
766-
if (X509Extensions::isValidExtensionsRecord(record))
767-
{
768-
m_ExtensionsOffset = currIndex++;
756+
if (record->getTagClass() == Asn1TagClass::ContextSpecific && record->getTagType() == 1)
757+
{
758+
m_IssuerUniqueID = currIndex++;
759+
record = root->getSubRecords().at(currIndex);
760+
}
761+
762+
if (record->getTagClass() == Asn1TagClass::ContextSpecific && record->getTagType() == 2)
763+
{
764+
m_SubjectUniqueID = currIndex++;
765+
record = root->getSubRecords().at(currIndex);
766+
}
767+
768+
if (X509Extensions::isValidExtensionsRecord(record))
769+
{
770+
m_ExtensionsOffset = currIndex++;
771+
}
769772
}
770773
}
771774
catch (const std::out_of_range&)
@@ -788,25 +791,25 @@ namespace pcpp
788791

789792
X509Name X509TBSCertificate::getIssuer() const
790793
{
791-
auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, getIndex(m_IssuerOffset), "Issuer");
794+
auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_IssuerOffset, "Issuer");
792795
return X509Name(root);
793796
}
794797

795798
X509Validity X509TBSCertificate::getValidity() const
796799
{
797-
auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, getIndex(m_ValidityOffset), "Validity");
800+
auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_ValidityOffset, "Validity");
798801
return X509Validity(root);
799802
}
800803

801804
X509Name X509TBSCertificate::getSubject() const
802805
{
803-
auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, getIndex(m_SubjectOffset), "Subject");
806+
auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_SubjectOffset, "Subject");
804807
return X509Name(root);
805808
}
806809

807810
X509SubjectPublicKeyInfo X509TBSCertificate::getSubjectPublicKeyInfo() const
808811
{
809-
auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, getIndex(m_SubjectPublicKeyInfoOffset),
812+
auto root = getSubRecordAndCast<Asn1SequenceRecord>(m_Root, m_SubjectPublicKeyInfoOffset,
810813
"Subject Public Key Info");
811814
return X509SubjectPublicKeyInfo(root);
812815
}
@@ -818,7 +821,7 @@ namespace pcpp
818821
return nullptr;
819822
}
820823

821-
auto root = getSubRecordAndCast<Asn1ConstructedRecord>(m_Root, getIndex(m_ExtensionsOffset), "Extensions");
824+
auto root = getSubRecordAndCast<Asn1ConstructedRecord>(m_Root, m_ExtensionsOffset, "Extensions");
822825
return std::unique_ptr<X509Extensions>(new X509Extensions(root));
823826
}
824827

@@ -1015,9 +1018,13 @@ namespace pcpp
10151018
{
10161019
if (!m_ExtensionsParsed)
10171020
{
1018-
for (const auto& extension : m_TBSCertificate.getExtensions()->getExtensions())
1021+
auto extensions = m_TBSCertificate.getExtensions();
1022+
if (extensions != nullptr)
10191023
{
1020-
m_Extensions.emplace_back(X509Extension(extension));
1024+
for (const auto& extension : extensions->getExtensions())
1025+
{
1026+
m_Extensions.emplace_back(X509Extension(extension));
1027+
}
10211028
}
10221029
m_ExtensionsParsed = true;
10231030
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDdzCCAl8CFGJm3LFNJOTEx7xjXH9glmfasIw3MA0GCSqGSIb3DQEBCwUAMHcx
3+
CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTERMA8GA1UEBwwITmV3IFlvcmsxITAf
4+
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDElMCMGCSqGSIb3DQEJARYW
5+
cGNhcHBsdXNwbHVzQGdtYWlsLmNvbTAgFw0yNTA4MTcwODI3MDdaGA8yMTI1MDcy
6+
NDA4MjcwN1owdzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMREwDwYDVQQHDAhO
7+
ZXcgWW9yazEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMSUwIwYJ
8+
KoZIhvcNAQkBFhZwY2FwcGx1c3BsdXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0B
9+
AQEFAAOCAQ8AMIIBCgKCAQEAqDIKWbgU655OiCKNmrjU/yhiFMsx79ROgwn3s4XL
10+
XQzx0T1RkA4gA9JBLs4vqEvjg28eeTCGA9K360JjnjQztggWEU4/18UtM2U5ogNj
11+
BGmKLFAaz92wnzW2Ra7rUowMXl97SylhqhSBL4BsNZ4EntqL1Y4IcV29UVxOzCHY
12+
K2km0uwgedwJ7p0b7rQIeiZS1mSI1f1HQ/M9aeeV1gdT8OJRltVCvFkhY9p9L52Z
13+
0t6szCFARadqiZPWtoessQjK2p0N26wiW5rXPisqFt2lyDkXWQ16sk+xENukfb6h
14+
SiY5h20MPyNT3vOpkWq0jwqwIhittD18kcfqXJBul5714QIDAQABMA0GCSqGSIb3
15+
DQEBCwUAA4IBAQBe+gxZahT2J++/8ddn7MXqW4qKgcOeT1KWxvMj8Iwt6Ozmpsjs
16+
7c2e3iARS9JY0//7gXSKDJfrc1wowNab/eJ273oXZtneDahNpRqQ/fD8x1hW+oFW
17+
UTUPHNFIr1CrpfhtwT28hFxcPUNeEeiUpLnWuSLyTMm1Lb5+0xkovInBUKh/2p5t
18+
QO0E+sbAnRcFjpQd7pNsNz9kmcybxWHGjA8b7vRNNk3+2tLiMz/TGSnvQYU4gAOW
19+
ClA3U7E4zKVTR1WBEFQzfdMCHKpQPGtrqlnJRYhmSRm8cAHsKKI9OgceV7NWE2ZE
20+
trVp0+8pBZ9DExV5n2wtBHeaujDolG/TCGBr
21+
-----END CERTIFICATE-----

Tests/Packet++Test/Tests/X509Tests.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,14 @@ PTF_TEST_CASE(X509VariantsParsingTest)
329329
auto x509Cert = pcpp::X509Certificate::fromDERFile("PacketExamples/x509_cert_serial_lead_zeros.der");
330330
PTF_ASSERT_EQUAL(x509Cert->getSerialNumber().toString(), "80");
331331
}
332+
333+
// No version and extensions fields
334+
{
335+
auto x509Cert = pcpp::X509Certificate::fromPEMFile("PacketExamples/x509_cert_no_version_extension_fields.pem");
336+
PTF_ASSERT_EQUAL(x509Cert->getVersion(), pcpp::X509Version::V1, enumclass);
337+
PTF_ASSERT_EQUAL(x509Cert->getNotBefore().toString(), "2025-08-17 08:27:07");
338+
PTF_ASSERT_EQUAL(x509Cert->getExtensions().size(), 0);
339+
}
332340
}
333341

334342
PTF_TEST_CASE(X509InvalidDataTest)

0 commit comments

Comments
 (0)