mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-22 06:13:27 -07:00
'lf hitag writer': add Hitag2 password auth
* (PRs 233, 303, 304 by @ViRb3 on https://github.com/RfidResearchGroup/proxmark3) * replace byte_t by uint8_t * note that Hitag1 commands are not yet available * whitespace fixes
This commit is contained in:
parent
5a446cb212
commit
56e92b77da
4 changed files with 732 additions and 700 deletions
|
@ -16,7 +16,6 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "usb_cmd.h"
|
#include "usb_cmd.h"
|
||||||
#include "hitag2.h"
|
|
||||||
#include "hitagS.h"
|
#include "hitagS.h"
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
#include "../common/crc32.h"
|
#include "../common/crc32.h"
|
||||||
|
|
292
armsrc/hitag2.c
292
armsrc/hitag2.c
|
@ -19,6 +19,7 @@
|
||||||
#include "hitag2.h"
|
#include "hitag2.h"
|
||||||
|
|
||||||
#include "proxmark3.h"
|
#include "proxmark3.h"
|
||||||
|
#include "cmd.h"
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "hitag.h"
|
#include "hitag.h"
|
||||||
|
@ -44,9 +45,9 @@ struct hitag2_tag {
|
||||||
TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
|
TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
|
||||||
} state;
|
} state;
|
||||||
unsigned int active_sector;
|
unsigned int active_sector;
|
||||||
byte_t crypto_active;
|
uint8_t crypto_active;
|
||||||
uint64_t cs;
|
uint64_t cs;
|
||||||
byte_t sectors[12][4];
|
uint8_t sectors[12][4];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hitag2_tag tag = {
|
static struct hitag2_tag tag = {
|
||||||
|
@ -77,14 +78,14 @@ static enum {
|
||||||
// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces.
|
// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces.
|
||||||
// Historically it used to be FREE_BUFFER_SIZE, which was 2744.
|
// Historically it used to be FREE_BUFFER_SIZE, which was 2744.
|
||||||
#define AUTH_TABLE_LENGTH 2744
|
#define AUTH_TABLE_LENGTH 2744
|
||||||
static byte_t* auth_table;
|
static uint8_t *auth_table;
|
||||||
static size_t auth_table_pos = 0;
|
static size_t auth_table_pos = 0;
|
||||||
static size_t auth_table_len = AUTH_TABLE_LENGTH;
|
static size_t auth_table_len = AUTH_TABLE_LENGTH;
|
||||||
|
|
||||||
static byte_t password[4];
|
static uint8_t password[4];
|
||||||
static byte_t NrAr[8];
|
static uint8_t NrAr[8];
|
||||||
static byte_t key[8];
|
static uint8_t key[8];
|
||||||
static byte_t writedata[4];
|
static uint8_t writedata[4];
|
||||||
static uint64_t cipher_state;
|
static uint64_t cipher_state;
|
||||||
|
|
||||||
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
||||||
|
@ -177,7 +178,7 @@ static int hitag2_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hitag2_cipher_reset(struct hitag2_tag *tag, const byte_t *iv)
|
static void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv)
|
||||||
{
|
{
|
||||||
uint64_t key = ((uint64_t)tag->sectors[2][2]) |
|
uint64_t key = ((uint64_t)tag->sectors[2][2]) |
|
||||||
((uint64_t)tag->sectors[2][3] << 8) |
|
((uint64_t)tag->sectors[2][3] << 8) |
|
||||||
|
@ -196,9 +197,9 @@ static void hitag2_cipher_reset(struct hitag2_tag *tag, const byte_t *iv)
|
||||||
tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_));
|
tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hitag2_cipher_authenticate(uint64_t* cs, const byte_t *authenticator_is)
|
static int hitag2_cipher_authenticate(uint64_t* cs, const uint8_t *authenticator_is)
|
||||||
{
|
{
|
||||||
byte_t authenticator_should[4];
|
uint8_t authenticator_should[4];
|
||||||
authenticator_should[0] = ~_hitag2_byte(cs);
|
authenticator_should[0] = ~_hitag2_byte(cs);
|
||||||
authenticator_should[1] = ~_hitag2_byte(cs);
|
authenticator_should[1] = ~_hitag2_byte(cs);
|
||||||
authenticator_should[2] = ~_hitag2_byte(cs);
|
authenticator_should[2] = ~_hitag2_byte(cs);
|
||||||
|
@ -206,7 +207,7 @@ static int hitag2_cipher_authenticate(uint64_t* cs, const byte_t *authenticator_
|
||||||
return (memcmp(authenticator_should, authenticator_is, 4) == 0);
|
return (memcmp(authenticator_should, authenticator_is, 4) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hitag2_cipher_transcrypt(uint64_t* cs, byte_t *data, unsigned int bytes, unsigned int bits)
|
static int hitag2_cipher_transcrypt(uint64_t* cs, uint8_t *data, unsigned int bytes, unsigned int bits)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<bytes; i++) data[i] ^= _hitag2_byte(cs);
|
for(i=0; i<bytes; i++) data[i] ^= _hitag2_byte(cs);
|
||||||
|
@ -271,7 +272,7 @@ static void hitag_send_bit(int bit) {
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hitag_send_frame(const byte_t* frame, size_t frame_len)
|
static void hitag_send_frame(const uint8_t *frame, size_t frame_len)
|
||||||
{
|
{
|
||||||
// Send start of frame
|
// Send start of frame
|
||||||
for(size_t i = 0; i < 5; i++) {
|
for(size_t i = 0; i < 5; i++) {
|
||||||
|
@ -280,7 +281,7 @@ static void hitag_send_frame(const byte_t* frame, size_t frame_len)
|
||||||
|
|
||||||
// Send the content of the frame
|
// Send the content of the frame
|
||||||
for (size_t i = 0; i < frame_len; i++) {
|
for (size_t i = 0; i < frame_len; i++) {
|
||||||
hitag_send_bit((frame[i/8] >> (7-(i%8)))&1);
|
hitag_send_bit((frame[i/8] >> (7-(i%8))) & 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop the modulation
|
// Drop the modulation
|
||||||
|
@ -288,9 +289,8 @@ static void hitag_send_frame(const byte_t* frame, size_t frame_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
|
static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
||||||
{
|
uint8_t rx_air[HITAG_FRAME_LEN];
|
||||||
byte_t rx_air[HITAG_FRAME_LEN];
|
|
||||||
|
|
||||||
// Copy the (original) received frame how it is send over the air
|
// Copy the (original) received frame how it is send over the air
|
||||||
memcpy(rx_air, rx, nbytes(rxlen));
|
memcpy(rx_air, rx, nbytes(rxlen));
|
||||||
|
@ -446,11 +446,11 @@ static void hitag_reader_send_bit(int bit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
|
static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len)
|
||||||
{
|
{
|
||||||
// Send the content of the frame
|
// Send the content of the frame
|
||||||
for(size_t i = 0; i < frame_len; i++) {
|
for(size_t i = 0; i < frame_len; i++) {
|
||||||
hitag_reader_send_bit((frame[i/8] >> (7-(i%8)))&1);
|
hitag_reader_send_bit((frame[i/8] >> (7-(i%8))) & 0x01);
|
||||||
}
|
}
|
||||||
// Send EOF
|
// Send EOF
|
||||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||||
|
@ -464,63 +464,11 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
|
||||||
|
|
||||||
size_t blocknr;
|
size_t blocknr;
|
||||||
|
|
||||||
static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
//-----------------------------------------------------------------------------
|
||||||
// Reset the transmission frame length
|
// Hitag2 operations
|
||||||
*txlen = 0;
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Try to find out which command was send by selecting on length (in bits)
|
static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
||||||
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(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
|
|
||||||
{
|
|
||||||
switch (writestate) {
|
switch (writestate) {
|
||||||
case WRITE_STATE_START:
|
case WRITE_STATE_START:
|
||||||
*txlen = 10;
|
*txlen = 10;
|
||||||
|
@ -530,9 +478,9 @@ static bool hitag2_write_page(byte_t* rx, const size_t rxlen, byte_t* tx, size_t
|
||||||
break;
|
break;
|
||||||
case WRITE_STATE_PAGENUM_WRITTEN:
|
case WRITE_STATE_PAGENUM_WRITTEN:
|
||||||
// Check if page number was received correctly
|
// Check if page number was received correctly
|
||||||
if ((rxlen == 10) &&
|
if ((rxlen == 10)
|
||||||
(rx[0] == (0x82 | (blocknr << 3) | ((blocknr^7) >> 2))) &&
|
&& (rx[0] == (0x82 | (blocknr << 3) | ((blocknr^7) >> 2)))
|
||||||
(rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) {
|
&& (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) {
|
||||||
*txlen = 32;
|
*txlen = 32;
|
||||||
memset(tx, 0, HITAG_FRAME_LEN);
|
memset(tx, 0, HITAG_FRAME_LEN);
|
||||||
memcpy(tx, writedata, 4);
|
memcpy(tx, writedata, 4);
|
||||||
|
@ -561,28 +509,92 @@ static bool hitag2_write_page(byte_t* rx, const size_t rxlen, byte_t* tx, size_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen, bool write) {
|
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 && !bAuthenticating && 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) {
|
||||||
|
bPwd = true;
|
||||||
|
bAuthenticating = true;
|
||||||
|
memcpy(tx, password, 4);
|
||||||
|
*txlen = 32;
|
||||||
|
} else {
|
||||||
|
if (bAuthenticating) {
|
||||||
|
bAuthenticating = false;
|
||||||
|
if (write) {
|
||||||
|
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(tag.sectors[blocknr], rx, 4);
|
||||||
|
blocknr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blocknr > 7) {
|
||||||
|
DbpString("Read successful!");
|
||||||
|
bSuccessful = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*txlen = 10;
|
||||||
|
tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
|
||||||
|
tx[1] = ((blocknr^7) << 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unexpected response
|
||||||
|
default: {
|
||||||
|
Dbprintf("Unknown 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
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
|
||||||
if (bCrypto) {
|
if (bCrypto) {
|
||||||
hitag2_cipher_transcrypt(&cipher_state, rx, rxlen/8, rxlen%8);
|
hitag2_cipher_transcrypt(&cipher_state, rx, rxlen/8, rxlen%8);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bCrypto && !bAuthenticating && write) {
|
if (bCrypto && !bAuthenticating && write) {
|
||||||
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
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
|
||||||
case 0:
|
case 0: {
|
||||||
{
|
|
||||||
// Stop if there is no answer while we are in crypto mode (after sending NrAr)
|
// Stop if there is no answer while we are in crypto mode (after sending NrAr)
|
||||||
if (bCrypto) {
|
if (bCrypto) {
|
||||||
// Failed during authentication
|
// Failed during authentication
|
||||||
|
@ -636,14 +648,15 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
// stage 2+, got data block
|
||||||
|
else {
|
||||||
// Store the received block
|
// Store the received block
|
||||||
memcpy(tag.sectors[blocknr], rx, 4);
|
memcpy(tag.sectors[blocknr], rx, 4);
|
||||||
blocknr++;
|
blocknr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blocknr > 7) {
|
if (blocknr > 7) {
|
||||||
DbpString("Read succesful!");
|
DbpString("Read successful!");
|
||||||
bSuccessful = true;
|
bSuccessful = true;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -656,7 +669,7 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx
|
||||||
|
|
||||||
// Unexpected response
|
// Unexpected response
|
||||||
default: {
|
default: {
|
||||||
Dbprintf("Uknown frame length: %d",rxlen);
|
Dbprintf("Unknown frame length: %d",rxlen);
|
||||||
return false;
|
return false;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@ -672,8 +685,7 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hitag2_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
||||||
static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
|
||||||
|
@ -697,7 +709,7 @@ static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size
|
||||||
memcpy(tx, NrAr, 8);
|
memcpy(tx, NrAr, 8);
|
||||||
bCrypto = true;
|
bCrypto = true;
|
||||||
} else {
|
} else {
|
||||||
DbpString("Authentication succesful!");
|
DbpString("Authentication successful!");
|
||||||
// We are done... for now
|
// We are done... for now
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -705,7 +717,7 @@ static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size
|
||||||
|
|
||||||
// Unexpected response
|
// Unexpected response
|
||||||
default: {
|
default: {
|
||||||
Dbprintf("Uknown frame length: %d",rxlen);
|
Dbprintf("Unknown frame length: %d",rxlen);
|
||||||
return false;
|
return false;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@ -714,7 +726,7 @@ static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
static bool hitag2_test_auth_attempts(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
||||||
|
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
@ -762,7 +774,7 @@ static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
Dbprintf("Uknown frame length: %d",rxlen);
|
Dbprintf("Unknown frame length: %d",rxlen);
|
||||||
return false;
|
return false;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@ -770,7 +782,7 @@ static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hitag2_read_uid(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
|
static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
|
||||||
|
@ -800,7 +812,7 @@ static bool hitag2_read_uid(byte_t* rx, const size_t rxlen, byte_t* tx, size_t*
|
||||||
} break;
|
} break;
|
||||||
// Unexpected response
|
// Unexpected response
|
||||||
default: {
|
default: {
|
||||||
Dbprintf("Uknown frame length: %d",rxlen);
|
Dbprintf("Unknown frame length: %d",rxlen);
|
||||||
return false;
|
return false;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@ -808,7 +820,7 @@ static bool hitag2_read_uid(byte_t* rx, const size_t rxlen, byte_t* tx, size_t*
|
||||||
}
|
}
|
||||||
|
|
||||||
void SnoopHitag(uint32_t type) {
|
void SnoopHitag(uint32_t type) {
|
||||||
int frame_count;
|
// int frame_count;
|
||||||
int response;
|
int response;
|
||||||
int overflow;
|
int overflow;
|
||||||
bool rising_edge;
|
bool rising_edge;
|
||||||
|
@ -816,7 +828,7 @@ void SnoopHitag(uint32_t type) {
|
||||||
int lastbit;
|
int lastbit;
|
||||||
bool bSkip;
|
bool bSkip;
|
||||||
int tag_sof;
|
int tag_sof;
|
||||||
byte_t rx[HITAG_FRAME_LEN] = {0};
|
uint8_t rx[HITAG_FRAME_LEN] = {0};
|
||||||
size_t rxlen = 0;
|
size_t rxlen = 0;
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
|
@ -829,7 +841,7 @@ void SnoopHitag(uint32_t type) {
|
||||||
auth_table_pos = 0;
|
auth_table_pos = 0;
|
||||||
|
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||||
|
|
||||||
DbpString("Starting Hitag2 snoop");
|
DbpString("Starting Hitag2 snoop");
|
||||||
|
@ -865,7 +877,7 @@ void SnoopHitag(uint32_t type) {
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||||
|
|
||||||
// Reset the received frame, frame count and timing info
|
// Reset the received frame, frame count and timing info
|
||||||
frame_count = 0;
|
// frame_count = 0;
|
||||||
response = 0;
|
response = 0;
|
||||||
overflow = 0;
|
overflow = 0;
|
||||||
reader_frame = false;
|
reader_frame = false;
|
||||||
|
@ -972,7 +984,7 @@ void SnoopHitag(uint32_t type) {
|
||||||
|
|
||||||
// Check if frame was captured
|
// Check if frame was captured
|
||||||
if (rxlen > 0) {
|
if (rxlen > 0) {
|
||||||
frame_count++;
|
// frame_count++;
|
||||||
if (!LogTraceHitag(rx, rxlen, response, 0, reader_frame)) {
|
if (!LogTraceHitag(rx, rxlen, response, 0, reader_frame)) {
|
||||||
DbpString("Trace full");
|
DbpString("Trace full");
|
||||||
break;
|
break;
|
||||||
|
@ -1021,13 +1033,13 @@ void SnoopHitag(uint32_t type) {
|
||||||
// DbpString("All done");
|
// DbpString("All done");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) {
|
||||||
int frame_count;
|
// int frame_count;
|
||||||
int response;
|
int response;
|
||||||
int overflow;
|
int overflow;
|
||||||
byte_t rx[HITAG_FRAME_LEN];
|
uint8_t rx[HITAG_FRAME_LEN];
|
||||||
size_t rxlen = 0;
|
size_t rxlen = 0;
|
||||||
byte_t tx[HITAG_FRAME_LEN];
|
uint8_t tx[HITAG_FRAME_LEN];
|
||||||
size_t txlen = 0;
|
size_t txlen = 0;
|
||||||
bool bQuitTraceFull = false;
|
bool bQuitTraceFull = false;
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
|
@ -1040,9 +1052,9 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
|
|
||||||
auth_table_len = 0;
|
auth_table_len = 0;
|
||||||
auth_table_pos = 0;
|
auth_table_pos = 0;
|
||||||
byte_t* auth_table;
|
uint8_t *auth_table;
|
||||||
BigBuf_free();
|
BigBuf_free();
|
||||||
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||||
|
|
||||||
DbpString("Starting Hitag2 simulation");
|
DbpString("Starting Hitag2 simulation");
|
||||||
|
@ -1051,7 +1063,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
|
|
||||||
if (tag_mem_supplied) {
|
if (tag_mem_supplied) {
|
||||||
DbpString("Loading hitag2 memory...");
|
DbpString("Loading hitag2 memory...");
|
||||||
memcpy((byte_t*)tag.sectors,data,48);
|
memcpy((uint8_t*)tag.sectors, data, 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t block = 0;
|
uint32_t block = 0;
|
||||||
|
@ -1097,7 +1109,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
|
|
||||||
// Reset the received frame, frame count and timing info
|
// Reset the received frame, frame count and timing info
|
||||||
memset(rx, 0x00, sizeof(rx));
|
memset(rx, 0x00, sizeof(rx));
|
||||||
frame_count = 0;
|
// frame_count = 0;
|
||||||
response = 0;
|
response = 0;
|
||||||
overflow = 0;
|
overflow = 0;
|
||||||
|
|
||||||
|
@ -1144,7 +1156,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
|
|
||||||
// Check if frame was captured
|
// Check if frame was captured
|
||||||
if (rxlen > 4) {
|
if (rxlen > 4) {
|
||||||
frame_count++;
|
// frame_count++;
|
||||||
if (!bQuiet) {
|
if (!bQuiet) {
|
||||||
if (!LogTraceHitag(rx, rxlen, response, 0, true)) {
|
if (!LogTraceHitag(rx, rxlen, response, 0, true)) {
|
||||||
DbpString("Trace full");
|
DbpString("Trace full");
|
||||||
|
@ -1212,12 +1224,12 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||||
int frame_count;
|
// int frame_count;
|
||||||
int response;
|
int response;
|
||||||
byte_t rx[HITAG_FRAME_LEN];
|
uint8_t rx[HITAG_FRAME_LEN];
|
||||||
size_t rxlen = 0;
|
size_t rxlen = 0;
|
||||||
byte_t txbuf[HITAG_FRAME_LEN];
|
uint8_t txbuf[HITAG_FRAME_LEN];
|
||||||
byte_t* tx = txbuf;
|
uint8_t *tx = txbuf;
|
||||||
size_t txlen = 0;
|
size_t txlen = 0;
|
||||||
int lastbit;
|
int lastbit;
|
||||||
bool bSkip;
|
bool bSkip;
|
||||||
|
@ -1246,6 +1258,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
bQuitTraceFull = false;
|
bQuitTraceFull = false;
|
||||||
bQuiet = false;
|
bQuiet = false;
|
||||||
bPwd = false;
|
bPwd = false;
|
||||||
|
bAuthenticating = false;
|
||||||
} break;
|
} break;
|
||||||
case RHT2F_AUTHENTICATE: {
|
case RHT2F_AUTHENTICATE: {
|
||||||
DbpString("Authenticating using nr,ar pair:");
|
DbpString("Authenticating using nr,ar pair:");
|
||||||
|
@ -1332,7 +1345,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||||
|
|
||||||
// Reset the received frame, frame count and timing info
|
// Reset the received frame, frame count and timing info
|
||||||
frame_count = 0;
|
// frame_count = 0;
|
||||||
response = 0;
|
response = 0;
|
||||||
lastbit = 1;
|
lastbit = 1;
|
||||||
|
|
||||||
|
@ -1363,7 +1376,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
|
|
||||||
// Check if frame was captured and store it
|
// Check if frame was captured and store it
|
||||||
if (rxlen > 0) {
|
if (rxlen > 0) {
|
||||||
frame_count++;
|
// frame_count++;
|
||||||
if (!bQuiet) {
|
if (!bQuiet) {
|
||||||
if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
|
if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
|
||||||
DbpString("Trace full");
|
DbpString("Trace full");
|
||||||
|
@ -1380,7 +1393,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: {
|
||||||
bStop = !hitag2_authenticate(rx, rxlen, tx, &txlen);
|
bStop = !hitag2_authenticate(rx, rxlen, tx, &txlen);
|
||||||
|
@ -1394,7 +1407,8 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
case RHT2F_UID_ONLY: {
|
case RHT2F_UID_ONLY: {
|
||||||
bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen);
|
bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen);
|
||||||
attempt_count++; //attempt 3 times to get uid then quit
|
attempt_count++; //attempt 3 times to get uid then quit
|
||||||
if (!bStop && attempt_count == 3) bStop = true;
|
if (!bStop && attempt_count == 3)
|
||||||
|
bStop = true;
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
Dbprintf("Error, unknown function: %d", htf);
|
Dbprintf("Error, unknown function: %d", htf);
|
||||||
|
@ -1423,7 +1437,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
|
|
||||||
// Add transmitted frame to total count
|
// Add transmitted frame to total count
|
||||||
if (txlen > 0) {
|
if (txlen > 0) {
|
||||||
frame_count++;
|
// frame_count++;
|
||||||
if (!bQuiet) {
|
if (!bQuiet) {
|
||||||
// Store the frame in the trace
|
// Store the frame in the trace
|
||||||
if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
|
if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
|
||||||
|
@ -1532,19 +1546,19 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
|
||||||
//Dbprintf("frame received: %d",frame_count);
|
//Dbprintf("frame received: %d",frame_count);
|
||||||
//DbpString("All done");
|
//DbpString("All done");
|
||||||
if (bSuccessful)
|
if (bSuccessful)
|
||||||
cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
|
cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t*)tag.sectors, 48);
|
||||||
else
|
else
|
||||||
cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
|
cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
int frame_count;
|
// int frame_count;
|
||||||
int response;
|
int response;
|
||||||
byte_t rx[HITAG_FRAME_LEN];
|
uint8_t rx[HITAG_FRAME_LEN];
|
||||||
size_t rxlen = 0;
|
size_t rxlen = 0;
|
||||||
byte_t txbuf[HITAG_FRAME_LEN];
|
uint8_t txbuf[HITAG_FRAME_LEN];
|
||||||
byte_t* tx = txbuf;
|
uint8_t *tx = txbuf;
|
||||||
size_t txlen = 0;
|
size_t txlen = 0;
|
||||||
int lastbit;
|
int lastbit;
|
||||||
bool bSkip;
|
bool bSkip;
|
||||||
|
@ -1566,8 +1580,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
|
|
||||||
// Check configuration
|
// Check configuration
|
||||||
switch (htf) {
|
switch (htf) {
|
||||||
case WHT2F_CRYPTO:
|
case WHT2F_CRYPTO: {
|
||||||
{
|
|
||||||
DbpString("Authenticating using key:");
|
DbpString("Authenticating using key:");
|
||||||
memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code.
|
memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code.
|
||||||
memcpy(writedata, htd->crypto.data, 4);
|
memcpy(writedata, htd->crypto.data, 4);
|
||||||
|
@ -1579,6 +1592,16 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
bQuitTraceFull = true;
|
bQuitTraceFull = true;
|
||||||
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;
|
||||||
|
bAuthenticating = false;
|
||||||
|
writestate = WRITE_STATE_START;
|
||||||
|
} break;
|
||||||
default: {
|
default: {
|
||||||
Dbprintf("Error, unknown function: %d", htf);
|
Dbprintf("Error, unknown function: %d", htf);
|
||||||
return;
|
return;
|
||||||
|
@ -1629,7 +1652,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||||
|
|
||||||
// Reset the received frame, frame count and timing info
|
// Reset the received frame, frame count and timing info
|
||||||
frame_count = 0;
|
// frame_count = 0;
|
||||||
response = 0;
|
response = 0;
|
||||||
lastbit = 1;
|
lastbit = 1;
|
||||||
bStop = false;
|
bStop = false;
|
||||||
|
@ -1660,7 +1683,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
|
|
||||||
// Check if frame was captured and store it
|
// Check if frame was captured and store it
|
||||||
if (rxlen > 0) {
|
if (rxlen > 0) {
|
||||||
frame_count++;
|
// frame_count++;
|
||||||
if (!bQuiet) {
|
if (!bQuiet) {
|
||||||
if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
|
if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
|
||||||
DbpString("Trace full");
|
DbpString("Trace full");
|
||||||
|
@ -1679,6 +1702,10 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
case WHT2F_CRYPTO: {
|
case WHT2F_CRYPTO: {
|
||||||
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;
|
||||||
|
@ -1706,7 +1733,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
|
|
||||||
// Add transmitted frame to total count
|
// Add transmitted frame to total count
|
||||||
if (txlen > 0) {
|
if (txlen > 0) {
|
||||||
frame_count++;
|
// frame_count++;
|
||||||
if (!bQuiet) {
|
if (!bQuiet) {
|
||||||
// Store the frame in the trace
|
// Store the frame in the trace
|
||||||
if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
|
if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
|
||||||
|
@ -1794,7 +1821,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
} else {
|
} else {
|
||||||
// Dbprintf("DEBUG: Wierd2");
|
// Dbprintf("DEBUG: Wierd2");
|
||||||
errorCount++;
|
errorCount++;
|
||||||
// Ignore wierd value, is to small to mean anything
|
// Ignore wierd value, it is to small to mean anything
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if we saw over 100 wierd values break it probably isn't hitag...
|
//if we saw over 100 wierd values break it probably isn't hitag...
|
||||||
|
@ -1806,8 +1833,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait some extra time for flash to be programmed
|
// Wait some extra time for flash to be programmed
|
||||||
if ((rxlen == 0) && (writestate == WRITE_STATE_PROG))
|
if ((rxlen == 0) && (writestate == WRITE_STATE_PROG)) {
|
||||||
{
|
|
||||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||||
while (AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_PROG - HITAG_T_WAIT_MAX));
|
while (AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_PROG - HITAG_T_WAIT_MAX));
|
||||||
}
|
}
|
||||||
|
@ -1821,5 +1847,5 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) {
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
//Dbprintf("frame received: %d",frame_count);
|
//Dbprintf("frame received: %d",frame_count);
|
||||||
//DbpString("All done");
|
//DbpString("All done");
|
||||||
cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
|
cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t*)tag.sectors, 48);
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,14 +261,15 @@ int CmdLFHitagReader(const char *Cmd) {
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
PrintAndLog("Usage: hitag reader <Reader Function #>");
|
PrintAndLog("Usage: hitag reader <Reader Function #>");
|
||||||
PrintAndLog("Reader Functions:");
|
PrintAndLog("Reader Functions:");
|
||||||
PrintAndLog(" HitagS (0*)");
|
PrintAndLog(" HitagS (0*):");
|
||||||
PrintAndLog(" 01 <nr> <ar> (Challenge) <firstPage> <tagmode> read all pages from a Hitag S tag");
|
PrintAndLog(" 01 <nr> <ar> (Challenge) <firstPage> <tagmode> read all pages from a Hitag S tag");
|
||||||
PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all pages from a Hitag S tag");
|
PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all pages from a Hitag S tag");
|
||||||
PrintAndLog(" 03 <nr> <ar> (Challenge) <firstPage> <tagmode> read all blocks from a Hitag S tag");
|
PrintAndLog(" 03 <nr> <ar> (Challenge) <firstPage> <tagmode> read all blocks from a Hitag S tag");
|
||||||
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all blocks from a Hitag S tag");
|
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all blocks from a Hitag S tag");
|
||||||
PrintAndLog(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
|
PrintAndLog(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
|
||||||
PrintAndLog(" Hitag1 (1*)");
|
PrintAndLog(" Hitag1 (1*):");
|
||||||
PrintAndLog(" Hitag2 (2*)");
|
PrintAndLog(" (not yet implemented)");
|
||||||
|
PrintAndLog(" Hitag2 (2*):");
|
||||||
PrintAndLog(" 21 <password> (password mode)");
|
PrintAndLog(" 21 <password> (password mode)");
|
||||||
PrintAndLog(" 22 <nr> <ar> (authentication)");
|
PrintAndLog(" 22 <nr> <ar> (authentication)");
|
||||||
PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
|
PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
|
||||||
|
@ -389,28 +390,33 @@ int CmdLFHitagWP(const char *Cmd) {
|
||||||
hitag_data* htd = (hitag_data*)c.d.asBytes;
|
hitag_data* htd = (hitag_data*)c.d.asBytes;
|
||||||
hitag_function htf = param_get32ex(Cmd,0,0,10);
|
hitag_function htf = param_get32ex(Cmd,0,0,10);
|
||||||
switch (htf) {
|
switch (htf) {
|
||||||
case 03: { //WHTSF_CHALLENGE
|
case WHTSF_CHALLENGE: {
|
||||||
num_to_bytes(param_get64ex(Cmd,1,0,16),8,htd->auth.NrAr);
|
num_to_bytes(param_get64ex(Cmd,1,0,16),8,htd->auth.NrAr);
|
||||||
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
|
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
|
||||||
num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data);
|
num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data);
|
||||||
} break;
|
} break;
|
||||||
case 04:
|
case WHTSF_KEY:
|
||||||
case 24:
|
case WHT2F_CRYPTO: {
|
||||||
{ //WHTSF_KEY
|
|
||||||
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
|
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
|
||||||
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
|
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
|
||||||
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;
|
||||||
|
case WHT2F_PASSWORD: {
|
||||||
|
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 4, htd->pwd.password);
|
||||||
|
c.arg[2] = param_get32ex(Cmd, 2, 0, 10);
|
||||||
|
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->crypto.data);
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
PrintAndLog("Error: unkown writer function %d",htf);
|
PrintAndLog("Error: unkown writer function %d",htf);
|
||||||
PrintAndLog("Hitag writer functions");
|
PrintAndLog("Hitag writer functions");
|
||||||
PrintAndLog(" HitagS (0*)");
|
PrintAndLog(" HitagS (0*):");
|
||||||
PrintAndLog(" 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
|
PrintAndLog(" 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
|
||||||
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
|
PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
|
||||||
PrintAndLog(" Hitag1 (1*)");
|
PrintAndLog(" Hitag1 (1*)");
|
||||||
PrintAndLog(" Hitag2 (2*)");
|
PrintAndLog(" (not yet implemented)");
|
||||||
|
PrintAndLog(" Hitag2 (2*):");
|
||||||
PrintAndLog(" 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
|
PrintAndLog(" 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
|
||||||
|
PrintAndLog(" 27 <password> <page> <byte0...byte3> write page on a Hitag2 tag");
|
||||||
return 1;
|
return 1;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue