/* ***************************************************************** *
 * Copyright 1998 International Business Machines Corporation. All   *
 * Rights Reserved.                                                  *
 *                                                                   *
 * Please read this carefully.  Your use of this reference           *
 * implementation of certain of the IETF public-key infrastructure   *
 * specifications ("Software") indicates your acceptance of the      *
 * following.  If you do not agree to the following, do not install  *
 * or use any of the Software.                                       *
 *                                                                   *
 * Permission to use, reproduce, distribute and create derivative    *
 * works from the Software ("Software Derivative Works"), and to     *
 * distribute such Software Derivative Works is hereby granted to    *
 * you by International Business Machines Corporation ("IBM").  This *
 * permission includes a license under the patents of IBM that are   *
 * necessarily infringed by your use of the Software as provided by  *
 * IBM.                                                              *
 *                                                                   *
 * IBM licenses the Software to you on an "AS IS" basis, without     *
 * warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL         *
 * WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,   *
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF       *
 * MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR    *
 * PURPOSE.  You are solely responsible for determining the          *
 * appropriateness of using this Software and assume all risks       *
 * associated with the use of this Software, including but not       *
 * limited to the risks of program errors, damage to or loss of      *
 * data, programs or equipment, and unavailability or interruption   *
 * of operations.                                                    *
 *                                                                   *
 * IBM WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, *
 * INCIDENTAL, OR  INDIRECT DAMAGES OR FOR ANY ECONOMIC              *
 * CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN   *
 * IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  IBM  *
 * will not be liable for the loss of, or damage to, your records or *
 * data, or any damages claimed by you based on a third party claim. *
 *                                                                   *
 * IBM wishes to obtain your feedback to assist in improving the     *
 * Software.  You grant IBM a world-wide, royalty-free right to use, *
 * copy, distribute, sublicense and prepare derivative works based   *
 * upon any feedback, including materials, error corrections,        *
 * Software Derivatives, enhancements, suggestions and the like that *
 * you provide to IBM relating to the Software (this does not        *
 * include products for which you charge a royalty and distribute to *
 * IBM under other terms and conditions).                            *
 *                                                                   *
 * You agree to distribute the Software and any Software Derivatives *
 * under a license agreement that: 1) is sufficient to notify all    *
 * licensees of the Software and Software Derivatives that IBM       *
 * assumes no liability for any claim that may arise regarding the   *
 * Software or Software Derivatives, and 2) that disclaims all       *
 * warranties, both express and implied, from IBM regarding the      *
 * Software and Software Derivatives.  (If you include this          *
 * Agreement with any distribution of the Software or Software       *
 * Derivatives you will have met this requirement.)  You agree that  *
 * you will not delete any copyright notices in the Software.        *
 *                                                                   *
 * This Agreement is the exclusive statement of your rights in the   *
 * Software as provided by IBM.   Except for the rights granted to   *
 * you in the second paragraph above, You are not granted any other  *
 * patent rights, including but not limited to the right to make     *
 * combinations of the Software with products that infringe IBM      *
 * patents. You agree to comply with all applicable laws and         *
 * regulations, including all export and import laws and regulation. *
 * This Agreement is governed by the laws of the State of New York.  *
 * This Agreement supersedes all other communications,               *
 * understandings or agreements we may have had prior to this        *
 * Agreement.                                                        *
 * ***************************************************************** */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <process.h>        
#include <signal.h>  

#include <cssmtype.h>
#include <platform.h>
#include <asnbase.h>
#include <scfunc.h>

/* Windows header files */
#include <windows.h>

/* PKCS#11 header files */
#include <pkcsjnh.h>

/* CDSA Memory functions */
#include <appmem.h>

/*------------------------ module prototypes ---------------------------------*/
void   CheckParameters(int, char **);

/*------------------------ module variables ----------------------------------*/
#define         idlen           4096
#define         concat(x,y)     #x y

int OPERATION   = 0;                         /* Operation                     */    
unsigned char addr[65];                      /* File Address                  */
CK_SLOT_ID            slot;                   /* Cryptoki Slot           */
CK_SESSION_HANDLE     shandle;                /* Cryptoki Session Handle */
  
/*============================================================================*/
/* Check command line parameters                                              */
/*============================================================================*/
void CheckParameters(int argc, char **argv)
{
  while (argc-- > 1)
  {
    if (*argv[argc]=='/' || *argv[argc]=='-' || *argv[argc]=='?')
    {
      switch (*++argv[argc])
      {
	case '1': OPERATION = 1; break;
	case '2': OPERATION = 2; break;
	case '3': OPERATION = 3; break;
      case '4': OPERATION = 4; break;
	case '5': OPERATION = 5; break;
	case '6': OPERATION = 6; break;
	case '7': OPERATION = 7; break;
	case '8': OPERATION = 8; break;
	case '9': OPERATION = 9; break;
	case 'A': OPERATION = 10; break;

	default:  puts("PKCSCLNT is the client side PKCS driver program.\n"
		       "Use /<option> or -<option> (case insensitive)\n"
			 " /1   : Initialize Smart Card\n"
			 " /2   : Set Security Officer Pin\n"
			 " /3   : Initialize User Pin (SO sets user pin)\n"
			 " /4   : Set User Pin (User sets own pin)\n"
			 " /5   : Store Key Pair\n"
			 " /6   : Retrieve Key Pair\n"
			 " /7   : Retrieve Latest Key Pair\n"
			 " /8   : See if token has been initialized\n"
			 " /9   : Create private key\n"
			 " /A  : Update keyslot\n");
		  exit(0);                                    
      }
    }
    /* This is for the name of the file containing data */
    else                                  
    {
      if (strlen(argv[argc])<=64)
      {
	strcpy((char *)&addr,argv[argc]);
      }
    } 
  }
}

/*============================================================================*/
int initcard(void * ptr)
{
    char                        pin[32];
    char				  newpin[32]; 
    uint32                       rv;

    DEBUG_MSG("Enter initcard\n");

    printf("Enter Current SO PIN\n");
    gets(pin);
    DEBUG_INFO("Current pin is %s\n", &pin);

    printf("Enter new SO PIN\n");
    gets(newpin);
    DEBUG_INFO("New pin is %s\n", &newpin);

    DEBUG_MSG("Calling routine to initialize card\n");
        rv = scInitializeCard((const char *)&pin, (const char *)&newpin);

    printf("rv from scInitializeCard = %x\n", rv);

    DEBUG_MSG("Exit inittoken\n");
    return 0;
}

/*============================================================================*/
int sopin(void * ptr)
{
    char                        cpin[32], npin[32];
    uint32                       rv;

    DEBUG_MSG("Enter sopin\n");

    printf("Enter current SO PIN\n");
    gets(cpin);
    DEBUG_INFO("Current pin is %s\n", &cpin);

    printf("Enter new SO PIN\n");
    gets(npin);
    DEBUG_INFO("New pin is %s\n", &npin);

    DEBUG_MSG("Calling routine to initialize SO Pin\n");
    rv = scChangeSOPin((const char *)&cpin, (const char *)&npin);

    printf("rv from = %x\n", rv);

    DEBUG_MSG("Exit sopin\n");
    return 0;
}


/*============================================================================*/
int userpin(void * ptr)
{
    char                        cpin[32], npin[32];
    uint32                       rv;

    DEBUG_MSG("Enter userpin\n");

    printf("Enter current User PIN\n");
    gets(cpin);
    DEBUG_INFO("Current pin is %s\n", &cpin);

    printf("Enter new User PIN\n");
    gets(npin);
    DEBUG_INFO("New pin is %s\n", &npin);

    DEBUG_MSG("Calling routine to initialize User Pin\n");
    rv = scChangeUserPin((const char *)&cpin, (const char *)&npin);

    printf("rv from = %x\n", rv);

    DEBUG_MSG("Exit userpin\n");
    return 0;
}

/*============================================================================*/
int setuserpin(void * ptr)
{
    char                        cpin[32], npin[32];
    uint32                       rv;

    DEBUG_MSG("Enter setuserpin\n");

    printf("Enter current SO PIN\n");
    gets(cpin);
    DEBUG_INFO("SO pin is %s\n", &cpin);

    printf("Enter new User PIN\n");
    gets(npin);
    DEBUG_INFO("New pin is %s\n", &npin);

    DEBUG_MSG("Calling routine to initialize User Pin\n");
    rv = scSetUserPin((const char *)&cpin, (const char *)&npin);

    printf("rv from = %x\n", rv);

    DEBUG_MSG("Exit setuserpin\n");
    return 0;
}

/*============================================================================*/
int pkstore(void * ptr)
{
    char                        pin[32];
    char				  subject[32];
    char 				  issuer[32];                        
    buffer_t                    key;
    buffer_t                    serial;
    int                         rv;
    CSSM_DATA           recordid;
    utf8String			  psubject = NULL_PTR;
    utf8String			  pissuer = NULL_PTR;
    uint32				  version = 1;

    DEBUG_MSG("Enter pkstore\n");

    printf("Enter PIN\n");
    gets(pin);
    DEBUG_INFO("Pin is %s\n", &pin);

    strcpy((char *)&subject, "SUBJECT\0");
    psubject = (utf8String)&subject;
    strcpy((char *)&issuer, "JONAHCA\0");
    pissuer = (utf8String)&issuer;
    key.append("ABCDEFGHIJ");
    serial.append("999888777");

    DEBUG_MSG("Calling routine to insert data\n");
    rv = scCreateCertificate(
	(char *)&pin, 
	psubject,
	pissuer,
	version,
	serial,
	key);

    printf("rv from scCreateCertificate = %x\n", rv);

    DEBUG_MSG("Exit pkstore\n");
    return 0;
}

/*============================================================================*/
int keypairstore(void * ptr)
{
    char                        pin[32];
    char				  subject[32];
    char 				  issuer[32];                        
    buffer_t                    key;
    buffer_t                    privkey;    
    buffer_t                    serial;
    int                         rv;
    CSSM_DATA           recordid;
    utf8String			  psubject = NULL_PTR;
    utf8String			  pissuer = NULL_PTR;
    uint32				  version = 1;

    DEBUG_MSG("Enter keypairstore\n");

    printf("Enter PIN\n");
    gets(pin);
    DEBUG_INFO("Pin is %s\n", &pin);
    printf("Enter version\n");
    scanf("%d", &version);
    DEBUG_INFO("Version is %d\n", version);

    strcpy((char *)&subject, "SUBJECT\0");
    psubject = (utf8String)&subject;
    strcpy((char *)&issuer, "JONAHCA\0");
    pissuer = (utf8String)&issuer;
    key.append("1234567890");
    privkey.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    serial.append("999888777");


    DEBUG_MSG("Calling routine to insert data\n");
    rv = scCreateKeySlot(
	(char *)&pin, 
	psubject,
	pissuer,
	version,
	serial,
	privkey,
	key);

    printf("rv from scCreateKeySlot = %x\n", rv);

    DEBUG_MSG("Exit keypairstore\n");
    return 0;
}


/*============================================================================*/
int keypairret(void * ptr)
{
    char                        pin[32];
    char				  subject[32];
    char 				  issuer[32];                        
    buffer_t                    key;
    buffer_t                    privkey;    
    buffer_t                    serial;
    int                         rv;
    CSSM_DATA           recordid;
    utf8String			  psubject = NULL_PTR;
    utf8String			  pissuer = NULL_PTR;
    uint32 				  version = 1;
    buffer_t * 			  pbuf; 

    DEBUG_MSG("Enter keypairret\n");

    printf("Enter PIN\n");
    gets(pin);
    DEBUG_INFO("Pin is %s\n", &pin);

    strcpy((char *)&subject, "SUBJECT\0");
    psubject = (utf8String)&subject;
    strcpy((char *)&issuer, "JONAHCA\0");
    pissuer = (utf8String)&issuer;
//    key.append("1234567890");
    privkey.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    serial.append("999888777");


    DEBUG_MSG("Calling routine to retrieve data\n");
    rv = scRetrieveKeySlot(
	(char *)&pin, 
	psubject,
	pissuer,
	version,
	&serial,
	&privkey,
	&key);

    printf("rv from scRetrieveSlot = %x\n", rv);

    pbuf = &key;
    printf("Public key buf = %s\n", pbuf->data);
    printf("Public key len = %d\n", pbuf->data_len);
    pbuf = &privkey;
    printf("Private key buf = %s\n", pbuf->data);
    printf("Private key len = %d\n", pbuf->data_len);

    DEBUG_MSG("Exit keypairret\n");
    return 0;
}

/*============================================================================*/
int latestkeypairret(void * ptr)
{
    char                        pin[32];
    char				  subject[32];
    char 				  issuer[32];                        
    buffer_t                    key;
    buffer_t                    privkey;    
    buffer_t                    serial;
    int                         rv;
    CSSM_DATA           recordid;
    utf8String			  psubject = NULL_PTR;
    utf8String			  pissuer = NULL_PTR;
    uint32 				  version = 0;
    buffer_t * 			  pbuf; 

    DEBUG_MSG("Enter keypairret\n");

    printf("Enter PIN\n");
    gets(pin);
    DEBUG_INFO("Pin is %s\n", &pin);

    strcpy((char *)&subject, "SUBJECT\0");
    psubject = (utf8String)&subject;
    strcpy((char *)&issuer, "JONAHCA\0");
    pissuer = (utf8String)&issuer;
//    key.append("1234567890");
    privkey.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    serial.append("999888777");


    DEBUG_MSG("Calling routine to retrieve data\n");
    rv = scRetrieveKeySlot(
	(char *)&pin, 
	psubject,
	pissuer,
	version,
	&serial,
	&privkey,
	&key);

    printf("rv from scRetrieveSlot = %x\n", rv);

    pbuf = &key;
    printf("Public key buf = %s\n", pbuf->data);
    printf("Public key len = %d\n", pbuf->data_len);
    pbuf = &privkey;
    printf("Private key buf = %s\n", pbuf->data);
    printf("Private key len = %d\n", pbuf->data_len);

    DEBUG_MSG("Exit keypairret\n");
    return 0;
}

/*============================================================================*/
int privatekeycreate(void * ptr)
{
    char                        pin[32];
    char				  subject[32];
    char 				  issuer[32];                        
    buffer_t                    key;
    buffer_t                    privkey;    
    buffer_t                    serial;
    int                         rv;
    CSSM_DATA           recordid;
    utf8String			  psubject = NULL_PTR;
    utf8String			  pissuer = NULL_PTR;
    uint32				  version = 1;

    DEBUG_MSG("Enter privatekeycreate\n");

    printf("Enter PIN\n");
    gets(pin);
    DEBUG_INFO("Pin is %s\n", &pin);
    printf("Enter version\n");
    scanf("%d", &version);
    DEBUG_INFO("Version is %d\n", version);

    strcpy((char *)&subject, "SUBJECT\0");
    psubject = (utf8String)&subject;
    strcpy((char *)&issuer, "JONAHCA\0");
    pissuer = (utf8String)&issuer;
//    key.append("1234567890");
    privkey.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
//    serial.append("999888777");


    DEBUG_MSG("Calling routine to create private key\n");
    rv = scCreateKeySlot(
	(char *)&pin, 
	psubject,
	pissuer,
	version,
	serial,
	privkey,
	key);

    printf("rv from scCreateKeySlot = %x\n", rv);

    DEBUG_MSG("Exit privatekeycreate\n");
    return 0;
}

/*============================================================================*/
int keypairupdate(void * ptr)
{
    char                        pin[32];
    char				  subject[32];
    char 				  issuer[32];                        
    buffer_t                    key;
    buffer_t                    privkey;    
    buffer_t                    serial;
    int                         rv;
    CSSM_DATA           recordid;
    utf8String			  psubject = NULL_PTR;
    utf8String			  pissuer = NULL_PTR;
    uint32				  version = 1;

    DEBUG_MSG("Enter keypairupdate\n");

    printf("Enter PIN\n");
    gets(pin);
    DEBUG_INFO("Pin is %s\n", &pin);
    printf("Enter version\n");
    scanf("%d", &version);
    DEBUG_INFO("Version is %d\n", version);

    strcpy((char *)&subject, "SUBJECT\0");
    psubject = (utf8String)&subject;
    strcpy((char *)&issuer, "JONAHCA\0");
    pissuer = (utf8String)&issuer;
    key.append("1234567890");
    privkey.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    serial.append("999888777");


    DEBUG_MSG("Calling routine to update data\n");
    rv = scUpdateKeySlot(
	(char *)&pin, 
	psubject,
	pissuer,
	version,
	serial,
	privkey,
	key);

    printf("rv from scUpdateKeySlot = %x\n", rv);

    DEBUG_MSG("Exit keypairupdate\n");
    return 0;
}

/*============================================================================*/
int istokeninitialized(void * ptr)
{

    DEBUG_MSG("Enter istokeninitialized\n");

    if (scIsTokenInitialized(NULL_PTR)) {
	printf("Token has been initialized\n");
    } else {
	printf("Token has not been initialized\n");
    }

    DEBUG_MSG("Exit istokeninitialized\n");
    return 0;
}

/*============================================================================*/
int main(int argc, char **argv)
{ 
  CK_RV                 rv;                     /* Cryptoki return values  */        
  CSSM_MEMORY_FUNCS mem = {
      app_malloc, 
      app_free, 
      app_realloc, 
      app_calloc,
      NULL};


  CheckParameters(argc, argv);               /* check command line parameters */

  rv = scInit(mem);

  switch (OPERATION)
  {
    case 1   : DEBUG_MSG("initcard\n"); rv = initcard(NULL);break;
    case 2   : DEBUG_MSG("sopin\n"); rv = sopin(NULL);break;
    case 3   : DEBUG_MSG("setuserpin\n"); rv = setuserpin(NULL);break;
    case 4   : DEBUG_MSG("userpin\n"); rv = userpin(NULL);break;
    case 5   : DEBUG_MSG("keypairstor\n"); rv = keypairstore(NULL); break;
    case 6   : DEBUG_MSG("keypairret\n"); rv = keypairret(NULL); break;
    case 7   : DEBUG_MSG("latestkeypairret\n"); rv = latestkeypairret(NULL); break;
    case 8   : DEBUG_MSG("istokeninitialized\n"); rv = istokeninitialized(NULL); break;
    case 9   : DEBUG_MSG("privatekeycreate\n"); rv = privatekeycreate(NULL); break;
    case 10  : DEBUG_MSG("keypairupdate\n"); rv = keypairupdate(NULL); break;

    default:  printf("EXIT:\n");
	      break;                                                                          
  }
  
  return 0;
}

