SecItemCopyMatching certificate not found

Hi,

I'm adding certificate to keychain as describe Here

I add the certificate to keychain successfully but when I try to fetch it, it always return error item not found (25300)

I'm running on macOS Big Sur (ver 11.6)

Below is the code. What am I missing ?

Thanks,

Tal

// code that insert the certificate
NSDictionary* addquery = @{ 
        (id)kSecValueRef:   (__bridge id)cert,
        (id)kSecClass:      (id)kSecClassCertificate,
        (id)kSecAttrLabel:  @"ClientCert"};

OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addquery, nullptr);

// code that fetch the certificate
NSDictionary *queryDict = @{
       (id) kSecClass : (id) kSecClassCertificate,
       (id) kSecAttrLabel : @"ClientCert",
       (id) kSecReturnRef : @YES};

auto sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef) queryDict, (CFTypeRef *) &m_client_cert);
  • UPDATE I replaced kSecAttrLabel with kSecAttrApplicationTag and it start working. No idea why it does not work as stated in the documentation.

  • UPDATE2 The replacement of kSecAttrLabel with kSecAttrApplicationTag actually did not work. The query disregard it and I notice I end up with a different certificate.

    So, I still need to figure out why kSecAttrLabel is not working on macOS.

Add a Comment

Accepted Answer

Is there a way for me to look at the certificate and keys (not from code)?

No.

I was actually quite surprised by this. You can view the data protection keychain in Keychain Access by selecting iCloud Keychain (or, if iCloud Keychain is disabled, Local Items) in the list on the left. However, this seems to only show password items, not keys and certificates.

Also, you wrote … is that means I cannot use a service or background process with that code ?

That depends on what you mean by “service or background process”. A launchd daemon, which runs in a global context, independent of any user login session, cannot use the data protection keychain. The same applies for system extensions, which are more-or-less daemons on the covers. Most other code runs in a specific user context and thus can use the data protection keychain. That list includes:

  • Apps

  • App extensions

  • XPC Services

  • launchd agents

  • Service Management login items

Technote 2083 Daemons and Agents goes it to gory details about execution contexts on macOS (it’s no longer 100% accurate but it’s still a good reference for most tasks).

Share and Enjoy

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

Answers

Is this problem on the read side or the write side? That is, if you dump the keychain dump using security dump-keychain, is the label set correctly?

Share and Enjoy

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

The problem is in the write. The label is the common name and not what I placed in kSecAttrLabel:

version: 512
class: 0x80001000
attributes:
    "alis"<blob>="toz@akamai.com"
    "cenc"<uint32>=0x00000003
    "ctyp"<uint32>=0x00000001
    "hpky"<blob>=0x360A667ECF0CF5ACA8E90C9A45C7F6AF8E20C56C  "6\012f~\317\014\365\254\250\351\014\232E\307\366\257\216 \305l"
    "issu"<blob>=0x3051310B300906035504061302494C3111300F06035504070C084B666172596F6E61310F300D060355040A0C06416B616D6169310B3009060355040B0C0252443111300F06035504030C08746573742E636F6D  "0Q1\0130\011\006\003U\004\006\023\002IL1\0210\017\006\003U\004\007\014\010KfarYona1\0170\015\006\003U\004\012\014\006Akamai1\0130\011\006\003U\004\013\014\002RD1\0210\017\006\003U\004\003\014\010test.com"
    "labl"<blob>="tlv.test.com"
    "skid"<blob>=<NULL>
    "snbr"<blob>=0x009D01D8E49FFEF615
    "subj"<blob>=0x3067310B300906035504061302494C3111300F06035504070C084B616172596F6E61310F300D060355040A0C06416B616D61693115301306035504030C0C746C762E746573742E636F6D311D301B06092A864886F70D010901160E746F7A40616B616D61692E636F6D  "0g1\0130\011\006\003U\004\006\023\002IL1\0210\017\006\003U\004\007\014\010KaarYona1\0170\015\006\003U\004\012\014\006Akamai1\0250\023\006\003U\004\003\014\014tlv.test.com1\0350\033\006\011*\206H\206\367\015\001\011\001\026\016toz@akamai.com"```

The label is the common name and not what I placed in kSecAttrLabel

Yeah, that’s tricky. When you create a keychain item using kSecValueRef, the keychain gets a set of attributes from the reference and then creates a keychain item from those attributes. Clearly the label it gets from the item is overriding the kSecAttrLabel you supplied.

A further complication here is that you’re using the file-based keychain compatibility shim. The data protection (iOS-style) keychain handles this correctly.

Share and Enjoy

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

Thanks Quinn. So I tried to use kSecUseDataProtectionKeychain as I saw a previous recommendation you gave. I was surprised to see I cannot see my certificate and keys from the keychain access app. Is there a way for me to look at the certificate and keys (not from code) ? Also, you wrote - "The data protection keychain (kSecUseDataProtectionKeychain) is available to code running in a user context (that is, not a daemon) " - is that means I cannot use a service or background process with that code ?

Is there a way for me to look at the certificate and keys (not from code)?

No.

I was actually quite surprised by this. You can view the data protection keychain in Keychain Access by selecting iCloud Keychain (or, if iCloud Keychain is disabled, Local Items) in the list on the left. However, this seems to only show password items, not keys and certificates.

Also, you wrote … is that means I cannot use a service or background process with that code ?

That depends on what you mean by “service or background process”. A launchd daemon, which runs in a global context, independent of any user login session, cannot use the data protection keychain. The same applies for system extensions, which are more-or-less daemons on the covers. Most other code runs in a specific user context and thus can use the data protection keychain. That list includes:

  • Apps

  • App extensions

  • XPC Services

  • launchd agents

  • Service Management login items

Technote 2083 Daemons and Agents goes it to gory details about execution contexts on macOS (it’s no longer 100% accurate but it’s still a good reference for most tasks).

Share and Enjoy

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