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