#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <Security/cssm.h>
#include <Security/cssmapple.h>
#include "cspwrap.h"
#include <security_cdsa_utils/cuFileIo.h>
#include "common.h"
#include <string.h>
#include "cspdlTesting.h"
#include <unistd.h>
#define LOOPS_DEF 200
#define PTEXT_SIZE_DEF 256
#define BLOCK_SIZE_MAX 32
typedef enum {
ALG_ASC = 0,
ALG_DES,
ALG_RC2,
ALG_RC4,
ALG_RC5,
ALG_3DES,
ALG_AES,
ALG_AES192,
ALG_AES256,
ALG_BFISH,
ALG_CAST
} SymAlg;
#define ALG_FIRST ALG_ASC
#define ALG_LAST ALG_CAST
static void usage(char **argv)
{
printf("usage: %s e|d dirName [options]\n", argv[0]);
printf(" e=encrypt, d=decrypt; blobs read/written in dirName\n");
printf(" Options:\n");
printf(" a=algorithm (d=DES; 3=3DES3; 2=RC2; 4=RC4; 5=RC5; a=AES; b=Blowfish; \n");
printf(" c=CAST; s=ASC, default=all)\n");
printf(" p=ptextSize (default=%d)\n", PTEXT_SIZE_DEF);
printf(" D (CSP/DL; default = bare CSP)\n");
printf(" v(erbose)\n");
printf(" q(uiet)\n");
printf(" h(elp)\n");
exit(1);
}
typedef struct {
SymAlg alg;
const char *algStr;
CSSM_ALGORITHMS cssmAlg;
CSSM_ENCRYPT_MODE mode;
CSSM_PADDING padding;
CSSM_SIZE keySizeBits;
CSSM_SIZE ivLen; } SymAlgParams;
static const SymAlgParams symAlgParams[] =
{
{ ALG_ASC, "ASC", CSSM_ALGID_ASC, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE,
CSP_ASC_KEY_SIZE_DEFAULT, 0 },
{ ALG_DES, "DES", CSSM_ALGID_DES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
CSP_DES_KEY_SIZE_DEFAULT, 8 },
{ ALG_RC2, "RC2", CSSM_ALGID_RC2, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
CSP_RC2_KEY_SIZE_DEFAULT, 8 },
{ ALG_RC4, "RC4", CSSM_ALGID_RC4, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE,
CSP_RC4_KEY_SIZE_DEFAULT, 0 },
{ ALG_RC5, "RC5", CSSM_ALGID_RC5, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
CSP_RC5_KEY_SIZE_DEFAULT, 8 },
{ ALG_3DES, "3DES", CSSM_ALGID_3DES_3KEY_EDE, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
CSP_DES3_KEY_SIZE_DEFAULT, 8 },
{ ALG_AES, "AES", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
CSP_AES_KEY_SIZE_DEFAULT, 16 },
{ ALG_AES192, "AES192", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
192, 24 },
{ ALG_AES256, "AES256", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
256, 32 },
{ ALG_BFISH, "Blowfish", CSSM_ALGID_BLOWFISH, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
CSP_BFISH_KEY_SIZE_DEFAULT, 8 },
{ ALG_CAST, "CAST", CSSM_ALGID_CAST, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
CSP_CAST_KEY_SIZE_DEFAULT, 8 }
};
static void genFileNames(
const char *algStr,
char *keyFile,
char *ptextFile,
char *ctextFile,
char *ivFile)
{
sprintf(keyFile, "key_%s", algStr);
sprintf(ptextFile, "ptext_%s", algStr);
sprintf(ctextFile, "ctext_%s", algStr);
sprintf(ivFile, "iv_%s", algStr);
}
static int doEncrypt(
CSSM_CSP_HANDLE cspHand,
const SymAlgParams *algParams,
CSSM_DATA *ptext, CSSM_BOOL quiet,
CSSM_BOOL verbose)
{
CSSM_KEY_PTR symKey = NULL;
CSSM_KEY rawKey;
CSSM_RETURN crtn;
CSSM_DATA ctext = {0, NULL};
uint8 iv[BLOCK_SIZE_MAX];
CSSM_DATA ivd = {BLOCK_SIZE_MAX, iv};
CSSM_DATA *ivp = NULL;
uint32 blockSize = 0;
char keyFile[FILENAME_MAX];
char ptextFile[FILENAME_MAX];
char ctextFile[FILENAME_MAX];
char ivFile[FILENAME_MAX];
if(!quiet) {
printf("...encrypting, alg %s\n", algParams->algStr);
}
symKey = cspGenSymKey(cspHand, algParams->cssmAlg,
"noLabel", 7,
CSSM_KEYUSE_ANY, algParams->keySizeBits, CSSM_TRUE);
if(symKey == NULL) {
printf("***Error generating key for alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
crtn = cspRefKeyToRaw(cspHand, symKey, &rawKey);
if(crtn) {
printf("***Error generating raw key for alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
appGetRandomBytes(ptext->Data, (unsigned)ptext->Length);
if(algParams->ivLen > 16) {
blockSize = algParams->ivLen;
}
if(algParams->ivLen) {
appGetRandomBytes(iv, algParams->ivLen);
ivd.Length = algParams->ivLen;
ivp = &ivd;
}
crtn = cspStagedEncrypt(cspHand,
algParams->cssmAlg, algParams->mode, algParams->padding,
symKey, NULL,
0, blockSize, 0,
ivp, ptext,
&ctext,
CSSM_FALSE);
if(crtn) {
printf("***Error encrypting for alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
genFileNames(algParams->algStr, keyFile, ptextFile, ctextFile, ivFile);
if(writeFile(keyFile, rawKey.KeyData.Data, (unsigned)rawKey.KeyData.Length) ||
writeFile(ptextFile, ptext->Data, (unsigned)ptext->Length) ||
writeFile(ctextFile, ctext.Data, (unsigned)ctext.Length)) {
printf("***Error writing result of alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
if(ivp != NULL) {
if(writeFile(ivFile, ivp->Data, (unsigned)ivp->Length)) {
printf("***Error writing IV for alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
}
CSSM_FreeKey(cspHand, NULL, symKey, CSSM_FALSE);
CSSM_FreeKey(cspHand, NULL, &rawKey, CSSM_FALSE);
CSSM_FREE(ctext.Data);
return 0;
}
static int doDecrypt(
CSSM_CSP_HANDLE cspHand,
const SymAlgParams *algParams,
CSSM_BOOL quiet,
CSSM_BOOL verbose)
{
CSSM_KEY symKey;
uint8 *symKeyBits;
unsigned symKeyLen; CSSM_DATA symKeyData;
CSSM_RETURN crtn;
uint8 *ctextChars;
unsigned ctextLen = 0;
CSSM_DATA ctext;
CSSM_DATA rptext = {0, NULL}; uint8 *refPTextChars;
unsigned refPtextLen;
CSSM_DATA refPtext = {0, NULL}; uint8 *iv = NULL;
unsigned ivLen;
CSSM_DATA ivd = {BLOCK_SIZE_MAX, iv};
CSSM_DATA *ivp = NULL;
uint32 blockSize = 0;
char keyFile[FILENAME_MAX];
char ptextFile[FILENAME_MAX];
char ctextFile[FILENAME_MAX];
char ivFile[FILENAME_MAX];
if(!quiet) {
printf("...decrypting, alg %s\n", algParams->algStr);
}
if(algParams->ivLen > 16) {
blockSize = algParams->ivLen;
}
if(algParams->ivLen) {
ivp = &ivd;
ivd.Length = algParams->ivLen;
}
genFileNames(algParams->algStr, keyFile, ptextFile, ctextFile, ivFile);
if(readFile(keyFile, &symKeyBits, &symKeyLen) ||
readFile(ptextFile, &refPTextChars, &refPtextLen) ||
readFile(ctextFile, &ctextChars, &ctextLen)) {
printf("***Error reading reference blobs for alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
if(ivp != NULL) {
if(readFile(ivFile, &iv, &ivLen)) {
printf("***Error writing IV for alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
if(ivLen != algParams->ivLen) {
printf("***Unexpected IV length: expect %u found %u\n",
(unsigned)algParams->ivLen, (unsigned)ivLen);
if(testError(quiet)) {
return 1;
}
}
ivd.Data = iv;
}
ctext.Data = ctextChars;
ctext.Length = ctextLen;
refPtext.Data = refPTextChars;
refPtext.Length = refPtextLen;
symKeyData.Data = symKeyBits;
symKeyData.Length = symKeyLen;
crtn = cspGenSymKeyWithBits(cspHand, algParams->cssmAlg,
CSSM_KEYUSE_ANY, &symKeyData, symKeyLen, &symKey);
if(crtn) {
printf("***Error creating key for alg %s keySize %u\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
crtn = cspStagedDecrypt(cspHand,
algParams->cssmAlg, algParams->mode, algParams->padding,
&symKey, NULL,
0, blockSize, 0,
ivp, &ctext,
&rptext,
CSSM_FALSE);
if(crtn) {
printf("***Error decrypting for alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
if(!appCompareCssmData(&rptext, &refPtext)) {
printf("***DATA MISCOMPARE AFTER DECRYPT alg %s size %u bits\n",
algParams->algStr, (unsigned)algParams->keySizeBits);
return testError(quiet);
}
CSSM_FreeKey(cspHand, NULL, &symKey, CSSM_FALSE);
free(symKeyBits); free(refPTextChars);
free(ctextChars);
CSSM_FREE(rptext.Data); if(iv) {
free(iv);
}
return 0;
}
int main(int argc, char **argv)
{
int arg;
char *argp;
CSSM_DATA ptext;
CSSM_CSP_HANDLE cspHand;
unsigned currAlg; int rtn = 0;
unsigned minAlg = ALG_FIRST;
unsigned maxAlg = ALG_LAST;
CSSM_BOOL verbose = CSSM_FALSE;
CSSM_BOOL quiet = CSSM_FALSE;
CSSM_BOOL bareCsp = CSSM_TRUE;
bool encrypt = false;
unsigned ptextSize = PTEXT_SIZE_DEF;
char *dirName;
if(argc < 3) {
usage(argv);
}
switch(argv[1][0]) {
case 'e':
encrypt = true;
break;
case 'd':
encrypt = false;
break;
default:
usage(argv);
}
dirName = argv[2];
for(arg=3; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'a':
if(argp[1] != '=') {
usage(argv);
}
switch(argp[2]) {
case 's':
minAlg = maxAlg = ALG_ASC;
break;
case 'd':
minAlg = maxAlg = ALG_DES;
break;
case '3':
minAlg = maxAlg = ALG_3DES;
break;
case '2':
minAlg = maxAlg = ALG_RC2;
break;
case '4':
minAlg = maxAlg = ALG_RC4;
break;
case '5':
minAlg = maxAlg = ALG_RC5;
break;
case 'a':
minAlg = maxAlg = ALG_AES;
break;
case 'b':
minAlg = maxAlg = ALG_BFISH;
break;
case 'c':
minAlg = maxAlg = ALG_CAST;
break;
default:
usage(argv);
}
break;
case 'v':
verbose = CSSM_TRUE;
break;
case 'D':
bareCsp = CSSM_FALSE;
break;
case 'p':
ptextSize = atoi(&argp[2]);
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 'h':
default:
usage(argv);
}
}
ptext.Data = (uint8 *)CSSM_MALLOC(ptextSize);
if(ptext.Data == NULL) {
printf("Insufficient heap space\n");
exit(1);
}
ptext.Length = ptextSize;
testStartBanner("symReference", argc, argv);
cspHand = cspDlDbStartup(bareCsp, NULL);
if(cspHand == 0) {
exit(1);
}
if(chdir(dirName)) {
perror(dirName);
printf("Error accessing directory %s. Aborting.\n", dirName);
exit(1);
}
for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
const SymAlgParams *algParams = &symAlgParams[currAlg];
if(encrypt) {
rtn = doEncrypt(cspHand, algParams, &ptext, quiet, verbose);
}
else {
rtn = doDecrypt(cspHand, algParams, quiet, verbose);
}
if(rtn) {
break;
}
}
cspShutdown(cspHand, bareCsp);
if((rtn == 0) && !quiet) {
printf("%s test complete\n", argv[0]);
}
CSSM_FREE(ptext.Data);
return rtn;
}