keyType = CKK_DH;
PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, 	SECItem *nickname, SECItem *publicValue, PRBool isPerm, 	PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk,	void *wincx) {    CK_BBOOL cktrue = CK_TRUE;    CK_BBOOL ckfalse = CK_FALSE;    CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;    CK_KEY_TYPE keyType = CKK_RSA;    CK_OBJECT_HANDLE objectID;    CK_ATTRIBUTE theTemplate[20];    int templateCount = 0;    SECStatus rv = SECFailure;    PRArenaPool *arena;    CK_ATTRIBUTE *attrs;    CK_ATTRIBUTE *signedattr = NULL;    int signedcount = 0;    CK_ATTRIBUTE *ap;    SECItem *ck_id = NULL;    arena = PORT_NewArena(2048);    if(!arena) {	return SECFailure;    }    attrs = theTemplate;    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;    PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse, 						sizeof(CK_BBOOL) ); attrs++;    PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse, 						sizeof(CK_BBOOL) ); attrs++;    PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse,						 sizeof(CK_BBOOL) ); attrs++;    switch (lpk->keyType) {    case rsaKey:	    PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ?				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;	    PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ?				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;	    PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? 				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;	    PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, 				(keyUsage & KU_DIGITAL_SIGNATURE) ? 				&cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++;	    ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus);	    if (ck_id == NULL) {		goto loser;	    }	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;	    if (nickname) {		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); attrs++; 	    } 	    signedattr = attrs;	    PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data,						lpk->u.rsa.modulus.len); attrs++;	    PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 	     			lpk->u.rsa.publicExponent.data,				lpk->u.rsa.publicExponent.len); attrs++;	    PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT, 	     			lpk->u.rsa.privateExponent.data,				lpk->u.rsa.privateExponent.len); attrs++;	    PK11_SETATTRS(attrs, CKA_PRIME_1, 	     			lpk->u.rsa.prime1.data,				lpk->u.rsa.prime1.len); attrs++;	    PK11_SETATTRS(attrs, CKA_PRIME_2, 	     			lpk->u.rsa.prime2.data,				lpk->u.rsa.prime2.len); attrs++;	    PK11_SETATTRS(attrs, CKA_EXPONENT_1, 	     			lpk->u.rsa.exponent1.data,				lpk->u.rsa.exponent1.len); attrs++;	    PK11_SETATTRS(attrs, CKA_EXPONENT_2, 	     			lpk->u.rsa.exponent2.data,				lpk->u.rsa.exponent2.len); attrs++;	    PK11_SETATTRS(attrs, CKA_COEFFICIENT, 	     			lpk->u.rsa.coefficient.data,				lpk->u.rsa.coefficient.len); attrs++;	    break;    case dsaKey:	    /* To make our intenal PKCS #11 module work correctly with 	     * our database, we need to pass in the public key value for 	     * this dsa key. We have a netscape only CKA_ value to do this.	     * Only send it to internal slots */	    if( publicValue == NULL ) {		goto loser;	    }	    if (PK11_IsInternal(slot)) {	        PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,				publicValue->data, publicValue->len); attrs++;	    }	    PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); attrs++;	    PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL)); attrs++;	    if(nickname) {		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);		attrs++; 	    } 	    ck_id = PK11_MakeIDFromPubKey(publicValue);	    if (ck_id == NULL) {		goto loser;	    }	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;	    signedattr = attrs;	    PK11_SETATTRS(attrs, CKA_PRIME,    lpk->u.dsa.params.prime.data,				lpk->u.dsa.params.prime.len); attrs++;	    PK11_SETATTRS(attrs,CKA_SUBPRIME,lpk->u.dsa.params.subPrime.data,				lpk->u.dsa.params.subPrime.len); attrs++;	    PK11_SETATTRS(attrs, CKA_BASE,  lpk->u.dsa.params.base.data,					lpk->u.dsa.params.base.len); attrs++;	    PK11_SETATTRS(attrs, CKA_VALUE,    lpk->u.dsa.privateValue.data, 					lpk->u.dsa.privateValue.len); attrs++;	    break;     case dhKey:	    /* To make our intenal PKCS #11 module work correctly with 	     * our database, we need to pass in the public key value for 	     * this dh key. We have a netscape only CKA_ value to do this.	     * Only send it to internal slots */	    if (PK11_IsInternal(slot)) {	        PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,				publicValue->data, publicValue->len); attrs++;	    }	    PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); attrs++;	    if(nickname) {		PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);		attrs++; 	    } 	    ck_id = PK11_MakeIDFromPubKey(publicValue);	    if (ck_id == NULL) {		goto loser;	    }	    PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++;	    signedattr = attrs;	    PK11_SETATTRS(attrs, CKA_PRIME,    lpk->u.dh.prime.data,				lpk->u.dh.prime.len); attrs++;	    PK11_SETATTRS(attrs, CKA_BASE,  lpk->u.dh.base.data,					lpk->u.dh.base.len); attrs++;	    PK11_SETATTRS(attrs, CKA_VALUE,    lpk->u.dh.privateValue.data, 					lpk->u.dh.privateValue.len); attrs++;	    break;	/* what about fortezza??? */    default:	    PORT_SetError(SEC_ERROR_BAD_KEY);	    goto loser;    }    templateCount = attrs - theTemplate;    PORT_Assert(templateCount <= sizeof(theTemplate)/sizeof(CK_ATTRIBUTE));    PORT_Assert(signedattr != NULL);    signedcount = attrs - signedattr;    for (ap=signedattr; signedcount; ap++, signedcount--) {	pk11_SignedToUnsigned(ap);    }    rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION,			theTemplate, templateCount, isPerm, &objectID);    /* create and return a SECKEYPrivateKey */    if( rv == SECSuccess && privk != NULL) {	*privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx);	if( *privk == NULL ) {	    rv = SECFailure;	}    }loser:    if (ck_id) {	SECITEM_ZfreeItem(ck_id, PR_TRUE);    }    return rv;}