X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/cspxutils/dhTest/dhTest.cpp diff --git a/SecurityTests/cspxutils/dhTest/dhTest.cpp b/SecurityTests/cspxutils/dhTest/dhTest.cpp new file mode 100644 index 00000000..3017eebf --- /dev/null +++ b/SecurityTests/cspxutils/dhTest/dhTest.cpp @@ -0,0 +1,468 @@ +/* + * dhTest - simple Diffie-Hellman exerciser. + */ +#include +#include +#include +#include "cspwrap.h" +#include "common.h" +#include +#include + +#define USAGE_DEF "noUsage" +#define LOOPS_DEF 10 +#define KEY_SIZE_DEF 512 +#define DERIVE_KEY_SIZE 128 +#define DERIVE_KEY_ALG CSSM_ALGID_AES + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf("Options:\n"); + printf(" k=keySize (default = %d)\n", KEY_SIZE_DEF); + printf(" l=loops (0=forever)\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" D (CSP/DL; default = bare CSP)\n"); + printf(" o=fileName (dump key and param blobs to filename)\n"); + printf(" i=filename (obtain param blobs from filename)\n"); + printf(" 8 (private key in PKCS8 format, default is PKCS3)\n"); + printf(" x (public key in X509 format, default is PKCS3)\n"); + printf(" f (public key is ref form; default is raw)\n"); + printf(" q(uiet)\n"); + printf(" v(erbose))\n"); + exit(1); +} + +/* + * Generate a Diffie-Hellman key pair. Optionally allows specification of + * algorithm parameters, and optionally returns algorithm parameters if + * we generate them. + */ +static int dhKeyGen( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR pubKey, + CSSM_KEY_PTR privKey, + const CSSM_DATA *inParams, // optional + CSSM_DATA_PTR outParams, // optional, we malloc + uint32 keySizeInBits, + CSSM_KEYBLOB_FORMAT privForm, + CSSM_KEYBLOB_FORMAT pubForm, + CSSM_BOOL pubIsRef, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA labelData = { strlen(USAGE_DEF), (uint8 *)USAGE_DEF }; + + if(inParams && outParams) { + printf("***dhKeyGen: inParams and outParams are mutually " + "exclusive.\n"); + return -1; + } + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + CSSM_ALGID_DH, + keySizeInBits, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + inParams, // Params, may be NULL + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateKeyGenContext", crtn); + return testError(quiet); + } + + if((inParams == NULL) && (outParams != NULL)) { + /* explicitly generate params and return them to caller */ + outParams->Data = NULL; + outParams->Length = 0; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySizeInBits, outParams); + if(crtn) { + printError("CSSM_GenerateAlgorithmParams", crtn); + return testError(quiet); + } + } + + uint32 privAttr = CSSM_KEYATTR_RETURN_REF; + uint32 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + if(privForm != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + privForm); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY" + "_FORMAT)", crtn); + return crtn; + } + privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + } + if(pubIsRef) { + pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; + } + else if(pubForm != CSSM_KEYBLOB_RAW_FORMAT_NONE) { + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, + sizeof(uint32), + CAT_Uint32, + NULL, + pubForm); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY" + "_FORMAT)", crtn); + return crtn; + } + } + crtn = CSSM_GenerateKeyPair(ccHand, + CSSM_KEYUSE_DERIVE, // only legal use of a Diffie-Hellman key + pubAttr, + &labelData, + pubKey, + /* private key specification */ + CSSM_KEYUSE_DERIVE, + privAttr, + &labelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(crtn) { + printError("CSSM_GenerateKeyPair", crtn); + return testError(quiet); + } + + CSSM_DeleteContext(ccHand); + return crtn; +} + +/* + * Perform Diffie-Hellman key exchange. + * Given "our" private key (in the form of a CSSM_KEY) and "their" public + * key (in the form of a raw blob of bytes), cook up a symmetric key. + */ +static int dhKeyExchange( + CSSM_CSP_HANDLE cspHand, + CSSM_KEY_PTR myPrivKey, + CSSM_KEY_PTR theirPubKey, + CSSM_KEY_PTR derivedKey, // RETURNED + uint32 deriveKeySizeInBits, + CSSM_ALGORITHMS derivedKeyAlg, + uint32 derivedKeyUsage, + uint32 derivedKeyAttr, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_CC_HANDLE ccHand; + CSSM_DATA labelData = { strlen(USAGE_DEF), (uint8 *)USAGE_DEF }; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + memset(derivedKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + CSSM_ALGID_DH, + derivedKeyAlg, + deriveKeySizeInBits, + &creds, + myPrivKey, // BaseKey + 0, // IterationCount + 0, // Salt + 0, // Seed + &ccHand); + if(crtn) { + printError("CSSM_CSP_CreateDeriveKeyContext", crtn); + return testError(quiet); + } + + /* + * Public key passed in as CSSM_DATA *Param - only if + * the pub key is in raw PKCS3 form + */ + CSSM_DATA nullParam = {0, NULL}; + CSSM_DATA_PTR paramPtr; + CSSM_KEYHEADER &hdr = theirPubKey->KeyHeader; + if((hdr.BlobType == CSSM_KEYBLOB_RAW) && + (hdr.Format == CSSM_KEYBLOB_RAW_FORMAT_PKCS3)) { + /* simple case */ + paramPtr = &theirPubKey->KeyData; + } + else { + /* add this pub key as a context attr */ + crtn = AddContextAttribute(ccHand, + CSSM_ATTRIBUTE_PUBLIC_KEY, + sizeof(CSSM_KEY), + CAT_Ptr, + (void *)theirPubKey, + 0); + if(crtn) { + printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY)", + crtn); + return crtn; + } + paramPtr = &nullParam; + } + crtn = CSSM_DeriveKey(ccHand, + paramPtr, + derivedKeyUsage, + derivedKeyAttr, + &labelData, + NULL, // cread/acl + derivedKey); + if(crtn) { + printError("CSSM_DeriveKey", crtn); + } + CSSM_DeleteContext(ccHand); + return crtn; +} + +int doTest( + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *inParams, // optional + CSSM_DATA_PTR outParams, // optional + uint32 keySizeInBits, + CSSM_KEYBLOB_FORMAT privForm, + CSSM_KEYBLOB_FORMAT pubForm, + CSSM_BOOL pubIsRef, + CSSM_BOOL quiet) +{ + CSSM_KEY myPriv; + CSSM_KEY myPub; + CSSM_KEY theirPriv; + CSSM_KEY theirPub; + int rtn = 0; + + /* generate two key pairs */ + if(dhKeyGen(cspHand, + &myPub, + &myPriv, + inParams, + outParams, + keySizeInBits, + privForm, + pubForm, + pubIsRef, + quiet)) { + return 1; + } + + /* note this MUST match the params either specified or generated in previous + * call */ + if((inParams == NULL) && (outParams == NULL)) { + printf("***BRRZAP! Must provide a way to match D-H parameters!\n"); + exit(1); + } + const CSSM_DATA *theParams = inParams; + if(theParams == NULL) { + theParams = outParams; + } + if(dhKeyGen(cspHand, + &theirPub, + &theirPriv, + theParams, + NULL, // outParams + keySizeInBits, + privForm, + pubForm, + pubIsRef, + quiet)) { + return 1; + } + + /* derive two keys, ensure they match */ + CSSM_KEY myDerive; + CSSM_KEY theirDerive; + if(dhKeyExchange(cspHand, + &myPriv, + &theirPub, + &myDerive, + DERIVE_KEY_SIZE, + DERIVE_KEY_ALG, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, + quiet)) { + return testError(quiet); + } + if(dhKeyExchange(cspHand, + &theirPriv, + &myPub, + &theirDerive, + DERIVE_KEY_SIZE, + DERIVE_KEY_ALG, + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, + quiet)) { + return testError(quiet); + } + + if(!appCompareCssmData(&myDerive.KeyData, &theirDerive.KeyData)) { + printf("***Key Exchange data miscompare***\n"); + rtn = testError(quiet); + } + cspFreeKey(cspHand, &myPub); + cspFreeKey(cspHand, &myPriv); + cspFreeKey(cspHand, &theirPub); + cspFreeKey(cspHand, &theirPriv); + cspFreeKey(cspHand, &myDerive); + cspFreeKey(cspHand, &theirDerive); + return rtn; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + CSSM_CSP_HANDLE cspHand; + unsigned loop; + int i; + CSSM_DATA inParams = {0, NULL}; + CSSM_DATA outParams = {0, NULL}; + CSSM_DATA_PTR inParamPtr = NULL; + CSSM_DATA_PTR outParamPtr = NULL; + + /* user-spec'd parameters */ + unsigned keySize = KEY_SIZE_DEF; + unsigned pauseInterval = 0; + unsigned loops = LOOPS_DEF; + CSSM_BOOL quiet = CSSM_FALSE; + CSSM_BOOL verbose = CSSM_FALSE; + CSSM_BOOL bareCsp = CSSM_TRUE; + char *inFileName = NULL; + char *outFileName = NULL; + /* default: "use default blob form", i.e., PKCS3 */ + CSSM_KEYBLOB_FORMAT privForm = CSSM_KEYBLOB_RAW_FORMAT_NONE; + CSSM_KEYBLOB_FORMAT pubForm = CSSM_KEYBLOB_RAW_FORMAT_NONE; + CSSM_BOOL pubIsRef = CSSM_FALSE; + + for(arg=1; arg