#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <Security/cssm.h>
#include "cspwrap.h"
#include "common.h"
#include "cspdlTesting.h"
#define WRAP_USAGE_ANY 0
#define WRAP_WITH_RSA 1
#define WRAP_WITH_RC4 1
#define PKCS7_FORMAT_ENABLE 1 // for wrapping symmetric keys
#define PKCS8_FORMAT_ENABLE 1 // for wrapping private keys
#define ENCR_LABEL "encrKey"
#define ENCR_LABEL_LEN (strlen(ENCR_LABEL))
#define WRAP_LABEL "wrapKey"
#define WRAP_LABEL_LEN (strlen(WRAP_LABEL))
#define LOOPS_DEF 10
#define MAX_PTEXT_SIZE 100
#define LOOP_PAUSE 100
#define MAX_DESC_DATA_SIZE 16
typedef unsigned PrivAlg;
enum {
ALG_DES = 1,
ALG_3DES,
ALG_RC2,
ALG_RC4,
ALG_RSA,
ALG_NULL,
ALG_FEEDEXP,
ALG_ASC,
ALG_AES
};
#define ALG_MIN ALG_DES
#define ALG_MAX_WRAP ALG_AES
#define ALG_MAX_ENCR ALG_AES
static void usage(char **argv)
{
printf("usage: %s [options]\n", argv[0]);
printf(" Options:\n");
printf(" w=wrapAlg (d=DES, 3=3DES, f=FEEDEXP, r=RSA, A=ASC, 4=RC4, "
"a=AES, n=null)\n");
printf(" e=encrAlg (d=DES, 3=3DES, f=FEEDEXP, r=RSA, A=ASC, 4=RC4, "
"a=AES)\n");
printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
printf(" r (ref keys only)\n");
printf(" p(ause every loop)\n");
printf(" D (CSP/DL; default = bare CSP)\n");
printf(" v(erbose)\n");
printf(" k (quick; small keys)\n");
printf(" h(elp)\n");
exit(1);
}
static const char *formatString(CSSM_KEYBLOB_FORMAT format)
{
static char noform[100];
switch(format) {
case CSSM_KEYBLOB_WRAPPED_FORMAT_NONE:
return "NONE (default)";
case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7:
return "PKCS7";
case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8:
return "PKCS8";
case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM:
return "APPLE_CUSTOM";
default:
sprintf(noform, "***UNKNOWN (%u)***", (unsigned)format);
return noform;
}
}
static int vfyWrapHeader(
const CSSM_KEYHEADER *srcHdr,
const CSSM_KEYHEADER *dstHdr,
CSSM_KEYBLOB_TYPE expectBlob,
const char *op,
CSSM_BOOL bareCsp,
int quiet)
{
if(dstHdr->BlobType != expectBlob) {
printf("***%s.BlobType error: expect %u got %u\n",
op, (unsigned)expectBlob, (unsigned)dstHdr->BlobType);
if(testError(quiet)) {
return 1;
}
}
if(srcHdr->KeyClass != dstHdr->KeyClass) {
printf("***%s.KeyClass error: expect %u got %u\n",
op, (unsigned)srcHdr->KeyClass, (unsigned)dstHdr->KeyClass);
if(testError(quiet)) {
return 1;
}
}
if(srcHdr->AlgorithmId != dstHdr->AlgorithmId) {
printf("***%s.AlgorithmId error: expect %u got %u\n",
op, (unsigned)srcHdr->AlgorithmId, (unsigned)dstHdr->AlgorithmId);
if(testError(quiet)) {
return 1;
}
}
if(srcHdr->KeyUsage != dstHdr->KeyUsage) {
printf("***%s.KeyUsage error: expect 0x%x got 0x%x\n",
op, (unsigned)srcHdr->KeyUsage, (unsigned)dstHdr->KeyUsage);
if(testError(quiet)) {
return 1;
}
}
if(bareCsp) {
if(memcmp(&srcHdr->CspId, &dstHdr->CspId, sizeof(CSSM_GUID))) {
printf("***%s.CspId mismatch\n", op);
if(testError(quiet)) {
return 1;
}
}
}
else {
if(!memcmp(&srcHdr->CspId, &dstHdr->CspId, sizeof(CSSM_GUID))) {
printf("***Unexpected %s.CspId compare\n", op);
if(testError(quiet)) {
return 1;
}
}
}
return 0;
}
#define UNWRAPPED_LABEL "unwrapped thing"
#define SHOW_WRAP_FORMAT 0
CSSM_DATA initVector = {16, (uint8 *)"SomeReallyStrangeInitVect"};
static int doTest(CSSM_CSP_HANDLE cspHand,
CSSM_KEY_PTR encrKey,
CSSM_BOOL wrapEncrKey, CSSM_KEY_PTR decrKey, CSSM_KEY_PTR wrappingKey, CSSM_KEY_PTR unwrappingKey,
CSSM_ALGORITHMS wrapAlg,
CSSM_ENCRYPT_MODE wrapMode,
CSSM_KEYBLOB_FORMAT wrapFormat, CSSM_KEYBLOB_FORMAT expectFormat, CSSM_PADDING wrapPad,
uint32 wrapIvSize,
CSSM_ALGORITHMS encrAlg,
CSSM_ENCRYPT_MODE encrMode,
CSSM_PADDING encrPad,
uint32 encrIvSize,
uint32 effectiveKeySizeInBits, CSSM_DATA_PTR ptext,
CSSM_DATA_PTR descData,
CSSM_BOOL quiet,
CSSM_BOOL bareCsp)
{
CSSM_DATA ctext;
CSSM_DATA rptext;
CSSM_KEY wrappedDecrKey;
CSSM_KEY unwrappedDecrKey;
CSSM_KEY wrappedEncrKey;
CSSM_RETURN crtn;
CSSM_KEY_PTR actualEncrKey;
uint32 maxPtextSize = MAX_PTEXT_SIZE;
CSSM_DATA outDescData1 = {0, NULL}; CSSM_DATA outDescData2 = {0, NULL}; CSSM_DATA nullInitVect = {0, NULL}; CSSM_DATA_PTR wrapIvp;
CSSM_DATA_PTR encrIvp;
#if 0
if(encrAlg == CSSM_ALGID_RSA) {
uint32 keySizeBytes = encrKey->KeyHeader.LogicalKeySizeInBits / 8;
maxPtextSize = keySizeBytes - 11;
if(maxPtextSize > MAX_PTEXT_SIZE) {
maxPtextSize = MAX_PTEXT_SIZE;
}
}
else {
maxPtextSize = MAX_PTEXT_SIZE;
}
#endif
simpleGenData(ptext, 1, maxPtextSize);
if(wrapEncrKey) {
CSSM_KEYBLOB_TYPE expectBlob;
if(encrKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) {
crtn = cspWrapKey(cspHand,
encrKey,
NULL, CSSM_ALGID_NONE,
CSSM_ALGMODE_NONE,
wrapFormat,
CSSM_PADDING_NONE,
NULL, descData,
&wrappedEncrKey);
expectBlob = CSSM_KEYBLOB_RAW;
}
else {
crtn = cspUnwrapKey(cspHand,
encrKey,
NULL, CSSM_ALGID_NONE,
CSSM_ALGMODE_NONE,
CSSM_PADDING_NONE,
NULL, &wrappedEncrKey,
&outDescData1,
WRAP_LABEL,
WRAP_LABEL_LEN);
expectBlob = CSSM_KEYBLOB_REFERENCE;
}
if(crtn) {
return testError(quiet);
}
if(vfyWrapHeader(&encrKey->KeyHeader,
&wrappedEncrKey.KeyHeader,
expectBlob,
"wrappedEncrKey",
bareCsp,
quiet)) {
return 1;
}
actualEncrKey = &wrappedEncrKey;
}
else {
actualEncrKey = encrKey;
}
ctext.Data = NULL;
ctext.Length = 0;
if(encrIvSize) {
initVector.Length = encrIvSize;
encrIvp = &initVector;
}
else {
encrIvp = NULL;
}
crtn = cspEncrypt(cspHand,
encrAlg,
encrMode,
encrPad,
actualEncrKey,
NULL, effectiveKeySizeInBits,
0, encrIvp,
ptext,
&ctext,
CSSM_TRUE); if(crtn) {
return testError(quiet);
}
if(expectFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) {
initVector.Length = 8;
}
else {
initVector.Length = wrapIvSize;
}
crtn = cspWrapKey(cspHand,
decrKey,
wrappingKey,
wrapAlg,
wrapMode,
wrapFormat,
wrapPad,
&initVector,
descData,
&wrappedDecrKey);
if(crtn) {
return testError(quiet);
}
if(wrapAlg != CSSM_ALGID_NONE) {
if(wrappedDecrKey.KeyHeader.Format != expectFormat) {
printf("***Wrap format mismatch expect %s got %s\n",
formatString(wrappedDecrKey.KeyHeader.Format),
formatString(expectFormat));
if(testError(quiet)) {
return 1;
}
}
}
if(vfyWrapHeader(&decrKey->KeyHeader,
&wrappedDecrKey.KeyHeader,
(wrapAlg == CSSM_ALGID_NONE) ? CSSM_KEYBLOB_RAW : CSSM_KEYBLOB_WRAPPED,
"wrappedDecrKey",
bareCsp,
quiet)) {
return 1;
}
if(wrappedDecrKey.KeyHeader.Format == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) {
wrapIvp = &nullInitVect;
}
else {
wrapIvp = &initVector;
initVector.Length = wrapIvSize;
}
crtn = cspUnwrapKey(cspHand,
&wrappedDecrKey,
unwrappingKey,
wrapAlg,
wrapMode,
wrapPad,
wrapIvp,
&unwrappedDecrKey,
&outDescData2,
"unwrapped thing",
15);
if(crtn) {
return testError(quiet);
}
if(vfyWrapHeader(&wrappedDecrKey.KeyHeader,
&unwrappedDecrKey.KeyHeader,
CSSM_KEYBLOB_REFERENCE,
"unwrappedDecrKey",
bareCsp,
quiet)) {
return 1;
}
if(descData) {
if(descData->Length != outDescData2.Length) {
printf("descData length mismatch\n");
if(testError(quiet)) {
return 1;
}
}
if(memcmp(descData->Data, outDescData2.Data, outDescData2.Length)) {
printf("***descDatadata miscompare\n");
if(testError(quiet)) {
return 1;
}
}
}
rptext.Data = NULL;
rptext.Length = 0;
if(encrIvSize) {
initVector.Length = encrIvSize;
}
crtn = cspDecrypt(cspHand,
encrAlg,
encrMode,
encrPad,
&unwrappedDecrKey,
NULL, effectiveKeySizeInBits,
0, &initVector,
&ctext,
&rptext,
CSSM_TRUE);
if(crtn) {
return testError(quiet);
}
if(ptext->Length != rptext.Length) {
printf("ptext length mismatch\n");
return testError(quiet);
}
if(memcmp(ptext->Data, rptext.Data, ptext->Length)) {
printf("***data miscompare\n");
return testError(quiet);
}
cspFreeKey(cspHand, &wrappedDecrKey);
cspFreeKey(cspHand, &unwrappedDecrKey);
if(wrapEncrKey) {
cspFreeKey(cspHand, actualEncrKey);
}
CSSM_FREE(ctext.Data);
CSSM_FREE(rptext.Data);
if(outDescData2.Data != NULL) {
CSSM_FREE(outDescData2.Data);
}
if(outDescData1.Data != NULL) {
CSSM_FREE(outDescData1.Data);
}
return 0;
}
typedef enum {
WT_Symmetric,
WT_Asymmetric,
WT_Null
} wrapType;
typedef struct {
uint32 keyGenAlg;
wrapType wtype;
CSSM_ALGORITHMS encrAlg;
CSSM_ENCRYPT_MODE encrMode;
CSSM_PADDING encrPad;
uint32 ivSize; const char *algName;
} AlgInfo;
static void getAlgInfo(PrivAlg privAlg, AlgInfo *algInfo)
{
switch(privAlg) {
case ALG_DES:
algInfo->keyGenAlg = CSSM_ALGID_DES;
algInfo->wtype = WT_Symmetric;
algInfo->encrAlg = CSSM_ALGID_DES;
algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
algInfo->encrPad = CSSM_PADDING_PKCS5;
algInfo->ivSize = 8;
algInfo->algName = "DES";
break;
case ALG_3DES:
algInfo->keyGenAlg = CSSM_ALGID_3DES_3KEY;
algInfo->wtype = WT_Symmetric;
algInfo->encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
algInfo->encrPad = CSSM_PADDING_PKCS5;
algInfo->ivSize = 8;
algInfo->algName = "3DES";
break;
case ALG_FEEDEXP:
algInfo->keyGenAlg = CSSM_ALGID_FEE;
algInfo->wtype = WT_Asymmetric;
algInfo->encrAlg = CSSM_ALGID_FEEDEXP;
algInfo->encrMode = CSSM_ALGMODE_NONE;
algInfo->encrPad = CSSM_PADDING_NONE;
algInfo->ivSize = 0;
algInfo->algName = "FEEDEXP";
break;
case ALG_RSA:
algInfo->keyGenAlg = CSSM_ALGID_RSA;
algInfo->wtype = WT_Asymmetric;
algInfo->encrAlg = CSSM_ALGID_RSA;
algInfo->encrMode = CSSM_ALGMODE_NONE;
algInfo->encrPad = CSSM_PADDING_PKCS1;
algInfo->ivSize = 0;
algInfo->algName = "RSA";
break;
case ALG_ASC:
algInfo->keyGenAlg = CSSM_ALGID_ASC;
algInfo->wtype = WT_Symmetric;
algInfo->encrAlg = CSSM_ALGID_ASC;
algInfo->encrMode = CSSM_ALGMODE_NONE;
algInfo->encrPad = CSSM_PADDING_NONE;
algInfo->ivSize = 0;
algInfo->algName = "ASC";
break;
case ALG_RC2:
algInfo->keyGenAlg = CSSM_ALGID_RC2;
algInfo->wtype = WT_Symmetric;
algInfo->encrAlg = CSSM_ALGID_RC2;
algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
algInfo->encrPad = CSSM_PADDING_PKCS5;
algInfo->ivSize = 8;
algInfo->algName = "RC2";
break;
case ALG_RC4:
algInfo->keyGenAlg = CSSM_ALGID_RC4;
algInfo->wtype = WT_Symmetric;
algInfo->encrAlg = CSSM_ALGID_RC4;
algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
algInfo->encrPad = CSSM_PADDING_PKCS5;
algInfo->ivSize = 0;
algInfo->algName = "RC4";
break;
case ALG_NULL:
algInfo->keyGenAlg = CSSM_ALGID_NONE;
algInfo->wtype = WT_Null;
algInfo->encrAlg = CSSM_ALGID_NONE;
algInfo->encrMode = CSSM_ALGMODE_NONE;
algInfo->encrPad = CSSM_PADDING_NONE;
algInfo->ivSize = 0;
algInfo->algName = "Null";
break;
case ALG_AES:
algInfo->keyGenAlg = CSSM_ALGID_AES;
algInfo->wtype = WT_Symmetric;
algInfo->encrAlg = CSSM_ALGID_AES;
algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
algInfo->encrPad = CSSM_PADDING_PKCS7;
algInfo->ivSize = 16;
algInfo->algName = "AES";
break;
default:
printf("Bogus privAlg\n");
exit(1);
}
return;
}
static PrivAlg letterToAlg(char **argv, char letter)
{
switch(letter) {
case 'd': return ALG_DES;
case '3': return ALG_3DES;
case 'f': return ALG_FEEDEXP;
case 'r': return ALG_RSA;
case 'A': return ALG_ASC;
case '4': return ALG_RC4;
case 'a': return ALG_AES;
default:
usage(argv);
return 0;
}
}
#define SYMM_NULL_WRAP_ENABLE 1
#define AI_WRAP 0
#define AI_ENCR 1
int main(int argc, char **argv)
{
int arg;
char *argp;
unsigned loop;
CSSM_CSP_HANDLE cspHand;
CSSM_RETURN crtn;
CSSM_DATA ptext;
uint32 encrKeySizeBits; uint32 wrapKeySizeBits;
uint32 effectiveKeySizeInBits; int rtn = 0;
uint32 maxRsaKeySize = 1024;
uint32 maxFeeKeySize = 192;
CSSM_KEYBLOB_FORMAT wrapFormat; CSSM_KEYBLOB_FORMAT expectFormat; CSSM_DATA descData = {0, NULL};
CSSM_DATA_PTR descDataP;
CSSM_KEY_PTR encrKeyPtr;
CSSM_KEY_PTR decrKeyPtr;
CSSM_KEY_PTR wrapKeyPtr;
CSSM_KEY_PTR unwrapKeyPtr;
CSSM_KEY pubEncrKey;
CSSM_KEY privEncrKey;
CSSM_KEY pubWrapKey;
CSSM_KEY privWrapKey;
PrivAlg privEncrAlg; PrivAlg privWrapAlg;
AlgInfo algInfo[2];
AlgInfo *encrInfo;
AlgInfo *wrapInfo;
CSSM_BOOL wrapEncrKey = CSSM_FALSE; CSSM_BOOL encrKeyIsRef = CSSM_TRUE;
CSSM_BOOL genSeed; int i;
unsigned loops = LOOPS_DEF;
CSSM_BOOL pause = CSSM_FALSE;
CSSM_BOOL verbose = CSSM_FALSE;
PrivAlg minWrapAlg = ALG_MIN;
PrivAlg maxWrapAlg = ALG_MAX_WRAP;
PrivAlg minEncrAlg = ALG_MIN;
PrivAlg maxEncrAlg = ALG_MAX_ENCR;
CSSM_BOOL quick = CSSM_FALSE;
CSSM_BOOL quiet = CSSM_FALSE;
CSSM_BOOL bareCsp = CSSM_TRUE;
CSSM_BOOL refKeysOnly = CSSM_FALSE;
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'w':
if(argp[2] == 'n') {
minWrapAlg = maxWrapAlg = ALG_NULL;
}
else {
minWrapAlg = maxWrapAlg = letterToAlg(argv, argp[2]);
}
break;
case 'e':
minEncrAlg = maxEncrAlg = letterToAlg(argv, argp[2]);
break;
case 'l':
loops = atoi(&argp[2]);
break;
case 'p':
pause = CSSM_TRUE;
break;
case 'v':
verbose = CSSM_TRUE;
break;
case 'D':
bareCsp = CSSM_FALSE;
#if CSPDL_ALL_KEYS_ARE_REF
refKeysOnly = CSSM_TRUE;
#endif
break;
case 'r':
refKeysOnly = CSSM_TRUE;
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 'k':
quick = CSSM_TRUE;
maxRsaKeySize = 512;
maxFeeKeySize = 127;
break;
default:
usage(argv);
}
}
cspHand = cspDlDbStartup(bareCsp, NULL);
if(cspHand == 0) {
exit(1);
}
wrapInfo = &algInfo[AI_WRAP];
encrInfo = &algInfo[AI_ENCR];
ptext.Data = (uint8 *)CSSM_MALLOC(MAX_PTEXT_SIZE);
descData.Data = (uint8 *)CSSM_MALLOC(MAX_DESC_DATA_SIZE);
printf("Starting wrapTest; args: ");
for(i=1; i<argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
for(loop=0; loop<loops; loop++) {
if(!quiet) {
printf("...loop %d\n", loop);
}
if(pause) {
fpurge(stdin);
printf("Hit CR to proceed: ");
getchar();
}
for(privEncrAlg=minEncrAlg; privEncrAlg<=maxEncrAlg; privEncrAlg++) {
switch(privEncrAlg) {
case ALG_NULL:
continue;
default:
break;
}
getAlgInfo(privEncrAlg, encrInfo);
effectiveKeySizeInBits = randKeySizeBits(encrInfo->keyGenAlg, OT_Encrypt);
if(!refKeysOnly) {
encrKeyIsRef = (loop & 2) ? CSSM_TRUE : CSSM_FALSE;
}
switch(encrInfo->wtype) {
case WT_Symmetric:
encrKeySizeBits = (effectiveKeySizeInBits + 7) & ~7;
if(encrKeySizeBits == effectiveKeySizeInBits) {
effectiveKeySizeInBits = 0;
}
encrKeyPtr = decrKeyPtr = cspGenSymKey(cspHand,
encrInfo->keyGenAlg,
ENCR_LABEL,
ENCR_LABEL_LEN,
CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
encrKeySizeBits,
encrKeyIsRef);
if(encrKeyPtr == NULL) {
rtn = 1;
goto testDone;
}
#if SYMM_NULL_WRAP_ENABLE
if(!refKeysOnly) {
wrapEncrKey = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
}
#else
wrapEncrKey = CSSM_FALSE;
#endif
break;
case WT_Asymmetric:
genSeed = CSSM_FALSE;
switch(privEncrAlg) {
case ALG_RSA:
if(effectiveKeySizeInBits > maxRsaKeySize) {
effectiveKeySizeInBits = maxRsaKeySize;
}
break;
case ALG_FEEDEXP:
if(effectiveKeySizeInBits > maxFeeKeySize) {
effectiveKeySizeInBits = maxFeeKeySize;
}
if(loop & 4) {
genSeed = CSSM_TRUE;
}
break;
default:
break;
}
encrKeySizeBits = effectiveKeySizeInBits;
effectiveKeySizeInBits = 0; crtn = cspGenKeyPair(cspHand,
encrInfo->keyGenAlg,
ENCR_LABEL,
ENCR_LABEL_LEN,
encrKeySizeBits,
&pubEncrKey,
encrKeyIsRef, CSSM_KEYUSE_ENCRYPT,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&privEncrKey,
CSSM_TRUE, CSSM_KEYUSE_DECRYPT,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
genSeed);
if(crtn) {
rtn = testError(quiet);
goto testDone;
}
encrKeyPtr = &pubEncrKey;
decrKeyPtr = &privEncrKey;
if(!refKeysOnly) {
wrapEncrKey = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
}
break;
case WT_Null:
printf("***BRRZAP: can't do null encrypt\n");
goto testDone;
}
if(verbose) {
printf(" ...encrAlg %s wrapEncrKey %d encrKeyIsRef %d size %u "
"bits effectSize %u\n",
encrInfo->algName, (int)wrapEncrKey, (int)encrKeyIsRef,
(unsigned)encrKeySizeBits, (unsigned)effectiveKeySizeInBits);
}
for(privWrapAlg=minWrapAlg; privWrapAlg<=maxWrapAlg; privWrapAlg++) {
if((privWrapAlg == ALG_AES) && (privEncrAlg == ALG_FEEDEXP)) {
continue;
}
getAlgInfo(privWrapAlg, wrapInfo);
switch(wrapInfo->wtype) {
case WT_Symmetric:
wrapKeySizeBits = randKeySizeBits(wrapInfo->keyGenAlg,
OT_KeyExch);
wrapKeySizeBits &= ~7;
wrapKeyPtr = unwrapKeyPtr = cspGenSymKey(cspHand,
wrapInfo->keyGenAlg,
WRAP_LABEL,
WRAP_LABEL_LEN,
WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY :
CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP,
wrapKeySizeBits,
CSSM_TRUE);
if(wrapKeyPtr == NULL) {
rtn = 1;
goto testDone;
}
break;
case WT_Asymmetric:
wrapKeySizeBits = randKeySizeBits(wrapInfo->keyGenAlg,
OT_KeyExch);
genSeed = CSSM_FALSE;
switch(privWrapAlg) {
case ALG_RSA:
if(wrapKeySizeBits > maxRsaKeySize) {
wrapKeySizeBits = maxRsaKeySize;
}
break;
case ALG_FEEDEXP:
if(wrapKeySizeBits > maxFeeKeySize) {
wrapKeySizeBits = maxFeeKeySize;
}
if(loop & 2) {
genSeed = CSSM_TRUE;
}
break;
default:
break;
}
crtn = cspGenKeyPair(cspHand,
wrapInfo->keyGenAlg,
WRAP_LABEL,
WRAP_LABEL_LEN,
wrapKeySizeBits,
&pubWrapKey,
CSSM_TRUE, WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_WRAP,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&privWrapKey,
CSSM_TRUE, WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_UNWRAP,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
genSeed);
if(crtn) {
rtn = testError(quiet);
goto testDone;
}
wrapKeyPtr = &pubWrapKey;
unwrapKeyPtr = &privWrapKey;
break;
case WT_Null:
#if !SYMM_NULL_WRAP_ENABLE
if(encrInfo->wtype == WT_Symmetric) {
continue;
}
#endif
wrapKeySizeBits = 0;
wrapKeyPtr = NULL;
unwrapKeyPtr = NULL;
break;
}
#if 0
if((wrapKeyPtr != NULL) &&
(wrapKeyPtr->KeyHeader.AlgorithmId == CSSM_ALGID_3DES_3KEY) &&
(decrKeyPtr->KeyHeader.AlgorithmId == CSSM_ALGID_3DES_3KEY)) {
isAppleCustom = CSSM_TRUE;
}
else {
isAppleCustom = CSSM_FALSE;
}
#endif
if(wrapInfo->wtype == WT_Null) {
wrapFormat = expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE;
}
else if((loop & 1)) {
wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE;
switch(encrInfo->wtype) {
case WT_Symmetric:
expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
break;
case WT_Asymmetric:
if(privEncrAlg == ALG_FEEDEXP) {
expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
}
else {
expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
}
break;
default:
printf("**GAK! Internal error\n");
}
}
else {
int die = loop & 2;
switch(encrInfo->wtype) {
case WT_Symmetric:
if(privWrapAlg == ALG_AES) {
wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
}
else if(die) {
wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
}
else {
wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
}
break;
case WT_Asymmetric:
if(privEncrAlg == ALG_FEEDEXP) {
wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
}
else if(die) {
wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
}
else if(privWrapAlg == ALG_AES) {
wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
}
else {
wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
}
break;
default:
printf("***GAK! Internal error\n");
exit(1);
}
expectFormat = wrapFormat;
}
if(expectFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) {
simpleGenData(&descData, 1, MAX_DESC_DATA_SIZE);
descDataP = &descData;
}
else {
descDataP = NULL;
}
if(verbose) {
printf(" ...wrapAlg = %s size %u bits format %s expect %s\n",
wrapInfo->algName, (unsigned)wrapKeySizeBits, formatString(wrapFormat),
formatString(expectFormat));
}
if(doTest(cspHand,
encrKeyPtr,
wrapEncrKey,
decrKeyPtr,
wrapKeyPtr,
unwrapKeyPtr,
wrapInfo->encrAlg,
wrapInfo->encrMode,
wrapFormat,
expectFormat,
wrapInfo->encrPad,
wrapInfo->ivSize,
encrInfo->encrAlg,
encrInfo->encrMode,
encrInfo->encrPad,
encrInfo->ivSize,
effectiveKeySizeInBits,
&ptext,
descDataP,
quiet,
bareCsp)) {
rtn = 1;
goto testDone;
}
switch(wrapInfo->wtype) {
case WT_Symmetric:
cspFreeKey(cspHand, wrapKeyPtr);
CSSM_FREE(wrapKeyPtr);
break;
case WT_Asymmetric:
cspFreeKey(cspHand, wrapKeyPtr);
cspFreeKey(cspHand, unwrapKeyPtr);
break;
default:
break;
}
}
cspFreeKey(cspHand, encrKeyPtr);
if(encrInfo->wtype == WT_Symmetric) {
CSSM_FREE(decrKeyPtr);
}
else {
cspFreeKey(cspHand, decrKeyPtr);
}
}
}
testDone:
cspShutdown(cspHand, bareCsp);
if(pause) {
fpurge(stdin);
printf("ModuleDetach/Unload complete; hit CR to exit: ");
getchar();
}
if((rtn == 0) && !quiet) {
printf("%s test complete\n", argv[0]);
}
return rtn;
}