xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/pki/parse_name.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2016 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 "parse_name.h"
6 
7 #include <cassert>
8 
9 #include <openssl/bytestring.h>
10 #include <openssl/mem.h>
11 
12 #include "parse_values.h"
13 #include "string_util.h"
14 
15 namespace bssl {
16 
17 namespace {
18 
19 // Returns a string containing the dotted numeric form of |oid|, or an empty
20 // string on error.
OidToString(der::Input oid)21 std::string OidToString(der::Input oid) {
22   CBS cbs;
23   CBS_init(&cbs, oid.data(), oid.size());
24   bssl::UniquePtr<char> text(CBS_asn1_oid_to_text(&cbs));
25   if (!text) {
26     return std::string();
27   }
28   return text.get();
29 }
30 
31 }  // namespace
32 
ValueAsString(std::string * out) const33 bool X509NameAttribute::ValueAsString(std::string *out) const {
34   switch (value_tag) {
35     case CBS_ASN1_T61STRING:
36       return der::ParseTeletexStringAsLatin1(value, out);
37     case CBS_ASN1_IA5STRING:
38       return der::ParseIA5String(value, out);
39     case CBS_ASN1_PRINTABLESTRING:
40       return der::ParsePrintableString(value, out);
41     case CBS_ASN1_UTF8STRING:
42       *out = BytesAsStringView(value);
43       return true;
44     case CBS_ASN1_UNIVERSALSTRING:
45       return der::ParseUniversalString(value, out);
46     case CBS_ASN1_BMPSTRING:
47       return der::ParseBmpString(value, out);
48     default:
49       return false;
50   }
51 }
52 
ValueAsStringWithUnsafeOptions(PrintableStringHandling printable_string_handling,std::string * out) const53 bool X509NameAttribute::ValueAsStringWithUnsafeOptions(
54     PrintableStringHandling printable_string_handling, std::string *out) const {
55   if (printable_string_handling == PrintableStringHandling::kAsUTF8Hack &&
56       value_tag == CBS_ASN1_PRINTABLESTRING) {
57     *out = BytesAsStringView(value);
58     return true;
59   }
60   return ValueAsString(out);
61 }
62 
ValueAsStringUnsafe(std::string * out) const63 bool X509NameAttribute::ValueAsStringUnsafe(std::string *out) const {
64   switch (value_tag) {
65     case CBS_ASN1_IA5STRING:
66     case CBS_ASN1_PRINTABLESTRING:
67     case CBS_ASN1_T61STRING:
68     case CBS_ASN1_UTF8STRING:
69       *out = BytesAsStringView(value);
70       return true;
71     case CBS_ASN1_UNIVERSALSTRING:
72       return der::ParseUniversalString(value, out);
73     case CBS_ASN1_BMPSTRING:
74       return der::ParseBmpString(value, out);
75     default:
76       assert(0);  // NOTREACHED
77       return false;
78   }
79 }
80 
AsRFC2253String(std::string * out) const81 bool X509NameAttribute::AsRFC2253String(std::string *out) const {
82   std::string type_string;
83   std::string value_string;
84   // TODO(mattm): Add streetAddress and domainComponent here?
85   if (type == der::Input(kTypeCommonNameOid)) {
86     type_string = "CN";
87   } else if (type == der::Input(kTypeSurnameOid)) {
88     type_string = "SN";
89   } else if (type == der::Input(kTypeCountryNameOid)) {
90     type_string = "C";
91   } else if (type == der::Input(kTypeLocalityNameOid)) {
92     type_string = "L";
93   } else if (type == der::Input(kTypeStateOrProvinceNameOid)) {
94     type_string = "ST";
95   } else if (type == der::Input(kTypeOrganizationNameOid)) {
96     type_string = "O";
97   } else if (type == der::Input(kTypeOrganizationUnitNameOid)) {
98     type_string = "OU";
99   } else if (type == der::Input(kTypeGivenNameOid)) {
100     type_string = "givenName";
101   } else if (type == der::Input(kTypeEmailAddressOid)) {
102     type_string = "emailAddress";
103   } else {
104     type_string = OidToString(type);
105     if (type_string.empty()) {
106       return false;
107     }
108     value_string = "#" + bssl::string_util::HexEncode(value);
109   }
110 
111   if (value_string.empty()) {
112     std::string unescaped;
113     if (!ValueAsStringUnsafe(&unescaped)) {
114       return false;
115     }
116 
117     bool nonprintable = false;
118     for (unsigned int i = 0; i < unescaped.length(); ++i) {
119       uint8_t c = static_cast<uint8_t>(unescaped[i]);
120       if (i == 0 && c == '#') {
121         value_string += "\\#";
122       } else if (i == 0 && c == ' ') {
123         value_string += "\\ ";
124       } else if (i == unescaped.length() - 1 && c == ' ') {
125         value_string += "\\ ";
126       } else if (c == ',' || c == '+' || c == '"' || c == '\\' || c == '<' ||
127                  c == '>' || c == ';') {
128         value_string += "\\";
129         value_string += c;
130       } else if (c < 32 || c > 126) {
131         nonprintable = true;
132         value_string +=
133             "\\" + bssl::string_util::HexEncode(MakeConstSpan(&c, 1));
134       } else {
135         value_string += c;
136       }
137     }
138 
139     // If we have non-printable characters in a TeletexString, we hex encode
140     // since we don't handle Teletex control codes.
141     if (nonprintable && value_tag == CBS_ASN1_T61STRING) {
142       value_string = "#" + bssl::string_util::HexEncode(value);
143     }
144   }
145 
146   *out = type_string + "=" + value_string;
147   return true;
148 }
149 
ReadRdn(der::Parser * parser,RelativeDistinguishedName * out)150 bool ReadRdn(der::Parser *parser, RelativeDistinguishedName *out) {
151   while (parser->HasMore()) {
152     der::Parser attr_type_and_value;
153     if (!parser->ReadSequence(&attr_type_and_value)) {
154       return false;
155     }
156     // Read the attribute type, which must be an OBJECT IDENTIFIER.
157     der::Input type;
158     if (!attr_type_and_value.ReadTag(CBS_ASN1_OBJECT, &type)) {
159       return false;
160     }
161 
162     // Read the attribute value.
163     CBS_ASN1_TAG tag;
164     der::Input value;
165     if (!attr_type_and_value.ReadTagAndValue(&tag, &value)) {
166       return false;
167     }
168 
169     // There should be no more elements in the sequence after reading the
170     // attribute type and value.
171     if (attr_type_and_value.HasMore()) {
172       return false;
173     }
174 
175     out->push_back(X509NameAttribute(type, tag, value));
176   }
177 
178   // RFC 5280 section 4.1.2.4
179   // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
180   return out->size() != 0;
181 }
182 
ParseName(der::Input name_tlv,RDNSequence * out)183 bool ParseName(der::Input name_tlv, RDNSequence *out) {
184   der::Parser name_parser(name_tlv);
185   der::Input name_value;
186   if (!name_parser.ReadTag(CBS_ASN1_SEQUENCE, &name_value)) {
187     return false;
188   }
189   return ParseNameValue(name_value, out);
190 }
191 
ParseNameValue(der::Input name_value,RDNSequence * out)192 bool ParseNameValue(der::Input name_value, RDNSequence *out) {
193   der::Parser rdn_sequence_parser(name_value);
194   while (rdn_sequence_parser.HasMore()) {
195     der::Parser rdn_parser;
196     if (!rdn_sequence_parser.ReadConstructed(CBS_ASN1_SET, &rdn_parser)) {
197       return false;
198     }
199     RelativeDistinguishedName type_and_values;
200     if (!ReadRdn(&rdn_parser, &type_and_values)) {
201       return false;
202     }
203     out->push_back(type_and_values);
204   }
205 
206   return true;
207 }
208 
ConvertToRFC2253(const RDNSequence & rdn_sequence,std::string * out)209 bool ConvertToRFC2253(const RDNSequence &rdn_sequence, std::string *out) {
210   std::string rdns_string;
211   size_t size = rdn_sequence.size();
212   for (size_t i = 0; i < size; ++i) {
213     RelativeDistinguishedName rdn = rdn_sequence[size - i - 1];
214     std::string rdn_string;
215     for (const auto &atv : rdn) {
216       if (!rdn_string.empty()) {
217         rdn_string += "+";
218       }
219       std::string atv_string;
220       if (!atv.AsRFC2253String(&atv_string)) {
221         return false;
222       }
223       rdn_string += atv_string;
224     }
225     if (!rdns_string.empty()) {
226       rdns_string += ",";
227     }
228     rdns_string += rdn_string;
229   }
230 
231   *out = rdns_string;
232   return true;
233 }
234 
235 }  // namespace bssl
236