vendredi 24 juin 2016

Objective-C The specified item already exists in the keychain [iOS]


I am not sure why this code fails. I am always getting errSecDuplicateItem

First I am trying to call SecPKCS12Import.

    CFDataRef inId = (CFDataRef)certToImport_;   
    OSStatus securityError = errSecSuccess;
    CFStringRef pw = (CFStringRef)password;
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { pw };

    CFDictionaryRef myDict = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);   
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

    securityError = SecPKCS12Import(inId, myDict, &items);

    if (securityError == errSecSuccess) {

        securityError = [self addIdentityToKeychain:items];
        if (securityError == errSecSuccess)
        {
            securityError = [self addRootCaToKeychain:items];
            ....

So from the code above, I am calling addIdentityToKeychain which returns success.

- (OSStatus)addIdentityToKeychain:(CFArrayRef)importDict
{
    CFDictionaryRef myId = CFArrayGetValueAtIndex(importDict, 0);

    const void *tempId = NULL;
    tempId = CFDictionaryGetValue(myId,kSecImportItemIdentity);
    SecIdentityRef secId = (SecIdentityRef)tempId;

    SecCertificateRef certRef;

    OSStatus securityError = SecIdentityCopyCertificate(secId, &certRef);

    if (securityError == errSecSuccess) {
        uniqueLabel_ = [[NSString alloc] initWithString:[self GetUniqueLabel:certRef]];
        NSMutableDictionary *secIdentityParams = [[NSMutableDictionary alloc] init];    
        [secIdentityParams setObject:(id)secId forKey:(id)kSecValueRef];
        securityError = SecItemAdd((CFDictionaryRef) secIdentityParams, NULL);
        [secIdentityParams release];
    }
    return securityError;
}

But when I am trying finally to call addRootCaToKeychain fails, complaining that we have a duplicate entry. it failed the very first time with a random certificate that could not have been imported in any case.

 - (OSStatus)addRootCaToKeychain:(CFArrayRef)importDict
    {
        OSStatus securityError = errSecSuccess;

        CFDictionaryRef myId = CFArrayGetValueAtIndex(importDict, 0);
        NSArray *certs = (NSArray*)CFDictionaryGetValue(myId, kSecImportItemCertChain);
        CFIndex cnt = [certs count];
        if (cnt)
        {
            CFIndex i = 0;
            while ((i < cnt)) {
                SecCertificateRef certRef = (SecCertificateRef)[certs objectAtIndex:i];
                NSMutableDictionary *secCertParams = [[NSMutableDictionary alloc] init];    
                [secCertParams setObject:(id)certRef forKey:(id)kSecValueRef];
                [secCertParams setObject:(id)uniqueLabel_ forKey:(id)kSecAttrLabel];
                securityError = SecItemAdd((CFDictionaryRef) secCertParams, NULL);
                [secCertParams release];
                // if we get something other than success or duplicate, we will quit right here and report the error.  
                if ((securityError != errSecSuccess) && (securityError != errSecDuplicateItem)) {
                    return securityError;
                }
                i++;
            }
        }
        return securityError;
    }

What is wrong with the code? Any idea?


Aucun commentaire:

Enregistrer un commentaire