+++ /dev/null
-/*
- * Copyright (c) 2008 Apple Inc. All Rights Reserved.
- *
- * ecdhTest.cpp - Test Elliptic Curve Diffie-Hellman key exchange.
- *
- * Created Jan. 1 2008 by Doug Mitchell.
- */
-
-#include <stdlib.h>
-#include <strings.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <Security/cssm.h>
-#include "cspwrap.h"
-#include "common.h"
-
-#define LOOPS_DEF 32
-#define KEY_SIZE_DEF 256
-
-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(" X (X9.63 key derivation)\n");
- printf(" l=loops (0=forever)\n");
- printf(" D (CSP/DL; default = bare CSP)\n");
- printf(" q(uiet)\n");
- printf(" v(erbose))\n");
- exit(1);
-}
-
-#define LABEL_DEF "noLabel"
-#define MAX_SHARED_INFO_LEN 400
-#define MAX_DERIVED_SIZE 1024
-
-static int doECDH(
- CSSM_CSP_HANDLE cspHand,
- CSSM_KEY_PTR privKey,
- /*
- * pubKey:
- * Ref form - use key as pubKey as is
- * X509 form - use as is
- * OCTET_STRING form - use key data as Param
- */
- CSSM_KEY_PTR pubKey,
- CSSM_BOOL bareCsp, // false --> derive ref key and NULL-wrap it
- CSSM_BOOL x963KDF,
- CSSM_DATA *sharedInfo,
- uint32 deriveSizeInBits,
- CSSM_BOOL quiet,
- CSSM_BOOL verbose,
-
- /* result RETURNED here */
- CSSM_KEY_PTR derivedKey)
-
-{
- CSSM_DATA paramData = {0, NULL};
- CSSM_KEY_PTR contextPubKey = NULL;
- CSSM_KEYHEADER_PTR hdr = &pubKey->KeyHeader;
-
- if((hdr->BlobType == CSSM_KEYBLOB_RAW) &&
- (hdr->Format == CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING)) {
- paramData = pubKey->KeyData;
- }
- else {
- contextPubKey = pubKey;
- }
-
- /* create key derivation context */
- CSSM_RETURN crtn;
- CSSM_ACCESS_CREDENTIALS creds;
- CSSM_CC_HANDLE ccHand;
-
- memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-
- CSSM_ALGORITHMS deriveAlg;
- if(x963KDF) {
- deriveAlg = CSSM_ALGID_ECDH_X963_KDF;
- }
- else {
- deriveAlg = CSSM_ALGID_ECDH;
- }
-
- crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
- deriveAlg,
- CSSM_ALGID_RC4, // doesn't matter, just give us the bits
- deriveSizeInBits,
- &creds,
- privKey, // BaseKey
- 0, // IterationCount
- sharedInfo, // Salt
- 0, // Seed
- &ccHand);
- if(crtn) {
- printError("CSSM_CSP_CreateDeriveKeyContext", crtn);
- return testError(quiet);
- }
-
- if(contextPubKey != NULL) {
- /* add pub key as a context attr */
- crtn = AddContextAttribute(ccHand,
- CSSM_ATTRIBUTE_PUBLIC_KEY,
- sizeof(CSSM_KEY),
- CAT_Ptr,
- (void *)contextPubKey,
- 0);
- if(crtn) {
- printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY)",
- crtn);
- return crtn;
- }
- }
-
- /* D-H derive key */
- CSSM_DATA labelData = { strlen(LABEL_DEF), (uint8 *)LABEL_DEF };
- CSSM_KEYATTR_FLAGS keyAttr = bareCsp ?
- (CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE) :
- (CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE);
- memset(derivedKey, 0, sizeof(CSSM_KEY));
- crtn = CSSM_DeriveKey(ccHand,
- ¶mData,
- CSSM_KEYUSE_ANY,
- keyAttr,
- &labelData,
- NULL, // cread/acl
- derivedKey);
- if(crtn) {
- printError("CSSM_DeriveKey", crtn);
- }
- CSSM_DeleteContext(ccHand);
- if(crtn) {
- return testError(quiet);
- }
-
- if(!bareCsp) {
- /* Got a ref key, give caller raw */
- CSSM_KEY refKey = *derivedKey;
- crtn = cspRefKeyToRaw(cspHand, &refKey, derivedKey);
- cspFreeKey(cspHand, &refKey);
- }
- return 0;
-}
-
-/* define public key style */
-typedef enum {
- PKT_Ref, /* ref key */
- PKT_Wrap, /* generate ref key, wrap to OCTET_STRING */
- PKT_X509, /* raw key X509 format */
- PKT_Octet /* generate to OCTET_STRING form */
-} PubKeyType;
-
-#define BoolStr(v) (v ? "true " : "false")
-
-static const char *KeyStypeStr(
- PubKeyType keyType)
-{
- switch(keyType) {
- case PKT_Ref: return "Ref";
- case PKT_Wrap: return "Ref->Wrap";
- case PKT_X509: return "X509";
- case PKT_Octet: return "X9.62";
- default: return "BRRZAP";
- }
-}
-
-static int doTest(
- CSSM_CSP_HANDLE cspHand,
- CSSM_BOOL ourKeysRef, /* our keys are reference */
- CSSM_BOOL theirPrivKeyRef, /* their private key is reference */
- PubKeyType theirPubKeyType,
- unsigned keySizeBits,
- CSSM_BOOL bareCsp,
- CSSM_BOOL x963KDF,
- CSSM_BOOL useSharedInfo, /* use the optional SharedInfo for x963KDF */
- CSSM_BOOL verbose,
- CSSM_BOOL quiet)
-{
-
- CSSM_RETURN crtn;
- CSSM_KEY ourPriv;
- CSSM_KEY ourPub;
- bool ourKeysGend = false;
- bool theirKeysGend = false;
- bool wrappedTheirPub = false;
- bool wrappedOurPub = false;
- bool derivedKey1 = false;
- bool derivedKey2 = false;
- CSSM_DATA sharedInfo = {0, NULL};
- uint32 deriveSizeInBits;
-
- if(x963KDF) {
- /* arbitrary derived size */
- deriveSizeInBits = genRand(1, MAX_DERIVED_SIZE);
- }
- else {
- deriveSizeInBits = keySizeBits;
- }
- if(useSharedInfo) {
- /* length should be totally arbitrary */
- appSetupCssmData(&sharedInfo, MAX_SHARED_INFO_LEN);
- simpleGenData(&sharedInfo, 1, MAX_SHARED_INFO_LEN);
- }
-
-
- if(!quiet) {
- if(x963KDF) {
- printf("...sharedInfoLen %4lu deriveSize %4lu ",
- (unsigned long)sharedInfo.Length, (unsigned long)deriveSizeInBits);
- }
- else {
- printf("...");
- }
- printf("ourRef %s theirPrivRef %s theirPub %s\n",
- BoolStr(ourKeysRef), BoolStr(theirPrivKeyRef),
- KeyStypeStr(theirPubKeyType));
- }
-
- crtn = cspGenKeyPair(cspHand, CSSM_ALGID_ECDSA,
- LABEL_DEF, strlen(LABEL_DEF), keySizeBits,
- &ourPub, ourKeysRef, CSSM_KEYUSE_DERIVE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
- &ourPriv, ourKeysRef, CSSM_KEYUSE_DERIVE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
- CSSM_FALSE);
- if(crtn) {
- return testError(quiet);
- }
- ourKeysGend = true;
-
- CSSM_KEY theirPriv;
- CSSM_KEY theirPub; /* the generated one */
- CSSM_KEY theirWrappedPub; /* optional NULL unwrap */
- CSSM_KEY_PTR theirPubPtr;
- CSSM_KEY ourWrappedPub; /* optional NULL unwrap */
- CSSM_KEY_PTR ourPubPtr;
- CSSM_KEY derived1;
- CSSM_KEY derived2;
- CSSM_BOOL pubIsRef = CSSM_FALSE;
- CSSM_KEYBLOB_FORMAT blobForm = CSSM_KEYBLOB_RAW_FORMAT_NONE;
- int ourRtn = 0;
-
- switch(theirPubKeyType) {
- case PKT_Ref:
- case PKT_Wrap:
- pubIsRef = CSSM_TRUE;
- break;
- case PKT_X509:
- pubIsRef = CSSM_FALSE;
- break;
- case PKT_Octet:
- pubIsRef = CSSM_FALSE;
- blobForm = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
- break;
- }
-
- crtn = cspGenKeyPair(cspHand, CSSM_ALGID_ECDSA,
- LABEL_DEF, strlen(LABEL_DEF), keySizeBits,
- &theirPub, pubIsRef, CSSM_KEYUSE_DERIVE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
- &theirPriv, theirPrivKeyRef, CSSM_KEYUSE_DERIVE, CSSM_KEYBLOB_RAW_FORMAT_NONE,
- CSSM_FALSE);
- if(crtn) {
- ourRtn = testError(quiet);
- goto errOut;
- }
-
- if(theirPubKeyType == PKT_Wrap) {
- /*
- * This test mode is here mainly to ring out the key wrap and
- * OCTET_STRING format functionality in the CrypkitCSP, it's
- * not really relevant to ECDH...
- */
- crtn = cspRefKeyToRawWithFormat(cspHand, &theirPub,
- CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, &theirWrappedPub);
- if(crtn) {
- ourRtn = testError(quiet);
- goto errOut;
- }
- theirPubPtr = &theirWrappedPub;
- wrappedTheirPub = true;
- }
- else {
- theirPubPtr = &theirPub;
- }
-
- if(!bareCsp) {
- /*
- * For CSPDL, convert our pub key to OCTET_STRING format so it
- * is sent as a Param - can't send a ref key (or any other pub
- * key) in the context
- */
- crtn = cspRefKeyToRawWithFormat(cspHand, &ourPub,
- CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING, &ourWrappedPub);
- if(crtn) {
- ourRtn = testError(quiet);
- goto errOut;
- }
- ourPubPtr = &ourWrappedPub;
- wrappedOurPub = true;
- }
- else {
- ourPubPtr = &ourPub;
- }
-
- /*
- * Here we go, do the two sides of D-H key agreement, results to
- * to CSSM_KEYs.
- */
- ourRtn = doECDH(cspHand, &ourPriv, theirPubPtr, bareCsp,
- x963KDF, useSharedInfo ? &sharedInfo : NULL,
- deriveSizeInBits, quiet, verbose, &derived1);
- if(ourRtn) {
- goto errOut;
- }
- ourRtn = doECDH(cspHand, &theirPriv, ourPubPtr, bareCsp,
- x963KDF, useSharedInfo ? &sharedInfo : NULL,
- deriveSizeInBits, quiet, verbose, &derived2);
- if(ourRtn) {
- goto errOut;
- }
-
- if(!appCompareCssmData(&derived1.KeyData, &derived2.KeyData)) {
- printf("***Data Miscompare on ECDH key derivation\n");
- }
-errOut:
- if(ourKeysGend) {
- cspFreeKey(cspHand, &ourPub);
- cspFreeKey(cspHand, &ourPriv);
- }
- if(theirKeysGend) {
- cspFreeKey(cspHand, &theirPub);
- cspFreeKey(cspHand, &theirPriv);
- }
- if(wrappedTheirPub) {
- cspFreeKey(cspHand, &theirWrappedPub);
- }
- if(wrappedOurPub) {
- cspFreeKey(cspHand, &ourWrappedPub);
- }
- if(derivedKey1) {
- cspFreeKey(cspHand, &derived1);
- }
- if(derivedKey2) {
- cspFreeKey(cspHand, &derived2);
- }
- if(sharedInfo.Data != NULL) {
- appFreeCssmData(&sharedInfo, CSSM_FALSE);
- }
- return ourRtn;
-}
-
-int main(int argc, char **argv)
-{
- int arg;
- char *argp;
- CSSM_CSP_HANDLE cspHand;
- unsigned loop;
- int ourRtn = 0;
-
- unsigned keySize = KEY_SIZE_DEF;
- unsigned loops = LOOPS_DEF;
- CSSM_BOOL quiet = CSSM_FALSE;
- CSSM_BOOL verbose = CSSM_FALSE;
- CSSM_BOOL bareCsp = CSSM_TRUE;
- CSSM_BOOL x963KDF = CSSM_FALSE;
-
- for(arg=1; arg<argc; arg++) {
- argp = argv[arg];
- switch(argp[0]) {
- case 'k':
- keySize = atoi(&argp[2]);
- break;
- case 'X':
- x963KDF = true;
- break;
- case 'l':
- loops = atoi(&argp[2]);
- break;
- case 'D':
- bareCsp = CSSM_FALSE;
- break;
- case 'q':
- quiet = CSSM_TRUE;
- break;
- case 'v':
- verbose = CSSM_TRUE;
- break;
- default:
- usage(argv);
- }
- }
- testStartBanner("ecdhTest", argc, argv);
-
- cspHand = cspDlDbStartup(bareCsp, NULL);
- if(cspHand == 0) {
- exit(1);
- }
-
- for(loop=1; ; loop++) {
- if(!quiet) {
- printf("...Loop %d\n", loop);
- }
-
- /* test mode from l.s. bits of loop counter */
-
- CSSM_BOOL ourKeysRef = (loop & 0x04) ? CSSM_TRUE : CSSM_FALSE;
- CSSM_BOOL theirPrivKeyRef = (loop & 0x08) ? CSSM_TRUE : CSSM_FALSE;
- PubKeyType theirPubKeyType;
- switch(loop & 0x03) {
- case 0:
- theirPubKeyType = PKT_Ref;
- break;
- case 1:
- theirPubKeyType = PKT_Wrap;
- break;
- case 2:
- theirPubKeyType = PKT_X509;
- break;
- default:
- theirPubKeyType = PKT_Octet;
- break;
- }
-
- if(!bareCsp) {
- /*
- * Generated keys have to be reference
- * pub keys have to be passed as Param
- */
- ourKeysRef = CSSM_TRUE;
- theirPrivKeyRef = CSSM_TRUE;
- theirPubKeyType = PKT_Wrap;
- }
-
- CSSM_BOOL useSharedInfo = CSSM_FALSE;
- if(x963KDF & ((loop & 0x01) == 0)) {
- useSharedInfo = CSSM_TRUE;
- }
- ourRtn = doTest(cspHand, ourKeysRef, theirPrivKeyRef, theirPubKeyType,
- keySize, bareCsp, x963KDF, useSharedInfo, verbose, quiet);
- if(ourRtn) {
- break;
- }
- if(loops && (loop == loops)) {
- break;
- }
- }
- CSSM_ModuleDetach(cspHand);
- if((ourRtn == 0) && !quiet) {
- printf("OK\n");
- }
-
- return ourRtn;
-}