Skip to content

Commit

Permalink
Add annotations for FMCOS2.0 CPU Card
Browse files Browse the repository at this point in the history
Adding annotations for the FMCOS 2.0 CPU Card that is used/sold in China.
  • Loading branch information
klks committed Dec 20, 2024
1 parent e5bee8d commit df3916c
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 0 deletions.
164 changes: 164 additions & 0 deletions client/src/cmdhflist.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
2 changes: 2 additions & 0 deletions client/src/cmdhflist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
10 changes: 10 additions & 0 deletions client/src/cmdtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand Down
1 change: 1 addition & 0 deletions doc/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
39 changes: 39 additions & 0 deletions include/protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

0 comments on commit df3916c

Please sign in to comment.