| Index: net/base/x509_certificate_mac.cc | 
| diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc | 
| deleted file mode 100644 | 
| index 9e2565aa8e3bfb7a87c903b639025996ca63c86e..0000000000000000000000000000000000000000 | 
| --- a/net/base/x509_certificate_mac.cc | 
| +++ /dev/null | 
| @@ -1,834 +0,0 @@ | 
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| -// Use of this source code is governed by a BSD-style license that can be | 
| -// found in the LICENSE file. | 
| - | 
| -#include "net/base/x509_certificate.h" | 
| - | 
| -#include <CommonCrypto/CommonDigest.h> | 
| -#include <CoreServices/CoreServices.h> | 
| -#include <Security/Security.h> | 
| -#include <time.h> | 
| - | 
| -#include <vector> | 
| - | 
| -#include "base/lazy_instance.h" | 
| -#include "base/logging.h" | 
| -#include "base/mac/mac_logging.h" | 
| -#include "base/mac/scoped_cftyperef.h" | 
| -#include "base/memory/singleton.h" | 
| -#include "base/pickle.h" | 
| -#include "base/sha1.h" | 
| -#include "base/string_piece.h" | 
| -#include "base/synchronization/lock.h" | 
| -#include "base/sys_string_conversions.h" | 
| -#include "crypto/cssm_init.h" | 
| -#include "crypto/mac_security_services_lock.h" | 
| -#include "crypto/nss_util.h" | 
| -#include "crypto/rsa_private_key.h" | 
| -#include "net/base/x509_util_mac.h" | 
| -#include "third_party/nss/mozilla/security/nss/lib/certdb/cert.h" | 
| - | 
| -using base::mac::ScopedCFTypeRef; | 
| -using base::Time; | 
| - | 
| -namespace net { | 
| - | 
| -namespace { | 
| - | 
| -void GetCertDistinguishedName( | 
| -    const x509_util::CSSMCachedCertificate& cached_cert, | 
| -    const CSSM_OID* oid, | 
| -    CertPrincipal* result) { | 
| -  x509_util::CSSMFieldValue distinguished_name; | 
| -  OSStatus status = cached_cert.GetField(oid, &distinguished_name); | 
| -  if (status || !distinguished_name.field()) | 
| -    return; | 
| -  result->ParseDistinguishedName(distinguished_name.field()->Data, | 
| -                                 distinguished_name.field()->Length); | 
| -} | 
| - | 
| -bool IsCertIssuerInEncodedList(X509Certificate::OSCertHandle cert_handle, | 
| -                               const std::vector<std::string>& issuers) { | 
| -  x509_util::CSSMCachedCertificate cached_cert; | 
| -  if (cached_cert.Init(cert_handle) != CSSM_OK) | 
| -    return false; | 
| - | 
| -  x509_util::CSSMFieldValue distinguished_name; | 
| -  OSStatus status = cached_cert.GetField(&CSSMOID_X509V1IssuerNameStd, | 
| -                                         &distinguished_name); | 
| -  if (status || !distinguished_name.field()) | 
| -    return false; | 
| - | 
| -  base::StringPiece name_piece( | 
| -      reinterpret_cast<const char*>(distinguished_name.field()->Data), | 
| -      static_cast<size_t>(distinguished_name.field()->Length)); | 
| - | 
| -  for (std::vector<std::string>::const_iterator it = issuers.begin(); | 
| -       it != issuers.end(); ++it) { | 
| -    base::StringPiece issuer_piece(*it); | 
| -    if (name_piece == issuer_piece) | 
| -      return true; | 
| -  } | 
| - | 
| -  return false; | 
| -} | 
| - | 
| -void GetCertDateForOID(const x509_util::CSSMCachedCertificate& cached_cert, | 
| -                       const CSSM_OID* oid, | 
| -                       Time* result) { | 
| -  *result = Time::Time(); | 
| - | 
| -  x509_util::CSSMFieldValue field; | 
| -  OSStatus status = cached_cert.GetField(oid, &field); | 
| -  if (status) | 
| -    return; | 
| - | 
| -  const CSSM_X509_TIME* x509_time = field.GetAs<CSSM_X509_TIME>(); | 
| -  if (x509_time->timeType != BER_TAG_UTC_TIME && | 
| -      x509_time->timeType != BER_TAG_GENERALIZED_TIME) { | 
| -    LOG(ERROR) << "Unsupported date/time format " | 
| -               << x509_time->timeType; | 
| -    return; | 
| -  } | 
| - | 
| -  base::StringPiece time_string( | 
| -      reinterpret_cast<const char*>(x509_time->time.Data), | 
| -      x509_time->time.Length); | 
| -  CertDateFormat format = x509_time->timeType == BER_TAG_UTC_TIME ? | 
| -      CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; | 
| -  if (!ParseCertificateDate(time_string, format, result)) | 
| -    LOG(ERROR) << "Invalid certificate date/time " << time_string; | 
| -} | 
| - | 
| -std::string GetCertSerialNumber( | 
| -    const x509_util::CSSMCachedCertificate& cached_cert) { | 
| -  x509_util::CSSMFieldValue serial_number; | 
| -  OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, | 
| -                                         &serial_number); | 
| -  if (status || !serial_number.field()) | 
| -    return std::string(); | 
| - | 
| -  return std::string( | 
| -      reinterpret_cast<const char*>(serial_number.field()->Data), | 
| -      serial_number.field()->Length); | 
| -} | 
| - | 
| -// Gets the issuer for a given cert, starting with the cert itself and | 
| -// including the intermediate and finally root certificates (if any). | 
| -// This function calls SecTrust but doesn't actually pay attention to the trust | 
| -// result: it shouldn't be used to determine trust, just to traverse the chain. | 
| -// Caller is responsible for releasing the value stored into *out_cert_chain. | 
| -OSStatus CopyCertChain(SecCertificateRef cert_handle, | 
| -                       CFArrayRef* out_cert_chain) { | 
| -  DCHECK(cert_handle); | 
| -  DCHECK(out_cert_chain); | 
| - | 
| -  // Create an SSL policy ref configured for client cert evaluation. | 
| -  SecPolicyRef ssl_policy; | 
| -  OSStatus result = x509_util::CreateSSLClientPolicy(&ssl_policy); | 
| -  if (result) | 
| -    return result; | 
| -  ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); | 
| - | 
| -  // Create a SecTrustRef. | 
| -  ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( | 
| -      NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), | 
| -      1, &kCFTypeArrayCallBacks)); | 
| -  SecTrustRef trust_ref = NULL; | 
| -  { | 
| -    base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 
| -    result = SecTrustCreateWithCertificates(input_certs, ssl_policy, | 
| -                                            &trust_ref); | 
| -  } | 
| -  if (result) | 
| -    return result; | 
| -  ScopedCFTypeRef<SecTrustRef> trust(trust_ref); | 
| - | 
| -  // Evaluate trust, which creates the cert chain. | 
| -  SecTrustResultType status; | 
| -  CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; | 
| -  { | 
| -    base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 
| -    result = SecTrustEvaluate(trust, &status); | 
| -  } | 
| -  if (result) | 
| -    return result; | 
| -  { | 
| -    base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 
| -    result = SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); | 
| -  } | 
| -  return result; | 
| -} | 
| - | 
| -// Returns true if |purpose| is listed as allowed in |usage|. This | 
| -// function also considers the "Any" purpose. If the attribute is | 
| -// present and empty, we return false. | 
| -bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, | 
| -                            const CSSM_OID* purpose) { | 
| -  for (unsigned p = 0; p < usage->numPurposes; ++p) { | 
| -    if (CSSMOIDEqual(&usage->purposes[p], purpose)) | 
| -      return true; | 
| -    if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) | 
| -      return true; | 
| -  } | 
| -  return false; | 
| -} | 
| - | 
| -// Test that a given |cert_handle| is actually a valid X.509 certificate, and | 
| -// return true if it is. | 
| -// | 
| -// On OS X, SecCertificateCreateFromData() does not return any errors if | 
| -// called with invalid data, as long as data is present. The actual decoding | 
| -// of the certificate does not happen until an API that requires a CSSM | 
| -// handle is called. While SecCertificateGetCLHandle is the most likely | 
| -// candidate, as it performs the parsing, it does not check whether the | 
| -// parsing was actually successful. Instead, SecCertificateGetSubject is | 
| -// used (supported since 10.3), as a means to check that the certificate | 
| -// parsed as a valid X.509 certificate. | 
| -bool IsValidOSCertHandle(SecCertificateRef cert_handle) { | 
| -  const CSSM_X509_NAME* sanity_check = NULL; | 
| -  OSStatus status = SecCertificateGetSubject(cert_handle, &sanity_check); | 
| -  return status == noErr && sanity_check; | 
| -} | 
| - | 
| -// Parses |data| of length |length|, attempting to decode it as the specified | 
| -// |format|. If |data| is in the specified format, any certificates contained | 
| -// within are stored into |output|. | 
| -void AddCertificatesFromBytes(const char* data, size_t length, | 
| -                              SecExternalFormat format, | 
| -                              X509Certificate::OSCertHandles* output) { | 
| -  SecExternalFormat input_format = format; | 
| -  ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( | 
| -      kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, | 
| -      kCFAllocatorNull)); | 
| - | 
| -  CFArrayRef items = NULL; | 
| -  OSStatus status; | 
| -  { | 
| -    base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 
| -    status = SecKeychainItemImport(local_data, NULL, &input_format, | 
| -                                   NULL, 0, NULL, NULL, &items); | 
| -  } | 
| - | 
| -  if (status) { | 
| -    OSSTATUS_DLOG(WARNING, status) | 
| -        << "Unable to import items from data of length " << length; | 
| -    return; | 
| -  } | 
| - | 
| -  ScopedCFTypeRef<CFArrayRef> scoped_items(items); | 
| -  CFTypeID cert_type_id = SecCertificateGetTypeID(); | 
| - | 
| -  for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { | 
| -    SecKeychainItemRef item = reinterpret_cast<SecKeychainItemRef>( | 
| -        const_cast<void*>(CFArrayGetValueAtIndex(items, i))); | 
| - | 
| -    // While inputFormat implies only certificates will be imported, if/when | 
| -    // other formats (eg: PKCS#12) are supported, this may also include | 
| -    // private keys or other items types, so filter appropriately. | 
| -    if (CFGetTypeID(item) == cert_type_id) { | 
| -      SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(item); | 
| -      // OS X ignores |input_format| if it detects that |local_data| is PEM | 
| -      // encoded, attempting to decode data based on internal rules for PEM | 
| -      // block headers. If a PKCS#7 blob is encoded with a PEM block of | 
| -      // CERTIFICATE, OS X 10.5 will return a single, invalid certificate | 
| -      // based on the decoded data. If this happens, the certificate should | 
| -      // not be included in |output|. Because |output| is empty, | 
| -      // CreateCertificateListfromBytes will use PEMTokenizer to decode the | 
| -      // data. When called again with the decoded data, OS X will honor | 
| -      // |input_format|, causing decode to succeed. On OS X 10.6, the data | 
| -      // is properly decoded as a PKCS#7, whether PEM or not, which avoids | 
| -      // the need to fallback to internal decoding. | 
| -      if (IsValidOSCertHandle(cert)) { | 
| -        CFRetain(cert); | 
| -        output->push_back(cert); | 
| -      } | 
| -    } | 
| -  } | 
| -} | 
| - | 
| -struct CSSMOIDString { | 
| -  const CSSM_OID* oid_; | 
| -  std::string string_; | 
| -}; | 
| - | 
| -typedef std::vector<CSSMOIDString> CSSMOIDStringVector; | 
| - | 
| -bool CERTNameToCSSMOIDVector(CERTName* name, CSSMOIDStringVector* out_values) { | 
| -  struct OIDCSSMMap { | 
| -    SECOidTag sec_OID_; | 
| -    const CSSM_OID* cssm_OID_; | 
| -  }; | 
| - | 
| -  const OIDCSSMMap kOIDs[] = { | 
| -      { SEC_OID_AVA_COMMON_NAME, &CSSMOID_CommonName }, | 
| -      { SEC_OID_AVA_COUNTRY_NAME, &CSSMOID_CountryName }, | 
| -      { SEC_OID_AVA_LOCALITY, &CSSMOID_LocalityName }, | 
| -      { SEC_OID_AVA_STATE_OR_PROVINCE, &CSSMOID_StateProvinceName }, | 
| -      { SEC_OID_AVA_STREET_ADDRESS, &CSSMOID_StreetAddress }, | 
| -      { SEC_OID_AVA_ORGANIZATION_NAME, &CSSMOID_OrganizationName }, | 
| -      { SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, &CSSMOID_OrganizationalUnitName }, | 
| -      { SEC_OID_AVA_DN_QUALIFIER, &CSSMOID_DNQualifier }, | 
| -      { SEC_OID_RFC1274_UID, &CSSMOID_UniqueIdentifier }, | 
| -      { SEC_OID_PKCS9_EMAIL_ADDRESS, &CSSMOID_EmailAddress }, | 
| -  }; | 
| - | 
| -  CERTRDN** rdns = name->rdns; | 
| -  for (size_t rdn = 0; rdns[rdn]; ++rdn) { | 
| -    CERTAVA** avas = rdns[rdn]->avas; | 
| -    for (size_t pair = 0; avas[pair] != 0; ++pair) { | 
| -      SECOidTag tag = CERT_GetAVATag(avas[pair]); | 
| -      if (tag == SEC_OID_UNKNOWN) { | 
| -        return false; | 
| -      } | 
| -      CSSMOIDString oidString; | 
| -      bool found_oid = false; | 
| -      for (size_t oid = 0; oid < ARRAYSIZE_UNSAFE(kOIDs); ++oid) { | 
| -        if (kOIDs[oid].sec_OID_ == tag) { | 
| -          SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value); | 
| -          if (!decode_item) | 
| -            return false; | 
| - | 
| -          // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote. | 
| -          std::string value(reinterpret_cast<char*>(decode_item->data), | 
| -                            decode_item->len); | 
| -          oidString.oid_ = kOIDs[oid].cssm_OID_; | 
| -          oidString.string_ = value; | 
| -          out_values->push_back(oidString); | 
| -          SECITEM_FreeItem(decode_item, PR_TRUE); | 
| -          found_oid = true; | 
| -          break; | 
| -        } | 
| -      } | 
| -      if (!found_oid) { | 
| -        DLOG(ERROR) << "Unrecognized OID: " << tag; | 
| -      } | 
| -    } | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -class ScopedCertName { | 
| - public: | 
| -  explicit ScopedCertName(CERTName* name) : name_(name) { } | 
| -  ~ScopedCertName() { | 
| -    if (name_) CERT_DestroyName(name_); | 
| -  } | 
| -  operator CERTName*() { return name_; } | 
| - | 
| - private: | 
| -  CERTName* name_; | 
| -}; | 
| - | 
| -class ScopedEncodedCertResults { | 
| - public: | 
| -  explicit ScopedEncodedCertResults(CSSM_TP_RESULT_SET* results) | 
| -      : results_(results) { } | 
| -  ~ScopedEncodedCertResults() { | 
| -    if (results_) { | 
| -      CSSM_ENCODED_CERT* encCert = | 
| -          reinterpret_cast<CSSM_ENCODED_CERT*>(results_->Results); | 
| -      for (uint32 i = 0; i < results_->NumberOfResults; i++) { | 
| -        crypto::CSSMFree(encCert[i].CertBlob.Data); | 
| -      } | 
| -    } | 
| -    crypto::CSSMFree(results_->Results); | 
| -    crypto::CSSMFree(results_); | 
| -  } | 
| - | 
| - private: | 
| -  CSSM_TP_RESULT_SET* results_; | 
| -}; | 
| - | 
| -}  // namespace | 
| - | 
| -void X509Certificate::Initialize() { | 
| -  x509_util::CSSMCachedCertificate cached_cert; | 
| -  if (cached_cert.Init(cert_handle_) == CSSM_OK) { | 
| -    GetCertDistinguishedName(cached_cert, &CSSMOID_X509V1SubjectNameStd, | 
| -                             &subject_); | 
| -    GetCertDistinguishedName(cached_cert, &CSSMOID_X509V1IssuerNameStd, | 
| -                             &issuer_); | 
| -    GetCertDateForOID(cached_cert, &CSSMOID_X509V1ValidityNotBefore, | 
| -                      &valid_start_); | 
| -    GetCertDateForOID(cached_cert, &CSSMOID_X509V1ValidityNotAfter, | 
| -                      &valid_expiry_); | 
| -    serial_number_ = GetCertSerialNumber(cached_cert); | 
| -  } | 
| - | 
| -  fingerprint_ = CalculateFingerprint(cert_handle_); | 
| -  ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); | 
| -} | 
| - | 
| -bool X509Certificate::IsIssuedByEncoded( | 
| -    const std::vector<std::string>& valid_issuers) { | 
| -  if (IsCertIssuerInEncodedList(cert_handle_, valid_issuers)) | 
| -    return true; | 
| - | 
| -  for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); | 
| -       it != intermediate_ca_certs_.end(); ++it) { | 
| -    if (IsCertIssuerInEncodedList(*it, valid_issuers)) | 
| -      return true; | 
| -  } | 
| -  return false; | 
| -} | 
| - | 
| -// static | 
| -X509Certificate* X509Certificate::CreateSelfSigned( | 
| -    crypto::RSAPrivateKey* key, | 
| -    const std::string& subject, | 
| -    uint32 serial_number, | 
| -    base::TimeDelta valid_duration) { | 
| -  DCHECK(key); | 
| -  DCHECK(!subject.empty()); | 
| - | 
| -  if (valid_duration.InSeconds() > kuint32max) { | 
| -     LOG(ERROR) << "valid_duration too big " << valid_duration.InSeconds(); | 
| -     valid_duration = base::TimeDelta::FromSeconds(kuint32max); | 
| -  } | 
| - | 
| -  // There is a comment in | 
| -  // http://www.opensource.apple.com/source/security_certtool/security_certtool-31828/src/CertTool.cpp | 
| -  // that serial_numbers being passed into CSSM_TP_SubmitCredRequest can't have | 
| -  // their high bit set. We will continue though and mask it out below. | 
| -  if (serial_number & 0x80000000) | 
| -    LOG(ERROR) << "serial_number has high bit set " << serial_number; | 
| - | 
| -  // NSS is used to parse the subject string into a set of | 
| -  // CSSM_OID/string pairs. There doesn't appear to be a system routine for | 
| -  // parsing Distinguished Name strings. | 
| -  crypto::EnsureNSSInit(); | 
| - | 
| -  CSSMOIDStringVector subject_name_oids; | 
| -  ScopedCertName subject_name( | 
| -      CERT_AsciiToName(const_cast<char*>(subject.c_str()))); | 
| -  if (!CERTNameToCSSMOIDVector(subject_name, &subject_name_oids)) { | 
| -    DLOG(ERROR) << "Unable to generate CSSMOIDMap from " << subject; | 
| -    return NULL; | 
| -  } | 
| - | 
| -  // Convert the map of oid/string pairs into an array of | 
| -  // CSSM_APPLE_TP_NAME_OIDs. | 
| -  std::vector<CSSM_APPLE_TP_NAME_OID> cssm_subject_names; | 
| -  for (CSSMOIDStringVector::iterator iter = subject_name_oids.begin(); | 
| -      iter != subject_name_oids.end(); ++iter) { | 
| -    CSSM_APPLE_TP_NAME_OID cssm_subject_name; | 
| -    cssm_subject_name.oid = iter->oid_; | 
| -    cssm_subject_name.string = iter->string_.c_str(); | 
| -    cssm_subject_names.push_back(cssm_subject_name); | 
| -  } | 
| - | 
| -  if (cssm_subject_names.empty()) { | 
| -    DLOG(ERROR) << "cssm_subject_names.size() == 0. Input: " << subject; | 
| -    return NULL; | 
| -  } | 
| - | 
| -  // Set up a certificate request. | 
| -  CSSM_APPLE_TP_CERT_REQUEST certReq; | 
| -  memset(&certReq, 0, sizeof(certReq)); | 
| -  certReq.cspHand = crypto::GetSharedCSPHandle(); | 
| -  certReq.clHand = crypto::GetSharedCLHandle(); | 
| -    // See comment about serial numbers above. | 
| -  certReq.serialNumber = serial_number & 0x7fffffff; | 
| -  certReq.numSubjectNames = cssm_subject_names.size(); | 
| -  certReq.subjectNames = &cssm_subject_names[0]; | 
| -  certReq.numIssuerNames = 0;  // Root. | 
| -  certReq.issuerNames = NULL; | 
| -  certReq.issuerNameX509 = NULL; | 
| -  certReq.certPublicKey = key->public_key(); | 
| -  certReq.issuerPrivateKey = key->key(); | 
| -  // These are the Apple defaults. | 
| -  certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA; | 
| -  certReq.signatureOid = CSSMOID_SHA1WithRSA; | 
| -  certReq.notBefore = 0; | 
| -  certReq.notAfter = static_cast<uint32>(valid_duration.InSeconds()); | 
| -  certReq.numExtensions = 0; | 
| -  certReq.extensions = NULL; | 
| -  certReq.challengeString = NULL; | 
| - | 
| -  CSSM_TP_REQUEST_SET reqSet; | 
| -  reqSet.NumberOfRequests = 1; | 
| -  reqSet.Requests = &certReq; | 
| - | 
| -  CSSM_FIELD policyId; | 
| -  memset(&policyId, 0, sizeof(policyId)); | 
| -  policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN; | 
| - | 
| -  CSSM_TP_CALLERAUTH_CONTEXT callerAuthContext; | 
| -  memset(&callerAuthContext, 0, sizeof(callerAuthContext)); | 
| -  callerAuthContext.Policy.NumberOfPolicyIds = 1; | 
| -  callerAuthContext.Policy.PolicyIds = &policyId; | 
| - | 
| -  CSSM_TP_HANDLE tp_handle = crypto::GetSharedTPHandle(); | 
| -  CSSM_DATA refId; | 
| -  memset(&refId, 0, sizeof(refId)); | 
| -  sint32 estTime; | 
| -  CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tp_handle, NULL, | 
| -      CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, &reqSet, &callerAuthContext, | 
| -       &estTime, &refId); | 
| -  if (crtn) { | 
| -    DLOG(ERROR) << "CSSM_TP_SubmitCredRequest failed " << crtn; | 
| -    return NULL; | 
| -  } | 
| - | 
| -  CSSM_BOOL confirmRequired; | 
| -  CSSM_TP_RESULT_SET* resultSet = NULL; | 
| -  crtn = CSSM_TP_RetrieveCredResult(tp_handle, &refId, NULL, &estTime, | 
| -                                    &confirmRequired, &resultSet); | 
| -  ScopedEncodedCertResults scopedResults(resultSet); | 
| -  crypto::CSSMFree(refId.Data); | 
| -  if (crtn) { | 
| -    DLOG(ERROR) << "CSSM_TP_RetrieveCredResult failed " << crtn; | 
| -    return NULL; | 
| -  } | 
| - | 
| -  if (confirmRequired) { | 
| -    // Potential leak here of resultSet. |confirmRequired| should never be | 
| -    // true. | 
| -    DLOG(ERROR) << "CSSM_TP_RetrieveCredResult required confirmation"; | 
| -    return NULL; | 
| -  } | 
| - | 
| -  if (resultSet->NumberOfResults != 1) { | 
| -     DLOG(ERROR) << "Unexpected number of results: " | 
| -                 << resultSet->NumberOfResults; | 
| -    return NULL; | 
| -  } | 
| - | 
| -  CSSM_ENCODED_CERT* encCert = | 
| -      reinterpret_cast<CSSM_ENCODED_CERT*>(resultSet->Results); | 
| -  ScopedCFTypeRef<SecCertificateRef> scoped_cert; | 
| -  SecCertificateRef certificate_ref = NULL; | 
| -  OSStatus os_status = | 
| -      SecCertificateCreateFromData(&encCert->CertBlob, encCert->CertType, | 
| -                                   encCert->CertEncoding, &certificate_ref); | 
| -  if (os_status != 0) { | 
| -    OSSTATUS_DLOG(ERROR, os_status) << "SecCertificateCreateFromData failed"; | 
| -    return NULL; | 
| -  } | 
| -  scoped_cert.reset(certificate_ref); | 
| - | 
| -  return CreateFromHandle(scoped_cert, X509Certificate::OSCertHandles()); | 
| -} | 
| - | 
| -void X509Certificate::GetSubjectAltName( | 
| -    std::vector<std::string>* dns_names, | 
| -    std::vector<std::string>* ip_addrs) const { | 
| -  if (dns_names) | 
| -    dns_names->clear(); | 
| -  if (ip_addrs) | 
| -    ip_addrs->clear(); | 
| - | 
| -  x509_util::CSSMCachedCertificate cached_cert; | 
| -  OSStatus status = cached_cert.Init(cert_handle_); | 
| -  if (status) | 
| -    return; | 
| -  x509_util::CSSMFieldValue subject_alt_name; | 
| -  status = cached_cert.GetField(&CSSMOID_SubjectAltName, &subject_alt_name); | 
| -  if (status || !subject_alt_name.field()) | 
| -    return; | 
| -  const CSSM_X509_EXTENSION* cssm_ext = | 
| -      subject_alt_name.GetAs<CSSM_X509_EXTENSION>(); | 
| -  if (!cssm_ext || !cssm_ext->value.parsedValue) | 
| -    return; | 
| -  const CE_GeneralNames* alt_name = | 
| -      reinterpret_cast<const CE_GeneralNames*>(cssm_ext->value.parsedValue); | 
| - | 
| -  for (size_t name = 0; name < alt_name->numNames; ++name) { | 
| -    const CE_GeneralName& name_struct = alt_name->generalName[name]; | 
| -    const CSSM_DATA& name_data = name_struct.name; | 
| -    // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs | 
| -    // respectively, both of which can be byte copied from | 
| -    // CSSM_DATA::data into the appropriate output vector. | 
| -    if (dns_names && name_struct.nameType == GNT_DNSName) { | 
| -      dns_names->push_back(std::string( | 
| -          reinterpret_cast<const char*>(name_data.Data), | 
| -          name_data.Length)); | 
| -    } else if (ip_addrs && name_struct.nameType == GNT_IPAddress) { | 
| -      ip_addrs->push_back(std::string( | 
| -          reinterpret_cast<const char*>(name_data.Data), | 
| -          name_data.Length)); | 
| -    } | 
| -  } | 
| -} | 
| - | 
| -// static | 
| -bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 
| -                                    std::string* encoded) { | 
| -  CSSM_DATA der_data; | 
| -  if (SecCertificateGetData(cert_handle, &der_data) != noErr) | 
| -    return false; | 
| -  encoded->assign(reinterpret_cast<char*>(der_data.Data), | 
| -                  der_data.Length); | 
| -  return true; | 
| -} | 
| - | 
| -// static | 
| -bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | 
| -                                   X509Certificate::OSCertHandle b) { | 
| -  DCHECK(a && b); | 
| -  if (a == b) | 
| -    return true; | 
| -  if (CFEqual(a, b)) | 
| -    return true; | 
| -  CSSM_DATA a_data, b_data; | 
| -  return SecCertificateGetData(a, &a_data) == noErr && | 
| -      SecCertificateGetData(b, &b_data) == noErr && | 
| -      a_data.Length == b_data.Length && | 
| -      memcmp(a_data.Data, b_data.Data, a_data.Length) == 0; | 
| -} | 
| - | 
| -// static | 
| -X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 
| -    const char* data, int length) { | 
| -  CSSM_DATA cert_data; | 
| -  cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); | 
| -  cert_data.Length = length; | 
| - | 
| -  OSCertHandle cert_handle = NULL; | 
| -  OSStatus status = SecCertificateCreateFromData(&cert_data, | 
| -                                                 CSSM_CERT_X_509v3, | 
| -                                                 CSSM_CERT_ENCODING_DER, | 
| -                                                 &cert_handle); | 
| -  if (status != noErr) | 
| -    return NULL; | 
| -  if (!IsValidOSCertHandle(cert_handle)) { | 
| -    CFRelease(cert_handle); | 
| -    return NULL; | 
| -  } | 
| -  return cert_handle; | 
| -} | 
| - | 
| -// static | 
| -X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | 
| -    const char* data, int length, Format format) { | 
| -  OSCertHandles results; | 
| - | 
| -  switch (format) { | 
| -    case FORMAT_SINGLE_CERTIFICATE: { | 
| -      OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); | 
| -      if (handle) | 
| -        results.push_back(handle); | 
| -      break; | 
| -    } | 
| -    case FORMAT_PKCS7: | 
| -      AddCertificatesFromBytes(data, length, kSecFormatPKCS7, &results); | 
| -      break; | 
| -    default: | 
| -      NOTREACHED() << "Certificate format " << format << " unimplemented"; | 
| -      break; | 
| -  } | 
| - | 
| -  return results; | 
| -} | 
| - | 
| -// static | 
| -X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 
| -    OSCertHandle handle) { | 
| -  if (!handle) | 
| -    return NULL; | 
| -  return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); | 
| -} | 
| - | 
| -// static | 
| -void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 
| -  CFRelease(cert_handle); | 
| -} | 
| - | 
| -// static | 
| -SHA1HashValue X509Certificate::CalculateFingerprint( | 
| -    OSCertHandle cert) { | 
| -  SHA1HashValue sha1; | 
| -  memset(sha1.data, 0, sizeof(sha1.data)); | 
| - | 
| -  CSSM_DATA cert_data; | 
| -  OSStatus status = SecCertificateGetData(cert, &cert_data); | 
| -  if (status) | 
| -    return sha1; | 
| - | 
| -  DCHECK(cert_data.Data); | 
| -  DCHECK_NE(cert_data.Length, 0U); | 
| - | 
| -  CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); | 
| - | 
| -  return sha1; | 
| -} | 
| - | 
| -// static | 
| -SHA1HashValue X509Certificate::CalculateCAFingerprint( | 
| -    const OSCertHandles& intermediates) { | 
| -  SHA1HashValue sha1; | 
| -  memset(sha1.data, 0, sizeof(sha1.data)); | 
| - | 
| -  // The CC_SHA(3cc) man page says all CC_SHA1_xxx routines return 1, so | 
| -  // we don't check their return values. | 
| -  CC_SHA1_CTX sha1_ctx; | 
| -  CC_SHA1_Init(&sha1_ctx); | 
| -  CSSM_DATA cert_data; | 
| -  for (size_t i = 0; i < intermediates.size(); ++i) { | 
| -    OSStatus status = SecCertificateGetData(intermediates[i], &cert_data); | 
| -    if (status) | 
| -      return sha1; | 
| -    CC_SHA1_Update(&sha1_ctx, cert_data.Data, cert_data.Length); | 
| -  } | 
| -  CC_SHA1_Final(sha1.data, &sha1_ctx); | 
| - | 
| -  return sha1; | 
| -} | 
| - | 
| -bool X509Certificate::SupportsSSLClientAuth() const { | 
| -  x509_util::CSSMCachedCertificate cached_cert; | 
| -  OSStatus status = cached_cert.Init(cert_handle_); | 
| -  if (status) | 
| -    return false; | 
| - | 
| -  // RFC5280 says to take the intersection of the two extensions. | 
| -  // | 
| -  // Our underlying crypto libraries don't expose | 
| -  // ClientCertificateType, so for now we will not support fixed | 
| -  // Diffie-Hellman mechanisms. For rsa_sign, we need the | 
| -  // digitalSignature bit. | 
| -  // | 
| -  // In particular, if a key has the nonRepudiation bit and not the | 
| -  // digitalSignature one, we will not offer it to the user. | 
| -  x509_util::CSSMFieldValue key_usage; | 
| -  status = cached_cert.GetField(&CSSMOID_KeyUsage, &key_usage); | 
| -  if (status == CSSM_OK && key_usage.field()) { | 
| -    const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); | 
| -    const CE_KeyUsage* key_usage_value = | 
| -        reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue); | 
| -    if (!((*key_usage_value) & CE_KU_DigitalSignature)) | 
| -      return false; | 
| -  } | 
| - | 
| -  status = cached_cert.GetField(&CSSMOID_ExtendedKeyUsage, &key_usage); | 
| -  if (status == CSSM_OK && key_usage.field()) { | 
| -    const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); | 
| -    const CE_ExtendedKeyUsage* ext_key_usage = | 
| -        reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); | 
| -    if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth)) | 
| -      return false; | 
| -  } | 
| -  return true; | 
| -} | 
| - | 
| -CFArrayRef X509Certificate::CreateClientCertificateChain() const { | 
| -  // Initialize the result array with just the IdentityRef of the receiver: | 
| -  SecIdentityRef identity; | 
| -  OSStatus result; | 
| -  { | 
| -    base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 
| -    result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); | 
| -  } | 
| -  if (result) { | 
| -    OSSTATUS_LOG(ERROR, result) << "SecIdentityCreateWithCertificate error"; | 
| -    return NULL; | 
| -  } | 
| -  ScopedCFTypeRef<CFMutableArrayRef> chain( | 
| -      CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); | 
| -  CFArrayAppendValue(chain, identity); | 
| - | 
| -  CFArrayRef cert_chain = NULL; | 
| -  result = CopyCertChain(cert_handle_, &cert_chain); | 
| -  ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); | 
| -  if (result) { | 
| -    OSSTATUS_LOG(ERROR, result) << "CreateIdentityCertificateChain error"; | 
| -    return chain.release(); | 
| -  } | 
| - | 
| -  // Append the intermediate certs from SecTrust to the result array: | 
| -  if (cert_chain) { | 
| -    int chain_count = CFArrayGetCount(cert_chain); | 
| -    if (chain_count > 1) { | 
| -      CFArrayAppendArray(chain, | 
| -                         cert_chain, | 
| -                         CFRangeMake(1, chain_count - 1)); | 
| -    } | 
| -  } | 
| - | 
| -  return chain.release(); | 
| -} | 
| - | 
| -CFArrayRef X509Certificate::CreateOSCertChainForCert() const { | 
| -  CFMutableArrayRef cert_list = | 
| -      CFArrayCreateMutable(kCFAllocatorDefault, 0, | 
| -                           &kCFTypeArrayCallBacks); | 
| -  if (!cert_list) | 
| -    return NULL; | 
| - | 
| -  CFArrayAppendValue(cert_list, os_cert_handle()); | 
| -  for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) | 
| -    CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); | 
| - | 
| -  return cert_list; | 
| -} | 
| - | 
| -// static | 
| -X509Certificate::OSCertHandle | 
| -X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) { | 
| -  const char* data; | 
| -  int length; | 
| -  if (!pickle_iter->ReadData(&data, &length)) | 
| -    return NULL; | 
| - | 
| -  return CreateOSCertHandleFromBytes(data, length); | 
| -} | 
| - | 
| -// static | 
| -bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, | 
| -                                                Pickle* pickle) { | 
| -  CSSM_DATA cert_data; | 
| -  OSStatus status = SecCertificateGetData(cert_handle, &cert_data); | 
| -  if (status) | 
| -    return false; | 
| - | 
| -  return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), | 
| -                           cert_data.Length); | 
| -} | 
| - | 
| -// static | 
| -void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, | 
| -                                       size_t* size_bits, | 
| -                                       PublicKeyType* type) { | 
| -  // Since we might fail, set the output parameters to default values first. | 
| -  *type = kPublicKeyTypeUnknown; | 
| -  *size_bits = 0; | 
| - | 
| -  SecKeyRef key; | 
| -  OSStatus status = SecCertificateCopyPublicKey(cert_handle, &key); | 
| -  if (status) { | 
| -    NOTREACHED() << "SecCertificateCopyPublicKey failed: " << status; | 
| -    return; | 
| -  } | 
| -  ScopedCFTypeRef<SecKeyRef> scoped_key(key); | 
| - | 
| -  const CSSM_KEY* cssm_key; | 
| -  status = SecKeyGetCSSMKey(key, &cssm_key); | 
| -  if (status) { | 
| -    NOTREACHED() << "SecKeyGetCSSMKey failed: " << status; | 
| -    return; | 
| -  } | 
| - | 
| -  *size_bits = cssm_key->KeyHeader.LogicalKeySizeInBits; | 
| - | 
| -  switch (cssm_key->KeyHeader.AlgorithmId) { | 
| -    case CSSM_ALGID_RSA: | 
| -      *type = kPublicKeyTypeRSA; | 
| -      break; | 
| -    case CSSM_ALGID_DSA: | 
| -      *type = kPublicKeyTypeDSA; | 
| -      break; | 
| -    case CSSM_ALGID_ECDSA: | 
| -      *type = kPublicKeyTypeECDSA; | 
| -      break; | 
| -    case CSSM_ALGID_DH: | 
| -      *type = kPublicKeyTypeDH; | 
| -      break; | 
| -    default: | 
| -      *type = kPublicKeyTypeUnknown; | 
| -      *size_bits = 0; | 
| -      break; | 
| -  } | 
| -} | 
| - | 
| -}  // namespace net | 
|  |