Hello, I have a problem with SecItemDelete
when trying to delete a private key stored using the data protection keychain on macOS 13.5 (testing on MB Pro 2023).
Everything else works:
- adding the item (using
SecKeyCreateRandomKey
) - getting a reference to the item using
SecItemCopyMatching
and reading the data
But calling SecItemDelete
with kSecValueRef
and a reference received from SecItemCopyMatching
fails with errSecItemNotFound
.
What's even more interesting, the call to SecItemDelete
fails with that error even if passed the exact same search dictionary (omitting the kSecReturnRef
key) that results in successfully getting an item reference when passed to SecItemCopyMatching
(the documentation of SecItemDelete
refers to the SecItemCopyMatching
documentation on construction a search dictionary, so, in theory, it should accept the same parameters).
I am at a dead end here honestly, and, despite knowing better, I'm starting to suspect this might be a bug in the API implementation. Any help is appreciated.
SecItemCopyMatching
call:
auto params = cf::create_dict({{kSecClass, kSecClassKey},
{kSecAttrKeyClass, kSecAttrKeyClassPrivate},
{kSecAttrLabel, cf::from_string(create_key_name(name))},
{kSecReturnRef, kCFBooleanTrue}});
SecKeyRef key_ref{nullptr};
auto status = ::SecItemCopyMatching(params.get(), (CFTypeRef*)&key_ref);
SecItemDeleteCall
with ref from SecItemCopyMatching
:
auto query = cf::create_dict({{kSecValueRef, key}});
sec::throw_if_fail(::SecItemDelete(query));
SecItemDeleteCall
with search by key label:
auto query = cf::create_dict({{kSecClass, kSecClassKey},
{kSecAttrKeyClass, kSecAttrKeyClassPrivate},
{kSecAttrLabel, cf::from_string(create_key_name(name))}
});
sec::throw_if_fail(::SecItemDelete(query));
Private key creation params for SecKeyCreateRandomKey
:
{kSecClass, kSecClassKey},
{kSecAttrKeyType, kSecAttrKeyTypeECSECPrimeRandom},
{kSecAttrKeySizeInBits, cf::make_guarded(::CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bit_length.at(key_spec.curve)))},
{kSecAttrIsPermanent, kCFBooleanTrue},
{kSecUseDataProtectionKeychain, kCFBooleanTrue},
{kSecAttrLabel, cf::from_string(create_key_name(name))},
{kSecAttrIsExtractable, storage_spec.exportable ? kCFBooleanTrue : kCFBooleanFalse}