From 2c3235f2fc4932a87bd9e6a9e21fb6b6dd7e5bfa Mon Sep 17 00:00:00 2001 From: klks Date: Mon, 25 May 2026 17:08:47 +0800 Subject: [PATCH 1/4] Use proper memory fail error message, fix bugs and missed DropField() checks --- client/src/cmdhffmcos.c | 157 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhffmcos.c b/client/src/cmdhffmcos.c index 6912c3043..1cfcb1d71 100644 --- a/client/src/cmdhffmcos.c +++ b/client/src/cmdhffmcos.c @@ -359,7 +359,7 @@ static bool fmcos_des_mac(const uint8_t *buf, size_t buf_len, size_t max_padded = buf_len + 8; uint8_t *padded = calloc(max_padded, 1); if (padded == NULL) { - PrintAndLogEx(ERR, "calloc failed"); + PrintAndLogEx(WARNING, "Failed to allocate memory"); return false; } @@ -424,7 +424,7 @@ static bool fmcos_packet_mac(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, size_t buf_len = 5 + data_len; uint8_t *mac_buf = calloc(buf_len, 1); if (mac_buf == NULL) { - PrintAndLogEx(ERR, "calloc failed"); + PrintAndLogEx(WARNING, "Failed to allocate memory"); return false; } @@ -481,7 +481,9 @@ static size_t fmcos_encrypt(const uint8_t *key, size_t key_len, } size_t padded_len = fmcos_iso7816_pad(data, data_len, padded); for (size_t off = 0; off < padded_len; off += 8) { - fmcos_ecb_encrypt(key, key_len, padded + off, out + off); + if (fmcos_ecb_encrypt(key, key_len, padded + off, out + off) != PM3_SUCCESS) { + return 0; + } } return padded_len; } @@ -1055,7 +1057,7 @@ static int fmcos_write_cmd(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, int prot, const uint8_t *key, size_t key_len, bool activate, bool leave_on, uint8_t *resp_out, int *resp_len_out) { - uint8_t payload[260] = {0}; + uint8_t payload[272] = {0}; size_t payload_len = 0; if (prot == FMCOS_PROT_ENC) { @@ -1068,7 +1070,7 @@ static int fmcos_write_cmd(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, memcpy(enc_in + 1, data, data_len); payload_len = fmcos_encrypt(key, key_len, enc_in, 1 + data_len, payload); if (payload_len == 0) { - return PM3_EMALLOC; + return PM3_ESOFT; } cla |= 0x04; } else { @@ -1095,7 +1097,7 @@ static int fmcos_write_cmd(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, payload_len += 4; } - uint8_t apdu[270]; + uint8_t apdu[280]; apdu[0] = cla; apdu[1] = ins; apdu[2] = p1; @@ -2605,6 +2607,9 @@ static int CmdHFFmcosPinUnblock(const char *Cmd) { memcpy(plain + 1, pin, (size_t)pin_len); uint8_t enc_data[16] = {0}; size_t enc_len = fmcos_encrypt(key, (size_t)key_len, plain, 1 + (size_t)pin_len, enc_data); + if (enc_len == 0) { + return PM3_ESOFT; + } // GET CHALLENGE for packet MAC IV - CLA=84, INS=24 uint8_t chal[8] = {0}; @@ -2619,6 +2624,9 @@ static int CmdHFFmcosPinUnblock(const char *Cmd) { uint8_t mac[4] = {0}; if (!fmcos_packet_mac(0x84, 0x24, id_buf[0], 0x00, enc_data, enc_len, chal, key, (size_t)key_len, mac)) { + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -2717,11 +2725,17 @@ static int CmdHFFmcosBalance(const char *Cmd) { int resp_len = 0; if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } if (resp_len < 2) { PrintAndLogEx(ERR, "Short response"); + if (!keep) { + DropField(); + } return PM3_ESOFT; } uint8_t sw1 = resp[resp_len - 2], sw2 = resp[resp_len - 1]; @@ -2733,6 +2747,9 @@ static int CmdHFFmcosBalance(const char *Cmd) { PrintAndLogEx(SUCCESS, "Balance (%s): " _GREEN_("%u") " (0x%08X)", bal_type == 0x01 ? "passbook" : "wallet", balance, balance); } + if (!keep) { + DropField(); + } return (sw1 == 0x90 && sw2 == 0x00) ? PM3_SUCCESS : PM3_ESOFT; } @@ -2831,6 +2848,10 @@ static int CmdHFFmcosCredit(const char *Cmd) { int resp_len = 0; if (fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len) != PM3_SUCCESS) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -2866,7 +2887,13 @@ static int CmdHFFmcosCredit(const char *Cmd) { memcpy(pk_buf, resp + 8, 4); // random_1 memcpy(pk_buf + 4, resp + 4, 2); // online_serial uint8_t pk_enc[24] = {0}; - fmcos_encrypt(crde_key, (size_t)crde_key_len, pk_buf, 6, pk_enc); + if (fmcos_encrypt(crde_key, (size_t)crde_key_len, pk_buf, 6, pk_enc) == 0) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } + return PM3_ESOFT; + } uint8_t process_key[8]; memcpy(process_key, pk_enc, 8); @@ -2883,6 +2910,10 @@ static int CmdHFFmcosCredit(const char *Cmd) { uint8_t zero_iv[8] = {0}; uint8_t mac1_calc[4] = {0}; if (!fmcos_des_mac(mac1_buf, 15, process_key, zero_iv, mac1_calc, 4)) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -2912,6 +2943,10 @@ static int CmdHFFmcosCredit(const char *Cmd) { uint8_t mac2[4] = {0}; if (!fmcos_des_mac(mac2_buf, 18, process_key, zero_iv, mac2, 4)) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -2931,18 +2966,27 @@ static int CmdHFFmcosCredit(const char *Cmd) { memset(resp, 0, sizeof(resp)); resp_len = 0; if (fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } // Response: TAC[4] SW[2] if (resp_len < 6) { PrintAndLogEx(ERR, "Phase 2 short response (%d bytes)", resp_len); + if (!keep) { + DropField(); + } return PM3_ESOFT; } sw1 = resp[resp_len - 2]; sw2 = resp[resp_len - 1]; if (sw1 != 0x90 || sw2 != 0x00) { fmcos_print_sw(sw1, sw2); + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -2964,6 +3008,9 @@ static int CmdHFFmcosCredit(const char *Cmd) { uint8_t tac_calc[4] = {0}; if (!fmcos_des_mac(tac_buf, 24, tac_key, zero_iv, tac_calc, 4)) { + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -2973,6 +3020,9 @@ static int CmdHFFmcosCredit(const char *Cmd) { PrintAndLogEx(SUCCESS, "TAC OK new balance " _GREEN_("%u"), new_balance); } fmcos_print_sw(sw1, sw2); + if (!keep) { + DropField(); + } return PM3_SUCCESS; } @@ -3082,6 +3132,10 @@ static int CmdHFFmcosPurchase(const char *Cmd) { int resp_len = 0; if (fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len) != PM3_SUCCESS) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -3118,7 +3172,13 @@ static int CmdHFFmcosPurchase(const char *Cmd) { pk_buf[6] = tx_serial[2]; pk_buf[7] = tx_serial[3]; uint8_t pk_enc[24] = {0}; - fmcos_encrypt(purch_key, (size_t)purch_key_len, pk_buf, 8, pk_enc); + if (fmcos_encrypt(purch_key, (size_t)purch_key_len, pk_buf, 8, pk_enc) == 0) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } + return PM3_ESOFT; + } uint8_t process_key[8]; memcpy(process_key, pk_enc, 8); @@ -3139,6 +3199,10 @@ static int CmdHFFmcosPurchase(const char *Cmd) { uint8_t zero_iv[8] = {0}; uint8_t mac1[4] = {0}; if (!fmcos_des_mac(mac1_buf, 18, process_key, zero_iv, mac1, 4)) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -3159,18 +3223,27 @@ static int CmdHFFmcosPurchase(const char *Cmd) { memset(resp, 0, sizeof(resp)); resp_len = 0; if (fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } // Response: TAC[4] mac2_card[4] SW[2] if (resp_len < 10) { PrintAndLogEx(ERR, "Phase 2 short response (%d bytes)", resp_len); + if (!keep) { + DropField(); + } return PM3_ESOFT; } sw1 = resp[resp_len - 2]; sw2 = resp[resp_len - 1]; if (sw1 != 0x90 || sw2 != 0x00) { fmcos_print_sw(sw1, sw2); + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -3195,6 +3268,9 @@ static int CmdHFFmcosPurchase(const char *Cmd) { uint8_t tac_calc[4] = {0}; if (!fmcos_des_mac(tac_buf, 22, tac_key, zero_iv, tac_calc, 4)) { + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -3204,6 +3280,9 @@ static int CmdHFFmcosPurchase(const char *Cmd) { PrintAndLogEx(SUCCESS, "TAC OK new balance " _GREEN_("%u"), new_balance); } fmcos_print_sw(sw1, sw2); + if (!keep) { + DropField(); + } return PM3_SUCCESS; } @@ -3292,6 +3371,10 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { int resp_len = 0; if (fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len) != PM3_SUCCESS) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -3329,7 +3412,13 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { memcpy(pk_buf, resp + 11, 4); memcpy(pk_buf + 4, resp + 4, 2); uint8_t pk_enc[24] = {0}; - fmcos_encrypt(od_key, (size_t)od_key_len, pk_buf, 6, pk_enc); + if (fmcos_encrypt(od_key, (size_t)od_key_len, pk_buf, 6, pk_enc) == 0) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } + return PM3_ESOFT; + } uint8_t process_key[8]; memcpy(process_key, pk_enc, 8); @@ -3343,6 +3432,10 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { uint8_t zero_iv[8] = {0}; uint8_t mac1_calc[4] = {0}; if (!fmcos_des_mac(mac1_buf, 14, process_key, zero_iv, mac1_calc, 4)) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -3371,6 +3464,10 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { uint8_t mac2[4] = {0}; if (!fmcos_des_mac(mac2_buf, 17, process_key, zero_iv, mac2, 4)) { + g_fmcos_session_active = keep; + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -3393,11 +3490,17 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { memset(resp, 0, sizeof(resp)); resp_len = 0; if (fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } if (resp_len < 2) { PrintAndLogEx(ERR, "Phase 2 short response"); + if (!keep) { + DropField(); + } return PM3_ESOFT; } sw1 = resp[resp_len - 2]; @@ -3405,6 +3508,9 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { fmcos_print_sw(sw1, sw2); if (sw1 != 0x90 || sw2 != 0x00) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -3440,6 +3546,9 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { uint8_t tac_calc[4] = {0}; if (!fmcos_des_mac(tac_buf, 23, tac_key, zero_iv, tac_calc, 4)) { + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -3454,6 +3563,9 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { PrintAndLogEx(INFO, "TAC (unverified): %s", sprint_hex(resp, 4)); } + if (!keep) { + DropField(); + } return PM3_SUCCESS; } @@ -3530,6 +3642,9 @@ static int CmdHFFmcosBlock(const char *Cmd) { uint8_t mac[4] = {0}; if (!fmcos_packet_mac(cla, ins, p1, p2, NULL, 0, chal, key, (size_t)key_len, mac)) { + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -3624,6 +3739,9 @@ static int CmdHFFmcosUnblock(const char *Cmd) { // APP UNBLOCK: CLA=84 INS=18 P1=00 P2=00 uint8_t mac[4] = {0}; if (!fmcos_packet_mac(0x84, 0x18, 0x00, 0x00, NULL, 0, chal, key, (size_t)key_len, mac)) { + if (!keep) { + DropField(); + } return PM3_EMALLOC; } @@ -3845,6 +3963,9 @@ static int CmdHFFmcosTidSetCard(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -3898,6 +4019,9 @@ static int CmdHFFmcosTidSetUID(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; if (fmcos_send_apdu(apdu, 5 + (size_t)uid_len, true, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -3957,6 +4081,9 @@ static int CmdHFFmcosTidSetAuth(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -4001,6 +4128,9 @@ static int CmdHFFmcosTidErase(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } @@ -4207,6 +4337,9 @@ static int CmdHFFmcosTidCreateDF(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; if (fmcos_send_apdu(apdu, 14 + (size_t)name_len, true, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } if (resp_len < 2) { @@ -4326,6 +4459,9 @@ static int CmdHFFmcosTidCreateBin(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } if (resp_len < 2) { @@ -4425,6 +4561,9 @@ static int CmdHFFmcosTidCreateRec(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + if (!keep) { + DropField(); + } return PM3_ESOFT; } if (resp_len < 2) { From 6d859fac438dabb95c0ef30e697d27a86a456529 Mon Sep 17 00:00:00 2001 From: klks Date: Mon, 25 May 2026 20:33:29 +0800 Subject: [PATCH 2/4] Update to align to pm3 coding guidelines --- client/src/cmdhffmcos.c | 336 ++++++++++++++++++++++------------------ 1 file changed, 189 insertions(+), 147 deletions(-) diff --git a/client/src/cmdhffmcos.c b/client/src/cmdhffmcos.c index 1cfcb1d71..98ba9e3b4 100644 --- a/client/src/cmdhffmcos.c +++ b/client/src/cmdhffmcos.c @@ -56,7 +56,7 @@ static int fmcos_send_apdu(const uint8_t *apdu, size_t apdu_len, if (res != PM3_SUCCESS) { g_fmcos_session_active = false; PrintAndLogEx(ERR, "APDU exchange failed"); - return PM3_ESOFT; + return res; } g_fmcos_session_active = leave_on; return PM3_SUCCESS; @@ -352,15 +352,15 @@ static size_t fmcos_iso7816_pad(const uint8_t *in, size_t in_len, uint8_t *out) // DES CBC-MAC with ISO7816 padding. key must be exactly 8 bytes. // iv is 8 bytes (typically the GET CHALLENGE response). // Writes mac_len bytes (<= 8) into mac_out. -static bool fmcos_des_mac(const uint8_t *buf, size_t buf_len, - const uint8_t key[8], - const uint8_t iv[8], - uint8_t *mac_out, size_t mac_len) { +static int fmcos_des_mac(const uint8_t *buf, size_t buf_len, + const uint8_t key[8], + const uint8_t iv[8], + uint8_t *mac_out, size_t mac_len) { size_t max_padded = buf_len + 8; uint8_t *padded = calloc(max_padded, 1); if (padded == NULL) { PrintAndLogEx(WARNING, "Failed to allocate memory"); - return false; + return PM3_EMALLOC; } size_t padded_len = fmcos_iso7816_pad(buf, buf_len, padded); @@ -382,22 +382,23 @@ static bool fmcos_des_mac(const uint8_t *buf, size_t buf_len, mac_len = 8; } memcpy(mac_out, val, mac_len); - return true; + return PM3_SUCCESS; } // 3DES Retail MAC: DES-CBC-MAC with left-key-half (8 bytes), then decrypt // with right-key-half, then re-encrypt with left-key-half. // key must be exactly 16 bytes. Writes mac_len bytes (<= 8) into mac_out. -static bool fmcos_3des_mac(const uint8_t *buf, size_t buf_len, - const uint8_t key[16], - const uint8_t iv[8], - uint8_t *mac_out, size_t mac_len) { +static int fmcos_3des_mac(const uint8_t *buf, size_t buf_len, + const uint8_t key[16], + const uint8_t iv[8], + uint8_t *mac_out, size_t mac_len) { const uint8_t *key_l = key; const uint8_t *key_r = key + 8; uint8_t val[8]; - if (!fmcos_des_mac(buf, buf_len, key_l, iv, val, 8)) { - return false; + int res = fmcos_des_mac(buf, buf_len, key_l, iv, val, 8); + if (res != PM3_SUCCESS) { + return res; } uint8_t tmp[8]; @@ -408,7 +409,7 @@ static bool fmcos_3des_mac(const uint8_t *buf, size_t buf_len, mac_len = 8; } memcpy(mac_out, val, mac_len); - return true; + return PM3_SUCCESS; } @@ -416,16 +417,16 @@ static bool fmcos_3des_mac(const uint8_t *buf, size_t buf_len, // iv is the 8-byte GET CHALLENGE response used as the CBC IV. // key_len 8 -> fmcos_des_mac; key_len 16 -> fmcos_3des_mac. // Lc encodes payload_len + 4 (reserves space for the MAC itself). -static bool fmcos_packet_mac(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, - const uint8_t *data, size_t data_len, - const uint8_t *iv, - const uint8_t *key, size_t key_len, - uint8_t *mac_out) { +static int fmcos_packet_mac(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, + const uint8_t *data, size_t data_len, + const uint8_t *iv, + const uint8_t *key, size_t key_len, + uint8_t *mac_out) { size_t buf_len = 5 + data_len; uint8_t *mac_buf = calloc(buf_len, 1); if (mac_buf == NULL) { PrintAndLogEx(WARNING, "Failed to allocate memory"); - return false; + return PM3_EMALLOC; } mac_buf[0] = cla; @@ -437,15 +438,15 @@ static bool fmcos_packet_mac(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, memcpy(&mac_buf[5], data, data_len); } - bool ok; + int res; if (key_len == 8) { - ok = fmcos_des_mac(mac_buf, buf_len, key, iv, mac_out, 4); + res = fmcos_des_mac(mac_buf, buf_len, key, iv, mac_out, 4); } else { - ok = fmcos_3des_mac(mac_buf, buf_len, key, iv, mac_out, 4); + res = fmcos_3des_mac(mac_buf, buf_len, key, iv, mac_out, 4); } free(mac_buf); - return ok; + return res; } // --------------------------------------------------------------------------- @@ -813,21 +814,21 @@ static int CmdHFFmcosSelect(const char *Cmd) { return (sw1 == 0x90 && sw2 == 0x00) ? PM3_SUCCESS : PM3_ESOFT; } -// Parse a required hex integer argument; returns false and prints an error on -// malformed input. Accepts bare hex digits (no "0x" prefix required). -static bool fmcos_parse_hex_int(const char *s, int *out) { +// Parse a required hex integer argument; returns PM3_EINVARG and prints an +// error on malformed input. Accepts bare hex digits (no "0x" prefix required). +static int fmcos_parse_hex_int(const char *s, int *out) { if (s == NULL || *s == '\0') { PrintAndLogEx(ERR, "Empty hex value"); - return false; + return PM3_EINVARG; } char *end = NULL; long v = strtol(s, &end, 16); if (end == s || *end != '\0') { PrintAndLogEx(ERR, "Invalid hex value: %s", s); - return false; + return PM3_EINVARG; } *out = (int)v; - return true; + return PM3_SUCCESS; } // --------------------------------------------------------------------------- @@ -854,9 +855,10 @@ static int CmdHFFmcosAuthExternal(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); int key_id; - if (!fmcos_parse_hex_int(arg_get_str(ctx, 1)->sval[0], &key_id)) { + int res = fmcos_parse_hex_int(arg_get_str(ctx, 1)->sval[0], &key_id); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t key[16] = {0}; @@ -1031,11 +1033,6 @@ static int CmdHFFmcosAuthInternal(const char *Cmd) { return (sw1 == 0x90 && sw2 == 0x00) ? PM3_SUCCESS : PM3_ESOFT; } -// --------------------------------------------------------------------------- -// hf fmcos authexternal / authinternal (Phase 2) -// --------------------------------------------------------------------------- - - // --------------------------------------------------------------------------- // Phase 4 - File management // --------------------------------------------------------------------------- @@ -1090,8 +1087,9 @@ static int fmcos_write_cmd(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, activate = false; uint8_t mac[4] = {0}; - if (!fmcos_packet_mac(cla, ins, p1, p2, payload, payload_len, chal, key, key_len, mac)) { - return PM3_EMALLOC; + res = fmcos_packet_mac(cla, ins, p1, p2, payload, payload_len, chal, key, key_len, mac); + if (res != PM3_SUCCESS) { + return res; } memcpy(payload + payload_len, mac, 4); payload_len += 4; @@ -1132,8 +1130,9 @@ static int fmcos_read_cmd(uint8_t ins, uint8_t p1, uint8_t p2, uint8_t read_len, if (prot != FMCOS_PROT_NONE) { // Case 4: CLA INS P1 P2 Lc=4 [MAC4] Le uint8_t mac[4] = {0}; - if (!fmcos_packet_mac(cla, ins, p1, p2, NULL, 0, mac_iv, key, key_len, mac)) { - return PM3_EMALLOC; + int res = fmcos_packet_mac(cla, ins, p1, p2, NULL, 0, mac_iv, key, key_len, mac); + if (res != PM3_SUCCESS) { + return res; } apdu[0] = cla; apdu[1] = ins; @@ -1186,14 +1185,13 @@ static int fmcos_read_cmd(uint8_t ins, uint8_t p1, uint8_t p2, uint8_t read_len, uint8_t *ret_mac = resp + msg_len; uint8_t calc_mac[4] = {0}; - bool mac_ok; if (key_len == 8) { - mac_ok = fmcos_des_mac(resp, (size_t)msg_len, key, mac_iv, calc_mac, 4); + res = fmcos_des_mac(resp, (size_t)msg_len, key, mac_iv, calc_mac, 4); } else { - mac_ok = fmcos_3des_mac(resp, (size_t)msg_len, key, mac_iv, calc_mac, 4); + res = fmcos_3des_mac(resp, (size_t)msg_len, key, mac_iv, calc_mac, 4); } - if (!mac_ok) { - return PM3_EMALLOC; + if (res != PM3_SUCCESS) { + return res; } if (memcmp(calc_mac, ret_mac, 4) != 0) { @@ -1300,9 +1298,10 @@ static int CmdHFFmcosCreateDir(const char *Cmd) { int id_len = 0; CLIGetHexWithReturn(ctx, 1, id_buf, &id_len); int space; - if (!fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &space)) { + int res = fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &space); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t cperm[1] = {0}; int cperm_len = 0; @@ -1439,15 +1438,17 @@ static int CmdHFFmcosCreateFile(const char *Cmd) { int id_len = 0; CLIGetHexWithReturn(ctx, 1, id_buf, &id_len); int ftype = 0; - if (CLIGetOptionList(arg_get_str(ctx, 2), g_fmcos_filetype_opts, &ftype)) { + int res = CLIGetOptionList(arg_get_str(ctx, 2), g_fmcos_filetype_opts, &ftype); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } int size; - if (!fmcos_parse_hex_int(arg_get_str(ctx, 3)->sval[0], &size)) { + res = fmcos_parse_hex_int(arg_get_str(ctx, 3)->sval[0], &size); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t rperm[1] = {0}; int rperm_len = 0; @@ -1459,9 +1460,10 @@ static int CmdHFFmcosCreateFile(const char *Cmd) { int access_len = 0; CLIGetHexWithReturn(ctx, 6, access, &access_len); int prot = FMCOS_PROT_NONE; - if (CLIGetOptionList(arg_get_str(ctx, 7), g_fmcos_prot_opts, &prot)) { + res = CLIGetOptionList(arg_get_str(ctx, 7), g_fmcos_prot_opts, &prot); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } bool keep = arg_get_lit(ctx, 8); @@ -1552,9 +1554,10 @@ static int CmdHFFmcosCreateKeyfile(const char *Cmd) { int id_len = 0; CLIGetHexWithReturn(ctx, 1, id_buf, &id_len); int space; - if (!fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &space)) { + int res = fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &space); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t dfsid[1] = {0}; int dfsid_len = 0; @@ -1656,9 +1659,10 @@ static int CmdHFFmcosReadBinary(const char *Cmd) { CLIGetHexWithReturn(ctx, 2, p2b, &p2_len); int rlen = arg_get_int_def(ctx, 3, 0); int prot = FMCOS_PROT_NONE; - if (CLIGetOptionList(arg_get_str(ctx, 4), g_fmcos_prot_opts, &prot)) { + int res = CLIGetOptionList(arg_get_str(ctx, 4), g_fmcos_prot_opts, &prot); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t key[16] = {0}; @@ -1727,9 +1731,10 @@ static int CmdHFFmcosReadRecord(const char *Cmd) { CLIGetHexWithReturn(ctx, 2, fid_buf, &fid_len); int rlen = arg_get_int_def(ctx, 3, 0); int prot = FMCOS_PROT_NONE; - if (CLIGetOptionList(arg_get_str(ctx, 4), g_fmcos_prot_opts, &prot)) { + int res = CLIGetOptionList(arg_get_str(ctx, 4), g_fmcos_prot_opts, &prot); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t key[16] = {0}; int key_len = 0; @@ -1818,9 +1823,10 @@ static int CmdHFFmcosWriteBinary(const char *Cmd) { int wdata_len = 0; CLIGetHexWithReturn(ctx, 3, wdata, &wdata_len); int prot = FMCOS_PROT_NONE; - if (CLIGetOptionList(arg_get_str(ctx, 4), g_fmcos_prot_opts, &prot)) { + int res = CLIGetOptionList(arg_get_str(ctx, 4), g_fmcos_prot_opts, &prot); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t key[16] = {0}; int key_len = 0; @@ -1906,9 +1912,10 @@ static int CmdHFFmcosWriteRecord(const char *Cmd) { int wdata_len = 0; CLIGetHexWithReturn(ctx, 3, wdata, &wdata_len); int prot = FMCOS_PROT_NONE; - if (CLIGetOptionList(arg_get_str(ctx, 4), g_fmcos_prot_opts, &prot)) { + int res = CLIGetOptionList(arg_get_str(ctx, 4), g_fmcos_prot_opts, &prot); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t key[16] = {0}; int key_len = 0; @@ -2013,9 +2020,10 @@ static int CmdHFFmcosAppend(const char *Cmd) { int wdata_len = 0; CLIGetHexWithReturn(ctx, 2, wdata, &wdata_len); int prot = FMCOS_PROT_NONE; - if (CLIGetOptionList(arg_get_str(ctx, 3), g_fmcos_prot_opts, &prot)) { + int res = CLIGetOptionList(arg_get_str(ctx, 3), g_fmcos_prot_opts, &prot); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t key[16] = {0}; int key_len = 0; @@ -2130,9 +2138,10 @@ static int CmdHFFmcosWriteKey(const char *Cmd) { int id_len = 0; CLIGetHexWithReturn(ctx, 2, id_buf, &id_len); int ktype = 0; - if (CLIGetOptionList(arg_get_str(ctx, 3), g_fmcos_keytype_opts, &ktype)) { + int res = CLIGetOptionList(arg_get_str(ctx, 3), g_fmcos_keytype_opts, &ktype); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t usage_b[1] = {0}; int usage_len = 0; @@ -2159,9 +2168,10 @@ static int CmdHFFmcosWriteKey(const char *Cmd) { int authkey_len = 0; CLIGetHexWithReturn(ctx, 11, authkey, &authkey_len); int prot = FMCOS_PROT_NONE; - if (CLIGetOptionList(arg_get_str(ctx, 12), g_fmcos_prot_opts, &prot)) { + res = CLIGetOptionList(arg_get_str(ctx, 12), g_fmcos_prot_opts, &prot); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } bool keep = arg_get_lit(ctx, 13); bool apdu_log = arg_get_lit(ctx, 14); @@ -2507,8 +2517,9 @@ static int CmdHFFmcosPinReset(const char *Cmd) { // MAC = DES-CBC-MAC(new_pin, mac_key, iv=0) uint8_t zero_iv[8] = {0}; uint8_t mac[4] = {0}; - if (!fmcos_des_mac(pin, (size_t)pin_len, mac_key, zero_iv, mac, 4)) { - return PM3_EMALLOC; + int res = fmcos_des_mac(pin, (size_t)pin_len, mac_key, zero_iv, mac, 4); + if (res != PM3_SUCCESS) { + return res; } // Data = new_pin + mac[4] @@ -2527,7 +2538,7 @@ static int CmdHFFmcosPinReset(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_send_apdu(apdu, 5 + data_len, true, keep, resp, &resp_len); + res = fmcos_send_apdu(apdu, 5 + data_len, true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -2622,12 +2633,13 @@ static int CmdHFFmcosPinUnblock(const char *Cmd) { } uint8_t mac[4] = {0}; - if (!fmcos_packet_mac(0x84, 0x24, id_buf[0], 0x00, - enc_data, enc_len, chal, key, (size_t)key_len, mac)) { + res = fmcos_packet_mac(0x84, 0x24, id_buf[0], 0x00, + enc_data, enc_len, chal, key, (size_t)key_len, mac); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } // Build data = enc_data + mac @@ -2717,18 +2729,19 @@ static int CmdHFFmcosBalance(const char *Cmd) { CLIParserFree(ctx); if (res != PM3_SUCCESS) { - return PM3_EINVARG; + return res; } uint8_t apdu[5] = {0x80, 0x5C, 0x00, (uint8_t)bal_type, 0x04}; uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + res = fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { @@ -2778,10 +2791,15 @@ static int CmdHFFmcosCredit(const char *Cmd) { int bal_type = 0; int res = CLIGetOptionList(arg_get_str(ctx, 1), g_fmcos_baltype_opts, &bal_type); - int key_id; - if (!fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &key_id)) { + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; + } + int key_id = 0; + res = fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &key_id); + if (res != PM3_SUCCESS) { + CLIParserFree(ctx); + return res; } int amount_i = arg_get_int(ctx, 3); @@ -2800,10 +2818,6 @@ static int CmdHFFmcosCredit(const char *Cmd) { bool keep = arg_get_lit(ctx, 7); CLIParserFree(ctx); - if (res != PM3_SUCCESS) { - return PM3_EINVARG; - } - if (key_id < 0 || key_id > 0xFF) { PrintAndLogEx(ERR, "Key ID must be 0-255"); return PM3_EINVARG; @@ -2847,12 +2861,13 @@ static int CmdHFFmcosCredit(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len) != PM3_SUCCESS) { + res = fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len); + if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } // Response: old_balance[4] online_serial[2] key_ver[1] algo[1] random_1[4] mac_1[4] SW[2] @@ -2909,12 +2924,13 @@ static int CmdHFFmcosCredit(const char *Cmd) { uint8_t zero_iv[8] = {0}; uint8_t mac1_calc[4] = {0}; - if (!fmcos_des_mac(mac1_buf, 15, process_key, zero_iv, mac1_calc, 4)) { + res = fmcos_des_mac(mac1_buf, 15, process_key, zero_iv, mac1_calc, 4); + if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } if (memcmp(mac1_calc, resp + 12, 4) != 0) { @@ -2942,12 +2958,13 @@ static int CmdHFFmcosCredit(const char *Cmd) { memcpy(mac2_buf + 15, ttime, 3); uint8_t mac2[4] = {0}; - if (!fmcos_des_mac(mac2_buf, 18, process_key, zero_iv, mac2, 4)) { + res = fmcos_des_mac(mac2_buf, 18, process_key, zero_iv, mac2, 4); + if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } // ---- Phase 2: CREDIT (INS 52) ---- @@ -2965,11 +2982,12 @@ static int CmdHFFmcosCredit(const char *Cmd) { memset(resp, 0, sizeof(resp)); resp_len = 0; - if (fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len) != PM3_SUCCESS) { + res = fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } // Response: TAC[4] SW[2] @@ -3007,11 +3025,12 @@ static int CmdHFFmcosCredit(const char *Cmd) { memcpy(tac_buf + 6, mac2_buf, 18); uint8_t tac_calc[4] = {0}; - if (!fmcos_des_mac(tac_buf, 24, tac_key, zero_iv, tac_calc, 4)) { + res = fmcos_des_mac(tac_buf, 24, tac_key, zero_iv, tac_calc, 4); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } if (memcmp(tac_calc, resp, 4) != 0) { @@ -3053,10 +3072,15 @@ static int CmdHFFmcosPurchase(const char *Cmd) { int bal_type = 0; int res = CLIGetOptionList(arg_get_str(ctx, 1), g_fmcos_baltype_opts, &bal_type); - int key_id; - if (!fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &key_id)) { + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; + } + int key_id = 0; + res = fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &key_id); + if (res != PM3_SUCCESS) { + CLIParserFree(ctx); + return res; } int amount_i = arg_get_int(ctx, 3); @@ -3079,10 +3103,6 @@ static int CmdHFFmcosPurchase(const char *Cmd) { bool keep = arg_get_lit(ctx, 8); CLIParserFree(ctx); - if (res != PM3_SUCCESS) { - return PM3_EINVARG; - } - if (key_id < 0 || key_id > 0xFF) { PrintAndLogEx(ERR, "Key ID must be 0-255"); return PM3_EINVARG; @@ -3131,12 +3151,13 @@ static int CmdHFFmcosPurchase(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len) != PM3_SUCCESS) { + res = fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len); + if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } // Response: old_balance[4] offline_serial[2] overdraft_lim[3] key_ver[1] algo[1] random_1[4] SW[2] @@ -3198,12 +3219,13 @@ static int CmdHFFmcosPurchase(const char *Cmd) { uint8_t zero_iv[8] = {0}; uint8_t mac1[4] = {0}; - if (!fmcos_des_mac(mac1_buf, 18, process_key, zero_iv, mac1, 4)) { + res = fmcos_des_mac(mac1_buf, 18, process_key, zero_iv, mac1, 4); + if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } // ---- Phase 2: DEBIT (INS 54, P1 01, P2 00) ---- @@ -3222,11 +3244,12 @@ static int CmdHFFmcosPurchase(const char *Cmd) { memset(resp, 0, sizeof(resp)); resp_len = 0; - if (fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len) != PM3_SUCCESS) { + res = fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } // Response: TAC[4] mac2_card[4] SW[2] @@ -3267,11 +3290,12 @@ static int CmdHFFmcosPurchase(const char *Cmd) { memcpy(tac_buf + 19, ttime, 3); uint8_t tac_calc[4] = {0}; - if (!fmcos_des_mac(tac_buf, 22, tac_key, zero_iv, tac_calc, 4)) { + res = fmcos_des_mac(tac_buf, 22, tac_key, zero_iv, tac_calc, 4); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } if (memcmp(tac_calc, resp, 4) != 0) { @@ -3310,9 +3334,10 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); int key_id; - if (!fmcos_parse_hex_int(arg_get_str(ctx, 1)->sval[0], &key_id)) { + int res = fmcos_parse_hex_int(arg_get_str(ctx, 1)->sval[0], &key_id); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } int limit_i = arg_get_int(ctx, 2); @@ -3370,12 +3395,13 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len) != PM3_SUCCESS) { + int res = fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len); + if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } // Response: old_balance[4] online_serial[2] old_od_limit[3] key_ver[1] algo[1] random_1[4] card_mac1[4] SW[2] @@ -3431,12 +3457,13 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { uint8_t zero_iv[8] = {0}; uint8_t mac1_calc[4] = {0}; - if (!fmcos_des_mac(mac1_buf, 14, process_key, zero_iv, mac1_calc, 4)) { + res = fmcos_des_mac(mac1_buf, 14, process_key, zero_iv, mac1_calc, 4); + if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } if (memcmp(mac1_calc, resp + 15, 4) != 0) { @@ -3463,12 +3490,13 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { memcpy(mac2_buf + 14, ttime, 3); uint8_t mac2[4] = {0}; - if (!fmcos_des_mac(mac2_buf, 17, process_key, zero_iv, mac2, 4)) { + res = fmcos_des_mac(mac2_buf, 17, process_key, zero_iv, mac2, 4); + if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } // ---- Phase 2: UPDATE OVERDRAFT (INS 58, P1 00, P2 00) ---- @@ -3489,11 +3517,12 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { memset(resp, 0, sizeof(resp)); resp_len = 0; - if (fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len) != PM3_SUCCESS) { + res = fmcos_send_apdu(ph2, sizeof(ph2), false, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { @@ -3545,11 +3574,12 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { memcpy(tac_buf + 20, ttime, 3); uint8_t tac_calc[4] = {0}; - if (!fmcos_des_mac(tac_buf, 23, tac_key, zero_iv, tac_calc, 4)) { + res = fmcos_des_mac(tac_buf, 23, tac_key, zero_iv, tac_calc, 4); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } if (memcmp(tac_calc, resp, 4) != 0) { @@ -3641,11 +3671,12 @@ static int CmdHFFmcosBlock(const char *Cmd) { uint8_t p1 = 0x00; uint8_t mac[4] = {0}; - if (!fmcos_packet_mac(cla, ins, p1, p2, NULL, 0, chal, key, (size_t)key_len, mac)) { + res = fmcos_packet_mac(cla, ins, p1, p2, NULL, 0, chal, key, (size_t)key_len, mac); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } uint8_t apdu[9]; @@ -3738,11 +3769,12 @@ static int CmdHFFmcosUnblock(const char *Cmd) { // APP UNBLOCK: CLA=84 INS=18 P1=00 P2=00 uint8_t mac[4] = {0}; - if (!fmcos_packet_mac(0x84, 0x18, 0x00, 0x00, NULL, 0, chal, key, (size_t)key_len, mac)) { + res = fmcos_packet_mac(0x84, 0x18, 0x00, 0x00, NULL, 0, chal, key, (size_t)key_len, mac); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_EMALLOC; + return res; } uint8_t apdu[9]; @@ -3962,11 +3994,12 @@ static int CmdHFFmcosTidSetCard(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + int res = fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { @@ -4018,11 +4051,12 @@ static int CmdHFFmcosTidSetUID(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(apdu, 5 + (size_t)uid_len, true, keep, resp, &resp_len) != PM3_SUCCESS) { + int res = fmcos_send_apdu(apdu, 5 + (size_t)uid_len, true, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { @@ -4080,11 +4114,12 @@ static int CmdHFFmcosTidSetAuth(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + int res = fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { @@ -4127,11 +4162,12 @@ static int CmdHFFmcosTidErase(const char *Cmd) { uint8_t apdu[5] = {0xE0, 0xEC, 0x00, 0x00, 0x00}; uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + int res = fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { @@ -4297,9 +4333,10 @@ static int CmdHFFmcosTidCreateDF(const char *Cmd) { int id_len = 0; CLIGetHexWithReturn(ctx, 1, id_buf, &id_len); int size; - if (!fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &size)) { + int res = fmcos_parse_hex_int(arg_get_str(ctx, 2)->sval[0], &size); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } uint8_t sfi_buf[1] = {0}; int sfi_len = 0; @@ -4336,11 +4373,12 @@ static int CmdHFFmcosTidCreateDF(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(apdu, 14 + (size_t)name_len, true, keep, resp, &resp_len) != PM3_SUCCESS) { + int res = fmcos_send_apdu(apdu, 14 + (size_t)name_len, true, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { if (!keep) { @@ -4390,9 +4428,10 @@ static int CmdHFFmcosTidCreateBin(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); int ftype = 0; - if (CLIGetOptionList(arg_get_str(ctx, 1), g_fmcos_tid_create_opts, &ftype)) { + int res = CLIGetOptionList(arg_get_str(ctx, 1), g_fmcos_tid_create_opts, &ftype); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } bool is_keyfile = (ftype == 1); @@ -4401,9 +4440,10 @@ static int CmdHFFmcosTidCreateBin(const char *Cmd) { CLIGetHexWithReturn(ctx, 2, id_buf, &id_len); int size = 0; if (arg_get_str(ctx, 3)->count > 0) { - if (!fmcos_parse_hex_int(arg_get_str(ctx, 3)->sval[0], &size)) { + res = fmcos_parse_hex_int(arg_get_str(ctx, 3)->sval[0], &size); + if (res != PM3_SUCCESS) { CLIParserFree(ctx); - return PM3_EINVARG; + return res; } } uint8_t sfi_buf[1] = {0}; @@ -4458,11 +4498,12 @@ static int CmdHFFmcosTidCreateBin(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + int res = fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { if (!keep) { @@ -4560,11 +4601,12 @@ static int CmdHFFmcosTidCreateRec(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - if (fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len) != PM3_SUCCESS) { + int res = fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len); + if (res != PM3_SUCCESS) { if (!keep) { DropField(); } - return PM3_ESOFT; + return res; } if (resp_len < 2) { if (!keep) { From 57986fd141df8e849fbf496c3968359b7d33092c Mon Sep 17 00:00:00 2001 From: klks Date: Mon, 25 May 2026 20:40:08 +0800 Subject: [PATCH 3/4] fix compile issue --- client/src/cmdhffmcos.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/client/src/cmdhffmcos.c b/client/src/cmdhffmcos.c index 98ba9e3b4..268fe58c1 100644 --- a/client/src/cmdhffmcos.c +++ b/client/src/cmdhffmcos.c @@ -882,7 +882,7 @@ static int CmdHFFmcosAuthExternal(const char *Cmd) { // GET CHALLENGE (8 bytes) - activates the field uint8_t challenge[8] = {0}; - int res = fmcos_get_challenge(8, true, challenge); + res = fmcos_get_challenge(8, true, challenge); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -1358,7 +1358,7 @@ static int CmdHFFmcosCreateDir(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_send_apdu(apdu, 5 + data_len, true, keep, resp, &resp_len); + res = fmcos_send_apdu(apdu, 5 + data_len, true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -1506,7 +1506,7 @@ static int CmdHFFmcosCreateFile(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_send_apdu(apdu, 12, true, keep, resp, &resp_len); + res = fmcos_send_apdu(apdu, 12, true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -1599,7 +1599,7 @@ static int CmdHFFmcosCreateKeyfile(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_send_apdu(apdu, 12, true, keep, resp, &resp_len); + res = fmcos_send_apdu(apdu, 12, true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -1690,7 +1690,7 @@ static int CmdHFFmcosReadBinary(const char *Cmd) { uint8_t data_out[256] = {0}; int data_out_len = 0; - int res = fmcos_read_cmd(0xB0, p1b[0], p2b[0], (uint8_t)rlen, + res = fmcos_read_cmd(0xB0, p1b[0], p2b[0], (uint8_t)rlen, prot, key, (size_t)key_len, true, keep, data_out, &data_out_len); if (res == PM3_SUCCESS) { @@ -1769,7 +1769,7 @@ static int CmdHFFmcosReadRecord(const char *Cmd) { uint8_t p2 = (uint8_t)(((fid_buf[0] & 0x1F) << 3) | 4); uint8_t data_out[256] = {0}; int data_out_len = 0; - int res = fmcos_read_cmd(0xB2, (uint8_t)rec, p2, (uint8_t)le, + res = fmcos_read_cmd(0xB2, (uint8_t)rec, p2, (uint8_t)le, prot, key, (size_t)key_len, true, keep, data_out, &data_out_len); if (res == PM3_SUCCESS) { @@ -1851,7 +1851,7 @@ static int CmdHFFmcosWriteBinary(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_write_cmd(0x00, 0xD6, p1b[0], p2b[0], + res = fmcos_write_cmd(0x00, 0xD6, p1b[0], p2b[0], wdata, (size_t)wdata_len, prot, key, (size_t)key_len, true, keep, resp, &resp_len); @@ -1963,7 +1963,7 @@ static int CmdHFFmcosWriteRecord(const char *Cmd) { uint8_t p2 = (uint8_t)(((fid_buf[0] & 0x1F) << 3) | 4); uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_write_cmd(0x00, 0xDC, (uint8_t)rec, p2, + res = fmcos_write_cmd(0x00, 0xDC, (uint8_t)rec, p2, send_buf, send_len, prot, key, (size_t)key_len, true, keep, resp, &resp_len); @@ -2050,7 +2050,7 @@ static int CmdHFFmcosAppend(const char *Cmd) { uint8_t p2 = (uint8_t)(((fid_buf[0] & 0x1F) << 3) | 4); uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_write_cmd(0x00, 0xE2, 0x00, p2, + res = fmcos_write_cmd(0x00, 0xE2, 0x00, p2, wdata, (size_t)wdata_len, prot, key, (size_t)key_len, true, keep, resp, &resp_len); @@ -2258,7 +2258,7 @@ static int CmdHFFmcosWriteKey(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_write_cmd(0x80, 0xD4, op_buf[0], id_buf[0], + res = fmcos_write_cmd(0x80, 0xD4, op_buf[0], id_buf[0], data, data_len, prot, authkey, (size_t)authkey_len, true, keep, resp, &resp_len); @@ -3395,7 +3395,7 @@ static int CmdHFFmcosOverdraft(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len); + res = fmcos_send_apdu(ph1, sizeof(ph1), true, true, resp, &resp_len); if (res != PM3_SUCCESS) { g_fmcos_session_active = keep; if (!keep) { @@ -4373,7 +4373,7 @@ static int CmdHFFmcosTidCreateDF(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_send_apdu(apdu, 14 + (size_t)name_len, true, keep, resp, &resp_len); + res = fmcos_send_apdu(apdu, 14 + (size_t)name_len, true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -4498,7 +4498,7 @@ static int CmdHFFmcosTidCreateBin(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; - int res = fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len); + res = fmcos_send_apdu(apdu, sizeof(apdu), true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); From ad6faf003d2d8f471e49260a60651b812513b609 Mon Sep 17 00:00:00 2001 From: klks Date: Mon, 25 May 2026 20:52:51 +0800 Subject: [PATCH 4/4] Make style fix --- client/src/cmdhffmcos.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/client/src/cmdhffmcos.c b/client/src/cmdhffmcos.c index 268fe58c1..02972c914 100644 --- a/client/src/cmdhffmcos.c +++ b/client/src/cmdhffmcos.c @@ -1691,8 +1691,8 @@ static int CmdHFFmcosReadBinary(const char *Cmd) { uint8_t data_out[256] = {0}; int data_out_len = 0; res = fmcos_read_cmd(0xB0, p1b[0], p2b[0], (uint8_t)rlen, - prot, key, (size_t)key_len, - true, keep, data_out, &data_out_len); + prot, key, (size_t)key_len, + true, keep, data_out, &data_out_len); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Data: " _GREEN_("%s"), sprint_hex(data_out, (size_t)data_out_len)); } @@ -1770,8 +1770,8 @@ static int CmdHFFmcosReadRecord(const char *Cmd) { uint8_t data_out[256] = {0}; int data_out_len = 0; res = fmcos_read_cmd(0xB2, (uint8_t)rec, p2, (uint8_t)le, - prot, key, (size_t)key_len, - true, keep, data_out, &data_out_len); + prot, key, (size_t)key_len, + true, keep, data_out, &data_out_len); if (res == PM3_SUCCESS) { uint8_t *payload = data_out; int payload_len = data_out_len; @@ -1852,9 +1852,9 @@ static int CmdHFFmcosWriteBinary(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; res = fmcos_write_cmd(0x00, 0xD6, p1b[0], p2b[0], - wdata, (size_t)wdata_len, - prot, key, (size_t)key_len, - true, keep, resp, &resp_len); + wdata, (size_t)wdata_len, + prot, key, (size_t)key_len, + true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -1964,9 +1964,9 @@ static int CmdHFFmcosWriteRecord(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; res = fmcos_write_cmd(0x00, 0xDC, (uint8_t)rec, p2, - send_buf, send_len, - prot, key, (size_t)key_len, - true, keep, resp, &resp_len); + send_buf, send_len, + prot, key, (size_t)key_len, + true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -2051,9 +2051,9 @@ static int CmdHFFmcosAppend(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; res = fmcos_write_cmd(0x00, 0xE2, 0x00, p2, - wdata, (size_t)wdata_len, - prot, key, (size_t)key_len, - true, keep, resp, &resp_len); + wdata, (size_t)wdata_len, + prot, key, (size_t)key_len, + true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField(); @@ -2259,9 +2259,9 @@ static int CmdHFFmcosWriteKey(const char *Cmd) { uint8_t resp[APDU_RES_LEN] = {0}; int resp_len = 0; res = fmcos_write_cmd(0x80, 0xD4, op_buf[0], id_buf[0], - data, data_len, - prot, authkey, (size_t)authkey_len, - true, keep, resp, &resp_len); + data, data_len, + prot, authkey, (size_t)authkey_len, + true, keep, resp, &resp_len); if (res != PM3_SUCCESS) { if (!keep) { DropField();