Reputation: 1768
I'm trying to use Keychain Services to save a value, which would persist even if a user reinstalls the app. So I check if an item exists using SecItemCopyMatching
, which returns errSecItemNotFound
the first time and add a new item using SecItemAdd
, which returns errSecSuccess
, but the value of _attrs
is nil
. Also, when the code is called second time, the SecItemCopyMatching
still returns errSecItemNotFound
, as if SecItemAdd
wasn't called. So what that could be related to?
CFMutableDictionaryRef _attrs = nil;
NSString* key = @"<unique key>";
NSMutableDictionary* query = [NSMutableDictionary dictionary];
query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;
query[(__bridge id)kSecAttrLabel] = key;
query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
query[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue;
OSStatus err = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&_attrs);
if (err == errSecSuccess) {
return YES;
}
NSString* str = @"<some data>";
if (err == errSecItemNotFound) {
query[(__bridge id)kSecValueData] = NSData_from_string(string_from_NSString(str));
query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAlways;
err = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef*)&_attrs);
assert(err == errSecSuccess);
}
Upvotes: 1
Views: 1156
Reputation: 11143
You are re-using query
for your call to SecItemAdd
, and the kSecMatchLimit
value being present in the dictionary for this function is breaking it. You should remove this key before calling SecItemAdd
.
It's also worth noting that [str dataUsingEncoding:NSUTF8StringEncoding]
might be a better choice than whatever NSData_from_string(string_from_NSString(str))
is, depending on what you're doing.
Upvotes: 1