Enumerate all Keychain items in my iOS application

noamtm picture noamtm · Jun 10, 2012 · Viewed 20.6k times · Source

What's the easiest way to programmatically (from within my app) get all items stored in the keychain?

It probably has something to do with SecItemCopyMatching(), but the documentation for that function is not very clear (and I failed to find a decent sample on the web).

Answer

Tammo Freese picture Tammo Freese · Jul 26, 2012

SecItemCopyMatching is the right call for that. First we build our query dictionary so that the items' attributes are returned in dictionaries, and that all items are returned:

NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:
    (__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnAttributes,
    (__bridge id)kSecMatchLimitAll, (__bridge id)kSecMatchLimit,
    nil];

As SecItemCopyMatching requires at least the class of the returned SecItems, we create an array with all the classes…

NSArray *secItemClasses = [NSArray arrayWithObjects:
                           (__bridge id)kSecClassGenericPassword,
                           (__bridge id)kSecClassInternetPassword,
                           (__bridge id)kSecClassCertificate,
                           (__bridge id)kSecClassKey,
                           (__bridge id)kSecClassIdentity,
                           nil];

…and for each class, set the class in our query, call SecItemCopyMatching, and log the result.

for (id secItemClass in secItemClasses) {
    [query setObject:secItemClass forKey:(__bridge id)kSecClass];

    CFTypeRef result = NULL;
    SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
    NSLog(@"%@", (__bridge id)result);
    if (result != NULL) CFRelease(result);
}

In production code, you should check that the OSStatus returned by SecItemCopyMatching is either errSecItemNotFound (no items found) or errSecSuccess (at least one item was found).