15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_cert_types.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <stdint.h>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CoreServices/CoreServices.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/SecAsn1Coder.h>
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <Security/Security.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/mac_logging.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/base/net_string_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The BER encoding of 0.9.2342.19200300.100.1.25.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On 10.6 and later this is available as CSSMOID_DomainComponent, which is an
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// external symbol from Security.framework. However, it appears that Apple's
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implementation improperly encoded this on 10.6+, and even still is
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unavailable on 10.5, so simply including the raw BER here.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: CSSM is allowed to store CSSM_OIDs in any arbitrary format desired,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as long as the symbols are properly exposed. The fact that Apple's
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implementation stores it in BER is an internal implementation detail
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// observed by studying libsecurity_cssm.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8 kDomainComponentData[] = {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CSSM_OID kDomainComponentOID = {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kDomainComponentData),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const_cast<uint8*>(kDomainComponentData)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const CSSM_OID* kOIDs[] = {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &CSSMOID_CommonName,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &CSSMOID_LocalityName,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &CSSMOID_StateProvinceName,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &CSSMOID_CountryName,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &CSSMOID_StreetAddress,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &CSSMOID_OrganizationName,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &CSSMOID_OrganizationalUnitName,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    &kDomainComponentOID,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following structs and templates work with Apple's very arcane and under-
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// documented SecAsn1Parser API, which is apparently the same as NSS's ASN.1
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// decoder:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn1.html
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These are used to parse the contents of a raw
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BER DistinguishedName structure.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SecAsn1Template kStringValueTemplate[] = {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_CHOICE, offsetof(CSSM_X509_TYPE_VALUE_PAIR, valueType), },
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_PRINTABLE_STRING,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BER_TAG_PRINTABLE_STRING },
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_IA5_STRING,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BER_TAG_IA5_STRING },
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_T61_STRING,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BER_TAG_T61_STRING },
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_UTF8_STRING,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BER_TAG_PKIX_UTF8_STRING },
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_BMP_STRING,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BER_TAG_PKIX_BMP_STRING },
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_UNIVERSAL_STRING,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offsetof(CSSM_X509_TYPE_VALUE_PAIR, value), 0,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BER_TAG_PKIX_UNIVERSAL_STRING },
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { 0, }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SecAsn1Template kKeyValuePairTemplate[] = {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CSSM_X509_TYPE_VALUE_PAIR) },
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_OBJECT_ID, offsetof(CSSM_X509_TYPE_VALUE_PAIR, type), },
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_INLINE, 0, &kStringValueTemplate, },
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { 0, }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct KeyValuePairs {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_X509_TYPE_VALUE_PAIR* pairs;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SecAsn1Template kKeyValuePairSetTemplate[] = {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_SET_OF, offsetof(KeyValuePairs, pairs),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kKeyValuePairTemplate, sizeof(KeyValuePairs) }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct X509Name {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KeyValuePairs** pairs_list;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SecAsn1Template kNameTemplate[] = {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SEC_ASN1_SEQUENCE_OF, offsetof(X509Name, pairs_list),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kKeyValuePairSetTemplate, sizeof(X509Name) }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts raw CSSM_DATA to a std::string. (Char encoding is unaltered.)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string DataToString(CSSM_DATA data) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string(
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<std::string::value_type*>(data.Data),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.Length);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts raw CSSM_DATA in ISO-8859-1 to a std::string in UTF-8.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Latin1DataToUTF8String(CSSM_DATA data) {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 utf16;
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!ConvertToUTF16(DataToString(data), kCharsetLatin1, &utf16))
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "";
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF16ToUTF8(utf16);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts big-endian UTF-16 to UTF-8 in a std::string.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: The byte-order flipping is done in place on the input buffer!
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool UTF16BigEndianToUTF8(base::char16* chars, size_t length,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* out_string) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < length; i++)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chars[i] = EndianU16_BtoN(chars[i]);
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF16ToUTF8(chars, length, out_string);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts big-endian UTF-32 to UTF-8 in a std::string.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: The byte-order flipping is done in place on the input buffer!
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool UTF32BigEndianToUTF8(int32_t* chars, size_t length,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          std::string* out_string) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < length; ++i)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chars[i] = EndianS32_BtoN(chars[i]);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(WCHAR_T_IS_UTF32)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::WideToUTF8(reinterpret_cast<const wchar_t*>(chars),
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          length, out_string);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error This code doesn't handle 16-bit wchar_t.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adds a type+value pair to the appropriate vector from a C array.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The array is keyed by the matching OIDs from kOIDS[].
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddTypeValuePair(const CSSM_OID type,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const std::string& value,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::vector<std::string>* values[]) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CSSMOIDEqual(&type, kOIDs[oid])) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      values[oid]->push_back(value);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stores the first string of the vector, if any, to *single_value.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetSingle(const std::vector<std::string>& values,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               std::string* single_value) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't expect to have more than one CN, L, S, and C.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(WARNING, values.size() > 1) << "Didn't expect multiple values";
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!values.empty())
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *single_value = values[0];
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool match(const std::string& str, const std::string& against) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(snej): Use the full matching rules specified in RFC 5280 sec. 7.1
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // including trimming and case-folding: <http://www.ietf.org/rfc/rfc5280.txt>.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return against == str;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool match(const std::vector<std::string>& rdn1,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           const std::vector<std::string>& rdn2) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "Two relative distinguished names RDN1 and RDN2 match if they have the
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same number of naming attributes and for each naming attribute in RDN1
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there is a matching naming attribute in RDN2." --RFC 5280 sec. 7.1.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rdn1.size() != rdn2.size())
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i1 = 0; i1 < rdn1.size(); ++i1) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned i2;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i2 = 0; i2 < rdn2.size(); ++i2) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (match(rdn1[i1], rdn2[i2]))
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i2 == rdn2.size())
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CertPrincipal::ParseDistinguishedName(const void* ber_name_data,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           size_t length) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ber_name_data);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First parse the BER |name_data| into the above structs.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SecAsn1CoderRef coder = NULL;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SecAsn1CoderCreate(&coder);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(coder);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  X509Name* name = NULL;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSStatus err = SecAsn1Decode(coder, ber_name_data, length, kNameTemplate,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &name);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSSTATUS_LOG(ERROR, err) << "SecAsn1Decode";
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SecAsn1CoderRelease(coder);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now scan the structs and add the values to my string vectors.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // I don't store multiple common/locality/state/country names, so use
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // temporary vectors for those.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> common_names, locality_names, state_names,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      country_names;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string>* values[] = {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &common_names, &locality_names,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &state_names, &country_names,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &this->street_addresses,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &this->organization_names,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &this->organization_unit_names,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &this->domain_components
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(arraysize(kOIDs) == arraysize(values));
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int rdn = 0; name[rdn].pairs_list; ++rdn) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSSM_X509_TYPE_VALUE_PAIR* pair;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int pair_index = 0;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         NULL != (pair = name[rdn].pairs_list[0][pair_index].pairs);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++pair_index) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (pair->valueType) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BER_TAG_IA5_STRING:          // ASCII (that means 7-bit!)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BER_TAG_PRINTABLE_STRING:    // a subset of ASCII
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BER_TAG_PKIX_UTF8_STRING:    // UTF-8
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddTypeValuePair(pair->type, DataToString(pair->value), values);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BER_TAG_T61_STRING:          // T61, pretend it's Latin-1
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddTypeValuePair(pair->type,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Latin1DataToUTF8String(pair->value),
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           values);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BER_TAG_PKIX_BMP_STRING: {        // UTF-16, big-endian
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::string value;
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          UTF16BigEndianToUTF8(
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              reinterpret_cast<base::char16*>(pair->value.Data),
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              pair->value.Length / sizeof(base::char16),
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)              &value);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddTypeValuePair(pair->type, value, values);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BER_TAG_PKIX_UNIVERSAL_STRING: {  // UTF-32, big-endian
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::string value;
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          UTF32BigEndianToUTF8(reinterpret_cast<int32_t*>(pair->value.Data),
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               pair->value.Length / sizeof(int32_t),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &value);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddTypeValuePair(pair->type, value, values);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK_EQ(pair->valueType, BER_TAG_UNKNOWN);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // We don't know what data type this is, but we'll store it as a blob.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Displaying the string may not work, but at least it can be compared
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // byte-for-byte by a Matches() call.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AddTypeValuePair(pair->type, DataToString(pair->value), values);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetSingle(common_names, &this->common_name);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetSingle(locality_names, &this->locality_name);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetSingle(state_names, &this->state_or_province_name);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetSingle(country_names, &this->country_name);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releasing |coder| frees all the memory pointed to via |name|.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SecAsn1CoderRelease(coder);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CertPrincipal::Matches(const CertPrincipal& against) const {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return match(common_name, against.common_name) &&
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match(locality_name, against.locality_name) &&
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match(state_or_province_name, against.state_or_province_name) &&
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match(country_name, against.country_name) &&
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match(street_addresses, against.street_addresses) &&
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match(organization_names, against.organization_names) &&
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match(organization_unit_names, against.organization_unit_names) &&
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match(domain_components, against.domain_components);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
293