2  * Copyright (c) 2002-2016 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  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> 
  36 #include "SecBridge.h" 
  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> 
  47 #include "CertificateValues.h" 
  49 #include "AppleBaselineEscrowCertificates.h" 
  52 OSStatus 
SecCertificateGetCLHandle_legacy(SecCertificateRef certificate
, CSSM_CL_HANDLE 
*clHandle
); 
  53 extern CSSM_KEYUSE 
ConvertArrayToKeyUsage(CFArrayRef usage
); 
  55 #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v); 
  57 SEC_CONST_DECL (kSecCertificateProductionEscrowKey
, "ProductionEscrowKey"); 
  58 SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey
, "ProductionPCSEscrowKey"); 
  59 SEC_CONST_DECL (kSecCertificateEscrowFileName
, "AppleESCertificates"); 
  62 using namespace CssmClient
; 
  64 CFTypeID 
static SecCertificateGetTypeID_osx(void) 
  68         return gTypes().Certificate
.typeID
; 
  70         END_SECAPI1(_kCFRuntimeNotATypeID
) 
  74 SecCertificateIsItemImplInstance(SecCertificateRef certificate
) 
  76     if (certificate 
== NULL
) { 
  80     CFTypeID typeID 
= CFGetTypeID(certificate
); 
  82 #if 0 /* debug code to verify type IDs */ 
  83         syslog(LOG_ERR
, "SecCertificate typeID=%d [STU=%d, OSX=%d, SKI=%d]", 
  85                         (int)SecCertificateGetTypeID(), 
  86                         (int)SecCertificateGetTypeID_osx(), 
  87                         (int)SecKeychainItemGetTypeID()); 
  89         if (typeID 
== _kCFRuntimeNotATypeID
) { 
  93     return (typeID 
== SecCertificateGetTypeID_osx() || 
  94             typeID 
== SecKeychainItemGetTypeID()) ? true : false; 
  97 /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */ 
  99 SecCertificateCreateItemImplInstance(SecCertificateRef certificate
) 
 104         SecCertificateRef implCertRef 
= (SecCertificateRef
) SecCertificateCopyKeychainItem(certificate
); 
 108         CFDataRef data 
= SecCertificateCopyData(certificate
); 
 113                 CSSM_DATA cssmCertData
; 
 114                 cssmCertData
.Length 
= (data
) ? (CSSM_SIZE
)CFDataGetLength(data
) : 0; 
 115                 cssmCertData
.Data 
= (data
) ? (uint8 
*)CFDataGetBytePtr(data
) : NULL
; 
 117                 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
)); 
 118                 implCertRef 
= certificatePtr
->handle(); 
 125 /* convert an old-world ItemImpl instance to a new-world SecCertificateRef */ 
 127 SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate
) 
 132         SecCertificateRef result 
= NULL
; 
 133         CFDataRef data 
= NULL
; 
 135                 CssmData certData 
= Certificate::required(certificate
)->data(); 
 136                 if (certData
.Data 
&& certData
.Length
) { 
 137                         data 
= CFDataCreate(NULL
, certData
.Data
, certData
.Length
); 
 140                         if (certData
.Data 
&& !certData
.Length
) { 
 141                                 /* zero-length certs can exist, so don't bother logging this */ 
 144                                 syslog(LOG_ERR
, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)", 
 145                                                 (long)certData
.Length
, (uintptr_t)certData
.Data
); 
 152         result 
= SecCertificateCreateWithKeychainItem(NULL
, data
, certificate
); 
 159 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ 
 161 SecCertificateCreateFromData(const CSSM_DATA 
*data
, CSSM_CERT_TYPE type
, CSSM_CERT_ENCODING encoding
, SecCertificateRef 
*certificate
) 
 163         /* bridge to support old functionality */ 
 164         if (!data 
|| !data
->Data 
|| !data
->Length 
|| !certificate
) { 
 167         SecCertificateRef certRef 
= NULL
; 
 169     // <rdar://problem/24403998> REG: Adobe {Photoshop, InDesign} CC(2015) crashes on launch 
 170     // If you take the length that SecKeychainItemCopyContent gives you (a Uint32) and assign it incorrectly 
 171     // to a CSSM_DATA Length field (a CSSM_SIZE, i.e., a size_t), the upper 32 bits aren't set. If those bits 
 172     // are non-zero, the length is incredibly wrong. 
 174     // Assume that there will not exist a certificate > 4GiB, and fake this length field. 
 175     CSSM_SIZE length 
= data
->Length 
& 0xfffffffful
; 
 177         CFDataRef dataRef 
= CFDataCreate(NULL
, data
->Data
, length
); 
 179                 certRef 
= SecCertificateCreateWithData(NULL
, dataRef
); 
 182         *certificate 
= certRef
; 
 183         return (certRef
) ? errSecSuccess 
: errSecUnknownFormat
; 
 186 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */ 
 188 SecCertificateAddToKeychain(SecCertificateRef certificate
, SecKeychainRef keychain
) 
 190         // This macro creates an ItemImpl certificate if it does not exist 
 193         Item 
item(Certificate::required(__itemImplRef
)); 
 194         Keychain::optional(keychain
)->add(item
); 
 199 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ 
 201 SecCertificateGetData(SecCertificateRef certificate
, CSSM_DATA_PTR data
) 
 205         if (!certificate 
|| !data
) { 
 206                 __secapiresult
=errSecParam
; 
 208         else if (SecCertificateIsItemImplInstance(certificate
)) { 
 209                 Required(data
) = Certificate::required(certificate
)->data(); 
 212                 data
->Length 
= (CSSM_SIZE
)SecCertificateGetLength(certificate
); 
 213                 data
->Data 
= (uint8
*)SecCertificateGetBytePtr(certificate
); 
 219 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ 
 221 SecCertificateGetType(SecCertificateRef certificate
, CSSM_CERT_TYPE 
*certificateType
) 
 223     // This macro creates an ItemImpl certificate if it does not exist 
 226     Required(certificateType
) = Certificate::required(__itemImplRef
)->type(); 
 231 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ 
 233 SecCertificateGetSubject(SecCertificateRef certificate
, const CSSM_X509_NAME 
**subject
) 
 235     // This macro creates an ItemImpl certificate if it does not exist 
 238     Required(subject
) = Certificate::required(__itemImplRef
)->subjectName(); 
 243 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ 
 245 SecCertificateGetIssuer(SecCertificateRef certificate
, const CSSM_X509_NAME 
**issuer
) 
 247     // This macro creates an ItemImpl certificate if it does not exist 
 250     Required(issuer
) = Certificate::required(__itemImplRef
)->issuerName(); 
 255 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ 
 257 SecCertificateGetCLHandle(SecCertificateRef certificate
, CSSM_CL_HANDLE 
*clHandle
) 
 259     // This macro creates an ItemImpl certificate if it does not exist 
 262     Required(clHandle
) = Certificate::required(__itemImplRef
)->clHandle(); 
 267 /* private function; assumes input is old-style ItemImpl certificate reference, 
 268    and does not release that certificate reference! 
 271 SecCertificateGetCLHandle_legacy(SecCertificateRef certificate
, CSSM_CL_HANDLE 
*clHandle
) 
 275     Required(clHandle
) = Certificate::required(certificate
)->clHandle(); 
 281  * Private API to infer a display name for a SecCertificateRef which 
 282  * may or may not be in a keychain. 
 287 SecCertificateInferLabel(SecCertificateRef certificate
, CFStringRef 
*label
) 
 289     // This macro creates an ItemImpl certificate if it does not exist 
 292     Certificate::required(__itemImplRef
)->inferLabel(false, &Required(label
)); 
 297 /* OS X only (note: iOS version has different arguments and return value) */ 
 299 SecCertificateCopyPublicKey(SecCertificateRef certificate
, SecKeyRef 
*key
) 
 301     // This macro creates an ItemImpl certificate if it does not exist 
 304     Required(key
) = Certificate::required(__itemImplRef
)->publicKey()->handle(); 
 309 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ 
 311 SecCertificateGetAlgorithmID(SecCertificateRef certificate
, const CSSM_X509_ALGORITHM_IDENTIFIER 
**algid
) 
 313     // This macro creates an ItemImpl certificate if it does not exist 
 316     Required(algid
) = Certificate::required(__itemImplRef
)->algorithmID(); 
 323 SecCertificateCopySubjectComponent(SecCertificateRef certificate
, const CSSM_OID 
*component
, CFStringRef 
*result
) 
 325     // This macro creates an ItemImpl certificate if it does not exist 
 328     Required(result
) = Certificate::required(__itemImplRef
)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct
, component
); 
 333 /* OS X only; deprecated SPI */ 
 335 SecCertificateGetCommonName(SecCertificateRef certificate
, CFStringRef 
*commonName
) 
 337     // deprecated SPI signature; replaced by SecCertificateCopyCommonName 
 338     return SecCertificateCopyCommonName(certificate
, commonName
); 
 341 /* OS X only; deprecated SPI */ 
 343 SecCertificateGetEmailAddress(SecCertificateRef certificate
, CFStringRef 
*emailAddress
) 
 345     // This macro creates an ItemImpl certificate if it does not exist 
 348     Required(emailAddress
) = Certificate::required(__itemImplRef
)->copyFirstEmailAddress(); 
 353 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field. 
 354  * Caller must call releaseFieldValues to free the storage allocated by this call. 
 359 SecCertificateCopyFieldValues(SecCertificateRef certificate
, const CSSM_OID 
*field
, CSSM_DATA_PTR 
**fieldValues
) 
 361     // This macro creates an ItemImpl certificate if it does not exist 
 364     Required(fieldValues
) = Certificate::required(__itemImplRef
)->copyFieldValues(Required(field
)); 
 371 SecCertificateReleaseFieldValues(SecCertificateRef certificate
, const CSSM_OID 
*field
, CSSM_DATA_PTR 
*fieldValues
) 
 373     // This macro creates an ItemImpl certificate if it does not exist 
 376     Certificate::required(__itemImplRef
)->releaseFieldValues(Required(field
), fieldValues
); 
 383 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID 
*field
, CSSM_DATA_PTR 
*fieldValue
) 
 385     // This macro creates an ItemImpl certificate if it does not exist 
 388     Required(fieldValue
) = Certificate::required(__itemImplRef
)->copyFirstFieldValue(Required(field
)); 
 395 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID 
*field
, CSSM_DATA_PTR fieldValue
) 
 397     // This macro creates an ItemImpl certificate if it does not exist 
 400     Certificate::required(__itemImplRef
)->releaseFieldValue(Required(field
), fieldValue
); 
 407 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray
,const CSSM_DATA 
*issuer
, 
 408         const CSSM_DATA 
*serialNumber
, SecCertificateRef 
*certificate
) 
 410     if (issuer 
&& serialNumber
) { 
 411         CFRef
<CFMutableDictionaryRef
> query 
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 412         CFDictionarySetValue(query
, kSecClass
, kSecClassCertificate
); 
 413         CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
); 
 414         CFDictionarySetValue(query
, kSecAttrNoLegacy
, kCFBooleanTrue
); 
 416         CFRef
<CFDataRef
> issuerData 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8 
*)issuer
->Data
, issuer
->Length
, kCFAllocatorNull
); 
 417         CFDictionarySetValue(query
, kSecAttrIssuer
, issuerData
); 
 419         CFRef
<CFDataRef
> serialNumberData 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8 
*)serialNumber
->Data
, serialNumber
->Length
, kCFAllocatorNull
); 
 420         CFDictionarySetValue(query
, kSecAttrSerialNumber
, serialNumberData
); 
 422         OSStatus status 
= SecItemCopyMatching(query
, (CFTypeRef
*)certificate
); 
 423         if (status 
== errSecSuccess
) { 
 430         StorageManager::KeychainList keychains
; 
 431         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 432         Required(certificate
) = Certificate::findByIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
))->handle(); 
 434     // convert ItemImpl-based SecCertificateRef to new-world version before returning 
 435         CssmData certData 
= Certificate::required(*certificate
)->data(); 
 436         CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
)); 
 437         SecCertificateRef tmpRef 
= *certificate
; 
 438         *certificate 
= SecCertificateCreateWithData(NULL
, cfData
); 
 446 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA 
*subjectKeyID
, 
 447         SecCertificateRef 
*certificate
) 
 450         CFRef
<CFMutableDictionaryRef
> query 
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 451         CFDictionarySetValue(query
, kSecClass
, kSecClassCertificate
); 
 452         CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
); 
 453         CFDictionarySetValue(query
, kSecAttrNoLegacy
, kCFBooleanTrue
); 
 455         CFRef
<CFDataRef
> subjectKeyIDData 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8 
*)subjectKeyID
->Data
, subjectKeyID
->Length
, kCFAllocatorNull
); 
 456         CFDictionarySetValue(query
, kSecAttrSubjectKeyID
, subjectKeyIDData
); 
 458         OSStatus status 
= SecItemCopyMatching(query
, (CFTypeRef
*)certificate
); 
 459         if (status 
== errSecSuccess
) { 
 466         StorageManager::KeychainList keychains
; 
 467         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 468         Required(certificate
) = Certificate::findBySubjectKeyID(keychains
, CssmData::required(subjectKeyID
))->handle(); 
 470     // convert ItemImpl-based SecCertificateRef to new-world version before returning 
 471         CssmData certData 
= Certificate::required(*certificate
)->data(); 
 472         CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
)); 
 473         SecCertificateRef tmpRef 
= *certificate
; 
 474         *certificate 
= SecCertificateCreateWithData(NULL
, cfData
); 
 482 SecCertificateFindByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
, SecCertificateRef 
*certificate
) 
 485         CFRef
<CFMutableDictionaryRef
> query 
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 486         CFDictionarySetValue(query
, kSecClass
, kSecClassCertificate
); 
 487         CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
); 
 488         CFDictionarySetValue(query
, kSecAttrNoLegacy
, kCFBooleanTrue
); 
 490         CFRef
<CFStringRef
> emailAddressString 
= CFStringCreateWithCString(kCFAllocatorDefault
, emailAddress
, kCFStringEncodingUTF8
); 
 491         CFTypeRef keys
[] = { kSecPolicyName 
}; 
 492         CFTypeRef values
[] = { emailAddressString 
}; 
 493         CFRef
<CFDictionaryRef
> properties 
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 494         CFRef
<SecPolicyRef
> policy 
= SecPolicyCreateWithProperties(kSecPolicyAppleSMIME
, properties
); 
 495         CFDictionarySetValue(query
, kSecMatchPolicy
, policy
); 
 497         OSStatus status 
= SecItemCopyMatching(query
, (CFTypeRef
*)certificate
); 
 498         if (status 
== errSecSuccess
) { 
 505         StorageManager::KeychainList keychains
; 
 506         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 507         Required(certificate
) = Certificate::findByEmail(keychains
, emailAddress
)->handle(); 
 509     // convert ItemImpl-based SecCertificateRef to new-world version before returning 
 510         CssmData certData 
= Certificate::required(*certificate
)->data(); 
 511         CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
)); 
 512         SecCertificateRef tmpRef 
= *certificate
; 
 513         *certificate 
= SecCertificateCreateWithData(NULL
, cfData
); 
 521 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray
, const CSSM_DATA 
*issuer
, 
 522         const CSSM_DATA 
*serialNumber
, SecKeychainSearchRef 
*searchRef
) 
 528         StorageManager::KeychainList keychains
; 
 529         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 530         KCCursor 
cursor(Certificate::cursorForIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
))); 
 531         *searchRef 
= cursor
->handle(); 
 538 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray
, CFDataRef issuer
, 
 539         CFDataRef serialNumber
, SecKeychainSearchRef 
*searchRef
) 
 545         StorageManager::KeychainList keychains
; 
 546         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 548         Required(serialNumber
); 
 549         KCCursor 
cursor(Certificate::cursorForIssuerAndSN_CF(keychains
, issuer
, serialNumber
)); 
 550         *searchRef 
= cursor
->handle(); 
 557 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA 
*subjectKeyID
, 
 558         SecKeychainSearchRef 
*searchRef
) 
 564         StorageManager::KeychainList keychains
; 
 565         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 566         KCCursor 
cursor(Certificate::cursorForSubjectKeyID(keychains
, CssmData::required(subjectKeyID
))); 
 567         *searchRef 
= cursor
->handle(); 
 574 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
, 
 575         SecKeychainSearchRef 
*searchRef
) 
 581         StorageManager::KeychainList keychains
; 
 582         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 583         KCCursor 
cursor(Certificate::cursorForEmail(keychains
, emailAddress
)); 
 584         *searchRef 
= cursor
->handle(); 
 591 SecDigestGetData (CSSM_ALGORITHMS alg
, CSSM_DATA
* digest
, const CSSM_DATA
* data
) 
 595         if (!digest 
|| !digest
->Data 
|| !digest
->Length 
|| !data 
|| !data
->Data 
|| !data
->Length
) 
 598         CSP 
csp(gGuidAppleCSP
); 
 599         Digest 
context(csp
, alg
); 
 600         CssmData 
input(data
->Data
, data
->Length
); 
 601         CssmData 
output(digest
->Data
, digest
->Length
); 
 603         context
.digest(input
, output
); 
 604         digest
->Length 
= output
.length(); 
 610 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ 
 612 SecCertificateCopyPreference( 
 614     CSSM_KEYUSE keyUsage
, 
 615     SecCertificateRef 
*certificate
) 
 620         Required(certificate
); 
 621         StorageManager::KeychainList keychains
; 
 622         globals().storageManager
.getSearchList(keychains
); 
 623         KCCursor 
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
); 
 625         char idUTF8
[MAXPATHLEN
]; 
 626     if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
)) 
 627         idUTF8
[0] = (char)'\0'; 
 628     CssmData 
service(const_cast<char *>(idUTF8
), strlen(idUTF8
)); 
 629     FourCharCode itemType 
= 'cprf'; 
 630     cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
); 
 631         cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
); 
 633         cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
); 
 636         if (!cursor
->next(prefItem
)) 
 637                 MacOSError::throwMe(errSecItemNotFound
); 
 639         // get persistent certificate reference 
 640         SecKeychainAttribute itemAttrs
[] = { { kSecGenericItemAttr
, 0, NULL 
} }; 
 641         SecKeychainAttributeList itemAttrList 
= { sizeof(itemAttrs
) / sizeof(itemAttrs
[0]), itemAttrs 
}; 
 642         prefItem
->getContent(NULL
, &itemAttrList
, NULL
, NULL
); 
 644         // find certificate, given persistent reference data 
 645         CFDataRef pItemRef 
= CFDataCreateWithBytesNoCopy(NULL
, (const UInt8 
*)itemAttrs
[0].data
, itemAttrs
[0].length
, kCFAllocatorNull
); 
 646         SecKeychainItemRef certItemRef 
= nil
; 
 647         OSStatus status 
= SecKeychainItemCopyFromPersistentReference(pItemRef
, &certItemRef
); //%%% need to make this a method of ItemImpl 
 648         prefItem
->freeContent(&itemAttrList
, NULL
); 
 654         *certificate 
= (SecCertificateRef
)certItemRef
; 
 656         if (certItemRef 
&& (CFGetTypeID(certItemRef
) == SecIdentityGetTypeID())) { 
 657                 // SecKeychainItemCopyFromPersistentReference handed out an identity reference 
 659                 status 
= SecIdentityCopyCertificate((SecIdentityRef
)certItemRef
, certificate
); 
 660                 CFRelease(certItemRef
); 
 669 SecCertificateCopyPreferred( 
 673         // This function will look for a matching preference in the following order: 
 674         // - matches the name and the supplied key use 
 675         // - matches the name and the special 'ANY' key use 
 676         // - matches the name with no key usage constraint 
 678         SecCertificateRef certRef 
= NULL
; 
 679         CSSM_KEYUSE keyUse 
= ConvertArrayToKeyUsage(keyUsage
); 
 680         OSStatus status 
= SecCertificateCopyPreference(name
, keyUse
, &certRef
); 
 681         if (status 
!= errSecSuccess 
&& keyUse 
!= CSSM_KEYUSE_ANY
) 
 682                 status 
= SecCertificateCopyPreference(name
, CSSM_KEYUSE_ANY
, &certRef
); 
 683         if (status 
!= errSecSuccess 
&& keyUse 
!= 0) 
 684                 status 
= SecCertificateCopyPreference(name
, 0, &certRef
); 
 689 /* OS X only; not exported */ 
 691 SecCertificateFindPreferenceItemWithNameAndKeyUsage( 
 692         CFTypeRef keychainOrArray
, 
 695         SecKeychainItemRef 
*itemRef
) 
 699         StorageManager::KeychainList keychains
; 
 700         globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
); 
 701         KCCursor 
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
); 
 703         char idUTF8
[MAXPATHLEN
]; 
 704     idUTF8
[0] = (char)'\0'; 
 707                 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
)) 
 708                         idUTF8
[0] = (char)'\0'; 
 710     size_t idUTF8Len 
= strlen(idUTF8
); 
 712         MacOSError::throwMe(errSecParam
); 
 714     CssmData 
service(const_cast<char *>(idUTF8
), idUTF8Len
); 
 715     cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
); 
 716         cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), (FourCharCode
)'cprf'); 
 718         cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
); 
 721         if (!cursor
->next(item
)) 
 722                 MacOSError::throwMe(errSecItemNotFound
); 
 725                 *itemRef
=item
->handle(); 
 730 /* OS X only; not exported */ 
 732 OSStatus 
SecCertificateDeletePreferenceItemWithNameAndKeyUsage( 
 733         CFTypeRef keychainOrArray
, 
 737         // when a specific key usage is passed, we'll only match & delete that pref; 
 738         // when a key usage of 0 is passed, all matching prefs should be deleted. 
 739         // maxUsages represents the most matches there could theoretically be, so 
 740         // cut things off at that point if we're still finding items (if they can't 
 741         // be deleted for some reason, we'd never break out of the loop.) 
 743         OSStatus status 
= errSecSuccess
; 
 744         SecKeychainItemRef item 
= NULL
; 
 745         int count 
= 0, maxUsages 
= 12; 
 746         while (++count 
<= maxUsages 
&& 
 747                         (status 
= SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray
, name
, keyUsage
, &item
)) == errSecSuccess
) { 
 748                 status 
= SecKeychainItemDelete(item
); 
 753         // it's not an error if the item isn't found 
 754         return (status 
== errSecItemNotFound
) ? errSecSuccess 
: status
; 
 757 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */ 
 758 OSStatus 
SecCertificateSetPreference( 
 759     SecCertificateRef certificate
, 
 761     CSSM_KEYUSE keyUsage
, 
 768                 // treat NULL certificate as a request to clear the preference 
 769                 // (note: if keyUsage is 0, this clears all key usage prefs for name) 
 770                 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL
, name
, keyUsage
); 
 773     // This macro creates an ItemImpl certificate if it does not exist 
 776         // determine the account attribute 
 778         // This attribute must be synthesized from certificate label + pref item type + key usage, 
 779         // as only the account and service attributes can make a generic keychain item unique. 
 780         // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that 
 781         // we can save a certificate preference if an identity preference already exists for the 
 782         // given service name, and vice-versa. 
 783         // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. 
 785     CFStringRef labelStr 
= nil
; 
 786         Certificate::required(__itemImplRef
)->inferLabel(false, &labelStr
); 
 788         MacOSError::throwMe(errSecDataTooLarge
); // data is "in a format which cannot be displayed" 
 790         CFIndex accountUTF8Len 
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr
), kCFStringEncodingUTF8
) + 1; 
 791         const char *templateStr 
= "%s [key usage 0x%X]"; 
 792         const int keyUsageMaxStrLen 
= 8; 
 793         accountUTF8Len 
+= strlen(templateStr
) + keyUsageMaxStrLen
; 
 794         char accountUTF8
[accountUTF8Len
]; 
 795     if (!CFStringGetCString(labelStr
, accountUTF8
, accountUTF8Len
-1, kCFStringEncodingUTF8
)) 
 796                 accountUTF8
[0] = (char)'\0'; 
 798                 snprintf(accountUTF8
, accountUTF8Len
-1, templateStr
, accountUTF8
, keyUsage
); 
 799     CssmData 
account(const_cast<char *>(accountUTF8
), strlen(accountUTF8
)); 
 802         // service attribute (name provided by the caller) 
 803         CFIndex serviceUTF8Len 
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(name
), kCFStringEncodingUTF8
) + 1;; 
 804         char serviceUTF8
[serviceUTF8Len
]; 
 805     if (!CFStringGetCString(name
, serviceUTF8
, serviceUTF8Len
-1, kCFStringEncodingUTF8
)) 
 806         serviceUTF8
[0] = (char)'\0'; 
 807     CssmData 
service(const_cast<char *>(serviceUTF8
), strlen(serviceUTF8
)); 
 809     // look for existing preference item, in case this is an update 
 810         StorageManager::KeychainList keychains
; 
 811         globals().storageManager
.getSearchList(keychains
); 
 812         KCCursor 
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
); 
 813     FourCharCode itemType 
= 'cprf'; 
 814     cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
); 
 815         cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
); 
 817         cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
); 
 821         Item 
item(kSecGenericPasswordItemClass
, 'aapl', 0, NULL
, false); 
 822     bool add 
= (!cursor
->next(item
)); 
 823         // at this point, we either have a new item to add or an existing item to update 
 825     // set item attribute values 
 826     item
->setAttribute(Schema::attributeInfo(kSecServiceItemAttr
), service
); 
 827     item
->setAttribute(Schema::attributeInfo(kSecTypeItemAttr
), itemType
); 
 828     item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
); 
 829     item
->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
); 
 830     item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), service
); 
 836         // generic attribute (store persistent certificate reference) 
 837         CFDataRef pItemRef 
= nil
; 
 838         Certificate::required(__itemImplRef
)->copyPersistentReference(pItemRef
); 
 840                 MacOSError::throwMe(errSecInvalidItemRef
); 
 842         const UInt8 
*dataPtr 
= CFDataGetBytePtr(pItemRef
); 
 843         CFIndex dataLen 
= CFDataGetLength(pItemRef
); 
 844         CssmData 
pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr
)), dataLen
); 
 845         item
->setAttribute(Schema::attributeInfo(kSecGenericItemAttr
), pref
); 
 849         Keychain keychain 
= nil
; 
 851             keychain 
= globals().storageManager
.defaultKeychain(); 
 852             if (!keychain
->exists()) 
 853                 MacOSError::throwMe(errSecNoSuchKeychain
);      // Might be deleted or not available at this time. 
 856             keychain 
= globals().storageManager
.defaultKeychainUI(item
); 
 862                 catch (const MacOSError 
&err
) { 
 863                         if (err
.osStatus() != errSecDuplicateItem
) 
 864                                 throw; // if item already exists, fall through to update 
 872 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ 
 873 OSStatus 
SecCertificateSetPreferred( 
 874         SecCertificateRef certificate
, 
 878         CSSM_KEYUSE keyUse 
= ConvertArrayToKeyUsage(keyUsage
); 
 879         return SecCertificateSetPreference(certificate
, name
, keyUse
, NULL
); 
 882 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ 
 883 CFDictionaryRef 
SecCertificateCopyValues(SecCertificateRef certificate
, CFArrayRef keys
, CFErrorRef 
*error
) 
 885         CFDictionaryRef result 
= NULL
; 
 886         OSStatus __secapiresult
; 
 887         SecCertificateRef tmpcert 
= NULL
; 
 889         // convert input to a new-style certificate reference if necessary, 
 890         // since the implementation of CertificateValues calls SecCertificate API functions 
 891         // which now assume a unified certificate reference. 
 892         if (SecCertificateIsItemImplInstance(certificate
)) { 
 893                 tmpcert 
= SecCertificateCreateFromItemImplInstance(certificate
); 
 895         if (certificate 
&& !tmpcert
) { 
 896                 tmpcert 
= (SecCertificateRef
) CFRetain(certificate
); 
 900                 CertificateValues 
cv(tmpcert
); 
 901                 result 
= cv
.copyFieldValues(keys
,error
); 
 904         catch (const MacOSError 
&err
) { __secapiresult
=err
.osStatus(); } 
 905         catch (const CommonError 
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); } 
 906         catch (const std::bad_alloc 
&) { __secapiresult
=errSecAllocate
; } 
 907         catch (...) { __secapiresult
=errSecInternalComponent
; } 
 908         if (tmpcert
) { CFRelease(tmpcert
); } 
 912 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ 
 913 CFStringRef 
SecCertificateCopyLongDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef 
*error
) 
 915         return SecCertificateCopyShortDescription(alloc
, certificate
, error
); 
 918 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ 
 919 CFStringRef 
SecCertificateCopyShortDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef 
*error
) 
 921         CFStringRef result 
= NULL
; 
 922         OSStatus __secapiresult 
= SecCertificateInferLabel(certificate
, &result
); 
 923         if (error
!=NULL 
&& __secapiresult
!=errSecSuccess
) 
 925                 *error 
= CFErrorCreate(kCFAllocatorDefault
, kCFErrorDomainOSStatus
, 
 926                         __secapiresult 
? __secapiresult 
: CSSM_ERRCODE_INTERNAL_ERROR
, NULL
); 
 931 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ 
 932 CFDataRef 
SecCertificateCopySerialNumber(SecCertificateRef certificate
, CFErrorRef 
*error
) 
 934         CFDataRef result 
= NULL
; 
 935         OSStatus __secapiresult
; 
 938                 CertificateValues 
cv(certificate
); 
 939                 result 
= cv
.copySerialNumber(error
); 
 942         catch (const MacOSError 
&err
) { __secapiresult
=err
.osStatus(); } 
 943         catch (const CommonError 
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); } 
 944         catch (const std::bad_alloc 
&) { __secapiresult
=errSecAllocate
; } 
 945         catch (...) { __secapiresult
=errSecInternalComponent
; } 
 949 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */ 
 950 CFDataRef 
SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate
, CFErrorRef 
*error
) 
 952         CFDataRef result 
= NULL
; 
 953         OSStatus __secapiresult
; 
 956                 CertificateValues 
cv(certificate
); 
 957                 result 
= cv
.copyNormalizedIssuerContent(error
); 
 960         catch (const MacOSError 
&err
) { __secapiresult
=err
.osStatus(); } 
 961         catch (const CommonError 
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); } 
 962         catch (const std::bad_alloc 
&) { __secapiresult
=errSecAllocate
; } 
 963         catch (...) { __secapiresult
=errSecInternalComponent
; } 
 967 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */ 
 968 CFDataRef 
SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate
, CFErrorRef 
*error
) 
 970         CFDataRef result 
= NULL
; 
 971         OSStatus __secapiresult
; 
 974                 CertificateValues 
cv(certificate
); 
 975                 result 
= cv
.copyNormalizedSubjectContent(error
); 
 978         catch (const MacOSError 
&err
) { __secapiresult
=err
.osStatus(); } 
 979         catch (const CommonError 
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); } 
 980         catch (const std::bad_alloc 
&) { __secapiresult
=errSecAllocate
; } 
 981         catch (...) { __secapiresult
=errSecInternalComponent
; } 
 985 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */ 
 986 bool SecCertificateIsValidX(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
) 
 989      * deprecated function name 
 991         return SecCertificateIsValid(certificate
, verifyTime
); 
 995 CFDataRef 
SecCertificateCopyPublicKeySHA1DigestFromCertificateData(CFAllocatorRef allocator
, 
 996                                                                    CFDataRef der_certificate
) 
 998     CFDataRef result 
= NULL
; 
 999     SecCertificateRef iosCertRef 
= SecCertificateCreateWithData(allocator
, der_certificate
); 
1000     if (NULL 
== iosCertRef
) 
1005     result 
= SecCertificateCopyPublicKeySHA1Digest(iosCertRef
); 
1006     CFRelease(iosCertRef
);