A late answer, but an answer nonetheless:
I've been struggling with updating items in the keychain as well, my context was a little different though.
What happened:
I could add a keychain item with success (using SecItemAdd
), but calling SecItemUpdate
on the same item failed with the notorious errSecParam -50
.
What was even worse; if the keychain item already existed (hence I called SecItemUpdate
immediately), the update went through with no problems at all.
I've got absolutely no idea as of why that happened...
How I fixed it:
Quite simple actually, I just removed "params" until the big bad -50
was satisfied. This happened when I removed the kSecClass
from the dictionary I retrieved from kSecItemCopyMatching
.
Here's my code:
// If the item already exists, we update it instead
if (SecItemCopyMatching((__bridge CFDictionaryRef)self.searchQueryDict, (CFTypeRef *)&foundItem) == errSecSuccess) {
NSMutableDictionary *updateDict = (__bridge NSMutableDictionary *)foundItem;
[updateDict addEntriesFromDictionary:dictToSave];
[updateDict removeObjectForKey:(__bridge id)kSecClass];
OSStatus updateSuccess = SecItemUpdate((__bridge CFDictionaryRef)self.updateQueryDict,
(__bridge CFDictionaryRef)updateDict);
NSAssert(updateSuccess == errSecSuccess, @"Couldn't save the dirty info to the keychain, might want to log the updateSuccess (%d)", updateSuccess);
}
As a reference I used the following dictionaries
self.searchQueryDict
contained:
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword
(__bridge id)kSecAttrService : service
(__bridge id)kSecAttrGeneric : [identifier dataUsingEncoding:NSUTF8StringEncoding]
(__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitOne
(__bridge id)kSecReturnAttributes : (__bridge id)kCFBooleanTrue
(__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue
self.updateQueryDict
contained:
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : service,
(__bridge id)kSecAttrGeneric : [identifier dataUsingEncoding:NSUTF8StringEncoding]
dictToSave
should contain the values (in the correct format) which needs to change
Removing the kSecClass
fixed the problem for me.