OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/internal/parse_certificate.h" | 5 #include "net/cert/internal/parse_certificate.h" |
6 | 6 |
7 #include "net/cert/internal/test_helpers.h" | 7 #include "net/cert/internal/test_helpers.h" |
8 #include "net/der/input.h" | 8 #include "net/der/input.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 | 10 |
11 namespace net { | 11 namespace net { |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 std::string GetFilePath(const std::string file_name) { | 15 std::string GetFilePath(const std::string file_name) { |
16 return std::string("net/data/parse_certificate_unittest/") + file_name; | 16 return std::string("net/data/parse_certificate_unittest/") + file_name; |
17 } | 17 } |
18 | 18 |
19 // Loads certificate data and expectations from the PEM file |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 | 20 // Verifies that parsing the Certificate succeeds, and each parsed field matches |
21 // the expectations. | 21 // the expectations. |
22 void EnsureParsingCertificateSucceds(const std::string& file_name) { | 22 void EnsureParsingCertificateSucceeds(const std::string& file_name) { |
23 std::string data; | 23 std::string data; |
24 std::string expected_tbs_certificate; | 24 std::string expected_tbs_certificate; |
25 std::string expected_signature_algorithm; | 25 std::string expected_signature_algorithm; |
26 std::string expected_signature; | 26 std::string expected_signature; |
27 | 27 |
28 // Read the certificate data and test expectations from a single PEM file. | 28 // Read the certificate data and test expectations from a single PEM file. |
29 const PemBlockMapping mappings[] = { | 29 const PemBlockMapping mappings[] = { |
30 {"CERTIFICATE", &data}, | 30 {"CERTIFICATE", &data}, |
31 {"SIGNATURE", &expected_signature}, | 31 {"SIGNATURE", &expected_signature}, |
32 {"SIGNATURE ALGORITHM", &expected_signature_algorithm}, | 32 {"SIGNATURE ALGORITHM", &expected_signature_algorithm}, |
(...skipping 26 matching lines...) Expand all Loading... |
59 | 59 |
60 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); | 60 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); |
61 | 61 |
62 // Parsing the Certificate should fail. | 62 // Parsing the Certificate should fail. |
63 ParsedCertificate parsed; | 63 ParsedCertificate parsed; |
64 ASSERT_FALSE(ParseCertificate(InputFromString(&data), &parsed)); | 64 ASSERT_FALSE(ParseCertificate(InputFromString(&data), &parsed)); |
65 } | 65 } |
66 | 66 |
67 // Tests parsing a Certificate. | 67 // Tests parsing a Certificate. |
68 TEST(ParseCertificateTest, Version3) { | 68 TEST(ParseCertificateTest, Version3) { |
69 EnsureParsingCertificateSucceds("cert_version3.pem"); | 69 EnsureParsingCertificateSucceeds("cert_version3.pem"); |
70 } | 70 } |
71 | 71 |
72 // Tests parsing a simplified Certificate-like structure (the sub-fields for | 72 // Tests parsing a simplified Certificate-like structure (the sub-fields for |
73 // algorithm and tbsCertificate are not actually valid, but ParseCertificate() | 73 // algorithm and tbsCertificate are not actually valid, but ParseCertificate() |
74 // doesn't check them) | 74 // doesn't check them) |
75 TEST(ParseCertificateTest, Skeleton) { | 75 TEST(ParseCertificateTest, Skeleton) { |
76 EnsureParsingCertificateSucceds("cert_skeleton.pem"); | 76 EnsureParsingCertificateSucceeds("cert_skeleton.pem"); |
77 } | 77 } |
78 | 78 |
79 // Tests parsing a Certificate that is not a sequence fails. | 79 // Tests parsing a Certificate that is not a sequence fails. |
80 TEST(ParseCertificateTest, NotSequence) { | 80 TEST(ParseCertificateTest, NotSequence) { |
81 EnsureParsingCertificateFails("cert_not_sequence.pem"); | 81 EnsureParsingCertificateFails("cert_not_sequence.pem"); |
82 } | 82 } |
83 | 83 |
84 // Tests that uncomsumed data is not allowed after the main SEQUENCE. | 84 // Tests that uncomsumed data is not allowed after the main SEQUENCE. |
85 TEST(ParseCertificateTest, DataAfterSignature) { | 85 TEST(ParseCertificateTest, DataAfterSignature) { |
86 EnsureParsingCertificateFails("cert_data_after_signature.pem"); | 86 EnsureParsingCertificateFails("cert_data_after_signature.pem"); |
(...skipping 14 matching lines...) Expand all Loading... |
101 TEST(ParseCertificateTest, EmptySequence) { | 101 TEST(ParseCertificateTest, EmptySequence) { |
102 EnsureParsingCertificateFails("cert_empty_sequence.pem"); | 102 EnsureParsingCertificateFails("cert_empty_sequence.pem"); |
103 } | 103 } |
104 | 104 |
105 // Tests what happens when the signature algorithm is present, but has the wrong | 105 // Tests what happens when the signature algorithm is present, but has the wrong |
106 // tag. | 106 // tag. |
107 TEST(ParseCertificateTest, AlgorithmNotSequence) { | 107 TEST(ParseCertificateTest, AlgorithmNotSequence) { |
108 EnsureParsingCertificateFails("cert_algorithm_not_sequence.pem"); | 108 EnsureParsingCertificateFails("cert_algorithm_not_sequence.pem"); |
109 } | 109 } |
110 | 110 |
| 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) { |
| 116 std::string data; |
| 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; |
| 126 |
| 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}, |
| 139 }; |
| 140 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); |
| 141 |
| 142 // Parsing the TBSCertificate should succeed. |
| 143 ParsedTbsCertificate parsed; |
| 144 ASSERT_TRUE(ParseTbsCertificate(InputFromString(&data), &parsed)); |
| 145 |
| 146 // Ensure that the ParsedTbsCertificate matches expectations. |
| 147 EXPECT_EQ(expected_version, parsed.version); |
| 148 |
| 149 EXPECT_EQ(InputFromString(&expected_serial_number), parsed.serial_number); |
| 150 EXPECT_EQ(InputFromString(&expected_signature_algorithm), |
| 151 parsed.signature_algorithm_tlv); |
| 152 |
| 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); |
| 157 |
| 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); |
| 164 |
| 165 EXPECT_EQ(InputFromString(&expected_extensions), parsed.extensions_tlv); |
| 166 EXPECT_EQ(!expected_extensions.empty(), parsed.has_extensions); |
| 167 } |
| 168 |
| 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) { |
| 172 std::string data; |
| 173 |
| 174 const PemBlockMapping mappings[] = { |
| 175 {"TBS CERTIFICATE", &data}, |
| 176 }; |
| 177 |
| 178 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); |
| 179 |
| 180 // Parsing the TBSCertificate should fail. |
| 181 ParsedTbsCertificate parsed; |
| 182 ASSERT_FALSE(ParseTbsCertificate(InputFromString(&data), &parsed)); |
| 183 } |
| 184 |
| 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); |
| 188 } |
| 189 |
| 190 // Tests parsing a TBSCertificate for v3 that contains extensions. |
| 191 TEST(ParseTbsCertificateTest, Version3WithExtensions) { |
| 192 EnsureParsingTbsSucceeds("tbs_v3_extensions.pem", CertificateVersion::V3); |
| 193 } |
| 194 |
| 195 // Tests parsing a TBSCertificate for v3 that contains no optional fields, and |
| 196 // has a negative serial number. |
| 197 // |
| 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); |
| 203 } |
| 204 |
| 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"); |
| 209 } |
| 210 |
| 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"); |
| 215 } |
| 216 |
| 217 // Tests parsing a TBSCertificate which lacks a version number (causing it to |
| 218 // default to v1). |
| 219 TEST(ParseTbsCertificateTest, Version1) { |
| 220 EnsureParsingTbsSucceeds("tbs_v1.pem", CertificateVersion::V1); |
| 221 } |
| 222 |
| 223 // The version was set to v1 explicitly rather than omitting the version field. |
| 224 TEST(ParseTbsCertificateTest, ExplicitVersion1) { |
| 225 EnsureParsingTbsFails("tbs_explicit_v1.pem"); |
| 226 } |
| 227 |
| 228 // Extensions are not defined in version 1. |
| 229 TEST(ParseTbsCertificateTest, Version1WithExtensions) { |
| 230 EnsureParsingTbsFails("tbs_v1_extensions.pem"); |
| 231 } |
| 232 |
| 233 // Extensions are not defined in version 2. |
| 234 TEST(ParseTbsCertificateTest, Version2WithExtensions) { |
| 235 EnsureParsingTbsFails("tbs_v2_extensions.pem"); |
| 236 } |
| 237 |
| 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); |
| 241 } |
| 242 |
| 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); |
| 247 } |
| 248 |
| 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); |
| 253 } |
| 254 |
| 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); |
| 259 } |
| 260 |
| 261 // The version was set to v4, which is unrecognized. |
| 262 TEST(ParseTbsCertificateTest, Version4) { |
| 263 EnsureParsingTbsFails("tbs_v4.pem"); |
| 264 } |
| 265 |
| 266 // Tests that extraneous data after extensions in a v3 is rejected. |
| 267 TEST(ParseTbsCertificateTest, Version3DataAfterExtensions) { |
| 268 EnsureParsingTbsFails("tbs_v3_data_after_extensions.pem"); |
| 269 } |
| 270 |
| 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); |
| 275 } |
| 276 |
111 } // namespace | 277 } // namespace |
112 | 278 |
113 } // namespace net | 279 } // namespace net |
OLD | NEW |