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