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