x509_cert_types_mac.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/x509_cert_types.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <CoreServices/CoreServices.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <Security/Security.h>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <Security/SecAsn1Coder.h>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/icu_string_conversions.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const CSSM_OID* kOIDs[] = {
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_CommonName,
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_LocalityName,
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_StateProvinceName,
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_CountryName,
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_StreetAddress,
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_OrganizationName,
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_OrganizationalUnitName,
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_DNQualifier      // This should be "DC" but is undoubtedly wrong.
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};                            // TODO(avi): Find the right OID.
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Converts raw CSSM_DATA to a std::string. (Char encoding is unaltered.)
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string DataToString(CSSM_DATA data);
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Converts raw CSSM_DATA in ISO-8859-1 to a std::string in UTF-8.
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string Latin1DataToUTF8String(CSSM_DATA data);
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Converts big-endian UTF-16 to UTF-8 in a std::string.
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Note: The byte-order flipping is done in place on the input buffer!
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool UTF16BigEndianToUTF8(char16* chars, size_t length,
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 std::string* out_string);
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Converts big-endian UTF-32 to UTF-8 in a std::string.
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Note: The byte-order flipping is done in place on the input buffer!
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool UTF32BigEndianToUTF8(char32* chars, size_t length,
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 std::string* out_string);
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Adds a type+value pair to the appropriate vector from a C array.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The array is keyed by the matching OIDs from kOIDS[].
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static void AddTypeValuePair(const CSSM_OID type,
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const std::string& value,
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               std::vector<std::string>* values[]);
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Stores the first string of the vector, if any, to *single_value.
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void SetSingle(const std::vector<std::string> &values,
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      std::string* single_value);
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CertPrincipal::Parse(const CSSM_X509_NAME* name) {
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string> common_names, locality_names, state_names,
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      country_names;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string>* values[] = {
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &common_names, &locality_names,
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &state_names, &country_names,
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &(this->street_addresses),
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &(this->organization_names),
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &(this->organization_unit_names),
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &(this->domain_components)
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(arraysize(kOIDs) == arraysize(values));
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t rdn = 0; rdn < name->numberOfRDNs; ++rdn) {
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CSSM_X509_RDN rdn_struct = name->RelativeDistinguishedName[rdn];
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t pair = 0; pair < rdn_struct.numberOfPairs; ++pair) {
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CSSM_X509_TYPE_VALUE_PAIR pair_struct =
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          rdn_struct.AttributeTypeAndValue[pair];
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AddTypeValuePair(pair_struct.type,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       DataToString(pair_struct.value),
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       values);
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(common_names, &this->common_name);
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(locality_names, &this->locality_name);
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(state_names, &this->state_or_province_name);
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(country_names, &this->country_name);
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The following structs and templates work with Apple's very arcane and under-
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// documented SecAsn1Parser API, which is apparently the same as NSS's ASN.1
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// decoder:
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn1.html
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These are used to parse the contents of a raw
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BER DistinguishedName structure.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct KeyValuePair {
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CSSM_OID key;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int value_type;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CSSM_DATA value;
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  enum {
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeOther = 0,
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypePrintableString,
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeIA5String,
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeT61String,
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeUTF8String,
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeBMPString,
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeUniversalString,
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SecAsn1Template kStringValueTemplate[] = {
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_CHOICE, offsetof(KeyValuePair, value_type), },
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_PRINTABLE_STRING,
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypePrintableString },
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_IA5_STRING,
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeIA5String },
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_T61_STRING,
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeT61String },
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_UTF8_STRING,
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeUTF8String },
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_BMP_STRING,
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeBMPString },
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_UNIVERSAL_STRING,
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeUniversalString },
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { 0, }
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SecAsn1Template kKeyValuePairTemplate[] = {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KeyValuePair) },
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_OBJECT_ID, offsetof(KeyValuePair, key), },
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_INLINE, 0, &kStringValueTemplate, },
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { 0, }
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct KeyValuePairs {
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  KeyValuePair* pairs;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SecAsn1Template kKeyValuePairSetTemplate[] = {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_SET_OF, offsetof(KeyValuePairs,pairs),
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kKeyValuePairTemplate, sizeof(KeyValuePairs) }
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct X509Name {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  KeyValuePairs** pairs_list;
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const SecAsn1Template kNameTemplate[] = {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_SEQUENCE_OF, offsetof(X509Name,pairs_list),
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kKeyValuePairSetTemplate, sizeof(X509Name) }
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CertPrincipal::ParseDistinguishedName(const void* ber_name_data,
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           size_t length) {
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ber_name_data);
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First parse the BER |name_data| into the above structs.
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SecAsn1CoderRef coder = NULL;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SecAsn1CoderCreate(&coder);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(coder);
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  X509Name* name = NULL;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OSStatus err = SecAsn1Decode(coder, ber_name_data, length, kNameTemplate,
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               &name);
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (err) {
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "SecAsn1Decode returned " << err << "; name=" << name;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SecAsn1CoderRelease(coder);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now scan the structs and add the values to my string vectors.
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // I don't store multiple common/locality/state/country names, so use
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // temporary vectors for those.
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string> common_names, locality_names, state_names,
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      country_names;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string>* values[] = {
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &common_names, &locality_names,
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &state_names, &country_names,
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &this->street_addresses,
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &this->organization_names,
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &this->organization_unit_names,
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &this->domain_components
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(arraysize(kOIDs) == arraysize(values));
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int rdn=0; name[rdn].pairs_list; ++rdn) {
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    KeyValuePair *pair;
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int pair_index = 0;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         NULL != (pair = name[rdn].pairs_list[0][pair_index].pairs);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         ++pair_index) {
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      switch (pair->value_type) {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeIA5String:          // ASCII (that means 7-bit!)
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypePrintableString:    // a subset of ASCII
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeUTF8String:         // UTF-8
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key, DataToString(pair->value), values);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeT61String:          // T61, pretend it's Latin-1
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key,
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           Latin1DataToUTF8String(pair->value),
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           values);
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeBMPString: {        // UTF-16, big-endian
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::string value;
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          UTF16BigEndianToUTF8(reinterpret_cast<char16*>(pair->value.Data),
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               pair->value.Length / sizeof(char16),
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               &value);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key, value, values);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeUniversalString: {  // UTF-32, big-endian
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::string value;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          UTF32BigEndianToUTF8(reinterpret_cast<char32*>(pair->value.Data),
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               pair->value.Length / sizeof(char32),
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               &value);
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key, value, values);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        default:
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          DCHECK_EQ(pair->value_type, KeyValuePair::kTypeOther);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // We don't know what data type this is, but we'll store it as a blob.
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // Displaying the string may not work, but at least it can be compared
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // byte-for-byte by a Matches() call.
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key, DataToString(pair->value), values);
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(common_names, &this->common_name);
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(locality_names, &this->locality_name);
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(state_names, &this->state_or_province_name);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(country_names, &this->country_name);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Releasing |coder| frees all the memory pointed to via |name|.
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SecAsn1CoderRelease(coder);
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SUBROUTINES:
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string DataToString(CSSM_DATA data) {
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return std::string(
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      reinterpret_cast<std::string::value_type*>(data.Data),
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      data.Length);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic std::string Latin1DataToUTF8String(CSSM_DATA data) {
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 utf16;
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!CodepageToUTF16(DataToString(data), base::kCodepageLatin1,
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       base::OnStringConversionError::FAIL, &utf16))
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return "";
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return UTF16ToUTF8(utf16);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UTF16BigEndianToUTF8(char16* chars, size_t length,
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          std::string* out_string) {
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < length; i++)
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    chars[i] = EndianU16_BtoN(chars[i]);
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return UTF16ToUTF8(chars, length, out_string);
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool UTF32BigEndianToUTF8(char32* chars, size_t length,
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          std::string* out_string) {
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < length; i++)
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    chars[i] = EndianS32_BtoN(chars[i]);
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(WCHAR_T_IS_UTF32)
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return WideToUTF8(reinterpret_cast<const wchar_t*>(chars),
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    length, out_string);
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#error This code doesn't handle 16-bit wchar_t.
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static void AddTypeValuePair(const CSSM_OID type,
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const std::string& value,
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               std::vector<std::string>* values[]) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (CSSMOIDEqual(&type, kOIDs[oid])) {
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      values[oid]->push_back(value);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void SetSingle(const std::vector<std::string> &values,
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      std::string* single_value) {
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't expect to have more than one CN, L, S, and C.
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LOG_IF(WARNING, values.size() > 1) << "Didn't expect multiple values";
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (values.size() > 0)
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *single_value = values[0];
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
294