开发者

How to add security identity (certificate + private key) to iPhone keychain?

开发者 https://www.devze.com 2022-12-29 10:55 出处:网络
How to add security identity (certificate + private key) to iPhone keychain? I have .p12 file in application. I can get identity from it using SecPKCS12Import() but

How to add security identity (certificate + private key) to iPhone keychain? I have .p12 file in application. I can get identity from it using SecPKCS12Import() but when i try to do the following:

NSMutableDictionary *secIdentityParams = [[NSMutableDictionary alloc] init];    
[secIde开发者_如何转开发ntityParams setObject:(id)kSecClassIdentity forKey:(id)kSecClass];
[secIdentityParams setObject:label forKey:(id)kSecAttrLabel];
[secIdentityParams setObject:(id)myIdentity forKey:(id)kSecValueRef];

status = SecItemAdd((CFDictionaryRef) secIdentityParams, NULL);

I am getting error = -25291 -> No trust results are available. What am I doing wrong?


Just use 1 parameter in attributes dictionary to add identity to keychain:

NSMutableDictionary *secIdentityParams = [[NSMutableDictionary alloc] init];    
[secIdentityParams setObject:(id)myIdentity forKey:(id)kSecValueRef];
OSStatus status = SecItemAdd((CFDictionaryRef) secIdentityParams, NULL);


Using kSecValueRef as the only parameter works perfectly. Do you know why the function fails when other parameters, like e.g. kSecClass, are provided? The Keychain Services Reference documents the first parameter of SecItemAdd() as follows:

A dictionary containing an item class key-value pair [...] and optional attribute key-value pairs [...] specifying the item's attribute values.

I assumed that kSecClass is a mandatory parameter that must always be present, either when using SecItemAdd() oder SecItemCopyMatching(). Certificate, Key, and Trust Services Tasks on iOS explains the process of adding a SecIdentityRef to the Keychain as follows (Listing 2-3):

CFDataRef persistentRefForIdentity(SecIdentityRef identity)
{
    OSStatus status;

    CFTypeRef  identity_handle = NULL;
    const void *keys[] =   { kSecReturnPersistentRef, kSecValueRef };
    const void *values[] = { kCFBooleanTrue,          identity };
    CFDictionaryRef dict = CFDictionaryCreate(NULL, keys, values,
                                              2, NULL, NULL);
    status = SecItemAdd(dict, &persistent_ref);

    if (dict)
        CFRelease(dict);

    return (CFDataRef)persistent_ref;
}

Is this example just wrong?


I managed to get Keychain Services to return a Persistent Keychain Reference when adding a new SecIdentityRef via SecItemAdd(). Here is the working code:

- (NSData *)persistentKeychainReferenceForIdentity:(SecIdentityRef)identity
{
    NSData *persistentRef = nil;
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                (id)identity, kSecValueRef, 
                                (id)kCFBooleanTrue, kSecReturnPersistentRef, 
                                nil];
    OSStatus itemAddStatus = SecItemAdd((CFDictionaryRef)attributes, 
                                        (CFTypeRef *)&persistentRef);
    if (itemAddStatus != errSecSuccess)
    {
        return nil;
    }    

    return persistentRef;
}

I hope this helps others too.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号