kc-15-key-update-valueref.c [plain text]
#include "keychain_regressions.h"
#include "kc-helpers.h"
#include "kc-item-helpers.h"
#include "kc-key-helpers.h"
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <Security/Security.h>
#include <utilities/SecCFRelease.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <time.h>
#include <sys/param.h>
static int debug = 1;
static int verbose = 1;
#define MAXNAMELEN MAXPATHLEN
#define MAXITEMS INT32_MAX
#pragma mark -- Utility Functions --
static void PrintTestResult(char *testStr, OSStatus status, OSStatus expected)
{
if (verbose) {
fprintf(stdout, "%s: %s (result=%d, expected=%d)\n", testStr,
(status==expected) ? "OK" : "FAILED",
(int)status, (int)expected);
}
if (debug) {
fprintf(stdout, "\n");
}
fflush(stdout);
}
static void PrintCFStringWithFormat(const char *formatStr, CFStringRef inStr)
{
char *buf = (char*)malloc(MAXNAMELEN);
if (buf) {
if (CFStringGetCString(inStr, buf, (CFIndex)MAXNAMELEN, kCFStringEncodingUTF8)) {
fprintf(stdout, formatStr, buf);
fflush(stdout);
}
free(buf);
}
}
const CFStringRef gPrefix = CFSTR("Test Key");
const CFStringRef gLabel = CFSTR("Test AES Encryption Key");
const CFStringRef gUUID = CFSTR("550e8400-e29b-41d4-a716-446655441234");
static int CreateSymmetricKey(
SecKeychainRef inKeychain,
CFStringRef keyLabel,
CFStringRef keyAppLabel,
CFStringRef keyAppTag,
OSStatus expected)
{
OSStatus status;
int keySizeValue = 128;
CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue);
SecKeychainRef keychain = NULL;
if (inKeychain == NULL)
status = SecKeychainCopyDefault(&keychain);
else
keychain = (SecKeychainRef) CFRetain(inKeychain);
SecAccessRef access = NULL;
status = SecAccessCreate(gLabel, NULL, &access);
CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue( params, kSecClass, kSecClassKey );
CFDictionaryAddValue( params, kSecUseKeychain, keychain );
CFDictionaryAddValue( params, kSecAttrAccess, access );
CFDictionaryAddValue( params, kSecAttrKeyClass, kSecAttrKeyClassSymmetric );
CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeAES );
CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); CFRelease(keySize);
CFDictionaryAddValue( params, kSecAttrIsPermanent, kCFBooleanTrue );
CFDictionaryAddValue( params, kSecAttrCanEncrypt, kCFBooleanTrue );
CFDictionaryAddValue( params, kSecAttrCanDecrypt, kCFBooleanTrue );
CFDictionaryAddValue( params, kSecAttrCanWrap, kCFBooleanFalse );
CFDictionaryAddValue( params, kSecAttrCanUnwrap, kCFBooleanFalse );
if (keyLabel)
CFDictionaryAddValue( params, kSecAttrLabel, keyLabel );
if (keyAppLabel)
CFDictionaryAddValue( params, kSecAttrApplicationLabel, keyAppLabel );
if (keyAppTag)
CFDictionaryAddValue( params, kSecAttrApplicationTag, keyAppTag );
CFErrorRef error = NULL;
SecKeyRef key = SecKeyGenerateSymmetric(params, &error);
if (debug) {
if (key == NULL) {
CFStringRef desc = (error) ? CFErrorCopyDescription(error) : CFRetain(CFSTR("(no result!"));
PrintCFStringWithFormat("SecKeyGenerateSymmetric failed: %s\n", desc);
CFRelease(desc);
}
else {
CFStringRef desc = CFCopyDescription(key);
PrintCFStringWithFormat("SecKeyGenerateSymmetric succeeded: %s\n", desc);
CFRelease(desc);
}
}
status = (error) ? (OSStatus) CFErrorGetCode(error) : noErr;
if (key) CFRelease(key);
if (error) CFRelease(error);
if (params) CFRelease(params);
if (keychain) CFRelease(keychain);
if (access) CFRelease(access);
PrintTestResult("CreateSymmetricKey", status, expected);
return status;
}
static int TestUpdateItems(SecKeychainRef keychain)
{
int result = 0;
OSStatus status = errSecSuccess;
CFGregorianDate curGDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), NULL);
CFStringRef curDateLabel = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%4d-%02d-%02d)"),
gPrefix, (int) (curGDate.year), (int) (curGDate.month), (int) (curGDate.day));
CFStringRef curAppTag = CFSTR("SecItemUpdate");
status = CreateSymmetricKey(keychain, curDateLabel, gUUID, curAppTag, noErr);
CFReleaseNull(curDateLabel);
if (status && status != errSecDuplicateItem)
++result;
CFStringRef keyLabel = CFSTR("iMessage test key");
CFStringRef newLabel = CFSTR("iMessage test PRIVATE key");
SecKeyRef publicKey = NULL;
SecKeyRef privateKey = NULL;
CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
int keySizeValue = 1024;
CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue);
CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeRSA );
CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); CFReleaseNull(keySize);
CFDictionaryAddValue( params, kSecAttrLabel, keyLabel );
CFDictionaryAddValue( params, kSecUseKeychain, keychain );
status = SecKeyGeneratePair(params, &publicKey, &privateKey);
ok_status(status, "%s: SecKeyGeneratePair", testName);
if (status != noErr) {
++result;
}
PrintTestResult("TestUpdateItems: generating key pair", status, noErr);
checkN(testName, createQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, keyLabel), 1);
checkN(testName, createQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, newLabel), 0);
CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue( query, kSecClass, kSecClassKey );
CFDictionaryAddValue( query, kSecValueRef, privateKey );
CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
SecAccessRef access = NULL;
status = SecAccessCreate(newLabel, NULL, &access);
ok_status(status, "%s: SecAccessCreate", testName);
if (status != noErr) {
++result;
}
PrintTestResult("TestUpdateItems: creating access", status, noErr);
CFDictionaryAddValue( attrs, kSecAttrLabel, newLabel );
status = SecItemUpdate( query, attrs );
ok_status(status, "%s: SecItemUpdate", testName);
if (status != noErr) {
++result;
}
PrintTestResult("TestUpdateItems: updating item", status, noErr);
checkN(testName, createQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, keyLabel), 0);
checkN(testName, createQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, newLabel), 1);
if (publicKey)
CFRelease(publicKey);
if (privateKey)
CFRelease(privateKey);
if (access)
CFRelease(access);
if (params)
CFRelease(params);
if (query)
CFRelease(query);
if (attrs)
CFRelease(attrs);
return result;
}
int kc_15_key_update_valueref(int argc, char *const *argv)
{
plan_tests(20);
initializeKeychainTests(__FUNCTION__);
SecKeychainRef keychain = getPopulatedTestKeychain();
TestUpdateItems(keychain);
checkPrompts(0, "no prompts during test");
ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName);
CFRelease(keychain);
deleteTestFiles();
return 0;
}