/ keychain / securityd / SecDbKeychainItem.m
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  }