• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "general_names.h"
6 
7 #include <openssl/base.h>
8 
9 #include <climits>
10 #include <cstring>
11 
12 #include "cert_error_params.h"
13 #include "cert_errors.h"
14 #include "ip_util.h"
15 #include "string_util.h"
16 #include "input.h"
17 #include "parser.h"
18 #include "tag.h"
19 
20 namespace bssl {
21 
22 DEFINE_CERT_ERROR_ID(kFailedParsingGeneralName, "Failed parsing GeneralName");
23 
24 namespace {
25 
26 DEFINE_CERT_ERROR_ID(kRFC822NameNotAscii, "rfc822Name is not ASCII");
27 DEFINE_CERT_ERROR_ID(kDnsNameNotAscii, "dNSName is not ASCII");
28 DEFINE_CERT_ERROR_ID(kURINotAscii, "uniformResourceIdentifier is not ASCII");
29 DEFINE_CERT_ERROR_ID(kFailedParsingIp, "Failed parsing iPAddress");
30 DEFINE_CERT_ERROR_ID(kUnknownGeneralNameType, "Unknown GeneralName type");
31 DEFINE_CERT_ERROR_ID(kFailedReadingGeneralNames,
32                      "Failed reading GeneralNames SEQUENCE");
33 DEFINE_CERT_ERROR_ID(kGeneralNamesTrailingData,
34                      "GeneralNames contains trailing data after the sequence");
35 DEFINE_CERT_ERROR_ID(kGeneralNamesEmpty,
36                      "GeneralNames is a sequence of 0 elements");
37 DEFINE_CERT_ERROR_ID(kFailedReadingGeneralName,
38                      "Failed reading GeneralName TLV");
39 
40 }  // namespace
41 
42 GeneralNames::GeneralNames() = default;
43 
44 GeneralNames::~GeneralNames() = default;
45 
46 // static
Create(const der::Input & general_names_tlv,CertErrors * errors)47 std::unique_ptr<GeneralNames> GeneralNames::Create(
48     const der::Input& general_names_tlv,
49     CertErrors* errors) {
50   BSSL_CHECK(errors);
51 
52   // RFC 5280 section 4.2.1.6:
53   // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
54   der::Parser parser(general_names_tlv);
55   der::Input sequence_value;
56   if (!parser.ReadTag(der::kSequence, &sequence_value)) {
57     errors->AddError(kFailedReadingGeneralNames);
58     return nullptr;
59   }
60   // Should not have trailing data after GeneralNames sequence.
61   if (parser.HasMore()) {
62     errors->AddError(kGeneralNamesTrailingData);
63     return nullptr;
64   }
65   return CreateFromValue(sequence_value, errors);
66 }
67 
68 // static
CreateFromValue(const der::Input & general_names_value,CertErrors * errors)69 std::unique_ptr<GeneralNames> GeneralNames::CreateFromValue(
70     const der::Input& general_names_value,
71     CertErrors* errors) {
72   BSSL_CHECK(errors);
73 
74   auto general_names = std::make_unique<GeneralNames>();
75 
76   der::Parser sequence_parser(general_names_value);
77   // The GeneralNames sequence should have at least 1 element.
78   if (!sequence_parser.HasMore()) {
79     errors->AddError(kGeneralNamesEmpty);
80     return nullptr;
81   }
82 
83   while (sequence_parser.HasMore()) {
84     der::Input raw_general_name;
85     if (!sequence_parser.ReadRawTLV(&raw_general_name)) {
86       errors->AddError(kFailedReadingGeneralName);
87       return nullptr;
88     }
89 
90     if (!ParseGeneralName(raw_general_name, IP_ADDRESS_ONLY,
91                           general_names.get(), errors)) {
92       errors->AddError(kFailedParsingGeneralName);
93       return nullptr;
94     }
95   }
96 
97   return general_names;
98 }
99 
ParseGeneralName(const der::Input & input,GeneralNames::ParseGeneralNameIPAddressType ip_address_type,GeneralNames * subtrees,CertErrors * errors)100 [[nodiscard]] bool ParseGeneralName(
101     const der::Input& input,
102     GeneralNames::ParseGeneralNameIPAddressType ip_address_type,
103     GeneralNames* subtrees,
104     CertErrors* errors) {
105   BSSL_CHECK(errors);
106   der::Parser parser(input);
107   der::Tag tag;
108   der::Input value;
109   if (!parser.ReadTagAndValue(&tag, &value))
110     return false;
111   GeneralNameTypes name_type = GENERAL_NAME_NONE;
112   if (tag == der::ContextSpecificConstructed(0)) {
113     // otherName                       [0]     OtherName,
114     name_type = GENERAL_NAME_OTHER_NAME;
115     subtrees->other_names.push_back(value);
116   } else if (tag == der::ContextSpecificPrimitive(1)) {
117     // rfc822Name                      [1]     IA5String,
118     name_type = GENERAL_NAME_RFC822_NAME;
119     const std::string_view s = value.AsStringView();
120     if (!bssl::string_util::IsAscii(s)) {
121       errors->AddError(kRFC822NameNotAscii);
122       return false;
123     }
124     subtrees->rfc822_names.push_back(s);
125   } else if (tag == der::ContextSpecificPrimitive(2)) {
126     // dNSName                         [2]     IA5String,
127     name_type = GENERAL_NAME_DNS_NAME;
128     const std::string_view s = value.AsStringView();
129     if (!bssl::string_util::IsAscii(s)) {
130       errors->AddError(kDnsNameNotAscii);
131       return false;
132     }
133     subtrees->dns_names.push_back(s);
134   } else if (tag == der::ContextSpecificConstructed(3)) {
135     // x400Address                     [3]     ORAddress,
136     name_type = GENERAL_NAME_X400_ADDRESS;
137     subtrees->x400_addresses.push_back(value);
138   } else if (tag == der::ContextSpecificConstructed(4)) {
139     // directoryName                   [4]     Name,
140     name_type = GENERAL_NAME_DIRECTORY_NAME;
141     // Name is a CHOICE { rdnSequence  RDNSequence }, therefore the SEQUENCE
142     // tag is explicit. Remove it, since the name matching functions expect
143     // only the value portion.
144     der::Parser name_parser(value);
145     der::Input name_value;
146     if (!name_parser.ReadTag(der::kSequence, &name_value) || parser.HasMore())
147       return false;
148     subtrees->directory_names.push_back(name_value);
149   } else if (tag == der::ContextSpecificConstructed(5)) {
150     // ediPartyName                    [5]     EDIPartyName,
151     name_type = GENERAL_NAME_EDI_PARTY_NAME;
152     subtrees->edi_party_names.push_back(value);
153   } else if (tag == der::ContextSpecificPrimitive(6)) {
154     // uniformResourceIdentifier       [6]     IA5String,
155     name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER;
156     const std::string_view s = value.AsStringView();
157     if (!bssl::string_util::IsAscii(s)) {
158       errors->AddError(kURINotAscii);
159       return false;
160     }
161     subtrees->uniform_resource_identifiers.push_back(s);
162   } else if (tag == der::ContextSpecificPrimitive(7)) {
163     // iPAddress                       [7]     OCTET STRING,
164     name_type = GENERAL_NAME_IP_ADDRESS;
165     if (ip_address_type == GeneralNames::IP_ADDRESS_ONLY) {
166       // RFC 5280 section 4.2.1.6:
167       // When the subjectAltName extension contains an iPAddress, the address
168       // MUST be stored in the octet string in "network byte order", as
169       // specified in [RFC791].  The least significant bit (LSB) of each octet
170       // is the LSB of the corresponding byte in the network address.  For IP
171       // version 4, as specified in [RFC791], the octet string MUST contain
172       // exactly four octets.  For IP version 6, as specified in [RFC2460],
173       // the octet string MUST contain exactly sixteen octets.
174       if ((value.Length() != kIPv4AddressSize &&
175            value.Length() != kIPv6AddressSize)) {
176         errors->AddError(kFailedParsingIp);
177         return false;
178       }
179       subtrees->ip_addresses.push_back(value);
180     } else {
181       BSSL_CHECK(ip_address_type == GeneralNames::IP_ADDRESS_AND_NETMASK);
182       // RFC 5280 section 4.2.1.10:
183       // The syntax of iPAddress MUST be as described in Section 4.2.1.6 with
184       // the following additions specifically for name constraints. For IPv4
185       // addresses, the iPAddress field of GeneralName MUST contain eight (8)
186       // octets, encoded in the style of RFC 4632 (CIDR) to represent an
187       // address range [RFC4632]. For IPv6 addresses, the iPAddress field
188       // MUST contain 32 octets similarly encoded. For example, a name
189       // constraint for "class C" subnet 192.0.2.0 is represented as the
190       // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation
191       // 192.0.2.0/24 (mask 255.255.255.0).
192       if (value.Length() != kIPv4AddressSize * 2 &&
193           value.Length() != kIPv6AddressSize * 2) {
194         errors->AddError(kFailedParsingIp);
195         return false;
196       }
197       der::Input addr(value.UnsafeData(), value.Length() / 2);
198       der::Input mask(value.UnsafeData() + value.Length() / 2,
199                       value.Length() / 2);
200       if (!IsValidNetmask(mask)) {
201         errors->AddError(kFailedParsingIp);
202         return false;
203       }
204       subtrees->ip_address_ranges.emplace_back(addr, mask);
205     }
206   } else if (tag == der::ContextSpecificPrimitive(8)) {
207     // registeredID                    [8]     OBJECT IDENTIFIER }
208     name_type = GENERAL_NAME_REGISTERED_ID;
209     subtrees->registered_ids.push_back(value);
210   } else {
211     errors->AddError(kUnknownGeneralNameType,
212                      CreateCertErrorParams1SizeT("tag", tag));
213     return false;
214   }
215   BSSL_CHECK(GENERAL_NAME_NONE != name_type);
216   subtrees->present_name_types |= name_type;
217   return true;
218 }
219 
220 }  // namespace net
221