Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ex-pkcs11-14.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
#include "pkcs11.h"
#include "pkcs11p6r.h" // optional, only needed if using P6R vendor extensions
// *** For this example to work Example #1 must be run successfully first. ***
// Copy the following files from example 1 into example 4: PKCS11, PKCS11.sig, pkcs11baseKey.txt,
// so that they don't have to be created for each example.
// ***
//
int main(int argc,char *argv[])
{
CK_MECHANISM oneMech;
CK_ATTRIBUTE keyTemplate[6];
CK_UTF8CHAR label[50];
CK_BYTE wrappedKey[ 4000 ];
CK_ULONG wrappedLength = 4000;
CK_SLOT_ID_PTR pSlotList = NULL_PTR;
CK_OBJECT_HANDLE hDataKey = 0;
CK_OBJECT_HANDLE hKEK = 0;
CK_SESSION_HANDLE hSession = 0;
CK_BBOOL bTFlag = CK_TRUE;
CK_ULONG ulSlotCount = 0;
CK_ULONG keyLength = 0;
CK_RV rv = 0;
int errorNumber = 0;
// [A] We must first initialize the entire PKCS 11 library
memset( &initArgs, 0, sizeof( CK_C_INITIALIZE_ARGS ));
initArgs.flags = CKF_OS_LOCKING_OK; // -> let PKCS11 use its own locking
if (CKR_OK != (rv = C_Initialize( &initArgs ))) {
printf( "PKCS11 example14: failed C_Initialize (error:%lx)", rv );
return -1;
}
// [B] We are just going to use slot 0 for this example
if (CKR_OK == (rv = C_GetSlotList( CK_FALSE, NULL_PTR, &ulSlotCount )))
{
if (NULL_PTR == (pSlotList = (CK_SLOT_ID_PTR) malloc( ulSlotCount * sizeof( CK_SLOT_ID )))) {
printf( "PKCS11 example14: memory allocation failed" );
return -2;
}
if (CKR_OK == (rv = C_GetSlotList( CK_FALSE, pSlotList, &ulSlotCount )))
{
// -> the normal user must login before he can save a key onto the token
if (CKR_OK != (rv = C_OpenSession( pSlotList[0], (CKF_SERIAL_SESSION | CKF_RW_SESSION), NULL, NULL, &hSession ))) {
printf( "PKCS11 example14: slot 0 failed to open a session (error:%lx)", pSlotList[0], rv );
return -3;
}
// -> wrap and return the data key by the key encrypting key (KEK)
pUserPin = (CK_UTF8CHAR_PTR)"roggerrabbit";
if (CKR_OK == (rv = C_Login( hSession, CKU_USER, pUserPin, 12 )))
{
// -> generate the data key on the HSM
oneMech.pParameter = NULL_PTR;
oneMech.ulParameterLen = 0;
keyLength = 16; // in bytes
strncpy( (char*)label, "AES data key", 12 );
keyTemplate[0].type = CKA_TOKEN;
keyTemplate[0].pValue = &bTFlag;
keyTemplate[0].ulValueLen = sizeof(CK_BBOOL);
keyTemplate[1].type = CKA_LABEL;
keyTemplate[1].pValue = label;
keyTemplate[1].ulValueLen = 12;
keyTemplate[2].type = CKA_VALUE_LEN;
keyTemplate[2].pValue = &keyLength;
keyTemplate[2].ulValueLen = sizeof(CK_ULONG);
keyTemplate[3].type = CKA_ENCRYPT;
keyTemplate[3].pValue = &bTFlag;
keyTemplate[3].ulValueLen = sizeof(CK_BBOOL);
keyTemplate[4].type = CKA_DECRYPT;
keyTemplate[4].pValue = &bTFlag;
keyTemplate[4].ulValueLen = sizeof(CK_BBOOL);
if (CKR_OK != (rv = C_GenerateKey( hSession, &oneMech, (CK_ATTRIBUTE_PTR)keyTemplate, 5, &hDataKey ))) {
printf( "PKCS11 example14: slot %ld failed to generate data key on token (error:%lx)", pSlotList[0], rv );
errorNumber = -4;
}
// -> generate the KEK to wrap the data key above
if (CKR_OK == rv)
{
strncpy( (char*)label, "AES key encrypting key (kek)", 28 );
keyTemplate[0].type = CKA_TOKEN;
keyTemplate[0].pValue = &bTFlag;
keyTemplate[0].ulValueLen = sizeof(CK_BBOOL);
keyTemplate[1].type = CKA_LABEL;
keyTemplate[1].pValue = label;
keyTemplate[1].ulValueLen = 28;
keyTemplate[2].type = CKA_VALUE_LEN;
keyTemplate[2].pValue = &keyLength;
keyTemplate[2].ulValueLen = sizeof(CK_ULONG);
keyTemplate[3].type = CKA_WRAP; /* *** notice *** */
keyTemplate[3].pValue = &bTFlag;
keyTemplate[3].ulValueLen = sizeof(CK_BBOOL);
keyTemplate[4].type = CKA_UNWRAP; /* *** notice *** */
keyTemplate[4].pValue = &bTFlag;
keyTemplate[4].ulValueLen = sizeof(CK_BBOOL);
if (CKR_OK != (rv = C_GenerateKey( hSession, &oneMech, (CK_ATTRIBUTE_PTR)keyTemplate, 5, &hKEK ))) {
printf( "PKCS11 example14: slot %ld failed to generate kek on token (error:%lx)", pSlotList[0], rv );
errorNumber = -5;
}
}
// ->
if (CKR_OK == rv)
{
oneMech.mechanism = CKM_AES_ECB; // CKM_AES_KEY_WRAP_PAD
oneMech.pParameter = NULL_PTR;
oneMech.ulParameterLen = 0;
if ( CKR_OK != (rv = C_WrapKey( hSession, &oneMech, hKEK, hDataKey, wrappedKey, &wrappedLength ))) {
printf( "PKCS11 example14: slot %ld failed to wrap the data key in the KEK token (error:%lx)", pSlotList[0], rv );
errorNumber = -6;
}
else printf( "PKCS11 example14: wrapped key size is %d bytes", wrappedLength );
}
if (CKR_OK != (rv = C_Logout( hSession ))) {
printf( "PKCS11 example14: slot %ld failed to logout of token (error:%lx)", pSlotList[0], rv );
}
}
// Now we are done we have to close the session to the token
if (CKR_OK != (rv = C_CloseSession( hSession ))) {
printf( "PKCS11 example14: slot %ld failed to close an active token session (error:%lx)", pSlotList[0], rv );
}
}
}
// At the end we must tell the library we are done
if (NULL_PTR != pSlotList) free( pSlotList );
if (CKR_OK != (rv = C_Finalize( NULL_PTR ))) {
printf( "PKCS11 example14: failed C_Finalize %lx", rv );
errorNumber = -7;
}
return errorNumber;
}