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