Login Keychain Access Autmation

I have been trying to find a way to be able to sign some data with private key of an identity in login keychain without raising any prompts.

I am able to do this with system keychain (obviously with correct permissions and checks) but not with login keychain. It always ends up asking user for their login password.

Here is how the code looks, roughly,

        NSDictionary *query = @{
            (__bridge id)kSecClass:       (__bridge id)kSecClassIdentity,
            (__bridge id)kSecReturnRef:   @YES,
            (__bridge id)kSecMatchLimit:  (__bridge id)kSecMatchLimitAll
        };
        CFTypeRef result = NULL;
        OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
        NSArray *identities = ( NSArray *)result;
        SecIdentityRef identity = NULL; 
        for (id _ident in identities) {
            // pick one as required

        }

        SecKeyRef privateKey = NULL;
        OSStatus status = SecIdentityCopyPrivateKey(identity, &privateKey);
        NSData *strData = [string dataUsingEncoding:NSUTF8StringEncoding];
        unsigned char hash[CC_SHA256_DIGEST_LENGTH];
        CC_SHA256(strData.bytes, (CC_LONG)strData.length, hash);
        NSData *digestData = [NSData dataWithBytes:hash length:CC_SHA256_DIGEST_LENGTH];
        CFErrorRef cfError = NULL;
        NSData *signature = (__bridge_transfer NSData *)SecKeyCreateSignature(privateKey,
                                                                             kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256,
                                                                             (__bridge CFDataRef)digestData,
                                                                             &cfError);

Above code raises these system logs in console

default 08:44:52.781024+0000 securityd client is valid, proceeding

default 08:44:52.781172+0000 securityd code requirement check failed (-67050), client is not Apple-signed

default 08:44:52.781233+0000 securityd displaying keychain prompt for /Applications/Demo.app(81692)

If the key is in login keychain, is there any way to do SecKeyCreateSignature without raising prompts? What does client is not Apple-signed mean?

PS: Identities are pre-installed either manually or via some device management solution, the application is not installing them.

Before you start, read TN3137 On Mac keychain APIs and implementations because the following uses terms from that.

Identities are pre-installed … the application is not installing them.

Right. This is where things go wrong. By default an app from Team A can’t access credentials created by an app from Team B, or by the system.

With the data protection keychain this is easier to understand because your app can’t even see items outside of its keychain access groups. However, this security policy was retrofitted to the file-based keychain, which makes things more confusing. It can see the item but triggers an access control alert when it uses it.

On iOS, where there is only the data protection keychain, this has been a source of much annoyance over the years. Fortunately, there’s a shiny new API to help with that, namely ManagedApp. Unfortunately this isn’t on macOS, so it doesn’t help you.

As to what you can do, the answer is gonna depend on how these keys are provisioned and what your app does with them. For example, if the user is involved then can use Keychain Access (or the security tool) to change the key’s ACL. If you can explain more about your specific requirements, I might be able to suggest more options.

Share and Enjoy

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

user is involved then can use Keychain Access (or the security tool)

For ACL, i have manually checked "Allow all applications to access this item", even that doesn't seem to help with the prompts to user for their password.

The requirement is pretty much what i have already stated, need to be able to sign some data with private key of an identity installed in login keychain without prompting user for their login password. That identity will come pre-installed, it's ACL could be updated through some MDM to include my application.

Updating ACL to include my application seems to be enough for system keychain level identity. No prompts after that. However when doing the same thing for login keychain, the prompts still persist.

There has to be a way to do this without bothering user

even that doesn't seem to help with the prompts to user for their password.

Right. This comes back to something I said earlier: This security policy was retrofitted to the file-based keychain. That’s implement via something call partition lists, and those present two challenges:

  • The ACL editor in Keychain Access isn’t aware of partition lists.

  • There’s no public API for manipulating partition lists.

There is rudimentary support for partition lists in the security tool, and those might be sufficient for your use case.

Share and Enjoy

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

Login Keychain Access Autmation
 
 
Q