/*
** Main OS routine calling all subfunctions. After sending the ATR it waits
** for incoming APDUs, which will then be processed by subfunctions
*/
int main (void)
{

  unsigned char result, cnt;

  command_APDU rec_APDU;        /* struct for command APDU */
  command_APDU *p_rec_APDU;     /* pointer to a command APDU */
  response_APDU res_APDU;       /* struct for response APDU */
  response_APDU *p_res_APDU;    /* pointer to a command APDU */

  p_rec_APDU = &rec_APDU;
  p_res_APDU = &res_APDU;


  for (cnt = 0; cnt < 50; cnt++) {
  }; /* wait before transmitting ATR (at least 400 cycles) */

  transmit_ATR ();              /* transmit the Answer to Reset */


  /* endless loop to receive and process commands */
  for (;;) {
    result = receive_APDU (p_rec_APDU);    /* receive APDU according to T=1 */

    if (result != OK) {            /* check for EDC checksum error */
      (*p_res_APDU).NAD = rec_APDU.NAD;
      (*p_res_APDU).PCB = rec_APDU.PCB;
      (*p_res_APDU).LEN = 2;
      (*p_res_APDU).LE = 0;
      (*p_res_APDU).SW1 = 0x67;    /* checksum error */
      (*p_res_APDU).SW2 = 0x00;
    }
    else {
      command_Handler (p_rec_APDU, p_res_APDU);    /* Call command handler  */
    }
    send_APDU (p_res_APDU);        /* transmit response APDU according to T=1 */

    /* Reset response and receive APDU */
    (*p_res_APDU).NAD = 0x00;
    (*p_res_APDU).PCB = 0x00;
    (*p_res_APDU).LEN = 2;
    (*p_res_APDU).LE = 0;
    (*p_res_APDU).SW1 = 0x64;    /* error w/o changing EEPROM */
    (*p_res_APDU).SW2 = 0x00;

    (*p_rec_APDU).NAD = 0x00;
    (*p_rec_APDU).PCB = 0x00;
    (*p_rec_APDU).LEN = 0;
    (*p_rec_APDU).LE = 0;
    (*p_rec_APDU).LC = 0;
    (*p_rec_APDU).CLA = 0x00;
    (*p_rec_APDU).INS = 0x00;
  }
}
Beispiel #2
0
int handleCommands(FILE *fd)
{
    BYTE buf[BUFLEN + 1];
    int rv = 0, i;
    char *token;
    OptionStr optionStr;

    while (fgets (buf, BUFLEN, fd) != NULL) {	
	token = strtokCheckComment(buf);
	while (token != NULL) {
	    if (token[0] == '#' || strncmp (token, "//", 2) == 0)
		break;
	    if (strcmp(token, "establish_context") == 0) {
		// Establish context
		rv = establish_context(&cardContext);
		if (rv != OPSP_ERROR_SUCCESS) {
		    printf ("establish_context failed with error %d\n", rv);
		    exit (1);
		}
		break;
	    } else if (strcmp(token, "release_context") == 0) {
		// Release context
		rv = release_context(cardContext);
		if (rv != OPSP_ERROR_SUCCESS) {
		    printf ("release_context failed with error %d\n", rv);
		    exit (1);
		}

		break;
	    } else if (strcmp(token, "card_connect") == 0) {
		TCHAR buf[BUFLEN + 1];
		DWORD readerStrLen = BUFLEN;
		// open reader
		handleOptions(&optionStr);
#ifdef DEBUG
		printf ("optionStr.reader %d\n", optionStr.reader);
#endif
		if (optionStr.reader == NULL) {	
		    // get the first reader
		    rv = list_readers (cardContext, buf, &readerStrLen);

		    optionStr.reader = buf;
#ifdef DEBUG
		    _tprintf ( _T("reader name %s\n"), optionStr.reader);
#endif
		}
		
		rv = card_connect (cardContext, optionStr.reader,
				   &cardHandle, optionStr.protocol);

		if (rv != 0) {
		    _tprintf (_T("card_connect() returns %d (%s)\n"), rv,
			      stringify_error(rv));
		}

		rv = get_card_status (cardHandle, &cardInfo);
		if (rv != 0) {
		    _tprintf (_T("get_card_status() returns %d (%s)\n"), rv,
			      stringify_error(rv));
		    exit (1);
		}
		
		break;
	    } if (strcmp(token, "open_sc") == 0) {
		// open secure channel
		handleOptions(&optionStr);
		/*for (i=0; i<TDES_KEY_LEN; i++) {
		  printf ("%02x ", optionStr.key[i]);
		  }*/
		rv = mutual_authentication(cardHandle,
					   optionStr.enc_key,
					   optionStr.mac_key,
					   optionStr.keySetVersion,
					   optionStr.keyIndex,
					   cardInfo,
					   optionStr.securityLevel,
					   &securityInfo);
		if (rv != 0) {
		    _tprintf (_T("mutual_authentication() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		    exit (1);
		}
					       
		break;
	    } else if (strcmp(token, "select") == 0) {
		// select instance
		handleOptions(&optionStr);
		rv = select_application (cardHandle, cardInfo,
					 optionStr.AID, optionStr.AIDLen);
		if (rv != 0) {
		    _tprintf (_T("select_application() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		    exit (1);
		}
		break;
	    } else if (strcmp(token, "getdata") == 0) {
		// Get Data
		handleOptions(&optionStr);
		// TODO: get data
		break;
	    } else if (strcmp(token, "load") == 0) {
		// Load Applet
		DWORD receiptDataLen = 0;
		handleOptions(&optionStr);

		rv = load_applet(cardHandle, &securityInfo, cardInfo,
				 NULL, 0, optionStr.file,
				 NULL, &receiptDataLen);
		if (rv != 0) {
		    _tprintf (_T("load_applet() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		    exit (1);
		}

		break;
	    }  else if (strcmp(token, "delete") == 0) {
		// Delete Applet
		OPSP_AID AIDs[1];
		OPSP_RECEIPT_DATA receipt[10];
		DWORD receiptLen = 10;
		    
		handleOptions(&optionStr);
		memcpy (AIDs[0].AID, optionStr.AID, optionStr.AIDLen);
		AIDs[0].AIDLength = optionStr.AIDLen;

		rv = delete_applet(cardHandle, &securityInfo,
				   cardInfo,
				   AIDs, 1,
                                   (OPSP_RECEIPT_DATA **)&receipt, &receiptLen);

		if (rv != 0) {
		    _tprintf (_T("delete_applet() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		}
		break;
	    }
    
	    else if (strcmp(token, "install_for_load") == 0) {
		// Install for Load
		handleOptions(&optionStr);

		rv = install_for_load(cardHandle, &securityInfo,
				      cardInfo,
				      optionStr.AID, optionStr.AIDLen,
				      optionStr.sdAID, optionStr.sdAIDLen,
				      NULL, NULL,
				      optionStr.nvCodeLimit,
				      optionStr.nvDataLimit,
				      optionStr.vDataLimit);
				      
		if (rv != 0) {
		    _tprintf (_T("install_for_load() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		    exit (1);
		}
		break;
	    } else if (strcmp(token, "install_for_install") == 0) {
		OPSP_RECEIPT_DATA receipt;
		DWORD receiptDataAvailable = 0;
		char installParam[1];
		installParam[0] = 0;

		// Install for Install
		handleOptions(&optionStr);
		
		rv = install_for_install_and_make_selectable(
					 cardHandle, &securityInfo,
					 cardInfo,
					 optionStr.pkgAID, optionStr.pkgAIDLen,
					 optionStr.AID, optionStr.AIDLen,
					 optionStr.instAID, optionStr.instAIDLen,
					 OPSP_APPLICATION_PRIVILEGE_PIN_CHANGE_PRIVILEGE, // 
					 optionStr.vDataLimit,
					 optionStr.nvDataLimit,
					 optionStr.instParam,
					 optionStr.instParamLen, 
					 NULL, // No install token
					 &receipt,
					 &receiptDataAvailable);

		if (rv != 0) {
		    _tprintf (_T("install_for_install_and_make_selectable() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		    exit (1);
		}
		break;
	    } else if (strcmp(token, "card_disconnect") == 0) {
		// disconnect card
		card_disconnect(cardHandle);

		break;
	    } else if (strcmp(token, "put_sc_key") == 0) {
		handleOptions(&optionStr);

		rv = put_secure_channel_keys(cardHandle, &securityInfo,
					     cardInfo,
					     optionStr.keySetVersion,
					     optionStr.newKeySetVersion,
					     optionStr.enc_key,
					     optionStr.mac_key,
					     optionStr.kek_key,
					     optionStr.current_kek);
		
		if (rv != 0) {
		    _tprintf (_T("put_secure_channel_keys() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		    exit (1);
		}
		break;
	    } else if (strcmp(token, "get_status") == 0) {
#define NUM_APPLICATIONS 64
		OPSP_APPLICATION_DATA data[NUM_APPLICATIONS];
		DWORD numData = NUM_APPLICATIONS;

		handleOptions(&optionStr);
		
		rv = get_status(cardHandle, &securityInfo, cardInfo,
				optionStr.element,
				data,
				&numData);
		if (rv != 0) {
		    _tprintf (_T("get_status() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		    exit (1);
		}
#ifdef DEBUG
		printf ("get_status() returned %d items\n", numData);
#endif
		printf ("\nList of applets (AID state privileges)\n");
		for (i=0; i<numData; i++) {
		    int j;
		    
		    for (j=0; j<data[i].AIDLength; j++) {
			printf ("%02x", data[i].AID[j]);
		    }

		    printf ("\t%x", data[i].lifeCycleState);
		    printf ("\t%x\n", data[i].privileges);
		}
		
		break;
	    } else if (strcmp(token, "send_apdu") == 0) {
		unsigned char recvAPDU[257];
		int recvAPDULen = 257, i;
		// Install for Load
		handleOptions(&optionStr);

		printf ("Send APDU: ");
		for (i=0; i<optionStr.APDULen; i++)
		    printf ("%02x ", optionStr.APDU[i]);
		printf ("\n");
		
		rv = send_APDU(cardHandle, 
			       optionStr.APDU, optionStr.APDULen, 
			       recvAPDU, &recvAPDULen,
			       cardInfo,
			       (optionStr.secureChannel == 0 ? NULL : &securityInfo));
		if (rv != 0) {
		    _tprintf (_T("send_APDU() returns %d (%s)\n"),
			      rv, stringify_error(rv));
		    exit (1);
		}

		printf ("Recv APDU: ");
		for (i=0; i<recvAPDULen; i++)
		    printf ("%02x ", recvAPDU[i]);
		printf ("\n");
		
		break;
	    } else {
		printf ("Unknown command %s\n", token);
		exit (1);
	    }

	    token = strtokCheckComment(NULL);
	}
    }

    return rv;
}