/ OSX / libsecurity_keychain / lib / SecCertificate.cpp
SecCertificate.cpp
   1  /*
   2   * Copyright (c) 2002-2016 Apple Inc. All Rights Reserved.
   3   *
   4   * @APPLE_LICENSE_HEADER_START@
   5   *
   6   * This file contains Original Code and/or Modifications of Original Code
   7   * as defined in and that are subject to the Apple Public Source License
   8   * Version 2.0 (the 'License'). You may not use this file except in
   9   * compliance with the License. Please obtain a copy of the License at
  10   * http://www.opensource.apple.com/apsl/ and read it before using this
  11   * file.
  12   *
  13   * The Original Code and all software distributed under the License are
  14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  18   * Please see the License for the specific language governing rights and
  19   * limitations under the License.
  20   *
  21   * @APPLE_LICENSE_HEADER_END@
  22   */
  23  
  24  #include <Security/SecCertificate.h>
  25  #include <Security/SecCertificatePriv.h>
  26  #include <security_keychain/Certificate.h>
  27  #include <security_keychain/Item.h>
  28  #include <security_keychain/KCCursor.h>
  29  #include <Security/cssmapi.h>
  30  #include <Security/cssmapple.h>
  31  #include <security_cdsa_client/cspclient.h>
  32  #include <security_cdsa_client/clclient.h>
  33  #include <security_cdsa_client/tpclient.h>
  34  #include <Security/cssmtype.h>
  35  
  36  #include "SecBridge.h"
  37  
  38  // %%% used by SecCertificate{Copy,Set}Preference
  39  #include <Security/SecKeychainItemPriv.h>
  40  #include <Security/SecIdentityPriv.h>
  41  #include <Security/SecItemPriv.h>
  42  #include <security_keychain/KCCursor.h>
  43  #include <security_cdsa_utilities/Schema.h>
  44  #include <security_cdsa_utils/cuCdsaUtils.h>
  45  #include <sys/param.h>
  46  #include <syslog.h>
  47  #include "CertificateValues.h"
  48  #include "LegacyAPICounts.h"
  49  
  50  OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle);
  51  extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage);
  52  
  53  
  54  
  55  
  56  using namespace CssmClient;
  57  
  58  CFTypeID static SecCertificateGetTypeID_osx(void)
  59  {
  60  	BEGIN_SECAPI
  61  
  62  	return gTypes().Certificate.typeID;
  63  
  64  	END_SECAPI1(_kCFRuntimeNotATypeID)
  65  }
  66  
  67  Boolean
  68  SecCertificateIsItemImplInstance(SecCertificateRef certificate)
  69  {
  70      if (certificate == NULL) {
  71          return false;
  72      }
  73  
  74      CFTypeID typeID = CFGetTypeID(certificate);
  75  
  76  	if (typeID == _kCFRuntimeNotATypeID) {
  77  		return false;
  78  	}
  79  
  80      return (typeID == SecCertificateGetTypeID_osx() ||
  81              typeID == SecKeychainItemGetTypeID()) ? true : false;
  82  }
  83  
  84  /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */
  85  SecCertificateRef
  86  SecCertificateCreateItemImplInstance(SecCertificateRef certificate)
  87  {
  88  	if (!certificate) {
  89  		return NULL;
  90  	}
  91  	SecCertificateRef implCertRef = (SecCertificateRef) SecCertificateCopyKeychainItem(certificate);
  92  	if (implCertRef) {
  93  		return implCertRef;
  94  	}
  95  	CFDataRef data = SecCertificateCopyData(certificate);
  96  	if (!data) {
  97  		return NULL;
  98  	}
  99  	try {
 100  		CSSM_DATA cssmCertData;
 101  		cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0;
 102  		cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL;
 103  
 104  		SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
 105  		implCertRef = certificatePtr->handle();
 106  	}
 107  	catch (...) {}
 108  	CFRelease(data);
 109  	return implCertRef;
 110  }
 111  
 112  /* convert an old-world ItemImpl instance to a new-world SecCertificateRef */
 113  SecCertificateRef
 114  SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate)
 115  {
 116  	if (!certificate) {
 117  		return NULL;
 118  	}
 119  	SecCertificateRef result = NULL;
 120  	CFDataRef data = NULL;
 121  	try {
 122  		CssmData certData = Certificate::required(certificate)->data();
 123  		if (certData.Data && certData.Length) {
 124  			data = CFDataCreate(NULL, certData.Data, certData.Length);
 125  		}
 126  		if (!data) {
 127  			if (certData.Data && !certData.Length) {
 128  				/* zero-length certs can exist, so don't bother logging this */
 129  			}
 130  			else {
 131  				syslog(LOG_ERR, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)",
 132  						(long)certData.Length, (uintptr_t)certData.Data);
 133  			}
 134  			return NULL;
 135  		}
 136  	}
 137  	catch (...) {}
 138  
 139  	result = SecCertificateCreateWithKeychainItem(NULL, data, certificate);
 140  	if (data)
 141  		CFRelease(data);
 142  	return result;
 143  }
 144  
 145  
 146  /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
 147  OSStatus
 148  SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate)
 149  {
 150  	/* bridge to support old functionality */
 151  	if (!data || !data->Data || !data->Length || !certificate) {
 152  		return errSecParam;
 153  	}
 154  	SecCertificateRef certRef = NULL;
 155  
 156      // <rdar://problem/24403998> REG: Adobe {Photoshop, InDesign} CC(2015) crashes on launch
 157      // If you take the length that SecKeychainItemCopyContent gives you (a Uint32) and assign it incorrectly
 158      // to a CSSM_DATA Length field (a CSSM_SIZE, i.e., a size_t), the upper 32 bits aren't set. If those bits
 159      // are non-zero, the length is incredibly wrong.
 160      //
 161      // Assume that there will not exist a certificate > 4GiB, and fake this length field.
 162      CSSM_SIZE length = data->Length & 0xfffffffful;
 163  
 164  	CFDataRef dataRef = CFDataCreate(NULL, data->Data, length);
 165  	if (dataRef) {
 166  		certRef = SecCertificateCreateWithData(NULL, dataRef);
 167  		CFRelease(dataRef);
 168  	}
 169  	*certificate = certRef;
 170  	return (certRef) ? errSecSuccess : errSecUnknownFormat;
 171  }
 172  
 173  /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
 174  OSStatus
 175  SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain)
 176  {
 177  	// This macro creates an ItemImpl certificate if it does not exist
 178  	BEGIN_SECCERTAPI
 179  
 180  	Item item(Certificate::required(__itemImplRef));
 181  	Keychain::optional(keychain)->add(item);
 182  
 183  	END_SECCERTAPI
 184  }
 185  
 186  /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
 187  OSStatus
 188  SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data)
 189  {
 190  	BEGIN_SECCERTAPI
 191  
 192  	if (!certificate || !data) {
 193  		__secapiresult=errSecParam;
 194  	}
 195  	else if (SecCertificateIsItemImplInstance(certificate)) {
 196  		Required(data) = Certificate::required(certificate)->data();
 197  	}
 198  	else {
 199  		data->Length = (CSSM_SIZE)SecCertificateGetLength(certificate);
 200  		data->Data = (uint8*)SecCertificateGetBytePtr(certificate);
 201  	}
 202  
 203  	END_SECCERTAPI
 204  }
 205  
 206  /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
 207  OSStatus
 208  SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType)
 209  {
 210      // This macro creates an ItemImpl certificate if it does not exist
 211      BEGIN_SECCERTAPI
 212  
 213      Required(certificateType) = Certificate::required(__itemImplRef)->type();
 214  
 215      END_SECCERTAPI
 216  }
 217  
 218  /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
 219  OSStatus
 220  SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject)
 221  {
 222      // This macro creates an ItemImpl certificate if it does not exist
 223      BEGIN_SECCERTAPI
 224  
 225      Required(subject) = Certificate::required(__itemImplRef)->subjectName();
 226  
 227      END_SECCERTAPI
 228  }
 229  
 230  /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
 231  OSStatus
 232  SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer)
 233  {
 234      // This macro creates an ItemImpl certificate if it does not exist
 235      BEGIN_SECCERTAPI
 236  
 237      Required(issuer) = Certificate::required(__itemImplRef)->issuerName();
 238  
 239      END_SECCERTAPI
 240  }
 241  
 242  /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
 243  OSStatus
 244  SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
 245  {
 246      // This macro creates an ItemImpl certificate if it does not exist
 247      BEGIN_SECCERTAPI
 248  
 249      Required(clHandle) = Certificate::required(__itemImplRef)->clHandle();
 250  
 251      END_SECCERTAPI
 252  }
 253  
 254  /* private function; assumes input is old-style ItemImpl certificate reference,
 255     and does not release that certificate reference!
 256   */
 257  OSStatus
 258  SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
 259  {
 260      BEGIN_SECAPI
 261  
 262      Required(clHandle) = Certificate::required(certificate)->clHandle();
 263  
 264      END_SECAPI
 265  }
 266  
 267  /*
 268   * Private API to infer a display name for a SecCertificateRef which
 269   * may or may not be in a keychain.
 270   *
 271   * OS X only
 272   */
 273  OSStatus
 274  SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label)
 275  {
 276      // This macro creates an ItemImpl certificate if it does not exist
 277      BEGIN_SECCERTAPI
 278  
 279      Certificate::required(__itemImplRef)->inferLabel(false, &Required(label));
 280  
 281      END_SECCERTAPI
 282  }
 283  
 284  /* OS X only (note: iOS version has different arguments and return value) */
 285  OSStatus
 286  SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key)
 287  {
 288      // This macro creates an ItemImpl certificate if it does not exist
 289      BEGIN_SECCERTAPI
 290  
 291      Required(key) = Certificate::required(__itemImplRef)->publicKey()->handle();
 292  
 293      END_SECCERTAPI
 294  }
 295  
 296  /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
 297  OSStatus
 298  SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid)
 299  {
 300      // This macro creates an ItemImpl certificate if it does not exist
 301      BEGIN_SECCERTAPI
 302  
 303      Required(algid) = Certificate::required(__itemImplRef)->algorithmID();
 304  
 305      END_SECCERTAPI
 306  }
 307  
 308  /* OS X only */
 309  OSStatus
 310  SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result)
 311  {
 312      // This macro creates an ItemImpl certificate if it does not exist
 313      BEGIN_SECCERTAPI
 314  
 315      Required(result) = Certificate::required(__itemImplRef)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component);
 316  
 317      END_SECCERTAPI
 318  }
 319  
 320  /* OS X only; deprecated SPI */
 321  OSStatus
 322  SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName)
 323  {
 324      // deprecated SPI signature; replaced by SecCertificateCopyCommonName
 325      return SecCertificateCopyCommonName(certificate, commonName);
 326  }
 327  
 328  /* OS X only; deprecated SPI */
 329  OSStatus
 330  SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress)
 331  {
 332      // This macro creates an ItemImpl certificate if it does not exist
 333      BEGIN_SECCERTAPI
 334  
 335      Required(emailAddress) = Certificate::required(__itemImplRef)->copyFirstEmailAddress();
 336  
 337      END_SECCERTAPI
 338  }
 339  
 340  /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field.
 341   * Caller must call releaseFieldValues to free the storage allocated by this call.
 342   *
 343   * OS X only
 344   */
 345  OSStatus
 346  SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues)
 347  {
 348      // This macro creates an ItemImpl certificate if it does not exist
 349      BEGIN_SECCERTAPI
 350  
 351      Required(fieldValues) = Certificate::required(__itemImplRef)->copyFieldValues(Required(field));
 352  
 353      END_SECCERTAPI
 354  }
 355  
 356  /* OS X only */
 357  OSStatus
 358  SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues)
 359  {
 360      // This macro creates an ItemImpl certificate if it does not exist
 361      BEGIN_SECCERTAPI
 362  
 363      Certificate::required(__itemImplRef)->releaseFieldValues(Required(field), fieldValues);
 364  
 365      END_SECCERTAPI
 366  }
 367  
 368  /* OS X only */
 369  OSStatus
 370  SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue)
 371  {
 372      // This macro creates an ItemImpl certificate if it does not exist
 373      BEGIN_SECCERTAPI
 374  
 375      Required(fieldValue) = Certificate::required(__itemImplRef)->copyFirstFieldValue(Required(field));
 376  
 377      END_SECCERTAPI
 378  }
 379  
 380  /* OS X only */
 381  OSStatus
 382  SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue)
 383  {
 384      // This macro creates an ItemImpl certificate if it does not exist
 385      BEGIN_SECCERTAPI
 386  
 387      Certificate::required(__itemImplRef)->releaseFieldValue(Required(field), fieldValue);
 388  
 389      END_SECCERTAPI
 390  }
 391  
 392  /* OS X only */
 393  OSStatus
 394  SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer,
 395  	const CSSM_DATA *serialNumber, SecCertificateRef *certificate)
 396  {
 397      if (issuer && serialNumber) {
 398          CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 399          CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
 400          CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
 401          CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue);
 402  
 403          CFRef<CFDataRef> issuerData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)issuer->Data, issuer->Length, kCFAllocatorNull);
 404          CFDictionarySetValue(query, kSecAttrIssuer, issuerData);
 405  
 406          CFRef<CFDataRef> serialNumberData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)serialNumber->Data, serialNumber->Length, kCFAllocatorNull);
 407          CFDictionarySetValue(query, kSecAttrSerialNumber, serialNumberData);
 408  
 409          OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
 410          if (status == errSecSuccess) {
 411              return status;
 412          }
 413      }
 414  
 415  	BEGIN_SECAPI
 416  
 417  	StorageManager::KeychainList keychains;
 418  	globals().storageManager.optionalSearchList(keychainOrArray, keychains);
 419  	Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle();
 420  
 421      // convert ItemImpl-based SecCertificateRef to new-world version before returning
 422  	CssmData certData = Certificate::required(*certificate)->data();
 423  	CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
 424  	SecCertificateRef tmpRef = *certificate;
 425  	*certificate = SecCertificateCreateWithData(NULL, cfData);
 426  	CFRelease(tmpRef);
 427  
 428  	END_SECAPI
 429  }
 430  
 431  /* OS X only */
 432  OSStatus
 433  SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
 434  	SecCertificateRef *certificate)
 435  {
 436      if (subjectKeyID) {
 437          CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 438          CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
 439          CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
 440          CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue);
 441  
 442          CFRef<CFDataRef> subjectKeyIDData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)subjectKeyID->Data, subjectKeyID->Length, kCFAllocatorNull);
 443          CFDictionarySetValue(query, kSecAttrSubjectKeyID, subjectKeyIDData);
 444  
 445          OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
 446          if (status == errSecSuccess) {
 447              return status;
 448          }
 449      }
 450  
 451      BEGIN_SECAPI
 452  
 453  	StorageManager::KeychainList keychains;
 454  	globals().storageManager.optionalSearchList(keychainOrArray, keychains);
 455  	Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle();
 456  
 457      // convert ItemImpl-based SecCertificateRef to new-world version before returning
 458  	CssmData certData = Certificate::required(*certificate)->data();
 459  	CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
 460  	SecCertificateRef tmpRef = *certificate;
 461  	*certificate = SecCertificateCreateWithData(NULL, cfData);
 462  	CFRelease(tmpRef);
 463  
 464  	END_SECAPI
 465  }
 466  
 467  /* OS X only */
 468  OSStatus
 469  SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate)
 470  {
 471      if (emailAddress) {
 472          CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 473          CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
 474          CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
 475          CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue);
 476  
 477          CFRef<CFStringRef> emailAddressString = CFStringCreateWithCString(kCFAllocatorDefault, emailAddress, kCFStringEncodingUTF8);
 478          CFTypeRef keys[] = { kSecPolicyName };
 479          CFTypeRef values[] = { emailAddressString };
 480          CFRef<CFDictionaryRef> properties = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 481          CFRef<SecPolicyRef> policy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, properties);
 482          CFDictionarySetValue(query, kSecMatchPolicy, policy);
 483  
 484          OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
 485          if (status == errSecSuccess) {
 486              return status;
 487          }
 488      }
 489  
 490      BEGIN_SECAPI
 491  
 492  	StorageManager::KeychainList keychains;
 493  	globals().storageManager.optionalSearchList(keychainOrArray, keychains);
 494  	Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle();
 495  
 496      // convert ItemImpl-based SecCertificateRef to new-world version before returning
 497  	CssmData certData = Certificate::required(*certificate)->data();
 498  	CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
 499  	SecCertificateRef tmpRef = *certificate;
 500  	*certificate = SecCertificateCreateWithData(NULL, cfData);
 501  	CFRelease(tmpRef);
 502  
 503  	END_SECAPI
 504  }
 505  
 506  /* OS X only */
 507  OSStatus
 508  SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer,
 509  	const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef)
 510  {
 511      BEGIN_SECAPI
 512  
 513  	Required(searchRef);
 514  
 515  	StorageManager::KeychainList keychains;
 516  	globals().storageManager.optionalSearchList(keychainOrArray, keychains);
 517  	KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber)));
 518  	*searchRef = cursor->handle();
 519  
 520  	END_SECAPI
 521  }
 522  
 523  /* OS X only */
 524  OSStatus
 525  SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer,
 526  	CFDataRef serialNumber, SecKeychainSearchRef *searchRef)
 527  {
 528      BEGIN_SECAPI
 529  
 530  	Required(searchRef);
 531  
 532  	StorageManager::KeychainList keychains;
 533  	globals().storageManager.optionalSearchList(keychainOrArray, keychains);
 534  	Required(issuer);
 535  	Required(serialNumber);
 536  	KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber));
 537  	*searchRef = cursor->handle();
 538  
 539  	END_SECAPI
 540  }
 541  
 542  /* OS X only */
 543  OSStatus
 544  SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
 545  	SecKeychainSearchRef *searchRef)
 546  {
 547      BEGIN_SECAPI
 548  
 549  	Required(searchRef);
 550  
 551  	StorageManager::KeychainList keychains;
 552  	globals().storageManager.optionalSearchList(keychainOrArray, keychains);
 553  	KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID)));
 554  	*searchRef = cursor->handle();
 555  
 556  	END_SECAPI
 557  }
 558  
 559  /* OS X only */
 560  OSStatus
 561  SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress,
 562  	SecKeychainSearchRef *searchRef)
 563  {
 564      BEGIN_SECAPI
 565  
 566  	Required(searchRef);
 567  
 568  	StorageManager::KeychainList keychains;
 569  	globals().storageManager.optionalSearchList(keychainOrArray, keychains);
 570  	KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress));
 571  	*searchRef = cursor->handle();
 572  
 573  	END_SECAPI
 574  }
 575  
 576  /* OS X only */
 577  CSSM_RETURN
 578  SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data)
 579  {
 580  	BEGIN_SECAPI
 581  	// sanity checking
 582  	if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length)
 583  		return errSecParam;
 584  
 585  	CSP csp(gGuidAppleCSP);
 586  	Digest context(csp, alg);
 587  	CssmData input(data->Data, data->Length);
 588  	CssmData output(digest->Data, digest->Length);
 589  
 590  	context.digest(input, output);
 591  	digest->Length = output.length();
 592  
 593  	return CSSM_OK;
 594  	END_SECAPI1(1);
 595  }
 596  
 597  /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
 598  OSStatus
 599  SecCertificateCopyPreference(
 600      CFStringRef name,
 601      CSSM_KEYUSE keyUsage,
 602      SecCertificateRef *certificate)
 603  {
 604      BEGIN_SECAPI
 605  
 606  	Required(name);
 607  	Required(certificate);
 608  	StorageManager::KeychainList keychains;
 609  	globals().storageManager.getSearchList(keychains);
 610  	KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
 611  
 612  	char idUTF8[MAXPATHLEN];
 613      if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
 614          idUTF8[0] = (char)'\0';
 615      CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8));
 616      FourCharCode itemType = 'cprf';
 617      cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
 618  	cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
 619      if (keyUsage) {
 620          cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
 621      }
 622  
 623      Item prefItem;
 624      if (!cursor->next(prefItem)) {
 625          MacOSError::throwMe(errSecItemNotFound);
 626      }
 627  
 628  	// get persistent certificate reference
 629  	SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } };
 630  	SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
 631  	prefItem->getContent(NULL, &itemAttrList, NULL, NULL);
 632  
 633  	// find certificate, given persistent reference data
 634  	CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull);
 635  	SecKeychainItemRef certItemRef = nil;
 636  	OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl
 637  	prefItem->freeContent(&itemAttrList, NULL);
 638  	if (pItemRef)
 639  		CFRelease(pItemRef);
 640  	if (status)
 641  		return status;
 642  
 643  	*certificate = (SecCertificateRef)certItemRef;
 644  
 645  	if (certItemRef && (CFGetTypeID(certItemRef) == SecIdentityGetTypeID())) {
 646  		// SecKeychainItemCopyFromPersistentReference handed out an identity reference
 647  		*certificate = NULL;
 648  		status = SecIdentityCopyCertificate((SecIdentityRef)certItemRef, certificate);
 649  		CFRelease(certItemRef);
 650  		return status;
 651  	}
 652  
 653      END_SECAPI
 654  }
 655  
 656  /* OS X only */
 657  SecCertificateRef
 658  SecCertificateCopyPreferred(
 659  	CFStringRef name,
 660  	CFArrayRef keyUsage)
 661  {
 662  	// This function will look for a matching preference in the following order:
 663  	// - matches the name and the supplied key use
 664  	// - matches the name and the special 'ANY' key use
 665  	// - matches the name with no key usage constraint
 666  
 667  	SecCertificateRef certRef = NULL;
 668  	CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
 669  	OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef);
 670  	if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY)
 671  		status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef);
 672  	if (status != errSecSuccess && keyUse != 0)
 673  		status = SecCertificateCopyPreference(name, 0, &certRef);
 674  
 675  	return certRef;
 676  }
 677  
 678  /* OS X only; not exported */
 679  static OSStatus
 680  SecCertificateFindPreferenceItemWithNameAndKeyUsage(
 681  	CFTypeRef keychainOrArray,
 682  	CFStringRef name,
 683  	int32_t keyUsage,
 684  	SecKeychainItemRef *itemRef)
 685  {
 686      BEGIN_SECAPI
 687  
 688  	StorageManager::KeychainList keychains;
 689  	globals().storageManager.optionalSearchList(keychainOrArray, keychains);
 690  	KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
 691  
 692  	char idUTF8[MAXPATHLEN];
 693      idUTF8[0] = (char)'\0';
 694  	if (name)
 695  	{
 696  		if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
 697  			idUTF8[0] = (char)'\0';
 698  	}
 699      size_t idUTF8Len = strlen(idUTF8);
 700      if (!idUTF8Len)
 701          MacOSError::throwMe(errSecParam);
 702  
 703      CssmData service(const_cast<char *>(idUTF8), idUTF8Len);
 704      cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
 705  	cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf');
 706      if (keyUsage) {
 707          cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
 708      }
 709  
 710  	Item item;
 711  	if (!cursor->next(item))
 712  		MacOSError::throwMe(errSecItemNotFound);
 713  
 714  	if (itemRef)
 715  		*itemRef=item->handle();
 716  
 717      END_SECAPI
 718  }
 719  
 720  /* OS X only; not exported */
 721  static
 722  OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
 723  	CFTypeRef keychainOrArray,
 724  	CFStringRef name,
 725  	int32_t keyUsage)
 726  {
 727  	// when a specific key usage is passed, we'll only match & delete that pref;
 728  	// when a key usage of 0 is passed, all matching prefs should be deleted.
 729  	// maxUsages represents the most matches there could theoretically be, so
 730  	// cut things off at that point if we're still finding items (if they can't
 731  	// be deleted for some reason, we'd never break out of the loop.)
 732  
 733  	OSStatus status = errSecSuccess;
 734  	SecKeychainItemRef item = NULL;
 735  	int count = 0, maxUsages = 12;
 736  	while (++count <= maxUsages &&
 737  			(status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) {
 738  		status = SecKeychainItemDelete(item);
 739  		CFRelease(item);
 740  		item = NULL;
 741  	}
 742  
 743  	// it's not an error if the item isn't found
 744  	return (status == errSecItemNotFound) ? errSecSuccess : status;
 745  }
 746  
 747  /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
 748  OSStatus SecCertificateSetPreference(
 749      SecCertificateRef certificate,
 750      CFStringRef name,
 751      CSSM_KEYUSE keyUsage,
 752      CFDateRef date)
 753  {
 754  	if (!name) {
 755  		return errSecParam;
 756  	}
 757  	if (!certificate) {
 758  		// treat NULL certificate as a request to clear the preference
 759  		// (note: if keyUsage is 0, this clears all key usage prefs for name)
 760  		return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage);
 761  	}
 762  
 763      // This macro creates an ItemImpl certificate if it does not exist
 764      BEGIN_SECCERTAPI
 765  
 766  	// determine the account attribute
 767  	//
 768  	// This attribute must be synthesized from certificate label + pref item type + key usage,
 769  	// as only the account and service attributes can make a generic keychain item unique.
 770  	// For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
 771  	// we can save a certificate preference if an identity preference already exists for the
 772  	// given service name, and vice-versa.
 773  	// If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
 774  	//
 775      CFStringRef labelStr = nil;
 776  	Certificate::required(__itemImplRef)->inferLabel(false, &labelStr);
 777  	if (!labelStr) {
 778          MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed"
 779  	}
 780  	CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1;
 781  	const char *templateStr = "%s [key usage 0x%X]";
 782  	const int keyUsageMaxStrLen = 8;
 783  	accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen;
 784  	char *accountUTF8 = (char *)malloc(accountUTF8Len);
 785  	if (!accountUTF8) {
 786  		MacOSError::throwMe(errSecMemoryError);
 787  	}
 788      if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8))
 789  		accountUTF8[0] = (char)'\0';
 790  	if (keyUsage)
 791  		snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage);
 792      CssmDataContainer account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
 793      free(accountUTF8);
 794      CFRelease(labelStr);
 795  
 796  	// service attribute (name provided by the caller)
 797  	CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;;
 798  	char *serviceUTF8 = (char *)malloc(serviceUTF8Len);
 799  	if (!serviceUTF8) {
 800  		MacOSError::throwMe(errSecMemoryError);
 801  	}
 802      if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8))
 803          serviceUTF8[0] = (char)'\0';
 804      CssmDataContainer service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
 805      free(serviceUTF8);
 806  
 807      // look for existing preference item, in case this is an update
 808  	StorageManager::KeychainList keychains;
 809  	globals().storageManager.getSearchList(keychains);
 810  	KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
 811      FourCharCode itemType = 'cprf';
 812      cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
 813  	cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
 814      if (keyUsage) {
 815          cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
 816      }
 817  
 818      Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false);
 819      bool add = (!cursor->next(item));
 820  	// at this point, we either have a new item to add or an existing item to update
 821  
 822      // set item attribute values
 823      item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
 824      item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType);
 825      item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
 826      item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
 827      item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
 828  
 829  	// generic attribute (store persistent certificate reference)
 830  	CFDataRef pItemRef = nil;
 831  	Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef);
 832  	if (!pItemRef) {
 833  		MacOSError::throwMe(errSecInvalidItemRef);
 834      }
 835  	const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef);
 836  	CFIndex dataLen = CFDataGetLength(pItemRef);
 837  	CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen);
 838  	item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref);
 839  	CFRelease(pItemRef);
 840  
 841      if (add) {
 842          Keychain keychain = nil;
 843          try {
 844              keychain = globals().storageManager.defaultKeychain();
 845              if (!keychain->exists())
 846                  MacOSError::throwMe(errSecNoSuchKeychain);	// Might be deleted or not available at this time.
 847          }
 848          catch(...) {
 849              keychain = globals().storageManager.defaultKeychainUI(item);
 850          }
 851  
 852  		try {
 853  			keychain->add(item);
 854  		}
 855  		catch (const MacOSError &err) {
 856  			if (err.osStatus() != errSecDuplicateItem)
 857  				throw; // if item already exists, fall through to update
 858  		}
 859      }
 860  	item->update();
 861  
 862      END_SECCERTAPI
 863  }
 864  
 865  /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
 866  OSStatus SecCertificateSetPreferred(
 867  	SecCertificateRef certificate,
 868  	CFStringRef name,
 869  	CFArrayRef keyUsage)
 870  {
 871  	COUNTLEGACYAPI
 872  	CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
 873  	return SecCertificateSetPreference(certificate, name, keyUse, NULL);
 874  }
 875  
 876  /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
 877  CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error)
 878  {
 879  	CFDictionaryRef result = NULL;
 880  	OSStatus __secapiresult;
 881  	SecCertificateRef tmpcert = NULL;
 882  
 883  	// convert input to a new-style certificate reference if necessary,
 884  	// since the implementation of CertificateValues calls SecCertificate API functions
 885  	// which now assume a unified certificate reference.
 886  	if (SecCertificateIsItemImplInstance(certificate)) {
 887  		tmpcert = SecCertificateCreateFromItemImplInstance(certificate);
 888  	}
 889  	if (certificate && !tmpcert) {
 890  		tmpcert = (SecCertificateRef) CFRetain(certificate);
 891  	}
 892  	try
 893  	{
 894  		CertificateValues cv(tmpcert);
 895  		result = cv.copyFieldValues(keys,error);
 896  		__secapiresult=0;
 897  	}
 898  	catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
 899  	catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
 900  	catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
 901  	catch (...) { __secapiresult=errSecInternalComponent; }
 902  	if (tmpcert) { CFRelease(tmpcert); }
 903  	return result;
 904  }
 905  
 906  /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
 907  CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
 908  {
 909  	return SecCertificateCopyShortDescription(alloc, certificate, error);
 910  }
 911  
 912  /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
 913  CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
 914  {
 915  	CFStringRef result = NULL;
 916  	OSStatus __secapiresult = SecCertificateInferLabel(certificate, &result);
 917  	if (error!=NULL && __secapiresult!=errSecSuccess)
 918  	{
 919  		*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus,
 920  			__secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
 921  	}
 922  	return result;
 923  }
 924  
 925  /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
 926  CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error)
 927  {
 928  	CFDataRef result = NULL;
 929  	OSStatus __secapiresult;
 930  	try
 931  	{
 932  		CertificateValues cv(certificate);
 933  		result = cv.copySerialNumber(error);
 934  		__secapiresult=0;
 935  	}
 936  	catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
 937  	catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
 938  	catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
 939  	catch (...) { __secapiresult=errSecInternalComponent; }
 940  	return result;
 941  }
 942  
 943  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */
 944  CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error)
 945  {
 946  	CFDataRef result = NULL;
 947  	OSStatus __secapiresult;
 948  	try
 949  	{
 950  		CertificateValues cv(certificate);
 951  		result = cv.copyNormalizedIssuerContent(error);
 952  		__secapiresult=0;
 953  	}
 954  	catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
 955  	catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
 956  	catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
 957  	catch (...) { __secapiresult=errSecInternalComponent; }
 958  	return result;
 959  }
 960  
 961  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */
 962  CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error)
 963  {
 964  	CFDataRef result = NULL;
 965  	OSStatus __secapiresult;
 966  	try
 967  	{
 968  		CertificateValues cv(certificate);
 969  		result = cv.copyNormalizedSubjectContent(error);
 970  		__secapiresult=0;
 971  	}
 972  	catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
 973  	catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
 974  	catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
 975  	catch (...) { __secapiresult=errSecInternalComponent; }
 976  	return result;
 977  }
 978  
 979  /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
 980  bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
 981  {
 982      /*
 983       * deprecated function name
 984       */
 985  	return SecCertificateIsValid(certificate, verifyTime);
 986  }
 987  
 988  /* OS X only */
 989  CFDataRef SecCertificateCopyPublicKeySHA1DigestFromCertificateData(CFAllocatorRef allocator,
 990                                                                     CFDataRef der_certificate)
 991  {
 992      CFDataRef result = NULL;
 993      SecCertificateRef iosCertRef = SecCertificateCreateWithData(allocator, der_certificate);
 994      if (NULL == iosCertRef)
 995      {
 996          return result;
 997      }
 998  
 999      result = SecCertificateCopyPublicKeySHA1Digest(iosCertRef);
1000      CFRelease(iosCertRef);
1001      return result;
1002  }
1003