PORT_SetError( PK11_MapError(crv) );
PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id){    CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;    PRArenaPool *arena;    PRArenaPool *tmp_arena;    SECKEYPublicKey *pubKey;    int templateCount = 0;    CK_KEY_TYPE pk11KeyType;    CK_RV crv;    CK_ATTRIBUTE template[8];    CK_ATTRIBUTE *attrs= template;    CK_ATTRIBUTE *modulus,*exponent,*base,*prime,*subprime,*value;    /* if we didn't know the key type, get it */    if (keyType== nullKey) {        pk11KeyType = PK11_ReadULongAttribute(slot,id,CKA_KEY_TYPE);	if (pk11KeyType ==  CK_UNAVAILABLE_INFORMATION) {	    PORT_SetError( PK11_MapError(crv) );	    return NULL;	}	switch (pk11KeyType) {	case CKK_RSA:	    keyType = rsaKey;	    break;	case CKK_DSA:	    keyType = dsaKey;	    break;	case CKK_DH:	    keyType = dhKey;	    break;	default:	    PORT_SetError( SEC_ERROR_BAD_KEY );	    return NULL;	}    }    /* now we need to create space for the public key */    arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);    if (arena == NULL) return NULL;    tmp_arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);    if (tmp_arena == NULL) {	PORT_FreeArena (arena, PR_FALSE);	return NULL;    }    pubKey = (SECKEYPublicKey *) 			PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));    if (pubKey == NULL) {	PORT_FreeArena (arena, PR_FALSE);	PORT_FreeArena (tmp_arena, PR_FALSE);	return NULL;    }    pubKey->arena = arena;    pubKey->keyType = keyType;    pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);    pubKey->pkcs11ID = id;    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, 						sizeof(keyClass)); attrs++;    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &pk11KeyType, 						sizeof(pk11KeyType) ); attrs++;    switch (pubKey->keyType) {    case rsaKey:	modulus = attrs;	PK11_SETATTRS(attrs, CKA_MODULUS, NULL, 0); attrs++; 	exponent = attrs;	PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, NULL, 0); attrs++; 	templateCount = attrs - template;	PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));	crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);	if (crv != CKR_OK) break;	if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_RSA)) {	    crv = CKR_OBJECT_HANDLE_INVALID;	    break;	} 	crv = pk11_Attr2SecItem(arena,modulus,&pubKey->u.rsa.modulus);	if (crv != CKR_OK) break;	crv = pk11_Attr2SecItem(arena,exponent,&pubKey->u.rsa.publicExponent);	if (crv != CKR_OK) break;	break;    case dsaKey:	prime = attrs;	PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; 	subprime = attrs;	PK11_SETATTRS(attrs, CKA_SUBPRIME, NULL, 0); attrs++; 	base = attrs;	PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; 	value = attrs;	PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; 	templateCount = attrs - template;	PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));	crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);	if (crv != CKR_OK) break;	if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) {	    crv = CKR_OBJECT_HANDLE_INVALID;	    break;	} 	crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dsa.params.prime);	if (crv != CKR_OK) break;	crv = pk11_Attr2SecItem(arena,subprime,&pubKey->u.dsa.params.subPrime);	if (crv != CKR_OK) break;	crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dsa.params.base);	if (crv != CKR_OK) break;	crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dsa.publicValue);	if (crv != CKR_OK) break;	break;    case dhKey:	prime = attrs;	PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; 	base = attrs;	PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; 	value =attrs;	PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; 	templateCount = attrs - template;	PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));	crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);	if (crv != CKR_OK) break;	if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) {	    crv = CKR_OBJECT_HANDLE_INVALID;	    break;	} 	crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dh.prime);	if (crv != CKR_OK) break;	crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dh.base);	if (crv != CKR_OK) break;	crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dh.publicValue);	if (crv != CKR_OK) break;	break;    case fortezzaKey:    case nullKey:    default:	crv = CKR_OBJECT_HANDLE_INVALID;	break;    }    PORT_FreeArena(tmp_arena,PR_FALSE);    if (crv != CKR_OK) {	PORT_FreeArena(arena,PR_FALSE);	PK11_FreeSlot(slot);	PORT_SetError( PK11_MapError(crv) );	return NULL;    }    return pubKey;}