PK11_EnterSlotMonitor(slot);
if (rwsession != CK_INVALID_SESSION) PK11_EnterSlotMonitor(slot); } if (rwsession == CK_INVALID_SESSION) { PK11_FreeSymKey(newKey); PORT_SetError(SEC_ERROR_BAD_DATA); return NULL;
PK11_UnwrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,		   CK_MECHANISM_TYPE wrapType, SECItem *param, 		   SECItem *wrappedKey, SECItem *label, 		   SECItem *idValue, PRBool perm, PRBool sensitive,		   CK_KEY_TYPE keyType, CK_ATTRIBUTE_TYPE *usage,		   int usageCount, void *wincx){    CK_BBOOL cktrue = CK_TRUE;    CK_BBOOL ckfalse = CK_FALSE;    CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;    CK_ATTRIBUTE keyTemplate[15] ;    int templateCount = 0;    CK_OBJECT_HANDLE privKeyID;    CK_MECHANISM mechanism;    CK_ATTRIBUTE *attrs = keyTemplate;    SECItem *param_free = NULL, *ck_id;    CK_RV crv;    CK_SESSION_HANDLE rwsession;    PK11SymKey *newKey = NULL;    int i;    if(!slot || !wrappedKey || !idValue) {	/* SET AN ERROR!!! */	return NULL;    }    ck_id = PK11_MakeIDFromPubKey(idValue);    if(!ck_id) {	return NULL;    }    PK11_SETATTRS(attrs, CKA_TOKEN, perm ? &cktrue : &ckfalse,					 sizeof(cktrue)); attrs++;    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++;    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++;    PK11_SETATTRS(attrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse,					 sizeof(cktrue)); attrs++;    PK11_SETATTRS(attrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse,					sizeof(cktrue)); attrs++;    PK11_SETATTRS(attrs, CKA_LABEL, label->data, label->len); attrs++;    PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len); attrs++;    for (i=0; i < usageCount; i++) {    	PK11_SETATTRS(attrs, usage[i], &cktrue, sizeof(cktrue)); attrs++;    }    if (PK11_IsInternal(slot)) {	PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, idValue->data, 		      idValue->len); attrs++;    }    templateCount = attrs - keyTemplate;    PR_ASSERT(templateCount <= (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)) );    mechanism.mechanism = wrapType;    if(!param) param = param_free= PK11_ParamFromIV(wrapType, NULL);    if(param) {	mechanism.pParameter = param->data;	mechanism.ulParameterLen = param->len;    } else {	mechanism.pParameter = NULL;	mechanism.ulParameterLen = 0;    }    if (wrappingKey->slot != slot) {	newKey = pk11_CopyToSlot(slot,wrapType,CKA_WRAP,wrappingKey);    } else {	newKey = PK11_ReferenceSymKey(wrappingKey);    }    if (newKey) {	if (perm) {	    /* Get RW Session will either lock the monitor if necessary, 	     *  or return a thread safe session handle. */ 	    rwsession = PK11_GetRWSession(slot);	} else {	    rwsession = slot->session;	    PK11_EnterSlotMonitor(slot);	}	crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession, &mechanism, 					 newKey->objectID,					 wrappedKey->data, 					 wrappedKey->len, keyTemplate, 					 templateCount, &privKeyID);	if (perm) {	    PK11_RestoreROSession(slot, rwsession);	} else {	    PK11_ExitSlotMonitor(slot);	}	PK11_FreeSymKey(newKey);    } else {	crv = CKR_FUNCTION_NOT_SUPPORTED;    }    if(ck_id) {	SECITEM_FreeItem(ck_id, PR_TRUE);	ck_id = NULL;    }    if (crv != CKR_OK) {	/* we couldn't unwrap the key, use the internal module to do the	 * unwrap, then load the new key into the token */	 PK11SlotInfo *int_slot = PK11_GetInternalSlot();	if (int_slot && (slot != int_slot)) {	    SECKEYPrivateKey *privKey = PK11_UnwrapPrivKey(int_slot,			wrappingKey, wrapType, param, wrappedKey, label,			idValue, PR_FALSE, PR_FALSE, 			keyType, usage, usageCount, wincx);	    if (privKey) {		SECKEYPrivateKey *newPrivKey = PK11_LoadPrivKey(slot,privKey,						NULL,perm,sensitive);		SECKEY_DestroyPrivateKey(privKey);		PK11_FreeSlot(int_slot);		return newPrivKey;	    }	}	if (int_slot) PK11_FreeSlot(int_slot);	PORT_SetError( PK11_MapError(crv) );	return NULL;    }    return PK11_MakePrivKey(slot, nullKey, PR_FALSE, privKeyID, wincx);}