#include "cryptoki.h"
#include "P11Objects.h"
#include "Util.h"
#include "Pkcs11Exceptions.h"


static CK_OBJECT_HANDLE	gNextObjectHandle = 0x00200000;

/* __________________________________________ CONSTRUCCION / DESTRUCCION _ */


/* Constructor:
   Descrip:    Contructor protegido para plantillas que se crean dentro
               de las clases derivadas.                                    */

CPKCS11Object::CPKCS11Object ()
{
	DBG_TRACE(( "Construyendo CPKCS11Object (0x%08x - 0x%08x)...\n", gNextObjectHandle, this ));
	m_valuePath.clear();
	m_valueIndex  = 0;
	m_valueLength = 0;
	m_hObject = gNextObjectHandle++;
}

//
// Destructor
//
CPKCS11Object::~CPKCS11Object ()
{
	map<CK_ATTRIBUTE_TYPE,byteBuffer *>::iterator	it;

	DBG_TRACE(( "Borrando CPKCS11Object (0x%08x)...\n", this ));

	for ( it=m_attributes.begin() ; it != m_attributes.end(); it++ )
	{
		DBG_TRACE(( "Borrando Atributo 0x%08x  BB=0x%08x...\n", it->first, it->second ));
		DBG_DUMP((*it->second));
		delete it->second;
	}

	m_attributes.clear();
}

bool CPKCS11Object::isPrivate ()
{
	return GetAttributeBool( CKA_PRIVATE );
}

void CPKCS11Object::SetAttribute( CK_ATTRIBUTE_TYPE attType, byte * pValue, ulong ulValueLen )
{
	byteBuffer	* pBBvalue = m_attributes[attType];

	if( !pBBvalue )
		m_attributes[attType] = new byteBuffer(pValue,ulValueLen);
	else
		pBBvalue->assign(pValue,ulValueLen);
}

void CPKCS11Object::SetAttribute( CK_ATTRIBUTE_TYPE attType, byteBuffer & value )
{
	SetAttribute( attType, &value[0], (ulong)value.size() );
}

void CPKCS11Object::SetAttribute( CK_ATTRIBUTE_TYPE attType, ulong value )
{
	SetAttribute( attType, (byte *)&value, sizeof(value) );
}

void CPKCS11Object::SetAttribute( CK_ATTRIBUTE_TYPE attType, byte value )
{
	SetAttribute( attType, (byte *)&value, sizeof(value) );
}

void CPKCS11Object::SetAttribute( CK_ATTRIBUTE_TYPE attType, bool value )
{
	SetAttribute( attType, (byte *)&value, sizeof(byte) );
}

#define ATTRIB_TYPE_INVALID		0
#define ATTRIB_TYPE_BOOLEAN		1
#define ATTRIB_TYPE_INTEGER		2
#define ATTRIB_TYPE_BYTE_PTR	3

void CPKCS11Object::AddAttribute2Object( CK_ATTRIBUTE_PTR att )
{
	CK_ATTRIBUTE_TYPE objType = 0;
	bool *bValor;

	objType = KindOfAttribute( att->type );

	switch (objType)
	{
		case ATTRIB_TYPE_BOOLEAN:
			bValor = (bool*)att->pValue;
			SetAttribute(att->type, *bValor);
			break;
		case ATTRIB_TYPE_INTEGER:
		case ATTRIB_TYPE_BYTE_PTR:
			SetAttribute(att->type, (byte*)att->pValue, att->ulValueLen);
			break;
		default:            // ATTRIB_TYPE_INVALID;
			throw Pkcs11Exception(CKR_ATTRIBUTE_TYPE_INVALID);
	}
}

int CPKCS11Object::KindOfAttribute( CK_ATTRIBUTE_TYPE  attribute )
{
	int iType = ATTRIB_TYPE_INVALID;

	switch ( attribute )
	{
		case CKA_TOKEN:
		case CKA_PRIVATE:
		case CKA_SENSITIVE:
		case CKA_ENCRYPT:
		case CKA_DECRYPT:
		case CKA_WRAP:
		case CKA_UNWRAP:
		case CKA_SIGN:
		case CKA_SIGN_RECOVER:
		case CKA_VERIFY:
		case CKA_VERIFY_RECOVER:
		case CKA_DERIVE:
		case CKA_EXTRACTABLE:
		case CKA_LOCAL:
		case CKA_NEVER_EXTRACTABLE:
		case CKA_ALWAYS_SENSITIVE:
		case CKA_MODIFIABLE:
		case CKA_ALWAYS_AUTHENTICATE:
			iType = ATTRIB_TYPE_BOOLEAN;
			break;

		case CKA_LABEL:
		case CKA_APPLICATION:
		case CKA_VALUE:
		case CKA_ISSUER:
		case CKA_SUBJECT:
		case CKA_ID:
			iType = ATTRIB_TYPE_BYTE_PTR;
			break;

		case CKA_CLASS:
		case CKA_OBJECT_ID:
		case CKA_CERTIFICATE_TYPE:
		case CKA_SERIAL_NUMBER:
		case CKA_KEY_TYPE:
		case CKA_START_DATE:
		case CKA_END_DATE:
		case CKA_MODULUS:
		case CKA_MODULUS_BITS:
		case CKA_PUBLIC_EXPONENT:
		case CKA_PRIVATE_EXPONENT:
		case CKA_PRIME_1:
		case CKA_PRIME_2:
		case CKA_EXPONENT_1:
		case CKA_EXPONENT_2:
		case CKA_COEFFICIENT:
		case CKA_PRIME:
		case CKA_SUBPRIME:
		case CKA_BASE:
		case CKA_VALUE_BITS:
		case CKA_VALUE_LEN:
			iType = ATTRIB_TYPE_INTEGER;
			break;
		default:
			iType = ATTRIB_TYPE_INVALID;
			break;
	}

	return iType;
}

void CPKCS11Object::SetValuePath( byte * pPath, int iPathSize, int iIndex, int iLength )
{
	if( iPathSize > 4 )
		CUtil::PathASCII2bin( pPath, iPathSize, m_valuePath );
	else
		m_valuePath.assign( pPath, iPathSize );

	m_valueIndex	= iIndex;
	m_valueLength	= iLength;
}

void CPKCS11Object::SetValuePath( byteBuffer & pPath, int iIndex, int iLength )
{
	if( pPath.size() > 4 )
		CUtil::PathASCII2bin( &pPath[0], (ulong)pPath.size(), m_valuePath );
	else
	{
		m_valuePath.resize(pPath.size());
		m_valuePath = pPath;
	}

	m_valueIndex	= iIndex;
	m_valueLength	= iLength;
}

byteBuffer * CPKCS11Object::GetAttribute( CK_ATTRIBUTE_TYPE attType )
{
	map<CK_ATTRIBUTE_TYPE,byteBuffer *>::iterator	it;

	it = m_attributes.find( attType );

	if( it == m_attributes.end() )
		return NULL;

	return it->second;
}

void CPKCS11Object::GetAttributeBuffer( CK_ATTRIBUTE_TYPE attType, byteBuffer * bBuffer )
{
	byteBuffer * pAttribute = GetAttribute( attType );

	if( !pAttribute )
	{
		bBuffer->clear();
		return;
	}

	if(pAttribute->size())
	{
		bBuffer->resize(pAttribute->size());
		memcpy(bBuffer, pAttribute, pAttribute->size());
	}
}

ulong CPKCS11Object::GetAttributeUlong( CK_ATTRIBUTE_TYPE attType )
{
	byteBuffer *	pAttribute = GetAttribute( attType );

	if( !pAttribute )
		throw Pkcs11Exception( CKR_ATTRIBUTE_TYPE_INVALID );

	if( pAttribute->size() != sizeof(ulong) )
		throw Pkcs11Exception( CKR_ATTRIBUTE_TYPE_INVALID );

	return *(ulong *)&pAttribute->at(0);
}


bool CPKCS11Object::GetAttributeBool( CK_ATTRIBUTE_TYPE attType )
{
	byteBuffer *	pAttribute = GetAttribute( attType );

	if( !pAttribute )
		throw Pkcs11Exception( CKR_ATTRIBUTE_TYPE_INVALID );

	if( pAttribute->size() != sizeof(bool) )
		throw Pkcs11Exception( CKR_ATTRIBUTE_TYPE_INVALID );

	return (pAttribute->at(0) == 0) ? false : true;
}


bool CPKCS11Object::MatchTemplate( CK_ATTRIBUTE_PTR pSearchTemplate, CK_ULONG ulCount )
{
	map<CK_ATTRIBUTE_TYPE,byteBuffer *>::iterator	it;

	for( ulong idx=0; idx<ulCount; ++idx )
	{
		it = m_attributes.find( pSearchTemplate[idx].type );
		if( it == m_attributes.end() )
			return false;

		if( it->second->size() != pSearchTemplate[idx].ulValueLen )
			return false;

		if( memcmp( &it->second->at(0), pSearchTemplate[idx].pValue, pSearchTemplate[idx].ulValueLen ) )
			return false;
	}
	return true;
}

byteBuffer * CPKCS11Object::GetValuePath( void )
{
	return &m_valuePath;
}

int * CPKCS11Object::GetValueIndex( void )
{
	return &m_valueIndex;
}

int * CPKCS11Object::GetValueLength( void )
{
	return &m_valueLength;
}

CK_OBJECT_HANDLE CPKCS11Object::GetHandle( void )
{
	return m_hObject;
}

void CPKCS11Object::CreateObject( CK_ATTRIBUTE_PTR  pTemplate,
								  CK_ULONG          ulCount )
{
	unsigned long ulIdx = 0;

	// Rellenamos el objeto con los atributos de la plantilla
	while( ulIdx<ulCount )
	{
		AddAttribute2Object( &pTemplate[ulIdx] );
		ulIdx++;
	}

}

bool CPKCS11Object::ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
{
	return false;
}

bool CPKCS11Object::VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate,
												CK_ULONG ulCount )
{
	return false;
}

bool CPKCS11Object::EsExportacionDesdeExplorer( CK_ATTRIBUTE_PTR  pTemplate,
												CK_ULONG          ulCount)
{
	// Variables locales a la función
	CK_ULONG ulPos = 0;

	// Variable que devolverá la función
	bool bReturn = false;

	// Comprobamos la longitud de la etiqueta. Cuando se mete mal,
	// el tamańo es de 32 bytes, en grupos de 8-4-4-4-12.

	// Buscamos dentro del template el atributo CKA_LABEL
	for(ulPos = 0; (pTemplate[ulPos].type != CKA_LABEL) && (ulPos<ulCount); ulPos++);
	if(pTemplate[ulPos].type != CKA_LABEL)
		return bReturn;

	// Hemos encontrado el atributo CKA_LABEL, así que deberemos comprobar
	// si está mal introducido por Mozilla
	char* pcEtiqueta = new (char[pTemplate[ulPos].ulValueLen]);

	memset(pcEtiqueta, 0x00, pTemplate[ulPos].ulValueLen);
	memcpy(pcEtiqueta, pTemplate[ulPos].pValue, pTemplate[ulPos].ulValueLen);

	char* pPosition = (char*)pTemplate[ulPos].pValue;
	int valores = 0x00;
	bool encontrado = true;
	while(encontrado)
	{
		pPosition = (char*)memchr(pPosition, 0x2D, pTemplate[ulPos].ulValueLen);
		if( pPosition== NULL)
			encontrado = false;
		else
		{
			valores++;
			pPosition++;
		}
	}
	if(valores>=0x03)
		bReturn = true;

	delete pcEtiqueta;

	return bReturn;
}

bool CPKCS11Object::ModificarEtiquetaExportacion()
{
	CK_BBOOL encontrado		= false;

	byteBuffer *bbSubjectPointer = GetAttribute(CKA_SUBJECT);
	
	// Si no había CKA_SUBJECT, salimos sin hacer ningún cambio
	if(!bbSubjectPointer)
		return false;
	
	byteBuffer bbSubject(*bbSubjectPointer);

	try
	{
		// Buscaremos la secuencia ASN1 que indica correspondiente
		// al atributo commonName (06 03 55 04 03 13 xx).
		int offset;
		long tag, len;

		// Leemos el primer TLV
		offset = CUtil::getTLV( &bbSubject[0], &tag, &len);

		if( (bbSubject.size() != offset + len) ||
			(tag != 0x30) )
		{
			return false;
		}

		// Leemos el TLV
		offset+= CUtil::getTLV( &bbSubject[offset], &tag, &len);
		offset+= len;

		if( (bbSubject.size()<=(unsigned long)offset)	||
			(bbSubject[offset] != 0x30) &&
			(bbSubject[offset] != 0x31))
			return false;

		// Leemos el TLV
		offset+= CUtil::getTLV( &bbSubject[offset], &tag, &len);
		offset+= len;

		if( (bbSubject.size()<=(unsigned long)offset)	||
			(bbSubject[offset] != 0x30) &&
			(bbSubject[offset] != 0x31))
			return false;

		// Leemos el TLV
		offset+= CUtil::getTLV( &bbSubject[offset], &tag, &len);
		offset+= len;

		if( (bbSubject.size()<=(unsigned long)offset)	||
			(bbSubject[offset] != 0x30) &&
			(bbSubject[offset] != 0x31))
			return false;

		// Leemos el TLV
		offset+= CUtil::getTLV( &bbSubject[offset], &tag, &len);
		offset+= len;

		if( (bbSubject.size()<=(unsigned long)offset)	||
			(bbSubject[offset] != 0x30) &&
			(bbSubject[offset] != 0x31))
			return false;

		// Leemos el TLV
		offset+= CUtil::getTLV( &bbSubject[offset], &tag, &len);

		if( (bbSubject.size()<=(unsigned long)offset)	||
			(bbSubject[offset] != 0x30) &&
			(bbSubject[offset] != 0x31))
			return false;

		// Leemos el TLV
		offset+= CUtil::getTLV( &bbSubject[offset], &tag, &len);

		if( (bbSubject.size()<=(unsigned long)offset)	||
			(bbSubject[offset] != 0x06) )
			return false;

		// Leemos el TLV
		offset+= CUtil::getTLV( &bbSubject[offset], &tag, &len);
		offset+= len;

		if( (bbSubject.size()<=(unsigned long)offset)	||
			(bbSubject[offset] != 0x13) )
			return false;

		this->SetAttribute(CKA_LABEL, &bbSubject[offset+2], bbSubject[offset+1]);

		return true;
	}
	catch(Pkcs11Exception & e)
	{
		return false;
	}

	return false;	
}

//______________________________________________________

CPKCS11CertificateObject::CPKCS11CertificateObject ()
{
	SetAttribute( CKA_CLASS,		(ulong)CKO_CERTIFICATE );
	SetAttribute( CKA_TOKEN,		true );
	SetAttribute( CKA_PRIVATE,		false );
	SetAttribute( CKA_MODIFIABLE,	true );
	SetAttribute( CKA_LABEL,		(byte*)"",0 );
}

/* Destructor:
   Descrip:    Libera la memoria asignada en el contructor si ha creado
               una plantilla propia.                                       */

CPKCS11CertificateObject::~CPKCS11CertificateObject ()
{
}

bool CPKCS11CertificateObject::ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
{
	unsigned int idx = 0;

	while ( idx<ulCount )
	{
		// Comprobamos los atributos válidos
		if( (pTemplate[idx].type != CKA_CLASS)				&&
			(pTemplate[idx].type != CKA_TOKEN)				&&
			(pTemplate[idx].type != CKA_PRIVATE)			&&
			(pTemplate[idx].type != CKA_MODIFIABLE)			&&
			(pTemplate[idx].type != CKA_LABEL)				&&

			(pTemplate[idx].type != CKA_CERTIFICATE_TYPE)	&&

			(pTemplate[idx].type != CKA_SUBJECT)			&&
			(pTemplate[idx].type != CKA_ID)					&&
			(pTemplate[idx].type != CKA_ISSUER)				&&
			(pTemplate[idx].type != CKA_SERIAL_NUMBER)		&&
			(pTemplate[idx].type != CKA_VALUE))
			return false;

		idx++;
	}

	return true;
}

bool CPKCS11CertificateObject::VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate,
														   CK_ULONG ulCount )
{
	CK_ULONG i = 0;

	while(i<ulCount)
	{
		// Comprobamos los únicos atributos susceptibles de ser modificados para este tipo de objeto
		if ( (pTemplate[i].type != CKA_LABEL)	&&
			 (pTemplate[i].type != CKA_ID)		&&
			 (pTemplate[i].type != CKA_ISSUER)	&&
			 (pTemplate[i].type != CKA_SERIAL_NUMBER) )
			return false;

		i++;
	}

	return true;
}


//______________________________________________________
/*CK_ULONG CPKCS11KeyObject::GetKeyLen()
{
	ulong ulBitsLen = 0;
	if(m_ulKeyLen>0x100)
		return m_ulKeyLen/8;

	return m_ulKeyLen;
};//*/


CPKCS11PublicKeyObject::CPKCS11PublicKeyObject ()
{
	SetAttribute( CKA_CLASS,			(ulong)CKO_PUBLIC_KEY );
	SetAttribute( CKA_TOKEN,			true );
	SetAttribute( CKA_PRIVATE,			false);
	SetAttribute( CKA_MODIFIABLE,		true );
	SetAttribute( CKA_LABEL,			(byte*)"",0 );
	SetAttribute( CKA_SUBJECT,			(byte*)"",0 );
	SetAttribute( CKA_DERIVE,			false);
	SetAttribute( CKA_LOCAL,         	false);
	SetAttribute( CKA_ENCRYPT,       	false);
	SetAttribute( CKA_VERIFY,        	false);
	SetAttribute( CKA_VERIFY_RECOVER,	false);
	SetAttribute( CKA_WRAP,          	false);
	SetAttribute( CKA_START_DATE,		(byte*)"",0 );
	SetAttribute( CKA_END_DATE,			(byte*)"",0 );
}

/* Destructor:
   Descrip:    Libera la memoria asignada en el contructor si ha creado
               una plantilla propia.                                       */

CPKCS11PublicKeyObject::~CPKCS11PublicKeyObject ()
{
}

bool CPKCS11PublicKeyObject::ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
{
	unsigned int idx = 0;

	while ( idx<ulCount )
	{
		// Comprobamos los atributos válidos
		if( (pTemplate[idx].type != CKA_CLASS)				&&
			(pTemplate[idx].type != CKA_TOKEN)				&&
			(pTemplate[idx].type != CKA_PRIVATE)			&&
			(pTemplate[idx].type != CKA_MODIFIABLE)			&&
			(pTemplate[idx].type != CKA_LABEL)				&&

			(pTemplate[idx].type != CKA_KEY_TYPE)			&&
			(pTemplate[idx].type != CKA_ID)					&&
			(pTemplate[idx].type != CKA_START_DATE)			&&
			(pTemplate[idx].type != CKA_END_DATE)			&&
			(pTemplate[idx].type != CKA_DERIVE)				&&
			(pTemplate[idx].type != CKA_LOCAL)				&&

			(pTemplate[idx].type != CKA_SUBJECT)			&&
			(pTemplate[idx].type != CKA_ENCRYPT)			&&
			(pTemplate[idx].type != CKA_VERIFY)				&&
			(pTemplate[idx].type != CKA_VERIFY_RECOVER)		&&
			(pTemplate[idx].type != CKA_WRAP)				&&

			(pTemplate[idx].type != CKA_MODULUS)			&&
			(pTemplate[idx].type != CKA_MODULUS_BITS)		&&
			(pTemplate[idx].type != CKA_PUBLIC_EXPONENT)
			)
			return false;

		idx++;
	}

	return true;
}

bool CPKCS11PublicKeyObject::VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate,
														 CK_ULONG ulCount )
{
	CK_ULONG i = 0;

	while(i<ulCount)
	{
		// Comprobamos los únicos atributos susceptibles de ser modificados para este tipo de objeto
		if ( (pTemplate[i].type != CKA_LABEL)		&&
			 (pTemplate[i].type != CKA_ID)			&&
			 (pTemplate[i].type != CKA_START_DATE)	&&
			 (pTemplate[i].type != CKA_END_DATE)	&&
			 (pTemplate[i].type != CKA_DERIVE)		&&
			 (pTemplate[i].type != CKA_SUBJECT)		&&
			 (pTemplate[i].type != CKA_ENCRYPT)		&&
			 (pTemplate[i].type != CKA_VERIFY)		&&
			 (pTemplate[i].type != CKA_VERIFY_RECOVER))
			return false;

		i++;
	}

	return true;
}

//______________________________________________________

CPKCS11PrivateKeyObject::CPKCS11PrivateKeyObject ()
{
	SetAttribute( CKA_CLASS,			(ulong)CKO_PRIVATE_KEY );
	SetAttribute( CKA_TOKEN,			true );
	SetAttribute( CKA_PRIVATE,			false);
	SetAttribute( CKA_MODIFIABLE,		true );
	SetAttribute( CKA_LABEL,			(byte*)"",0 );
	SetAttribute( CKA_SUBJECT,			(byte*)"",0 );
	SetAttribute( CKA_DERIVE,			false);
	SetAttribute( CKA_LOCAL,			false);
	SetAttribute( CKA_SENSITIVE,		true);	
	SetAttribute( CKA_DECRYPT,			false);
	SetAttribute( CKA_SIGN,				false);
	SetAttribute( CKA_SIGN_RECOVER,		false);
	SetAttribute( CKA_UNWRAP,			false);
	SetAttribute( CKA_EXTRACTABLE,		false);
	SetAttribute( CKA_ALWAYS_SENSITIVE, true);
	SetAttribute( CKA_NEVER_EXTRACTABLE,true);
	SetAttribute( CKA_START_DATE,		(byte*)"",0 );
	SetAttribute( CKA_END_DATE,			(byte*)"",0 );

}

/* Destructor:
   Descrip:    Libera la memoria asignada en el contructor si ha creado
               una plantilla propia.                                       */

CPKCS11PrivateKeyObject::~CPKCS11PrivateKeyObject ()
{
}

bool CPKCS11PrivateKeyObject::IsSensitive ( CK_ATTRIBUTE_TYPE attType )
{
	return	(attType == CKA_PRIVATE_EXPONENT) ||
			(attType == CKA_PRIME_1) ||
			(attType == CKA_PRIME_2) ||
			(attType == CKA_EXPONENT_1) ||
			(attType == CKA_EXPONENT_2) ||
			(attType == CKA_COEFFICIENT);

}

bool CPKCS11PrivateKeyObject::ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
{
	unsigned int idx = 0;

	while ( idx<ulCount )
	{
		// Comprobamos los atributos válidos
		if( (pTemplate[idx].type != CKA_CLASS)				&&
			(pTemplate[idx].type != CKA_TOKEN)				&&
			(pTemplate[idx].type != CKA_PRIVATE)			&&
			(pTemplate[idx].type != CKA_MODIFIABLE)			&&
			(pTemplate[idx].type != CKA_LABEL)				&&

			(pTemplate[idx].type != CKA_KEY_TYPE)			&&
			(pTemplate[idx].type != CKA_ID)					&&
			(pTemplate[idx].type != CKA_START_DATE)			&&
			(pTemplate[idx].type != CKA_END_DATE)			&&
			(pTemplate[idx].type != CKA_DERIVE)				&&
			(pTemplate[idx].type != CKA_LOCAL)				&&

			(pTemplate[idx].type != CKA_SUBJECT)			&&
			(pTemplate[idx].type != CKA_SENSITIVE)			&&
			(pTemplate[idx].type != CKA_DECRYPT)			&&
			(pTemplate[idx].type != CKA_SIGN)				&&
			(pTemplate[idx].type != CKA_SIGN_RECOVER)		&&
			(pTemplate[idx].type != CKA_UNWRAP)				&&
			(pTemplate[idx].type != CKA_EXTRACTABLE)		&&
			(pTemplate[idx].type != CKA_ALWAYS_SENSITIVE)	&&
			(pTemplate[idx].type != CKA_NEVER_EXTRACTABLE)	&&

			(pTemplate[idx].type != CKA_MODULUS)			&&
			(pTemplate[idx].type != CKA_PUBLIC_EXPONENT)	&&
			(pTemplate[idx].type != CKA_PRIVATE_EXPONENT)	&&
			(pTemplate[idx].type != CKA_PRIME_1)			&&
			(pTemplate[idx].type != CKA_PRIME_2)			&&
			(pTemplate[idx].type != CKA_EXPONENT_1)			&&
			(pTemplate[idx].type != CKA_EXPONENT_2)			&&
			(pTemplate[idx].type != CKA_COEFFICIENT)
			)
			return false;

		idx++;
	}

	return true;
}

bool CPKCS11PrivateKeyObject::VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate,
														  CK_ULONG ulCount )
{
	CK_ULONG i = 0;

	while(i<ulCount)
	{
		// Comprobamos los únicos atributos susceptibles de ser modificados para este tipo de objeto
		if ( (pTemplate[i].type != CKA_LABEL)		&&
			 (pTemplate[i].type != CKA_ID)			&&
			 (pTemplate[i].type != CKA_START_DATE)	&&
			 (pTemplate[i].type != CKA_END_DATE)	&&
			 (pTemplate[i].type != CKA_DERIVE)		&&
			 (pTemplate[i].type != CKA_SUBJECT)		&&
			 (pTemplate[i].type != CKA_SENSITIVE)	&&
			 (pTemplate[i].type != CKA_DECRYPT)		&&
			 (pTemplate[i].type != CKA_SIGN)		&&
			 (pTemplate[i].type != CKA_SIGN_RECOVER)&&
			 (pTemplate[i].type != CKA_UNWRAP)		&&
			 (pTemplate[i].type != CKA_EXTRACTABLE))
			return false;

		i++;
	}

	return true;
}
//______________________________________________________

CPKCS11DataObject::CPKCS11DataObject ()
{
	SetAttribute( CKA_CLASS,		(ulong)CKO_DATA );
	SetAttribute( CKA_TOKEN,		true );
	SetAttribute( CKA_PRIVATE,		false );
	SetAttribute( CKA_MODIFIABLE,	true );
	SetAttribute( CKA_LABEL,		(byte*)"",0 );
	SetAttribute( CKA_APPLICATION,	(byte*)"",0 );
}

/* Destructor:
   Descrip:    Libera la memoria asignada en el contructor si ha creado
               una plantilla propia.                                       */

CPKCS11DataObject::~CPKCS11DataObject ()
{
}

bool CPKCS11DataObject::ValidAttributes( CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
{
	unsigned int idx = 0;

	while ( idx<ulCount )
	{
		// Comprobamos los atributos válidos
		if( (pTemplate[idx].type != CKA_CLASS)				&&
			(pTemplate[idx].type != CKA_TOKEN)				&&
			(pTemplate[idx].type != CKA_PRIVATE)			&&
			(pTemplate[idx].type != CKA_MODIFIABLE)			&&
			(pTemplate[idx].type != CKA_LABEL)				&&

			(pTemplate[idx].type != CKA_APPLICATION)		&&
			(pTemplate[idx].type != CKA_OBJECT_ID)			&&
			(pTemplate[idx].type != CKA_VALUE))
			return false;

		idx++;
	}

	return true;
}

bool CPKCS11DataObject::VerifyModifiableAttributes( CK_ATTRIBUTE_PTR pTemplate,
													CK_ULONG ulCount )
{
	CK_ULONG i = 0;

	while(i<ulCount)
	{
		// Comprobamos los únicos atributos susceptibles de ser modificados para este tipo de objeto
		if ( (pTemplate[i].type != CKA_LABEL)		&&
			 (pTemplate[i].type != CKA_VALUE)		&&
			 (pTemplate[i].type != CKA_APPLICATION))
			return false;

		i++;
	}

	return true;
}
