#include "Communicator.h"
#include "Util.h"

//
// Includes de CryptoPP
//
#include "CryptoPP/integer.h"

using namespace CryptoPP;

class CComm_DNIe : public CCommunicator
{

public:
	CComm_DNIe( CSlot & slot );
	~CComm_DNIe();
	
	#if defined _CFG_CACHE_PIN
		void SignMech ( CMech * pMechanism, byteBuffer & data, byteBuffer & signature );
	#endif

	void VerifyPIN( CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen );
	void ChangePIN( CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen,
					CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen,
					byte bCodeId = 1);
	void UnblockPIN( CK_UTF8CHAR_PTR pUnblock, CK_ULONG ulUnbLen,
					 CK_UTF8CHAR_PTR pNewPIN, CK_ULONG ulPinLen);
	ushort GetPINCounter();
	int GetDniType();

protected:
	void sendAPDU( byte * pCmd, ulong cmdLen, byteBuffer & answer, unsigned short expected_SW = 0x9000 );
	void sendAPDU( byteBuffer &cmd, byteBuffer & answer, unsigned short expected_SW = 0x9000 );
	void sendAPDUExt( byteBuffer & cmdHeader, byteBuffer & cmdData, byteBuffer & answer,unsigned short expected_SW );
	
private:
			
	#if defined _CFG_CACHE_PIN
		// Miembro para almacenar la caché de PIN
		byteBuffer		m_bbRest;
		
		// Método para presentar el PIN de la caché
		void RestorePIN( );
	#endif

	//
	// Estructuras internas
	//
	typedef struct
	{
		RSA_PublicKey	PK_RCAicc;

		byteBuffer		PK_RCA_AUT_keyRef;
		byteBuffer		C_CV_CA_CS_AUT;
		byteBuffer		PK_CA_CS_AUT_keyRef;
		byteBuffer		C_CV_IFD_AUT;
		byteBuffer		IFD_keyRef;

		byteBuffer		SN_IFD;
		byteBuffer		PK_IFD_AUT_keyRef;
		byteBuffer		SK_ICC_AUT_keyRef;
		RSA_PrivateKey	SK_IFD_AUT;
		int				MAC_Len;
	} sChannelData;

	//
	// Método para establecer el canal seguro
	//
	void	setChannel( bool isPinChannel = false );

	//
	// Métodos privados utilizados en la contrucción de mensajes
	// securizados
	//
	void	secChannelEncodeAPDU( byteBuffer & apdu );
	void	secChannelDecodeResponse( byteBuffer & answer );
	void	computeMAC( byteBuffer & data, byteBuffer & cc );

	//
	// Funciones para cargar y liberar los datos de canal.
	//
	void	loadChannelData( sChannelData & channelData, bool isPinChannel = false);
	void	freeChannelData( sChannelData & channelData );

	//
	// Variables para controlar el estado del canal
	//
	bool			m_secureChannel;
	byteBuffer		m_kenc;
	byteBuffer		m_kmac;
	byteBuffer		m_ssc;
	int				m_macLen;

	//
	// Variable que nos va a indicar si se trata de un DNIe + Pasaporte (DNIe 3.0)
	// 
	int				m_DniType;	// 0 no es DNIe
								// 1 DNIe 2.0 (canal USUARIO)
								// 2 DNIe 3.0 (canal PIN y canal USUARIO)
};