Assembling the Application

1.Now bring all the required components for the fcrypt application together in the main application body.

#undef FN 
#define FN "main:" 
int main(int argc, char ** argv)
{  CK_RV rv; int err = 0;char * arg;char * sender = NULL; /* provides signing key */char * recipient = NULL; /* provides encryption key */char * ofile = "file.enc"; /* default output file name 
*/ printf( "Cryptoki File Encryption $Revision: 1.1 $\n" );printf( "Copyright (c) SafeNet, Inc 1999-2006\n" ); 

2.The first call within a PKCS#11 application must be C_Initialize, which initializes the PKCS#11 library.  The function takes as an argument either value NULL_PTR or points to a CK_C_INITIALIZE_ARGS structure containing information on how the library should deal with multi-threaded access - no threading information is required for ProtectToolkit-C, so a NULL_PTR is used as the argument.

3.The function call to CT_ErrorString is part of the ProtectToolkit-C extended capability within ctutil.h and converts a PKCS#11 error code into a printable string.

/* This must be the first PKCS#11 call made */
rv = C_Initialize(NULL_PTR);
if ( rv ) { C_ErrorString(rv,ErrorString,sizeof(ErrorString));fprintf(stderr, "C_Initialize error %x, %s\n", rv,ErrorString);}

4.Since Thales supports versions of PKCS#11 that are incompatible with one another, the CheckCryptokiVersion function is called to ensure that an application compiled for V1.X compliance is not going to fail if it links against a V 2.X-compliant DLL and vice versa. This function is part of the extended ProtectToolkit-C functionality within ctutil.h and ensures that the version of PKCS#11 is correct.

/* Check PKCS#11 version */
rv = CheckCryptokiVersion();
if ( rv ) {printf( "Incompatible PKCS#11 version (0x%x)\n", rv ); return -1; } /* process command line arguments */
for ( argv++; (arg = *argv) != NULL; argv++ ) {
if ( arg[0] == '-' || arg[0] == '/' ) {
switch( arg[1] ) {
case 'd':
dflag = 1;break; case 't':
  tflag = 1;
break;
case 'o':
  ofile = arg+2;
break;
case 's':
  sender = arg+2;
break;
case 'r':
  recipient = arg+2;
break;
case 'p': recipient = sender = arg+2;  pflag = 1; break; default:
usage();
  return 1;
}
}
else {
time_t now, t1, t2; /* we will time the     operation */ if ( sender == NULL || recipient == NULL ) {usage();  return 2; } if ( tflag ) {/* Mark the time now */for ( t1 = now = time(NULL); now == t1; )    t1 = time(NULL); } /* process the file */if ( dflag )err = decryptFile( sender, recipient, arg,ofile );else err = encryptFile( sender, recipient, arg,ofile ); /* report error or timing */if ( err ) {fprintf(stderr, "Error %scrypting file     %s\n", dflag?"de":"en", arg ); }else if ( tflag ) {   t2 = time(NULL);
  printf("%d seconds\n", t2-t1);
}
}
}
/* shut down PKCS#11 operations */

5.When the application is done using PKCS#11, it calls the PKCS#11 function C_Finalize and ceases to be a PKCS#11 application. It should be the last PKCS#11 call made by an application. The parameter is reserved for future versions and should be set to NULL_PTR.

rv = C_Finalize(NULL_PTR);
if ( rv ) {C_ErrorString(rv,ErrorString,sizeof(ErrorString));fprintf(stderr, "C_Finalize error %x, %s\n", rv,
ErrorString);
} return err;