2  * Copyright (c) 2000-2004,2011-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/SecBase.h> 
  25 #include <Security/SecKeychainItem.h> 
  26 #include <Security/SecKeychainItemPriv.h> 
  27 #include <Security/SecCertificatePriv.h> 
  28 #include <Security/SecItemPriv.h> 
  30 #include <security_keychain/Keychains.h> 
  31 #include <security_keychain/KeyItem.h> 
  32 #include <security_keychain/Item.h> 
  33 #include <security_keychain/Certificate.h> 
  34 #include <security_keychain/Identity.h> 
  35 #include <security_keychain/KCCursor.h> // @@@ Remove this when SecKeychainItemFindFirst moves to SecKeychainSearch 
  37 #include <securityd_client/dictionary.h> 
  38 #include <security_cdsa_utilities/Schema.h> 
  39 #include <Security/cssmapplePriv.h> 
  42 #include "SecBridge.h" 
  43 #include "KCExceptions.h" 
  45 #include "SecKeychainItemExtendedAttributes.h" 
  47 extern "C" Boolean 
SecKeyIsCDSAKey(SecKeyRef ref
); 
  50 // Given a polymorphic Sec type object, return 
  51 // its AclBearer component. 
  52 // Note: Login ACLs are not hooked into this layer; 
  53 // modules or attachments have no Sec* layer representation. 
  56 RefPointer
<AclBearer
> aclBearer(CFTypeRef itemRef
) 
  58         // well, exactly what kind of something are you? 
  59         CFTypeID id 
= CFGetTypeID(itemRef
); 
  60         if (id 
== gTypes().ItemImpl
.typeID
) { 
  61                 // keychain item. If it's in a protected group, return the group key 
  62                 if (SSGroup group 
= ItemImpl::required(SecKeychainItemRef(itemRef
))->group()) 
  64         } else if (id 
== SecKeyGetTypeID() && SecKeyIsCDSAKey((SecKeyRef
)itemRef
)) { 
  65                 // key item, return the key itself. 
  66                 if (CssmClient::Key key 
= KeyItem::required(SecKeyRef(itemRef
))->key()) 
  68         } else if (id 
== gTypes().KeychainImpl
.typeID
) { 
  69                 // keychain (this yields the database ACL) 
  70                 //@@@ not hooked up yet 
  73         MacOSError::throwMe(errSecNoAccessForItem
); 
  78 SecKeychainItemGetTypeID(void) 
  82         return gTypes().ItemImpl
.typeID
; 
  84         END_SECAPI1(_kCFRuntimeNotATypeID
) 
  89 SecKeychainItemCreateFromContent(SecItemClass itemClass
, SecKeychainAttributeList 
*attrList
, 
  90                 UInt32 length
, const void *data
, SecKeychainRef keychainRef
, 
  91                 SecAccessRef initialAccess
, SecKeychainItemRef 
*itemRef
) 
  95         KCThrowParamErrIf_(length
!=0 && data
==NULL
); 
  96         Item 
item(itemClass
, attrList
, length
, data
); 
  98                 item
->setAccess(Access::required(initialAccess
)); 
 100         Keychain keychain 
= nil
; 
 103                 keychain 
= Keychain::optional(keychainRef
); 
 104                 if ( !keychain
->exists() ) 
 106                         MacOSError::throwMe(errSecNoSuchKeychain
);      // Might be deleted or not available at this time. 
 111                 keychain 
= globals().storageManager
.defaultKeychainUI(item
); 
 116                 *itemRef 
= item
->handle(); 
 124 SecKeychainItemModifyContent(SecKeychainItemRef itemRef
, const SecKeychainAttributeList 
*attrList
, UInt32 length
, const void *data
) 
 128         Item item 
= ItemImpl::required(__itemImplRef
); 
 129         item
->modifyContent(attrList
, length
, data
); 
 136 SecKeychainItemCopyContent(SecKeychainItemRef itemRef
, SecItemClass 
*itemClass
, SecKeychainAttributeList 
*attrList
, UInt32 
*length
, void **outData
) 
 140         Item item 
= ItemImpl::required(__itemImplRef
); 
 141         item
->getContent(itemClass
, attrList
, length
, outData
); 
 148 SecKeychainItemFreeContent(SecKeychainAttributeList 
*attrList
, void *data
) 
 152         ItemImpl::freeContent(attrList
, data
); 
 159 SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef
, const SecKeychainAttributeList 
*attrList
, UInt32 length
, const void *data
) 
 163         Item item 
= ItemImpl::required(__itemImplRef
); 
 164         item
->modifyAttributesAndData(attrList
, length
, data
); 
 171 SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef
, SecKeychainAttributeInfo 
*info
, SecItemClass 
*itemClass
, SecKeychainAttributeList 
**attrList
, UInt32 
*length
, void **outData
) 
 175         Item item 
= ItemImpl::required(__itemImplRef
); 
 176         item
->getAttributesAndData(info
, itemClass
, attrList
, length
, outData
); 
 183 SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList 
*attrList
, void *data
) 
 187         ItemImpl::freeAttributesAndData(attrList
, data
); 
 194 SecKeychainItemDelete(SecKeychainItemRef itemRef
) 
 198         Item item 
= ItemImpl::required(__itemImplRef
); 
 199         Keychain keychain 
= item
->keychain(); 
 200         // item must be persistent. 
 201         KCThrowIf_( !keychain
, errSecInvalidItemRef 
); 
 204          * Before deleting the item, delete any existing Extended Attributes. 
 207         CFArrayRef attrNames 
= NULL
; 
 208         ortn 
= SecKeychainItemCopyAllExtendedAttributes(__itemImplRef
, &attrNames
, NULL
); 
 209         if(ortn 
== errSecSuccess
) { 
 210                 CFIndex numAttrs 
= CFArrayGetCount(attrNames
); 
 211                 for(CFIndex dex
=0; dex
<numAttrs
; dex
++) { 
 212                         CFStringRef attrName 
= (CFStringRef
)CFArrayGetValueAtIndex(attrNames
, dex
); 
 213                         /* setting value to NULL ==> delete */ 
 214                         SecKeychainItemSetExtendedAttribute(__itemImplRef
, attrName
, NULL
); 
 218         /* now delete the item */ 
 219         keychain
->deleteItem( item 
); 
 226 SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef
, SecKeychainRef
* keychainRef
) 
 230         // make sure this item has a keychain 
 231         Keychain kc 
= ItemImpl::required(__itemImplRef
)->keychain(); 
 234                 MacOSError::throwMe(errSecNoSuchKeychain
); 
 237         Required(keychainRef
) = kc
->handle(); 
 244 SecKeychainItemCreateCopy(SecKeychainItemRef itemRef
, SecKeychainRef destKeychainRef
, 
 245         SecAccessRef initialAccess
, SecKeychainItemRef 
*itemCopy
) 
 249         Item copy 
= ItemImpl::required(__itemImplRef
)->copyTo(Keychain::optional(destKeychainRef
), Access::optional(initialAccess
)); 
 251                 *itemCopy 
= copy
->handle(); 
 259 SecKeychainItemGetUniqueRecordID(SecKeychainItemRef itemRef
, const CSSM_DB_UNIQUE_RECORD 
**uniqueRecordID
) 
 263         Required(uniqueRecordID
) = ItemImpl::required(__itemImplRef
)->dbUniqueRecord(); 
 270 SecKeychainItemGetDLDBHandle(SecKeychainItemRef itemRef
, CSSM_DL_DB_HANDLE
* dldbHandle
) 
 274         *dldbHandle 
= ItemImpl::required(__itemImplRef
)->keychain()->database()->handle(); 
 281 OSStatus 
SecAccessCreateFromObject(CFTypeRef sourceRef
, 
 282         SecAccessRef 
*accessRef
) 
 286         Required(accessRef
);    // preflight 
 287         SecPointer
<Access
> access 
= new Access(*aclBearer(sourceRef
)); 
 288         *accessRef 
= access
->handle(); 
 297 OSStatus 
SecAccessModifyObject(SecAccessRef accessRef
, CFTypeRef sourceRef
) 
 301         Access::required(accessRef
)->setAccess(*aclBearer(sourceRef
), true); 
 308 SecKeychainItemCopyAccess(SecKeychainItemRef itemRef
, SecAccessRef
* accessRef
) 
 312         Required(accessRef
);    // preflight 
 313         SecPointer
<Access
> access 
= new Access(*aclBearer(reinterpret_cast<CFTypeRef
>(__itemImplRef
))); 
 314         *accessRef 
= access
->handle(); 
 321 SecKeychainItemSetAccess(SecKeychainItemRef itemRef
, SecAccessRef accessRef
) 
 325         Access::required(accessRef
)->setAccess(*aclBearer(reinterpret_cast<CFTypeRef
>(__itemImplRef
)), true); 
 327         ItemImpl::required(__itemImplRef
)->postItemEvent(kSecUpdateEvent
); 
 332 OSStatus 
SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef
, SecAccessRef accessRef
, UInt32 passwordLength
, const void * password
) 
 338     // try to unlock the keychain with this password first 
 339     SecKeychainRef kc 
= NULL
; 
 340     result 
= SecKeychainItemCopyKeychain(__itemImplRef
, &kc
); 
 342         SecKeychainUnlock(kc
, passwordLength
, password
, true); 
 348     // Create some credentials with this password 
 349     CssmAutoData 
data(Allocator::standard(), password
, passwordLength
); 
 350     AclFactory::PassphraseUnlockCredentials 
cred(data
, Allocator::standard()); 
 352     Access::required(accessRef
)->editAccess(*aclBearer(reinterpret_cast<CFTypeRef
>(__itemImplRef
)), true, cred
.getAccessCredentials()); 
 353     ItemImpl::required(itemRef
)->postItemEvent (kSecUpdateEvent
); 
 359 /*  Sets an item's data for legacy "KC" CoreServices APIs. 
 360     Note this version sets the data, but doesn't update the item 
 361     as the KC behavior dictates. 
 363 OSStatus 
SecKeychainItemSetData(SecKeychainItemRef itemRef
, UInt32 length
, const void* data
) 
 367         ItemImpl::required(__itemImplRef
)->setData(length
, data
); 
 372 /*  Gets an item's data for legacy "KC" CoreServices APIs. 
 373     Note this version doesn't take a SecItemClass parameter. 
 375 OSStatus 
SecKeychainItemGetData(SecKeychainItemRef itemRef
, UInt32 maxLength
, void* data
, UInt32
* actualLength
) 
 379         /* The caller either needs to specify data and maxLength or an actualLength, 
 380          * so we return either the data itself or the actual length of the data or both. 
 382         if (!((data 
&& maxLength
) || actualLength
)) { 
 383                 MacOSError::throwMe(errSecParam
); 
 385         CssmDataContainer aData
; 
 386         ItemImpl::required(__itemImplRef
)->getData(aData
); 
 388                 *actualLength 
= (UInt32
)aData
.length(); 
 391                 // Make sure the buffer is big enough 
 392                 if (aData
.length() > maxLength
) { 
 393                         MacOSError::throwMe(errSecBufferTooSmall
); 
 395                 memcpy(data
, aData
.data(), aData
.length()); 
 401 /*  Update a keychain item for legacy "KC" CoreServices APIs. 
 402     The "KC" API's do a 'set attribute', then an 'update'. 
 404 OSStatus 
SecKeychainItemUpdate(SecKeychainItemRef itemRef
) 
 408         ItemImpl::required(__itemImplRef
)->update(); 
 413 /* Add a 'floating' keychain item without UI for legacy "KC" CoreServices APIs. 
 415 OSStatus 
SecKeychainItemAddNoUI(SecKeychainRef keychainRef
, SecKeychainItemRef itemRef
) 
 419         Item item 
= ItemImpl::required(__itemImplRef
); 
 420         Keychain::optional(keychainRef
)->add(item
); 
 425 /* Add a 'floating' keychain item to the default keychain with possible UI for legacy "KC" Carbon APIs. 
 427 OSStatus 
SecKeychainItemAdd(SecKeychainItemRef itemRef
) 
 431         Item item 
= ItemImpl::required(__itemImplRef
); 
 432         Keychain defaultKeychain 
= globals().storageManager
.defaultKeychainUI(item
); 
 433         defaultKeychain
->add(item
); 
 438 /* Creates a floating keychain item for legacy "KC" CoreServices APIs 
 440 OSStatus 
SecKeychainItemCreateNew(SecItemClass itemClass
, OSType itemCreator
, UInt32 length
, const void* data
, SecKeychainItemRef
* itemRef
) 
 444         RequiredParam(itemRef
) = Item(itemClass
, itemCreator
, length
, data
, false)->handle(); 
 449 /* Gets an individual attribute for legacy "KC" CoreServices APIs 
 451 OSStatus 
SecKeychainItemGetAttribute(SecKeychainItemRef itemRef
, SecKeychainAttribute
* attribute
, UInt32
* actualLength
) 
 455         ItemImpl::required(__itemImplRef
)->getAttribute(RequiredParam(attribute
), actualLength
); 
 460 /* Sets an individual attribute for legacy "KC" CoreServices APIs 
 462 OSStatus 
SecKeychainItemSetAttribute(SecKeychainItemRef itemRef
, SecKeychainAttribute
* attribute
) 
 466         ItemImpl::required(__itemImplRef
)->setAttribute(RequiredParam(attribute
)); 
 471 /*  Finds a keychain item for legacy "KC" CoreServices APIs. 
 472     Note: This version doesn't take a SecItemClass because 
 473             SecKeychainSearchCreateFromAttributes() requires it. 
 474     @@@ This should move to SecKeychainSearch.cpp 
 476 OSStatus 
SecKeychainItemFindFirst(SecKeychainRef keychainRef
, const SecKeychainAttributeList 
*attrList
, SecKeychainSearchRef 
*searchRef
, SecKeychainItemRef 
*itemRef
) 
 482                 cursor 
= KeychainImpl::required(keychainRef
)->createCursor(attrList
); 
 484                 cursor 
= globals().storageManager
.createCursor(attrList
); 
 488         if (!cursor
->next(item
)) 
 489                 return errSecItemNotFound
; 
 491         *itemRef
=item
->handle(); 
 493                 *searchRef
=cursor
->handle(); 
 499 static OSStatus 
SecKeychainItemCreatePersistentReferenceFromCertificate(SecCertificateRef certRef
, 
 500     CFDataRef 
*persistentItemRef
, Boolean isIdentity
) 
 502         OSStatus __secapiresult
; 
 503         if (!certRef 
|| !persistentItemRef
) { 
 507         // If we already have a keychain item, we won't need to look it up by serial and issuer 
 508         SecKeychainItemRef kcItem 
= NULL
; 
 509         if (SecCertificateIsItemImplInstance(certRef
)) { 
 510                 kcItem 
= (SecKeychainItemRef
) CFRetain(certRef
); 
 513                 kcItem 
= (SecKeychainItemRef
) SecCertificateCopyKeychainItem(certRef
); 
 516                 __secapiresult 
= errSecParam
; 
 518                         Item item 
= ItemImpl::required((kcItem
)); 
 519                         item
->copyPersistentReference(*persistentItemRef
, isIdentity
); 
 520                         __secapiresult 
= errSecSuccess
; 
 524                 if (__secapiresult 
== errSecSuccess
) { 
 525                         return __secapiresult
; 
 529         // Certificate does not have a keychain item reference; look it up by serial and issuer 
 530         SecCertificateRef certItem 
= NULL
; 
 531         if (SecCertificateIsItemImplInstance(certRef
)) { 
 532                 certItem 
= SecCertificateCreateFromItemImplInstance(certRef
); 
 535                 certItem 
= (SecCertificateRef
) CFRetain(certRef
); 
 538         CFErrorRef errorRef 
= NULL
; 
 539         CFDataRef serialData 
= SecCertificateCopySerialNumber(certItem
, &errorRef
); 
 541                 CFIndex err 
= CFErrorGetCode(errorRef
); 
 543                 if (serialData
) { CFRelease(serialData
); } 
 544                 if (certItem
) { CFRelease(certItem
); } 
 545                 return (OSStatus
)err
; 
 547         CFDataRef issuerData 
= SecCertificateCopyNormalizedIssuerContent(certItem
, &errorRef
); 
 549                 CFIndex err 
= CFErrorGetCode(errorRef
); 
 551                 if (serialData
) { CFRelease(serialData
); } 
 552                 if (issuerData
) { CFRelease(issuerData
); } 
 553                 if (certItem
) { CFRelease(certItem
); } 
 554                 return (OSStatus
)err
; 
 558                 // look up ItemImpl cert in keychain by normalized issuer and serial number 
 559                 StorageManager::KeychainList keychains
; 
 560                 globals().storageManager
.optionalSearchList(NULL
, keychains
); 
 561                 KCCursor 
cursor(Certificate::cursorForIssuerAndSN_CF(keychains
, issuerData
, serialData
)); 
 563                 if (!cursor
->next(item
)) { 
 564                         MacOSError::throwMe(errSecItemNotFound
); 
 566                 item
->copyPersistentReference(*persistentItemRef
, false); 
 567                 __secapiresult 
= errSecSuccess
; 
 569         catch (const MacOSError 
&err
) { __secapiresult
=err
.osStatus(); } 
 570         catch (const CommonError 
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); } 
 571         catch (const std::bad_alloc 
&) { __secapiresult
=errSecAllocate
; } 
 572         catch (...) { __secapiresult
=errSecInternalComponent
; } 
 575                 CFRelease(serialData
); 
 577                 CFRelease(issuerData
); 
 581         return __secapiresult
; 
 584 OSStatus 
SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef
, CFDataRef 
*persistentItemRef
) 
 586     /* We're in the unified world, where SecCertificateRef is not a SecKeychainItemRef. */ 
 587     if (!itemRef 
|| !persistentItemRef
) { 
 590     // first, query the iOS keychain 
 592         const void *keys
[] = { kSecValueRef
, kSecReturnPersistentRef
, kSecAttrNoLegacy 
}; 
 593         const void *values
[] = { itemRef
, kCFBooleanTrue
, kCFBooleanTrue 
}; 
 594         CFRef
<CFDictionaryRef
> query 
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, 
 595                                                           sizeof(keys
) / sizeof(*keys
), 
 596                                                           &kCFTypeDictionaryKeyCallBacks
, 
 597                                                           &kCFTypeDictionaryValueCallBacks
); 
 598         OSStatus status 
= SecItemCopyMatching(query
, (CFTypeRef 
*)persistentItemRef
); 
 599         if (status 
== errSecSuccess
) { 
 603     // otherwise, handle certificate 
 604     SecCertificateRef certRef 
= NULL
; 
 605     CFTypeID itemType 
= CFGetTypeID(itemRef
); 
 606     bool isIdentity 
= false; 
 607     if (itemType 
== SecIdentityGetTypeID()) { 
 608         SecIdentityCopyCertificate((SecIdentityRef
)itemRef
, &certRef
); 
 611     else if (itemType 
== SecCertificateGetTypeID()) { 
 612         certRef 
= (SecCertificateRef
) CFRetain(itemRef
); 
 615         OSStatus status 
= SecKeychainItemCreatePersistentReferenceFromCertificate(certRef
, persistentItemRef
, isIdentity
); 
 619     // otherwise, not a certificate, so proceed as usual for keychain item 
 622     Item item 
= ItemImpl::required(itemRef
); 
 623     item
->copyPersistentReference(*persistentItemRef
, false); 
 627 OSStatus 
SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef
, SecKeychainItemRef 
*itemRef
) 
 631     KCThrowParamErrIf_(!persistentItemRef 
|| !itemRef
); 
 632     // first, query the iOS keychain 
 634         const void *keys
[] = { kSecValuePersistentRef
, kSecReturnRef
, kSecAttrNoLegacy
}; 
 635         const void *values
[] = { persistentItemRef
, kCFBooleanTrue
, kCFBooleanTrue 
}; 
 636         CFRef
<CFDictionaryRef
> query 
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, 
 637                                                           sizeof(keys
) / sizeof(*keys
), 
 638                                                           &kCFTypeDictionaryKeyCallBacks
, 
 639                                                           &kCFTypeDictionaryValueCallBacks
); 
 640         OSStatus status 
= SecItemCopyMatching(query
, (CFTypeRef 
*)itemRef
); 
 641         if (status 
== errSecSuccess
) { 
 645     // otherwise, proceed as usual for keychain item 
 646     CFTypeRef result 
= NULL
; 
 647     bool isIdentityRef 
= false; 
 648     Item item 
= ItemImpl::makeFromPersistentReference(persistentItemRef
, &isIdentityRef
); 
 650         // item was stored as an identity, attempt to reconstitute it 
 651         SecPointer
<Certificate
> certificatePtr(static_cast<Certificate 
*>(item
.get())); 
 652         StorageManager::KeychainList keychains
; 
 653         globals().storageManager
.optionalSearchList(NULL
, keychains
); 
 654         SecPointer
<Identity
> identityPtr(new Identity(keychains
, certificatePtr
)); 
 655         result 
= identityPtr
->handle(); 
 656         KCThrowIf_( !result
, errSecItemNotFound 
); 
 659         result 
= item
->handle(); 
 661     *itemRef 
= (SecKeychainItemRef
) result
; 
 663     /* see if we should convert outgoing item to a unified SecCertificateRef */ 
 664     SecItemClass tmpItemClass 
= Schema::itemClassFor(item
->recordType()); 
 665     if (tmpItemClass 
== kSecCertificateItemClass 
&& !isIdentityRef
) { 
 666         SecPointer
<Certificate
> certificate(static_cast<Certificate 
*>(&*item
)); 
 667         CssmData certData 
= certificate
->data(); 
 668         CFDataRef data 
= NULL
; 
 669         if (certData
.Data 
&& certData
.Length
) { 
 670             data 
= CFDataCreate(NULL
, certData
.Data
, certData
.Length
); 
 674             if (certData
.Data 
&& !certData
.Length
) { 
 675                 syslog(LOG_ERR
, "WARNING: SecKeychainItemCopyFromPersistentReference skipped a zero-length certificate (data=0x%lX)", 
 676                        (uintptr_t)certData
.Data
); 
 677                 return errSecDataNotAvailable
; 
 680                 syslog(LOG_ERR
, "WARNING: SecKeychainItemCopyFromPersistentReference failed to retrieve certificate data (length=%ld, data=0x%lX)", 
 681                        (long)certData
.Length
, (uintptr_t)certData
.Data
); 
 682                 return errSecInternal
; 
 685         SecKeychainItemRef tmpRef 
= *itemRef
; 
 686         *itemRef 
= (SecKeychainItemRef
) SecCertificateCreateWithKeychainItem(NULL
, data
, tmpRef
); 
 696 OSStatus 
SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef
, CFDataRef 
*recordIdentifier
) 
 701         RequiredParam (recordIdentifier
); 
 702         Item item 
= ItemImpl::required(__itemImplRef
); 
 703         item
->copyRecordIdentifier (data
); 
 704         *recordIdentifier 
= ::CFDataCreate(kCFAllocatorDefault
, (UInt8
*) data
.Data
, data
.Length
); 
 711 SecKeychainItemCopyFromRecordIdentifier(SecKeychainRef keychainRef
, 
 712                                                                                 SecKeychainItemRef 
*itemRef
, 
 713                                                                                 CFDataRef recordIdentifier
) 
 717         // make a local Keychain reference 
 718         RequiredParam (keychainRef
); 
 719         Keychain keychain 
= KeychainImpl::optional (keychainRef
); 
 720         RequiredParam (itemRef
); 
 721         RequiredParam (recordIdentifier
); 
 723         Db 
db(keychain
->database()); 
 725         // make a raw database call to get the data 
 726         CSSM_DL_DB_HANDLE dbHandle 
= db
.handle (); 
 727         CSSM_DB_UNIQUE_RECORD uniqueRecord
; 
 729         // according to source, we should be able to reconsitute the uniqueRecord 
 730         // from the data we earlier retained 
 732         // prepare the record id 
 733         memset (&uniqueRecord
, 0, sizeof (uniqueRecord
)); 
 734         uniqueRecord
.RecordIdentifier
.Data 
= (uint8
*) CFDataGetBytePtr (recordIdentifier
); 
 735         uniqueRecord
.RecordIdentifier
.Length 
= CFDataGetLength (recordIdentifier
); 
 737         // convert this unique id to a CSSM_DB_UNIQUE_RECORD that works for the CSP/DL 
 738         CSSM_DB_UNIQUE_RECORD_PTR outputUniqueRecordPtr
; 
 740         result 
= CSSM_DL_PassThrough (dbHandle
, CSSM_APPLECSPDL_DB_CONVERT_RECORD_IDENTIFIER
, &uniqueRecord
, (void**) &outputUniqueRecordPtr
); 
 741         KCThrowIf_(result 
!= 0, errSecItemNotFound
); 
 743         // from this, get the record type 
 744         CSSM_DB_RECORD_ATTRIBUTE_DATA attributeData
; 
 745         memset (&attributeData
, 0, sizeof (attributeData
)); 
 747         result 
= CSSM_DL_DataGetFromUniqueRecordId (dbHandle
, outputUniqueRecordPtr
, &attributeData
, NULL
); 
 748         KCThrowIf_(result 
!= 0, errSecItemNotFound
); 
 749         CSSM_DB_RECORDTYPE recordType 
= attributeData
.DataRecordType
; 
 751         // make the unique record item -- precursor to creation of a SecKeychainItemRef 
 752         DbUniqueRecord 
unique(db
); 
 753         CSSM_DB_UNIQUE_RECORD_PTR 
*uniquePtr 
= unique
; 
 754         *uniquePtr 
= outputUniqueRecordPtr
; 
 757         Item item 
= keychain
->item (recordType
, unique
); 
 760                 *itemRef 
= item
->handle(); 
 766 OSStatus 
SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass
, 
 767                 UInt32 length
, const void *data
, SecKeychainRef keychainRef
, 
 768                 SecAccessRef initialAccess
, SecKeychainItemRef 
*itemRef
, CFDataRef 
*localID
) 
 772         KCThrowParamErrIf_(length
!=0 && data
==NULL
); 
 773         RequiredParam (localID
); 
 774         RequiredParam (keychainRef
); 
 776         Item 
item(itemClass
, (uint32
) 0, length
, data
, true); 
 778                 item
->setAccess(Access::required(initialAccess
)); 
 780         Keychain keychain 
= Keychain::optional(keychainRef
); 
 781         if (!keychain
->exists()) 
 783                 MacOSError::throwMe(errSecNoSuchKeychain
);      // Might be deleted or not available at this time. 
 786         item
->doNotEncrypt (); 
 791         catch (const CommonError 
&err
) 
 793                 if (err
.osStatus () == errSecNoSuchClass
) 
 795                         // the only time this should happen is if the item is a certificate (for keychain syncing) 
 796                         if (itemClass 
== CSSM_DL_DB_RECORD_X509_CERTIFICATE
) 
 798                                 // create the certificate relation 
 799                                 Db 
db(keychain
->database()); 
 801                                 db
->createRelation(CSSM_DL_DB_RECORD_X509_CERTIFICATE
, 
 802                                                 "CSSM_DL_DB_RECORD_X509_CERTIFICATE", 
 803                                                 Schema::X509CertificateSchemaAttributeCount
, 
 804                                                 Schema::X509CertificateSchemaAttributeList
, 
 805                                                 Schema::X509CertificateSchemaIndexCount
, 
 806                                                 Schema::X509CertificateSchemaIndexList
); 
 807                                 keychain
->keychainSchema()->didCreateRelation( 
 808                                                 CSSM_DL_DB_RECORD_X509_CERTIFICATE
, 
 809                                                 "CSSM_DL_DB_RECORD_X509_CERTIFICATE", 
 810                                                 Schema::X509CertificateSchemaAttributeCount
, 
 811                                                 Schema::X509CertificateSchemaAttributeList
, 
 812                                                 Schema::X509CertificateSchemaIndexCount
, 
 813                                                 Schema::X509CertificateSchemaIndexList
); 
 815                                 // add the item again 
 826                 *itemRef 
= item
->handle(); 
 829         item
->copyRecordIdentifier (recordID
); 
 831         *localID 
= CFDataCreate(kCFAllocatorDefault
, (UInt8
*) recordID
.Data
, recordID
.Length
); 
 832         free (recordID
.Data
); 
 837 OSStatus 
SecKeychainItemCopyAttributesAndEncryptedData(SecKeychainItemRef itemRef
, SecKeychainAttributeInfo 
*info
, 
 838                                                                                                            SecItemClass 
*itemClass
, SecKeychainAttributeList 
**attrList
, 
 839                                                                                                            UInt32 
*length
, void **outData
) 
 843         Item item 
= ItemImpl::required(__itemImplRef
); 
 844         item
->doNotEncrypt (); 
 845         item
->getAttributesAndData(info
, itemClass
, attrList
, length
, outData
); 
 850 OSStatus 
SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef
, UInt32 length
, const void *data
) 
 854         Item item 
= ItemImpl::required(__itemImplRef
); 
 855         item
->doNotEncrypt (); 
 856         item
->modifyAttributesAndData(NULL
, length
, data
);