PK11_EnterSlotMonitor(slot);
PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,    void *param, SECKEYPublicKey **pubKey, PRBool token, 					PRBool sensitive, void *wincx){    /* we have to use these native types because when we call PKCS 11 modules     * we have to make sure that we are using the correct sizes for all the     * parameters. */    CK_BBOOL ckfalse = CK_FALSE;    CK_BBOOL cktrue = CK_TRUE;    CK_ULONG modulusBits;    CK_BYTE publicExponent[4];    CK_ATTRIBUTE privTemplate[] = {	{ CKA_SENSITIVE, NULL, 0},	{ CKA_TOKEN,  NULL, 0},	{ CKA_PRIVATE,  NULL, 0},	{ CKA_DERIVE,  NULL, 0},	{ CKA_UNWRAP,  NULL, 0},	{ CKA_SIGN,  NULL, 0},	{ CKA_DECRYPT,  NULL, 0},    };    CK_ATTRIBUTE rsaPubTemplate[] = {	{ CKA_MODULUS_BITS, NULL, 0},	{ CKA_PUBLIC_EXPONENT, NULL, 0},	{ CKA_TOKEN,  NULL, 0},	{ CKA_DERIVE,  NULL, 0},	{ CKA_WRAP,  NULL, 0},	{ CKA_VERIFY,  NULL, 0},	{ CKA_VERIFY_RECOVER,  NULL, 0},	{ CKA_ENCRYPT,  NULL, 0},    };    CK_ATTRIBUTE dsaPubTemplate[] = {	{ CKA_PRIME, NULL, 0 },	{ CKA_SUBPRIME, NULL, 0 },	{ CKA_BASE, NULL, 0 },	{ CKA_TOKEN,  NULL, 0},	{ CKA_DERIVE,  NULL, 0},	{ CKA_WRAP,  NULL, 0},	{ CKA_VERIFY,  NULL, 0},	{ CKA_VERIFY_RECOVER,  NULL, 0},	{ CKA_ENCRYPT,  NULL, 0},    };    CK_ATTRIBUTE dhPubTemplate[] = {      { CKA_PRIME, NULL, 0 },       { CKA_BASE, NULL, 0 },       { CKA_TOKEN,  NULL, 0},      { CKA_DERIVE,  NULL, 0},      { CKA_WRAP,  NULL, 0},      { CKA_VERIFY,  NULL, 0},      { CKA_VERIFY_RECOVER,  NULL, 0},      { CKA_ENCRYPT,  NULL, 0},    };#ifdef NSS_ENABLE_ECC    CK_ATTRIBUTE ecPubTemplate[] = {      { CKA_EC_PARAMS, NULL, 0 },       { CKA_TOKEN,  NULL, 0},      { CKA_DERIVE,  NULL, 0},      { CKA_WRAP,  NULL, 0},      { CKA_VERIFY,  NULL, 0},      { CKA_VERIFY_RECOVER,  NULL, 0},      { CKA_ENCRYPT,  NULL, 0},    };    int ecPubCount = sizeof(ecPubTemplate)/sizeof(ecPubTemplate[0]);    SECKEYECParams * ecParams;#endif /* NSS_ENABLE_ECC */    int dsaPubCount = sizeof(dsaPubTemplate)/sizeof(dsaPubTemplate[0]);    /*CK_ULONG key_size = 0;*/    CK_ATTRIBUTE *pubTemplate;    int privCount = sizeof(privTemplate)/sizeof(privTemplate[0]);    int rsaPubCount = sizeof(rsaPubTemplate)/sizeof(rsaPubTemplate[0]);    int dhPubCount = sizeof(dhPubTemplate)/sizeof(dhPubTemplate[0]);    int pubCount = 0;    PK11RSAGenParams *rsaParams;    SECKEYPQGParams *dsaParams;    SECKEYDHParams * dhParams;    CK_MECHANISM mechanism;    CK_MECHANISM test_mech;    CK_SESSION_HANDLE session_handle;    CK_RV crv;    CK_OBJECT_HANDLE privID,pubID;    SECKEYPrivateKey *privKey;    KeyType keyType;    PRBool restore;    int peCount,i;    CK_ATTRIBUTE *attrs;    CK_ATTRIBUTE *privattrs;    SECItem *pubKeyIndex;    CK_ATTRIBUTE setTemplate;    CK_MECHANISM_INFO mechanism_info;    CK_OBJECT_CLASS keyClass;    SECItem *cka_id;    PRBool haslock = PR_FALSE;    PRBool pubIsToken = PR_FALSE;    PORT_Assert(slot != NULL);    if (slot == NULL) {	PORT_SetError( SEC_ERROR_NO_MODULE);	return NULL;    }    /* if our slot really doesn't do this mechanism, Generate the key     * in our internal token and write it out */    if (!PK11_DoesMechanism(slot,type)) {	PK11SlotInfo *int_slot = PK11_GetInternalSlot();	/* don't loop forever looking for a slot */	if (slot == int_slot) {	    PK11_FreeSlot(int_slot);	    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);	    return NULL;	}	/* if there isn't a suitable slot, then we can't do the keygen */	if (int_slot == NULL) {	    PORT_SetError( SEC_ERROR_NO_MODULE );	    return NULL;	}	/* generate the temporary key to load */	privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE, 							PR_FALSE, wincx);	PK11_FreeSlot(int_slot);	/* if successful, load the temp key into the new token */	if (privKey != NULL) {	    SECKEYPrivateKey *newPrivKey = pk11_loadPrivKey(slot,privKey,						*pubKey,token,sensitive);	    SECKEY_DestroyPrivateKey(privKey);	    if (newPrivKey == NULL) {		SECKEY_DestroyPublicKey(*pubKey);		*pubKey = NULL;	    }	    return newPrivKey;	}	return NULL;   }    mechanism.mechanism = type;    mechanism.pParameter = NULL;    mechanism.ulParameterLen = 0;    test_mech.pParameter = NULL;    test_mech.ulParameterLen = 0;    /* set up the private key template */    privattrs = privTemplate;    PK11_SETATTRS(privattrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse, 					sizeof(CK_BBOOL)); privattrs++;    PK11_SETATTRS(privattrs, CKA_TOKEN, token ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); privattrs++;    PK11_SETATTRS(privattrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); privattrs++;    /* set up the mechanism specific info */    switch (type) {    case CKM_RSA_PKCS_KEY_PAIR_GEN:    case CKM_RSA_X9_31_KEY_PAIR_GEN:	rsaParams = (PK11RSAGenParams *)param;	if (rsaParams->pe == 0) {	    PORT_SetError(SEC_ERROR_INVALID_ARGS);	    return NULL;	}	modulusBits = rsaParams->keySizeInBits;	peCount = 0;	/* convert pe to a PKCS #11 string */	for (i=0; i < 4; i++) {	    if (peCount || (rsaParams->pe & 				((unsigned long)0xff000000L >> (i*8)))) {		publicExponent[peCount] = 				(CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff);		peCount++;	    }	}	PORT_Assert(peCount != 0);	attrs = rsaPubTemplate;	PK11_SETATTRS(attrs, CKA_MODULUS_BITS, 				&modulusBits, sizeof(modulusBits)); attrs++;	PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 				publicExponent, peCount);attrs++;	pubTemplate = rsaPubTemplate;	pubCount = rsaPubCount;	keyType = rsaKey;	test_mech.mechanism = CKM_RSA_PKCS;	break;    case CKM_DSA_KEY_PAIR_GEN:	dsaParams = (SECKEYPQGParams *)param;	attrs = dsaPubTemplate;	PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data,				dsaParams->prime.len); attrs++;	PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data,					dsaParams->subPrime.len); attrs++;	PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data,						dsaParams->base.len); attrs++;	pubTemplate = dsaPubTemplate;	pubCount = dsaPubCount;	keyType = dsaKey;	test_mech.mechanism = CKM_DSA;	break;    case CKM_DH_PKCS_KEY_PAIR_GEN:        dhParams = (SECKEYDHParams *)param;        attrs = dhPubTemplate;        PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data,                      dhParams->prime.len);   attrs++;        PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data,                      dhParams->base.len);    attrs++;        pubTemplate = dhPubTemplate;	pubCount = dhPubCount;        keyType = dhKey;        test_mech.mechanism = CKM_DH_PKCS_DERIVE;	break;#ifdef NSS_ENABLE_ECC    case CKM_EC_KEY_PAIR_GEN:        ecParams = (SECKEYECParams *)param;        attrs = ecPubTemplate;        PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data, 	              ecParams->len);   attrs++;        pubTemplate = ecPubTemplate;        pubCount = ecPubCount;        keyType = ecKey;	/* XXX An EC key can be used for other mechanisms too such	 * as CKM_ECDSA and CKM_ECDSA_SHA1. How can we reflect	 * that in test_mech.mechanism so the CKA_SIGN, CKA_VERIFY	 * attributes are set correctly? 	 */        test_mech.mechanism = CKM_ECDH1_DERIVE;        break;#endif /* NSS_ENABLE_ECC */    default:	PORT_SetError( SEC_ERROR_BAD_KEY );	return NULL;    }    /* now query the slot to find out how "good" a key we can generate */    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);    crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,				test_mech.mechanism,&mechanism_info);    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);    if ((crv != CKR_OK) || (mechanism_info.flags == 0)) {	/* must be old module... guess what it should be... */	switch (test_mech.mechanism) {	case CKM_RSA_PKCS:		mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT | 			CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);;		break;	case CKM_DSA:		mechanism_info.flags = CKF_SIGN | CKF_VERIFY;		break;	case CKM_DH_PKCS_DERIVE:		mechanism_info.flags = CKF_DERIVE;		break;#ifdef NSS_ENABLE_ECC	case CKM_ECDH1_DERIVE:		mechanism_info.flags = CKF_DERIVE;		break;	case CKM_ECDSA:	case CKM_ECDSA_SHA1:		mechanism_info.flags = CKF_SIGN | CKF_VERIFY;		break;#endif /* NSS_ENABLE_ECC */	default:	       break;	}    }    /* set the public key objects */    PK11_SETATTRS(attrs, CKA_TOKEN, token ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); attrs++;    PK11_SETATTRS(attrs, CKA_DERIVE, 		mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); attrs++;    PK11_SETATTRS(attrs, CKA_WRAP, 		mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); attrs++;    PK11_SETATTRS(attrs, CKA_VERIFY, 		mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); attrs++;    PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER, 		mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); attrs++;    PK11_SETATTRS(attrs, CKA_ENCRYPT, 		mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); attrs++;    PK11_SETATTRS(privattrs, CKA_DERIVE, 		mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); privattrs++;    PK11_SETATTRS(privattrs, CKA_UNWRAP, 		mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); privattrs++;    PK11_SETATTRS(privattrs, CKA_SIGN, 		mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); privattrs++;    PK11_SETATTRS(privattrs, CKA_DECRYPT, 		mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse,					 sizeof(CK_BBOOL)); privattrs++;    if (token) {	session_handle = PK11_GetRWSession(slot);	haslock = PK11_RWSessionHasLock(slot,session_handle);	restore = PR_TRUE;    } else {        PK11_EnterSlotMonitor(slot); /* gross!! */	session_handle = slot->session;	restore = PR_FALSE;	haslock = PR_TRUE;    }    crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism,	pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID);    if (crv != CKR_OK) {	if (restore)  {	    PK11_RestoreROSession(slot,session_handle);	} else PK11_ExitSlotMonitor(slot);	PORT_SetError( PK11_MapError(crv) );	return NULL;    }    /* This locking code is dangerous and needs to be more thought     * out... the real problem is that we're holding the mutex open this long     */    if (haslock) { PK11_ExitSlotMonitor(slot); }    /* swap around the ID's for older PKCS #11 modules */    keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS);    if (keyClass != CKO_PUBLIC_KEY) {	CK_OBJECT_HANDLE tmp = pubID;	pubID = privID;	privID = tmp;    }    *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID);    if (*pubKey == NULL) {	if (restore)  {	    /* we may have to restore the mutex so it get's exited properly	     * in RestoreROSession */            if (haslock)  PK11_EnterSlotMonitor(slot); 	    PK11_RestoreROSession(slot,session_handle);	} 	PK11_DestroyObject(slot,pubID);	PK11_DestroyObject(slot,privID);	return NULL;    }    /* set the ID to the public key so we can find it again */    pubKeyIndex =  NULL;    switch (type) {    case CKM_RSA_PKCS_KEY_PAIR_GEN:    case CKM_RSA_X9_31_KEY_PAIR_GEN:      pubKeyIndex = &(*pubKey)->u.rsa.modulus;      break;    case CKM_DSA_KEY_PAIR_GEN:      pubKeyIndex = &(*pubKey)->u.dsa.publicValue;      break;    case CKM_DH_PKCS_KEY_PAIR_GEN:      pubKeyIndex = &(*pubKey)->u.dh.publicValue;      break;      #ifdef NSS_ENABLE_ECC    case CKM_EC_KEY_PAIR_GEN:      pubKeyIndex = &(*pubKey)->u.ec.publicValue;      break;      #endif /* NSS_ENABLE_ECC */    }    PORT_Assert(pubKeyIndex != NULL);    cka_id = PK11_MakeIDFromPubKey(pubKeyIndex);    pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN);    PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);    if (haslock) { PK11_EnterSlotMonitor(slot); }    crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID,		&setTemplate, 1);       if (crv == CKR_OK && pubIsToken) {    	crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID,		&setTemplate, 1);    }    if (restore) {	PK11_RestoreROSession(slot,session_handle);    } else {	PK11_ExitSlotMonitor(slot);    }    SECITEM_FreeItem(cka_id,PR_TRUE);    if (crv != CKR_OK) {	PK11_DestroyObject(slot,pubID);	PK11_DestroyObject(slot,privID);	PORT_SetError( PK11_MapError(crv) );	*pubKey = NULL;	return NULL;    }    privKey = PK11_MakePrivKey(slot,keyType,(PRBool)!token,privID,wincx);    if (privKey == NULL) {	SECKEY_DestroyPublicKey(*pubKey);	PK11_DestroyObject(slot,privID);	*pubKey = NULL;	return NULL;    }    return privKey;}