--- /dev/null
+/* Copyright (c) 1998,2003-2006,2008 Apple Inc.
+ *
+ * symTest.c - test CSP symmetric encrypt/decrypt.
+ *
+ * Revision History
+ * ----------------
+ * 4 May 2000 Doug Mitchell
+ * Ported to X/CDSA2.
+ * 20 May 1998 Doug Mitchell at Apple
+ * Ported to CDSA1.2, new Apple CSP
+ * 15 Aug 1997 Doug Mitchell at Apple
+ * Ported from CryptKit ObjC version
+ * 26 Aug 1996 Doug Mitchell at NeXT
+ * Created.
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <Security/cssm.h>
+#include <Security/cssmapple.h>
+#include "cspwrap.h"
+#include "common.h"
+#include "cspdlTesting.h"
+
+/*
+ * Defaults.
+ */
+#define LOOPS_DEF 50
+#define MIN_PTEXT_SIZE 8
+#define MAX_PTEXT_SIZE 0x10000
+
+/*
+ * Enumerate algs our own way to allow iteration.
+ */
+typedef enum {
+ ALG_ASC = 1,
+ ALG_DES,
+ ALG_RC2,
+ ALG_RC4,
+ ALG_RC5,
+ ALG_3DES,
+ ALG_AES,
+ ALG_BFISH,
+ ALG_CAST,
+ ALG_NULL /* normally not used */
+} SymAlg;
+#define ALG_FIRST ALG_ASC
+#define ALG_LAST ALG_CAST
+
+#define PBE_ENABLE 0
+#define PWD_LENGTH_MAX 64
+#define MAX_DATA_SIZE (100000 + 100) /* bytes */
+#define LOOP_NOTIFY 20
+
+#define LOG_SIZE 0
+#if LOG_SIZE
+#define logSize(s) printf s
+#else
+#define logSize(s)
+#endif
+
+static void usage(char **argv)
+{
+ printf("usage: %s [options]\n", argv[0]);
+ printf(" Options:\n");
+ printf(" a=algorithm (s=ASC; d=DES; 3=3DES; 2=RC2; 4=RC4; 5=RC5; a=AES;\n");
+ printf(" b=Blowfish; c=CAST; n=Null; default=all)\n");
+ printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
+ printf(" n=minPtextSize (default=%d)\n", MIN_PTEXT_SIZE);
+ printf(" x=maxPtextSize (default=%d)\n", MAX_PTEXT_SIZE);
+ printf(" k=keySizeInBits\n");
+ printf(" r(eference keys only)\n");
+ printf(" e(xport)\n");
+ printf(" d (no DB open)\n");
+ printf(" p=pauseInterval (default=0, no pause)\n");
+ printf(" o (no padding, well-aligned plaintext)\n");
+ printf(" u (no multi-update ops)\n");
+ printf(" U (only multi-update ops)\n");
+ printf(" m (CSP mallocs out bufs)\n");
+ printf(" D (CSP/DL; default = bare CSP)\n");
+ printf(" K (key gen only)\n");
+ printf(" v(erbose)\n");
+ printf(" q(uiet)\n");
+ printf(" h(elp)\n");
+ exit(1);
+}
+
+/* constant seed data */
+static CSSM_DATA seedData = {8, (uint8 *)"12345678"};
+
+/* alternate between two derivation algs, with different digest sizes */
+#define PBE_DERIVE_ALG_ODD CSSM_ALGID_PKCS5_PBKDF1_MD5
+#define PBE_DERIVE_ALG_EVEN CSSM_ALGID_PKCS5_PBKDF1_SHA1
+
+/*
+ * When expectEqualText is true, encrypt/decrypt in place.
+ */
+#define EQUAL_TEXT_IN_PLACE 1
+
+static int doTest(CSSM_CSP_HANDLE cspHand,
+ CSSM_DATA_PTR ptext,
+ uint32 keyAlg, // CSSM_ALGID_xxx of the key
+ uint32 encrAlg, // encrypt/decrypt
+ uint32 mode,
+ uint32 padding,
+ uint32 effectiveKeySizeInBits,
+ CSSM_BOOL refKey,
+ CSSM_DATA_PTR pwd, // password- NULL means use a random key data
+ CSSM_BOOL stagedEncr,
+ CSSM_BOOL stagedDecr,
+ CSSM_BOOL mallocPtext, // only meaningful if !stagedDecr
+ CSSM_BOOL mallocCtext, // only meaningful if !stagedEncr
+ CSSM_BOOL quiet,
+ CSSM_BOOL keyGenOnly,
+ CSSM_BOOL expectEqualText) // ptext size must == ctext size
+{
+ CSSM_KEY_PTR symKey = NULL;
+ CSSM_DATA ctext = {0, NULL};
+ CSSM_DATA rptext = {0, NULL};
+ CSSM_RETURN crtn;
+ int rtn = 0;
+ uint32 keySizeInBits;
+ CSSM_DATA initVector;
+ uint32 rounds = 0;
+
+ /* generate keys with well aligned sizes; effectiveKeySize specified in encrypt
+ * only if not well aligned */
+ keySizeInBits = (effectiveKeySizeInBits + 7) & ~7;
+ if(keySizeInBits == effectiveKeySizeInBits) {
+ effectiveKeySizeInBits = 0;
+ }
+
+ if(encrAlg == CSSM_ALGID_RC5) {
+ /* roll the dice, pick one of three values for rounds */
+ unsigned die = genRand(1,3);
+ switch(die) {
+ case 1:
+ rounds = 8;
+ break;
+ case 2:
+ rounds = 12;
+ break;
+ case 3:
+ rounds = 16;
+ break;
+ }
+ }
+
+ if(pwd == NULL) {
+ /* random key */
+ symKey = cspGenSymKey(cspHand,
+ keyAlg,
+ "noLabel",
+ 7,
+ CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
+ keySizeInBits,
+ refKey);
+ }
+ else {
+ /* this code isn't tested */
+ uint32 pbeAlg;
+ initVector.Data = NULL; // we're going to ignore this
+ initVector.Length = 0;
+ /* one of two random PBE algs */
+ if(ptext->Data[0] & 1) {
+ pbeAlg = PBE_DERIVE_ALG_ODD;
+ }
+ else {
+ pbeAlg = PBE_DERIVE_ALG_EVEN;
+ }
+ symKey = cspDeriveKey(cspHand,
+ pbeAlg,
+ keyAlg,
+ "noLabel",
+ 7,
+ CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
+ keySizeInBits,
+ refKey,
+ pwd,
+ &seedData,
+ 1, // iteration count
+ &initVector);
+ if(initVector.Data != NULL) {
+ CSSM_FREE(initVector.Data);
+ }
+ }
+ if(symKey == NULL) {
+ rtn = testError(quiet);
+ goto abort;
+ }
+ if(keyGenOnly) {
+ rtn = 0;
+ goto abort;
+ }
+
+ /* not all algs need this, pass it in anyway */
+ initVector.Data = (uint8 *)"someStrangeInitVect";
+ switch(encrAlg) {
+ case CSSM_ALGID_AES:
+ case CSSM_ALGID_NONE:
+ initVector.Length = 16;
+ break;
+ default:
+ initVector.Length = 8;
+ break;
+ }
+ if(stagedEncr) {
+ crtn = cspStagedEncrypt(cspHand,
+ encrAlg,
+ mode,
+ padding,
+ symKey,
+ NULL, // second key unused
+ effectiveKeySizeInBits,
+ 0, // cipherBlockSize
+ rounds,
+ &initVector,
+ ptext,
+ &ctext,
+ CSSM_TRUE); // multi
+ }
+ else {
+ const CSSM_DATA *ptextPtr = ptext;
+ if(expectEqualText && mallocCtext && CSPDL_NOPAD_ENFORCE_SIZE) {
+ /*
+ * !pad test: ensure this works when ctextlen == ptextlen by
+ * mallocing ourself right now (instead of cspEncrypt doing it
+ * after doing a CSSM_QuerySize())
+ */
+ ctext.Data = (uint8 *)appMalloc(ptext->Length, NULL);
+ if(ctext.Data == NULL) {
+ printf("memmory failure\n");
+ rtn = testError(quiet);
+ goto abort;
+ }
+ ctext.Length = ptext->Length;
+ #if EQUAL_TEXT_IN_PLACE
+ /* encrypt in place */
+ memmove(ctext.Data, ptext->Data, ptext->Length);
+ ptextPtr = &ctext;
+ #endif
+ }
+ crtn = cspEncrypt(cspHand,
+ encrAlg,
+ mode,
+ padding,
+ symKey,
+ NULL, // second key unused
+ effectiveKeySizeInBits,
+ rounds,
+ &initVector,
+ ptextPtr,
+ &ctext,
+ mallocCtext);
+ }
+ if(crtn) {
+ rtn = testError(quiet);
+ goto abort;
+ }
+ if(expectEqualText && (ptext->Length != ctext.Length)) {
+ printf("***ctext/ptext length mismatch: ptextLen %lu ctextLen %lu\n",
+ ptext->Length, ctext.Length);
+ rtn = testError(quiet);
+ if(rtn) {
+ goto abort;
+ }
+ }
+ logSize(("###ctext len %lu\n", ctext.Length));
+ if(stagedDecr) {
+ crtn = cspStagedDecrypt(cspHand,
+ encrAlg,
+ mode,
+ padding,
+ symKey,
+ NULL, // second key unused
+ effectiveKeySizeInBits,
+ 0, // cipherBlockSize
+ rounds,
+ &initVector,
+ &ctext,
+ &rptext,
+ CSSM_TRUE); // multi
+ }
+ else {
+ const CSSM_DATA *ctextPtr = &ctext;
+ if(expectEqualText && mallocPtext && CSPDL_NOPAD_ENFORCE_SIZE) {
+ /*
+ * !pad test: ensure this works when ctextlen == ptextlen by
+ * mallocing ourself right now (instead of cspDecrypt doing it
+ * after doing a CSSM_QuerySize())
+ */
+ rptext.Data = (uint8 *)appMalloc(ctext.Length, NULL);
+ if(rptext.Data == NULL) {
+ printf("memmory failure\n");
+ rtn = testError(quiet);
+ goto abort;
+ }
+ rptext.Length = ctext.Length;
+ #if EQUAL_TEXT_IN_PLACE
+ /* decrypt in place */
+ memmove(rptext.Data, ctext.Data, ctext.Length);
+ ctextPtr = &rptext;
+ #endif
+ }
+ crtn = cspDecrypt(cspHand,
+ encrAlg,
+ mode,
+ padding,
+ symKey,
+ NULL, // second key unused
+ effectiveKeySizeInBits,
+ rounds,
+ &initVector,
+ ctextPtr,
+ &rptext,
+ mallocPtext);
+ }
+ if(crtn) {
+ rtn = testError(quiet);
+ goto abort;
+ }
+ logSize(("###rptext len %lu\n", rptext.Length));
+ /* compare ptext, rptext */
+ if(ptext->Length != rptext.Length) {
+ printf("Ptext length mismatch: expect %lu, got %lu\n", ptext->Length, rptext.Length);
+ rtn = testError(quiet);
+ if(rtn) {
+ goto abort;
+ }
+ }
+ if(memcmp(ptext->Data, rptext.Data, ptext->Length)) {
+ printf("***data miscompare\n");
+ rtn = testError(quiet);
+ }
+abort:
+ /* free key if we have it*/
+ if(symKey != NULL) {
+ if(cspFreeKey(cspHand, symKey)) {
+ printf("Error freeing privKey\n");
+ rtn = 1;
+ }
+ CSSM_FREE(symKey);
+ }
+ /* free rptext, ctext */
+ appFreeCssmData(&rptext, CSSM_FALSE);
+ appFreeCssmData(&ctext, CSSM_FALSE);
+ return rtn;
+}
+
+int main(int argc, char **argv)
+{
+ int arg;
+ char *argp;
+ unsigned loop;
+ CSSM_DATA ptext;
+ CSSM_CSP_HANDLE cspHand;
+ CSSM_BOOL stagedEncr;
+ CSSM_BOOL stagedDecr;
+ CSSM_BOOL mallocCtext;
+ CSSM_BOOL mallocPtext;
+ CSSM_BOOL refKey;
+ const char *algStr;
+ uint32 keyAlg; // CSSM_ALGID_xxx of the key
+ uint32 encrAlg; // CSSM_ALGID_xxx of the encrypt/decrypt/sign
+ int i;
+ int currAlg; // ALG_xxx
+ CSSM_DATA_PTR pPwd;
+ CSSM_DATA pwd;
+ uint32 actKeySizeInBits;
+ int rtn = 0;
+ uint32 blockSize; // for noPadding case
+ CSSM_BOOL expectEqualText;
+
+ /*
+ * User-spec'd params
+ */
+ CSSM_BOOL keySizeSpec = CSSM_FALSE; // false: use rand key size
+ SymAlg minAlg = ALG_FIRST;
+ SymAlg maxAlg = ALG_LAST;
+ unsigned loops = LOOPS_DEF;
+ CSSM_BOOL verbose = CSSM_FALSE;
+ unsigned minPtextSize = MIN_PTEXT_SIZE;
+ unsigned maxPtextSize = MAX_PTEXT_SIZE;
+ CSSM_BOOL quiet = CSSM_FALSE;
+ unsigned pauseInterval = 0;
+ uint32 mode;
+ uint32 padding;
+ CSSM_BOOL noDbOpen = CSSM_FALSE;
+ CSSM_BOOL bareCsp = CSSM_TRUE;
+ CSSM_BOOL keyGenOnly = CSSM_FALSE;
+ CSSM_BOOL noPadding = CSSM_FALSE;
+ CSSM_BOOL multiEnable = CSSM_TRUE;
+ CSSM_BOOL multiOnly = CSSM_FALSE;
+ CSSM_BOOL refKeysOnly = CSSM_FALSE;
+ CSSM_BOOL cspMallocs = CSSM_FALSE;
+
+ #if macintosh
+ argc = ccommand(&argv);
+ #endif
+ for(arg=1; 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;
+ case 'n':
+ minAlg = maxAlg = ALG_NULL;
+ break;
+ default:
+ usage(argv);
+ }
+ break;
+ case 'l':
+ loops = atoi(&argp[2]);
+ break;
+ case 'n':
+ minPtextSize = atoi(&argp[2]);
+ break;
+ case 'x':
+ maxPtextSize = atoi(&argp[2]);
+ break;
+ case 'r':
+ refKeysOnly = CSSM_TRUE;
+ break;
+ case 'k':
+ actKeySizeInBits = atoi(&argp[2]);
+ keySizeSpec = 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 'q':
+ quiet = CSSM_TRUE;
+ break;
+ case 'p':
+ pauseInterval = atoi(&argp[2]);;
+ break;
+ case 'o':
+ noPadding = CSSM_TRUE;
+ break;
+ case 'd':
+ noDbOpen = CSSM_TRUE;
+ break;
+ case 'K':
+ keyGenOnly = CSSM_TRUE;
+ break;
+ case 'u':
+ multiEnable = CSSM_FALSE;
+ break;
+ case 'U':
+ multiOnly = CSSM_TRUE;
+ break;
+ case 'm':
+ cspMallocs = CSSM_TRUE;
+ break;
+ case 'h':
+ default:
+ usage(argv);
+ }
+ }
+ if(multiOnly && !multiEnable) {
+ printf("***can't specify multi disable and multi only\n");
+ exit(1);
+ }
+ if(minPtextSize > maxPtextSize) {
+ printf("***minPtextSize must be <= maxPtextSize\n");
+ usage(argv);
+ }
+ pwd.Data = (uint8 *)CSSM_MALLOC(PWD_LENGTH_MAX);
+ ptext.Data = (uint8 *)CSSM_MALLOC(maxPtextSize);
+ if(ptext.Data == NULL) {
+ printf("Insufficient heap space\n");
+ exit(1);
+ }
+ /* ptext length set in test loop */
+ printf("Starting symTest; 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++) {
+ /* some default values... */
+ mode = CSSM_ALGMODE_NONE;
+ padding = CSSM_PADDING_NONE;
+ blockSize = 0; // i.e., don't align
+ expectEqualText = CSSM_FALSE;
+ switch(currAlg) {
+ case ALG_ASC:
+ encrAlg = keyAlg = CSSM_ALGID_ASC;
+ algStr = "ASC";
+ break;
+ case ALG_DES:
+ encrAlg = keyAlg = CSSM_ALGID_DES;
+ algStr = "DES";
+ if(noPadding) {
+ mode = CSSM_ALGMODE_CBC_IV8;
+ blockSize = 8;
+ expectEqualText = CSSM_TRUE;
+ }
+ else {
+ mode = CSSM_ALGMODE_CBCPadIV8;
+ padding = CSSM_PADDING_PKCS1;
+ }
+ break;
+ case ALG_3DES:
+ /* currently the only one with different key and encr algs */
+ /* Though actually these two consts are equivalent...for now... */
+ keyAlg = CSSM_ALGID_3DES_3KEY;
+ encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
+ algStr = "3DES";
+ if(noPadding) {
+ mode = CSSM_ALGMODE_CBC_IV8;
+ blockSize = 8;
+ expectEqualText = CSSM_TRUE;
+ }
+ else {
+ mode = CSSM_ALGMODE_CBCPadIV8;
+ padding = CSSM_PADDING_PKCS1;
+ }
+ break;
+ case ALG_RC2:
+ encrAlg = keyAlg = CSSM_ALGID_RC2;
+ algStr = "RC2";
+ if(noPadding) {
+ mode = CSSM_ALGMODE_CBC_IV8;
+ blockSize = 8;
+ expectEqualText = CSSM_TRUE;
+ }
+ else {
+ mode = CSSM_ALGMODE_CBCPadIV8;
+ padding = CSSM_PADDING_PKCS1; // what does padding do here?
+ }
+ break;
+ case ALG_RC4:
+ encrAlg = keyAlg = CSSM_ALGID_RC4;
+ algStr = "RC4";
+ mode = CSSM_ALGMODE_NONE;
+ expectEqualText = CSSM_TRUE; // always for RC4
+ break;
+ case ALG_RC5:
+ encrAlg = keyAlg = CSSM_ALGID_RC5;
+ algStr = "RC5";
+ if(noPadding) {
+ mode = CSSM_ALGMODE_CBC_IV8;
+ blockSize = 8;
+ expectEqualText = CSSM_TRUE;
+ }
+ else {
+ mode = CSSM_ALGMODE_CBCPadIV8;
+ padding = CSSM_PADDING_PKCS1; // eh?
+ }
+ break;
+ case ALG_AES:
+ encrAlg = keyAlg = CSSM_ALGID_AES;
+ algStr = "AES";
+ if(noPadding) {
+ mode = CSSM_ALGMODE_CBC_IV8;
+ blockSize = 16;
+ expectEqualText = CSSM_TRUE;
+ }
+ else {
+ mode = CSSM_ALGMODE_CBCPadIV8;
+ padding = CSSM_PADDING_PKCS5;
+ }
+ break;
+ case ALG_BFISH:
+ encrAlg = keyAlg = CSSM_ALGID_BLOWFISH;
+ algStr = "Blowfish";
+ if(noPadding) {
+ mode = CSSM_ALGMODE_CBC_IV8;
+ blockSize = 8;
+ expectEqualText = CSSM_TRUE;
+ }
+ else {
+ mode = CSSM_ALGMODE_CBCPadIV8;
+ padding = CSSM_PADDING_PKCS5;
+ }
+ break;
+ case ALG_CAST:
+ encrAlg = keyAlg = CSSM_ALGID_CAST;
+ algStr = "CAST";
+ if(noPadding) {
+ mode = CSSM_ALGMODE_CBC_IV8;
+ blockSize = 8;
+ expectEqualText = CSSM_TRUE;
+ }
+ else {
+ mode = CSSM_ALGMODE_CBCPadIV8;
+ padding = CSSM_PADDING_PKCS5;
+ }
+ break;
+ case ALG_NULL:
+ encrAlg = keyAlg = CSSM_ALGID_NONE;
+ algStr = "NULL";
+ if(noPadding) {
+ mode = CSSM_ALGMODE_CBC_IV8;
+ blockSize = 16;
+ expectEqualText = CSSM_TRUE;
+ }
+ else {
+ mode = CSSM_ALGMODE_CBCPadIV8;
+ padding = CSSM_PADDING_PKCS5;
+ }
+ break;
+ }
+ if(!quiet || verbose) {
+ printf("Testing alg %s\n", algStr);
+ }
+ for(loop=1; ; loop++) {
+ simpleGenData(&ptext, minPtextSize, maxPtextSize);
+ if(blockSize) {
+ /* i.e., no padding --> align ptext */
+ ptext.Length = ((ptext.Length + blockSize - 1) / blockSize) * blockSize;
+ }
+ if(!keySizeSpec) {
+ actKeySizeInBits = randKeySizeBits(keyAlg, OT_Encrypt);
+ }
+ /* else constant, spec'd by user, may be 0 (default per alg) */
+ /* mix up some random and derived keys, as well as staging and "who does
+ * the malloc?" */
+ pPwd = (loop & 1) ? &pwd : NULL;
+ if(multiEnable) {
+ if(multiOnly) {
+ stagedEncr = stagedDecr = CSSM_TRUE;
+ }
+ else {
+ stagedEncr = (loop & 2) ? CSSM_TRUE : CSSM_FALSE;
+ stagedDecr = (loop & 4) ? CSSM_TRUE : CSSM_FALSE;
+ }
+ }
+ else {
+ stagedEncr = CSSM_FALSE;
+ stagedDecr = CSSM_FALSE;
+ }
+ if(!stagedEncr && !cspMallocs) {
+ mallocCtext = (ptext.Data[0] & 1) ? CSSM_TRUE : CSSM_FALSE;
+ }
+ else {
+ mallocCtext = CSSM_FALSE;
+ }
+ if(!stagedDecr && !cspMallocs) {
+ mallocPtext = (ptext.Data[0] & 2) ? CSSM_TRUE : CSSM_FALSE;
+ }
+ else {
+ mallocPtext = CSSM_FALSE;
+ }
+ if(refKeysOnly) {
+ refKey = CSSM_TRUE;
+ }
+ else {
+ refKey = (ptext.Data[0] & 4) ? CSSM_TRUE : CSSM_FALSE;
+ }
+ #if !PBE_ENABLE
+ pPwd = NULL;
+ #endif
+ if(!quiet) {
+ if(verbose || ((loop % LOOP_NOTIFY) == 0)) {
+ printf("..loop %d text size %lu keySizeBits %u\n",
+ loop, (unsigned long)ptext.Length, (unsigned)actKeySizeInBits);
+ if(verbose) {
+ printf(" refKey %d derive %d stagedEncr %d stagedDecr %d mallocCtext %d "
+ "mallocPtext %d\n",
+ (int)refKey, (pPwd == NULL) ? 0 : 1, (int)stagedEncr, (int)stagedDecr,
+ (int)mallocCtext, (int)mallocPtext);
+ }
+ }
+ }
+ #if PBE_ENABLE
+ if(pPwd != NULL) {
+ /* PBE - cook up random password */
+ simpleGenData(pPwd, APPLE_PBE_MIN_PASSWORD, PWD_LENGTH_MAX);
+ }
+ #endif
+
+ if(doTest(cspHand,
+ &ptext,
+ keyAlg,
+ encrAlg,
+ mode,
+ padding,
+ actKeySizeInBits,
+ refKey,
+ pPwd,
+ stagedEncr,
+ stagedDecr,
+ mallocPtext,
+ mallocCtext,
+ quiet,
+ keyGenOnly,
+ expectEqualText)) {
+ rtn = 1;
+ break;
+ }
+ if(pauseInterval && ((loop % pauseInterval) == 0)) {
+ char c;
+ fpurge(stdin);
+ printf("Hit CR to proceed, q to abort: ");
+ c = getchar();
+ if(c == 'q') {
+ goto testDone;
+ }
+ }
+ if(loops && (loop == loops)) {
+ break;
+ }
+ } /* main loop */
+ if(rtn) {
+ break;
+ }
+
+ } /* for algs */
+
+testDone:
+ 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(pwd.Data);
+ CSSM_FREE(ptext.Data);
+ return rtn;
+}