SecAddItem Only Retuns errSecParam, No Matter I Do
Asked Answered
Y

2

5

For some reason I can't get this simple keychain code to work.

//Let's create an empty mutable dictionary:
NSMutableDictionary *keychainItem = [NSMutableDictionary dictionary];

NSString *username = self.nwUsernameTxtFld.text;
NSString *password = self.passwordTxtFld.text;

//Populate it with the data and the attributes we want to use.

keychainItem[(__bridge id)kSecClass] = (__bridge id)kSecClassInternetPassword; // We specify what kind of keychain item this is.
keychainItem[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleWhenUnlocked; // This item can only be accessed when the user unlocks the device.
keychainItem[(__bridge id)kSecAttrServer] = @"http://www.myawesomeservice.com";
keychainItem[(__bridge id)kSecAttrAccount] = username; //Our username.

if(SecItemCopyMatching((__bridge CFDictionaryRef)keychainItem, NULL) == noErr)
{

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"The Item Already Exists", nil)
                                                    message:NSLocalizedString(@"Please update it instead.", )
                                                   delegate:nil
                                          cancelButtonTitle:NSLocalizedString(@"OK", nil)
                                          otherButtonTitles:nil];
    [alert show];

}else
{
    NSLog(@"can add new item.");
    keychainItem[(__bridge id)kSecValueData] = password; //Our password

    OSStatus sts = SecItemAdd((__bridge CFDictionaryRef)keychainItem, NULL);
    NSLog(@"%d", (int)sts);
}

I have checked Apple's documentation on the matter and according to it:

One or more parameters passed to the function were not valid.

Yet, the SecAddItem function takes two paramters:

OSStatus SecItemAdd (
   CFDictionaryRef attributes,
   CFTypeRef *result
);

I am passing NULL to result. This is acceptable according to Apple's documentation:

result On return, a reference to the newly added items. The exact type of the result is based on the values supplied in attributes, as discussed below. Pass NULL if this result is not required.

So I Don't really know what I'm doing wrong here. I'm passing it a dictionary and a NULL value. The function expects both and I'm giving it both. Can someone please enlighten me as to what's wrong?

For reference, the documentation is here.

Yandell answered 11/6, 2014 at 2:8 Comment(4)
What is the type of password in this code?Canto
NSString. Both username and password are NSString.Yandell
And what is the type listed for kSecValueData at the bottom of the page that you linked?Canto
Thanks. Can't believe I let that error pass. Feel free to add your comments as a more elaborated answer so I can mark it as the accepted answer.Yandell
C
5

You are inserting an incorrect data type into the dictionary for the key kSecValueData. As indicated in the documentation at the bottom of your question, it needs to be CFDataRef (or bridged NSData) but you are inserting an NSString instead. It is a trivial matter to convert NSString to NSData and once you do so you will stop having this error.

Canto answered 11/6, 2014 at 5:37 Comment(0)
Y
2

I got this error for setting the wrong kSecClass. I had used kSecClassInternetPassword instead of kSecClassGenericPassword. Hope this helps

Yalonda answered 10/2, 2016 at 15:4 Comment(2)
Whoever downvoted this, please justify why. At least to me, it makes sense this could be another cause for that error.Yandell
As conveyed, I did get this error for this reason , so down voter kindly justify why you feel otherwiseYalonda

© 2022 - 2024 — McMap. All rights reserved.