Migrating Keys From Software to a SafeNet Luna PCIe HSM

SafeNet Luna PCIe HSMs expect key material to be in PKCS#8 format.  PKCS#8 format follows BER (Basic encoding rules)/DER (distinguished encoding rules) encoding. An example of this format can be found in the document "Some examples of PKCS standards" produced by RSA, and available on their web site (http://www.rsasecurity.com/rsalabs/pkcs/index.html at the bottom of the page, under “Related Documents”).

Here is an example of a formatted key:

 0x30, 
 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 
 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x04, 
 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 
 0x00, 0xb8, 0xb5, 0x0f, 0x49, 0x46, 0xb5, 0x5d, 0x58, 0x04, 0x8e, 0x52, 
 0x59, 0x39, 0xdf, 0xd6, 0x29, 0x45, 0x6b, 0x6c, 0x96, 0xbb, 0xab, 0xa5, 
 0x6f, 0x72, 0x1b, 0x16, 0x96, 0x74, 0xd5, 0xf9, 0xb4, 0x41, 0xa3, 0x7c, 
 0xe1, 0x94, 0x73, 0x4b, 0xa7, 0x23, 0xff, 0x61, 0xeb, 0xce, 0x5a, 0xe7, 
 0x7f, 0xe3, 0x74, 0xe8, 0x52, 0x5b, 0xd6, 0x5d, 0x5c, 0xdc, 0x98, 0x49, 
 0xfe, 0x51, 0xc2, 0x7e, 0x8f, 0x3b, 0x37, 0x5c, 0xb3, 0x11, 0xed, 0x85, 
 0x91, 0x15, 0x92, 0x24, 0xd8, 0xf1, 0x7b, 0x3d, 0x2f, 0x8b, 0xcd, 0x1b, 
 0x30, 0x14, 0xa3, 0x6b, 0x1b, 0x4d, 0x27, 0xff, 0x6a, 0x58, 0x84, 0x9e, 
 0x79, 0x94, 0xca, 0x78, 0x64, 0x01, 0x33, 0xc3, 0x58, 0xfc, 0xd3, 0x83, 
 0xeb, 0x2f, 0xab, 0x6f, 0x85, 0x5a, 0x38, 0x41, 0x3d, 0x73, 0x20, 0x1b, 
 0x82, 0xbc, 0x7e, 0x76, 0xde, 0x5c, 0xfe, 0x42, 0xd6, 0x7b, 0x86, 0x4f, 
 0x79, 0x78, 0x29, 0x82, 0x87, 0xa6, 0x24, 0x43, 0x39, 0x74, 0xfe, 0xf2, 
 0x0c, 0x08, 0xbe, 0xfa, 0x1e, 0x0a, 0x48, 0x6f, 0x14, 0x86, 0xc5, 0xcd, 
 0x9a, 0x98, 0x09, 0x2d, 0xf3, 0xf3, 0x5a, 0x7a, 0xa4, 0xe6, 0x8a, 0x2e, 
 0x49, 0x8a,  0xde, 
 0x73, 0xe9, 0x37, 0xa0, 0x5b, 0xef, 0xd0, 0xe0, 0x13, 0xac, 0x88, 0x5f, 
 0x59, 0x47, 0x96, 0x7f, 0x78, 0x18, 0x0e, 0x44, 0x6a, 0x5d,  0xec, 
 0x6e, 0xed, 0x4f, 0xf6, 0x6a, 0x7a, 0x58, 0x6b, 0xfe, 0x6c, 0x5a, 0xb9, 
 0xd2, 0x22, 0x3a, 0x1f, 0xdf, 0xc3, 0x09, 0x3f, 0x6b, 0x2e, 0xf1, 0x6d, 
 0xc3, 0xfb, 0x4e, 0xd4, 0xf2, 0xa3, 0x94, 0x13, 0xb0, 0xbf, 0x1e, 0x06, 
 0x2e, 0x29, 0x55, 0x00, 0xaa, 0x98, 0xd9, 0xe8, 0x77, 0x84, 0x8b, 0x3f, 
 0x5f, 0x5e, 0xf7, 0xf8, 0xa7, 0xe6, 0x02, 0xd2, 0x18, 0xb0, 0x52, 0xd0, 
 0x37, 0x2e, 0x53, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 
 0x0c, 0xdf, 0xd1, 0xe8, 0xf1, 0x9c, 0xc2, 0x9c, 0xd7, 0xf4, 0x73, 0x98, 
 0xf4, 0x87, 0xbd, 0x8d, 0xb2, 0xe1, 0x01, 0xf8, 0x9f, 0xac, 0x1f, 0x23, 
 0xdd, 0x78, 0x35, 0xe2, 0xd6, 0xd1, 0xf3, 0x4d, 0xb5, 0x25, 0x88, 0x16, 
 0xd1, 0x1a, 0x18, 0x33, 0xd6, 0x36, 0x7e, 0xc4, 0xc8, 0xe5, 0x5d, 0x2d, 
 0x74, 0xd5, 0x39, 0x3c, 0x44, 0x5a, 0x74, 0xb7, 0x7c, 0x48, 0xc1, 0x1f, 
 0x90, 0xe3, 0x55, 0x9e, 0xf6, 0x29, 0xad, 0xb4, 0x6d, 0x93, 0x78, 0xb3, 
 0xdc, 0x25, 0x0b, 0x9c, 0x73, 0x78, 0x7b, 0x93, 0x4c, 0xd3, 0x47, 0x09, 
 0xda, 0xe6, 0x69, 0x18, 0xc6, 0x0f, 0xfb, 0xa5, 0x95, 0xf5, 0xe8, 0x75, 
 0xe1, 0x01, 0x1b, 0xd3, 0x1c, 0xa2, 0x57, 0x03, 0x64, 0xdb, 0xf9, 0x5d, 
 0xf3, 0x3c, 0xa7, 0xd1, 0x4b, 0xb0, 0x90, 0x1b, 0x90, 0x62, 0xb4, 0x88, 
 0x30, 0x4b, 0x40, 0x4d, 0xcf, 0x7d, 0x89, 0x7a, 0xfb, 0x29, 0xc9, 0x64, 
 0x34, 0x0a, 0x52, 0xf6, 0x70, 0x7c, 0x76, 0x5a, 0x2e, 0x8f, 0x50, 0xd4, 
 0x92, 0x15, 0x97, 0xed, 0x4c, 0x2e, 0xf2, 0x3a, 0xd0, 0x58, 0x7e, 0xdb, 
 0xf1, 0xf4, 0xdd, 0x07, 0x76, 0x04, 0xf0, 0x55, 0x8b, 0x72, 0x2b, 0xa7, 
 0xa8, 0x78, 0x78, 0x67, 0xe6, 0xd8, 0xa5, 0xde, 0xe7, 0xc9, 0x1f, 0x5a, 
 0xa0, 0x89, 0xc7, 0x24, 0xa2, 0x71, 0xb6, 0x7b, 0x3b, 0xe6, 0x92, 0x69, 
 0x22, 0xaa, 0xe2, 0x47, 0x4b, 0x80, 0x3f, 0x6a, 0xab, 0xce, 0x4e, 0xcd, 
 0xe8, 0x94, 0x6c, 0xf7, 0x84, 0x73, 0x85, 0xfd, 0x85, 0x1d, 0xae, 0x81, 
 0xf7, 0xec, 0x12, 0x31, 0x7d, 0xc1, 0x99, 0xc0, 0x3c, 0x51, 0xb0, 0xdc, 
 0xb0, 0xba, 0x9c, 0x84, 0xb8, 0x70, 0xc2, 0x09, 0x7f, 0x96, 0x3d, 0xa1, 
 0xe2, 0x64, 0x27, 0x7a, 0x22, 0xb8, 0x75, 0xb9, 0xd1, 0x5f, 0xa5, 0x23, 
 0xf9, 0x62, 0xe0, 0x41, 0x02, 0x81, 0x81, 0x00, 0xf4, 0xf3, 0x08, 0xcf, 
 0x83, 0xb0, 0xab, 0xf2, 0x0f, 0x1a, 0x08, 0xaf, 0xc2, 0x42, 0x29, 0xa7, 
 0x9c, 0x5e, 0x52, 0x19, 0x69, 0x8d, 0x5b, 0x52, 0x29, 0x9c, 0x06, 0x6a, 
 0x5a, 0x32, 0x8f, 0x08, 0x45, 0x6c, 0x43, 0xb5, 0xac, 0xc3, 0xbb, 0x90, 
 0x7b, 0xec, 0xbb, 0x5d, 0x71, 0x25, 0x82, 0xf8, 0x40, 0xbf, 0x38, 0x00, 
 0x20, 0xf3, 0x8a, 0x38, 0x43, 0xde, 0x04, 0x41, 0x19, 0x5f, 0xeb, 0xb0, 
 0x50, 0x59, 0x10, 0xe1, 0x54, 0x62, 0x5c, 0x93, 0xd9, 0xdc, 0x63, 0x24, 
 0xd0, 0x17, 0x00, 0xc0, 0x44, 0x3e, 0xfc, 0xd1, 0xda, 0x4b, 0x24, 0xf7, 
 0xcb, 0x16, 0x35, 0xe6, 0x9f, 0x67, 0x96, 0x5f, 0xb0, 0x94, 0xde, 0xfa, 
 0xa1, 0xfd, 0x8c, 0x8a, 0xd1, 0x5c, 0x02, 0x8d, 0xe0, 0xa0, 0xa0,  0x02, 
 0x1d, 0x56, 0xaf, 0x13, 0x3a, 0x65, 0x5e, 0x8e, 0xde, 0xd1, 0xa8, 0x28, 
 0x8b, 0x71, 0xc9, 0x65, 0x02, 0x81, 0x81, 0x00, 0xc1, 0x0a,  0x47, 
 0x39, 0x91, 0x06, 0x1e, 0xb9, 0x43, 0x7c, 0x9e, 0x97, 0xc5, 0x09, 0x08, 
 0xbc, 0x22, 0x47, 0xe2, 0x96, 0x8e, 0x1c, 0x74, 0x80, 0x50, 0x6c, 0x9f, 
 0xef, 0x2f, 0xe5, 0x06, 0x3e, 0x73, 0x66, 0x76, 0x02, 0xbd, 0x9a, 0x1c, 
 0xfc, 0xf9, 0x6a, 0xb8, 0xf9, 0x36, 0x15, 0xb5, 0x20, 0x0b, 0x6b, 0x54, 
 0x83, 0x9c, 0x86, 0xba, 0x13, 0xb7, 0x99, 0x54, 0xa0, 0x93, 0x0d, 0xd6, 
 0x1e, 0xc1, 0x12, 0x72, 0x0d, 0xea, 0xb0, 0x14, 0x30, 0x70, 0x73, 0xef, 
 0x6b, 0x4c, 0xae, 0xb6, 0xff, 0xd4, 0xbb, 0x89, 0xa1, 0xec, 0xca, 0xa6, 
 0xe9, 0x95, 0x56, 0xac, 0xe2, 0x9b, 0x97, 0x2f, 0x2c, 0xdf, 0xa3, 0x6e, 
 0x59, 0xff, 0xcd, 0x3c, 0x6f, 0x57, 0xcc, 0x6e, 0x44, 0xc4, 0x27, 0xbf, 
 0xc3, 0xdd, 0x19, 0x9e, 0x81, 0x16, 0xe2, 0x8f, 0x65, 0x34, 0xa7, 0x0f, 
 0x22, 0xba, 0xbf, 0x79, 0x57, 0x02, 0x81, 0x80, 0x2e, 0x21, 0x0e, 0xc9, 
 0xb5, 0xad, 0x31, 0xd4, 0x76, 0x0f, 0x9b, 0x0f, 0x2e, 0x70, 0x33, 0x54, 
 0x03, 0x58, 0xa7, 0xf1, 0x6d, 0x35, 0x57, 0xbb, 0x53, 0x66, 0xb4, 0xb6, 
 0x96, 0xa1, 0xea, 0xd9, 0xcd, 0xe9, 0x23, 0x9f, 0x35, 0x17, 0xef, 0x5c, 
 0xb8, 0x59, 0xce, 0xb7, 0x3c, 0x35, 0xaa, 0x42, 0x82, 0x3f, 0x00, 0x96, 
 0xd5, 0x9d, 0xc7, 0xab, 0xec, 0xec, 0x04, 0xb5, 0x15, 0xc8, 0x40, 0xa4, 
 0x85, 0x9d, 0x20, 0x56, 0xaf, 0x03, 0x8f, 0x17, 0xb0, 0xf1, 0x96, 0x22, 
 0x3a, 0xa5, 0xfa, 0x58, 0x3b, 0x01, 0xf9, 0xae, 0xb3, 0x83, 0x6f, 0x44, 
 0xd3, 0x14, 0x2d, 0xb6, 0x6e, 0xd2, 0x9d, 0x39, 0x0c, 0x12, 0x1d, 0x23, 
 0xea, 0x19, 0xcb, 0xbb, 0xe0, 0xcd, 0x89, 0x15, 0x9a, 0xf5, 0xe4, 0xec, 
 0x41, 0x06, 0x30, 0x16, 0x58, 0xea, 0xfa, 0x31, 0xc1, 0xb8, 0x8e, 0x08, 
 0x84, 0xaa, 0x3b, 0x19, 0x02, 0x81, 0x80, 0x70, 0x4c, 0xf8, 0x6e, 0x86, 
 0xed, 0xd6, 0x85, 0xd4, 0xba, 0xf4, 0xd0, 0x3a, 0x32, 0x2d, 0x40, 0xb5, 
 0x78, 0xb8, 0x5a, 0xf9, 0xc5, 0x98, 0x08, 0xe5, 0xc0, 0xab, 0xb2, 0x4c, 
 0x5c, 0xa2, 0x2b, 0x46, 0x9b, 0x3e, 0xe0, 0x0d, 0x49, 0x50, 0xbf, 0xe2, 
 0xa1, 0xb1, 0x86, 0x59, 0x6e, 0x7b, 0x76, 0x6e, 0xee, 0x3b, 0xb6, 0x6d, 
 0x22, 0xfb, 0xb1, 0x68, 0xc7, 0xec, 0xb1, 0x95, 0x9b, 0x21, 0x0b, 0xb7, 
 0x2a, 0x71, 0xeb, 0xa2, 0xb2, 0x58, 0xac, 0x6d, 0x5f, 0x24, 0xd3, 0x79, 
 0x42, 0xd2, 0xf7, 0x35, 0xdc, 0xfc, 0x0e, 0x95, 0x60, 0xb7, 0x85, 0x7f, 
 0xf9, 0x72, 0x8e, 0x4a, 0x11, 0xc3, 0xc2, 0x09, 0x40, 0x5c, 0x7c, 0x43, 
 0x12, 0x34, 0xac, 0x59, 0x99, 0x76, 0x34,  0xcf, 
 0x20, 0x88, 0xb0, 0xfb, 0x39, 0x62, 0x3a, 0x9b, 0x03, 0xa6, 0x84, 0x2c, 
 0x03, 0x5c, 0x0c, 0xca, 0x33, 0x85, 0xf5, 0x02, 0x81, 0x80,  0x56, 
 0x99, 0xe9, 0x17, 0xdc, 0x33, 0xe1, 0x33, 0x8d, 0x5c, 0xba, 0x17, 0x32, 
 0xb7, 0x8c, 0xbd, 0x4b, 0x7f, 0x42, 0x3a, 0x79, 0x90, 0xe3,  0x70, 
 0xe3, 0x27, 0xce, 0x22, 0x59, 0x02, 0xc0, 0xb1, 0x0e, 0x57, 0xf5, 0xdf, 
 0x07, 0xbf, 0xf8, 0x4e, 0x10, 0xef, 0x2a, 0x62, 0x30, 0x03,  0xd4, 
 0x80, 0xcf, 0x20, 0x84, 0x25, 0x66, 0x3f, 0xc7, 0x4f, 0x56, 0x8c, 0x1e, 
 0xe1, 0x18, 0x91, 0xc1, 0xfd, 0x71, 0x5f, 0x65, 0x9b, 0xe4,  0x4f, 
 0xe0, 0x1a, 0x3a, 0xf8, 0xc1, 0x69, 0xdb, 0xd3, 0xbb, 0x8d, 0x91, 0xd1, 
 0x11, 0x4f, 0x7e, 0x91, 0x1b, 0xb4, 0x27, 0xa5, 0xab, 0x7c,  0x7b, 
 0x76, 0xd4, 0x78, 0xfe, 0x63, 0x44, 0x63, 0x7e, 0xe3, 0xa6, 0x60, 0x4f, 
 0xb9, 0x55, 0x28, 0xba, 0xba, 0x83, 0x1a, 0x2d, 0x43, 0xd5,  0xf7, 
 0x2e, 0xe0, 0xfc, 0xa8, 0x14, 0x9b, 0x91, 0x2a, 0x36, 0xbf, 0xc7, 0x14
 

The example above contains the exponent, the modulus, and private key material.

Other Formats of Key Material

The format of key material depends on the application, and is therefore unpredictable. Key material commonly exists in any of the following formats; ASN1, PEM, P12, PFX, etc. Key material in those formats, or in another format, can likely be re-formatted to be acceptable for moving onto the SafeNet Luna PCIe HSM.

Sample Program

The sample program below encrypts a known RSA private key, then unwraps the key pair onto the SafeNet Luna PCIe HSM Partition.

/****************************************************************************\
*
* File: UnwrapKey.cpp*
* Encrypts a PrivateKeyInfo structure with a generated DES 
 key and then
* unwraps the RSA key onto a token. 
*
* This file is provided as an example only.
* 
*
* Copyright (C) 2017, Gemalto, Inc.
*
* All rights reserved. This file contains information that 
 is
* proprietary to SafeNet, Inc. and may not be 
* distributed or copied without written consent from 
* SafeNet, Inc.
*
\**************************************************************/
#ifdef UNIX
#define _POSIX_SOURCE 1
#endif
#ifdef USING_STATIC_CHRYSTOKI
# define STATIC  ckdemo_cpp
#endif
#include <assert.h>
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#ifdef _WINDOWS
#include <conio.h>
#include <io.h>
#include <windows.h>
#endif
#ifdef UNIX
#include <unistd.h>
#endif
#include "source/cryptoki.h"
#include "source/Ckbridge.h"
#define DIM(a)                   (sizeof(a)/sizeof(a[0]))
CK_BBOOL no = FALSE;
CK_BBOOL yes = TRUE;
const int MAX =100;
// Function Prototypes
CK_RV  Pinlogin(CK_SESSION_HANDLE 
 hSession);
int getPinString(CK_CHAR_PTR pw);
// Main
int main( void )
{
   int 
               error 
 = 0;
   CK_RV 
             retCode 
 = CKR_OK;
   CK_SESSION_HANDLE 
 hSessionHandle;
   CK_CHAR_PTR 
       userPIN 
 = (CK_CHAR_PTR)"default";
   CK_USHORT 
         lenuserPIN 
  = 7;
   CK_CHAR_PTR 
       soPIN 
 = (CK_CHAR_PTR)"default";
   CK_USHORT 
         lensoPIN 
 = 7;
   CK_USHORT 
         usNumberOfSlots;
   CK_SLOT_ID_PTR 
    pSlotList;
   CK_OBJECT_HANDLE 
 hKey;
   CK_MECHANISM 
 mech;
   CK_VERSION 
 version;
   struct
   {
      CK_INFO 
 info;
      char 
 reserved[100]; // This is in case the library that we are
                          // 
 talking to requires a larger info structure
                          // 
 then the one defined.
   } 
 protectedInfo;
//Disclaimer
   cout 
 << "\n\n\n\n";
cout << "THE SOFTWARE IS PROVIDED BY SAFENET INCORPORATED 
 (SAFENET) ON AN 'AS IS' BASIS, \n";
cout << "WITHOUT ANY OTHER WARRANTIES OR CONDITIONS, 
 EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED \n";
cout << "TO, WARRANTIES OF MERCHANTABLE QUALITY, 
 SATISFACTORY QUALITY, MERCHANTABILITY OR FITNESS FOR\n";
cout << "A PARTICULAR PURPOSE, OR THOSE ARISING 
 BY LAW, STATUTE, USAGE OF TRADE, COURSE OF DEALING OR\n";
cout << "OTHERWISE.  SAFENET 
 DOES NOT WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS OR \n";
cout << "THAT OPERATION OF THE SOFTWARE WILL BE 
 UNINTERRUPTED OR THAT THE SOFTWARE WILL BE ERROR-FREE.\n";
cout << "YOU ASSUME THE ENTIRE RISK AS TO THE 
 RESULTS AND PERFORMANCE OF THE SOFTWARE.  NEITHER 
 \n";
cout << "SAFENET NOR OUR LICENSORS, DEALERS OR 
 SUPPLIERS SHALL HAVE ANY LIABILITY TO YOU OR ANY\n";
cout << "OTHER PERSON OR ENTITY FOR ANY INDIRECT, 
 INCIDENTAL, SPECIAL, CONSEQUENTIAL, PUNITIVE, \n";
cout << "EXEMPLARY OR AY OTHER DAMAGES WHATSOEVER, 
 INCLUDING, BUT NOT LIMITED TO, LOSS OF REVENUE OR \n";
cout << "PROFIT, LOST OR DAMAGED DATA, LOSS OF 
 USE OR OTHER COMMERCIAL OR ECONOMIC LOSS, EVEN IF \n";
cout << "SAFENET HAS BEEN ADVISED OF THE POSSIBILITY 
 OF SUCH DAMAGES, OR THEY ARE FORESEEABLE. \n";
cout << "SAFENET IS ALSO NOT RESPONSIBLE FOR CLAIMS 
 BY A THIRD PARTY.  THE 
 MAXIMUM AGGREGATE \n";
cout << "LIABILITY OF SAFENET TO YOU AND THAT 
 OF SAFENET’S LICENSORS, DEALERS AND SUPPLIERS \n";
cout << "SHALL NOT EXCEED FORTY DOLLARS ($40.00CDN). 
  THE LIMITATIONS 
 IN THIS SECTION SHALL APPLY \n";
cout << "WHETHER OR NOT THE ALLEGED BREACH OR 
 DEFAULT IS A BREACH OF A FUNDAMENTAL CONDITION OR TERM \n";
cout << "OR A FUNDAMENTAL BREACH.  SOME 
 STATES/COUNTRIES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF\n";
cout << "LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL 
 DAMAGES, SO THE ABOVE LIMITATION MAY NOT APPLY TO \n";
cout << "YOU.\n";
cout << "THE LIMITED WARRANTY, EXCLUSIVE REMEDIES 
 AND LIMITED LIABILITY SET OUT HEREIN ARE FUNDAMENTAL \n";
cout << "ELEMENTS OF THE BASIS OF THE BARGAIN 
 BETWEEN YOU AND SAFENET.  \n";
cout << "NO SUPPORT.  YOU 
 ACKNOWLEDGE AND AGREE THAT THERE ARE NO SUPPORT SERVICES PROVIDED BY SAFENET\n";
cout << "INCORPORATED FOR THIS SOFTWARE\n" 
 << endl;
   // 
 Display Generic Warning
   cout 
 << "\nInsert a token for the test...";
   cout 
 << "\n\nWARNING!!! This test initializes the first ";
   cout 
 << " token detected in the card reader.";
   cout 
 << "\nDo not use a token that you don't want erased.";
   cout 
 << "\nYou can use CTRL-C to abort now...Otherwise...";
   cout 
 << "\n\n... press <Enter> key to continue ...\n";
   cout.flush();
   getchar(); 
 // Wait for keyboard hit
#ifndef STATIC   
   // 
 Connect to Chrystoki
if(!CrystokiConnect())
{
cout << "\n" "Unable to connect to Chrystoki. 
  Error = 
 " << LibError() << "\n";
error = -1;
      goto 
 exit_routine_1;
}
#endif
   // 
 Verify this is the version of the library required
   retCode 
 = C_GetInfo(&protectedInfo.info);
   if( 
 retCode != CKR_OK )
   {
      cout 
 << endl << "Unable to call C_GetInfo() before C_Initialize()\n";
error = -2;
      goto 
 exit_routine_2;
   }
   else
   {
      CK_BYTE 
 majorVersion = protectedInfo.info.version.major;
      CK_BYTE 
 expectedVersion;
#ifndef PKCS11_2_0
      expectedVersion 
 = 1;
#else
      expectedVersion 
 = 2;
#endif
      if( 
 expectedVersion != majorVersion )
      {
         cout 
 << endl << "This version of the program was built for 
 Cryptoki version "
              << 
 (int)expectedVersion << ".\n"
              << 
 "The loaded Cryptoki library reports its version to be "
              << 
 (int)majorVersion << ".\n"
              << 
 "Program will terminate.\n";
         // 
 Wait to exit until user read message and acknowledges
         cout 
 << endl << "Press <Enter> key to end.";
         getchar(); 
 // Wait for keyboard hit
   error 
 = -3;
         goto 
 exit_routine_2;
      }
   }
   // 
 Initialize the Library
retCode = C_Initialize(NULL);
if(retCode != CKR_OK)
{
cout << "\n" "Error 0x" << 
 hex << retCode << " initializing cryptoki.\n";
error = -4;
      goto 
 exit_routine_3;
}
// Get the number of tokens possibly available
retCode = C_GetSlotList(TRUE, NULL, &usNumberOfSlots);
if(retCode != CKR_OK)
{
cout << "\n" "Error 0x" << 
 hex << retCode << " getting slot list.\n";
error = -5;
      goto 
 exit_routine_3;
}
// Are any tokens present?
if(usNumberOfSlots == 0)
{
cout << "\n" "No tokens found\n";
error = -6;
      goto 
 exit_routine_3;
   }
   // 
 Get a list of slots
pSlotList = new CK_SLOT_ID[usNumberOfSlots];
retCode = C_GetSlotList(TRUE, pSlotList, &usNumberOfSlots);
if(retCode != CKR_OK)
{
cout << "\n" "Error 0x" << 
 hex << retCode << " getting slot list.\n";
error = -7;
      goto 
 exit_routine_4;
}
   // 
 Open a session
retCode = C_OpenSession(pSlotList[0], CKF_RW_SESSION | CKF_SERIAL_SESSION, 
 
      NULL, 
 NULL, &hSessionHandle);
if(retCode != CKR_OK)
{
cout << "\n" "Error 0x" << 
 hex << retCode << " opening session.\n";
error = -9;
      goto 
 exit_routine_4;
}
Pinlogin(hSessionHandle);
if(retCode != CKR_OK)
{
cout << "\n" "Error 0x" << 
 hex << retCode << " Calling PinLogin fn";
exit(hSessionHandle);
}
  // 
 Encrypt an RSA Key and then unwrap it onto the token
   {
      // 
 The following is an RSA Key that is formatted as a PrivateKeyInfo structure
   //BER 
 encoded format
      const 
 CK_BYTE pRsaKey[] = {
 0x30, 
 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 
 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 
0x01, 0x05, 0x00, 0x04,
 0x82, 
 0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 
 0x01, 0x00, 0xb8, 0xb5, 0x0f, 0x49, 
0x46, 0xb5, 0x5d, 0x58,
 0x04, 
 0x8e, 0x52, 0x59, 0x39, 0xdf, 0xd6, 0x29, 0x45, 0x6b, 0x6c, 0x96, 0xbb, 
 0xab, 0xa5, 0x6f, 0x72, 0x1b, 0x16, 
0x96, 0x74, 0xd5, 0xf9,
 0xb4, 
 0x41, 0xa3, 0x7c, 0xe1, 0x94, 0x73, 0x4b, 0xa7, 0x23, 0xff, 0x61, 0xeb, 
 0xce, 0x5a, 0xe7, 0x7f, 0xe3, 0x74, 
0xe8, 0x52, 0x5b, 0xd6,
 0x5d, 
 0x5c, 0xdc, 0x98, 0x49, 0xfe, 0x51, 0xc2, 0x7e, 0x8f, 0x3b, 0x37, 0x5c, 
 0xb3, 0x11, 0xed, 0x85, 0x91, 0x15, 
0x92, 0x24, 0xd8, 0xf1,
 0x7b, 
 0x3d, 0x2f, 0x8b, 0xcd, 0x1b, 0x30, 0x14, 0xa3, 0x6b, 0x1b, 0x4d, 0x27, 
 0xff, 0x6a, 0x58, 0x84, 0x9e, 0x79, 
0x94, 0xca, 0x78, 0x64,
 0x01, 
 0x33, 0xc3, 0x58, 0xfc, 0xd3, 0x83, 0xeb, 0x2f, 0xab, 0x6f, 0x85, 0x5a, 
 0x38, 0x41, 0x3d, 0x73, 0x20, 0x1b, 
0x82, 0xbc, 0x7e, 0x76,
 0xde, 
 0x5c, 0xfe, 0x42, 0xd6, 0x7b, 0x86, 0x4f, 0x79, 0x78, 0x29, 0x82, 0x87, 
 0xa6, 0x24, 0x43, 0x39, 0x74, 0xfe, 
0xf2, 0x0c, 0x08, 0xbe,
 0xfa, 
 0x1e, 0x0a, 0x48, 0x6f, 0x14, 0x86, 0xc5, 0xcd, 0x9a, 0x98, 0x09, 0x2d, 
 0xf3, 0xf3, 0x5a, 0x7a, 0xa4, 0xe6, 
0x8a, 0x2e, 0x49, 0x8a, 0xde, 0x73, 0xe9, 0x37, 0xa0, 0x5b, 
 0xef,
 0xd0, 
 0xe0, 0x13, 0xac, 0x88, 0x5f, 0x59, 0x47, 0x96, 0x7f, 0x78, 0x18, 0x0e, 
 0x44, 0x6a, 0x5d, 0xec, 0x6e, 0xed, 
0x4f, 0xf6, 0x6a, 0x7a,
 0x58, 
 0x6b, 0xfe, 0x6c, 0x5a, 0xb9, 0xd2, 0x22, 0x3a, 0x1f, 0xdf, 0xc3, 0x09, 
 0x3f, 0x6b, 0x2e, 0xf1, 0x6d, 0xc3, 
0xfb, 0x4e, 0xd4, 0xf2,
 0xa3, 
 0x94, 0x13, 0xb0, 0xbf, 0x1e, 0x06, 0x2e, 0x29, 0x55, 0x00, 0xaa, 0x98, 
 0xd9, 0xe8, 0x77, 0x84, 0x8b, 0x3f, 
0x5f, 0x5e, 0xf7, 0xf8,
 0xa7, 
 0xe6, 0x02, 0xd2, 0x18, 0xb0, 0x52, 0xd0, 0x37, 0x2e, 0x53, 0x02, 0x03, 
 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 
0x00, 0x0c, 0xdf, 0xd1,
 0xe8, 
 0xf1, 0x9c, 0xc2, 0x9c, 0xd7, 0xf4, 0x73, 0x98, 0xf4, 0x87, 0xbd, 0x8d, 
 0xb2, 0xe1, 0x01, 0xf8, 0x9f, 0xac, 
0x1f, 0x23, 0xdd, 0x78,
 0x35, 
 0xe2, 0xd6, 0xd1, 0xf3, 0x4d, 0xb5, 0x25, 0x88, 0x16, 0xd1, 0x1a, 0x18, 
 0x33, 0xd6, 0x36, 0x7e, 0xc4, 0xc8, 
0xe5, 0x5d, 0x2d, 0x74,
 0xd5, 
 0x39, 0x3c, 0x44, 0x5a, 0x74, 0xb7, 0x7c, 0x48, 0xc1, 0x1f, 0x90, 0xe3, 
 0x55, 0x9e, 0xf6, 0x29, 0xad, 0xb4, 
0x6d, 0x93, 0x78, 0xb3,
 0xdc, 
 0x25, 0x0b, 0x9c, 0x73, 0x78, 0x7b, 0x93, 0x4c, 0xd3, 0x47, 0x09, 0xda, 
 0xe6, 0x69, 0x18, 0xc6, 0x0f, 0xfb, 
0xa5, 0x95, 0xf5, 0xe8,
 0x75, 
 0xe1, 0x01, 0x1b, 0xd3, 0x1c, 0xa2, 0x57, 0x03, 0x64, 0xdb, 0xf9, 0x5d, 
 0xf3, 0x3c, 0xa7, 0xd1, 0x4b, 0xb0, 
0x90, 0x1b, 0x90, 0x62,
 0xb4, 
 0x88, 0x30, 0x4b, 0x40, 0x4d, 0xcf, 0x7d, 0x89, 0x7a, 0xfb, 0x29, 0xc9, 
 0x64, 0x34, 0x0a, 0x52, 0xf6, 0x70, 
0x7c, 0x76, 0x5a, 0x2e,
 0x8f, 
 0x50, 0xd4, 0x92, 0x15, 0x97, 0xed, 0x4c, 0x2e, 0xf2, 0x3a, 0xd0, 0x58, 
 0x7e, 0xdb, 0xf1, 0xf4, 0xdd, 0x07, 
0x76, 0x04, 0xf0, 0x55,
 0x8b, 
 0x72, 0x2b, 0xa7, 0xa8, 0x78, 0x78, 0x67, 0xe6, 0xd8, 0xa5, 0xde, 0xe7, 
 0xc9, 0x1f, 0x5a, 0xa0, 0x89, 0xc7, 
0x24, 0xa2, 0x71, 0xb6,
 0x7b, 
 0x3b, 0xe6, 0x92, 0x69, 0x22, 0xaa, 0xe2, 0x47, 0x4b, 0x80, 0x3f, 0x6a, 
 0xab, 0xce, 0x4e, 0xcd, 0xe8, 0x94, 
0x6c, 0xf7, 0x84, 0x73,
 0x85, 
 0xfd, 0x85, 0x1d, 0xae, 0x81, 0xf7, 0xec, 0x12, 0x31, 0x7d, 0xc1, 0x99, 
 0xc0, 0x3c, 0x51, 0xb0, 0xdc, 0xb0, 
0xba, 0x9c, 0x84, 0xb8,
 0x70, 
 0xc2, 0x09, 0x7f, 0x96, 0x3d, 0xa1, 0xe2, 0x64, 0x27, 0x7a, 0x22, 0xb8, 
 0x75, 0xb9, 0xd1, 0x5f, 0xa5, 0x23, 
0xf9, 0x62, 0xe0, 0x41,
 0x02, 
 0x81, 0x81, 0x00, 0xf4, 0xf3, 0x08, 0xcf, 0x83, 0xb0, 0xab, 0xf2, 0x0f, 
 0x1a, 0x08, 0xaf, 0xc2, 0x42, 0x29, 
0xa7, 0x9c, 0x5e, 0x52,
 0x19, 
 0x69, 0x8d, 0x5b, 0x52, 0x29, 0x9c, 0x06, 0x6a, 0x5a, 0x32, 0x8f, 0x08, 
 0x45, 0x6c, 0x43, 0xb5, 0xac, 0xc3, 
0xbb, 0x90, 0x7b, 0xec,
 0xbb, 
 0x5d, 0x71, 0x25, 0x82, 0xf8, 0x40, 0xbf, 0x38, 0x00, 0x20, 0xf3, 0x8a, 
 0x38, 0x43, 0xde, 0x04, 0x41, 0x19, 
0x5f, 0xeb, 0xb0, 0x50,
 0x59, 
 0x10, 0xe1, 0x54, 0x62, 0x5c, 0x93, 0xd9, 0xdc, 0x63, 0x24, 0xd0, 0x17, 
 0x00, 0xc0, 0x44, 0x3e, 0xfc, 0xd1, 
0xda, 0x4b, 0x24, 0xf7,
 0xcb, 
 0x16, 0x35, 0xe6, 0x9f, 0x67, 0x96, 0x5f, 0xb0, 0x94, 0xde, 0xfa, 0xa1, 
 0xfd, 0x8c, 0x8a, 0xd1, 0x5c, 0x02, 
0x8d, 0xe0, 0xa0, 0xa0, 
 0x02, 
 0x1d, 0x56, 0xaf, 0x13, 0x3a, 0x65, 0x5e, 0x8e, 0xde, 0xd1, 0xa8, 0x28, 
 0x8b, 0x71, 0xc9, 0x65, 0x02, 0x81, 
0x81, 0x00, 0xc1, 0x0a, 
 0x47, 
 0x39, 0x91, 0x06, 0x1e, 0xb9, 0x43, 0x7c, 0x9e, 0x97, 0xc5, 0x09, 0x08, 
 0xbc, 0x22, 0x47, 0xe2, 0x96, 0x8e, 
0x1c, 0x74, 0x80, 0x50,
 0x6c, 
 0x9f, 0xef, 0x2f, 0xe5, 0x06, 0x3e, 0x73, 0x66, 0x76, 0x02, 0xbd, 0x9a, 
 0x1c, 0xfc, 0xf9, 0x6a, 0xb8, 0xf9, 
0x36, 0x15, 0xb5, 0x20,
 0x0b, 
 0x6b, 0x54, 0x83, 0x9c, 0x86, 0xba, 0x13, 0xb7, 0x99, 0x54, 0xa0, 0x93, 
 0x0d, 0xd6, 0x1e, 0xc1, 0x12, 0x72, 
0x0d, 0xea, 0xb0, 0x14,
 0x30, 
 0x70, 0x73, 0xef, 0x6b, 0x4c, 0xae, 0xb6, 0xff, 0xd4, 0xbb, 0x89, 0xa1, 
 0xec, 0xca, 0xa6, 0xe9, 0x95, 0x56, 
0xac, 0xe2, 0x9b, 0x97,
 0x2f, 
 0x2c, 0xdf, 0xa3, 0x6e, 0x59, 0xff, 0xcd, 0x3c, 0x6f, 0x57, 0xcc, 0x6e, 
 0x44, 0xc4, 0x27, 0xbf, 0xc3, 0xdd, 
0x19, 0x9e, 0x81, 0x16,
 0xe2, 
 0x8f, 0x65, 0x34, 0xa7, 0x0f, 0x22, 0xba, 0xbf, 0x79, 0x57, 0x02, 0x81, 
 0x80, 0x2e, 0x21, 0x0e, 0xc9, 0xb5, 
0xad, 0x31, 0xd4, 0x76,
 0x0f, 
 0x9b, 0x0f, 0x2e, 0x70, 0x33, 0x54, 0x03, 0x58, 0xa7, 0xf1, 0x6d, 0x35, 
 0x57, 0xbb, 0x53, 0x66, 0xb4, 0xb6, 
0x96, 0xa1, 0xea, 0xd9,
 0xcd, 
 0xe9, 0x23, 0x9f, 0x35, 0x17, 0xef, 0x5c, 0xb8, 0x59, 0xce, 0xb7, 0x3c, 
 0x35, 0xaa, 0x42, 0x82, 0x3f, 0x00, 
0x96, 0xd5, 0x9d, 0xc7,
 0xab, 
 0xec, 0xec, 0x04, 0xb5, 0x15, 0xc8, 0x40, 0xa4, 0x85, 0x9d, 0x20, 0x56, 
 0xaf, 0x03, 0x8f, 0x17, 0xb0, 0xf1, 
0x96, 0x22, 0x3a, 0xa5,
 0xfa, 
 0x58, 0x3b, 0x01, 0xf9, 0xae, 0xb3, 0x83, 0x6f, 0x44, 0xd3, 0x14, 0x2d, 
 0xb6, 0x6e, 0xd2, 0x9d, 0x39, 0x0c, 
0x12, 0x1d, 0x23, 0xea,
 0x19, 
 0xcb, 0xbb, 0xe0, 0xcd, 0x89, 0x15, 0x9a, 0xf5, 0xe4, 0xec, 0x41, 0x06, 
 0x30, 0x16, 0x58, 0xea, 0xfa, 0x31, 
0xc1, 0xb8, 0x8e, 0x08,
 0x84, 
 0xaa, 0x3b, 0x19, 0x02, 0x81, 0x80, 0x70, 0x4c, 0xf8, 0x6e, 0x86, 0xed, 
 0xd6, 0x85, 0xd4, 0xba, 0xf4, 0xd0, 
0x3a, 0x32, 0x2d, 0x40,
 0xb5, 
 0x78, 0xb8, 0x5a, 0xf9, 0xc5, 0x98, 0x08, 0xe5, 0xc0, 0xab, 0xb2, 0x4c, 
 0x5c, 0xa2, 0x2b, 0x46, 0x9b, 0x3e, 
0xe0, 0x0d, 0x49, 0x50,
 0xbf, 
 0xe2, 0xa1, 0xb1, 0x86, 0x59, 0x6e, 0x7b, 0x76, 0x6e, 0xee, 0x3b, 0xb6, 
 0x6d, 0x22, 0xfb, 0xb1, 0x68, 0xc7, 
0xec, 0xb1, 0x95, 0x9b,
 0x21, 
 0x0b, 0xb7, 0x2a, 0x71, 0xeb, 0xa2, 0xb2, 0x58, 0xac, 0x6d, 0x5f, 0x24, 
 0xd3, 0x79, 0x42, 0xd2, 0xf7, 0x35, 
0xdc, 0xfc, 0x0e, 0x95,
 0x60, 
 0xb7, 0x85, 0x7f, 0xf9, 0x72, 0x8e, 0x4a, 0x11, 0xc3, 0xc2, 0x09, 0x40, 
 0x5c, 0x7c, 0x43, 0x12, 0x34, 0xac, 
0x59, 0x99, 0x76, 0x34, 
 0xcf, 
 0x20, 0x88, 0xb0, 0xfb, 0x39, 0x62, 0x3a, 0x9b, 0x03, 0xa6, 0x84, 0x2c, 
 0x03, 0x5c, 0x0c, 0xca, 0x33, 0x85, 
0xf5, 0x02, 0x81, 0x80, 
 0x56, 
 0x99, 0xe9, 0x17, 0xdc, 0x33, 0xe1, 0x33, 0x8d, 0x5c, 0xba, 0x17, 0x32, 
 0xb7, 0x8c, 0xbd, 0x4b, 0x7f, 0x42, 
0x3a, 0x79, 0x90, 0xe3, 
 0x70, 
 0xe3, 0x27, 0xce, 0x22, 0x59, 0x02, 0xc0, 0xb1, 0x0e, 0x57, 0xf5, 0xdf, 
 0x07, 0xbf, 0xf8, 0x4e, 0x10, 0xef, 
0x2a, 0x62, 0x30, 0x03, 
 0xd4, 
 0x80, 0xcf, 0x20, 0x84, 0x25, 0x66, 0x3f, 0xc7, 0x4f, 0x56, 0x8c, 0x1e, 
 0xe1, 0x18, 0x91, 0xc1, 0xfd, 0x71, 
0x5f, 0x65, 0x9b, 0xe4, 
 0x4f, 
 0xe0, 0x1a, 0x3a, 0xf8, 0xc1, 0x69, 0xdb, 0xd3, 0xbb, 0x8d, 0x91, 0xd1, 
 0x11, 0x4f, 0x7e, 0x91, 0x1b, 0xb4, 
0x27, 0xa5, 0xab, 0x7c, 
 0x7b, 
 0x76, 0xd4, 0x78, 0xfe, 0x63, 0x44, 0x63, 0x7e, 0xe3, 0xa6, 0x60, 0x4f, 
 0xb9, 0x55, 0x28, 0xba, 0xba, 0x83, 
0x1a, 0x2d, 0x43, 0xd5, 
 0xf7, 
 0x2e, 0xe0, 0xfc, 0xa8, 0x14, 0x9b, 0x91, 0x2a, 0x36, 0xbf, 0xc7, 0x14
  };
CK_BYTE 
  knownRSA1Modulus[] 
 = {
0xb8, 0xb5, 0x0f, 0x49, 0x46, 0xb5, 0x5d, 0x58, 0x04, 0x8e, 
 0x52, 0x59, 0x39, 0xdf, 0xd6, 
0x29, 
0x45, 0x6b, 0x6c, 0x96, 0xbb, 0xab, 0xa5, 0x6f, 0x72, 0x1b, 
 0x16, 0x96, 0x74, 0xd5, 0xf9, 
0xb4, 
0x41, 0xa3, 0x7c, 0xe1, 0x94, 0x73, 0x4b, 0xa7, 0x23, 0xff, 
 0x61, 0xeb, 0xce, 0x5a, 0xe7, 
0x7f, 
0xe3, 0x74, 0xe8, 0x52, 0x5b, 0xd6, 0x5d, 0x5c, 0xdc, 0x98, 
 0x49, 0xfe, 0x51, 0xc2, 0x7e, 
0x8f, 
0x3b, 0x37, 0x5c, 0xb3, 0x11, 0xed, 0x85, 0x91, 0x15, 0x92, 
 0x24, 0xd8, 0xf1, 0x7b, 0x3d, 
0x2f, 
0x8b, 0xcd, 0x1b, 0x30, 0x14, 0xa3, 0x6b, 0x1b, 0x4d, 0x27, 
 0xff, 0x6a, 0x58, 0x84, 0x9e, 
0x79, 
0x94, 0xca, 0x78, 0x64, 0x01, 0x33, 0xc3, 0x58, 0xfc, 0xd3, 
 0x83, 0xeb, 0x2f, 0xab, 0x6f, 
0x85, 
0x5a, 0x38, 0x41, 0x3d, 0x73, 0x20, 0x1b, 0x82, 0xbc, 0x7e, 
 0x76, 0xde, 0x5c, 0xfe, 0x42, 
0xd6, 
0x7b, 0x86, 0x4f, 0x79, 0x78, 0x29, 0x82, 0x87, 0xa6, 0x24, 
 0x43, 0x39, 0x74, 0xfe, 0xf2, 
0x0c, 
0x08, 0xbe, 0xfa, 0x1e, 0x0a, 0x48, 0x6f, 0x14, 0x86, 0xc5, 
 0xcd, 0x9a, 0x98, 0x09, 0x2d, 
0xf3, 
0xf3, 0x5a, 0x7a, 0xa4, 0xe6, 0x8a, 0x2e, 0x49, 0x8a, 0xde, 
 0x73, 0xe9, 0x37, 0xa0, 0x5b, 
0xef, 
0xd0, 0xe0, 0x13, 0xac, 0x88, 0x5f, 0x59, 0x47, 0x96, 0x7f, 
 0x78, 0x18, 0x0e, 0x44, 0x6a, 
0x5d, 
0xec, 0x6e, 0xed, 0x4f, 0xf6, 0x6a, 0x7a, 0x58, 0x6b, 0xfe, 
 0x6c, 0x5a, 0xb9, 0xd2, 0x22, 
0x3a, 
0x1f, 0xdf, 0xc3, 0x09, 0x3f, 0x6b, 0x2e, 0xf1, 0x6d, 0xc3, 
 0xfb, 0x4e, 0xd4, 0xf2, 0xa3, 
0x94, 
0x13, 0xb0, 0xbf, 0x1e, 0x06, 0x2e, 0x29, 0x55, 0x00, 0xaa, 
 0x98, 0xd9, 0xe8, 0x77, 0x84, 
0x8b, 
0x3f, 0x5f, 0x5e, 0xf7, 0xf8, 0xa7, 0xe6, 0x02, 0xd2, 0x18, 
 0xb0, 0x52, 0xd0, 0x37, 0x2e, 
0x53, 
      },
      knownRSA1PubExponent[] 
 = { 0x01, 0x00, 0x01 };
      char 
 *pPlainData = 0;
      unsigned 
 long ulPlainDataLength;
      char 
 *pEncryptedData = 0;
      unsigned 
 long ulEncryptedDataLength = 0;
      CK_MECHANISM 
 mech;
      CK_USHORT 
   usStatus=0,
                  usKeyLength;
      CK_OBJECT_HANDLE 
 hKey;
      CK_OBJECT_CLASS 
    SymKeyClass 
  = CKO_SECRET_KEY;
      CK_BBOOL 
           bTrue 
 = 1,
                         bFalse 
 = 0,
                         bToken 
 = bTrue,
                         bSensitive 
 = bTrue,
                         bPrivate 
 = bTrue,
                         bEncrypt 
 = bTrue,
                         bDecrypt 
 = bTrue,
                         bSign 
 = bFalse, // "..."
                         bVerify 
 = bFalse, //Will not allow sign/verify operation.
                         bWrap 
 = bTrue,
                         bUnwrap 
 = bTrue,
#ifdef EXTRACTABLE
                         bExtract 
 = bTrue,
#endif //EXTRACTABLE
                         bDerive 
 = bTrue;
      CK_KEY_TYPE 
        keyType;
      CK_USHORT 
          usValueBits;
      char 
               pbPublicKeyLabel[128];
      CK_ATTRIBUTE_PTR 
 pPublicTemplate;
      CK_USHORT 
 usPublicTemplateSize = 0;
      char 
 iv[8] = { '1', '2', '3', '4', '5', '6', '7', '8' };
      CK_ATTRIBUTE 
 SymKeyTemplate[] = {
         {CKA_CLASS, 
 0, sizeof(SymKeyClass)},
         {CKA_KEY_TYPE, 
 0, sizeof(keyType)},
         {CKA_TOKEN, 
 0, sizeof(bToken)},
         {CKA_SENSITIVE, 
 0, sizeof(bSensitive)},
         {CKA_PRIVATE, 
 0, sizeof(bPrivate)},
         {CKA_ENCRYPT, 
 0, sizeof(bEncrypt)},
         {CKA_DECRYPT, 
 0, sizeof(bDecrypt)},
         {CKA_SIGN, 
 0, sizeof(bSign)},
         {CKA_VERIFY, 
 0, sizeof(bVerify)},
         {CKA_WRAP, 
 0, sizeof(bWrap)},
         {CKA_UNWRAP, 
 0, sizeof(bUnwrap)},
         {CKA_DERIVE, 
 0, sizeof(bDerive)},
         {CKA_VALUE_LEN,0, 
  sizeof(usKeyLength) 
 },
         {CKA_LABEL, 
 0, 0}  // 
 Always keep last!!!
#ifdef EXTRACTABLE      //Conditional 
 stuff must be at the end!!!!!
         {CKA_EXTRACTABLE, 
 0, sizeof(bExtract)},
#endif //EXTRACTABLE
      };
      CK_OBJECT_HANDLE 
 hUnWrappedKey, hPublicRSAKey;
      char 
             *pbWrappedKey;
      unsigned 
 long    ulWrappedKeySize;
      CK_OBJECT_CLASS 
  privateKey 
 = CKO_PRIVATE_KEY,
publicKey = CKO_PUBLIC_KEY;
      CK_KEY_TYPE 
      rsaType 
   = 
 CKK_RSA;
      CK_BYTE 
          pLabel[] 
  = "RSA 
 private Key",
pbPublicRSAKeyLabel[] = "RSA Public Key";
      CK_ATTRIBUTE 
 *pTemplate;
      CK_ULONG 
     usTemplateSize,
ulPublicRSAKeyTemplateSize;
      CK_ATTRIBUTE 
 pPublicRSAKeyTemplate[] = {
         {CKA_CLASS, 
    0, 
 sizeof(publicKey) },
         {CKA_KEY_TYPE, 
 0,    sizeof(rsaType) 
    },
         {CKA_TOKEN, 
    0, 
     sizeof(bToken) 
     },
         {CKA_PRIVATE, 
  0,   sizeof(bPrivate) 
   },
         {CKA_ENCRYPT, 
  0,   sizeof(bEncrypt) 
   },
         {CKA_VERIFY, 
   0, 
      sizeof(bSign) 
      },
         {CKA_WRAP, 
     0, 
      sizeof(bWrap) 
      },
 {CKA_MODULUS, 
 0, sizeof(knownRSA1Modulus) },
 {CKA_PUBLIC_EXPONENT, 
 0, sizeof(knownRSA1PubExponent) },
         {CKA_LABEL, 
    0, 
      sizeof(pbPublicRSAKeyLabel) 
     }
      };
      CK_ATTRIBUTE 
 pPrivateKeyTemplate[] = {
         {CKA_CLASS, 
    &privateKey, 
 sizeof(privateKey) },
         {CKA_KEY_TYPE, 
 &rsaType,    sizeof(rsaType) 
    },
         {CKA_TOKEN, 
    &bToken, 
     sizeof(bToken) 
     },
         {CKA_SENSITIVE,&bSensitive, 
 sizeof(bSensitive) },
         {CKA_PRIVATE, 
  &bPrivate, 
   sizeof(bPrivate) 
   },
         {CKA_DECRYPT, 
  &bEncrypt, 
   sizeof(bEncrypt) 
   },
         {CKA_SIGN, 
     &bSign, 
      sizeof(bSign) 
      },
 //{CKA_SIGN_RECOVER, 
 &bTrue, sizeof(bTrue)     },
         {CKA_UNWRAP, 
   &bWrap, 
      sizeof(bWrap) 
      },
{CKA_EXTRACTABLE, &bFalse, sizeof(bFalse)      },
{CKA_LABEL,       pLabel, 
  sizeof(pLabel) 
     }
      };
      // 
 Generate a DES3 Key
      SymKeyTemplate[0].pValue 
 = &SymKeyClass;
      SymKeyTemplate[1].pValue 
 = &keyType;
      SymKeyTemplate[2].pValue 
 = &bToken;
      SymKeyTemplate[3].pValue 
 = &bSensitive;
      SymKeyTemplate[4].pValue 
 = &bPrivate;
      SymKeyTemplate[5].pValue 
 = &bEncrypt;    
      SymKeyTemplate[6].pValue 
 = &bDecrypt;
      SymKeyTemplate[7].pValue 
 = &bSign;
      SymKeyTemplate[8].pValue 
 = &bVerify;
      SymKeyTemplate[9].pValue 
 = &bWrap;
      SymKeyTemplate[10].pValue 
 = &bUnwrap;
      SymKeyTemplate[11].pValue 
 = &bDerive;
      SymKeyTemplate[12].pValue 
 =  &usKeyLength;
      SymKeyTemplate[13].pValue 
 = pbPublicKeyLabel;
#ifdef EXTRACTABLE        
      SymKeyTemplate[14].pValue 
 = &bExtract;
#endif //EXTRACTABLE
      mech.mechanism 
 = CKM_DES3_KEY_GEN;
      mech.pParameter 
 = 0;
      mech.usParameterLen 
 = 0;
      keyType 
 = CKK_DES3;
      usKeyLength 
 = 24;
      strcpy( 
 pbPublicKeyLabel, "Generated DES3 Key" );
      pPublicTemplate 
 = SymKeyTemplate;
      usPublicTemplateSize 
 = DIM(SymKeyTemplate);
      // 
 Adjust size of label (ALWAYS LAST ENTRY IN ARRAY)
      pPublicTemplate[usPublicTemplateSize-1].usValueLen 
 = strlen( 
pbPublicKeyLabel );
      retCode 
 = C_GenerateKey(   hSessionHandle,
                                 (CK_MECHANISM_PTR)&mech,
                                 pPublicTemplate,
                                 usPublicTemplateSize,
                                 &hKey);
      if(retCode 
 == CKR_OK)
      {
         cout 
 << pbPublicKeyLabel << ": " << hKey << 
 endl;
      }
      else
      {
   cout 
 << "\n" "Error 0x" << hex << retCode;
         cout 
 << " generating the DES3 Key.\n";
   error 
 = -11;
         goto 
 exit_routine_6;
      }
      // 
 Encrypt the RSA Key
      mech.mechanism 
 = CKM_DES3_CBC;
      mech.pParameter 
 = iv;
      mech.usParameterLen 
 = sizeof(iv);
      pPlainData 
 = (char *)(pRsaKey);
      ulPlainDataLength 
 = sizeof(pRsaKey);
      // 
 Allocate memory for output buffer
      if( 
 retCode == CKR_OK )
      {
         pEncryptedData 
 = new char [ulPlainDataLength + 2048]; // Leave
// extra room for 
// RSA Operations
         if( 
 !pEncryptedData )
         {
            retCode 
 = CKR_DEVICE_ERROR;
         }
      }
      // 
 Start encrypting
      if( 
 retCode == CKR_OK )
      {
         retCode 
 = C_EncryptInit(hSessionHandle, &mech, hKey);
      }
      // 
 Continue encrypting
      if( 
 retCode == CKR_OK )
      {
         CK_USHORT 
 usInDataLen,
                   usOutDataLen 
 = (CK_USHORT) (ulPlainDataLength + 2048);
         CK_ULONG 
  ulBytesRemaining 
 = ulPlainDataLength;
         char 
 *    pPlainTextPointer 
 = pPlainData;
         char 
 *    pEncryptedDataPointer 
 = pEncryptedData; 
         while 
 (ulBytesRemaining > 0)
         {
            if 
 (ulBytesRemaining > 0xfff0) // We are longer than a USHORT can handle
            {
               usInDataLen 
 = 0xfff0;
               ulBytesRemaining 
 -= usInDataLen;
            }
            else
            {
               usInDataLen 
 = (CK_USHORT) ulBytesRemaining;
               ulBytesRemaining 
 -= usInDataLen;
            }
            retCode 
 = C_EncryptUpdate( hSessionHandle,
                                       (CK_BYTE_PTR)pPlainTextPointer,
                                       usInDataLen,
                                       (CK_BYTE_PTR)pEncryptedDataPointer,
                                       &usOutDataLen 
 );
            pPlainTextPointer 
 += usInDataLen;
            pEncryptedDataPointer 
 += usOutDataLen;
            ulEncryptedDataLength 
 += usOutDataLen;
         }
      } 
         
   
      // 
 Finish encrypting
      if( 
 retCode == CKR_OK )
      {
         CK_USHORT 
 usOutDataLen;
         CK_BYTE_PTR 
 pOutData = (CK_BYTE_PTR)pEncryptedData;
         pOutData 
 += ulEncryptedDataLength;
         retCode 
 = C_EncryptFinal(hSessionHandle, pOutData, &usOutDataLen);
         ulEncryptedDataLength 
 += usOutDataLen;
      }
      else
      {
   cout 
 << "\n" "Error 0x" << hex << retCode;
         cout 
 << " somewhere in the encrypting.\n";
         if( 
 pEncryptedData )
         {
            delete 
 pEncryptedData;
         }
   error 
 = -12;
         goto 
 exit_routine_6;
      }
      mech.mechanism 
      = 
 CKM_DES3_CBC;
      mech.pParameter 
     = 
 (void*) "12345678"; // 8 byte IV
      mech.usParameterLen 
 = 8;
      pTemplate 
 = pPrivateKeyTemplate;
      usTemplateSize 
 = DIM(pPrivateKeyTemplate);
     pbWrappedKey 
 = pEncryptedData;
      ulWrappedKeySize 
 = ulEncryptedDataLength;
      if( 
 retCode == CKR_OK )
      {
         retCode 
 = C_UnwrapKey( hSessionHandle,
                                 &mech,
                                 hKey,
                                 (CK_BYTE_PTR)pbWrappedKey,
                                 (CK_USHORT)ulWrappedKeySize,
                                 pTemplate,
                                 usTemplateSize,
                                 &hUnWrappedKey);
      }
      // 
 Report unwrapped key handle
      if( 
 retCode == CKR_OK )
      {
         cout 
 << "\n Private key Unwrapped key is:" << hUnWrappedKey 
 <<"\n\n";
      }
      else
      {
   cout 
 << "\n" "Error 0x" << hex << retCode;
         cout 
 << " unwrapping.\n";
         if( 
 pEncryptedData )
         {
            delete 
 pEncryptedData;
         }
   error 
 = -13;
         goto 
 exit_routine_6;
      }
      // 
 Release temporary memory
      if( 
 pEncryptedData )
      {
         delete 
 pEncryptedData;
      }
   // 
 Create the Public Key that goes with the Private Key
   if( 
 retCode == CKR_OK )
   {
  // 
 Unwrap it onto the token
  pPublicRSAKeyTemplate[0].pValue 
 = &publicKey;
  pPublicRSAKeyTemplate[1].pValue 
 = &rsaType;
  pPublicRSAKeyTemplate[2].pValue 
 = &bToken;
  pPublicRSAKeyTemplate[3].pValue 
 = &bPrivate;
  pPublicRSAKeyTemplate[4].pValue 
 = &bEncrypt;    
  pPublicRSAKeyTemplate[5].pValue 
 = &bSign;
  pPublicRSAKeyTemplate[6].pValue 
 = &bWrap;
  pPublicRSAKeyTemplate[7].pValue 
 = knownRSA1Modulus;
  pPublicRSAKeyTemplate[8].pValue 
 = knownRSA1PubExponent;
  pPublicRSAKeyTemplate[9].pValue 
 = pbPublicRSAKeyLabel;
  pTemplate 
 = pPublicRSAKeyTemplate;
  usTemplateSize 
 = DIM(pPublicRSAKeyTemplate);
  retCode 
 = C_CreateObject(  hSessionHandle,
pTemplate,
 usTemplateSize,
 &hPublicRSAKey);
  if(retCode 
 == CKR_OK)
  {
 cout 
 << pbPublicRSAKeyLabel << ": " << hPublicRSAKey 
 << endl;
  }
  else
  {
 cout 
 << "\n" "Error 0x" << hex << retCode;
 cout 
 << " creating the RSA Public Key.\n";
 error 
 = -14;
 goto 
 exit_routine_6;
  }
   }
if( retCode == CKR_OK )
   {
CK_CHAR label[] = "RSA Key";
CK_ATTRIBUTE RSAFindPriTemplate[] = 
{
CKA_LABEL, label, sizeof(label)
};
CK_ULONG numHandles;
CK_OBJECT_HANDLE handles[1000];
retCode = C_FindObjectsInit( hSessionHandle, RSAFindPriTemplate, 
 1 );
if(retCode != CKR_OK)
{
cout << "C_FindObjectsInit not returning OK (" 
 << hex << retCode << ")\n\n";
goto exit_routine_6;
}
retCode =C_FindObjects( hSessionHandle , handles, 90, 
&numHandles );
if(retCode != CKR_OK)
{
cout << "C_FindObjects not returning OK (" 
 << hex << 
retCode << ")\n\n";
goto exit_routine_6;
}
cout << "Everything's GOOD\n\n";
for(int i=0; i < numHandles; i++)
{
cout << handles[i] << "\n";
}
}
}
//CJM-> END OF TEST CODE
   // 
 Beginning of exit routines
exit_routine_6:
   // 
 Logout
   retCode 
 = C_Logout(hSessionHandle);
   if(retCode 
 != CKR_OK)
{
cout << "\n" "Error 0x" << 
 hex << retCode << " logging out.";
}
exit_routine_5:
// Close the session
   retCode 
 = C_CloseSession(hSessionHandle); 
if(retCode != CKR_OK)
{
cout << "\n" "Error 0x" << 
 hex << retCode << " closing session.";
}
exit_routine_4:
   delete 
 pSlotList;
exit_routine_3:
#ifdef PKCS11_2_0
   C_Finalize(0);
#else
   C_Terminate();
#endif
exit_routine_2:
#ifndef STATIC
   // 
 No longer need Chrystoki
   CrystokiDisconnect();
#endif
exit_routine_1:
   cout 
 << "\nDone. (" << dec << error << ")\n";
   cout.flush();
   return 
 error;
}
CK_RV  Pinlogin(CK_SESSION_HANDLE 
 hSession)
{
 
CK_RV retCode; 
unsigned char buffer[MAX];
int count =0;
cout << "Please enter the USER password : " 
 << endl;
//calling get PinString to mask input, variable "count" 
 
//holds length of "buffer"(password) 
//needed for Login call 
count = getPinString(buffer);
//Login as user on  token 
 in slot
retCode = C_Login(hSession, CKU_USER, buffer, count);
if(retCode != CKR_OK)
{
cout << "\n" "Error 0x" << 
 hex << retCode;
      cout 
 << " logging in as user.";
  exit(hSession);
  return 
 -3;
} 
cout << "logging into the token....";
cout << "\nlogged into token " << endl;
return retCode;
}
///////////////////////////////////////////////////////////////////////
// getPinString()
// ==============
//
// This function retrieves a pin string from the user.  It 
 modifies the
// console mode before starting so that the characters the 
 user types are
// not echoed, and a '*' character is displayed for each 
 typed character
// instead.
//
// Backspace is supported, but we don't get any fancier than 
 that.
////////////////////////////////////////////////////////////////////////
int getPinString(CK_CHAR_PTR pw) 
{
    int 
 len=0;
    char 
 c=0;
    // 
 Unfortunately, the method of turning off character echo is 
// different for Windows and Unix platforms.  So 
 we have to 
// conditionally compile the appropriate section.  Even 
 the basic
// password retrieval is slightly different, since
    // 
 Windows and Unix use different character codes for the return key.
#ifdef WIN32
    DWORD 
 mode;
    // 
 This console mode stuff only applies to windows.  We'll 
 have to 
// do something else when it comes to unix.
    if 
 (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode)) {
        if 
 (SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode & (!ENABLE_ECHO_INPUT))) 
 {
            while 
 (c  != '\r') 
 {
                // 
 wait for a character to be hit
                while 
 (!_kbhit()) {
                    Sleep(100);
                }
                // 
 get it
                c 
 = _getch();
                // 
 check for carriage return
                if 
 (c != '\r') {
                    // 
 check for backspace
                    if 
 (c!='\b') {
                        // 
 neither CR nor BS -- add it to the password string
                        printf("*");
                        *pw++ 
 = c;
                        len++;
                    } 
 else {
// handle backspace -- delete the last character & 
// erase it from the screen
                        if 
 (len > 0) {
                            pw--;
                            len--;
                            printf("\b 
 \b");
}
}
}
}
            // 
 Add the zero-termination
            *pw 
 = '\0';
            SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), 
 mode);
            printf("\n");
}
    }
#endif
    return 
 len;
}