#include "common.h"
#include <security_cdsa_utils/cuFileIo.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static void usage(char **argv)
{
printf("usage:\n");
printf(" %s op password keySize inFile outFile [a=algorithm]\n", argv[0]);
printf(" op:\n");
printf(" e encrypt\n");
printf(" d decrypt\n");
printf(" algorithm:\n");
printf(" 4 RC4 (default if no algorithm specified)\n");
printf(" c ASC/ComCryption\n");
printf(" d DES\n");
printf(" a AES\n");
exit(1);
}
static CSSM_RETURN ctDeriveKey(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) {
printError("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) {
printError("CSSM_DeriveKey", crtn);
return crtn;
}
crtn = CSSM_DeleteContext(ccHand);
if(crtn) {
printError("CSSM_DeleteContext", crtn);
}
return crtn;
}
int main(int argc, char **argv)
{
int rtn;
uint32 keySizeInBytes; char *password; char *inFileName; unsigned char *inFile; unsigned inFileSize; char *outFileName; CSSM_CSP_HANDLE cspHand;
CSSM_RETURN crtn;
int doEncrypt = 0;
CSSM_DATA passwordData;
CSSM_DATA saltData = {8, (uint8 *)"someSalt"};
CSSM_DATA inData; CSSM_DATA outData = {0, NULL}; CSSM_CC_HANDLE ccHand; CSSM_DATA remData = {0, NULL};
CSSM_SIZE bytesProcessed;
CSSM_KEY symKey;
char algSpec = '4';
CSSM_ALGORITHMS keyAlg = 0;
CSSM_ALGORITHMS encrAlg = 0;
CSSM_ENCRYPT_MODE encrMode = 0;
CSSM_PADDING padding = 0;
CSSM_DATA initVect = {16, (uint8 *)"someStrangeInitVector"};
CSSM_DATA_PTR initVectPtr = NULL;
if(argc < 6) {
usage(argv);
}
switch(argv[1][0]) {
case 'e':
doEncrypt = 1;
break;
case 'd':
doEncrypt = 0;
break;
default:
usage(argv);
}
password = argv[2];
passwordData.Data = (uint8 *)password;
passwordData.Length = strlen(password);
keySizeInBytes = atoi(argv[3]);
if(keySizeInBytes == 0) {
printf("keySize of 0 illegal\n");
exit(1);
}
inFileName = argv[4];
outFileName = argv[5];
if(argc == 7) {
if(argv[6][0] != 'a') {
usage(argv);
}
algSpec = argv[6][2];
}
switch(algSpec) {
case '4':
keyAlg = CSSM_ALGID_RC4;
encrAlg = CSSM_ALGID_RC4;
encrMode = CSSM_ALGMODE_NONE;
padding = CSSM_PADDING_NONE;
break;
case 'c':
keyAlg = CSSM_ALGID_ASC;
encrAlg = CSSM_ALGID_ASC;
encrMode = CSSM_ALGMODE_NONE;
padding = CSSM_PADDING_NONE;
break;
case 'd':
if(keySizeInBytes != 8) {
printf("***DES must have key size of 8 bytes\n");
exit(1);
}
keyAlg = CSSM_ALGID_DES;
encrAlg = CSSM_ALGID_DES;
encrMode = CSSM_ALGMODE_CBCPadIV8;
padding = CSSM_PADDING_PKCS7;
initVect.Length = 8;
initVectPtr = &initVect;
break;
case 'a':
if(keySizeInBytes != 16) {
printf("***AES must have key size of 8 bytes\n");
exit(1);
}
keyAlg = CSSM_ALGID_AES;
encrAlg = CSSM_ALGID_AES;
encrMode = CSSM_ALGMODE_CBCPadIV8;
padding = CSSM_PADDING_PKCS7;
initVect.Length = 16;
initVectPtr = &initVect;
break;
default:
usage(argv);
}
rtn = readFile(inFileName, &inFile, &inFileSize);
if(rtn) {
printf("Error reading %s: %s\n", inFileName, strerror(rtn));
exit(1);
}
inData.Data = inFile;
inData.Length = inFileSize;
cspHand = cspStartup();
if(cspHand == 0) {
exit(1);
}
crtn = ctDeriveKey(cspHand,
keyAlg,
"someLabel", 9, doEncrypt ? CSSM_KEYUSE_ENCRYPT : CSSM_KEYUSE_DECRYPT,
keySizeInBytes * 8, &passwordData,
&saltData,
1000, &symKey);
if(crtn) {
exit(1);
}
crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
encrAlg, encrMode, NULL, &symKey,
initVectPtr, padding, NULL, &ccHand);
if(crtn) {
printError("CSSM_CSP_CreateSymmetricContext", crtn);
exit(1);
}
if(doEncrypt) {
crtn = CSSM_EncryptDataInit(ccHand);
if(crtn) {
printError("CSSM_EncryptDataInit", crtn);
exit(1);
}
crtn = CSSM_EncryptDataUpdate(ccHand,
&inData,
1,
&outData,
1,
&bytesProcessed);
if(crtn) {
printError("CSSM_EncryptDataUpdate", crtn);
exit(1);
}
outData.Length = bytesProcessed;
crtn = CSSM_EncryptDataFinal(ccHand, &remData);
if(crtn) {
printError("CSSM_EncryptDataFinal", crtn);
exit(1);
}
if(remData.Length != 0) {
uint32 newLen = outData.Length + remData.Length;
outData.Data = (uint8 *)appRealloc(outData.Data,
newLen,
NULL);
memmove(outData.Data + outData.Length, remData.Data, remData.Length);
outData.Length = newLen;
appFree(remData.Data, NULL);
}
}
else {
crtn = CSSM_DecryptDataInit(ccHand);
if(crtn) {
printError("CSSM_DecryptDataInit", crtn);
exit(1);
}
crtn = CSSM_DecryptDataUpdate(ccHand,
&inData,
1,
&outData,
1,
&bytesProcessed);
if(crtn) {
printError("CSSM_DecryptDataUpdate", crtn);
exit(1);
}
outData.Length = bytesProcessed;
crtn = CSSM_DecryptDataFinal(ccHand, &remData);
if(crtn) {
printError("CSSM_DecryptDataFinal", crtn);
exit(1);
}
if(remData.Length != 0) {
uint32 newLen = outData.Length + remData.Length;
outData.Data = (uint8 *)appRealloc(outData.Data,
newLen,
NULL);
memmove(outData.Data + outData.Length, remData.Data, remData.Length);
outData.Length = newLen;
appFree(remData.Data, NULL);
}
}
if(crtn == CSSM_OK) {
rtn = writeFile(outFileName, outData.Data, outData.Length);
if(rtn) {
printf("Error writing %s: %s\n", outFileName, strerror(rtn));
exit(1);
}
else {
printf("SUCCESS: inFile length %u bytes, outFile length %u bytes\n",
inFileSize, (unsigned)outData.Length);
}
}
crtn = CSSM_DeleteContext(ccHand);
if(crtn) {
printError("CSSM_DeleteContext", crtn);
}
crtn = CSSM_FreeKey(cspHand,
NULL, &symKey,
CSSM_FALSE); if(crtn) {
printError("CSSM_FreeKey", crtn);
}
free(inFile);
appFree(outData.Data, NULL);
CSSM_ModuleDetach(cspHand);
return rtn;
}