secd-33-keychain-ctk.c [plain text]
#include <CoreFoundation/CoreFoundation.h>
#include <Security/SecFramework.h>
#include <Security/SecBase.h>
#include <Security/SecItem.h>
#include <Security/SecItemPriv.h>
#include <Security/SecKey.h>
#include <Security/SecKeyPriv.h>
#include <Security/SecECKey.h>
#include <Security/SecAccessControl.h>
#include <Security/SecAccessControlPriv.h>
#include <Security/SecInternal.h>
#include <utilities/SecFileLocations.h>
#include <utilities/SecCFWrappers.h>
#include <utilities/SecCFError.h>
#include <libaks_acl_cf_keys.h>
#include <ctkclient_test.h>
#include "secd_regressions.h"
#include "SecdTestKeychainUtilities.h"
#include "SecKeybagSupport.h"
extern void LASetErrorCodeBlock(CFErrorRef (^newCreateErrorBlock)(void));
static void test_item_add(void) {
static const UInt8 data[] = { 0x01, 0x02, 0x03, 0x04 };
CFDataRef valueData = CFDataCreate(NULL, data, sizeof(data));
static const UInt8 oid[] = { 0x05, 0x06, 0x07, 0x08 };
CFDataRef oidData = CFDataCreate(NULL, oid, sizeof(oid));
CFMutableDictionaryRef attrs = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecClass, kSecClassGenericPassword,
kSecAttrTokenID, CFSTR("tokenid"),
kSecAttrService, CFSTR("ctktest-service"),
kSecValueData, valueData,
kSecReturnAttributes, kCFBooleanTrue,
NULL);
__block int phase = 0;
TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
phase++;
eq_cf(CFDictionaryGetValue(attributes, kSecAttrTokenID), CFSTR("tokenid"));
blocks->createOrUpdateObject = Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
phase++;
is(objectID, NULL);
eq_cf(CFDictionaryGetValue(at, kSecClass), kSecClassGenericPassword);
eq_cf(CFDictionaryGetValue(at, kSecAttrService), CFDictionaryGetValue(attrs, kSecAttrService));
eq_cf(CFDictionaryGetValue(at, kSecAttrTokenID), CFSTR("tokenid"));
eq_cf(CFDictionaryGetValue(at, kSecValueData), valueData);
CFDictionaryRemoveValue(at, kSecValueData);
return CFRetainSafe(oidData);
});
blocks->copyObjectAccessControl = Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
phase++;
SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
CFDataRef acData = SecAccessControlCopyData(ac);
CFRelease(ac);
return acData;
});
blocks->copyObjectData = Block_copy(^CFTypeRef(CFDataRef oid, CFErrorRef *error) {
phase++;
return CFRetain(valueData);
});
});
CFTypeRef result = NULL;
ok_status(SecItemAdd(attrs, &result));
eq_cf(CFDictionaryGetValue(result, kSecAttrService), CFSTR("ctktest-service"));
eq_cf(CFDictionaryGetValue(result, kSecAttrTokenID), CFSTR("tokenid"));
is(CFDictionaryGetValue(result, kSecValueData), NULL);
CFReleaseNull(result);
is(phase, 3);
phase = 0;
CFDictionarySetValue(attrs, kSecReturnData, kCFBooleanTrue);
CFDictionarySetValue(attrs, kSecAttrService, CFSTR("ctktest-service1"));
ok_status(SecItemAdd(attrs, &result));
eq_cf(CFDictionaryGetValue(result, kSecAttrService), CFSTR("ctktest-service1"));
eq_cf(CFDictionaryGetValue(result, kSecAttrTokenID), CFSTR("tokenid"));
eq_cf(CFDictionaryGetValue(result, kSecValueData), valueData);
CFReleaseNull(result);
is(phase, 4);
phase = 0;
CFDictionaryRemoveValue(attrs, kSecReturnAttributes);
CFDictionarySetValue(attrs, kSecAttrAccount, CFSTR("2nd"));
ok_status(SecItemAdd(attrs, &result));
eq_cf(result, valueData);
CFReleaseNull(result);
is(phase, 4);
CFRelease(attrs);
CFRelease(valueData);
CFRelease(oidData);
}
static const int kItemAddTestCount = 31;
static void test_item_query() {
static const UInt8 oid[] = { 0x05, 0x06, 0x07, 0x08 };
CFDataRef oidData = CFDataCreate(NULL, oid, sizeof(oid));
static const UInt8 data[] = { 0x01, 0x02, 0x03, 0x04 };
CFDataRef valueData = CFDataCreate(NULL, data, sizeof(data));
CFDataRef valueData2 = CFDataCreate(NULL, data, sizeof(data) - 1);
__block int phase = 0;
TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
phase++;
eq_cf(CFDictionaryGetValue(attributes, kSecAttrTokenID), CFSTR("tokenid"));
blocks->copyObjectData = _Block_copy(^CFTypeRef(CFDataRef oid, CFErrorRef *error) {
phase++;
return CFRetain(valueData);
});
});
CFMutableDictionaryRef attrs = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecClass, kSecClassGenericPassword,
kSecAttrService, CFSTR("ctktest-service"),
kSecValueData, valueData2,
NULL);
ok_status(SecItemAdd(attrs, NULL));
CFRelease(attrs);
CFMutableDictionaryRef query;
query = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecClass, kSecClassGenericPassword,
kSecAttrService, CFSTR("ctktest-service"),
kSecReturnAttributes, kCFBooleanTrue,
kSecReturnData, kCFBooleanTrue,
NULL);
phase = 0;
CFTypeRef result = NULL;
ok_status(SecItemCopyMatching(query, &result));
is(phase, 2);
is(CFGetTypeID(result), CFDictionaryGetTypeID());
eq_cf(CFDictionaryGetValue(result, kSecValueData), valueData);
is(CFGetTypeID(CFDictionaryGetValue(result, kSecAttrAccessControl)), SecAccessControlGetTypeID());
eq_cf(CFDictionaryGetValue(result, kSecAttrService), CFSTR("ctktest-service"));
CFReleaseSafe(result);
phase = 0;
CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
ok_status(SecItemCopyMatching(query, &result));
is(phase, 2);
is(CFGetTypeID(result), CFArrayGetTypeID());
is(CFArrayGetCount(result), 2);
CFReleaseSafe(result);
phase = 0;
CFDictionaryRemoveValue(query, kSecMatchLimit);
CFDictionaryRemoveValue(query, kSecReturnData);
ok_status(SecItemCopyMatching(query, &result));
is(phase, 0);
is(CFGetTypeID(result), CFDictionaryGetTypeID());
is(CFDictionaryGetValue(result, kSecValueData), NULL);
CFReleaseSafe(result);
phase = 0;
CFDictionaryRemoveValue(query, kSecReturnAttributes);
CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
CFDictionarySetValue(query, kSecAttrTokenID, CFSTR("tokenid"));
ok_status(SecItemCopyMatching(query, &result));
is(phase, 2);
eq_cf(result, valueData);
CFReleaseSafe(result);
CFRelease(query);
CFRelease(valueData);
CFRelease(valueData2);
CFRelease(oidData);
}
static const int kItemQueryTestCount = 21;
static void test_item_update() {
static const UInt8 data[] = { 0x01, 0x02, 0x03, 0x04 };
CFDataRef valueData2 = CFDataCreate(NULL, data, sizeof(data) - 1);
CFTypeRef result = NULL;
CFMutableDictionaryRef query, attrs;
__block int phase = 0;
__block bool store_value = false;
TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
phase++;
eq_cf(CFDictionaryGetValue(attributes, kSecAttrTokenID), CFSTR("tokenid"));
blocks->createOrUpdateObject = Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
phase++;
eq_cf(CFDictionaryGetValue(at, kSecValueData), valueData2);
if (!store_value) {
CFDictionaryRemoveValue(at, kSecValueData);
}
return CFRetainSafe(objectID);
});
blocks->copyObjectAccessControl = Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
phase++;
SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
CFDataRef acData = SecAccessControlCopyData(ac);
CFRelease(ac);
return acData;
});
blocks->copyObjectData = Block_copy(^CFTypeRef(CFDataRef oid, CFErrorRef *error) {
phase++;
return CFRetain(valueData2);
});
});
query = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecClass, kSecClassGenericPassword,
kSecAttrTokenID, CFSTR("tokenid"),
kSecAttrService, CFSTR("ctktest-service"),
NULL);
attrs = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecValueData, valueData2,
NULL);
ok_status(SecItemUpdate(query, attrs));
is(phase, 3);
phase = 0;
CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
ok_status(SecItemCopyMatching(query, &result));
eq_cf(valueData2, result);
CFRelease(result);
is(phase, 2);
phase = 0;
store_value = true;
CFDictionaryRemoveValue(query, kSecReturnData);
ok_status(SecItemUpdate(query, attrs));
is(phase, 3);
phase = 0;
CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
ok_status(SecItemCopyMatching(query, &result));
eq_cf(valueData2, result);
CFRelease(result);
is(phase, 0);
phase = 0;
CFDictionarySetValue(query, kSecAttrService, CFSTR("ctktest-service1"));
CFDictionaryRemoveValue(query, kSecReturnData);
ok_status(SecItemUpdate(query, attrs));
is(phase, 5);
phase = 0;
CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
ok_status(SecItemCopyMatching(query, &result));
is(phase, 0);
is(CFGetTypeID(result), CFArrayGetTypeID());
is(CFArrayGetCount(result), 2);
eq_cf(CFArrayGetValueAtIndex(result, 0), valueData2);
eq_cf(CFArrayGetValueAtIndex(result, 1), valueData2);
CFRelease(query);
CFRelease(attrs);
CFRelease(valueData2);
}
static const int kItemUpdateTestCount = 26;
static void test_item_delete(void) {
CFMutableDictionaryRef query;
CFTypeRef result;
__block int phase = 0;
__block CFErrorRef deleteError = NULL;
TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
phase++;
eq_cf(CFDictionaryGetValue(attributes, kSecAttrTokenID), CFSTR("tokenid"));
blocks->copyObjectAccessControl = _Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
phase++;
SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
CFDataRef acData = SecAccessControlCopyData(ac);
CFRelease(ac);
return acData;
});
blocks->deleteObject = _Block_copy(^bool(CFDataRef objectID, CFErrorRef *error) {
phase++;
if (deleteError != NULL) {
CFAssignRetained(*error, deleteError);
deleteError = NULL;
return false;
}
return true;
});
});
query = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecClass, kSecClassGenericPassword,
kSecAttrTokenID, CFSTR("tokenid"),
kSecAttrService, CFSTR("ctktest-service"),
NULL);
phase = 0;
ok_status(SecItemDelete(query));
is(phase, 2);
phase = 0;
is_status(SecItemCopyMatching(query, &result), errSecItemNotFound);
is(phase, 0);
phase = 0;
CFDictionarySetValue(query, kSecAttrService, CFSTR("ctktest-service1"));
ok_status(SecItemCopyMatching(query, &result));
is(phase, 0);
phase = 0;
#if USE_KEYSTORE
LASetErrorCodeBlock(^{ return (CFErrorRef)NULL; });
deleteError = CFErrorCreate(NULL, CFSTR(kTKErrorDomain), kTKErrorCodeAuthenticationFailed, NULL);
ok_status(SecItemDelete(query), "delete multiple token items");
is(phase, 6, "connect + delete-auth-fail + copyAccess + connect + delete + delete-2nd");
#else
ok_status(SecItemDelete(query), "delete multiple token items");
is(phase, 3, "connect + delete + delete");
#endif
phase = 0;
is_status(SecItemCopyMatching(query, &result), errSecItemNotFound);
is(phase, 0);
is_status(SecItemDelete(query), errSecItemNotFound);
CFRelease(query);
CFReleaseSafe(deleteError);
}
#if USE_KEYSTORE
static const int kItemDeleteTestCount = 15;
#else
static const int kItemDeleteTestCount = 14;
#endif
static void test_key_generate(void) {
__block int phase = 0;
TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
phase++;
blocks->createOrUpdateObject = _Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
phase++;
is(objectID, NULL);
CFDictionarySetValue(at, kSecClass, kSecClassKey);
SecKeyRef publicKey = NULL, privateKey = NULL;
CFMutableDictionaryRef params = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecAttrKeyType, kSecAttrKeyTypeEC,
kSecAttrKeySizeInBits, CFSTR("256"),
NULL);
ok_status(SecKeyGeneratePair(params, &publicKey, &privateKey));
CFDictionaryRef privKeyAttrs = SecKeyCopyAttributeDictionary(privateKey);
CFRelease(privateKey);
CFRelease(publicKey);
CFRelease(params);
CFDataRef oid = CFRetainSafe(CFDictionaryGetValue(privKeyAttrs, kSecValueData));
CFRelease(privKeyAttrs);
return oid;
});
blocks->copyObjectAccessControl = _Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
phase++;
SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
CFDataRef acData = SecAccessControlCopyData(ac);
CFRelease(ac);
return acData;
});
blocks->copyPublicKeyData = _Block_copy(^CFDataRef(CFDataRef objectID, CFErrorRef *error) {
phase++;
SecKeyRef privKey = SecKeyCreateECPrivateKey(NULL, CFDataGetBytePtr(objectID), CFDataGetLength(objectID), kSecKeyEncodingBytes);
CFDataRef publicData;
ok_status(SecKeyCopyPublicBytes(privKey, &publicData));
CFRelease(privKey);
return publicData;
});
blocks->copyObjectData = _Block_copy(^CFTypeRef(CFDataRef oid, CFErrorRef *error) {
phase++;
return kCFNull;
});
});
CFDictionaryRef prk_params = CFDictionaryCreateForCFTypes(NULL,
kSecAttrIsPermanent, kCFBooleanTrue,
NULL);
CFMutableDictionaryRef params = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecAttrKeyType, kSecAttrKeyTypeEC,
kSecAttrKeySizeInBits, CFSTR("256"),
kSecAttrTokenID, CFSTR("tokenid"),
kSecPrivateKeyAttrs, prk_params,
NULL);
CFRelease(prk_params);
SecKeyRef publicKey = NULL, privateKey = NULL;
phase = 0;
ok_status(SecKeyGeneratePair(params, &publicKey, &privateKey));
is(phase, 5);
CFDictionaryRef query = CFDictionaryCreateForCFTypes(NULL,
kSecValueRef, privateKey,
kSecReturnAttributes, kCFBooleanTrue,
kSecReturnRef, kCFBooleanTrue,
kSecReturnData, kCFBooleanTrue,
NULL);
phase = 0;
CFDictionaryRef result = NULL, keyAttrs = NULL;
ok_status(SecItemCopyMatching(query, (CFTypeRef *)&result));
is(phase, 3);
is(CFDictionaryGetValue(result, kSecValueData), NULL);
eq_cf(CFDictionaryGetValue(result, kSecAttrTokenID), CFSTR("tokenid"));
keyAttrs = SecKeyCopyAttributeDictionary((SecKeyRef)CFDictionaryGetValue(result, kSecValueRef));
eq_cf(CFDictionaryGetValue(keyAttrs, kSecAttrApplicationLabel), CFDictionaryGetValue(result, kSecAttrApplicationLabel));
CFAssignRetained(keyAttrs, SecKeyCopyAttributeDictionary(publicKey));
eq_cf(CFDictionaryGetValue(keyAttrs, kSecAttrApplicationLabel), CFDictionaryGetValue(result, kSecAttrApplicationLabel));
CFRelease(result);
CFRelease(keyAttrs);
CFRelease(publicKey);
CFRelease(privateKey);
CFRelease(query);
CFRelease(params);
}
static const int kKeyGenerateTestCount = 14;
static void test_key_sign(void) {
static const UInt8 data[] = { 0x01, 0x02, 0x03, 0x04 };
CFDataRef valueData = CFDataCreate(NULL, data, sizeof(data));
__block int phase = 0;
__block CFErrorRef signError = NULL;
TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
phase++;
blocks->copyPublicKeyData = _Block_copy(^CFDataRef(CFDataRef objectID, CFErrorRef *error) {
phase++;
SecKeyRef privKey = SecKeyCreateECPrivateKey(NULL, CFDataGetBytePtr(objectID), CFDataGetLength(objectID), kSecKeyEncodingBytes);
CFDataRef publicData;
ok_status(SecKeyCopyPublicBytes(privKey, &publicData));
CFRelease(privKey);
return publicData;
});
blocks->copyObjectAccessControl = _Block_copy(^CFDataRef(CFDataRef oid, CFErrorRef *error) {
phase++;
SecAccessControlRef ac = SecAccessControlCreate(NULL, NULL);
SecAccessControlSetProtection(ac, kSecAttrAccessibleAlways, NULL);
SecAccessControlAddConstraintForOperation(ac, kAKSKeyOpDefaultAcl, kCFBooleanTrue, NULL);
CFDataRef acData = SecAccessControlCopyData(ac);
CFRelease(ac);
return acData;
});
blocks->copySignature = _Block_copy(^CFDataRef(CFDataRef objectID, CFIndex padding, CFDataRef plainText, CFErrorRef *error) {
phase++;
if (signError != NULL) {
CFAssignRetained(*error, signError);
signError = NULL;
return NULL;
}
return CFRetainSafe(valueData);
});
});
CFDictionaryRef query = CFDictionaryCreateForCFTypes(NULL,
kSecClass, kSecClassKey,
kSecReturnRef, kCFBooleanTrue,
NULL);
phase = 0;
SecKeyRef privateKey = NULL;
ok_status(SecItemCopyMatching(query, (CFTypeRef *)&privateKey));
is(phase, 1);
phase = 0;
CFMutableDataRef sig = CFDataCreateMutable(NULL, 0);
CFDataSetLength(sig, 256);
size_t sigLen = CFDataGetLength(sig);
ok_status(SecKeyRawSign(privateKey, kSecPaddingNone, data, sizeof(data), CFDataGetMutableBytePtr(sig), &sigLen));
is(phase, 1);
CFDataSetLength(sig, sigLen);
is(CFDataGetLength(sig), CFDataGetLength(valueData));
eq_cf(valueData, sig);
#if USE_KEYSTORE
phase = 0;
CFDataSetLength(sig, 256);
sigLen = CFDataGetLength(sig);
LASetErrorCodeBlock(^ { return (CFErrorRef)NULL; });
signError = CFErrorCreate(NULL, CFSTR(kTKErrorDomain), kTKErrorCodeAuthenticationFailed, NULL);
ok_status(SecKeyRawSign(privateKey, kSecPaddingNone, data, sizeof(data), CFDataGetMutableBytePtr(sig), &sigLen));
is(phase, 4);
is(signError, NULL);
CFDataSetLength(sig, sigLen);
is(CFDataGetLength(sig), CFDataGetLength(valueData));
eq_cf(valueData, sig);
#endif
CFReleaseSafe(signError);
CFRelease(sig);
CFRelease(privateKey);
CFRelease(query);
}
#if USE_KEYSTORE
static const int kKeySignTestCount = 11;
#else
static const int kKeySignTestCount = 5;
#endif
static void test_key_generate_with_params(void) {
const UInt8 data[] = "foo";
CFDataRef cred_ref = CFDataCreate(NULL, data, 4);
__block int phase = 0;
TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
phase++;
eq_cf(CFDictionaryGetValue(attributes, kSecUseOperationPrompt), CFSTR("prompt"));
is(CFDictionaryGetValue(attributes, kSecUseAuthenticationUI), NULL);
eq_cf(CFDictionaryGetValue(attributes, kSecUseCredentialReference), cred_ref);
blocks->createOrUpdateObject = _Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
phase++;
SecCFCreateError(-4 , CFSTR(kTKErrorDomain), CFSTR(""), NULL, error);
return NULL;
});
});
CFDictionaryRef prk_params = CFDictionaryCreateForCFTypes(NULL,
kSecAttrIsPermanent, kCFBooleanTrue,
NULL);
CFMutableDictionaryRef params = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecAttrKeyType, kSecAttrKeyTypeEC,
kSecAttrKeySizeInBits, CFSTR("256"),
kSecAttrTokenID, CFSTR("tokenid"),
kSecPrivateKeyAttrs, prk_params,
kSecUseOperationPrompt, CFSTR("prompt"),
kSecUseAuthenticationUI, kSecUseAuthenticationUIAllow,
kSecUseCredentialReference, cred_ref,
NULL);
CFRelease(prk_params);
SecKeyRef publicKey = NULL, privateKey = NULL;
phase = 0;
is_status(SecKeyGeneratePair(params, &publicKey, &privateKey), errSecUserCanceled);
is(phase, 2);
CFReleaseSafe(publicKey);
CFReleaseSafe(privateKey);
CFRelease(params);
CFRelease(cred_ref);
}
static const int kKeyGenerateWithParamsTestCount = 5;
static void test_error_codes(void) {
CFMutableDictionaryRef attrs = CFDictionaryCreateMutableForCFTypesWith(NULL,
kSecClass, kSecClassGenericPassword,
kSecAttrTokenID, CFSTR("tokenid"),
NULL);
__block OSStatus ctk_error = 0;
TKTokenTestSetHook(^(CFDictionaryRef attributes, TKTokenTestBlocks *blocks) {
blocks->createOrUpdateObject = _Block_copy(^CFDataRef(CFDataRef objectID, CFMutableDictionaryRef at, CFErrorRef *error) {
SecCFCreateError(ctk_error, CFSTR(kTKErrorDomain), CFSTR(""), NULL, error);
return NULL;
});
});
ctk_error = kTKErrorCodeBadParameter;
is_status(SecItemAdd(attrs, NULL), errSecParam);
ctk_error = -1 ;
is_status(SecItemAdd(attrs, NULL), errSecUnimplemented);
ctk_error = -4 ;
is_status(SecItemAdd(attrs, NULL), errSecUserCanceled);
CFRelease(attrs);
}
static const int kErrorCodesCount = 3;
static void tests(void) {
secd_test_setup_temp_keychain("secd_33_keychain_ctk", NULL);
test_item_add();
test_item_query();
test_item_update();
test_item_delete();
test_key_generate();
test_key_sign();
test_key_generate_with_params();
test_error_codes();
}
int secd_33_keychain_ctk(int argc, char *const *argv) {
plan_tests(kItemAddTestCount +
kItemQueryTestCount +
kItemUpdateTestCount +
kItemDeleteTestCount +
kKeyGenerateTestCount +
kKeySignTestCount +
kKeyGenerateWithParamsTestCount +
kErrorCodesCount +
kSecdTestSetupTestCount);
tests();
return 0;
}