/*
[]=================================================================[]
	CryptoDemo.cpp

	Copyright (C) 2001 Feitian Tech. Co. Ltd. All rights reserved.
	by Water Bird
	Created at 31-5-2001   9:50

	Comment : 
[]=================================================================[]
*/

#include <Windows.h>
#include <Stdio.h>
#include <conio.h>
#include "CryptoDemo.h"
#include "../common/eps1kDemo.h"
#include "../common/eps1kUtility.h"

#define CRYPTO_KEY1 0xEF03
#define CRYPTO_KEY2 0xEF04
#define RANDOM_BUFFER_SIZE 0x20
#define USER_KEY_SIZE 20

// Global varibles.

int main(void)
{
	EPAS_STATUS epsRet;
	EPAS_HANDLE handle;
	EPAS_DIRINFO diDemo;
	unsigned char pucUserKey[USER_KEY_SIZE];
	unsigned char pRandomBuf[RANDOM_BUFFER_SIZE];

	unsigned char pucSoftMD5HMAC[16];
	unsigned char pucDeviceMD5HMAC[16];
	
	ShowDemoTitle();

	// Create context handle.
	epsRet = epas_CreateContext(
		&handle,
		0,
		EPAS_API_VERSION
		);
	if (FT_SUCCESS == epsRet)
	{
		// Open an unused device.
		epsRet = OpenAnUnusedDevice(handle);
		if (!CheckOP(epsRet, "Find an unused device and opened"))
		{
			epas_DeleteContext(handle);
			return (1);
		}

		// Create a directory for demo.
		CreateDemoDir(handle, &diDemo);

		// Get user input for create key file.
		printf("\nPlease set your security key (Max to %d characters): ",USER_KEY_SIZE);
		scanf("%s",pucUserKey);

		// In the demo directory, create two key files for MD5_HMAC.
		CreateKeyFiles(handle,pucUserKey);

		// Create random data for MD5_HMAC compute.
		epsRet = epas_GenRandom(
			handle,
			0,
			pRandomBuf,
			RANDOM_BUFFER_SIZE
			);
		CheckOP(epsRet, "Get random data");

		printf("\nNow let's do MD5_HMAC compute.\n");

		// Software MD5_HMAC compute.
		// This can be used in server.
		MD5_HMAC(
			pRandomBuf,
			RANDOM_BUFFER_SIZE,
			pucUserKey,
			lstrlen((char*)pucUserKey),
			NULL,
			NULL,
			pucSoftMD5HMAC
			);
		printf("\nResult of MD5_HMAC by software :\n");
		ShowData(pucSoftMD5HMAC, 16);
		printf("\n\n");

		// MD5_HMAC compute by device.
		// Usually used in client.
		epsRet = epas_MD5_HMAC(
			handle,
			CRYPTO_KEY1,
			CRYPTO_KEY2,
			pRandomBuf,
			RANDOM_BUFFER_SIZE,
			pucDeviceMD5HMAC
			);
		if(CheckOP(epsRet, "MD5_HMAC compute by device"))
		{
			printf("Result of MD5_HMAC by device :\n");
			ShowData(pucDeviceMD5HMAC, 16);
		}

		// Are them look as same?
		if (0 == memcmp(pucSoftMD5HMAC, pucDeviceMD5HMAC, 16))
		{
			printf("\n\nCongratulation! You passed the MD5_HMAC verify.\n\n");
		}

		// Clear up the demo data.
		epsRet = epas_DeleteDir(
			handle,
			EPAS_DIR_BY_ID | EPAS_DELETE_RECURSIVE,
			diDemo.ulID,
			NULL
			);
		CheckOP(epsRet, "Remove demo directory and all demo files");
		
		epas_CloseDevice(handle);
		epas_DeleteContext(handle);
	}

	return (0);
} // End of main().

void CreateDemoDir(EPAS_HANDLE handle, PEPAS_DIRINFO pdiDemo)
{
	EPAS_STATUS epsRet;

	epsRet = epas_CreateDir(
		handle,
		EPAS_CREATE_AUTO_ID,
		NULL,
		NULL,
		pdiDemo,
		sizeof(EPAS_DIRINFO)
		);
	CheckOP(epsRet, "Create directory for demo");
} // End of CreateDemoDir().

void CreateKeyFiles(EPAS_HANDLE handle, unsigned char* pucKey)
{
	EPAS_STATUS epsRet;
	EPAS_FILEINFO fi;
	unsigned char pucKey1[16];
	unsigned char pucKey2[16];
	unsigned char pucTarget[16];
	unsigned long ulWritten;
	
	MD5_HMAC(
		NULL,
		0,
		pucKey,
		lstrlen((char*)pucKey),
		pucKey1,
		pucKey2,
		pucTarget
		);

	// Create first key file.
	ZeroMemory(&fi, sizeof(EPAS_FILEINFO));
	
	fi.ulID = CRYPTO_KEY1;
	fi.ulFileSize = 16;
	fi.ucFileType = EPAS_FILETYPE_KEY;
	fi.ucReadAccess = EPAS_ACCESS_NONE;
	fi.ucWriteAccess = EPAS_ACCESS_ANYONE;
	fi.ucCryptAccess = EPAS_ACCESS_ANYONE;
	
	epsRet = epas_CreateFile(
		handle,
		0,
		&fi,
		sizeof(EPAS_FILEINFO)
		);
	CheckOP(epsRet, "Create 1st key file");
	
	epsRet = epas_Write(
		handle,
		0,
		0,
		pucKey1,
		16,
		&ulWritten);
	CheckOP(epsRet, "Save context of 1st key file");
	
	// Create second key file.
	ZeroMemory(&fi, sizeof(EPAS_FILEINFO));
	
	fi.ulID = CRYPTO_KEY2;
	fi.ulFileSize = 16;
	fi.ucFileType = EPAS_FILETYPE_KEY;
	fi.ucReadAccess = EPAS_ACCESS_NONE;
	fi.ucWriteAccess = EPAS_ACCESS_ANYONE;
	fi.ucCryptAccess = EPAS_ACCESS_ANYONE;
	
	epsRet = epas_CreateFile(
		handle,
		0,
		&fi,
		sizeof(EPAS_FILEINFO)
		);
	CheckOP(epsRet, "Create 2nd key file");
	
	epsRet = epas_Write(
		handle,
		0,
		0,
		pucKey2,
		16,
		&ulWritten);
	CheckOP(epsRet, "Save context of 2nd key file");
} // End of CreateKeyFiles().
