I was following the tutorial by Apple: https://developer.apple.com/documentation/security/certificate_key_and_trust_services/certificates/storing_a_certificate_in_the_keychain
and
on how to store and retrieve an identity from the keychain.
Storing the identity seems to work fine, errSecSuccess
is returned. However, when trying to obtain any identity, I get back errSecItemNotFound
(or -25300
).
Even dumping the keychain does not work as expected; after successfully adding an identity, SecItemCopyMatching
still returns errSecItemNotFound
.
See the following piece of code that pretty much matches the extract provided in the documentation:
// Store the digital identity in the keychain:
let addQuery: [String : Any] = [kSecClass as String: kSecClassIdentity,
kSecValueRef as String: identity,
kSecAttrLabel as String: "myid"]
guard SecItemAdd(addQuery as CFDictionary, nil) == errSecSuccess else {
print("Could not store identity in keychain")
return false
}
// Obtain the digital identity from the keychain:
let getQuery: [String : Any] = [kSecClass as String: kSecClassIdentity,
kSecAttrLabel as String: "myid",
kSecReturnRef as String: kCFBooleanTrue!]
var item: CFTypeRef?
let status = SecItemCopyMatching(getQuery as CFDictionary, &item)
guard status == errSecSuccess else {
print("Could not find identity in keychain, OSerror: \(status)") // <---- -25300
return false
}
let localIdentity = item as! SecIdentity
// [...]
For the sake of completion, this is how I "dump" the keychain (at least the identities):
let getQuery: [String : Any] = [kSecClass as String : secClass,
kSecReturnData as String : kCFBooleanTrue!,
kSecReturnAttributes as String : kCFBooleanTrue!,
kSecReturnRef as String : kCFBooleanTrue!,
kSecMatchLimit as String : kSecMatchLimitAll]
var items: CFTypeRef?
let status = SecItemCopyMatching(getQuery as CFDictionary, &items) // <--- again, status = -25300
What's missing?
I went through the docs multiple times. Does storing items in the keychain take some time? If so, does the example provided by Apple mention that?
Why do I get an errSecSuccess
when storing the item but it won't let me read the item right after?
I‘m also testing on a real device.
I finally found the answer myself.
Using labels on an identity is tricky because identities are not stored in the keychain as an atomic item but are store as a separate private key and certificate, and those items use labels in different ways.
https://forums.developer.apple.com/thread/98029
That is:
kSecReturnPersistentRef
to SecItemAdd
when you add the identity to the keychainSecItemCopyMatching
with that persistent referenceThis makes sense and I was finally able to solve my problem this way.