diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ce6d79dbb..849bfcb2b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1866,6 +1866,17 @@ static void PacketReceived(PacketCommandNG *packet) { MifareHasStaticNonce(); break; } + case CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE: { + struct p { + uint8_t block_no; + uint8_t key_type; + uint8_t key[6]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + + MifareHasStaticEncryptedNonce(payload->block_no, payload->key_type, payload->key); + break; + } #endif #ifdef WITH_NFCBARCODE diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 32e90d56a..1f0683599 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -90,7 +90,7 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c goto OUT; } - if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) { + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); retval = PM3_ESOFT; goto OUT; @@ -158,7 +158,7 @@ int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write goto OUT; }; - if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) { + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); retval = PM3_ESOFT; goto OUT; @@ -2681,6 +2681,73 @@ OUT: // 2B F9 1C 1B D5 08 48 48 03 A4 B1 B1 75 FF 2D 90 // ^^ ^^ +void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *key) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + clear_trace(); + set_tracing(true); + + int retval = PM3_SUCCESS; + uint8_t *uid = BigBuf_malloc(10); + memset(uid, 0x00, 10); + + uint8_t data[1] = { NONCE_FAIL }; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + uint64_t ui64key = bytes_to_num(key, 6); + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + iso14a_card_select_t card_info; + uint32_t cuid = 0; + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + retval = PM3_ESOFT; + goto OUT; + } + + uint8_t key_auth_cmd = MIFARE_AUTH_KEYA + (key_type & 1); + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL, NULL)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); + retval = PM3_ESOFT; + goto OUT; + }; + + uint32_t nt = 0; + uint8_t enc_counter = 0; + uint32_t ntenc = 0; + uint32_t oldntenc = 0; + for (uint8_t i = 0; i < 3; i++) { + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_NESTED, &nt, &ntenc, NULL)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); + retval = PM3_ESOFT; + goto OUT; + }; + + if (g_dbglevel >= DBG_INFO) + Dbprintf("nt: %x, nt encoded: %x", nt, ntenc); + + if (oldntenc == 0) + oldntenc = ntenc; + else if (ntenc == oldntenc) + enc_counter++; + } + + if (enc_counter) { + data[0] = NONCE_STATIC_ENC; + } else { + data[0] = NONCE_NORMAL; + } + +OUT: + crypto1_deinit(pcs); + + reply_ng(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, retval, data, sizeof(data)); + // turns off + OnSuccessMagic(); + BigBuf_free(); +} + void OnSuccessMagic(void) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 52bc37f35..64df74f97 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -49,6 +49,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work wi void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); void MifareCIdent(bool is_mfc); // is "magic chinese" card? void MifareHasStaticNonce(void); // Has the tag a static nonce? +void MifareHasStaticEncryptedNonce(uint8_t block_no, uint8_t key_type, uint8_t *key); // Has the tag a static encrypted nonce? // MFC GEN3 int DoGen3Cmd(uint8_t *cmd, uint8_t cmd_len); diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 581efda8f..3258007e3 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -142,9 +142,9 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); } int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { - return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, ui64Key, isNested, ntptr, timing); + return mifare_classic_authex_cmd(pcs, uid, blockNo, (keyType & 1) ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, ui64Key, isNested, ntptr, NULL, timing); } -int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { +int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *ntencptr, uint32_t *timing) { // "random" reader nonce: uint8_t nr[4]; @@ -159,6 +159,8 @@ int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t bl // Save the tag nonce (nt) uint32_t nt = bytes_to_num(receivedAnswer, 4); + if (ntencptr) + *ntencptr = nt; // ----------------------------- crypto1 create if (isNested) diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 1e45d50be..e7ee0f7f9 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -72,7 +72,7 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t // mifare classic int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); -int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); +int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *ntencptr, uint32_t *timing); int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData); int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 3a400899c..357e1d45e 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -8875,7 +8875,7 @@ static int CmdHF14AMfInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]); PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]); - if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) + if (setDeviceDebugLevel(verbose ? DBG_INFO : DBG_NONE, false) != PM3_SUCCESS) return PM3_EFAILED; PrintAndLogEx(INFO, "--- " _CYAN_("Backdoors Information") "---------------------"); @@ -8951,7 +8951,11 @@ static int CmdHF14AMfInfo(const char *Cmd) { // detect static encrypted nonce if (keyType != 0xff) { - + res = detect_classic_static_encrypted_nonce(0, keyType, key); // TODO: add block number to the config + if (res == NONCE_STATIC) + PrintAndLogEx(SUCCESS, "Static nested nonce: " _YELLOW_("yes")); + if (res == NONCE_STATIC_ENC) + PrintAndLogEx(SUCCESS, "Static encrypted nonce: " _YELLOW_("yes")); } if (do_nack_test) diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index f28f38aaa..8c129b8d9 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1349,6 +1349,33 @@ int detect_classic_static_nonce(void) { return NONCE_FAIL; } +/* Detect Mifare Classic static encrypted nonce +detects special magic cards that has a static / fixed nonce +returns: +0 = nonce ok +1 = has static/fixed nonce +2 = cmd failed +3 = has encrypted nonce +*/ +int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key) { + + clearCommandBuffer(); + uint8_t cdata[1 + 1 + MIFARE_KEY_SIZE] = {0}; + cdata[0] = block_no; + cdata[1] = key_type; + memcpy(&cdata[2], key, MIFARE_KEY_SIZE); + SendCommandNG(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, cdata, sizeof(cdata)); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE, &resp, 1000)) { + + if (resp.status == PM3_ESOFT) + return NONCE_FAIL; + + return resp.data.asBytes[0]; + } + return NONCE_FAIL; +} + /* try to see if card responses to "Chinese magic backdoor" commands. */ int detect_mf_magic(bool is_mfc) { diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 6f131f924..5eacabda3 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -102,6 +102,7 @@ int detect_classic_prng(void); int detect_classic_nackbug(bool verbose); int detect_mf_magic(bool is_mfc); int detect_classic_static_nonce(void); +int detect_classic_static_encrypted_nonce(uint8_t block_no, uint8_t key_type, uint8_t *key); bool detect_mfc_ev1_signature(void); int read_mfc_ev1_signature(uint8_t *signature); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 9189704e4..33803857d 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -675,6 +675,7 @@ typedef struct { #define CMD_HF_MIFARE_NACK_DETECT 0x0730 #define CMD_HF_MIFARE_STATIC_NONCE 0x0731 +#define CMD_HF_MIFARE_STATIC_ENCRYPTED_NONCE 0x0732 // MFU OTP TearOff #define CMD_HF_MFU_OTP_TEAROFF 0x0740 @@ -740,9 +741,10 @@ typedef struct { #define MODE_FULLSIM 2 // Static Nonce detection -#define NONCE_FAIL 0x01 -#define NONCE_NORMAL 0x02 -#define NONCE_STATIC 0x03 +#define NONCE_FAIL 0x01 +#define NONCE_NORMAL 0x02 +#define NONCE_STATIC 0x03 +#define NONCE_STATIC_ENC 0x04 // Dbprintf flags #define FLAG_RAWPRINT 0x00