/*--
	ImportTheCert.cpp

	2015-11-12

	Test pkcs import the cert(*.pfx¡¢*.p12)
--*/

#include "../global.h"
#include "import.h"

#pragma comment( lib, "ImportCert.lib")

#define MAX_CERT_COUNT 12
CK_FUNCTION_LIST_PTR fl = 0; 

int main(int argc, char* argv[])
{
	CK_RV rv;
	CK_ULONG slot_count = 100;
	CK_SLOT_ID slots[100];
	CK_SESSION_HANDLE session;

	CK_BYTE pCertFilePath[1024] = {0};
	CK_BYTE pCertPassword[128] = {0};
	CK_OBJECT_HANDLE signature_pub_key;
	CK_OBJECT_HANDLE signature_pri_key;
	CK_OBJECT_HANDLE pSignatureCerts[MAX_CERT_COUNT] = {0};

	CK_OBJECT_HANDLE encrypt_pub_key;
	CK_OBJECT_HANDLE encrypt_pri_key;
	CK_OBJECT_HANDLE pEncryptCerts[MAX_CERT_COUNT] = {0};
	CK_ULONG ulCertCount = 0;
	CK_ULONG ulRet = 0;

	CK_BYTE conName[256] = {0};
	CK_ATTRIBUTE get_con[] = {
		{CKA_ID, conName, 256}
	};

	printf("Import the cert sample:\n");
	
	fl = InitFunctionList();
	if (fl == 0)
		return leave("Can't get function list. \n");
	
	/* Initialize the PKCS #11 library
	 */
	if (PKCS_OK != fl->C_Initialize (0))
		return leave("C_Initialize failed...");                       
	
	/* Get list of slots containing UniMate
	 */
	
	if (PKCS_OK != fl->C_GetSlotList (TRUE, slots, &slot_count))
		return leave("C_GetSlotList failed...");

	/* One or more UniMate/UniToken must be inserted
	 */
	if (slot_count < 1)
		return leave("No UniMate/UniToken is available.\n");
	
	printf ("Found UniMate/UniToken.\n");
	/* open a read/write session on the first UniMate/UniToken found
	 */
	if (PKCS_OK != fl->C_OpenSession(slots[0], 
		(CKF_SERIAL_SESSION | CKF_RW_SESSION), 0, 0, &session)
		)
		return leave("C_OpenSession failed.\n");
	
	/* login as user so we can use the public and private
	 * keys on the UniMate/UniToken
	 */
	if (PKCS_OK != fl->C_Login(session, CKU_USER, USER_PIN, 8))
		return leave("C_Login failed.\n");
	
	/* Input the cert file path and password
	*/
	printf("Please input the signature cert file path (*.pfx|*.p12):\n");
	scanf("%s", pCertFilePath);
	fflush(stdin);

	printf("\n");
	printf("Please input the signature cert file password:\n");
	scanf("%s", pCertPassword);
	fflush(stdin);

	printf("\n");
	printf("\nWait for import the signature cert file now ...\n");
	printf("\n");
	// import the cert file
	ulRet = import_cert(session, fl, pCertFilePath, pCertPassword, NULL, 0, AT_SIGNATURE, &signature_pub_key, &signature_pri_key, pSignatureCerts, &ulCertCount);
	if (ulRet == ERROR_OPEN_FILE)
	{
		printf("Failed to open the cert file!\n");
		goto log_out;
	}
	else if (ulRet == ERROR_PRASE_CERT)
	{
		printf("Failed to parse the cert file!\n");
		goto log_out;
	}
	else if(ulRet == ERROR_IMPORT_PUB)
	{
		printf("Import public key failed!\n");
		goto log_out;
	}
	else if(ulRet == ERROR_IMPORT_PRI)
	{
		printf("The private key of the certificate is wrong!\n");
		goto log_out;
	}
	else if(ulRet == ERROR_IMPORT_CERT)
	{
		printf("Import certificate failed!\n");
		goto log_out;
	}
	else if(ulRet == ERROR_PUB_EXIST)
	{
		printf("The certificate already exists!\n");
		goto log_out;
	}
	else if (ulRet == CKR_DEVICE_MEMORY)
	{
		printf("Device memory is insufficient.\n");
		goto log_out;
	}
	else if(ulRet!=0 || ulCertCount<=0)
	{
		printf("Import certificate failed!\n");
		goto log_out;
	}

	printf("Import signature cert successful!\n");

	/* Get the container id(same as the signature cert id)
	the last cert in pSignatureCerts is CERT_MY
	*/
	rv = fl->C_GetAttributeValue(session, pSignatureCerts[ulCertCount-1], get_con, 1);
	if (rv != CKR_OK)
	{
		printf("Failed to get the container name!\n");
		goto log_out;
	}

	/* Input the cert file path and password
	*/
	printf("Please input the encrypt cert file path (*.pfx|*.p12):\n");
	memset(pCertFilePath, 0, 1024);
	scanf("%s", pCertFilePath);
	fflush(stdin);

	printf("\n");
	printf("Please input the encrypt cert file password:\n");
	memset(pCertPassword, 0, 128);
	scanf("%s", pCertPassword);
	fflush(stdin);

	printf("\n");
	printf("\nWait for import the encrypt cert file now ...\n");
	printf("\n");
	ulRet = import_cert(session, fl, pCertFilePath, pCertPassword, conName, get_con[0].ulValueLen, AT_KEYEXCHANGE, &encrypt_pub_key, &encrypt_pri_key, pEncryptCerts, &ulCertCount);
	if (ulRet == ERROR_OPEN_FILE)
	{
		printf("Failed to open the cert file!\n");
		goto log_out;
	}
	else if (ulRet == ERROR_PRASE_CERT)
	{
		printf("Failed to parse the cert file!\n");
		goto log_out;
	}
	else if(ulRet == ERROR_IMPORT_PUB)
	{
		printf("Import public key failed!\n");
		goto log_out;
	}
	else if(ulRet == ERROR_IMPORT_PRI)
	{
		printf("The private key of the certificate is wrong!\n");
		goto log_out;
	}
	else if(ulRet == ERROR_IMPORT_CERT)
	{
		printf("Import certificate failed!\n");
		goto log_out;
	}
	else if(ulRet == ERROR_PUB_EXIST)
	{
		printf("The certificate already exists!\n");
		goto log_out;
	}
	else if (ulRet == CKR_DEVICE_MEMORY)
	{
		printf("Device memory is insufficient.\n");
		goto log_out;
	}
	else if (ulRet == ERROR_CONTAINER_NOT_EXIST)
	{
		printf("The specified container not exist!\n");
		goto log_out;
	}
	else if (ulRet == ERROR_CONTAINER_OCCUPIED)
	{
		printf("The specified container is occupied!\n");
		goto log_out;
	}
	else if (ulRet == ERROR_CERT_KEY_USAGE_UNMATCHED)
	{
		printf("The specified cert keyusage unmatched!\n");
		goto log_out;
	}
	else if(ulRet!=0 || ulCertCount<=0)
	{
		printf("Import certificate failed!\n");
		goto log_out;
	}
	
	printf("Import encrypt cert successful!\n");

log_out:
	if (PKCS_OK != fl->C_Logout (session))
		return leave("C_Logout failed.\n");
    
	/* close open session
	 */
	if (PKCS_OK != fl->C_CloseSession (session))
		return leave("C_CloseSession failed.\n");
	
	
	/* close PKCS #11 library
	 */
	if (PKCS_OK != fl->C_Finalize(0))
		return leave("C_Finalize failed.\n");
    Finalize();

	printf ("Press Enter to exit...");
	getchar ();
	
	return PKCS_OK;
}
