diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 2382be273..46e9a43dd 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -331,64 +331,6 @@ size_t blocknr; // Hitag2 operations //----------------------------------------------------------------------------- -static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { - // Reset the transmission frame length - *txlen = 0; - - // Try to find out which command was send by selecting on length (in bits) - switch (rxlen) { - // No answer, try to resurrect - case 0: { - // Stop if there is no answer (after sending password) - if (bPwd) { - DbpString("Password failed!"); - return false; - } - *txlen = 5; - memcpy(tx, "\xC0", nbytes(*txlen)); - } - break; - - // Received UID, tag password - case 32: { - if (!bPwd) { - *txlen = 32; - memcpy(tx, password, 4); - bPwd = true; - memcpy(tag.sectors[blocknr], rx, 4); - blocknr++; - } else { - - if (blocknr == 1) { - //store password in block1, the TAG answers with Block3, but we need the password in memory - memcpy(tag.sectors[blocknr], tx, 4); - } else { - memcpy(tag.sectors[blocknr], rx, 4); - } - - blocknr++; - if (blocknr > 7) { - DbpString("Read succesful!"); - bSuccessful = true; - return false; - } - *txlen = 10; - tx[0] = 0xC0 | (blocknr << 3) | ((blocknr ^ 7) >> 2); - tx[1] = ((blocknr ^ 7) << 6); - } - } - break; - - // Unexpected response - default: { - Dbprintf("Uknown frame length: %d", rxlen); - return false; - } - break; - } - return true; -} - static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { switch (writestate) { case WRITE_STATE_START: @@ -431,6 +373,71 @@ static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size return true; } +static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool write) { + // Reset the transmission frame length + *txlen = 0; + + if (bPwd && write) { + if (!hitag2_write_page(rx, rxlen, tx, txlen)) { + return false; + } + } else { + // Try to find out which command was send by selecting on length (in bits) + switch (rxlen) { + // No answer, try to resurrect + case 0: { + // Stop if there is no answer (after sending password) + if (bPwd) { + DbpString("Password failed!"); + return false; + } + *txlen = 5; + memcpy(tx, "\xC0", nbytes(*txlen)); + } + break; + + // Received UID, tag password + case 32: { + if (!bPwd) { + *txlen = 32; + memcpy(tx, password, 4); + bPwd = true; + memcpy(tag.sectors[blocknr], rx, 4); + blocknr++; + } else { + + if (blocknr == 1) { + //store password in block1, the TAG answers with Block3, but we need the password in memory + memcpy(tag.sectors[blocknr], tx, 4); + } else { + memcpy(tag.sectors[blocknr], rx, 4); + } + + blocknr++; + if (blocknr > 7) { + DbpString("Read succesful!"); + bSuccessful = true; + return false; + } + *txlen = 10; + tx[0] = 0xC0 | (blocknr << 3) | ((blocknr ^ 7) >> 2); + tx[1] = ((blocknr ^ 7) << 6); + } + } + break; + + // Unexpected response + default: { + Dbprintf("Uknown frame length: %d", rxlen); + return false; + } + break; + } + } + + return true; +} + static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool write) { // Reset the transmission frame length *txlen = 0; @@ -1217,7 +1224,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { tx = txbuf; switch (htf) { case RHT2F_PASSWORD: { - bStop = !hitag2_password(rx, rxlen, tx, &txlen); + bStop = !hitag2_password(rx, rxlen, tx, &txlen, false); break; } case RHT2F_AUTHENTICATE: { @@ -1391,6 +1398,16 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { writestate = WRITE_STATE_START; } break; + case WHT2F_PASSWORD: { + DbpString("Authenticating using password:"); + memcpy(password, htd->pwd.password, 4); + memcpy(writedata, htd->crypto.data, 4); + Dbhexdump(4, password, false); + blocknr = page; + bPwd = false; + writestate = WRITE_STATE_START; + } + break; default: { Dbprintf("Error, unknown function: %d", htf); StartTicks(); @@ -1480,6 +1497,10 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, true); } break; + case WHT2F_PASSWORD: { + bStop = !hitag2_password(rx, rxlen, tx, &txlen, true); + } + break; default: { Dbprintf("Error, unknown function: %d", htf); return; diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 27c352c53..47e08eb2e 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -106,6 +106,7 @@ static int usage_hitag_writer(void) { PrintAndLogEx(NORMAL, " Hitag1 (1*)"); PrintAndLogEx(NORMAL, " Hitag2 (2*)"); PrintAndLogEx(NORMAL, " 24 (set to 0 if no authentication is needed) write page on a Hitag2 tag"); + PrintAndLogEx(NORMAL, " 27 write page on a Hitag2 tag"); return 0; } static int usage_hitag_checkchallenges(void) { @@ -659,6 +660,12 @@ static int CmdLFHitagWriter(const char *Cmd) { num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data); break; } + case WHT2F_PASSWORD: { + num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 4, htd.pwd.password); + arg2 = param_get32ex(Cmd, 2, 0, 10); + num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data); + break; + } case RHTSF_CHALLENGE: case RHTSF_KEY: case RHT2F_PASSWORD: diff --git a/include/hitag.h b/include/hitag.h index 742d7ecd0..f57f1180a 100644 --- a/include/hitag.h +++ b/include/hitag.h @@ -31,6 +31,7 @@ typedef enum { WHT2F_CRYPTO = 24, RHT2F_TEST_AUTH_ATTEMPTS = 25, RHT2F_UID_ONLY = 26, + WHT2F_PASSWORD = 27, } hitag_function; typedef struct {