]> git.saurik.com Git - apple/security.git/blob - OSX/sec/securityd/SecDbKeychainItem.m
Security-58286.60.28.tar.gz
[apple/security.git] / OSX / sec / securityd / SecDbKeychainItem.m
1 /*
2 * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * SecDbKeychainItem.c - CoreFoundation-based constants and functions for
26 access to Security items (certificates, keys, identities, and
27 passwords.)
28 */
29
30 #include <securityd/SecDbKeychainItem.h>
31
32 #import "SecInternalReleasePriv.h"
33 #include <securityd/SecItemSchema.h>
34 #include <securityd/SecItemServer.h>
35 #include <securityd/SecItemDb.h>
36 #include <CommonCrypto/CommonCryptor.h>
37 #include <CommonCrypto/CommonCryptorSPI.h>
38 #include <Security/SecBasePriv.h>
39 #include <Security/SecItem.h>
40 #include <Security/SecItemPriv.h>
41 #include <Security/SecItemInternal.h>
42 #include <Security/SecRandom.h>
43 #include <Security/SecAccessControl.h>
44 #include <Security/SecAccessControlPriv.h>
45 #include <utilities/der_plist.h>
46 #include <utilities/der_plist_internal.h>
47 #include <utilities/SecCFCCWrappers.h>
48 #import "SecDbKeychainItemV7.h"
49
50 #if USE_KEYSTORE
51 #include <LocalAuthentication/LAPublicDefines.h>
52 #include <LocalAuthentication/LAPrivateDefines.h>
53 #include <coreauthd_spi.h>
54 #include <libaks_acl_cf_keys.h>
55 #include <securityd/spi.h>
56
57 #endif /* USE_KEYSTORE */
58
59 pthread_key_t CURRENT_CONNECTION_KEY;
60
61 // From SecItemServer, should be a acl-check block
62 bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups);
63
64 static keyclass_t kc_parse_keyclass(CFTypeRef value, CFErrorRef *error);
65 static CFTypeRef kc_encode_keyclass(keyclass_t keyclass);
66 static CFDataRef kc_copy_protection_data(SecAccessControlRef access_control);
67 static CFTypeRef kc_copy_protection_from(const uint8_t *der, const uint8_t *der_end);
68 static CF_RETURNS_RETAINED CFMutableDictionaryRef s3dl_item_v2_decode(CFDataRef plain, CFErrorRef *error);
69 static CF_RETURNS_RETAINED CFMutableDictionaryRef s3dl_item_v3_decode(CFDataRef plain, CFErrorRef *error);
70 #if USE_KEYSTORE
71 static bool kc_attribs_key_encrypted_data_from_blob(keybag_handle_t keybag, const SecDbClass *class, const void *blob_data, size_t blob_data_len, SecAccessControlRef access_control, uint32_t version,
72 CFMutableDictionaryRef *authenticated_attributes, aks_ref_key_t *ref_key, CFDataRef *encrypted_data, CFErrorRef *error);
73 static CFDataRef kc_create_auth_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes);
74 static CFDataRef kc_copy_access_groups_data(CFArrayRef access_groups, CFErrorRef *error);
75 #endif
76
77 static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef pl, CFOptionFlags mutability, CFPropertyListRef* cf, CFErrorRef *error,
78 const uint8_t* der, const uint8_t *der_end,
79 const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error,
80 const uint8_t* der, const uint8_t *der_end));
81 static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFDictionaryRef* dictionary, CFErrorRef *error,
82 const uint8_t* der, const uint8_t *der_end,
83 const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error,
84 const uint8_t* der, const uint8_t *der_end));
85 static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error,
86 const uint8_t* der, const uint8_t *der_end,
87 const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error,
88 const uint8_t* der, const uint8_t *der_end));
89 static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFArrayRef* array, CFErrorRef *error,
90 const uint8_t* der, const uint8_t *der_end,
91 const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error,
92 const uint8_t* der, const uint8_t *der_end));
93 static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability, CFSetRef* set, CFErrorRef *error,
94 const uint8_t* der, const uint8_t *der_end,
95 const uint8_t* (^repairBlock)(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error,
96 const uint8_t* der, const uint8_t *der_end));
97
98 const uint32_t kUseDefaultIVMask = 1<<31;
99 const int16_t kIVSizeAESGCM = 12;
100
101 // echo "keychainblobstaticiv" | openssl dgst -sha256 | cut -c1-24 | xargs -I {} echo "0x{}" | xxd -r | xxd -p -i
102 static const uint8_t gcmIV[kIVSizeAESGCM] = {
103 0x1e, 0xa0, 0x5c, 0xa9, 0x98, 0x2e, 0x87, 0xdc, 0xf1, 0x45, 0xe8, 0x24
104 };
105
106 /* Given plainText create and return a CFDataRef containing:
107 BULK_KEY = RandomKey()
108 version || keyclass|ACL || KeyStore_WRAP(keyclass, BULK_KEY) ||
109 AES(BULK_KEY, NULL_IV, plainText || padding)
110 */
111 bool ks_encrypt_data_legacy(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context,
112 CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, bool useDefaultIV, CFErrorRef *error) {
113 CFMutableDataRef blob = NULL;
114 CFDataRef ac_data = NULL;
115 bool ok = true;
116 //check(keybag >= 0);
117
118 /* Precalculate output blob length. */
119 const uint32_t bulkKeySize = 32; /* Use 256 bit AES key for bulkKey. */
120 const uint32_t maxKeyWrapOverHead = 8 + 32;
121 uint8_t bulkKey[bulkKeySize];
122 CFMutableDataRef bulkKeyWrapped = CFDataCreateMutable(NULL, 0);
123 CFDataSetLength(bulkKeyWrapped, bulkKeySize + maxKeyWrapOverHead);
124 uint32_t key_wrapped_size;
125 size_t ivLen = 0;
126 const uint8_t *iv = NULL;
127 const uint8_t *aad = NULL; // Additional Authenticated Data
128 ptrdiff_t aadLen = 0;
129
130 #if USE_KEYSTORE
131 CFDataRef auth_data = NULL;
132 #endif
133
134 /* If access_control specifies only protection and no ACL, use legacy blob format version 3,
135 which has better support for sync/backup. Otherwise, force new format v6 unless useDefaultIV is set. */
136 bool hasACLConstraints = SecAccessControlGetConstraints(access_control);
137 const uint32_t version = (hasACLConstraints ? 6 : 3);
138 CFDataRef plainText = NULL;
139 if (version < 4) {
140 CFMutableDictionaryRef attributes_dict = CFDictionaryCreateMutableCopy(NULL, 0, attributes);
141 if (authenticated_attributes) {
142 CFDictionaryForEach(authenticated_attributes, ^(const void *key, const void *value) {
143 CFDictionaryAddValue(attributes_dict, key, value);
144 });
145 }
146
147 if (attributes_dict) {
148 // Drop the accc attribute for non v6 items during encode.
149 CFDictionaryRemoveValue(attributes_dict, kSecAttrAccessControl);
150 plainText = CFPropertyListCreateDERData(kCFAllocatorDefault, attributes_dict, error);
151 CFRelease(attributes_dict);
152 }
153 } else {
154 #if USE_KEYSTORE
155 if (attributes) {
156 plainText = CFPropertyListCreateDERData(kCFAllocatorDefault, attributes, error);
157 }
158 #else
159 CFMutableDictionaryRef attributes_dict = CFDictionaryCreateMutableCopy(NULL, 0, attributes);
160 if (authenticated_attributes) {
161 CFDictionaryForEach(authenticated_attributes, ^(const void *key, const void *value) {
162 CFDictionaryAddValue(attributes_dict, key, value);
163 });
164 }
165
166 if (attributes_dict) {
167 plainText = CFPropertyListCreateDERData(kCFAllocatorDefault, attributes_dict, error);
168 CFRelease(attributes_dict);
169 }
170 #endif
171 }
172
173 if (!plainText || CFGetTypeID(plainText) != CFDataGetTypeID()
174 || access_control == 0) {
175 ok = SecError(errSecParam, error, CFSTR("ks_encrypt_data: invalid plain text"));
176 goto out;
177 }
178
179 size_t ptLen = CFDataGetLength(plainText);
180 size_t ctLen = ptLen;
181 size_t tagLen = 16;
182 keyclass_t actual_class = 0;
183
184 if (SecRandomCopyBytes(kSecRandomDefault, bulkKeySize, bulkKey)) {
185 ok = SecError(errSecAllocate, error, CFSTR("ks_encrypt_data: SecRandomCopyBytes failed"));
186 goto out;
187 }
188
189 /* Extract keyclass from access control. */
190 keyclass_t keyclass = kc_parse_keyclass(SecAccessControlGetProtection(access_control), error);
191 if (!keyclass)
192 goto out;
193
194 #if USE_KEYSTORE
195 if (version >= 4) {
196 auth_data = kc_create_auth_data(access_control, authenticated_attributes);
197 require_quiet(ok = ks_encrypt_acl(keybag, keyclass, bulkKeySize, bulkKey, bulkKeyWrapped, auth_data, acm_context, access_control, error), out);
198 } else
199 #endif
200 {
201 /* Encrypt bulkKey. */
202 require_quiet(ok = ks_crypt(kAKSKeyOpEncrypt, keybag,
203 keyclass, bulkKeySize, bulkKey,
204 &actual_class, bulkKeyWrapped,
205 error), out);
206 }
207
208 key_wrapped_size = (uint32_t)CFDataGetLength(bulkKeyWrapped);
209 UInt8 *cursor;
210 size_t blobLen = sizeof(version);
211 uint32_t prot_length = 0;
212
213 if (!hasACLConstraints) {
214 blobLen += sizeof(actual_class);
215 } else {
216 require_quiet(ac_data = kc_copy_protection_data(access_control), out);
217 prot_length = (uint32_t)CFDataGetLength(ac_data);
218 blobLen += sizeof(prot_length) + prot_length;
219 }
220
221 blobLen += sizeof(key_wrapped_size) + key_wrapped_size + ctLen + tagLen;
222 require_quiet(blob = CFDataCreateMutable(NULL, blobLen), out);
223 CFDataSetLength(blob, blobLen);
224 cursor = CFDataGetMutableBytePtr(blob);
225
226 *((uint32_t *)cursor) = useDefaultIV ? (version | kUseDefaultIVMask) : version;
227 cursor += sizeof(version);
228
229 //secerror("class: %d actual class: %d", keyclass, actual_class);
230 if (!hasACLConstraints) {
231 *((keyclass_t *)cursor) = actual_class;
232 cursor += sizeof(keyclass);
233 } else {
234 *((uint32_t *)cursor) = prot_length;
235 cursor += sizeof(prot_length);
236
237 CFDataGetBytes(ac_data, CFRangeMake(0, prot_length), cursor);
238 cursor += prot_length;
239 }
240
241 *((uint32_t *)cursor) = key_wrapped_size;
242 cursor += sizeof(key_wrapped_size);
243
244 if (useDefaultIV) {
245 iv = gcmIV;
246 ivLen = kIVSizeAESGCM;
247 // AAD is (version || ac_data || key_wrapped_size)
248 aad = CFDataGetMutableBytePtr(blob);
249 aadLen = cursor - aad;
250 }
251
252 memcpy(cursor, CFDataGetBytePtr(bulkKeyWrapped), key_wrapped_size);
253 cursor += key_wrapped_size;
254
255 /* Encrypt the plainText with the bulkKey. */
256 CCCryptorStatus ccerr = CCCryptorGCM(kCCEncrypt, kCCAlgorithmAES128,
257 bulkKey, bulkKeySize,
258 iv, ivLen, /* iv */
259 aad, aadLen, /* auth data */
260 CFDataGetBytePtr(plainText), ptLen,
261 cursor,
262 cursor + ctLen, &tagLen);
263 if (ccerr) {
264 ok = SecError(errSecInternal, error, CFSTR("ks_encrypt_data: CCCryptorGCM failed: %d"), ccerr);
265 goto out;
266 }
267 if (tagLen != 16) {
268 ok = SecError(errSecInternal, error, CFSTR("ks_encrypt_data: CCCryptorGCM expected: 16 got: %ld byte tag"), tagLen);
269 goto out;
270 }
271
272 out:
273 memset(bulkKey, 0, sizeof(bulkKey));
274 CFReleaseSafe(ac_data);
275 CFReleaseSafe(bulkKeyWrapped);
276 CFReleaseSafe(plainText);
277 if (!ok) {
278 CFReleaseSafe(blob);
279 } else {
280 *pBlob = blob;
281 }
282
283 #if USE_KEYSTORE
284 CFReleaseSafe(auth_data);
285 #endif
286 return ok;
287 }
288
289 bool ks_encrypt_data(keybag_handle_t keybag, SecAccessControlRef access_control, CFDataRef acm_context,
290 CFDictionaryRef secretData, CFDictionaryRef attributes, CFDictionaryRef authenticated_attributes, CFDataRef *pBlob, bool useDefaultIV, CFErrorRef *error) {
291 if (CFDictionaryGetCount(secretData) == 0) {
292 secerror("SecDbKeychainItem: encrypting item with no secret data"); // not actually making this an error because it seems this is done frequently by third parties
293 }
294
295 if (keybag != KEYBAG_DEVICE) {
296 secwarning("ks_encrypt_data: called with non-device keybag - call should be rerouted to ks_encrypt_data_legacy");
297
298 CFMutableDictionaryRef allAttributes = CFDictionaryCreateMutableCopy(NULL, CFDictionaryGetCount(secretData) + CFDictionaryGetCount(attributes), attributes);
299 CFDictionaryForEach(secretData, ^(const void *key, const void *value) {
300 CFDictionaryAddValue(allAttributes, key, value);
301 });
302 bool result = ks_encrypt_data_legacy(keybag, access_control, acm_context, allAttributes, authenticated_attributes, pBlob, useDefaultIV, error);
303 CFReleaseNull(allAttributes);
304 return result;
305 }
306
307 keyclass_t key_class = kc_parse_keyclass(SecAccessControlGetProtection(access_control), error);
308 if (!key_class) {
309 return false;
310 }
311
312 if (SecAccessControlGetConstraints(access_control)) {
313 NSMutableDictionary* allAttributes = [(__bridge NSDictionary*)attributes mutableCopy];
314 [allAttributes addEntriesFromDictionary:(__bridge NSDictionary*)secretData];
315 return ks_encrypt_data_legacy(keybag, access_control, acm_context, (__bridge CFDictionaryRef)allAttributes, authenticated_attributes, pBlob, useDefaultIV, error);
316 }
317
318 bool success = false;
319 @autoreleasepool {
320 NSMutableDictionary* metadataAttributes = attributes ? [(__bridge NSDictionary*)attributes mutableCopy] : [NSMutableDictionary dictionary];
321 [metadataAttributes addEntriesFromDictionary:(__bridge NSDictionary*)authenticated_attributes];
322 metadataAttributes[@"SecAccessControl"] = (__bridge_transfer NSData*)SecAccessControlCopyData(access_control);
323
324 NSString* tamperCheck = [[NSUUID UUID] UUIDString]; // can use the item persistent reference when that starts getting filled in
325 SecDbKeychainItemV7* item = [[SecDbKeychainItemV7 alloc] initWithSecretAttributes:(__bridge NSDictionary*)secretData metadataAttributes:metadataAttributes tamperCheck:tamperCheck keyclass:key_class];
326
327 NSError* localError = nil;
328 NSData* encryptedBlob = [item encryptedBlobWithKeybag:keybag accessControl:access_control acmContext:(__bridge NSData*)acm_context error:&localError];
329 if (encryptedBlob) {
330 NSMutableData* encryptedBlobWithVersion = [NSMutableData dataWithLength:encryptedBlob.length + sizeof(uint32_t)];
331 *((uint32_t*)encryptedBlobWithVersion.mutableBytes) = (uint32_t)7;
332 memcpy((uint32_t*)encryptedBlobWithVersion.mutableBytes + 1, encryptedBlob.bytes, encryptedBlob.length);
333 *pBlob = (__bridge_retained CFDataRef)encryptedBlobWithVersion;
334 success = true;
335 }
336 else {
337 if (error) {
338 *error = (__bridge_retained CFErrorRef)localError;
339 }
340 }
341 }
342
343 return success;
344 }
345
346 /* Given cipherText containing:
347 version || keyclass || KeyStore_WRAP(keyclass, BULK_KEY) ||
348 AES(BULK_KEY, NULL_IV, plainText || padding)
349 return the plainText. */
350 bool ks_decrypt_data(keybag_handle_t keybag, CFTypeRef cryptoOp, SecAccessControlRef *paccess_control, CFDataRef acm_context,
351 CFDataRef blob, const SecDbClass *db_class, CFArrayRef caller_access_groups,
352 CFMutableDictionaryRef *attributes_p, uint32_t *version_p, bool decryptSecretData, keyclass_t* outKeyclass, CFErrorRef *error) {
353 const uint32_t v0KeyWrapOverHead = 8;
354 CFMutableDataRef bulkKey = CFDataCreateMutable(0, 32); /* Use 256 bit AES key for bulkKey. */
355 CFDataSetLength(bulkKey, 32); /* Use 256 bit AES key for bulkKey. */
356 bool ok = true;
357 SecAccessControlRef access_control = NULL;
358
359 if (attributes_p)
360 *attributes_p = NULL;
361 if (version_p)
362 *version_p = 0;
363
364 CFMutableDataRef plainText = NULL;
365 CFMutableDictionaryRef attributes = NULL;
366 uint32_t version = 0;
367 size_t ivLen = 0;
368 const uint8_t *iv = NULL;
369 const uint8_t *aad = NULL; // Additional Authenticated Data
370 ptrdiff_t aadLen = 0;
371
372 #if USE_KEYSTORE
373 CFMutableDictionaryRef authenticated_attributes = NULL;
374 CFDataRef caller_access_groups_data = NULL;
375 CFDataRef ed_data = NULL;
376 aks_ref_key_t ref_key = NULL;
377 #if TARGET_OS_IPHONE
378 check(keybag >= 0);
379 #else
380 check((keybag >= 0) || (keybag == session_keybag_handle));
381 #endif
382 #endif
383
384 if (!blob) {
385 ok = SecError(errSecParam, error, CFSTR("ks_decrypt_data: invalid blob"));
386 goto out;
387 }
388
389 size_t blobLen = CFDataGetLength(blob);
390 const uint8_t *cursor = CFDataGetBytePtr(blob);
391 keyclass_t keyclass;
392
393 if (blobLen < sizeof(version)) {
394 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow (length)"));
395 goto out;
396 }
397
398 version = *((uint32_t *)cursor);
399 if (version & kUseDefaultIVMask) {
400 version &= ~kUseDefaultIVMask;
401 iv = gcmIV;
402 ivLen = kIVSizeAESGCM;
403 }
404
405 cursor += sizeof(version);
406 blobLen -= sizeof(version);
407
408 bool hasProtectionData = (version >= 4 && version < 7);
409
410 if (version >= 7) {
411 @autoreleasepool {
412 NSError* localError = nil;
413 NSData* encryptedBlob = [NSData dataWithBytes:cursor length:blobLen];
414 SecDbKeychainItemV7* item = [[SecDbKeychainItemV7 alloc] initWithData:encryptedBlob decryptionKeybag:keybag error:&localError];
415 if (outKeyclass) {
416 *outKeyclass = item.keyclass;
417 }
418
419 NSMutableDictionary* itemAttributes = [[item metadataAttributesWithError:&localError] mutableCopy];
420 if (itemAttributes && !localError) {
421 NSData* accessControlData = itemAttributes[@"SecAccessControl"];
422 access_control = SecAccessControlCreateFromData(NULL, (__bridge CFDataRef)accessControlData, error);
423 [itemAttributes removeObjectForKey:@"SecAccessControl"];
424
425 if (decryptSecretData) {
426 NSDictionary* secretAttributes = [item secretAttributesWithAcmContext:(__bridge NSData*)acm_context accessControl:access_control callerAccessGroups:(__bridge NSArray*)caller_access_groups error:&localError];
427 if (secretAttributes) {
428 [itemAttributes addEntriesFromDictionary:secretAttributes];
429
430 if (secretAttributes.count == 0) {
431 secerror("SecDbKeychainItemV7: item decrypted succussfully, but has no secret data so it's useless"); // not actually making this an error because a bunch of third parties store items with no secret data on purpose
432 }
433 }
434 else {
435 ok = false;
436 }
437 }
438
439 if (ok) {
440 if (CFEqual(kAKSKeyOpDelete, cryptoOp)) {
441 ok = [item deleteWithAcmContext:(__bridge NSData*)acm_context accessControl:access_control callerAccessGroups:(__bridge NSArray*)caller_access_groups error:&localError];
442 }
443
444 attributes = (__bridge_retained CFMutableDictionaryRef)itemAttributes;
445 }
446 }
447 else {
448 ok = false;
449 }
450
451 if (!ok && error) {
452 *error = (__bridge_retained CFErrorRef)localError;
453 }
454 }
455 goto out;
456 }
457
458 if (hasProtectionData) {
459 /* Deserialize SecAccessControl object from the blob. */
460 uint32_t prot_length;
461
462 /*
463 * Parse proto length
464 */
465
466 if (blobLen < sizeof(prot_length)) {
467 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow (prot_length)"));
468 goto out;
469 }
470
471 prot_length = *((uint32_t *)cursor);
472 cursor += sizeof(prot_length);
473 blobLen -= sizeof(prot_length);
474
475 /*
476 * Parse proto itself
477 */
478
479 if (blobLen < prot_length) {
480 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow (prot)"));
481 goto out;
482 }
483
484 CFTypeRef protection = kc_copy_protection_from(cursor, cursor + prot_length);
485 if (!protection) {
486 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid ACL"));
487 goto out;
488 } else {
489 access_control = SecAccessControlCreate(NULL, NULL);
490 require_quiet(access_control, out);
491 ok = SecAccessControlSetProtection(access_control, protection, NULL);
492 CFRelease(protection);
493 if (!ok) {
494 SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid ACL"));
495 goto out;
496 }
497 }
498
499 cursor += prot_length;
500 blobLen -= prot_length;
501
502 /*
503 * Get numeric value of keyclass from the access_control.
504 */
505 keyclass = kc_parse_keyclass(SecAccessControlGetProtection(access_control), error);
506 if (!keyclass) {
507 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid ACL"));
508 goto out;
509 }
510 } else {
511 if (blobLen < sizeof(keyclass)) {
512 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow (keyclass)"));
513 goto out;
514 }
515
516 keyclass = *((keyclass_t *)cursor);
517
518 #if USE_KEYSTORE
519 CFTypeRef protection = kc_encode_keyclass(keyclass & key_class_last); // mask out generation
520 #else
521 CFTypeRef protection = kc_encode_keyclass(keyclass);
522 #endif
523 require_action_quiet(protection, out, ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid keyclass detected")));
524 require_action_quiet(access_control = SecAccessControlCreate(kCFAllocatorDefault, error), out,
525 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: SecAccessControlCreate failed")));
526 require_action_quiet(SecAccessControlSetProtection(access_control, protection, error), out,
527 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: SecAccessControlSetProtection failed")));
528
529 cursor += sizeof(keyclass);
530 blobLen -= sizeof(keyclass);
531 }
532
533 size_t tagLen = 0;
534 uint32_t wrapped_key_size = 0;
535
536 switch (version) {
537 case 0:
538 wrapped_key_size = (uint32_t)CFDataGetLength(bulkKey) + v0KeyWrapOverHead;
539 break;
540 case 2:
541 case 3:
542 /* DROPTHROUGH */
543 /* v2 and v3 have the same crypto, just different dictionary encodings. */
544 /* Difference between v3 and v6 is already handled above, so treat v3 as v6. */
545 case 4:
546 case 5:
547 case 6:
548 tagLen = 16;
549 /* DROPTHROUGH */
550 case 1:
551 if (blobLen < sizeof(wrapped_key_size)) {
552 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow (wrapped_key_size)"));
553 goto out;
554 }
555 wrapped_key_size = *((uint32_t *)cursor);
556
557 cursor += sizeof(wrapped_key_size);
558 blobLen -= sizeof(wrapped_key_size);
559
560 break;
561 default:
562 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid version %d"), version);
563 goto out;
564 }
565
566 if (blobLen < tagLen + wrapped_key_size) {
567 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow (wrapped_key/taglen)"));
568 goto out;
569 }
570
571 size_t ctLen = blobLen - tagLen - wrapped_key_size;
572
573 /*
574 * Pre-version 2 have some additial constraints since it use AES in CBC mode
575 */
576 if (version < 2) {
577 if (ctLen < kCCBlockSizeAES128) {
578 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: Check for underflow (CBC check)"));
579 goto out;
580 }
581 if ((ctLen & 0xF) != 0) {
582 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: invalid length on CBC data"));
583 goto out;
584 }
585 }
586
587 #if USE_KEYSTORE
588 if (hasProtectionData) {
589 if (caller_access_groups) {
590 caller_access_groups_data = kc_copy_access_groups_data(caller_access_groups, error);
591 require_quiet(ok = (caller_access_groups_data != NULL), out);
592 }
593
594 require_quiet(ok = kc_attribs_key_encrypted_data_from_blob(keybag, db_class, cursor, wrapped_key_size, access_control, version,
595 &authenticated_attributes, &ref_key, &ed_data, error), out);
596 if (CFEqual(cryptoOp, kAKSKeyOpDecrypt)) {
597 require_quiet(ok = ks_decrypt_acl(ref_key, ed_data, bulkKey, acm_context, caller_access_groups_data, access_control, error), out);
598 } else if (CFEqual(cryptoOp, kAKSKeyOpDelete)) {
599 require_quiet(ok = ks_delete_acl(ref_key, ed_data, acm_context, caller_access_groups_data, access_control, error), out);
600 attributes = CFRetainSafe(authenticated_attributes);
601 goto out;
602 } else {
603 ok = SecError(errSecInternal, error, CFSTR("ks_decrypt_data: invalid operation"));
604 goto out;
605 }
606 } else
607 #endif
608 {
609 /* Now unwrap the bulk key using a key in the keybag. */
610 require_quiet(ok = ks_crypt(cryptoOp, keybag,
611 keyclass, wrapped_key_size, cursor, NULL, bulkKey, error), out);
612 }
613
614 if (iv) {
615 // AAD is (version || ... [|| key_wrapped_size ])
616 aad = CFDataGetBytePtr(blob);
617 aadLen = cursor - aad;
618 }
619
620 cursor += wrapped_key_size;
621
622 plainText = CFDataCreateMutable(NULL, ctLen);
623 if (!plainText) {
624 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: failed to allocate data for plain text"));
625 goto out;
626 }
627 CFDataSetLength(plainText, ctLen);
628
629 /* Decrypt the cipherText with the bulkKey. */
630 CCCryptorStatus ccerr;
631 if (tagLen) {
632 uint8_t tag[tagLen];
633 ccerr = CCCryptorGCM(kCCDecrypt, kCCAlgorithmAES128,
634 CFDataGetBytePtr(bulkKey), CFDataGetLength(bulkKey),
635 iv, ivLen, /* iv */
636 aad, aadLen, /* auth data */
637 cursor, ctLen,
638 CFDataGetMutableBytePtr(plainText),
639 tag, &tagLen);
640 if (ccerr) {
641 /* TODO: Should this be errSecDecode once AppleKeyStore correctly
642 identifies uuid unwrap failures? */
643 /* errSecInteractionNotAllowed; */
644 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCryptorGCM failed: %d"), ccerr);
645 goto out;
646 }
647 if (tagLen != 16) {
648 ok = SecError(errSecInternal, error, CFSTR("ks_decrypt_data: CCCryptorGCM expected: 16 got: %ld byte tag"), tagLen);
649 goto out;
650 }
651 cursor += ctLen;
652 if (timingsafe_bcmp(tag, cursor, tagLen)) {
653 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCryptorGCM computed tag not same as tag in blob"));
654 goto out;
655 }
656 } else {
657 size_t ptLen;
658 ccerr = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
659 CFDataGetBytePtr(bulkKey), CFDataGetLength(bulkKey), NULL, cursor, ctLen,
660 CFDataGetMutableBytePtr(plainText), ctLen, &ptLen);
661 if (ccerr) {
662 /* TODO: Should this be errSecDecode once AppleKeyStore correctly
663 identifies uuid unwrap failures? */
664 /* errSecInteractionNotAllowed; */
665 ok = SecError(errSecDecode, error, CFSTR("ks_decrypt_data: CCCrypt failed: %d"), ccerr);
666 goto out;
667 }
668 CFDataSetLength(plainText, ptLen);
669 }
670
671 if (version < 2) {
672 attributes = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
673 CFDictionaryAddValue(attributes, CFSTR("v_Data"), plainText);
674 } else if (version < 3) {
675 attributes = s3dl_item_v2_decode(plainText, error);
676 } else {
677 attributes = s3dl_item_v3_decode(plainText, error);
678 }
679
680 require_action_quiet(attributes, out, { ok = false; secerror("decode v%d failed: %@", version, error ? *error : NULL); });
681
682 #if USE_KEYSTORE
683 if (version >= 4 && authenticated_attributes != NULL) {
684 CFDictionaryForEach(authenticated_attributes, ^(const void *key, const void *value) {
685 CFDictionaryAddValue(attributes, key, value);
686 });
687 }
688 #endif
689
690 out:
691 memset(CFDataGetMutableBytePtr(bulkKey), 0, CFDataGetLength(bulkKey));
692 CFReleaseNull(bulkKey);
693 CFReleaseNull(plainText);
694
695 // Always copy access control data (if present), because if we fail it may indicate why.
696 if (paccess_control)
697 *paccess_control = access_control;
698 else
699 CFReleaseNull(access_control);
700
701 if (ok) {
702 if (attributes_p)
703 CFRetainAssign(*attributes_p, attributes);
704 if (version_p)
705 *version_p = version;
706 }
707 CFReleaseNull(attributes);
708 #if USE_KEYSTORE
709 CFReleaseNull(authenticated_attributes);
710 CFReleaseNull(caller_access_groups_data);
711 CFReleaseNull(ed_data);
712 if (ref_key) aks_ref_key_free(&ref_key);
713 #endif
714 return ok;
715 }
716
717 static keyclass_t kc_parse_keyclass(CFTypeRef value, CFErrorRef *error) {
718 if (!isString(value)) {
719 SecError(errSecParam, error, CFSTR("accessible attribute %@ not a string"), value);
720 } else if (CFEqual(value, kSecAttrAccessibleWhenUnlocked)) {
721 return key_class_ak;
722 } else if (CFEqual(value, kSecAttrAccessibleAfterFirstUnlock)) {
723 return key_class_ck;
724 } else if (CFEqual(value, kSecAttrAccessibleAlwaysPrivate)) {
725 return key_class_dk;
726 } else if (CFEqual(value, kSecAttrAccessibleWhenUnlockedThisDeviceOnly)) {
727 return key_class_aku;
728 } else if (CFEqual(value, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)) {
729 return key_class_cku;
730 } else if (CFEqual(value, kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate)) {
731 return key_class_dku;
732 } else if (CFEqual(value, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly)) {
733 return key_class_akpu;
734 } else {
735 SecError(errSecParam, error, CFSTR("accessible attribute %@ unknown"), value);
736 }
737 return 0;
738 }
739
740 static CFTypeRef kc_encode_keyclass(keyclass_t keyclass) {
741 switch (keyclass) {
742 case key_class_ak:
743 return kSecAttrAccessibleWhenUnlocked;
744 case key_class_ck:
745 return kSecAttrAccessibleAfterFirstUnlock;
746 case key_class_dk:
747 return kSecAttrAccessibleAlwaysPrivate;
748 case key_class_aku:
749 return kSecAttrAccessibleWhenUnlockedThisDeviceOnly;
750 case key_class_cku:
751 return kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
752 case key_class_dku:
753 return kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate;
754 case key_class_akpu:
755 return kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly;
756 default:
757 return 0;
758 }
759 }
760
761 #if USE_KEYSTORE
762 static bool kc_attribs_key_encrypted_data_from_blob(keybag_handle_t keybag, const SecDbClass *class, const void *blob_data, size_t blob_data_len, SecAccessControlRef access_control, uint32_t version,
763 CFMutableDictionaryRef *authenticated_attributes, aks_ref_key_t *ref_key, CFDataRef *encrypted_data, CFErrorRef *error)
764 {
765 CFMutableDictionaryRef acl = NULL;
766 CFDictionaryRef blob_dict = NULL;
767 aks_ref_key_t tmp_ref_key = NULL;
768 CFDataRef key_data = NULL;
769 CFDataRef ed = NULL;
770 bool ok = false;
771
772 der_decode_plist(NULL, kCFPropertyListImmutable, (CFPropertyListRef*)&blob_dict, NULL, blob_data, blob_data + blob_data_len);
773 require_action_quiet(blob_dict, out, SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: failed to decode 'blob data'")));
774
775 if (!ks_separate_data_and_key(blob_dict, &ed, &key_data)) {
776 ed = CFDataCreate(kCFAllocatorDefault, blob_data, blob_data_len);
777 key_data = CFRetain(ed);
778 }
779 require_action_quiet(ed, out, SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: failed to decode 'encrypted data'")));
780 require_action_quiet(key_data, out, SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: failed to decode 'key data'")));
781
782 const void *external_data = NULL;
783 size_t external_data_len = 0;
784 require_quiet(external_data = ks_ref_key_get_external_data(keybag, key_data, &tmp_ref_key, &external_data_len, error), out);
785
786 CFPropertyListRef external_data_dict = NULL;
787 der_decode_plist(NULL, kCFPropertyListImmutable, &external_data_dict, NULL, external_data, external_data + external_data_len);
788 require_action_quiet(external_data_dict, out, SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: failed to decode 'encrypted data dictionary'")));
789 acl = CFDictionaryCreateMutableCopy(NULL, 0, external_data_dict);
790 SecDbForEachAttrWithMask(class, attr_desc, kSecDbInAuthenticatedDataFlag) {
791 CFDictionaryRemoveValue(acl, attr_desc->name);
792 CFTypeRef value = CFDictionaryGetValue(external_data_dict, attr_desc->name);
793 if (value) {
794 if (!*authenticated_attributes)
795 *authenticated_attributes = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
796
797 CFDictionaryAddValue(*authenticated_attributes, attr_desc->name, value);
798 }
799 }
800 CFReleaseSafe(external_data_dict);
801
802 if (acl) {
803 /* v4 data format used wrong ACL placement, for backward compatibility we have to support both formats */
804 if (version == 4) {
805 SecAccessControlSetConstraints(access_control, acl);
806 } else {
807 CFDictionaryRef constraints = CFDictionaryGetValue(acl, kAKSKeyAcl);
808 require_action_quiet(isDictionary(constraints), out,
809 SecError(errSecDecode, error, CFSTR("kc_attribs_key_encrypted_data_from_blob: acl missing")));
810 SecAccessControlSetConstraints(access_control, constraints);
811 }
812
813 /* v4/v5 data format usualy does not contain kAKSKeyOpEncrypt, so add kAKSKeyOpEncrypt if is missing */
814 if (version < 6) {
815 SecAccessConstraintRef encryptConstraint = SecAccessControlGetConstraint(access_control, kAKSKeyOpEncrypt);
816 if (!encryptConstraint)
817 SecAccessControlAddConstraintForOperation(access_control, kAKSKeyOpEncrypt, kCFBooleanTrue, NULL);
818 }
819
820 }
821
822 if (encrypted_data)
823 *encrypted_data = CFRetain(ed);
824
825 if (ref_key) {
826 *ref_key = tmp_ref_key;
827 tmp_ref_key = NULL;
828 }
829
830 ok = true;
831
832 out:
833 if (tmp_ref_key)
834 aks_ref_key_free(&tmp_ref_key);
835 CFReleaseSafe(blob_dict);
836 CFReleaseSafe(key_data);
837 CFReleaseSafe(ed);
838 CFReleaseSafe(acl);
839
840
841 return ok;
842 }
843
844 static CFDataRef kc_create_auth_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes) {
845 CFDictionaryRef constraints = SecAccessControlGetConstraints(access_control);
846 CFMutableDictionaryRef auth_data = CFDictionaryCreateMutableCopy(NULL, 0, auth_attributes);
847 CFDictionarySetValue(auth_data, kAKSKeyAcl, constraints);
848 CFDataRef encoded = CFPropertyListCreateDERData(kCFAllocatorDefault, auth_data, NULL);
849 CFReleaseSafe(auth_data);
850 return encoded;
851 }
852
853 static CFDataRef kc_copy_access_groups_data(CFArrayRef access_groups, CFErrorRef *error)
854 {
855 size_t ag_size = der_sizeof_plist(access_groups, error);
856 CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0);
857 CFDataSetLength(result, ag_size);
858 if (!der_encode_plist(access_groups, error, CFDataGetMutableBytePtr(result), CFDataGetMutableBytePtr(result) + ag_size)) {
859 CFRelease(result);
860 return NULL;
861 }
862 else
863 return result;
864 }
865
866 #endif /* USE_KEYSTORE */
867
868 static CFDataRef kc_copy_protection_data(SecAccessControlRef access_control)
869 {
870 CFTypeRef protection = SecAccessControlGetProtection(access_control);
871 size_t protection_size = der_sizeof_plist(protection, NULL);
872 CFMutableDataRef result = CFDataCreateMutable(NULL, 0);
873 CFDataSetLength(result, protection_size);
874 if (!der_encode_plist(protection, NULL, CFDataGetMutableBytePtr(result), CFDataGetMutableBytePtr(result) + protection_size)) {
875 CFRelease(result);
876 return NULL;
877 }
878 else
879 return result;
880 }
881
882 static CFTypeRef kc_copy_protection_from(const uint8_t *der, const uint8_t *der_end)
883 {
884 CFTypeRef result = NULL;
885 der_decode_plist(NULL, kCFPropertyListImmutable, &result, NULL, der, der_end);
886 return result;
887 }
888
889 /* Return a (mutable) dictionary if plist is a dictionary, return NULL and set error otherwise. Does nothing if plist is already NULL. */
890 static CF_RETURNS_RETAINED
891 CFMutableDictionaryRef dictionaryFromPlist(CFPropertyListRef plist CF_CONSUMED, CFErrorRef *error) {
892 if (plist && !isDictionary(plist)) {
893 CFStringRef typeName = CFCopyTypeIDDescription(CFGetTypeID((CFTypeRef)plist));
894 SecError(errSecDecode, error, CFSTR("plist is a %@, expecting a dictionary"), typeName);
895 CFReleaseSafe(typeName);
896 CFReleaseNull(plist);
897 }
898 return (CFMutableDictionaryRef)plist;
899 }
900
901 static CF_RETURNS_RETAINED
902 CFMutableDictionaryRef s3dl_item_v2_decode(CFDataRef plain, CFErrorRef *error) {
903 CFPropertyListRef item;
904 item = CFPropertyListCreateWithData(0, plain, kCFPropertyListMutableContainers, NULL, error);
905 return dictionaryFromPlist(item, error);
906 }
907
908 static const uint8_t* (^s3dl_item_v3_decode_repair_date)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*, const uint8_t*, const uint8_t*) =
909 ^const uint8_t*(CFAllocatorRef allocator, CFOptionFlags mutability, CFPropertyListRef* pl, CFErrorRef *error, const uint8_t* der, const uint8_t *der_end) {
910 if (error && CFEqualSafe(CFErrorGetDomain(*error), sSecDERErrorDomain) && CFErrorGetCode(*error) == kSecDERErrorUnknownEncoding) {
911 CFAbsoluteTime date = 0;
912 CFCalendarRef calendar = CFCalendarCreateWithIdentifier(allocator, kCFGregorianCalendar);
913 CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(allocator, 0);
914 CFCalendarSetTimeZone(calendar, tz);
915 CFCalendarComposeAbsoluteTime(calendar, &date, "yMd", 2001, 3, 24); // random date for <rdar://problem/20458954> 15A143: can't recover keychain
916 CFReleaseSafe(tz);
917 CFReleaseSafe(calendar);
918
919 *pl = CFDateCreate(allocator, date);
920 if (NULL != *pl) {
921 CFReleaseNull(*error);
922 return der_end;
923 }
924 }
925 return NULL;
926 };
927
928 static CF_RETURNS_RETAINED
929 CFMutableDictionaryRef s3dl_item_v3_decode(CFDataRef plain, CFErrorRef *error) {
930 CFPropertyListRef item = NULL;
931 const uint8_t *der_beg = CFDataGetBytePtr(plain);
932 const uint8_t *der_end = der_beg + CFDataGetLength(plain);
933 const uint8_t *der = der_decode_plist(0, kCFPropertyListMutableContainers, &item, error, der_beg, der_end);
934 if (!der && error && CFEqualSafe(CFErrorGetDomain(*error), sSecDERErrorDomain) && CFErrorGetCode(*error) == kSecDERErrorUnknownEncoding) {
935 CFReleaseNull(*error);
936 der = der_decode_plist_with_repair(0, kCFPropertyListMutableContainers, &item, error, der_beg, der_end, s3dl_item_v3_decode_repair_date);
937 }
938 if (der && der != der_end) {
939 SecCFCreateError(errSecDecode, kSecErrorDomain, CFSTR("trailing garbage at end of decrypted item"), NULL, error);
940 CFReleaseNull(item);
941 }
942 return dictionaryFromPlist(item, error);
943 }
944
945 bool s3dl_item_from_data(CFDataRef edata, Query *q, CFArrayRef accessGroups,
946 CFMutableDictionaryRef *item, SecAccessControlRef *access_control, keyclass_t* keyclass, CFErrorRef *error) {
947 SecAccessControlRef ac = NULL;
948 CFDataRef ac_data = NULL;
949 bool ok = false;
950
951 /* Decrypt and decode the item and check the decoded attributes against the query. */
952 uint32_t version = 0;
953
954 bool decryptSecretData = false;
955 if ((q->q_return_type & kSecReturnDataMask) || (q->q_return_type & kSecReturnRefMask)) {
956 decryptSecretData = true;
957 }
958 else if (q->q_match_policy || q->q_match_valid_on_date || q->q_match_trusted_only) {
959 decryptSecretData = true;
960 }
961
962 require_quiet((ok = ks_decrypt_data(q->q_keybag, kAKSKeyOpDecrypt, &ac, q->q_use_cred_handle, edata, q->q_class,
963 q->q_caller_access_groups, item, &version, decryptSecretData, keyclass, error)), out);
964 if (version < 2) {
965 goto out;
966 }
967
968 ac_data = SecAccessControlCopyData(ac);
969 if (!itemInAccessGroup(*item, accessGroups)) {
970 secerror("items accessGroup %@ not in %@",
971 CFDictionaryGetValue(*item, kSecAttrAccessGroup),
972 accessGroups);
973 ok = SecError(errSecDecode, error, CFSTR("items accessGroup %@ not in %@"),
974 CFDictionaryGetValue(*item, kSecAttrAccessGroup),
975 accessGroups);
976 CFReleaseNull(*item);
977 }
978
979 /* AccessControl attribute does not exist in the db, so synthesize it. */
980 if (version > 3)
981 CFDictionarySetValue(*item, kSecAttrAccessControl, ac_data);
982
983 /* TODO: Validate access_control attribute. */
984
985 out:
986 if (access_control)
987 *access_control = CFRetainSafe(ac);
988 CFReleaseSafe(ac);
989 CFReleaseSafe(ac_data);
990 return ok;
991 }
992
993 /* Infer accessibility and access group for pre-v2 (iOS4.x and earlier) items
994 being imported from a backup. */
995 static bool SecDbItemImportMigrate(SecDbItemRef item, CFErrorRef *error) {
996 bool ok = true;
997 CFStringRef agrp = SecDbItemGetCachedValueWithName(item, kSecAttrAccessGroup);
998 CFStringRef accessible = SecDbItemGetCachedValueWithName(item, kSecAttrAccessible);
999
1000 if (!isString(agrp) || !isString(accessible))
1001 return ok;
1002 if (SecDbItemGetClass(item) == genp_class() && CFEqual(accessible, kSecAttrAccessibleAlwaysPrivate)) {
1003 CFStringRef svce = SecDbItemGetCachedValueWithName(item, kSecAttrService);
1004 if (!isString(svce)) return ok;
1005 if (CFEqual(agrp, CFSTR("apple"))) {
1006 if (CFEqual(svce, CFSTR("AirPort"))) {
1007 ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleAfterFirstUnlock, error);
1008 } else if (CFEqual(svce, CFSTR("com.apple.airplay.password"))) {
1009 ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error);
1010 } else if (CFEqual(svce, CFSTR("YouTube"))) {
1011 ok = (SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error) &&
1012 SecDbItemSetValueWithName(item, kSecAttrAccessGroup, CFSTR("com.apple.youtube.credentials"), error));
1013 } else {
1014 CFStringRef desc = SecDbItemGetCachedValueWithName(item, kSecAttrDescription);
1015 if (!isString(desc)) return ok;
1016 if (CFEqual(desc, CFSTR("IPSec Shared Secret")) || CFEqual(desc, CFSTR("PPP Password"))) {
1017 ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleAfterFirstUnlock, error);
1018 }
1019 }
1020 }
1021 } else if (SecDbItemGetClass(item) == inet_class() && CFEqual(accessible, kSecAttrAccessibleAlwaysPrivate)) {
1022 if (CFEqual(agrp, CFSTR("PrintKitAccessGroup"))) {
1023 ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error);
1024 } else if (CFEqual(agrp, CFSTR("apple"))) {
1025 CFTypeRef ptcl = SecDbItemGetCachedValueWithName(item, kSecAttrProtocol);
1026 bool is_proxy = false;
1027 if (isNumber(ptcl)) {
1028 SInt32 iptcl;
1029 CFNumberGetValue(ptcl, kCFNumberSInt32Type, &iptcl);
1030 is_proxy = (iptcl == FOUR_CHAR_CODE('htpx') ||
1031 iptcl == FOUR_CHAR_CODE('htsx') ||
1032 iptcl == FOUR_CHAR_CODE('ftpx') ||
1033 iptcl == FOUR_CHAR_CODE('rtsx') ||
1034 iptcl == FOUR_CHAR_CODE('xpth') ||
1035 iptcl == FOUR_CHAR_CODE('xsth') ||
1036 iptcl == FOUR_CHAR_CODE('xptf') ||
1037 iptcl == FOUR_CHAR_CODE('xstr'));
1038 } else if (isString(ptcl)) {
1039 is_proxy = (CFEqual(ptcl, kSecAttrProtocolHTTPProxy) ||
1040 CFEqual(ptcl, kSecAttrProtocolHTTPSProxy) ||
1041 CFEqual(ptcl, kSecAttrProtocolRTSPProxy) ||
1042 CFEqual(ptcl, kSecAttrProtocolFTPProxy));
1043 }
1044 if (is_proxy)
1045 ok = SecDbItemSetValueWithName(item, kSecAttrAccessible, kSecAttrAccessibleWhenUnlocked, error);
1046 }
1047 }
1048 return ok;
1049 }
1050
1051 bool SecDbItemDecrypt(SecDbItemRef item, bool decryptSecretData, CFDataRef edata, CFErrorRef *error) {
1052 bool ok = true;
1053 CFMutableDictionaryRef dict = NULL;
1054 SecAccessControlRef access_control = NULL;
1055 uint32_t version = 0;
1056
1057 require_quiet(ok = ks_decrypt_data(SecDbItemGetKeybag(item), item->cryptoOp, &access_control, item->credHandle, edata,
1058 item->class, item->callerAccessGroups, &dict, &version, decryptSecretData, NULL, error), out);
1059
1060 if (version < 2) {
1061 /* Old V4 style keychain backup being imported. */
1062 ok = SecDbItemSetValueWithName(item, CFSTR("v_Data"), CFDictionaryGetValue(dict, CFSTR("v_Data")), error) &&
1063 SecDbItemImportMigrate(item, error);
1064 } else {
1065 ok = dict && SecDbItemSetValues(item, dict, error);
1066 }
1067
1068 SecAccessControlRef my_access_control = SecDbItemCopyAccessControl(item, error);
1069 if (!my_access_control) {
1070 ok = false;
1071 goto out;
1072 }
1073
1074 /* Make sure that the protection of ACL in the dictionary (read from DB) matched what we got
1075 back from decoding the data blob. */
1076 if (!CFEqual(SecAccessControlGetProtection(my_access_control), SecAccessControlGetProtection(access_control))) {
1077 ok = SecError(errSecDecode, error, CFSTR("ACL protection doesn't match the one in blob (%@ : %@)"),
1078 SecAccessControlGetProtection(my_access_control),
1079 SecAccessControlGetProtection(access_control));
1080 }
1081 CFRelease(my_access_control);
1082
1083 out:
1084 // If we got protection back from ks_decrypt_data, update the appropriate attribute even if anything else
1085 // (incl. actual decryption) failed. We need to access the protection type even if we are not able to actually
1086 // decrypt the data.
1087 ok = SecDbItemSetAccessControl(item, access_control, NULL) && ok;
1088
1089 CFReleaseSafe(dict);
1090 CFReleaseSafe(access_control);
1091 return ok;
1092 }
1093
1094 /* Automagically make a item syncable, based on various attributes. */
1095 bool SecDbItemInferSyncable(SecDbItemRef item, CFErrorRef *error)
1096 {
1097 CFStringRef agrp = SecDbItemGetCachedValueWithName(item, kSecAttrAccessGroup);
1098
1099 if (!isString(agrp))
1100 return true;
1101
1102 if (CFEqual(agrp, CFSTR("com.apple.cfnetwork")) && SecDbItemGetClass(item) == inet_class()) {
1103 CFTypeRef srvr = SecDbItemGetCachedValueWithName(item, kSecAttrServer);
1104 CFTypeRef ptcl = SecDbItemGetCachedValueWithName(item, kSecAttrProtocol);
1105 CFTypeRef atyp = SecDbItemGetCachedValueWithName(item, kSecAttrAuthenticationType);
1106
1107 if (isString(srvr) && isString(ptcl) && isString(atyp)) {
1108 /* This looks like a Mobile Safari Password, make syncable */
1109 secnotice("item", "Make this item syncable: %@", item);
1110 return SecDbItemSetSyncable(item, true, error);
1111 }
1112 }
1113
1114 return true;
1115 }
1116
1117 /* This create a SecDbItem from the item dictionnary that are exported for backups.
1118 Item are stored in the backup as a dictionary containing two keys:
1119 - v_Data: the encrypted data blob
1120 - v_PersistentRef: a persistent Ref.
1121 src_keybag is normally the backup keybag.
1122 dst_keybag is normally the device keybag.
1123 */
1124 SecDbItemRef SecDbItemCreateWithBackupDictionary(CFAllocatorRef allocator, const SecDbClass *dbclass, CFDictionaryRef dict, keybag_handle_t src_keybag, keybag_handle_t dst_keybag, CFErrorRef *error)
1125 {
1126 CFDataRef edata = CFDictionaryGetValue(dict, CFSTR("v_Data"));
1127 SecDbItemRef item = NULL;
1128
1129 if (edata) {
1130 item = SecDbItemCreateWithEncryptedData(kCFAllocatorDefault, dbclass, edata, src_keybag, error);
1131 if (item)
1132 if (!SecDbItemSetKeybag(item, dst_keybag, error))
1133 CFReleaseNull(item);
1134 } else {
1135 SecError(errSecDecode, error, CFSTR("No v_Data in backup dictionary %@"), dict);
1136 }
1137
1138 return item;
1139 }
1140
1141 bool SecDbItemExtractRowIdFromBackupDictionary(SecDbItemRef item, CFDictionaryRef dict, CFErrorRef *error) {
1142 CFDataRef ref = CFDictionaryGetValue(dict, CFSTR("v_PersistentRef"));
1143 if (!ref)
1144 return SecError(errSecDecode, error, CFSTR("No v_PersistentRef in backup dictionary %@"), dict);
1145
1146 CFStringRef className;
1147 sqlite3_int64 rowid;
1148 if (!_SecItemParsePersistentRef(ref, &className, &rowid, NULL))
1149 return SecError(errSecDecode, error, CFSTR("v_PersistentRef %@ failed to decode"), ref);
1150
1151 if (!CFEqual(SecDbItemGetClass(item)->name, className))
1152 return SecError(errSecDecode, error, CFSTR("v_PersistentRef has unexpected class %@"), className);
1153
1154 return SecDbItemSetRowId(item, rowid, error);
1155 }
1156
1157 static CFDataRef SecDbItemCopyDERWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error) {
1158 CFDataRef der = NULL;
1159 CFMutableDictionaryRef dict = SecDbItemCopyPListWithMask(item, mask, error);
1160 if (dict) {
1161 der = CFPropertyListCreateDERData(kCFAllocatorDefault, dict, error);
1162 CFRelease(dict);
1163 }
1164 return der;
1165 }
1166
1167 static CFTypeRef SecDbItemCopyDigestWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error) {
1168 CFDataRef digest = NULL;
1169 CFDataRef der = SecDbItemCopyDERWithMask(item, mask, error);
1170 if (der) {
1171 digest = CFDataCopySHA1Digest(der, error);
1172 CFRelease(der);
1173 }
1174 return digest;
1175 }
1176
1177 static CFTypeRef SecDbItemCopySHA256DigestWithMask(SecDbItemRef item, CFOptionFlags mask, CFErrorRef *error) {
1178 CFDataRef digest = NULL;
1179 CFDataRef der = SecDbItemCopyDERWithMask(item, mask, error);
1180 if (der) {
1181 digest = CFDataCopySHA256Digest(der, error);
1182 CFRelease(der);
1183 }
1184 return digest;
1185 }
1186
1187 CFTypeRef SecDbKeychainItemCopyPrimaryKey(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error) {
1188 return SecDbItemCopyDigestWithMask(item, kSecDbPrimaryKeyFlag, error);
1189 }
1190
1191 CFTypeRef SecDbKeychainItemCopySHA256PrimaryKey(SecDbItemRef item, CFErrorRef *error) {
1192 return SecDbItemCopySHA256DigestWithMask(item, kSecDbPrimaryKeyFlag, error);
1193 }
1194
1195 CFTypeRef SecDbKeychainItemCopySHA1(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error) {
1196 return SecDbItemCopyDigestWithMask(item, kSecDbInHashFlag, error);
1197 }
1198
1199 CFTypeRef SecDbKeychainItemCopyEncryptedData(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error) {
1200 CFDataRef edata = NULL;
1201 CFMutableDictionaryRef secretStuff = SecDbItemCopyPListWithMask(item, kSecDbReturnDataFlag, error);
1202 CFMutableDictionaryRef attributes = SecDbItemCopyPListWithMask(item, kSecDbInCryptoDataFlag, error);
1203 CFMutableDictionaryRef auth_attributes = SecDbItemCopyPListWithMask(item, kSecDbInAuthenticatedDataFlag, error);
1204 if (secretStuff || attributes || auth_attributes) {
1205 SecAccessControlRef access_control = SecDbItemCopyAccessControl(item, error);
1206 CFDataRef sha1 = SecDbKeychainItemCopySHA1(item, attr, error);
1207 if (access_control && sha1) {
1208 if (!auth_attributes) {
1209 auth_attributes = CFDictionaryCreateMutable(NULL, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1210 }
1211 CFDictionarySetValue(auth_attributes, kSecAttrSHA1, sha1);
1212
1213 CFDictionaryForEach(secretStuff, ^(const void *key, const void *value) {
1214 CFDictionaryRemoveValue(attributes, key);
1215 CFDictionaryRemoveValue(auth_attributes, key);
1216 });
1217
1218 if (ks_encrypt_data(item->keybag, access_control, item->credHandle, secretStuff, attributes, auth_attributes, &edata, true, error)) {
1219 item->_edataState = kSecDbItemEncrypting;
1220 } else if (!error || !*error || CFErrorGetCode(*error) != errSecAuthNeeded || !CFEqualSafe(CFErrorGetDomain(*error), kSecErrorDomain) ) {
1221 seccritical("ks_encrypt_data (db): failed: %@", error ? *error : (CFErrorRef)CFSTR(""));
1222 }
1223 CFRelease(access_control);
1224 }
1225 CFReleaseNull(secretStuff);
1226 CFReleaseNull(attributes);
1227 CFReleaseNull(auth_attributes);
1228 CFReleaseNull(sha1);
1229 }
1230
1231 return edata;
1232 }
1233
1234 CFTypeRef SecDbKeychainItemCopyCurrentDate(SecDbItemRef item, const SecDbAttr *attr, CFErrorRef *error) {
1235 CFTypeRef value = NULL;
1236 switch (attr->kind) {
1237 case kSecDbDateAttr:
1238 value = CFDateCreate(kCFAllocatorDefault, 0.0);
1239 break;
1240 case kSecDbCreationDateAttr:
1241 case kSecDbModificationDateAttr:
1242 value = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent());
1243 break;
1244 default:
1245 SecError(errSecInternal, error, CFSTR("attr %@ has no default value"), attr->name);
1246 value = NULL;
1247 }
1248
1249 return value;
1250 }
1251
1252 SecAccessControlRef SecDbItemCopyAccessControl(SecDbItemRef item, CFErrorRef *error) {
1253 SecAccessControlRef accc = NULL, pdmn = NULL, result = NULL;
1254 CFTypeRef acccData = SecDbItemGetValue(item, SecDbClassAttrWithKind(item->class, kSecDbAccessControlAttr, error), error);
1255 CFTypeRef pdmnValue = SecDbItemGetValue(item, SecDbClassAttrWithKind(item->class, kSecDbAccessAttr, error), error);
1256
1257 if (!acccData || !pdmnValue)
1258 return NULL;
1259 if (!CFEqual(acccData, kCFNull))
1260 require_quiet(accc = SecAccessControlCreateFromData(CFGetAllocator(item), acccData, error), out);
1261
1262 if (!CFEqual(pdmnValue, kCFNull)) {
1263 require_quiet(pdmn = SecAccessControlCreate(CFGetAllocator(item), error), out);
1264 require_quiet(SecAccessControlSetProtection(pdmn, pdmnValue, error), out);
1265 }
1266
1267 if (accc && pdmn) {
1268 CFTypeRef acccProt = SecAccessControlGetProtection(accc);
1269 CFTypeRef pdmnProt = SecAccessControlGetProtection(pdmn);
1270 if (!acccProt || !pdmnProt || !CFEqual(acccProt, pdmnProt)) {
1271 secerror("SecDbItemCopyAccessControl accc %@ != pdmn %@, setting pdmn to accc value", acccProt, pdmnProt);
1272 __security_simulatecrash(CFSTR("Corrupted item on decrypt accc != pdmn"), __sec_exception_code_CorruptItem);
1273 // Setting pdmn to accc prot value.
1274 require_quiet(SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbAccessAttr, error), acccProt, error), out);
1275 }
1276 }
1277
1278 if (accc)
1279 CFRetainAssign(result, accc);
1280 else if(pdmn)
1281 CFRetainAssign(result, pdmn);
1282
1283 out:
1284 CFReleaseSafe(accc);
1285 CFReleaseSafe(pdmn);
1286
1287 return result;
1288 }
1289
1290 static const uint8_t* der_decode_plist_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability,
1291 CFPropertyListRef* pl, CFErrorRef *error,
1292 const uint8_t* der, const uint8_t *der_end,
1293 const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*,
1294 const uint8_t*, const uint8_t*))
1295 {
1296 if (NULL == der) {
1297 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Null DER"), NULL, error);
1298 return NULL;
1299 }
1300
1301 ccder_tag tag;
1302 if (NULL == ccder_decode_tag(&tag, der, der_end)) {
1303 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding"), NULL, error);
1304 return NULL;
1305 }
1306
1307 switch (tag) {
1308 case CCDER_NULL:
1309 return der_decode_null(allocator, mutability, (CFNullRef*)pl, error, der, der_end);
1310 case CCDER_BOOLEAN:
1311 return der_decode_boolean(allocator, mutability, (CFBooleanRef*)pl, error, der, der_end);
1312 case CCDER_OCTET_STRING:
1313 return der_decode_data(allocator, mutability, (CFDataRef*)pl, error, der, der_end);
1314 case CCDER_GENERALIZED_TIME: {
1315 const uint8_t* der_result = der_decode_date(allocator, mutability, (CFDateRef*)pl, error, der, der_end);
1316 if (!der_result) {
1317 der_result = repairBlock(allocator, mutability, pl, error, der, der_end);
1318 }
1319 return der_result;
1320 }
1321 case CCDER_CONSTRUCTED_SEQUENCE:
1322 return der_decode_array_with_repair(allocator, mutability, (CFArrayRef*)pl, error, der, der_end, repairBlock);
1323 case CCDER_UTF8_STRING:
1324 return der_decode_string(allocator, mutability, (CFStringRef*)pl, error, der, der_end);
1325 case CCDER_INTEGER:
1326 return der_decode_number(allocator, mutability, (CFNumberRef*)pl, error, der, der_end);
1327 case CCDER_CONSTRUCTED_SET:
1328 return der_decode_dictionary_with_repair(allocator, mutability, (CFDictionaryRef*)pl, error, der, der_end, repairBlock);
1329 case CCDER_CONSTRUCTED_CFSET:
1330 return der_decode_set_with_repair(allocator, mutability, (CFSetRef*)pl, error, der, der_end, repairBlock);
1331 default:
1332 SecCFDERCreateError(kSecDERErrorUnsupportedDERType, CFSTR("Unsupported DER Type"), NULL, error);
1333 return NULL;
1334 }
1335 }
1336
1337 static const uint8_t* der_decode_dictionary_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability,
1338 CFDictionaryRef* dictionary, CFErrorRef *error,
1339 const uint8_t* der, const uint8_t *der_end,
1340 const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*,
1341 const uint8_t*, const uint8_t*))
1342 {
1343 if (NULL == der) {
1344 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Null DER"), NULL, error);
1345 return NULL;
1346 }
1347
1348 const uint8_t *payload_end = 0;
1349 const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SET, &payload_end, der, der_end);
1350
1351 if (NULL == payload) {
1352 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding, expected CCDER_CONSTRUCTED_SET"), NULL, error);
1353 return NULL;
1354 }
1355
1356
1357 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1358
1359 if (NULL == dict) {
1360 SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create dictionary"), NULL, error);
1361 payload = NULL;
1362 goto exit;
1363 }
1364
1365 while (payload != NULL && payload < payload_end) {
1366 CFTypeRef key = NULL;
1367 CFTypeRef value = NULL;
1368
1369 payload = der_decode_key_value_with_repair(allocator, mutability, &key, &value, error, payload, payload_end, repairBlock);
1370
1371 if (payload) {
1372 CFDictionaryAddValue(dict, key, value);
1373 }
1374
1375 CFReleaseNull(key);
1376 CFReleaseNull(value);
1377 }
1378
1379
1380 exit:
1381 if (payload == payload_end) {
1382 *dictionary = dict;
1383 dict = NULL;
1384 }
1385
1386 CFReleaseNull(dict);
1387
1388 return payload;
1389 }
1390
1391 static const uint8_t* der_decode_key_value_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability,
1392 CFPropertyListRef* key, CFPropertyListRef* value, CFErrorRef *error,
1393 const uint8_t* der, const uint8_t *der_end,
1394 const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*,
1395 const uint8_t*, const uint8_t*))
1396 {
1397 const uint8_t *payload_end = 0;
1398 const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &payload_end, der, der_end);
1399
1400 if (NULL == payload) {
1401 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding, expected CCDER_CONSTRUCTED_SEQUENCE"), NULL, error);
1402 return NULL;
1403 }
1404
1405 CFTypeRef keyObject = NULL;
1406 CFTypeRef valueObject = NULL;
1407
1408
1409 payload = der_decode_plist_with_repair(allocator, mutability, &keyObject, error, payload, payload_end, repairBlock);
1410 payload = der_decode_plist_with_repair(allocator, mutability, &valueObject, error, payload, payload_end, repairBlock);
1411
1412 if (payload != NULL) {
1413 *key = keyObject;
1414 *value = valueObject;
1415 } else {
1416 CFReleaseNull(keyObject);
1417 CFReleaseNull(valueObject);
1418 }
1419 return payload;
1420 }
1421
1422 static const uint8_t* der_decode_array_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability,
1423 CFArrayRef* array, CFErrorRef *error,
1424 const uint8_t* der, const uint8_t *der_end,
1425 const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*,
1426 const uint8_t*, const uint8_t*))
1427 {
1428 if (NULL == der) {
1429 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Null DER"), NULL, error);
1430 return NULL;
1431 }
1432
1433 CFMutableArrayRef result = CFArrayCreateMutable(allocator, 0, &kCFTypeArrayCallBacks);
1434
1435 const uint8_t *elements_end;
1436 const uint8_t *current_element = ccder_decode_sequence_tl(&elements_end, der, der_end);
1437
1438 while (current_element != NULL && current_element < elements_end) {
1439 CFPropertyListRef element = NULL;
1440 current_element = der_decode_plist_with_repair(allocator, mutability, &element, error, current_element, elements_end, repairBlock);
1441 if (current_element) {
1442 CFArrayAppendValue(result, element);
1443 CFReleaseNull(element);
1444 }
1445 }
1446
1447 if (current_element) {
1448 *array = result;
1449 result = NULL;
1450 }
1451
1452 CFReleaseNull(result);
1453 return current_element;
1454 }
1455
1456 static const uint8_t* der_decode_set_with_repair(CFAllocatorRef allocator, CFOptionFlags mutability,
1457 CFSetRef* set, CFErrorRef *error,
1458 const uint8_t* der, const uint8_t *der_end,
1459 const uint8_t* (^repairBlock)(CFAllocatorRef, CFOptionFlags, CFPropertyListRef*, CFErrorRef*,
1460 const uint8_t*, const uint8_t*))
1461 {
1462 if (NULL == der) {
1463 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Null DER"), NULL, error);
1464 return NULL;
1465 }
1466
1467 const uint8_t *payload_end = 0;
1468 const uint8_t *payload = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_CFSET, &payload_end, der, der_end);
1469
1470 if (NULL == payload) {
1471 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown data encoding, expected CCDER_CONSTRUCTED_CFSET"), NULL, error);
1472 return NULL;
1473 }
1474
1475 CFMutableSetRef theSet = (set && *set) ? CFSetCreateMutableCopy(allocator, 0, *set)
1476 : CFSetCreateMutable(allocator, 0, &kCFTypeSetCallBacks);
1477
1478 if (NULL == theSet) {
1479 SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Failed to create set"), NULL, error);
1480 payload = NULL;
1481 goto exit;
1482 }
1483
1484 while (payload != NULL && payload < payload_end) {
1485 CFTypeRef value = NULL;
1486
1487 payload = der_decode_plist_with_repair(allocator, mutability, &value, error, payload, payload_end, repairBlock);
1488
1489 if (payload) {
1490 CFSetAddValue(theSet, value);
1491 }
1492 CFReleaseNull(value);
1493 }
1494
1495
1496 exit:
1497 if (set && payload == payload_end) {
1498 CFTransferRetained(*set, theSet);
1499 }
1500
1501 CFReleaseNull(theSet);
1502
1503 return payload;
1504 }
1505
1506 void SecDbResetMetadataKeys(void) {
1507 #if !TARGET_OS_BRIDGE
1508 [SecDbKeychainMetadataKeyStore resetSharedStore];
1509 #endif
1510 }