How to limit keychain item search in particular domains

I am new to security framework. I want to access items only in dynamic keychain for smartCards. And just user keychains in case of some other scenario.

But SecKeychainOpen,SecKeychainGetPath and SecKeychainCopyDomainSearchList are deprecated. How do I make sure the secItemCopyMatching only looks for items in specific type of keychain.

Replies

macOS’s modern smart card integration doesn’t work through separate keychains. That mechanism is intimately tied to the whole file-based keychain model, which is why you’re hitting these deprecation warnings. Rather, smart card credentials are accessible through the data protection keychain. See TN3137 On Mac keychain APIs and implementations for more background on this terminology.

If you search DevForums for kSecAttrAccessGroupToken you’ll a few examples where I show how to access token-based credentials.

Share and Enjoy

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

@eskimo , Thank you for the information. One more quick question, In the above documentation, It is mentioned that

File-based keychains are stored, as the name suggests, in files. Every context has a keychain search list and a default keychain. In a user context the search list includes a per-user login keychain and a single System keychain, with the former being the default. In the system context the search list includes just the System keychain, which is also the default keychain.

When using the SecItem API to target the file-based keychain:

SecItemAdd adds the item to the default keychain. Use kSecUseKeychain to override this.

Queries, like those done using SecItemCopyMatching, consult all keychains in the search list. Use kSecMatchSearchList to override this.

So to use attributes like kSecMatchSearchList, kSecUseKeychain -> How to fetch the right keychains (be it system or login) reference?

Thanks in advance.

I’m confused. My understanding is that you want to use smart card based keys. Given that, you’d use the data protection keychain, and kSecMatchSearchList and kSecUseKeychain don’t make sense in that context.

Anyway, to answer your specific question, you can discover keychains using calls like SecKeychainCopyDomainDefault and SecKeychainCopyDomainSearchList. You can also use file system APIs and call SecKeychainOpen. All of these are deprecated because, as TN3137 says, file-based keychains are on the road to deprecation.

Share and Enjoy

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

@eskimo, Not in the context to previous question, My question is -> To use attributes like kSecMatchSearchList, kSecUseKeychain -> How to fetch the right keychains (be it system or login) reference? All APIs(SecKeychainCopyDomainSearchList, SecKeychainGetPath, SecKeychainOpen) to achieve that seems to be deprecated.

Also, In the document tn3137, It's mentioned Queries, like those done using SecItemCopyMatching, consult all keychains in the search list. Use kSecMatchSearchList to override this.,

Just to clarify on this does that mean it targets all the keychains present in your system, or by search list it means there is a search list we provide in secItemCopyMatching dictionary?

@eskimo, Please clarify above queries, It will be of big help.

All APIs (SecKeychainCopyDomainSearchList, SecKeychainGetPath, SecKeychainOpen) to achieve that seems to be deprecated.

Right. That’s because the entire concept of file-based keychains is, quoting TN3137, “on the road to deprecation”. In some situations you must use a file-based keychain, for example, if you’re building a launchd daemon. If you’re writing normal app code, it’s best to adopt with the data protection keychain.

Just to clarify on this does that mean it targets all the keychains present in your system, or by search list it means there is a search list we provide in SecItemCopyMatching dictionary?

Neither. It means all items in the keychain search list for the context in which you’re running. If you’re building a GUI app, that search list is the one you see when you run this command in Terminal:

% security list-keychains
    "/Users/quinn/Library/Keychains/login.keychain-db"
    "/Users/quinn/Library/Keychains/DeveloperID QQ.keychain-db"
    "/Users/quinn/Library/Keychains/MouseCA.keychain-db"
    "/Users/quinn/Library/Keychains/Scratch.keychain-db"
    "/Library/Keychains/System.keychain"

Normally only the first and last entries are present; on my system I have three extra keychains that I set up using Keychain Access.

Share and Enjoy

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

Thanks @eskimo for clarifying this.

@eskimo Please one more quick question. I am trying to restrict my search to only system keychain using kSecMatchSearchList which requires an array of secKeychainRef. Now to retrieve SecKeychainRef of system keychain(/Library/Keychains/System.keychain , all of the APIs are deprecated. Could you please provide a sample code with non-deprecated APIs to retrieve SecKeychainRef of system keychain.

SecKeychainOpen("/Library/Keychains/System.keychain", &keychain);

SecKeychainCopyDomainSearchList(kSecPreferencesDomainSystem, &keychain)

Could you please provide a sample code with non-deprecated APIs to retrieve SecKeychainRef of system keychain.

There are no such APIs. Everything specific to the file-based keychain is deprecated.

My general advice is that you switch to the data protection keychain. If you have to use the file-based keychain for some reason, my advice is:

  • If your use case is unique, file a bug describing it. You can skip this if you’re using the System keychain from a daemon because we already understand that requirement.

  • Continue to use the deprecated APIs.

Share and Enjoy

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