1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/cert/internal/parse_certificate.h"
7 #include "net/cert/internal/test_helpers.h"
8 #include "net/der/input.h"
9 #include "testing/gtest/include/gtest/gtest.h"
15 std::string
GetFilePath(const std::string file_name
) {
16 return std::string("net/data/parse_certificate_unittest/") + file_name
;
19 // Loads certificate data and expectations from the PEM file |file_name|.
20 // Verifies that parsing the Certificate succeeds, and each parsed field matches
22 void EnsureParsingCertificateSucceeds(const std::string
& file_name
) {
24 std::string expected_tbs_certificate
;
25 std::string expected_signature_algorithm
;
26 std::string expected_signature
;
28 // Read the certificate data and test expectations from a single PEM file.
29 const PemBlockMapping mappings
[] = {
30 {"CERTIFICATE", &data
},
31 {"SIGNATURE", &expected_signature
},
32 {"SIGNATURE ALGORITHM", &expected_signature_algorithm
},
33 {"TBS CERTIFICATE", &expected_tbs_certificate
},
35 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name
), mappings
));
37 // Parsing the certificate should succeed.
38 ParsedCertificate parsed
;
39 ASSERT_TRUE(ParseCertificate(InputFromString(&data
), &parsed
));
41 // Ensure that the ParsedCertificate matches expectations.
42 EXPECT_EQ(0, parsed
.signature_value
.unused_bits());
43 EXPECT_EQ(InputFromString(&expected_signature
),
44 parsed
.signature_value
.bytes());
45 EXPECT_EQ(InputFromString(&expected_signature_algorithm
),
46 parsed
.signature_algorithm_tlv
);
47 EXPECT_EQ(InputFromString(&expected_tbs_certificate
),
48 parsed
.tbs_certificate_tlv
);
51 // Loads certificate data from the PEM file |file_name| and verifies that the
52 // Certificate parsing fails.
53 void EnsureParsingCertificateFails(const std::string
& file_name
) {
56 const PemBlockMapping mappings
[] = {
57 {"CERTIFICATE", &data
},
60 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name
), mappings
));
62 // Parsing the Certificate should fail.
63 ParsedCertificate parsed
;
64 ASSERT_FALSE(ParseCertificate(InputFromString(&data
), &parsed
));
67 // Tests parsing a Certificate.
68 TEST(ParseCertificateTest
, Version3
) {
69 EnsureParsingCertificateSucceeds("cert_version3.pem");
72 // Tests parsing a simplified Certificate-like structure (the sub-fields for
73 // algorithm and tbsCertificate are not actually valid, but ParseCertificate()
74 // doesn't check them)
75 TEST(ParseCertificateTest
, Skeleton
) {
76 EnsureParsingCertificateSucceeds("cert_skeleton.pem");
79 // Tests parsing a Certificate that is not a sequence fails.
80 TEST(ParseCertificateTest
, NotSequence
) {
81 EnsureParsingCertificateFails("cert_not_sequence.pem");
84 // Tests that uncomsumed data is not allowed after the main SEQUENCE.
85 TEST(ParseCertificateTest
, DataAfterSignature
) {
86 EnsureParsingCertificateFails("cert_data_after_signature.pem");
89 // Tests that parsing fails if the signature BIT STRING is missing.
90 TEST(ParseCertificateTest
, MissingSignature
) {
91 EnsureParsingCertificateFails("cert_missing_signature.pem");
94 // Tests that parsing fails if the signature is present but not a BIT STRING.
95 TEST(ParseCertificateTest
, SignatureNotBitString
) {
96 EnsureParsingCertificateFails("cert_signature_not_bit_string.pem");
99 // Tests that parsing fails if the main SEQUENCE is empty (missing all the
101 TEST(ParseCertificateTest
, EmptySequence
) {
102 EnsureParsingCertificateFails("cert_empty_sequence.pem");
105 // Tests what happens when the signature algorithm is present, but has the wrong
107 TEST(ParseCertificateTest
, AlgorithmNotSequence
) {
108 EnsureParsingCertificateFails("cert_algorithm_not_sequence.pem");
111 // Loads tbsCertificate data and expectations from the PEM file |file_name|.
112 // Verifies that parsing the TBSCertificate succeeds, and each parsed field
113 // matches the expectations.
114 void EnsureParsingTbsSucceeds(const std::string
& file_name
,
115 CertificateVersion expected_version
) {
117 std::string expected_serial_number
;
118 std::string expected_signature_algorithm
;
119 std::string expected_issuer
;
120 std::string expected_validity
;
121 std::string expected_subject
;
122 std::string expected_spki
;
123 std::string expected_issuer_unique_id
;
124 std::string expected_subject_unique_id
;
125 std::string expected_extensions
;
127 // Read the certificate data and test expectations from a single PEM file.
128 const PemBlockMapping mappings
[] = {
129 {"TBS CERTIFICATE", &data
},
130 {"SIGNATURE ALGORITHM", &expected_signature_algorithm
},
131 {"SERIAL NUMBER", &expected_serial_number
},
132 {"ISSUER", &expected_issuer
},
133 {"VALIDITY", &expected_validity
},
134 {"SUBJECT", &expected_subject
},
135 {"SPKI", &expected_spki
},
136 {"ISSUER UNIQUE ID", &expected_issuer_unique_id
, true},
137 {"SUBJECT UNIQUE ID", &expected_subject_unique_id
, true},
138 {"EXTENSIONS", &expected_extensions
, true},
140 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name
), mappings
));
142 // Parsing the TBSCertificate should succeed.
143 ParsedTbsCertificate parsed
;
144 ASSERT_TRUE(ParseTbsCertificate(InputFromString(&data
), &parsed
));
146 // Ensure that the ParsedTbsCertificate matches expectations.
147 EXPECT_EQ(expected_version
, parsed
.version
);
149 EXPECT_EQ(InputFromString(&expected_serial_number
), parsed
.serial_number
);
150 EXPECT_EQ(InputFromString(&expected_signature_algorithm
),
151 parsed
.signature_algorithm_tlv
);
153 EXPECT_EQ(InputFromString(&expected_issuer
), parsed
.issuer_tlv
);
154 EXPECT_EQ(InputFromString(&expected_validity
), parsed
.validity_tlv
);
155 EXPECT_EQ(InputFromString(&expected_subject
), parsed
.subject_tlv
);
156 EXPECT_EQ(InputFromString(&expected_spki
), parsed
.spki_tlv
);
158 EXPECT_EQ(InputFromString(&expected_issuer_unique_id
),
159 parsed
.issuer_unique_id
.bytes());
160 EXPECT_EQ(!expected_issuer_unique_id
.empty(), parsed
.has_issuer_unique_id
);
161 EXPECT_EQ(InputFromString(&expected_subject_unique_id
),
162 parsed
.subject_unique_id
.bytes());
163 EXPECT_EQ(!expected_subject_unique_id
.empty(), parsed
.has_subject_unique_id
);
165 EXPECT_EQ(InputFromString(&expected_extensions
), parsed
.extensions_tlv
);
166 EXPECT_EQ(!expected_extensions
.empty(), parsed
.has_extensions
);
169 // Loads certificate data from the PEM file |file_name| and verifies that the
170 // Certificate parsing succeed, however the TBSCertificate parsing fails.
171 void EnsureParsingTbsFails(const std::string
& file_name
) {
174 const PemBlockMapping mappings
[] = {
175 {"TBS CERTIFICATE", &data
},
178 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name
), mappings
));
180 // Parsing the TBSCertificate should fail.
181 ParsedTbsCertificate parsed
;
182 ASSERT_FALSE(ParseTbsCertificate(InputFromString(&data
), &parsed
));
185 // Tests parsing a TBSCertificate for v3 that contains no optional fields.
186 TEST(ParseTbsCertificateTest
, Version3NoOptionals
) {
187 EnsureParsingTbsSucceeds("tbs_v3_no_optionals.pem", CertificateVersion::V3
);
190 // Tests parsing a TBSCertificate for v3 that contains extensions.
191 TEST(ParseTbsCertificateTest
, Version3WithExtensions
) {
192 EnsureParsingTbsSucceeds("tbs_v3_extensions.pem", CertificateVersion::V3
);
195 // Tests parsing a TBSCertificate for v3 that contains no optional fields, and
196 // has a negative serial number.
198 // CAs are not supposed to include negative serial numbers, however RFC 5280
199 // expects consumers to deal with it anyway).
200 TEST(ParseTbsCertificateTest
, NegativeSerialNumber
) {
201 EnsureParsingTbsSucceeds("tbs_negative_serial_number.pem",
202 CertificateVersion::V3
);
205 // Tests parsing a TBSCertificate with a serial number that is 21 octets long
206 // (and the first byte is 0).
207 TEST(ParseTbCertificateTest
, SerialNumber21OctetsLeading0
) {
208 EnsureParsingTbsFails("tbs_serial_number_21_octets_leading_0.pem");
211 // Tests parsing a TBSCertificate with a serial number that is 26 octets long
212 // (and does not contain a leading 0).
213 TEST(ParseTbsCertificateTest
, SerialNumber26Octets
) {
214 EnsureParsingTbsFails("tbs_serial_number_26_octets.pem");
217 // Tests parsing a TBSCertificate which lacks a version number (causing it to
219 TEST(ParseTbsCertificateTest
, Version1
) {
220 EnsureParsingTbsSucceeds("tbs_v1.pem", CertificateVersion::V1
);
223 // The version was set to v1 explicitly rather than omitting the version field.
224 TEST(ParseTbsCertificateTest
, ExplicitVersion1
) {
225 EnsureParsingTbsFails("tbs_explicit_v1.pem");
228 // Extensions are not defined in version 1.
229 TEST(ParseTbsCertificateTest
, Version1WithExtensions
) {
230 EnsureParsingTbsFails("tbs_v1_extensions.pem");
233 // Extensions are not defined in version 2.
234 TEST(ParseTbsCertificateTest
, Version2WithExtensions
) {
235 EnsureParsingTbsFails("tbs_v2_extensions.pem");
238 // A boring version 2 certificate with none of the optional fields.
239 TEST(ParseTbsCertificateTest
, Version2NoOptionals
) {
240 EnsureParsingTbsSucceeds("tbs_v2_no_optionals.pem", CertificateVersion::V2
);
243 // A version 2 certificate with an issuer unique ID field.
244 TEST(ParseTbsCertificateTest
, Version2IssuerUniqueId
) {
245 EnsureParsingTbsSucceeds("tbs_v2_issuer_unique_id.pem",
246 CertificateVersion::V2
);
249 // A version 2 certificate with both a issuer and subject unique ID field.
250 TEST(ParseTbsCertificateTest
, Version2IssuerAndSubjectUniqueId
) {
251 EnsureParsingTbsSucceeds("tbs_v2_issuer_and_subject_unique_id.pem",
252 CertificateVersion::V2
);
255 // A version 3 certificate with all of the optional fields (issuer unique id,
256 // subject unique id, and extensions).
257 TEST(ParseTbsCertificateTest
, Version3AllOptionals
) {
258 EnsureParsingTbsSucceeds("tbs_v3_all_optionals.pem", CertificateVersion::V3
);
261 // The version was set to v4, which is unrecognized.
262 TEST(ParseTbsCertificateTest
, Version4
) {
263 EnsureParsingTbsFails("tbs_v4.pem");
266 // Tests that extraneous data after extensions in a v3 is rejected.
267 TEST(ParseTbsCertificateTest
, Version3DataAfterExtensions
) {
268 EnsureParsingTbsFails("tbs_v3_data_after_extensions.pem");
271 // Tests using a real-world certificate (whereas the other tests are fabricated
272 // (and in fact invalid) data.
273 TEST(ParseTbsCertificateTest
, Version3Real
) {
274 EnsureParsingTbsSucceeds("tbs_v3_real.pem", CertificateVersion::V3
);