Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(641)

Side by Side Diff: net/cert/internal/parse_certificate_unittest.cc

Issue 2341943002: Add error details to TBSCertificate parsing function and tests. (Closed)
Patch Set: update comment Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/strings/stringprintf.h" 7 #include "base/strings/stringprintf.h"
8 #include "net/cert/internal/cert_errors.h" 8 #include "net/cert/internal/cert_errors.h"
9 #include "net/cert/internal/test_helpers.h" 9 #include "net/cert/internal/test_helpers.h"
10 #include "net/der/input.h" 10 #include "net/der/input.h"
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 115
116 // Tests what happens when the signature algorithm is present, but has the wrong 116 // Tests what happens when the signature algorithm is present, but has the wrong
117 // tag. 117 // tag.
118 TEST(ParseCertificateTest, AlgorithmNotSequence) { 118 TEST(ParseCertificateTest, AlgorithmNotSequence) {
119 RunCertificateTest("cert_algorithm_not_sequence.pem"); 119 RunCertificateTest("cert_algorithm_not_sequence.pem");
120 } 120 }
121 121
122 // Loads tbsCertificate data and expectations from the PEM file |file_name|. 122 // Loads tbsCertificate data and expectations from the PEM file |file_name|.
123 // Verifies that parsing the TBSCertificate succeeds, and each parsed field 123 // Verifies that parsing the TBSCertificate succeeds, and each parsed field
124 // matches the expectations. 124 // matches the expectations.
125 void EnsureParsingTbsSucceeds(const std::string& file_name, 125 //
126 CertificateVersion expected_version) { 126 // TODO(eroman): Get rid of the |expected_version| parameter -- this should be
127 // encoded in the test expectations file.
128 void RunTbsCertificateTestGivenVersion(const std::string& file_name,
129 CertificateVersion expected_version) {
127 std::string data; 130 std::string data;
128 std::string expected_serial_number; 131 std::string expected_serial_number;
129 std::string expected_signature_algorithm; 132 std::string expected_signature_algorithm;
130 std::string expected_issuer; 133 std::string expected_issuer;
131 std::string expected_validity_not_before; 134 std::string expected_validity_not_before;
132 std::string expected_validity_not_after; 135 std::string expected_validity_not_after;
133 std::string expected_subject; 136 std::string expected_subject;
134 std::string expected_spki; 137 std::string expected_spki;
135 std::string expected_issuer_unique_id; 138 std::string expected_issuer_unique_id;
136 std::string expected_subject_unique_id; 139 std::string expected_subject_unique_id;
137 std::string expected_extensions; 140 std::string expected_extensions;
141 std::string expected_errors;
138 142
139 // Read the certificate data and test expectations from a single PEM file. 143 // Read the certificate data and test expectations from a single PEM file.
140 const PemBlockMapping mappings[] = { 144 const PemBlockMapping mappings[] = {
141 {"TBS CERTIFICATE", &data}, 145 {"TBS CERTIFICATE", &data},
142 {"SIGNATURE ALGORITHM", &expected_signature_algorithm}, 146 {"SIGNATURE ALGORITHM", &expected_signature_algorithm, true},
143 {"SERIAL NUMBER", &expected_serial_number}, 147 {"SERIAL NUMBER", &expected_serial_number, true},
144 {"ISSUER", &expected_issuer}, 148 {"ISSUER", &expected_issuer, true},
145 {"VALIDITY NOTBEFORE", &expected_validity_not_before}, 149 {"VALIDITY NOTBEFORE", &expected_validity_not_before, true},
146 {"VALIDITY NOTAFTER", &expected_validity_not_after}, 150 {"VALIDITY NOTAFTER", &expected_validity_not_after, true},
147 {"SUBJECT", &expected_subject}, 151 {"SUBJECT", &expected_subject, true},
148 {"SPKI", &expected_spki}, 152 {"SPKI", &expected_spki, true},
149 {"ISSUER UNIQUE ID", &expected_issuer_unique_id, true}, 153 {"ISSUER UNIQUE ID", &expected_issuer_unique_id, true},
150 {"SUBJECT UNIQUE ID", &expected_subject_unique_id, true}, 154 {"SUBJECT UNIQUE ID", &expected_subject_unique_id, true},
151 {"EXTENSIONS", &expected_extensions, true}, 155 {"EXTENSIONS", &expected_extensions, true},
156 {"ERRORS", &expected_errors, true},
152 }; 157 };
153 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); 158 std::string test_file_path = GetFilePath(file_name);
159 ASSERT_TRUE(ReadTestDataFromPemFile(test_file_path, mappings));
154 160
155 // Parsing the TBSCertificate should succeed. 161 bool expected_result = !expected_spki.empty();
162
156 ParsedTbsCertificate parsed; 163 ParsedTbsCertificate parsed;
157 ASSERT_TRUE(ParseTbsCertificate(der::Input(&data), {}, &parsed)); 164 CertErrors errors;
165 bool actual_result =
166 ParseTbsCertificate(der::Input(&data), {}, &parsed, &errors);
167
168 EXPECT_EQ(expected_result, actual_result);
169 EXPECT_EQ(expected_errors, errors.ToDebugString()) << "Test file: "
170 << test_file_path;
171
172 if (!expected_result || !actual_result)
173 return;
158 174
159 // Ensure that the ParsedTbsCertificate matches expectations. 175 // Ensure that the ParsedTbsCertificate matches expectations.
160 EXPECT_EQ(expected_version, parsed.version); 176 EXPECT_EQ(expected_version, parsed.version);
161 177
162 EXPECT_EQ(der::Input(&expected_serial_number), parsed.serial_number); 178 EXPECT_EQ(der::Input(&expected_serial_number), parsed.serial_number);
163 EXPECT_EQ(der::Input(&expected_signature_algorithm), 179 EXPECT_EQ(der::Input(&expected_signature_algorithm),
164 parsed.signature_algorithm_tlv); 180 parsed.signature_algorithm_tlv);
165 181
166 EXPECT_EQ(der::Input(&expected_issuer), parsed.issuer_tlv); 182 EXPECT_EQ(der::Input(&expected_issuer), parsed.issuer_tlv);
167 183
168 // In the test expectations PEM file, validity is described as a 184 // In the test expectations PEM file, validity is described as a
169 // textual string of the parsed value (rather than as DER). 185 // textual string of the parsed value (rather than as DER).
170 EXPECT_EQ(expected_validity_not_before, ToString(parsed.validity_not_before)); 186 EXPECT_EQ(expected_validity_not_before, ToString(parsed.validity_not_before));
171 EXPECT_EQ(expected_validity_not_after, ToString(parsed.validity_not_after)); 187 EXPECT_EQ(expected_validity_not_after, ToString(parsed.validity_not_after));
172 188
173 EXPECT_EQ(der::Input(&expected_subject), parsed.subject_tlv); 189 EXPECT_EQ(der::Input(&expected_subject), parsed.subject_tlv);
174 EXPECT_EQ(der::Input(&expected_spki), parsed.spki_tlv); 190 EXPECT_EQ(der::Input(&expected_spki), parsed.spki_tlv);
175 191
176 EXPECT_EQ(der::Input(&expected_issuer_unique_id), 192 EXPECT_EQ(der::Input(&expected_issuer_unique_id),
177 parsed.issuer_unique_id.bytes()); 193 parsed.issuer_unique_id.bytes());
178 EXPECT_EQ(!expected_issuer_unique_id.empty(), parsed.has_issuer_unique_id); 194 EXPECT_EQ(!expected_issuer_unique_id.empty(), parsed.has_issuer_unique_id);
179 EXPECT_EQ(der::Input(&expected_subject_unique_id), 195 EXPECT_EQ(der::Input(&expected_subject_unique_id),
180 parsed.subject_unique_id.bytes()); 196 parsed.subject_unique_id.bytes());
181 EXPECT_EQ(!expected_subject_unique_id.empty(), parsed.has_subject_unique_id); 197 EXPECT_EQ(!expected_subject_unique_id.empty(), parsed.has_subject_unique_id);
182 198
183 EXPECT_EQ(der::Input(&expected_extensions), parsed.extensions_tlv); 199 EXPECT_EQ(der::Input(&expected_extensions), parsed.extensions_tlv);
184 EXPECT_EQ(!expected_extensions.empty(), parsed.has_extensions); 200 EXPECT_EQ(!expected_extensions.empty(), parsed.has_extensions);
185 } 201 }
186 202
187 // Loads certificate data from the PEM file |file_name| and verifies that the 203 void RunTbsCertificateTest(const std::string& file_name) {
188 // Certificate parsing succeed, however the TBSCertificate parsing fails. 204 RunTbsCertificateTestGivenVersion(file_name, CertificateVersion::V3);
189 void EnsureParsingTbsFails(const std::string& file_name) {
190 std::string data;
191
192 const PemBlockMapping mappings[] = {
193 {"TBS CERTIFICATE", &data},
194 };
195
196 ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings));
197
198 // Parsing the TBSCertificate should fail.
199 ParsedTbsCertificate parsed;
200 ASSERT_FALSE(ParseTbsCertificate(der::Input(&data), {}, &parsed));
201 } 205 }
202 206
203 // Tests parsing a TBSCertificate for v3 that contains no optional fields. 207 // Tests parsing a TBSCertificate for v3 that contains no optional fields.
204 TEST(ParseTbsCertificateTest, Version3NoOptionals) { 208 TEST(ParseTbsCertificateTest, Version3NoOptionals) {
205 EnsureParsingTbsSucceeds("tbs_v3_no_optionals.pem", CertificateVersion::V3); 209 RunTbsCertificateTest("tbs_v3_no_optionals.pem");
206 } 210 }
207 211
208 // Tests parsing a TBSCertificate for v3 that contains extensions. 212 // Tests parsing a TBSCertificate for v3 that contains extensions.
209 TEST(ParseTbsCertificateTest, Version3WithExtensions) { 213 TEST(ParseTbsCertificateTest, Version3WithExtensions) {
210 EnsureParsingTbsSucceeds("tbs_v3_extensions.pem", CertificateVersion::V3); 214 RunTbsCertificateTest("tbs_v3_extensions.pem");
211 } 215 }
212 216
213 // Tests parsing a TBSCertificate for v3 that contains no optional fields, and 217 // Tests parsing a TBSCertificate for v3 that contains no optional fields, and
214 // has a negative serial number. 218 // has a negative serial number.
215 // 219 //
216 // CAs are not supposed to include negative serial numbers, however RFC 5280 220 // CAs are not supposed to include negative serial numbers, however RFC 5280
217 // expects consumers to deal with it anyway). 221 // expects consumers to deal with it anyway).
218 TEST(ParseTbsCertificateTest, NegativeSerialNumber) { 222 TEST(ParseTbsCertificateTest, NegativeSerialNumber) {
219 EnsureParsingTbsSucceeds("tbs_negative_serial_number.pem", 223 RunTbsCertificateTest("tbs_negative_serial_number.pem");
220 CertificateVersion::V3);
221 } 224 }
222 225
223 // Tests parsing a TBSCertificate with a serial number that is 21 octets long 226 // Tests parsing a TBSCertificate with a serial number that is 21 octets long
224 // (and the first byte is 0). 227 // (and the first byte is 0).
225 TEST(ParseTbCertificateTest, SerialNumber21OctetsLeading0) { 228 TEST(ParseTbCertificateTest, SerialNumber21OctetsLeading0) {
226 EnsureParsingTbsFails("tbs_serial_number_21_octets_leading_0.pem"); 229 RunTbsCertificateTest("tbs_serial_number_21_octets_leading_0.pem");
227 } 230 }
228 231
229 // Tests parsing a TBSCertificate with a serial number that is 26 octets long 232 // Tests parsing a TBSCertificate with a serial number that is 26 octets long
230 // (and does not contain a leading 0). 233 // (and does not contain a leading 0).
231 TEST(ParseTbsCertificateTest, SerialNumber26Octets) { 234 TEST(ParseTbsCertificateTest, SerialNumber26Octets) {
232 EnsureParsingTbsFails("tbs_serial_number_26_octets.pem"); 235 RunTbsCertificateTest("tbs_serial_number_26_octets.pem");
233 } 236 }
234 237
235 // Tests parsing a TBSCertificate which lacks a version number (causing it to 238 // Tests parsing a TBSCertificate which lacks a version number (causing it to
236 // default to v1). 239 // default to v1).
237 TEST(ParseTbsCertificateTest, Version1) { 240 TEST(ParseTbsCertificateTest, Version1) {
238 EnsureParsingTbsSucceeds("tbs_v1.pem", CertificateVersion::V1); 241 RunTbsCertificateTestGivenVersion("tbs_v1.pem", CertificateVersion::V1);
239 } 242 }
240 243
241 // The version was set to v1 explicitly rather than omitting the version field. 244 // The version was set to v1 explicitly rather than omitting the version field.
242 TEST(ParseTbsCertificateTest, ExplicitVersion1) { 245 TEST(ParseTbsCertificateTest, ExplicitVersion1) {
243 EnsureParsingTbsFails("tbs_explicit_v1.pem"); 246 RunTbsCertificateTest("tbs_explicit_v1.pem");
244 } 247 }
245 248
246 // Extensions are not defined in version 1. 249 // Extensions are not defined in version 1.
247 TEST(ParseTbsCertificateTest, Version1WithExtensions) { 250 TEST(ParseTbsCertificateTest, Version1WithExtensions) {
248 EnsureParsingTbsFails("tbs_v1_extensions.pem"); 251 RunTbsCertificateTest("tbs_v1_extensions.pem");
249 } 252 }
250 253
251 // Extensions are not defined in version 2. 254 // Extensions are not defined in version 2.
252 TEST(ParseTbsCertificateTest, Version2WithExtensions) { 255 TEST(ParseTbsCertificateTest, Version2WithExtensions) {
253 EnsureParsingTbsFails("tbs_v2_extensions.pem"); 256 RunTbsCertificateTest("tbs_v2_extensions.pem");
254 } 257 }
255 258
256 // A boring version 2 certificate with none of the optional fields. 259 // A boring version 2 certificate with none of the optional fields.
257 TEST(ParseTbsCertificateTest, Version2NoOptionals) { 260 TEST(ParseTbsCertificateTest, Version2NoOptionals) {
258 EnsureParsingTbsSucceeds("tbs_v2_no_optionals.pem", CertificateVersion::V2); 261 RunTbsCertificateTestGivenVersion("tbs_v2_no_optionals.pem",
262 CertificateVersion::V2);
259 } 263 }
260 264
261 // A version 2 certificate with an issuer unique ID field. 265 // A version 2 certificate with an issuer unique ID field.
262 TEST(ParseTbsCertificateTest, Version2IssuerUniqueId) { 266 TEST(ParseTbsCertificateTest, Version2IssuerUniqueId) {
263 EnsureParsingTbsSucceeds("tbs_v2_issuer_unique_id.pem", 267 RunTbsCertificateTestGivenVersion("tbs_v2_issuer_unique_id.pem",
264 CertificateVersion::V2); 268 CertificateVersion::V2);
265 } 269 }
266 270
267 // A version 2 certificate with both a issuer and subject unique ID field. 271 // A version 2 certificate with both a issuer and subject unique ID field.
268 TEST(ParseTbsCertificateTest, Version2IssuerAndSubjectUniqueId) { 272 TEST(ParseTbsCertificateTest, Version2IssuerAndSubjectUniqueId) {
269 EnsureParsingTbsSucceeds("tbs_v2_issuer_and_subject_unique_id.pem", 273 RunTbsCertificateTestGivenVersion("tbs_v2_issuer_and_subject_unique_id.pem",
270 CertificateVersion::V2); 274 CertificateVersion::V2);
271 } 275 }
272 276
273 // A version 3 certificate with all of the optional fields (issuer unique id, 277 // A version 3 certificate with all of the optional fields (issuer unique id,
274 // subject unique id, and extensions). 278 // subject unique id, and extensions).
275 TEST(ParseTbsCertificateTest, Version3AllOptionals) { 279 TEST(ParseTbsCertificateTest, Version3AllOptionals) {
276 EnsureParsingTbsSucceeds("tbs_v3_all_optionals.pem", CertificateVersion::V3); 280 RunTbsCertificateTest("tbs_v3_all_optionals.pem");
277 } 281 }
278 282
279 // The version was set to v4, which is unrecognized. 283 // The version was set to v4, which is unrecognized.
280 TEST(ParseTbsCertificateTest, Version4) { 284 TEST(ParseTbsCertificateTest, Version4) {
281 EnsureParsingTbsFails("tbs_v4.pem"); 285 RunTbsCertificateTest("tbs_v4.pem");
282 } 286 }
283 287
284 // Tests that extraneous data after extensions in a v3 is rejected. 288 // Tests that extraneous data after extensions in a v3 is rejected.
285 TEST(ParseTbsCertificateTest, Version3DataAfterExtensions) { 289 TEST(ParseTbsCertificateTest, Version3DataAfterExtensions) {
286 EnsureParsingTbsFails("tbs_v3_data_after_extensions.pem"); 290 RunTbsCertificateTest("tbs_v3_data_after_extensions.pem");
287 } 291 }
288 292
289 // Tests using a real-world certificate (whereas the other tests are fabricated 293 // Tests using a real-world certificate (whereas the other tests are fabricated
290 // (and in fact invalid) data. 294 // (and in fact invalid) data.
291 TEST(ParseTbsCertificateTest, Version3Real) { 295 TEST(ParseTbsCertificateTest, Version3Real) {
292 EnsureParsingTbsSucceeds("tbs_v3_real.pem", CertificateVersion::V3); 296 RunTbsCertificateTest("tbs_v3_real.pem");
293 } 297 }
294 298
295 // Parses a TBSCertificate whose "validity" field expresses both notBefore 299 // Parses a TBSCertificate whose "validity" field expresses both notBefore
296 // and notAfter using UTCTime. 300 // and notAfter using UTCTime.
297 TEST(ParseTbsCertificateTest, ValidityBothUtcTime) { 301 TEST(ParseTbsCertificateTest, ValidityBothUtcTime) {
298 EnsureParsingTbsSucceeds("tbs_validity_both_utc_time.pem", 302 RunTbsCertificateTest("tbs_validity_both_utc_time.pem");
299 CertificateVersion::V3);
300 } 303 }
301 304
302 // Parses a TBSCertificate whose "validity" field expresses both notBefore 305 // Parses a TBSCertificate whose "validity" field expresses both notBefore
303 // and notAfter using GeneralizedTime. 306 // and notAfter using GeneralizedTime.
304 TEST(ParseTbsCertificateTest, ValidityBothGeneralizedTime) { 307 TEST(ParseTbsCertificateTest, ValidityBothGeneralizedTime) {
305 EnsureParsingTbsSucceeds("tbs_validity_both_generalized_time.pem", 308 RunTbsCertificateTest("tbs_validity_both_generalized_time.pem");
306 CertificateVersion::V3);
307 } 309 }
308 310
309 // Parses a TBSCertificate whose "validity" field expresses notBefore using 311 // Parses a TBSCertificate whose "validity" field expresses notBefore using
310 // UTCTime and notAfter using GeneralizedTime. 312 // UTCTime and notAfter using GeneralizedTime.
311 TEST(ParseTbsCertificateTest, ValidityUTCTimeAndGeneralizedTime) { 313 TEST(ParseTbsCertificateTest, ValidityUTCTimeAndGeneralizedTime) {
312 EnsureParsingTbsSucceeds("tbs_validity_utc_time_and_generalized_time.pem", 314 RunTbsCertificateTest("tbs_validity_utc_time_and_generalized_time.pem");
313 CertificateVersion::V3);
314 } 315 }
315 316
316 // Parses a TBSCertificate whose validity" field expresses notBefore using 317 // Parses a TBSCertificate whose validity" field expresses notBefore using
317 // GeneralizedTime and notAfter using UTCTime. Also of interest, notBefore > 318 // GeneralizedTime and notAfter using UTCTime. Also of interest, notBefore >
318 // notAfter. Parsing will succeed, however no time can satisfy this constraint. 319 // notAfter. Parsing will succeed, however no time can satisfy this constraint.
319 TEST(ParseTbsCertificateTest, ValidityGeneralizedTimeAndUTCTime) { 320 TEST(ParseTbsCertificateTest, ValidityGeneralizedTimeAndUTCTime) {
320 EnsureParsingTbsSucceeds("tbs_validity_generalized_time_and_utc_time.pem", 321 RunTbsCertificateTest("tbs_validity_generalized_time_and_utc_time.pem");
321 CertificateVersion::V3);
322 } 322 }
323 323
324 // Parses a TBSCertificate whose "validity" field does not strictly follow 324 // Parses a TBSCertificate whose "validity" field does not strictly follow
325 // the DER rules (and fails to be parsed). 325 // the DER rules (and fails to be parsed).
326 TEST(ParseTbsCertificateTest, ValidityRelaxed) { 326 TEST(ParseTbsCertificateTest, ValidityRelaxed) {
327 EnsureParsingTbsFails("tbs_validity_relaxed.pem"); 327 RunTbsCertificateTest("tbs_validity_relaxed.pem");
328 } 328 }
329 329
330 // Reads a PEM file containing a block "EXTENSION". This input will be 330 // Reads a PEM file containing a block "EXTENSION". This input will be
331 // passed to ParseExtension, and the results filled in |out|. 331 // passed to ParseExtension, and the results filled in |out|.
332 bool ParseExtensionFromFile(const std::string& file_name, 332 bool ParseExtensionFromFile(const std::string& file_name,
333 ParsedExtension* out, 333 ParsedExtension* out,
334 std::string* data) { 334 std::string* data) {
335 const PemBlockMapping mappings[] = { 335 const PemBlockMapping mappings[] = {
336 {"EXTENSION", data}, 336 {"EXTENSION", data},
337 }; 337 };
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 0x00, // Number of unused bits 784 0x00, // Number of unused bits
785 }; 785 };
786 786
787 der::BitString key_usage; 787 der::BitString key_usage;
788 ASSERT_FALSE(ParseKeyUsage(der::Input(der), &key_usage)); 788 ASSERT_FALSE(ParseKeyUsage(der::Input(der), &key_usage));
789 } 789 }
790 790
791 } // namespace 791 } // namespace
792 792
793 } // namespace net 793 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698