symKey = pk11_CreateSymKey(slot,target,!isPerm,baseKey->cx);
symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, baseKey->cx);
pk11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, 	SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 	int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs,							 PRBool isPerm){    PK11SlotInfo *  slot	= baseKey->slot;    PK11SymKey *    symKey;    PK11SymKey *    newBaseKey	= NULL;    CK_BBOOL        cktrue	= CK_TRUE;     CK_OBJECT_CLASS keyClass	= CKO_SECRET_KEY;    CK_KEY_TYPE     keyType	= CKK_GENERIC_SECRET;    CK_ULONG        valueLen	= 0;    CK_MECHANISM    mechanism;     CK_RV           crv;    CK_ATTRIBUTE    keyTemplate[MAX_TEMPL_ATTRS];    CK_ATTRIBUTE *  attrs	= keyTemplate;    CK_SESSION_HANDLE session;    unsigned int    templateCount;    if (numAttrs > MAX_TEMPL_ATTRS) {    	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return NULL;    }    /* first copy caller attributes in. */    for (templateCount = 0; templateCount < numAttrs; ++templateCount) {    	*attrs++ = *userAttr++;    }    /* We only add the following attributes to the template if the caller    ** didn't already supply them.    */    if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) {	PK11_SETATTRS(attrs, CKA_CLASS,     &keyClass, sizeof keyClass); 	attrs++;    }    if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) {	keyType = PK11_GetKeyType(target, keySize);	PK11_SETATTRS(attrs, CKA_KEY_TYPE,  &keyType,  sizeof keyType ); 	attrs++;    }    if (keySize > 0 &&    	  !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) {	valueLen = (CK_ULONG)keySize;	PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); 	attrs++;    }    if ((operation != CKA_FLAGS_ONLY) &&	  !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) {	PK11_SETATTRS(attrs, operation, &cktrue, sizeof cktrue); attrs++;    }    templateCount = attrs - keyTemplate;    PR_ASSERT(templateCount <= MAX_TEMPL_ATTRS);    /* move the key to a slot that can do the function */    if (!PK11_DoesMechanism(slot,derive)) {	/* get a new base key & slot */	PK11SlotInfo *newSlot = PK11_GetBestSlot(derive, baseKey->cx);	if (newSlot == NULL) return NULL;        newBaseKey = pk11_CopyToSlot (newSlot, derive, CKA_DERIVE, 				     baseKey);	PK11_FreeSlot(newSlot);	if (newBaseKey == NULL) 	    return NULL;		baseKey = newBaseKey;	slot = baseKey->slot;    }    /* get our key Structure */    symKey = pk11_CreateSymKey(slot,target,!isPerm,baseKey->cx);    if (symKey == NULL) {	return NULL;    }    symKey->size = keySize;    mechanism.mechanism = derive;    if (param) {	mechanism.pParameter = param->data;	mechanism.ulParameterLen = param->len;    } else {	mechanism.pParameter = NULL;	mechanism.ulParameterLen = 0;    }    symKey->origin=PK11_OriginDerive;    if (isPerm) {	session =  PK11_GetRWSession(slot);    } else {        pk11_EnterKeyMonitor(symKey);	session = symKey->session;    }    if (session == CK_INVALID_SESSION) {	if (!isPerm)	    pk11_ExitKeyMonitor(symKey);	crv = CKR_SESSION_HANDLE_INVALID;    } else {	crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism,	     baseKey->objectID, keyTemplate, templateCount, &symKey->objectID);	if (isPerm) {	    PK11_RestoreROSession(slot, session);	} else {	    pk11_ExitKeyMonitor(symKey);	}    }    if (newBaseKey)     	PK11_FreeSymKey(newBaseKey);    if (crv != CKR_OK) {	PK11_FreeSymKey(symKey);	return NULL;    }    return symKey;}