diff --git a/armsrc/cmac_calc.c b/armsrc/cmac_calc.c index 57df15806..f10a2af01 100644 --- a/armsrc/cmac_calc.c +++ b/armsrc/cmac_calc.c @@ -23,6 +23,8 @@ #include "BigBuf.h" #include "dbprint.h" #include "mbedtls/aes.h" +#include "pm3_cmd.h" +#include "iso14443a.h" static ulaes_key_t g_secure_session = { .counter = 0, @@ -173,3 +175,27 @@ void append_cmac(uint8_t *d, size_t n) { increase_session_counter(); } + +int verify_cmac(uint8_t *d, size_t n, bool verify_crc) { + // n = data size without cmac and without crc + uint8_t chk_d[n + ULAES_CMAC8_SIZE + 2]; + memcpy(chk_d, d, n); + memset(chk_d + n, 0, sizeof(chk_d) - n); + append_cmac(chk_d, n); + if (memcmp(chk_d + n, d + n, ULAES_CMAC8_SIZE) != 0) { + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("CMAC response error."); + } + return PM3_ECRC; + } + if (verify_crc) { + AddCrc14A(chk_d, n + ULAES_CMAC8_SIZE); + if (memcmp(chk_d + n + ULAES_CMAC8_SIZE, d + n + ULAES_CMAC8_SIZE, 2) != 0) { + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("CRC response error."); + } + return PM3_ECRC; + } + } + return PM3_SUCCESS; +} diff --git a/armsrc/cmac_calc.h b/armsrc/cmac_calc.h index 157a8359c..cfda9dc3a 100644 --- a/armsrc/cmac_calc.h +++ b/armsrc/cmac_calc.h @@ -23,6 +23,8 @@ #include "common.h" +#define ULAES_CMAC8_SIZE 8 + typedef struct { bool use_schann; uint8_t cmac_sk1[16]; @@ -41,5 +43,6 @@ bool get_session_channel(void); void ulaes_cmac(const uint8_t *key, size_t key_len, const uint8_t *input, size_t ilen, uint8_t output[16]); void ulaes_cmac8(uint8_t *cmac, uint8_t *mac); void append_cmac(uint8_t *d, size_t n); +int verify_cmac(uint8_t *d, size_t n, bool verify_crc); #endif diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 60063a23b..7bcd8d5c3 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -868,7 +868,7 @@ void MifareUSetKey(mful_setkey_t *packet) { if (iso14443a_select_card(NULL, NULL, NULL, true, 0, true) == 0) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); - OnError(0); + OnErrorNG(CMD_HF_MIFAREU_SETKEY, PM3_ESOFT); return; }; diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index bb32f89fa..7abd45f9b 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -595,48 +595,54 @@ static int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) { uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; uint16_t len = 0; - uint8_t offset = 0; if (get_session_channel()) { - offset = 8; - uint8_t cmd[2 + 8] = { ISO14443A_CMD_READBLOCK, blockNo }; + uint8_t cmd[2 + ULAES_CMAC8_SIZE] = { ISO14443A_CMD_READBLOCK, blockNo }; append_cmac(cmd, 2); len = mifare_sendcmd_schann(cmd, sizeof(cmd), receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, NULL); + if (len != 16 + ULAES_CMAC8_SIZE + 2) { + if (len == 1) { + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + } + return PM3_ECARDEXCHANGE; + } else { + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Cmd Error: card timeout. len: %x", len); + } + return PM3_ETIMEOUT; + } + } + int ret = verify_cmac(receivedAnswer, 16, true); + if (ret != PM3_SUCCESS) { + return ret; + } } else { len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, NULL); - } - - if (len == 1) { - if (g_dbglevel >= DBG_ERROR) { - Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if (len != 16 + 2) { + if (len == 1) { + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + } + return PM3_ECARDEXCHANGE; + } else { + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Cmd Error: card timeout. len: %x", len); + } + return PM3_ETIMEOUT; + } } - return PM3_ECARDEXCHANGE; - } - - // Ev1 / Ul-C == 18 bytes response - // UL-Aes in secure messaging == 26 - if (len != 18 + offset) { - if (g_dbglevel >= DBG_ERROR) { - Dbprintf("Cmd Error: card timeout. len: %x", len); + uint8_t bt[2] = {0x00, 0x00}; + memcpy(bt, receivedAnswer + 16, 2); + AddCrc14A(receivedAnswer, 16); + if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Cmd CRC response error."); + return PM3_ECRC; + } } - return PM3_ETIMEOUT; } - uint8_t bt[2] = {0x00, 0x00}; - memcpy(bt, receivedAnswer + 16 + offset, 2); - AddCrc14A(receivedAnswer, 16 + offset); - if (bt[0] != receivedAnswer[16 + offset] || bt[1] != receivedAnswer[17 + offset]) { - if (g_dbglevel >= DBG_ERROR) { - Dbprintf("Cmd CRC response error."); - } - return PM3_ECRC; - } - - // we are skipping verifying the cmac since we don't care. - - // increase counter for the read response - increase_session_counter(); - memcpy(blockData, receivedAnswer, 16); return PM3_SUCCESS; } @@ -822,21 +828,20 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) { uint16_t len = 0; if (get_session_channel()) { - uint8_t cmd[2 + 4 + 8] = { MIFARE_ULC_WRITE, blockNo }; + uint8_t cmd[2 + 4 + ULAES_CMAC8_SIZE] = { MIFARE_ULC_WRITE, blockNo }; memcpy(cmd + 2, blockData, 4); append_cmac(cmd, 2 + 4); len = mifare_sendcmd_schann(cmd, sizeof(cmd), receivedAnswer, sizeof(receivedAnswer), receivedAnswerPar, NULL); - // we are skipping verifying the cmac, since we don't care. - // increase counter for the write response - increase_session_counter(); - - if (len != 10) { + if (len != ULAES_CMAC8_SIZE + 2) { if (g_dbglevel >= DBG_INFO) { Dbprintf("Cmd Send Error: " _RED_("%d"), len); } return PM3_EFAILED; } - + int ret = verify_cmac(receivedAnswer, 0, true); + if (ret != PM3_SUCCESS) { + return ret; + } } else { // command MIFARE_CLASSIC_WRITEBLOCK diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 7805bea67..29590f87a 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -1459,27 +1459,31 @@ static int ulev1_print_configuration(uint64_t tagtype, uint8_t *data, uint8_t st return PM3_SUCCESS; } -static int ulev1_print_counters(void) { +static int ulev1_print_counters(uint64_t tagtype, bool use_schann) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Counters")); uint8_t tear[1] = {0}; uint8_t counter[3] = {0, 0, 0}; int len = 0; for (uint8_t i = 0; i < 3; ++i) { - ulev1_readTearing(i, tear, sizeof(tear)); - len = ulev1_readCounter(i, counter, sizeof(counter), false); + len = ulev1_readCounter(i, counter, sizeof(counter), use_schann); if (len == 3) { PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3)); - PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )" - , tear[0] - , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") - ); + if ((tagtype & MFU_TT_UL_AES) != MFU_TT_UL_AES) { + ulev1_readTearing(i, tear, sizeof(tear)); + PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )" + , tear[0] + , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") + ); + } } } return len; } static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); int index = -1; if (signature_len == 32) { index = originality_check_verify(uid, 7, signature, signature_len, PK_MFUL); @@ -2618,13 +2622,13 @@ static int CmdHF14AMfUInfo(const char *Cmd) { } } - // do counters and signature first (don't neet auth) + // do counters and signature first (don't need auth) // ul counters are different than ntag counters if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_AES))) { - if (ulev1_print_counters() != 3) { + if (ulev1_print_counters(tagtype, use_schann) != 3) { // failed - re-select - if (ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, pack, sizeof(pack), false) == PM3_ESOFT) { + if (ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, pack, sizeof(pack), use_schann) == PM3_ESOFT) { return PM3_ESOFT; } } @@ -3631,7 +3635,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { if (has_auth_key) { uint8_t dummy_pack[] = {0, 0}; - ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), false); + ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), use_schann); } else { ul_select(&card); } @@ -3651,11 +3655,11 @@ static int CmdHF14AMfUDump(const char *Cmd) { if (has_auth_key) { uint8_t dummy_pack[] = {0, 0}; - ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), false); + ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), use_schann); } else { ul_select(&card); } - ulev1_readCounter(n, &get_counter_tearing[n][0], 3, false); + ulev1_readCounter(n, &get_counter_tearing[n][0], 3, use_schann); if (has_auth_key) { uint8_t dummy_pack[] = {0, 0}; @@ -3670,12 +3674,12 @@ static int CmdHF14AMfUDump(const char *Cmd) { if (has_auth_key) { uint8_t dummy_pack[] = {0, 0}; - ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), false); + ul_auth_select(&card, tagtype, has_auth_key, auth_key_ptr, dummy_pack, sizeof(dummy_pack), use_schann); } else { ul_select(&card); } - ulev1_readSignature(get_signature, sizeof(get_signature), false); + ulev1_readSignature(get_signature, sizeof(get_signature), use_schann); DropField(); } @@ -5023,6 +5027,7 @@ static int CmdHF14AMfUSetKey(const char *Cmd) { SendCommandNG(CMD_HF_MIFAREU_SETKEY, (uint8_t *)&packet, sizeof(packet)); if (WaitForResponseTimeout(CMD_HF_MIFAREU_SETKEY, &resp, 1500) == false) { + PrintAndLogEx(WARNING, "command execution time out"); return PM3_ETIMEOUT; } if (resp.status == PM3_SUCCESS) { diff --git a/client/src/crypto/originality.c b/client/src/crypto/originality.c index 08891576f..38e209ae7 100644 --- a/client/src/crypto/originality.c +++ b/client/src/crypto/originality.c @@ -195,8 +195,6 @@ int originality_check_verify_ex(uint8_t *data, uint8_t data_len, uint8_t *signat int originality_check_print(uint8_t *signature, int signature_len, int index) { - PrintAndLogEx(NORMAL, ""); - if ((index < 0) || (index >= ARRAYLEN(manufacturer_public_keys))) { PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));