title: Apple keychain store client identity so only my application could access it
body: <h2>Aim</h2>
  
  <p>I need to store client identity on OS X application in secure way in such way that only my application could access it. No prompting asking for permissions. </p>
  
  <h2>Problem</h2>
  
  <p>Problem appeared immediately when I was trying to store client identity.
  Here is code sample (what have I tied so far): </p>
  
  <pre><code>- (BOOL)saveClientIdentity:(SecIdentityRef)clientIdentity error:(NSError**) error
  {
      NSDictionary *attributes = @{
          (__bridge id)kSecAttrAccessible:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly,
          (__bridge id)kSecValueRef:(__bridge id)clientIdentity,
          (__bridge id)kSecAttrApplicationTag:[kMyKeychainAttrApplicationTag dataUsingEncoding: NSUTF8StringEncoding],
          (__bridge id)kSecAttrAccessGroup:kMyKeychainAttrAccessGroup
      };
  
      OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
      // status == -25299
      …
  }
  </code></pre>
  
  <p>I'm constantly getting code -25299 and tool expalint the problem:</p>
  
  <pre class="lang-sh prettyprint-override"><code>$ security error -25299
  Error: 0xFFFF9D2D -25299 The specified item already exists in the keychain.
  </code></pre>
  
  <p>So it tries override global client identity (I never successful written a client identity for this application so there shouldn't be such conflict) and I don't what to do that.
  It have to be private for only this application.</p>
  
  <p>I verified what happens for respective loading code. It loads my developer identity and I do not want that.</p>
  
  <pre><code>- (SecIdentityRef)clientIdentity
  {
      NSDictionary *attributes =
      @{
        (__bridge id)kSecClass:(__bridge id)kSecClassIdentity,
        (__bridge id)kSecAttrAccessible:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly,
        (__bridge id)kSecAttrApplicationTag:[kMyKeychainAttrApplicationTag dataUsingEncoding: NSUTF8StringEncoding],
        (__bridge id)kSecAttrAccessGroup:kMyKeychainAttrAccessGroup
        };
  
      CFTypeRef universalResult = NULL;
      OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)attributes, &amp;universalResult);
      SecIdentityRef result = (SecIdentityRef)universalResult;
      if (result)
      {
          CFAutorelease(result);
      }
      if (status != noErr)
      {
          NSLog(@"Failed to load client identity: %@", NSErrorFromStatusErrorCode(status));
      }
      return result;
  }
  </code></pre>
  
  <h2>Notes</h2>
  
  <p>I need to use same code for iOS, but here should be no problem since by default iOS keychain is not shared between applications.</p>