context->cipherInfo = &(privKey->u.dsa);
context->cipherInfo = privKey;
CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,		 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey){    PK11Session *session;    PK11Object *key;    PK11SessionContext *context;    CK_KEY_TYPE key_type;    CK_RV crv = CKR_OK;    SECKEYLowPrivateKey *privKey;    PK11HashSignInfo *info = NULL;    /* Block Cipher MACing Algorithms use a different Context init method..*/    crv = pk11_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, PK11_SIGN);    if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;    /* we're not using a block cipher mac */    session = pk11_SessionFromHandle(hSession);    if (session == NULL) return CKR_SESSION_HANDLE_INVALID;    crv = pk11_InitGeneric(session,&context,PK11_SIGN,&key,hKey,&key_type,						CKO_PRIVATE_KEY,CKA_SIGN);    if (crv != CKR_OK) {	pk11_FreeSession(session);	return crv;    }    context->multi = PR_FALSE;    switch(pMechanism->mechanism) {    case CKM_MD5_RSA_PKCS:        context->multi = PR_TRUE;	crv = pk11_doSubMD5(context);	if (crv != CKR_OK) break;	context->update = (PK11Cipher) pk11_HashSign;	info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));	if (info == NULL) {	   crv = CKR_HOST_MEMORY;	   break;	}	info->hashOid = SEC_OID_MD5;	goto finish_rsa;    case CKM_MD2_RSA_PKCS:        context->multi = PR_TRUE;	crv = pk11_doSubMD2(context);	if (crv != CKR_OK) break;	context->update = (PK11Cipher) pk11_HashSign;	info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));	if (info == NULL) {	   crv = CKR_HOST_MEMORY;	   break;	}	info->hashOid = SEC_OID_MD2;	goto finish_rsa;    case CKM_SHA1_RSA_PKCS:        context->multi = PR_TRUE;	crv = pk11_doSubSHA1(context);	if (crv != CKR_OK) break;	context->update = (PK11Cipher) pk11_HashSign;	info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));	if (info == NULL) {	   crv = CKR_HOST_MEMORY;	   break;	}	info->hashOid = SEC_OID_SHA1;	goto finish_rsa;    case CKM_RSA_PKCS:	context->update = (PK11Cipher) RSA_Sign;	goto finish_rsa;    case CKM_RSA_X_509:	context->update = (PK11Cipher)  RSA_SignRaw;finish_rsa:	if (key_type != CKK_RSA) {	    if (info) PORT_Free(info);	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	context->multi = PR_FALSE;	privKey = pk11_GetPrivKey(key,CKK_RSA);	if (privKey == NULL) {	    if (info) PORT_Free(info);	    crv = CKR_HOST_MEMORY;	    break;	}	/* OK, info is allocated only if we're doing hash and sign mechanism.	 * It's necessary to be able to set the correct OID in the final 	 * signature.	 * Second, what's special about privKey == key->objectInfo?	 * Well we don't 'cache' token versions	 * of private keys because (1) it's sensitive data, and (2) it never	 * gets destroyed. Instead we grab the key out of the database as	 * necessary, but now the key is our context, and we need to free	 * it when we are done. Non-token private keys will get freed when	 * the user destroys the session object (or the session the session	 * object lives in) */	if (info) {	    info->key = privKey;	    context->cipherInfo = info;	    context->destroy = (privKey == key->objectInfo) ?		(PK11Destroy)pk11_Space:(PK11Destroy)pk11_FreeSignInfo;	} else {	    context->cipherInfo = privKey;	    context->destroy = (privKey == key->objectInfo) ?		(PK11Destroy)pk11_Null:(PK11Destroy)pk11_FreePrivKey;	}	break;    case CKM_DSA_SHA1:        context->multi = PR_TRUE;	crv = pk11_doSubSHA1(context);	if (crv != CKR_OK) break;	/* fall through */    case CKM_DSA:	if (key_type != CKK_DSA) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	privKey = pk11_GetPrivKey(key,CKK_DSA);	if (privKey == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	context->cipherInfo = &(privKey->u.dsa);	context->update     = (PK11Cipher) nsc_DSA_Sign_Stub;	context->destroy    = pk11_Null;        if (key->objectInfo != privKey) SECKEY_LowDestroyPrivateKey(privKey);	break;    case CKM_MD2_HMAC_GENERAL:	crv = pk11_doHMACInit(context,SEC_OID_MD2,key,				*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_MD2_HMAC:	crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH);	break;    case CKM_MD5_HMAC_GENERAL:	crv = pk11_doHMACInit(context,SEC_OID_MD5,key,				*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_MD5_HMAC:	crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH);	break;    case CKM_SHA_1_HMAC_GENERAL:	crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,				*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_SHA_1_HMAC:	crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH);	break;    case CKM_SSL3_MD5_MAC:	crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key,					*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_SSL3_SHA1_MAC:	crv = pk11_doSSLMACInit(context,SEC_OID_SHA1,key,					*(CK_ULONG *)pMechanism->pParameter);	break;    case CKM_TLS_PRF_GENERAL:	crv = pk11_TLSPRFInit(context, key, key_type);	break;    default:	crv = CKR_MECHANISM_INVALID;	break;    }    pk11_FreeObject(key);    if (crv != CKR_OK) {        PORT_Free(context);	pk11_FreeSession(session);	return crv;    }    pk11_SetContextByType(session, PK11_SIGN, context);    pk11_FreeSession(session);    return CKR_OK;}