Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / cert / internal / parse_certificate_unittest.cc
blobcf6da4afc82bb57b8240c2b15a135fbbc0507fbe
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 "base/strings/stringprintf.h"
8 #include "net/cert/internal/test_helpers.h"
9 #include "net/der/input.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace net {
14 namespace {
16 // Pretty-prints a GeneralizedTime as a human-readable string for use in test
17 // expectations (it is more readable to specify the expected results as a
18 // string).
19 std::string ToString(const der::GeneralizedTime& time) {
20 return base::StringPrintf(
21 "year=%d, month=%d, day=%d, hours=%d, minutes=%d, seconds=%d", time.year,
22 time.month, time.day, time.hours, time.minutes, time.seconds);
25 std::string GetFilePath(const std::string& file_name) {
26 return std::string("net/data/parse_certificate_unittest/") + file_name;
29 // Loads certificate data and expectations from the PEM file |file_name|.
30 // Verifies that parsing the Certificate succeeds, and each parsed field matches
31 // the expectations.
32 void EnsureParsingCertificateSucceeds(const std::string& file_name) {
33 std::string data;
34 std::string expected_tbs_certificate;
35 std::string expected_signature_algorithm;
36 std::string expected_signature;
38 // Read the certificate data and test expectations from a single PEM file.
39 const PemBlockMapping mappings[] = {
40 {"CERTIFICATE", &data},
41 {"SIGNATURE", &expected_signature},
42 {"SIGNATURE ALGORITHM", &expected_signature_algorithm},
43 {"TBS CERTIFICATE", &expected_tbs_certificate},
45 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings));
47 // Parsing the certificate should succeed.
48 ParsedCertificate parsed;
49 ASSERT_TRUE(ParseCertificate(InputFromString(&data), &parsed));
51 // Ensure that the ParsedCertificate matches expectations.
52 EXPECT_EQ(0, parsed.signature_value.unused_bits());
53 EXPECT_EQ(InputFromString(&expected_signature),
54 parsed.signature_value.bytes());
55 EXPECT_EQ(InputFromString(&expected_signature_algorithm),
56 parsed.signature_algorithm_tlv);
57 EXPECT_EQ(InputFromString(&expected_tbs_certificate),
58 parsed.tbs_certificate_tlv);
61 // Loads certificate data from the PEM file |file_name| and verifies that the
62 // Certificate parsing fails.
63 void EnsureParsingCertificateFails(const std::string& file_name) {
64 std::string data;
66 const PemBlockMapping mappings[] = {
67 {"CERTIFICATE", &data},
70 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings));
72 // Parsing the Certificate should fail.
73 ParsedCertificate parsed;
74 ASSERT_FALSE(ParseCertificate(InputFromString(&data), &parsed));
77 // Tests parsing a Certificate.
78 TEST(ParseCertificateTest, Version3) {
79 EnsureParsingCertificateSucceeds("cert_version3.pem");
82 // Tests parsing a simplified Certificate-like structure (the sub-fields for
83 // algorithm and tbsCertificate are not actually valid, but ParseCertificate()
84 // doesn't check them)
85 TEST(ParseCertificateTest, Skeleton) {
86 EnsureParsingCertificateSucceeds("cert_skeleton.pem");
89 // Tests parsing a Certificate that is not a sequence fails.
90 TEST(ParseCertificateTest, NotSequence) {
91 EnsureParsingCertificateFails("cert_not_sequence.pem");
94 // Tests that uncomsumed data is not allowed after the main SEQUENCE.
95 TEST(ParseCertificateTest, DataAfterSignature) {
96 EnsureParsingCertificateFails("cert_data_after_signature.pem");
99 // Tests that parsing fails if the signature BIT STRING is missing.
100 TEST(ParseCertificateTest, MissingSignature) {
101 EnsureParsingCertificateFails("cert_missing_signature.pem");
104 // Tests that parsing fails if the signature is present but not a BIT STRING.
105 TEST(ParseCertificateTest, SignatureNotBitString) {
106 EnsureParsingCertificateFails("cert_signature_not_bit_string.pem");
109 // Tests that parsing fails if the main SEQUENCE is empty (missing all the
110 // fields).
111 TEST(ParseCertificateTest, EmptySequence) {
112 EnsureParsingCertificateFails("cert_empty_sequence.pem");
115 // Tests what happens when the signature algorithm is present, but has the wrong
116 // tag.
117 TEST(ParseCertificateTest, AlgorithmNotSequence) {
118 EnsureParsingCertificateFails("cert_algorithm_not_sequence.pem");
121 // Loads tbsCertificate data and expectations from the PEM file |file_name|.
122 // Verifies that parsing the TBSCertificate succeeds, and each parsed field
123 // matches the expectations.
124 void EnsureParsingTbsSucceeds(const std::string& file_name,
125 CertificateVersion expected_version) {
126 std::string data;
127 std::string expected_serial_number;
128 std::string expected_signature_algorithm;
129 std::string expected_issuer;
130 std::string expected_validity_not_before;
131 std::string expected_validity_not_after;
132 std::string expected_subject;
133 std::string expected_spki;
134 std::string expected_issuer_unique_id;
135 std::string expected_subject_unique_id;
136 std::string expected_extensions;
138 // Read the certificate data and test expectations from a single PEM file.
139 const PemBlockMapping mappings[] = {
140 {"TBS CERTIFICATE", &data},
141 {"SIGNATURE ALGORITHM", &expected_signature_algorithm},
142 {"SERIAL NUMBER", &expected_serial_number},
143 {"ISSUER", &expected_issuer},
144 {"VALIDITY NOTBEFORE", &expected_validity_not_before},
145 {"VALIDITY NOTAFTER", &expected_validity_not_after},
146 {"SUBJECT", &expected_subject},
147 {"SPKI", &expected_spki},
148 {"ISSUER UNIQUE ID", &expected_issuer_unique_id, true},
149 {"SUBJECT UNIQUE ID", &expected_subject_unique_id, true},
150 {"EXTENSIONS", &expected_extensions, true},
152 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings));
154 // Parsing the TBSCertificate should succeed.
155 ParsedTbsCertificate parsed;
156 ASSERT_TRUE(ParseTbsCertificate(InputFromString(&data), &parsed));
158 // Ensure that the ParsedTbsCertificate matches expectations.
159 EXPECT_EQ(expected_version, parsed.version);
161 EXPECT_EQ(InputFromString(&expected_serial_number), parsed.serial_number);
162 EXPECT_EQ(InputFromString(&expected_signature_algorithm),
163 parsed.signature_algorithm_tlv);
165 EXPECT_EQ(InputFromString(&expected_issuer), parsed.issuer_tlv);
167 // In the test expectations PEM file, validity is described as a
168 // textual string of the parsed value (rather than as DER).
169 EXPECT_EQ(expected_validity_not_before, ToString(parsed.validity_not_before));
170 EXPECT_EQ(expected_validity_not_after, ToString(parsed.validity_not_after));
172 EXPECT_EQ(InputFromString(&expected_subject), parsed.subject_tlv);
173 EXPECT_EQ(InputFromString(&expected_spki), parsed.spki_tlv);
175 EXPECT_EQ(InputFromString(&expected_issuer_unique_id),
176 parsed.issuer_unique_id.bytes());
177 EXPECT_EQ(!expected_issuer_unique_id.empty(), parsed.has_issuer_unique_id);
178 EXPECT_EQ(InputFromString(&expected_subject_unique_id),
179 parsed.subject_unique_id.bytes());
180 EXPECT_EQ(!expected_subject_unique_id.empty(), parsed.has_subject_unique_id);
182 EXPECT_EQ(InputFromString(&expected_extensions), parsed.extensions_tlv);
183 EXPECT_EQ(!expected_extensions.empty(), parsed.has_extensions);
186 // Loads certificate data from the PEM file |file_name| and verifies that the
187 // Certificate parsing succeed, however the TBSCertificate parsing fails.
188 void EnsureParsingTbsFails(const std::string& file_name) {
189 std::string data;
191 const PemBlockMapping mappings[] = {
192 {"TBS CERTIFICATE", &data},
195 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings));
197 // Parsing the TBSCertificate should fail.
198 ParsedTbsCertificate parsed;
199 ASSERT_FALSE(ParseTbsCertificate(InputFromString(&data), &parsed));
202 // Tests parsing a TBSCertificate for v3 that contains no optional fields.
203 TEST(ParseTbsCertificateTest, Version3NoOptionals) {
204 EnsureParsingTbsSucceeds("tbs_v3_no_optionals.pem", CertificateVersion::V3);
207 // Tests parsing a TBSCertificate for v3 that contains extensions.
208 TEST(ParseTbsCertificateTest, Version3WithExtensions) {
209 EnsureParsingTbsSucceeds("tbs_v3_extensions.pem", CertificateVersion::V3);
212 // Tests parsing a TBSCertificate for v3 that contains no optional fields, and
213 // has a negative serial number.
215 // CAs are not supposed to include negative serial numbers, however RFC 5280
216 // expects consumers to deal with it anyway).
217 TEST(ParseTbsCertificateTest, NegativeSerialNumber) {
218 EnsureParsingTbsSucceeds("tbs_negative_serial_number.pem",
219 CertificateVersion::V3);
222 // Tests parsing a TBSCertificate with a serial number that is 21 octets long
223 // (and the first byte is 0).
224 TEST(ParseTbCertificateTest, SerialNumber21OctetsLeading0) {
225 EnsureParsingTbsFails("tbs_serial_number_21_octets_leading_0.pem");
228 // Tests parsing a TBSCertificate with a serial number that is 26 octets long
229 // (and does not contain a leading 0).
230 TEST(ParseTbsCertificateTest, SerialNumber26Octets) {
231 EnsureParsingTbsFails("tbs_serial_number_26_octets.pem");
234 // Tests parsing a TBSCertificate which lacks a version number (causing it to
235 // default to v1).
236 TEST(ParseTbsCertificateTest, Version1) {
237 EnsureParsingTbsSucceeds("tbs_v1.pem", CertificateVersion::V1);
240 // The version was set to v1 explicitly rather than omitting the version field.
241 TEST(ParseTbsCertificateTest, ExplicitVersion1) {
242 EnsureParsingTbsFails("tbs_explicit_v1.pem");
245 // Extensions are not defined in version 1.
246 TEST(ParseTbsCertificateTest, Version1WithExtensions) {
247 EnsureParsingTbsFails("tbs_v1_extensions.pem");
250 // Extensions are not defined in version 2.
251 TEST(ParseTbsCertificateTest, Version2WithExtensions) {
252 EnsureParsingTbsFails("tbs_v2_extensions.pem");
255 // A boring version 2 certificate with none of the optional fields.
256 TEST(ParseTbsCertificateTest, Version2NoOptionals) {
257 EnsureParsingTbsSucceeds("tbs_v2_no_optionals.pem", CertificateVersion::V2);
260 // A version 2 certificate with an issuer unique ID field.
261 TEST(ParseTbsCertificateTest, Version2IssuerUniqueId) {
262 EnsureParsingTbsSucceeds("tbs_v2_issuer_unique_id.pem",
263 CertificateVersion::V2);
266 // A version 2 certificate with both a issuer and subject unique ID field.
267 TEST(ParseTbsCertificateTest, Version2IssuerAndSubjectUniqueId) {
268 EnsureParsingTbsSucceeds("tbs_v2_issuer_and_subject_unique_id.pem",
269 CertificateVersion::V2);
272 // A version 3 certificate with all of the optional fields (issuer unique id,
273 // subject unique id, and extensions).
274 TEST(ParseTbsCertificateTest, Version3AllOptionals) {
275 EnsureParsingTbsSucceeds("tbs_v3_all_optionals.pem", CertificateVersion::V3);
278 // The version was set to v4, which is unrecognized.
279 TEST(ParseTbsCertificateTest, Version4) {
280 EnsureParsingTbsFails("tbs_v4.pem");
283 // Tests that extraneous data after extensions in a v3 is rejected.
284 TEST(ParseTbsCertificateTest, Version3DataAfterExtensions) {
285 EnsureParsingTbsFails("tbs_v3_data_after_extensions.pem");
288 // Tests using a real-world certificate (whereas the other tests are fabricated
289 // (and in fact invalid) data.
290 TEST(ParseTbsCertificateTest, Version3Real) {
291 EnsureParsingTbsSucceeds("tbs_v3_real.pem", CertificateVersion::V3);
294 // Parses a TBSCertificate whose "validity" field expresses both notBefore
295 // and notAfter using UTCTime.
296 TEST(ParseTbsCertificateTest, ValidityBothUtcTime) {
297 EnsureParsingTbsSucceeds("tbs_validity_both_utc_time.pem",
298 CertificateVersion::V3);
301 // Parses a TBSCertificate whose "validity" field expresses both notBefore
302 // and notAfter using GeneralizedTime.
303 TEST(ParseTbsCertificateTest, ValidityBothGeneralizedTime) {
304 EnsureParsingTbsSucceeds("tbs_validity_both_generalized_time.pem",
305 CertificateVersion::V3);
308 // Parses a TBSCertificate whose "validity" field expresses notBefore using
309 // UTCTime and notAfter using GeneralizedTime.
310 TEST(ParseTbsCertificateTest, ValidityUTCTimeAndGeneralizedTime) {
311 EnsureParsingTbsSucceeds("tbs_validity_utc_time_and_generalized_time.pem",
312 CertificateVersion::V3);
315 // Parses a TBSCertificate whose validity" field expresses notBefore using
316 // GeneralizedTime and notAfter using UTCTime. Also of interest, notBefore >
317 // notAfter. Parsing will succeed, however no time can satisfy this constraint.
318 TEST(ParseTbsCertificateTest, ValidityGeneralizedTimeAndUTCTime) {
319 EnsureParsingTbsSucceeds("tbs_validity_generalized_time_and_utc_time.pem",
320 CertificateVersion::V3);
323 // Parses a TBSCertificate whose "validity" field does not strictly follow
324 // the DER rules (and fails to be parsed).
325 TEST(ParseTbsCertificateTest, ValidityRelaxed) {
326 EnsureParsingTbsFails("tbs_validity_relaxed.pem");
329 } // namespace
331 } // namespace net