kc-17-item-find-key.c   [plain text]


#include <Security/SecKey.h>
#include <Security/SecKeychain.h>
#include <Security/SecKeychainSearch.h>
#include <stdlib.h>
#include <unistd.h>

#include "testmore.h"
#include "testenv.h"
#include "testleaks.h"

void tests(void)
{
	SecKeychainRef keychain;
	ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain),
		"create keychain");
	SecKeyRef pub_crypt = NULL, prv_crypt = NULL;
	ok_status(SecKeyCreatePair(keychain, CSSM_ALGID_RSA, 256,
		0 /* contextHandle */,
		CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_WRAP,
		CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE,
		CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_UNWRAP,
		CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE |
			CSSM_KEYATTR_SENSITIVE,
		NULL /* initialAccess */, &pub_crypt, &prv_crypt),
		"generate encryption keypair");

	SecKeyRef pub_sign = NULL, prv_sign = NULL;
	ok_status(SecKeyCreatePair(keychain, CSSM_ALGID_RSA, 256,
		0 /* contextHandle */,
		CSSM_KEYUSE_VERIFY,
		CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE,
		CSSM_KEYUSE_SIGN,
		CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE |
			CSSM_KEYATTR_SENSITIVE,
		NULL /* initialAccess */, &pub_sign, &prv_sign),
		"generate signing keypair");

	uint32 btrue = 1;
	uint32 bfalse = 0;
	/* uint32 prv_class = CSSM_KEYCLASS_PRIVATE_KEY; */
	SecKeychainAttribute attrs[] = 
	{
		{ kSecKeyDecrypt, sizeof(uint32), &btrue },
		{ kSecKeyEncrypt, sizeof(uint32), &bfalse },
		/* { kSecKeyKeyClass, sizeof(uint32), &prv_class } */
	};
	SecKeychainAttributeList attrList = { sizeof(attrs) / sizeof(*attrs), attrs };
	SecKeychainSearchRef search;
	OSStatus result;
	SecKeychainItemRef item;
	
	ok_status((result = SecKeychainSearchCreateFromAttributes(keychain,
		CSSM_DL_DB_RECORD_PRIVATE_KEY, &attrList, &search)), "create key search");
	if (result == noErr)
	{
		ok_status(SecKeychainSearchCopyNext(search, &item), "get first key");
		cmp_ok((intptr_t)prv_crypt, ==, (intptr_t)item, "is key found the right one?");
		CFRelease(item);
		item = NULL;
		is_status(SecKeychainSearchCopyNext(search, &item),
			errSecItemNotFound, "get next key");
		is((intptr_t)item, 0, "no item returned");
		CFRelease(search);
	}
	
	SecKeychainAttribute attrs2[] = { { kSecKeySign, sizeof(btrue), &btrue } };
	SecKeychainAttributeList attrList2 = { sizeof(attrs2) / sizeof(*attrs2), attrs2 };
	ok_status((result = SecKeychainSearchCreateFromAttributes(keychain,
		CSSM_DL_DB_RECORD_PRIVATE_KEY, &attrList2, &search)), "create private signing key search");
	
	if (result == noErr)
	{
		ok_status(SecKeychainSearchCopyNext(search, &item), "get first key");
		cmp_ok((intptr_t)prv_sign, ==, (intptr_t)item, "is key found the right one?");
		CFRelease(item);
		is_status(SecKeychainSearchCopyNext(search, &item),
			errSecItemNotFound, "get next key");
		CFRelease(search);
	}
	
	CFRelease(pub_crypt);
	CFRelease(prv_crypt);
	CFRelease(pub_sign);
	CFRelease(prv_sign);
	CFRelease(keychain);

	ok(tests_end(1), "cleanup");
}

int main(int argc, char *const *argv)
{
	plan_tests(14);

	if (!tests_begin(argc, argv))
		BAIL_OUT("tests_begin failed");

	tests();
	ok_leaks("no leaks");

	return 0;
}