Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ex-pkcs11-3.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 & 2 must be run successfully first. ***
// Copy the following files from example 1 into example 3: PKCS11, PKCS11.sig, pkcs11baseKey.txt
// ***
//
// Example 2 stores a client generated key onto the token.
//
int main(int argc,char *argv[])
{
CK_SLOT_INFO oneSlot;
CK_ATTRIBUTE findTemplate[10];
CK_ATTRIBUTE getTemplate[5];
CK_UTF8CHAR label[50];
CK_SLOT_ID_PTR pSlotList = NULL_PTR;
CK_BYTE_PTR pKeyMaterial = NULL_PTR;
CK_OBJECT_CLASS objClass = 0;
CK_KEY_TYPE keyType = 0;
CK_BBOOL bTFlag = CK_TRUE;
CK_BBOOL bDecrypt = CK_FALSE;
CK_SESSION_HANDLE hSession = 0;
CK_FLAGS flags = 0;
CK_ULONG ulSlotCount = 0;
CK_ULONG foundCount = 0;
CK_ULONG keyLength = 0;
CK_ULONG delCount = 0;
CK_ULONG i = 0;
CK_RV rv = 0;
CK_RV rv2 = 0;
int match = 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 example3: failed C_Initialize (error:%lx)", rv );
return -1;
}
// [B] What slots are defined (see p6pkcs11.conf file)
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 example3: memory allocation failed" );
return -2;
}
// -> find the slot we want to work on by its description
if (CKR_OK == (rv = C_GetSlotList( CK_FALSE, pSlotList, &ulSlotCount )))
{
for( i=0; i < ulSlotCount; i++ )
{
if (CKR_OK == (rv = C_GetSlotInfo( pSlotList[i], (CK_SLOT_INFO_PTR)&oneSlot )))
{
// -> slot description field is a fixed 64 characters long and is not NULL terminated
match = strncmp( (const char*)oneSlot.slotDescription, "KMIP SLOT1 ", 64 );
if (0 == match)
{
// The normal user must login before he can save a key onto the token
// -> most things on a token require that we first create a session to the token in the slot
if (CKR_OK != (rv = C_OpenSession( pSlotList[i], flags, NULL, NULL, &hSession ))) {
printf( "PKCS11 example3: slot %ld failed to open a session (error:%lx)", pSlotList[i], rv );
break;
}
// Here the client searches for several keys on the token and reads their values
pUserPin = (CK_UTF8CHAR_PTR)"roggerrabbit";
if (CKR_OK == (rv = C_Login( hSession, CKU_USER, pUserPin, 12 )))
{
// [C] Find the key created in example 2
objClass = CKO_SECRET_KEY;
keyType = CKK_AES;
strncpy( (char*)label, "An updated AES secret key object on token", 41 );
findTemplate[0].type = CKA_CLASS;
findTemplate[0].pValue = &objClass;
findTemplate[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
findTemplate[1].type = CKA_KEY_TYPE;
findTemplate[1].pValue = &keyType;
findTemplate[1].ulValueLen = sizeof(CK_KEY_TYPE);
findTemplate[2].type = CKA_TOKEN;
findTemplate[2].pValue = &bTFlag;
findTemplate[2].ulValueLen = sizeof(CK_BBOOL);
findTemplate[3].type = CKA_LABEL;
findTemplate[3].pValue = &label;
findTemplate[3].ulValueLen = 41;
findTemplate[4].type = CKA_ENCRYPT;
findTemplate[4].pValue = &bTFlag;
findTemplate[4].ulValueLen = sizeof(CK_BBOOL);
// -> ask for one object, we could keep calling C_FindObjects over and over again or ask for multiple object handles back at once
// -> here there should only be one match
rv = C_FindObjectsInit( hSession, (CK_ATTRIBUTE_PTR)findTemplate, 5 );
if (CKR_OK == rv) rv2 = C_FindObjects( hSession, &hObject, 1, &foundCount );
if ( CKR_OK == rv && CKR_OK == rv2 )
{
// -> first find out the size of the key material
getTemplate[0].type = CKA_VALUE;
getTemplate[0].pValue = NULL_PTR;
getTemplate[0].ulValueLen = 0;
if ( CKR_OK == (rv = C_GetAttributeValue( hSession, hObject, (CK_ATTRIBUTE_PTR)getTemplate, 1 )))
{
keyLength = getTemplate[0].ulValueLen;
pKeyMaterial = (CK_BYTE_PTR) malloc( keyLength + 1 );
getTemplate[0].type = CKA_VALUE;
getTemplate[0].pValue = pKeyMaterial;
getTemplate[0].ulValueLen = keyLength;
getTemplate[1].type = CKA_DECRYPT;
getTemplate[1].pValue = &bDecrypt;
getTemplate[1].ulValueLen = sizeof(CK_BBOOL);
if ( CKR_OK == (rv = C_GetAttributeValue( hSession, hObject, (CK_ATTRIBUTE_PTR)getTemplate, 2 )))
{
// -> AES key material available here for use in pKeyMaterial buffer and bDecrypt the value from the token object
;
}
else printf( "PKCS11 example3: slot %ld failed read key off of token (error:%lx)", pSlotList[i], rv );
}
else printf( "PKCS11 example3: slot %ld failed read key size off of token (error:%lx)", pSlotList[i], rv );
}
else
{ printf( "PKCS11 example3: slot %ld failed to find key on token (error:%lx)", pSlotList[i], rv );
}
if (CKR_OK == rv) rv = C_FindObjectsFinal( hSession ); // -> need to tell the library we are done with the search
if (NULL != pKeyMaterial) free( pKeyMaterial );
// [D] Iterate though all objects in the token and delete the first 5 seen
delCount = 0;
rv = C_FindObjectsInit( hSession, NULL_PTR, 0 );
while( CKR_OK == rv2 )
{
hObject = 0; // -> zero is an invalid object handle value
rv = C_FindObjects( hSession, &hObject, 1, &foundCount );
if (0 == foundCount) {
// -> no more object to iterate though
break;
}
if (delCount < 5) {
rv = C_DestroyObject( hSession, hObject );
}
}
rv = C_FindObjectsFinal( hSession );
if (CKR_OK != (rv = C_Logout( hSession ))) {
printf( "PKCS11 example3: slot %ld failed to logout of token (error:%lx)", pSlotList[i], rv );
}
}
// Now we are done we have to close the session to the token
if (CKR_OK != (rv = C_CloseSession( hSession ))) {
printf( "PKCS11 example3: slot %ld failed to close an active token session (error:%lx)", pSlotList[i], rv );
break;
}
}
else {
printf( "PKCS11 example3: slot %ld failed to log user into token (error:%lx)", pSlotList[i], rv );
}
}
}
}
}
// [E] 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 example2: failed C_Finalize %lx", rv );
return -3;
}
return 0;
}