15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 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_util_mac.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/apple_apsl/cssmapplePriv.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace x509_util {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a SecPolicyRef for the given OID, with optional value.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSStatus CreatePolicy(const CSSM_OID* policy_oid,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      void* option_data,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      size_t option_length,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      SecPolicyRef* policy) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SecPolicySearchRef search;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSStatus err = SecPolicySearchCreate(CSSM_CERT_X_509v3, policy_oid, NULL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &search);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return err;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  err = SecPolicySearchCopyNext(search, policy);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFRelease(search);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (err)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return err;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (option_data) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSSM_DATA options_data = {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      option_length,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<uint8_t*>(option_data)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    err = SecPolicySetValue(*policy, &options_data);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (err) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CFRelease(*policy);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return err;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return noErr;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSStatus CreateSSLClientPolicy(SecPolicyRef* policy) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&tp_ssl_options, 0, sizeof(tp_ssl_options));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tp_ssl_options.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tp_ssl_options.Flags |= CSSM_APPLE_TP_SSL_CLIENT;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      sizeof(tp_ssl_options), policy);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSStatus CreateSSLServerPolicy(const std::string& hostname,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               SecPolicyRef* policy) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&tp_ssl_options, 0, sizeof(tp_ssl_options));
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tp_ssl_options.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!hostname.empty()) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tp_ssl_options.ServerName = hostname.data();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tp_ssl_options.ServerNameLen = hostname.size();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      sizeof(tp_ssl_options), policy);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSStatus CreateBasicX509Policy(SecPolicyRef* policy) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreatePolicy(&CSSMOID_APPLE_X509_BASIC, NULL, 0, policy);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSStatus CreateRevocationPolicies(bool enable_revocation_checking,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool enable_ev_checking,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  CFMutableArrayRef policies) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSStatus status = noErr;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In order to bypass the system revocation checking settings, the
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SecTrustRef must have at least one revocation policy associated with it.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since it is not known prior to verification whether the Apple TP will
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // consider a certificate as an EV candidate, the default policy used is a
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CRL policy, since it does not communicate over the network.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the TP believes the leaf is an EV cert, it will explicitly add an
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OCSP policy to perform the online checking, and if it doesn't believe
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that the leaf is EV, then the default CRL policy will effectively no-op.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This behaviour is used to implement EV-only revocation checking.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enable_ev_checking || enable_revocation_checking) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&tp_crl_options, 0, sizeof(tp_crl_options));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only allow network CRL fetches if the caller explicitly requests
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // online revocation checking. Note that, as of OS X 10.7.2, the system
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // will set force this flag on according to system policies, so
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // online revocation checks cannot be completely disabled.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (enable_revocation_checking)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tp_crl_options.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SecPolicyRef crl_policy;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          sizeof(tp_crl_options), &crl_policy);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (status)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return status;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CFArrayAppendValue(policies, crl_policy);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CFRelease(crl_policy);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If revocation checking is explicitly enabled, then add an OCSP policy
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and allow network access. If both revocation checking and EV checking
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are disabled, then the added OCSP policy will be prevented from
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // accessing the network. This is done because the TP will force an OCSP
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // policy to be present when it believes the certificate is EV. If network
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fetching was not explicitly disabled, then it would be as if
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // enable_ev_checking was always set to true.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enable_revocation_checking || !enable_ev_checking) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (enable_revocation_checking) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The default for the OCSP policy is to fetch responses via the network,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // unlike the CRL policy default. The policy is further modified to
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // prefer OCSP over CRLs, if both are specified on the certificate. This
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // is because an OCSP response is both sufficient and typically
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // significantly smaller than the CRL counterpart.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Effectively disable OCSP checking by making it impossible to get an
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // OCSP response. Even if the Apple TP forces OCSP, no checking will
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // be able to succeed. If this happens, the Apple TP will report an error
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // that OCSP was unavailable, but this will be handled and suppressed in
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // X509Certificate::Verify().
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET |
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SecPolicyRef ocsp_policy;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, &tp_ocsp_options,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          sizeof(tp_ocsp_options), &ocsp_policy);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (status)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return status;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CFArrayAppendValue(policies, ocsp_policy);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CFRelease(ocsp_policy);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return status;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CSSMFieldValue::CSSMFieldValue()
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : cl_handle_(CSSM_INVALID_HANDLE),
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      oid_(NULL),
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_(NULL) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CSSMFieldValue::CSSMFieldValue(CSSM_CL_HANDLE cl_handle,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const CSSM_OID* oid,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               CSSM_DATA_PTR field)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : cl_handle_(cl_handle),
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      oid_(const_cast<CSSM_OID_PTR>(oid)),
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      field_(field) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CSSMFieldValue::~CSSMFieldValue() {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset(CSSM_INVALID_HANDLE, NULL, NULL);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CSSMFieldValue::Reset(CSSM_CL_HANDLE cl_handle,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           CSSM_OID_PTR oid,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           CSSM_DATA_PTR field) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl_handle_ && oid_ && field_)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSSM_CL_FreeFieldValue(cl_handle_, oid_, field_);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cl_handle_ = cl_handle;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  oid_ = oid;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  field_ = field;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CSSMCachedCertificate::CSSMCachedCertificate()
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : cl_handle_(CSSM_INVALID_HANDLE),
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cached_cert_handle_(CSSM_INVALID_HANDLE) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CSSMCachedCertificate::~CSSMCachedCertificate() {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl_handle_ && cached_cert_handle_)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CSSM_CL_CertAbortCache(cl_handle_, cached_cert_handle_);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSStatus CSSMCachedCertificate::Init(SecCertificateRef os_cert_handle) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!cl_handle_ && !cached_cert_handle_);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(os_cert_handle);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_DATA cert_data;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSStatus status = SecCertificateGetData(os_cert_handle, &cert_data);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status = SecCertificateGetCLHandle(os_cert_handle, &cl_handle_);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!cl_handle_);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status = CSSM_CL_CertCache(cl_handle_, &cert_data, &cached_cert_handle_);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!cached_cert_handle_);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return status;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OSStatus CSSMCachedCertificate::GetField(const CSSM_OID* field_oid,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         CSSMFieldValue* field) const {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(cl_handle_);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(cached_cert_handle_);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_OID_PTR oid = const_cast<CSSM_OID_PTR>(field_oid);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_DATA_PTR field_ptr = NULL;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_HANDLE results_handle = CSSM_INVALID_HANDLE;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 field_value_count = 0;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_RETURN status = CSSM_CL_CertGetFirstCachedFieldValue(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cl_handle_, cached_cert_handle_, oid, &results_handle,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &field_value_count, &field_ptr);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (status)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: |field_value_count| may be > 1, indicating that more than one
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value is present. This may happen with extensions, but for current
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // usages, only the first value is returned.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CSSM_CL_CertAbortQuery(cl_handle_, results_handle);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  field->Reset(cl_handle_, oid, field_ptr);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CSSM_OK;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace x509_util
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
232