SecKeychainItemCopyContents chases secret keys

I use this code to list all private keys and retrieve information about them using the Apple Security API:

int main(int argc, const char * argv[]) { const void *keys[] = { kSecClass, kSecReturnRef, kSecMatchLimit, kSecAttrKeyClass}; const void *values[] = { kSecClassKey, kCFBooleanTrue, kSecMatchLimitAll, kSecAttrKeyClassPrivate}; CFDictionaryRef searchDict = CFDictionaryCreate( NULL, keys, values, sizeof(keys) / sizeof(keys[0]), NULL, NULL ); checkAlloc(searchDict); CFArrayRef items; check(SecItemCopyMatching(searchDict, (CFTypeRef *)&items)); for(int i=0; i<CFArrayGetCount(items); i++) { SecKeychainItemRef item = (SecKeychainItemRef) CFArrayGetValueAtIndex(items, i); CFShow((CFTypeRef)item); SecItemClass cls; SecKeychainAttributeList attrs; UInt32 dataLen; void* data; check(SecKeychainItemCopyContent(item, &cls, &attrs, &dataLen, &data)); printf("Key: %d\n", (int)dataLen); check(SecKeychainItemFreeContent(&attrs, data)); } CFRelease(items); CFRelease(searchDict); return 0; } 

Calling SecKeychainItemCopyContent segfaults, although none of the pointers I passed are invalid.

CFShow prints lines similar to <SecKey 0x7fb4d9d01420 [0x7fff74790ed0]> , so item should be SecKeyRef , but the documentation for it says it's ok to use SecKeyRef as SecKeychainItemRef if the key is in the keychain. However, I do not see any functions to find out if the key is in the keychain, so I cannot confirm that the keys returned can be used as such.

What am I doing wrong here?

+5
source share
2 answers

To copy data and / or attributes stored in a given keychain element, the 3rd parameter of the SecKeychainItemCopyContent() function is SecKeychainAttributeList *attrList with type type

  struct SecKeychainAttributeList { UInt32 count; SecKeychainAttribute *attr; }; 

For this parameter, IN / OUT attrList : The input is a list of attributes that you request to retrieve. At the output, the attributes are populated. Pass NULL if there is no need to retrieve any attributes or pass the list of attributes that you need to get. It must be one of the two passages mentioned in the arguments. Leaving it uninitialized can cause problems like segfault.

So, please try this way, this should work well.

 SecKeychainAttributeList attrs = {0, NULL}; //... check(SecKeychainItemCopyContent(item, &cls, &attrs, &dataLen, &data)); 

or

 //SecKeychainAttributeList attrs ; //... check(SecKeychainItemCopyContent(item, &cls, NULL, &dataLen, &data)); printf("Key: %d\n", (int)dataLen); check(SecKeychainItemFreeContent(NULL, data)); 

If you need to get a list of attributes, the code example may be as follows:

  SecKeychainAttributeList xlist; SecKeychainAttribute outList[] = { {kSecAddressItemAttr,}, {kSecAccountItemAttr,}, {kSecVolumeItemAttr,}, {kSecProtocolItemAttr} }; xlist.count = sizeof(outList)/sizeof(outList[0]); xlist.attr = outList; //... err = SecKeychainItemCopyContent (itemRef, nil, &xlist, &len, &outData); //... 
0
source

Apparently, the SecKeychainAttributeList parameter is not just an output. This is also an input containing attributes to receive.

SecKeychainAttributeList dereferenced the uninitialized pointer attrs->attr and crashed. Initializing a pointer to NULL fixes the problem.

+1
source

All Articles