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/verify_name_match.h" | 5 #include "net/cert/internal/verify_name_match.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/strings/string16.h" | 10 #include "base/strings/string16.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "base/strings/utf_string_conversion_utils.h" | 12 #include "base/strings/utf_string_conversion_utils.h" |
13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
14 #include "base/sys_byteorder.h" | 14 #include "base/sys_byteorder.h" |
15 #include "base/third_party/icu/icu_utf.h" | 15 #include "base/third_party/icu/icu_utf.h" |
16 #include "base/tuple.h" | 16 #include "base/tuple.h" |
17 #include "net/der/input.h" | 17 #include "net/der/input.h" |
18 #include "net/der/parser.h" | 18 #include "net/der/parser.h" |
19 #include "net/der/tag.h" | 19 #include "net/der/tag.h" |
20 | 20 |
21 namespace net { | 21 namespace net { |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
| 25 // RFC 5280 section A.1: |
| 26 // |
| 27 // pkcs-9 OBJECT IDENTIFIER ::= |
| 28 // { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } |
| 29 // |
| 30 // id-emailAddress AttributeType ::= { pkcs-9 1 } |
| 31 // |
| 32 // In dotted form: 1.2.840.113549.1.9.1 |
| 33 const uint8_t kOidEmailAddress[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, |
| 34 0x0D, 0x01, 0x09, 0x01}; |
| 35 |
| 36 // RFC 5280 section A.1: |
| 37 // |
| 38 // id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 } |
| 39 // |
| 40 // id-at-commonName AttributeType ::= { id-at 3 } |
| 41 // |
| 42 // In dotted form: 2.5.4.3 |
| 43 const uint8_t kOidCommonName[] = {0x55, 0x04, 0x03}; |
| 44 |
25 // Types of character set checking that NormalizeDirectoryString can perform. | 45 // Types of character set checking that NormalizeDirectoryString can perform. |
26 enum CharsetEnforcement { | 46 enum CharsetEnforcement { |
27 NO_ENFORCEMENT, | 47 NO_ENFORCEMENT, |
28 ENFORCE_PRINTABLE_STRING, | 48 ENFORCE_PRINTABLE_STRING, |
29 ENFORCE_ASCII, | 49 ENFORCE_ASCII, |
30 }; | 50 }; |
31 | 51 |
32 // Normalizes |output|, a UTF-8 encoded string, as if it contained | 52 // Normalizes |output|, a UTF-8 encoded string, as if it contained |
33 // only ASCII characters. | 53 // only ASCII characters. |
34 // | 54 // |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 } | 397 } |
378 if (!matched) | 398 if (!matched) |
379 return false; | 399 return false; |
380 } | 400 } |
381 | 401 |
382 // Every element in |a_type_and_values| had a matching element in | 402 // Every element in |a_type_and_values| had a matching element in |
383 // |b_type_and_values|. | 403 // |b_type_and_values|. |
384 return true; | 404 return true; |
385 } | 405 } |
386 | 406 |
387 } // namespace | 407 enum NameMatchType { |
| 408 EXACT_MATCH, |
| 409 SUBTREE_MATCH, |
| 410 }; |
388 | 411 |
| 412 // Verify that |a| matches |b|. If |match_type| is EXACT_MATCH, returns true if |
| 413 // they are an exact match as defined by RFC 5280 7.1. If |match_type| is |
| 414 // SUBTREE_MATCH, returns true if |a| is within the subtree defined by |b| as |
| 415 // defined by RFC 5280 7.1. |
| 416 // |
389 // |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag), | 417 // |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag), |
390 // defined in RFC 5280 section 4.1.2.4: | 418 // defined in RFC 5280 section 4.1.2.4: |
391 // | 419 // |
392 // Name ::= CHOICE { -- only one possibility for now -- | 420 // Name ::= CHOICE { -- only one possibility for now -- |
393 // rdnSequence RDNSequence } | 421 // rdnSequence RDNSequence } |
394 // | 422 // |
395 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName | 423 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName |
396 // | 424 // |
397 // RelativeDistinguishedName ::= | 425 // RelativeDistinguishedName ::= |
398 // SET SIZE (1..MAX) OF AttributeTypeAndValue | 426 // SET SIZE (1..MAX) OF AttributeTypeAndValue |
399 bool VerifyNameMatch(const der::Input& a, const der::Input& b) { | 427 bool VerifyNameMatchInternal(const der::Input& a, |
| 428 const der::Input& b, |
| 429 NameMatchType match_type) { |
400 // Empty Names are allowed. RFC 5280 section 4.1.2.4 requires "The issuer | 430 // Empty Names are allowed. RFC 5280 section 4.1.2.4 requires "The issuer |
401 // field MUST contain a non-empty distinguished name (DN)", while section | 431 // field MUST contain a non-empty distinguished name (DN)", while section |
402 // 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is | 432 // 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is |
403 // assumed to have verified those conditions. | 433 // assumed to have verified those conditions. |
404 | 434 |
405 // RFC 5280 section 7.1: | 435 // RFC 5280 section 7.1: |
406 // Two distinguished names DN1 and DN2 match if they have the same number of | 436 // Two distinguished names DN1 and DN2 match if they have the same number of |
407 // RDNs, for each RDN in DN1 there is a matching RDN in DN2, and the matching | 437 // RDNs, for each RDN in DN1 there is a matching RDN in DN2, and the matching |
408 // RDNs appear in the same order in both DNs. | 438 // RDNs appear in the same order in both DNs. |
409 | 439 |
410 // First just check if the inputs have the same number of RDNs: | 440 // First just check if the inputs have the same number of RDNs: |
411 der::Parser a_rdn_sequence_counter(a); | 441 der::Parser a_rdn_sequence_counter(a); |
412 der::Parser b_rdn_sequence_counter(b); | 442 der::Parser b_rdn_sequence_counter(b); |
413 while (a_rdn_sequence_counter.HasMore() && b_rdn_sequence_counter.HasMore()) { | 443 while (a_rdn_sequence_counter.HasMore() && b_rdn_sequence_counter.HasMore()) { |
414 if (!a_rdn_sequence_counter.SkipTag(der::kSet) || | 444 if (!a_rdn_sequence_counter.SkipTag(der::kSet) || |
415 !b_rdn_sequence_counter.SkipTag(der::kSet)) { | 445 !b_rdn_sequence_counter.SkipTag(der::kSet)) { |
416 return false; | 446 return false; |
417 } | 447 } |
418 } | 448 } |
419 if (a_rdn_sequence_counter.HasMore() || b_rdn_sequence_counter.HasMore()) | 449 // If doing exact match and either of the sequences has more elements than the |
| 450 // other, not a match. If doing a subtree match, the first Name may have more |
| 451 // RDNs than the second. |
| 452 if (b_rdn_sequence_counter.HasMore()) |
| 453 return false; |
| 454 if (match_type == EXACT_MATCH && a_rdn_sequence_counter.HasMore()) |
420 return false; | 455 return false; |
421 | 456 |
422 // Same number of RDNs, now check if they match. | 457 // Same number of RDNs, now check if they match. |
423 der::Parser a_rdn_sequence(a); | 458 der::Parser a_rdn_sequence(a); |
424 der::Parser b_rdn_sequence(b); | 459 der::Parser b_rdn_sequence(b); |
425 while (a_rdn_sequence.HasMore() && b_rdn_sequence.HasMore()) { | 460 while (a_rdn_sequence.HasMore() && b_rdn_sequence.HasMore()) { |
426 der::Parser a_rdn, b_rdn; | 461 der::Parser a_rdn, b_rdn; |
427 if (!a_rdn_sequence.ReadConstructed(der::kSet, &a_rdn) || | 462 if (!a_rdn_sequence.ReadConstructed(der::kSet, &a_rdn) || |
428 !b_rdn_sequence.ReadConstructed(der::kSet, &b_rdn)) { | 463 !b_rdn_sequence.ReadConstructed(der::kSet, &b_rdn)) { |
429 return false; | 464 return false; |
430 } | 465 } |
431 if (!VerifyRdnMatch(&a_rdn, &b_rdn)) | 466 if (!VerifyRdnMatch(&a_rdn, &b_rdn)) |
432 return false; | 467 return false; |
433 } | 468 } |
434 | 469 |
435 return true; | 470 return true; |
436 } | 471 } |
437 | 472 |
| 473 } // namespace |
| 474 |
| 475 bool VerifyNameMatch(const der::Input& a_rdn_sequence, |
| 476 const der::Input& b_rdn_sequence) { |
| 477 return VerifyNameMatchInternal(a_rdn_sequence, b_rdn_sequence, EXACT_MATCH); |
| 478 } |
| 479 |
| 480 bool VerifyNameInSubtree(const der::Input& name_rdn_sequence, |
| 481 const der::Input& parent_rdn_sequence) { |
| 482 return VerifyNameMatchInternal(name_rdn_sequence, parent_rdn_sequence, |
| 483 SUBTREE_MATCH); |
| 484 } |
| 485 |
| 486 bool NameContainsEmailAddress(const der::Input& name_rdn_sequence, |
| 487 bool* contained_email_address) { |
| 488 der::Parser rdn_sequence_parser(name_rdn_sequence); |
| 489 |
| 490 while (rdn_sequence_parser.HasMore()) { |
| 491 der::Parser rdn_parser; |
| 492 if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) |
| 493 return false; |
| 494 |
| 495 std::vector<AttributeTypeAndValue> type_and_values; |
| 496 if (!ReadRdn(&rdn_parser, &type_and_values)) |
| 497 return false; |
| 498 |
| 499 for (const auto& type_and_value : type_and_values) { |
| 500 if (type_and_value.type.Equals(der::Input(kOidEmailAddress))) { |
| 501 *contained_email_address = true; |
| 502 return true; |
| 503 } |
| 504 } |
| 505 } |
| 506 |
| 507 *contained_email_address = false; |
| 508 return true; |
| 509 } |
| 510 |
| 511 bool GetNormalizedCommonNameFromName(const der::Input& name_rdn_sequence, |
| 512 std::string* normalized_common_name) { |
| 513 der::Parser rdn_sequence_parser(name_rdn_sequence); |
| 514 |
| 515 while (rdn_sequence_parser.HasMore()) { |
| 516 der::Parser rdn_parser; |
| 517 if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) |
| 518 return false; |
| 519 |
| 520 std::vector<AttributeTypeAndValue> type_and_values; |
| 521 if (!ReadRdn(&rdn_parser, &type_and_values)) |
| 522 return false; |
| 523 |
| 524 for (const auto& type_and_value : type_and_values) { |
| 525 if (type_and_value.type.Equals(der::Input(kOidCommonName))) { |
| 526 if (!IsNormalizableDirectoryString(type_and_value.value_tag)) |
| 527 return false; |
| 528 return NormalizeValue(type_and_value.value_tag, type_and_value.value, |
| 529 normalized_common_name); |
| 530 } |
| 531 } |
| 532 } |
| 533 |
| 534 return false; |
| 535 } |
| 536 |
438 } // namespace net | 537 } // namespace net |
OLD | NEW |