1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "parsed_certificate.h"
6
7 #include "cert_errors.h"
8 #include "parse_certificate.h"
9 #include "test_helpers.h"
10 #include "input.h"
11 #include <gtest/gtest.h>
12 #include <openssl/pool.h>
13
14 // TODO(eroman): Add tests for parsing of policy mappings.
15
16 namespace bssl {
17
18 namespace {
19
GetFilePath(const std::string & file_name)20 std::string GetFilePath(const std::string& file_name) {
21 return std::string("testdata/parse_certificate_unittest/") + file_name;
22 }
23
24 // Reads and parses a certificate from the PEM file |file_name|.
25 //
26 // Returns nullptr if the certificate parsing failed, and verifies that any
27 // errors match the ERRORS block in the .pem file.
ParseCertificateFromFile(const std::string & file_name,const ParseCertificateOptions & options)28 std::shared_ptr<const ParsedCertificate> ParseCertificateFromFile(
29 const std::string& file_name,
30 const ParseCertificateOptions& options) {
31 std::string data;
32 std::string expected_errors;
33
34 // Read the certificate data and error expectations from a single PEM file.
35 const PemBlockMapping mappings[] = {
36 {"CERTIFICATE", &data},
37 {"ERRORS", &expected_errors, true /*optional*/},
38 };
39 std::string test_file_path = GetFilePath(file_name);
40 EXPECT_TRUE(ReadTestDataFromPemFile(test_file_path, mappings));
41
42 CertErrors errors;
43 std::shared_ptr<const ParsedCertificate> cert = ParsedCertificate::Create(
44 bssl::UniquePtr<CRYPTO_BUFFER>(CRYPTO_BUFFER_new(
45 reinterpret_cast<const uint8_t*>(data.data()), data.size(), nullptr)),
46 options, &errors);
47
48 // The errors are baselined for |!allow_invalid_serial_numbers|. So if
49 // requesting a non-default option skip the error checks.
50 // TODO(eroman): This is ugly.
51 if (!options.allow_invalid_serial_numbers)
52 VerifyCertErrors(expected_errors, errors, test_file_path);
53
54 // Every parse failure being tested should emit error information.
55 if (!cert) {
56 EXPECT_FALSE(errors.ToDebugString().empty());
57 }
58
59 return cert;
60 }
61
DavidBenOid()62 der::Input DavidBenOid() {
63 // This OID corresponds with
64 // 1.2.840.113554.4.1.72585.0 (https://davidben.net/oid)
65 static const uint8_t kOid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12,
66 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00};
67 return der::Input(kOid);
68 }
69
70 // Parses an Extension whose critical field is true (255).
TEST(ParsedCertificateTest,ExtensionCritical)71 TEST(ParsedCertificateTest, ExtensionCritical) {
72 std::shared_ptr<const ParsedCertificate> cert =
73 ParseCertificateFromFile("extension_critical.pem", {});
74 ASSERT_TRUE(cert);
75
76 const uint8_t kExpectedValue[] = {0x30, 0x00};
77
78 ParsedExtension extension;
79 ASSERT_TRUE(cert->GetExtension(DavidBenOid(), &extension));
80
81 EXPECT_TRUE(extension.critical);
82 EXPECT_EQ(DavidBenOid(), extension.oid);
83 EXPECT_EQ(der::Input(kExpectedValue), extension.value);
84 }
85
86 // Parses an Extension whose critical field is false (omitted).
TEST(ParsedCertificateTest,ExtensionNotCritical)87 TEST(ParsedCertificateTest, ExtensionNotCritical) {
88 std::shared_ptr<const ParsedCertificate> cert =
89 ParseCertificateFromFile("extension_not_critical.pem", {});
90 ASSERT_TRUE(cert);
91
92 const uint8_t kExpectedValue[] = {0x30, 0x00};
93
94 ParsedExtension extension;
95 ASSERT_TRUE(cert->GetExtension(DavidBenOid(), &extension));
96
97 EXPECT_FALSE(extension.critical);
98 EXPECT_EQ(DavidBenOid(), extension.oid);
99 EXPECT_EQ(der::Input(kExpectedValue), extension.value);
100 }
101
102 // Parses an Extension whose critical field is 0. This is in one sense FALSE,
103 // however because critical has DEFAULT of false this is in fact invalid
104 // DER-encoding.
TEST(ParsedCertificateTest,ExtensionCritical0)105 TEST(ParsedCertificateTest, ExtensionCritical0) {
106 ASSERT_FALSE(ParseCertificateFromFile("extension_critical_0.pem", {}));
107 }
108
109 // Parses an Extension whose critical field is 3. Under DER-encoding BOOLEAN
110 // values must an octet of either all zero bits, or all 1 bits, so this is not
111 // valid.
TEST(ParsedCertificateTest,ExtensionCritical3)112 TEST(ParsedCertificateTest, ExtensionCritical3) {
113 ASSERT_FALSE(ParseCertificateFromFile("extension_critical_3.pem", {}));
114 }
115
116 // Parses an Extensions that is an empty sequence.
TEST(ParsedCertificateTest,ExtensionsEmptySequence)117 TEST(ParsedCertificateTest, ExtensionsEmptySequence) {
118 ASSERT_FALSE(ParseCertificateFromFile("extensions_empty_sequence.pem", {}));
119 }
120
121 // Parses an Extensions that is not a sequence.
TEST(ParsedCertificateTest,ExtensionsNotSequence)122 TEST(ParsedCertificateTest, ExtensionsNotSequence) {
123 ASSERT_FALSE(ParseCertificateFromFile("extensions_not_sequence.pem", {}));
124 }
125
126 // Parses an Extensions that has data after the sequence.
TEST(ParsedCertificateTest,ExtensionsDataAfterSequence)127 TEST(ParsedCertificateTest, ExtensionsDataAfterSequence) {
128 ASSERT_FALSE(
129 ParseCertificateFromFile("extensions_data_after_sequence.pem", {}));
130 }
131
132 // Parses an Extensions that contains duplicated key usages.
TEST(ParsedCertificateTest,ExtensionsDuplicateKeyUsage)133 TEST(ParsedCertificateTest, ExtensionsDuplicateKeyUsage) {
134 ASSERT_FALSE(
135 ParseCertificateFromFile("extensions_duplicate_key_usage.pem", {}));
136 }
137
138 // Parses a certificate with a bad key usage extension (BIT STRING with zero
139 // elements).
TEST(ParsedCertificateTest,BadKeyUsage)140 TEST(ParsedCertificateTest, BadKeyUsage) {
141 ASSERT_FALSE(ParseCertificateFromFile("bad_key_usage.pem", {}));
142 }
143
144 // Parses a certificate that has a PolicyQualifierInfo that is missing the
145 // qualifier field.
TEST(ParsedCertificateTest,BadPolicyQualifiers)146 TEST(ParsedCertificateTest, BadPolicyQualifiers) {
147 ASSERT_FALSE(ParseCertificateFromFile("bad_policy_qualifiers.pem", {}));
148 }
149
150 // Parses a certificate that uses an unknown signature algorithm OID (00).
TEST(ParsedCertificateTest,BadSignatureAlgorithmOid)151 TEST(ParsedCertificateTest, BadSignatureAlgorithmOid) {
152 std::shared_ptr<const ParsedCertificate> cert =
153 ParseCertificateFromFile("bad_signature_algorithm_oid.pem", {});
154 ASSERT_TRUE(cert);
155 ASSERT_FALSE(cert->signature_algorithm());
156 }
157
158 // The validity encodes time as UTCTime but following the BER rules rather than
159 // DER rules (i.e. YYMMDDHHMMZ instead of YYMMDDHHMMSSZ).
TEST(ParsedCertificateTest,BadValidity)160 TEST(ParsedCertificateTest, BadValidity) {
161 ASSERT_FALSE(ParseCertificateFromFile("bad_validity.pem", {}));
162 }
163
164 // The signature algorithm contains an unexpected parameters field.
TEST(ParsedCertificateTest,FailedSignatureAlgorithm)165 TEST(ParsedCertificateTest, FailedSignatureAlgorithm) {
166 std::shared_ptr<const ParsedCertificate> cert =
167 ParseCertificateFromFile("failed_signature_algorithm.pem", {});
168 ASSERT_TRUE(cert);
169 ASSERT_FALSE(cert->signature_algorithm());
170 }
171
TEST(ParsedCertificateTest,IssuerBadPrintableString)172 TEST(ParsedCertificateTest, IssuerBadPrintableString) {
173 ASSERT_FALSE(ParseCertificateFromFile("issuer_bad_printable_string.pem", {}));
174 }
175
TEST(ParsedCertificateTest,NameConstraintsBadIp)176 TEST(ParsedCertificateTest, NameConstraintsBadIp) {
177 ASSERT_FALSE(ParseCertificateFromFile("name_constraints_bad_ip.pem", {}));
178 }
179
TEST(ParsedCertificateTest,PolicyQualifiersEmptySequence)180 TEST(ParsedCertificateTest, PolicyQualifiersEmptySequence) {
181 ASSERT_FALSE(
182 ParseCertificateFromFile("policy_qualifiers_empty_sequence.pem", {}));
183 }
184
TEST(ParsedCertificateTest,SubjectBlankSubjectAltNameNotCritical)185 TEST(ParsedCertificateTest, SubjectBlankSubjectAltNameNotCritical) {
186 ASSERT_FALSE(ParseCertificateFromFile(
187 "subject_blank_subjectaltname_not_critical.pem", {}));
188 }
189
TEST(ParsedCertificateTest,SubjectNotAscii)190 TEST(ParsedCertificateTest, SubjectNotAscii) {
191 ASSERT_FALSE(ParseCertificateFromFile("subject_not_ascii.pem", {}));
192 }
193
TEST(ParsedCertificateTest,SubjectNotPrintableString)194 TEST(ParsedCertificateTest, SubjectNotPrintableString) {
195 ASSERT_FALSE(
196 ParseCertificateFromFile("subject_not_printable_string.pem", {}));
197 }
198
TEST(ParsedCertificateTest,SubjectAltNameBadIp)199 TEST(ParsedCertificateTest, SubjectAltNameBadIp) {
200 ASSERT_FALSE(ParseCertificateFromFile("subjectaltname_bad_ip.pem", {}));
201 }
202
TEST(ParsedCertificateTest,SubjectAltNameDnsNotAscii)203 TEST(ParsedCertificateTest, SubjectAltNameDnsNotAscii) {
204 ASSERT_FALSE(
205 ParseCertificateFromFile("subjectaltname_dns_not_ascii.pem", {}));
206 }
207
TEST(ParsedCertificateTest,SubjectAltNameGeneralNamesEmptySequence)208 TEST(ParsedCertificateTest, SubjectAltNameGeneralNamesEmptySequence) {
209 ASSERT_FALSE(ParseCertificateFromFile(
210 "subjectaltname_general_names_empty_sequence.pem", {}));
211 }
212
TEST(ParsedCertificateTest,SubjectAltNameTrailingData)213 TEST(ParsedCertificateTest, SubjectAltNameTrailingData) {
214 ASSERT_FALSE(
215 ParseCertificateFromFile("subjectaltname_trailing_data.pem", {}));
216 }
217
TEST(ParsedCertificateTest,V1ExplicitVersion)218 TEST(ParsedCertificateTest, V1ExplicitVersion) {
219 ASSERT_FALSE(ParseCertificateFromFile("v1_explicit_version.pem", {}));
220 }
221
222 // Parses an Extensions that contains an extended key usages.
TEST(ParsedCertificateTest,ExtendedKeyUsage)223 TEST(ParsedCertificateTest, ExtendedKeyUsage) {
224 std::shared_ptr<const ParsedCertificate> cert =
225 ParseCertificateFromFile("extended_key_usage.pem", {});
226 ASSERT_TRUE(cert);
227
228 ASSERT_EQ(4u, cert->extensions().size());
229
230 ParsedExtension extension;
231 ASSERT_TRUE(cert->GetExtension(der::Input(kExtKeyUsageOid), &extension));
232
233 EXPECT_FALSE(extension.critical);
234 EXPECT_EQ(45u, extension.value.Length());
235
236 EXPECT_TRUE(cert->has_extended_key_usage());
237 EXPECT_EQ(4u, cert->extended_key_usage().size());
238 }
239
240 // Parses an Extensions that contains a key usage.
TEST(ParsedCertificateTest,KeyUsage)241 TEST(ParsedCertificateTest, KeyUsage) {
242 std::shared_ptr<const ParsedCertificate> cert =
243 ParseCertificateFromFile("key_usage.pem", {});
244 ASSERT_TRUE(cert);
245
246 ASSERT_TRUE(cert->has_key_usage());
247
248 EXPECT_EQ(5u, cert->key_usage().unused_bits());
249 const uint8_t kExpectedBytes[] = {0xA0};
250 EXPECT_EQ(der::Input(kExpectedBytes), cert->key_usage().bytes());
251
252 EXPECT_TRUE(cert->key_usage().AssertsBit(0));
253 EXPECT_FALSE(cert->key_usage().AssertsBit(1));
254 EXPECT_TRUE(cert->key_usage().AssertsBit(2));
255 }
256
257 // Parses an Extensions that contains a policies extension.
TEST(ParsedCertificateTest,Policies)258 TEST(ParsedCertificateTest, Policies) {
259 std::shared_ptr<const ParsedCertificate> cert =
260 ParseCertificateFromFile("policies.pem", {});
261 ASSERT_TRUE(cert);
262
263 ASSERT_EQ(4u, cert->extensions().size());
264
265 ParsedExtension extension;
266 ASSERT_TRUE(
267 cert->GetExtension(der::Input(kCertificatePoliciesOid), &extension));
268
269 EXPECT_FALSE(extension.critical);
270 EXPECT_EQ(95u, extension.value.Length());
271
272 EXPECT_TRUE(cert->has_policy_oids());
273 EXPECT_EQ(2u, cert->policy_oids().size());
274 }
275
276 // Parses an Extensions that contains a subjectaltname extension.
TEST(ParsedCertificateTest,SubjectAltName)277 TEST(ParsedCertificateTest, SubjectAltName) {
278 std::shared_ptr<const ParsedCertificate> cert =
279 ParseCertificateFromFile("subject_alt_name.pem", {});
280 ASSERT_TRUE(cert);
281
282 ASSERT_TRUE(cert->has_subject_alt_names());
283 }
284
285 // Parses an Extensions that contains multiple extensions, sourced from a
286 // real-world certificate.
TEST(ParsedCertificateTest,ExtensionsReal)287 TEST(ParsedCertificateTest, ExtensionsReal) {
288 std::shared_ptr<const ParsedCertificate> cert =
289 ParseCertificateFromFile("extensions_real.pem", {});
290 ASSERT_TRUE(cert);
291
292 ASSERT_EQ(7u, cert->extensions().size());
293
294 EXPECT_TRUE(cert->has_key_usage());
295 EXPECT_TRUE(cert->has_basic_constraints());
296 EXPECT_TRUE(cert->has_authority_info_access());
297 EXPECT_TRUE(cert->has_policy_oids());
298
299 ASSERT_TRUE(cert->authority_key_identifier());
300 ASSERT_TRUE(cert->authority_key_identifier()->key_identifier);
301 EXPECT_FALSE(cert->authority_key_identifier()->authority_cert_issuer);
302 EXPECT_FALSE(cert->authority_key_identifier()->authority_cert_serial_number);
303 const uint8_t expected_authority_key_identifier[] = {
304 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64,
305 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e,
306 };
307 EXPECT_EQ(der::Input(expected_authority_key_identifier),
308 cert->authority_key_identifier()->key_identifier);
309
310 ASSERT_TRUE(cert->subject_key_identifier());
311 const uint8_t expected_subject_key_identifier[] = {
312 0x4a, 0xdd, 0x06, 0x16, 0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76,
313 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba, 0x5a, 0x81, 0x2f};
314 EXPECT_EQ(der::Input(expected_subject_key_identifier),
315 cert->subject_key_identifier());
316
317 ParsedExtension extension;
318 ASSERT_TRUE(
319 cert->GetExtension(der::Input(kCertificatePoliciesOid), &extension));
320
321 EXPECT_FALSE(extension.critical);
322 EXPECT_EQ(16u, extension.value.Length());
323
324 // TODO(eroman): Verify the other extensions' values.
325 }
326
327 // Parses a BasicConstraints with no CA or pathlen.
TEST(ParsedCertificateTest,BasicConstraintsNotCa)328 TEST(ParsedCertificateTest, BasicConstraintsNotCa) {
329 std::shared_ptr<const ParsedCertificate> cert =
330 ParseCertificateFromFile("basic_constraints_not_ca.pem", {});
331 ASSERT_TRUE(cert);
332
333 EXPECT_TRUE(cert->has_basic_constraints());
334 EXPECT_FALSE(cert->basic_constraints().is_ca);
335 EXPECT_FALSE(cert->basic_constraints().has_path_len);
336 }
337
338 // Parses a BasicConstraints with CA but no pathlen.
TEST(ParsedCertificateTest,BasicConstraintsCaNoPath)339 TEST(ParsedCertificateTest, BasicConstraintsCaNoPath) {
340 std::shared_ptr<const ParsedCertificate> cert =
341 ParseCertificateFromFile("basic_constraints_ca_no_path.pem", {});
342 ASSERT_TRUE(cert);
343
344 EXPECT_TRUE(cert->has_basic_constraints());
345 EXPECT_TRUE(cert->basic_constraints().is_ca);
346 EXPECT_FALSE(cert->basic_constraints().has_path_len);
347 }
348
349 // Parses a BasicConstraints with CA and pathlen of 9.
TEST(ParsedCertificateTest,BasicConstraintsCaPath9)350 TEST(ParsedCertificateTest, BasicConstraintsCaPath9) {
351 std::shared_ptr<const ParsedCertificate> cert =
352 ParseCertificateFromFile("basic_constraints_ca_path_9.pem", {});
353 ASSERT_TRUE(cert);
354
355 EXPECT_TRUE(cert->has_basic_constraints());
356 EXPECT_TRUE(cert->basic_constraints().is_ca);
357 EXPECT_TRUE(cert->basic_constraints().has_path_len);
358 EXPECT_EQ(9u, cert->basic_constraints().path_len);
359 }
360
361 // Parses a BasicConstraints with CA and pathlen of 255 (largest allowed size).
TEST(ParsedCertificateTest,BasicConstraintsPathlen255)362 TEST(ParsedCertificateTest, BasicConstraintsPathlen255) {
363 std::shared_ptr<const ParsedCertificate> cert =
364 ParseCertificateFromFile("basic_constraints_pathlen_255.pem", {});
365 ASSERT_TRUE(cert);
366
367 EXPECT_TRUE(cert->has_basic_constraints());
368 EXPECT_TRUE(cert->basic_constraints().is_ca);
369 EXPECT_TRUE(cert->basic_constraints().has_path_len);
370 EXPECT_EQ(255, cert->basic_constraints().path_len);
371 }
372
373 // Parses a BasicConstraints with CA and pathlen of 256 (too large).
TEST(ParsedCertificateTest,BasicConstraintsPathlen256)374 TEST(ParsedCertificateTest, BasicConstraintsPathlen256) {
375 ASSERT_FALSE(
376 ParseCertificateFromFile("basic_constraints_pathlen_256.pem", {}));
377 }
378
379 // Parses a BasicConstraints with CA and a negative pathlen.
TEST(ParsedCertificateTest,BasicConstraintsNegativePath)380 TEST(ParsedCertificateTest, BasicConstraintsNegativePath) {
381 ASSERT_FALSE(
382 ParseCertificateFromFile("basic_constraints_negative_path.pem", {}));
383 }
384
385 // Parses a BasicConstraints with CA and pathlen that is very large (and
386 // couldn't fit in a 64-bit integer).
TEST(ParsedCertificateTest,BasicConstraintsPathTooLarge)387 TEST(ParsedCertificateTest, BasicConstraintsPathTooLarge) {
388 ASSERT_FALSE(
389 ParseCertificateFromFile("basic_constraints_path_too_large.pem", {}));
390 }
391
392 // Parses a BasicConstraints with CA explicitly set to false. This violates
393 // DER-encoding rules, however is commonly used, so it is accepted.
TEST(ParsedCertificateTest,BasicConstraintsCaFalse)394 TEST(ParsedCertificateTest, BasicConstraintsCaFalse) {
395 std::shared_ptr<const ParsedCertificate> cert =
396 ParseCertificateFromFile("basic_constraints_ca_false.pem", {});
397 ASSERT_TRUE(cert);
398
399 EXPECT_TRUE(cert->has_basic_constraints());
400 EXPECT_FALSE(cert->basic_constraints().is_ca);
401 EXPECT_FALSE(cert->basic_constraints().has_path_len);
402 }
403
404 // Parses a BasicConstraints with CA set to true and an unexpected NULL at
405 // the end.
TEST(ParsedCertificateTest,BasicConstraintsUnconsumedData)406 TEST(ParsedCertificateTest, BasicConstraintsUnconsumedData) {
407 ASSERT_FALSE(
408 ParseCertificateFromFile("basic_constraints_unconsumed_data.pem", {}));
409 }
410
411 // Parses a BasicConstraints with CA omitted (false), but with a pathlen of 1.
412 // This is valid DER for the ASN.1, however is not valid when interpreting the
413 // BasicConstraints at a higher level.
TEST(ParsedCertificateTest,BasicConstraintsPathLenButNotCa)414 TEST(ParsedCertificateTest, BasicConstraintsPathLenButNotCa) {
415 std::shared_ptr<const ParsedCertificate> cert =
416 ParseCertificateFromFile("basic_constraints_pathlen_not_ca.pem", {});
417 ASSERT_TRUE(cert);
418
419 EXPECT_TRUE(cert->has_basic_constraints());
420 EXPECT_FALSE(cert->basic_constraints().is_ca);
421 EXPECT_TRUE(cert->basic_constraints().has_path_len);
422 EXPECT_EQ(1u, cert->basic_constraints().path_len);
423 }
424
425 // Tests parsing a certificate that contains a policyConstraints
426 // extension having requireExplicitPolicy:3.
TEST(ParsedCertificateTest,PolicyConstraintsRequire)427 TEST(ParsedCertificateTest, PolicyConstraintsRequire) {
428 std::shared_ptr<const ParsedCertificate> cert =
429 ParseCertificateFromFile("policy_constraints_require.pem", {});
430 ASSERT_TRUE(cert);
431
432 EXPECT_TRUE(cert->has_policy_constraints());
433 EXPECT_TRUE(cert->policy_constraints().require_explicit_policy.has_value());
434 EXPECT_EQ(3, cert->policy_constraints().require_explicit_policy.value());
435 EXPECT_FALSE(cert->policy_constraints().inhibit_policy_mapping.has_value());
436 }
437
438 // Tests parsing a certificate that contains a policyConstraints
439 // extension having inhibitPolicyMapping:1.
TEST(ParsedCertificateTest,PolicyConstraintsInhibit)440 TEST(ParsedCertificateTest, PolicyConstraintsInhibit) {
441 std::shared_ptr<const ParsedCertificate> cert =
442 ParseCertificateFromFile("policy_constraints_inhibit.pem", {});
443 ASSERT_TRUE(cert);
444
445 EXPECT_TRUE(cert->has_policy_constraints());
446 EXPECT_FALSE(cert->policy_constraints().require_explicit_policy.has_value());
447 EXPECT_TRUE(cert->policy_constraints().inhibit_policy_mapping.has_value());
448 EXPECT_EQ(1, cert->policy_constraints().inhibit_policy_mapping.value());
449 }
450
451 // Tests parsing a certificate that contains a policyConstraints
452 // extension having requireExplicitPolicy:5,inhibitPolicyMapping:2.
TEST(ParsedCertificateTest,PolicyConstraintsInhibitRequire)453 TEST(ParsedCertificateTest, PolicyConstraintsInhibitRequire) {
454 std::shared_ptr<const ParsedCertificate> cert =
455 ParseCertificateFromFile("policy_constraints_inhibit_require.pem", {});
456 ASSERT_TRUE(cert);
457
458 EXPECT_TRUE(cert->has_policy_constraints());
459 EXPECT_TRUE(cert->policy_constraints().require_explicit_policy.has_value());
460 EXPECT_EQ(5, cert->policy_constraints().require_explicit_policy.value());
461 EXPECT_TRUE(cert->policy_constraints().inhibit_policy_mapping.has_value());
462 EXPECT_EQ(2, cert->policy_constraints().inhibit_policy_mapping.value());
463 }
464
465 // Tests parsing a certificate that has a policyConstraints
466 // extension with an empty sequence.
TEST(ParsedCertificateTest,PolicyConstraintsEmpty)467 TEST(ParsedCertificateTest, PolicyConstraintsEmpty) {
468 std::shared_ptr<const ParsedCertificate> cert =
469 ParseCertificateFromFile("policy_constraints_empty.pem", {});
470 ASSERT_FALSE(cert);
471 }
472
473 // Tests a certificate with a serial number with a leading 0 padding byte in
474 // the encoding since it is not negative.
TEST(ParsedCertificateTest,SerialNumberZeroPadded)475 TEST(ParsedCertificateTest, SerialNumberZeroPadded) {
476 std::shared_ptr<const ParsedCertificate> cert =
477 ParseCertificateFromFile("serial_zero_padded.pem", {});
478 ASSERT_TRUE(cert);
479
480 static const uint8_t expected_serial[3] = {0x00, 0x80, 0x01};
481 EXPECT_EQ(der::Input(expected_serial), cert->tbs().serial_number);
482 }
483
484 // Tests a serial number where the MSB is >= 0x80, causing the encoded
485 // length to be 21 bytes long. This is an error, as RFC 5280 specifies a
486 // maximum of 20 bytes.
TEST(ParsedCertificateTest,SerialNumberZeroPadded21BytesLong)487 TEST(ParsedCertificateTest, SerialNumberZeroPadded21BytesLong) {
488 std::shared_ptr<const ParsedCertificate> cert =
489 ParseCertificateFromFile("serial_zero_padded_21_bytes.pem", {});
490 ASSERT_FALSE(cert);
491
492 // Try again with allow_invalid_serial_numbers=true. Parsing should succeed.
493 ParseCertificateOptions options;
494 options.allow_invalid_serial_numbers = true;
495 cert = ParseCertificateFromFile("serial_zero_padded_21_bytes.pem", options);
496 ASSERT_TRUE(cert);
497
498 static const uint8_t expected_serial[21] = {
499 0x00, 0x80, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
500 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13};
501 EXPECT_EQ(der::Input(expected_serial), cert->tbs().serial_number);
502 }
503
504 // Tests a serial number which is negative. CAs are not supposed to include
505 // negative serial numbers, however RFC 5280 expects consumers to deal with it
506 // anyway.
TEST(ParsedCertificateTest,SerialNumberNegative)507 TEST(ParsedCertificateTest, SerialNumberNegative) {
508 std::shared_ptr<const ParsedCertificate> cert =
509 ParseCertificateFromFile("serial_negative.pem", {});
510 ASSERT_TRUE(cert);
511
512 static const uint8_t expected_serial[2] = {0x80, 0x01};
513 EXPECT_EQ(der::Input(expected_serial), cert->tbs().serial_number);
514 }
515
516 // Tests a serial number which is very long. RFC 5280 specifies a maximum of 20
517 // bytes.
TEST(ParsedCertificateTest,SerialNumber37BytesLong)518 TEST(ParsedCertificateTest, SerialNumber37BytesLong) {
519 std::shared_ptr<const ParsedCertificate> cert =
520 ParseCertificateFromFile("serial_37_bytes.pem", {});
521 ASSERT_FALSE(cert);
522
523 // Try again with allow_invalid_serial_numbers=true. Parsing should succeed.
524 ParseCertificateOptions options;
525 options.allow_invalid_serial_numbers = true;
526 cert = ParseCertificateFromFile("serial_37_bytes.pem", options);
527 ASSERT_TRUE(cert);
528
529 static const uint8_t expected_serial[37] = {
530 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
531 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
532 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
533 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25};
534 EXPECT_EQ(der::Input(expected_serial), cert->tbs().serial_number);
535 }
536
537 // Tests a serial number which is zero. RFC 5280 says they should be positive,
538 // however also recommends supporting non-positive ones, so parsing here
539 // is expected to succeed.
TEST(ParsedCertificateTest,SerialNumberZero)540 TEST(ParsedCertificateTest, SerialNumberZero) {
541 std::shared_ptr<const ParsedCertificate> cert =
542 ParseCertificateFromFile("serial_zero.pem", {});
543 ASSERT_TRUE(cert);
544
545 static const uint8_t expected_serial[] = {0x00};
546 EXPECT_EQ(der::Input(expected_serial), cert->tbs().serial_number);
547 }
548
549 // Tests a serial number which not a number (NULL).
TEST(ParsedCertificateTest,SerialNotNumber)550 TEST(ParsedCertificateTest, SerialNotNumber) {
551 std::shared_ptr<const ParsedCertificate> cert =
552 ParseCertificateFromFile("serial_not_number.pem", {});
553 ASSERT_FALSE(cert);
554 }
555
556 // Tests a serial number which uses a non-minimal INTEGER encoding
TEST(ParsedCertificateTest,SerialNotMinimal)557 TEST(ParsedCertificateTest, SerialNotMinimal) {
558 std::shared_ptr<const ParsedCertificate> cert =
559 ParseCertificateFromFile("serial_not_minimal.pem", {});
560 ASSERT_FALSE(cert);
561 }
562
563 // Tests parsing a certificate that has an inhibitAnyPolicy extension.
TEST(ParsedCertificateTest,InhibitAnyPolicy)564 TEST(ParsedCertificateTest, InhibitAnyPolicy) {
565 std::shared_ptr<const ParsedCertificate> cert =
566 ParseCertificateFromFile("inhibit_any_policy.pem", {});
567 ASSERT_TRUE(cert);
568
569 ParsedExtension extension;
570 ASSERT_TRUE(cert->GetExtension(der::Input(kInhibitAnyPolicyOid), &extension));
571
572 std::optional<uint8_t> skip_count = ParseInhibitAnyPolicy(extension.value);
573 ASSERT_TRUE(skip_count.has_value());
574 EXPECT_EQ(3, skip_count.value());
575 }
576
577 // Tests a subjectKeyIdentifier that is not an OCTET_STRING.
TEST(ParsedCertificateTest,SubjectKeyIdentifierNotOctetString)578 TEST(ParsedCertificateTest, SubjectKeyIdentifierNotOctetString) {
579 std::shared_ptr<const ParsedCertificate> cert = ParseCertificateFromFile(
580 "subject_key_identifier_not_octet_string.pem", {});
581 ASSERT_FALSE(cert);
582 }
583
584 // Tests an authorityKeyIdentifier that is not a SEQUENCE.
TEST(ParsedCertificateTest,AuthourityKeyIdentifierNotSequence)585 TEST(ParsedCertificateTest, AuthourityKeyIdentifierNotSequence) {
586 std::shared_ptr<const ParsedCertificate> cert =
587 ParseCertificateFromFile("authority_key_identifier_not_sequence.pem", {});
588 ASSERT_FALSE(cert);
589 }
590
591 } // namespace
592
593 } // namespace net
594