From: merlokk Date: Tue, 31 Oct 2017 16:14:32 +0000 (+0200) Subject: added showing apdu response codes X-Git-Tag: v3.1.0~133^2~15 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/fe346768b35409677b6c7f40a6f2a6768cf54ac3 added showing apdu response codes --- diff --git a/client/Makefile b/client/Makefile index 3a96e9e9..8e1574d4 100644 --- a/client/Makefile +++ b/client/Makefile @@ -107,6 +107,7 @@ CMDSRCS = crapto1/crapto1.c\ ui.c \ cmddata.c \ lfdemod.c \ + emv/apduinfo.c\ cmdhf.c \ cmdhf14a.c \ cmdhf14b.c \ diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index f6ed899a..6d6ea854 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2011, Merlok +// 2011, 2017 Merlok // Copyright (C) 2010 iZsh , 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) { diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 407cf07d..919ece5a 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -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 index 00000000..e2e51d9d --- /dev/null +++ b/client/emv/apduinfo.c @@ -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, …)"}, + {"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 index 00000000..e388ae68 --- /dev/null +++ b/client/emv/apduinfo.h @@ -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 +#include +#include +#include + +#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 index 00000000..e69de29b