PORT_Free(pqgParam.prime.data); PORT_Free(pqgParam.subPrime.data); PORT_Free(pqgParam.base.data);
PORT_Free(dhParam.prime.data); PORT_Free(dhParam.base.data);
CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,    CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,    CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,    CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,    					CK_OBJECT_HANDLE_PTR phPrivateKey){    PK11Object *	publicKey,*privateKey;    PK11Session *	session;    CK_KEY_TYPE 	key_type;    CK_RV 		crv 	= CKR_OK;    CK_BBOOL 		cktrue 	= CK_TRUE;    SECStatus 		rv;    CK_OBJECT_CLASS 	pubClass = CKO_PUBLIC_KEY;    CK_OBJECT_CLASS 	privClass = CKO_PRIVATE_KEY;    int 		i;    PK11Slot *		slot 	= pk11_SlotFromSessionHandle(hSession);    unsigned int bitSize;    /* RSA */    int 		public_modulus_bits = 0;    SECItem 		pubExp;    RSAPrivateKey *	rsaPriv;    /* DSA */    PQGParams 		pqgParam;    DHParams  		dhParam;    DSAPrivateKey *	dsaPriv;    /* Diffie Hellman */    int 		private_value_bits = 0;    DHPrivateKey *	dhPriv;#ifdef NSS_ENABLE_ECC    /* Elliptic Curve Cryptography */    SECItem  		ecEncodedParams;  /* DER Encoded parameters */    ECPrivateKey *	ecPriv;    ECParams *          ecParams;#endif /* NSS_ENABLE_ECC */    /*     * now lets create an object to hang the attributes off of     */    publicKey = pk11_NewObject(slot); /* fill in the handle later */    if (publicKey == NULL) {	return CKR_HOST_MEMORY;    }    /*     * load the template values into the publicKey     */    for (i=0; i < (int) ulPublicKeyAttributeCount; i++) {	if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {	    public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;	    continue;	}	crv = pk11_AddAttributeType(publicKey,				    pk11_attr_expand(&pPublicKeyTemplate[i]));	if (crv != CKR_OK) break;    }    if (crv != CKR_OK) {	pk11_FreeObject(publicKey);	return CKR_HOST_MEMORY;    }    privateKey = pk11_NewObject(slot); /* fill in the handle later */    if (privateKey == NULL) {	pk11_FreeObject(publicKey);	return CKR_HOST_MEMORY;    }    /*     * now load the private key template     */    for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) {	if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {	    private_value_bits = *(CK_ULONG *)pPrivateKeyTemplate[i].pValue;	    continue;	}	crv = pk11_AddAttributeType(privateKey,				    pk11_attr_expand(&pPrivateKeyTemplate[i]));	if (crv != CKR_OK) break;    }    if (crv != CKR_OK) {	pk11_FreeObject(publicKey);	pk11_FreeObject(privateKey);	return CKR_HOST_MEMORY;    }    pk11_DeleteAttributeType(privateKey,CKA_CLASS);    pk11_DeleteAttributeType(privateKey,CKA_KEY_TYPE);    pk11_DeleteAttributeType(privateKey,CKA_VALUE);    pk11_DeleteAttributeType(publicKey,CKA_CLASS);    pk11_DeleteAttributeType(publicKey,CKA_KEY_TYPE);    pk11_DeleteAttributeType(publicKey,CKA_VALUE);    /* Now Set up the parameters to generate the key (based on mechanism) */    switch (pMechanism->mechanism) {    case CKM_RSA_PKCS_KEY_PAIR_GEN:	/* format the keys */    	pk11_DeleteAttributeType(publicKey,CKA_MODULUS);    	pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);    	pk11_DeleteAttributeType(privateKey,CKA_MODULUS);    	pk11_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT);    	pk11_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT);    	pk11_DeleteAttributeType(privateKey,CKA_PRIME_1);    	pk11_DeleteAttributeType(privateKey,CKA_PRIME_2);    	pk11_DeleteAttributeType(privateKey,CKA_EXPONENT_1);    	pk11_DeleteAttributeType(privateKey,CKA_EXPONENT_2);    	pk11_DeleteAttributeType(privateKey,CKA_COEFFICIENT);	key_type = CKK_RSA;	if (public_modulus_bits == 0) {	    crv = CKR_TEMPLATE_INCOMPLETE;	    break;	}	if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {	    crv = CKR_ATTRIBUTE_VALUE_INVALID;	    break;	}	if (public_modulus_bits % 2 != 0) {	    crv = CKR_ATTRIBUTE_VALUE_INVALID;	    break;	}	/* extract the exponent */	crv=pk11_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT);	if (crv != CKR_OK) break;        bitSize = pk11_GetLengthInBits(pubExp.data, pubExp.len);	if (bitSize < 2) {	    crv = CKR_ATTRIBUTE_VALUE_INVALID;	    break;	}        crv = pk11_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,				    		    pk11_item_expand(&pubExp));	if (crv != CKR_OK) {	    PORT_Free(pubExp.data);	    break;	}	rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);	PORT_Free(pubExp.data);	if (rsaPriv == NULL) {	    crv = CKR_DEVICE_ERROR;	    break;	}        /* now fill in the RSA dependent paramenters in the public key */        crv = pk11_AddAttributeType(publicKey,CKA_MODULUS,			   pk11_item_expand(&rsaPriv->modulus));	if (crv != CKR_OK) goto kpg_done;        /* now fill in the RSA dependent paramenters in the private key */        crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,			   pk11_item_expand(&rsaPriv->modulus));	if (crv != CKR_OK) goto kpg_done;        crv = pk11_AddAttributeType(privateKey,CKA_MODULUS,			   pk11_item_expand(&rsaPriv->modulus));	if (crv != CKR_OK) goto kpg_done;        crv = pk11_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,			   pk11_item_expand(&rsaPriv->privateExponent));	if (crv != CKR_OK) goto kpg_done;        crv = pk11_AddAttributeType(privateKey,CKA_PRIME_1,			   pk11_item_expand(&rsaPriv->prime1));	if (crv != CKR_OK) goto kpg_done;        crv = pk11_AddAttributeType(privateKey,CKA_PRIME_2,			   pk11_item_expand(&rsaPriv->prime2));	if (crv != CKR_OK) goto kpg_done;        crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_1,			   pk11_item_expand(&rsaPriv->exponent1));	if (crv != CKR_OK) goto kpg_done;        crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_2,			   pk11_item_expand(&rsaPriv->exponent2));	if (crv != CKR_OK) goto kpg_done;        crv = pk11_AddAttributeType(privateKey,CKA_COEFFICIENT,			   pk11_item_expand(&rsaPriv->coefficient));kpg_done:	/* Should zeroize the contents first, since this func doesn't. */	PORT_FreeArena(rsaPriv->arena, PR_TRUE);	break;    case CKM_DSA_KEY_PAIR_GEN:    	pk11_DeleteAttributeType(publicKey,CKA_VALUE);    	pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);	pk11_DeleteAttributeType(privateKey,CKA_PRIME);	pk11_DeleteAttributeType(privateKey,CKA_SUBPRIME);	pk11_DeleteAttributeType(privateKey,CKA_BASE);	key_type = CKK_DSA;	/* extract the necessary paramters and copy them to the private key */	crv=pk11_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME);	if (crv != CKR_OK) break;	crv=pk11_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey,	                            CKA_SUBPRIME);	if (crv != CKR_OK) {	    PORT_Free(pqgParam.prime.data);	    break;	}	crv=pk11_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE);	if (crv != CKR_OK) {	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    break;	}        crv = pk11_AddAttributeType(privateKey,CKA_PRIME,				    pk11_item_expand(&pqgParam.prime));	if (crv != CKR_OK) {	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    PORT_Free(pqgParam.base.data);	    break;	}        crv = pk11_AddAttributeType(privateKey,CKA_SUBPRIME,			    	    pk11_item_expand(&pqgParam.subPrime));	if (crv != CKR_OK) {	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    PORT_Free(pqgParam.base.data);	    break;	}        crv = pk11_AddAttributeType(privateKey,CKA_BASE,			    	    pk11_item_expand(&pqgParam.base));	if (crv != CKR_OK) {	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    PORT_Free(pqgParam.base.data);	    break;	}        bitSize = pk11_GetLengthInBits(pqgParam.subPrime.data, 							pqgParam.subPrime.len);        if (bitSize != DSA_Q_BITS)  {	    crv = CKR_TEMPLATE_INCOMPLETE;	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    PORT_Free(pqgParam.base.data);	    break;	}        bitSize = pk11_GetLengthInBits(pqgParam.prime.data,pqgParam.prime.len);        if ((bitSize <  DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {	    crv = CKR_TEMPLATE_INCOMPLETE;	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    PORT_Free(pqgParam.base.data);	    break;	}        bitSize = pk11_GetLengthInBits(pqgParam.base.data,pqgParam.base.len);        if ((bitSize <  1) || (bitSize > DSA_MAX_P_BITS)) {	    crv = CKR_TEMPLATE_INCOMPLETE;	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    PORT_Free(pqgParam.base.data);	    break;	}	    	/* Generate the key */	rv = DSA_NewKey(&pqgParam, &dsaPriv);	PORT_Free(pqgParam.prime.data);	PORT_Free(pqgParam.subPrime.data);	PORT_Free(pqgParam.base.data);	if (rv != SECSuccess) { crv = CKR_DEVICE_ERROR; break; }	/* store the generated key into the attributes */        crv = pk11_AddAttributeType(publicKey,CKA_VALUE,			   pk11_item_expand(&dsaPriv->publicValue));	if (crv != CKR_OK) goto dsagn_done;        /* now fill in the RSA dependent paramenters in the private key */        crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,			   pk11_item_expand(&dsaPriv->publicValue));	if (crv != CKR_OK) goto dsagn_done;        crv = pk11_AddAttributeType(privateKey,CKA_VALUE,			   pk11_item_expand(&dsaPriv->privateValue));dsagn_done:	/* should zeroize, since this function doesn't. */	PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);	break;    case CKM_DH_PKCS_KEY_PAIR_GEN:	pk11_DeleteAttributeType(privateKey,CKA_PRIME);	pk11_DeleteAttributeType(privateKey,CKA_BASE);	pk11_DeleteAttributeType(privateKey,CKA_VALUE);    	pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);	key_type = CKK_DH;	/* extract the necessary parameters and copy them to private keys */        crv = pk11_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, 				      CKA_PRIME);	if (crv != CKR_OK) break;	crv = pk11_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);	if (crv != CKR_OK) {	    PORT_Free(dhParam.prime.data);	    break;	}	crv = pk11_AddAttributeType(privateKey, CKA_PRIME, 				    pk11_item_expand(&dhParam.prime));	if (crv != CKR_OK) {	    PORT_Free(dhParam.prime.data);	    PORT_Free(dhParam.base.data);	    break;	}	crv = pk11_AddAttributeType(privateKey, CKA_BASE, 				    pk11_item_expand(&dhParam.base));	if (crv != CKR_OK) {	    PORT_Free(dhParam.prime.data);	    PORT_Free(dhParam.base.data);	    break;	}        bitSize = pk11_GetLengthInBits(dhParam.prime.data,dhParam.prime.len);        if ((bitSize <  DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {	    crv = CKR_TEMPLATE_INCOMPLETE;	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    PORT_Free(pqgParam.base.data);	    break;	}        bitSize = pk11_GetLengthInBits(dhParam.base.data,dhParam.base.len);        if ((bitSize <  1) || (bitSize > DH_MAX_P_BITS)) {	    crv = CKR_TEMPLATE_INCOMPLETE;	    PORT_Free(pqgParam.prime.data);	    PORT_Free(pqgParam.subPrime.data);	    PORT_Free(pqgParam.base.data);	    break;	}	rv = DH_NewKey(&dhParam, &dhPriv);	PORT_Free(dhParam.prime.data);	PORT_Free(dhParam.base.data);	if (rv != SECSuccess) { 	    crv = CKR_DEVICE_ERROR;	    break;	}	crv=pk11_AddAttributeType(publicKey, CKA_VALUE, 				pk11_item_expand(&dhPriv->publicValue));	if (crv != CKR_OK) goto dhgn_done;        crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,			   pk11_item_expand(&dhPriv->publicValue));	if (crv != CKR_OK) goto dhgn_done;	crv=pk11_AddAttributeType(privateKey, CKA_VALUE, 			      pk11_item_expand(&dhPriv->privateValue));dhgn_done:	/* should zeroize, since this function doesn't. */	PORT_FreeArena(dhPriv->arena, PR_TRUE);	break;#ifdef NSS_ENABLE_ECC    case CKM_EC_KEY_PAIR_GEN:	pk11_DeleteAttributeType(privateKey,CKA_EC_PARAMS);	pk11_DeleteAttributeType(privateKey,CKA_VALUE);    	pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);	key_type = CKK_EC;	/* extract the necessary parameters and copy them to private keys */	crv = pk11_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, 				      CKA_EC_PARAMS);	if (crv != CKR_OK) break;	crv = pk11_AddAttributeType(privateKey, CKA_EC_PARAMS, 				    pk11_item_expand(&ecEncodedParams));	if (crv != CKR_OK) {	  PORT_Free(ecEncodedParams.data);	  break;	}	/* Decode ec params before calling EC_NewKey */	rv = EC_DecodeParams(&ecEncodedParams, &ecParams);	PORT_Free(ecEncodedParams.data);	if (rv != SECSuccess) {	    crv = CKR_DEVICE_ERROR;	    break;	}	rv = EC_NewKey(ecParams, &ecPriv);	PORT_FreeArena(ecParams->arena, PR_TRUE);	if (rv != SECSuccess) { 	  crv = CKR_DEVICE_ERROR;	  break;	}	crv = pk11_AddAttributeType(publicKey, CKA_EC_POINT, 				pk11_item_expand(&ecPriv->publicValue));	if (crv != CKR_OK) goto ecgn_done;	crv = pk11_AddAttributeType(privateKey, CKA_VALUE, 			      pk11_item_expand(&ecPriv->privateValue));	if (crv != CKR_OK) goto ecgn_done;        crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,			   pk11_item_expand(&ecPriv->publicValue));ecgn_done:	/* should zeroize, since this function doesn't. */	PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);	break;#endif /* NSS_ENABLE_ECC */    default:	crv = CKR_MECHANISM_INVALID;    }    if (crv != CKR_OK) {	pk11_FreeObject(privateKey);	pk11_FreeObject(publicKey);	return crv;    }    /* Add the class, key_type The loop lets us check errors blow out     *  on errors and clean up at the bottom */    session = NULL; /* make pedtantic happy... session cannot leave the*/		    /* loop below NULL unless an error is set... */    do {	crv = pk11_AddAttributeType(privateKey,CKA_CLASS,&privClass,						sizeof(CK_OBJECT_CLASS));        if (crv != CKR_OK) break;	crv = pk11_AddAttributeType(publicKey,CKA_CLASS,&pubClass,						sizeof(CK_OBJECT_CLASS));        if (crv != CKR_OK) break;	crv = pk11_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type,						sizeof(CK_KEY_TYPE));        if (crv != CKR_OK) break;	crv = pk11_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type,						sizeof(CK_KEY_TYPE));        if (crv != CKR_OK) break;        session = pk11_SessionFromHandle(hSession);        if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID;    } while (0);    if (crv != CKR_OK) {	 pk11_FreeObject(privateKey);	 pk11_FreeObject(publicKey);	 return crv;    }    /*     * handle the base object cleanup for the public Key     */    crv = pk11_handleObject(privateKey,session);    if (crv != CKR_OK) {        pk11_FreeSession(session);	pk11_FreeObject(privateKey);	pk11_FreeObject(publicKey);	return crv;    }    /*     * handle the base object cleanup for the private Key     * If we have any problems, we destroy the public Key we've     * created and linked.     */    crv = pk11_handleObject(publicKey,session);    pk11_FreeSession(session);    if (crv != CKR_OK) {	pk11_FreeObject(publicKey);	NSC_DestroyObject(hSession,privateKey->handle);	pk11_FreeObject(privateKey);	return crv;    }    if (pk11_isTrue(privateKey,CKA_SENSITIVE)) {	pk11_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE,						&cktrue,sizeof(CK_BBOOL));    }    if (pk11_isTrue(publicKey,CKA_SENSITIVE)) {	pk11_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE,						&cktrue,sizeof(CK_BBOOL));    }    if (!pk11_isTrue(privateKey,CKA_EXTRACTABLE)) {	pk11_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE,						&cktrue,sizeof(CK_BBOOL));    }    if (!pk11_isTrue(publicKey,CKA_EXTRACTABLE)) {	pk11_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE,						&cktrue,sizeof(CK_BBOOL));    }    *phPrivateKey = privateKey->handle;    *phPublicKey = publicKey->handle;    pk11_FreeObject(publicKey);    pk11_FreeObject(privateKey);    return CKR_OK;}