--- /dev/null
+/*
+ * dsaPartial.cpp - test for partial DSA public handling
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <Security/cssm.h>
+#include <Security/cssmapple.h>
+#include <string.h>
+#include "cspwrap.h"
+#include "common.h"
+#include <security_cdsa_utils/cuFileIo.h>
+#include "nssAppUtils.h"
+
+/*
+ * generate key pairs with one set of parameters, dsa1Priv and dsa1Pub;
+ * genenate another pair with a different set of params, dsa2Priv and
+ * dsa2Pub;
+ * manually cook up dsa1PubPartial from dsa1Pub;
+ * manually cook up dsa2PubPartial from dsa2Pub;
+ *
+ * with all legal and/or specified combos of {ref,raw} keys {
+ * sign with dsa1Priv;
+ * vfy with dsa1Pub;
+ * vfy with dsa1PubPartial: CSSMERR_CSP_APPLE_DSA_PUBLIC_KEY_INCOMPLETE
+ * vfy with dsa1PubPartial and dsa1Pub (attrs)
+ * vfy with dsa2PubPartial and dsa1Pub (attrs) --> vfy fail
+ * vfy with dsa1PubPartial and dsa2Pub (attrs) --> vfy fail
+ * merge dsa1PubPartial + dsa1Pub --> merged;
+ * vfy with merged, should be good
+ * merge dsa1PubPartial + dsa2Pub -->merged;
+ * vfy with merged; vfy fail;
+ * }
+ */
+
+/*
+ * Static parameter files.
+ *
+ * Regenerate these every once in a while with rsatool:
+ *
+ * # rsatool g a=d k=/tmp/foo M=dsaParam512_1.der
+ */
+#define PARAMS_512_1 "dsaParam512_1.der"
+#define PARAMS_512_2 "dsaParam512_2.der"
+
+#define MAX_PTEXT_SIZE 512
+#define KEY_ALG CSSM_ALGID_DSA
+#define SIG_ALG CSSM_ALGID_SHA1WithDSA
+#define LOOPS_DEF 32
+#define KEY_SIZE_DEF 512
+
+static void usage(char **argv)
+{
+ printf("Usage: %s [options]\n", argv[0]);
+ printf("Options:\n");
+ printf(" l=loops\n");
+ printf(" p(ause on loop)\n");
+ printf(" q(uiet)\n");
+ printf(" v(erbose)\n");
+ printf(" D (CSPDL)\n");
+ printf(" r (all keys are raw)\n");
+ printf(" f (all keys are ref)\n");
+ exit(1);
+}
+
+/*
+ * Generate DSA key pair with required alg parameters.
+ */
+static CSSM_RETURN genDsaKeyPair(
+ CSSM_CSP_HANDLE cspHand,
+ uint32 keySize, // in bits
+ CSSM_KEY_PTR pubKey, // mallocd by caller
+ CSSM_BOOL pubIsRef, // true - reference key, false - data
+ CSSM_KEY_PTR privKey, // mallocd by caller
+ CSSM_BOOL privIsRef, // true - reference key, false - data
+ const CSSM_DATA *params)
+{
+ CSSM_RETURN crtn;
+ CSSM_CC_HANDLE ccHand;
+ CSSM_DATA keyLabelData;
+ uint32 pubAttr;
+ uint32 privAttr;
+
+ if(params == NULL) {
+ return CSSMERR_CSSM_INVALID_POINTER;
+ }
+
+ keyLabelData.Data = (uint8 *)"foobar",
+ keyLabelData.Length = 6;
+ memset(pubKey, 0, sizeof(CSSM_KEY));
+ memset(privKey, 0, sizeof(CSSM_KEY));
+
+ crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
+ CSSM_ALGID_DSA,
+ keySize,
+ NULL, // Seed
+ NULL, // Salt
+ NULL, // StartDate
+ NULL, // EndDate
+ params,
+ &ccHand);
+ if(crtn) {
+ printError("CSSM_CSP_CreateKeyGenContext", crtn);
+ return crtn;
+ }
+
+ /* cook up attribute bits */
+ if(pubIsRef) {
+ pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
+ }
+ else {
+ pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
+ }
+ if(privIsRef) {
+ privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
+ }
+ else {
+ privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
+ }
+
+ crtn = CSSM_GenerateKeyPair(ccHand,
+ CSSM_KEYUSE_VERIFY,
+ pubAttr,
+ &keyLabelData,
+ pubKey,
+ CSSM_KEYUSE_SIGN,
+ privAttr,
+ &keyLabelData, // same labels
+ NULL, // CredAndAclEntry
+ privKey);
+ if(crtn) {
+ printError("CSSM_GenerateKeyPair", crtn);
+ }
+ CSSM_DeleteContext(ccHand);
+ return crtn;
+}
+
+
+/*
+ * Create new public key by merging specified partial key and
+ * parameter-bearing key. All keys can be in any format (though
+ * it's the caller's responsibility to avoid using a ref paramKey
+ * with the CSPDL).
+ */
+static CSSM_RETURN dsaMergeParams(
+ CSSM_CSP_HANDLE cspHand,
+ const CSSM_KEY *partialKey,
+ const CSSM_KEY *paramKey,
+ CSSM_KEY &fullKey, // RETURNED
+ bool fullIsRef) // ref/raw
+{
+ /*
+ * First step is a null wrap or unwrap depending on
+ * format of partialKey.
+ */
+ CSSM_CC_HANDLE ccHand;
+ CSSM_RETURN crtn;
+ CSSM_ACCESS_CREDENTIALS creds;
+ CSSM_DATA label = {10, (uint8 *)"dummyLabel"};
+ CSSM_DATA descrData = {0, NULL};
+ const CSSM_KEYHEADER &hdr = partialKey->KeyHeader;
+
+ memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
+ crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
+ CSSM_ALGID_NONE,
+ CSSM_ALGMODE_NONE,
+ &creds,
+ NULL, // wrapping key
+ NULL, // initVector
+ CSSM_PADDING_NONE,
+ 0, // Params
+ &ccHand);
+ if(crtn) {
+ printError("CSSM_CSP_CreateSymmetricContext", crtn);
+ return crtn;
+ }
+
+ /* add in paramKey */
+ crtn = AddContextAttribute(ccHand,
+ CSSM_ATTRIBUTE_PARAM_KEY,
+ sizeof(CSSM_KEY),
+ CAT_Ptr,
+ paramKey,
+ 0);
+ if(crtn) {
+ printError("AddContextAttribute", crtn);
+ return crtn;
+ }
+
+ /* go */
+ CSSM_KEY targetKey;
+ memset(&targetKey, 0, sizeof(targetKey));
+ if(hdr.BlobType == CSSM_KEYBLOB_RAW) {
+ /* raw --> ref : null unwrap */
+ crtn = CSSM_UnwrapKey(ccHand,
+ NULL, // PublicKey
+ partialKey,
+ hdr.KeyUsage, // same as original
+ CSSM_KEYATTR_EXTRACTABLE |CSSM_KEYATTR_RETURN_REF,
+ &label,
+ NULL, // CredAndAclEntry
+ &targetKey,
+ &descrData); // required
+ if(crtn) {
+ printError("dsaMergeParams CSSM_UnwrapKey (1)", crtn);
+ return crtn;
+ }
+ }
+ else {
+ /* ref --> raw : null wrap */
+ crtn = CSSM_WrapKey(ccHand,
+ &creds,
+ partialKey,
+ NULL, // DescriptiveData
+ &targetKey);
+ if(crtn) {
+ printError("dsaMergeParams CSSM_WrapKey (1)", crtn);
+ return crtn;
+ }
+ }
+
+ if(targetKey.KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL) {
+ printf("***merged key still has CSSM_KEYATTR_PARTIAL\n");
+ return CSSMERR_CSSM_INTERNAL_ERROR;
+ }
+
+ CSSM_KEYBLOB_TYPE targetBlob;
+ if(fullIsRef) {
+ targetBlob = CSSM_KEYBLOB_REFERENCE;
+ }
+ else {
+ targetBlob = CSSM_KEYBLOB_RAW;
+ }
+
+ if(targetKey.KeyHeader.BlobType == targetBlob) {
+ /* we're done */
+ fullKey = targetKey;
+ CSSM_DeleteContext(ccHand);
+ return CSSM_OK;
+ }
+
+ /*
+ * We're going to reuse the context, but since the parameter merge
+ * has already been done, remove the CSSM_ATTRIBUTE_PARAM_KEY
+ * attribute.
+ */
+ CSSM_CONTEXT_ATTRIBUTE attr;
+ memset(&attr, 0, sizeof(attr));
+ attr.AttributeType = CSSM_ATTRIBUTE_PARAM_KEY;
+ crtn = CSSM_DeleteContextAttributes(ccHand, 1, &attr);
+ if(crtn) {
+ printError("CSSM_DeleteContextAttributes", crtn);
+ return crtn;
+ }
+
+ /* one more conversion */
+ if(targetBlob == CSSM_KEYBLOB_REFERENCE) {
+ /* raw --> ref : null unwrap */
+ crtn = CSSM_UnwrapKey(ccHand,
+ NULL, // PublicKey
+ &targetKey,
+ hdr.KeyUsage, // same as original
+ CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF,
+ &label,
+ NULL, // CredAndAclEntry
+ &fullKey,
+ &descrData); // required
+ if(crtn) {
+ printError("dsaMergeParams CSSM_UnwrapKey (2)", crtn);
+ return crtn;
+ }
+ }
+ else {
+ /* ref --> raw : null wrap */
+ crtn = CSSM_WrapKey(ccHand,
+ &creds,
+ &targetKey,
+ NULL, // DescriptiveData
+ &fullKey);
+ if(crtn) {
+ printError("dsaMergeParams CSSM_WrapKey (2)", crtn);
+ return crtn;
+ }
+ }
+ CSSM_FreeKey(cspHand, NULL, &targetKey, CSSM_FALSE);
+ CSSM_DeleteContext(ccHand);
+ return CSSM_OK;
+}
+
+/*
+ * Custom cspSigVerify with optional CSSM_ATTRIBUTE_PARAM_KEY
+ */
+CSSM_RETURN sigVerify(CSSM_CSP_HANDLE cspHand,
+ uint32 algorithm, // CSSM_ALGID_SHA1WithDSA, etc.
+ CSSM_KEY_PTR key, // public key
+ CSSM_KEY_PTR paramKey, // optional parameter key
+ const CSSM_DATA *ptext,
+ const CSSM_DATA *sig,
+ CSSM_RETURN expectResult,
+ const char *op,
+ CSSM_BOOL verbose)
+{
+ CSSM_CC_HANDLE sigHand;
+ CSSM_RETURN ocrtn = CSSM_OK;
+ CSSM_RETURN crtn;
+
+ if(verbose) {
+ printf(" ...%s\n", op);
+ }
+ crtn = CSSM_CSP_CreateSignatureContext(cspHand,
+ algorithm,
+ NULL, // passPhrase
+ key,
+ &sigHand);
+ if(crtn) {
+ printError("CSSM_CSP_CreateSignatureContext", crtn);
+ return crtn;
+ }
+ if(paramKey) {
+ crtn = AddContextAttribute(sigHand,
+ CSSM_ATTRIBUTE_PARAM_KEY,
+ sizeof(CSSM_KEY),
+ CAT_Ptr,
+ paramKey,
+ 0);
+ if(crtn) {
+ printError("AddContextAttribute", crtn);
+ return crtn;
+ }
+ }
+ crtn = CSSM_VerifyData(sigHand,
+ ptext,
+ 1,
+ CSSM_ALGID_NONE,
+ sig);
+ if(crtn != expectResult) {
+ if(!crtn) {
+ printf("%s: Unexpected good Sig Verify (expect %s)\n",
+ op, cssmErrToStr(expectResult));
+ ocrtn = CSSMERR_CSSM_INTERNAL_ERROR;
+ }
+ else {
+ printError(op, crtn);
+ ocrtn = crtn;
+ }
+ }
+ CSSM_DeleteContext(sigHand);
+ return ocrtn;
+}
+
+static int doTest(
+ CSSM_CSP_HANDLE cspHand,
+ CSSM_KEY_PTR privKey_0,
+ CSSM_KEY_PTR pubKeyBase_0,
+ CSSM_KEY_PTR pubKeyPartial_0,
+ CSSM_KEY_PTR pubKeyParam_0, // full, raw format if CSPDL
+ CSSM_KEY_PTR pubKeyPartial_1,
+ CSSM_KEY_PTR pubKeyParam_1, // full, raw format if CSPDL
+ bool mergedIsRef,
+ CSSM_BOOL quiet,
+ CSSM_BOOL verbose)
+{
+ uint8 ptextBuf[MAX_PTEXT_SIZE];
+ CSSM_DATA ptext = {0, ptextBuf};
+ simpleGenData(&ptext, 1, MAX_PTEXT_SIZE);
+ CSSM_DATA sig = {0, NULL};
+ CSSM_RETURN crtn;
+
+ /* the single sign op for this routine */
+ crtn = cspSign(cspHand, SIG_ALG, privKey_0, &ptext, &sig);
+ if(crtn) {
+ return testError(quiet);
+ }
+
+ /* normal verify with full key */
+ crtn = sigVerify(cspHand, SIG_ALG, pubKeyBase_0, NULL,
+ &ptext, &sig, CSSM_OK, "vfy with full key", verbose);
+ if(crtn) {
+ return testError(quiet);
+ }
+
+ /* good verify with partial key plus params */
+ crtn = sigVerify(cspHand, SIG_ALG, pubKeyPartial_0, pubKeyParam_0,
+ &ptext, &sig, CSSM_OK, "vfy with partial key and params",
+ verbose);
+ if(crtn) {
+ if(testError(quiet)) {
+ return 1;
+ }
+ }
+
+ /* partial key failure */
+ crtn = sigVerify(cspHand, SIG_ALG, pubKeyPartial_0, NULL,
+ &ptext, &sig,
+ CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE,
+ "vfy with partial key no params", verbose);
+ if(crtn) {
+ if(testError(quiet)) {
+ return 1;
+ }
+ }
+
+ /* partial key, wrong params */
+ crtn = sigVerify(cspHand, SIG_ALG, pubKeyPartial_0, pubKeyParam_1,
+ &ptext, &sig,
+ CSSMERR_CSP_VERIFY_FAILED,
+ "vfy with partial key wrong params", verbose);
+ if(crtn) {
+ if(testError(quiet)) {
+ return 1;
+ }
+ }
+
+ /* wrong partial key, good params */
+ crtn = sigVerify(cspHand, SIG_ALG, pubKeyPartial_1, pubKeyParam_0,
+ &ptext, &sig,
+ CSSMERR_CSP_VERIFY_FAILED,
+ "vfy with wrong partial key, good params", verbose);
+ if(crtn) {
+ if(testError(quiet)) {
+ return 1;
+ }
+ }
+
+ /*
+ * Test merge via wrap/unwrap.
+ * First, a good merged key.
+ */
+ CSSM_KEY merged;
+ crtn = dsaMergeParams(cspHand,
+ pubKeyPartial_0,
+ pubKeyParam_0,
+ merged,
+ mergedIsRef);
+ if(crtn) {
+ return testError(quiet);
+ }
+ crtn = sigVerify(cspHand, SIG_ALG, &merged, NULL,
+ &ptext, &sig, CSSM_OK, "vfy with good merged key", verbose);
+ if(crtn) {
+ return testError(quiet);
+ }
+ CSSM_FreeKey(cspHand, NULL, &merged, CSSM_FALSE);
+
+ /* now with a badly merged key (with the wrong params) */
+ crtn = dsaMergeParams(cspHand,
+ pubKeyPartial_0,
+ pubKeyParam_1,
+ merged,
+ mergedIsRef);
+ if(crtn) {
+ return testError(quiet);
+ }
+ crtn = sigVerify(cspHand, SIG_ALG, &merged, NULL,
+ &ptext, &sig,
+ CSSMERR_CSP_VERIFY_FAILED,
+ "vfy with merged key wrong params", verbose);
+ if(crtn) {
+ if(testError(quiet)) {
+ return 1;
+ }
+ }
+ CSSM_FreeKey(cspHand, NULL, &merged, CSSM_FALSE);
+
+ CSSM_FREE(sig.Data);
+ return CSSM_OK;
+}
+
+
+int main(int argc, char **argv)
+{
+ char *argp;
+ CSSM_CSP_HANDLE cspHand;
+ CSSM_RETURN crtn;
+
+ /* user spec'd variables */
+ unsigned loops = LOOPS_DEF;
+ CSSM_BOOL doPause = CSSM_FALSE;
+ CSSM_BOOL quiet = CSSM_FALSE;
+ CSSM_BOOL rawCSP = CSSM_TRUE;
+ CSSM_BOOL verbose = CSSM_FALSE;
+ uint32 keySize = KEY_SIZE_DEF;
+ CSSM_BOOL allRaw = CSSM_FALSE;
+ CSSM_BOOL allRef = CSSM_FALSE;
+
+ for(int arg=1; arg<argc; arg++) {
+ argp = argv[arg];
+ switch(argp[0]) {
+ case 'l':
+ loops = atoi(&argp[2]);
+ break;
+ case 'q':
+ quiet = CSSM_TRUE;
+ break;
+ case 'p':
+ doPause = CSSM_TRUE;
+ break;
+ case 'v':
+ verbose = CSSM_TRUE;
+ break;
+ case 'D':
+ rawCSP = CSSM_FALSE;
+ break;
+ case 'r':
+ allRaw = CSSM_TRUE;
+ break;
+ case 'f':
+ allRef = CSSM_TRUE;
+ break;
+ default:
+ usage(argv);
+ }
+ }
+
+ if(!rawCSP && (allRaw || allRef)) {
+ printf("CSPDL inconsistent with allRef and allRaw\n");
+ usage(argv);
+ }
+ if(allRef && allRaw) {
+ printf("allRef and allRaw are mutually exclusive\n");
+ usage(argv);
+ }
+
+ /* read in params for two keypairs */
+ CSSM_DATA params1;
+ CSSM_DATA params2;
+ unsigned len;
+ if(readFile(PARAMS_512_1, (unsigned char **)¶ms1.Data, &len)) {
+ printf("***Error reading %s. Aborting.\n", PARAMS_512_1);
+ printf("***This test must be run from the cspxutils/dsaPartial directory.\n");
+ exit(1);
+ }
+ params1.Length = len;
+ if(readFile(PARAMS_512_2, (unsigned char **)¶ms2.Data, &len)) {
+ printf("***Error reading %s. Aborting.\n", PARAMS_512_2);
+ printf("***This test must be run from the cspxutils/dsaPartial directory.\n");
+ exit(1);
+ }
+ params2.Length = len;
+
+ printf("Starting dsaPartial; args: ");
+ for(int i=1; i<argc; i++) {
+ printf("%s ", argv[i]);
+ }
+ printf("\n");
+ cspHand = cspDlDbStartup(rawCSP, NULL);
+ if(cspHand == 0) {
+ exit(1);
+ }
+
+ /* generate two keypairs */
+ CSSM_KEY dsa1Priv;
+ CSSM_KEY dsa1Pub;
+ CSSM_KEY dsa2Priv;
+ CSSM_KEY dsa2Pub;
+
+ if(verbose) {
+ printf("...generating keys...\n");
+ }
+ CSSM_BOOL genRefKeys = CSSM_FALSE;
+ if(!rawCSP || allRef) {
+ genRefKeys = CSSM_TRUE;
+ }
+ crtn = genDsaKeyPair(cspHand, keySize,
+ &dsa1Pub, genRefKeys,
+ &dsa1Priv, genRefKeys,
+ ¶ms1);
+ if(crtn) {
+ exit(1);
+ }
+ crtn = genDsaKeyPair(cspHand, keySize,
+ &dsa2Pub, genRefKeys,
+ &dsa2Priv, genRefKeys,
+ ¶ms2);
+ if(crtn) {
+ exit(1);
+ }
+
+ /* CSPDL also requires separate raw parameter keys */
+ CSSM_KEY dsa1PubParam;
+ CSSM_KEY dsa2PubParam;
+ if(!rawCSP) {
+ if(cspRefKeyToRaw(cspHand, &dsa1Pub, &dsa1PubParam) ||
+ cspRefKeyToRaw(cspHand, &dsa2Pub, &dsa2PubParam)) {
+ exit(1);
+ }
+ }
+
+ /* generate partial pub keys in raw form */
+ CSSM_KEY dsa1PubPartial;
+ CSSM_KEY dsa2PubPartial;
+ crtn = extractDsaPartial(cspHand, &dsa1Pub, &dsa1PubPartial);
+ if(crtn) {
+ exit(1);
+ }
+ crtn = extractDsaPartial(cspHand, &dsa2Pub, &dsa2PubPartial);
+ if(crtn) {
+ exit(1);
+ }
+
+ /*
+ * Reference version of all 4 pub keys if we're going to mix & match
+ */
+ CSSM_KEY dsa1PubRef;
+ CSSM_KEY dsa2PubRef;
+ CSSM_KEY dsa1PubPartialRef;
+ CSSM_KEY dsa2PubPartialRef;
+ if(rawCSP && // CSPDL --> these were created as ref keys
+ !allRaw && // allRaw --> don't want ref keys
+ !allRef) { // allRef --> these were created as ref keys
+ if(cspRawKeyToRef(cspHand, &dsa1Pub, &dsa1PubRef) ||
+ cspRawKeyToRef(cspHand, &dsa2Pub, &dsa2PubRef)) {
+ exit(1);
+ }
+ }
+ if(!rawCSP || !allRaw) {
+ /* these were created in raw form unconditionally */
+ if(cspRawKeyToRef(cspHand, &dsa1PubPartial,
+ &dsa1PubPartialRef) ||
+ cspRawKeyToRef(cspHand, &dsa2PubPartial,
+ &dsa2PubPartialRef)) {
+ exit(1);
+ }
+
+ /* verify that these came back with the partial flag set */
+ if(!(dsa1PubPartialRef.KeyHeader.KeyAttr &
+ CSSM_KEYATTR_PARTIAL)) {
+ printf("***CSSM_KEYATTR_PARTIAL not set after null unwrap"
+ " of partial DSA key\n");
+ if(testError(quiet)) {
+ exit(1);
+ }
+ }
+ if(!(dsa2PubPartialRef.KeyHeader.KeyAttr &
+ CSSM_KEYATTR_PARTIAL)) {
+ printf("***CSSM_KEYATTR_PARTIAL not set after null unwrap"
+ " of partial DSA key\n");
+ if(testError(quiet)) {
+ exit(1);
+ }
+ }
+ }
+
+ int rtn = 0;
+ for(unsigned loop=0; loop<loops; loop++) {
+ /* four pub keys - raw or ref */
+ CSSM_KEY_PTR pubKey_a;
+ CSSM_KEY_PTR pubKey_b;
+ CSSM_KEY_PTR pubKeyPartial_a;
+ CSSM_KEY_PTR pubKeyPartial_b;
+ bool mergedIsRef;
+
+ if(allRef) {
+ /* raw CSP only - all ref keys */
+ /* base keys were generated as ref */
+ pubKey_a = &dsa1Pub;
+ pubKey_b = &dsa2Pub;
+ /* these alwasy generated as raw */
+ pubKeyPartial_a = &dsa1PubPartialRef;
+ pubKeyPartial_b = &dsa2PubPartialRef;
+ /* generated merged key ref too */
+ mergedIsRef = true;
+ }
+ else if(allRaw) {
+ /* raw CSP only - all raw keys */
+ pubKey_a = &dsa1Pub;
+ pubKey_b = &dsa2Pub;
+ pubKeyPartial_a = &dsa1PubPartial;
+ pubKeyPartial_b = &dsa2PubPartial;
+ /* generated merged key ref too */
+ mergedIsRef = false;
+ }
+ else if(!rawCSP) {
+ /* CSPDL - base keys are ref, partials are raw */
+ pubKey_a = &dsa1Pub;
+ pubKey_b = &dsa2Pub;
+ pubKeyPartial_a = &dsa1PubPartialRef;
+ pubKeyPartial_b = &dsa2PubPartialRef;
+ /* generated merged key ref too */
+ mergedIsRef = true;
+ }
+ else {
+ /* default: mix & match */
+ pubKey_a = (loop & 1) ? &dsa1Pub : &dsa1PubRef;
+ pubKey_b = (loop & 2) ? &dsa2Pub : &dsa2PubRef;
+ pubKeyPartial_a = (loop & 4) ?
+ &dsa1PubPartial : &dsa1PubPartialRef;
+ pubKeyPartial_b = (loop & 8) ?
+ &dsa2PubPartial : &dsa2PubPartialRef;
+ /* generated merged key different from partial_a*/
+ mergedIsRef = (loop & 2) ? true : false;
+ }
+
+ /* and two param keys - CSPDL requires raw, else the same as
+ * the "base" public key */
+ CSSM_KEY_PTR pubKeyParam_a = pubKey_a;
+ CSSM_KEY_PTR pubKeyParam_b = pubKey_b;
+ if(!rawCSP) {
+ pubKeyParam_a = &dsa1PubParam;
+ pubKeyParam_b = &dsa2PubParam;
+ }
+ if(!quiet) {
+ printf("...loop %u\n", loop);
+ }
+ rtn = doTest(cspHand, &dsa1Priv,
+ pubKey_a, pubKeyPartial_a, pubKeyParam_a,
+ pubKeyPartial_b, pubKeyParam_b,
+ mergedIsRef, quiet, verbose);
+ if(rtn) {
+ break;
+ }
+ if(doPause) {
+ fpurge(stdin);
+ printf("Hit CR to proceed, q to quit: ");
+ char inch = getchar();
+ if(inch == 'q') {
+ break;
+ }
+ }
+ }
+
+ /* cleanup */
+ return(rtn);
+}