X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/298143218af2c123d27929638ff42c579f218c60..72622d6429ebd62f6e416356aeda565956352aed:/client/emv/apduinfo.c

diff --git a/client/emv/apduinfo.c b/client/emv/apduinfo.c
index ec7a64a1..65d7404e 100644
--- a/client/emv/apduinfo.c
+++ b/client/emv/apduinfo.c
@@ -10,256 +10,261 @@
 
 #include "apduinfo.h"
 
+#include <stdio.h>
+#include <string.h>
+#include "ui.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)"}
+	{"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 successfully 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 successfully 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 successfully 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 successfully 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 successfully verified, PIN not installed"},
+	{"9F00",    APDUCODE_TYPE_NONE,         "PIN blocked and Unblock Try Counter is 3"},
+	{"9F04",    APDUCODE_TYPE_NONE,         "PIN not successfully 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)"}
 };
-const size_t APDUCodeTableLen = sizeof(APDUCodeTable)/sizeof(APDUCode);
+const size_t APDUCodeTableLen = sizeof(APDUCodeTable) / sizeof(APDUCode);
 
-int CodeCmp(const char *code1, const char *code2) {
+static int CodeCmp(const char *code1, const char *code2) {
 	int xsymb = 0;
 	int cmp = 0;
 	for (int i = 0; i < 4; i++) {
@@ -270,30 +275,28 @@ int CodeCmp(const char *code1, const char *code2) {
 	}
 	if (cmp == 4)
 		return 0;
-	
+
 	if (cmp + xsymb == 4)
 		return xsymb;
-	
+
 	return -1;
 }
 
-const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) {
-	char buf[5] = {0};
-	int res;
-	int mineq = 100;
+const APDUCode *GetAPDUCode(uint8_t sw1, uint8_t sw2) {
+	char buf[6] = {0};
+	int mineq = APDUCodeTableLen;
 	int mineqindx = 0;
-	
-	sprintf(&buf[0], "%02X", sw1);
-	sprintf(&buf[2], "%02X", sw2);
-	
+
+	sprintf(buf, "%02X%02X", sw1, sw2);
+
 	for (int i = 0; i < APDUCodeTableLen; i++) {
-		res = CodeCmp(APDUCodeTable[i].ID, buf);
-		
+		int res = CodeCmp(APDUCodeTable[i].ID, buf);
+
 		// equal
-		if (res == 0) { 
+		if (res == 0) {
 			return &APDUCodeTable[i];
 		}
-		
+
 		// with some  'X'
 		if (res > 0 && mineq > res) {
 			mineq = res;
@@ -302,17 +305,204 @@ const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) {
 	}
 
 	// if we have not equal, but with some 'X'
-	if (mineqindx < 100) {
+	if (mineqindx < APDUCodeTableLen) {
 		return &APDUCodeTable[mineqindx];
 	}
-	
+
 	return NULL;
 }
 
-const char* GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2) {
+const char *GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2) {
 	const APDUCode *cd = GetAPDUCode(sw1, sw2);
 	if (cd)
 		return cd->Description;
 	else
 		return APDUCodeTable[0].Description; //empty string
 }
+
+int APDUDecode(uint8_t *data, int len, APDUStruct *apdu) {
+	ExtAPDUHeader *hapdu = (ExtAPDUHeader *)data;
+
+	apdu->cla = hapdu->cla;
+	apdu->ins = hapdu->ins;
+	apdu->p1 = hapdu->p1;
+	apdu->p2 = hapdu->p2;
+
+	apdu->lc = 0;
+	apdu->data = NULL;
+	apdu->le = 0;
+	apdu->extended_apdu = false;
+	apdu->case_type = 0x00;
+
+	uint8_t b0 = hapdu->lc[0];
+
+	// case 1
+	if (len == 4) {
+		apdu->case_type = 0x01;
+	}
+
+	// case 2S (Le)
+	if (len == 5) {
+		apdu->case_type = 0x02;
+		apdu->le = b0;
+		if (!apdu->le)
+			apdu->le = 0x100;
+	}
+
+	// case 3S (Lc + data)
+	if (len == 5U + b0 && b0 != 0) {
+		apdu->case_type = 0x03;
+		apdu->lc = b0;
+	}
+
+	// case 4S (Lc + data + Le)
+	if (len == 5U + b0 + 1U && b0 != 0) {
+		apdu->case_type = 0x04;
+		apdu->lc = b0;
+		apdu->le = data[len - 1];
+		if (!apdu->le)
+			apdu->le = 0x100;
+	}
+
+	// extended length apdu
+	if (len >= 7 && b0 == 0) {
+		uint16_t extlen = (hapdu->lc[1] << 8) + hapdu->lc[2];
+
+		// case 2E (Le) - extended
+		if (len == 7) {
+			apdu->case_type = 0x12;
+			apdu->extended_apdu = true;
+			apdu->le = extlen;
+			if (!apdu->le)
+				apdu->le = 0x10000;
+		}
+
+		// case 3E (Lc + data) - extended
+		if (len == 7U + extlen) {
+			apdu->case_type = 0x13;
+			apdu->extended_apdu = true;
+			apdu->lc = extlen;
+		}
+
+		// case 4E (Lc + data + Le) - extended 2-byte Le
+		if (len == 7U + extlen + 2U) {
+			apdu->case_type = 0x14;
+			apdu->extended_apdu = true;
+			apdu->lc = extlen;
+			apdu->le = (data[len - 2] << 8) + data[len - 1];
+			if (!apdu->le)
+				apdu->le = 0x10000;
+		}
+
+		// case 4E (Lc + data + Le) - extended 3-byte Le
+		if (len == 7U + extlen + 3U && data[len - 3] == 0) {
+			apdu->case_type = 0x24;
+			apdu->extended_apdu = true;
+			apdu->lc = extlen;
+			apdu->le = (data[len - 2] << 8) + data[len - 1];
+			if (!apdu->le)
+				apdu->le = 0x10000;
+		}
+	}
+
+	if (!apdu->case_type)
+		return 1;
+
+	if (apdu->lc) {
+		if (apdu->extended_apdu) {
+			apdu->data = data + 7;
+		} else {
+			apdu->data = data + 5;
+		}
+
+	}
+
+	return 0;
+}
+
+int APDUEncode(APDUStruct *apdu, uint8_t *data, int *len) {
+	if (len)
+		*len = 0;
+
+	if (apdu->le > 0x10000 || apdu->lc > 0xffff)
+		return 1;
+
+	size_t dptr = 0;
+	data[dptr++] = apdu->cla;
+	data[dptr++] = apdu->ins;
+	data[dptr++] = apdu->p1;
+	data[dptr++] = apdu->p2;
+
+	if (apdu->lc) {
+		if (apdu->extended_apdu || apdu->lc > 0xff || apdu->le > 0x100) {
+			data[dptr++] = 0x00;
+			data[dptr++] = (apdu->lc >> 8) & 0xff;
+			data[dptr++] = (apdu->lc) & 0xff;
+			memmove(&data[dptr], apdu->data, apdu->lc);
+			dptr += apdu->lc;
+			apdu->extended_apdu = true;
+		} else {
+			data[dptr++] = apdu->lc;
+			memmove(&data[dptr], apdu->data, apdu->lc);
+			dptr += apdu->lc;
+		}
+	}
+
+	if (apdu->le) {
+		if (apdu->extended_apdu) {
+			if (apdu->le != 0x10000) {
+				data[dptr++] = 0x00;
+				data[dptr++] = (apdu->le >> 8) & 0xff;
+				data[dptr++] = (apdu->le) & 0xff;
+			} else {
+				data[dptr++] = 0x00;
+				data[dptr++] = 0x00;
+				data[dptr++] = 0x00;
+			}
+		} else {
+			if (apdu->le != 0x100)
+				data[dptr++] = apdu->le;
+			else
+				data[dptr++] = 0x00;
+		}
+	}
+
+	if (len)
+		*len = dptr;
+	return 0;
+}
+
+int APDUEncodeS(sAPDU *sapdu, bool extended, uint16_t le, uint8_t *data, int *len) {
+	if (extended && le > 0x100)
+		return 10;
+
+	APDUStruct apdu;
+
+	apdu.cla = sapdu->CLA;
+	apdu.ins = sapdu->INS;
+	apdu.p1 = sapdu->P1;
+	apdu.p2 = sapdu->P2;
+
+	apdu.lc = sapdu->Lc;
+	if (sapdu->Lc)
+		apdu.data = sapdu->data;
+	else
+		apdu.data = NULL;
+	apdu.le = le;
+
+	apdu.extended_apdu = extended;
+	apdu.case_type = 0x00;
+
+	return APDUEncode(&apdu, data, len);
+}
+
+void APDUPrint(APDUStruct apdu) {
+	APDUPrintEx(apdu, 0);
+}
+
+void APDUPrintEx(APDUStruct apdu, size_t maxdatalen) {
+	PrintAndLogEx(INFO, "APDU: %scase=0x%02x cla=0x%02x ins=0x%02x p1=0x%02x p2=0x%02x Lc=0x%02x(%d) Le=0x%02x(%d)",
+				  apdu.extended_apdu ? "[e]" : "", apdu.case_type, apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.lc, apdu.lc, apdu.le, apdu.le);
+	if (maxdatalen > 0)
+		PrintAndLogEx(INFO, "data: %s%s", sprint_hex(apdu.data, MIN(apdu.lc, maxdatalen)), apdu.lc > maxdatalen ? "..." : "");
+}