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 SafeNet ProtectToolkit-C, so a NULL_PTR is used as the argument.
3.The function call to CT_ErrorString is part of the SafeNet ProtectToolkit-C extended capability within CTLUTIL.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 SafeNet ProtectToolkit-C functionality within CTLUTIL.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;