Merge pull request #233 from ViRb3/master

Add hitag2 write password auth
This commit is contained in:
Philippe Teuwen 2019-07-10 09:59:21 +02:00 committed by GitHub
commit c388f66b81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 59 deletions

View file

@ -331,10 +331,57 @@ size_t blocknr;
// Hitag2 operations // Hitag2 operations
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
switch (writestate) {
case WRITE_STATE_START:
*txlen = 10;
tx[0] = 0x82 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
tx[1] = ((blocknr ^ 7) << 6);
writestate = WRITE_STATE_PAGENUM_WRITTEN;
break;
case WRITE_STATE_PAGENUM_WRITTEN:
// Check if page number was received correctly
if ((rxlen == 10)
&& (rx[0] == (0x82 | (blocknr << 3) | ((blocknr ^ 7) >> 2)))
&& (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) {
*txlen = 32;
memset(tx, 0, HITAG_FRAME_LEN);
memcpy(tx, writedata, 4);
writestate = WRITE_STATE_PROG;
} else {
Dbprintf("hitag2_write_page: Page number was not received correctly: rxlen=%d rx=%02x%02x%02x%02x",
rxlen, rx[0], rx[1], rx[2], rx[3]);
bSuccessful = false;
return false;
}
break;
case WRITE_STATE_PROG:
if (rxlen == 0) {
bSuccessful = true;
} else {
bSuccessful = false;
Dbprintf("hitag2_write_page: unexpected rx data (%d) after page write", rxlen);
}
return false;
default:
DbpString("hitag2_write_page: Unknown state %d");
bSuccessful = false;
return false;
}
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 // Reset the transmission frame length
*txlen = 0; *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) // Try to find out which command was send by selecting on length (in bits)
switch (rxlen) { switch (rxlen) {
// No answer, try to resurrect // No answer, try to resurrect
@ -386,46 +433,6 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
} }
break; 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:
*txlen = 10;
tx[0] = 0x82 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
tx[1] = ((blocknr ^ 7) << 6);
writestate = WRITE_STATE_PAGENUM_WRITTEN;
break;
case WRITE_STATE_PAGENUM_WRITTEN:
// Check if page number was received correctly
if ((rxlen == 10)
&& (rx[0] == (0x82 | (blocknr << 3) | ((blocknr ^ 7) >> 2)))
&& (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) {
*txlen = 32;
memset(tx, 0, HITAG_FRAME_LEN);
memcpy(tx, writedata, 4);
writestate = WRITE_STATE_PROG;
} else {
Dbprintf("hitag2_write_page: Page number was not received correctly: rxlen=%d rx=%02x%02x%02x%02x",
rxlen, rx[0], rx[1], rx[2], rx[3]);
bSuccessful = false;
return false;
}
break;
case WRITE_STATE_PROG:
if (rxlen == 0) {
bSuccessful = true;
} else {
bSuccessful = false;
Dbprintf("hitag2_write_page: unexpected rx data (%d) after page write", rxlen);
}
return false;
default:
DbpString("hitag2_write_page: Unknown state %d");
bSuccessful = false;
return false;
} }
return true; return true;
@ -1217,7 +1224,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
tx = txbuf; tx = txbuf;
switch (htf) { switch (htf) {
case RHT2F_PASSWORD: { case RHT2F_PASSWORD: {
bStop = !hitag2_password(rx, rxlen, tx, &txlen); bStop = !hitag2_password(rx, rxlen, tx, &txlen, false);
break; break;
} }
case RHT2F_AUTHENTICATE: { case RHT2F_AUTHENTICATE: {
@ -1391,6 +1398,16 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
writestate = WRITE_STATE_START; writestate = WRITE_STATE_START;
} }
break; 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: { default: {
Dbprintf("Error, unknown function: %d", htf); Dbprintf("Error, unknown function: %d", htf);
StartTicks(); StartTicks();
@ -1480,6 +1497,10 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, true); bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, true);
} }
break; break;
case WHT2F_PASSWORD: {
bStop = !hitag2_password(rx, rxlen, tx, &txlen, true);
}
break;
default: { default: {
Dbprintf("Error, unknown function: %d", htf); Dbprintf("Error, unknown function: %d", htf);
return; return;

View file

@ -106,6 +106,7 @@ static int usage_hitag_writer(void) {
PrintAndLogEx(NORMAL, " Hitag1 (1*)"); PrintAndLogEx(NORMAL, " Hitag1 (1*)");
PrintAndLogEx(NORMAL, " Hitag2 (2*)"); PrintAndLogEx(NORMAL, " Hitag2 (2*)");
PrintAndLogEx(NORMAL, " 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag2 tag"); PrintAndLogEx(NORMAL, " 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag2 tag");
PrintAndLogEx(NORMAL, " 27 <password> <page> <byte0...byte3> write page on a Hitag2 tag");
return 0; return 0;
} }
static int usage_hitag_checkchallenges(void) { 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); num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data);
break; 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_CHALLENGE:
case RHTSF_KEY: case RHTSF_KEY:
case RHT2F_PASSWORD: case RHT2F_PASSWORD:

View file

@ -31,6 +31,7 @@ typedef enum {
WHT2F_CRYPTO = 24, WHT2F_CRYPTO = 24,
RHT2F_TEST_AUTH_ATTEMPTS = 25, RHT2F_TEST_AUTH_ATTEMPTS = 25,
RHT2F_UID_ONLY = 26, RHT2F_UID_ONLY = 26,
WHT2F_PASSWORD = 27,
} hitag_function; } hitag_function;
typedef struct { typedef struct {