Copy // *** HEADER FILES ***
// Windows Specific
#ifdef WIN32
#include "windows.h"
#include "process.h"
#include <fstream>
using namespace std;
// Solaris Specific
#elif defined (SOLARIS)
#include <memory.h>
#include <stdio.h>
#include <unistd.h>
#include <fstream>
// Linux Specific
#elif defined (LINUX32)
#include <memory.h>
#include <stdio.h>
#include <unistd.h>
// Other OS Specific
#else
#error OS Specific defined required
#endif
// Common to all Platforms
#include “PKCS11_SampleCode.h"
#include "pkcs11x.h"
#include "Cryptoki.h"
// *** DECLARE/INITIALIZE GLOBAL VARIABLES ***
static CCryptoki pkcs11;
static CK_BYTE UserPin[] = "1234";
static CK_BBOOL bTrue = TRUE;
static CK_BBOOL bFalse = FALSE;
static CK_OBJECT_CLASS SecretKeyClass = CKO_SECRET_KEY;
static CK_KEY_TYPE AESKeyType = CKK_AES;
static CK_OBJECT_HANDLE hAESkey= 0 ; // AES Key Handle for AES Encryption/Decryption Test
// *** MAIN ***************************************************************************************
int main(int argc, char* argv[])
{
CK_RV rc = 0;
CK_BBOOL bInitialized = false;
char buffer[256] = {0};
try
{
//1. Initialize the pkcs#11 library ...
CK_C_INITIALIZE_ARGS args = {0};
rc = pkcs11.Initialize(&args);
if ( rc != CKR_OK ) return rc ;
bInitialized = true;
//2. Get the 1st SlotID
// When you already know the SlotID, there is no need to call getSlot() : SlotID information is in the machine file . For example, CK_SLOT_ID slotID = n ;
CK_SLOT_ID slotID(-1);
rc = PKCS11_SampleCode::getSlot(slotID);
if ( rc != CKR_OK ) throw buffer ;
//3. Then open a session and login as a User ...
// open session (must be serial/rw)
CK_SESSION_HANDLE hSession(-1) ;
rc = pkcs11.OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &hSession);
if ( rc != CKR_OK ) throw bufer ;
// login as a User
rc = pkcs11.Login(hSession, CKU_USER, UserPin, strlen((char*) UserPin));
if ( rc != CKR_OK )
{
printf("\n\n--- Incorrect User PIN number-----------\n");
throw buffer ;
}
//4. Generate AES Key and Encryption & Decryption test
rc = PKCS11_SampleCode::AESSamples(hSession);
if ( rc != CKR_OK ) throw buffer ;
//5. When we have completed the Crypto Operations, we must tidy up ...
// logout
rc = pkcs11.Logout(hSession);
// close session
rc = pkcs11.CloseSession(hSession);
//6. The last Cryptoki call - always finalize the library (if it has been initialised)!
if (bInitialized)
{
rc = pkcs11.Finalize(NULL_PTR);
}
}
catch (char* e)
{
printf(e);
if (bInitialized)
{
try{rc = pkcs11.Finalize(NULL_PTR);}
catch(...){}
}
}
catch (...)
{
printf("FATAL ERROR\n");
if (bInitialized)
{
try{rc = pkcs11.Finalize(NULL_PTR);}
catch(...){}
}
}
return rc;
}
// *** end of MAIN ********************************************************************************
// *** GET the 1st SLOT *********************************************************************************
CK_RV PKCS11_SampleCode::getSlot(CK_SLOT_ID &slotID)
{
CK_RV rc;
try
{
// see if there are slots with tokens
CK_ULONG numSlots;
rc = pkcs11.GetSlotList(TRUE, NULL, &numSlots);
if (numSlots) // we've got one or more
{
// call pkcs11.GetSlotList() again with a correctly sized buffer
CK_SLOT_ID_PTR pSlotList = new CK_SLOT_ID[numSlots];
memset(pSlotList, 0xFF, sizeof(CK_SLOT_ID)*numSlots);
rc = pkcs11.GetSlotList(TRUE, pSlotList, &numSlots);
// save the slot for use later
slotID = pSlotList[0]; // 1st slot ID
// tidy up
delete [] pSlotList;
pSlotList = NULL;
}
}
catch (char* e)
{
printf(e);
}
catch (...){}
return rc;
}
// *** AES SAMPLE CODE ****************************************************************************
CK_RV PKCS11_SampleCode::AESSamples(CK_SESSION_HANDLE hSession)
{
printf("\n\n~~~ AES Key Generation & Encryption & Decryption Test ~~~~~~~~~~~\n");
CK_RV rc;
char buffer[256] = {0};
try
{
// generate some 64-byte data for test
CK_BYTE data[64];
CK_ULONG dataLen = sizeof(data);
int i ;
rc = pkcs11.GenerateRandom(hSession, data, dataLen);
printf("\r\nOriginal Data : ") ;
for ( i = 0 ; i < 64 ; i++ ) {
printf(" %02X ",data[i]) ;
}
// generate a AES key
CK_OBJECT_HANDLE hAESKey;
int ByteLength = 16; // 128 bit key : 16 byte = 128 bit
CK_CHAR label[] = "AES1Key";
rc = PKCS11_SampleCode::generateAESKey(hSession, hAESKey, ByteLength, label);
if ( rc != CKR_OK ) return rc ;
// encrypt/decrypt
rc = PKCS11_SampleCode::AESEncryptDecrypt(hSession, hAESKey, ByteLength, data, dataLen);
if ( rc != CKR_OK ) return rc ;
// Retrieve AES Key from HSM by FindObject()
CK_OBJECT_HANDLE hNewKey= 0 ;
CK_CHAR newlabel[] = "AES1Key" ;
printf("\n\n--- Find Key Object By Label from HSM ------------------\n");
// declare variables
CK_ULONG count = 0;
// declare the find object Template
CK_ATTRIBUTE objTemplate[] = {
{CKA_TOKEN, &bTrue, sizeof(bTrue)},
{CKA_LABEL, newlabel, strlen((char*)newlabel)}};
// find the object by its label
rc = pkcs11.FindObjectsInit(hSession, objTemplate, 2);
if (rc == CKR_OK)
{
rc = pkcs11.FindObjects(hSession, &hNewKey, 1, &count);
pkcs11.FindObjectsFinal(hSession);
}
else return rc ;
if ( hNewKey == 0 )
{
printf("\n\n--- There is no AES key with given label in HSM-----\n");
return rc ;
};
// encrypt/decrypt again with retrieved Key
rc = PKCS11_SampleCode::AESEncryptDecrypt(hSession, hNewKey, ByteLength, data, dataLen);
}
catch (char* e)
{
printf(e);
}
catch (...){}
return rc;
}
// ___GENERATE A AES KEY ______________________________________________________
CK_RV PKCS11_SampleCode::generateAESKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE& hAESKey, int ByteLength, CK_CHAR_PTR label)
{
printf("\n\n--- Generate AES Key -------------------\n");
CK_RV rc;
CK_ULONG KeySize=0;
try
{
// get the AES Key Generation mechanism
CK_KEY_TYPE KeyType;
CK_MECHANISM genMech;
genMech.mechanism = CKM_AES_KEY_GEN;
KeyType = CKK_AES;
KeySize=ByteLength;
// set the parameter
genMech.pParameter = 0;
genMech.ulParameterLen = 0;
// reset the AES Key handle
hAESKey = 0;
// set up the AES Key template
CK_ATTRIBUTE AESKeyTemplate[] =
{
{CKA_CLASS, &SecretKeyClass, sizeof(SecretKeyClass)},
{CKA_KEY_TYPE, &KeyType, sizeof(KeyType)},
{CKA_LABEL, label, strlen((char*)label)},
{CKA_TOKEN, &bTrue, sizeof(bTrue)},
{CKA_EXTRACTABLE, &bTrue, sizeof(bTrue)},
{CKA_SIGN, &bTrue, sizeof(bTrue)},
{CKA_VERIFY, &bTrue, sizeof(bTrue)},
{CKA_ENCRYPT, &bTrue, sizeof(bTrue)},
{CKA_DECRYPT, &bTrue, sizeof(bTrue)},
{CKA_WRAP, &bTrue, sizeof(bTrue)},
{CKA_UNWRAP, &bTrue, sizeof(bTrue)},
{CKA_VALUE_LEN, &KeySize, sizeof(KeySize)}
};
// generate the AES Key
rc = pkcs11.GenerateKey(hSession, &genMech, AESKeyTemplate, sizeof(AESKeyTemplate)/sizeof(AESKeyTemplate[0]), &hAESKey);
}
catch (char* e)
{
printf(e);
}
catch (...) {}
return rc;
}
// ___ AES ENCRYPT/DECRYPT ____________________________________________________
CK_RV PKCS11_SampleCode::AESEncryptDecrypt(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hAESKey, int ByteLength, const CK_BYTE_PTR data, const CK_ULONG dataLen)
{
printf("\n\n--- AES Encrypt/Decrypt ----------------\n");
CK_RV rc;
try
{
// declare variables
CK_ULONG realDataLen = dataLen + 8;
CK_BYTE_PTR encData = new CK_BYTE[realDataLen];
CK_BYTE_PTR decData = new CK_BYTE[realDataLen];
CK_ULONG encLen = realDataLen;
CK_ULONG decLen = realDataLen;
unsigned char IV[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
CK_ULONG i ;
// set up the AES encrypt/decrypt mechanism (dependent upon the bit length)
CK_MECHANISM encDecMech;
encDecMech.mechanism = CKM_AES_CBC;
// set up parameter
encDecMech.pParameter = IV;
encDecMech.ulParameterLen = 16;
// encrypt the data
rc = pkcs11.EncryptInit(hSession, &encDecMech, hAESKey);
rc = pkcs11.Encrypt(hSession, data, dataLen, encData, &encLen);
printf("\r\nEncrypted Data : ") ;
for ( i = 0 ; i < encLen ; i++ ) {
printf(" %02X ",encData[i]) ;
}
printf("\r\n") ;
// decrypt the data
rc = pkcs11.DecryptInit(hSession, &encDecMech, hAESKey);
rc = pkcs11.Decrypt(hSession, encData, encLen, decData, &decLen);
printf("\r\nDecrypted Data : ") ;
for ( i = 0 ; i < decLen ; i++ ) {
printf(" %02X ",decData[i]) ;
}
printf("\r\n") ;
// tidy up
delete [] encData;
delete [] decData;
}
catch (char*
{
printf(e);
}
catch (...) {}
return rc;
}