diff options
author | eroman <eroman@chromium.org> | 2015-11-10 20:24:29 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-11 04:25:20 +0000 |
commit | 7b97d82c73a604053f0ac6b5539984e95bb14561 (patch) | |
tree | f80f4b1f284bf29c0c4338174e12e81c2e45248c | |
parent | a91f4345158a5cd33931325312703a4e294512d0 (diff) | |
download | chromium_src-7b97d82c73a604053f0ac6b5539984e95bb14561.zip chromium_src-7b97d82c73a604053f0ac6b5539984e95bb14561.tar.gz chromium_src-7b97d82c73a604053f0ac6b5539984e95bb14561.tar.bz2 |
Add a function to parse RFC 5280 "Extensions".
BUG=410574
Review URL: https://codereview.chromium.org/1415293004
Cr-Commit-Position: refs/heads/master@{#359050}
15 files changed, 552 insertions, 0 deletions
diff --git a/net/cert/internal/parse_certificate.cc b/net/cert/internal/parse_certificate.cc index d2bc980..3247381 100644 --- a/net/cert/internal/parse_certificate.cc +++ b/net/cert/internal/parse_certificate.cc @@ -4,6 +4,8 @@ #include "net/cert/internal/parse_certificate.h" +#include <utility> + #include "net/der/input.h" #include "net/der/parse_values.h" #include "net/der/parser.h" @@ -405,4 +407,117 @@ bool ParseExtension(const der::Input& extension_tlv, ParsedExtension* out) { return true; } +der::Input KeyUsageOid() { + // From RFC 5280: + // + // id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } + // + // In dotted notation: 2.5.29.15 + static const uint8_t oid[] = {0x55, 0x1d, 0x0f}; + return der::Input(oid); +} + +der::Input SubjectAltNameOid() { + // From RFC 5280: + // + // id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } + // + // In dotted notation: 2.5.29.17 + static const uint8_t oid[] = {0x55, 0x1d, 0x11}; + return der::Input(oid); +} + +der::Input BasicConstraintsOid() { + // From RFC 5280: + // + // id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } + // + // In dotted notation: 2.5.29.19 + static const uint8_t oid[] = {0x55, 0x1d, 0x13}; + return der::Input(oid); +} + +der::Input NameConstraintsOid() { + // From RFC 5280: + // + // id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } + // + // In dotted notation: 2.5.29.30 + static const uint8_t oid[] = {0x55, 0x1d, 0x1e}; + return der::Input(oid); +} + +der::Input CertificatePoliciesOid() { + // From RFC 5280: + // + // id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + // + // In dotted notation: 2.5.29.32 + static const uint8_t oid[] = {0x55, 0x1d, 0x20}; + return der::Input(oid); +} + +der::Input PolicyConstraintsOid() { + // From RFC 5280: + // + // id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } + // + // In dotted notation: 2.5.29.36 + static const uint8_t oid[] = {0x55, 0x1d, 0x24}; + return der::Input(oid); +} + +der::Input ExtKeyUsageOid() { + // From RFC 5280: + // + // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } + // + // In dotted notation: 2.5.29.37 + static const uint8_t oid[] = {0x55, 0x1d, 0x25}; + return der::Input(oid); +} + +NET_EXPORT bool ParseExtensions( + const der::Input& extensions_tlv, + std::map<der::Input, ParsedExtension>* extensions) { + der::Parser parser(extensions_tlv); + + // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + der::Parser extensions_parser; + if (!parser.ReadSequence(&extensions_parser)) + return false; + + // The Extensions SEQUENCE must contains at least 1 element (otherwise it + // should have been omitted). + if (!extensions_parser.HasMore()) + return false; + + extensions->clear(); + + while (extensions_parser.HasMore()) { + ParsedExtension extension; + + der::Input extension_tlv; + if (!extensions_parser.ReadRawTLV(&extension_tlv)) + return false; + + if (!ParseExtension(extension_tlv, &extension)) + return false; + + bool is_duplicate = + !extensions->insert(std::make_pair(extension.oid, extension)).second; + + // RFC 5280 says that an extension should not appear more than once. + if (is_duplicate) + return false; + } + + // By definition the input was a single Extensions sequence, so there + // shouldn't be unconsumed data. + if (parser.HasMore()) + return false; + + return true; +} + } // namespace net diff --git a/net/cert/internal/parse_certificate.h b/net/cert/internal/parse_certificate.h index 7d2d826..3980695 100644 --- a/net/cert/internal/parse_certificate.h +++ b/net/cert/internal/parse_certificate.h @@ -5,6 +5,8 @@ #ifndef NET_CERT_INTERNAL_PARSE_CERTIFICATE_H_ #define NET_CERT_INTERNAL_PARSE_CERTIFICATE_H_ +#include <map> + #include "base/basictypes.h" #include "base/compiler_specific.h" #include "net/base/net_export.h" @@ -245,6 +247,67 @@ struct NET_EXPORT ParsedExtension { NET_EXPORT bool ParseExtension(const der::Input& extension_tlv, ParsedExtension* out) WARN_UNUSED_RESULT; +// From RFC 5280: +// +// id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } +// +// In dotted notation: 2.5.29.15 +NET_EXPORT der::Input KeyUsageOid(); + +// From RFC 5280: +// +// id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } +// +// In dotted notation: 2.5.29.17 +NET_EXPORT der::Input SubjectAltNameOid(); + +// From RFC 5280: +// +// id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } +// +// In dotted notation: 2.5.29.19 +NET_EXPORT der::Input BasicConstraintsOid(); + +// From RFC 5280: +// +// id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } +// +// In dotted notation: 2.5.29.30 +NET_EXPORT der::Input NameConstraintsOid(); + +// From RFC 5280: +// +// id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } +// +// In dotted notation: 2.5.29.32 +NET_EXPORT der::Input CertificatePoliciesOid(); + +// From RFC 5280: +// +// id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } +// +// In dotted notation: 2.5.29.36 +NET_EXPORT der::Input PolicyConstraintsOid(); + +// From RFC 5280: +// +// id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } +// +// In dotted notation: 2.5.29.37 +NET_EXPORT der::Input ExtKeyUsageOid(); + +// Parses the Extensions sequence as defined by RFC 5280. Extensions are added +// to the map |extensions| keyed by the OID. Parsing guarantees that each OID +// is unique. Note that certificate verification must consume each extension +// marked as critical. +// +// Returns true on success and fills |extensions|. The output will reference +// bytes in |extensions_tlv|, so that data must be kept alive. +// On failure |extensions| may be partially written to and should not be used. +NET_EXPORT bool ParseExtensions( + const der::Input& extensions_tlv, + std::map<der::Input, ParsedExtension>* extensions) WARN_UNUSED_RESULT; + } // namespace net #endif // NET_CERT_INTERNAL_PARSE_CERTIFICATE_H_ diff --git a/net/cert/internal/parse_certificate_unittest.cc b/net/cert/internal/parse_certificate_unittest.cc index 99312cd..5292e5b 100644 --- a/net/cert/internal/parse_certificate_unittest.cc +++ b/net/cert/internal/parse_certificate_unittest.cc @@ -391,6 +391,196 @@ TEST(ParseExtensionTest, Critical3) { ParseExtensionFromFile("extension_critical_3.pem", &extension, &data)); } +// Runs a test for extensions parsing. The input file is a PEM file which +// contains a DER-encoded Extensions sequence, as well as the expected value +// for each contained extension. +void EnsureParsingExtensionsSucceeds( + const std::string& file_name, + std::map<der::Input, ParsedExtension>* extensions, + std::string* data) { + const PemBlockMapping mappings[] = { + // Test Input. + {"EXTENSIONS", data}, + }; + + ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); + ASSERT_TRUE(ParseExtensions(InputFromString(data), extensions)); +} + +// Runs a test that verifies extensions parsing fails. The input file is a PEM +// file which contains a DER-encoded Extensions sequence. +void EnsureParsingExtensionsFails(const std::string& file_name) { + std::string data; + + const PemBlockMapping mappings[] = { + {"EXTENSIONS", &data}, + }; + + std::map<der::Input, ParsedExtension> extensions; + ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); + ASSERT_FALSE(ParseExtensions(InputFromString(&data), &extensions)); +} + +// Parses an Extensions that is an empty sequence. +TEST(ParseExtensionsTest, EmptySequence) { + EnsureParsingExtensionsFails("extensions_empty_sequence.pem"); +} + +// Parses an Extensions that is not a sequence. +TEST(ParseExtensionsTest, NotSequence) { + EnsureParsingExtensionsFails("extensions_not_sequence.pem"); +} + +// Parses an Extensions that has data after the sequence. +TEST(ParseExtensionsTest, DataAfterSequence) { + EnsureParsingExtensionsFails("extensions_data_after_sequence.pem"); +} + +// Parses an Extensions that contains duplicated key usages. +TEST(ParseExtensionsTest, DuplicateKeyUsage) { + EnsureParsingExtensionsFails("extensions_duplicate_key_usage.pem"); +} + +// Parses an Extensions that contains an unknown critical extension. +TEST(ParseExtensionsTest, UnknownCritical) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_unknown_critical.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + // This OID corresponds with + // 1.2.840.113554.4.1.72585.0 (https://davidben.net/oid) + const uint8_t oid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, + 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00}; + + auto iter = extensions.find(der::Input(oid)); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(4u, iter->second.value.Length()); +} + +// Parses an Extensions that contains an unknown non-critical extension. +TEST(ParseExtensionsTest, UnknownNonCritical) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_unknown_non_critical.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + // This OID corresponds with + // 1.2.840.113554.4.1.72585.0 (https://davidben.net/oid) + const uint8_t oid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, + 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00}; + + auto iter = extensions.find(der::Input(oid)); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(4u, iter->second.value.Length()); +} + +// Parses an Extensions that contains a basic constraints. +TEST(ParseExtensionsTest, BasicConstraints) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_basic_constraints.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(BasicConstraintsOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(2u, iter->second.value.Length()); +} + +// Parses an Extensions that contains an extended key usages. +TEST(ParseExtensionsTest, ExtendedKeyUsage) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_extended_key_usage.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(ExtKeyUsageOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(45u, iter->second.value.Length()); +} + +// Parses an Extensions that contains a key usage. +TEST(ParseExtensionsTest, KeyUsage) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_key_usage.pem", &extensions, + &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(KeyUsageOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(4u, iter->second.value.Length()); +} + +// Parses an Extensions that contains a policies extension. +TEST(ParseExtensionsTest, Policies) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_policies.pem", &extensions, + &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(CertificatePoliciesOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(95u, iter->second.value.Length()); +} + +// Parses an Extensions that contains a subjectaltname extension. +TEST(ParseExtensionsTest, SubjectAltName) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_subject_alt_name.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(SubjectAltNameOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(23u, iter->second.value.Length()); +} + +// Parses an Extensions that contains multiple extensions, sourced from a +// real-world certificate. +TEST(ParseExtensionsTest, Real) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_real.pem", &extensions, &data); + + ASSERT_EQ(7u, extensions.size()); + + auto iter = extensions.find(KeyUsageOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(4u, iter->second.value.Length()); + + iter = extensions.find(BasicConstraintsOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(8u, iter->second.value.Length()); + + iter = extensions.find(CertificatePoliciesOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(16u, iter->second.value.Length()); + + // TODO(eroman): Verify the other 4 extensions' values. +} + } // namespace } // namespace net diff --git a/net/data/parse_certificate_unittest/extensions_basic_constraints.pem b/net/data/parse_certificate_unittest/extensions_basic_constraints.pem new file mode 100644 index 0000000..211cef0 --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_basic_constraints.pem @@ -0,0 +1,16 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 14 cons: SEQUENCE + 2:d=1 hl=2 l= 12 cons: SEQUENCE + 4:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Basic Constraints + 9:d=2 hl=2 l= 1 prim: BOOLEAN :255 + 12:d=2 hl=2 l= 2 prim: OCTET STRING [HEX DUMP]:3000 +-----BEGIN EXTENSIONS----- +MA4wDAYDVR0TAQH/BAIwAA== +-----END EXTENSIONS----- + +$ openssl asn1parse -i < [BASIC CONSTRAINTS] + 0:d=0 hl=2 l= 0 cons: SEQUENCE +-----BEGIN BASIC CONSTRAINTS----- +MAA= +-----END BASIC CONSTRAINTS----- + diff --git a/net/data/parse_certificate_unittest/extensions_data_after_sequence.pem b/net/data/parse_certificate_unittest/extensions_data_after_sequence.pem new file mode 100644 index 0000000..5bf26ac --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_data_after_sequence.pem @@ -0,0 +1,11 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 18 cons: SEQUENCE + 2:d=1 hl=2 l= 14 cons: SEQUENCE + 4:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Key Usage + 9:d=2 hl=2 l= 1 prim: BOOLEAN :255 + 12:d=2 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:030203B8 + 18:d=1 hl=2 l= 0 prim: NULL +-----BEGIN EXTENSIONS----- +MBIwDgYDVR0PAQH/BAQDAgO4BQA= +-----END EXTENSIONS----- + diff --git a/net/data/parse_certificate_unittest/extensions_duplicate_key_usage.pem b/net/data/parse_certificate_unittest/extensions_duplicate_key_usage.pem new file mode 100644 index 0000000..c263384 --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_duplicate_key_usage.pem @@ -0,0 +1,14 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 32 cons: SEQUENCE + 2:d=1 hl=2 l= 14 cons: SEQUENCE + 4:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Key Usage + 9:d=2 hl=2 l= 1 prim: BOOLEAN :255 + 12:d=2 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:030203B8 + 18:d=1 hl=2 l= 14 cons: SEQUENCE + 20:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Key Usage + 25:d=2 hl=2 l= 1 prim: BOOLEAN :255 + 28:d=2 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:030203B8 +-----BEGIN EXTENSIONS----- +MCAwDgYDVR0PAQH/BAQDAgO4MA4GA1UdDwEB/wQEAwIDuA== +-----END EXTENSIONS----- + diff --git a/net/data/parse_certificate_unittest/extensions_empty_sequence.pem b/net/data/parse_certificate_unittest/extensions_empty_sequence.pem new file mode 100644 index 0000000..d3f1a73 --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_empty_sequence.pem @@ -0,0 +1,6 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 0 cons: SEQUENCE +-----BEGIN EXTENSIONS----- +MAA= +-----END EXTENSIONS----- + diff --git a/net/data/parse_certificate_unittest/extensions_extended_key_usage.pem b/net/data/parse_certificate_unittest/extensions_extended_key_usage.pem new file mode 100644 index 0000000..9cda6e2 --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_extended_key_usage.pem @@ -0,0 +1,20 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 54 cons: SEQUENCE + 2:d=1 hl=2 l= 52 cons: SEQUENCE + 4:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Extended Key Usage + 9:d=2 hl=2 l= 45 prim: OCTET STRING [HEX DUMP]:302B06082B0601050507030106082B06010505070302060A2B0601040182370A030306096086480186F8420401 +-----BEGIN EXTENSIONS----- +MDYwNAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBgorBgEEAYI3CgMDBglghkgBhvhCBAE += +-----END EXTENSIONS----- + +$ openssl asn1parse -i < [EXTENDED KEY USAGE] + 0:d=0 hl=2 l= 43 cons: SEQUENCE + 2:d=1 hl=2 l= 8 prim: OBJECT :TLS Web Server Authentication + 12:d=1 hl=2 l= 8 prim: OBJECT :TLS Web Client Authentication + 22:d=1 hl=2 l= 10 prim: OBJECT :Microsoft Server Gated Crypto + 34:d=1 hl=2 l= 9 prim: OBJECT :Netscape Server Gated Crypto +-----BEGIN EXTENDED KEY USAGE----- +MCsGCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAwYJYIZIAYb4QgQB +-----END EXTENDED KEY USAGE----- + diff --git a/net/data/parse_certificate_unittest/extensions_key_usage.pem b/net/data/parse_certificate_unittest/extensions_key_usage.pem new file mode 100644 index 0000000..1b56edd --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_key_usage.pem @@ -0,0 +1,16 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 16 cons: SEQUENCE + 2:d=1 hl=2 l= 14 cons: SEQUENCE + 4:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Key Usage + 9:d=2 hl=2 l= 1 prim: BOOLEAN :255 + 12:d=2 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:030205A0 +-----BEGIN EXTENSIONS----- +MBAwDgYDVR0PAQH/BAQDAgWg +-----END EXTENSIONS----- + +$ openssl asn1parse -i < [KEY USAGE] + 0:d=0 hl=2 l= 2 prim: BIT STRING +-----BEGIN KEY USAGE----- +AwIFoA== +-----END KEY USAGE----- + diff --git a/net/data/parse_certificate_unittest/extensions_not_sequence.pem b/net/data/parse_certificate_unittest/extensions_not_sequence.pem new file mode 100644 index 0000000..f8cb11b --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_not_sequence.pem @@ -0,0 +1,6 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 0 prim: NULL +-----BEGIN EXTENSIONS----- +BQA= +-----END EXTENSIONS----- + diff --git a/net/data/parse_certificate_unittest/extensions_policies.pem b/net/data/parse_certificate_unittest/extensions_policies.pem new file mode 100644 index 0000000..79a1c90 --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_policies.pem @@ -0,0 +1,25 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 104 cons: SEQUENCE + 2:d=1 hl=2 l= 102 cons: SEQUENCE + 4:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Certificate Policies + 9:d=2 hl=2 l= 95 prim: OCTET STRING [HEX DUMP]:305D304D060A2A83088C9C1E01020201303F303D06082B06010505070201163168747470733A2F2F7265706F312E7365636F6D74727573742E6E65742F73706370702F6370732F696E6465782E68746D6C300C060A2A83088C9B1B64870501 +-----BEGIN EXTENSIONS----- +MGgwZgYDVR0gBF8wXTBNBgoqgwiMnB4BAgIBMD8wPQYIKwYBBQUHAgEWMWh0dHBzOi8vcmVwbzE +uc2Vjb210cnVzdC5uZXQvc3BjcHAvY3BzL2luZGV4Lmh0bWwwDAYKKoMIjJsbZIcFAQ== +-----END EXTENSIONS----- + +$ openssl asn1parse -i < [POLICIES] + 0:d=0 hl=2 l= 93 cons: SEQUENCE + 2:d=1 hl=2 l= 77 cons: SEQUENCE + 4:d=2 hl=2 l= 10 prim: OBJECT :1.2.392.200222.1.2.2.1 + 16:d=2 hl=2 l= 63 cons: SEQUENCE + 18:d=3 hl=2 l= 61 cons: SEQUENCE + 20:d=4 hl=2 l= 8 prim: OBJECT :Policy Qualifier CPS + 30:d=4 hl=2 l= 49 prim: IA5STRING :https://repo1.secomtrust.net/spcpp/cps/index.html + 81:d=1 hl=2 l= 12 cons: SEQUENCE + 83:d=2 hl=2 l= 10 prim: OBJECT :1.2.392.200091.100.901.1 +-----BEGIN POLICIES----- +MF0wTQYKKoMIjJweAQICATA/MD0GCCsGAQUFBwIBFjFodHRwczovL3JlcG8xLnNlY29tdHJ1c3Q +ubmV0L3NwY3BwL2Nwcy9pbmRleC5odG1sMAwGCiqDCIybG2SHBQE= +-----END POLICIES----- + diff --git a/net/data/parse_certificate_unittest/extensions_real.pem b/net/data/parse_certificate_unittest/extensions_real.pem new file mode 100644 index 0000000..5ece71c --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_real.pem @@ -0,0 +1,35 @@ +A real world extensions sequence (taken from Google's GAI2). + +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=3 l= 228 cons: SEQUENCE + 3:d=1 hl=2 l= 31 cons: SEQUENCE + 5:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Authority Key Identifier + 10:d=2 hl=2 l= 24 prim: OCTET STRING [HEX DUMP]:30168014C07A98688D89FBAB05640C117DAA7D65B8CACC4E + 36:d=1 hl=2 l= 29 cons: SEQUENCE + 38:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Subject Key Identifier + 43:d=2 hl=2 l= 22 prim: OCTET STRING [HEX DUMP]:04144ADD06161BBCF668B576F581B6BB621ABA5A812F + 67:d=1 hl=2 l= 14 cons: SEQUENCE + 69:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Key Usage + 74:d=2 hl=2 l= 1 prim: BOOLEAN :255 + 77:d=2 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:03020106 + 83:d=1 hl=2 l= 46 cons: SEQUENCE + 85:d=2 hl=2 l= 8 prim: OBJECT :Authority Information Access + 95:d=2 hl=2 l= 34 prim: OCTET STRING [HEX DUMP]:3020301E06082B060105050730018612687474703A2F2F672E73796D63642E636F6D + 131:d=1 hl=2 l= 18 cons: SEQUENCE + 133:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Basic Constraints + 138:d=2 hl=2 l= 1 prim: BOOLEAN :255 + 141:d=2 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:30060101FF020100 + 151:d=1 hl=2 l= 53 cons: SEQUENCE + 153:d=2 hl=2 l= 3 prim: OBJECT :X509v3 CRL Distribution Points + 158:d=2 hl=2 l= 46 prim: OCTET STRING [HEX DUMP]:302C302AA028A0268624687474703A2F2F672E73796D63622E636F6D2F63726C732F6774676C6F62616C2E63726C + 206:d=1 hl=2 l= 23 cons: SEQUENCE + 208:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Certificate Policies + 213:d=2 hl=2 l= 16 prim: OCTET STRING [HEX DUMP]:300E300C060A2B06010401D679020501 +-----BEGIN EXTENSIONS----- +MIHkMB8GA1UdIwQYMBaAFMB6mGiNifurBWQMEX2qfWW4ysxOMB0GA1UdDgQWBBRK3QYWG7z2aLV +29YG2u2IaulqBLzAOBgNVHQ8BAf8EBAMCAQYwLgYIKwYBBQUHAQEEIjAgMB4GCCsGAQUFBzABhh +JodHRwOi8vZy5zeW1jZC5jb20wEgYDVR0TAQH/BAgwBgEB/wIBADA1BgNVHR8ELjAsMCqgKKAmh +iRodHRwOi8vZy5zeW1jYi5jb20vY3Jscy9ndGdsb2JhbC5jcmwwFwYDVR0gBBAwDjAMBgorBgEE +AdZ5AgUB +-----END EXTENSIONS----- + diff --git a/net/data/parse_certificate_unittest/extensions_subject_alt_name.pem b/net/data/parse_certificate_unittest/extensions_subject_alt_name.pem new file mode 100644 index 0000000..3ce5fda --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_subject_alt_name.pem @@ -0,0 +1,16 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 32 cons: SEQUENCE + 2:d=1 hl=2 l= 30 cons: SEQUENCE + 4:d=2 hl=2 l= 3 prim: OBJECT :X509v3 Subject Alternative Name + 9:d=2 hl=2 l= 23 prim: OCTET STRING [HEX DUMP]:30158213656D657267656E6379737570706F72742E7573 +-----BEGIN EXTENSIONS----- +MCAwHgYDVR0RBBcwFYITZW1lcmdlbmN5c3VwcG9ydC51cw== +-----END EXTENSIONS----- + +$ openssl asn1parse -i < [SUBJECT ALT NAME] + 0:d=0 hl=2 l= 21 cons: SEQUENCE + 2:d=1 hl=2 l= 19 prim: cont [ 2 ] +-----BEGIN SUBJECT ALT NAME----- +MBWCE2VtZXJnZW5jeXN1cHBvcnQudXM= +-----END SUBJECT ALT NAME----- + diff --git a/net/data/parse_certificate_unittest/extensions_unknown_critical.pem b/net/data/parse_certificate_unittest/extensions_unknown_critical.pem new file mode 100644 index 0000000..3913615 --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_unknown_critical.pem @@ -0,0 +1,10 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 25 cons: SEQUENCE + 2:d=1 hl=2 l= 23 cons: SEQUENCE + 4:d=2 hl=2 l= 12 prim: OBJECT :1.2.840.113554.4.1.72585.0 + 18:d=2 hl=2 l= 1 prim: BOOLEAN :255 + 21:d=2 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:030203B8 +-----BEGIN EXTENSIONS----- +MBkwFwYMKoZIhvcSBAGEtwkAAQH/BAQDAgO4 +-----END EXTENSIONS----- + diff --git a/net/data/parse_certificate_unittest/extensions_unknown_non_critical.pem b/net/data/parse_certificate_unittest/extensions_unknown_non_critical.pem new file mode 100644 index 0000000..532cb2ab --- /dev/null +++ b/net/data/parse_certificate_unittest/extensions_unknown_non_critical.pem @@ -0,0 +1,9 @@ +$ openssl asn1parse -i < [EXTENSIONS] + 0:d=0 hl=2 l= 22 cons: SEQUENCE + 2:d=1 hl=2 l= 20 cons: SEQUENCE + 4:d=2 hl=2 l= 12 prim: OBJECT :1.2.840.113554.4.1.72585.0 + 18:d=2 hl=2 l= 4 prim: OCTET STRING [HEX DUMP]:030203B8 +-----BEGIN EXTENSIONS----- +MBYwFAYMKoZIhvcSBAGEtwkABAQDAgO4 +-----END EXTENSIONS----- + |