How to get the access control list from SecKey?

HI,


I have a daemon which has created the symmetric encryption/decryption key in the keychain and added some dependant apps and itself to the ACL. I am trying to verify the ACL of this key later in the code but it fails.


Looking up the key in keychain:

let getquery: [String: Any] = [kSecClass as String: kSecClassKey,
                                       kSecAttrApplicationLabel as String: keychainApplicationLabel,
                                       kSecAttrKeyType as String: kSecAttrKeyTypeAES,
                                       kSecReturnRef as String: true]
        var item: CFTypeRef?
        let status = SecItemCopyMatching(getquery as CFDictionary, &item)
        let key = item as! SecKey


To get the ACL of this key:


        let keychainItem = item as! SecKeychainItem
        var secAccess : SecAccess?
        var status = SecKeychainItemCopyAccess(keychainItem, &secAccess)
        guard status == errSecSuccess, secAccess != nil else {
            DLog(message: "Could not get SecAccess : \(SecCopyErrorMessageString(status, nil)! as String)")
            return false
        }
        var aclList : CFArray?
        status = SecAccessCopyACLList(secAccess!, &aclList)
        if status == errSecSuccess, aclList != nil {
            DLog(message: "Could not get ACLList : \(SecCopyErrorMessageString(status, nil)! as String)")
            return false
        }


As per documentation of "SecKey", "A

SecKey
instance that represents a key that is stored in a keychain can be safely cast to a
SecKeychainItem
for manipulation as a keychain item."


But in our case "item as! SecKeychainItem" crashes even when "item" is looked up successfully in the keychain.


Any suggestions how to achieve this?


Thanks.

Replies

But in our case "item as! SecKeychainItem" crashes even when "item" is looked up successfully in the keychain.

How does it crash? Is this a Swift trap caused by the

as!
cast?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Yes Quinn, "as! cast" causes the crash " EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)".


It looks like only this typecasting from SecKey to SecKeychainItem has issue else following code (to typecast CFTypeRef to SecKeychainItem) works fine and give SecACL just fine:


        var status = SecItemCopyMatching(getquery as CFDictionary, &item)
        //let dict = item as! CFDictionary
        guard status == errSecSuccess else {
            DLog(message: "Keychain lookup failed error : \(SecCopyErrorMessageString(status, nil)! as String)")
            return nil
        }
        let key = item as! SecKeychainItem
       
        var secAccess : SecAccess?
        status = SecKeychainItemCopyAccess(key, &secAccess)
        guard status == errSecSuccess, secAccess != nil else {
            DLog(message: "Could not get SecAccess : \(SecCopyErrorMessageString(status, nil)! as String)")
            return nil
        }



Also, would it be possible to update the ACL of this keychain item by the owner of the key i.e. daemon? When we call "SecKeychainItemSetAccess" to update the ACL on this keychain item it always fails with "errSecAuthFailed" even when daemon is trying to do this operation.

It looks like only this typecasting from

SecKey
to
SecKeychainItem
has issue

Interesting. I suspected that was the case. There’s clearly a mismatch between Swift’s view of the types in play and the CF runtime.

following code (to typecast

CFTypeRef
to
SecKeychainItem
) works fine

Yeah, bouncing via

CFTypeRef
seems like a reasonable workaround.

Also, would it be possible to update the ACL of this keychain item by the owner of the key i.e. daemon?

Changing an ACL almost always results in a keychain authorisation dialog, which isn’t going to work in a daemon. If you need specific ACL items, you really want to set them up when you create the item.

Also, be aware that recent versions of macOS do not allow you to add ACL entries for totally unrelated executables. All of the programs listed in your ACL must come from the same team. If the program is from a different team, or it’s a system program, the system will display a keychain authorisation dialog (if possible) when the program tries to access the item.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks Quinn. All of the binaries are from the same team. Is it not possible at all to change the ACL then from the daemon maybe using NSTask and security command? The problem is we have already shipped the app with daemon in production with the current ACL and it works fine. Now, the app name and containing apps are changed for the next release and so need to update ACL with it else it would break the use cases. Any suggestions on this? I have raised DTS for this as well, if it comes your way 🙂 As user-agent name itself is changed we can not even do this ACL change from it as authorization prompt would be fine from it I guess.

I have raised DTS for this as well …

Indeed. Our frontline folks have just sent you an email about that. Given your latest post here I think it would be best to handle this via DTS. Please reply to them and Cc me (at individual email address, which you can in my signature, below).

Note Everyone else in DTS is off for the US Thanksgiving holiday, but if you Cc me I’ll make sure to pick it up from there.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks Quinn. I have replied over DTS email now.