diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index f9016a29ab..1db7fd95ae 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -2373,3 +2373,167 @@ uint64_t GetCrypto1ProbableKey(AuthData_t *ad) { crypto1_destroy(revstate); return key; } + +// FMCOS 2.0 +void annotateFMCOS20(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { + + if (cmdsize < 2) + return; + + int pos = 0; + switch (cmd[0]) { + case 2: + case 3: + pos = 2; + break; + case 0: + pos = 1; + break; + default: + pos = 3; + break; + } + switch (cmd[pos]) { + case FMCOS20_CMD_EXTERNAL_AUTHENTICATION: + snprintf(exp, size, "EXT. AUTH"); + break; + case FMCOS20_CMD_GET_CHALLENGE: + snprintf(exp, size, "GET CHALLENGE"); + break; + case FMCOS20_CMD_INTERNAL_AUTHENTICATION: + snprintf(exp, size, "INT. AUTH"); + break; + case FMCOS20_CMD_SELECT: + snprintf(exp, size, "SELECT"); + break; + case FMCOS20_CMD_VERIFY_PIN: + snprintf(exp, size, "VERIFY PIN"); + break; + case FMCOS20_CMD_READ_BINARY: + snprintf(exp, size, "READ BINARY"); + break; + case FMCOS20_CMD_READ_RECORD: + snprintf(exp, size, "READ RECORD"); + break; + case FMCOS20_CMD_UPDATE_BINARY: + snprintf(exp, size, "UPDATE BINARY"); + break; + case FMCOS20_CMD_UPDATE_RECORD: + snprintf(exp, size, "UPDATE RECORD"); + break; + case FMCOS20_CMD_APPEND_RECORD: + snprintf(exp, size, "APPEND RECORD"); + break; + case FMCOS20_CMD_ERASE_DF: + snprintf(exp, size, "ERASE DF"); + break; + case FMCOS20_CMD_WRITE_KEY: + snprintf(exp, size, "WRITE KEY"); + break; + case FMCOS20_CMD_CREATE_FILE: + snprintf(exp, size, "CREATE FILE"); + break; + case FMCOS20_CMD_CARD_BLOCK: + snprintf(exp, size, "CARD BLOCK"); + break; + case FMCOS20_CMD_APP_UNBLOCK: + snprintf(exp, size, "APP UNBLOCK"); + break; + case FMCOS20_CMD_APP_BLOCK: + if (cmd[pos+1] == 0) + snprintf(exp, size, "APP BLOCK (TEMP)"); + else if(cmd[pos+1] == 1) + snprintf(exp, size, "APP BLOCK (PERM)"); + else + snprintf(exp, size, "APP BLOCK"); + break; + case FMCOS20_CMD_PIN_UNBLOCK: + snprintf(exp, size, "PIN UNBLOCK"); + break; + case FMCOS20_CMD_CHANGE_PIN: + if (cmd[pos+1] == 0) + snprintf(exp, size, "RESET PIN"); + else if (cmd[pos+1] == 1) + snprintf(exp, size, "CHANGE PIN"); + break; + case FMCOS20_CMD_INITIALIZE_TRANSACTION: + if (cmd[pos+1] == 0) + snprintf(exp, size, "INIT. TRANSACTION (CREDIT)"); + else if (cmd[pos+1] == 1) + snprintf(exp, size, "INIT. TRANSACTION (PURCHASE)"); + else if (cmd[pos+1] == 2) + snprintf(exp, size, "INIT. TRANSACTION (CASH WITHDRAW)"); + else if (cmd[pos+1] == 3) + snprintf(exp, size, "INIT. TRANSACTION (CAPP PURCHASE)"); + else if (cmd[pos+1] == 4) + snprintf(exp, size, "INIT. TRANSACTION (OVERDRAFT)"); + else if (cmd[pos+1] == 5) + snprintf(exp, size, "INIT. TRANSACTION (WITHDRAW)"); + break; + case FMCOS20_CMD_CREDIT_LOAD: + snprintf(exp, size, "CREDIT LOAD"); + break; + case FMCOS20_CMD_PURCHASE: + if(cmd[pos+1] == 0) + snprintf(exp, size, "PURCHASE"); + else if (cmd[pos+1] == 1) + snprintf(exp, size, "CAPP PURCHASE / CASH WITHDRAW"); + else if (cmd[pos+1] == 3) + snprintf(exp, size, "WITHDRAW"); + break; + case FMCOS20_CMD_UPDATE_OVERDRAW_LIMIT: + snprintf(exp, size, "UPDATE OVERDRAFT"); + break; + case FMCOS20_CMD_GET_TRANSACTION_PROOF: + snprintf(exp, size, "TRANSACTION RECORD"); + break; + case FMCOS20_CMD_GET_BALANCE: + snprintf(exp, size, "GET BALANCE"); + break; + case FMCOS20_CMD_INITIALIZE_GREY_LOCK_UNLOCK: + if (cmd[pos+1] == 8) + snprintf(exp, size, "INIT. GRAY LOCK"); + else if (cmd[pos+1] == 9) + snprintf(exp, size, "INIT. GRAY UNLOCK"); + break; + case FMCOS20_CMD_GREY_LOCK_UNLOCK: + if (cmd[pos+1] == 8) + snprintf(exp, size, "GRAY LOCK"); + else if (cmd[pos+1] == 9) + snprintf(exp, size, "GRAY UNLOCK"); + break; + case FMCOS20_CMD_DEBIT_UNLOCK: + snprintf(exp, size, "DEBIT UNLOCK"); + break; + case FMCOS20_CMD_CALCULATE_ROM_CRC: + snprintf(exp, size, "CALC. ROM CRC"); + break; + case FMCOS20_CMD_GET_RESPONSE: + snprintf(exp, size, "GET RESPONSE"); + break; + case FMCOS20_CMD_UNBLOCK: + snprintf(exp, size, "UNBLOCK"); + break; + case FMCOS20_CMD_PULL: + snprintf(exp, size, "PULL"); + break; + case FMCOS20_CMD_CHARGE: + snprintf(exp, size, "CHARGE"); + break; + case FMCOS20_CMD_WRITE_EEPROM: + snprintf(exp, size, "WRITE EEPROM"); + break; + case FMCOS20_CMD_READ_EEPROM: + snprintf(exp, size, "READ EEPROM"); + break; + case FMCOS20_CMD_INITIALIZE_EEPROM: + snprintf(exp, size, "INIT. EEPROM"); + break; + case FMCOS20_CMD_READ_ROM: + snprintf(exp, size, "READ ROM"); + break; + default: + //snprintf(exp, size, "?"); + break; + } +} \ No newline at end of file diff --git a/client/src/cmdhflist.h b/client/src/cmdhflist.h index cbe18e92c7..92f54e4afc 100644 --- a/client/src/cmdhflist.h +++ b/client/src/cmdhflist.h @@ -76,4 +76,6 @@ bool NestedCheckKey(uint64_t key, AuthData_t *ad, uint8_t *cmd, uint8_t cmdsize, bool CheckCrypto1Parity(const uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, const uint8_t *parity_enc); uint64_t GetCrypto1ProbableKey(AuthData_t *ad); +void annotateFMCOS20(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); + #endif // CMDHFLIST diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 8e19c3bb5f..569e13e23a 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -779,6 +779,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr switch (protocol) { case ISO_14443A: case ISO_7816_4: + case PROTO_FMCOS20: annotateIso14443a(explanation, sizeof(explanation), frame, data_len, hdr->isResponse); break; case PROTO_MIFARE: @@ -836,6 +837,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr case SEOS: annotateSeos(explanation, sizeof(explanation), frame, data_len); break; + case PROTO_FMCOS20: + annotateFMCOS20(explanation, sizeof(explanation), frame, data_len); + break; default: break; } @@ -1310,6 +1314,7 @@ int CmdTraceList(const char *Cmd) { "trace list -t thinfilm -> interpret as " _YELLOW_("Thinfilm") "\n" "trace list -t topaz -> interpret as " _YELLOW_("Topaz") "\n" "trace list -t mfp -> interpret as " _YELLOW_("MIFARE Plus") "\n" + "trace list -t fmcos20 -> interpret as " _YELLOW_("FMCOS 2.0") "\n" "\n" "trace list -t mf -f mfc_default_keys.dic -> use default dictionary file\n" "trace list -t 14a --frame -> show frame delay times\n" @@ -1377,6 +1382,7 @@ int CmdTraceList(const char *Cmd) { else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM; else if (strcmp(type, "topaz") == 0) protocol = TOPAZ; else if (strcmp(type, "mfp") == 0) protocol = PROTO_MFPLUS; + else if (strcmp(type, "fmcos20") == 0) protocol = PROTO_FMCOS20; else if (strcmp(type, "") == 0) protocol = -1; else { PrintAndLogEx(FAILED, "Unknown protocol \"%s\"", type); @@ -1460,6 +1466,10 @@ int CmdTraceList(const char *Cmd) { PrintAndLogEx(INFO, _YELLOW_("Hitag 1 / Hitag 2 / Hitag S") " - Timings in ETU (8us)"); } + if (protocol == PROTO_FMCOS20) { + PrintAndLogEx(INFO, _YELLOW_("FMCOS 2.0 / CPU Card") " - Timings n/a"); + } + if (protocol == FELICA) { if (use_us) PrintAndLogEx(INFO, _YELLOW_("ISO18092 / FeliCa") " - all times are in microseconds"); diff --git a/doc/commands.json b/doc/commands.json index aca2de7f72..0bfc7059df 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -12837,6 +12837,7 @@ "trace list -t thinfilm -> interpret as Thinfilm", "trace list -t topaz -> interpret as Topaz", "trace list -t mfp -> interpret as MIFARE Plus", + "trace list -t fmcos20 -> interpret as FMCOS 2.0", "", "trace list -t mf -f mfc_default_keys.dic -> use default dictionary file", "trace list -t 14a --frame -> show frame delay times", diff --git a/include/protocols.h b/include/protocols.h index 3aa40ea796..3591a8dc20 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -453,6 +453,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define PROTO_MFPLUS 17 #define PROTO_TEXKOM 18 #define PROTO_XEROX 19 +#define PROTO_FMCOS20 20 // Picopass fuses #define FUSE_FPERS 0x80 @@ -950,5 +951,43 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. // 0x0A = ACK // 0x05 = NACK +//FMCOS2.0 +#define FMCOS20_CMD_VERIFY_PIN 0x20 +#define FMCOS20_CMD_EXTERNAL_AUTHENTICATION 0x82 +#define FMCOS20_CMD_GET_CHALLENGE 0x84 +#define FMCOS20_CMD_INTERNAL_AUTHENTICATION 0x88 +#define FMCOS20_CMD_SELECT 0xA4 +#define FMCOS20_CMD_READ_BINARY 0xB0 +#define FMCOS20_CMD_READ_RECORD 0xB2 +#define FMCOS20_CMD_GET_RESPONSE 0xC0 +#define FMCOS20_CMD_UPDATE_BINARY 0xD6 +#define FMCOS20_CMD_UPDATE_RECORD 0xDC +#define FMCOS20_CMD_APPEND_RECORD 0xE2 +#define FMCOS20_CMD_CARD_BLOCK 0x16 +#define FMCOS20_CMD_APP_UNBLOCK 0x18 +#define FMCOS20_CMD_APP_BLOCK 0x1E +#define FMCOS20_CMD_PIN_UNBLOCK 0x24 +#define FMCOS20_CMD_UNBLOCK 0x2C +#define FMCOS20_CMD_INITIALIZE_TRANSACTION 0x50 +#define FMCOS20_CMD_CREDIT_LOAD 0x52 +#define FMCOS20_CMD_PURCHASE 0x54 +#define FMCOS20_CMD_UPDATE_OVERDRAW_LIMIT 0x58 +#define FMCOS20_CMD_GET_TRANSACTION_PROOF 0x5A +#define FMCOS20_CMD_GET_BALANCE 0x5C +#define FMCOS20_CMD_CHANGE_PIN 0x5E +#define FMCOS20_CMD_ERASE_DF 0x0E +#define FMCOS20_CMD_PULL 0x30 +#define FMCOS20_CMD_CHARGE 0x32 +#define FMCOS20_CMD_WRITE_KEY 0xD4 +#define FMCOS20_CMD_CREATE_FILE 0xE0 +#define FMCOS20_CMD_WRITE_EEPROM 0x00 +#define FMCOS20_CMD_READ_EEPROM 0x04 +#define FMCOS20_CMD_INITIALIZE_EEPROM 0x02 +#define FMCOS20_CMD_READ_ROM 0x0C +#define FMCOS20_CMD_INITIALIZE_GREY_LOCK_UNLOCK 0x7A +#define FMCOS20_CMD_GREY_LOCK_UNLOCK 0x7C +#define FMCOS20_CMD_DEBIT_UNLOCK 0x7E +#define FMCOS20_CMD_CALCULATE_ROM_CRC 0x0A + #endif // PROTOCOLS_H