symKey = pk11_CreateSymKey(slot,target,PR_TRUE,wincx);
symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx);
PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,    PRBool isSender, SECItem *randomA, SECItem *randomB,     CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,			CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx){    PK11SlotInfo *slot = privKey->pkcs11Slot;    CK_MECHANISM mechanism;    PK11SymKey *symKey;    CK_RV crv;    if (rb_email == NULL) {	rb_email = PORT_ZAlloc(128);	if (rb_email == NULL) {	    return NULL;	}	rb_email[127] = 1;    }    /* get our key Structure */    symKey = pk11_CreateSymKey(slot,target,PR_TRUE,wincx);    if (symKey == NULL) {	return NULL;    }    symKey->origin = PK11_OriginDerive;    switch (privKey->keyType) {    case rsaKey:    case nullKey:	PORT_SetError(SEC_ERROR_BAD_KEY);	break;    case dsaKey:    case keaKey:    case fortezzaKey:	{	    CK_KEA_DERIVE_PARAMS param;	    param.isSender = (CK_BBOOL) isSender;	    param.ulRandomLen = randomA->len;	    param.pRandomA = randomA->data;	    param.pRandomB = rb_email;	    if (randomB)		 param.pRandomB = randomB->data;	    if (pubKey->keyType == fortezzaKey) {		param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;		param.pPublicData = pubKey->u.fortezza.KEAKey.data;	    } else {		/* assert type == keaKey */		/* XXX change to match key key types */		param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;		param.pPublicData = pubKey->u.fortezza.KEAKey.data;	    }	    mechanism.mechanism = derive;	    mechanism.pParameter = &param;	    mechanism.ulParameterLen = sizeof(param);	    /* get a new symKey structure */	    pk11_EnterKeyMonitor(symKey);	    crv=PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,			privKey->pkcs11ID, NULL, 0, &symKey->objectID);	    pk11_ExitKeyMonitor(symKey);	    if (crv == CKR_OK) return symKey;	    PORT_SetError( PK11_MapError(crv) );	}	break;    case dhKey:	{	    CK_BBOOL cktrue = CK_TRUE;	    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;	    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;	    CK_ULONG key_size = 0;	    CK_ATTRIBUTE keyTemplate[4];	    int templateCount;	    CK_ATTRIBUTE *attrs = keyTemplate;	    if (pubKey->keyType != dhKey) {		PORT_SetError(SEC_ERROR_BAD_KEY);		break;	    }	    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));	    attrs++;	    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));	    attrs++;	    PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++;	    PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); 	    attrs++;	    templateCount =  attrs - keyTemplate;	    PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));	    keyType = PK11_GetKeyType(target,keySize);	    key_size = keySize;	    symKey->size = keySize;	    if (key_size == 0) templateCount--;	    mechanism.mechanism = derive;	    /* we can undefine these when we define diffie-helman keys */	    mechanism.pParameter = pubKey->u.dh.publicValue.data; 	    mechanism.ulParameterLen = pubKey->u.dh.publicValue.len;			    pk11_EnterKeyMonitor(symKey);	    crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,	     privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID);	    pk11_ExitKeyMonitor(symKey);	    if (crv == CKR_OK) return symKey;	    PORT_SetError( PK11_MapError(crv) );	}	break;    case ecKey:        {	    CK_BBOOL cktrue = CK_TRUE;	    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;	    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;	    CK_ULONG key_size = 0;	    CK_ATTRIBUTE keyTemplate[4];	    int templateCount;	    CK_ATTRIBUTE *attrs = keyTemplate;	    CK_ECDH1_DERIVE_PARAMS *mechParams = NULL;	    if (pubKey->keyType != ecKey) {		PORT_SetError(SEC_ERROR_BAD_KEY);		break;	    }	    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));	    attrs++;	    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));	    attrs++;	    PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++;	    PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); 	    attrs++;	    templateCount =  attrs - keyTemplate;	    PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE));	    keyType = PK11_GetKeyType(target,keySize);	    key_size = keySize;	    symKey->size = keySize;	    if (key_size == 0) templateCount--;	    mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); 	    mechParams->kdf = CKD_SHA1_KDF;	    mechParams->ulSharedDataLen = 0;	    mechParams->pSharedData = NULL;	    mechParams->ulPublicDataLen =  pubKey->u.ec.publicValue.len;	    mechParams->pPublicData =  pubKey->u.ec.publicValue.data;	    mechanism.mechanism = derive;	    mechanism.pParameter = mechParams;	    mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);	    pk11_EnterKeyMonitor(symKey);	    crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, 		&mechanism, privKey->pkcs11ID, keyTemplate, 		templateCount, &symKey->objectID);	    pk11_ExitKeyMonitor(symKey);	    PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));	    if (crv == CKR_OK) return symKey;	    PORT_SetError( PK11_MapError(crv) );	}   }   PK11_FreeSymKey(symKey);   return NULL;}