added showing apdu response codes
authormerlokk <olegmsn@gmail.com>
Tue, 31 Oct 2017 16:14:32 +0000 (18:14 +0200)
committermerlokk <olegmsn@gmail.com>
Tue, 31 Oct 2017 16:14:32 +0000 (18:14 +0200)
client/Makefile
client/cmdhf14a.c
client/cmdhf14a.h
client/emv/apduinfo.c [new file with mode: 0644]
client/emv/apduinfo.h [new file with mode: 0644]
client/obj/emv/.dummy [new file with mode: 0644]

index 3a96e9e928bccb59795f29f4f56b56566e52d3e7..8e1574d4558a390e68385edfb0099b02cc9fdd27 100644 (file)
@@ -107,6 +107,7 @@ CMDSRCS =   crapto1/crapto1.c\
                        ui.c \
                        cmddata.c \
                        lfdemod.c \
+                       emv/apduinfo.c\
                        cmdhf.c \
                        cmdhf14a.c \
                        cmdhf14b.c \
index f6ed899ae44e3dba4358178193528beba77322fc..6d6ea8549a7cb9cbcae78ecf6f0f2c75cdb6db65 100644 (file)
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// 2011, Merlok
+// 2011, 2017 Merlok
 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
 //
 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
@@ -685,7 +685,7 @@ int CmdHF14AAPDU(const char *cmd) {
 
        PrintAndLog("<<<< %s", sprint_hex(data, datalen));
        
-       PrintAndLog("APDU response: %02x %02x", data[datalen - 2], data[datalen - 1]); // TODO add APDU descriptions
+       PrintAndLog("APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); 
 
        // here TLV decoder...
        if (decodeTLV) {
index 407cf07dec907ce8ecfbe2acc4eebd314b97cc1e..919ece5ab607870bf52c50eda060cbe3f9b52464 100644 (file)
@@ -30,6 +30,7 @@
 #include "mifare.h"
 #include "cmdhfmfu.h"
 #include "mifarehost.h"
+#include "emv/apduinfo.h"
 
 // structure and database for uid -> tagtype lookups 
 typedef struct { 
diff --git a/client/emv/apduinfo.c b/client/emv/apduinfo.c
new file mode 100644 (file)
index 0000000..e2e51d9
--- /dev/null
@@ -0,0 +1,304 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2017 Merlok
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// APDU status bytes information
+//-----------------------------------------------------------------------------
+
+#include "apduinfo.h"
+
+const APDUCode APDUCodeTable[] = {
+       //  ID             Type                  Description
+       {"XXXX",        APDUCODE_TYPE_NONE,                     ""}, // blank string
+       {"6---",        APDUCODE_TYPE_ERROR,            "Class not supported."},
+       {"61--",        APDUCODE_TYPE_INFO,                     "Response bytes still available"},
+       {"61XX",        APDUCODE_TYPE_INFO,                     "Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE."},
+       {"62--",        APDUCODE_TYPE_WARNING,          "State of non-volatile memory unchanged"},
+       {"6200",        APDUCODE_TYPE_WARNING,          "No information given (NV-Ram not changed)"},
+       {"6201",        APDUCODE_TYPE_WARNING,          "NV-Ram not changed 1."},
+       {"6281",        APDUCODE_TYPE_WARNING,          "Part of returned data may be corrupted"},
+       {"6282",        APDUCODE_TYPE_WARNING,          "End of file/record reached before reading Le bytes"},
+       {"6283",        APDUCODE_TYPE_WARNING,          "Selected file invalidated"},
+       {"6284",        APDUCODE_TYPE_WARNING,          "Selected file is not valid. FCI not formated according to ISO"},
+       {"6285",        APDUCODE_TYPE_WARNING,          "No input data available from a sensor on the card. No Purse Engine enslaved for R3bc"},
+       {"62A2",        APDUCODE_TYPE_WARNING,          "Wrong R-MAC"},
+       {"62A4",        APDUCODE_TYPE_WARNING,          "Card locked (during reset( ))"},
+       {"62CX",        APDUCODE_TYPE_WARNING,          "Counter with value x (command dependent)"},
+       {"62F1",        APDUCODE_TYPE_WARNING,          "Wrong C-MAC"},
+       {"62F3",        APDUCODE_TYPE_WARNING,          "Internal reset"},
+       {"62F5",        APDUCODE_TYPE_WARNING,          "Default agent locked"},
+       {"62F7",        APDUCODE_TYPE_WARNING,          "Cardholder locked"},
+       {"62F8",        APDUCODE_TYPE_WARNING,          "Basement is current agent"},
+       {"62F9",        APDUCODE_TYPE_WARNING,          "CALC Key Set not unblocked"},
+       {"62FX",        APDUCODE_TYPE_WARNING,          "-"},
+       {"62XX",        APDUCODE_TYPE_WARNING,          "RFU"},
+       {"63--",        APDUCODE_TYPE_WARNING,          "State of non-volatile memory changed"},
+       {"6300",        APDUCODE_TYPE_WARNING,          "No information given (NV-Ram changed)"},
+       {"6381",        APDUCODE_TYPE_WARNING,          "File filled up by the last write. Loading/updating is not allowed."},
+       {"6382",        APDUCODE_TYPE_WARNING,          "Card key not supported."},
+       {"6383",        APDUCODE_TYPE_WARNING,          "Reader key not supported."},
+       {"6384",        APDUCODE_TYPE_WARNING,          "Plaintext transmission not supported."},
+       {"6385",        APDUCODE_TYPE_WARNING,          "Secured transmission not supported."},
+       {"6386",        APDUCODE_TYPE_WARNING,          "Volatile memory is not available."},
+       {"6387",        APDUCODE_TYPE_WARNING,          "Non-volatile memory is not available."},
+       {"6388",        APDUCODE_TYPE_WARNING,          "Key number not valid."},
+       {"6389",        APDUCODE_TYPE_WARNING,          "Key length is not correct."},
+       {"63C0",        APDUCODE_TYPE_WARNING,          "Verify fail, no try left."},
+       {"63C1",        APDUCODE_TYPE_WARNING,          "Verify fail, 1 try left."},
+       {"63C2",        APDUCODE_TYPE_WARNING,          "Verify fail, 2 tries left."},
+       {"63C3",        APDUCODE_TYPE_WARNING,          "Verify fail, 3 tries left."},
+       {"63CX",        APDUCODE_TYPE_WARNING,          "The counter has reached the value 'x' (0 = x = 15) (command dependent)."},
+       {"63F1",        APDUCODE_TYPE_WARNING,          "More data expected."},
+       {"63F2",        APDUCODE_TYPE_WARNING,          "More data expected and proactive command pending."},
+       {"63FX",        APDUCODE_TYPE_WARNING,          "-"},
+       {"63XX",        APDUCODE_TYPE_WARNING,          "RFU"},
+       {"64--",        APDUCODE_TYPE_ERROR,            "State of non-volatile memory unchanged"},
+       {"6400",        APDUCODE_TYPE_ERROR,            "No information given (NV-Ram not changed)"},
+       {"6401",        APDUCODE_TYPE_ERROR,            "Command timeout. Immediate response required by the card."},
+       {"64XX",        APDUCODE_TYPE_ERROR,            "RFU"},
+       {"65--",        APDUCODE_TYPE_ERROR,            "State of non-volatile memory changed"},
+       {"6500",        APDUCODE_TYPE_ERROR,            "No information given"},
+       {"6501",        APDUCODE_TYPE_ERROR,            "Write error. Memory failure. There have been problems in writing or reading the EEPROM. Other hardware problems may also bring this error."},
+       {"6581",        APDUCODE_TYPE_ERROR,            "Memory failure"},
+       {"65FX",        APDUCODE_TYPE_ERROR,            "-"},
+       {"65XX",        APDUCODE_TYPE_ERROR,            "RFU"},
+       {"66--",        APDUCODE_TYPE_SECURITY,         " "},
+       {"6600",        APDUCODE_TYPE_SECURITY,         "Error while receiving (timeout)"},
+       {"6601",        APDUCODE_TYPE_SECURITY,         "Error while receiving (character parity error)"},
+       {"6602",        APDUCODE_TYPE_SECURITY,         "Wrong checksum"},
+       {"6603",        APDUCODE_TYPE_SECURITY,         "The current DF file without FCI"},
+       {"6604",        APDUCODE_TYPE_SECURITY,         "No SF or KF under the current DF"},
+       {"6669",        APDUCODE_TYPE_SECURITY,         "Incorrect Encryption/Decryption Padding"},
+       {"66XX",        APDUCODE_TYPE_SECURITY,         "-"},
+       {"67--",        APDUCODE_TYPE_ERROR,            " "},
+       {"6700",        APDUCODE_TYPE_ERROR,            "Wrong length"},
+       {"67XX",        APDUCODE_TYPE_ERROR,            "length incorrect (procedure)(ISO 7816-3)"},
+       {"68--",        APDUCODE_TYPE_ERROR,            "Functions in CLA not supported"},
+       {"6800",        APDUCODE_TYPE_ERROR,            "No information given (The request function is not supported by the card)"},
+       {"6881",        APDUCODE_TYPE_ERROR,            "Logical channel not supported"},
+       {"6882",        APDUCODE_TYPE_ERROR,            "Secure messaging not supported"},
+       {"6883",        APDUCODE_TYPE_ERROR,            "Last command of the chain expected"},
+       {"6884",        APDUCODE_TYPE_ERROR,            "Command chaining not supported"},
+       {"68FX",        APDUCODE_TYPE_ERROR,            "-"},
+       {"68XX",        APDUCODE_TYPE_ERROR,            "RFU"},
+       {"69--",        APDUCODE_TYPE_ERROR,            "Command not allowed"},
+       {"6900",        APDUCODE_TYPE_ERROR,            "No information given (Command not allowed)"},
+       {"6901",        APDUCODE_TYPE_ERROR,            "Command not accepted (inactive state)"},
+       {"6981",        APDUCODE_TYPE_ERROR,            "Command incompatible with file structure"},
+       {"6982",        APDUCODE_TYPE_ERROR,            "Security condition not satisfied."},
+       {"6983",        APDUCODE_TYPE_ERROR,            "Authentication method blocked"},
+       {"6984",        APDUCODE_TYPE_ERROR,            "Referenced data reversibly blocked (invalidated)"},
+       {"6985",        APDUCODE_TYPE_ERROR,            "Conditions of use not satisfied."},
+       {"6986",        APDUCODE_TYPE_ERROR,            "Command not allowed (no current EF)"},
+       {"6987",        APDUCODE_TYPE_ERROR,            "Expected secure messaging (SM) object missing"},
+       {"6988",        APDUCODE_TYPE_ERROR,            "Incorrect secure messaging (SM) data object"},
+       {"698D",        APDUCODE_TYPE_NONE,             "Reserved"},
+       {"6996",        APDUCODE_TYPE_ERROR,            "Data must be updated again"},
+       {"69E1",        APDUCODE_TYPE_ERROR,            "POL1 of the currently Enabled Profile prevents this action."},
+       {"69F0",        APDUCODE_TYPE_ERROR,            "Permission Denied"},
+       {"69F1",        APDUCODE_TYPE_ERROR,            "Permission Denied - Missing Privilege"},
+       {"69FX",        APDUCODE_TYPE_ERROR,            "-"},
+       {"69XX",        APDUCODE_TYPE_ERROR,            "RFU"},
+       {"6A--",        APDUCODE_TYPE_ERROR,            "Wrong parameter(s) P1-P2"},
+       {"6A00",        APDUCODE_TYPE_ERROR,            "No information given (Bytes P1 and/or P2 are incorrect)"},
+       {"6A80",        APDUCODE_TYPE_ERROR,            "The parameters in the data field are incorrect."},
+       {"6A81",        APDUCODE_TYPE_ERROR,            "Function not supported"},
+       {"6A82",        APDUCODE_TYPE_ERROR,            "File not found"},
+       {"6A83",        APDUCODE_TYPE_ERROR,            "Record not found"},
+       {"6A84",        APDUCODE_TYPE_ERROR,            "There is insufficient memory space in record or file"},
+       {"6A85",        APDUCODE_TYPE_ERROR,            "Lc inconsistent with TLV structure"},
+       {"6A86",        APDUCODE_TYPE_ERROR,            "Incorrect P1 or P2 parameter."},
+       {"6A87",        APDUCODE_TYPE_ERROR,            "Lc inconsistent with P1-P2"},
+       {"6A88",        APDUCODE_TYPE_ERROR,            "Referenced data not found"},
+       {"6A89",        APDUCODE_TYPE_ERROR,            "File already exists"},
+       {"6A8A",        APDUCODE_TYPE_ERROR,            "DF name already exists."},
+       {"6AF0",        APDUCODE_TYPE_ERROR,            "Wrong parameter value"},
+       {"6AFX",        APDUCODE_TYPE_ERROR,            "-"},
+       {"6AXX",        APDUCODE_TYPE_ERROR,            "RFU"},
+       {"6B--",        APDUCODE_TYPE_ERROR,            " "},
+       {"6B00",        APDUCODE_TYPE_ERROR,            "Wrong parameter(s) P1-P2"},
+       {"6BXX",        APDUCODE_TYPE_ERROR,            "Reference incorrect (procedure byte), (ISO 7816-3)"},
+       {"6C--",        APDUCODE_TYPE_ERROR,            "Wrong length Le"},
+       {"6C00",        APDUCODE_TYPE_ERROR,            "Incorrect P3 length."},
+       {"6CXX",        APDUCODE_TYPE_ERROR,            "Bad length value in Le; 'xx' is the correct exact Le"},
+       {"6D--",        APDUCODE_TYPE_ERROR,            " "},
+       {"6D00",        APDUCODE_TYPE_ERROR,            "Instruction code not supported or invalid"},
+       {"6DXX",        APDUCODE_TYPE_ERROR,            "Instruction code not programmed or invalid (procedure byte), (ISO 7816-3)"},
+       {"6E--",        APDUCODE_TYPE_ERROR,            " "},
+       {"6E00",        APDUCODE_TYPE_ERROR,            "Class not supported"},
+       {"6EXX",        APDUCODE_TYPE_ERROR,            "Instruction class not supported (procedure byte), (ISO 7816-3)"},
+       {"6F--",        APDUCODE_TYPE_ERROR,            "Internal exception"},
+       {"6F00",        APDUCODE_TYPE_ERROR,            "Command aborted - more exact diagnosis not possible (e.g., operating system error)."},
+       {"6FFF",        APDUCODE_TYPE_ERROR,            "Card dead (overuse, \85)"},
+       {"6FXX",        APDUCODE_TYPE_ERROR,            "No precise diagnosis (procedure byte), (ISO 7816-3)"},
+       {"9---",        APDUCODE_TYPE_NONE,             ""},
+       {"9000",        APDUCODE_TYPE_INFO,                     "Command successfully executed (OK)."},
+       {"9004",        APDUCODE_TYPE_WARNING,          "PIN not succesfully verified, 3 or more PIN tries left"},
+       {"9008",        APDUCODE_TYPE_NONE,             "Key/file not found"},
+       {"9080",        APDUCODE_TYPE_WARNING,          "Unblock Try Counter has reached zero"},
+       {"9100",        APDUCODE_TYPE_NONE,             "OK"},
+       {"9101",        APDUCODE_TYPE_NONE,             "States.activity, States.lock Status or States.lockable has wrong value"},
+       {"9102",        APDUCODE_TYPE_NONE,             "Transaction number reached its limit"},
+       {"910C",        APDUCODE_TYPE_NONE,             "No changes"},
+       {"910E",        APDUCODE_TYPE_NONE,             "Insufficient NV-Memory to complete command"},
+       {"911C",        APDUCODE_TYPE_NONE,             "Command code not supported"},
+       {"911E",        APDUCODE_TYPE_NONE,             "CRC or MAC does not match data"},
+       {"9140",        APDUCODE_TYPE_NONE,             "Invalid key number specified"},
+       {"917E",        APDUCODE_TYPE_NONE,             "Length of command string invalid"},
+       {"919D",        APDUCODE_TYPE_NONE,             "Not allow the requested command"},
+       {"919E",        APDUCODE_TYPE_NONE,             "Value of the parameter invalid"},
+       {"91A0",        APDUCODE_TYPE_NONE,             "Requested AID not present on PICC"},
+       {"91A1",        APDUCODE_TYPE_NONE,             "Unrecoverable error within application"},
+       {"91AE",        APDUCODE_TYPE_NONE,             "Authentication status does not allow the requested command"},
+       {"91AF",        APDUCODE_TYPE_NONE,             "Additional data frame is expected to be sent"},
+       {"91BE",        APDUCODE_TYPE_NONE,             "Out of boundary"},
+       {"91C1",        APDUCODE_TYPE_NONE,             "Unrecoverable error within PICC"},
+       {"91CA",        APDUCODE_TYPE_NONE,             "Previous Command was not fully completed"},
+       {"91CD",        APDUCODE_TYPE_NONE,             "PICC was disabled by an unrecoverable error"},
+       {"91CE",        APDUCODE_TYPE_NONE,             "Number of Applications limited to 28"},
+       {"91DE",        APDUCODE_TYPE_NONE,             "File or application already exists"},
+       {"91EE",        APDUCODE_TYPE_NONE,             "Could not complete NV-write operation due to loss of power"},
+       {"91F0",        APDUCODE_TYPE_NONE,             "Specified file number does not exist"},
+       {"91F1",        APDUCODE_TYPE_NONE,             "Unrecoverable error within file"},
+       {"920x",        APDUCODE_TYPE_INFO,                     "Writing to EEPROM successful after 'x' attempts."},
+       {"9210",        APDUCODE_TYPE_ERROR,            "Insufficient memory. No more storage available."},
+       {"9240",        APDUCODE_TYPE_ERROR,            "Writing to EEPROM not successful."},
+       {"9301",        APDUCODE_TYPE_NONE,             "Integrity error"},
+       {"9302",        APDUCODE_TYPE_NONE,             "Candidate S2 invalid"},
+       {"9303",        APDUCODE_TYPE_ERROR,            "Application is permanently locked"},
+       {"9400",        APDUCODE_TYPE_ERROR,            "No EF selected."},
+       {"9401",        APDUCODE_TYPE_NONE,             "Candidate currency code does not match purse currency"},
+       {"9402",        APDUCODE_TYPE_NONE,             "Candidate amount too high"},
+       {"9402",        APDUCODE_TYPE_ERROR,            "Address range exceeded."},
+       {"9403",        APDUCODE_TYPE_NONE,             "Candidate amount too low"},
+       {"9404",        APDUCODE_TYPE_ERROR,            "FID not found, record not found or comparison pattern not found."},
+       {"9405",        APDUCODE_TYPE_NONE,             "Problems in the data field"},
+       {"9406",        APDUCODE_TYPE_ERROR,            "Required MAC unavailable"},
+       {"9407",        APDUCODE_TYPE_NONE,             "Bad currency : purse engine has no slot with R3bc currency"},
+       {"9408",        APDUCODE_TYPE_NONE,             "R3bc currency not supported in purse engine"},
+       {"9408",        APDUCODE_TYPE_ERROR,            "Selected file type does not match command."},
+       {"9580",        APDUCODE_TYPE_NONE,             "Bad sequence"},
+       {"9681",        APDUCODE_TYPE_NONE,             "Slave not found"},
+       {"9700",        APDUCODE_TYPE_NONE,             "PIN blocked and Unblock Try Counter is 1 or 2"},
+       {"9702",        APDUCODE_TYPE_NONE,             "Main keys are blocked"},
+       {"9704",        APDUCODE_TYPE_NONE,             "PIN not succesfully verified, 3 or more PIN tries left"},
+       {"9784",        APDUCODE_TYPE_NONE,             "Base key"},
+       {"9785",        APDUCODE_TYPE_NONE,             "Limit exceeded - C-MAC key"},
+       {"9786",        APDUCODE_TYPE_NONE,             "SM error - Limit exceeded - R-MAC key"},
+       {"9787",        APDUCODE_TYPE_NONE,             "Limit exceeded - sequence counter"},
+       {"9788",        APDUCODE_TYPE_NONE,             "Limit exceeded - R-MAC length"},
+       {"9789",        APDUCODE_TYPE_NONE,             "Service not available"},
+       {"9802",        APDUCODE_TYPE_ERROR,            "No PIN defined."},
+       {"9804",        APDUCODE_TYPE_ERROR,            "Access conditions not satisfied, authentication failed."},
+       {"9835",        APDUCODE_TYPE_ERROR,            "ASK RANDOM or GIVE RANDOM not executed."},
+       {"9840",        APDUCODE_TYPE_ERROR,            "PIN verification not successful."},
+       {"9850",        APDUCODE_TYPE_ERROR,            "INCREASE or DECREASE could not be executed because a limit has been reached."},
+       {"9862",        APDUCODE_TYPE_ERROR,            "Authentication Error, application specific (incorrect MAC)"},
+       {"9900",        APDUCODE_TYPE_NONE,             "1 PIN try left"},
+       {"9904",        APDUCODE_TYPE_NONE,             "PIN not succesfully verified, 1 PIN try left"},
+       {"9985",        APDUCODE_TYPE_NONE,             "Wrong status - Cardholder lock"},
+       {"9986",        APDUCODE_TYPE_ERROR,            "Missing privilege"},
+       {"9987",        APDUCODE_TYPE_NONE,             "PIN is not installed"},
+       {"9988",        APDUCODE_TYPE_NONE,             "Wrong status - R-MAC state"},
+       {"9A00",        APDUCODE_TYPE_NONE,             "2 PIN try left"},
+       {"9A04",        APDUCODE_TYPE_NONE,             "PIN not succesfully verified, 2 PIN try left"},
+       {"9A71",        APDUCODE_TYPE_NONE,             "Wrong parameter value - Double agent AID"},
+       {"9A72",        APDUCODE_TYPE_NONE,             "Wrong parameter value - Double agent Type"},
+       {"9D05",        APDUCODE_TYPE_ERROR,            "Incorrect certificate type"},
+       {"9D07",        APDUCODE_TYPE_ERROR,            "Incorrect session data size"},
+       {"9D08",        APDUCODE_TYPE_ERROR,            "Incorrect DIR file record size"},
+       {"9D09",        APDUCODE_TYPE_ERROR,            "Incorrect FCI record size"},
+       {"9D0A",        APDUCODE_TYPE_ERROR,            "Incorrect code size"},
+       {"9D10",        APDUCODE_TYPE_ERROR,            "Insufficient memory to load application"},
+       {"9D11",        APDUCODE_TYPE_ERROR,            "Invalid AID"},
+       {"9D12",        APDUCODE_TYPE_ERROR,            "Duplicate AID"},
+       {"9D13",        APDUCODE_TYPE_ERROR,            "Application previously loaded"},
+       {"9D14",        APDUCODE_TYPE_ERROR,            "Application history list full"},
+       {"9D15",        APDUCODE_TYPE_ERROR,            "Application not open"},
+       {"9D17",        APDUCODE_TYPE_ERROR,            "Invalid offset"},
+       {"9D18",        APDUCODE_TYPE_ERROR,            "Application already loaded"},
+       {"9D19",        APDUCODE_TYPE_ERROR,            "Invalid certificate"},
+       {"9D1A",        APDUCODE_TYPE_ERROR,            "Invalid signature"},
+       {"9D1B",        APDUCODE_TYPE_ERROR,            "Invalid KTU"},
+       {"9D1D",        APDUCODE_TYPE_ERROR,            "MSM controls not set"},
+       {"9D1E",        APDUCODE_TYPE_ERROR,            "Application signature does not exist"},
+       {"9D1F",        APDUCODE_TYPE_ERROR,            "KTU does not exist"},
+       {"9D20",        APDUCODE_TYPE_ERROR,            "Application not loaded"},
+       {"9D21",        APDUCODE_TYPE_ERROR,            "Invalid Open command data length"},
+       {"9D30",        APDUCODE_TYPE_ERROR,            "Check data parameter is incorrect (invalid start address)"},
+       {"9D31",        APDUCODE_TYPE_ERROR,            "Check data parameter is incorrect (invalid length)"},
+       {"9D32",        APDUCODE_TYPE_ERROR,            "Check data parameter is incorrect (illegal memory check area)"},
+       {"9D40",        APDUCODE_TYPE_ERROR,            "Invalid MSM Controls ciphertext"},
+       {"9D41",        APDUCODE_TYPE_ERROR,            "MSM controls already set"},
+       {"9D42",        APDUCODE_TYPE_ERROR,            "Set MSM Controls data length less than 2 bytes"},
+       {"9D43",        APDUCODE_TYPE_ERROR,            "Invalid MSM Controls data length"},
+       {"9D44",        APDUCODE_TYPE_ERROR,            "Excess MSM Controls ciphertext"},
+       {"9D45",        APDUCODE_TYPE_ERROR,            "Verification of MSM Controls data failed"},
+       {"9D50",        APDUCODE_TYPE_ERROR,            "Invalid MCD Issuer production ID"},
+       {"9D51",        APDUCODE_TYPE_ERROR,            "Invalid MCD Issuer ID"},
+       {"9D52",        APDUCODE_TYPE_ERROR,            "Invalid set MSM controls data date"},
+       {"9D53",        APDUCODE_TYPE_ERROR,            "Invalid MCD number"},
+       {"9D54",        APDUCODE_TYPE_ERROR,            "Reserved field error"},
+       {"9D55",        APDUCODE_TYPE_ERROR,            "Reserved field error"},
+       {"9D56",        APDUCODE_TYPE_ERROR,            "Reserved field error"},
+       {"9D57",        APDUCODE_TYPE_ERROR,            "Reserved field error"},
+       {"9D60",        APDUCODE_TYPE_ERROR,            "MAC verification failed"},
+       {"9D61",        APDUCODE_TYPE_ERROR,            "Maximum number of unblocks reached"},
+       {"9D62",        APDUCODE_TYPE_ERROR,            "Card was not blocked"},
+       {"9D63",        APDUCODE_TYPE_ERROR,            "Crypto functions not available"},
+       {"9D64",        APDUCODE_TYPE_ERROR,            "No application loaded"},
+       {"9E00",        APDUCODE_TYPE_NONE,             "PIN not installed"},
+       {"9E04",        APDUCODE_TYPE_NONE,             "PIN not succesfully verified, PIN not installed"},
+       {"9F00",        APDUCODE_TYPE_NONE,             "PIN blocked and Unblock Try Counter is 3"},
+       {"9F04",        APDUCODE_TYPE_NONE,             "PIN not succesfully verified, PIN blocked and Unblock Try Counter is 3"},
+       {"9FXX",        APDUCODE_TYPE_NONE,             "Command successfully executed; 'xx' bytes of data are available and can be requested using GET RESPONSE."},
+       {"9xXX",        APDUCODE_TYPE_NONE,             "Application related status, (ISO 7816-3)"}
+};
+
+int CodeCmp(const char *code1, const char *code2) {
+       int xsymb = 0;
+       int cmp = 0;
+       for (int i = 0; i < 4; i++) {
+               if (code1[i] == code2[i])
+                       cmp++;
+               if (code1[i] == 'X' || code2[i] == 'X')
+                       xsymb++;
+       }
+       if (cmp == 4)
+               return 0;
+       
+       if (cmp + xsymb == 4)
+               return xsymb;
+       
+       return -1;
+}
+
+APDUCode *GetAPDUCode(uint8_t sw1, uint8_t sw2) {
+       char buf[4] = {0};
+       
+       sprintf(&buf[0], "%02X ", sw1);
+       sprintf(&buf[2], "%02X ", sw2);
+       
+               
+       int tableLen = sizeof(APDUCodeTable)/sizeof(APDUCode);
+       for (int i = 0; i < tableLen; i++) {
+               if (CodeCmp(APDUCodeTable[i].ID, buf) == 0) { // TODO make not so equal comparation... XXXX - not works...
+                       return &APDUCodeTable[i];
+               }
+       }
+
+       return NULL;
+}
+
+const char *GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2) {
+       APDUCode *cd = GetAPDUCode(sw1, sw2);
+       if (cd)
+               return cd->Description;
+       else
+               return APDUCodeTable[0].Description; //empty string
+}
+
+
diff --git a/client/emv/apduinfo.h b/client/emv/apduinfo.h
new file mode 100644 (file)
index 0000000..e388ae6
--- /dev/null
@@ -0,0 +1,34 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2017 Merlok
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// APDU status bytes information
+//-----------------------------------------------------------------------------
+
+#ifndef APDUINFO_H__
+#define APDUINFO_H__
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#define APDUCODE_TYPE_NONE             0
+#define APDUCODE_TYPE_INFO             1
+#define APDUCODE_TYPE_WARNING  2
+#define APDUCODE_TYPE_ERROR            3
+#define APDUCODE_TYPE_SECURITY 4
+
+typedef struct {
+       const char *ID;
+       const uint8_t Type;
+       const char *Description;
+} APDUCode;
+       
+extern APDUCode* GetAPDUCode(uint8_t sw1, uint8_t sw2);
+extern const char* GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2);
+
+#endif
diff --git a/client/obj/emv/.dummy b/client/obj/emv/.dummy
new file mode 100644 (file)
index 0000000..e69de29
Impressum, Datenschutz