// attribute_extract.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "../pkcs11_wrapper.h"


int _tmain(int argc, _TCHAR* argv[])
{
	if(argc < 2)
		return 1;

	char * p11_dll = argv[1];

	pkcs11_wrapper p11_wrapper;

	if(0 != p11_wrapper.pkcs11_initialize(p11_dll))
	{
		return 1;
	}

	CK_FUNCTION_LIST_PTR pToken = p11_wrapper.GetFunctionsPtr();
	CK_RV rv = CKR_OK;

	CK_SLOT_ID_PTR pSlotList;
	CK_ULONG ulCount;
	CK_SESSION_HANDLE hSession;

	rv = pToken->C_GetSlotList(CK_TRUE, NULL_PTR, &ulCount);
	ERROR_THROW(rv);

	pSlotList = (CK_SLOT_ID_PTR)new CK_SLOT_ID[ulCount];;
	rv = pToken->C_GetSlotList(CK_TRUE, pSlotList, &ulCount);
	ERROR_THROW(rv);

	//Create a read only session
	rv = pToken->C_OpenSession(pSlotList[0], CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
	ERROR_THROW(rv);

	CK_UTF8CHAR uPin[] = "11111111";
	rv = pToken->C_Login(hSession, CKU_USER, uPin, 8);
	ERROR_THROW(rv);

	CK_BYTE cka_value[128] = {1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8};
	CK_OBJECT_CLASS oClass = CKO_SECRET_KEY;
	CK_KEY_TYPE keyType = CKK_AES; 
	CK_BBOOL bTrue = true;
	CK_BBOOL bFalse = false;
	CK_ULONG ulLen = 16;

	CK_ATTRIBUTE AESItem[] = {
		{CKA_CLASS, &oClass, sizeof(CK_OBJECT_CLASS)},
		{CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)},
		{CKA_ENCRYPT, &bTrue, sizeof(CK_BBOOL)},
		{CKA_DECRYPT, &bTrue, sizeof(CK_BBOOL)},
		{CKA_EXTRACTABLE, &bTrue, sizeof(CK_BBOOL)},
		{CKA_VALUE, cka_value, ulLen}, 
		{CKA_PRIVATE, &bFalse, sizeof(CK_BBOOL)}
	};

	ulCount = sizeof(AESItem) / sizeof(CK_ATTRIBUTE);

	CK_OBJECT_HANDLE objHandle = 0;
	rv = pToken->C_CreateObject(hSession, AESItem, ulCount, &objHandle);
	ERROR_THROW(rv);

	CK_ATTRIBUTE keyValues[] = {
		{CKA_VALUE, cka_value, ulLen}, 
		{CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)},
	};

	//unextrable object 
	ulCount = sizeof(keyValues) / sizeof(CK_ATTRIBUTE);
	rv = pToken->C_SetAttributeValue(hSession, objHandle, keyValues, ulCount);
	
	//rv = (rv == CKR_OK);
	ERROR_THROW(rv);

	rv = pToken->C_GetAttributeValue(hSession, objHandle, keyValues, ulCount);
	ERROR_THROW(rv);

	CK_ATTRIBUTE keyAttr[] = {
		{CKA_SENSITIVE, &bTrue, sizeof(CK_BBOOL)}, 
	};
	ulCount = sizeof(keyAttr) / sizeof(CK_ATTRIBUTE);
	rv = pToken->C_SetAttributeValue(hSession, objHandle, keyAttr, ulCount);
	ERROR_THROW(rv);

	rv = pToken->C_SetAttributeValue(hSession, objHandle, keyAttr, ulCount);
	//rv = (rv == CKR_OK);
	ERROR_THROW(rv);


	ulCount = sizeof(keyValues) / sizeof(CK_ATTRIBUTE);
	rv = pToken->C_GetAttributeValue(hSession, objHandle, keyValues, ulCount);
	rv = (rv == CKR_OK);
	ERROR_THROW(rv);

	
	//EXTRACTABLE Attribute Test
	CK_ATTRIBUTE extractAttr[] = {
		{CKA_EXTRACTABLE, &bFalse, sizeof(CK_BBOOL)}, 
	};
	ulCount = sizeof(extractAttr) / sizeof(CK_ATTRIBUTE);
	rv = pToken->C_SetAttributeValue(hSession, objHandle, extractAttr, ulCount);
	ERROR_THROW(rv);

	rv = pToken->C_SetAttributeValue(hSession, objHandle, extractAttr, ulCount);
	//rv = (rv == CKR_OK);
	ERROR_THROW(rv);


	CK_ATTRIBUTE modifableAttr[] = {
		{CKA_MODIFIABLE, &bFalse, sizeof(CK_BBOOL)}, 
	};
	ulCount = sizeof(modifableAttr) / sizeof(CK_ATTRIBUTE);
	rv = pToken->C_SetAttributeValue(hSession, objHandle, modifableAttr, ulCount);
	ERROR_THROW(rv);

	rv = pToken->C_SetAttributeValue(hSession, objHandle, modifableAttr, ulCount);
	rv = (rv == CKR_OK);
	ERROR_THROW(rv);


END_OF_FUN:
	
	if(rv != CKR_OK)
	{
		printf("Error = %0x \n", rv);
	}
	else
	{
		printf("Successfully!\n");
	}
	getchar();
	return 0;
}

