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