#include "srCdsaUtils.h"
#include <stdlib.h>
#include <stdio.h>
#include <Security/SecCertificate.h>
#include <Security/cssmapple.h>
#include <Security/oidsalg.h>
#include <strings.h>
static CSSM_VERSION vers = {2, 0};
static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
void * srAppMalloc (CSSM_SIZE size, void *allocRef) {
return( malloc(size) );
}
void srAppFree (void *mem_ptr, void *allocRef) {
free(mem_ptr);
return;
}
void * srAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) {
return( realloc( ptr, size ) );
}
void * srAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) {
return( calloc( num, size ) );
}
static CSSM_API_MEMORY_FUNCS memFuncs = {
srAppMalloc,
srAppFree,
srAppRealloc,
srAppCalloc,
NULL
};
CSSM_BOOL srCompareCssmData(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;
}
static CSSM_BOOL cssmInitd = CSSM_FALSE;
CSSM_BOOL srCssmStartup()
{
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)
{
srPrintError("CSSM_Init", crtn);
return CSSM_FALSE;
}
else {
cssmInitd = CSSM_TRUE;
return CSSM_TRUE;
}
}
CSSM_CSP_HANDLE srCspStartup(
CSSM_BOOL bareCsp) {
CSSM_CSP_HANDLE cspHand;
CSSM_RETURN crtn;
const CSSM_GUID *guid;
if(srCssmStartup() == CSSM_FALSE) {
return 0;
}
if(bareCsp) {
guid = &gGuidAppleCSP;
}
else {
guid = &gGuidAppleCSPDL;
}
crtn = CSSM_ModuleLoad(guid,
CSSM_KEY_HIERARCHY_NONE,
NULL, NULL); if(crtn) {
srPrintError("CSSM_ModuleLoad()", crtn);
return 0;
}
crtn = CSSM_ModuleAttach (guid,
&vers,
&memFuncs, 0, CSSM_SERVICE_CSP,
0, CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &cspHand);
if(crtn) {
srPrintError("CSSM_ModuleAttach()", crtn);
return 0;
}
return cspHand;
}
CSSM_DL_HANDLE srDlStartup()
{
CSSM_DL_HANDLE dlHand = 0;
CSSM_RETURN crtn;
if(srCssmStartup() == CSSM_FALSE) {
return 0;
}
crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL,
CSSM_KEY_HIERARCHY_NONE,
NULL, NULL); if(crtn) {
srPrintError("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) {
srPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn);
return 0;
}
return dlHand;
}
CSSM_CL_HANDLE srClStartup()
{
CSSM_CL_HANDLE clHand;
CSSM_RETURN crtn;
if(srCssmStartup() == CSSM_FALSE) {
return 0;
}
crtn = CSSM_ModuleLoad(&gGuidAppleX509CL,
CSSM_KEY_HIERARCHY_NONE,
NULL, NULL); if(crtn) {
srPrintError("CSSM_ModuleLoad(AppleCL)", crtn);
return 0;
}
crtn = CSSM_ModuleAttach (&gGuidAppleX509CL,
&vers,
&memFuncs, 0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &clHand);
if(crtn) {
srPrintError("CSSM_ModuleAttach(AppleCL)", crtn);
return 0;
}
else {
return clHand;
}
}
CSSM_TP_HANDLE srTpStartup()
{
CSSM_TP_HANDLE tpHand;
CSSM_RETURN crtn;
if(srCssmStartup() == CSSM_FALSE) {
return 0;
}
crtn = CSSM_ModuleLoad(&gGuidAppleX509TP,
CSSM_KEY_HIERARCHY_NONE,
NULL, NULL); if(crtn) {
srPrintError("CSSM_ModuleLoad(AppleTP)", crtn);
return 0;
}
crtn = CSSM_ModuleAttach (&gGuidAppleX509TP,
&vers,
&memFuncs, 0, CSSM_SERVICE_TP, 0, CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &tpHand);
if(crtn) {
srPrintError("CSSM_ModuleAttach(AppleTP)", crtn);
return 0;
}
else {
return tpHand;
}
}
static CSSM_RETURN srAddContextAttribute(CSSM_CC_HANDLE CCHandle,
uint32 AttributeType,
uint32 AttributeLength,
const void *AttributePtr)
{
CSSM_CONTEXT_ATTRIBUTE newAttr;
CSSM_RETURN crtn;
newAttr.AttributeType = AttributeType;
newAttr.AttributeLength = AttributeLength;
newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr;
crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
if(crtn) {
srPrintError("CSSM_UpdateContextAttributes", crtn);
}
return crtn;
}
CSSM_RETURN srCspDeriveKey(CSSM_CSP_HANDLE cspHand,
uint32 keyAlg, const char *keyLabel,
unsigned keyLabelLen,
uint32 keyUsage, uint32 keySizeInBits,
CSSM_DATA_PTR password, CSSM_DATA_PTR salt, uint32 iterationCnt, CSSM_KEY_PTR key)
{
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
uint32 keyAttr;
CSSM_DATA dummyLabel;
CSSM_PKCS5_PBKDF2_PARAMS pbeParams;
CSSM_DATA pbeData;
CSSM_ACCESS_CREDENTIALS creds;
memset(key, 0, sizeof(CSSM_KEY));
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
CSSM_ALGID_PKCS5_PBKDF2,
keyAlg,
keySizeInBits,
&creds,
NULL, iterationCnt,
salt,
NULL, &ccHand);
if(crtn) {
srPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn);
return crtn;
}
keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF |
CSSM_KEYATTR_SENSITIVE;
dummyLabel.Length = keyLabelLen;
dummyLabel.Data = (uint8 *)keyLabel;
pbeParams.Passphrase = *password;
pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1;
pbeData.Data = (uint8 *)&pbeParams;
pbeData.Length = sizeof(pbeParams);
crtn = CSSM_DeriveKey(ccHand,
&pbeData,
keyUsage,
keyAttr,
&dummyLabel,
NULL, key);
if(crtn) {
srPrintError("CSSM_DeriveKey", crtn);
return crtn;
}
crtn = CSSM_DeleteContext(ccHand);
if(crtn) {
srPrintError("CSSM_DeleteContext", crtn);
}
return crtn;
}
#define DO_DSA_GEN_PARAMS 0
CSSM_RETURN srCspGenKeyPair(CSSM_CSP_HANDLE cspHand,
CSSM_DL_DB_HANDLE *dlDbHand, uint32 algorithm,
const char *keyLabel,
unsigned keyLabelLen,
uint32 keySize, CSSM_KEY_PTR pubKey, CSSM_KEYUSE pubKeyUsage, CSSM_KEYATTR_FLAGS pubAttrs, CSSM_KEY_PTR privKey, CSSM_KEYUSE privKeyUsage, CSSM_KEYATTR_FLAGS privAttrs) {
CSSM_RETURN crtn;
CSSM_RETURN ocrtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATA keyLabelData;
keyLabelData.Data = (uint8 *)keyLabel;
keyLabelData.Length = keyLabelLen;
memset(pubKey, 0, sizeof(CSSM_KEY));
memset(privKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
algorithm,
keySize,
NULL, NULL, NULL, NULL, NULL, &ccHand);
if(crtn) {
srPrintError("CSSM_CSP_CreateKeyGenContext", crtn);
return crtn;
}
switch(algorithm) {
#if DO_DSA_GEN_PARAMS
case CSSM_ALGID_DSA:
{
CSSM_DATA dummy = {0, NULL};
crtn = CSSM_GenerateAlgorithmParams(ccHand,
keySize, &dummy);
if(crtn) {
srPrintError("CSSM_GenerateAlgorithmParams", crtn);
CSSM_DeleteContext(ccHand);
return crtn;
}
srAppFree(dummy.Data, NULL);
}
break;
#endif
default:
break;
}
if(dlDbHand) {
crtn = srAddContextAttribute(ccHand,
CSSM_ATTRIBUTE_DL_DB_HANDLE,
sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE),
dlDbHand);
if(crtn) {
CSSM_DeleteContext(ccHand);
return crtn;
}
}
ocrtn = CSSM_GenerateKeyPair(ccHand,
pubKeyUsage,
pubAttrs,
&keyLabelData,
pubKey,
privKeyUsage,
privAttrs,
&keyLabelData, NULL, privKey);
if(ocrtn) {
srPrintError("CSSM_GenerateKeyPair", ocrtn);
}
crtn = CSSM_DeleteContext(ccHand);
if(crtn) {
srPrintError("CSSM_DeleteContext", crtn);
if(ocrtn == CSSM_OK) {
ocrtn = crtn;
}
}
return ocrtn;
}
CSSM_RETURN srAddCertToKC(
SecKeychainRef keychain,
const CSSM_DATA *cert,
CSSM_CERT_TYPE certType,
CSSM_CERT_ENCODING certEncoding,
const char *printName, const CSSM_DATA *keyLabel) {
SecCertificateRef certificate;
OSStatus rslt = SecCertificateCreateFromData(cert, certType, certEncoding, &certificate);
if (!rslt)
{
rslt = SecCertificateAddToKeychain(certificate, keychain);
CFRelease(certificate);
}
return rslt;
}
unsigned srDER_ToInt(const CSSM_DATA *DER_Data)
{
uint32 rtn = 0;
unsigned i = 0;
while(i < DER_Data->Length) {
rtn |= DER_Data->Data[i];
if(++i == DER_Data->Length) {
break;
}
rtn <<= 8;
}
return rtn;
}
void srPrintError(const char *op, CSSM_RETURN err)
{
cssmPerror(op, err);
}
char *srCfStrToCString(
CFStringRef cfStr)
{
CFIndex len = CFStringGetLength(cfStr) + 1;
char *cstr = (char *)malloc(len);
if(cstr == NULL) {
return NULL;
}
if(!CFStringGetCString(cfStr, cstr, len, kCFStringEncodingASCII)) {
printf("***CFStringGetCString error\n");
free(cstr);
return NULL;
}
return cstr;
}