SecItemAdd with kSecUseKeychain returns error -50

Hi all,

I'm working on a macOS project with C interface. And I'm trying to import my private key to a SecKeychainRef, but I always got error code -50. Would you have any advice or suggestion in it? Thanks in advance.

Here is my code:

// Get default keychain
SecKeychainRef import_keychain = NULL;
OSStatus keychain_status = SecKeychainCopyDefault(&import_keychain);

// Create key from ECC key data in X963 format
CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(default_alloc, 0, NULL, NULL);
CFDictionarySetValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom);
CFDictionarySetValue(parameters, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
CFDictionarySetValue(parameters, kSecAttrApplicationLabel, cfLabel);
SecKeyRef private_key= SecKeyCreateWithData(hard_code_key_ref, parameters, &key_error);

// Add seckey to key chain
CFMutableDictionaryRef secItemParams = CFDictionaryCreateMutable(default_alloc, 0, NULL, NULL);
CFDictionarySetValue(secItemParams, kSecClass, kSecClassKey);
CFDictionarySetValue(secItemParams, kSecValueRef, privateKey);
CFDictionarySetValue(secItemParams, kSecUseKeychain, import_keychain);

OSStatus key_status = SecItemAdd(secItemParams, NULL);

I also tried to test "SecItemAdd" with password value, but it also failed with -25308. I'm not sure if it is related or not. Here is the test code:


            CFStringRef server = CFStringCreateWithCString(default_alloc, "example.com", kCFStringEncodingUTF8);
            CFStringRef username = CFStringCreateWithCString(default_alloc, "username", kCFStringEncodingUTF8);
            CFStringRef password = CFStringCreateWithCString(default_alloc, "password", kCFStringEncodingUTF8);
            CFMutableDictionaryRef secItemParams = CFDictionaryCreateMutable(default_alloc, 0, NULL, NULL);
            CFDictionarySetValue(secItemParams, kSecClass, kSecClassInternetPassword);
            CFDictionarySetValue(secItemParams, kSecValueData, password);
            CFDictionarySetValue(secItemParams, kSecAttrAccount, username);
            CFDictionarySetValue(secItemParams, kSecAttrServer, server);
            
            CFDictionarySetValue(secItemParams, kSecUseKeychain, import_keychain);
            CFDictionarySetValue(secItemParams, kSecAttrAccessible, kSecAttrAccessibleAlways);

            OSStatus key_status = SecItemAdd(secItemParams, NULL);

The above code failed with "OSStatus -25308 : User interaction is not allowed." Any advice is welcomed. Thank you!

I wanted to post a quick summary of my findings, mostly for the benefit of Future Quinn™. Importing an EC key into a file-based keychain is a challenge, as I explained in my previous posts. The code I eventually settled on was this:

let ecPrivateKey = Data(ecPrivateKeyBytes)
var format = SecExternalFormat.formatOpenSSL
var type = SecExternalItemType.itemTypePrivateKey
let keys = try secCall { SecItemImport(ecPrivateKey as NSData, nil, &format, &type, [], nil, keychain, $0) } as! [SecKey]
assert(keys.count == 1)
// print(keys)
let privateKey = keys.first!

This does not work with the raw key bytes from xiazhvera’s earlier post. Rather, you have to rework those bytes into an ECPrivateKey structure, per the definition in my On Cryptographic Key Formats post.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Quinn,

That's a great news and thank you so much!! I will try it out. I followed the post here to contribute the key binary. (https://developer.apple.com/forums/thread/72445) However, I could did something wrong with the raw keys. I will work on it. Again, thank you so much.

SecItemAdd with kSecUseKeychain returns error -50
 
 
Q