#include "keychain_regressions.h"
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include <Security/SecBase.h>
#include <Security/SecBasePriv.h>
#include <Security/SecKeychainPriv.h>
#include <TargetConditionals.h>
#include <Security/cssmapi.h>
#include <stdlib.h>
#include "kc-30-xara-item-helpers.h"
#include "kc-30-xara-key-helpers.h"
#include "kc-30-xara-upgrade-helpers.h"
#if TARGET_OS_MAC
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wunused-function"
static void *cssmMalloc(CSSM_SIZE size, void *allocRef) { return malloc(size); }
static void cssmFree(void *mem_ptr, void *allocRef) { free(mem_ptr); return; }
static void *cssmRealloc(void *ptr, CSSM_SIZE size, void *allocRef) { return realloc( ptr, size ); }
static void *cssmCalloc(uint32 num, CSSM_SIZE size, void *allocRef) { return calloc( num, size ); }
static CSSM_API_MEMORY_FUNCS memFuncs = { cssmMalloc, cssmFree, cssmRealloc, cssmCalloc, NULL };
static CSSM_DL_DB_HANDLE initializeDL() {
CSSM_VERSION version = { 2, 0 };
CSSM_DL_DB_HANDLE dldbHandle;
CSSM_GUID myGuid = { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } };
CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
ok_status(CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &myGuid, CSSM_KEY_HIERARCHY_NONE, &pvcPolicy, NULL), "cssm_init");
ok_status(CSSM_ModuleLoad(&gGuidAppleFileDL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL), "module_load");
ok_status(CSSM_ModuleAttach(&gGuidAppleFileDL, &version, &memFuncs, 0, CSSM_SERVICE_DL, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &dldbHandle.DLHandle), "module_attach");
return dldbHandle;
}
#define initializeDLTests 3
static void unloadDL(CSSM_DL_DB_HANDLE* dldbHandle) {
ok_status(CSSM_ModuleDetach(dldbHandle->DLHandle), "detach");
ok_status(CSSM_ModuleUnload(&gGuidAppleFileDL, NULL, NULL), "unload");
ok_status(CSSM_Terminate(), "terminate");
}
#define unloadDLTests 3
static void modifyAttributeInKeychain(char * name, CSSM_DL_DB_HANDLE dldbHandle, char * keychainName, CSSM_DB_RECORDTYPE recordType, char* attributeName, char* newValue, size_t len) {
CSSM_RETURN status = CSSM_OK;
ok_status(CSSM_DL_DbOpen(dldbHandle.DLHandle, keychainName,
NULL,
CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE,
NULL,
NULL,
&dldbHandle.DBHandle), "%s: CSSM_DL_DbOpen", name);
CSSM_QUERY queryAll = {};
queryAll.RecordType = recordType;
CSSM_HANDLE results = 0;
CSSM_DATA data = {};
CSSM_DB_UNIQUE_RECORD_PTR uniqueIdPtr = NULL;
CSSM_DB_RECORD_ATTRIBUTE_DATA attributes = {};
attributes.NumberOfAttributes = 1;
attributes.AttributeData = malloc(sizeof(CSSM_DB_ATTRIBUTE_DATA) * attributes.NumberOfAttributes);
attributes.AttributeData[0].Info.Label.AttributeName = attributeName;
attributes.AttributeData[0].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
attributes.AttributeData[0].NumberOfValues = 1;
attributes.AttributeData[0].Value = malloc(sizeof(CSSM_DATA)*attributes.AttributeData[0].NumberOfValues);
status = CSSM_DL_DataGetFirst(dldbHandle, &queryAll, &results, &attributes, &data, &uniqueIdPtr);
while(status == CSSM_OK) {
attributes.AttributeData[0].Value[0].Data = (void*)newValue;
attributes.AttributeData[0].Value[0].Length = strlen(newValue);
CSSM_DL_DataModify(dldbHandle,
attributes.DataRecordType,
uniqueIdPtr,
&attributes,
NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
CSSM_DL_FreeUniqueRecord(dldbHandle, uniqueIdPtr);
status = CSSM_DL_DataGetNext(dldbHandle, results, &attributes, &data, &uniqueIdPtr);
}
ok_status(CSSM_DL_DbClose(dldbHandle), "%s: CSSM_DL_DbClose", name);
}
#define modifyAttributeInKeychainTests 2
static void testAttackItem(CSSM_DL_DB_HANDLE dldbHandle) {
char * name = "testAttackItem";
secdebugfunc("integrity", "************************************* %s", name);
SecKeychainRef kc = newKeychain(name);
checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0);
makeItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
CFReleaseNull(kc);
char * modification = "evil_application";
modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification));
kc = openKeychain(name);
checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0);
ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
}
#define testAttackItemTests (newKeychainTests + checkNTests + makeItemWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1)
static void testAttackKey(CSSM_DL_DB_HANDLE dldbHandle) {
char * name = "testAttackKey";
secdebugfunc("integrity", "************************************* %s", name);
SecKeychainRef kc = newKeychain(name);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
makeKeyWithIntegrity(name, kc, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
CFReleaseNull(kc);
char * modification = "evil_application";
modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "Label", modification, strlen(modification));
kc = openKeychain(name);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
}
#define testAttackKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1)
static void testAddAfterCorruptItem(CSSM_DL_DB_HANDLE dldbHandle) {
char * name = "testAddAfterCorruptItem";
secdebugfunc("integrity", "************************************* %s", name);
SecKeychainRef kc = newKeychain(name);
checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0);
makeCustomItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("test_label"), CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
CFReleaseNull(item);
makeDuplicateItem(name, kc, kSecClassGenericPassword);
CFReleaseNull(kc);
char * modification = "evil_application";
modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification));
kc = openKeychain(name);
checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0);
makeCustomItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("evil_application"), CFSTR("d2aa97b30a1f96f9e61fcade2b00d9f4284976a83a5b68392251ee5ec827f8cc"));
checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("evil_application"));
ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
}
#define testAddAfterCorruptItemTests (newKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeDuplicateItemTests \
+ modifyAttributeInKeychainTests + openKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeCustomDuplicateItemTests + 1)
static void testAddAfterCorruptKey(CSSM_DL_DB_HANDLE dldbHandle) {
char * name = "testAddAfterCorruptKey";
secdebugfunc("integrity", "************************************* %s", name);
SecKeychainRef kc = newKeychain(name);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0);
makeCustomKeyWithIntegrity(name, kc, CFSTR("test_key"), CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
makeCustomDuplicateKey(name, kc, CFSTR("test_key"));
CFReleaseNull(item);
SecKeyRef pub;
SecKeyRef priv;
makeCustomKeyPair(name, kc, CFSTR("test_key_pair"), &pub, &priv);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
CFReleaseNull(pub);
CFReleaseNull(priv);
ok_status(SecKeychainListRemoveKeychain(&kc), "%s: SecKeychainListRemoveKeychain", name);
char * modification = "evil_application";
modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "PrintName", modification, strlen(modification));
modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_PUBLIC_KEY, "PrintName", modification, strlen(modification));
modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_PRIVATE_KEY, "PrintName", modification, strlen(modification));
kc = openKeychain(name);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0);
makeCustomKeyWithIntegrity(name, kc, CFSTR("evil_application"), CFSTR("ca6d90a0b053113e43bbb67f64030230c96537f77601f66bdf821d8684431dfc"));
item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
makeCustomDuplicateKey(name, kc, CFSTR("evil_application"));
makeCustomKeyPair(name, kc, CFSTR("evil_application"), &pub, &priv);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
CFReleaseNull(item);
ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
}
#define testAddAfterCorruptKeyTests (newKeychainTests \
+ checkNTests + checkNTests + checkNTests \
+ makeCustomKeyWithIntegrityTests + checkNTests + makeCustomDuplicateKeyTests \
+ makeCustomKeyPairTests + checkNTests + checkNTests \
+ 1 \
+ modifyAttributeInKeychainTests \
+ modifyAttributeInKeychainTests \
+ modifyAttributeInKeychainTests \
+ openKeychainTests \
+ checkNTests + checkNTests + checkNTests \
+ makeCustomKeyWithIntegrityTests + checkNTests \
+ makeCustomDuplicateKeyTests \
+ makeCustomKeyPairTests + checkNTests + checkNTests \
+ 1)
static void testKeychainUpgrade() {
char name[100];
sprintf(name, "testKeychainUpgrade");
secdebugfunc("integrity", "************************************* %s", name);
writeOldKeychain(name, keychainFile);
SecKeychainRef kc = openCustomKeychain(name, "test.keychain", "password");
SecKeychainItemRef item;
item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
checkIntegrityHash(name, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5"));
makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic"));
item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1);
checkIntegrityHash(name, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03"));
makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet"));
item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578"));
item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d"));
CFReleaseNull(kc);
kc = openCustomKeychain(name, "test.keychain", "password");
item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
checkIntegrityHash(name, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5"));
makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic"));
item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1);
checkIntegrityHash(name, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03"));
makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet"));
item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1);
checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1);
checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578"));
item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1);
checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d"));
ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
}
#define testKeychainUpgradeTests (openCustomKeychainTests \
+ checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
+ checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
+ checkNTests + checkIntegrityHashTests + \
+ checkNTests + checkIntegrityHashTests + \
+ checkNTests + checkIntegrityHashTests + \
+ openCustomKeychainTests \
+ checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
+ checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \
+ checkNTests + checkIntegrityHashTests +\
+ checkNTests + checkIntegrityHashTests +\
+ checkNTests + checkIntegrityHashTests +\
1)
static SecAccessRef makeUidAccess(uid_t uid)
{
CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = {
CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, CSSM_ACL_MATCH_UID, uid, 0 };
CSSM_LIST_ELEMENT subject2 = { NULL, 0 };
subject2.Element.Word.Data = (UInt8 *)&selector;
subject2.Element.Word.Length = sizeof(selector);
CSSM_LIST_ELEMENT subject1 = {
&subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID
};
CSSM_ACL_AUTHORIZATION_TAG rights[] = {
CSSM_ACL_AUTHORIZATION_ANY };
CSSM_ACL_OWNER_PROTOTYPE owner = {
{ CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
false
};
CSSM_ACL_ENTRY_INFO acls[] = {
{
{
{ CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 },
false, { sizeof(rights) / sizeof(rights[0]), rights },
}
}
};
SecAccessRef access;
SecAccessCreateFromOwnerAndACL(&owner, sizeof(acls) / sizeof(acls[0]), acls, &access);
return access;
}
static void checkAccessLength(const char * name, SecAccessRef access, int expected) {
CFArrayRef acllist = NULL;
ok_status(SecAccessCopyACLList(access, &acllist), "%s: SecAccessCopyACLList", name);
int aclsFound = 0;
CFStringRef output = NULL;
if(acllist) {
for(int i = 0; i < CFArrayGetCount(acllist); i++) {
SecACLRef acl = (SecACLRef) CFArrayGetValueAtIndex(acllist, i);
CFArrayRef auths = SecACLCopyAuthorizations(acl);
CFRange searchrange = CFRangeMake(0, CFArrayGetCount(auths));
if(!CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationIntegrity) &&
!CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationPartitionID)) {
aclsFound += 1;
}
CFReleaseNull(auths);
}
CFReleaseNull(acllist);
}
is(aclsFound, expected, "%s: ACL has correct number of entries", name);
}
#define checkAccessLengthTests 2
static void testUidAccess() {
char name[100];
sprintf(name, "testUidAccess");
secdebugfunc("integrity", "************************************* %s", name);
SecAccessRef access = makeUidAccess(getuid());
SecKeychainRef kc = newKeychain(name);
CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label"));
CFDictionarySetValue(query, kSecAttrAccess, access);
CFTypeRef result = NULL;
ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name);
ok(result != NULL, "%s: SecItemAdd returned a result", name);
SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
ok_status(SecKeychainItemSetAccess(item, access), "%s: SecKeychainItemSetAccess", name);
checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
access = NULL;
ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name);
checkAccessLength(name, access, 2);
const char * newPassword = "newPassword";
ok_status(SecKeychainItemModifyContent(item, NULL, (UInt32) strlen(newPassword), newPassword), "%s: SecKeychainItemModifyContent", name);
access = NULL;
ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name);
checkAccessLength(name, access, 2);
ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
}
#define testUidAccessTests (newKeychainTests + 2 + checkNTests + 1 + checkNTests + 1 + checkAccessLengthTests \
+ 2 + checkAccessLengthTests + 1)
static SecAccessRef makeMultipleUidAccess(uid_t* uids, uint32 count)
{
CSSM_ACL_AUTHORIZATION_TAG rights[] =
{
CSSM_ACL_AUTHORIZATION_ANY };
size_t numRights = sizeof(rights) / sizeof(rights[0]);
CSSM_ACL_PROCESS_SUBJECT_SELECTOR selectors[count];
CSSM_LIST_ELEMENT heads[count], tails[count];
CSSM_ACL_ENTRY_INFO acls[count];
memset(heads, 0, sizeof(heads));
memset(acls, 0, sizeof(acls));
uint32 i = count;
while (i--)
{
selectors[i].version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION;
selectors[i].mask = CSSM_ACL_MATCH_UID; selectors[i].uid = uids[i]; selectors[i].gid = 0;
heads[i].NextElement = &(tails[i]);
heads[i].WordID = CSSM_ACL_SUBJECT_TYPE_PROCESS;
heads[i].ElementType = CSSM_LIST_ELEMENT_WORDID;
tails[i].NextElement = NULL;
tails[i].WordID = CSSM_WORDID__NLU_;
tails[i].ElementType = CSSM_LIST_ELEMENT_DATUM;
tails[i].Element.Word.Data = (UInt8 *)&selectors[i];
tails[i].Element.Word.Length = sizeof(selectors[i]);
acls[i].EntryPublicInfo.TypedSubject.ListType = CSSM_LIST_TYPE_UNKNOWN;
acls[i].EntryPublicInfo.TypedSubject.Head = &heads[i];
acls[i].EntryPublicInfo.TypedSubject.Tail = &tails[i];
acls[i].EntryPublicInfo.Delegate = CSSM_FALSE;
acls[i].EntryPublicInfo.Authorization.NumberOfAuthTags = (uint32) numRights;
acls[i].EntryPublicInfo.Authorization.AuthTags = rights;
acls[i].EntryHandle = i;
}
CSSM_ACL_OWNER_PROTOTYPE owner;
owner.TypedSubject = acls[0].EntryPublicInfo.TypedSubject;
owner.Delegate = acls[0].EntryPublicInfo.Delegate;
SecAccessRef access;
SecAccessCreateFromOwnerAndACL(&owner, count, acls, &access);
return access;
}
static void testMultipleUidAccess() {
char name[100];
sprintf(name, "testMultipleUidAccess");
secdebugfunc("integrity", "************************************* %s", name);
uid_t uids[5];
uids[0] = getuid();
uids[1] = 0;
uids[2] = 500;
uids[3] = 501;
uids[4] = 502;
SecAccessRef access = makeMultipleUidAccess(uids, 5);
SecKeychainRef kc = newKeychain(name);
CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label"));
CFDictionarySetValue(query, kSecAttrAccess, access);
CFTypeRef result = NULL;
ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name);
ok(result != NULL, "%s: SecItemAdd returned a result", name);
checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
}
#define testMultipleUidAccessTests (newKeychainTests + checkNTests + 3)
static void testRootUidAccess() {
char name[100];
sprintf(name, "testRootUidAccess");
secdebugfunc("integrity", "************************************* %s", name);
SecAccessRef access = SecAccessCreateWithOwnerAndACL(getuid(), 0, (kSecUseOnlyUID | kSecHonorRoot), NULL, NULL);
SecKeychainRef kc = newKeychain(name);
CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label"));
CFDictionarySetValue(query, kSecAttrAccess, access);
CFTypeRef result = NULL;
ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name);
ok(result != NULL, "%s: SecItemAdd returned a result", name);
query = makeQueryItemDictionary(kc, kSecClassGenericPassword);
SecKeychainItemRef item = checkN(name, query, 1);
ok_status(SecKeychainItemSetAccess(item, access), "%s: SecKeychainItemSetAccess", name);
checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1);
ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name);
}
#define testRootUidAccessTests (newKeychainTests + checkNTests + 4 + checkNTests)
#define kTestCount (0 \
+ testAddItemTests \
+ testAddItemTests \
+ testCopyMatchingItemTests \
+ testCopyMatchingItemTests \
+ testUpdateItemTests \
+ testUpdateItemTests \
+ testAddDuplicateItemTests \
+ testAddDuplicateItemTests \
+ testDeleteItemTests \
+ testDeleteItemTests \
+ testUpdateRetainedItemTests \
+ testUpdateRetainedItemTests \
\
+ testAddKeyTests \
+ testAddFreeKeyTests \
+ testCopyMatchingKeyTests \
+ testUpdateKeyTests \
+ testAddDuplicateKeyTests \
+ testKeyPairTests \
+ testExportImportKeyPairTests \
\
+ initializeDLTests \
+ testAttackItemTests \
+ testAttackKeyTests \
+ testAddAfterCorruptItemTests \
+ testAddAfterCorruptKeyTests \
+ unloadDLTests \
\
+ testKeychainUpgradeTests \
+ testUidAccessTests \
+ testMultipleUidAccessTests \
+ testRootUidAccessTests \
)
static void tests(void)
{
const char *home_dir = getenv("HOME");
sprintf(keychainFile, "%s/Library/Keychains/test.keychain", home_dir);
sprintf(keychainName, "test.keychain");
testAddItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
testAddItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
testCopyMatchingItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
testCopyMatchingItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
testUpdateItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"),
CFSTR("7b7be2fd6ee9f81ba4c5575ea451f2c21117fc0f241625a6cf90c65180b8c9f5"));
testUpdateItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"),
CFSTR("d71af9e4d54127a5dbc10c5ec097b828065cfbaf2b775caf1a3c4e3410f80851"));
testAddDuplicateItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
testAddDuplicateItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
testDeleteItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"));
testDeleteItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"));
testUpdateRetainedItem(kSecClassGenericPassword);
testUpdateRetainedItem(kSecClassInternetPassword);
testAddKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
testAddFreeKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
testCopyMatchingKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
testUpdateKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"),
CFSTR("a744ce6db8359ad264ed5f4a35ecfcc8b6599b89319e7ea316035acd3fb02c22"));
testAddDuplicateKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
testAddDuplicateFreeKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"));
testKeyPair();
testExportImportKeyPair();
CSSM_DL_DB_HANDLE dldbHandle = initializeDL();
testAttackItem(dldbHandle);
testAttackKey(dldbHandle);
testAddAfterCorruptItem(dldbHandle);
testAddAfterCorruptKey(dldbHandle);
unloadDL(&dldbHandle);
testKeychainUpgrade();
testUidAccess();
testMultipleUidAccess();
testRootUidAccess();
}
#pragma clang pop
#else
#define kTestCount (0)
static void tests(void)
{
}
#endif
int kc_30_xara(int argc, char *const *argv)
{
plan_tests(kTestCount);
tests();
return 0;
}