#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <Security/cssm.h>
#include <Security/cssmapple.h>
#include "cspwrap.h"
#include "common.h"
#include "bsafeUtils.h"
#include "cspdlTesting.h"
#include <string.h>
#define OLOOPS_DEF 10
#define ILOOPS_DEF 10
#define MAX_TEXT_SIZE 1024
#define LOOP_NOTIFY 20
#define ALG_RSA_MD5 1
#define ALG_RSA_SHA1 2
#define ALG_RSA_MD2 3
#define ALG_FEE_MD5 4
#define ALG_FEE_SHA1 5
#define ALG_ECDSA_SHA1 6
#define ALG_DSA_SHA1 7
#define ALG_ANSI_ECDSA_SHA1 8
#define ALG_ECDSA_SHA256 9
#define ALG_ECDSA_SHA384 10
#define ALG_ECDSA_SHA512 11
#define ALG_FIRST ALG_RSA_MD5
#define ALG_LAST ALG_ECDSA_SHA512
static void usage(char **argv)
{
printf("usage: %s [options]\n", argv[0]);
printf(" Options:\n");
printf(" a=alg (5=RSA/MD5; 2=RSA/MD2; R=RSA/SHA1; d=DSA/SHA1; f=FEE/MD5; F=FEE/SHA1; \n");
printf(" e=ECDSA/SHA1; E=ANSI_ECDSA/SHA1; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=all)\n");
printf(" l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF);
printf(" i=innerLoops (default=%d)\n", ILOOPS_DEF);
printf(" k=keySizeInBits; default is random\n");
printf(" p=pauseInterval (default=0, no pause)\n");
printf(" s(mall keys)\n");
printf(" D (CSP/DL; default = bare CSP)\n");
printf(" v(erbose)\n");
printf(" q(uiet)\n");
printf(" h(elp)\n");
exit(1);
}
int main(int argc, char **argv)
{
int arg;
char *argp;
unsigned oloop;
unsigned iloop;
CSSM_DATA ptext = {0, NULL};
CSSM_CSP_HANDLE cspHand;
int i;
int rtn = 0;
uint32 keySizeInBits = 0;
CSSM_KEY pubKey;
CSSM_KEY privKey;
CSSM_DATA sig = {0, NULL};
CSSM_DATA digest = {0, NULL};
CSSM_RETURN crtn;
unsigned currAlg;
CSSM_ALGORITHMS digestAlg;
CSSM_ALGORITHMS rawSigAlg;
CSSM_ALGORITHMS sigAlg;
CSSM_ALGORITHMS keyGenAlg;
const char *sigAlgStr;
CSSM_BOOL keySizeSpec = CSSM_FALSE;
unsigned oloops = OLOOPS_DEF;
unsigned iloops = ILOOPS_DEF;
CSSM_BOOL verbose = CSSM_FALSE;
CSSM_BOOL quiet = CSSM_FALSE;
unsigned pauseInterval = 0;
CSSM_BOOL bareCsp = CSSM_TRUE;
unsigned minAlg = ALG_FIRST;
uint32 maxAlg = ALG_LAST;
CSSM_BOOL smallKeys = CSSM_FALSE;
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'a':
switch(argp[2]) {
case 'f':
minAlg = maxAlg = ALG_FEE_MD5;
break;
case 'F':
minAlg = maxAlg = ALG_FEE_SHA1;
break;
case 'e':
minAlg = maxAlg = ALG_ECDSA_SHA1;
break;
case '5':
minAlg = maxAlg = ALG_RSA_MD5;
break;
case '2':
minAlg = maxAlg = ALG_RSA_MD2;
break;
case 'R':
minAlg = maxAlg = ALG_RSA_SHA1;
break;
case 'd':
minAlg = maxAlg = ALG_DSA_SHA1;
break;
case 'E':
minAlg = maxAlg = ALG_ANSI_ECDSA_SHA1;
break;
case '7':
minAlg = maxAlg = ALG_ECDSA_SHA256;
break;
case '8':
minAlg = maxAlg = ALG_ECDSA_SHA384;
break;
case '9':
minAlg = maxAlg = ALG_ECDSA_SHA512;
break;
default:
usage(argv);
}
break;
case 'l':
oloops = atoi(&argp[2]);
break;
case 'i':
iloops = atoi(&argp[2]);
break;
case 'k':
keySizeInBits = atoi(&argp[2]);
keySizeSpec = CSSM_TRUE;
break;
case 'v':
verbose = CSSM_TRUE;
break;
case 'D':
bareCsp = CSSM_FALSE;
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 's':
smallKeys = CSSM_TRUE;
break;
case 'p':
pauseInterval = atoi(&argp[2]);;
break;
case 'h':
default:
usage(argv);
}
}
ptext.Data = (uint8 *)CSSM_MALLOC(MAX_TEXT_SIZE);
if(ptext.Data == NULL) {
printf("Insufficient heap space\n");
exit(1);
}
printf("Starting rawSig; args: ");
for(i=1; i<argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
cspHand = cspDlDbStartup(bareCsp, NULL);
if(cspHand == 0) {
exit(1);
}
if(pauseInterval) {
fpurge(stdin);
printf("Top of test; hit CR to proceed: ");
getchar();
}
for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
switch(currAlg) {
case ALG_RSA_MD5:
digestAlg = CSSM_ALGID_MD5;
rawSigAlg = CSSM_ALGID_RSA;
sigAlg = CSSM_ALGID_MD5WithRSA;
keyGenAlg = CSSM_ALGID_RSA;
sigAlgStr = "MD5WithRSA";
break;
case ALG_RSA_MD2:
digestAlg = CSSM_ALGID_MD2;
rawSigAlg = CSSM_ALGID_RSA;
sigAlg = CSSM_ALGID_MD2WithRSA;
keyGenAlg = CSSM_ALGID_RSA;
sigAlgStr = "MD2WithRSA";
break;
case ALG_RSA_SHA1:
digestAlg = CSSM_ALGID_SHA1;
rawSigAlg = CSSM_ALGID_RSA;
sigAlg = CSSM_ALGID_SHA1WithRSA;
keyGenAlg = CSSM_ALGID_RSA;
sigAlgStr = "SHA1WithRSA";
break;
case ALG_DSA_SHA1:
digestAlg = CSSM_ALGID_SHA1;
rawSigAlg = CSSM_ALGID_DSA;
sigAlg = CSSM_ALGID_SHA1WithDSA;
keyGenAlg = CSSM_ALGID_DSA;
sigAlgStr = "SHA1WithDSA";
break;
case ALG_FEE_MD5:
digestAlg = CSSM_ALGID_MD5;
rawSigAlg = CSSM_ALGID_FEE;
sigAlg = CSSM_ALGID_FEE_MD5;
keyGenAlg = CSSM_ALGID_FEE;
sigAlgStr = "MD5WithFEE";
break;
case ALG_FEE_SHA1:
digestAlg = CSSM_ALGID_SHA1;
rawSigAlg = CSSM_ALGID_FEE;
sigAlg = CSSM_ALGID_FEE_SHA1;
keyGenAlg = CSSM_ALGID_FEE;
sigAlgStr = "SHA1WithFEE";
break;
case ALG_ECDSA_SHA1:
digestAlg = CSSM_ALGID_SHA1;
rawSigAlg = CSSM_ALGID_ECDSA;
sigAlg = CSSM_ALGID_SHA1WithECDSA;
keyGenAlg = CSSM_ALGID_FEE;
sigAlgStr = "SHA1WithECDSA";
break;
case ALG_ANSI_ECDSA_SHA1:
digestAlg = CSSM_ALGID_SHA1;
rawSigAlg = CSSM_ALGID_ECDSA;
sigAlg = CSSM_ALGID_SHA1WithECDSA;
keyGenAlg = CSSM_ALGID_ECDSA;
sigAlgStr = "ANSI ECDSA";
break;
case ALG_ECDSA_SHA256:
digestAlg = CSSM_ALGID_SHA256;
rawSigAlg = CSSM_ALGID_ECDSA;
sigAlg = CSSM_ALGID_SHA256WithECDSA;
keyGenAlg = CSSM_ALGID_ECDSA;
sigAlgStr = "ECDSA/SHA256";
break;
case ALG_ECDSA_SHA384:
digestAlg = CSSM_ALGID_SHA384;
rawSigAlg = CSSM_ALGID_ECDSA;
sigAlg = CSSM_ALGID_SHA384WithECDSA;
keyGenAlg = CSSM_ALGID_ECDSA;
sigAlgStr = "ECDSA/SHA384";
break;
case ALG_ECDSA_SHA512:
digestAlg = CSSM_ALGID_SHA512;
rawSigAlg = CSSM_ALGID_ECDSA;
sigAlg = CSSM_ALGID_SHA512WithECDSA;
keyGenAlg = CSSM_ALGID_ECDSA;
sigAlgStr = "ECDSA/SHA512";
break;
default:
printf("BRRZAP!\n");
exit(1);
}
if(!quiet) {
printf("Testing alg %s...\n", sigAlgStr);
}
for(oloop=0; ; oloop++) {
if(smallKeys) {
keySizeInBits = cspDefaultKeySize(keyGenAlg);
}
else if(!keySizeSpec) {
keySizeInBits = randKeySizeBits(rawSigAlg, OT_Sign);
}
if(!quiet) {
if(verbose || ((oloop % LOOP_NOTIFY) == 0)) {
printf(" ...oloop %d keySize %u\n", oloop, (unsigned)keySizeInBits);
}
}
if(currAlg == ALG_DSA_SHA1) {
CSSM_BOOL doGenParams;
if(bareCsp || CSPDL_DSA_GEN_PARAMS) {
doGenParams = CSSM_TRUE;
}
else {
doGenParams = CSSM_FALSE;
}
crtn = cspGenDSAKeyPair(cspHand,
"foo",
3,
keySizeInBits,
&pubKey,
CSSM_TRUE, CSSM_KEYUSE_VERIFY,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&privKey,
CSSM_TRUE,
CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
doGenParams, NULL); }
else {
crtn = cspGenKeyPair(cspHand,
keyGenAlg,
"foo",
3,
keySizeInBits,
&pubKey,
CSSM_TRUE, CSSM_KEYUSE_VERIFY,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&privKey,
CSSM_TRUE,
CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
CSSM_FALSE); }
if(crtn) {
return testError(quiet);
}
for(iloop=0; iloop<iloops; iloop++) {
CSSM_CC_HANDLE sigHand;
simpleGenData(&ptext, 1, MAX_TEXT_SIZE);
if(!quiet) {
if(verbose || ((iloop % LOOP_NOTIFY) == 0)) {
printf(" ...iloop %d text size %lu\n",
iloop, ptext.Length);
}
}
crtn = cspStagedSign(cspHand,
sigAlg,
&privKey,
&ptext,
CSSM_TRUE, &sig);
if(crtn && testError(quiet)) {
goto abort;
}
crtn = cspStagedDigest(cspHand,
digestAlg,
CSSM_FALSE, CSSM_TRUE, &ptext,
&digest);
if(crtn && testError(quiet)) {
goto abort;
}
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
rawSigAlg,
NULL, &pubKey,
&sigHand);
if(crtn) {
printError("CSSM_CSP_CreateSignatureContext (1)", crtn);
return crtn;
}
crtn = CSSM_VerifyData(sigHand,
&digest,
1,
digestAlg,
&sig);
if(crtn) {
printError("CSSM_VerifyData(raw)", crtn);
if(testError(quiet)) {
goto abort;
}
}
appFreeCssmData(&sig, CSSM_FALSE);
CSSM_DeleteContext(sigHand);
crtn = CSSM_CSP_CreateSignatureContext(cspHand,
rawSigAlg,
NULL, &privKey,
&sigHand);
if(crtn) {
printError("CSSM_CSP_CreateSignatureContext (2)", crtn);
return crtn;
}
crtn = CSSM_SignData(sigHand,
&digest,
1,
digestAlg,
&sig);
if(crtn) {
printError("CSSM_SignData(raw)", crtn);
if(testError(quiet)) {
goto abort;
}
}
crtn = cspStagedSigVerify(cspHand,
sigAlg,
&pubKey,
&ptext,
&sig,
CSSM_TRUE, CSSM_OK);
if(crtn && testError(quiet)) {
goto abort;
}
appFreeCssmData(&sig, CSSM_FALSE);
appFreeCssmData(&digest, CSSM_FALSE);
CSSM_DeleteContext(sigHand);
}
cspFreeKey(cspHand, &pubKey);
cspFreeKey(cspHand, &privKey);
if(oloops && (oloop == oloops)) {
break;
}
if(pauseInterval && ((oloop % pauseInterval) == 0)) {
fpurge(stdin);
printf("hit CR to proceed: ");
getchar();
}
}
}
abort:
cspShutdown(cspHand, bareCsp);
if(pauseInterval) {
fpurge(stdin);
printf("ModuleDetach/Unload complete; hit CR to exit: ");
getchar();
}
if((rtn == 0) && !quiet) {
printf("%s test complete\n", argv[0]);
}
CSSM_FREE(ptext.Data);
return rtn;
}