z/OS Cryptographic Services ICSF Writing PKCS #11 Applications
Previous topic | Next topic | Contents | Index | Contact z/OS | Library | PDF


Source code for the testpkcs11 sample program

z/OS Cryptographic Services ICSF Writing PKCS #11 Applications
SA23-2231-05

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");
 
}

Go to the previous page Go to the next page




Copyright IBM Corporation 1990, 2014