|
For information about building and using the testpkcs11 sample
program, see The testpkcs11 program.
/*********************************************************************/
/* */
/* COMPONENT_NAME: testpkcs11.c */
/* */
/* Licensed Materials - Property of IBM */
/* 5694-A01 */
/* Copyright IBM Corp. 2007, 2009 */
/* Status = HCR7770 */
/* */
/*********************************************************************/
/*********************************************************************/
/* */
/* This file contains sample code. IBM PROVIDES THIS CODE ON AN */
/* 'AS IS' BASIS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR */
/* IMPLIED, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES */
/* OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. */
/* */
/*********************************************************************/
/* */
/* Change Activity: */
/* $L0=P11C1 ,HCR7740, 060124,PDJS: PKCS11 initial release */
/* $D1=MG08269 ,HCR7740, 061114,PDJS: Misc fixes */
/* $D2=MG08740 ,HCR7740, 070302,PDGL: XPLINK */
/* $P1=MG13406 ,HCR7770, 090812,PDGL: fix XPLINK define */
/* $P2=MG13431 ,HCR7770, 090826,PDER: update prolog */
/* */
/*********************************************************************/
#ifdef IBM
/* Customers may remove this copyright statement */
#pragma comment (copyright,"\
Licensed Materials - Property of IBM \
5694-A01 Copyright IBM Corp. 2007, 2009 \
All Rights Reserved \
US Government Users Restricted Rights - \
Use, duplication or disclosure restricted by \
GSA ADP Schedule Contract with IBM Corp.")
#endif
/* Install verification test for PKCS #11 */
#define _UNIX03_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <dlfcn.h>
#include <sys/timeb.h>
#include <csnpdefs.h>
int skip_token_obj;
CK_FUNCTION_LIST *funcs;
CK_SLOT_ID slotID = CK_UNAVAILABLE_INFORMATION;
CK_BYTE tokenName[32];
void ProcessRetCode( CK_RV rc )
{
switch (rc) {
case CKR_OK: printf(" CKR_OK"); break;
case CKR_CANCEL: printf(" CKR_CANCEL"); break;
case CKR_HOST_MEMORY: printf(" CKR_HOST_MEMORY"); break;
case CKR_SLOT_ID_INVALID: printf(" CKR_SLOT_ID_INVALID"); break;
case CKR_GENERAL_ERROR: printf(" CKR_GENERAL_ERROR"); break;
case CKR_FUNCTION_FAILED: printf(" CKR_FUNCTION_FAILED"); break;
case CKR_ARGUMENTS_BAD: printf(" CKR_ARGUMENTS_BAD"); break;
case CKR_NO_EVENT: printf(" CKR_NO_EVENT"); break;
case CKR_NEED_TO_CREATE_THREADS: printf(" CKR_NEED_TO_CREATE_THREADS"); break;
case CKR_CANT_LOCK: printf(" CKR_CANT_LOCK"); break;
case CKR_ATTRIBUTE_READ_ONLY: printf(" CKR_ATTRIBUTE_READ_ONLY"); break;
case CKR_ATTRIBUTE_SENSITIVE: printf(" CKR_ATTRIBUTE_SENSITIVE"); break;
case CKR_ATTRIBUTE_TYPE_INVALID: printf(" CKR_ATTRIBUTE_TYPE_INVALID"); break;
case CKR_ATTRIBUTE_VALUE_INVALID: printf(" CKR_ATTRIBUTE_VALUE_INVALID"); break;
case CKR_DATA_INVALID: printf(" CKR_DATA_INVALID"); break;
case CKR_DATA_LEN_RANGE: printf(" CKR_DATA_LEN_RANGE"); break;
case CKR_DEVICE_ERROR: printf(" CKR_DEVICE_ERROR"); break;
case CKR_DEVICE_MEMORY: printf(" CKR_DEVICE_MEMORY"); break;
case CKR_DEVICE_REMOVED: printf(" CKR_DEVICE_REMOVED"); break;
case CKR_ENCRYPTED_DATA_INVALID: printf(" CKR_ENCRYPTED_DATA_INVALID"); break;
case CKR_ENCRYPTED_DATA_LEN_RANGE: printf(" CKR_ENCRYPTED_DATA_LEN_RANGE"); break;
case CKR_FUNCTION_CANCELED: printf(" CKR_FUNCTION_CANCELED"); break;
case CKR_FUNCTION_NOT_PARALLEL: printf(" CKR_FUNCTION_NOT_PARALLEL"); break;
case CKR_FUNCTION_NOT_SUPPORTED: printf(" CKR_FUNCTION_NOT_SUPPORTED"); break;
case CKR_KEY_HANDLE_INVALID: printf(" CKR_KEY_HANDLE_INVALID"); break;
case CKR_KEY_SIZE_RANGE: printf(" CKR_KEY_SIZE_RANGE"); break;
case CKR_KEY_TYPE_INCONSISTENT: printf(" CKR_KEY_TYPE_INCONSISTENT"); break;
case CKR_KEY_NOT_NEEDED: printf(" CKR_KEY_NOT_NEEDED"); break;
case CKR_KEY_CHANGED: printf(" CKR_KEY_CHANGED"); break;
case CKR_KEY_NEEDED: printf(" CKR_KEY_NEEDED"); break;
case CKR_KEY_INDIGESTIBLE: printf(" CKR_KEY_INDIGESTIBLE"); break;
case CKR_KEY_FUNCTION_NOT_PERMITTED: printf(" CKR_KEY_FUNCTION_NOT_PERMITTED"); break;
case CKR_KEY_NOT_WRAPPABLE: printf(" CKR_KEY_NOT_WRAPPABLE"); break;
case CKR_KEY_UNEXTRACTABLE: printf(" CKR_KEY_UNEXTRACTABLE"); break;
case CKR_MECHANISM_INVALID: printf(" CKR_MECHANISM_INVALID"); break;
case CKR_MECHANISM_PARAM_INVALID: printf(" CKR_MECHANISM_PARAM_INVALID"); break;
case CKR_OBJECT_HANDLE_INVALID: printf(" CKR_OBJECT_HANDLE_INVALID"); break;
case CKR_OPERATION_ACTIVE: printf(" CKR_OPERATION_ACTIVE"); break;
case CKR_OPERATION_NOT_INITIALIZED: printf(" CKR_OPERATION_NOT_INITIALIZED"); break;
case CKR_PIN_INCORRECT: printf(" CKR_PIN_INCORRECT"); break;
case CKR_PIN_INVALID: printf(" CKR_PIN_INVALID"); break;
case CKR_PIN_LEN_RANGE: printf(" CKR_PIN_LEN_RANGE"); break;
case CKR_PIN_EXPIRED: printf(" CKR_PIN_EXPIRED"); break;
case CKR_PIN_LOCKED: printf(" CKR_PIN_LOCKED"); break;
case CKR_SESSION_CLOSED: printf(" CKR_SESSION_CLOSED"); break;
case CKR_SESSION_COUNT: printf(" CKR_SESSION_COUNT"); break;
case CKR_SESSION_HANDLE_INVALID: printf(" CKR_SESSION_HANDLE_INVALID"); break;
case CKR_SESSION_PARALLEL_NOT_SUPPORTED: printf(" CKR_SESSION_PARALLEL_NOT_SUPPORTED"); break;
case CKR_SESSION_READ_ONLY: printf(" CKR_SESSION_READ_ONLY"); break;
case CKR_SESSION_EXISTS: printf(" CKR_SESSION_EXISTS"); break;
case CKR_SESSION_READ_ONLY_EXISTS: printf(" CKR_SESSION_READ_ONLY_EXISTS"); break;
case CKR_SESSION_READ_WRITE_SO_EXISTS: printf(" CKR_SESSION_READ_WRITE_SO_EXISTS"); break;
case CKR_SIGNATURE_INVALID: printf(" CKR_SIGNATURE_INVALID"); break;
case CKR_SIGNATURE_LEN_RANGE: printf(" CKR_SIGNATURE_LEN_RANGE"); break;
case CKR_TEMPLATE_INCOMPLETE: printf(" CKR_TEMPLATE_INCOMPLETE"); break;
case CKR_TEMPLATE_INCONSISTENT: printf(" CKR_TEMPLATE_INCONSISTENT"); break;
case CKR_TOKEN_NOT_PRESENT:
printf(" CKR_TOKEN_NOT_PRESENT - ICSF is not active or not configured for TKDS operations"); break;
case CKR_TOKEN_NOT_RECOGNIZED:
printf(" CKR_TOKEN_NOT_RECOGNIZED - You are not authorized to perform the token operation"); break;
case CKR_TOKEN_WRITE_PROTECTED: printf(" CKR_TOKEN_WRITE_PROTECTED"); break;
case CKR_UNWRAPPING_KEY_HANDLE_INVALID: printf(" CKR_UNWRAPPING_KEY_HANDLE_INVALID"); break;
case CKR_UNWRAPPING_KEY_SIZE_RANGE: printf(" CKR_UNWRAPPING_KEY_SIZE_RANGE"); break;
case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: printf(" CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"); break;
case CKR_USER_ALREADY_LOGGED_IN: printf(" CKR_USER_ALREADY_LOGGED_IN"); break;
case CKR_USER_NOT_LOGGED_IN: printf(" CKR_USER_NOT_LOGGED_IN"); break;
case CKR_USER_PIN_NOT_INITIALIZED: printf(" CKR_USER_PIN_NOT_INITIALIZED"); break;
case CKR_USER_TYPE_INVALID: printf(" CKR_USER_TYPE_INVALID"); break;
case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: printf(" CKR_USER_ANOTHER_ALREADY_LOGGED_IN"); break;
case CKR_USER_TOO_MANY_TYPES: printf(" CKR_USER_TOO_MANY_TYPES"); break;
case CKR_WRAPPED_KEY_INVALID: printf(" CKR_WRAPPED_KEY_INVALID"); break;
case CKR_WRAPPED_KEY_LEN_RANGE: printf(" CKR_WRAPPED_KEY_LEN_RANGE"); break;
case CKR_WRAPPING_KEY_HANDLE_INVALID: printf(" CKR_WRAPPING_KEY_HANDLE_INVALID"); break;
case CKR_WRAPPING_KEY_SIZE_RANGE: printf(" CKR_WRAPPING_KEY_SIZE_RANGE"); break;
case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: printf(" CKR_WRAPPING_KEY_TYPE_INCONSISTENT"); break;
case CKR_RANDOM_SEED_NOT_SUPPORTED: printf(" CKR_RANDOM_SEED_NOT_SUPPORTED"); break;
case CKR_RANDOM_NO_RNG: printf(" CKR_RANDOM_NO_RNG"); break;
case CKR_BUFFER_TOO_SMALL: printf(" CKR_BUFFER_TOO_SMALL"); break;
case CKR_SAVED_STATE_INVALID: printf(" CKR_SAVED_STATE_INVALID"); break;
case CKR_INFORMATION_SENSITIVE: printf(" CKR_INFORMATION_SENSITIVE"); break;
case CKR_STATE_UNSAVEABLE: printf(" CKR_STATE_UNSAVEABLE"); break;
case CKR_CRYPTOKI_NOT_INITIALIZED: printf(" CKR_CRYPTOKI_NOT_INITIALIZED"); break;
case CKR_CRYPTOKI_ALREADY_INITIALIZED: printf(" CKR_CRYPTOKI_ALREADY_INITIALIZED"); break;
case CKR_MUTEX_BAD: printf(" CKR_MUTEX_BAD"); break;
case CKR_MUTEX_NOT_LOCKED: printf(" CKR_MUTEX_NOT_LOCKED"); break;
/* Otherwise - Value does not match a known PKCS11 return value */
}
}
void showError( char *str, CK_RV rc )
{
printf("%s returned: %d (0x%0x)", str, rc, rc );
ProcessRetCode( rc );
printf("\n");
}
CK_RV createToken( void )
{
CK_VOID_PTR p = NULL; // @D1C
CK_RV rc;
CK_FLAGS flags = 0;
printf("Creating the temporary token... \n");
/* wait for slot event. On z/OS this creates a new slot synchronously */
rc = funcs->C_WaitForSlotEvent(flags, &slotID, p);
if (rc != CKR_OK) {
showError(" C_WaitForSlotEvent #1", rc );
return !CKR_OK;
}
/* The slot has been created. Now initialize the token in the slot */
/* On z/OS no PIN is required, so we will pass NULL. */
rc= funcs->C_InitToken(slotID, NULL, 0, tokenName);
if (rc != CKR_OK) {
showError(" C_InitToken #1", rc );
if (rc == CKR_ARGUMENTS_BAD) {
printf(" Make sure your the token name you specified meets ICSF rules:\n");
printf(" Contains only alphanumeric characters, nationals (@#$), and periods.\n");
printf(" The first character cannot be a numeric or a period.\n");
}
return !CKR_OK;
}
return CKR_OK;
}
CK_RV deleteToken( void )
{
CK_VOID_PTR p;
CK_RV rc;
CK_FLAGS flags = 0;
if (slotID != CK_UNAVAILABLE_INFORMATION) {
printf("Deleting the temporary token... \n");
/* C_InitToken with the reserved label $$DELETE-TOKEN$$ is the way to delete a token */
/* on z/OS */
memset(tokenName, ' ', sizeof(tokenName));
memcpy(tokenName, DEL_TOK, sizeof(DEL_TOK));
rc= funcs->C_InitToken(slotID, NULL, 0, tokenName);
if (rc != CKR_OK) {
showError(" C_InitToken #2 (for delete)", rc );
return !CKR_OK;
}
}
return CKR_OK;
}
CK_RV encryptRSA( void )
{
CK_BYTE data1[100];
CK_BYTE data2[256];
CK_BYTE cipher[256];
CK_SLOT_ID slot_id;
CK_SESSION_HANDLE session;
CK_MECHANISM mech;
CK_OBJECT_HANDLE publ_key, priv_key;
CK_FLAGS flags;
CK_ULONG i;
CK_ULONG len1, len2, cipherlen;
CK_RV rc;
static CK_OBJECT_CLASS class = CKO_PUBLIC_KEY;
static CK_KEY_TYPE type= CKK_RSA;
static CK_OBJECT_CLASS privclass = CKO_PRIVATE_KEY;
static CK_BBOOL true = TRUE;
static CK_BBOOL false = FALSE;
static CK_ULONG bits = 1024;
static CK_BYTE pub_exp[] = { 0x01, 0x00, 0x01 };
/* Attributes for the public key to be generated */
CK_ATTRIBUTE pub_tmpl[] = {
{CKA_MODULUS_BITS, &bits, sizeof(bits) },
{CKA_ENCRYPT, &true, sizeof(true) },
{CKA_VERIFY, &true, sizeof(true) },
{CKA_PUBLIC_EXPONENT, &pub_exp, sizeof(pub_exp) }
};
/* Attributes for the private key to be generated */
CK_ATTRIBUTE priv_tmpl[] =
{
{CKA_DECRYPT, &true, sizeof(true) },
{CKA_SIGN, &true, sizeof(true) }
};
slot_id = slotID;
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
printf("Opening a session... \n");
rc = funcs->C_OpenSession( slot_id, flags, (CK_VOID_PTR) NULL, NULL, &session );
if (rc != CKR_OK) {
showError(" C_OpenSession #1", rc );
return !CKR_OK;
}
printf("Generating keys. This may take a while... \n");
mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
rc = funcs->C_GenerateKeyPair( session, &mech,
pub_tmpl, 4,
priv_tmpl, 2,
&publ_key, &priv_key );
if (rc != CKR_OK) {
showError(" C_GenerateKeyPair #1", rc );
return !CKR_OK;
}
/* now, encrypt some data */
len1 = sizeof(data1);
len2 = sizeof(data2);
cipherlen = sizeof(cipher);
for (i=0; i < len1; i++)
data1[i] = (i) % 255;
mech.mechanism = CKM_RSA_PKCS;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
printf("Enciphering data... \n");
rc = funcs->C_EncryptInit( session, &mech, publ_key );
if (rc != CKR_OK) {
showError(" C_EncryptInit #1", rc );
funcs->C_CloseSession( session );
return !CKR_OK;
}
rc = funcs->C_Encrypt( session, data1, len1, cipher, &cipherlen );
if (rc != CKR_OK) {
showError(" C_Encrypt #1", rc );
funcs->C_CloseSession( session );
return !CKR_OK;
}
/* now, decrypt the data */
printf("Deciphering data... \n");
rc = funcs->C_DecryptInit( session, &mech, priv_key );
if (rc != CKR_OK) {
showError(" C_DecryptInit #1", rc );
funcs->C_CloseSession( session );
return !CKR_OK;
}
rc = funcs->C_Decrypt( session, cipher, cipherlen, data2, &len2 );
if (rc != CKR_OK) {
showError(" C_Decrypt #1", rc );
funcs->C_CloseSession( session );
return !CKR_OK;
}
/* PKCS - returns clear data as is */
if (len1 != len2) {
printf(" ERROR: lengths don't match\n");
printf(" Length of original data = %d, after decryption = %d\n",len1, len2);
funcs->C_CloseSession( session );
return !CKR_OK;
}
for (i=0; i <len1; i++) {
if (data1[i] != data2[i]) {
printf(" ERROR: mismatch at byte %d\n", i );
funcs->C_CloseSession( session );
return !CKR_OK;
}
}
printf("Destroying keys... \n");
rc = funcs->C_DestroyObject( session, priv_key );
if (rc != CKR_OK) {
showError(" C_DestroyObject #1", rc );
funcs->C_CloseSession( session );
return !CKR_OK;
}
rc = funcs->C_DestroyObject( session, publ_key );
if (rc != CKR_OK) {
showError(" C_DestroyObject #2", rc );
funcs->C_CloseSession( session );
return !CKR_OK;
}
printf("Closing the session... \n");
rc = funcs->C_CloseSession( session );
if (rc != CKR_OK) {
showError(" C_CloseSession #1", rc );
return !CKR_OK;
}
return CKR_OK;
}
CK_RV getFunctionList( void )
{
CK_RV rc;
CK_RV (*pFunc)();
void *d;
#ifdef _LP64
char e[]="CSNPCA64";
#elif __XPLINK__ /* @P1C */
char e[]="CSNPCA3X"; /* @D2A */
#else
char e[]="CSNPCAPI";
#endif
printf("Getting the PKCS11 function list...\n");
d = dlopen(e,RTLD_NOW);
if ( d == NULL ) {
printf("%s not found in linklist or LIBPATH\n",e); // @D1A
return !CKR_OK;
}
pFunc = (CK_RV (*)())dlsym(d,"C_GetFunctionList");
if (pFunc == NULL ) {
printf("C_GetFunctionList() not found in module %s\n",e); // @D1A
return !CKR_OK;
}
rc = pFunc(&funcs);
if (rc != CKR_OK) {
showError(" C_GetFunctionList", rc );
return !CKR_OK;
}
return CKR_OK;
}
void displaySyntax(char *pgm) {
printf("usage: %s { -t <token-name> | -h }\n\n", pgm );
printf(" -t <token-name> = The name of a temporary token to create for the test. The\n");
printf(" name must be less than 33 characters in length and contains only alphanumeric\n");
printf(" characters, nationals (@#$), and periods. The first character cannot be a\n");
printf(" numeric or a period. The token will be deleted when the test is complete.\n\n");
printf(" -h = Displays this help.\n\n");
}
void main( int argc, char **argv )
{
CK_C_INITIALIZE_ARGS cinit_args;
CK_RV rc, i;
memset(tokenName, ' ', sizeof(tokenName)); /* Token name is left justified, padded with blanks */
if (argc == 3) {
if (strcmp(argv[1], "-t") == 0)
if (strlen(argv[2]) > 0 && strlen(argv[2]) < 33) {
memcpy(tokenName, argv[2], strlen(argv[2]));
}
else {
displaySyntax(argv[0]);
return;
}
else {
displaySyntax(argv[0]);
return;
}
}
else {
displaySyntax(argv[0]);
return;
}
rc = getFunctionList();
if (rc != CKR_OK) {
printf("getFunctionList failed!\n"); // @D1C
return;
}
memset( &cinit_args, 0x0, sizeof(cinit_args) );
cinit_args.flags = CKF_OS_LOCKING_OK;
printf("Initializing the PKCS11 environment...\n");
rc = funcs->C_Initialize( &cinit_args );
if (rc != CKR_OK) {
showError(" C_Initialize", rc );
return;
}
rc = createToken();
if (rc != CKR_OK) {
funcs->C_Finalize( NULL );
return;
}
rc = encryptRSA();
if (rc != CKR_OK) {
deleteToken();
funcs->C_Finalize( NULL );
return;
}
rc = deleteToken();
if (rc != CKR_OK) {
funcs->C_Finalize( NULL );
return;
}
rc = funcs->C_Finalize( NULL );
if (rc != CKR_OK) {
showError(" C_Initialize", rc );
return;
}
printf("Test completed successfully!\n");
}
|