Search code examples
iosobjective-ckeychain

SecItem methods fail with -34018


I use code below to safely store strings on iOS. Sometimes SecItemCopyMatching() and then also SecItemAdd() fail and return error code -34018. I've not been able to find this code; what does it mean?

NSMutableDictionary* query = [NSMutableDictionary dictionary];

[query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[query setObject:account forKey:(__bridge id)kSecAttrAccount];
[query setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];

OSStatus error = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL);
if (error == errSecSuccess)
{
    // Do update.
    NSDictionary* attributesToUpdate;
    attributesToUpdate = [NSDictionary dictionaryWithObject:[inputString dataUsingEncoding:NSUTF8StringEncoding]
                                                     forKey:(__bridge id)kSecValueData];

    error = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributesToUpdate);
    if (error != errSecSuccess)
    {
        NBLog(@"SecItemUpdate failed: %d", (int)error);
        result = NO;
    }
}
else if (error == errSecItemNotFound)
{
    // Do add.
    [query setObject:[inputString dataUsingEncoding:NSUTF8StringEncoding] forKey:(__bridge id)kSecValueData];

    error = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
    if (error != errSecSuccess)
    {
        NBLog(@"SecItemAdd failed: %d", (int)error);
        result = NO;
    }
}

Solution

  • -34018 is errSecMissingEntitlement according to osstatus.com

    Internal error when a required entitlement isn't present.

    For iOS 10+ you need a .entitlements file to access the keychain. Something like this:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>com.apple.keystore.access-keychain-keys</key>
        <true/>
        <key>com.apple.keystore.device</key>
        <true/>
    </dict>
    </plist>