Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / cert / internal / verify_name_match_unittest.cc
blobd6dc3884dcbb513513b7b0f47aef2249fbeb394d
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/verify_name_match.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
9 #include "net/cert/internal/test_helpers.h"
10 #include "net/der/input.h"
11 #include "net/der/parser.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace net {
15 namespace {
17 der::Input SequenceValueFromString(const std::string* s) {
18 der::Parser parser(InputFromString(s));
19 der::Input data;
20 if (!parser.ReadTag(der::kSequence, &data)) {
21 ADD_FAILURE();
22 return der::Input();
24 if (parser.HasMore()) {
25 ADD_FAILURE();
26 return der::Input();
28 return data;
31 // Loads test data from file. The filename is constructed from the parameters:
32 // |prefix| describes the type of data being tested, e.g. "ascii",
33 // "unicode_bmp", "unicode_supplementary", and "invalid".
34 // |value_type| indicates what ASN.1 type is used to encode the data.
35 // |suffix| indicates any additional modifications, such as caseswapping,
36 // whitespace adding, etc.
37 ::testing::AssertionResult LoadTestData(const std::string& prefix,
38 const std::string& value_type,
39 const std::string& suffix,
40 std::string* result) {
41 std::string path = "net/data/verify_name_match_unittest/names/" + prefix +
42 "-" + value_type + "-" + suffix + ".pem";
44 const PemBlockMapping mappings[] = {
45 {"NAME", result},
48 return ReadTestDataFromPemFile(path, mappings);
51 bool TypesAreComparable(const std::string& type_1, const std::string& type_2) {
52 if (type_1 == type_2)
53 return true;
54 if ((type_1 == "PRINTABLESTRING" || type_1 == "UTF8" ||
55 type_1 == "BMPSTRING" || type_1 == "UNIVERSALSTRING") &&
56 (type_2 == "PRINTABLESTRING" || type_2 == "UTF8" ||
57 type_2 == "BMPSTRING" || type_2 == "UNIVERSALSTRING")) {
58 return true;
60 return false;
63 // All string types.
64 static const char* kValueTypes[] = {"PRINTABLESTRING", "T61STRING", "UTF8",
65 "BMPSTRING", "UNIVERSALSTRING"};
66 // String types that can encode the Unicode Basic Multilingual Plane.
67 static const char* kUnicodeBMPValueTypes[] = {"UTF8", "BMPSTRING",
68 "UNIVERSALSTRING"};
69 // String types that can encode the Unicode Supplementary Planes.
70 static const char* kUnicodeSupplementaryValueTypes[] = {"UTF8",
71 "UNIVERSALSTRING"};
73 static const char* kMangleTypes[] = {"unmangled", "case_swap",
74 "extra_whitespace"};
76 } // namespace
78 class VerifyNameMatchSimpleTest
79 : public ::testing::TestWithParam<
80 ::testing::tuple<const char*, const char*>> {
81 public:
82 std::string value_type() const { return ::testing::get<0>(GetParam()); }
83 std::string suffix() const { return ::testing::get<1>(GetParam()); }
86 // Compare each input against itself, verifies that all input data is parsed
87 // successfully.
88 TEST_P(VerifyNameMatchSimpleTest, ExactEquality) {
89 std::string der;
90 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix(), &der));
91 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&der),
92 SequenceValueFromString(&der)));
94 std::string der_extra_attr;
95 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix() + "-extra_attr",
96 &der_extra_attr));
97 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&der_extra_attr),
98 SequenceValueFromString(&der_extra_attr)));
100 std::string der_extra_rdn;
101 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix() + "-extra_rdn",
102 &der_extra_rdn));
103 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&der_extra_rdn),
104 SequenceValueFromString(&der_extra_rdn)));
107 // Ensure that a Name does not match another Name which is exactly the same but
108 // with an extra attribute in one Relative Distinguished Name.
109 TEST_P(VerifyNameMatchSimpleTest, ExtraAttrDoesNotMatch) {
110 std::string der;
111 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix(), &der));
112 std::string der_extra_attr;
113 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix() + "-extra_attr",
114 &der_extra_attr));
115 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&der),
116 SequenceValueFromString(&der_extra_attr)));
117 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&der_extra_attr),
118 SequenceValueFromString(&der)));
121 // Ensure that a Name does not match another Name which has the same number of
122 // RDNs and attributes, but where one of the attributes is duplicated in one of
123 // the names but not in the other.
124 TEST_P(VerifyNameMatchSimpleTest, DupeAttrDoesNotMatch) {
125 std::string der_dupe_attr;
126 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix() + "-dupe_attr",
127 &der_dupe_attr));
128 std::string der_extra_attr;
129 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix() + "-extra_attr",
130 &der_extra_attr));
131 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&der_dupe_attr),
132 SequenceValueFromString(&der_extra_attr)));
133 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&der_extra_attr),
134 SequenceValueFromString(&der_dupe_attr)));
135 // However, the name with a dupe attribute should match itself.
136 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&der_dupe_attr),
137 SequenceValueFromString(&der_dupe_attr)));
140 // Ensure that a Name does not match another Name which is exactly the same but
141 // with an extra Relative Distinguished Name.
142 TEST_P(VerifyNameMatchSimpleTest, ExtraRdnDoesNotMatch) {
143 std::string der;
144 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix(), &der));
145 std::string der_extra_rdn;
146 ASSERT_TRUE(LoadTestData("ascii", value_type(), suffix() + "-extra_rdn",
147 &der_extra_rdn));
148 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&der),
149 SequenceValueFromString(&der_extra_rdn)));
150 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&der_extra_rdn),
151 SequenceValueFromString(&der)));
154 // Runs VerifyNameMatchSimpleTest for all combinations of value_type and and
155 // suffix.
156 INSTANTIATE_TEST_CASE_P(InstantiationName,
157 VerifyNameMatchSimpleTest,
158 ::testing::Combine(::testing::ValuesIn(kValueTypes),
159 ::testing::ValuesIn(kMangleTypes)));
161 class VerifyNameMatchNormalizationTest
162 : public ::testing::TestWithParam<::testing::tuple<bool, const char*>> {
163 public:
164 bool expected_result() const { return ::testing::get<0>(GetParam()); }
165 std::string value_type() const { return ::testing::get<1>(GetParam()); }
168 // Verify matching is case insensitive (for the types which currently support
169 // normalization).
170 TEST_P(VerifyNameMatchNormalizationTest, CaseInsensitivity) {
171 std::string normal;
172 ASSERT_TRUE(LoadTestData("ascii", value_type(), "unmangled", &normal));
173 std::string case_swap;
174 ASSERT_TRUE(LoadTestData("ascii", value_type(), "case_swap", &case_swap));
175 EXPECT_EQ(expected_result(),
176 VerifyNameMatch(SequenceValueFromString(&normal),
177 SequenceValueFromString(&case_swap)));
178 EXPECT_EQ(expected_result(),
179 VerifyNameMatch(SequenceValueFromString(&case_swap),
180 SequenceValueFromString(&normal)));
183 // Verify matching folds whitespace (for the types which currently support
184 // normalization).
185 TEST_P(VerifyNameMatchNormalizationTest, CollapseWhitespace) {
186 std::string normal;
187 ASSERT_TRUE(LoadTestData("ascii", value_type(), "unmangled", &normal));
188 std::string whitespace;
189 ASSERT_TRUE(
190 LoadTestData("ascii", value_type(), "extra_whitespace", &whitespace));
191 EXPECT_EQ(expected_result(),
192 VerifyNameMatch(SequenceValueFromString(&normal),
193 SequenceValueFromString(&whitespace)));
194 EXPECT_EQ(expected_result(),
195 VerifyNameMatch(SequenceValueFromString(&whitespace),
196 SequenceValueFromString(&normal)));
199 // Runs VerifyNameMatchNormalizationTest for each (expected_result, value_type)
200 // tuple.
201 INSTANTIATE_TEST_CASE_P(
202 InstantiationName,
203 VerifyNameMatchNormalizationTest,
204 ::testing::Values(
205 ::testing::make_tuple(true,
206 static_cast<const char*>("PRINTABLESTRING")),
207 ::testing::make_tuple(false, static_cast<const char*>("T61STRING")),
208 ::testing::make_tuple(true, static_cast<const char*>("UTF8")),
209 ::testing::make_tuple(true, static_cast<const char*>("BMPSTRING")),
210 ::testing::make_tuple(true,
211 static_cast<const char*>("UNIVERSALSTRING"))));
213 class VerifyNameMatchDifferingTypesTest
214 : public ::testing::TestWithParam<
215 ::testing::tuple<const char*, const char*>> {
216 public:
217 std::string value_type_1() const { return ::testing::get<0>(GetParam()); }
218 std::string value_type_2() const { return ::testing::get<1>(GetParam()); }
221 TEST_P(VerifyNameMatchDifferingTypesTest, NormalizableTypesAreEqual) {
222 std::string der_1;
223 ASSERT_TRUE(LoadTestData("ascii", value_type_1(), "unmangled", &der_1));
224 std::string der_2;
225 ASSERT_TRUE(LoadTestData("ascii", value_type_2(), "unmangled", &der_2));
226 if (TypesAreComparable(value_type_1(), value_type_2())) {
227 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&der_1),
228 SequenceValueFromString(&der_2)));
229 } else {
230 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&der_1),
231 SequenceValueFromString(&der_2)));
235 // Runs VerifyNameMatchDifferingTypesTest for all combinations of value types in
236 // value_type1 and value_type_2.
237 INSTANTIATE_TEST_CASE_P(InstantiationName,
238 VerifyNameMatchDifferingTypesTest,
239 ::testing::Combine(::testing::ValuesIn(kValueTypes),
240 ::testing::ValuesIn(kValueTypes)));
242 class VerifyNameMatchUnicodeConversionTest
243 : public ::testing::TestWithParam<
244 ::testing::tuple<const char*,
245 ::testing::tuple<const char*, const char*>>> {
246 public:
247 std::string prefix() const { return ::testing::get<0>(GetParam()); }
248 std::string value_type_1() const {
249 return ::testing::get<0>(::testing::get<1>(GetParam()));
251 std::string value_type_2() const {
252 return ::testing::get<1>(::testing::get<1>(GetParam()));
256 TEST_P(VerifyNameMatchUnicodeConversionTest, UnicodeConversionsAreEqual) {
257 std::string der_1;
258 ASSERT_TRUE(LoadTestData(prefix(), value_type_1(), "unmangled", &der_1));
259 std::string der_2;
260 ASSERT_TRUE(LoadTestData(prefix(), value_type_2(), "unmangled", &der_2));
261 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&der_1),
262 SequenceValueFromString(&der_2)));
265 // Runs VerifyNameMatchUnicodeConversionTest with prefix="unicode_bmp" for all
266 // combinations of Basic Multilingual Plane-capable value types in value_type1
267 // and value_type_2.
268 INSTANTIATE_TEST_CASE_P(
269 BMPConversion,
270 VerifyNameMatchUnicodeConversionTest,
271 ::testing::Combine(
272 ::testing::Values("unicode_bmp"),
273 ::testing::Combine(::testing::ValuesIn(kUnicodeBMPValueTypes),
274 ::testing::ValuesIn(kUnicodeBMPValueTypes))));
276 // Runs VerifyNameMatchUnicodeConversionTest with prefix="unicode_supplementary"
277 // for all combinations of Unicode Supplementary Plane-capable value types in
278 // value_type1 and value_type_2.
279 INSTANTIATE_TEST_CASE_P(
280 SMPConversion,
281 VerifyNameMatchUnicodeConversionTest,
282 ::testing::Combine(
283 ::testing::Values("unicode_supplementary"),
284 ::testing::Combine(
285 ::testing::ValuesIn(kUnicodeSupplementaryValueTypes),
286 ::testing::ValuesIn(kUnicodeSupplementaryValueTypes))));
288 // Matching should fail if a PrintableString contains invalid characters.
289 TEST(VerifyNameMatchInvalidDataTest, FailOnInvalidPrintableStringChars) {
290 std::string der;
291 ASSERT_TRUE(LoadTestData("ascii", "PRINTABLESTRING", "unmangled", &der));
292 // Find a known location inside a PrintableString in the DER-encoded data.
293 size_t replace_location = der.find("0123456789");
294 ASSERT_NE(std::string::npos, replace_location);
295 for (int c = 0; c < 256; ++c) {
296 SCOPED_TRACE(base::IntToString(c));
297 if (base::IsAsciiAlpha(c) || base::IsAsciiDigit(c))
298 continue;
299 switch (c) {
300 case ' ':
301 case '\'':
302 case '(':
303 case ')':
304 case '*':
305 case '+':
306 case ',':
307 case '-':
308 case '.':
309 case '/':
310 case ':':
311 case '=':
312 case '?':
313 continue;
315 der.replace(replace_location, 1, 1, c);
316 // Verification should fail due to the invalid character.
317 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&der),
318 SequenceValueFromString(&der)));
322 // Matching should fail if an IA5String contains invalid characters.
323 TEST(VerifyNameMatchInvalidDataTest, FailOnInvalidIA5StringChars) {
324 std::string der;
325 ASSERT_TRUE(LoadTestData("ascii", "mixed", "rdn_dupetype_sorting_1", &der));
326 // Find a known location inside an IA5String in the DER-encoded data.
327 size_t replace_location = der.find("eXaMple");
328 ASSERT_NE(std::string::npos, replace_location);
329 for (int c = 0; c < 256; ++c) {
330 SCOPED_TRACE(base::IntToString(c));
331 der.replace(replace_location, 1, 1, c);
332 bool expected_result = (c <= 127);
333 EXPECT_EQ(expected_result, VerifyNameMatch(SequenceValueFromString(&der),
334 SequenceValueFromString(&der)));
338 TEST(VerifyNameMatchInvalidDataTest, FailOnAttributeTypeAndValueExtraData) {
339 std::string invalid;
340 ASSERT_TRUE(
341 LoadTestData("invalid", "AttributeTypeAndValue", "extradata", &invalid));
342 // Verification should fail due to extra element in AttributeTypeAndValue
343 // sequence.
344 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&invalid),
345 SequenceValueFromString(&invalid)));
348 TEST(VerifyNameMatchInvalidDataTest, FailOnAttributeTypeAndValueShort) {
349 std::string invalid;
350 ASSERT_TRUE(LoadTestData("invalid", "AttributeTypeAndValue", "onlyOneElement",
351 &invalid));
352 // Verification should fail due to AttributeTypeAndValue sequence having only
353 // one element.
354 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&invalid),
355 SequenceValueFromString(&invalid)));
358 TEST(VerifyNameMatchInvalidDataTest, FailOnAttributeTypeAndValueEmpty) {
359 std::string invalid;
360 ASSERT_TRUE(
361 LoadTestData("invalid", "AttributeTypeAndValue", "empty", &invalid));
362 // Verification should fail due to empty AttributeTypeAndValue sequence.
363 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&invalid),
364 SequenceValueFromString(&invalid)));
367 TEST(VerifyNameMatchInvalidDataTest, FailOnBadAttributeType) {
368 std::string invalid;
369 ASSERT_TRUE(LoadTestData("invalid", "AttributeTypeAndValue",
370 "badAttributeType", &invalid));
371 // Verification should fail due to Attribute Type not being an OID.
372 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&invalid),
373 SequenceValueFromString(&invalid)));
376 TEST(VerifyNameMatchInvalidDataTest, FailOnAttributeTypeAndValueNotSequence) {
377 std::string invalid;
378 ASSERT_TRUE(LoadTestData("invalid", "AttributeTypeAndValue", "setNotSequence",
379 &invalid));
380 // Verification should fail due to AttributeTypeAndValue being a Set instead
381 // of a Sequence.
382 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&invalid),
383 SequenceValueFromString(&invalid)));
386 TEST(VerifyNameMatchInvalidDataTest, FailOnRdnNotSet) {
387 std::string invalid;
388 ASSERT_TRUE(LoadTestData("invalid", "RDN", "sequenceInsteadOfSet", &invalid));
389 // Verification should fail due to RDN being a Sequence instead of a Set.
390 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&invalid),
391 SequenceValueFromString(&invalid)));
394 TEST(VerifyNameMatchInvalidDataTest, FailOnEmptyRdn) {
395 std::string invalid;
396 ASSERT_TRUE(LoadTestData("invalid", "RDN", "empty", &invalid));
397 // Verification should fail due to RDN having zero AttributeTypeAndValues.
398 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&invalid),
399 SequenceValueFromString(&invalid)));
402 // Matching should fail if a BMPString contains surrogates.
403 TEST(VerifyNameMatchInvalidDataTest, FailOnBmpStringSurrogates) {
404 std::string normal;
405 ASSERT_TRUE(LoadTestData("unicode_bmp", "BMPSTRING", "unmangled", &normal));
406 // Find a known location inside a BMPSTRING in the DER-encoded data.
407 size_t replace_location = normal.find("\x67\x71\x4e\xac");
408 ASSERT_NE(std::string::npos, replace_location);
409 // Replace with U+1D400 MATHEMATICAL BOLD CAPITAL A, which requires surrogates
410 // to represent.
411 std::string invalid =
412 normal.replace(replace_location, 4, std::string("\xd8\x35\xdc\x00", 4));
413 // Verification should fail due to the invalid codepoints.
414 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&invalid),
415 SequenceValueFromString(&invalid)));
418 TEST(VerifyNameMatchTest, EmptyNameMatching) {
419 std::string empty;
420 ASSERT_TRUE(LoadTestData("valid", "Name", "empty", &empty));
421 // Empty names are equal.
422 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&empty),
423 SequenceValueFromString(&empty)));
425 // An empty name is not equal to non-empty name.
426 std::string non_empty;
427 ASSERT_TRUE(
428 LoadTestData("ascii", "PRINTABLESTRING", "unmangled", &non_empty));
429 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&empty),
430 SequenceValueFromString(&non_empty)));
431 EXPECT_FALSE(VerifyNameMatch(SequenceValueFromString(&non_empty),
432 SequenceValueFromString(&empty)));
435 // Matching should succeed when the RDNs are sorted differently but are still
436 // equal after normalizing.
437 TEST(VerifyNameMatchRDNSorting, Simple) {
438 std::string a;
439 ASSERT_TRUE(LoadTestData("ascii", "PRINTABLESTRING", "rdn_sorting_1", &a));
440 std::string b;
441 ASSERT_TRUE(LoadTestData("ascii", "PRINTABLESTRING", "rdn_sorting_2", &b));
442 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&a),
443 SequenceValueFromString(&b)));
444 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&b),
445 SequenceValueFromString(&a)));
448 // Matching should succeed when the RDNs are sorted differently but are still
449 // equal after normalizing, even in malformed RDNs that contain multiple
450 // elements with the same type.
451 TEST(VerifyNameMatchRDNSorting, DuplicateTypes) {
452 std::string a;
453 ASSERT_TRUE(LoadTestData("ascii", "mixed", "rdn_dupetype_sorting_1", &a));
454 std::string b;
455 ASSERT_TRUE(LoadTestData("ascii", "mixed", "rdn_dupetype_sorting_2", &b));
456 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&a),
457 SequenceValueFromString(&b)));
458 EXPECT_TRUE(VerifyNameMatch(SequenceValueFromString(&b),
459 SequenceValueFromString(&a)));
462 } // namespace net