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
);