/* ** 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; } }
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; }