Exemple #1
0
int print_avail(int verbose)
{
    sc_context_t *ctx = NULL;

    int r;
    r = sc_establish_context(&ctx, "");
    if (r) {
        fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
        return 1;
    }
    ctx->debug = verbose;

    r = list_readers(ctx);

    if (ctx)
        sc_release_context(ctx);

    return r;
}
int main(int argc, char * const argv[])
{
	int err = 0, r, c, long_optind = 0;
	int do_list_readers = 0;
	int do_list_drivers = 0;
	int do_list_rdrivers = 0;
	int do_list_files = 0;
	int do_send_apdu = 0;
	int do_print_atr = 0;
	int do_print_serial = 0;
	int do_print_name = 0;
	int action_count = 0;
	const char *opt_driver = NULL;
	sc_context_param_t ctx_param;
		
	setbuf(stderr, NULL);
	setbuf(stdout, NULL);

	while (1) {
		c = getopt_long(argc, argv, "nlfr:vs:DRc:aw", options, &long_optind);
		if (c == -1)
			break;
		if (c == '?')
			print_usage_and_die(app_name, options, option_help);
		switch (c) {
		case 'l':
			do_list_readers = 1;
			action_count++;
			break;
		case 'D':
			do_list_drivers = 1;
			action_count++;
			break;
		case 'R':
			do_list_rdrivers = 1;
			action_count++;
			break;
		case 'f':
			do_list_files = 1;
			action_count++;
			break;
		case 's':
			opt_apdus = (char **) realloc(opt_apdus,
					(opt_apdu_count + 1) * sizeof(char *));
			opt_apdus[opt_apdu_count] = optarg;
			do_send_apdu++;
			if (opt_apdu_count == 0)
				action_count++;
			opt_apdu_count++;
			break;
		case 'a':
			do_print_atr = 1;
			action_count++;
			break;
		case 'n':
			do_print_name = 1;
			action_count++;
			break;
		case 'r':
			opt_reader = atoi(optarg);
			break;
		case 'v':
			verbose++;
			break;
		case 'c':
			opt_driver = optarg;
			break;
		case 'w':
			opt_wait = 1;
			break;
		case OPT_SERIAL:
			do_print_serial = 1;
			action_count++;
			break;
		}
	}
	if (action_count == 0)
		print_usage_and_die(app_name, options, option_help);

	memset(&ctx_param, 0, sizeof(ctx_param));
	ctx_param.ver      = 0;
	ctx_param.app_name = app_name;

	r = sc_context_create(&ctx, &ctx_param);
	if (r) {
		fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r));
		return 1;
	}
	if (verbose > 1)
		ctx->debug = verbose-1;
	if (do_list_rdrivers) {
		if ((err = list_reader_drivers()))
			goto end;
		action_count--;
	}
	if (do_list_readers) {
		if ((err = list_readers()))
			goto end;
		action_count--;
	}
	if (do_list_drivers) {
		if ((err = list_drivers()))
			goto end;
		action_count--;
	}
	if (action_count <= 0)
		goto end;

	if (opt_driver != NULL) {
		err = sc_set_card_driver(ctx, opt_driver);
		if (err) {
			fprintf(stderr, "Driver '%s' not found!\n", opt_driver);
			err = 1;
			goto end;
		}
	}

	err = connect_card(ctx, &card, opt_reader, 0, opt_wait, verbose);
	if (err)
		goto end;

	if (do_print_atr) {
		if (verbose) {
			printf("Card ATR:\n");
			hex_dump_asc(stdout, card->atr, card->atr_len, -1);		
		} else {
			char tmp[SC_MAX_ATR_SIZE*3];
			sc_bin_to_hex(card->atr, card->atr_len, tmp, sizeof(tmp) - 1, ':');
			fprintf(stdout,"%s\n",tmp);
		}
		action_count--;
	}
	if (do_print_serial) {
		if (verbose)
			printf("Card serial number:");
		print_serial(card);
		action_count--;
	}
	if (do_print_name) {
		if (verbose)
			printf("Card name: ");
		printf("%s\n", card->name);
		action_count--;
	}
	if (do_send_apdu) {
		if ((err = send_apdu()))
			goto end;
		action_count--;
	}
	
	if (do_list_files) {
		if ((err = list_files()))
			goto end;
		action_count--;
	}
end:
	if (card) {
		sc_unlock(card);
		sc_disconnect_card(card, 0);
	}
	if (ctx)
		sc_release_context(ctx);
	return err;
}
Exemple #3
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;
}
Exemple #4
0
static int handleCommands(FILE *fd)
{
    char buf[BUFLEN + 1], commandLine[BUFLEN + 1];
    int rv = EXIT_SUCCESS, i;
    char *token;
    OptionStr optionStr;

    while (fgets (buf, BUFLEN, fd) != NULL) {

	// copy command line for printing it out later
	strncpy (commandLine, buf, BUFLEN);

	token = strtokCheckComment(buf);
	while (token != NULL) {
	    if (token[0] == '#' || strncmp (token, "//", 2) == 0)
		break;

	    // print command line
	    printf ("%s", commandLine);

	    if (strcmp(token, "establish_context") == 0) {
		// Establish context
		rv = establish_context(&cardContext);
		if (rv != OPGP_ERROR_SUCCESS) {
		    printf ("establish_context failed with error 0x%08X\n", rv);
			rv = EXIT_FAILURE;
			goto end;
		}
		break;
	    } else if (strcmp(token, "release_context") == 0) {
		// Release context
		rv = release_context(cardContext);
		if (rv != OPGP_ERROR_SUCCESS) {
		    printf ("release_context failed with error 0x%08X\n", rv);
			rv = EXIT_FAILURE;
			goto end;
		}

		break;
	    } else if (strcmp(token, "card_connect") == 0) {
		TCHAR buf[BUFLEN + 1];
		DWORD readerStrLen = BUFLEN;
		// open reader
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		if (_tcslen(optionStr.reader) == 0) {
			int j=0;
			int k=0;

			// get all readers
		    rv = list_readers (cardContext, buf, &readerStrLen);

			for (j=0; j<(int)readerStrLen;) {
				/* Check for end of readers */
				if (buf[j] == _T('\0'))
					break;
				_tcsncpy(optionStr.reader, buf+j, READERNAMELEN+1);
				if (k == optionStr.readerNumber)
					break;
				k++;
				j+=(int)_tcslen(buf+j)+1;
			}
			optionStr.reader[READERNAMELEN] = _T('\0');

#ifdef DEBUG
		    _tprintf ( _T("* reader name %s\n"), optionStr.reader);
#endif
		}

		rv = card_connect (cardContext, optionStr.reader,
				   &cardInfo, optionStr.protocol);

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

		break;
	    } if (strcmp(token, "open_sc") == 0) {
		// open secure channel
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		if (platform_mode == PLATFORM_MODE_OP_201) {
			if (gemXpressoPro) {
				rv = GemXpressoPro_create_daughter_keys(cardInfo, optionStr.key,  
								 optionStr.enc_key, optionStr.mac_key, optionStr.kek_key);
				if (rv != 0) {
					_tprintf (_T("GemXpressoPro_create_daughter_keys() returns 0x%08X (%s)\n"),
						rv, stringify_error(rv));
					rv = EXIT_FAILURE;
					goto end;
				}
			}
		    rv = OP201_mutual_authentication(cardInfo,
						     optionStr.enc_key,
						     optionStr.mac_key,
							 optionStr.kek_key,
						     optionStr.keySetVersion,
						     optionStr.keyIndex,
						     optionStr.securityLevel,
						     &securityInfo201);
		} else if (platform_mode == PLATFORM_MODE_GP_211) {
			if (optionStr.scp == 0 || optionStr.scpImpl == 0) {
				rv = GP211_get_secure_channel_protocol_details(cardInfo,
					&optionStr.scp,
					&optionStr.scpImpl);
				if (rv != 0) {
					_tprintf (_T("GP211_get_secure_channel_protocol_details() returns 0x%08X (%s)\n"),
						rv, stringify_error(rv));
					rv = EXIT_FAILURE;
					goto end;
				}
			}

		    rv = GP211_mutual_authentication(cardInfo,
						     optionStr.key,
						     optionStr.enc_key,
						     optionStr.mac_key,
						     optionStr.kek_key,
						     optionStr.keySetVersion,
						     optionStr.keyIndex,
						     optionStr.scp,
						     optionStr.scpImpl,
						     optionStr.securityLevel,
						     &securityInfo211);

		}

		if (rv != 0) {
		    _tprintf (_T("mutual_authentication() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
			rv = EXIT_FAILURE;
			goto end;
		}

		break;
	    } else if (strcmp(token, "select") == 0) {
		// select instance
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		rv = select_application (cardInfo,
                                         (PBYTE)optionStr.AID, optionStr.AIDLen);
		if (rv != 0) {
		    _tprintf (_T("select_application() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
			rv = EXIT_FAILURE;
			goto end;
		}
		break;
	    } else if (strcmp(token, "getdata") == 0) {
		// Get Data
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		// TODO: get data
		break;
	    } else if (strcmp(token, "load") == 0) {
		// Load Applet
		DWORD receiptDataLen = 0;
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		if (platform_mode == PLATFORM_MODE_OP_201) {
		    rv = OP201_load(cardInfo, &securityInfo201,
				    NULL, 0,
				    optionStr.file,
				    NULL, &receiptDataLen);
		} else if (platform_mode == PLATFORM_MODE_GP_211) {
		    rv = GP211_load(cardInfo, &securityInfo211,
				    NULL, 0,
				    optionStr.file,
				    NULL, &receiptDataLen);
		}

		if (rv != 0) {
		    _tprintf (_T("load_applet() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
			rv = EXIT_FAILURE;
			goto end;
		}

		break;
	    }  else if (strcmp(token, "delete") == 0) {
		// Delete Applet
		OPGP_AID AIDs[1];

		DWORD receiptLen = 10;

		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		memcpy (AIDs[0].AID, optionStr.AID, optionStr.AIDLen);
		AIDs[0].AIDLength = optionStr.AIDLen;

		if (platform_mode == PLATFORM_MODE_OP_201) {
		    OP201_RECEIPT_DATA receipt[10];
		    rv = OP201_delete_application(cardInfo, &securityInfo201,
					      AIDs, 1,
					      (OP201_RECEIPT_DATA *)receipt,
					      &receiptLen);
		} else if (platform_mode == PLATFORM_MODE_GP_211) {
		    GP211_RECEIPT_DATA receipt[10];
		    rv = GP211_delete_application(cardInfo, &securityInfo211,
						  AIDs, 1,
						  (GP211_RECEIPT_DATA *)receipt,
						  &receiptLen);

		}

		if (rv != 0) {
		    _tprintf (_T("delete_applet() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
		}
		break;
	    }

	    else if (strcmp(token, "install") == 0) {
			// One step install
			OPGP_LOAD_FILE_PARAMETERS loadFileParams;
			DWORD receiptDataAvailable = 0;
			DWORD receiptDataLen = 0;
			char installParam[1];
			installParam[0] = 0;

			rv = handleOptions(&optionStr);
			if (rv != EXIT_SUCCESS) {
				goto end;
			}
			rv = read_executable_load_file_parameters(optionStr.file, &loadFileParams);
			if (rv != EXIT_SUCCESS) {
				_tprintf (_T("read_executable_load_file_parameters() returns 0x%08X (%s)\n"),
					rv, stringify_error(rv));
				rv = EXIT_FAILURE;
				goto end;
			}
			if (optionStr.pkgAIDLen == 0) {
				optionStr.pkgAIDLen = loadFileParams.loadFileAID.AIDLength;
				memcpy(optionStr.pkgAID, loadFileParams.loadFileAID.AID, optionStr.pkgAIDLen);
			}
			if (optionStr.AIDLen == 0) {
				optionStr.AIDLen = loadFileParams.appletAIDs[0].AIDLength;
				memcpy(optionStr.AID, loadFileParams.appletAIDs[0].AID, optionStr.AIDLen);
			}
			if (optionStr.instAIDLen == 0) {
				optionStr.instAIDLen = loadFileParams.appletAIDs[0].AIDLength;
				memcpy(optionStr.instAID, loadFileParams.appletAIDs[0].AID, optionStr.instAIDLen);
			}
			if (optionStr.nvCodeLimit == 0) {
				optionStr.nvCodeLimit = loadFileParams.loadFileSize;
			}
			if (platform_mode == PLATFORM_MODE_OP_201) {
				if (optionStr.sdAIDLen == 0) {
					optionStr.sdAIDLen = sizeof(OP201_CARD_MANAGER_AID);
					memcpy(optionStr.sdAID, OP201_CARD_MANAGER_AID, optionStr.sdAIDLen);
				}
				rv = OP201_install_for_load(cardInfo, &securityInfo201,
							(PBYTE)optionStr.pkgAID, optionStr.pkgAIDLen,
							(PBYTE)optionStr.sdAID, optionStr.sdAIDLen,
						NULL, NULL,
						optionStr.nvCodeLimit,
						0,
						0);
			} else if (platform_mode == PLATFORM_MODE_GP_211) {
				if (optionStr.sdAIDLen == 0) {
					optionStr.sdAIDLen = sizeof(GP211_CARD_MANAGER_AID);
					memcpy(optionStr.sdAID, GP211_CARD_MANAGER_AID, optionStr.sdAIDLen);
				}
				rv = GP211_install_for_load(cardInfo, &securityInfo211,
							(PBYTE)optionStr.pkgAID, optionStr.pkgAIDLen,
							(PBYTE)optionStr.sdAID, optionStr.sdAIDLen,
							NULL, NULL,
							optionStr.nvCodeLimit,
							optionStr.nvDataLimit,
							optionStr.vDataLimit);
			}

			if (rv != 0) {
				_tprintf (_T("install_for_load() returns 0x%08X (%s)\n"),
					rv, stringify_error(rv));
				rv = EXIT_FAILURE;
				goto end;
			}
			if (platform_mode == PLATFORM_MODE_OP_201) {
				rv = OP201_load(cardInfo, &securityInfo201,
						NULL, 0,
						optionStr.file,
						NULL, &receiptDataLen);
			} else if (platform_mode == PLATFORM_MODE_GP_211) {
				rv = GP211_load(cardInfo, &securityInfo211,
						NULL, 0,
						optionStr.file,
						NULL, &receiptDataLen);
			}

			if (rv != 0) {
				_tprintf (_T("load_applet() returns 0x%08X (%s)\n"),
					rv, stringify_error(rv));
				rv = EXIT_FAILURE;
				goto end;
			}

			if (platform_mode == PLATFORM_MODE_OP_201) {
				OP201_RECEIPT_DATA receipt;
				rv = OP201_install_for_install_and_make_selectable(
							cardInfo, &securityInfo201,
						(PBYTE)optionStr.pkgAID, optionStr.pkgAIDLen,
						(PBYTE)optionStr.AID, optionStr.AIDLen,
						(PBYTE)optionStr.instAID, optionStr.instAIDLen,
						optionStr.privilege,
						optionStr.vDataLimit,
						optionStr.nvDataLimit,
											(PBYTE)optionStr.instParam,
						optionStr.instParamLen,
						NULL, // No install token
						&receipt,
						&receiptDataAvailable);
			} else if (platform_mode == PLATFORM_MODE_GP_211) {
				GP211_RECEIPT_DATA receipt;

				rv = GP211_install_for_install_and_make_selectable(
						cardInfo, &securityInfo211,
						(PBYTE)optionStr.pkgAID, optionStr.pkgAIDLen,
						(PBYTE)optionStr.AID, optionStr.AIDLen,
						(PBYTE)optionStr.instAID, optionStr.instAIDLen,
						optionStr.privilege,
						optionStr.vDataLimit,
						optionStr.nvDataLimit,
											(PBYTE)optionStr.instParam,
						optionStr.instParamLen,
						NULL, // No install token
						&receipt,
						&receiptDataAvailable);
			}

			if (rv != 0) {
				_tprintf (_T("install_for_install_and_make_selectable() returns 0x%08X (%s)\n"),
					rv, stringify_error(rv));
				rv = EXIT_FAILURE;
				goto end;
			}
			break;
		}
	    else if (strcmp(token, "install_for_load") == 0) {
		// Install for Load
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		if (platform_mode == PLATFORM_MODE_OP_201) {
			if (optionStr.sdAIDLen == 0) {
				optionStr.sdAIDLen = sizeof(OP201_CARD_MANAGER_AID);
				memcpy(optionStr.sdAID, OP201_CARD_MANAGER_AID, optionStr.sdAIDLen);
			}
			rv = OP201_install_for_load(cardInfo, &securityInfo201,
                        (PBYTE)optionStr.pkgAID, optionStr.pkgAIDLen,
                        (PBYTE)optionStr.sdAID, optionStr.sdAIDLen,
				      NULL, NULL,
				      optionStr.nvCodeLimit,
				      optionStr.nvDataLimit,
				      optionStr.vDataLimit);
		} else if (platform_mode == PLATFORM_MODE_GP_211) {
			if (optionStr.sdAIDLen == 0) {
				optionStr.sdAIDLen = sizeof(GP211_CARD_MANAGER_AID);
				memcpy(optionStr.sdAID, GP211_CARD_MANAGER_AID, optionStr.sdAIDLen);
			}
			rv = GP211_install_for_load(cardInfo, &securityInfo211,
                        (PBYTE)optionStr.pkgAID, optionStr.pkgAIDLen,
                        (PBYTE)optionStr.sdAID, optionStr.sdAIDLen,
					    NULL, NULL,
					    optionStr.nvCodeLimit,
					    optionStr.nvDataLimit,
					    optionStr.vDataLimit);
		}

		if (rv != 0) {
		    _tprintf (_T("install_for_load() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
			rv = EXIT_FAILURE;
			goto end;
		}
		break;
	    } else if (strcmp(token, "install_for_install") == 0) {


		DWORD receiptDataAvailable = 0;
		char installParam[1];
		installParam[0] = 0;

		// Install for Install
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		if (platform_mode == PLATFORM_MODE_OP_201) {
		    OP201_RECEIPT_DATA receipt;
		    rv = OP201_install_for_install_and_make_selectable(
				         cardInfo, &securityInfo201,
                    (PBYTE)optionStr.pkgAID, optionStr.pkgAIDLen,
                    (PBYTE)optionStr.AID, optionStr.AIDLen,
                    (PBYTE)optionStr.instAID, optionStr.instAIDLen,
					 optionStr.privilege,
					 optionStr.vDataLimit,
					 optionStr.nvDataLimit,
                                         (PBYTE)optionStr.instParam,
					 optionStr.instParamLen,
					 NULL, // No install token
					 &receipt,
					 &receiptDataAvailable);
		} else if (platform_mode == PLATFORM_MODE_GP_211) {
		    GP211_RECEIPT_DATA receipt;

		    rv = GP211_install_for_install_and_make_selectable(
					cardInfo, &securityInfo211,
                    (PBYTE)optionStr.pkgAID, optionStr.pkgAIDLen,
                    (PBYTE)optionStr.AID, optionStr.AIDLen,
                    (PBYTE)optionStr.instAID, optionStr.instAIDLen,
					optionStr.privilege,
					optionStr.vDataLimit,
					optionStr.nvDataLimit,
                                        (PBYTE)optionStr.instParam,
					optionStr.instParamLen,
					NULL, // No install token
					&receipt,
					&receiptDataAvailable);
		}

		if (rv != 0) {
		    _tprintf (_T("install_for_install_and_make_selectable() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
			rv = EXIT_FAILURE;
			goto end;
		}

		break;
	    } else if (strcmp(token, "card_disconnect") == 0) {
		// disconnect card
		card_disconnect(cardInfo);

		break;
	    } else if (strcmp(token, "put_sc_key") == 0) {
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		if (platform_mode == PLATFORM_MODE_OP_201) {
		    rv = OP201_put_secure_channel_keys(cardInfo, &securityInfo201,
						       optionStr.keySetVersion,
						       optionStr.newKeySetVersion,
						       optionStr.enc_key,
						       optionStr.mac_key,
						       optionStr.kek_key,
						       optionStr.current_kek);
		} else if (platform_mode == PLATFORM_MODE_GP_211) {
		    rv = GP211_put_secure_channel_keys(cardInfo,
						       &securityInfo211,
						       optionStr.keySetVersion,
						       optionStr.newKeySetVersion,
						       NULL,
						       optionStr.enc_key,
						       optionStr.mac_key,
						       optionStr.kek_key);
		}

		if (rv != 0) {
		    _tprintf (_T("put_secure_channel_keys() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
			rv = EXIT_FAILURE;
			goto end;
		}
		break;
	    } else if (strcmp(token, "get_status") == 0) {
#define NUM_APPLICATIONS 64
		DWORD numData = NUM_APPLICATIONS;

		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		if (platform_mode == PLATFORM_MODE_OP_201) {
		    OP201_APPLICATION_DATA data[NUM_APPLICATIONS];
		    rv = OP201_get_status(cardInfo, &securityInfo201,
				      optionStr.element,
				      data,
				      &numData);

		    if (rv != 0) {
			_tprintf (_T("OP201_get_status() returns 0x%08X (%s)\n"),
				  rv, stringify_error(rv));
				rv = EXIT_FAILURE;
				goto end;
		    }
#ifdef DEBUG
		    printf ("OP201_get_status() returned %d items\n", numData);
#endif
		    printf ("\nList of applets (AID state privileges)\n");
		    for (i=0; i<(int)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);
		    }
		} else if (platform_mode == PLATFORM_MODE_GP_211) {
                  GP211_APPLICATION_DATA appData[NUM_APPLICATIONS];
                  GP211_EXECUTABLE_MODULES_DATA execData[NUM_APPLICATIONS];
		    rv = GP211_get_status(cardInfo, &securityInfo211,
                                          optionStr.element,
					  appData,
					  execData,
					  &numData);

		    if (rv != 0) {
				_tprintf (_T("GP211_get_status() returns 0x%08X (%s)\n"),
				  rv, stringify_error(rv));
				rv = EXIT_FAILURE;
				goto end;
		    }
#ifdef DEBUG
		    printf ("GP211_get_status() returned %d items\n", numData);
#endif
		    printf ("\nList of applets (AID state privileges)\n");
		    for (i=0; i<(int)numData; i++) {
			int j;

			for (j=0; j<appData[i].AIDLength; j++) {
			    printf ("%02x", appData[i].AID[j]);
			}

			printf ("\t%x", appData[i].lifeCycleState);
			printf ("\t%x\n", appData[i].privileges);
		    }
		}
		if (rv != 0) {
		    _tprintf (_T("get_status() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
			rv = EXIT_FAILURE;
			goto end;
		}


		break;
	    } else if (strcmp(token, "send_apdu") == 0) {
		unsigned char recvAPDU[257];
                DWORD recvAPDULen = 257;
                int i;
		// Install for Load
		rv = handleOptions(&optionStr);
		if (rv != EXIT_SUCCESS) {
			goto end;
		}
		printf ("Send APDU: ");
		for (i=0; i<optionStr.APDULen; i++)
		    printf ("%02X ", optionStr.APDU[i] & 0xFF);
		printf ("\n");

		if (platform_mode == PLATFORM_MODE_OP_201) {
		    rv = OP201_send_APDU(cardInfo,
				     (optionStr.secureChannel == 0 ? NULL : &securityInfo201),
				     (PBYTE)(optionStr.APDU), optionStr.APDULen,
				     recvAPDU, &recvAPDULen);
		} else if (platform_mode == PLATFORM_MODE_GP_211) {
		    rv = GP211_send_APDU(cardInfo,
				     (optionStr.secureChannel == 0 ? NULL : &securityInfo211),
					 (PBYTE)(optionStr.APDU), optionStr.APDULen,
				     recvAPDU, &recvAPDULen);
		}
		if (rv != 0) {
		    _tprintf (_T("send_APDU() returns 0x%08X (%s)\n"),
			      rv, stringify_error(rv));
			rv = EXIT_FAILURE;
			goto end;
		}

		printf ("Recv APDU: ");
		for (i=0; i<(int)recvAPDULen; i++)
		    printf ("%02x ", recvAPDU[i]);
		printf ("\n");

		break;
	    } else if (strcmp(token, "mode_201") == 0) {
			platform_mode = PLATFORM_MODE_OP_201;
	    } else if (strcmp(token, "mode_211") == 0) {
			platform_mode = PLATFORM_MODE_GP_211;
	    } else if (strcmp(token, "enable_trace") == 0) {
			enableTraceMode(OPGP_TRACE_MODE_ENABLE, NULL);
	    } else if (strcmp(token, "gemXpressoPro") == 0) {
			gemXpressoPro = 1;
	    }

	    else {
			printf ("Unknown command %s\n", token);
			rv = EXIT_FAILURE;
			goto end;
	    }

	    token = strtokCheckComment(NULL);
	}
    }
end:
    return rv;
}