#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <Security/cssm.h>
#include "cspwrap.h"
#include "common.h"
#include "cspdlTesting.h"
#include <security_cdsa_utils/cuFileIo.h>
#define USAGE_NAME "noUsage"
#define USAGE_NAME_LEN (strlen(USAGE_NAME))
#define LOOPS_DEF 10
#define DSA_PARAM_FILE "dsaParams_512.der"
#define DH_PARAM_FILE "dhParams_512.der"
static void usage(char **argv)
{
printf("usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
printf(" D (CSP/DL; default = bare CSP)\n");
printf(" p(ause on each loop)\n");
printf(" q(uiet)\n");
printf(" v(erbose))\n");
exit(1);
}
static CSSM_DATA dsa512Params;
static CSSM_DATA dh512Params;
typedef struct {
CSSM_ALGORITHMS keyAlg;
CSSM_KEYBLOB_FORMAT pubKeyForm;
CSSM_KEYBLOB_FORMAT privKeyForm;
uint32 keySizeInBits;
CSSM_DATA *algParams; } KeyHashTest;
KeyHashTest KeyHashTestParams[] =
{
{ CSSM_ALGID_RSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, NULL
},
{ CSSM_ALGID_RSA,
CSSM_KEYBLOB_RAW_FORMAT_PKCS1, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, NULL
},
{ CSSM_ALGID_RSA,
CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, NULL
},
{ CSSM_ALGID_RSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS1,
512, NULL
},
{ CSSM_ALGID_RSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8,
512, NULL
},
{ CSSM_ALGID_ECDSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
192, NULL
},
{ CSSM_ALGID_ECDSA,
CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8,
256, NULL
},
{ CSSM_ALGID_ECDSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8,
384, NULL
},
{ CSSM_ALGID_ECDSA,
CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8,
521, NULL
},
{ CSSM_ALGID_DSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, &dsa512Params
},
{ CSSM_ALGID_DSA,
CSSM_KEYBLOB_RAW_FORMAT_FIPS186, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, &dsa512Params
},
{ CSSM_ALGID_DSA,
CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, &dsa512Params
},
{ CSSM_ALGID_DSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_FIPS186,
512, &dsa512Params
},
{ CSSM_ALGID_DSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_OPENSSL,
512, &dsa512Params
},
{ CSSM_ALGID_DSA,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8,
512, &dsa512Params
},
{ CSSM_ALGID_DSA,
CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8,
512, &dsa512Params
},
{ CSSM_ALGID_DH,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, &dh512Params
},
{ CSSM_ALGID_DH,
CSSM_KEYBLOB_RAW_FORMAT_PKCS3, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, &dh512Params
},
{ CSSM_ALGID_DH,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS3,
512, &dh512Params
},
{ CSSM_ALGID_DH,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_PKCS8,
512, &dh512Params
},
{ CSSM_ALGID_DH,
CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_NONE,
512, &dh512Params
},
{ CSSM_ALGID_DH,
CSSM_KEYBLOB_RAW_FORMAT_X509, CSSM_KEYBLOB_RAW_FORMAT_PKCS8,
512, &dh512Params
},
{ CSSM_ALGID_FEE,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
127, NULL
},
{ CSSM_ALGID_FEE,
CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, CSSM_KEYBLOB_RAW_FORMAT_NONE,
128, NULL
},
{ CSSM_ALGID_FEE,
CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING,
161, NULL
},
{ CSSM_ALGID_FEE,
CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING,
CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING,
192, NULL
},
};
#define NUM_TEST_PARAMS\
(sizeof(KeyHashTestParams) / sizeof(KeyHashTestParams[0]))
static void dumpBuf(uint8 *buf,
unsigned len)
{
unsigned i;
printf(" ");
for(i=0; i<len; i++) {
printf("%02X ", buf[i]);
if((i % 24) == 23) {
printf("\n ");
}
}
printf("\n");
}
const char *formStr(CSSM_KEYBLOB_FORMAT form)
{
switch(form) {
case CSSM_KEYBLOB_RAW_FORMAT_NONE: return "NONE";
case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: return "PKCS1";
case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: return "PKCS3";
case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: return "FIPS186";
case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: return "PKCS8";
case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: return "OCTET_STRING";
case CSSM_KEYBLOB_RAW_FORMAT_OTHER: return "OTHER";
case CSSM_KEYBLOB_RAW_FORMAT_X509: return "X509";
case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: return "OPENSSH";
case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: return "OPENSSL";
default:
printf("**BRRZAP! formStr needs work\n");
exit(1);
}
}
const char *algStr(CSSM_ALGORITHMS alg)
{
switch(alg) {
case CSSM_ALGID_RSA: return "RSA";
case CSSM_ALGID_DSA: return "DSA";
case CSSM_ALGID_DH: return "DH";
case CSSM_ALGID_FEE: return "FEE";
case CSSM_ALGID_ECDSA: return "ECDSA";
default:
printf("**BRRZAP! algStr needs work\n");
exit(1);
}
}
static void showTestParams(KeyHashTest *testParam)
{
printf("alg %s pubForm %s privForm %s\n",
algStr(testParam->keyAlg),
formStr(testParam->pubKeyForm),
formStr(testParam->privKeyForm));
}
static CSSM_RETURN genKeyPair(
CSSM_CSP_HANDLE cspHand,
CSSM_ALGORITHMS keyAlg,
uint32 keySize, CSSM_KEY_PTR pubKey,
CSSM_KEYBLOB_FORMAT pubFormat,
CSSM_KEY_PTR privKey,
CSSM_KEYBLOB_FORMAT privFormat,
const CSSM_DATA *inParams) {
CSSM_RETURN crtn;
CSSM_CC_HANDLE ccHand;
CSSM_DATA keyLabelData;
CSSM_RETURN ocrtn = CSSM_OK;
keyLabelData.Data = (uint8 *)USAGE_NAME,
keyLabelData.Length = USAGE_NAME_LEN;
memset(pubKey, 0, sizeof(CSSM_KEY));
memset(privKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
keyAlg,
keySize,
NULL, NULL, NULL, NULL, inParams, &ccHand);
if(crtn) {
printError("CSSM_CSP_CreateKeyGenContext", crtn);
return crtn;
}
if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) {
crtn = AddContextAttribute(ccHand,
CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT,
sizeof(uint32),
CAT_Uint32,
NULL,
pubFormat);
if(crtn) {
printError("AddContextAttribute("
"CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn);
return crtn;
}
}
if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) {
crtn = AddContextAttribute(ccHand,
CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT,
sizeof(uint32),
CAT_Uint32,
NULL,
privFormat);
if(crtn) {
printError("AddContextAttribute("
"CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn);
return crtn;
}
}
CSSM_KEYATTR_FLAGS attrFlags = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
crtn = CSSM_GenerateKeyPair(ccHand,
CSSM_KEYUSE_DERIVE,
attrFlags,
&keyLabelData,
pubKey,
CSSM_KEYUSE_DERIVE,
attrFlags,
&keyLabelData, NULL, privKey);
if(crtn) {
printError("CSSM_GenerateKeyPair", crtn);
ocrtn = crtn;
}
if(ccHand != 0) {
crtn = CSSM_DeleteContext(ccHand);
if(crtn) {
printError("CSSM_DeleteContext", crtn);
ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
}
}
return ocrtn;
}
static int compareKeyHashes(
const CSSM_DATA *key1Hash,
const char *key1Descr,
const CSSM_DATA *key2Hash,
const char *key2Descr,
CSSM_BOOL verbose)
{
if(appCompareCssmData(key1Hash, key2Hash)) {
return 0;
}
printf("***Key Digest miscompare (%s,%s)***\n", key1Descr, key2Descr);
if(!verbose) {
printf("...%s hash:\n", key1Descr);
dumpBuf(key1Hash->Data, key1Hash->Length);
printf("...%s hash:\n", key2Descr);
dumpBuf(key2Hash->Data, key2Hash->Length);
}
return 1;
}
static int doTest(
CSSM_CSP_HANDLE rawCspHand, CSSM_CSP_HANDLE refCspHand, KeyHashTest *testParam,
CSSM_BOOL verbose,
CSSM_BOOL quiet)
{
CSSM_RETURN crtn;
CSSM_KEY pubKey;
CSSM_KEY privKey;
CSSM_KEY pubKeyRef;
CSSM_KEY privKeyRef;
CSSM_DATA_PTR rawPubHash;
CSSM_DATA_PTR rawPrivHash;
CSSM_DATA_PTR refPubHash;
CSSM_DATA_PTR refPrivHash;
int rtn = 0;
crtn = genKeyPair(rawCspHand,
testParam->keyAlg,
testParam->keySizeInBits,
&pubKey,
testParam->pubKeyForm,
&privKey,
testParam->privKeyForm,
testParam->algParams);
if(crtn) {
return testError(quiet);
}
crtn = cspRawKeyToRef(refCspHand, &pubKey, &pubKeyRef);
if(crtn) {
return testError(quiet);
}
crtn = cspRawKeyToRef(refCspHand, &privKey, &privKeyRef);
if(crtn) {
return testError(quiet);
}
crtn = cspKeyHash(rawCspHand, &pubKey, &rawPubHash);
if(crtn) {
return testError(quiet);
}
crtn = cspKeyHash(rawCspHand, &privKey, &rawPrivHash);
if(crtn) {
return testError(quiet);
}
crtn = cspKeyHash(refCspHand, &pubKeyRef, &refPubHash);
if(crtn) {
return testError(quiet);
}
crtn = cspKeyHash(refCspHand, &privKeyRef, &refPrivHash);
if(crtn) {
return testError(quiet);
}
if(verbose) {
printf("...raw pub key hash:\n");
dumpBuf(rawPubHash->Data, rawPubHash->Length);
printf("...ref pub key hash:\n");
dumpBuf(refPubHash->Data, refPubHash->Length);
printf("...raw priv key hash:\n");
dumpBuf(rawPrivHash->Data, rawPrivHash->Length);
printf("...ref priv key hash:\n");
dumpBuf(refPrivHash->Data, refPrivHash->Length);
}
rtn += compareKeyHashes(rawPubHash, "Raw public",
refPubHash, "Ref public", verbose);
rtn += compareKeyHashes(rawPrivHash, "Raw private",
refPrivHash, "Ref private", verbose);
rtn += compareKeyHashes(refPubHash, "Ref public",
refPrivHash, "Ref private", verbose);
if(rtn) {
rtn = testError(quiet);
}
cspFreeKey(rawCspHand, &pubKey);
cspFreeKey(rawCspHand, &privKey);
cspFreeKey(refCspHand, &pubKeyRef);
cspFreeKey(refCspHand, &privKeyRef);
appFreeCssmData(rawPubHash, CSSM_TRUE);
appFreeCssmData(rawPrivHash, CSSM_TRUE);
appFreeCssmData(refPubHash, CSSM_TRUE);
appFreeCssmData(refPrivHash, CSSM_TRUE);
return rtn;
}
int main(int argc, char **argv)
{
int arg;
char *argp;
unsigned loop;
CSSM_CSP_HANDLE rawCspHand; CSSM_CSP_HANDLE refCspHand; int rtn = 0;
int i;
unsigned len;
unsigned loops = LOOPS_DEF;
CSSM_BOOL verbose = CSSM_FALSE;
CSSM_BOOL quiet = CSSM_FALSE;
CSSM_BOOL bareCsp = CSSM_TRUE;
CSSM_BOOL doPause = CSSM_FALSE;
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'l':
loops = atoi(&argp[2]);
break;
case 'D':
bareCsp = CSSM_FALSE;
break;
case 'p':
doPause = CSSM_TRUE;
break;
case 'v':
verbose = CSSM_TRUE;
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 'h':
default:
usage(argv);
}
}
rtn = readFile(DSA_PARAM_FILE, &dsa512Params.Data, &len);
if(rtn) {
printf("***%s file missing. Aborting.\n", DSA_PARAM_FILE);
exit(1);
}
dsa512Params.Length = len;
rtn = readFile(DH_PARAM_FILE, &dh512Params.Data, &len);
if(rtn) {
printf("***%s file missing. Aborting.\n", DH_PARAM_FILE);
exit(1);
}
dh512Params.Length = len;
printf("Starting keyHashAsym; args: ");
for(i=1; i<argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
refCspHand = cspDlDbStartup(bareCsp, NULL);
if(refCspHand == 0) {
exit(1);
}
if(bareCsp) {
rawCspHand = refCspHand;
}
else {
rawCspHand = cspDlDbStartup(CSSM_TRUE, NULL);
if(rawCspHand == 0) {
exit(1);
}
}
for(loop=1; ; loop++) {
if(!quiet) {
printf("...loop %d\n", loop);
}
for(unsigned testNum=0; testNum<NUM_TEST_PARAMS; testNum++) {
KeyHashTest *testParams = &KeyHashTestParams[testNum];
if(!quiet) {
printf("..."); showTestParams(testParams);
}
rtn = doTest(rawCspHand, refCspHand, testParams, verbose, quiet);
if(rtn) {
goto done;
}
if(doPause) {
fpurge(stdin);
printf("Hit CR to proceed: ");
getchar();
}
}
if(loops && (loop == loops)) {
break;
}
}
done:
if((rtn == 0) && !quiet) {
printf("...%s complete\n", argv[0]);
}
return rtn;
}