diff options
author | davidben <davidben@chromium.org> | 2016-02-18 16:43:07 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-19 00:44:28 +0000 |
commit | fb4788dd358c2bbefbb18aec82544ad103201f12 (patch) | |
tree | 829c076165ce5cd600b3886e058b3c1b70e13f0d /net/cert | |
parent | 9c24d5df79c6e5a8432f93243543039387abe162 (diff) | |
download | chromium_src-fb4788dd358c2bbefbb18aec82544ad103201f12.zip chromium_src-fb4788dd358c2bbefbb18aec82544ad103201f12.tar.gz chromium_src-fb4788dd358c2bbefbb18aec82544ad103201f12.tar.bz2 |
Don't decompose a der::Tag when processing it.
Decomposing the number and class is a little iffy (one can make a CHOICE of
SEQUENCE and [0]). Treating the constructed bit as part of the tag is, in
the general BER case, not quite right, but it is a valid simplification in DER.
This pattern makes it less likely that we check the number without the class,
etc.
BUG=none
Review URL: https://codereview.chromium.org/1710613002
Cr-Commit-Position: refs/heads/master@{#376313}
Diffstat (limited to 'net/cert')
-rw-r--r-- | net/cert/internal/name_constraints.cc | 179 |
1 files changed, 73 insertions, 106 deletions
diff --git a/net/cert/internal/name_constraints.cc b/net/cert/internal/name_constraints.cc index 2ad35dd..7bf4685 100644 --- a/net/cert/internal/name_constraints.cc +++ b/net/cert/internal/name_constraints.cc @@ -144,124 +144,91 @@ WARN_UNUSED_RESULT bool ParseGeneralName( der::Input value; if (!parser.ReadTagAndValue(&tag, &value)) return false; - if (!der::IsContextSpecific(tag)) - return false; GeneralNameTypes name_type = GENERAL_NAME_NONE; - // GeneralName ::= CHOICE { - switch (der::GetTagNumber(tag)) { + if (tag == der::ContextSpecificConstructed(0)) { // otherName [0] OtherName, - case 0: - if (!der::IsConstructed(tag)) - return false; - name_type = GENERAL_NAME_OTHER_NAME; - break; + name_type = GENERAL_NAME_OTHER_NAME; + } else if (tag == der::ContextSpecificPrimitive(1)) { // rfc822Name [1] IA5String, - case 1: - if (der::IsConstructed(tag)) - return false; - name_type = GENERAL_NAME_RFC822_NAME; - break; + name_type = GENERAL_NAME_RFC822_NAME; + } else if (tag == der::ContextSpecificPrimitive(2)) { // dNSName [2] IA5String, - case 2: { - if (der::IsConstructed(tag)) - return false; - name_type = GENERAL_NAME_DNS_NAME; - const std::string s = value.AsString(); - if (!base::IsStringASCII(s)) - return false; - subtrees->dns_names.push_back(s); - break; - } + name_type = GENERAL_NAME_DNS_NAME; + const std::string s = value.AsString(); + if (!base::IsStringASCII(s)) + return false; + subtrees->dns_names.push_back(s); + } else if (tag == der::ContextSpecificConstructed(3)) { // x400Address [3] ORAddress, - case 3: - if (!der::IsConstructed(tag)) - return false; - name_type = GENERAL_NAME_X400_ADDRESS; - break; + name_type = GENERAL_NAME_X400_ADDRESS; + } else if (tag == der::ContextSpecificConstructed(4)) { // directoryName [4] Name, - case 4: { - if (!der::IsConstructed(tag)) - return false; - name_type = GENERAL_NAME_DIRECTORY_NAME; - // Name is a CHOICE { rdnSequence RDNSequence }, therefore the SEQUENCE - // tag is explicit. Remove it, since the name matching functions expect - // only the value portion. - der::Parser name_parser(value); - der::Input name_value; - if (!name_parser.ReadTag(der::kSequence, &name_value) || parser.HasMore()) - return false; - subtrees->directory_names.push_back( - std::vector<uint8_t>(name_value.UnsafeData(), - name_value.UnsafeData() + name_value.Length())); - break; - } + name_type = GENERAL_NAME_DIRECTORY_NAME; + // Name is a CHOICE { rdnSequence RDNSequence }, therefore the SEQUENCE + // tag is explicit. Remove it, since the name matching functions expect + // only the value portion. + der::Parser name_parser(value); + der::Input name_value; + if (!name_parser.ReadTag(der::kSequence, &name_value) || parser.HasMore()) + return false; + subtrees->directory_names.push_back( + std::vector<uint8_t>(name_value.UnsafeData(), + name_value.UnsafeData() + name_value.Length())); + } else if (tag == der::ContextSpecificConstructed(5)) { // ediPartyName [5] EDIPartyName, - case 5: - if (!der::IsConstructed(tag)) - return false; - name_type = GENERAL_NAME_EDI_PARTY_NAME; - break; + name_type = GENERAL_NAME_EDI_PARTY_NAME; + } else if (tag == der::ContextSpecificPrimitive(6)) { // uniformResourceIdentifier [6] IA5String, - case 6: - if (der::IsConstructed(tag)) - return false; - name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER; - break; + name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER; + } else if (tag == der::ContextSpecificPrimitive(7)) { // iPAddress [7] OCTET STRING, - case 7: - if (der::IsConstructed(tag)) + name_type = GENERAL_NAME_IP_ADDRESS; + if (ip_address_type == IP_ADDRESS_ONLY) { + // RFC 5280 section 4.2.1.6: + // When the subjectAltName extension contains an iPAddress, the address + // MUST be stored in the octet string in "network byte order", as + // specified in [RFC791]. The least significant bit (LSB) of each octet + // is the LSB of the corresponding byte in the network address. For IP + // version 4, as specified in [RFC791], the octet string MUST contain + // exactly four octets. For IP version 6, as specified in [RFC2460], + // the octet string MUST contain exactly sixteen octets. + if ((value.Length() != kIPv4AddressSize && + value.Length() != kIPv6AddressSize)) { return false; - name_type = GENERAL_NAME_IP_ADDRESS; - if (ip_address_type == IP_ADDRESS_ONLY) { - // RFC 5280 section 4.2.1.6: - // When the subjectAltName extension contains an iPAddress, the address - // MUST be stored in the octet string in "network byte order", as - // specified in [RFC791]. The least significant bit (LSB) of each octet - // is the LSB of the corresponding byte in the network address. For IP - // version 4, as specified in [RFC791], the octet string MUST contain - // exactly four octets. For IP version 6, as specified in [RFC2460], - // the octet string MUST contain exactly sixteen octets. - if ((value.Length() != kIPv4AddressSize && - value.Length() != kIPv6AddressSize)) { - return false; - } - subtrees->ip_addresses.push_back(std::vector<uint8_t>( - value.UnsafeData(), value.UnsafeData() + value.Length())); - } else { - DCHECK_EQ(ip_address_type, IP_ADDRESS_AND_NETMASK); - // RFC 5280 section 4.2.1.10: - // The syntax of iPAddress MUST be as described in Section 4.2.1.6 with - // the following additions specifically for name constraints. For IPv4 - // addresses, the iPAddress field of GeneralName MUST contain eight (8) - // octets, encoded in the style of RFC 4632 (CIDR) to represent an - // address range [RFC4632]. For IPv6 addresses, the iPAddress field - // MUST contain 32 octets similarly encoded. For example, a name - // constraint for "class C" subnet 192.0.2.0 is represented as the - // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation - // 192.0.2.0/24 (mask 255.255.255.0). - if (value.Length() != kIPv4AddressSize * 2 && - value.Length() != kIPv6AddressSize * 2) { - return false; - } - const std::vector<uint8_t> mask(value.UnsafeData() + value.Length() / 2, - value.UnsafeData() + value.Length()); - const unsigned mask_prefix_length = MaskPrefixLength(mask); - if (!IsSuffixZero(mask, mask_prefix_length)) - return false; - subtrees->ip_address_ranges.push_back(std::make_pair( - std::vector<uint8_t>(value.UnsafeData(), - value.UnsafeData() + value.Length() / 2), - mask_prefix_length)); } - break; - // registeredID [8] OBJECT IDENTIFIER } - case 8: - if (der::IsConstructed(tag)) + subtrees->ip_addresses.push_back(std::vector<uint8_t>( + value.UnsafeData(), value.UnsafeData() + value.Length())); + } else { + DCHECK_EQ(ip_address_type, IP_ADDRESS_AND_NETMASK); + // RFC 5280 section 4.2.1.10: + // The syntax of iPAddress MUST be as described in Section 4.2.1.6 with + // the following additions specifically for name constraints. For IPv4 + // addresses, the iPAddress field of GeneralName MUST contain eight (8) + // octets, encoded in the style of RFC 4632 (CIDR) to represent an + // address range [RFC4632]. For IPv6 addresses, the iPAddress field + // MUST contain 32 octets similarly encoded. For example, a name + // constraint for "class C" subnet 192.0.2.0 is represented as the + // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation + // 192.0.2.0/24 (mask 255.255.255.0). + if (value.Length() != kIPv4AddressSize * 2 && + value.Length() != kIPv6AddressSize * 2) { return false; - name_type = GENERAL_NAME_REGISTERED_ID; - break; - default: - return false; + } + const std::vector<uint8_t> mask(value.UnsafeData() + value.Length() / 2, + value.UnsafeData() + value.Length()); + const unsigned mask_prefix_length = MaskPrefixLength(mask); + if (!IsSuffixZero(mask, mask_prefix_length)) + return false; + subtrees->ip_address_ranges.push_back(std::make_pair( + std::vector<uint8_t>(value.UnsafeData(), + value.UnsafeData() + value.Length() / 2), + mask_prefix_length)); + } + } else if (tag == der::ContextSpecificPrimitive(8)) { + // registeredID [8] OBJECT IDENTIFIER } + name_type = GENERAL_NAME_REGISTERED_ID; + } else { + return false; } DCHECK_NE(GENERAL_NAME_NONE, name_type); if ((name_type & kSupportedNameTypes) || |