]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
fa7225c8 | 2 | * Copyright (c) 2000-2004,2011-2016 Apple Inc. All Rights Reserved. |
427c49bc | 3 | * |
b1ab9ed8 | 4 | * @APPLE_LICENSE_HEADER_START@ |
5c19dc3a | 5 | * |
b1ab9ed8 A |
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. | |
5c19dc3a | 12 | * |
b1ab9ed8 A |
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. | |
5c19dc3a | 20 | * |
b1ab9ed8 A |
21 | * @APPLE_LICENSE_HEADER_END@ |
22 | */ | |
23 | ||
427c49bc | 24 | #include <Security/SecBase.h> |
b1ab9ed8 A |
25 | #include <Security/SecKeychainItem.h> |
26 | #include <Security/SecKeychainItemPriv.h> | |
5c19dc3a | 27 | #include <Security/SecCertificatePriv.h> |
fa7225c8 | 28 | #include <Security/SecItemPriv.h> |
b1ab9ed8 A |
29 | |
30 | #include <security_keychain/Keychains.h> | |
31 | #include <security_keychain/KeyItem.h> | |
32 | #include <security_keychain/Item.h> | |
427c49bc A |
33 | #include <security_keychain/Certificate.h> |
34 | #include <security_keychain/Identity.h> | |
b1ab9ed8 A |
35 | #include <security_keychain/KCCursor.h> // @@@ Remove this when SecKeychainItemFindFirst moves to SecKeychainSearch |
36 | ||
37 | #include <securityd_client/dictionary.h> | |
38 | #include <security_cdsa_utilities/Schema.h> | |
39 | #include <Security/cssmapplePriv.h> | |
5c19dc3a | 40 | #include <syslog.h> |
866f8763 | 41 | #include <os/activity.h> |
b1ab9ed8 A |
42 | |
43 | #include "SecBridge.h" | |
44 | #include "KCExceptions.h" | |
45 | #include "Access.h" | |
46 | #include "SecKeychainItemExtendedAttributes.h" | |
47 | ||
fa7225c8 | 48 | extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); |
5c19dc3a | 49 | |
b1ab9ed8 A |
50 | // |
51 | // Given a polymorphic Sec type object, return | |
52 | // its AclBearer component. | |
53 | // Note: Login ACLs are not hooked into this layer; | |
54 | // modules or attachments have no Sec* layer representation. | |
55 | // | |
427c49bc | 56 | static |
b1ab9ed8 A |
57 | RefPointer<AclBearer> aclBearer(CFTypeRef itemRef) |
58 | { | |
59 | // well, exactly what kind of something are you? | |
60 | CFTypeID id = CFGetTypeID(itemRef); | |
61 | if (id == gTypes().ItemImpl.typeID) { | |
62 | // keychain item. If it's in a protected group, return the group key | |
63 | if (SSGroup group = ItemImpl::required(SecKeychainItemRef(itemRef))->group()) | |
64 | return &*group; | |
fa7225c8 | 65 | } else if (id == SecKeyGetTypeID() && SecKeyIsCDSAKey((SecKeyRef)itemRef)) { |
b1ab9ed8 A |
66 | // key item, return the key itself. |
67 | if (CssmClient::Key key = KeyItem::required(SecKeyRef(itemRef))->key()) | |
68 | return &*key; | |
69 | } else if (id == gTypes().KeychainImpl.typeID) { | |
70 | // keychain (this yields the database ACL) | |
71 | //@@@ not hooked up yet | |
72 | } | |
73 | // Guess not. Bummer | |
74 | MacOSError::throwMe(errSecNoAccessForItem); | |
75 | } | |
76 | ||
77 | ||
78 | CFTypeID | |
79 | SecKeychainItemGetTypeID(void) | |
80 | { | |
81 | BEGIN_SECAPI | |
82 | ||
83 | return gTypes().ItemImpl.typeID; | |
84 | ||
85 | END_SECAPI1(_kCFRuntimeNotATypeID) | |
86 | } | |
87 | ||
88 | ||
89 | OSStatus | |
90 | SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAttributeList *attrList, | |
91 | UInt32 length, const void *data, SecKeychainRef keychainRef, | |
92 | SecAccessRef initialAccess, SecKeychainItemRef *itemRef) | |
93 | { | |
fa7225c8 | 94 | BEGIN_SECAPI |
866f8763 A |
95 | os_activity_t activity = os_activity_create("SecKeychainItemCreateFromContent", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
96 | os_activity_scope(activity); | |
97 | os_release(activity); | |
fa7225c8 A |
98 | |
99 | KCThrowParamErrIf_(length!=0 && data==NULL); | |
100 | Item item(itemClass, attrList, length, data); | |
101 | if (initialAccess) { | |
102 | item->setAccess(Access::required(initialAccess)); | |
103 | } | |
104 | Keychain keychain = nil; | |
105 | try | |
106 | { | |
107 | keychain = Keychain::optional(keychainRef); | |
108 | if ( !keychain->exists() ) | |
109 | { | |
110 | MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. | |
111 | } | |
112 | } | |
113 | catch(...) | |
114 | { | |
115 | keychain = globals().storageManager.defaultKeychainUI(item); | |
116 | } | |
117 | ||
118 | keychain->add(item); | |
119 | if (itemRef) { | |
120 | *itemRef = item->handle(); | |
121 | } | |
b1ab9ed8 | 122 | |
b1ab9ed8 A |
123 | END_SECAPI |
124 | } | |
125 | ||
126 | ||
127 | OSStatus | |
128 | SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data) | |
129 | { | |
fa7225c8 | 130 | BEGIN_SECKCITEMAPI |
866f8763 A |
131 | os_activity_t activity = os_activity_create("SecKeychainItemModifyContent", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
132 | os_activity_scope(activity); | |
133 | os_release(activity); | |
fa7225c8 A |
134 | |
135 | Item item = ItemImpl::required(__itemImplRef); | |
136 | item->modifyContent(attrList, length, data); | |
137 | ||
138 | END_SECKCITEMAPI | |
b1ab9ed8 A |
139 | } |
140 | ||
141 | ||
142 | OSStatus | |
143 | SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass *itemClass, SecKeychainAttributeList *attrList, UInt32 *length, void **outData) | |
144 | { | |
fa7225c8 | 145 | BEGIN_SECKCITEMAPI |
866f8763 A |
146 | os_activity_t activity = os_activity_create("SecKeychainItemCopyContent", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
147 | os_activity_scope(activity); | |
148 | os_release(activity); | |
5c19dc3a | 149 | |
fa7225c8 A |
150 | Item item = ItemImpl::required(__itemImplRef); |
151 | item->getContent(itemClass, attrList, length, outData); | |
5c19dc3a | 152 | |
fa7225c8 | 153 | END_SECKCITEMAPI |
b1ab9ed8 A |
154 | } |
155 | ||
156 | ||
157 | OSStatus | |
158 | SecKeychainItemFreeContent(SecKeychainAttributeList *attrList, void *data) | |
159 | { | |
160 | BEGIN_SECAPI | |
866f8763 A |
161 | os_activity_t activity = os_activity_create("SecKeychainItemFreeContent", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
162 | os_activity_scope(activity); | |
163 | os_release(activity); | |
fa7225c8 A |
164 | |
165 | ItemImpl::freeContent(attrList, data); | |
166 | ||
b1ab9ed8 A |
167 | END_SECAPI |
168 | } | |
169 | ||
170 | ||
171 | OSStatus | |
172 | SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data) | |
173 | { | |
fa7225c8 | 174 | BEGIN_SECKCITEMAPI |
866f8763 A |
175 | os_activity_t activity = os_activity_create("SecKeychainItemModifyAttributesAndData", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
176 | os_activity_scope(activity); | |
177 | os_release(activity); | |
fa7225c8 A |
178 | |
179 | Item item = ItemImpl::required(__itemImplRef); | |
180 | item->modifyAttributesAndData(attrList, length, data); | |
181 | ||
182 | END_SECKCITEMAPI | |
b1ab9ed8 A |
183 | } |
184 | ||
185 | ||
186 | OSStatus | |
187 | SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo *info, SecItemClass *itemClass, SecKeychainAttributeList **attrList, UInt32 *length, void **outData) | |
188 | { | |
fa7225c8 | 189 | BEGIN_SECKCITEMAPI |
5c19dc3a | 190 | |
fa7225c8 A |
191 | Item item = ItemImpl::required(__itemImplRef); |
192 | item->getAttributesAndData(info, itemClass, attrList, length, outData); | |
5c19dc3a | 193 | |
fa7225c8 | 194 | END_SECKCITEMAPI |
b1ab9ed8 A |
195 | } |
196 | ||
197 | ||
198 | OSStatus | |
199 | SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList *attrList, void *data) | |
200 | { | |
201 | BEGIN_SECAPI | |
fa7225c8 A |
202 | |
203 | ItemImpl::freeAttributesAndData(attrList, data); | |
204 | ||
b1ab9ed8 A |
205 | END_SECAPI |
206 | } | |
207 | ||
208 | ||
209 | OSStatus | |
210 | SecKeychainItemDelete(SecKeychainItemRef itemRef) | |
211 | { | |
fa7225c8 | 212 | BEGIN_SECKCITEMAPI |
866f8763 A |
213 | os_activity_t activity = os_activity_create("SecKeychainItemDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
214 | os_activity_scope(activity); | |
215 | os_release(activity); | |
fa7225c8 A |
216 | |
217 | Item item = ItemImpl::required(__itemImplRef); | |
218 | Keychain keychain = item->keychain(); | |
219 | // item must be persistent. | |
220 | KCThrowIf_( !keychain, errSecInvalidItemRef ); | |
221 | ||
222 | /* | |
223 | * Before deleting the item, delete any existing Extended Attributes. | |
224 | */ | |
225 | OSStatus ortn; | |
226 | CFArrayRef attrNames = NULL; | |
227 | ortn = SecKeychainItemCopyAllExtendedAttributes(__itemImplRef, &attrNames, NULL); | |
228 | if(ortn == errSecSuccess) { | |
229 | CFIndex numAttrs = CFArrayGetCount(attrNames); | |
230 | for(CFIndex dex=0; dex<numAttrs; dex++) { | |
231 | CFStringRef attrName = (CFStringRef)CFArrayGetValueAtIndex(attrNames, dex); | |
232 | /* setting value to NULL ==> delete */ | |
233 | SecKeychainItemSetExtendedAttribute(__itemImplRef, attrName, NULL); | |
5c19dc3a A |
234 | } |
235 | } | |
5c19dc3a | 236 | |
fa7225c8 A |
237 | /* now delete the item */ |
238 | keychain->deleteItem( item ); | |
5c19dc3a | 239 | |
fa7225c8 | 240 | END_SECKCITEMAPI |
b1ab9ed8 A |
241 | } |
242 | ||
243 | ||
244 | OSStatus | |
245 | SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef* keychainRef) | |
246 | { | |
fa7225c8 | 247 | BEGIN_SECKCITEMAPI |
5c19dc3a | 248 | |
fa7225c8 A |
249 | // make sure this item has a keychain |
250 | Keychain kc = ItemImpl::required(__itemImplRef)->keychain(); | |
251 | if (kc == NULL) | |
5c19dc3a | 252 | { |
fa7225c8 | 253 | MacOSError::throwMe(errSecNoSuchKeychain); |
5c19dc3a | 254 | } |
5c19dc3a | 255 | |
fa7225c8 A |
256 | Required(keychainRef) = kc->handle(); |
257 | ||
258 | END_SECKCITEMAPI | |
b1ab9ed8 A |
259 | } |
260 | ||
261 | ||
262 | OSStatus | |
263 | SecKeychainItemCreateCopy(SecKeychainItemRef itemRef, SecKeychainRef destKeychainRef, | |
264 | SecAccessRef initialAccess, SecKeychainItemRef *itemCopy) | |
265 | { | |
fa7225c8 | 266 | BEGIN_SECKCITEMAPI |
866f8763 A |
267 | os_activity_t activity = os_activity_create("SecKeychainItemCreateCopy", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
268 | os_activity_scope(activity); | |
269 | os_release(activity); | |
fa7225c8 A |
270 | |
271 | Item copy = ItemImpl::required(__itemImplRef)->copyTo(Keychain::optional(destKeychainRef), Access::optional(initialAccess)); | |
272 | if (itemCopy) { | |
273 | *itemCopy = copy->handle(); | |
5c19dc3a | 274 | } |
5c19dc3a | 275 | |
fa7225c8 | 276 | END_SECKCITEMAPI |
b1ab9ed8 A |
277 | } |
278 | ||
279 | ||
280 | OSStatus | |
281 | SecKeychainItemGetUniqueRecordID(SecKeychainItemRef itemRef, const CSSM_DB_UNIQUE_RECORD **uniqueRecordID) | |
282 | { | |
fa7225c8 | 283 | BEGIN_SECKCITEMAPI |
866f8763 A |
284 | os_activity_t activity = os_activity_create("SecKeychainItemGetUniqueRecordID", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
285 | os_activity_scope(activity); | |
286 | os_release(activity); | |
fa7225c8 A |
287 | |
288 | Required(uniqueRecordID) = ItemImpl::required(__itemImplRef)->dbUniqueRecord(); | |
289 | ||
290 | END_SECKCITEMAPI | |
b1ab9ed8 A |
291 | } |
292 | ||
293 | ||
294 | OSStatus | |
295 | SecKeychainItemGetDLDBHandle(SecKeychainItemRef itemRef, CSSM_DL_DB_HANDLE* dldbHandle) | |
296 | { | |
fa7225c8 | 297 | BEGIN_SECKCITEMAPI |
866f8763 A |
298 | os_activity_t activity = os_activity_create("SecKeychainItemGetDLDBHandle", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
299 | os_activity_scope(activity); | |
300 | os_release(activity); | |
fa7225c8 A |
301 | |
302 | *dldbHandle = ItemImpl::required(__itemImplRef)->keychain()->database()->handle(); | |
303 | ||
304 | END_SECKCITEMAPI | |
b1ab9ed8 A |
305 | } |
306 | ||
427c49bc A |
307 | #if 0 |
308 | static | |
b1ab9ed8 A |
309 | OSStatus SecAccessCreateFromObject(CFTypeRef sourceRef, |
310 | SecAccessRef *accessRef) | |
311 | { | |
312 | BEGIN_SECAPI | |
fa7225c8 | 313 | |
b1ab9ed8 A |
314 | Required(accessRef); // preflight |
315 | SecPointer<Access> access = new Access(*aclBearer(sourceRef)); | |
316 | *accessRef = access->handle(); | |
fa7225c8 | 317 | |
b1ab9ed8 A |
318 | END_SECAPI |
319 | } | |
320 | ||
321 | ||
322 | /*! | |
323 | */ | |
427c49bc | 324 | static |
b1ab9ed8 A |
325 | OSStatus SecAccessModifyObject(SecAccessRef accessRef, CFTypeRef sourceRef) |
326 | { | |
327 | BEGIN_SECAPI | |
fa7225c8 | 328 | |
b1ab9ed8 | 329 | Access::required(accessRef)->setAccess(*aclBearer(sourceRef), true); |
fa7225c8 | 330 | |
b1ab9ed8 A |
331 | END_SECAPI |
332 | } | |
427c49bc | 333 | #endif |
b1ab9ed8 A |
334 | |
335 | OSStatus | |
336 | SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef* accessRef) | |
337 | { | |
fa7225c8 | 338 | BEGIN_SECKCITEMAPI |
866f8763 A |
339 | os_activity_t activity = os_activity_create("SecKeychainItemCopyAccess", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
340 | os_activity_scope(activity); | |
341 | os_release(activity); | |
b1ab9ed8 A |
342 | |
343 | Required(accessRef); // preflight | |
fa7225c8 | 344 | SecPointer<Access> access = new Access(*aclBearer(reinterpret_cast<CFTypeRef>(__itemImplRef))); |
b1ab9ed8 A |
345 | *accessRef = access->handle(); |
346 | ||
fa7225c8 | 347 | END_SECKCITEMAPI |
b1ab9ed8 A |
348 | } |
349 | ||
350 | ||
351 | OSStatus | |
352 | SecKeychainItemSetAccess(SecKeychainItemRef itemRef, SecAccessRef accessRef) | |
353 | { | |
fa7225c8 | 354 | BEGIN_SECKCITEMAPI |
866f8763 A |
355 | os_activity_t activity = os_activity_create("SecKeychainItemSetAccess", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
356 | os_activity_scope(activity); | |
357 | os_release(activity); | |
b1ab9ed8 | 358 | |
fa7225c8 | 359 | Access::required(accessRef)->setAccess(*aclBearer(reinterpret_cast<CFTypeRef>(__itemImplRef)), true); |
b1ab9ed8 | 360 | |
fa7225c8 | 361 | ItemImpl::required(__itemImplRef)->postItemEvent(kSecUpdateEvent); |
427c49bc | 362 | |
fa7225c8 | 363 | END_SECKCITEMAPI |
b1ab9ed8 A |
364 | } |
365 | ||
fa7225c8 A |
366 | OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) |
367 | { | |
368 | BEGIN_SECKCITEMAPI | |
866f8763 A |
369 | os_activity_t activity = os_activity_create("SecKeychainItemSetAccessWithPassword", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
370 | os_activity_scope(activity); | |
371 | os_release(activity); | |
e3d460c9 A |
372 | |
373 | OSStatus result; | |
374 | ||
866f8763 A |
375 | if(!__itemImplRef) { |
376 | return errSecParam; | |
377 | } | |
378 | ||
e3d460c9 A |
379 | // try to unlock the keychain with this password first |
380 | SecKeychainRef kc = NULL; | |
fa7225c8 | 381 | result = SecKeychainItemCopyKeychain(__itemImplRef, &kc); |
e3d460c9 A |
382 | if(!result) { |
383 | SecKeychainUnlock(kc, passwordLength, password, true); | |
384 | if(kc) { | |
385 | CFRelease(kc); | |
386 | } | |
387 | } | |
388 | ||
389 | // Create some credentials with this password | |
390 | CssmAutoData data(Allocator::standard(), password, passwordLength); | |
391 | AclFactory::PassphraseUnlockCredentials cred(data, Allocator::standard()); | |
392 | ||
fa7225c8 | 393 | Access::required(accessRef)->editAccess(*aclBearer(reinterpret_cast<CFTypeRef>(__itemImplRef)), true, cred.getAccessCredentials()); |
e3d460c9 A |
394 | ItemImpl::required(itemRef)->postItemEvent (kSecUpdateEvent); |
395 | ||
fa7225c8 | 396 | END_SECKCITEMAPI |
e3d460c9 A |
397 | } |
398 | ||
399 | ||
b1ab9ed8 | 400 | /* Sets an item's data for legacy "KC" CoreServices APIs. |
427c49bc | 401 | Note this version sets the data, but doesn't update the item |
b1ab9ed8 A |
402 | as the KC behavior dictates. |
403 | */ | |
404 | OSStatus SecKeychainItemSetData(SecKeychainItemRef itemRef, UInt32 length, const void* data) | |
405 | { | |
fa7225c8 | 406 | BEGIN_SECKCITEMAPI |
866f8763 A |
407 | os_activity_t activity = os_activity_create("SecKeychainItemSetData", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
408 | os_activity_scope(activity); | |
409 | os_release(activity); | |
fa7225c8 A |
410 | |
411 | ItemImpl::required(__itemImplRef)->setData(length, data); | |
412 | ||
413 | END_SECKCITEMAPI | |
b1ab9ed8 A |
414 | } |
415 | ||
416 | /* Gets an item's data for legacy "KC" CoreServices APIs. | |
417 | Note this version doesn't take a SecItemClass parameter. | |
418 | */ | |
419 | OSStatus SecKeychainItemGetData(SecKeychainItemRef itemRef, UInt32 maxLength, void* data, UInt32* actualLength) | |
420 | { | |
fa7225c8 | 421 | BEGIN_SECKCITEMAPI |
866f8763 A |
422 | os_activity_t activity = os_activity_create("SecKeychainItemGetData", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
423 | os_activity_scope(activity); | |
424 | os_release(activity); | |
b1ab9ed8 | 425 | |
fa7225c8 A |
426 | /* The caller either needs to specify data and maxLength or an actualLength, |
427 | * so we return either the data itself or the actual length of the data or both. | |
428 | */ | |
429 | if (!((data && maxLength) || actualLength)) { | |
430 | MacOSError::throwMe(errSecParam); | |
431 | } | |
432 | CssmDataContainer aData; | |
433 | ItemImpl::required(__itemImplRef)->getData(aData); | |
434 | if (actualLength) { | |
435 | *actualLength = (UInt32)aData.length(); | |
436 | } | |
437 | if (data) { | |
438 | // Make sure the buffer is big enough | |
439 | if (aData.length() > maxLength) { | |
440 | MacOSError::throwMe(errSecBufferTooSmall); | |
b1ab9ed8 | 441 | } |
fa7225c8 A |
442 | memcpy(data, aData.data(), aData.length()); |
443 | } | |
444 | ||
445 | END_SECKCITEMAPI | |
b1ab9ed8 A |
446 | } |
447 | ||
448 | /* Update a keychain item for legacy "KC" CoreServices APIs. | |
449 | The "KC" API's do a 'set attribute', then an 'update'. | |
450 | */ | |
451 | OSStatus SecKeychainItemUpdate(SecKeychainItemRef itemRef) | |
452 | { | |
fa7225c8 | 453 | BEGIN_SECKCITEMAPI |
866f8763 A |
454 | os_activity_t activity = os_activity_create("SecKeychainItemUpdate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
455 | os_activity_scope(activity); | |
456 | os_release(activity); | |
fa7225c8 A |
457 | |
458 | ItemImpl::required(__itemImplRef)->update(); | |
459 | ||
460 | END_SECKCITEMAPI | |
b1ab9ed8 A |
461 | } |
462 | ||
463 | /* Add a 'floating' keychain item without UI for legacy "KC" CoreServices APIs. | |
464 | */ | |
465 | OSStatus SecKeychainItemAddNoUI(SecKeychainRef keychainRef, SecKeychainItemRef itemRef) | |
466 | { | |
fa7225c8 | 467 | BEGIN_SECKCITEMAPI |
866f8763 A |
468 | os_activity_t activity = os_activity_create("SecKeychainItemAddNoUI", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
469 | os_activity_scope(activity); | |
470 | os_release(activity); | |
fa7225c8 A |
471 | |
472 | Item item = ItemImpl::required(__itemImplRef); | |
473 | Keychain::optional(keychainRef)->add(item); | |
474 | ||
475 | END_SECKCITEMAPI | |
b1ab9ed8 A |
476 | } |
477 | ||
478 | /* Add a 'floating' keychain item to the default keychain with possible UI for legacy "KC" Carbon APIs. | |
479 | */ | |
480 | OSStatus SecKeychainItemAdd(SecKeychainItemRef itemRef) | |
481 | { | |
fa7225c8 | 482 | BEGIN_SECKCITEMAPI |
866f8763 A |
483 | os_activity_t activity = os_activity_create("SecKeychainItemAdd", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
484 | os_activity_scope(activity); | |
485 | os_release(activity); | |
fa7225c8 A |
486 | |
487 | Item item = ItemImpl::required(__itemImplRef); | |
488 | Keychain defaultKeychain = globals().storageManager.defaultKeychainUI(item); | |
489 | defaultKeychain->add(item); | |
490 | ||
491 | END_SECKCITEMAPI | |
b1ab9ed8 A |
492 | } |
493 | ||
494 | /* Creates a floating keychain item for legacy "KC" CoreServices APIs | |
495 | */ | |
496 | OSStatus SecKeychainItemCreateNew(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, SecKeychainItemRef* itemRef) | |
497 | { | |
fa7225c8 | 498 | BEGIN_SECAPI |
866f8763 A |
499 | os_activity_t activity = os_activity_create("SecKeychainItemCreateNew", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
500 | os_activity_scope(activity); | |
501 | os_release(activity); | |
fa7225c8 A |
502 | |
503 | RequiredParam(itemRef) = Item(itemClass, itemCreator, length, data, false)->handle(); | |
504 | ||
b1ab9ed8 A |
505 | END_SECAPI |
506 | } | |
507 | ||
508 | /* Gets an individual attribute for legacy "KC" CoreServices APIs | |
509 | */ | |
510 | OSStatus SecKeychainItemGetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute, UInt32* actualLength) | |
511 | { | |
fa7225c8 | 512 | BEGIN_SECKCITEMAPI |
866f8763 A |
513 | os_activity_t activity = os_activity_create("SecKeychainItemGetAttribute", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
514 | os_activity_scope(activity); | |
515 | os_release(activity); | |
fa7225c8 A |
516 | |
517 | ItemImpl::required(__itemImplRef)->getAttribute(RequiredParam(attribute), actualLength); | |
518 | ||
519 | END_SECKCITEMAPI | |
b1ab9ed8 A |
520 | } |
521 | ||
522 | /* Sets an individual attribute for legacy "KC" CoreServices APIs | |
523 | */ | |
524 | OSStatus SecKeychainItemSetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute) | |
525 | { | |
fa7225c8 | 526 | BEGIN_SECKCITEMAPI |
866f8763 A |
527 | os_activity_t activity = os_activity_create("SecKeychainItemSetAttribute", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
528 | os_activity_scope(activity); | |
529 | os_release(activity); | |
fa7225c8 A |
530 | |
531 | ItemImpl::required(__itemImplRef)->setAttribute(RequiredParam(attribute)); | |
532 | ||
533 | END_SECKCITEMAPI | |
b1ab9ed8 A |
534 | } |
535 | ||
536 | /* Finds a keychain item for legacy "KC" CoreServices APIs. | |
427c49bc | 537 | Note: This version doesn't take a SecItemClass because |
b1ab9ed8 A |
538 | SecKeychainSearchCreateFromAttributes() requires it. |
539 | @@@ This should move to SecKeychainSearch.cpp | |
540 | */ | |
541 | OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef, SecKeychainItemRef *itemRef) | |
542 | { | |
fa7225c8 | 543 | BEGIN_SECAPI |
866f8763 A |
544 | os_activity_t activity = os_activity_create("SecKeychainItemFindFirst", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
545 | os_activity_scope(activity); | |
546 | os_release(activity); | |
fa7225c8 A |
547 | |
548 | KCCursor cursor; | |
549 | if (keychainRef) { | |
550 | cursor = KeychainImpl::required(keychainRef)->createCursor(attrList); | |
551 | } else { | |
552 | cursor = globals().storageManager.createCursor(attrList); | |
553 | } | |
554 | ||
555 | Item item; | |
556 | if (!cursor->next(item)) | |
557 | return errSecItemNotFound; | |
558 | ||
559 | *itemRef=item->handle(); | |
560 | if (searchRef) { | |
561 | *searchRef=cursor->handle(); | |
562 | } | |
563 | ||
b1ab9ed8 A |
564 | END_SECAPI |
565 | } | |
566 | ||
5c19dc3a | 567 | static OSStatus SecKeychainItemCreatePersistentReferenceFromCertificate(SecCertificateRef certRef, |
fa7225c8 | 568 | CFDataRef *persistentItemRef, Boolean isIdentity) |
b1ab9ed8 | 569 | { |
fa7225c8 A |
570 | OSStatus __secapiresult; |
571 | if (!certRef || !persistentItemRef) { | |
5c19dc3a | 572 | return errSecParam; |
fa7225c8 A |
573 | } |
574 | ||
575 | // If we already have a keychain item, we won't need to look it up by serial and issuer | |
576 | SecKeychainItemRef kcItem = NULL; | |
577 | if (SecCertificateIsItemImplInstance(certRef)) { | |
578 | kcItem = (SecKeychainItemRef) CFRetain(certRef); | |
579 | } | |
580 | else { | |
581 | kcItem = (SecKeychainItemRef) SecCertificateCopyKeychainItem(certRef); | |
582 | } | |
583 | if (kcItem) { | |
584 | __secapiresult = errSecParam; | |
585 | try { | |
586 | Item item = ItemImpl::required((kcItem)); | |
587 | item->copyPersistentReference(*persistentItemRef, isIdentity); | |
588 | __secapiresult = errSecSuccess; | |
589 | } | |
590 | catch(...) {} | |
591 | CFRelease(kcItem); | |
592 | if (__secapiresult == errSecSuccess) { | |
593 | return __secapiresult; | |
594 | } | |
595 | } | |
596 | ||
597 | // Certificate does not have a keychain item reference; look it up by serial and issuer | |
598 | SecCertificateRef certItem = NULL; | |
599 | if (SecCertificateIsItemImplInstance(certRef)) { | |
600 | certItem = SecCertificateCreateFromItemImplInstance(certRef); | |
601 | } | |
602 | else { | |
603 | certItem = (SecCertificateRef) CFRetain(certRef); | |
604 | } | |
5c19dc3a | 605 | |
5c19dc3a | 606 | CFErrorRef errorRef = NULL; |
fa7225c8 | 607 | CFDataRef serialData = SecCertificateCopySerialNumber(certItem, &errorRef); |
5c19dc3a A |
608 | if (errorRef) { |
609 | CFIndex err = CFErrorGetCode(errorRef); | |
610 | CFRelease(errorRef); | |
611 | if (serialData) { CFRelease(serialData); } | |
fa7225c8 | 612 | if (certItem) { CFRelease(certItem); } |
5c19dc3a A |
613 | return (OSStatus)err; |
614 | } | |
fa7225c8 | 615 | CFDataRef issuerData = SecCertificateCopyNormalizedIssuerContent(certItem, &errorRef); |
5c19dc3a A |
616 | if (errorRef) { |
617 | CFIndex err = CFErrorGetCode(errorRef); | |
618 | CFRelease(errorRef); | |
619 | if (serialData) { CFRelease(serialData); } | |
620 | if (issuerData) { CFRelease(issuerData); } | |
fa7225c8 | 621 | if (certItem) { CFRelease(certItem); } |
5c19dc3a A |
622 | return (OSStatus)err; |
623 | } | |
624 | ||
625 | try { | |
626 | // look up ItemImpl cert in keychain by normalized issuer and serial number | |
627 | StorageManager::KeychainList keychains; | |
628 | globals().storageManager.optionalSearchList(NULL, keychains); | |
629 | KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuerData, serialData)); | |
427c49bc | 630 | Item item; |
5c19dc3a A |
631 | if (!cursor->next(item)) { |
632 | MacOSError::throwMe(errSecItemNotFound); | |
427c49bc | 633 | } |
5c19dc3a A |
634 | item->copyPersistentReference(*persistentItemRef, false); |
635 | __secapiresult = errSecSuccess; | |
636 | } | |
637 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
638 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
639 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
640 | catch (...) { __secapiresult=errSecInternalComponent; } | |
641 | ||
642 | if (serialData) | |
643 | CFRelease(serialData); | |
644 | if (issuerData) | |
645 | CFRelease(issuerData); | |
fa7225c8 A |
646 | if (certItem) |
647 | CFRelease(certItem); | |
5c19dc3a A |
648 | |
649 | return __secapiresult; | |
650 | } | |
5c19dc3a A |
651 | |
652 | OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CFDataRef *persistentItemRef) | |
653 | { | |
5c19dc3a A |
654 | /* We're in the unified world, where SecCertificateRef is not a SecKeychainItemRef. */ |
655 | if (!itemRef || !persistentItemRef) { | |
656 | return errSecParam; | |
657 | } | |
fa7225c8 A |
658 | // first, query the iOS keychain |
659 | { | |
660 | const void *keys[] = { kSecValueRef, kSecReturnPersistentRef, kSecAttrNoLegacy }; | |
661 | const void *values[] = { itemRef, kCFBooleanTrue, kCFBooleanTrue }; | |
662 | CFRef<CFDictionaryRef> query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, | |
663 | sizeof(keys) / sizeof(*keys), | |
664 | &kCFTypeDictionaryKeyCallBacks, | |
665 | &kCFTypeDictionaryValueCallBacks); | |
666 | OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)persistentItemRef); | |
667 | if (status == errSecSuccess) { | |
668 | return status; | |
669 | } | |
670 | } | |
671 | // otherwise, handle certificate | |
5c19dc3a | 672 | SecCertificateRef certRef = NULL; |
fa7225c8 A |
673 | CFTypeID itemType = CFGetTypeID(itemRef); |
674 | bool isIdentity = false; | |
675 | if (itemType == SecIdentityGetTypeID()) { | |
5c19dc3a | 676 | SecIdentityCopyCertificate((SecIdentityRef)itemRef, &certRef); |
fa7225c8 | 677 | isIdentity = true; |
5c19dc3a | 678 | } |
fa7225c8 | 679 | else if (itemType == SecCertificateGetTypeID()) { |
5c19dc3a A |
680 | certRef = (SecCertificateRef) CFRetain(itemRef); |
681 | } | |
682 | if (certRef) { | |
fa7225c8 | 683 | OSStatus status = SecKeychainItemCreatePersistentReferenceFromCertificate(certRef, persistentItemRef, isIdentity); |
5c19dc3a A |
684 | CFRelease(certRef); |
685 | return status; | |
686 | } | |
687 | // otherwise, not a certificate, so proceed as usual for keychain item | |
688 | ||
689 | BEGIN_SECAPI | |
866f8763 A |
690 | os_activity_t activity = os_activity_create("SecKeychainItemCreatePersistentReference", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
691 | os_activity_scope(activity); | |
692 | os_release(activity); | |
5c19dc3a A |
693 | Item item = ItemImpl::required(itemRef); |
694 | item->copyPersistentReference(*persistentItemRef, false); | |
695 | END_SECAPI | |
b1ab9ed8 A |
696 | } |
697 | ||
698 | OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, SecKeychainItemRef *itemRef) | |
699 | { | |
700 | BEGIN_SECAPI | |
866f8763 A |
701 | os_activity_t activity = os_activity_create("SecKeychainItemCopyFromPersistentReference", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
702 | os_activity_scope(activity); | |
703 | os_release(activity); | |
5c19dc3a A |
704 | |
705 | KCThrowParamErrIf_(!persistentItemRef || !itemRef); | |
fa7225c8 A |
706 | // first, query the iOS keychain |
707 | { | |
708 | const void *keys[] = { kSecValuePersistentRef, kSecReturnRef, kSecAttrNoLegacy}; | |
709 | const void *values[] = { persistentItemRef, kCFBooleanTrue, kCFBooleanTrue }; | |
710 | CFRef<CFDictionaryRef> query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, | |
711 | sizeof(keys) / sizeof(*keys), | |
712 | &kCFTypeDictionaryKeyCallBacks, | |
713 | &kCFTypeDictionaryValueCallBacks); | |
714 | OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)itemRef); | |
715 | if (status == errSecSuccess) { | |
716 | return status; | |
717 | } | |
718 | } | |
719 | // otherwise, proceed as usual for keychain item | |
5c19dc3a A |
720 | CFTypeRef result = NULL; |
721 | bool isIdentityRef = false; | |
722 | Item item = ItemImpl::makeFromPersistentReference(persistentItemRef, &isIdentityRef); | |
723 | if (isIdentityRef) { | |
724 | // item was stored as an identity, attempt to reconstitute it | |
725 | SecPointer<Certificate> certificatePtr(static_cast<Certificate *>(item.get())); | |
726 | StorageManager::KeychainList keychains; | |
727 | globals().storageManager.optionalSearchList(NULL, keychains); | |
728 | SecPointer<Identity> identityPtr(new Identity(keychains, certificatePtr)); | |
729 | result = identityPtr->handle(); | |
730 | KCThrowIf_( !result, errSecItemNotFound ); | |
731 | } | |
732 | if (!result) { | |
733 | result = item->handle(); | |
734 | } | |
735 | *itemRef = (SecKeychainItemRef) result; | |
736 | ||
5c19dc3a A |
737 | /* see if we should convert outgoing item to a unified SecCertificateRef */ |
738 | SecItemClass tmpItemClass = Schema::itemClassFor(item->recordType()); | |
fa7225c8 | 739 | if (tmpItemClass == kSecCertificateItemClass && !isIdentityRef) { |
5c19dc3a A |
740 | SecPointer<Certificate> certificate(static_cast<Certificate *>(&*item)); |
741 | CssmData certData = certificate->data(); | |
742 | CFDataRef data = NULL; | |
743 | if (certData.Data && certData.Length) { | |
744 | data = CFDataCreate(NULL, certData.Data, certData.Length); | |
745 | } | |
746 | if (!data) { | |
747 | *itemRef = NULL; | |
748 | if (certData.Data && !certData.Length) { | |
749 | syslog(LOG_ERR, "WARNING: SecKeychainItemCopyFromPersistentReference skipped a zero-length certificate (data=0x%lX)", | |
750 | (uintptr_t)certData.Data); | |
751 | return errSecDataNotAvailable; | |
752 | } | |
753 | else { | |
754 | syslog(LOG_ERR, "WARNING: SecKeychainItemCopyFromPersistentReference failed to retrieve certificate data (length=%ld, data=0x%lX)", | |
755 | (long)certData.Length, (uintptr_t)certData.Data); | |
756 | return errSecInternal; | |
757 | } | |
758 | } | |
759 | SecKeychainItemRef tmpRef = *itemRef; | |
760 | *itemRef = (SecKeychainItemRef) SecCertificateCreateWithKeychainItem(NULL, data, tmpRef); | |
761 | if (data) | |
762 | CFRelease(data); | |
763 | if (tmpRef) | |
764 | CFRelease(tmpRef); | |
765 | } | |
5c19dc3a | 766 | |
b1ab9ed8 A |
767 | END_SECAPI |
768 | } | |
769 | ||
770 | OSStatus SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef, CFDataRef *recordIdentifier) | |
771 | { | |
fa7225c8 | 772 | BEGIN_SECKCITEMAPI |
866f8763 A |
773 | os_activity_t activity = os_activity_create("SecKeychainItemCopyRecordIdentifier", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
774 | os_activity_scope(activity); | |
775 | os_release(activity); | |
fa7225c8 A |
776 | |
777 | CSSM_DATA data; | |
778 | RequiredParam (recordIdentifier); | |
779 | Item item = ItemImpl::required(__itemImplRef); | |
780 | item->copyRecordIdentifier (data); | |
781 | *recordIdentifier = ::CFDataCreate(kCFAllocatorDefault, (UInt8*) data.Data, data.Length); | |
782 | free (data.Data); | |
783 | ||
784 | END_SECKCITEMAPI | |
b1ab9ed8 A |
785 | } |
786 | ||
787 | OSStatus | |
788 | SecKeychainItemCopyFromRecordIdentifier(SecKeychainRef keychainRef, | |
789 | SecKeychainItemRef *itemRef, | |
790 | CFDataRef recordIdentifier) | |
791 | { | |
792 | BEGIN_SECAPI | |
866f8763 A |
793 | os_activity_t activity = os_activity_create("SecKeychainItemCopyFromRecordIdentifier", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
794 | os_activity_scope(activity); | |
795 | os_release(activity); | |
fa7225c8 A |
796 | |
797 | // make a local Keychain reference | |
798 | RequiredParam (keychainRef); | |
799 | Keychain keychain = KeychainImpl::optional (keychainRef); | |
800 | RequiredParam (itemRef); | |
801 | RequiredParam (recordIdentifier); | |
802 | ||
803 | Db db(keychain->database()); | |
804 | ||
805 | // make a raw database call to get the data | |
806 | CSSM_DL_DB_HANDLE dbHandle = db.handle (); | |
807 | CSSM_DB_UNIQUE_RECORD uniqueRecord; | |
808 | ||
809 | // according to source, we should be able to reconsitute the uniqueRecord | |
810 | // from the data we earlier retained | |
811 | ||
812 | // prepare the record id | |
813 | memset (&uniqueRecord, 0, sizeof (uniqueRecord)); | |
814 | uniqueRecord.RecordIdentifier.Data = (uint8*) CFDataGetBytePtr (recordIdentifier); | |
815 | uniqueRecord.RecordIdentifier.Length = CFDataGetLength (recordIdentifier); | |
816 | ||
817 | // convert this unique id to a CSSM_DB_UNIQUE_RECORD that works for the CSP/DL | |
818 | CSSM_DB_UNIQUE_RECORD_PTR outputUniqueRecordPtr; | |
819 | CSSM_RETURN result; | |
820 | result = CSSM_DL_PassThrough (dbHandle, CSSM_APPLECSPDL_DB_CONVERT_RECORD_IDENTIFIER, &uniqueRecord, (void**) &outputUniqueRecordPtr); | |
821 | KCThrowIf_(result != 0, errSecItemNotFound); | |
822 | ||
823 | // from this, get the record type | |
824 | CSSM_DB_RECORD_ATTRIBUTE_DATA attributeData; | |
825 | memset (&attributeData, 0, sizeof (attributeData)); | |
826 | ||
827 | result = CSSM_DL_DataGetFromUniqueRecordId (dbHandle, outputUniqueRecordPtr, &attributeData, NULL); | |
828 | KCThrowIf_(result != 0, errSecItemNotFound); | |
829 | CSSM_DB_RECORDTYPE recordType = attributeData.DataRecordType; | |
830 | ||
831 | // make the unique record item -- precursor to creation of a SecKeychainItemRef | |
832 | DbUniqueRecord unique(db); | |
833 | CSSM_DB_UNIQUE_RECORD_PTR *uniquePtr = unique; | |
834 | *uniquePtr = outputUniqueRecordPtr; | |
835 | ||
836 | unique->activate (); | |
837 | Item item = keychain->item (recordType, unique); | |
838 | if (itemRef) | |
839 | { | |
840 | *itemRef = item->handle(); | |
841 | } | |
842 | ||
b1ab9ed8 A |
843 | END_SECAPI |
844 | } | |
845 | ||
846 | OSStatus SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass, | |
847 | UInt32 length, const void *data, SecKeychainRef keychainRef, | |
848 | SecAccessRef initialAccess, SecKeychainItemRef *itemRef, CFDataRef *localID) | |
849 | { | |
fa7225c8 | 850 | BEGIN_SECAPI |
866f8763 A |
851 | os_activity_t activity = os_activity_create("SecKeychainItemCreateFromEncryptedContent", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
852 | os_activity_scope(activity); | |
853 | os_release(activity); | |
b1ab9ed8 | 854 | |
fa7225c8 A |
855 | KCThrowParamErrIf_(length!=0 && data==NULL); |
856 | RequiredParam (localID); | |
857 | RequiredParam (keychainRef); | |
427c49bc | 858 | |
fa7225c8 A |
859 | Item item(itemClass, (uint32) 0, length, data, true); |
860 | if (initialAccess) | |
861 | item->setAccess(Access::required(initialAccess)); | |
b1ab9ed8 | 862 | |
fa7225c8 A |
863 | Keychain keychain = Keychain::optional(keychainRef); |
864 | if (!keychain->exists()) | |
865 | { | |
866 | MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. | |
867 | } | |
b1ab9ed8 | 868 | |
fa7225c8 A |
869 | item->doNotEncrypt (); |
870 | try | |
871 | { | |
872 | keychain->add(item); | |
873 | } | |
874 | catch (const CommonError &err) | |
875 | { | |
876 | if (err.osStatus () == errSecNoSuchClass) | |
b1ab9ed8 | 877 | { |
fa7225c8 A |
878 | // the only time this should happen is if the item is a certificate (for keychain syncing) |
879 | if (itemClass == CSSM_DL_DB_RECORD_X509_CERTIFICATE) | |
b1ab9ed8 | 880 | { |
fa7225c8 A |
881 | // create the certificate relation |
882 | Db db(keychain->database()); | |
b1ab9ed8 | 883 | |
fa7225c8 | 884 | db->createRelation(CSSM_DL_DB_RECORD_X509_CERTIFICATE, |
b1ab9ed8 A |
885 | "CSSM_DL_DB_RECORD_X509_CERTIFICATE", |
886 | Schema::X509CertificateSchemaAttributeCount, | |
887 | Schema::X509CertificateSchemaAttributeList, | |
888 | Schema::X509CertificateSchemaIndexCount, | |
889 | Schema::X509CertificateSchemaIndexList); | |
fa7225c8 | 890 | keychain->keychainSchema()->didCreateRelation( |
b1ab9ed8 A |
891 | CSSM_DL_DB_RECORD_X509_CERTIFICATE, |
892 | "CSSM_DL_DB_RECORD_X509_CERTIFICATE", | |
893 | Schema::X509CertificateSchemaAttributeCount, | |
894 | Schema::X509CertificateSchemaAttributeList, | |
895 | Schema::X509CertificateSchemaIndexCount, | |
896 | Schema::X509CertificateSchemaIndexList); | |
427c49bc | 897 | |
fa7225c8 A |
898 | // add the item again |
899 | keychain->add(item); | |
b1ab9ed8 A |
900 | } |
901 | } | |
fa7225c8 A |
902 | else |
903 | { | |
904 | throw; | |
905 | } | |
906 | } | |
b1ab9ed8 | 907 | |
fa7225c8 A |
908 | if (itemRef) |
909 | *itemRef = item->handle(); | |
427c49bc | 910 | |
fa7225c8 A |
911 | CSSM_DATA recordID; |
912 | item->copyRecordIdentifier (recordID); | |
913 | ||
914 | *localID = CFDataCreate(kCFAllocatorDefault, (UInt8*) recordID.Data, recordID.Length); | |
915 | free (recordID.Data); | |
427c49bc | 916 | |
b1ab9ed8 A |
917 | END_SECAPI |
918 | } | |
919 | ||
920 | OSStatus SecKeychainItemCopyAttributesAndEncryptedData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo *info, | |
921 | SecItemClass *itemClass, SecKeychainAttributeList **attrList, | |
922 | UInt32 *length, void **outData) | |
923 | { | |
fa7225c8 | 924 | BEGIN_SECKCITEMAPI |
866f8763 A |
925 | os_activity_t activity = os_activity_create("SecKeychainItemCopyAttributesAndEncryptedData", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
926 | os_activity_scope(activity); | |
927 | os_release(activity); | |
fa7225c8 A |
928 | |
929 | Item item = ItemImpl::required(__itemImplRef); | |
930 | item->doNotEncrypt (); | |
931 | item->getAttributesAndData(info, itemClass, attrList, length, outData); | |
932 | ||
933 | END_SECKCITEMAPI | |
b1ab9ed8 A |
934 | } |
935 | ||
936 | OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 length, const void *data) | |
937 | { | |
fa7225c8 | 938 | BEGIN_SECKCITEMAPI |
866f8763 A |
939 | os_activity_t activity = os_activity_create("SecKeychainItemModifyEncryptedData", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_IF_NONE_PRESENT); |
940 | os_activity_scope(activity); | |
941 | os_release(activity); | |
fa7225c8 A |
942 | |
943 | Item item = ItemImpl::required(__itemImplRef); | |
944 | item->doNotEncrypt (); | |
945 | item->modifyAttributesAndData(NULL, length, data); | |
946 | ||
947 | END_SECKCITEMAPI | |
b1ab9ed8 | 948 | } |