#include "libCdsaCrypt.h"
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#pragma mark --- static session data and private functions ----
static CSSM_VERSION vers = {2, 0};
static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
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 ) );
}
static CSSM_API_MEMORY_FUNCS memFuncs = {
appMalloc,
appFree,
appRealloc,
appCalloc,
NULL
};
static CSSM_BOOL cssmInitd = CSSM_FALSE;
CSSM_RETURN cssmStartup()
{
if(cssmInitd) {
return CSSM_OK;
}
CSSM_RETURN crtn;
CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
crtn = CSSM_Init (&vers,
CSSM_PRIVILEGE_SCOPE_NONE,
&testGuid,
CSSM_KEY_HIERARCHY_NONE,
&pvcPolicy,
NULL );
if(crtn != CSSM_OK) {
return crtn;
}
else {
cssmInitd = CSSM_TRUE;
return CSSM_OK;
}
}
static CSSM_RETURN genCryptHandle(
CSSM_CSP_HANDLE cspHandle,
const CSSM_KEY *key,
const CSSM_DATA *ivPtr,
CSSM_CC_HANDLE *ccHandle)
{
CSSM_ALGORITHMS keyAlg = key->KeyHeader.AlgorithmId;
CSSM_ALGORITHMS encrAlg;
CSSM_ENCRYPT_MODE encrMode = CSSM_ALGMODE_NONE;
CSSM_PADDING encrPad = CSSM_PADDING_NONE;
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand = 0;
CSSM_ACCESS_CREDENTIALS creds;
CSSM_BOOL isSymmetric = CSSM_TRUE;
switch(keyAlg) {
case CSSM_ALGID_3DES_3KEY:
encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
break;
default:
encrAlg = keyAlg;
break;
}
switch(encrAlg) {
case CSSM_ALGID_DES:
case CSSM_ALGID_3DES_3KEY_EDE:
case CSSM_ALGID_RC5:
case CSSM_ALGID_RC2:
encrMode = CSSM_ALGMODE_CBCPadIV8;
encrPad = CSSM_PADDING_PKCS5;
break;
case CSSM_ALGID_AES:
encrMode = CSSM_ALGMODE_CBCPadIV8;
encrPad = CSSM_PADDING_PKCS7;
break;
case CSSM_ALGID_ASC:
case CSSM_ALGID_RC4:
encrMode = CSSM_ALGMODE_NONE;
encrPad = CSSM_PADDING_NONE;
break;
case CSSM_ALGID_RSA:
encrPad = CSSM_PADDING_PKCS1;
isSymmetric = CSSM_FALSE;
break;
default:
return CSSMERR_CSP_INTERNAL_ERROR;
}
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
if(isSymmetric) {
crtn = CSSM_CSP_CreateSymmetricContext(cspHandle,
encrAlg,
encrMode,
NULL, key,
ivPtr, encrPad,
NULL, &ccHand);
}
else {
crtn = CSSM_CSP_CreateAsymmetricContext(cspHandle,
encrAlg,
&creds, key,
encrPad,
&ccHand);
}
if(crtn) {
return crtn;
}
*ccHandle = ccHand;
return CSSM_OK;
}
#pragma mark --- start of public Functions ---
CSSM_RETURN cdsaCspAttach(
CSSM_CSP_HANDLE *cspHandle)
{
CSSM_CSP_HANDLE cspHand;
CSSM_RETURN crtn;
crtn = cssmStartup();
if(crtn) {
return crtn;
}
crtn = CSSM_ModuleLoad(&gGuidAppleCSP,
CSSM_KEY_HIERARCHY_NONE,
NULL, NULL); if(crtn) {
return crtn;
}
crtn = CSSM_ModuleAttach (&gGuidAppleCSP,
&vers,
&memFuncs, 0, CSSM_SERVICE_CSP,
0, CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &cspHand);
if(crtn) {
return crtn;
}
*cspHandle = cspHand;
return CSSM_OK;
}
CSSM_RETURN cdsaCspDetach(
CSSM_CSP_HANDLE cspHandle)
{
return CSSM_ModuleDetach(cspHandle);
}
CSSM_RETURN cdsaFreeKey(
CSSM_CSP_HANDLE cspHandle,
CSSM_KEY_PTR key)
{
return CSSM_FreeKey(cspHandle,
NULL, key,
CSSM_FALSE); }
#pragma mark ------ Diffie-Hellman key generation and derivation ------
CSSM_RETURN cdsaDhGenerateKeyPair(
CSSM_CSP_HANDLE cspHandle,
CSSM_KEY_PTR publicKey,
CSSM_KEY_PTR privateKey,
uint32 keySizeInBits,
const CSSM_DATA *inParams, CSSM_DATA_PTR outParams) {
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHandle;
CSSM_DATA labelData = {8, (uint8 *)"tempKey"};
if(inParams && outParams) {
return CSSMERR_CSSM_INVALID_POINTER;
}
if(!inParams && !outParams) {
return CSSMERR_CSSM_INVALID_POINTER;
}
memset(publicKey, 0, sizeof(CSSM_KEY));
memset(privateKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHandle,
CSSM_ALGID_DH,
keySizeInBits,
NULL, NULL, NULL, NULL, inParams, &ccHandle);
if(crtn) {
return crtn;
}
if(outParams) {
outParams->Data = NULL;
outParams->Length = 0;
crtn = CSSM_GenerateAlgorithmParams(ccHandle,
keySizeInBits, outParams);
if(crtn) {
CSSM_DeleteContext(ccHandle);
return crtn;
}
}
crtn = CSSM_GenerateKeyPair(ccHandle,
CSSM_KEYUSE_DERIVE, CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE,
&labelData,
publicKey,
CSSM_KEYUSE_DERIVE,
CSSM_KEYATTR_RETURN_REF,
&labelData, NULL, privateKey);
CSSM_DeleteContext(ccHandle);
return crtn;
}
CSSM_RETURN cdsaDhKeyExchange(
CSSM_CSP_HANDLE cspHandle,
CSSM_KEY_PTR myPrivateKey, const void *theirPubKey,
uint32 theirPubKeyLen,
CSSM_KEY_PTR derivedKey, uint32 deriveKeySizeInBits,
CSSM_ALGORITHMS derivedKeyAlg) {
CSSM_RETURN crtn;
CSSM_ACCESS_CREDENTIALS creds;
CSSM_CC_HANDLE ccHandle;
CSSM_DATA labelData = {8, (uint8 *)"tempKey"};
memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
memset(derivedKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateDeriveKeyContext(cspHandle,
CSSM_ALGID_DH,
derivedKeyAlg,
deriveKeySizeInBits,
&creds,
myPrivateKey, 0, 0, 0, &ccHandle);
if(crtn) {
return crtn;
}
CSSM_DATA theirPubKeyData = { theirPubKeyLen, (uint8 *)theirPubKey };
crtn = CSSM_DeriveKey(ccHandle,
&theirPubKeyData,
CSSM_KEYUSE_ANY,
CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE,
&labelData,
NULL, derivedKey);
CSSM_DeleteContext(ccHandle);
return crtn;
}
#pragma mark ------ Simple encrypt/decrypt routines ------
static uint8 iv[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
static const CSSM_DATA ivCommon = {16, iv};
CSSM_RETURN cdsaEncrypt(
CSSM_CSP_HANDLE cspHandle,
const CSSM_KEY *key,
const CSSM_DATA *plainText,
CSSM_DATA_PTR cipherText)
{
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHandle;
CSSM_DATA remData = {0, NULL};
CSSM_SIZE bytesEncrypted;
crtn = genCryptHandle(cspHandle, key, &ivCommon, &ccHandle);
if(crtn) {
return crtn;
}
cipherText->Length = 0;
cipherText->Data = NULL;
crtn = CSSM_EncryptData(ccHandle,
plainText,
1,
cipherText,
1,
&bytesEncrypted,
&remData);
CSSM_DeleteContext(ccHandle);
if(crtn) {
return crtn;
}
cipherText->Length = bytesEncrypted;
if(remData.Length != 0) {
uint32 newLen = cipherText->Length + remData.Length;
cipherText->Data = (uint8 *)appRealloc(cipherText->Data,
newLen,
NULL);
memmove(cipherText->Data + cipherText->Length,
remData.Data, remData.Length);
cipherText->Length = newLen;
appFree(remData.Data, NULL);
}
return CSSM_OK;
}
CSSM_RETURN cdsaDecrypt(
CSSM_CSP_HANDLE cspHandle,
const CSSM_KEY *key,
const CSSM_DATA *cipherText,
CSSM_DATA_PTR plainText)
{
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHandle;
CSSM_DATA remData = {0, NULL};
CSSM_SIZE bytesDecrypted;
crtn = genCryptHandle(cspHandle, key, &ivCommon, &ccHandle);
if(crtn) {
return crtn;
}
plainText->Length = 0;
plainText->Data = NULL;
crtn = CSSM_DecryptData(ccHandle,
cipherText,
1,
plainText,
1,
&bytesDecrypted,
&remData);
CSSM_DeleteContext(ccHandle);
if(crtn) {
return crtn;
}
plainText->Length = bytesDecrypted;
if(remData.Length != 0) {
uint32 newLen = plainText->Length + remData.Length;
plainText->Data = (uint8 *)appRealloc(plainText->Data,
newLen,
NULL);
memmove(plainText->Data + plainText->Length,
remData.Data, remData.Length);
plainText->Length = newLen;
appFree(remData.Data, NULL);
}
return CSSM_OK;
}
#pragma mark ------ Digest routines ------
CSSM_RETURN cdsaDigest(
CSSM_CSP_HANDLE cspHandle, CSSM_ALGORITHMS digestAlg, const CSSM_DATA *inData,
CSSM_DATA_PTR digestData)
{
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHandle;
digestData->Data = NULL;
digestData->Length = 0;
crtn = CSSM_CSP_CreateDigestContext(cspHandle, digestAlg, &ccHandle);
if(crtn) {
return crtn;
}
crtn = CSSM_DigestData(ccHandle, inData, 1, digestData);
CSSM_DeleteContext(ccHandle);
return crtn;
}