blob: d4ab2348d139c0794790217dc26db302154836eb [file] [log] [blame]
Bob Beckbc97b7a2023-04-18 08:35:15 -06001// Copyright 2017 The Chromium Authors
David Benjamin33d10492025-02-03 17:00:03 -05002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Bob Beckbc97b7a2023-04-18 08:35:15 -060014
15#include "general_names.h"
16
Bob Beck05007562023-08-17 20:22:17 +000017#include <openssl/base.h>
David Benjamin2a5db682024-02-06 21:56:57 -050018#include <openssl/bytestring.h>
Bob Beck05007562023-08-17 20:22:17 +000019
Bob Beckbc97b7a2023-04-18 08:35:15 -060020#include <climits>
21#include <cstring>
22
23#include "cert_error_params.h"
24#include "cert_errors.h"
Bob Beckbc97b7a2023-04-18 08:35:15 -060025#include "input.h"
Bob Beck5c7a2a02023-11-20 17:28:21 -070026#include "ip_util.h"
Bob Beckbc97b7a2023-04-18 08:35:15 -060027#include "parser.h"
Bob Beck5c7a2a02023-11-20 17:28:21 -070028#include "string_util.h"
Bob Beckbc97b7a2023-04-18 08:35:15 -060029
David Benjamin0fbc17a2024-08-21 15:13:10 -040030BSSL_NAMESPACE_BEGIN
Bob Beckbc97b7a2023-04-18 08:35:15 -060031
32DEFINE_CERT_ERROR_ID(kFailedParsingGeneralName, "Failed parsing GeneralName");
33
34namespace {
35
36DEFINE_CERT_ERROR_ID(kRFC822NameNotAscii, "rfc822Name is not ASCII");
37DEFINE_CERT_ERROR_ID(kDnsNameNotAscii, "dNSName is not ASCII");
38DEFINE_CERT_ERROR_ID(kURINotAscii, "uniformResourceIdentifier is not ASCII");
39DEFINE_CERT_ERROR_ID(kFailedParsingIp, "Failed parsing iPAddress");
40DEFINE_CERT_ERROR_ID(kUnknownGeneralNameType, "Unknown GeneralName type");
41DEFINE_CERT_ERROR_ID(kFailedReadingGeneralNames,
42 "Failed reading GeneralNames SEQUENCE");
43DEFINE_CERT_ERROR_ID(kGeneralNamesTrailingData,
44 "GeneralNames contains trailing data after the sequence");
45DEFINE_CERT_ERROR_ID(kGeneralNamesEmpty,
46 "GeneralNames is a sequence of 0 elements");
47DEFINE_CERT_ERROR_ID(kFailedReadingGeneralName,
48 "Failed reading GeneralName TLV");
49
Bob Beckbc97b7a2023-04-18 08:35:15 -060050} // namespace
51
52GeneralNames::GeneralNames() = default;
53
54GeneralNames::~GeneralNames() = default;
55
56// static
David Benjamin81138bc2024-01-23 14:53:40 -050057std::unique_ptr<GeneralNames> GeneralNames::Create(der::Input general_names_tlv,
58 CertErrors *errors) {
Bob Beck05007562023-08-17 20:22:17 +000059 BSSL_CHECK(errors);
Bob Beckbc97b7a2023-04-18 08:35:15 -060060
61 // RFC 5280 section 4.2.1.6:
62 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
63 der::Parser parser(general_names_tlv);
64 der::Input sequence_value;
David Benjamin2a5db682024-02-06 21:56:57 -050065 if (!parser.ReadTag(CBS_ASN1_SEQUENCE, &sequence_value)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -060066 errors->AddError(kFailedReadingGeneralNames);
67 return nullptr;
68 }
69 // Should not have trailing data after GeneralNames sequence.
70 if (parser.HasMore()) {
71 errors->AddError(kGeneralNamesTrailingData);
72 return nullptr;
73 }
74 return CreateFromValue(sequence_value, errors);
75}
76
77// static
78std::unique_ptr<GeneralNames> GeneralNames::CreateFromValue(
David Benjamin81138bc2024-01-23 14:53:40 -050079 der::Input general_names_value, CertErrors *errors) {
Bob Beck05007562023-08-17 20:22:17 +000080 BSSL_CHECK(errors);
Bob Beckbc97b7a2023-04-18 08:35:15 -060081
82 auto general_names = std::make_unique<GeneralNames>();
83
84 der::Parser sequence_parser(general_names_value);
85 // The GeneralNames sequence should have at least 1 element.
86 if (!sequence_parser.HasMore()) {
87 errors->AddError(kGeneralNamesEmpty);
88 return nullptr;
89 }
90
91 while (sequence_parser.HasMore()) {
92 der::Input raw_general_name;
93 if (!sequence_parser.ReadRawTLV(&raw_general_name)) {
94 errors->AddError(kFailedReadingGeneralName);
95 return nullptr;
96 }
97
98 if (!ParseGeneralName(raw_general_name, IP_ADDRESS_ONLY,
99 general_names.get(), errors)) {
100 errors->AddError(kFailedParsingGeneralName);
101 return nullptr;
102 }
103 }
104
105 return general_names;
106}
107
108[[nodiscard]] bool ParseGeneralName(
David Benjamin81138bc2024-01-23 14:53:40 -0500109 der::Input input,
Bob Beckbc97b7a2023-04-18 08:35:15 -0600110 GeneralNames::ParseGeneralNameIPAddressType ip_address_type,
Bob Beck5c7a2a02023-11-20 17:28:21 -0700111 GeneralNames *subtrees, CertErrors *errors) {
Bob Beck05007562023-08-17 20:22:17 +0000112 BSSL_CHECK(errors);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600113 der::Parser parser(input);
David Benjamin2a5db682024-02-06 21:56:57 -0500114 CBS_ASN1_TAG tag;
Bob Beckbc97b7a2023-04-18 08:35:15 -0600115 der::Input value;
Bob Beck6beabf32023-11-21 09:43:52 -0700116 if (!parser.ReadTagAndValue(&tag, &value)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600117 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700118 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600119 GeneralNameTypes name_type = GENERAL_NAME_NONE;
David Benjamin2a5db682024-02-06 21:56:57 -0500120 if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600121 // otherName [0] OtherName,
122 name_type = GENERAL_NAME_OTHER_NAME;
123 subtrees->other_names.push_back(value);
David Benjamin2a5db682024-02-06 21:56:57 -0500124 } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 1)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600125 // rfc822Name [1] IA5String,
126 name_type = GENERAL_NAME_RFC822_NAME;
David Benjamin71c58962024-01-29 22:20:18 -0500127 const std::string_view s = BytesAsStringView(value);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600128 if (!bssl::string_util::IsAscii(s)) {
129 errors->AddError(kRFC822NameNotAscii);
130 return false;
131 }
132 subtrees->rfc822_names.push_back(s);
David Benjamin2a5db682024-02-06 21:56:57 -0500133 } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 2)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600134 // dNSName [2] IA5String,
135 name_type = GENERAL_NAME_DNS_NAME;
David Benjamin71c58962024-01-29 22:20:18 -0500136 const std::string_view s = BytesAsStringView(value);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600137 if (!bssl::string_util::IsAscii(s)) {
138 errors->AddError(kDnsNameNotAscii);
139 return false;
140 }
141 subtrees->dns_names.push_back(s);
David Benjamin2a5db682024-02-06 21:56:57 -0500142 } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600143 // x400Address [3] ORAddress,
144 name_type = GENERAL_NAME_X400_ADDRESS;
145 subtrees->x400_addresses.push_back(value);
David Benjamin2a5db682024-02-06 21:56:57 -0500146 } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 4)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600147 // directoryName [4] Name,
148 name_type = GENERAL_NAME_DIRECTORY_NAME;
149 // Name is a CHOICE { rdnSequence RDNSequence }, therefore the SEQUENCE
150 // tag is explicit. Remove it, since the name matching functions expect
151 // only the value portion.
152 der::Parser name_parser(value);
153 der::Input name_value;
David Benjamin2a5db682024-02-06 21:56:57 -0500154 if (!name_parser.ReadTag(CBS_ASN1_SEQUENCE, &name_value) ||
155 parser.HasMore()) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600156 return false;
Bob Beck6beabf32023-11-21 09:43:52 -0700157 }
Bob Beckbc97b7a2023-04-18 08:35:15 -0600158 subtrees->directory_names.push_back(name_value);
David Benjamin2a5db682024-02-06 21:56:57 -0500159 } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 5)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600160 // ediPartyName [5] EDIPartyName,
161 name_type = GENERAL_NAME_EDI_PARTY_NAME;
162 subtrees->edi_party_names.push_back(value);
David Benjamin2a5db682024-02-06 21:56:57 -0500163 } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 6)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600164 // uniformResourceIdentifier [6] IA5String,
165 name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER;
David Benjamin71c58962024-01-29 22:20:18 -0500166 const std::string_view s = BytesAsStringView(value);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600167 if (!bssl::string_util::IsAscii(s)) {
168 errors->AddError(kURINotAscii);
169 return false;
170 }
171 subtrees->uniform_resource_identifiers.push_back(s);
David Benjamin2a5db682024-02-06 21:56:57 -0500172 } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 7)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600173 // iPAddress [7] OCTET STRING,
174 name_type = GENERAL_NAME_IP_ADDRESS;
175 if (ip_address_type == GeneralNames::IP_ADDRESS_ONLY) {
176 // RFC 5280 section 4.2.1.6:
177 // When the subjectAltName extension contains an iPAddress, the address
178 // MUST be stored in the octet string in "network byte order", as
179 // specified in [RFC791]. The least significant bit (LSB) of each octet
180 // is the LSB of the corresponding byte in the network address. For IP
181 // version 4, as specified in [RFC791], the octet string MUST contain
182 // exactly four octets. For IP version 6, as specified in [RFC2460],
183 // the octet string MUST contain exactly sixteen octets.
David Benjamin90ceeb02024-01-23 14:25:39 -0500184 if ((value.size() != kIPv4AddressSize &&
185 value.size() != kIPv6AddressSize)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600186 errors->AddError(kFailedParsingIp);
187 return false;
188 }
Bob Beck8e7025e2023-09-05 17:05:26 -0600189 subtrees->ip_addresses.push_back(value);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600190 } else {
Bob Beck05007562023-08-17 20:22:17 +0000191 BSSL_CHECK(ip_address_type == GeneralNames::IP_ADDRESS_AND_NETMASK);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600192 // RFC 5280 section 4.2.1.10:
193 // The syntax of iPAddress MUST be as described in Section 4.2.1.6 with
194 // the following additions specifically for name constraints. For IPv4
195 // addresses, the iPAddress field of GeneralName MUST contain eight (8)
196 // octets, encoded in the style of RFC 4632 (CIDR) to represent an
197 // address range [RFC4632]. For IPv6 addresses, the iPAddress field
198 // MUST contain 32 octets similarly encoded. For example, a name
199 // constraint for "class C" subnet 192.0.2.0 is represented as the
200 // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation
201 // 192.0.2.0/24 (mask 255.255.255.0).
David Benjamin90ceeb02024-01-23 14:25:39 -0500202 if (value.size() != kIPv4AddressSize * 2 &&
203 value.size() != kIPv6AddressSize * 2) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600204 errors->AddError(kFailedParsingIp);
205 return false;
206 }
David Benjamin90ceeb02024-01-23 14:25:39 -0500207 der::Input addr = value.first(value.size() / 2);
208 der::Input mask = value.subspan(value.size() / 2);
Bob Beck8e7025e2023-09-05 17:05:26 -0600209 if (!IsValidNetmask(mask)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600210 errors->AddError(kFailedParsingIp);
211 return false;
212 }
Bob Beck8e7025e2023-09-05 17:05:26 -0600213 subtrees->ip_address_ranges.emplace_back(addr, mask);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600214 }
David Benjamin2a5db682024-02-06 21:56:57 -0500215 } else if (tag == (CBS_ASN1_CONTEXT_SPECIFIC | 8)) {
Bob Beckbc97b7a2023-04-18 08:35:15 -0600216 // registeredID [8] OBJECT IDENTIFIER }
217 name_type = GENERAL_NAME_REGISTERED_ID;
218 subtrees->registered_ids.push_back(value);
219 } else {
220 errors->AddError(kUnknownGeneralNameType,
221 CreateCertErrorParams1SizeT("tag", tag));
222 return false;
223 }
Bob Beck05007562023-08-17 20:22:17 +0000224 BSSL_CHECK(GENERAL_NAME_NONE != name_type);
Bob Beckbc97b7a2023-04-18 08:35:15 -0600225 subtrees->present_name_types |= name_type;
226 return true;
227}
228
David Benjamin0fbc17a2024-08-21 15:13:10 -0400229BSSL_NAMESPACE_END