
#include "stdafx.h"
#include <time.h>
#include "EncFile.h"
#include "des.h"

#include <epassapi.h>

static EPAS_HANDLE g_hToken = NULL;

void ShowMsg(LPCTSTR lpMsg)
{
	MessageBox(NULL,lpMsg,"ePassShellExt",MB_OK);
}

void EF_GenKey(PENCFILE_DESC pDesc)
{
	memset(pDesc->sRandStr,0,55);
	
	srand(time(NULL));
	for(int i=0;i<55;i++)
	{
		pDesc->sRandStr[i] = (BYTE)rand();
	}
	pDesc->iKeyID1 = 1;
	pDesc->iKeyID2 = 2;
}

void ShowErrInfo(EPAS_STATUS retval)
{
	switch(retval)
	{
	case FT_SUCCESS					 :
		ShowMsg("Suscess!\n");
		return;
	case FT_CANNOT_OPEN_DRIVER		 :
		ShowMsg("Err: failed to open the driver!");
		break;
	case FT_INVALID_DRVR_VERSION	 :
		ShowMsg("Err: Invalid driver version!");
		break;
	case FT_INVALID_COMMAND          :
		ShowMsg("Err: Invalid command!");
		break;
	case FT_ACCESS_DENIED            :
		ShowMsg("Err: access denied!");
		break;
	case FT_UNIT_NOT_FOUND           :
		ShowMsg("Err: unit was not found!");
		break;
	case FT_DEVICE_REMOVED           :
		ShowMsg("Err: the device was removed!");
		break;
	case FT_COMMUNICATIONS_ERROR     :
		ShowMsg("Err: communication terminated abnormally!");
		break;
	case FT_DIR_NOT_FOUND            :
		ShowMsg("Err: The directory was not found!");
		break;
	case FT_FILE_NOT_FOUND           :
		ShowMsg("Err: The file was not found!");
		break;
	case FT_MEM_CORRUPT              :
		ShowMsg("Err: Memory inside the token was corrupted!");
		break;
	case FT_INTERNAL_HW_ERROR        :
		ShowMsg("Err: Internal hardware error occured!");
		break;
	case FT_INVALID_RESP_SIZE        :
		ShowMsg("Err: Abnormal response received from the token!");
		break;
	case FT_PIN_EXPIRED              :
		ShowMsg("Err: The PIN retry counter register return zero!");
		break;
	case FT_ALREADY_EXISTS           :
		ShowMsg("Err: The item already exist!");
		break;
	case FT_NOT_ENOUGH_MEMORY        :
		ShowMsg("Err: Insufficient memory to perform the command!");
		break;
	case FT_INVALID_PARAMETER        :
		ShowMsg("Err: Invalid parameter was assigned to the functoin!");
		break;
	case FT_INPUT_TOO_LONG           :
		ShowMsg("Err: The length of the input data is too long!");
		break;
	case FT_INVALID_FILE_SELECTED    :
		ShowMsg("Err: The selected file is invalid!");
		break;
	case FT_DEVICE_IN_USE            :
		ShowMsg("Err: The device is currently used by another application!");
		break;
	case FT_INVALID_API_VERSION      :
		ShowMsg("Err: The version of the API library is invalid!");
		break;
	case FT_TIME_OUT_ERROR           :
		ShowMsg("Err: The operation time out!");
		break;
	case FT_ITEM_NOT_FOUND           :
		ShowMsg("Err: The item was not found!");
		break;
	case FT_COMMAND_ABORTED          :
		ShowMsg("Err: Command aborted abnormally!");
		break;
	case FT_INVALID_STATUS           :
		ShowMsg("Err: Invalid return value received from the token!");
		break;
	default							 :
		ShowMsg("Err: Unknown error occured!");
		break;
	}
	char buf[128];
	wsprintf(buf,"(0x%X)\n",retval);
	ShowMsg(buf);
}

int EF_InitKey(UCHAR uKey[],PENCFILE_DESC pDesc)
{
	int iRet = 0;
	int iCode = 0;
	iCode = epas_CreateContext(&g_hToken,0,EPAS_API_VERSION);
	if(iCode!=FT_SUCCESS)
	{
		ShowErrInfo(iCode);
		iRet =  -1;
		goto lbl_DelCtx;
	}
	iCode = epas_OpenDevice(g_hToken,EPAS_OPEN_FIRST,NULL);
	if(iCode!=FT_SUCCESS)
	{
		ShowErrInfo(iCode);
		iRet =  -1;
		goto lbl_DelCtx;
	}
	
	BYTE bufDigest[64];
	iCode = epas_MD5_HMAC(g_hToken,
					pDesc->iKeyID1,
					pDesc->iKeyID2,
					pDesc->sRandStr,
					55,
					bufDigest);
	if(iCode != FT_SUCCESS)
	{
		ShowErrInfo(iCode);
		iRet =  -1;
		goto lbl_final;
	}
	memcpy(uKey,bufDigest,8);
lbl_final:
	epas_CloseDevice(g_hToken);
lbl_DelCtx:
	epas_DeleteContext(g_hToken);
	return iRet;
}

void EF_AddExt(LPTSTR lpFileName)
{
	strcat(lpFileName,".!ef");
}

void EF_RemoveExt(LPTSTR lpFileName)
{
	char* p = lpFileName;
	int iLen = strlen(lpFileName);
	p+=iLen-4;
	if(stricmp(p,".!ef")==0)
		*p = 0;
}

void EF_WriteDesc(PENCFILE_DESC pDesc,HANDLE hFile)
{
	DWORD dwWritten=0;

	pDesc->dwHeadSize = sizeof(ENCFILE_DESC);
	pDesc->dwSign = ENC_SIGN;	

	WriteFile(hFile,pDesc,sizeof(ENCFILE_DESC),&dwWritten,NULL);
}

int EF_ReadDesc(PENCFILE_DESC pDesc,HANDLE hFile)
{
	DWORD dwRead=0;	
	if(!ReadFile(hFile,pDesc,sizeof(ENCFILE_DESC),&dwRead,NULL))
	{
		ShowMsg("Read file header error");
		return -1;
	}
	if(dwRead!=sizeof(ENCFILE_DESC))
	{
		ShowMsg("sign is mismatch");
		return -1;
	}		
	return 0;
}

int EF_Encrypt(LPCTSTR lpSrcFileName)
{
	char  lpDstFileName[MAX_PATH];
	char  lpBakFileName[MAX_PATH];
	char  lpBuf[MAX_PATH];
	const int BufSize = 512*32;
	BYTE  buffer[BufSize];
	DWORD dwSizeToRead=BufSize,dwSizeOfRead=1;
	DWORD dwSizeToWrite,dwSizeOfWrite;
	bool  bSucc = true;
	
	strcpy(lpDstFileName,lpSrcFileName);
	EF_AddExt(lpDstFileName);
	strcpy(lpBakFileName,lpSrcFileName);
	SYSTEMTIME	st;
	GetLocalTime(&st);
	wsprintf(lpBuf,"_%04d%02d%02d_%02d%02d%02d.bak",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);
	strcat(lpBakFileName,lpBuf);
	CopyFile(lpSrcFileName,lpBakFileName,FALSE);

	HANDLE hSrcFile = CreateFile(lpSrcFileName,
						  GENERIC_READ,
						  0,
						  NULL,
						  OPEN_EXISTING,
						  FILE_ATTRIBUTE_NORMAL,
						  NULL);	
	HANDLE hDstFile = CreateFile(lpDstFileName,
						  GENERIC_WRITE|GENERIC_READ,
						  0,
						  NULL,
						  CREATE_ALWAYS,
						  FILE_ATTRIBUTE_NORMAL,
						  NULL);
	
	des_ctx dc;
	UCHAR   key[16] = "1234567";

	ENCFILE_DESC efDesc;
	memset(&efDesc,0,sizeof(ENCFILE_DESC));
	EF_GenKey(&efDesc);

	if(EF_InitKey(key,&efDesc)!=FT_SUCCESS)
	{
		bSucc = false;
		goto lbl_final;
	}

	des_key(&dc,key);

	DWORD dwHigh;		
	efDesc.dwOrgFileSize = GetFileSize(hSrcFile,&dwHigh);
	EF_WriteDesc(&efDesc,hDstFile);

	char szBuf[512];
	wsprintf(szBuf,"filesize %d",efDesc.dwOrgFileSize);
	OutputDebugString(szBuf);	
	
	
	while(dwSizeOfRead)
	{			
		ReadFile(hSrcFile,buffer,dwSizeToRead,&dwSizeOfRead,NULL);

		if(dwSizeOfRead!=0)
		{
			int nBlock;
			if((dwSizeOfRead%8)!=0)
			{
				nBlock = dwSizeOfRead/8 +1;
			}
			else
				nBlock = dwSizeOfRead/8;

			des_enc(&dc,buffer,nBlock);			
		
			if(dwSizeOfRead!=dwSizeToRead)
			{			
				dwSizeToWrite = nBlock * 8;
			}
			else
				dwSizeToWrite = dwSizeOfRead;

			WriteFile(hDstFile,buffer,dwSizeToWrite,&dwSizeOfWrite,NULL);
		}		
	}
lbl_final:
	CloseHandle(hSrcFile);
	CloseHandle(hDstFile);
	if(bSucc)
		DeleteFile(lpSrcFileName);

	return 0;
}

int EF_Decrypt(LPCTSTR lpSrcFileName)
{
	char  lpDstFileName[MAX_PATH];
	const int BufSize = 512*32;
	BYTE  buffer[BufSize];
	DWORD dwSizeToRead=BufSize,dwSizeOfRead=1;
	DWORD dwSizeToWrite,dwSizeOfWrite;
	bool  bSucc = true;
	
	strcpy(lpDstFileName,lpSrcFileName);
	EF_RemoveExt(lpDstFileName);

	HANDLE hSrcFile = CreateFile(lpSrcFileName,
						  GENERIC_READ,
						  0,
						  NULL,
						  OPEN_EXISTING,
						  FILE_ATTRIBUTE_NORMAL,
						  NULL);	
	HANDLE hDstFile = CreateFile(lpDstFileName,
						  GENERIC_WRITE|GENERIC_READ,
						  0,
						  NULL,
						  CREATE_ALWAYS,
						  FILE_ATTRIBUTE_NORMAL,
						  NULL);

	
	des_ctx dc;
	UCHAR   key[16] = "1234567";

	ENCFILE_DESC efDesc;
	EF_ReadDesc(&efDesc,hSrcFile);
	DWORD dwOrgFileSize = efDesc.dwOrgFileSize;

	if(EF_InitKey(key,&efDesc)!=FT_SUCCESS)
	{
		bSucc = false;
		goto lbl_final;
	}

	des_key(&dc,key);
	
	while(dwOrgFileSize!=0)
	{			
		
		ReadFile(hSrcFile,buffer,dwSizeToRead,&dwSizeOfRead,NULL);

		if(dwSizeOfRead!=0)
		{
			int nBlock = dwSizeOfRead/8;

			des_dec(&dc,buffer,nBlock);						
			
			if(dwOrgFileSize>dwSizeOfRead)
				dwSizeToWrite = dwSizeOfRead;
			else
				dwSizeToWrite = dwOrgFileSize;

			WriteFile(hDstFile,buffer,dwSizeToWrite,&dwSizeOfWrite,NULL);

			dwOrgFileSize -= dwSizeOfRead;
		}	
		else
			break;
	}
lbl_final:
	CloseHandle(hSrcFile);
	CloseHandle(hDstFile);
	if(bSucc)
		DeleteFile(lpSrcFileName);

	return 0;
}

