#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Security/cssm.h>
#include "common.h"
#include <Security/cssmapple.h>
#include <time.h>
static CSSM_VERSION vers = {2, 0};
const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
#define DETECT_MALLOC_ABUSE 1
#if DETECT_MALLOC_ABUSE
#define APP_MALLOC_MAGIC 'Util'
void * appMalloc (CSSM_SIZE size, void *allocRef) {
void *ptr;
ptr = malloc(size + 4);
*(uint32 *)ptr = APP_MALLOC_MAGIC;
ptr = (char *)ptr + 4;
return ptr;
}
void appFree (void *ptr, void *allocRef) {
if(ptr == NULL) {
return;
}
ptr = (char *)ptr - 4;
if(*(uint32 *)ptr != APP_MALLOC_MAGIC) {
printf("ERROR: appFree() freeing a block that we didn't allocate!\n");
return; }
*(uint32 *)ptr = 0;
free(ptr);
}
void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef) {
if(ptr == NULL) {
return appMalloc(size, allocRef);
}
ptr = (char *)ptr - 4;
if(*(uint32 *)ptr != APP_MALLOC_MAGIC) {
printf("ERROR: appRealloc() on a block that we didn't allocate!\n");
}
*(uint32 *)ptr = 0;
ptr = realloc(ptr, size + 4);
*(uint32 *)ptr = APP_MALLOC_MAGIC;
ptr = (char *)ptr + 4;
return ptr;
}
void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef) {
uint32 memSize = num * size;
void *ptr = appMalloc(memSize, allocRef);
memset(ptr, 0, memSize);
return ptr;
}
#else
void * appMalloc (CSSM_SIZE size, void *allocRef) {
return( malloc(size) );
}
void appFree (void *mem_ptr, void *allocRef) {
free(mem_ptr);
return;
}
void * appRealloc (void *ptr, CSSM_SIZE size, void *allocRef) {
return( realloc( ptr, size ) );
}
void * appCalloc (uint32 num, CSSM_SIZE size, void *allocRef) {
return( calloc( num, size ) );
}
#endif
static CSSM_API_MEMORY_FUNCS memFuncs = {
appMalloc,
appFree,
appRealloc,
appCalloc,
NULL
};
static CSSM_BOOL cssmInitd = CSSM_FALSE;
CSSM_BOOL cssmStartup()
{
CSSM_RETURN crtn;
CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
if(cssmInitd) {
return CSSM_TRUE;
}
crtn = CSSM_Init (&vers,
CSSM_PRIVILEGE_SCOPE_NONE,
&testGuid,
CSSM_KEY_HIERARCHY_NONE,
&pvcPolicy,
NULL );
if(crtn != CSSM_OK)
{
printError("CSSM_Init", crtn);
return CSSM_FALSE;
}
else {
cssmInitd = CSSM_TRUE;
return CSSM_TRUE;
}
}
CSSM_CSP_HANDLE cspStartup()
{
return cspDlDbStartup(CSSM_TRUE, NULL);
}
CSSM_CSP_HANDLE cspDbStartup(
CSSM_DB_HANDLE *dbHandPtr)
{
return cspDlDbStartup(CSSM_TRUE, NULL);
}
CSSM_CSP_HANDLE cspDlDbStartup(
CSSM_BOOL bareCsp, CSSM_DB_HANDLE *dbHandPtr) {
CSSM_CSP_HANDLE cspHand;
CSSM_RETURN crtn;
const CSSM_GUID *guid;
char *modName;
if(dbHandPtr) {
*dbHandPtr = 0;
}
if(cssmStartup() == CSSM_FALSE) {
return 0;
}
if(bareCsp) {
guid = &gGuidAppleCSP;
modName = (char*) "AppleCSP";
}
else {
guid = &gGuidAppleCSPDL;
modName = (char *) "AppleCSPDL";
}
crtn = CSSM_ModuleLoad(guid,
CSSM_KEY_HIERARCHY_NONE,
NULL, NULL); if(crtn) {
char outStr[100];
sprintf(outStr, "CSSM_ModuleLoad(%s)", modName);
printError(outStr, crtn);
return 0;
}
crtn = CSSM_ModuleAttach (guid,
&vers,
&memFuncs, 0, CSSM_SERVICE_CSP,
0, CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &cspHand);
if(crtn) {
char outStr[100];
sprintf(outStr, "CSSM_ModuleAttach(%s)", modName);
printError(outStr, crtn);
return 0;
}
return cspHand;
}
CSSM_RETURN cspShutdown(
CSSM_CSP_HANDLE cspHand,
CSSM_BOOL bareCsp) {
CSSM_RETURN crtn;
const CSSM_GUID *guid;
char *modName;
if(bareCsp) {
guid = &gGuidAppleCSP;
modName = (char *) "AppleCSP";
}
else {
guid = &gGuidAppleCSPDL;
modName = (char *) "AppleCSPDL";
}
crtn = CSSM_ModuleDetach(cspHand);
if(crtn) {
printf("Error detaching from %s\n", modName);
printError("CSSM_ModuleDetach", crtn);
return crtn;
}
crtn = CSSM_ModuleUnload(guid, NULL, NULL);
if(crtn) {
printf("Error unloading %s\n", modName);
printError("CSSM_ModuleUnload", crtn);
}
return crtn;
}
CSSM_DL_HANDLE dlStartup()
{
CSSM_DL_HANDLE dlHand = 0;
CSSM_RETURN crtn;
if(cssmStartup() == CSSM_FALSE) {
return 0;
}
crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL,
CSSM_KEY_HIERARCHY_NONE,
NULL, NULL); if(crtn) {
printError("CSSM_ModuleLoad(Apple CSPDL)", crtn);
return 0;
}
crtn = CSSM_ModuleAttach (&gGuidAppleCSPDL,
&vers,
&memFuncs, 0, CSSM_SERVICE_DL,
0, CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &dlHand);
if(crtn) {
printError("CSSM_ModuleAttach(Apple CSPDL)", crtn);
return 0;
}
return dlHand;
}
#define DELETE_WITH_AUTHENT 0
CSSM_RETURN dbDelete(
CSSM_DL_HANDLE dlHand, const char *dbName)
{
return CSSM_DL_DbDelete(dlHand, dbName, NULL, NULL);
}
CSSM_DB_HANDLE dbStartup(
CSSM_DL_HANDLE dlHand, const char *dbName)
{
CSSM_DB_HANDLE dbHand = 0;
CSSM_RETURN crtn = dbCreateOpen(dlHand, dbName,
CSSM_TRUE, CSSM_TRUE, NULL, &dbHand);
if(crtn == CSSM_OK) {
return dbHand;
}
else {
return 0;
}
}
#if 0
CSSM_DB_HANDLE dbStartupByName(CSSM_DL_HANDLE dlHand,
char *dbName,
CSSM_BOOL doCreate)
{
CSSM_RETURN crtn;
CSSM_DB_HANDLE dbHand;
crtn = CSSM_DL_DbOpen(dlHand,
dbName,
NULL, CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE,
NULL, NULL, &dbHand);
if(dbHand != 0) {
return dbHand;
}
if(!doCreate) {
printf("***no such data base (%s)\n", dbName);
printError("CSSM_DL_DbOpen", crtn);
return 0;
}
return dbStartup(dlHand, dbName);
}
#endif
void intToBytes(unsigned i, unsigned char *buf)
{
*buf++ = (unsigned char)((i >> 24) & 0xff);
*buf++ = (unsigned char)((i >> 16) & 0xff);
*buf++ = (unsigned char)((i >> 8) & 0xff);
*buf = (unsigned char)(i & 0xff);
}
void shortToBytes(unsigned short s, unsigned char *buf)
{
*buf++ = (unsigned char)((s >> 8) & 0xff);
*buf = (unsigned char)(s & 0xff);
}
unsigned bytesToInt(const unsigned char *buf) {
unsigned result;
result = (((unsigned)buf[0] << 24) & 0xff000000) |
(((unsigned)buf[1] << 16) & 0x00ff0000) |
(((unsigned)buf[2] << 8) & 0xff00) |
(((unsigned)buf[3]) & 0xff);
return result;
}
unsigned short bytesToShort(const unsigned char *buf) {
unsigned short result;
result = (((unsigned short)buf[0] << 8) & 0xff00) |
(((unsigned short)buf[1]) & 0xff);
return result;
}
CSSM_RETURN AddContextAttribute(CSSM_CC_HANDLE CCHandle,
uint32 AttributeType,
uint32 AttributeLength,
ContextAttrType attrType,
const void *AttributePtr,
uint32 attributeInt)
{
CSSM_CONTEXT_ATTRIBUTE newAttr;
CSSM_RETURN crtn;
newAttr.AttributeType = AttributeType;
newAttr.AttributeLength = AttributeLength;
if(attrType == CAT_Uint32) {
newAttr.Attribute.Uint32 = attributeInt;
}
else {
newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr;
}
crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
if(crtn) {
printError("CSSM_UpdateContextAttributes", crtn);
}
return crtn;
}
CSSM_RETURN appSetupCssmData(
CSSM_DATA_PTR data,
uint32 numBytes)
{
if(data == NULL) {
printf("Hey! appSetupCssmData with NULL Data!\n");
return CSSMERR_CSSM_INTERNAL_ERROR;
}
data->Data = (uint8 *)CSSM_MALLOC(numBytes);
if(data->Data == NULL) {
return CSSMERR_CSSM_MEMORY_ERROR;
}
data->Length = numBytes;
return CSSM_OK;
}
void appFreeCssmData(CSSM_DATA_PTR data,
CSSM_BOOL freeStruct)
{
if(data == NULL) {
return;
}
if(data->Length != 0) {
CSSM_FREE(data->Data);
}
if(freeStruct) {
CSSM_FREE(data);
}
else {
data->Length = 0;
data->Data = NULL;
}
}
CSSM_RETURN appCopyCssmData(const CSSM_DATA *src,
CSSM_DATA_PTR dst)
{
return appCopyData(src->Data, src->Length, dst);
}
CSSM_RETURN appCopyData(const void *src,
uint32 len,
CSSM_DATA_PTR dst)
{
dst->Length = 0;
if(len == 0) {
dst->Data = NULL;
return CSSM_OK;
}
dst->Data = (uint8 *)CSSM_MALLOC(len);
if(dst->Data == NULL) {
return CSSM_ERRCODE_MEMORY_ERROR;
}
dst->Length = len;
memcpy(dst->Data, src, len);
return CSSM_OK;
}
CSSM_BOOL appCompareCssmData(const CSSM_DATA *d1,
const CSSM_DATA *d2)
{
if(d1->Length != d2->Length) {
return CSSM_FALSE;
}
if(memcmp(d1->Data, d2->Data, d1->Length)) {
return CSSM_FALSE;
}
return CSSM_TRUE;
}
unsigned genRand(unsigned min, unsigned max)
{
unsigned i;
if(min == max) {
return min;
}
appGetRandomBytes(&i, 4);
return (min + (i % (max - min + 1)));
}
void simpleGenData(CSSM_DATA_PTR dbuf, unsigned minBufSize, unsigned maxBufSize)
{
unsigned len = genRand(minBufSize, maxBufSize);
appGetRandomBytes(dbuf->Data, len);
dbuf->Length = len;
}
#define MIN_OFFSET 0
#define MAX_OFFSET 99
#define MIN_ASCII 'a'
#define MAX_ASCII 'z'
unsigned genData(unsigned char *dataPool,
unsigned minExp,
unsigned maxExp,
dataType type)
{
int exp;
int offset;
int size;
char *cp;
int i;
char ac;
exp = genRand(minExp, maxExp);
offset = genRand(MIN_OFFSET, MAX_OFFSET);
size = 1;
while(exp--) { size *= 10;
}
size += offset;
switch(type) {
case DT_Zero:
bzero(dataPool, size);
break;
case DT_Increment:
{
int i;
for(i=0; i<size; i++) {
dataPool[i] = i;
}
}
break;
case DT_ASCII:
ac = MIN_ASCII;
cp = (char *)dataPool;
for(i=0; i<size; i++) {
*cp++ = ac++;
if(ac > MAX_ASCII) {
ac = MIN_ASCII;
}
}
break;
case DT_Random:
appGetRandomBytes(dataPool, size);
break;
}
return size;
}
void dumpBuffer(
const char *bufName, unsigned char *buf,
unsigned len)
{
unsigned i;
if(bufName) {
printf("%s\n", bufName);
}
printf(" ");
for(i=0; i<len; i++) {
printf("%02X ", buf[i]);
if((i % 24) == 23) {
printf("\n ");
}
}
printf("\n");
}
int testError(CSSM_BOOL quiet)
{
char resp;
if(quiet) {
printf("\n***Test aborting.\n");
exit(1);
}
fpurge(stdin);
printf("a to abort, c to continue: ");
resp = getchar();
return (resp == 'a');
}
void testStartBanner(
char *testName,
int argc,
char **argv)
{
printf("Starting %s; args: ", testName);
int i;
for(i=1; i<argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
}