1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/base/x509_certificate.h"
6
7#include <CommonCrypto/CommonDigest.h>
8#include <CoreServices/CoreServices.h>
9#include <Security/Security.h>
10#include <time.h>
11
12#include <vector>
13
14#include "base/lazy_instance.h"
15#include "base/logging.h"
16#include "base/mac/scoped_cftyperef.h"
17#include "base/memory/singleton.h"
18#include "base/pickle.h"
19#include "base/sha1.h"
20#include "base/sys_string_conversions.h"
21#include "crypto/cssm_init.h"
22#include "crypto/nss_util.h"
23#include "crypto/rsa_private_key.h"
24#include "net/base/asn1_util.h"
25#include "net/base/cert_status_flags.h"
26#include "net/base/cert_verify_result.h"
27#include "net/base/net_errors.h"
28#include "net/base/test_root_certs.h"
29#include "net/base/x509_certificate_known_roots_mac.h"
30#include "third_party/apple_apsl/cssmapplePriv.h"
31#include "third_party/nss/mozilla/security/nss/lib/certdb/cert.h"
32
33using base::mac::ScopedCFTypeRef;
34using base::Time;
35
36namespace net {
37
38namespace {
39
40typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef,
41                                                      CFDictionaryRef*);
42
43int NetErrorFromOSStatus(OSStatus status) {
44  switch (status) {
45    case noErr:
46      return OK;
47    case errSecNotAvailable:
48    case errSecNoCertificateModule:
49    case errSecNoPolicyModule:
50      return ERR_NOT_IMPLEMENTED;
51    case errSecAuthFailed:
52      return ERR_ACCESS_DENIED;
53    default:
54      LOG(ERROR) << "Unknown error " << status << " mapped to ERR_FAILED";
55      return ERR_FAILED;
56  }
57}
58
59int CertStatusFromOSStatus(OSStatus status) {
60  switch (status) {
61    case noErr:
62      return 0;
63
64    case CSSMERR_TP_INVALID_ANCHOR_CERT:
65    case CSSMERR_TP_NOT_TRUSTED:
66    case CSSMERR_TP_INVALID_CERT_AUTHORITY:
67      return CERT_STATUS_AUTHORITY_INVALID;
68
69    case CSSMERR_TP_CERT_EXPIRED:
70    case CSSMERR_TP_CERT_NOT_VALID_YET:
71      // "Expired" and "not yet valid" collapse into a single status.
72      return CERT_STATUS_DATE_INVALID;
73
74    case CSSMERR_TP_CERT_REVOKED:
75    case CSSMERR_TP_CERT_SUSPENDED:
76      return CERT_STATUS_REVOKED;
77
78    case CSSMERR_APPLETP_HOSTNAME_MISMATCH:
79      return CERT_STATUS_COMMON_NAME_INVALID;
80
81    case CSSMERR_APPLETP_CRL_NOT_FOUND:
82    case CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK:
83    case CSSMERR_APPLETP_OCSP_UNAVAILABLE:
84      return CERT_STATUS_NO_REVOCATION_MECHANISM;
85
86    case CSSMERR_APPLETP_CRL_NOT_TRUSTED:
87    case CSSMERR_APPLETP_CRL_SERVER_DOWN:
88    case CSSMERR_APPLETP_CRL_NOT_VALID_YET:
89    case CSSMERR_APPLETP_NETWORK_FAILURE:
90    case CSSMERR_APPLETP_OCSP_BAD_RESPONSE:
91    case CSSMERR_APPLETP_OCSP_NO_SIGNER:
92    case CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED:
93    case CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED:
94    case CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ:
95    case CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR:
96    case CSSMERR_APPLETP_OCSP_RESP_TRY_LATER:
97      // We asked for a revocation check, but didn't get it.
98      return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
99
100    default:
101      // Failure was due to something Chromium doesn't define a
102      // specific status for (such as basic constraints violation, or
103      // unknown critical extension)
104      return CERT_STATUS_INVALID;
105  }
106}
107
108bool OverrideHostnameMismatch(const std::string& hostname,
109                              std::vector<std::string>* dns_names) {
110  // SecTrustEvaluate() does not check dotted IP addresses. If
111  // hostname is provided as, say, 127.0.0.1, then the error
112  // CSSMERR_APPLETP_HOSTNAME_MISMATCH will always be returned,
113  // even if the certificate contains 127.0.0.1 as one of its names.
114  // We, however, want to allow that behavior. SecTrustEvaluate()
115  // only checks for digits and dots when considering whether a
116  // hostname is an IP address, so IPv6 and hex addresses go through
117  // its normal comparison.
118  bool is_dotted_ip = true;
119  bool override_hostname_mismatch = false;
120  for (std::string::const_iterator c = hostname.begin();
121       c != hostname.end() && is_dotted_ip; ++c)
122    is_dotted_ip = (*c >= '0' && *c <= '9') || *c == '.';
123  if (is_dotted_ip) {
124    for (std::vector<std::string>::const_iterator name = dns_names->begin();
125         name != dns_names->end() && !override_hostname_mismatch; ++name)
126      override_hostname_mismatch = (*name == hostname);
127  }
128  return override_hostname_mismatch;
129}
130
131struct CSSMFields {
132  CSSMFields() : cl_handle(NULL), num_of_fields(0), fields(NULL) {}
133  ~CSSMFields() {
134    if (cl_handle)
135      CSSM_CL_FreeFields(cl_handle, num_of_fields, &fields);
136  }
137
138  CSSM_CL_HANDLE cl_handle;
139  uint32 num_of_fields;
140  CSSM_FIELD_PTR fields;
141};
142
143OSStatus GetCertFields(X509Certificate::OSCertHandle cert_handle,
144                       CSSMFields* fields) {
145  DCHECK(cert_handle);
146  DCHECK(fields);
147
148  CSSM_DATA cert_data;
149  OSStatus status = SecCertificateGetData(cert_handle, &cert_data);
150  if (status)
151    return status;
152
153  status = SecCertificateGetCLHandle(cert_handle, &fields->cl_handle);
154  if (status) {
155    DCHECK(!fields->cl_handle);
156    return status;
157  }
158
159  status = CSSM_CL_CertGetAllFields(fields->cl_handle, &cert_data,
160                                    &fields->num_of_fields, &fields->fields);
161  return status;
162}
163
164void GetCertGeneralNamesForOID(X509Certificate::OSCertHandle cert_handle,
165                               CSSM_OID oid, CE_GeneralNameType name_type,
166                               std::vector<std::string>* result) {
167  // For future extension: We only support general names of types
168  // GNT_RFC822Name, GNT_DNSName or GNT_URI.
169  DCHECK(name_type == GNT_RFC822Name ||
170         name_type == GNT_DNSName ||
171         name_type == GNT_URI);
172
173  CSSMFields fields;
174  OSStatus status = GetCertFields(cert_handle, &fields);
175  if (status)
176    return;
177
178  for (size_t field = 0; field < fields.num_of_fields; ++field) {
179    if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) {
180      CSSM_X509_EXTENSION_PTR cssm_ext =
181          reinterpret_cast<CSSM_X509_EXTENSION_PTR>(
182              fields.fields[field].FieldValue.Data);
183      CE_GeneralNames* alt_name =
184          reinterpret_cast<CE_GeneralNames*>(cssm_ext->value.parsedValue);
185
186      for (size_t name = 0; name < alt_name->numNames; ++name) {
187        const CE_GeneralName& name_struct = alt_name->generalName[name];
188        // All of the general name types we support are encoded as
189        // IA5String. In general, we should be switching off
190        // |name_struct.nameType| and doing type-appropriate conversions. See
191        // certextensions.h and the comment immediately preceding
192        // CE_GeneralNameType for more information.
193        if (name_struct.nameType == name_type) {
194          const CSSM_DATA& name_data = name_struct.name;
195          std::string value = std::string(
196              reinterpret_cast<const char*>(name_data.Data),
197              name_data.Length);
198          result->push_back(value);
199        }
200      }
201    }
202  }
203}
204
205void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle,
206                       CSSM_OID oid, Time* result) {
207  *result = Time::Time();
208
209  CSSMFields fields;
210  OSStatus status = GetCertFields(cert_handle, &fields);
211  if (status)
212    return;
213
214  for (size_t field = 0; field < fields.num_of_fields; ++field) {
215    if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) {
216      CSSM_X509_TIME* x509_time = reinterpret_cast<CSSM_X509_TIME*>(
217          fields.fields[field].FieldValue.Data);
218      if (x509_time->timeType != BER_TAG_UTC_TIME &&
219          x509_time->timeType != BER_TAG_GENERALIZED_TIME) {
220        LOG(ERROR) << "Unsupported date/time format "
221                   << x509_time->timeType;
222        return;
223      }
224
225      base::StringPiece time_string(
226          reinterpret_cast<const char*>(x509_time->time.Data),
227          x509_time->time.Length);
228      CertDateFormat format = x509_time->timeType == BER_TAG_UTC_TIME ?
229          CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
230      if (!ParseCertificateDate(time_string, format, result))
231        LOG(ERROR) << "Invalid certificate date/time " << time_string;
232      return;
233    }
234  }
235}
236
237std::string GetCertSerialNumber(X509Certificate::OSCertHandle cert_handle) {
238  CSSMFields fields;
239  OSStatus status = GetCertFields(cert_handle, &fields);
240  if (status)
241    return "";
242
243  std::string ret;
244  for (size_t field = 0; field < fields.num_of_fields; ++field) {
245    if (!CSSMOIDEqual(&fields.fields[field].FieldOid,
246                      &CSSMOID_X509V1SerialNumber)) {
247      continue;
248    }
249    ret.assign(
250        reinterpret_cast<char*>(fields.fields[field].FieldValue.Data),
251        fields.fields[field].FieldValue.Length);
252    break;
253  }
254
255  // Remove leading zeros.
256  while (ret.size() > 1 && ret[0] == 0)
257    ret = ret.substr(1, ret.size() - 1);
258
259  return ret;
260}
261
262// Creates a SecPolicyRef for the given OID, with optional value.
263OSStatus CreatePolicy(const CSSM_OID* policy_OID,
264                      void* option_data,
265                      size_t option_length,
266                      SecPolicyRef* policy) {
267  SecPolicySearchRef search;
268  OSStatus err = SecPolicySearchCreate(CSSM_CERT_X_509v3, policy_OID, NULL,
269                                       &search);
270  if (err)
271    return err;
272  err = SecPolicySearchCopyNext(search, policy);
273  CFRelease(search);
274  if (err)
275    return err;
276
277  if (option_data) {
278    CSSM_DATA options_data = {
279      option_length,
280      reinterpret_cast<uint8_t*>(option_data)
281    };
282    err = SecPolicySetValue(*policy, &options_data);
283    if (err) {
284      CFRelease(*policy);
285      return err;
286    }
287  }
288  return noErr;
289}
290
291// Creates a series of SecPolicyRefs to be added to a SecTrustRef used to
292// validate a certificate for an SSL peer. |hostname| contains the name of
293// the SSL peer that the certificate should be verified against. |flags| is
294// a bitwise-OR of VerifyFlags that can further alter how trust is
295// validated, such as how revocation is checked. If successful, returns
296// noErr, and stores the resultant array of SecPolicyRefs in |policies|.
297OSStatus CreateTrustPolicies(const std::string& hostname, int flags,
298                             ScopedCFTypeRef<CFArrayRef>* policies) {
299  // Create an SSL SecPolicyRef, and configure it to perform hostname
300  // validation. The hostname check does 99% of what we want, with the
301  // exception of dotted IPv4 addreses, which we handle ourselves below.
302  CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = {
303    CSSM_APPLE_TP_SSL_OPTS_VERSION,
304    hostname.size(),
305    hostname.data(),
306    0
307  };
308  SecPolicyRef ssl_policy;
309  OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options,
310                                 sizeof(tp_ssl_options), &ssl_policy);
311  if (status)
312    return status;
313  ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy);
314
315  // Manually add OCSP and CRL policies. If neither an OCSP or CRL policy is
316  // specified, the Apple TP module will add whatever the system settings
317  // are, which is not desirable here.
318  //
319  // Note that this causes any locally configured OCSP responder URL to be
320  // ignored.
321  CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options;
322  memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options));
323  tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
324
325  CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options;
326  memset(&tp_crl_options, 0, sizeof(tp_crl_options));
327  tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
328
329  if (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) {
330    // If an OCSP responder is available, use it, and avoid fetching any
331    // CRLs for that certificate if possible, as they may be much larger.
332    tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT;
333    // Ensure that CRLs can be fetched if a crlDistributionPoint extension
334    // is found. Otherwise, only the local CRL cache will be consulted.
335    tp_crl_options.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET;
336  } else {
337    // Disable OCSP network fetching, but still permit cached OCSP responses
338    // to be used. This is equivalent to the Windows code's usage of
339    // CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY.
340    tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET;
341    // The default CrlFlags will ensure only cached CRLs are used.
342  }
343
344  SecPolicyRef ocsp_policy;
345  status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, &tp_ocsp_options,
346                        sizeof(tp_ocsp_options), &ocsp_policy);
347  if (status)
348    return status;
349  ScopedCFTypeRef<SecPolicyRef> scoped_ocsp_policy(ocsp_policy);
350
351  SecPolicyRef crl_policy;
352  status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options,
353                        sizeof(tp_crl_options), &crl_policy);
354  if (status)
355    return status;
356  ScopedCFTypeRef<SecPolicyRef> scoped_crl_policy(crl_policy);
357
358  CFTypeRef local_policies[] = { ssl_policy, ocsp_policy, crl_policy };
359  CFArrayRef policy_array = CFArrayCreate(kCFAllocatorDefault, local_policies,
360                                          arraysize(local_policies),
361                                          &kCFTypeArrayCallBacks);
362  if (!policy_array)
363    return memFullErr;
364
365  policies->reset(policy_array);
366  return noErr;
367}
368
369// Gets the issuer for a given cert, starting with the cert itself and
370// including the intermediate and finally root certificates (if any).
371// This function calls SecTrust but doesn't actually pay attention to the trust
372// result: it shouldn't be used to determine trust, just to traverse the chain.
373// Caller is responsible for releasing the value stored into *out_cert_chain.
374OSStatus CopyCertChain(SecCertificateRef cert_handle,
375                       CFArrayRef* out_cert_chain) {
376  DCHECK(cert_handle);
377  DCHECK(out_cert_chain);
378  // Create an SSL policy ref configured for client cert evaluation.
379  SecPolicyRef ssl_policy;
380  OSStatus result = X509Certificate::CreateSSLClientPolicy(&ssl_policy);
381  if (result)
382    return result;
383  ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy);
384
385  // Create a SecTrustRef.
386  ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate(
387      NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)),
388      1, &kCFTypeArrayCallBacks));
389  SecTrustRef trust_ref = NULL;
390  result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref);
391  if (result)
392    return result;
393  ScopedCFTypeRef<SecTrustRef> trust(trust_ref);
394
395  // Evaluate trust, which creates the cert chain.
396  SecTrustResultType status;
397  CSSM_TP_APPLE_EVIDENCE_INFO* status_chain;
398  result = SecTrustEvaluate(trust, &status);
399  if (result)
400    return result;
401  return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain);
402}
403
404// Returns true if |purpose| is listed as allowed in |usage|. This
405// function also considers the "Any" purpose. If the attribute is
406// present and empty, we return false.
407bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage,
408                            const CSSM_OID* purpose) {
409  for (unsigned p = 0; p < usage->numPurposes; ++p) {
410    if (CSSMOIDEqual(&usage->purposes[p], purpose))
411      return true;
412    if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny))
413      return true;
414  }
415  return false;
416}
417
418// Test that a given |cert_handle| is actually a valid X.509 certificate, and
419// return true if it is.
420//
421// On OS X, SecCertificateCreateFromData() does not return any errors if
422// called with invalid data, as long as data is present. The actual decoding
423// of the certificate does not happen until an API that requires a CSSM
424// handle is called. While SecCertificateGetCLHandle is the most likely
425// candidate, as it performs the parsing, it does not check whether the
426// parsing was actually successful. Instead, SecCertificateGetSubject is
427// used (supported since 10.3), as a means to check that the certificate
428// parsed as a valid X.509 certificate.
429bool IsValidOSCertHandle(SecCertificateRef cert_handle) {
430  const CSSM_X509_NAME* sanity_check = NULL;
431  OSStatus status = SecCertificateGetSubject(cert_handle, &sanity_check);
432  return status == noErr && sanity_check;
433}
434
435// Parses |data| of length |length|, attempting to decode it as the specified
436// |format|. If |data| is in the specified format, any certificates contained
437// within are stored into |output|.
438void AddCertificatesFromBytes(const char* data, size_t length,
439                              SecExternalFormat format,
440                              X509Certificate::OSCertHandles* output) {
441  SecExternalFormat input_format = format;
442  ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy(
443      kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length,
444      kCFAllocatorNull));
445
446  CFArrayRef items = NULL;
447  OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format,
448                                          NULL, 0, NULL, NULL, &items);
449  if (status) {
450    DLOG(WARNING) << status << " Unable to import items from data of length "
451                  << length;
452    return;
453  }
454
455  ScopedCFTypeRef<CFArrayRef> scoped_items(items);
456  CFTypeID cert_type_id = SecCertificateGetTypeID();
457
458  for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) {
459    SecKeychainItemRef item = reinterpret_cast<SecKeychainItemRef>(
460        const_cast<void*>(CFArrayGetValueAtIndex(items, i)));
461
462    // While inputFormat implies only certificates will be imported, if/when
463    // other formats (eg: PKCS#12) are supported, this may also include
464    // private keys or other items types, so filter appropriately.
465    if (CFGetTypeID(item) == cert_type_id) {
466      SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(item);
467      // OS X ignores |input_format| if it detects that |local_data| is PEM
468      // encoded, attempting to decode data based on internal rules for PEM
469      // block headers. If a PKCS#7 blob is encoded with a PEM block of
470      // CERTIFICATE, OS X 10.5 will return a single, invalid certificate
471      // based on the decoded data. If this happens, the certificate should
472      // not be included in |output|. Because |output| is empty,
473      // CreateCertificateListfromBytes will use PEMTokenizer to decode the
474      // data. When called again with the decoded data, OS X will honor
475      // |input_format|, causing decode to succeed. On OS X 10.6, the data
476      // is properly decoded as a PKCS#7, whether PEM or not, which avoids
477      // the need to fallback to internal decoding.
478      if (IsValidOSCertHandle(cert)) {
479        CFRetain(cert);
480        output->push_back(cert);
481      }
482    }
483  }
484}
485
486struct CSSMOIDString {
487  const CSSM_OID* oid_;
488  std::string string_;
489};
490
491typedef std::vector<CSSMOIDString> CSSMOIDStringVector;
492
493bool CERTNameToCSSMOIDVector(CERTName* name, CSSMOIDStringVector* out_values) {
494  struct OIDCSSMMap {
495    SECOidTag sec_OID_;
496    const CSSM_OID* cssm_OID_;
497  };
498
499  const OIDCSSMMap kOIDs[] = {
500      { SEC_OID_AVA_COMMON_NAME, &CSSMOID_CommonName },
501      { SEC_OID_AVA_COUNTRY_NAME, &CSSMOID_CountryName },
502      { SEC_OID_AVA_LOCALITY, &CSSMOID_LocalityName },
503      { SEC_OID_AVA_STATE_OR_PROVINCE, &CSSMOID_StateProvinceName },
504      { SEC_OID_AVA_STREET_ADDRESS, &CSSMOID_StreetAddress },
505      { SEC_OID_AVA_ORGANIZATION_NAME, &CSSMOID_OrganizationName },
506      { SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, &CSSMOID_OrganizationalUnitName },
507      { SEC_OID_AVA_DN_QUALIFIER, &CSSMOID_DNQualifier },
508      { SEC_OID_RFC1274_UID, &CSSMOID_UniqueIdentifier },
509      { SEC_OID_PKCS9_EMAIL_ADDRESS, &CSSMOID_EmailAddress },
510  };
511
512  CERTRDN** rdns = name->rdns;
513  for (size_t rdn = 0; rdns[rdn]; ++rdn) {
514    CERTAVA** avas = rdns[rdn]->avas;
515    for (size_t pair = 0; avas[pair] != 0; ++pair) {
516      SECOidTag tag = CERT_GetAVATag(avas[pair]);
517      if (tag == SEC_OID_UNKNOWN) {
518        return false;
519      }
520      CSSMOIDString oidString;
521      bool found_oid = false;
522      for (size_t oid = 0; oid < ARRAYSIZE_UNSAFE(kOIDs); ++oid) {
523        if (kOIDs[oid].sec_OID_ == tag) {
524          SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
525          if (!decode_item)
526            return false;
527
528          // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
529          std::string value(reinterpret_cast<char*>(decode_item->data),
530                            decode_item->len);
531          oidString.oid_ = kOIDs[oid].cssm_OID_;
532          oidString.string_ = value;
533          out_values->push_back(oidString);
534          SECITEM_FreeItem(decode_item, PR_TRUE);
535          found_oid = true;
536          break;
537        }
538      }
539      if (!found_oid) {
540        DLOG(ERROR) << "Unrecognized OID: " << tag;
541      }
542    }
543  }
544  return true;
545}
546
547class ScopedCertName {
548 public:
549  explicit ScopedCertName(CERTName* name) : name_(name) { }
550  ~ScopedCertName() {
551    if (name_) CERT_DestroyName(name_);
552  }
553  operator CERTName*() { return name_; }
554
555 private:
556  CERTName* name_;
557};
558
559class ScopedEncodedCertResults {
560 public:
561  explicit ScopedEncodedCertResults(CSSM_TP_RESULT_SET* results)
562      : results_(results) { }
563  ~ScopedEncodedCertResults() {
564    if (results_) {
565      CSSM_ENCODED_CERT* encCert =
566          reinterpret_cast<CSSM_ENCODED_CERT*>(results_->Results);
567      for (uint32 i = 0; i < results_->NumberOfResults; i++) {
568        crypto::CSSMFree(encCert[i].CertBlob.Data);
569      }
570    }
571    crypto::CSSMFree(results_->Results);
572    crypto::CSSMFree(results_);
573  }
574
575private:
576  CSSM_TP_RESULT_SET* results_;
577};
578
579void AppendPublicKeyHashes(CFArrayRef chain,
580                           std::vector<SHA1Fingerprint>* hashes) {
581  const CFIndex n = CFArrayGetCount(chain);
582  for (CFIndex i = 0; i < n; i++) {
583    SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
584        const_cast<void*>(CFArrayGetValueAtIndex(chain, i)));
585
586    CSSM_DATA cert_data;
587    OSStatus err = SecCertificateGetData(cert, &cert_data);
588    DCHECK_EQ(err, noErr);
589    base::StringPiece der_bytes(reinterpret_cast<const char*>(cert_data.Data),
590                               cert_data.Length);
591    base::StringPiece spki_bytes;
592    if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes))
593      continue;
594
595    SHA1Fingerprint hash;
596    CC_SHA1(spki_bytes.data(), spki_bytes.size(), hash.data);
597    hashes->push_back(hash);
598  }
599}
600
601}  // namespace
602
603void X509Certificate::Initialize() {
604  const CSSM_X509_NAME* name;
605  OSStatus status = SecCertificateGetSubject(cert_handle_, &name);
606  if (!status)
607    subject_.Parse(name);
608
609  status = SecCertificateGetIssuer(cert_handle_, &name);
610  if (!status)
611    issuer_.Parse(name);
612
613  GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore,
614                    &valid_start_);
615  GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter,
616                    &valid_expiry_);
617
618  fingerprint_ = CalculateFingerprint(cert_handle_);
619  serial_number_ = GetCertSerialNumber(cert_handle_);
620}
621
622// IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA
623// that we recognise as a standard root.
624// static
625bool X509Certificate::IsIssuedByKnownRoot(CFArrayRef chain) {
626  int n = CFArrayGetCount(chain);
627  if (n < 1)
628    return false;
629  SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>(
630      const_cast<void*>(CFArrayGetValueAtIndex(chain, n - 1)));
631  SHA1Fingerprint hash = X509Certificate::CalculateFingerprint(root_ref);
632  return IsSHA1HashInSortedArray(
633      hash, &kKnownRootCertSHA1Hashes[0][0], sizeof(kKnownRootCertSHA1Hashes));
634}
635
636// static
637X509Certificate* X509Certificate::CreateSelfSigned(
638    crypto::RSAPrivateKey* key,
639    const std::string& subject,
640    uint32 serial_number,
641    base::TimeDelta valid_duration) {
642  DCHECK(key);
643  DCHECK(!subject.empty());
644
645  if (valid_duration.InSeconds() > UINT32_MAX) {
646     LOG(ERROR) << "valid_duration too big" << valid_duration.InSeconds();
647     valid_duration = base::TimeDelta::FromSeconds(UINT32_MAX);
648  }
649
650  // There is a comment in
651  // http://www.opensource.apple.com/source/security_certtool/security_certtool-31828/src/CertTool.cpp
652  // that serial_numbers being passed into CSSM_TP_SubmitCredRequest can't have
653  // their high bit set. We will continue though and mask it out below.
654  if (serial_number & 0x80000000)
655    LOG(ERROR) << "serial_number has high bit set " << serial_number;
656
657  // NSS is used to parse the subject string into a set of
658  // CSSM_OID/string pairs. There doesn't appear to be a system routine for
659  // parsing Distinguished Name strings.
660  crypto::EnsureNSSInit();
661
662  CSSMOIDStringVector subject_name_oids;
663  ScopedCertName subject_name(
664      CERT_AsciiToName(const_cast<char*>(subject.c_str())));
665  if (!CERTNameToCSSMOIDVector(subject_name, &subject_name_oids)) {
666    DLOG(ERROR) << "Unable to generate CSSMOIDMap from " << subject;
667    return NULL;
668  }
669
670  // Convert the map of oid/string pairs into an array of
671  // CSSM_APPLE_TP_NAME_OIDs.
672  std::vector<CSSM_APPLE_TP_NAME_OID> cssm_subject_names;
673  for(CSSMOIDStringVector::iterator iter = subject_name_oids.begin();
674      iter != subject_name_oids.end(); ++iter) {
675    CSSM_APPLE_TP_NAME_OID cssm_subject_name;
676    cssm_subject_name.oid = iter->oid_;
677    cssm_subject_name.string = iter->string_.c_str();
678    cssm_subject_names.push_back(cssm_subject_name);
679  }
680
681  if (cssm_subject_names.empty()) {
682    DLOG(ERROR) << "cssm_subject_names.size() == 0. Input: " << subject;
683    return NULL;
684  }
685
686  // Set up a certificate request.
687  CSSM_APPLE_TP_CERT_REQUEST certReq;
688  memset(&certReq, 0, sizeof(certReq));
689  certReq.cspHand = crypto::GetSharedCSPHandle();
690  certReq.clHand = crypto::GetSharedCLHandle();
691    // See comment about serial numbers above.
692  certReq.serialNumber = serial_number & 0x7fffffff;
693  certReq.numSubjectNames = cssm_subject_names.size();
694  certReq.subjectNames = &cssm_subject_names[0];
695  certReq.numIssuerNames = 0; // Root.
696  certReq.issuerNames = NULL;
697  certReq.issuerNameX509 = NULL;
698  certReq.certPublicKey = key->public_key();
699  certReq.issuerPrivateKey = key->key();
700  // These are the Apple defaults.
701  certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA;
702  certReq.signatureOid = CSSMOID_SHA1WithRSA;
703  certReq.notBefore = 0;
704  certReq.notAfter = static_cast<uint32>(valid_duration.InSeconds());
705  certReq.numExtensions = 0;
706  certReq.extensions = NULL;
707  certReq.challengeString = NULL;
708
709  CSSM_TP_REQUEST_SET reqSet;
710  reqSet.NumberOfRequests = 1;
711  reqSet.Requests = &certReq;
712
713  CSSM_FIELD policyId;
714  memset(&policyId, 0, sizeof(policyId));
715  policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;
716
717  CSSM_TP_CALLERAUTH_CONTEXT callerAuthContext;
718  memset(&callerAuthContext, 0, sizeof(callerAuthContext));
719  callerAuthContext.Policy.NumberOfPolicyIds = 1;
720  callerAuthContext.Policy.PolicyIds = &policyId;
721
722  CSSM_TP_HANDLE tp_handle = crypto::GetSharedTPHandle();
723  CSSM_DATA refId;
724  memset(&refId, 0, sizeof(refId));
725  sint32 estTime;
726  CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tp_handle, NULL,
727      CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, &reqSet, &callerAuthContext,
728       &estTime, &refId);
729  if(crtn) {
730    DLOG(ERROR) << "CSSM_TP_SubmitCredRequest failed " << crtn;
731    return NULL;
732  }
733
734  CSSM_BOOL confirmRequired;
735  CSSM_TP_RESULT_SET *resultSet = NULL;
736  crtn = CSSM_TP_RetrieveCredResult(tp_handle, &refId, NULL, &estTime,
737                                    &confirmRequired, &resultSet);
738  ScopedEncodedCertResults scopedResults(resultSet);
739  crypto::CSSMFree(refId.Data);
740  if (crtn) {
741    DLOG(ERROR) << "CSSM_TP_RetrieveCredResult failed " << crtn;
742    return NULL;
743  }
744
745  if (confirmRequired) {
746    // Potential leak here of resultSet. |confirmRequired| should never be
747    // true.
748    DLOG(ERROR) << "CSSM_TP_RetrieveCredResult required confirmation";
749    return NULL;
750  }
751
752  if (resultSet->NumberOfResults != 1) {
753     DLOG(ERROR) << "Unexpected number of results: "
754                 << resultSet->NumberOfResults;
755    return NULL;
756  }
757
758  CSSM_ENCODED_CERT* encCert =
759      reinterpret_cast<CSSM_ENCODED_CERT*>(resultSet->Results);
760  base::mac::ScopedCFTypeRef<SecCertificateRef> scoped_cert;
761  SecCertificateRef certificate_ref = NULL;
762  OSStatus os_status =
763      SecCertificateCreateFromData(&encCert->CertBlob, encCert->CertType,
764                                   encCert->CertEncoding, &certificate_ref);
765  if (os_status != 0) {
766    DLOG(ERROR) << "SecCertificateCreateFromData failed: " << os_status;
767    return NULL;
768  }
769  scoped_cert.reset(certificate_ref);
770
771  return CreateFromHandle(
772     scoped_cert, X509Certificate::SOURCE_LONE_CERT_IMPORT,
773     X509Certificate::OSCertHandles());
774}
775
776void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
777  dns_names->clear();
778
779  GetCertGeneralNamesForOID(cert_handle_, CSSMOID_SubjectAltName, GNT_DNSName,
780                            dns_names);
781
782  if (dns_names->empty())
783    dns_names->push_back(subject_.common_name);
784}
785
786int X509Certificate::Verify(const std::string& hostname, int flags,
787                            CertVerifyResult* verify_result) const {
788  verify_result->Reset();
789
790  if (IsBlacklisted()) {
791    verify_result->cert_status |= CERT_STATUS_REVOKED;
792    return ERR_CERT_REVOKED;
793  }
794
795  ScopedCFTypeRef<CFArrayRef> trust_policies;
796  OSStatus status = CreateTrustPolicies(hostname, flags, &trust_policies);
797  if (status)
798    return NetErrorFromOSStatus(status);
799
800  // Create and configure a SecTrustRef, which takes our certificate(s)
801  // and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an
802  // array of certificates, the first of which is the certificate we're
803  // verifying, and the subsequent (optional) certificates are used for
804  // chain building.
805  CFMutableArrayRef cert_array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
806                                                      &kCFTypeArrayCallBacks);
807  if (!cert_array)
808    return ERR_OUT_OF_MEMORY;
809  ScopedCFTypeRef<CFArrayRef> scoped_cert_array(cert_array);
810  CFArrayAppendValue(cert_array, cert_handle_);
811  for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i)
812    CFArrayAppendValue(cert_array, intermediate_ca_certs_[i]);
813
814  // From here on, only one thread can be active at a time. We have had a number
815  // of sporadic crashes in the SecTrustEvaluate call below, way down inside
816  // Apple's cert code, which we suspect are caused by a thread-safety issue.
817  // So as a speculative fix allow only one thread to use SecTrust on this cert.
818  base::AutoLock lock(verification_lock_);
819
820  SecTrustRef trust_ref = NULL;
821  status = SecTrustCreateWithCertificates(cert_array, trust_policies,
822                                          &trust_ref);
823  if (status)
824    return NetErrorFromOSStatus(status);
825  ScopedCFTypeRef<SecTrustRef> scoped_trust_ref(trust_ref);
826
827  if (TestRootCerts::HasInstance()) {
828    status = TestRootCerts::GetInstance()->FixupSecTrustRef(trust_ref);
829    if (status)
830      return NetErrorFromOSStatus(status);
831  }
832
833  CSSM_APPLE_TP_ACTION_DATA tp_action_data;
834  memset(&tp_action_data, 0, sizeof(tp_action_data));
835  tp_action_data.Version = CSSM_APPLE_TP_ACTION_VERSION;
836  // Allow CSSM to download any missing intermediate certificates if an
837  // authorityInfoAccess extension or issuerAltName extension is present.
838  tp_action_data.ActionFlags = CSSM_TP_ACTION_FETCH_CERT_FROM_NET;
839
840  if (flags & VERIFY_REV_CHECKING_ENABLED) {
841    // Require a positive result from an OCSP responder or a CRL (or both)
842    // for every certificate in the chain. The Apple TP automatically
843    // excludes the self-signed root from this requirement. If a certificate
844    // is missing both a crlDistributionPoints extension and an
845    // authorityInfoAccess extension with an OCSP responder URL, then we
846    // will get a kSecTrustResultRecoverableTrustFailure back from
847    // SecTrustEvaluate(), with a
848    // CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK error code. In that case,
849    // we'll set our own result to include
850    // CERT_STATUS_NO_REVOCATION_MECHANISM. If one or both extensions are
851    // present, and a check fails (server unavailable, OCSP retry later,
852    // signature mismatch), then we'll set our own result to include
853    // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION.
854    tp_action_data.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT;
855    verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
856  } else {
857    // EV requires revocation checking.
858    // Note, under the hood, SecTrustEvaluate() will modify the OCSP options
859    // so as to attempt OCSP fetching if it believes a certificate may chain
860    // to an EV root. However, because network fetches are disabled in
861    // CreateTrustPolicies() when revocation checking is disabled, these
862    // will only go against the local cache.
863    flags &= ~VERIFY_EV_CERT;
864  }
865
866  CFDataRef action_data_ref =
867      CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
868                                  reinterpret_cast<UInt8*>(&tp_action_data),
869                                  sizeof(tp_action_data), kCFAllocatorNull);
870  if (!action_data_ref)
871    return ERR_OUT_OF_MEMORY;
872  ScopedCFTypeRef<CFDataRef> scoped_action_data_ref(action_data_ref);
873  status = SecTrustSetParameters(trust_ref, CSSM_TP_ACTION_DEFAULT,
874                                 action_data_ref);
875  if (status)
876    return NetErrorFromOSStatus(status);
877
878  // Verify the certificate. A non-zero result from SecTrustGetResult()
879  // indicates that some fatal error occurred and the chain couldn't be
880  // processed, not that the chain contains no errors. We need to examine the
881  // output of SecTrustGetResult() to determine that.
882  SecTrustResultType trust_result;
883  status = SecTrustEvaluate(trust_ref, &trust_result);
884  if (status)
885    return NetErrorFromOSStatus(status);
886  CFArrayRef completed_chain = NULL;
887  CSSM_TP_APPLE_EVIDENCE_INFO* chain_info;
888  status = SecTrustGetResult(trust_ref, &trust_result, &completed_chain,
889                             &chain_info);
890  if (status)
891    return NetErrorFromOSStatus(status);
892  ScopedCFTypeRef<CFArrayRef> scoped_completed_chain(completed_chain);
893
894  // Evaluate the results
895  OSStatus cssm_result;
896  bool got_certificate_error = false;
897  switch (trust_result) {
898    case kSecTrustResultUnspecified:
899    case kSecTrustResultProceed:
900      // Certificate chain is valid and trusted ("unspecified" indicates that
901      // the user has not explicitly set a trust setting)
902      break;
903
904    case kSecTrustResultDeny:
905    case kSecTrustResultConfirm:
906      // Certificate chain is explicitly untrusted. For kSecTrustResultConfirm,
907      // we're following what Secure Transport does and treating it as
908      // "deny".
909      verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
910      break;
911
912    case kSecTrustResultRecoverableTrustFailure:
913      // Certificate chain has a failure that can be overridden by the user.
914      status = SecTrustGetCssmResultCode(trust_ref, &cssm_result);
915      if (status)
916        return NetErrorFromOSStatus(status);
917      switch (cssm_result) {
918        case CSSMERR_TP_NOT_TRUSTED:
919        case CSSMERR_TP_INVALID_ANCHOR_CERT:
920          verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
921          break;
922        case CSSMERR_TP_CERT_EXPIRED:
923        case CSSMERR_TP_CERT_NOT_VALID_YET:
924          verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
925          break;
926        case CSSMERR_TP_CERT_REVOKED:
927        case CSSMERR_TP_CERT_SUSPENDED:
928          verify_result->cert_status |= CERT_STATUS_REVOKED;
929          break;
930        default:
931          // Look for specific per-certificate errors below.
932          break;
933      }
934      // Walk the chain of error codes in the CSSM_TP_APPLE_EVIDENCE_INFO
935      // structure which can catch multiple errors from each certificate.
936      for (CFIndex index = 0, chain_count = CFArrayGetCount(completed_chain);
937           index < chain_count; ++index) {
938        if (chain_info[index].StatusBits & CSSM_CERT_STATUS_EXPIRED ||
939            chain_info[index].StatusBits & CSSM_CERT_STATUS_NOT_VALID_YET)
940          verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
941        for (uint32 status_code_index = 0;
942             status_code_index < chain_info[index].NumStatusCodes;
943             ++status_code_index) {
944          got_certificate_error = true;
945          int cert_status = CertStatusFromOSStatus(
946              chain_info[index].StatusCodes[status_code_index]);
947          if (cert_status == CERT_STATUS_COMMON_NAME_INVALID) {
948            std::vector<std::string> names;
949            GetDNSNames(&names);
950            if (OverrideHostnameMismatch(hostname, &names))
951              cert_status = 0;
952          }
953          verify_result->cert_status |= cert_status;
954        }
955      }
956      // Be paranoid and ensure that we recorded at least one certificate
957      // status on receiving kSecTrustResultRecoverableTrustFailure. The
958      // call to SecTrustGetCssmResultCode() should pick up when the chain
959      // is not trusted and the loop through CSSM_TP_APPLE_EVIDENCE_INFO
960      // should pick up everything else, but let's be safe.
961      if (!verify_result->cert_status && !got_certificate_error) {
962        verify_result->cert_status |= CERT_STATUS_INVALID;
963        NOTREACHED();
964      }
965      break;
966
967    default:
968      status = SecTrustGetCssmResultCode(trust_ref, &cssm_result);
969      if (status)
970        return NetErrorFromOSStatus(status);
971      verify_result->cert_status |= CertStatusFromOSStatus(cssm_result);
972      if (!verify_result->cert_status)
973        verify_result->cert_status |= CERT_STATUS_INVALID;
974      break;
975  }
976
977  // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be
978  // compatible with Windows, which in turn implements this behavior to be
979  // compatible with WinHTTP, which doesn't report this error (bug 3004).
980  verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM;
981
982  if (IsCertStatusError(verify_result->cert_status))
983    return MapCertStatusToNetError(verify_result->cert_status);
984
985  if (flags & VERIFY_EV_CERT) {
986    // Determine the certificate's EV status using SecTrustCopyExtendedResult(),
987    // which we need to look up because the function wasn't added until
988    // Mac OS X 10.5.7.
989    // Note: "ExtendedResult" means extended validation results.
990    CFBundleRef bundle =
991        CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"));
992    if (bundle) {
993      SecTrustCopyExtendedResultFuncPtr copy_extended_result =
994          reinterpret_cast<SecTrustCopyExtendedResultFuncPtr>(
995              CFBundleGetFunctionPointerForName(bundle,
996                  CFSTR("SecTrustCopyExtendedResult")));
997      if (copy_extended_result) {
998        CFDictionaryRef ev_dict = NULL;
999        status = copy_extended_result(trust_ref, &ev_dict);
1000        if (!status && ev_dict) {
1001          // The returned dictionary contains the EV organization name from the
1002          // server certificate, which we don't need at this point (and we
1003          // have other ways to access, anyway). All we care is that
1004          // SecTrustCopyExtendedResult() returned noErr and a non-NULL
1005          // dictionary.
1006          CFRelease(ev_dict);
1007          verify_result->cert_status |= CERT_STATUS_IS_EV;
1008        }
1009      }
1010    }
1011  }
1012
1013  AppendPublicKeyHashes(completed_chain, &verify_result->public_key_hashes);
1014  verify_result->is_issued_by_known_root = IsIssuedByKnownRoot(completed_chain);
1015
1016  if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) {
1017    verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
1018    return MapCertStatusToNetError(verify_result->cert_status);
1019  }
1020
1021  return OK;
1022}
1023
1024bool X509Certificate::GetDEREncoded(std::string* encoded) {
1025  encoded->clear();
1026  CSSM_DATA der_data;
1027  if(SecCertificateGetData(cert_handle_, &der_data) == noErr) {
1028    encoded->append(reinterpret_cast<char*>(der_data.Data),
1029                    der_data.Length);
1030    return true;
1031  }
1032  return false;
1033}
1034
1035bool X509Certificate::VerifyEV() const {
1036  // We don't call this private method, but we do need to implement it because
1037  // it's defined in x509_certificate.h. We perform EV checking in the
1038  // Verify() above.
1039  NOTREACHED();
1040  return false;
1041}
1042
1043// static
1044bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
1045                                   X509Certificate::OSCertHandle b) {
1046  DCHECK(a && b);
1047  if (a == b)
1048    return true;
1049  if (CFEqual(a, b))
1050    return true;
1051  CSSM_DATA a_data, b_data;
1052  return SecCertificateGetData(a, &a_data) == noErr &&
1053      SecCertificateGetData(b, &b_data) == noErr &&
1054      a_data.Length == b_data.Length &&
1055      memcmp(a_data.Data, b_data.Data, a_data.Length) == 0;
1056}
1057
1058// static
1059X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
1060    const char* data, int length) {
1061  CSSM_DATA cert_data;
1062  cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data));
1063  cert_data.Length = length;
1064
1065  OSCertHandle cert_handle = NULL;
1066  OSStatus status = SecCertificateCreateFromData(&cert_data,
1067                                                 CSSM_CERT_X_509v3,
1068                                                 CSSM_CERT_ENCODING_DER,
1069                                                 &cert_handle);
1070  if (status != noErr)
1071    return NULL;
1072  if (!IsValidOSCertHandle(cert_handle)) {
1073    CFRelease(cert_handle);
1074    return NULL;
1075  }
1076  return cert_handle;
1077}
1078
1079// static
1080X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
1081    const char* data, int length, Format format) {
1082  OSCertHandles results;
1083
1084  switch (format) {
1085    case FORMAT_SINGLE_CERTIFICATE: {
1086      OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
1087      if (handle)
1088        results.push_back(handle);
1089      break;
1090    }
1091    case FORMAT_PKCS7:
1092      AddCertificatesFromBytes(data, length, kSecFormatPKCS7, &results);
1093      break;
1094    default:
1095      NOTREACHED() << "Certificate format " << format << " unimplemented";
1096      break;
1097  }
1098
1099  return results;
1100}
1101
1102// static
1103X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
1104    OSCertHandle handle) {
1105  if (!handle)
1106    return NULL;
1107  return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle)));
1108}
1109
1110// static
1111void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
1112  CFRelease(cert_handle);
1113}
1114
1115// static
1116SHA1Fingerprint X509Certificate::CalculateFingerprint(
1117    OSCertHandle cert) {
1118  SHA1Fingerprint sha1;
1119  memset(sha1.data, 0, sizeof(sha1.data));
1120
1121  CSSM_DATA cert_data;
1122  OSStatus status = SecCertificateGetData(cert, &cert_data);
1123  if (status)
1124    return sha1;
1125
1126  DCHECK(cert_data.Data);
1127  DCHECK_NE(cert_data.Length, 0U);
1128
1129  CC_SHA1(cert_data.Data, cert_data.Length, sha1.data);
1130
1131  return sha1;
1132}
1133
1134bool X509Certificate::SupportsSSLClientAuth() const {
1135  CSSMFields fields;
1136  if (GetCertFields(cert_handle_, &fields) != noErr)
1137    return false;
1138
1139  // Gather the extensions we care about. We do not support
1140  // CSSMOID_NetscapeCertType on OS X.
1141  const CE_ExtendedKeyUsage* ext_key_usage = NULL;
1142  const CE_KeyUsage* key_usage = NULL;
1143  for (unsigned f = 0; f < fields.num_of_fields; ++f) {
1144    const CSSM_FIELD& field = fields.fields[f];
1145    const CSSM_X509_EXTENSION* ext =
1146        reinterpret_cast<const CSSM_X509_EXTENSION*>(field.FieldValue.Data);
1147    if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_KeyUsage)) {
1148      key_usage = reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue);
1149    } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) {
1150      ext_key_usage =
1151          reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue);
1152    }
1153  }
1154
1155  // RFC5280 says to take the intersection of the two extensions.
1156  //
1157  // Our underlying crypto libraries don't expose
1158  // ClientCertificateType, so for now we will not support fixed
1159  // Diffie-Hellman mechanisms. For rsa_sign, we need the
1160  // digitalSignature bit.
1161  //
1162  // In particular, if a key has the nonRepudiation bit and not the
1163  // digitalSignature one, we will not offer it to the user.
1164  if (key_usage && !((*key_usage) & CE_KU_DigitalSignature))
1165    return false;
1166  if (ext_key_usage && !ExtendedKeyUsageAllows(ext_key_usage,
1167                                               &CSSMOID_ClientAuth))
1168    return false;
1169  return true;
1170}
1171
1172bool X509Certificate::IsIssuedBy(
1173    const std::vector<CertPrincipal>& valid_issuers) {
1174  // Get the cert's issuer chain.
1175  CFArrayRef cert_chain = NULL;
1176  OSStatus result;
1177  result = CopyCertChain(os_cert_handle(), &cert_chain);
1178  if (result)
1179    return false;
1180  ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain);
1181
1182  // Check all the certs in the chain for a match.
1183  int n = CFArrayGetCount(cert_chain);
1184  for (int i = 0; i < n; ++i) {
1185    SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>(
1186        const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
1187    scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle(
1188        cert_handle,
1189        X509Certificate::SOURCE_LONE_CERT_IMPORT,
1190        X509Certificate::OSCertHandles()));
1191    for (unsigned j = 0; j < valid_issuers.size(); j++) {
1192      if (cert->issuer().Matches(valid_issuers[j]))
1193        return true;
1194    }
1195  }
1196  return false;
1197}
1198
1199// static
1200OSStatus X509Certificate::CreateSSLClientPolicy(SecPolicyRef* out_policy) {
1201  CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = {
1202    CSSM_APPLE_TP_SSL_OPTS_VERSION,
1203    0,
1204    NULL,
1205    CSSM_APPLE_TP_SSL_CLIENT
1206  };
1207  return CreatePolicy(&CSSMOID_APPLE_TP_SSL,
1208                      &tp_ssl_options,
1209                      sizeof(tp_ssl_options),
1210                      out_policy);
1211}
1212
1213// static
1214bool X509Certificate::GetSSLClientCertificates(
1215    const std::string& server_domain,
1216    const std::vector<CertPrincipal>& valid_issuers,
1217    CertificateList* certs) {
1218  ScopedCFTypeRef<SecIdentityRef> preferred_identity;
1219  if (!server_domain.empty()) {
1220    // See if there's an identity preference for this domain:
1221    ScopedCFTypeRef<CFStringRef> domain_str(
1222        base::SysUTF8ToCFStringRef("https://" + server_domain));
1223    SecIdentityRef identity = NULL;
1224    // While SecIdentityCopyPreferences appears to take a list of CA issuers
1225    // to restrict the identity search to, within Security.framework the
1226    // argument is ignored and filtering unimplemented. See
1227    // SecIdentity.cpp in libsecurity_keychain, specifically
1228    // _SecIdentityCopyPreferenceMatchingName().
1229    if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr)
1230      preferred_identity.reset(identity);
1231  }
1232
1233  // Now enumerate the identities in the available keychains.
1234  SecIdentitySearchRef search = nil;
1235  OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search);
1236  ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search);
1237  while (!err) {
1238    SecIdentityRef identity = NULL;
1239    err = SecIdentitySearchCopyNext(search, &identity);
1240    if (err)
1241      break;
1242    ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity);
1243
1244    SecCertificateRef cert_handle;
1245    err = SecIdentityCopyCertificate(identity, &cert_handle);
1246    if (err != noErr)
1247      continue;
1248    ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle);
1249
1250    scoped_refptr<X509Certificate> cert(
1251        CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT,
1252                         OSCertHandles()));
1253    if (cert->HasExpired() || !cert->SupportsSSLClientAuth())
1254      continue;
1255
1256    // Skip duplicates (a cert may be in multiple keychains).
1257    const SHA1Fingerprint& fingerprint = cert->fingerprint();
1258    unsigned i;
1259    for (i = 0; i < certs->size(); ++i) {
1260      if ((*certs)[i]->fingerprint().Equals(fingerprint))
1261        break;
1262    }
1263    if (i < certs->size())
1264      continue;
1265
1266    bool is_preferred = preferred_identity &&
1267        CFEqual(preferred_identity, identity);
1268
1269    // Make sure the issuer matches valid_issuers, if given.
1270    // But an explicit cert preference overrides this.
1271    if (!is_preferred &&
1272        !valid_issuers.empty() &&
1273        !cert->IsIssuedBy(valid_issuers))
1274      continue;
1275
1276    // The cert passes, so add it to the vector.
1277    // If it's the preferred identity, add it at the start (so it'll be
1278    // selected by default in the UI.)
1279    if (is_preferred)
1280      certs->insert(certs->begin(), cert);
1281    else
1282      certs->push_back(cert);
1283  }
1284
1285  if (err != errSecItemNotFound) {
1286    LOG(ERROR) << "SecIdentitySearch error " << err;
1287    return false;
1288  }
1289  return true;
1290}
1291
1292CFArrayRef X509Certificate::CreateClientCertificateChain() const {
1293  // Initialize the result array with just the IdentityRef of the receiver:
1294  OSStatus result;
1295  SecIdentityRef identity;
1296  result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity);
1297  if (result) {
1298    LOG(ERROR) << "SecIdentityCreateWithCertificate error " << result;
1299    return NULL;
1300  }
1301  ScopedCFTypeRef<CFMutableArrayRef> chain(
1302      CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks));
1303  CFArrayAppendValue(chain, identity);
1304
1305  CFArrayRef cert_chain = NULL;
1306  result = CopyCertChain(cert_handle_, &cert_chain);
1307  ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain);
1308  if (result) {
1309    LOG(ERROR) << "CreateIdentityCertificateChain error " << result;
1310    return chain.release();
1311  }
1312
1313  // Append the intermediate certs from SecTrust to the result array:
1314  if (cert_chain) {
1315    int chain_count = CFArrayGetCount(cert_chain);
1316    if (chain_count > 1) {
1317      CFArrayAppendArray(chain,
1318                         cert_chain,
1319                         CFRangeMake(1, chain_count - 1));
1320    }
1321  }
1322
1323  return chain.release();
1324}
1325
1326// static
1327X509Certificate::OSCertHandle
1328X509Certificate::ReadCertHandleFromPickle(const Pickle& pickle,
1329                                          void** pickle_iter) {
1330  const char* data;
1331  int length;
1332  if (!pickle.ReadData(pickle_iter, &data, &length))
1333    return NULL;
1334
1335  return CreateOSCertHandleFromBytes(data, length);
1336}
1337
1338// static
1339bool X509Certificate::WriteCertHandleToPickle(OSCertHandle cert_handle,
1340                                              Pickle* pickle) {
1341  CSSM_DATA cert_data;
1342  OSStatus status = SecCertificateGetData(cert_handle, &cert_data);
1343  if (status)
1344    return false;
1345
1346  return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data),
1347                           cert_data.Length);
1348}
1349
1350}  // namespace net
1351