title: SecItemAdd() : errSecParam Results When trying to use kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
body: <p>Dearest Stack Overflow Helpful Beings Of Light,</p>
  
  <p>When using the <strong>kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly</strong> attribute in a keychain entry for <strong>SecItemAdd()</strong>, what other attributes need to be included?  My understanding is that <strong>kSecAttrAccessControl</strong> and  <strong>kSecUseAuthenticationUI</strong> are appropriate, using a SecAccessControlRef instance and @(BOOL), accordingly.  This, however, is not working for me.</p>
  
  <p>I am attempting to save two dictionaries in two keychain entries.</p>
  
  <p>One is succeeding and the other is failing, 
  The one that is succeeding uses <strong>kSecAttrAccessibleAfterFirstUnlock</strong> for accessibility.
  The one that is failing uses <strong>kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly</strong>, and fails with a status of errSecParam (-50) - suggesting I’m using an incorrect parameter in what I pass to SecItemAdd().</p>
  
  <p>In the successful keychain entry there are 5 key/value pairs in the dictionary passed to SecItemAdd().</p>
  
  <pre><code>keychainQuery __NSDictionaryM *  5 key/value pairs
  [0] @"svce" : @"session"
  [1] @"acct" : @"com.xxx.yyy”
  [2] @"v_Data" : 490 bytes
  [3] @"class" : @"genp"
  [4] @"pdmn" : @"ck"
  </code></pre>
  
  <p>The @“ck” value for @“pdmn” corresponds to the kSecAttrAccessibleAfterFirstUnlock accessibility attribute.
  The keychain item is added, and able to be retrieved and the data successfully read from it.</p>
  
  <p>In the unsuccessful keychain entry there are 7 key/value pairs in the dictionary passed to SecItemAdd().</p>
  
  <pre><code>keychainQuery __NSDictionaryM *  7 key/value pairs
  [0] @"svce" : @"credentials"
  [1] @"acct" : @"com.xxx.yyy”
  [2] @"v_Data" : 370 bytes
  [3] @"class" : @"genp"
  [4] @"pdmn" : @"akpu"
  [5] @"accc" : (no summary)
  [6] @"u_AuthUI" : @"1"
  </code></pre>
  
  <p>The @“akpu” value for @“pdmn” corresponds to the kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly accessibility attribute.
  For this dictionary kSecAttrAccessControl and  kSecUseAuthenticationUI are also specified, using a SecAccessControlRef instance and @(YES) accordingly.</p>
  
  <p>Here’s how the base query is being created:</p>
  
  <pre><code>+ (NSMutableDictionary *)getKeychainQuery
  {
      NSMutableDictionary *queryDict = [NSMutableDictionary dictionary];
  
      queryDict[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;
      queryDict[(__bridge id)kSecAttrService] = [self service];
      queryDict[(__bridge id)kSecAttrAccount] = [self account];
  
      if( [self userPresence] )
      {
          CFErrorRef error = NULL;
          SecAccessControlRef sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
                                                                              [self accessibility],
                                                                              kSecAccessControlUserPresence, &amp;error);
  
          if (error == NULL || sacObject != NULL)
          {
              queryDict[(__bridge id)kSecAttrAccessControl] = (__bridge_transfer id)sacObject;
              queryDict[(__bridge id)kSecUseAuthenticationUI] = @YES;
          }
      }
  
      return queryDict;
  }
  </code></pre>
  
  <p>Here’s the usage: </p>
  
  <pre><code>+ (void)saveToKeychain:(XGKeychainItem *)keychainItem
  {
      NSMutableDictionary *keychainQuery = [self getKeychainQuery];
      keychainQuery[(__bridge id)kSecAttrAccessible] = (__bridge id)[self accessibility];
  
      NSData *keychainData = [NSKeyedArchiver archivedDataWithRootObject:keychainItem];
      keychainQuery[(__bridge id)kSecValueData] = keychainData;
  
      OSStatus addStatus = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
      NSLog(@"ADD STATUS: %d for service - %@", (int)addStatus, [self service]);
  }
  </code></pre>
  
  <p>If, immediately before passing the problem dictionary to SecItemAdd(), I remove the two attributes that are not in the first dictionary, and set the accessibility to match the first, the keychain item is successfully added.</p>
  
  <p>So, it seems that there’s something wrong with my usage of kSecUseAuthenticationUI, kSecAttrAccessControl, and/or with my SecAccessControlRef.  All of these, however, seem to check out with the documentation and all of the example code I can find, as well as all of the Stack Overflow threads I’ve dug up.</p>
  
  <p>What am I screwing up?  Why is one of these parameters displeasing to iOS?  If the suspect offending attributes are removed, I can decode the data without issue, so I'm confident my password data dictionary is not the problem.  What's my damage?</p>