X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/cspxutils/wrapTest/wrapTest.c?ds=sidebyside diff --git a/SecurityTests/cspxutils/wrapTest/wrapTest.c b/SecurityTests/cspxutils/wrapTest/wrapTest.c new file mode 100644 index 00000000..b3a7bc6e --- /dev/null +++ b/SecurityTests/cspxutils/wrapTest/wrapTest.c @@ -0,0 +1,1077 @@ +/* Copyright (c) 1998,2003-2005,2008 Apple Inc. + * + * wrapTest.c - wrap/unwrap exerciser. + * + * Revision History + * ---------------- + * 4 May 2000 Doug Mitchell + * Ported to X/CDSA2. + * 6 Aug 1998 Doug Mitchell at Apple + * Created. + */ + +#include +#include +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include "cspdlTesting.h" + +/* + * Currently the CSP can use wrapping keys flagged exclusively for wrapping + * (CSSM_KEYUSE_{WRAP,UNWRAP} for the actual wrap sinceÊthe wrp/unwrap op is + * done with an encrypt/decrypt op. The WrapKey op doesn't even see the + * wrapping key - it's in the context we pass it. Thus for now wrap/unwrap + * keys have to be marked with CSSM_KEYUSE_ANY. + */ +#define WRAP_USAGE_ANY 0 + +/* + * When false, the CMS wrap algorithm can't deal with RSA encryption - we + * have to encrypt something twice with the same key. An impossibility with + * BSAFE-based RSA encryption because the output of the first encrypt is + * the size of the key modulus, and you can't encrypt something that big + * with that key. + * This is not a limitation with openssl-based RSA. + */ +#define WRAP_WITH_RSA 1 + +/* + * When false, can't wrap with RC4 because the RC4 context is stateful + * but doesn't get reinit'd for the second CMS encrypt. + */ +#define WRAP_WITH_RC4 1 + +/* + * Temporary hack to use CSSM_KEYBLOB_WRAPPED_FORMAT_{PKCS7,PKCS8}, which + * are no longer supported as of 7/28/00 + */ +#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 + +/* + * Enumerate algorithms our way to allow loop interations. + */ +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); +} + +/* wrapped format to string */ +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) { + /* GUIDs must match */ + if(memcmp(&srcHdr->CspId, &dstHdr->CspId, sizeof(CSSM_GUID))) { + printf("***%s.CspId mismatch\n", op); + if(testError(quiet)) { + return 1; + } + } + } + else { + /* CSPDL - GUIDs do NOT match - ref keys are in the CSPDL's domain; + * wrapped keys are in the bare CSP's domain. */ + 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 + +/* not all algs need this */ +CSSM_DATA initVector = {16, (uint8 *)"SomeReallyStrangeInitVect"}; + +static int doTest(CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR encrKey, + CSSM_BOOL wrapEncrKey, // wrap encrKey before using + CSSM_KEY_PTR decrKey, // we wrap this one + CSSM_KEY_PTR wrappingKey, // ...using this key + CSSM_KEY_PTR unwrappingKey, + CSSM_ALGORITHMS wrapAlg, + CSSM_ENCRYPT_MODE wrapMode, + CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8, APPLE_CUSTOM + CSSM_KEYBLOB_FORMAT expectFormat, // PKCS7, PKCS8, APPLE_CUSTOM + CSSM_PADDING wrapPad, + uint32 wrapIvSize, + CSSM_ALGORITHMS encrAlg, + CSSM_ENCRYPT_MODE encrMode, + CSSM_PADDING encrPad, + uint32 encrIvSize, + uint32 effectiveKeySizeInBits, // for encr/decr - 0 means none specified + 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}; // for encr key + CSSM_DATA outDescData2 = {0, NULL}; // for decr key, must match descData + CSSM_DATA nullInitVect = {0, NULL}; // for custom unwrap + CSSM_DATA_PTR wrapIvp; + CSSM_DATA_PTR encrIvp; + + /* Hack to deal with RSA's max encrypt size */ + #if 0 + /* no more */ + 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); + + /* + * Optionaly wrap/unwrap encrKey. If encrKey is a ref key, do a + * NULL wrap. If encrKey is a raw key, do a NULL unwrap. + */ + if(wrapEncrKey) { + CSSM_KEYBLOB_TYPE expectBlob; + + if(encrKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) { + crtn = cspWrapKey(cspHand, + encrKey, + NULL, // wrappingKey + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + wrapFormat, + CSSM_PADDING_NONE, + NULL, // iv + descData, + &wrappedEncrKey); + expectBlob = CSSM_KEYBLOB_RAW; + } + else { + crtn = cspUnwrapKey(cspHand, + encrKey, + NULL, // unwrappingKey + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + CSSM_PADDING_NONE, + NULL, // iv + &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; + } + /* encrypt using actualEncrKey ==> ctext */ + ctext.Data = NULL; + ctext.Length = 0; + if(encrIvSize) { + initVector.Length = encrIvSize; + encrIvp = &initVector; + } + else { + encrIvp = NULL; + } + crtn = cspEncrypt(cspHand, + encrAlg, + encrMode, + encrPad, + actualEncrKey, + NULL, // no 2nd key + effectiveKeySizeInBits, + 0, // rounds + encrIvp, + ptext, + &ctext, + CSSM_TRUE); // mallocCtext + if(crtn) { + return testError(quiet); + } + /* wrap decrKey using wrappingKey ==> wrappedDecrKey */ + /* Note that APPLE_CUSTOM wrap alg REQUIRES an 8-byte IV */ + 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) { + /* special case - no IV needed - test it */ + wrapIvp = &nullInitVect; + } + else { + wrapIvp = &initVector; + initVector.Length = wrapIvSize; + } + + /* unwrap wrappedDecrKey using unwrappingKey ==> unwrappedDecrKey; */ + 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; + } + + /* compare descData to outDescData2 */ + 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; + } + } + } + + /* decrypt ctext with unwrappedDecrKey ==> rptext; */ + rptext.Data = NULL; + rptext.Length = 0; + if(encrIvSize) { + initVector.Length = encrIvSize; + } + crtn = cspDecrypt(cspHand, + encrAlg, + encrMode, + encrPad, + &unwrappedDecrKey, + NULL, // no 2nd key + effectiveKeySizeInBits, + 0, // rounds + &initVector, + &ctext, + &rptext, + CSSM_TRUE); + if(crtn) { + return testError(quiet); + } + /* compare ptext vs. rptext; */ + 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); + } + /* free resources */ + 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; +} + +/* + * values associated with a private algorithm (e.g., ALG_DES). + */ +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; // in bytes; 0 means no IV + const char *algName; +} AlgInfo; + +/* + * Convert our private alg to CDSA keygen alg, encr alg, encr mode, pad + */ +static void getAlgInfo(PrivAlg privAlg, // e.g., ALG_DES + 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; +} + +/* argv letter to private alg */ +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; + } +} + +/* + * Null wrapping of symmetric keys now allowed + */ +#define SYMM_NULL_WRAP_ENABLE 1 + +/* indices into algInfo[] */ +#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; // well aligned + uint32 wrapKeySizeBits; + uint32 effectiveKeySizeInBits; // for encr, may be odd + int rtn = 0; + uint32 maxRsaKeySize = 1024; + uint32 maxFeeKeySize = 192; + CSSM_KEYBLOB_FORMAT wrapFormat; // NONE, PKCS7, PKCS8, APPLE_CUSTOM + CSSM_KEYBLOB_FORMAT expectFormat; // PKCS7, PKCS8, APPLE_CUSTOM + CSSM_DATA descData = {0, NULL}; + CSSM_DATA_PTR descDataP; + + /* + * key pointers passed to doTest() - for symmetric algs, the pairs + * might point to the same key + */ + CSSM_KEY_PTR encrKeyPtr; + CSSM_KEY_PTR decrKeyPtr; + CSSM_KEY_PTR wrapKeyPtr; + CSSM_KEY_PTR unwrapKeyPtr; + + /* persistent asymmetric keys - symm keys are dynamically allocated */ + CSSM_KEY pubEncrKey; + CSSM_KEY privEncrKey; + CSSM_KEY pubWrapKey; + CSSM_KEY privWrapKey; + + /* we iterate these values thru all possible algs */ + PrivAlg privEncrAlg; // ALG_xxx + PrivAlg privWrapAlg; + + /* two AlgInfo which contain everything we need to know per alg */ + AlgInfo algInfo[2]; + AlgInfo *encrInfo; + AlgInfo *wrapInfo; + CSSM_BOOL wrapEncrKey = CSSM_FALSE; // varies loop-to-loop + CSSM_BOOL encrKeyIsRef = CSSM_TRUE; // ditto + + CSSM_BOOL genSeed; // for FEE key gen + int i; + + /* user-specified vars */ + 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; argkeyGenAlg, OT_Encrypt); + if(!refKeysOnly) { + encrKeyIsRef = (loop & 2) ? CSSM_TRUE : CSSM_FALSE; + } + + switch(encrInfo->wtype) { + case WT_Symmetric: + /* round up to even byte */ + 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 + /* wrapEncrKey every other loop */ + if(!refKeysOnly) { + wrapEncrKey = (loop & 1) ? CSSM_TRUE : CSSM_FALSE; + } + #else + wrapEncrKey = CSSM_FALSE; + #endif /* SYMM_NULL_WRAP_ENABLE */ + break; + case WT_Asymmetric: + /* handle alg-specific cases */ + 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; // i.e., not specified + crtn = cspGenKeyPair(cspHand, + encrInfo->keyGenAlg, + ENCR_LABEL, + ENCR_LABEL_LEN, + encrKeySizeBits, + &pubEncrKey, + encrKeyIsRef, // pubIsRef + CSSM_KEYUSE_ENCRYPT, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &privEncrKey, + CSSM_TRUE, // privIsRef + CSSM_KEYUSE_DECRYPT, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + genSeed); + if(crtn) { + rtn = testError(quiet); + goto testDone; + } + encrKeyPtr = &pubEncrKey; + decrKeyPtr = &privEncrKey; + /* wrapEncrKey every other loop */ + 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); + } + /* iterate thru all wrap algs */ + for(privWrapAlg=minWrapAlg; privWrapAlg<=maxWrapAlg; privWrapAlg++) { + /* handle disabled algs */ + if((privWrapAlg == ALG_AES) && (privEncrAlg == ALG_FEEDEXP)) { + /* + * Can't do it. FEED can't do PKCS8 because it doesn't + * support PKCS8 private key format, and AES can't + * do APPLE_CUSTOM because AES needs a 16-byte IV. + */ + continue; + } + /* any other restrictions/ */ + + /* generate wrapping key(s) */ + getAlgInfo(privWrapAlg, wrapInfo); + switch(wrapInfo->wtype) { + case WT_Symmetric: + /* note we can't do odd-size wrapping keys */ + 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, // pubIsRef + WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_WRAP, + CSSM_KEYBLOB_RAW_FORMAT_NONE, + &privWrapKey, + CSSM_TRUE, // privIsRef + 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) { + /* can't do null wrap of symmetric key */ + continue; + } + #endif + wrapKeySizeBits = 0; + wrapKeyPtr = NULL; + unwrapKeyPtr = NULL; + break; + } + + /* special case for 3DES/3DES */ + #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 + + /* cook up a wrapFormat - every other loop use default, others + * specify a reasonable one */ + if(wrapInfo->wtype == WT_Null) { + wrapFormat = expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; + } + else if((loop & 1)) { + /* + * FORMAT_NONE - default - figure out expected format; + * this has to track CSP behavior + */ + 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: + /* NULL encr not done */ + printf("**GAK! Internal error\n"); + } + } + else { + /* pick a good explicit one - this encapsulates the + * range of legal wrap formats per wrap/encrypt alg */ + int die = loop & 2; + switch(encrInfo->wtype) { + case WT_Symmetric: + if(privWrapAlg == ALG_AES) { + /* can't do APPLE_CUSTOM - 16 byte IV */ + 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: + /* Can't wrap FEE key with AES no way, no how - + * this is detected at the top of the privWrapAlg + * loop + */ + if(privEncrAlg == ALG_FEEDEXP) { + /* FEE doesn't do PKCS8 private key format */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + } + else if(die) { + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; + } + else if(privWrapAlg == ALG_AES) { + /* AES can't do APPLE_CUSTOM - 16 byte IV */ + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; + } + else { + wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; + } + break; + default: + /* NULL encr not done */ + printf("***GAK! Internal error\n"); + exit(1); + } + expectFormat = wrapFormat; + } + + /* + * If wrapping with apple custom - either by default or + * explicitly - generate some descriptive data. + */ + 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)); + } + /* OK, here we go! */ + 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; + } + /* end of wrap alg loop - free/delete wrap key(s) */ + switch(wrapInfo->wtype) { + case WT_Symmetric: + cspFreeKey(cspHand, wrapKeyPtr); + /* mallocd by cspGenSymKey */ + CSSM_FREE(wrapKeyPtr); + break; + case WT_Asymmetric: + cspFreeKey(cspHand, wrapKeyPtr); + cspFreeKey(cspHand, unwrapKeyPtr); + break; + default: + break; + } + } /* for wrapAlg */ + /* end of encr alg loop - free encr key(s) */ + cspFreeKey(cspHand, encrKeyPtr); + if(encrInfo->wtype == WT_Symmetric) { + /* mallocd by cspGenSymKey */ + 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; +}